Skip to content

Commit

Permalink
Merge pull request #2301 from alphagov/205_filter-publications_UI
Browse files Browse the repository at this point in the history
205 filter publications UI
  • Loading branch information
davidtrussler authored Sep 6, 2024
2 parents ff72ea4 + a814f65 commit 41a25c0
Show file tree
Hide file tree
Showing 9 changed files with 211 additions and 41 deletions.
4 changes: 3 additions & 1 deletion app/assets/stylesheets/application.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ $govuk-page-width: 1140px;
@import 'govuk_publishing_components/govuk_frontend_support';
@import 'govuk_publishing_components/component_support';
@import 'govuk_publishing_components/components/button';
@import 'govuk_publishing_components/components/checkboxes';
@import 'govuk_publishing_components/components/date-input';
@import 'govuk_publishing_components/components/document-list';
@import 'govuk_publishing_components/components/error-alert';
Expand All @@ -22,13 +23,14 @@ $govuk-page-width: 1140px;
@import 'govuk_publishing_components/components/notice';
@import 'govuk_publishing_components/components/previous-and-next-navigation';
@import 'govuk_publishing_components/components/search';
@import 'govuk_publishing_components/components/select';
@import 'govuk_publishing_components/components/skip-link';
@import 'govuk_publishing_components/components/success-alert';
@import 'govuk_publishing_components/components/summary-list';
@import 'govuk_publishing_components/components/table';
@import 'govuk_publishing_components/components/textarea';
@import 'govuk_publishing_components/components/title';
@import "downtimes";
@import "publications";
@import "summary-card";
@import "popular_links";
@import "publications-table";
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
$width: 40;

.publications-filter {
background: govuk-colour("light-grey");

.gem-c-select {
label {
font-weight: 700;
}
}

.govuk-checkboxes__label::before {
background: govuk-colour("white");
}
}

