Skip to content

Commit

Permalink
Style the publications page pagination controls
Browse files Browse the repository at this point in the history
Copy the way Whitehall Publisher overrides Kaminari's partials to style
 its pagination components. It would be good for the
 govuk_publishing_components gem to have a pagination control which both
 apps could use, but implementing that would take some time so we will
 create a new ticket for this.
  • Loading branch information
mtaylorgds committed Aug 28, 2024
1 parent 6c662a1 commit 827341b
Show file tree
Hide file tree
Showing 5 changed files with 233 additions and 0 deletions.
1 change: 1 addition & 0 deletions app/assets/stylesheets/application.scss
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ $govuk-page-width: 1140px;
@import 'govuk_publishing_components/components/layout-header';
@import 'govuk_publishing_components/components/lead-paragraph';
@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/skip-link';
@import 'govuk_publishing_components/components/success-alert';
Expand Down
158 changes: 158 additions & 0 deletions app/helpers/pagination_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
module PaginationHelper
class << self
LARGE_NUMBER_OF_PAGES = 6

def pagination_hash(current_page:, total_pages:, path:)
return if total_pages == 1

self.current_page = current_page
self.total_pages = total_pages
self.path = normalise_path(path, current_page)

previous_page = current_page - 1 if current_page >= 2
next_page = current_page + 1 if current_page < total_pages

previous_page_href = build_path_for(current_page - 1)
self.previous_href = previous_page.present? ? previous_page_href : nil

next_page_href = build_path_for(current_page + 1) if next_page.present?
self.next_href = next_page_href.presence

if total_pages >= LARGE_NUMBER_OF_PAGES
large_page_number_hash
else
small_page_number_hash
end
end

private

attr_accessor :path, :previous_href, :next_href, :current_page, :total_pages

def normalise_path(path, current_page)
if url_has_page_param?(path)
path
elsif url_has_a_query_string?(path) && !url_has_an_anchor?(path)
path + "&page=#{current_page}"
elsif url_has_a_query_string?(path) && url_has_an_anchor?(path)
path.gsub("#", "&page=#{current_page}#")
elsif url_has_an_anchor?(path)
path.gsub("#", "?page=#{current_page}#")
else
path + "?page=#{current_page}"
end
end

def url_has_page_param?(path)
path.include?("page=#{current_page}")
end

def url_has_a_query_string?(path)
path.include?("?")
end

def url_has_an_anchor?(path)
path.include?("#")
end

def build_path_for(page)
path.gsub("page=#{current_page}", "page=#{page}")
end

def small_page_number_hash
items = []

[*1..total_pages].map do |page|
items << {
href: build_path_for(page),
current: page == current_page,
}
end

{
previous_href:,
next_href:,
items:,
}
end

def large_page_number_hash
items = [
first_page_hash,
first_elipsis_hash,
middle_pages_array,
second_elipsis_hash,
last_page_hash,
]
.flatten
.compact

{
previous_href:,
next_href:,
items:,
}
end

def first_page_hash
{
href: build_path_for(1),
label: "1",
current: current_page == 1,
aria_label: "Page 1",
}
end

def first_elipsis_hash
return unless current_page >= 4

{ ellipses: true }
end

def middle_pages_array
get_page_numbers.map do |page|
{
href: build_path_for(page),
label: page.to_s,
current: current_page == page,
aria_label: "Page #{page}",
}
end
end

def get_page_numbers
first_page = 1
second_page = 2
penultimate_page = total_pages - 1
last_page = total_pages

case current_page
when first_page
[first_page + 1, first_page + 2, first_page + 3]
when second_page
[second_page, second_page + 1, second_page + 2]
when last_page
[last_page - 3, last_page - 2, last_page - 1]
when penultimate_page
[penultimate_page - 2, penultimate_page - 1, penultimate_page]
else
[current_page - 1, current_page, current_page + 1]
end
end

def second_elipsis_hash
return unless total_pages - current_page >= 3

