From 833bc80eca5458a27c2213c6d410f3ebe9d4e7b0 Mon Sep 17 00:00:00 2001 From: taitus Date: Sat, 23 Jan 2021 14:01:20 +0100 Subject: [PATCH] Allow add local targets to RelatedListSelectorComponent --- .../sdg/related_list_selector_component.rb | 3 +- app/models/concerns/sdg/relatable.rb | 13 +++--- app/models/sdg/goal.rb | 9 ++++ app/models/sdg/local_target.rb | 10 ++--- app/models/sdg/target.rb | 12 +++--- .../related_list_selector_component_spec.rb | 16 ++++++- spec/models/sdg/goal_spec.rb | 28 ++++++++++++ spec/models/sdg/local_target_spec.rb | 16 +++++++ spec/models/sdg/relatable_spec.rb | 29 ++++++++++--- spec/models/sdg/target_spec.rb | 16 +++++++ spec/system/sdg_management/relations_spec.rb | 43 +++++++++++++------ 11 files changed, 157 insertions(+), 38 deletions(-) diff --git a/app/components/sdg/related_list_selector_component.rb b/app/components/sdg/related_list_selector_component.rb index b183765ded5f..4f32adf5a464 100644 --- a/app/components/sdg/related_list_selector_component.rb +++ b/app/components/sdg/related_list_selector_component.rb @@ -15,7 +15,8 @@ def sdg_related_suggestions def goals_and_targets goals.map do |goal| - [goal, *goal.targets.sort] + global_and_local_targets = goal.targets + goal.local_targets + [goal, global_and_local_targets.sort] end.flatten end diff --git a/app/models/concerns/sdg/relatable.rb b/app/models/concerns/sdg/relatable.rb index 636feca73958..1b1b8d4a4956 100644 --- a/app/models/concerns/sdg/relatable.rb +++ b/app/models/concerns/sdg/relatable.rb @@ -74,19 +74,20 @@ def sdg_target_list end def sdg_related_list - sdg_goals.order(:code).map do |goal| - [goal, sdg_global_targets.where(goal: goal).sort] - end.flatten.map(&:code).join(", ") + related_sdgs.sort.map(&:code).join(", ") end def sdg_related_list=(codes) target_codes, goal_codes = codes.tr(" ", "").split(",").partition { |code| code.include?(".") } - targets = target_codes.map { |code| SDG::Target[code] } + local_targets_codes, global_targets_codes = target_codes.partition { |code| code.split(".")[2] } + global_targets = global_targets_codes.map { |code| SDG::Target[code] } + local_targets = local_targets_codes.map { |code| SDG::LocalTarget[code] } goals = goal_codes.map { |code| SDG::Goal[code] } transaction do - self.sdg_global_targets = targets - self.sdg_goals = (targets.map(&:goal) + goals).uniq + self.sdg_local_targets = local_targets + self.sdg_global_targets = global_targets + self.sdg_goals = (global_targets.map(&:goal) + local_targets.map(&:goal) + goals).uniq end end end diff --git a/app/models/sdg/goal.rb b/app/models/sdg/goal.rb index 167dc2bf4ef5..3e0b8700751f 100644 --- a/app/models/sdg/goal.rb +++ b/app/models/sdg/goal.rb @@ -1,4 +1,5 @@ class SDG::Goal < ApplicationRecord + include Comparable include SDG::Related validates :code, presence: true, uniqueness: true, inclusion: { in: 1..17 } @@ -18,6 +19,14 @@ def description I18n.t("sdg.goals.goal_#{code}.description") end + def <=>(goal_or_target) + if goal_or_target.class == self.class + code <=> goal_or_target.code + elsif goal_or_target.respond_to?(:goal) + [self, -1] <=> [goal_or_target.goal, 1] + end + end + def self.[](code) find_by!(code: code) end diff --git a/app/models/sdg/local_target.rb b/app/models/sdg/local_target.rb index 1bc9a9a0e5a1..6e07d48950f0 100644 --- a/app/models/sdg/local_target.rb +++ b/app/models/sdg/local_target.rb @@ -23,11 +23,11 @@ def self.[](code) find_by!(code: code) end - def <=>(any_target) - if any_target.class == self.class - [target, numeric_subcode] <=> [any_target.target, any_target.numeric_subcode] - elsif any_target.class == target.class - -1 * (any_target <=> self) + def <=>(goal_or_target) + if goal_or_target.class == self.class + [target, numeric_subcode] <=> [goal_or_target.target, goal_or_target.numeric_subcode] + elsif [target.class, goal.class].include?(goal_or_target.class) + -1 * (goal_or_target <=> self) end end diff --git a/app/models/sdg/target.rb b/app/models/sdg/target.rb index ee1e96a45f42..e20536e1b969 100644 --- a/app/models/sdg/target.rb +++ b/app/models/sdg/target.rb @@ -12,11 +12,13 @@ def title I18n.t("sdg.goals.goal_#{goal.code}.targets.target_#{code_key}.title") end - def <=>(any_target) - if any_target.class == self.class - [goal.code, numeric_subcode] <=> [any_target.goal.code, any_target.numeric_subcode] - elsif any_target.class.name == "SDG::LocalTarget" - [self, -1] <=> [any_target.target, 1] + def <=>(goal_or_target) + if goal_or_target.class == self.class + [goal.code, numeric_subcode] <=> [goal_or_target.goal.code, goal_or_target.numeric_subcode] + elsif goal_or_target.class == goal.class + -1 * (goal_or_target <=> self) + elsif goal_or_target.class.name == "SDG::LocalTarget" + [self, -1] <=> [goal_or_target.target, 1] end end diff --git a/spec/components/sdg/related_list_selector_component_spec.rb b/spec/components/sdg/related_list_selector_component_spec.rb index 7326400e01f1..38a2fe74ea47 100644 --- a/spec/components/sdg/related_list_selector_component_spec.rb +++ b/spec/components/sdg/related_list_selector_component_spec.rb @@ -36,10 +36,12 @@ describe "#goals_and_targets" do it "return all goals and target with order" do + create(:sdg_local_target, code: "1.1.1") goals_and_targets = component.goals_and_targets expect(goals_and_targets.first).to eq SDG::Goal[1] expect(goals_and_targets.second).to eq SDG::Target[1.1] + expect(goals_and_targets.third).to eq SDG::LocalTarget["1.1.1"] expect(goals_and_targets.last).to eq SDG::Target[17.19] end end @@ -56,7 +58,7 @@ }) end - it "return suggestion tag for target" do + it "returns suggestion tag for global target" do suggestion = component.suggestion_tag_for(SDG::Target[1.1]) expect(suggestion).to eq({ @@ -66,5 +68,17 @@ value: "1.1" }) end + + it "returns suggestion tag for local target" do + create(:sdg_local_target, code: "1.1.1", title: "By 2030, eradicate extreme custom text") + suggestion = component.suggestion_tag_for(SDG::LocalTarget["1.1.1"]) + + expect(suggestion).to eq({ + tag: "1.1.1. By 2030 eradicate extreme custom text", + display_text: "1.1.1", + title: "By 2030, eradicate extreme custom text", + value: "1.1.1" + }) + end end end diff --git a/spec/models/sdg/goal_spec.rb b/spec/models/sdg/goal_spec.rb index 94d20710bf40..ac53fc049602 100644 --- a/spec/models/sdg/goal_spec.rb +++ b/spec/models/sdg/goal_spec.rb @@ -21,6 +21,34 @@ end end + describe "#<=>" do + let(:goal) { SDG::Goal[10] } + + it "can be compared against goals" do + lesser_goal = SDG::Goal[9] + greater_goal = SDG::Goal[11] + + expect(goal).to be > lesser_goal + expect(goal).to be < greater_goal + end + + it "can be compared against global targets" do + lesser_target = build(:sdg_target, code: "9.A", goal: SDG::Goal[9]) + greater_target = build(:sdg_target, code: "11.1", goal: SDG::Goal[11]) + + expect(goal).to be > lesser_target + expect(goal).to be < greater_target + end + + it "can be compared against local and global targets" do + lesser_local_target = build(:sdg_local_target, code: "9.B.12") + greater_target = build(:sdg_target, code: "11.1", goal: SDG::Goal[11]) + + expect(goal).to be > lesser_local_target + expect(goal).to be < greater_target + end + end + describe ".[]" do it "finds existing goals by code" do expect(SDG::Goal[1].code).to be 1 diff --git a/spec/models/sdg/local_target_spec.rb b/spec/models/sdg/local_target_spec.rb index bf2496728fbe..fc615ebb1164 100644 --- a/spec/models/sdg/local_target_spec.rb +++ b/spec/models/sdg/local_target_spec.rb @@ -90,6 +90,22 @@ expect(local_target).to be > lesser_target expect(local_target).to be < greater_target end + + it "can be compared against goals" do + lesser_goal = build(:sdg_goal, code: "10") + greater_goal = build(:sdg_goal, code: "11") + + expect(local_target).to be > lesser_goal + expect(local_target).to be < greater_goal + end + + it "can be compared against goals and global targets" do + lesser_goal = build(:sdg_goal, code: "10") + greater_target = build(:sdg_target, code: "11.1", goal: SDG::Goal[11]) + + expect(local_target).to be > lesser_goal + expect(local_target).to be < greater_target + end end describe ".[]" do diff --git a/spec/models/sdg/relatable_spec.rb b/spec/models/sdg/relatable_spec.rb index 4dd6aea511f4..4df51eadce99 100644 --- a/spec/models/sdg/relatable_spec.rb +++ b/spec/models/sdg/relatable_spec.rb @@ -102,9 +102,10 @@ describe "#sdg_related_list" do it "orders related list by code" do relatable.sdg_goals = [SDG::Goal[1], SDG::Goal[3], SDG::Goal[2]] - relatable.sdg_targets = [SDG::Target[2.2], SDG::Target[1.2], SDG::Target[2.1]] + local_targets = %w[2.2.2 2.2.1 3.1.1].map { |code| create(:sdg_local_target, code: code) } + relatable.sdg_targets = [SDG::Target[2.2], SDG::Target[1.2], SDG::Target[2.1]] + local_targets - expect(relatable.sdg_related_list).to eq "1, 1.2, 2, 2.1, 2.2, 3" + expect(relatable.sdg_related_list).to eq "1, 1.2, 2, 2.1, 2.2, 2.2.1, 2.2.2, 3, 3.1.1" end end @@ -133,6 +134,13 @@ expect(relatable.reload.sdg_targets).to match_array [SDG::Target[1.1]] end + it "assigns a single local target" do + relatable.sdg_related_list = local_target.code + + expect(relatable.reload.sdg_goals).to match_array [local_target.goal] + expect(relatable.reload.sdg_local_targets).to match_array [local_target] + end + it "assigns multiple targets" do relatable.sdg_related_list = "1.1,2.3" @@ -146,6 +154,14 @@ expect(relatable.reload.sdg_goals).to match_array [SDG::Goal[1], SDG::Goal[2], SDG::Goal[3]] end + it "assigns a multiple local targets" do + relatable.sdg_related_list = "#{local_target.code}, #{another_local_target.code}" + + expect(relatable.reload.sdg_goals).to match_array [local_target.goal, another_local_target.goal] + expect(relatable.reload.sdg_local_targets).to match_array [local_target, another_local_target] + end + + it "ignores trailing spaces and spaces between commas" do relatable.sdg_related_list = " 1.1, 2.3 " @@ -153,11 +169,12 @@ expect(relatable.reload.sdg_targets).to match_array [SDG::Target[1.1], SDG::Target[2.3]] end - it "assigns goals and targets" do - relatable.sdg_related_list = "1.1,3,4,4.1" + it "assigns goals, targets and local_targets" do + relatable.sdg_related_list = "1.1,3,4,4.1,#{another_local_target.code}" - expect(relatable.reload.sdg_goals).to match_array [SDG::Goal[1], SDG::Goal[3], SDG::Goal[4]] - expect(relatable.reload.sdg_targets).to match_array [SDG::Target[1.1], SDG::Target[4.1]] + expect(relatable.reload.sdg_goals).to match_array [SDG::Goal[1], another_local_target.goal, SDG::Goal[3], SDG::Goal[4]] + expect(relatable.reload.sdg_global_targets).to match_array [SDG::Target[1.1], SDG::Target[4.1]] + expect(relatable.reload.sdg_local_targets).to match_array [another_local_target] end end diff --git a/spec/models/sdg/target_spec.rb b/spec/models/sdg/target_spec.rb index d227d9954582..acff451de07f 100644 --- a/spec/models/sdg/target_spec.rb +++ b/spec/models/sdg/target_spec.rb @@ -87,6 +87,22 @@ expect(target).to be < local_target end end + + it "can be compared against goals" do + lesser_goal = build(:sdg_goal, code: "9") + greater_goal = build(:sdg_goal, code: "11") + + expect(target).to be > lesser_goal + expect(target).to be < greater_goal + end + + it "can be compared against goals and global targets" do + lesser_goal = build(:sdg_goal, code: "9") + greater_target = build(:sdg_target, code: "11.1", goal: SDG::Goal[11]) + + expect(target).to be > lesser_goal + expect(target).to be < greater_target + end end describe ".[]" do diff --git a/spec/system/sdg_management/relations_spec.rb b/spec/system/sdg_management/relations_spec.rb index 6469df2770a3..9b9b67699669 100644 --- a/spec/system/sdg_management/relations_spec.rb +++ b/spec/system/sdg_management/relations_spec.rb @@ -204,14 +204,17 @@ end describe "Edit" do - scenario "allows adding the goals and targets and marks the resource as reviewed" do + + scenario "allows adding the goals, global targets and local targets and marks the resource as reviewed" do process = create(:legislation_process, title: "SDG process") - process.sdg_goals = [SDG::Goal[3]] - process.sdg_targets = [SDG::Target[3.3]] + create(:sdg_local_target, code: "1.1.1") + create(:sdg_local_target, code: "3.3.3") + process.sdg_goals = [SDG::Goal[3], SDG::Goal[4]] + process.sdg_targets = [SDG::Target[3.3], SDG::LocalTarget["3.3.3"]] visit sdg_management_edit_legislation_process_path(process) - find(:css, ".sdg-related-list-selector-input").set("1.2, 2,") + find(:css, ".sdg-related-list-selector-input").set("1.2, 2, 1.1.1, ") click_button "Update Process" @@ -220,20 +223,22 @@ click_link "Marked as reviewed" within("tr", text: "SDG process") do - expect(page).to have_css "td", exact_text: "1.2, 3.3" - expect(page).to have_css "td", exact_text: "1, 2, 3" + expect(page).to have_css "td", exact_text: "1.1.1, 1.2, 3.3, 3.3.3" + expect(page).to have_css "td", exact_text: "1, 2, 3, 4" end end - scenario "allows removing the goals and targets" do + scenario "allows removing the goals, global target and local_targets" do process = create(:legislation_process, title: "SDG process") - process.sdg_goals = [SDG::Goal[2], SDG::Goal[3]] - process.sdg_targets = [SDG::Target[2.1], SDG::Target[3.3]] + create(:sdg_local_target, code: "1.1.1") + process.sdg_goals = [SDG::Goal[1], SDG::Goal[2], SDG::Goal[3]] + process.sdg_targets = [SDG::Target[2.1], SDG::Target[3.3], SDG::LocalTarget["1.1.1"]] visit sdg_management_edit_legislation_process_path(process) remove_sdg_goal_or_target_tag(2) remove_sdg_goal_or_target_tag(3.3) + remove_sdg_goal_or_target_tag("1.1.1") click_button "Update Process" @@ -242,14 +247,13 @@ click_link "Marked as reviewed" within("tr", text: "SDG process") do - expect(page).to have_css "td", exact_text: "2, 3" + expect(page).to have_css "td", exact_text: "1, 2, 3" expect(page).to have_css "td", exact_text: "2.1" end end scenario "does not show the review notice when resource was already reviewed" do debate = create(:sdg_review, relatable: create(:debate, title: "SDG debate")).relatable - debate.sdg_targets = [SDG::Target[3.3]] visit sdg_management_edit_debate_path(debate, filter: "sdg_reviewed") find(:css, ".sdg-related-list-selector-input").set("1.2, 2.1,") @@ -265,8 +269,9 @@ end end - scenario "allows adding the goals and targets with autocomplete" do + scenario "allows adding the goals, global targets and local targets with autocomplete" do process = create(:legislation_process, title: "SDG process") + create(:sdg_local_target, code: "1.1.1") visit sdg_management_edit_legislation_process_path(process) fill_in "Sustainable Development Goals and Targets", with: "3" @@ -279,12 +284,17 @@ within(".amsify-suggestags-input-area") { expect(page).to have_content "1.1" } + fill_in "Sustainable Development Goals and Targets", with: "1.1.1" + within(".amsify-list") { find(:css, "[data-val='1.1.1']").click } + + within(".amsify-suggestags-input-area") { expect(page).to have_content "1.1.1" } + click_button "Update Process" click_link "Marked as reviewed" within("tr", text: "SDG process") do expect(page).to have_css "td", exact_text: "1, 3" - expect(page).to have_css "td", exact_text: "1.1" + expect(page).to have_css "td", exact_text: "1.1, 1.1.1" end end @@ -338,8 +348,9 @@ scenario "when remove a last tag related to a Goal, the icon will not be checked" do process = create(:legislation_process, title: "SDG process") + create(:sdg_local_target, code: "1.1.1") process.sdg_goals = [SDG::Goal[1]] - process.sdg_targets = [SDG::Target[1.1]] + process.sdg_targets = [SDG::Target[1.1], SDG::LocalTarget["1.1.1"]] visit sdg_management_edit_legislation_process_path(process) remove_sdg_goal_or_target_tag(1) @@ -348,6 +359,10 @@ remove_sdg_goal_or_target_tag(1.1) + expect(find("li[data-code='1']")["aria-checked"]).to eq "true" + + remove_sdg_goal_or_target_tag("1.1.1") + expect(find("li[data-code='1']")["aria-checked"]).to eq "false" end end