Skip to content

Commit

Permalink
Merge pull request #2508 from alphagov/508-search-by-slug-and-title-p…
Browse files Browse the repository at this point in the history
…ublication-page

Update publications filter search box
  • Loading branch information
mtaylorgds authored Jan 24, 2025
2 parents f26490d + 6196c5a commit 9f0f082
Show file tree
Hide file tree
Showing 10 changed files with 63 additions and 40 deletions.
2 changes: 1 addition & 1 deletion app/controllers/content_item_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ def by_content_id

if artefact
redirect_url = if Flipflop.enabled?("design_system_publications_filter".to_sym)
"/?title_filter=#{artefact.latest_edition.title}&assignee_filter=&content_type_filter=all&states_filter%5B%5D=draft&states_filter%5B%5D=in_review&states_filter%5B%5D=amends_needed&states_filter%5B%5D=fact_check&states_filter%5B%5D=fact_check_received&states_filter%5B%5D=ready&states_filter%5B%5D=scheduled_for_publishing&states_filter%5B%5D=published"
"/?search_text=#{artefact.latest_edition.title}&assignee_filter=&content_type_filter=all&states_filter%5B%5D=draft&states_filter%5B%5D=in_review&states_filter%5B%5D=amends_needed&states_filter%5B%5D=fact_check&states_filter%5B%5D=fact_check_received&states_filter%5B%5D=ready&states_filter%5B%5D=scheduled_for_publishing&states_filter%5B%5D=published"
else
"/?list=published&string_filter=#{artefact.latest_edition.slug}&user_filter=all"
end
Expand Down
8 changes: 4 additions & 4 deletions app/controllers/root_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,21 @@ def index
end
session[:assignee_filter] = assignee_filter
content_type_filter = filter_params_hash[:content_type_filter]
title_filter = filter_params_hash[:title_filter]
search_text = filter_params_hash[:search_text]
@presenter = FilteredEditionsPresenter.new(
current_user,
states_filter: sanitised_states_filter_params,
assigned_to_filter: assignee_filter,
content_type_filter:,
title_filter:,
search_text:,
page: filter_params_hash[:page],
)
end

private

def user_has_submitted_filters?
filter_params.to_h[:title_filter]
filter_params.to_h[:search_text]
end

def assignee_filter
Expand All @@ -56,6 +56,6 @@ def assignee_filter
end

def filter_params
params.permit(:page, :assignee_filter, :content_type_filter, :title_filter, states_filter: [])
params.permit(:page, :assignee_filter, :content_type_filter, :search_text, states_filter: [])
end
end
4 changes: 2 additions & 2 deletions app/models/edition.rb
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,10 @@ class ResurrectionError < RuntimeError
scope :draft_in_publishing_api, -> { where(state: { "$in" => PUBLISHING_API_DRAFT_STATES }) }

scope :in_states, ->(states) { where(state: { "$in" => states }) }
scope :title_contains,
scope :search_title_and_slug,
lambda { |term|
regex = ::Regexp.new(::Regexp.escape(term), true) # case-insensitive
where({ title: regex })
any_of({ title: regex }, { slug: regex })
}