{ ellipses: true }
end

def last_page_hash
{
href: build_path_for(total_pages),
label: total_pages.to_s,
current: current_page == total_pages,
aria_label: "Page #{total_pages}",
}
end
end
end
60 changes: 60 additions & 0 deletions app/views/components/_pagination.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<%
id ||= "pagination-#{SecureRandom.hex(4)}"
aria_label ||= "Pagination"
items ||= []
previous_href ||= false
next_href ||= false
%>

<nav id="<% id %>" class="app-c-pagination govuk-pagination" role="navigation" aria-label="<%= aria_label %>">
<% if previous_href %>
<div class="govuk-pagination__prev">
<a class="govuk-link govuk-pagination__link" href="<%= previous_href %>" rel="prev">
<svg class="govuk-pagination__icon govuk-pagination__icon--prev" xmlns="http://www.w3.org/2000/svg" height="13" width="15" aria-hidden="true" focusable="false" viewBox="0 0 15 13">
<path d="m6.5938-0.0078125-6.7266 6.7266 6.7441 6.4062 1.377-1.449-4.1856-3.9768h12.896v-2h-12.984l4.2931-4.293-1.414-1.414z"></path>
</svg>
<span class="govuk-pagination__link-title">Previous<span class="govuk-visually-hidden"> page</span></span>
</a>
</div>
<% end %>

<ul class="govuk-pagination__list">
<% items.each_with_index do | item, index | %>
<%
item_label = item[:label] ? item[:label] : index + 1
item_aria_label = item[:label] ? item[:label] : "Page #{item_label}"
item_aria_label = (item[:aria_label].presence || item_aria_label)
list_item_classes = %w[govuk-pagination__item]
list_item_classes << "govuk-pagination__item--current" if item[:current]
list_item_classes << "govuk-pagination__item--ellipses" if item[:ellipses]
%>

<%= tag.li class: list_item_classes do %>
<% if item[:ellipses] %>
&ctdot;
<% else %>
<%= tag.a(
item_label,
class: "govuk-link govuk-pagination__link",
href: item[:href],
aria: {
label: item_aria_label,
current: item[:current] ? "page" : nil,
},
) %>
<% end %>
<% end %>
<% end %>
</ul>

<% if next_href %>
<div class="govuk-pagination__next">
<a class="govuk-link govuk-pagination__link" href="<%= next_href %>" rel="next">
<span class="govuk-pagination__link-title">Next<span class="govuk-visually-hidden"> page</span></span>
<svg class="govuk-pagination__icon govuk-pagination__icon--next" xmlns="http://www.w3.org/2000/svg" height="13" width="15" aria-hidden="true" focusable="false" viewBox="0 0 15 13">
<path d="m8.107-0.0078125-1.4136 1.414 4.2926 4.293h-12.986v2h12.896l-4.1855 3.9766 1.377 1.4492 6.7441-6.4062-6.7246-6.7266z"></path>
</svg>
</a>
</div>
<% end %>
</nav>
11 changes: 11 additions & 0 deletions app/views/kaminari/_paginator.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<% anchor = anchor.presence || "" %>

<% if total_pages > 1 %>
<% PaginationHelper.pagination_hash(current_page: current_page.to_i, total_pages:, path: request.url + anchor).tap do |hash| %>
<%= render "components/pagination", {
previous_href: hash[:previous_href],
next_href: hash[:next_href],
items: hash[:items],
} %>
<% end %>
<% end %>
3 changes: 3 additions & 0 deletions test/integration/edition_scheduled_publishing_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ class EditionScheduledPublishingTest < LegacyJavascriptIntegrationTest
stub_holidays_used_by_fact_check
# queue up the edition, don't perform inline
Sidekiq::Testing.fake!

test_strategy = Flipflop::FeatureSet.current.test!
test_strategy.switch!(:design_system_publications_filter, false)
end

teardown do
Expand Down

0 comments on commit 827341b

Please sign in to comment.