From 08c410cc93334f411d2149c555a75c13e22daa9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javi=20Mart=C3=ADn?= Date: Thu, 28 Jan 2021 13:46:08 +0100 Subject: [PATCH] Make target filter change when goal filter changes Note we're using both the `hidden` and `disabled` properties to guarantee compatibility with user agents which might still display the option even when using the `hidden` attribute or hiding it with `display: none`. We could also use `hide()` and `show()` instead of the `hidden` property, but since we're using the `disabled` property, I thought the code would be easier to read if we used properties in both cases. Also note users will no longer be able to get, let's say, debates which are related to goal 1 and target 2.1. We think this use case is highly unlikely and there's no need to take it into account. --- app/assets/javascripts/advanced_search.js | 2 ++ app/assets/javascripts/application.js | 4 ++- .../sdg/sync_goal_and_target_filters.js | 28 +++++++++++++++++++ .../sdg_management/relations/search.js | 8 ++++++ .../relations/search_component.html.erb | 2 +- spec/system/advanced_search_spec.rb | 28 +++++++++++++++++++ spec/system/sdg_management/relations_spec.rb | 26 +++++++++++++++++ 7 files changed, 96 insertions(+), 2 deletions(-) create mode 100644 app/assets/javascripts/sdg/sync_goal_and_target_filters.js create mode 100644 app/assets/javascripts/sdg_management/relations/search.js diff --git a/app/assets/javascripts/advanced_search.js b/app/assets/javascripts/advanced_search.js index 51b257ee7..9fcf8ae5f 100644 --- a/app/assets/javascripts/advanced_search.js +++ b/app/assets/javascripts/advanced_search.js @@ -32,6 +32,8 @@ App.AdvancedSearch.toggle_date_options(); } }); + + App.SDGSyncGoalAndTargetFilters.sync($("#advanced_search_form")); } }; }).call(this); diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index ad7798135..f66510049 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -112,7 +112,8 @@ //= require columns_selector //= require budget_edit_associations //= require datepicker -//= require sdg/related_list_selector +//= require_tree ./sdg +//= require_tree ./sdg_management var initialize_modules = function() { "use strict"; @@ -166,6 +167,7 @@ var initialize_modules = function() { App.BudgetEditAssociations.initialize(); App.Datepicker.initialize(); App.SDGRelatedListSelector.initialize(); + App.SDGManagementRelationSearch.initialize(); }; var destroy_non_idempotent_modules = function() { diff --git a/app/assets/javascripts/sdg/sync_goal_and_target_filters.js b/app/assets/javascripts/sdg/sync_goal_and_target_filters.js new file mode 100644 index 000000000..6ded27389 --- /dev/null +++ b/app/assets/javascripts/sdg/sync_goal_and_target_filters.js @@ -0,0 +1,28 @@ +(function() { + "use strict"; + App.SDGSyncGoalAndTargetFilters = { + sync: function(form) { + var goal_filter = form.find("[name*=goal]"); + var target_filter = form.find("[name*=target]"); + + goal_filter.on("change", function() { + if (this.value) { + App.SDGSyncGoalAndTargetFilters.enable_goal_options(target_filter, this.value); + } else { + target_filter.find("option").prop("disabled", false).prop("hidden", false); + } + }).trigger("change"); + }, + enable_goal_options: function(target_filter, goal_code) { + var base_target_code = goal_code + "."; + var target_selector = "[value^='" + base_target_code + "'], [value='']"; + + target_filter.find("option" + target_selector).prop("disabled", false).prop("hidden", false); + target_filter.find("option:not(" + target_selector + ")").prop("disabled", true).prop("hidden", true); + + if (!target_filter[0].value.startsWith(base_target_code)) { + target_filter.val(""); + } + } + }; +}).call(this); diff --git a/app/assets/javascripts/sdg_management/relations/search.js b/app/assets/javascripts/sdg_management/relations/search.js new file mode 100644 index 000000000..328d40fea --- /dev/null +++ b/app/assets/javascripts/sdg_management/relations/search.js @@ -0,0 +1,8 @@ +(function() { + "use strict"; + App.SDGManagementRelationSearch = { + initialize: function() { + App.SDGSyncGoalAndTargetFilters.sync($(".sdg-relations-search")); + } + }; +}).call(this); diff --git a/app/components/sdg_management/relations/search_component.html.erb b/app/components/sdg_management/relations/search_component.html.erb index b4a61be21..d77f21c8f 100644 --- a/app/components/sdg_management/relations/search_component.html.erb +++ b/app/components/sdg_management/relations/search_component.html.erb @@ -1,4 +1,4 @@ -<%= render Admin::SearchComponent.new(label: label, class: "complex") do |component| %> +<%= render Admin::SearchComponent.new(label: label, class: "sdg-relations-search complex") do |component| %> <%= component.select_tag :goal_code, goal_options, include_blank: goal_blank_option, "aria-label": goal_label %> diff --git a/spec/system/advanced_search_spec.rb b/spec/system/advanced_search_spec.rb index c3d41a1ea..a18795f65 100644 --- a/spec/system/advanced_search_spec.rb +++ b/spec/system/advanced_search_spec.rb @@ -371,6 +371,7 @@ describe "Advanced search", :js do before do Setting["feature.sdg"] = true Setting["sdg.process.debates"] = true + Setting["sdg.process.proposals"] = true Setting["sdg.process.budgets"] = true end @@ -389,6 +390,10 @@ describe "Advanced search", :js do expect(page).to have_content "Purifier" expect(page).not_to have_content "Hospital" end + + expect(page).to have_select "By target", + selected: "Select a target", + enabled_options: ["Select a target"] + %w[6.1 6.2 6.3 6.4 6.5 6.6 6.A 6.B] end scenario "Search by target" do @@ -409,6 +414,29 @@ describe "Advanced search", :js do expect(page).not_to have_content("Unrelated") end end + + scenario "Dynamic target options depending on the selected goal" do + visit proposals_path + + click_link "Advanced search" + select "1. No Poverty", from: "By SDG" + + expect(page).to have_select "By target", + selected: "Select a target", + enabled_options: ["Select a target"] + %w[1.1 1.2 1.3 1.4 1.5 1.A 1.B] + + select "1.1", from: "By target" + select "13. Climate Action", from: "By SDG" + + expect(page).to have_select "By target", + selected: "Select a target", + enabled_options: ["Select a target"] + %w[13.1 13.2 13.3 13.A 13.B] + + select "13.1", from: "By target" + select "Select a goal", from: "By SDG" + + expect(page).to have_select "By target", selected: "13.1", disabled_options: [] + end end end end diff --git a/spec/system/sdg_management/relations_spec.rb b/spec/system/sdg_management/relations_spec.rb index 9221e01c1..be5bff406 100644 --- a/spec/system/sdg_management/relations_spec.rb +++ b/spec/system/sdg_management/relations_spec.rb @@ -152,6 +152,10 @@ describe "SDG Relations", :js do expect(page).to have_content "School" expect(page).not_to have_content "Hospital" expect(page).to have_css "li.is-active h2", exact_text: "Pending" + + expect(page).to have_select "By target", + selected: "All targets", + enabled_options: ["All targets"] + %w[4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.A 4.B 4.C] end scenario "target filter" do @@ -200,6 +204,28 @@ describe "SDG Relations", :js do expect(page).to have_css "li.is-active h2", exact_text: "All" end + + scenario "dynamic target options depending on the selected goal" do + visit sdg_management_polls_path + + select "1. No Poverty", from: "By goal" + + expect(page).to have_select "By target", + selected: "All targets", + enabled_options: ["All targets"] + %w[1.1 1.2 1.3 1.4 1.5 1.A 1.B] + + select "1.1", from: "By target" + select "13. Climate Action", from: "By goal" + + expect(page).to have_select "By target", + selected: "All targets", + enabled_options: ["All targets"] + %w[13.1 13.2 13.3 13.A 13.B] + + select "13.1", from: "By target" + select "All goals", from: "By goal" + + expect(page).to have_select "By target", selected: "13.1", disabled_options: [] + end end end