diff --git a/lib/engines/content_block_manager/app/controllers/content_block_manager/content_block/documents_controller.rb b/lib/engines/content_block_manager/app/controllers/content_block_manager/content_block/documents_controller.rb index 2556fc2d54d..5452e7a2db8 100644 --- a/lib/engines/content_block_manager/app/controllers/content_block_manager/content_block/documents_controller.rb +++ b/lib/engines/content_block_manager/app/controllers/content_block_manager/content_block/documents_controller.rb @@ -1,6 +1,7 @@ class ContentBlockManager::ContentBlock::DocumentsController < ContentBlockManager::BaseController def index - @content_block_documents = ContentBlockManager::ContentBlock::Document.live + @filters = params_filters + @content_block_documents = ContentBlockManager::ContentBlock::Document::DocumentFilter.new(@filters).documents end def show @@ -23,4 +24,12 @@ def new_document_options_redirect redirect_to content_block_manager.new_content_block_manager_content_block_document_path, flash: { error: "You must select a block type" } end end + +private + + def params_filters + params.slice(:title) + .permit! + .to_h + end end diff --git a/lib/engines/content_block_manager/app/models/content_block_manager/content_block/document.rb b/lib/engines/content_block_manager/app/models/content_block_manager/content_block/document.rb index 99975c640b5..2ecfd2a72ea 100644 --- a/lib/engines/content_block_manager/app/models/content_block_manager/content_block/document.rb +++ b/lib/engines/content_block_manager/app/models/content_block_manager/content_block/document.rb @@ -1,6 +1,8 @@ module ContentBlockManager module ContentBlock class Document < ApplicationRecord + include Scopes::SearchableByTitle + extend FriendlyId friendly_id :title, use: :slugged, slug_column: :content_id_alias, routes: :default diff --git a/lib/engines/content_block_manager/app/models/content_block_manager/content_block/document/document_filter.rb b/lib/engines/content_block_manager/app/models/content_block_manager/content_block/document/document_filter.rb new file mode 100644 index 00000000000..e44f3dcc909 --- /dev/null +++ b/lib/engines/content_block_manager/app/models/content_block_manager/content_block/document/document_filter.rb @@ -0,0 +1,14 @@ +module ContentBlockManager + class ContentBlock::Document::DocumentFilter + def initialize(filters = {}) + @filters = filters + end + + def documents + documents = ContentBlock::Document + documents = documents.live + documents = documents.with_title(@filters[:title]) if @filters[:title].present? + documents + end + end +end diff --git a/lib/engines/content_block_manager/app/models/content_block_manager/content_block/document/scopes/searchable_by_title.rb b/lib/engines/content_block_manager/app/models/content_block_manager/content_block/document/scopes/searchable_by_title.rb new file mode 100644 index 00000000000..aa9badfc4f1 --- /dev/null +++ b/lib/engines/content_block_manager/app/models/content_block_manager/content_block/document/scopes/searchable_by_title.rb @@ -0,0 +1,18 @@ +module ContentBlockManager + module ContentBlock::Document::Scopes::SearchableByTitle + extend ActiveSupport::Concern + + included do + scope :with_title, + lambda { |keywords| + split_keywords = keywords.split + pattern = "" + split_keywords.map do |k| + escaped_word = Regexp.escape(k) + pattern += "(?=.*#{escaped_word})" + end + where("title REGEXP :pattern", pattern:) + } + end + end +end diff --git a/lib/engines/content_block_manager/app/views/content_block_manager/content_block/documents/_filter_options.html.erb b/lib/engines/content_block_manager/app/views/content_block_manager/content_block/documents/_filter_options.html.erb new file mode 100644 index 00000000000..9205f293098 --- /dev/null +++ b/lib/engines/content_block_manager/app/views/content_block_manager/content_block/documents/_filter_options.html.erb @@ -0,0 +1,17 @@ +<%= form_with url: content_block_manager.content_block_manager_content_block_documents_path, method: :get do %> + <%= render "govuk_publishing_components/components/input", { + label: { + text: "Title", + bold: true, + }, + hint: 'For example, "driving standards"', + name: "title", + id: "title_filter", + value: !@filters.nil? && @filters[:title], + } %> + + <%= render "govuk_publishing_components/components/button", { + text: "View results", + margin_bottom: 4, + } %> +<% end %> diff --git a/lib/engines/content_block_manager/app/views/content_block_manager/content_block/documents/index.html.erb b/lib/engines/content_block_manager/app/views/content_block_manager/content_block/documents/index.html.erb index d9bf6ae6485..ba03c68400f 100644 --- a/lib/engines/content_block_manager/app/views/content_block_manager/content_block/documents/index.html.erb +++ b/lib/engines/content_block_manager/app/views/content_block_manager/content_block/documents/index.html.erb @@ -11,9 +11,13 @@
-
- <% @content_block_documents.each do |content_block_document| %> - <%= render ContentBlockManager::ContentBlock::Document::Index::SummaryCardComponent.new(content_block_document:) %> - <% end %> +
+ <%= render "filter_options" %> +
+
+

<%= pluralize(@content_block_documents.count, "result") %>

