diff --git a/app/assets/stylesheets/participation.scss b/app/assets/stylesheets/participation.scss index 9c014addc..d47dda44e 100644 --- a/app/assets/stylesheets/participation.scss +++ b/app/assets/stylesheets/participation.scss @@ -606,12 +606,6 @@ img { max-width: 12rem; } - - .budget-investment-content { - ul { - margin-bottom: 0; - } - } } } diff --git a/app/assets/stylesheets/sdg/goals/filter_links.scss b/app/assets/stylesheets/sdg/goals/tag_cloud.scss similarity index 69% rename from app/assets/stylesheets/sdg/goals/filter_links.scss rename to app/assets/stylesheets/sdg/goals/tag_cloud.scss index 914c4e7b0..8008cfb64 100644 --- a/app/assets/stylesheets/sdg/goals/filter_links.scss +++ b/app/assets/stylesheets/sdg/goals/tag_cloud.scss @@ -1,4 +1,4 @@ -.sdg-goal-filter-links { +.sdg-goal-tag-cloud { .sdg-goal-tag-list { @extend %sdg-goal-list; diff --git a/app/components/concerns/sdg/tag_list.rb b/app/components/concerns/sdg/tag_list.rb index a27225370..59ba6d4e3 100644 --- a/app/components/concerns/sdg/tag_list.rb +++ b/app/components/concerns/sdg/tag_list.rb @@ -1,50 +1,31 @@ module SDG::TagList extend ActiveSupport::Concern - attr_reader :record_or_name, :limit - delegate :link_list, to: :helpers + attr_reader :record, :limit - def initialize(record_or_name, limit: nil) - @record_or_name = record_or_name + def initialize(record, limit: nil) + @record = record @limit = limit end def render? - process.enabled? + SDG::ProcessEnabled.new(record).enabled? end - def see_more_link(collection) - count = count_out_of_limit(collection) + def tag_records + tags = record.send(association_name) - if count > 0 - [ - "#{count}+", - polymorphic_path(record), - class: "more-#{i18n_namespace}", title: t("sdg.#{i18n_namespace}.filter.more", count: count) - ] + if tags.respond_to?(:limit) + tags.order(:code).limit(limit) + else + tags.sort[0..(limit.to_i - 1)] end end - def filter_text(goal_or_target) - t("sdg.#{i18n_namespace}.filter.link", - resources: model.model_name.human(count: :other), - code: goal_or_target.code) + def see_more_link + render Shared::SeeMoreLinkComponent.new(record, association_name, limit: limit) end - def index_by(advanced_search) - polymorphic_path(model, advanced_search: advanced_search) - end - - def count_out_of_limit(collection) - return 0 unless limit - - collection.size - limit - end - - def process - @process ||= SDG::ProcessEnabled.new(record_or_name) - end - - def model - process.name.constantize + def association_name + raise NotImplementedError, "method must be implemented in the included class" end end diff --git a/app/components/sdg/filter_links_component.html.erb b/app/components/sdg/filter_links_component.html.erb new file mode 100644 index 000000000..874755b8a --- /dev/null +++ b/app/components/sdg/filter_links_component.html.erb @@ -0,0 +1 @@ +<%= link_list(*links, class: "sdg-#{parameter_name}-tag-list") %> diff --git a/app/components/sdg/filter_links_component.rb b/app/components/sdg/filter_links_component.rb new file mode 100644 index 000000000..80cc6b548 --- /dev/null +++ b/app/components/sdg/filter_links_component.rb @@ -0,0 +1,49 @@ +class SDG::FilterLinksComponent < ApplicationComponent + attr_reader :records, :related_model, :see_more_link + delegate :link_list, to: :helpers + + def initialize(records, related_model, see_more_link: nil) + @records = records + @related_model = related_model + @see_more_link = see_more_link + end + + def links + [*sdg_links, see_more_link] + end + + private + + def sdg_links + records.map do |goal_or_target| + [ + render(SDG::TagComponent.new(goal_or_target)), + index_by(parameter_name => goal_or_target.code), + title: filter_text(goal_or_target), + data: { code: goal_or_target.code } + ] + end + end + + def filter_text(goal_or_target) + t("sdg.#{i18n_namespace}.filter.link", + resources: related_model.model_name.human(count: :other), + code: goal_or_target.code) + end + + def index_by(advanced_search) + polymorphic_path(related_model, advanced_search: advanced_search) + end + + def i18n_namespace + parameter_name.pluralize + end + + def parameter_name + if records.first.is_a?(SDG::Goal) + "goal" + else + "target" + end + end +end diff --git a/app/components/sdg/goals/filter_links_component.html.erb b/app/components/sdg/goals/filter_links_component.html.erb deleted file mode 100644 index dc4b3c122..000000000 --- a/app/components/sdg/goals/filter_links_component.html.erb +++ /dev/null @@ -1,5 +0,0 @@ - diff --git a/app/components/sdg/goals/plain_tag_list_component.rb b/app/components/sdg/goals/plain_tag_list_component.rb index 8b60b692b..5e8b4ff53 100644 --- a/app/components/sdg/goals/plain_tag_list_component.rb +++ b/app/components/sdg/goals/plain_tag_list_component.rb @@ -3,31 +3,17 @@ class SDG::Goals::PlainTagListComponent < ApplicationComponent private - def record - record_or_name - end - def tags - [*goal_tags, see_more_link].compact - end - - def see_more_link - options = super(goals) - - link_to(*options) if options.present? + [*goal_tags, see_more_link].select(&:present?) end def goal_tags - goals.order(:code).limit(limit).map do |goal| - render SDG::Goals::IconComponent.new(goal) + tag_records.map do |goal| + render SDG::TagComponent.new(goal) end end - def goals - record.sdg_goals - end - - def i18n_namespace - "goals" + def association_name + :sdg_goals end end diff --git a/app/components/sdg/goals/tag_cloud_component.html.erb b/app/components/sdg/goals/tag_cloud_component.html.erb new file mode 100644 index 000000000..d44f9768f --- /dev/null +++ b/app/components/sdg/goals/tag_cloud_component.html.erb @@ -0,0 +1,5 @@ +
+ + + <%= render SDG::FilterLinksComponent.new(goals, class_name.constantize) %> +
diff --git a/app/components/sdg/goals/filter_links_component.rb b/app/components/sdg/goals/tag_cloud_component.rb similarity index 68% rename from app/components/sdg/goals/filter_links_component.rb rename to app/components/sdg/goals/tag_cloud_component.rb index 3d4affc78..0ffac19b9 100644 --- a/app/components/sdg/goals/filter_links_component.rb +++ b/app/components/sdg/goals/tag_cloud_component.rb @@ -1,4 +1,4 @@ -class SDG::Goals::FilterLinksComponent < ApplicationComponent +class SDG::Goals::TagCloudComponent < ApplicationComponent attr_reader :class_name def initialize(class_name) @@ -14,4 +14,8 @@ class SDG::Goals::FilterLinksComponent < ApplicationComponent def heading t("sdg.goals.filter.heading") end + + def goals + SDG::Goal.order(:code) + end end diff --git a/app/components/sdg/goals/tag_list_component.html.erb b/app/components/sdg/goals/tag_list_component.html.erb index 344d54181..1ddd0dd2d 100644 --- a/app/components/sdg/goals/tag_list_component.html.erb +++ b/app/components/sdg/goals/tag_list_component.html.erb @@ -1 +1 @@ -<%= link_list(*links, class: "sdg-goal-tag-list") %> +<%= render SDG::FilterLinksComponent.new(tag_records, related_model, see_more_link: see_more_link) %> diff --git a/app/components/sdg/goals/tag_list_component.rb b/app/components/sdg/goals/tag_list_component.rb index 391e07f55..fb9c181e9 100644 --- a/app/components/sdg/goals/tag_list_component.rb +++ b/app/components/sdg/goals/tag_list_component.rb @@ -3,33 +3,11 @@ class SDG::Goals::TagListComponent < ApplicationComponent private - def record - record_or_name if record_or_name.respond_to?(:sdg_goals) + def association_name + :sdg_goals end - def links - [*goal_links, see_more_link(goals)] - end - - def goal_links - goals.order(:code).limit(limit).map do |goal| - [ - render(SDG::Goals::IconComponent.new(goal)), - index_by_goal(goal), - title: filter_text(goal) - ] - end - end - - def goals - record&.sdg_goals || SDG::Goal.all - end - - def index_by_goal(goal) - index_by(goal: goal.code) - end - - def i18n_namespace - "goals" + def related_model + record.class end end diff --git a/app/components/sdg/tag_component.html.erb b/app/components/sdg/tag_component.html.erb new file mode 100644 index 000000000..bfbda2748 --- /dev/null +++ b/app/components/sdg/tag_component.html.erb @@ -0,0 +1 @@ +<%= text -%> diff --git a/app/components/sdg/tag_component.rb b/app/components/sdg/tag_component.rb new file mode 100644 index 000000000..366e5005a --- /dev/null +++ b/app/components/sdg/tag_component.rb @@ -0,0 +1,15 @@ +class SDG::TagComponent < ApplicationComponent + attr_reader :goal_or_target + + def initialize(goal_or_target) + @goal_or_target = goal_or_target + end + + def text + if goal_or_target.is_a?(SDG::Goal) + render SDG::Goals::IconComponent.new(goal_or_target) + else + "#{SDG::Target.model_name.human} #{goal_or_target.code}" + end + end +end diff --git a/app/components/sdg/targets/plain_tag_list_component.rb b/app/components/sdg/targets/plain_tag_list_component.rb index b24792cb2..78ccc4b42 100644 --- a/app/components/sdg/targets/plain_tag_list_component.rb +++ b/app/components/sdg/targets/plain_tag_list_component.rb @@ -3,35 +3,17 @@ class SDG::Targets::PlainTagListComponent < ApplicationComponent private - def record - record_or_name - end - def tags - [*target_tags, see_more_link].compact - end - - def see_more_link - options = super(targets) - - link_to(*options) if options.present? + [*target_tags, see_more_link].select(&:present?) end def target_tags - targets.sort[0..(limit.to_i - 1)].map do |target| - tag.span(text(target), data: { code: target.code }) + tag_records.map do |target| + tag.span(render(SDG::TagComponent.new(target)), data: { code: target.code }) end end - def targets - record.sdg_targets - end - - def text(target) - "#{SDG::Target.model_name.human} #{target.code}" - end - - def i18n_namespace - "targets" + def association_name + :sdg_targets end end diff --git a/app/components/sdg/targets/tag_list_component.html.erb b/app/components/sdg/targets/tag_list_component.html.erb index 1c97ade36..1ddd0dd2d 100644 --- a/app/components/sdg/targets/tag_list_component.html.erb +++ b/app/components/sdg/targets/tag_list_component.html.erb @@ -1 +1 @@ -<%= link_list(*links, class: "sdg-target-tag-list") %> +<%= render SDG::FilterLinksComponent.new(tag_records, related_model, see_more_link: see_more_link) %> diff --git a/app/components/sdg/targets/tag_list_component.rb b/app/components/sdg/targets/tag_list_component.rb index cb79f80b6..2d8e1a92b 100644 --- a/app/components/sdg/targets/tag_list_component.rb +++ b/app/components/sdg/targets/tag_list_component.rb @@ -3,34 +3,11 @@ class SDG::Targets::TagListComponent < ApplicationComponent private - def record - record_or_name + def association_name + :sdg_targets end - def links - [*target_links, see_more_link(targets)] - end - - def target_links - targets.sort[0..(limit.to_i - 1)].map do |target| - [ - "#{SDG::Target.model_name.human} #{target.code}", - index_by_target(target), - title: filter_text(target), - data: { code: target.code } - ] - end - end - - def targets - record.sdg_targets - end - - def index_by_target(target) - index_by(target: target.code) - end - - def i18n_namespace - "targets" + def related_model + record.class end end diff --git a/app/components/shared/see_more_link_component.html.erb b/app/components/shared/see_more_link_component.html.erb new file mode 100644 index 000000000..dd78b17a5 --- /dev/null +++ b/app/components/shared/see_more_link_component.html.erb @@ -0,0 +1,3 @@ +<% if count_out_of_limit > 0 %> + <%= link_to text, url, class: html_class, title: title %> +<% end %> diff --git a/app/components/shared/see_more_link_component.rb b/app/components/shared/see_more_link_component.rb new file mode 100644 index 000000000..339f66384 --- /dev/null +++ b/app/components/shared/see_more_link_component.rb @@ -0,0 +1,37 @@ +class Shared::SeeMoreLinkComponent < ApplicationComponent + attr_reader :record, :association_name, :limit + + def initialize(record, association_name, limit: nil) + @record = record + @association_name = association_name + @limit = limit + end + + private + + def text + "#{count_out_of_limit}+" + end + + def url + polymorphic_path(record) + end + + def title + t("#{i18n_namespace}.filter.more", count: count_out_of_limit) + end + + def count_out_of_limit + return 0 unless limit + + record.send(association_name).size - limit + end + + def i18n_namespace + association_name.to_s.tr("_", ".") + end + + def html_class + "more-#{i18n_namespace.split(".").last}" + end +end diff --git a/app/components/shared/tag_list_component.html.erb b/app/components/shared/tag_list_component.html.erb new file mode 100644 index 000000000..217f9855c --- /dev/null +++ b/app/components/shared/tag_list_component.html.erb @@ -0,0 +1 @@ +<%= link_list(*links, class: "tags", id: "tags_#{dom_id(taggable)}") %> diff --git a/app/components/shared/tag_list_component.rb b/app/components/shared/tag_list_component.rb new file mode 100644 index 000000000..79510718e --- /dev/null +++ b/app/components/shared/tag_list_component.rb @@ -0,0 +1,37 @@ +class Shared::TagListComponent < ApplicationComponent + attr_reader :taggable, :limit + delegate :link_list, to: :helpers + + def initialize(taggable, limit:) + @taggable = taggable + @limit = limit + end + + private + + def links + [*tag_links, see_more_link] + end + + def tag_links + taggable.tag_list_with_limit(limit).map do |tag| + [ + sanitize(tag.name), + taggables_path(taggable, tag.name) + ] + end + end + + def see_more_link + render Shared::SeeMoreLinkComponent.new(taggable, :tags, limit: limit) + end + + def taggables_path(taggable, tag_name) + case taggable.class.name + when "Legislation::Proposal" + legislation_process_proposals_path(taggable.process, search: tag_name) + else + polymorphic_path(taggable.class, search: tag_name) + end + end +end diff --git a/app/helpers/link_list_helper.rb b/app/helpers/link_list_helper.rb index f3e00d1bb..5af374fae 100644 --- a/app/helpers/link_list_helper.rb +++ b/app/helpers/link_list_helper.rb @@ -1,11 +1,15 @@ module LinkListHelper def link_list(*links, **options) - return "" if links.compact.empty? + return "" if links.select(&:present?).empty? tag.ul(options) do - safe_join(links.compact.map do |text, url, current = false, **link_options| + safe_join(links.select(&:present?).map do |text, url, current = false, **link_options| tag.li(({ "aria-current": true } if current)) do - link_to text, url, link_options + if url + link_to text, url, link_options + else + text + end end end, "\n") end diff --git a/app/helpers/tags_helper.rb b/app/helpers/tags_helper.rb deleted file mode 100644 index 464a155d0..000000000 --- a/app/helpers/tags_helper.rb +++ /dev/null @@ -1,10 +0,0 @@ -module TagsHelper - def taggables_path(taggable, tag_name) - case taggable.class.name - when "Legislation::Proposal" - legislation_process_proposals_path(taggable.process, search: tag_name) - else - polymorphic_path(taggable.class, search: tag_name) - end - end -end diff --git a/app/models/concerns/taggable.rb b/app/models/concerns/taggable.rb index c840dd97e..73889ae81 100644 --- a/app/models/concerns/taggable.rb +++ b/app/models/concerns/taggable.rb @@ -12,13 +12,6 @@ module Taggable tags.sort { |a, b| b.taggings_count <=> a.taggings_count }[0, limit] end - def tags_count_out_of_limit(limit = nil) - return 0 unless limit - - count = tags.size - limit - count < 0 ? 0 : count - end - def max_number_of_tags errors.add(:tag_list, :less_than_or_equal_to, count: 6) if tag_list.count > 6 end diff --git a/app/views/shared/_tag_cloud.html.erb b/app/views/shared/_tag_cloud.html.erb index 05507c5e2..1983f262a 100644 --- a/app/views/shared/_tag_cloud.html.erb +++ b/app/views/shared/_tag_cloud.html.erb @@ -13,4 +13,4 @@ -<%= render SDG::Goals::FilterLinksComponent.new(taggable) %> +<%= render SDG::Goals::TagCloudComponent.new(taggable) %> diff --git a/app/views/shared/_tags.html.erb b/app/views/shared/_tags.html.erb index f4ac1773e..bb868393e 100644 --- a/app/views/shared/_tags.html.erb +++ b/app/views/shared/_tags.html.erb @@ -1,20 +1,4 @@ <%- limit ||= nil %> <%= render SDG::TagListComponent.new(taggable, limit: limit) %> - -<% if taggable.tags.any? %> - -<% end %> +<%= render Shared::TagListComponent.new(taggable, limit: limit) %> diff --git a/config/i18n-tasks.yml b/config/i18n-tasks.yml index 37a8abda1..dd76cacec 100644 --- a/config/i18n-tasks.yml +++ b/config/i18n-tasks.yml @@ -221,6 +221,7 @@ ignore_unused: - "sdg.goals.goal_*" - "sdg.*.filter.more.*" - "sdg_management.relations.index.filter*" + - "tags.filter.more.*" #### ## Exclude these keys from the `i18n-tasks eq-base" report: # ignore_eq_base: diff --git a/config/locales/en/general.yml b/config/locales/en/general.yml index a150efd5a..3985effb9 100644 --- a/config/locales/en/general.yml +++ b/config/locales/en/general.yml @@ -973,3 +973,8 @@ en: create: enqueue_remote_translation: Translations have been correctly requested. button: Translate page + tags: + filter: + more: + one: "One more tag" + other: "%{count} more tags" diff --git a/config/locales/es/general.yml b/config/locales/es/general.yml index c9e011657..9b0e15134 100644 --- a/config/locales/es/general.yml +++ b/config/locales/es/general.yml @@ -973,3 +973,8 @@ es: create: enqueue_remote_translation: Se han solicitado correctamente las traducciones. button: Traducir página + tags: + filter: + more: + one: "Una etiqueta más" + other: "%{count} etiquetas más" diff --git a/spec/components/sdg/goals/filter_links_component_spec.rb b/spec/components/sdg/goals/filter_links_component_spec.rb deleted file mode 100644 index 408e8ee1b..000000000 --- a/spec/components/sdg/goals/filter_links_component_spec.rb +++ /dev/null @@ -1,25 +0,0 @@ -require "rails_helper" - -describe SDG::Goals::FilterLinksComponent, type: :component do - before do - Setting["feature.sdg"] = true - Setting["sdg.process.debates"] = true - Setting["sdg.process.proposals"] = true - end - - it "renders a title" do - component = SDG::Goals::FilterLinksComponent.new("Debate") - - render_inline component - - expect(page).to have_content "Filters by SDG" - end - - it "renders all goals" do - component = SDG::Goals::FilterLinksComponent.new("Proposal") - - render_inline component - - expect(page).to have_css ".sdg-goal-icon", count: 17 - end -end diff --git a/spec/components/sdg/goals/tag_cloud_component_spec.rb b/spec/components/sdg/goals/tag_cloud_component_spec.rb new file mode 100644 index 000000000..6738ba0da --- /dev/null +++ b/spec/components/sdg/goals/tag_cloud_component_spec.rb @@ -0,0 +1,27 @@ +require "rails_helper" + +describe SDG::Goals::TagCloudComponent, type: :component do + before do + Setting["feature.sdg"] = true + Setting["sdg.process.debates"] = true + Setting["sdg.process.proposals"] = true + end + + it "renders a title" do + component = SDG::Goals::TagCloudComponent.new("Debate") + + render_inline component + + expect(page).to have_content "Filters by SDG" + end + + it "renders all goals ordered by code" do + component = SDG::Goals::TagCloudComponent.new("Proposal") + + render_inline component + + expect(page).to have_selector ".sdg-goal-icon", count: 17 + expect(page.first("a")[:title]).to end_with "goal 1" + expect(page.all("a").last[:title]).to end_with "goal 17" + end +end diff --git a/spec/components/sdg/goals/tag_list_component_spec.rb b/spec/components/sdg/goals/tag_list_component_spec.rb index 6f1d3f12b..493dc9dbc 100644 --- a/spec/components/sdg/goals/tag_list_component_spec.rb +++ b/spec/components/sdg/goals/tag_list_component_spec.rb @@ -60,16 +60,4 @@ describe SDG::Goals::TagListComponent, type: :component do title: "One more goal", href: "/debates/#{debate.to_param}" end - - context "given a class name" do - let(:component) { SDG::Goals::TagListComponent.new("Debate") } - - it "renders all goals ordered by code" do - render_inline component - - expect(page).to have_selector "li", count: 17 - expect(page.first("a")[:title]).to end_with "goal 1" - expect(page.all("a").last[:title]).to end_with "goal 17" - end - end end diff --git a/spec/helpers/link_list_helper_spec.rb b/spec/helpers/link_list_helper_spec.rb index 31ff73768..7626d0198 100644 --- a/spec/helpers/link_list_helper_spec.rb +++ b/spec/helpers/link_list_helper_spec.rb @@ -19,6 +19,15 @@ describe LinkListHelper do expect(list).to be_html_safe end + it "accepts anchor tags" do + list = helper.link_list(link_to("Home", "/"), ["Info", "/info"], class: "menu") + + expect(list).to eq '' + expect(list).to be_html_safe + end + it "accepts options for links" do render helper.link_list(["Home", "/", class: "root"], ["Info", "/info", id: "info"]) @@ -30,7 +39,15 @@ describe LinkListHelper do it "ignores nil entries" do render helper.link_list(["Home", "/", class: "root"], nil, ["Info", "/info", id: "info"]) - expect(page).to have_css "a", count: 2 + expect(page).to have_css "li", count: 2 + expect(page).to have_css "a.root", count: 1, exact_text: "Home" + expect(page).to have_css "a#info", count: 1, exact_text: "Info" + end + + it "ignores empty entries" do + render helper.link_list(["Home", "/", class: "root"], "", ["Info", "/info", id: "info"]) + + expect(page).to have_css "li", count: 2 expect(page).to have_css "a.root", count: 1, exact_text: "Home" expect(page).to have_css "a#info", count: 1, exact_text: "Info" end