From ebbc812154cc76e9dc9749c6d9d088e13fae46e2 Mon Sep 17 00:00:00 2001 From: Ynda Jas Date: Fri, 14 Jun 2024 17:00:38 +0100 Subject: [PATCH] Allow users to bulk republish by organisation This adds a page where users can enter an organisation slug, followed by a page where users confirm that they want all documents associated with that organisation to be republished. Users are then redirected back to the index with a flashed confirmation message --- .../admin/bulk_republishing_controller.rb | 49 +++++++- app/helpers/admin/republishing_helper.rb | 8 +- ...confirm_documents_by_organisation.html.erb | 16 +++ .../new_documents_by_organisation.html.erb | 20 ++++ config/routes.rb | 6 + .../bulk_republishing_controller_test.rb | 105 ++++++++++++++++++ .../admin/republishing_controller_test.rb | 1 + .../helpers/admin/republishing_helper_test.rb | 13 ++- 8 files changed, 211 insertions(+), 7 deletions(-) create mode 100644 app/views/admin/bulk_republishing/confirm_documents_by_organisation.html.erb create mode 100644 app/views/admin/bulk_republishing/new_documents_by_organisation.html.erb diff --git a/app/controllers/admin/bulk_republishing_controller.rb b/app/controllers/admin/bulk_republishing_controller.rb index f7901ad73447..5403c2e33d11 100644 --- a/app/controllers/admin/bulk_republishing_controller.rb +++ b/app/controllers/admin/bulk_republishing_controller.rb @@ -30,13 +30,58 @@ def republish end end + def new_documents_by_organisation; end + + def search_documents_by_organisation + @organisation = Organisation.find_by(slug: params[:organisation_slug]) + + unless @organisation + flash[:alert] = "Organisation with slug '#{params[:organisation_slug]}' not found" + return redirect_to(admin_bulk_republishing_documents_by_organisation_new_path) + end + + redirect_to(admin_bulk_republishing_documents_by_organisation_confirm_path(params[:organisation_slug])) + end + + def confirm_documents_by_organisation + unless @organisation&.slug == params[:organisation_slug] + @organisation = Organisation.find_by(slug: params[:organisation_slug]) + render "admin/errors/not_found", status: :not_found unless @organisation + end + + @bulk_content_type_metadata = bulk_content_type_metadata.fetch(:all_documents_by_organisation) + @republishing_event = RepublishingEvent.new + end + + def republish_documents_by_organisation + unless @organisation&.slug == params[:organisation_slug] + @organisation = Organisation.find_by(slug: params[:organisation_slug]) + return render "admin/errors/not_found", status: :not_found unless @organisation + end + + bulk_content_type_key = :all_documents_by_organisation + @bulk_content_type_metadata = bulk_content_type_metadata.fetch(bulk_content_type_key) + action = "#{@bulk_content_type_metadata[:name].upcase_first} '#{@organisation.name}' have been queued for republishing" + bulk_content_type_value = RepublishingEvent.bulk_content_types.fetch(bulk_content_type_key) + @republishing_event = build_republishing_event(action:, bulk_content_type: bulk_content_type_value, organisation_id: @organisation.id) + + if @republishing_event.save + @bulk_content_type_metadata[:republish_method].call(@organisation) + + flash[:notice] = action + redirect_to(admin_republishing_index_path) + else + render "confirm_documents_by_organisation" + end + end + private def enforce_permissions! enforce_permission!(:administer, :republish_content) end - def build_republishing_event(action:, bulk_content_type:) - RepublishingEvent.new(user: current_user, reason: params.fetch(:reason), action:, bulk_content_type:, bulk: true) + def build_republishing_event(action:, bulk_content_type:, organisation_id: nil) + RepublishingEvent.new(user: current_user, reason: params.fetch(:reason), action:, bulk_content_type:, bulk: true, organisation_id:) end end diff --git a/app/helpers/admin/republishing_helper.rb b/app/helpers/admin/republishing_helper.rb index c919a937162f..0b3822f500eb 100644 --- a/app/helpers/admin/republishing_helper.rb +++ b/app/helpers/admin/republishing_helper.rb @@ -45,6 +45,12 @@ def bulk_content_type_metadata confirmation_path: admin_bulk_republishing_confirm_path("all-published-organisation-about-us-pages"), republish_method: -> { BulkRepublisher.new.republish_all_published_organisation_about_us_pages }, }, + all_documents_by_organisation: { + id: "all-documents-by-organisation", + name: "all documents by organisation", + new_path: admin_bulk_republishing_documents_by_organisation_new_path, + republish_method: ->(organisation) { BulkRepublisher.new.republish_all_documents_by_organisation(organisation) }, + }, } end @@ -68,7 +74,7 @@ def republishing_index_bulk_republishing_rows }, { text: link_to(sanitize("Republish #{tag.span(content_type[:name], class: 'govuk-visually-hidden')}"), - content_type[:confirmation_path], + content_type[:new_path] || content_type[:confirmation_path], id: content_type[:id], class: "govuk-link"), }, diff --git a/app/views/admin/bulk_republishing/confirm_documents_by_organisation.html.erb b/app/views/admin/bulk_republishing/confirm_documents_by_organisation.html.erb new file mode 100644 index 000000000000..215cf3274c8b --- /dev/null +++ b/app/views/admin/bulk_republishing/confirm_documents_by_organisation.html.erb @@ -0,0 +1,16 @@ +<% content_for :page_title, "Republish #{@bulk_content_type_metadata[:name]} '#{@organisation.name}'" %> +<% content_for :title, "Are you sure you want to republish #{@bulk_content_type_metadata[:name]} '#{@organisation.name}'?" %> +<% content_for :title_margin_bottom, 6 %> +<% content_for :error_summary, render(Admin::ErrorSummaryComponent.new(object: @republishing_event)) %> + +
+
+

