diff --git a/app/assets/stylesheets/sdg/goals/index.scss b/app/assets/stylesheets/sdg/goals/index.scss index b20bdcd35..5c0ea1553 100644 --- a/app/assets/stylesheets/sdg/goals/index.scss +++ b/app/assets/stylesheets/sdg/goals/index.scss @@ -47,4 +47,8 @@ @include grid-row-nest; } } + + .background-header { + margin-bottom: $line-height; + } } diff --git a/app/assets/stylesheets/sdg_management/homepage/show.scss b/app/assets/stylesheets/sdg_management/homepage/show.scss index 098e8e311..c586aa7fa 100644 --- a/app/assets/stylesheets/sdg_management/homepage/show.scss +++ b/app/assets/stylesheets/sdg_management/homepage/show.scss @@ -1,3 +1,4 @@ +.sdg-header, .phase-cards { > header { align-items: flex-start; diff --git a/app/components/admin/widget/cards/edit_component.html.erb b/app/components/admin/widget/cards/edit_component.html.erb index 745988b90..62fa5d2dd 100644 --- a/app/components/admin/widget/cards/edit_component.html.erb +++ b/app/components/admin/widget/cards/edit_component.html.erb @@ -1,3 +1,3 @@ <%= back_link_to index_path %> <%= header %> -<%= render "admin/widget/cards/form", card: card %> +<%= render "admin/widget/cards/form", card: card, url: form_path %> diff --git a/app/components/admin/widget/cards/edit_component.rb b/app/components/admin/widget/cards/edit_component.rb index 8dd728ffe..5a5734f0a 100644 --- a/app/components/admin/widget/cards/edit_component.rb +++ b/app/components/admin/widget/cards/edit_component.rb @@ -1,10 +1,11 @@ class Admin::Widget::Cards::EditComponent < ApplicationComponent include Header - attr_reader :card, :index_path + attr_reader :card, :index_path, :form_path - def initialize(card, index_path:) + def initialize(card, index_path:, form_path: nil) @card = card @index_path = index_path + @form_path = form_path end private diff --git a/app/components/admin/widget/cards/new_component.html.erb b/app/components/admin/widget/cards/new_component.html.erb index 745988b90..62fa5d2dd 100644 --- a/app/components/admin/widget/cards/new_component.html.erb +++ b/app/components/admin/widget/cards/new_component.html.erb @@ -1,3 +1,3 @@ <%= back_link_to index_path %> <%= header %> -<%= render "admin/widget/cards/form", card: card %> +<%= render "admin/widget/cards/form", card: card, url: form_path %> diff --git a/app/components/admin/widget/cards/new_component.rb b/app/components/admin/widget/cards/new_component.rb index 810ade51a..5e195f9d4 100644 --- a/app/components/admin/widget/cards/new_component.rb +++ b/app/components/admin/widget/cards/new_component.rb @@ -1,10 +1,11 @@ class Admin::Widget::Cards::NewComponent < ApplicationComponent include Header - attr_reader :card, :index_path + attr_reader :card, :index_path, :form_path - def initialize(card, index_path:) + def initialize(card, index_path:, form_path: nil) @card = card @index_path = index_path + @form_path = form_path end private diff --git a/app/components/admin/widget/cards/row_component.html.erb b/app/components/admin/widget/cards/row_component.html.erb index 94025a7b1..974753dc8 100644 --- a/app/components/admin/widget/cards/row_component.html.erb +++ b/app/components/admin/widget/cards/row_component.html.erb @@ -17,6 +17,6 @@ <% end %> - <%= render Admin::TableActionsComponent.new(card) %> + <%= render Admin::TableActionsComponent.new(card, options) %> diff --git a/app/components/admin/widget/cards/row_component.rb b/app/components/admin/widget/cards/row_component.rb index fed569949..58343d41f 100644 --- a/app/components/admin/widget/cards/row_component.rb +++ b/app/components/admin/widget/cards/row_component.rb @@ -1,7 +1,8 @@ class Admin::Widget::Cards::RowComponent < ApplicationComponent - attr_reader :card + attr_reader :card, :options - def initialize(card) + def initialize(card, **options) @card = card + @options = options end end diff --git a/app/components/admin/widget/cards/table_component.html.erb b/app/components/admin/widget/cards/table_component.html.erb index d7fc9e579..3a3cf9720 100644 --- a/app/components/admin/widget/cards/table_component.html.erb +++ b/app/components/admin/widget/cards/table_component.html.erb @@ -11,7 +11,7 @@ <% cards.each do |card| %> - <%= render Admin::Widget::Cards::RowComponent.new(card) %> + <%= render Admin::Widget::Cards::RowComponent.new(card, options) %> <% end %> diff --git a/app/components/admin/widget/cards/table_component.rb b/app/components/admin/widget/cards/table_component.rb index eba23de30..efdb279c7 100644 --- a/app/components/admin/widget/cards/table_component.rb +++ b/app/components/admin/widget/cards/table_component.rb @@ -1,9 +1,10 @@ class Admin::Widget::Cards::TableComponent < ApplicationComponent - attr_reader :cards, :no_cards_message + attr_reader :cards, :no_cards_message, :options - def initialize(cards, no_cards_message:) + def initialize(cards, no_cards_message:, **options) @cards = cards @no_cards_message = no_cards_message + @options = options end private diff --git a/app/components/sdg/goals/index_component.html.erb b/app/components/sdg/goals/index_component.html.erb index 81c7c3c02..98eb1af1b 100644 --- a/app/components/sdg/goals/index_component.html.erb +++ b/app/components/sdg/goals/index_component.html.erb @@ -1,9 +1,13 @@ <% provide(:title) { title } %>
-
-

<%= title %>

-
+ <% if header.present? %> + <%= render "shared/header", header: header %> + <% else %> +
+

<%= title %>

+
+ <% end %> <%= render Shared::BannerComponent.new("sdg") %> diff --git a/app/components/sdg/goals/index_component.rb b/app/components/sdg/goals/index_component.rb index f9715d01a..8dbfe147c 100644 --- a/app/components/sdg/goals/index_component.rb +++ b/app/components/sdg/goals/index_component.rb @@ -1,9 +1,10 @@ class SDG::Goals::IndexComponent < ApplicationComponent - attr_reader :goals, :phases + attr_reader :goals, :header, :phases delegate :link_list, to: :helpers - def initialize(goals, phases) + def initialize(goals, header:, phases:) @goals = goals + @header = header @phases = phases end diff --git a/app/components/sdg_management/homepage/show_component.html.erb b/app/components/sdg_management/homepage/show_component.html.erb index 53046b11b..232fe4155 100644 --- a/app/components/sdg_management/homepage/show_component.html.erb +++ b/app/components/sdg_management/homepage/show_component.html.erb @@ -1,5 +1,22 @@ <%= header %> +
+
+

<%= t("sdg_management.homepage.header.title") %>

+ + <% unless header_card %> + <%= link_to t("sdg_management.homepage.header.create"), new_sdg_management_homepage_header_path %> + <% end %> +
+ + <%= render Admin::Widget::Cards::TableComponent.new( + [header_card], + edit_path: edit_sdg_management_homepage_header_path, + destroy_path: sdg_management_homepage_header_path, + no_cards_message: t("sdg_management.homepage.header.no_cards") + ) %> +
+ <% phases.each do |phase| %>
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