diff --git a/app/components/sdg_management/homepage/show_component.rb b/app/components/sdg_management/homepage/show_component.rb
index e5dbaf6cf..08865e461 100644
--- a/app/components/sdg_management/homepage/show_component.rb
+++ b/app/components/sdg_management/homepage/show_component.rb
@@ -1,9 +1,10 @@
class SDGManagement::Homepage::ShowComponent < ApplicationComponent
include Header
- attr_reader :phases
+ attr_reader :header_card, :phases
- def initialize(phases)
+ def initialize(header_card, phases)
+ @header_card = header_card
@phases = phases
end
diff --git a/app/controllers/concerns/admin/widget/cards_actions.rb b/app/controllers/concerns/admin/widget/cards_actions.rb
index b089ca1a0..bcd39cf7e 100644
--- a/app/controllers/concerns/admin/widget/cards_actions.rb
+++ b/app/controllers/concerns/admin/widget/cards_actions.rb
@@ -3,6 +3,10 @@ module Admin::Widget::CardsActions
include Translatable
include ImageAttributes
+ included do
+ helper_method :form_path
+ end
+
def new
@card.header = header_card?
render template: "#{cards_view_path}/new"
@@ -56,4 +60,8 @@ module Admin::Widget::CardsActions
def cards_view_path
"admin/widget/cards"
end
+
+ def form_path
+ nil
+ end
end
diff --git a/app/controllers/sdg/goals_controller.rb b/app/controllers/sdg/goals_controller.rb
index 05dfb309c..1c34983c8 100644
--- a/app/controllers/sdg/goals_controller.rb
+++ b/app/controllers/sdg/goals_controller.rb
@@ -6,6 +6,7 @@ class SDG::GoalsController < ApplicationController
def index
@goals = @goals.order(:code)
@phases = SDG::Phase.accessible_by(current_ability).order(:kind)
+ @header = WebSection.find_by!(name: "sdg").header
end
def show
diff --git a/app/controllers/sdg_management/header_controller.rb b/app/controllers/sdg_management/header_controller.rb
new file mode 100644
index 000000000..f3bf73ae3
--- /dev/null
+++ b/app/controllers/sdg_management/header_controller.rb
@@ -0,0 +1,29 @@
+class SDGManagement::HeaderController < SDGManagement::BaseController
+ include Admin::Widget::CardsActions
+ helper_method :index_path
+
+ before_action :load_cardable
+ load_and_authorize_resource :header,
+ class: "Widget::Card",
+ through: :cardable,
+ singleton: true,
+ instance_name: :card
+
+ private
+
+ def load_cardable
+ @cardable = WebSection.find_by!(name: "sdg")
+ end
+
+ def index_path
+ sdg_management_homepage_path
+ end
+
+ def form_path
+ sdg_management_homepage_header_path
+ end
+
+ def header_params
+ card_params
+ end
+end
diff --git a/app/controllers/sdg_management/homepage_controller.rb b/app/controllers/sdg_management/homepage_controller.rb
index 4f9d67109..9b823e278 100644
--- a/app/controllers/sdg_management/homepage_controller.rb
+++ b/app/controllers/sdg_management/homepage_controller.rb
@@ -1,5 +1,6 @@
class SDGManagement::HomepageController < SDGManagement::BaseController
def show
@phases = SDG::Phase.accessible_by(current_ability).order(:kind)
+ @card = WebSection.find_by!(name: "sdg").header
end
end
diff --git a/app/models/abilities/sdg/manager.rb b/app/models/abilities/sdg/manager.rb
index a3264c9f3..3958238cd 100644
--- a/app/models/abilities/sdg/manager.rb
+++ b/app/models/abilities/sdg/manager.rb
@@ -6,7 +6,9 @@ class Abilities::SDG::Manager
can :read, ::SDG::Target
can :manage, ::SDG::LocalTarget
- can [:read, :update, :destroy], Widget::Card, cardable_type: "SDG::Phase"
- can(:create, Widget::Card) { |card| card.cardable_type == "SDG::Phase" }
+ can :read, WebSection, name: "sdg"
+ can [:create, :update, :destroy], Widget::Card do |card|
+ card.cardable_type == "SDG::Phase" || card.cardable&.name == "sdg"
+ end
end
end
diff --git a/app/models/web_section.rb b/app/models/web_section.rb
index 3c2dd5790..e68ce2804 100644
--- a/app/models/web_section.rb
+++ b/app/models/web_section.rb
@@ -1,4 +1,5 @@
class WebSection < ApplicationRecord
has_many :sections
has_many :banners, through: :sections
+ has_one :header, class_name: "Widget::Card", as: :cardable, dependent: :destroy
end
diff --git a/app/views/admin/widget/cards/_form.html.erb b/app/views/admin/widget/cards/_form.html.erb
index a2bf520a5..1faf4c3ee 100644
--- a/app/views/admin/widget/cards/_form.html.erb
+++ b/app/views/admin/widget/cards/_form.html.erb
@@ -1,6 +1,6 @@
<%= render "shared/globalize_locales", resource: card %>
-<%= translatable_form_for [namespace, card.cardable, card] do |f| %>
+<%= translatable_form_for [namespace, card.cardable, card], url: local_assigns[:url] do |f| %>
<%= render "shared/errors", resource: card %>
diff --git a/app/views/admin/widget/cards/edit.html.erb b/app/views/admin/widget/cards/edit.html.erb
index c95b6fb7d..e26773ee2 100644
--- a/app/views/admin/widget/cards/edit.html.erb
+++ b/app/views/admin/widget/cards/edit.html.erb
@@ -1 +1 @@
-<%= render Admin::Widget::Cards::EditComponent.new(@card, index_path: index_path) %>
+<%= render Admin::Widget::Cards::EditComponent.new(@card, index_path: index_path, form_path: form_path) %>
diff --git a/app/views/admin/widget/cards/new.html.erb b/app/views/admin/widget/cards/new.html.erb
index d25857cef..7e1b8b5d2 100644
--- a/app/views/admin/widget/cards/new.html.erb
+++ b/app/views/admin/widget/cards/new.html.erb
@@ -1 +1 @@
-<%= render Admin::Widget::Cards::NewComponent.new(@card, index_path: index_path) %>
+<%= render Admin::Widget::Cards::NewComponent.new(@card, index_path: index_path, form_path: form_path) %>
diff --git a/app/views/sdg/goals/index.html.erb b/app/views/sdg/goals/index.html.erb
index b38a0eebd..9cd046de3 100644
--- a/app/views/sdg/goals/index.html.erb
+++ b/app/views/sdg/goals/index.html.erb
@@ -1 +1 @@
-<%= render SDG::Goals::IndexComponent.new(@goals, @phases) %>
+<%= render SDG::Goals::IndexComponent.new(@goals, header: @header, phases: @phases) %>
diff --git a/app/views/sdg_management/homepage/show.html.erb b/app/views/sdg_management/homepage/show.html.erb
index f76456364..0e578e0d0 100644
--- a/app/views/sdg_management/homepage/show.html.erb
+++ b/app/views/sdg_management/homepage/show.html.erb
@@ -1 +1 @@
-<%= render SDGManagement::Homepage::ShowComponent.new(@phases) %>
+<%= render SDGManagement::Homepage::ShowComponent.new(@card, @phases) %>
diff --git a/app/views/welcome/_header.html.erb b/app/views/shared/_header.html.erb
similarity index 100%
rename from app/views/welcome/_header.html.erb
rename to app/views/shared/_header.html.erb
diff --git a/app/views/welcome/index.html.erb b/app/views/welcome/index.html.erb
index 8c2611397..c31ab5398 100644
--- a/app/views/welcome/index.html.erb
+++ b/app/views/welcome/index.html.erb
@@ -11,7 +11,7 @@
social_url: root_url %>
<% end %>
-<%= render "header", header: @header %>
+<%= render "shared/header", header: @header %>
<%= render "feeds" %>
diff --git a/config/locales/en/sdg_management.yml b/config/locales/en/sdg_management.yml
index d132f0dac..89afa448c 100644
--- a/config/locales/en/sdg_management.yml
+++ b/config/locales/en/sdg_management.yml
@@ -6,6 +6,10 @@ en:
title: "SDG content"
homepage:
title: "Homepage configuration"
+ header:
+ create: "Create header"
+ no_cards: "There is no header"
+ title: "Header"
create_card: "Create %{phase} card"
no_cards: "There are no cards for this phase"
menu:
diff --git a/config/locales/es/sdg_management.yml b/config/locales/es/sdg_management.yml
index fc4dbf05f..fd19e5f25 100644
--- a/config/locales/es/sdg_management.yml
+++ b/config/locales/es/sdg_management.yml
@@ -6,6 +6,10 @@ es:
title: "Contenido ODS"
homepage:
title: "Configuración de la pÔgina de inicio"
+ header:
+ create: "Crear cabecera"
+ no_cards: "No hay cabecera"
+ title: "Cabecera"
create_card: "Crear tarjeta de %{phase}"
no_cards: "No hay tarjetas para esta fase"
menu:
diff --git a/config/routes/sdg_management.rb b/config/routes/sdg_management.rb
index c8816ad56..d048bc2d1 100644
--- a/config/routes/sdg_management.rb
+++ b/config/routes/sdg_management.rb
@@ -4,7 +4,9 @@ namespace :sdg_management do
resources :goals, only: [:index]
resources :targets, only: [:index]
resources :local_targets, except: [:show]
- resource :homepage, controller: :homepage, only: [:show]
+ resource :homepage, controller: :homepage, only: [:show] do
+ resource :header, controller: :header, only: [:new, :create, :edit, :update, :destroy]
+ end
resources :phases, only: [], as: :sdg_phases do
resources :cards, except: [:index, :show], as: :widget_cards
diff --git a/spec/components/sdg/goals/index_component_spec.rb b/spec/components/sdg/goals/index_component_spec.rb
index 2c756ccff..4caffb3ce 100644
--- a/spec/components/sdg/goals/index_component_spec.rb
+++ b/spec/components/sdg/goals/index_component_spec.rb
@@ -3,16 +3,29 @@ require "rails_helper"
describe SDG::Goals::IndexComponent, type: :component do
let!(:goals) { SDG::Goal.all }
let!(:phases) { SDG::Phase.all }
- let!(:component) { SDG::Goals::IndexComponent.new(goals, phases) }
+ let!(:component) { SDG::Goals::IndexComponent.new(goals, header: nil, phases: phases) }
before do
Setting["feature.sdg"] = true
end
- it "renders a heading" do
- render_inline component
+ describe "header" do
+ it "renders the default header when a custom one is not defined" do
+ render_inline component
- expect(page).to have_css "h1", exact_text: "Sustainable Development Goals"
+ expect(page).to have_css "h1", exact_text: "Sustainable Development Goals"
+ end
+
+ it "renders a custom header" do
+ sdg_web_section = WebSection.find_by!(name: "sdg")
+ header = create(:widget_card, cardable: sdg_web_section)
+ component = SDG::Goals::IndexComponent.new(goals, header: header, phases: phases)
+
+ render_inline component
+
+ expect(page).to have_content header.title
+ expect(page).not_to have_css "h1", exact_text: "Sustainable Development Goals"
+ end
end
it "renders phases" do
diff --git a/spec/models/abilities/sdg/manager_spec.rb b/spec/models/abilities/sdg/manager_spec.rb
index fa4febb16..fafd274d1 100644
--- a/spec/models/abilities/sdg/manager_spec.rb
+++ b/spec/models/abilities/sdg/manager_spec.rb
@@ -9,13 +9,19 @@ describe "Abilities::SDG::Manager" do
it { should be_able_to(:read, SDG::Target) }
it { should be_able_to(:manage, SDG::LocalTarget) }
+ it { should be_able_to(:read, WebSection.find_by!(name: "sdg")) }
it { should_not be_able_to(:read, SDG::Manager) }
it { should_not be_able_to(:create, SDG::Manager) }
it { should_not be_able_to(:delete, SDG::Manager) }
+ it { should_not be_able_to(:read, WebSection.find_by!(name: "homepage")) }
it { should_not be_able_to(:update, create(:widget_card)) }
it { should be_able_to(:update, create(:widget_card, cardable: SDG::Phase.sample)) }
+ it { should be_able_to(:update, create(:widget_card, cardable: WebSection.find_by!(name: "sdg"))) }
+ it { should_not be_able_to(:update, create(:widget_card, cardable: WebSection.find_by!(name: "homepage"))) }
it { should_not be_able_to(:create, build(:widget_card)) }
it { should be_able_to(:create, build(:widget_card, cardable: SDG::Phase.sample)) }
+ it { should be_able_to(:create, build(:widget_card, cardable: WebSection.find_by!(name: "sdg"))) }
+ it { should_not be_able_to(:create, build(:widget_card, cardable: WebSection.find_by!(name: "homepage"))) }
end
diff --git a/spec/system/sdg_management/homepage_spec.rb b/spec/system/sdg_management/homepage_spec.rb
index 598066adc..3bc74550d 100644
--- a/spec/system/sdg_management/homepage_spec.rb
+++ b/spec/system/sdg_management/homepage_spec.rb
@@ -48,5 +48,42 @@ describe "SDG homepage configuration", :js do
expect(page).not_to have_content "My monitoring card"
end
end
+
+ scenario "Create header card" do
+ visit sdg_management_homepage_path
+ click_link "Create header"
+
+ within(".translatable-fields") { fill_in "Title", with: "My header" }
+ click_button "Create card"
+
+ within(".sdg-header") do
+ expect(page).to have_content "My header"
+ expect(page).not_to have_content "Create header"
+ end
+ end
+
+ scenario "Update header card" do
+ create(:widget_card, cardable: WebSection.find_by!(name: "sdg"))
+ visit sdg_management_homepage_path
+ within ".sdg-header" do
+ click_link "Edit"
+ end
+
+ within(".translatable-fields") { fill_in "Title", with: "My header update" }
+ click_button "Save card"
+
+ expect(page).to have_content "My header update"
+ end
+
+ scenario "Remove header card" do
+ create(:widget_card, title: "SDG Header", cardable: WebSection.find_by!(name: "sdg"))
+ visit sdg_management_homepage_path
+
+ within ".sdg-header" do
+ accept_confirm { click_link "Delete" }
+ end
+
+ expect(page).not_to have_content "SDG Header"
+ end
end
end