+ This will queue all documents associated with the organisation <%= link_to @organisation.name, @organisation.public_url, { class: "govuk-link" } %> to be republished. +

+ <%= render partial: "shared/republishing_form", locals: { + republishing_event: @republishing_event, + republishing_path: admin_bulk_republishing_documents_by_organisation_republish_path(@organisation.slug), + } %> +
+
diff --git a/app/views/admin/bulk_republishing/new_documents_by_organisation.html.erb b/app/views/admin/bulk_republishing/new_documents_by_organisation.html.erb new file mode 100644 index 000000000000..96174e5dfae4 --- /dev/null +++ b/app/views/admin/bulk_republishing/new_documents_by_organisation.html.erb @@ -0,0 +1,20 @@ +<% content_for :page_title, "Republish all by organisation" %> +<% content_for :title, "What organisation's documents would you like to republish?" %> +<% content_for :title_margin_bottom, 6 %> + +
+
+ <%= form_with(url: admin_bulk_republishing_documents_by_organisation_search_path, method: :post) do %> + <%= render "govuk_publishing_components/components/input", { + label: { + text: "Enter the slug for the organisation", + }, + hint: "You can get the slug from the last part of the public URL - everything after '/government/organisations/'.", + name: "organisation_slug", + } %> + <%= render "govuk_publishing_components/components/button", { + text: "Continue", + } %> + <% end %> +
+
diff --git a/config/routes.rb b/config/routes.rb index 59f43b7a9fdc..b224f679d47f 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -53,6 +53,12 @@ def redirect(path, options = { prefix: Whitehall.router_prefix }) post "/:document_slug/republish" => "republishing#republish_document", as: :republishing_document_republish end scope :bulk do + scope "documents-by-organisation" do + get "/new" => "bulk_republishing#new_documents_by_organisation", as: :bulk_republishing_documents_by_organisation_new + post "/search" => "bulk_republishing#search_documents_by_organisation", as: :bulk_republishing_documents_by_organisation_search + get "/:organisation_slug/confirm" => "bulk_republishing#confirm_documents_by_organisation", as: :bulk_republishing_documents_by_organisation_confirm + post "/:organisation_slug/republish" => "bulk_republishing#republish_documents_by_organisation", as: :bulk_republishing_documents_by_organisation_republish + end get "/:bulk_content_type/confirm" => "bulk_republishing#confirm", as: :bulk_republishing_confirm post "/:bulk_content_type/republish" => "bulk_republishing#republish", as: :bulk_republishing_republish end diff --git a/test/functional/admin/bulk_republishing_controller_test.rb b/test/functional/admin/bulk_republishing_controller_test.rb index f5dd0bbd25c7..52510d2a4a3d 100644 --- a/test/functional/admin/bulk_republishing_controller_test.rb +++ b/test/functional/admin/bulk_republishing_controller_test.rb @@ -64,4 +64,109 @@ class Admin::BulkRepublishingControllerTest < ActionController::TestCase post :republish, params: { bulk_content_type: "all-published-organisation-about-us-pages", reason: "this needs republishing" } assert_response :forbidden end + + test "GDS Admin users should be able to GET :new_documents_by_organisation" do + get :new_documents_by_organisation + assert_response :ok + end + + test "Non-GDS Admin users should not be able to GET :new_documents_by_organisation" do + login_as :writer + + get :new_documents_by_organisation + assert_response :forbidden + end + + test "GDS Admin users should be able to POST :search_documents_by_organisation with an existing organisation slug" do + create(:organisation, slug: "an-existing-organisation") + + post :search_documents_by_organisation, params: { organisation_slug: "an-existing-organisation" } + + assert_redirected_to admin_bulk_republishing_documents_by_organisation_confirm_path("an-existing-organisation") + end + + test "GDS Admin users should be redirected back to :new_documents_by_organisation when trying to POST :search_documents_by_organisation with a nonexistent organisation slug" do + post :search_documents_by_organisation, params: { organisation_slug: "not-an-existing-organisation" } + + assert_redirected_to admin_bulk_republishing_documents_by_organisation_new_path + assert_equal "Organisation with slug 'not-an-existing-organisation' not found", flash[:alert] + end + + test "Non-GDS Admin users should not be able to POST :search_documents_by_organisation" do + create(:organisation, slug: "an-existing-organisation") + + login_as :writer + + post :search_documents_by_organisation, params: { organisation_slug: "an-existing-organisation" } + assert_response :forbidden + end + + test "GDS Admin users should be able to GET :confirm_documents_by_organisation with an existing organisation slug" do + create(:organisation, slug: "an-existing-organisation") + + get :confirm_documents_by_organisation, params: { organisation_slug: "an-existing-organisation" } + assert_response :ok + end + + test "GDS Admin users should see a 404 page when trying to GET :confirm_documents_by_organisation with a nonexistent organisation slug" do + get :confirm_documents_by_organisation, params: { organisation_slug: "not-an-existing-organisation" } + assert_response :not_found + end + + test "Non-GDS Admin users should not be able to access :confirm_documents_by_organisation" do + create(:organisation, slug: "an-existing-organisation") + + login_as :writer + + get :confirm_documents_by_organisation, params: { organisation_slug: "organisation" } + assert_response :forbidden + end + + test "GDS Admin users should be able to POST :republish_documents_by_organisation with an existing organisation slug, creating a RepublishingEvent for the current user" do + organisation = create(:organisation, id: "1234", slug: "an-existing-organisation", name: "An Existing Organisation") + + BulkRepublisher.any_instance.expects(:republish_all_documents_by_organisation).with(organisation).once + + post :republish_documents_by_organisation, params: { organisation_slug: "an-existing-organisation", reason: "this needs republishing" } + + newly_created_event = RepublishingEvent.last + assert_equal current_user, newly_created_event.user + assert_equal "this needs republishing", newly_created_event.reason + assert_equal "All documents by organisation 'An Existing Organisation' have been queued for republishing", newly_created_event.action + assert_equal true, newly_created_event.bulk + assert_equal "all_documents_by_organisation", newly_created_event.bulk_content_type + assert_equal "1234", newly_created_event.organisation_id + + assert_redirected_to admin_republishing_index_path + assert_equal "All documents by organisation 'An Existing Organisation' have been queued for republishing", flash[:notice] + end + + test "GDS Admin users should encounter an error on POST :republish_documents_by_organisation without a `reason` and be sent back to the confirm page" do + organisation = create(:organisation, slug: "an-existing-organisation", name: "An Existing Organisation") + + BulkRepublisher.any_instance.expects(:republish_all_documents_by_organisation).with(organisation).never + + post :republish_documents_by_organisation, params: { organisation_slug: "an-existing-organisation", reason: "" } + + assert_equal ["Reason can't be blank"], assigns(:republishing_event).errors.full_messages + assert_template "confirm_documents_by_organisation" + end + + test "GDS Admin users should see a 404 page when trying to POST :republish_documents_by_organisation with a nonexistent organisation slug" do + BulkRepublisher.any_instance.expects(:republish_all_documents_by_organisation).never + + post :republish_documents_by_organisation, params: { organisation_slug: "not-an-existing-organisation" } + assert_response :not_found + end + + test "Non-GDS Admin users should not be able to POST :republish_documents_by_organisation" do + organisation = create(:organisation, slug: "an-existing-organisation", name: "An Existing Organisation") + + BulkRepublisher.any_instance.expects(:republish_all_documents_by_organisation).with(organisation).never + + login_as :writer + + post :republish_documents_by_organisation, params: { organisation_slug: "an-existing-organisation" } + assert_response :forbidden + end end diff --git a/test/functional/admin/republishing_controller_test.rb b/test/functional/admin/republishing_controller_test.rb index 7655cf399312..e5af2a83fe72 100644 --- a/test/functional/admin/republishing_controller_test.rb +++ b/test/functional/admin/republishing_controller_test.rb @@ -25,6 +25,7 @@ class Admin::RepublishingControllerTest < ActionController::TestCase assert_select ".govuk-table:nth-of-type(3) .govuk-table__body .govuk-table__row:nth-child(4) .govuk-table__cell:nth-child(2) a[href='/government/admin/republishing/bulk/all-documents-with-publicly-visible-editions-with-attachments/confirm']", text: "Republish all documents with publicly-visible editions with attachments" assert_select ".govuk-table:nth-of-type(3) .govuk-table__body .govuk-table__row:nth-child(5) .govuk-table__cell:nth-child(2) a[href='/government/admin/republishing/bulk/all-documents-with-publicly-visible-editions-with-html-attachments/confirm']", text: "Republish all documents with publicly-visible editions with HTML attachments" assert_select ".govuk-table:nth-of-type(3) .govuk-table__body .govuk-table__row:nth-child(6) .govuk-table__cell:nth-child(2) a[href='/government/admin/republishing/bulk/all-published-organisation-about-us-pages/confirm']", text: "Republish all published organisation 'About us' pages" + assert_select ".govuk-table:nth-of-type(3) .govuk-table__body .govuk-table__row:nth-child(7) .govuk-table__cell:nth-child(2) a[href='/government/admin/republishing/bulk/documents-by-organisation/new']", text: "Republish all documents by organisation" assert_response :ok end diff --git a/test/unit/app/helpers/admin/republishing_helper_test.rb b/test/unit/app/helpers/admin/republishing_helper_test.rb index 39e8c8737825..913277346df9 100644 --- a/test/unit/app/helpers/admin/republishing_helper_test.rb +++ b/test/unit/app/helpers/admin/republishing_helper_test.rb @@ -34,11 +34,16 @@ class Admin::RepublishingHelperTest < ActionView::TestCase assert_equal first_bulk_content_type, "All documents" end - test "#republishing_index_bulk_republishing_rows creates a link to the specific bulk republishing confirmation page" do - first_link = republishing_index_bulk_republishing_rows.first[1][:text] - expected_link = 'Republish all documents' + # this can be removed when rebased on the by type branch + test "#republishing_index_bulk_republishing_rows creates a link to the new page for content types that require extra input" do + _all_documents_by_organisation_description, all_documents_by_organisation_action_link = republishing_index_bulk_republishing_rows.find do |row| + description_column = row[0] + description_column == "All documents by organisation" + end - assert_equal first_link, expected_link + expected_link = 'Republish all documents by organisation' + + assert_equal all_documents_by_organisation_action_link, expected_link end end