.publications-table {
th:first-child {
width: calc($width * 1%);
Expand Down
6 changes: 3 additions & 3 deletions app/controllers/root_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ def index
states_filter_params = filter_params_hash[:states_filter]
sanitised_states_filter_params = states_filter_params&.select { |fp| PERMITTED_FILTER_STATES.include?(fp) }
assignee_filter = filter_params_hash[:assignee_filter]
format_filter = filter_params_hash[:format_filter]
content_type_filter = filter_params_hash[:content_type_filter]
title_filter = filter_params_hash[:title_filter]
@presenter = FilteredEditionsPresenter.new(
states_filter: sanitised_states_filter_params,
assigned_to_filter: assignee_filter,
format_filter:,
content_type_filter:,
title_filter:,
page: filter_params_hash[:page],
)
Expand All @@ -34,6 +34,6 @@ def index
private

def filter_params
params.permit(:page, :assignee_filter, :format_filter, :title_filter, states_filter: [])
params.permit(:page, :assignee_filter, :content_type_filter, :title_filter, states_filter: [])
end
end
9 changes: 0 additions & 9 deletions app/helpers/editions_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,4 @@ def legacy_format_filter_selection_options
[displayed_format_name, format_name]
end
end

def format_filter_selection_options
[%w[All all]] +
Artefact::FORMATS_BY_DEFAULT_OWNING_APP["publisher"].map do |format_name|
displayed_format_name = format_name.humanize
displayed_format_name += " (Retired)" if Artefact::RETIRED_FORMATS.include?(format_name)
[displayed_format_name, format_name]
end
end
end
83 changes: 76 additions & 7 deletions app/presenters/filtered_editions_presenter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,66 @@
class FilteredEditionsPresenter
ITEMS_PER_PAGE = 20

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

def title
@title_filter
end

def content_types
types = []

content_type_filter_selection_options.map do |content_type|
types << if content_type[1] == @content_type_filter
{ text: content_type[0], value: content_type[1], selected: "true" }
else
{ text: content_type[0], value: content_type[1] }
end
end

types
end

def edition_states
states = []

state_names.map do |scope, status_label|
states << if @states_filter.include? scope.to_s
{ label: status_label, value: scope, checked: "true" }
else
{ label: status_label, value: scope }
end
end

states
end

def available_users
User.enabled.alphabetized
end

def assignees
users = [{ text: "All assignees", value: "" }]

available_users.map do |user|
users << if user.id.to_s == @assigned_to_filter
{ text: user.name, value: user.id, selected: "true" }
else
{ text: user.name, value: user.id }
end
end

users
end

def editions
result = editions_by_format
result = editions_by_content_type
result = apply_states_filter(result)
result = apply_assigned_to_filter(result)
result = apply_title_filter(result)
Expand All @@ -26,10 +72,33 @@ def editions

private

def editions_by_format
return Edition.all unless format_filter && format_filter != "all"
def state_names
{
draft: "Drafts",
in_review: "In review",
amends_needed: "Amends needed",
fact_check: "Out for fact check",
fact_check_received: "Fact check received",
ready: "Ready",
scheduled_for_publishing: "Scheduled",
published: "Published",
archived: "Archived",
}
end

def content_type_filter_selection_options
[%w[All all]] +
Artefact::FORMATS_BY_DEFAULT_OWNING_APP["publisher"].map do |format_name|
displayed_format_name = format_name.humanize
displayed_format_name += " (Retired)" if Artefact::RETIRED_FORMATS.include?(format_name)
[displayed_format_name, format_name]
end
end

def editions_by_content_type
return Edition.all unless content_type_filter && content_type_filter != "all"

Edition.where(_type: "#{format_filter.camelcase}Edition")
Edition.where(_type: "#{content_type_filter.camelcase}Edition")
end

def apply_states_filter(editions)
Expand Down Expand Up @@ -60,5 +129,5 @@ def apply_title_filter(editions)
editions.title_contains(title_filter)
end

attr_reader :states_filter, :assigned_to_filter, :format_filter, :title_filter, :page
attr_reader :states_filter, :assigned_to_filter, :content_type_filter, :title_filter, :page
end
48 changes: 48 additions & 0 deletions app/views/root/_filter.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<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",
margin_bottom: 4,
} %>

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

<%= render "govuk_publishing_components/components/select", {
id: "assignee_filter",
full_width: true,
label: "Assigned to",
options: @presenter.assignees,
} %>

<%= render "govuk_publishing_components/components/select", {
id: "content_type_filter",
label: "Content type",
full_width: true,
options: @presenter.content_types,
} %>

<%= render "govuk_publishing_components/components/checkboxes", {
name: "states_filter[]",
heading: "Status",
heading_size: "s",
items: @presenter.edition_states,
} %>

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

<p class="govuk-body">
<%= link_to "Reset all fields", root_path, class: "govuk-link" %>
</p>
<% end %>
</div>
18 changes: 2 additions & 16 deletions app/views/root/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,9 @@
<% content_for :title, "Publications" %>

<div class="govuk-grid-column-one-third">
<%= form_with url: root_path, method: :get do |form| %>
<%= form.label :title_filter, "Title" %>
<%= text_field_tag :title_filter %>
<%= form.label :format_filter, "Format" %>
<%= select_tag :format_filter,
options_for_select(format_filter_selection_options) %>
<%= form.label :assignee_filter, "Assignee" %>
<%= select_tag :assignee_filter,
options_for_select([%w[Nobody nobody]]) <<
options_from_collection_for_select(@presenter.available_users, "id", "name") %>
<%= form.label :states_filter_draft, "Draft" %>
<%= check_box_tag "states_filter[]", "draft", false, { id: "states_filter_draft" } %>
<%= form.label :states_filter_published, "Published" %>
<%= check_box_tag "states_filter[]", "published", false, :id => "states_filter_published" %>
<%= form.submit %>
<% end %>
<%= render :partial => "filter" %>
</div>

<div class="govuk-grid-column-two-thirds">
<%= render :partial => "table" %>
<%= paginate @presenter.editions %>
Expand Down
13 changes: 10 additions & 3 deletions test/functional/root_controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ class RootControllerTest < ActionController::TestCase
assert_select "p.publications-table__heading", "1 document(s)"
end

should "filter publications by format" do
should "filter publications by content type" do
FactoryBot.create(:guide_edition)
FactoryBot.create(:completed_transaction_edition)

get :index, params: { format_filter: "guide" }
get :index, params: { content_type_filter: "guide" }

assert_response :ok
assert_select "p.publications-table__heading", "1 document(s)"
Expand All @@ -57,7 +57,14 @@ class RootControllerTest < ActionController::TestCase
FilteredEditionsPresenter
.expects(:new)
.with(has_entry(:states_filter, %w[draft]))
.returns(stub(editions: Kaminari.paginate_array([]).page(1), available_users: []))
.returns(stub(
editions: Kaminari.paginate_array([]).page(1),
available_users: [],
title: "",
assignees: [],
content_types: [],
edition_states: [],
))

get :index, params: { states_filter: %w[draft not_a_real_state] }
end
Expand Down
57 changes: 55 additions & 2 deletions test/unit/presenters/filtered_editions_presenter_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,59 @@
require "test_helper"

class FilteredEditionsPresenterTest < ActiveSupport::TestCase
context "#content_types" do
should "return content types with none selected when no content type filter has been specified" do
content_types = FilteredEditionsPresenter.new.content_types

assert_equal(13, content_types.count)
assert_includes(content_types, { text: "All", value: "all" })
assert_includes(content_types, { text: "Answer", value: "answer" })
assert_includes(content_types, { text: "Campaign (Retired)", value: "campaign" })
assert_includes(content_types, { text: "Completed transaction", value: "completed_transaction" })
assert_includes(content_types, { text: "Guide", value: "guide" })
assert_includes(content_types, { text: "Help page", value: "help_page" })
assert_includes(content_types, { text: "Licence (Retired)", value: "licence" })
assert_includes(content_types, { text: "Local transaction", value: "local_transaction" })
assert_includes(content_types, { text: "Place", value: "place" })
assert_includes(content_types, { text: "Programme (Retired)", value: "programme" })
assert_includes(content_types, { text: "Simple smart answer", value: "simple_smart_answer" })
assert_includes(content_types, { text: "Transaction", value: "transaction" })
assert_includes(content_types, { text: "Video (Retired)", value: "video" })
end

should "mark the relevant content type as selected when a content type filter has been specified" do
content_types = FilteredEditionsPresenter.new(content_type_filter: "answer").content_types

assert_includes(content_types, { text: "Answer", value: "answer", selected: "true" })
assert_includes(content_types, { text: "Place", value: "place" }) # Not selected
end
end

context "#edition_states" do
should "return states with none checked when no state filter has been specified" do
states = FilteredEditionsPresenter.new.edition_states

assert_equal(9, states.count)
assert_includes(states, { label: "Drafts", value: :draft })
assert_includes(states, { label: "In review", value: :in_review })
assert_includes(states, { label: "Amends needed", value: :amends_needed })
assert_includes(states, { label: "Out for fact check", value: :fact_check })
assert_includes(states, { label: "Fact check received", value: :fact_check_received })
assert_includes(states, { label: "Ready", value: :ready })
assert_includes(states, { label: "Scheduled", value: :scheduled_for_publishing })
assert_includes(states, { label: "Published", value: :published })
assert_includes(states, { label: "Archived", value: :archived })
end

should "mark the relevant states as checked when a state filter has been specified" do
states = FilteredEditionsPresenter.new(states_filter: %w[in_review ready]).edition_states

assert_includes(states, { label: "In review", value: :in_review, checked: "true" })
assert_includes(states, { label: "Ready", value: :ready, checked: "true" })
assert_includes(states, { label: "Published", value: :published }) # Not checked
end
end

context "#editions" do
should "return all editions when no filters are specified" do
draft_guide = FactoryBot.create(:guide_edition, state: "draft")
Expand Down Expand Up @@ -60,7 +113,7 @@ class FilteredEditionsPresenterTest < ActiveSupport::TestCase
guide = FactoryBot.create(:guide_edition)
FactoryBot.create(:completed_transaction_edition)

filtered_editions = FilteredEditionsPresenter.new(format_filter: "guide").editions
filtered_editions = FilteredEditionsPresenter.new(content_type_filter: "guide").editions

assert_equal([guide], filtered_editions.to_a)
end
Expand All @@ -69,7 +122,7 @@ class FilteredEditionsPresenterTest < ActiveSupport::TestCase
FactoryBot.create(:guide_edition)
FactoryBot.create(:completed_transaction_edition)

filtered_editions = FilteredEditionsPresenter.new(format_filter: "all").editions
filtered_editions = FilteredEditionsPresenter.new(content_type_filter: "all").editions

assert_equal(2, filtered_editions.count)
end
Expand Down

0 comments on commit 41a25c0

Please sign in to comment.