row">
-
+ <%= link_to t("welcome.feed.see_all_proposals"), see_all_path, class: "see-all" %>
+
diff --git a/app/components/widgets/feeds/proposals_component.rb b/app/components/widgets/feeds/proposals_component.rb
index d799c55160bd..6edbed128feb 100644
--- a/app/components/widgets/feeds/proposals_component.rb
+++ b/app/components/widgets/feeds/proposals_component.rb
@@ -1,7 +1,2 @@
-class Widgets::Feeds::ProposalsComponent < ApplicationComponent
- attr_reader :feed
-
- def initialize(feed)
- @feed = feed
- end
+class Widgets::Feeds::ProposalsComponent < Widgets::Feeds::DebatesComponent
end
diff --git a/app/controllers/sdg/goals_controller.rb b/app/controllers/sdg/goals_controller.rb
new file mode 100644
index 000000000000..595add701bd4
--- /dev/null
+++ b/app/controllers/sdg/goals_controller.rb
@@ -0,0 +1,12 @@
+class SDG::GoalsController < ApplicationController
+ include FeatureFlags
+ feature_flag :sdg
+ load_and_authorize_resource find_by: :code, id_param: :code
+
+ def index
+ @goals = @goals.order(:code)
+ end
+
+ def show
+ end
+end
diff --git a/app/models/abilities/everyone.rb b/app/models/abilities/everyone.rb
index 432099150a2f..5f9dcb3a57ce 100644
--- a/app/models/abilities/everyone.rb
+++ b/app/models/abilities/everyone.rb
@@ -27,6 +27,8 @@ def initialize(user)
can [:read], Legislation::Question
can [:read, :map, :share], Legislation::Proposal
can [:search, :comments, :read, :create, :new_comment], Legislation::Annotation
+
+ can :read, ::SDG::Goal
end
end
end
diff --git a/app/models/abilities/sdg/manager.rb b/app/models/abilities/sdg/manager.rb
index 8d28e0f304dd..62237e49e89b 100644
--- a/app/models/abilities/sdg/manager.rb
+++ b/app/models/abilities/sdg/manager.rb
@@ -5,7 +5,6 @@ class SDG::Manager
def initialize(user)
merge Abilities::Common.new(user)
- can :read, ::SDG::Goal
can :read, ::SDG::Target
end
end
diff --git a/app/models/sdg/widget/feed.rb b/app/models/sdg/widget/feed.rb
new file mode 100644
index 000000000000..824e253017f5
--- /dev/null
+++ b/app/models/sdg/widget/feed.rb
@@ -0,0 +1,17 @@
+class SDG::Widget::Feed
+ attr_reader :feed, :goal
+ delegate :kind, to: :feed
+
+ def initialize(feed, goal)
+ @feed = feed
+ @goal = goal
+ end
+
+ def items
+ feed.items.by_goal(goal)
+ end
+
+ def self.for_goal(goal)
+ ::Widget::Feed.active.map { |feed| new(feed, goal) }
+ end
+end
diff --git a/app/views/sdg/goals/index.html.erb b/app/views/sdg/goals/index.html.erb
new file mode 100644
index 000000000000..7dfb01513f8c
--- /dev/null
+++ b/app/views/sdg/goals/index.html.erb
@@ -0,0 +1 @@
+<%= render SDG::Goals::IndexComponent.new(@goals) %>
diff --git a/app/views/sdg/goals/show.html.erb b/app/views/sdg/goals/show.html.erb
new file mode 100644
index 000000000000..2eb018511796
--- /dev/null
+++ b/app/views/sdg/goals/show.html.erb
@@ -0,0 +1 @@
+<%= render SDG::Goals::ShowComponent.new(@goal) %>
diff --git a/app/views/shared/_subnavigation.html.erb b/app/views/shared/_subnavigation.html.erb
index 95553b4a4800..4a393e50a9e4 100644
--- a/app/views/shared/_subnavigation.html.erb
+++ b/app/views/shared/_subnavigation.html.erb
@@ -42,12 +42,20 @@
accesskey: "5" %>
<% end %>
+ <% if feature?(:sdg) %>
+
+ <%= layout_menu_link_to t("layouts.header.sdg"),
+ sdg_goals_path,
+ controller_path.split("/").first == "sdg",
+ accesskey: "6" %>
+
+ <% end %>
<% if feature?(:help_page) %>
<%= layout_menu_link_to t("layouts.header.help"),
help_path,
current_page?(help_path),
- accesskey: "6" %>
+ accesskey: "7" %>
<% end %>
diff --git a/app/views/welcome/index.html.erb b/app/views/welcome/index.html.erb
index fafbcafbbc4e..94e3a04b2ba5 100644
--- a/app/views/welcome/index.html.erb
+++ b/app/views/welcome/index.html.erb
@@ -19,7 +19,7 @@
<% if @cards.any? %>
">
-
<%= t("welcome.cards.title") %>
+ <%= t("welcome.cards.title") %>
<%= render "shared/cards" %>
diff --git a/config/locales/en/general.yml b/config/locales/en/general.yml
index 5a47cdb64748..a1c7a886ce56 100644
--- a/config/locales/en/general.yml
+++ b/config/locales/en/general.yml
@@ -251,6 +251,7 @@ en:
other: You have %{count} new notifications
notifications: Notifications
no_notifications: "You don't have new notifications"
+ sdg: "SDG"
notifications:
index:
empty_notifications: You don't have new notifications.
diff --git a/config/locales/es/general.yml b/config/locales/es/general.yml
index 7f7b2b7139c4..b9da8ab10f62 100644
--- a/config/locales/es/general.yml
+++ b/config/locales/es/general.yml
@@ -251,6 +251,7 @@ es:
other: Tienes %{count} notificaciones nuevas
notifications: Notificaciones
no_notifications: "No tienes notificaciones nuevas"
+ sdg: "ODS"
notifications:
index:
empty_notifications: No tienes notificaciones nuevas.
diff --git a/config/routes.rb b/config/routes.rb
index aeb715684a31..acbdf90d143a 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -21,6 +21,7 @@
draw :poll
draw :proposal
draw :related_content
+ draw :sdg
draw :sdg_management
draw :tag
draw :user
diff --git a/config/routes/sdg.rb b/config/routes/sdg.rb
new file mode 100644
index 000000000000..52525c685743
--- /dev/null
+++ b/config/routes/sdg.rb
@@ -0,0 +1,3 @@
+namespace :sdg do
+ resources :goals, param: :code, only: [:index, :show]
+end
diff --git a/spec/components/widgets/feeds/debates_component_spec.rb b/spec/components/widgets/feeds/debates_component_spec.rb
new file mode 100644
index 000000000000..1bd90c40757d
--- /dev/null
+++ b/spec/components/widgets/feeds/debates_component_spec.rb
@@ -0,0 +1,23 @@
+require "rails_helper"
+
+describe Widgets::Feeds::DebatesComponent, type: :component do
+ describe "#see_all_path" do
+ let(:feed) { Widget::Feed.new(kind: "debates") }
+
+ it "points to the debates path for homepage feeds" do
+ component = Widgets::Feeds::DebatesComponent.new(feed)
+
+ render_inline component
+
+ expect(component.see_all_path).to eq "/debates"
+ end
+
+ it "points to the debates filtered by goal for goal feeds" do
+ component = Widgets::Feeds::DebatesComponent.new(SDG::Widget::Feed.new(feed, SDG::Goal[6]))
+
+ render_inline component
+
+ expect(component.see_all_path).to eq "/debates?advanced_search#{CGI.escape("[goal]")}=6"
+ end
+ end
+end
diff --git a/spec/controllers/sdg/goals_spec.rb b/spec/controllers/sdg/goals_spec.rb
new file mode 100644
index 000000000000..f72c283ddad8
--- /dev/null
+++ b/spec/controllers/sdg/goals_spec.rb
@@ -0,0 +1,13 @@
+require 'rails_helper'
+
+describe SDG::GoalsController do
+ context "featured disabled" do
+ before do
+ Setting["feature.sdg"] = false
+ end
+
+ it "raises feature disabled" do
+ expect { get :index }.to raise_exception(FeatureFlags::FeatureDisabled)
+ end
+ end
+end
diff --git a/spec/models/abilities/administrator_spec.rb b/spec/models/abilities/administrator_spec.rb
index f237964dc554..873768d87fd0 100644
--- a/spec/models/abilities/administrator_spec.rb
+++ b/spec/models/abilities/administrator_spec.rb
@@ -107,7 +107,6 @@
it { should be_able_to(:create, LocalCensusRecords::Import) }
it { should be_able_to(:show, LocalCensusRecords::Import) }
- it { should be_able_to(:read, SDG::Goal) }
it { should be_able_to(:read, SDG::Target) }
it { should be_able_to(:read, SDG::Manager) }
diff --git a/spec/models/abilities/common_spec.rb b/spec/models/abilities/common_spec.rb
index 33611601280e..b060f594490c 100644
--- a/spec/models/abilities/common_spec.rb
+++ b/spec/models/abilities/common_spec.rb
@@ -305,7 +305,6 @@
it { should be_able_to(:disable_recommendations, Proposal) }
end
- it { should_not be_able_to(:read, SDG::Goal) }
it { should_not be_able_to(:read, SDG::Target) }
it { should_not be_able_to(:read, SDG::Manager) }
diff --git a/spec/models/abilities/everyone_spec.rb b/spec/models/abilities/everyone_spec.rb
index a5399e25b902..81b82dcd5fa2 100644
--- a/spec/models/abilities/everyone_spec.rb
+++ b/spec/models/abilities/everyone_spec.rb
@@ -53,7 +53,7 @@
it { should_not be_able_to(:summary, create(:legislation_process, :open)) }
it { should_not be_able_to(:summary, create(:legislation_process, :past, :not_published)) }
- it { should_not be_able_to(:read, SDG::Goal) }
+ it { should be_able_to(:read, SDG::Goal) }
it { should_not be_able_to(:read, SDG::Target) }
it { should_not be_able_to(:read, SDG::Manager) }
diff --git a/spec/models/abilities/moderator_spec.rb b/spec/models/abilities/moderator_spec.rb
index 76258353409c..1b2bd4f48b23 100644
--- a/spec/models/abilities/moderator_spec.rb
+++ b/spec/models/abilities/moderator_spec.rb
@@ -109,7 +109,6 @@
it { should_not be_able_to(:comment_as_administrator, legislation_question) }
end
- it { should_not be_able_to(:read, SDG::Goal) }
it { should_not be_able_to(:read, SDG::Target) }
it { should_not be_able_to(:read, SDG::Manager) }
diff --git a/spec/models/abilities/organization_spec.rb b/spec/models/abilities/organization_spec.rb
index 2553b3f181f3..874a5ce40499 100644
--- a/spec/models/abilities/organization_spec.rb
+++ b/spec/models/abilities/organization_spec.rb
@@ -23,7 +23,6 @@
it { should be_able_to(:create, Comment) }
it { should_not be_able_to(:vote, Comment) }
- it { should_not be_able_to(:read, SDG::Goal) }
it { should_not be_able_to(:read, SDG::Target) }
it { should_not be_able_to(:read, SDG::Manager) }
diff --git a/spec/models/abilities/sdg/manager.rb b/spec/models/abilities/sdg/manager.rb
index 004ad0adad1f..43e1e20f4365 100644
--- a/spec/models/abilities/sdg/manager.rb
+++ b/spec/models/abilities/sdg/manager.rb
@@ -7,7 +7,6 @@
let(:user) { sdg_manager.user }
let(:sdg_manager) { create(:sdg_manager) }
- it { should be_able_to(:read, SDG::Goal) }
it { should be_able_to(:read, SDG::Target) }
it { should_not be_able_to(:read, SDG::Manager) }
diff --git a/spec/models/abilities/valuator_spec.rb b/spec/models/abilities/valuator_spec.rb
index 634dd7e9282f..328c1cb48634 100644
--- a/spec/models/abilities/valuator_spec.rb
+++ b/spec/models/abilities/valuator_spec.rb
@@ -40,7 +40,6 @@
it { should_not be_able_to(:comment_valuation, assigned_investment) }
end
- it { should_not be_able_to(:read, SDG::Goal) }
it { should_not be_able_to(:read, SDG::Target) }
it { should_not be_able_to(:read, SDG::Manager) }
diff --git a/spec/routing/sdg_routes_spec.rb b/spec/routing/sdg_routes_spec.rb
new file mode 100644
index 000000000000..24487fc46a1a
--- /dev/null
+++ b/spec/routing/sdg_routes_spec.rb
@@ -0,0 +1,22 @@
+require "rails_helper"
+
+describe "SDG routes" do
+ it "maps goals to their code" do
+ expect(get("/sdg/goals/1")).to route_to(
+ controller: "sdg/goals",
+ action: "show",
+ code: "1"
+ )
+ end
+
+ it "requires using the code instead of the ID when the ID is different" do
+ SDG::Goal[2].destroy!
+ SDG::Goal.create!(code: 2)
+
+ expect(get(sdg_goal_path(SDG::Goal[2].code))).to route_to(
+ controller: "sdg/goals",
+ action: "show",
+ code: "2"
+ )
+ end
+end
diff --git a/spec/system/sdg/goals_spec.rb b/spec/system/sdg/goals_spec.rb
new file mode 100644
index 000000000000..f6e326842b46
--- /dev/null
+++ b/spec/system/sdg/goals_spec.rb
@@ -0,0 +1,66 @@
+require "rails_helper"
+
+describe "SDG Goals" do
+ before do
+ Setting["feature.sdg"] = true
+ end
+
+ describe "SDG navigation link" do
+ scenario "is not present when the feature is disabled" do
+ Setting["feature.sdg"] = false
+
+ visit root_path
+
+ within("#navigation_bar") { expect(page).not_to have_link "SDG" }
+ end
+
+ scenario "routes to the goals index" do
+ visit root_path
+ within("#navigation_bar") { click_link "SDG" }
+
+ expect(page).to have_current_path sdg_goals_path
+ end
+ end
+
+ describe "Index" do
+ scenario "has links to SDGs" do
+ visit sdg_goals_path
+
+ click_link "7. Affordable and Clean Energy"
+
+ expect(page).to have_current_path sdg_goal_path(7)
+ end
+ end
+
+ describe "Show" do
+ scenario "shows the SDG and its related content" do
+ goal = SDG::Goal[15]
+
+ create(:debate, title: "Solar panels", sdg_goals: [SDG::Goal[7]])
+ create(:debate, title: "Hunting ground", sdg_goals: [goal])
+ create(:proposal, title: "Animal farm", sdg_goals: [goal])
+ create(:proposal, title: "Sea farm", sdg_goals: [SDG::Goal[14]])
+ create(:legislation_process, title: "Bullfighting regulations", sdg_goals: [goal])
+ create(:legislation_process, title: "Tax regulations", sdg_goals: [SDG::Goal[10]])
+
+ visit sdg_goal_path(15)
+
+ within(".sdg-goal header") { expect(page).to have_content "Life on Land" }
+
+ within ".feed-proposals" do
+ expect(page).to have_content "Animal farm"
+ expect(page).not_to have_content "Sea farm"
+ end
+
+ within ".feed-debates" do
+ expect(page).to have_content "Hunting ground"
+ expect(page).not_to have_content "Solar panels"
+ end
+
+ within ".feed-processes" do
+ expect(page).to have_content "Bullfighting regulations"
+ expect(page).not_to have_content "Tax regulations"
+ end
+ end
+ end
+end