diff --git a/app/controllers/concerns/commentable_actions.rb b/app/controllers/concerns/commentable_actions.rb
index e46ba7da4..286d2a297 100644
--- a/app/controllers/concerns/commentable_actions.rb
+++ b/app/controllers/concerns/commentable_actions.rb
@@ -73,7 +73,7 @@ module CommentableActions
end
def tag_cloud
- resource_model.last_week.tag_counts.order("#{resource_name.pluralize}_count": :desc, name: :asc).limit(5)
+ TagCloud.new(resource_model, params[:search])
end
def load_geozones
diff --git a/app/helpers/tags_helper.rb b/app/helpers/tags_helper.rb
index 59bc56bce..da7824622 100644
--- a/app/helpers/tags_helper.rb
+++ b/app/helpers/tags_helper.rb
@@ -3,26 +3,12 @@ module TagsHelper
def taggable_path(taggable_type, tag_name)
case taggable_type
when 'debate'
- debates_path(tag: tag_name)
+ debates_path(search: tag_name)
when 'proposal'
- proposals_path(tag: tag_name)
+ proposals_path(search: tag_name)
else
'#'
end
end
- def taggable_counter_field(taggable_type)
- "#{taggable_type.underscore.pluralize}_count"
- end
-
- def tag_cloud(tags, classes, counter_field = :taggings_count)
- return [] if tags.empty?
-
- max_count = tags.sort_by(&counter_field).last.send(counter_field).to_f
-
- tags.each do |tag|
- index = ((tag.send(counter_field) / max_count) * (classes.size - 1))
- yield tag, classes[index.nan? ? 0 : index.round]
- end
- end
end
diff --git a/app/models/tag_cloud.rb b/app/models/tag_cloud.rb
new file mode 100644
index 000000000..086d88c48
--- /dev/null
+++ b/app/models/tag_cloud.rb
@@ -0,0 +1,38 @@
+class TagCloud
+
+ attr_accessor :resource_model, :scope
+
+ def initialize(resource_model, scope=nil)
+ @resource_model = resource_model
+ @scope = scope
+ end
+
+ def tags
+ resource_model_scoped.
+ last_week.tag_counts.
+ where("lower(name) NOT IN (?)", category_names + geozone_names + default_blacklist).
+ order("#{table_name}_count": :desc, name: :asc).
+ limit(10)
+ end
+
+ def category_names
+ ActsAsTaggableOn::Tag.where("kind = 'category'").map {|tag| tag.name.downcase }
+ end
+
+ def geozone_names
+ Geozone.all.map {|geozone| geozone.name.downcase }
+ end
+
+ def resource_model_scoped
+ scope && resource_model == Proposal ? resource_model.search(scope) : resource_model
+ end
+
+ def default_blacklist
+ ['']
+ end
+
+ def table_name
+ resource_model.to_s.downcase.pluralize
+ end
+
+end
\ No newline at end of file
diff --git a/app/views/shared/_tag_cloud.html.erb b/app/views/shared/_tag_cloud.html.erb
index 06bf85c2b..6b27de955 100644
--- a/app/views/shared/_tag_cloud.html.erb
+++ b/app/views/shared/_tag_cloud.html.erb
@@ -3,10 +3,9 @@
- <% tag_cloud @tag_cloud, %w[s m l] do |tag, css_class| %>
- <%= link_to taggable_path(taggable, tag.name), class: css_class do %>
- <%= tag.name %>
- (<%= tag.send(taggable_counter_field(taggable)) %>)
+ <% @tag_cloud.tags.each do |tag| %>
+ <%= link_to taggable_path(taggable, tag.name) do %>
+ <%= tag.name %>
<% end %>
<% end %>
diff --git a/spec/features/tags_spec.rb b/spec/features/tags_spec.rb
index 3f57c6b91..0b95e1de4 100644
--- a/spec/features/tags_spec.rb
+++ b/spec/features/tags_spec.rb
@@ -54,22 +54,6 @@ feature 'Tags' do
expect(page).to have_content "Hacienda"
end
- scenario 'Tag Cloud' do
- 1.times { create(:debate, tag_list: 'Medio Ambiente') }
- 5.times { create(:debate, tag_list: 'Corrupción') }
- 5.times { create(:debate, tag_list: 'Educación') }
- 10.times { create(:debate, tag_list: 'Economía') }
-
- visit debates_path
-
- within(:css, "#tag-cloud") do
- expect(page.find("a:eq(1)")).to have_content("Economía (10)")
- expect(page.find("a:eq(2)")).to have_content("Corrupción (5)")
- expect(page.find("a:eq(3)")).to have_content("Educación (5)")
- expect(page.find("a:eq(4)")).to have_content("Medio Ambiente (1)")
- end
- end
-
scenario 'Create' do
user = create(:user)
login_as(user)
@@ -141,4 +125,81 @@ feature 'Tags' do
expect(page).to_not have_content 'Economía'
end
+ context 'Tag cloud' do
+
+ scenario 'Proposals' do
+ earth = create(:proposal, tag_list: 'Medio Ambiente')
+ money = create(:proposal, tag_list: 'Economía')
+
+ visit proposals_path
+
+ within "#tag-cloud" do
+ expect(page).to have_content "Medio Ambiente"
+ expect(page).to have_content "Economía"
+ end
+ end
+
+ scenario 'Debates' do
+ earth = create(:debate, tag_list: 'Medio Ambiente')
+ money = create(:debate, tag_list: 'Economía')
+
+ visit debates_path
+
+ within "#tag-cloud" do
+ expect(page).to have_content "Medio Ambiente"
+ expect(page).to have_content "Economía"
+ end
+ end
+
+ scenario "scoped by category" do
+ create(:tag, kind: 'category', name: 'Medio Ambiente')
+ create(:tag, kind: 'category', name: 'Economía')
+
+ earth = create(:proposal, tag_list: 'Medio Ambiente, Agua')
+ money = create(:proposal, tag_list: 'Economía, Corrupción')
+
+ visit proposals_path(search: 'Economía')
+
+ within "#tag-cloud" do
+ expect(page).to have_css(".tag", count: 1)
+ expect(page).to have_content "Corrupción"
+ expect(page).to_not have_content "Economía"
+ end
+ end
+
+ scenario "scoped by district" do
+ create(:geozone, name: 'Madrid')
+ create(:geozone, name: 'Barcelona')
+
+ earth = create(:proposal, tag_list: 'Madrid, Agua')
+ money = create(:proposal, tag_list: 'Barcelona, Playa')
+
+ visit proposals_path(search: 'Barcelona')
+
+ within "#tag-cloud" do
+ expect(page).to have_css(".tag", count: 1)
+ expect(page).to have_content "Playa"
+ expect(page).to_not have_content "Agua"
+ end
+ end
+
+ scenario "tag links" do
+ proposal1 = create(:proposal, tag_list: 'Medio Ambiente')
+ proposal2 = create(:proposal, tag_list: 'Medio Ambiente')
+ proposal3 = create(:proposal, tag_list: 'Economía')
+
+ visit proposals_path
+
+ within "#tag-cloud" do
+ click_link "Medio Ambiente"
+ end
+
+ expect(page).to have_css ".proposal", count: 2
+ expect(page).to have_content proposal1.title
+ expect(page).to have_content proposal2.title
+ expect(page).to_not have_content proposal3.title
+ end
+
+ end
+
end
diff --git a/spec/models/tag_cloud_spec.rb b/spec/models/tag_cloud_spec.rb
new file mode 100644
index 000000000..d040c0527
--- /dev/null
+++ b/spec/models/tag_cloud_spec.rb
@@ -0,0 +1,116 @@
+require 'rails_helper'
+
+describe TagCloud do
+
+ describe "#tags" do
+
+ it "returns proposal tags" do
+ create(:proposal, tag_list: 'participation')
+ create(:debate, tag_list: 'world hunger')
+
+ tag_cloud = TagCloud.new(Proposal)
+
+ expect(tag_names(tag_cloud)).to contain_exactly('participation')
+ end
+
+ it "returns debate tags" do
+ create(:proposal, tag_list: 'participation')
+ create(:debate, tag_list: 'world hunger')
+
+ tag_cloud = TagCloud.new(Debate)
+
+ expect(tag_names(tag_cloud)).to contain_exactly('world hunger')
+ end
+
+ it "returns tags from last week" do
+ create(:proposal, tag_list: 'participation', created_at: 1.day.ago)
+ create(:proposal, tag_list: 'corruption', created_at: 2.weeks.ago)
+
+ tag_cloud = TagCloud.new(Proposal)
+
+ expect(tag_names(tag_cloud)).to contain_exactly('participation')
+ end
+
+ it "does not return category tags" do
+ create(:tag, kind: 'category', name: 'Education')
+ create(:tag, kind: 'category', name: 'Participation')
+
+ create(:proposal, tag_list: 'education, parks')
+ create(:proposal, tag_list: 'participation, water')
+
+ tag_cloud = TagCloud.new(Proposal)
+
+ expect(tag_names(tag_cloud)).to contain_exactly('parks', 'water')
+ end
+
+ it "does not return geozone names" do
+ create(:geozone, name: 'California')
+ create(:geozone, name: 'New York')
+
+ create(:proposal, tag_list: 'parks, California')
+ create(:proposal, tag_list: 'water, New York')
+
+ tag_cloud = TagCloud.new(Proposal)
+
+ expect(tag_names(tag_cloud)).to contain_exactly('parks', 'water')
+ end
+
+ it "returns tags scoped by category" do
+ create(:tag, kind: 'category', name: 'Education')
+ create(:tag, kind: 'category', name: 'Participation')
+
+ create(:proposal, tag_list: 'education, parks')
+ create(:proposal, tag_list: 'participation, water')
+
+ tag_cloud = TagCloud.new(Proposal, 'Education')
+
+ expect(tag_names(tag_cloud)).to contain_exactly('parks')
+ end
+
+ it "returns tags scoped by geozone" do
+ create(:geozone, name: 'California')
+ create(:geozone, name: 'New York')
+
+ create(:proposal, tag_list: 'parks, California')
+ create(:proposal, tag_list: 'water, New York')
+
+ tag_cloud = TagCloud.new(Proposal, 'California')
+
+ expect(tag_names(tag_cloud)).to contain_exactly('parks')
+ end
+
+ xit "returns tags scoped by category for debates"
+ xit "returns tags scoped by geozone for debates"
+
+ it "orders tags by count" do
+ 3.times { create(:proposal, tag_list: 'participation') }
+ create(:proposal, tag_list: 'corruption')
+
+ tag_cloud = TagCloud.new(Proposal)
+
+ expect(tag_names(tag_cloud).first).to eq 'participation'
+ expect(tag_names(tag_cloud).second).to eq 'corruption'
+ end
+
+ it "orders tags by count and then by name" do
+ 3.times { create(:proposal, tag_list: 'participation') }
+ 3.times { create(:proposal, tag_list: 'health') }
+ create(:proposal, tag_list: 'corruption')
+
+ tag_cloud = TagCloud.new(Proposal)
+
+ expect(tag_names(tag_cloud).first).to eq 'health'
+ expect(tag_names(tag_cloud).second).to eq 'participation'
+ expect(tag_names(tag_cloud).third).to eq 'corruption'
+ end
+
+ it "returns a maximum of 10 tags" do
+ 12.times { |i| create(:proposal, tag_list: "Tag #{i}") }
+
+ tag_cloud = TagCloud.new(Proposal)
+
+ expect(tag_names(tag_cloud).count).to eq(10)
+ end
+ end
+
+end
\ No newline at end of file
diff --git a/spec/support/common_actions.rb b/spec/support/common_actions.rb
index 437a3c7ca..f9331d328 100644
--- a/spec/support/common_actions.rb
+++ b/spec/support/common_actions.rb
@@ -175,4 +175,8 @@ module CommonActions
create(:debate, :with_confidence_score, cached_votes_up: 80)]
end
+ def tag_names(tag_cloud)
+ tag_cloud.tags.map(&:name)
+ end
+
end