+ <% @content_block_documents.each do |content_block_document| %> + <%= render ContentBlockManager::ContentBlock::Document::Index::SummaryCardComponent.new(content_block_document:) %> + <% end %>
diff --git a/lib/engines/content_block_manager/features/search_for_object.feature b/lib/engines/content_block_manager/features/search_for_object.feature new file mode 100644 index 00000000000..6977dd461f4 --- /dev/null +++ b/lib/engines/content_block_manager/features/search_for_object.feature @@ -0,0 +1,18 @@ +Feature: Search for a content object + Background: + Given the content block manager feature flag is enabled + Given I am a GDS admin + And the organisation "Ministry of Example" exists + And a schema "email_address" exists with the following fields: + | email_address | + And an email address content block has been created + And an email address content block has been created with the title "example search title" + + Scenario: GDS Editor searches for a content object by keyword in title + When I visit the Content Block Manager home page + Then I should see the details for all documents + And "2" content blocks are returned + When I enter the title "example search" + And I click to view results + Then I should see the content block with title "example search title" returned + And "1" content blocks are returned \ No newline at end of file diff --git a/lib/engines/content_block_manager/features/step_definitions/content_block_manager_steps.rb b/lib/engines/content_block_manager/features/step_definitions/content_block_manager_steps.rb index 753bde0a7fc..c1a32dcbcda 100644 --- a/lib/engines/content_block_manager/features/step_definitions/content_block_manager_steps.rb +++ b/lib/engines/content_block_manager/features/step_definitions/content_block_manager_steps.rb @@ -37,6 +37,10 @@ click_button "Cancel" end +When("I click to view results") do + click_button "View results" +end + Then("I should see all the schemas listed") do @schemas.values.each do |schema| expect(page).to have_content(schema.name) @@ -183,6 +187,25 @@ @content_blocks.push(@content_block) end +Given("an email address content block has been created with the title {string}") do |title| + @content_blocks ||= [] + @email_address = "foo@example.com" + organisation = create(:organisation) + document = create(:content_block_document, :email_address, title:) + @content_block = create( + :content_block_edition, + :email_address, + document:, + details: { email_address: @email_address }, + creator: @user, + organisation:, + ) + ContentBlockManager::ContentBlock::Edition::HasAuditTrail.acting_as(@user) do + @content_block.publish! + end + @content_blocks.push(@content_block) +end + When("I visit the page for the content block") do visit content_block_manager.content_block_manager_content_block_edition_path(@content_block) end @@ -214,6 +237,14 @@ end end +Then("I should see the content block with title {string} returned") do |title| + expect(page).to have_selector(".govuk-summary-card__title", text: title) +end + +Then("{string} content blocks are returned") do |count| + assert_text "#{count} #{'result'.pluralize(count.to_i)}" +end + When("I click to view the document") do @schema = @schemas[@content_block.document.block_type] click_link href: content_block_manager.content_block_manager_content_block_document_path(@content_block.document) @@ -445,6 +476,10 @@ def should_show_edit_form_for_email_address_content_block(document_title, email_ fill_in_date_and_time_field(past_date) end +When("I enter the title {string}") do |title| + fill_in "Title", with: title +end + Then("the edition should have been scheduled successfully") do @schema = @schemas[@content_block.document.block_type] assert_text "#{@schema.name} scheduled successfully" diff --git a/lib/engines/content_block_manager/test/unit/app/models/content_block_edition/document/document_filter_test.rb b/lib/engines/content_block_manager/test/unit/app/models/content_block_edition/document/document_filter_test.rb new file mode 100644 index 00000000000..87cb47b1fb6 --- /dev/null +++ b/lib/engines/content_block_manager/test/unit/app/models/content_block_edition/document/document_filter_test.rb @@ -0,0 +1,26 @@ +require "test_helper" + +class ContentBlockManager::DocumentFilterTest < ActiveSupport::TestCase + extend Minitest::Spec::DSL + + describe "documents" do + describe "when no filters are given" do + it "returns live documents" do + document_scope_mock = mock + ContentBlockManager::ContentBlock::Document.expects(:live).returns(document_scope_mock) + document_scope_mock.expects(:with_title).never + + ContentBlockManager::ContentBlock::Document::DocumentFilter.new({}).documents + end + end + + describe "when a title filter is given" do + it "returns live documents with keyword in title" do + document_scope_mock = mock + ContentBlockManager::ContentBlock::Document.expects(:live).returns(document_scope_mock) + document_scope_mock.expects(:with_title).returns([]) + ContentBlockManager::ContentBlock::Document::DocumentFilter.new({ title: "ministry of example" }).documents + end + end + end +end diff --git a/lib/engines/content_block_manager/test/unit/app/models/content_block_edition/document/scopes/searchable_by_title_test.rb b/lib/engines/content_block_manager/test/unit/app/models/content_block_edition/document/scopes/searchable_by_title_test.rb new file mode 100644 index 00000000000..7d6162a2111 --- /dev/null +++ b/lib/engines/content_block_manager/test/unit/app/models/content_block_edition/document/scopes/searchable_by_title_test.rb @@ -0,0 +1,21 @@ +require "test_helper" + +class ContentBlockManager::SearchableByTitleTest < ActiveSupport::TestCase + extend Minitest::Spec::DSL + + describe ".with_title" do + test "should find documents with title containing keyword" do + document_with_first_keyword = create(:content_block_document, :email_address, title: "klingons and such") + _edition_with_first_keyword = create(:content_block_edition, :email_address, document: document_with_first_keyword) + _document_without_first_keyword = create(:content_block_document, :email_address, title: "this document is about muppets") + assert_equal [document_with_first_keyword], ContentBlockManager::ContentBlock::Document.with_title("klingons") + end + + test "should find documents with title containing keywords not in order" do + document_with_first_keyword = create(:content_block_document, :email_address, title: "klingons and such") + _edition_with_first_keyword = create(:content_block_edition, :email_address, document: document_with_first_keyword) + _document_without_first_keyword = create(:content_block_document, :email_address, title: "muppets and such") + assert_equal [document_with_first_keyword], ContentBlockManager::ContentBlock::Document.with_title("such klingons") + end + end +end