ACTIONS = {
Expand Down
20 changes: 9 additions & 11 deletions app/presenters/filtered_editions_presenter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,17 @@
class FilteredEditionsPresenter
ITEMS_PER_PAGE = 20

def initialize(user, states_filter: [], assigned_to_filter: nil, content_type_filter: nil, title_filter: nil, page: nil)
attr_reader :search_text

def initialize(user, states_filter: [], assigned_to_filter: nil, content_type_filter: nil, search_text: nil, page: nil)
@user = user
@states_filter = states_filter || []
@assigned_to_filter = assigned_to_filter
@content_type_filter = content_type_filter
@title_filter = title_filter
@search_text = search_text
@page = page
end

def title
@title_filter
end

def content_types
types = []

Expand Down Expand Up @@ -68,7 +66,7 @@ def query_editions
result = editions_by_content_type
result = apply_states_filter(result)
result = apply_assigned_to_filter(result)
result = apply_title_filter(result)
result = apply_search_text(result)
result = result.accessible_to(user)
result = result.where.not(_type: "PopularLinksEdition")
result.order_by(%w[updated_at desc]).page(@page).per(ITEMS_PER_PAGE)
Expand Down Expand Up @@ -129,11 +127,11 @@ def apply_assigned_to_filter(editions)
editions
end

def apply_title_filter(editions)
return editions if title_filter.blank?
def apply_search_text(editions)
return editions if search_text.blank?

editions.title_contains(title_filter)
editions.search_title_and_slug(search_text)
end

attr_reader :user, :states_filter, :assigned_to_filter, :content_type_filter, :title_filter, :page
attr_reader :user, :states_filter, :assigned_to_filter, :content_type_filter, :page
end
14 changes: 8 additions & 6 deletions app/views/root/_filter.html.erb
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
<div class="publications-filter govuk-!-padding-5">
<%= form_with url: root_path, method: :get do |form| %>
<%= render "govuk_publishing_components/components/heading", {
text: "Filter by",
text: "Filter",
margin_bottom: 4,
} %>

<%= render "govuk_publishing_components/components/input", {
label: {
text: "Title",
text: "Search",
bold: true,
},
name: "title_filter",
id: "title_filter",
value: @presenter.title,
hint: "Search by title or slug",
name: "search_text",
id: "search_text",
value: @presenter.search_text,
} %>

<%= render "govuk_publishing_components/components/select", {
Expand All @@ -33,11 +34,12 @@
name: "states_filter[]",
heading: "Status",
heading_size: "s",
hint_text: "Select all that apply",
items: @presenter.edition_states,
} %>

<%= render "govuk_publishing_components/components/button", {
text: "Update filter",
text: "Search",
margin_bottom: 4,
} %>

Expand Down
6 changes: 3 additions & 3 deletions test/functional/root_controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ class RootControllerTest < ActionController::TestCase
FactoryBot.create(:guide_edition, title: "How to train your dragon", assigned_to: @user)
FactoryBot.create(:guide_edition, title: "What to do in the event of a zombie apocalypse", assigned_to: @user)

get :index, params: { title_filter: "zombie" }
get :index, params: { search_text: "zombie" }

assert_response :ok
assert_select "p.publications-table__heading", "1 document(s)"
Expand All @@ -156,13 +156,13 @@ class RootControllerTest < ActionController::TestCase
.returns(stub(
editions: Kaminari.paginate_array([]).page(1),
available_users: [],
title: "",
search_text: "",
assignees: [],
content_types: [],
edition_states: [],
))

get :index, params: { title_filter: "", states_filter: %w[draft not_a_real_state] }
get :index, params: { search_text: "", states_filter: %w[draft not_a_real_state] }
end

should "show the first page of publications when no page is specified" do
Expand Down
20 changes: 17 additions & 3 deletions test/integration/root_overview_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,29 @@ class RootOverviewTest < IntegrationTest
assert page.has_no_content?("ZZZ")
end

should "filter by title content" do
should "search by title content" do
FactoryBot.create(:user, :govuk_editor)
FactoryBot.create(:guide_edition, title: "XXX")
FactoryBot.create(:guide_edition, title: "YYY")

visit "/"
filter_by_user("All")

filter_by_content("xXx")
search_by_title_or_slug("xXx")

assert page.has_content?("XXX")
assert page.has_no_content?("YYY")
end

should "search by slug" do
FactoryBot.create(:user, :govuk_editor)
FactoryBot.create(:guide_edition, slug: "XXX")
FactoryBot.create(:guide_edition, slug: "YYY")

visit "/"
filter_by_user("All")

search_by_title_or_slug("xXx")

assert page.has_content?("XXX")
assert page.has_no_content?("YYY")
Expand All @@ -72,7 +86,7 @@ class RootOverviewTest < IntegrationTest

visit "/"
filter_by_status("Amends needed")
filter_by_content("xXx")
search_by_title_or_slug("xXx")

assert page.has_css?(".publications-filter input[value='amends_needed'][checked]")
end
Expand Down
12 changes: 6 additions & 6 deletions test/integration_test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,14 @@ def login_as(user)
def filter_by_user(option, from: "Assigned to")
within ".publications-filter form" do
select(option, from:)
click_on "Update filter"
click_on "Search"
end
end

def filter_by_content(substring)
def search_by_title_or_slug(substring)
within ".publications-filter form" do
fill_in "Title", with: substring
click_on "Update filter"
fill_in "Search", with: substring
click_on "Search"
end
end

Expand All @@ -52,14 +52,14 @@ def filter_by_status(option)
end
end
check(option)
click_on "Update filter"
click_on "Search"
end
end

def filter_by_content_type(option, from: "Content type")
within ".publications-filter form" do
select(option, from:)
click_on "Update filter"
click_on "Search"
end
end
end
Expand Down
4 changes: 2 additions & 2 deletions test/models/edition_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -495,14 +495,14 @@ def draft_second_edition_from(published_edition)
guide = FactoryBot.create(:guide_edition, title: "Hitchhiker's Guide to the Galaxy")
FactoryBot.create(:guide_edition)

assert_equal [guide], Edition.title_contains("Galaxy").to_a
assert_equal [guide], Edition.search_title_and_slug("Galaxy").to_a
end

test "should scope publications by case-insensitive title match" do
guide = FactoryBot.create(:guide_edition, title: "Hitchhiker's Guide to the Galaxy")
FactoryBot.create(:guide_edition)

assert_equal [guide], Edition.title_contains("Hitchhiker's gUIDE to the Galaxy").to_a
assert_equal [guide], Edition.search_title_and_slug("Hitchhiker's gUIDE to the Galaxy").to_a
end

test "cannot delete a publication that has been published" do
Expand Down
13 changes: 11 additions & 2 deletions test/unit/presenters/filtered_editions_presenter_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -131,11 +131,20 @@ def a_gds_user
assert_equal(2, filtered_editions.count)
end

should "filter by a partially-matching title" do
should "search by a case-insensitively, partially-matching title" do
guide_fawkes = FactoryBot.create(:guide_edition, title: "Guide Fawkes")
FactoryBot.create(:guide_edition, title: "Hitchhiker's Guide")

filtered_editions = FilteredEditionsPresenter.new(a_gds_user, title_filter: "Fawkes").editions
filtered_editions = FilteredEditionsPresenter.new(a_gds_user, search_text: "fawkes").editions

assert_equal([guide_fawkes], filtered_editions.to_a)
end

should "search by a case-insensitively, partially-matching slug" do
guide_fawkes = FactoryBot.create(:guide_edition, title: "A non-matching title", slug: "guide-fawkes")
FactoryBot.create(:guide_edition, title: "Another non-matching title", slug: "hitchhikers-guide")

filtered_editions = FilteredEditionsPresenter.new(a_gds_user, search_text: "fawkes").editions

assert_equal([guide_fawkes], filtered_editions.to_a)
end
Expand Down

0 comments on commit 9f0f082

Please sign in to comment.