mirror of
https://github.com/TracksApp/tracks.git
synced 2025-12-26 12:08:47 +01:00
Merge branch 'tag-cloud' of https://github.com/kytrinyx/tracks
This commit is contained in:
commit
8b0f3e986a
9 changed files with 159 additions and 77 deletions
|
|
@ -552,49 +552,11 @@ class StatsController < ApplicationController
|
|||
end
|
||||
|
||||
def get_stats_tags
|
||||
# tag cloud code inspired by this article
|
||||
# http://www.juixe.com/techknow/index.php/2006/07/15/acts-as-taggable-tag-cloud/
|
||||
tags = Stats::TagCloudQuery.new(current_user).result
|
||||
@tag_cloud = Stats::TagCloud.new(tags)
|
||||
|
||||
levels=10
|
||||
# TODO: parameterize limit
|
||||
|
||||
# Get the tag cloud for all tags for actions
|
||||
query = "SELECT tags.id, name, count(*) AS count"
|
||||
query << " FROM taggings, tags, todos"
|
||||
query << " WHERE tags.id = tag_id"
|
||||
query << " AND taggings.taggable_id = todos.id"
|
||||
query << " AND todos.user_id="+current_user.id.to_s+" "
|
||||
query << " AND taggings.taggable_type='Todo' "
|
||||
query << " GROUP BY tags.id, tags.name"
|
||||
query << " ORDER BY count DESC, name"
|
||||
query << " LIMIT 100"
|
||||
@tags_for_cloud = Tag.find_by_sql(query).sort_by { |tag| tag.name.downcase }
|
||||
tag_counts = @tags_for_cloud.map(&:count)
|
||||
max = tag_counts.max || 0
|
||||
@tags_min = tag_counts.min || 0
|
||||
|
||||
@tags_divisor = ((max - @tags_min) / levels) + 1
|
||||
|
||||
# Get the tag cloud for all tags for actions
|
||||
query = "SELECT tags.id, tags.name AS name, count(*) AS count"
|
||||
query << " FROM taggings, tags, todos"
|
||||
query << " WHERE tags.id = tag_id"
|
||||
query << " AND todos.user_id=? "
|
||||
query << " AND taggings.taggable_type='Todo' "
|
||||
query << " AND taggings.taggable_id=todos.id "
|
||||
query << " AND (todos.created_at > ? OR "
|
||||
query << " todos.completed_at > ?) "
|
||||
query << " GROUP BY tags.id, tags.name"
|
||||
query << " ORDER BY count DESC, name"
|
||||
query << " LIMIT 100"
|
||||
@tags_for_cloud_90days = Tag.find_by_sql(
|
||||
[query, current_user.id, @cut_off_3months, @cut_off_3months]
|
||||
).sort_by { |tag| tag.name.downcase }
|
||||
|
||||
tag_counts_90days = @tags_for_cloud_90days.map(&:count)
|
||||
max_90days = tag_counts_90days.max || 0
|
||||
@tags_min_90days = tag_counts_90days.min || 0
|
||||
@tags_divisor_90days = ((max_90days - @tags_min_90days) / levels) + 1
|
||||
tags = Stats::TagCloudQuery.new(current_user, @cut_off_3months).result
|
||||
@tag_cloud_90days = Stats::TagCloud.new(tags)
|
||||
end
|
||||
|
||||
def get_ids_from (actions, week_from, week_to, at_end)
|
||||
|
|
|
|||
38
app/models/stats/tag_cloud.rb
Normal file
38
app/models/stats/tag_cloud.rb
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
# tag cloud code inspired by this article
|
||||
# http://www.juixe.com/techknow/index.php/2006/07/15/acts-as-taggable-tag-cloud/
|
||||
module Stats
|
||||
class TagCloud
|
||||
|
||||
attr_reader :levels, :tags
|
||||
def initialize(tags)
|
||||
@levels = 10
|
||||
@tags = tags.sort_by { |tag| tag.name.downcase }
|
||||
end
|
||||
|
||||
def empty?
|
||||
tags.empty?
|
||||
end
|
||||
|
||||
def font_size(tag)
|
||||
(9 + 2*(tag.count-min)/divisor)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def max
|
||||
@max ||= counts.max
|
||||
end
|
||||
|
||||
def min
|
||||
@min ||= counts.min
|
||||
end
|
||||
|
||||
def divisor
|
||||
@divisor ||= ((max - min) / levels) + 1
|
||||
end
|
||||
|
||||
def counts
|
||||
@counts ||= tags.map {|t| t.count}
|
||||
end
|
||||
end
|
||||
end
|
||||
38
app/models/stats/tag_cloud_query.rb
Normal file
38
app/models/stats/tag_cloud_query.rb
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
module Stats
|
||||
class TagCloudQuery
|
||||
|
||||
attr_reader :user, :cutoff
|
||||
def initialize(user, cutoff = nil)
|
||||
@user = user
|
||||
@cutoff = cutoff
|
||||
end
|
||||
|
||||
def result
|
||||
Tag.find_by_sql(query_options)
|
||||
end
|
||||
|
||||
def query_options
|
||||
options = [sql, user.id]
|
||||
options += [cutoff, cutoff] if cutoff
|
||||
options
|
||||
end
|
||||
|
||||
def sql
|
||||
# TODO: parameterize limit
|
||||
query = "SELECT tags.id, tags.name AS name, count(*) AS count"
|
||||
query << " FROM taggings, tags, todos"
|
||||
query << " WHERE tags.id = tag_id"
|
||||
query << " AND todos.user_id=? "
|
||||
query << " AND taggings.taggable_type='Todo' "
|
||||
query << " AND taggings.taggable_id=todos.id "
|
||||
if cutoff
|
||||
query << " AND (todos.created_at > ? OR "
|
||||
query << " todos.completed_at > ?) "
|
||||
end
|
||||
query << " GROUP BY tags.id, tags.name"
|
||||
query << " ORDER BY count DESC, name"
|
||||
query << " LIMIT 100"
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
@ -1,34 +1,19 @@
|
|||
<div class="stats_module">
|
||||
<h3><%= t('stats.tag_cloud_title') %></h3>
|
||||
<p><%= t('stats.tag_cloud_description') %></p>
|
||||
|
||||
<p>
|
||||
<% if @tags_for_cloud.size < 1
|
||||
<h3><%= t("stats.tag_cloud#{key}_title") %></h3>
|
||||
<p><%= t("stats.tag_cloud#{key}_description") %></p>
|
||||
<p>
|
||||
<%
|
||||
if tag_cloud.empty?
|
||||
t('stats.no_tags_available')
|
||||
else
|
||||
@tags_for_cloud.each do |t| %>
|
||||
<%= link_to t.name, tag_path(t.name), {
|
||||
:style => "font-size: " + (9 + 2*(t.count.to_i-@tags_min)/@tags_divisor).to_s + "pt",
|
||||
:title => t.count.to_s+" #{t('common.actions_midsentence', :count => t.count)}"}
|
||||
-%> <%
|
||||
else
|
||||
tag_cloud.tags.each do |t|
|
||||
%><%=
|
||||
link_to t.name, tag_path(t.name), {
|
||||
:style => "font-size: " + "#{tag_cloud.font_size(t)}pt",
|
||||
:title => "#{t.count} #{t('common.actions_midsentence', :count => t.count)}"}
|
||||
-%><%
|
||||
end
|
||||
end
|
||||
end-%>
|
||||
-%>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="stats_module">
|
||||
<h3><%= t('stats.tag_cloud_90days_title') %></h3>
|
||||
<p><%= t('stats.tag_cloud_90days_description') %></p>
|
||||
<p>
|
||||
<% if @tags_for_cloud_90days.size < 1
|
||||
t('stats.no_tags_available')
|
||||
else
|
||||
@tags_for_cloud_90days.each do |t| %>
|
||||
<%= link_to t.name, tag_path(t.name), {
|
||||
:style => "font-size: " + (9 + 2*(t.count.to_i-@tags_min_90days)/@tags_divisor_90days).to_s + "pt",
|
||||
:title => t.count.to_s+" #{t('common.actions_midsentence', :count => t.count)}"}
|
||||
-%> <%
|
||||
end
|
||||
end-%>
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -15,7 +15,8 @@
|
|||
<%= render :partial => 'projects' -%>
|
||||
|
||||
<h2><%= t('stats.tags') %></h2>
|
||||
<%= render :partial => 'tags' -%>
|
||||
<%= render :partial => 'tags', :locals => {:tag_cloud => @tag_cloud, :key => ''} -%>
|
||||
<%= render :partial => 'tags', :locals => {:tag_cloud => @tag_cloud_90days, :key => '_90days'} -%>
|
||||
|
||||
<% else -%>
|
||||
|
||||
|
|
@ -23,4 +24,4 @@
|
|||
|
||||
<% end -%>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
7
test/minimal_test_helper.rb
Normal file
7
test/minimal_test_helper.rb
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
require 'simplecov'
|
||||
SimpleCov.start 'rails'
|
||||
|
||||
ENV["RAILS_ENV"] = "test"
|
||||
require 'test/unit'
|
||||
|
||||
$:.unshift File.dirname(File.dirname(__FILE__))
|
||||
|
|
@ -1,7 +1,4 @@
|
|||
require 'simplecov'
|
||||
SimpleCov.start 'rails'
|
||||
|
||||
ENV["RAILS_ENV"] = "test"
|
||||
require File.expand_path('../minimal_test_helper', __FILE__)
|
||||
require File.expand_path('../../config/environment', __FILE__)
|
||||
require 'rails/test_help'
|
||||
|
||||
|
|
|
|||
31
test/unit/tag_cloud_query_test.rb
Normal file
31
test/unit/tag_cloud_query_test.rb
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
||||
|
||||
class TagCloudQueryTest < ActiveSupport::TestCase
|
||||
|
||||
fixtures :tags, :taggings, :users
|
||||
|
||||
def user
|
||||
@user ||= User.find 1
|
||||
end
|
||||
|
||||
def test_get_all_tags
|
||||
tags = Stats::TagCloudQuery.new(user).result
|
||||
assert_equal 2, tags.size
|
||||
tags.sort_by! {|t| t.id}
|
||||
tag = tags.first
|
||||
assert_equal 3, tag.count
|
||||
assert_equal "foo", tag.name
|
||||
|
||||
tag = tags.last
|
||||
assert_equal 1, tag.count
|
||||
assert_equal "bar", tag.name
|
||||
end
|
||||
|
||||
def test_get_subset_of_tags
|
||||
tags = Stats::TagCloudQuery.new(user, 1.week.ago).result
|
||||
|
||||
assert_equal 1, tags.size
|
||||
assert_equal 2, tags.first.count
|
||||
assert_equal "foo", tags.first.name
|
||||
end
|
||||
end
|
||||
23
test/unit/tag_cloud_test.rb
Normal file
23
test/unit/tag_cloud_test.rb
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
require File.expand_path(File.dirname(__FILE__) + '/../minimal_test_helper')
|
||||
require 'app/models/stats/tag_cloud'
|
||||
|
||||
class TagCloudTest < Test::Unit::TestCase
|
||||
|
||||
FakeTag = Struct.new(:name, :count)
|
||||
|
||||
def test_tags_get_sorted_alphabetically
|
||||
tags = [FakeTag.new("bee", 1), FakeTag.new("See", 10), FakeTag.new("aye", 100)]
|
||||
|
||||
assert_equal %w(aye bee See), Stats::TagCloud.new(tags).tags.map(&:name)
|
||||
end
|
||||
|
||||
def test_tag_font_size
|
||||
tags = [FakeTag.new("bee", 1), FakeTag.new("See", 10), FakeTag.new("aye", 100)]
|
||||
cloud = Stats::TagCloud.new(tags)
|
||||
|
||||
assert_equal 9, cloud.font_size(FakeTag.new("whatever", 1))
|
||||
assert_equal 18, cloud.font_size(FakeTag.new("whatever", 50))
|
||||
assert_equal 28, cloud.font_size(FakeTag.new("whatever", 100))
|
||||
end
|
||||
|
||||
end
|
||||
Loading…
Add table
Add a link
Reference in a new issue