From 2e79183ff906bd7f541cab0dc4f4bd9e4d1a8005 Mon Sep 17 00:00:00 2001 From: Alex Newton Date: Wed, 8 Jan 2025 12:09:45 +0000 Subject: [PATCH 1/3] Add ability to reorder social media links --- ...onable_social_media_accounts_controller.rb | 26 +++++++++++++++++++ app/models/social_media_account.rb | 5 ++++ ...e_social_media_accounts_index_presenter.rb | 6 ++++- .../worldwide_organisation_presenter.rb | 2 +- .../index.html.erb | 21 +++++++++++---- .../reorder.html.erb | 26 +++++++++++++++++++ config/routes.rb | 4 +++ ...4_add_ordering_to_social_media_accounts.rb | 5 ++++ db/schema.rb | 3 ++- 9 files changed, 90 insertions(+), 8 deletions(-) create mode 100644 app/views/admin/editionable_social_media_accounts/reorder.html.erb create mode 100644 db/migrate/20250108102234_add_ordering_to_social_media_accounts.rb diff --git a/app/controllers/admin/editionable_social_media_accounts_controller.rb b/app/controllers/admin/editionable_social_media_accounts_controller.rb index ce5cc4cea9f..953672ea2fb 100644 --- a/app/controllers/admin/editionable_social_media_accounts_controller.rb +++ b/app/controllers/admin/editionable_social_media_accounts_controller.rb @@ -46,6 +46,15 @@ def update end end + def reorder + if request.put? + update_ordering + redirect_to admin_edition_social_media_accounts_path(@edition), notice: "Social media accounts reordered" + else + @reorderable_social_media_accounts = @edition.social_media_accounts.order(:ordering) + end + end + private def find_edition @@ -62,8 +71,25 @@ def social_media_account_params :social_media_service_id, :title, :url, + :ordering, ).merge( socialable: @edition, ) end + + def extract_items_from_ordering_params + item_ordering = params[:ordering] || {} + item_ordering.permit!.to_h + .map { |item_id, ordering| [SocialMediaAccount.find(item_id), ordering.to_i] } + .sort_by { |_, ordering| ordering } + .map { |item, _| item } + .compact + end + + def update_ordering + ordered_accounts = extract_items_from_ordering_params + ordered_accounts.each_with_index do |account, index| + account.update_order(index + 1) + end + end end diff --git a/app/models/social_media_account.rb b/app/models/social_media_account.rb index 3df724291d9..59d66638884 100644 --- a/app/models/social_media_account.rb +++ b/app/models/social_media_account.rb @@ -24,4 +24,9 @@ def service_name def display_name title.presence || service_name end + + def update_order(new_order) + self.ordering = new_order + save! + end end diff --git a/app/presenters/editionable_social_media_accounts_index_presenter.rb b/app/presenters/editionable_social_media_accounts_index_presenter.rb index 358e43a1edf..e1c99a476e3 100644 --- a/app/presenters/editionable_social_media_accounts_index_presenter.rb +++ b/app/presenters/editionable_social_media_accounts_index_presenter.rb @@ -8,7 +8,7 @@ def initialize(edition) end def social_media_accounts - edition.social_media_accounts.map do |social_media_account| + order_social_media_accounts.map do |social_media_account| { title: social_media_account.service_name, rows: social_media_account_rows(social_media_account), @@ -17,6 +17,10 @@ def social_media_accounts end end + def order_social_media_accounts + @edition.social_media_accounts.order(:ordering) + end + private def social_media_account_rows(social_media_account) diff --git a/app/presenters/publishing_api/worldwide_organisation_presenter.rb b/app/presenters/publishing_api/worldwide_organisation_presenter.rb index b8bd597d125..950bc93ba3b 100644 --- a/app/presenters/publishing_api/worldwide_organisation_presenter.rb +++ b/app/presenters/publishing_api/worldwide_organisation_presenter.rb @@ -151,7 +151,7 @@ def secondary_role_person def social_media_links return [] unless item.social_media_accounts.any? - item.social_media_accounts.map do |social_media_account| + item.social_media_accounts.order(:ordering).map do |social_media_account| { href: social_media_account.url, service_type: social_media_account.service_name.parameterize, diff --git a/app/views/admin/editionable_social_media_accounts/index.html.erb b/app/views/admin/editionable_social_media_accounts/index.html.erb index b32e6f09511..1e2f386f16e 100644 --- a/app/views/admin/editionable_social_media_accounts/index.html.erb +++ b/app/views/admin/editionable_social_media_accounts/index.html.erb @@ -18,11 +18,22 @@ <%= link_to "Add new social media account", new_admin_edition_social_media_account_path(@edition), class: "govuk-link govuk-link--no-visited-state" %>

- <%= render "govuk_publishing_components/components/heading", { - text: "Social media accounts", - font_size: "l", - margin_bottom: 3, - } %> +
+
+ <%= render "govuk_publishing_components/components/heading", { + text: "Social media accounts", + font_size: "l", + margin_bottom: 3, + } %> +
+ <% if @edition.social_media_accounts.many? %> +
+

+ <%= link_to("Reorder", reorder_admin_edition_social_media_accounts_path(@edition), class: "govuk-link govuk-link--no-visited-state") %> +

+
+ <% end %> +
<% if @edition.social_media_accounts.any? %> <% @editionable_social_media_accounts_index_presenter.social_media_accounts.each do |social_media_account| %> diff --git a/app/views/admin/editionable_social_media_accounts/reorder.html.erb b/app/views/admin/editionable_social_media_accounts/reorder.html.erb new file mode 100644 index 00000000000..b206af5de93 --- /dev/null +++ b/app/views/admin/editionable_social_media_accounts/reorder.html.erb @@ -0,0 +1,26 @@ +<% content_for :page_title, "Reorder social media accounts" %> +<% content_for :title, "Reorder social media accounts" %> +<% content_for :title_margin_bottom, 6 %> + +
+
+ <%= form_with url: reorder_admin_edition_social_media_accounts_path(@edition), method: :put do %> + <%= render "govuk_publishing_components/components/reorderable_list", { + items: @reorderable_social_media_accounts.map do |account| + { + id: account.id, + title: account.title, + } + end, + } %> + +
+ <%= render "govuk_publishing_components/components/button", { + text: "Update order", + } %> + + <%= link_to("Cancel", admin_edition_social_media_accounts_path(@edition), class: "govuk-link govuk-link--no-visited-state") %> +
+ <% end %> +
+
diff --git a/config/routes.rb b/config/routes.rb index ec2400c9561..70bb9363f64 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -250,6 +250,10 @@ def redirect(path, options = { prefix: Whitehall.router_prefix }) resources :lead_images, controller: "edition_lead_images", only: %i[update] resources :social_media_accounts, only: %i[create destroy edit index new update], controller: "editionable_social_media_accounts" do get :confirm_destroy, on: :member + collection do + get :reorder + put :reorder + end end end diff --git a/db/migrate/20250108102234_add_ordering_to_social_media_accounts.rb b/db/migrate/20250108102234_add_ordering_to_social_media_accounts.rb new file mode 100644 index 00000000000..9f6e765f4a6 --- /dev/null +++ b/db/migrate/20250108102234_add_ordering_to_social_media_accounts.rb @@ -0,0 +1,5 @@ +class AddOrderingToSocialMediaAccounts < ActiveRecord::Migration[7.1] + def change + add_column :social_media_accounts, :ordering, :integer + end +end diff --git a/db/schema.rb b/db/schema.rb index 4b09da4056b..5fcfcf55d69 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.1].define(version: 2025_01_06_160308) do +ActiveRecord::Schema[7.1].define(version: 2025_01_08_102234) do create_table "assets", charset: "utf8mb3", force: :cascade do |t| t.string "asset_manager_id", null: false t.string "variant", null: false @@ -1006,6 +1006,7 @@ t.datetime "created_at", precision: nil t.datetime "updated_at", precision: nil t.string "socialable_type" + t.integer "ordering" t.index ["social_media_service_id"], name: "index_social_media_accounts_on_social_media_service_id" t.index ["socialable_id"], name: "index_social_media_accounts_on_organisation_id" end From 84dff189347224c40f9862053f6bfda9cab3e5dc Mon Sep 17 00:00:00 2001 From: Alex Newton Date: Wed, 8 Jan 2025 12:12:18 +0000 Subject: [PATCH 2/3] DRY up ordering parameter methods --- app/controllers/admin/contacts_controller.rb | 10 +++------- .../editionable_social_media_accounts_controller.rb | 12 ++++-------- app/controllers/admin/home_page_list_controller.rb | 2 +- .../admin/worldwide_offices_controller.rb | 10 +++------- app/controllers/concerns/orderable_items_concern.rb | 12 ++++++++++++ 5 files changed, 23 insertions(+), 23 deletions(-) create mode 100644 app/controllers/concerns/orderable_items_concern.rb diff --git a/app/controllers/admin/contacts_controller.rb b/app/controllers/admin/contacts_controller.rb index 13f77f06113..a3de8f0ae7f 100644 --- a/app/controllers/admin/contacts_controller.rb +++ b/app/controllers/admin/contacts_controller.rb @@ -1,4 +1,5 @@ class Admin::ContactsController < Admin::BaseController + include OrderableItemsConcern before_action :find_contactable before_action :find_contact, only: %i[edit update destroy confirm_destroy] before_action :destroy_blank_contact_numbers, only: %i[create update] @@ -82,13 +83,8 @@ def extract_show_on_home_page_param @show_on_home_page = params[:contact].delete(:show_on_home_page) end - def extract_items_from_ordering_params - item_ordering = params[:ordering] || {} - item_ordering.permit!.to_h - .map { |item_id, ordering| [Contact.find_by(id: item_id), ordering.to_i] } - .sort_by { |_, ordering| ordering } - .map { |item, _| item } - .compact + def fetch_ordered_items + @ordered_items = extract_items_from_ordering_params(Contact) end def find_contactable diff --git a/app/controllers/admin/editionable_social_media_accounts_controller.rb b/app/controllers/admin/editionable_social_media_accounts_controller.rb index 953672ea2fb..1ebfc0fa7b7 100644 --- a/app/controllers/admin/editionable_social_media_accounts_controller.rb +++ b/app/controllers/admin/editionable_social_media_accounts_controller.rb @@ -1,4 +1,5 @@ class Admin::EditionableSocialMediaAccountsController < Admin::BaseController + include OrderableItemsConcern before_action :find_edition before_action :find_social_media_account, only: %i[confirm_destroy destroy edit update] @@ -77,17 +78,12 @@ def social_media_account_params ) end - def extract_items_from_ordering_params - item_ordering = params[:ordering] || {} - item_ordering.permit!.to_h - .map { |item_id, ordering| [SocialMediaAccount.find(item_id), ordering.to_i] } - .sort_by { |_, ordering| ordering } - .map { |item, _| item } - .compact + def fetch_ordered_items + @ordered_items = extract_items_from_ordering_params(SocialMediaAccount) end def update_ordering - ordered_accounts = extract_items_from_ordering_params + ordered_accounts = fetch_ordered_items ordered_accounts.each_with_index do |account, index| account.update_order(index + 1) end diff --git a/app/controllers/admin/home_page_list_controller.rb b/app/controllers/admin/home_page_list_controller.rb index bc9d6f00706..bf01e2d64fe 100644 --- a/app/controllers/admin/home_page_list_controller.rb +++ b/app/controllers/admin/home_page_list_controller.rb @@ -7,7 +7,7 @@ def is_home_page_list_controller_for(list_name, opts) redirect_proc = opts[:redirect_to] home_page_list_controller_methods = Module.new do define_method(:reorder_for_home_page) do - reordered_items = extract_items_from_ordering_params + reordered_items = fetch_ordered_items home_page_list_container.__send__(:"reorder_#{plural_name}_on_home_page!", reordered_items) publish_container_to_publishing_api redirect_to redirect_proc.call(home_page_list_container, home_page_list_item), notice: %(#{plural_name.titleize} on home page reordered successfully) diff --git a/app/controllers/admin/worldwide_offices_controller.rb b/app/controllers/admin/worldwide_offices_controller.rb index 92d1687a779..fb760b17417 100644 --- a/app/controllers/admin/worldwide_offices_controller.rb +++ b/app/controllers/admin/worldwide_offices_controller.rb @@ -1,4 +1,5 @@ class Admin::WorldwideOfficesController < Admin::BaseController + include OrderableItemsConcern before_action :find_worldwide_organisation before_action :find_worldwide_office, only: %i[edit update confirm_destroy destroy] extend Admin::HomePageListController @@ -94,13 +95,8 @@ def handle_show_on_home_page_param end end - def extract_items_from_ordering_params - item_ordering = params[:ordering] || {} - item_ordering.permit!.to_h - .map { |item_id, ordering| [WorldwideOffice.find_by(id: item_id), ordering.to_i] } - .sort_by { |_, ordering| ordering } - .map { |item, _| item } - .compact + def fetch_ordered_items + @ordered_items = extract_items_from_ordering_params(WorldwideOffice) end def extract_show_on_home_page_param diff --git a/app/controllers/concerns/orderable_items_concern.rb b/app/controllers/concerns/orderable_items_concern.rb new file mode 100644 index 00000000000..94ceafe820c --- /dev/null +++ b/app/controllers/concerns/orderable_items_concern.rb @@ -0,0 +1,12 @@ +module OrderableItemsConcern + extend ActiveSupport::Concern + + def extract_items_from_ordering_params(model_class) + item_ordering = params[:ordering] || {} + item_ordering.permit!.to_h + .map { |item_id, ordering| [model_class.find_by(id: item_id), ordering.to_i] } + .sort_by { |_, ordering| ordering } + .map { |item, _| item } + .compact + end +end From 1a301efbf6324349b0865ff086e94b63d4cb1d9e Mon Sep 17 00:00:00 2001 From: Alex Newton Date: Wed, 8 Jan 2025 14:48:44 +0000 Subject: [PATCH 3/3] Add tests for social media reordering' --- ...e_social_media_accounts_controller_test.rb | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/test/functional/admin/editionable_social_media_accounts_controller_test.rb b/test/functional/admin/editionable_social_media_accounts_controller_test.rb index e854f8c8a1e..46010ced30e 100644 --- a/test/functional/admin/editionable_social_media_accounts_controller_test.rb +++ b/test/functional/admin/editionable_social_media_accounts_controller_test.rb @@ -146,4 +146,27 @@ class Admin::EditionableSocialMediaAccountsControllerTest < ActionController::Te assert_response :redirect assert_empty @edition.social_media_accounts end + + view_test "GET :reorder displays the reorderable social media accounts" do + get :reorder, params: { edition_id: @edition } + + assert_response :success + assert_select ".gem-c-reorderable-list__item", count: @edition.social_media_accounts.count + end + + test "PUT :reorder updates the ordering of social media accounts" do + social_media_account1 = create(:social_media_account, socialable: @edition, ordering: 1) + social_media_account2 = create(:social_media_account, socialable: @edition, ordering: 2) + + put :reorder, + params: { edition_id: @edition, + ordering: { + social_media_account2.id.to_s => "1", + social_media_account1.id.to_s => "2", + } } + + assert_response :redirect + reordered_accounts = @edition.reload.social_media_accounts.where(id: [social_media_account1.id, social_media_account2.id]).order(:ordering) + assert_equal [social_media_account2, social_media_account1], reordered_accounts + end end