diff --git a/app/assets/stylesheets/layout.scss b/app/assets/stylesheets/layout.scss index a5291c925..4f229794e 100644 --- a/app/assets/stylesheets/layout.scss +++ b/app/assets/stylesheets/layout.scss @@ -945,6 +945,7 @@ footer { .tag-cloud a, .categories a, .geozone a, +.sdg-goal-tag-list .more-goals, .sidebar-links a, .tags span { background: #ececec; diff --git a/app/assets/stylesheets/sdg/goals/icon.scss b/app/assets/stylesheets/sdg/goals/icon.scss new file mode 100644 index 000000000..7e87f92c3 --- /dev/null +++ b/app/assets/stylesheets/sdg/goals/icon.scss @@ -0,0 +1,4 @@ +.sdg-goal-icon { + min-width: 40px; + width: 4vw; +} diff --git a/app/assets/stylesheets/sdg/goals/tag_list.scss b/app/assets/stylesheets/sdg/goals/tag_list.scss new file mode 100644 index 000000000..04b2ce9e0 --- /dev/null +++ b/app/assets/stylesheets/sdg/goals/tag_list.scss @@ -0,0 +1,14 @@ +.sdg-goal-tag-list { + list-style: none; + margin-bottom: 0; + margin-left: 0; + + li { + display: inline-block; + margin-bottom: 1ch; + + &:not(:last-child) { + padding-right: 1ch; + } + } +} diff --git a/app/components/sdg/goals/icon_component.html.erb b/app/components/sdg/goals/icon_component.html.erb new file mode 100644 index 000000000..794edc5d4 --- /dev/null +++ b/app/components/sdg/goals/icon_component.html.erb @@ -0,0 +1 @@ +<%= image_tag image_path, alt: image_text, class: "sdg-goal-icon" %> diff --git a/app/components/sdg/goals/icon_component.rb b/app/components/sdg/goals/icon_component.rb new file mode 100644 index 000000000..c86c933cc --- /dev/null +++ b/app/components/sdg/goals/icon_component.rb @@ -0,0 +1,32 @@ +class SDG::Goals::IconComponent < ApplicationComponent + attr_reader :goal + delegate :code, to: :goal + + def initialize(goal) + @goal = goal + end + + def image_path + "sdg/#{folder}/goal_#{code}.png" + end + + private + + def image_text + goal.code_and_title + end + + def folder + [*I18n.fallbacks[I18n.locale], "default"].find do |locale| + find_asset("sdg/#{locale}/goal_#{code}.png") + end + end + + def find_asset(path) + if Rails.application.assets + Rails.application.assets.find_asset(path) + else + Rails.application.assets_manifest.assets[path] + end + end +end diff --git a/app/components/sdg/goals/tag_list_component.html.erb b/app/components/sdg/goals/tag_list_component.html.erb new file mode 100644 index 000000000..344d54181 --- /dev/null +++ b/app/components/sdg/goals/tag_list_component.html.erb @@ -0,0 +1 @@ +<%= link_list(*links, class: "sdg-goal-tag-list") %> diff --git a/app/components/sdg/goals/tag_list_component.rb b/app/components/sdg/goals/tag_list_component.rb new file mode 100644 index 000000000..e07ad17f5 --- /dev/null +++ b/app/components/sdg/goals/tag_list_component.rb @@ -0,0 +1,57 @@ +class SDG::Goals::TagListComponent < ApplicationComponent + attr_reader :record, :limit + delegate :link_list, to: :helpers + + def initialize(record, limit: nil) + @record = record + @limit = limit + end + + def render? + SDG::ProcessEnabled.new(record.class.name).enabled? + end + + private + + def links + [*goal_links, see_more_link] + end + + def goal_links + goals.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.order(:code) + end + + def see_more_link + return unless limit && count_out_of_limit > 0 + + [ + "#{count_out_of_limit}+", + polymorphic_path(record), + class: "more-goals", title: t("sdg.goals.filter.more", count: count_out_of_limit) + ] + end + + def index_by_goal(goal) + polymorphic_path(record.class, advanced_search: { goal: goal.code }) + end + + def filter_text(goal) + t("sdg.goals.filter.link", + resources: record.model_name.human(count: :other), + code: goal.code) + end + + def count_out_of_limit + goals.size - limit + end +end diff --git a/app/views/shared/_tags.html.erb b/app/views/shared/_tags.html.erb index e061a09d0..679bbdbf1 100644 --- a/app/views/shared/_tags.html.erb +++ b/app/views/shared/_tags.html.erb @@ -16,3 +16,5 @@ <% end %> <% end %> + +<%= render SDG::Goals::TagListComponent.new(taggable, limit: limit) %> diff --git a/config/i18n-tasks.yml b/config/i18n-tasks.yml index 64e8f676c..c644c0311 100644 --- a/config/i18n-tasks.yml +++ b/config/i18n-tasks.yml @@ -45,6 +45,7 @@ data: - config/locales/%{locale}/user_groups.yml - config/locales/%{locale}/i18n.yml - config/locales/%{locale}/milestones.yml + - config/locales/%{locale}/sdg.yml - config/locales/%{locale}/sdg_management.yml - config/locales/%{locale}/stats.yml @@ -217,6 +218,7 @@ ignore_unused: - landings.cambia_tu_ciudad.* - "seeds.settings.*" - "dashboard.polls.*.submit" + - "sdg.goals.goal_*" #### ## Exclude these keys from the `i18n-tasks eq-base" report: # ignore_eq_base: diff --git a/config/locales/en/sdg.yml b/config/locales/en/sdg.yml index 4303ccae0..2d2c997bd 100644 --- a/config/locales/en/sdg.yml +++ b/config/locales/en/sdg.yml @@ -424,3 +424,8 @@ en: title: "By 2020, enhance capacity-building support to developing countries, including for least developed countries and small island developing States, to increase significantly the availability of high-quality, timely and reliable data disaggregated by income, gender, age, race, ethnicity, migratory status, disability, geographic location and other characteristics relevant in national contexts." target_17_19: title: "By 2030, build on existing initiatives to develop measurements of progress on sustainable development that complement gross domestic product, and support statistical capacity-building in developing countries." + filter: + link: "See all %{resources} related to goal %{code}" + more: + one: "One more goal" + other: "%{count} more goals" diff --git a/config/locales/es/sdg.yml b/config/locales/es/sdg.yml index deedb7a12..eb43b5616 100644 --- a/config/locales/es/sdg.yml +++ b/config/locales/es/sdg.yml @@ -424,3 +424,8 @@ es: title: "De aquí a 2020, mejorar el apoyo a la creación de capacidad prestado a los países en desarrollo, incluidos los países menos adelantados y los pequeños Estados insulares en desarrollo, para aumentar significativamente la disponibilidad de datos oportunos, fiables y de gran calidad desglosados por ingresos, sexo, edad, raza, origen étnico, estatus migratorio, discapacidad, ubicación geográfica y otras características pertinentes en los contextos nacionales." target_17_19: title: "De aquí a 2030, aprovechar las iniciativas existentes para elaborar indicadores que permitan medir los progresos en materia de desarrollo sostenible y complementen el producto interno bruto, y apoyar la creación de capacidad estadística en los países en desarrollo." + filter: + link: "Ver %{resources} del objetivo %{code}" + more: + one: "Un objetivo más" + other: "%{count} objetivos más" diff --git a/spec/components/sdg/goals/icon_component_spec.rb b/spec/components/sdg/goals/icon_component_spec.rb new file mode 100644 index 000000000..2894957d7 --- /dev/null +++ b/spec/components/sdg/goals/icon_component_spec.rb @@ -0,0 +1,19 @@ +require "rails_helper" + +describe SDG::Goals::IconComponent do + describe "#image_path" do + let(:component) { SDG::Goals::IconComponent.new(SDG::Goal[8]) } + + it "returns icons for the first fallback language with icons" do + allow(I18n).to receive(:fallbacks).and_return({ en: [:es, :de] }) + + expect(component.image_path).to eq "sdg/es/goal_8.png" + end + + it "returns the default icons when no fallback language has icons" do + allow(I18n).to receive(:fallbacks).and_return({}) + + expect(component.image_path).to eq "sdg/default/goal_8.png" + end + end +end diff --git a/spec/components/sdg/goals/tag_list_component_spec.rb b/spec/components/sdg/goals/tag_list_component_spec.rb new file mode 100644 index 000000000..493dc9dbc --- /dev/null +++ b/spec/components/sdg/goals/tag_list_component_spec.rb @@ -0,0 +1,63 @@ +require "rails_helper" + +describe SDG::Goals::TagListComponent, type: :component do + let(:debate) { create(:debate, sdg_goals: [SDG::Goal[1], SDG::Goal[3]]) } + let(:component) { SDG::Goals::TagListComponent.new(debate) } + + before do + Setting["feature.sdg"] = true + Setting["sdg.process.debates"] = true + end + + it "does not render when the feature is disabled" do + Setting["feature.sdg"] = false + + render_inline component + + expect(page).not_to have_css "li" + end + + it "does not render when the SDG process feature is disabled" do + Setting["sdg.process.debates"] = false + + render_inline component + + expect(page).not_to have_css "li" + end + + it "renders a list of goals" do + render_inline component + + expect(page).to have_css "li", count: 2 + end + + it "renders links for each goal" do + render_inline component + + expect(page).to have_selector "a", count: 2 + expect(page).to have_link "1. No Poverty", + title: "See all Debates related to goal 1", + href: "/debates?advanced_search#{CGI.escape("[goal]")}=1" + expect(page).to have_link "3. Good Health and Well-Being", + title: "See all Debates related to goal 3", + href: "/debates?advanced_search#{CGI.escape("[goal]")}=3" + end + + it "orders goals by code" do + render_inline component + + expect(page.first("a")[:title]).to end_with "goal 1" + end + + it "renders a link for more goals when out of limit" do + component = SDG::Goals::TagListComponent.new(debate, limit: 1) + + render_inline component + + expect(page).to have_selector "a", count: 2 + expect(page).to have_link "1. No Poverty" + expect(page).to have_link "1+", + title: "One more goal", + href: "/debates/#{debate.to_param}" + end +end