Skip to content

Commit

Permalink
Add pagination to Manage users and Vaccine batches (#114)
Browse files Browse the repository at this point in the history
This adds a pagination component to the bottom of the Manage users page,
rather than just displaying all users on a single page.

The number of users per page is set at 20, although this could be
tweaked.

The pagination component is not yet part of the NHS design system, so
I’ve borrowed the GOV.UK one and applied NHS styling. This is still
work-in-progress, and I’m working on contributing this to the NHS design
system here: nhsuk/nhsuk-frontend#1026

## Screenshots

### Manage users

| First page | Middle page | Last page |
| ------ | ------ | ------ |
|
![manage-users-page-1](https://github.com/user-attachments/assets/79f2e200-f771-4327-bc60-e4e30f706d09)
|
![manage-users-page-3](https://github.com/user-attachments/assets/635e8a69-72ab-4f93-8fba-623d484cb225)
|
![manage-users-page-5](https://github.com/user-attachments/assets/3ba01ff2-3d6d-48be-be78-5e79ec588794)
|

### Vaccine batches (on vaccine product page for a given site)


![pagination-of-vaccine-batches](https://github.com/user-attachments/assets/99772ecc-8a09-4300-935f-0c463f6ae7a2)


If there are a lot of pages, then ellipsis would be used to show gaps in
the sequence, so that the first page, last page, previous and next page
are always included:

<img width="608" alt="Screenshot 2024-09-23 at 16 09 43"
src="https://github.com/user-attachments/assets/500b8dfd-2ecc-4f69-b8a4-3078642a1fbe">
  • Loading branch information
frankieroberto authored Oct 24, 2024
1 parent 3a5707f commit be0609d
Show file tree
Hide file tree
Showing 12 changed files with 1,306 additions and 8 deletions.
1 change: 1 addition & 0 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ const appViews = [
path.join(__dirname, 'node_modules/nhsuk-frontend/packages/macros'),
path.join(__dirname, 'docs/views/'),
path.join(__dirname, 'lib/prototype-admin/'),
path.join(__dirname, 'app/components/'),
];

const nunjucksConfig = {
Expand Down
2 changes: 2 additions & 0 deletions app/assets/sass/main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ $govuk-brand-colour: $nhsuk-link-color;
@import 'components/table';


@import '../../components/pagination/_pagination';

.autocomplete__wrapper ul > li {
margin-bottom: 0;
}
Expand Down
5 changes: 5 additions & 0 deletions app/components/pagination/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Pagination

This is a work-in-progress modification of the Pagination component to support numbered pages.

See https://github.com/nhsuk/nhsuk-frontend/pull/1026
240 changes: 240 additions & 0 deletions app/components/pagination/_pagination.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
/* ==========================================================================
COMPONENTS / #PAGINATION
========================================================================== */

/**
* 1. Padding to give the icon spacing.
* 2. Append the word 'page' after next and
* previous on print stylesheets to make it easier
* to understand in print context.
*/

// Previous and next pages variant
.nhsuk-pagination {
@include nhsuk-responsive-margin(7, "top");
@include nhsuk-responsive-margin(7, "bottom");
}

.nhsuk-pagination__list {
@include clearfix();
}

.nhsuk-pagination-item--previous {
float: left;
text-align: left;
width: 50%;

.nhsuk-icon {
left: -6px;
}

.nhsuk-pagination__title {
padding-left: nhsuk-spacing(5); /* [1] */
}
}

.nhsuk-pagination-item--next {
float: right;
text-align: right;
width: 50%;

.nhsuk-icon {
right: -6px;
}

.nhsuk-pagination__title {
padding-right: nhsuk-spacing(5); /* [1] */
}
}

.nhsuk-pagination__link {
display: block;
position: relative;
text-decoration: none;
width: 100%;

@include mq($media-type: print) {
color: $color_nhsuk-black;
}

.nhsuk-icon {
position: absolute;
top: -2px;

@include mq($media-type: print) {
color: $color_nhsuk-black;
margin-top: 0;
}
}

&:hover {
color: $nhsuk-link-hover-color;

.nhsuk-icon {
fill: $nhsuk-link-hover-color;
}

.nhsuk-pagination__page {
text-decoration: none;
}
}

&:focus {
@include nhsuk-focused-text;

.nhsuk-pagination__page {
text-decoration: none;
}

&:visited,
&:hover,
&:active {
.nhsuk-icon {
fill: $nhsuk-focus-text-color;
}
}
}

&:visited {
.nhsuk-icon {
fill: $nhsuk-link-visited-color;
}

&:hover {
.nhsuk-icon {
fill: $nhsuk-link-hover-color;
}
}

&:focus {
.nhsuk-icon {
fill: $nhsuk-focus-text-color;
}
}
}
}

.nhsuk-pagination__title {
@include nhsuk-typography-responsive(24);

display: block;

@include mq($media-type: print) {
&:after {
content: " page"; /* [2] */
}
}
}

.nhsuk-pagination__page {
@include nhsuk-typography-responsive(16);

display: block;
text-decoration: underline;
}

// Numbered pages variant
.nhsuk-pagination--numbered {
@include clearfix();
}

// In a numbered list, the previous link, numbered page links,
// and next link should all line up
.nhsuk-pagination--numbered__prev,
.nhsuk-pagination--numbered__next,
.nhsuk-pagination--numbered__item {
@include nhsuk-font(19);
box-sizing: border-box;
position: relative;
min-width: 45px;
min-height: 45px;
padding: nhsuk-spacing(2) nhsuk-spacing(2);
text-align: center;
margin: 0;
float: left;
}

.nhsuk-pagination--numbered__link:visited:hover,
.nhsuk-pagination--numbered__item a:hover {
color: $nhsuk-link-hover-color;
}

.nhsuk-pagination--numbered__prev:hover,
.nhsuk-pagination--numbered__next:hover,
.nhsuk-pagination--numbered__item:hover {
background-color: $color_nhsuk-grey-4;
color: $color_nhsuk-blue;
}

// Container for the list of numbered items
.nhsuk-pagination__list--numbered {
margin: 0;
padding: 0;
list-style: none;
}

// Current number
.nhsuk-pagination--numbered__item--current,
.nhsuk-pagination--numbered__item--current:hover {
background-color: $color_nhsuk-blue;
font-weight: $nhsuk-font-bold;

.nhsuk-pagination--numbered__link {
color: $color_nhsuk-white;
}

.nhsuk-pagination--numbered__link:focus {
color: $color_nhsuk-black;
}
}

.nhsuk-pagination--numbered__item--ellipses {
font-weight: $nhsuk-font-bold;
color: $nhsuk-secondary-text-color;

&:hover {
background-color: transparent;
}
}

.nhsuk-pagination--numbered__link {
min-width: nhsuk-spacing(3);
vertical-align: middle;
color: $color_nhsuk-blue;

// Increase the touch area for the link to the parent element.
@media screen {
&::after {
content: "";
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
}
}

.nhsuk-pagination--numbered .nhsuk-icon {
margin-top: 0;
margin-bottom: -12px;
fill: $color_nhsuk-blue;
}

.nhsuk-pagination--numbered__link:visited .nhsuk-icon {
fill: $nhsuk-link-visited-color;
}

.nhsuk-pagination--numbered__link:hover .nhsuk-icon {
fill: $nhsuk-link-hover-color;
}

.nhsuk-pagination--numbered .nhsuk-icon__arrow-left {
margin-left: -13px;
margin-right: nhsuk-spacing(2);
}

.nhsuk-pagination--numbered .nhsuk-icon__arrow-right {
margin-left: nhsuk-spacing(2);
margin-right: -13px;
}
3 changes: 3 additions & 0 deletions app/components/pagination/macro.njk
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{% macro appPagination(params) %}
{%- include './template.njk' -%}
{% endmacro %}
106 changes: 106 additions & 0 deletions app/components/pagination/template.njk
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
{% from "../../../node_modules/nhsuk-frontend/packages/macros/attributes.njk" import nhsukAttributes %}

{# There are 2 variants of this component, one for content pages which
has only previous and next links including the titles of those pages,
and one for navigating between pages of items, like search results.
The numbered variable sets which variant is being used, based on the
presence of items (pages). #}
{% set numbered = true if params.items %}

{# Arrow pointing left - used by both variants #}
{%- macro _arrowPrevious() -%}
<svg class="nhsuk-icon nhsuk-icon__arrow-left" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true" width="34" height="34">
<path d="M4.1 12.3l2.7 3c.2.2.5.2.7 0 .1-.1.1-.2.1-.3v-2h11c.6 0 1-.4 1-1s-.4-1-1-1h-11V9c0-.2-.1-.4-.3-.5h-.2c-.1 0-.3.1-.4.2l-2.7 3c0 .2 0 .4.1.6z"></path>
</svg>
{%- endmacro -%}

{# Arrow pointing right - used by both variants #}
{%- macro _arrowNext() -%}
<svg class="nhsuk-icon nhsuk-icon__arrow-right" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true" width="34" height="34">
<path d="M19.6 11.66l-2.73-3A.51.51 0 0 0 16 9v2H5a1 1 0 0 0 0 2h11v2a.5.5 0 0 0 .32.46.39.39 0 0 0 .18 0 .52.52 0 0 0 .37-.16l2.73-3a.5.5 0 0 0 0-.64z"></path>
</svg>
{%- endmacro -%}

{# Numbered page - included as a link within a list item. #}
{%- macro _pageItem(item) -%}
<li class="nhsuk-pagination--numbered__item {%- if item.current %} nhsuk-pagination--numbered__item--current{% endif %} {%- if item.ellipsis %} nhsuk-pagination--numbered__item--ellipses{% endif %} {%- if item.classes %} {{ item.classes }}{% endif %}">
{% if item.ellipsis %}
&ctdot;
{% else %}
<a class="nhsuk-pagination--numbered__link" href="{{ item.href }}" aria-label="{{ item.visuallyHiddenText | default("Page " + item.number) }}"
{%- if item.current %} aria-current="page"{% endif %}
{{- nhsukAttributes(item.attributes) }}>
{{ item.number }}
</a>
{% endif %}
</li>
{%- endmacro -%}

{# Link for the previous or next or next page, displayed at either end of
the numbered variant only, and including an arrow pointing left or right. #}
{%- macro _arrowLink(link, type = "next") %}
{% set arrowType = arrowPrevious if type == "prev" else arrowNext %}
<div class="nhsuk-pagination--numbered__{{ type }}">
<a class="nhsuk-pagination--numbered__link" href="{{ link }}" rel="{{ type }}">
{%- if type == "prev" -%}
{{ _arrowPrevious() }}
{%- endif -%}
{{ caller() | safe }}
{%- if type == "next" -%}
{{ _arrowNext() }}
{%- endif -%}
</a>
</div>
{% endmacro -%}

<nav class="nhsuk-pagination {{ "nhsuk-pagination--numbered" if numbered }}
{%- if params.classes %} {{ params.classes }}{% endif %}" role="navigation" aria-label="Pagination"
{{- nhsukAttributes(params.attributes) }}>

{%- if numbered %}
{% if params.previousUrl %}
{% call _arrowLink(params.previousUrl, "prev") -%}
Previous<span class="nhsuk-u-visually-hidden"> page</span>
{% endcall %}
{% endif %}

<ul class="nhsuk-pagination__list--numbered">
{% for item in params.items %}
{{ _pageItem(item) | indent(2) }}
{% endfor %}
</ul>

{% if params.nextUrl %}
{% call _arrowLink(params.nextUrl, "next") -%}
Next<span class="nhsuk-u-visually-hidden"> page</span>
{%- endcall %}
{% endif %}

{%- else %}

<ul class="nhsuk-list nhsuk-pagination__list">
{%- if params.previousUrl and params.previousPage %}
<li class="nhsuk-pagination-item--previous">
<a class="nhsuk-pagination__link nhsuk-pagination__link--prev" href="{{ params.previousUrl }}">
<span class="nhsuk-pagination__title">Previous</span>
<span class="nhsuk-u-visually-hidden">:</span>
<span class="nhsuk-pagination__page">{{ params.previousPage }}</span>
{{ _arrowPrevious() }}
</a>
</li>
{%- endif %}
{%- if params.nextUrl and params.nextPage %}
<li class="nhsuk-pagination-item--next">
<a class="nhsuk-pagination__link nhsuk-pagination__link--next" href="{{ params.nextUrl }}">
<span class="nhsuk-pagination__title">Next</span>
<span class="nhsuk-u-visually-hidden">:</span>
<span class="nhsuk-pagination__page">{{ params.nextPage }}</span>
{{ _arrowNext() }}
</a>
</li>

{%- endif %}
</ul>
{%- endif %}
</nav>
Loading

0 comments on commit be0609d

Please sign in to comment.