Skip to content

Commit

Permalink
VACMS-16986 Resources & Support, Story Listing, Press Releases pagina…
Browse files Browse the repository at this point in the history
…tion upgrade and link upgrades (#1941)
  • Loading branch information
randimays authored Mar 12, 2024
1 parent d0f135c commit 7d38181
Show file tree
Hide file tree
Showing 7 changed files with 176 additions and 57 deletions.
2 changes: 1 addition & 1 deletion src/site/filters/liquid.js
Original file line number Diff line number Diff line change
Expand Up @@ -1294,7 +1294,6 @@ module.exports = function registerFilters() {
//* paginatePages has limitations, it is not yet fully operational.
liquid.filters.paginatePages = (page, items, aria) => {
const perPage = 10;

const ariaLabel = aria ? ` of ${aria}` : '';

const paginationPath = pageNum => {
Expand All @@ -1308,6 +1307,7 @@ module.exports = function registerFilters() {

for (let pageNum = 0; pageNum < pagedEntities.length; pageNum++) {
let pagedPage = { ...page };

if (pageNum > 0) {
pagedPage = set(
'entityUrl.path',
Expand Down
97 changes: 97 additions & 0 deletions src/site/includes/README-pagination.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# Pagination in Drupal static pages

Template: [pagination.drupal.liquid](https://github.com/department-of-veterans-affairs/content-build/blob/main/src/site/includes/pagination.drupal.liquid)

As of March 2024, content-build is using the V3 pagination web component ([docs here](https://design.va.gov/components/pagination)).

On static pages, we cannot dynamically swap content on the page, so a full page reload is necessary for changing between sets of paginated items. The `<va-pagination>` component requires a `pageSelect` event handler, so we use the `updateCurrentPage` function to handle pagination.

There are two types of pagination methods that we know of. For Resources & Support (`support_resources_article_listing.drupal.liquid`), the pages exist at `/{path}/{pageNumber}`. For Story Listings (`story_listing.drupal.liquid`) and Press Releases (`press_releases_listing.drupal.liquid`), the pages exist at `/{path}/page-{pageNumber}`. This formatting comes from Drupal.

## Code implementation summary

Before the `updateCurrentPage` event handler is fired, we first select the `<va-pagination>` parent element, and set its `page` attribute based on the landing URL. `<va-pagination>`'s `page` attribute sets the active page number on the component.

When the `updateCurrentPage` event handler is fired, we grab the page number that was clicked (`newPage`) and couple that with the landing URL to form the next page to display.

## Full code explanation

From `pagination.drupal.liquid`:

```
// Determine whether this is a Resources & Support page, Story Listing or Press Release
// This data is passed in through those respective templates.
const addPrefixToPage = !!'{{ pagePrefix }}';
// Select the `<va-pagination>` element
const pagination = document.querySelector('va-pagination');
// The full URL for the page we're looking at currently
const landingUrl = '{{ entityUrl }}';
// Make URLs uniform with a trailing slash so appending page numbers will be straightforward
if (landingUrl.charAt(landingUrl.length - 1) !== '/') {
landingUrl = `${landingUrl}/`;
}
// Break URL into parts, remove empty parts and focus on the last part (the page number if it exists)
let urlParts = landingUrl.split('/');
urlParts = urlParts.filter(part => part !== '');
const lastPart = urlParts[urlParts.length - 1];
let currentPage;
// If the end of the URL has a Story Listing or Press Release page format (`/{path}/page-{pageNumber}`)
// Remove the `page-` part and assign that to the `currentPage` variable
// Then remove the page data from the URL
if (lastPart.includes('page')) {
currentPage = lastPart.replace('page-', '');
urlParts.pop(lastPart);
// If the end of the URL has a Resources & Support page format (`/{path}/{pageNumber}`)
// Assign that to the `currentPage` variable
// Then remove the page data from the URL
} else if (Number(lastPart)) {
currentPage = lastPart;
urlParts.pop(lastPart);
// If the end of the URL is not a page number, we've landed on page 1 of a paginated page
} else {
currentPage = '1';
}
// Assign the `page` attribute to the `<va-pagination>` component
// This highlights the correct number on the interface
pagination.setAttribute('page', currentPage);
// ACTUAL PAGE CLICK HANDLER
const updateCurrentPage = event => {
// Save clicked number
let newPage = event?.detail?.page;
let newEntityUrl;
// If the page is 1, the URL should not include a page number
if (newPage === '1') {
newPage = '';
// If Story Listing or Press Release page format (`/{path}/page-{pageNumber}`)
// add page- to the newPage variable so it can be used to create the newEntityUrl
} else if (addPrefixToPage && newPage !== '1') {
newPage = `page-${newPage}`;
}
// Join the segmented URL back together (array is created outside the event handler)
const joinedUrl = urlParts.join('/');
// Prepend a forward slash if needed and assign the newEntityUrl
if (joinedUrl.charAt(0) === '/') {
newEntityUrl = `${joinedUrl}/${newPage}`;
} else {
newEntityUrl = `/${joinedUrl}/${newPage}`;
}
// Navigate to the newEntityUrl
window.location.href = newEntityUrl;
}
pagination.addEventListener('pageSelect', updateCurrentPage);
```


98 changes: 61 additions & 37 deletions src/site/includes/pagination.drupal.liquid
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
{% comment %}
See README-pagination.md for details about this template
paginator {
prev: url or null
page {
Expand All @@ -11,46 +13,68 @@
}
{% endcomment %}


{% assign paginatorCount = paginator.inner | size %}
{% assign totalItems = paginatorCount %}

{% if numItems %}
{% assign totalItems = numItems | times: .1 %}
{% endif%}

{% if paginator != empty and totalItems <= paginatorCount %}
<va-pagination
max-page-list-length="7"
page="1"
pages="{{ totalItems }}"
uswds
>
</va-pagination>

<script>
// See README-pagination.md for a detailed walkthrough of this code
const addPrefixToPage = !!'{{ pagePrefix }}';
const pagination = document.querySelector('va-pagination');
let landingUrl = '{{ entityUrl }}';
if (landingUrl.charAt(landingUrl.length - 1) !== '/') {
landingUrl = `${landingUrl}/`;
}
let urlParts = landingUrl.split('/');
urlParts = urlParts.filter(part => part !== '');
const lastPart = urlParts[urlParts.length - 1];
let currentPage;
if (lastPart.includes('page')) {
currentPage = lastPart.replace('page-', '');
urlParts.pop(lastPart);
} else if (Number(lastPart)) {
currentPage = lastPart;
urlParts.pop(lastPart);
} else {
currentPage = '1';
}
pagination.setAttribute('page', currentPage);
const updateCurrentPage = event => {
let newPage = event?.detail?.page.toString();
let newEntityUrl;
if (newPage === '1') {
newPage = '';
} else if (addPrefixToPage && newPage !== '1') {
newPage = `page-${newPage}`;
}
const joinedUrl = urlParts.join('/');
if (joinedUrl.charAt(0) === '/') {
newEntityUrl = `${joinedUrl}/${newPage}`;
} else {
newEntityUrl = `/${joinedUrl}/${newPage}`;
}
window.location.href = newEntityUrl;
}
<div class="va-pagination" data-template="includes/pagination">
{% if paginator.prev != empty %}
<span class="va-pagination-prev">
<a href="{{ paginator.prev }}" aria-label="Load previous page{{ paginator.ariaLabel }}">
<abbr title="Previous">Prev</abbr>
</a>
</span>
{% endif %}
<div class="va-pagination-inner">
{% for page in paginator.inner %}
<a
aria-label="Load page {{ page.label }}{{ paginator.ariaLabel }}"
{% if page.class %}
class="{{ page.class }}"
{% endif %}
{% if page.class != "va-pagination-active" %}
href="{{ page.href }}"
{% endif %}
>
{{ page.label }}
</a>
{% assign totalItems = totalItems | minus: 1 %}
{% endfor %}
</div>
{% if paginator.next != empty %}
<span class="va-pagination-next">
<a href="{{ paginator.next }}" aria-label="Load next page{{ paginator.ariaLabel }}">
Next
</a>
</span>
{% endif %}
</div>
pagination.addEventListener('pageSelect', updateCurrentPage);
</script>
{% endif %}
6 changes: 4 additions & 2 deletions src/site/layouts/press_releases_listing.drupal.liquid
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,10 @@ larger space in the Fayette Plaza at 627 Pittsburgh Road, Suite 2, Uniontown,
{% if pagedItems.length < 1 %}
<div class="clearfix-text">No news releases at this time.</div>
{% endif %}

{% include "src/site/includes/pagination.drupal.liquid" %}
{% include "src/site/includes/pagination.drupal.liquid" with
entityUrl = entityUrl.path
pagePrefix = true
%}
</article>
<!--Last updated & feedback button-->
{% include "src/site/includes/above-footer-elements.drupal.liquid" %}
Expand Down
6 changes: 4 additions & 2 deletions src/site/layouts/story_listing.drupal.liquid
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@
{% if stories.length == 0 %}
<div class="clearfix-text">No stories at this time.</div>
{% endif %}

{% include "src/site/includes/pagination.drupal.liquid" %}
{% include "src/site/includes/pagination.drupal.liquid" with
entityUrl = entityUrl.path
pagePrefix = true
%}
</article>
<!--Last updated & feedback button-->
{% include "src/site/includes/above-footer-elements.drupal.liquid" %}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
{{ articleTypesByEntityBundle | get: article.entityBundle }}
</div>
<h2 class="vads-u-font-size--h3 vads-u-margin-top--0">
<a href="{{ article.entityUrl.path }}">{{ article.title }}</a>
<va-link href="{{ article.entityUrl.path }}" text="{{ article.title }}"></va-link>
</h2>
{% assign snippet = article.fieldIntroTextLimitedHtml %}

Expand All @@ -49,7 +49,7 @@
{% endfor %}
</ul>
</div>
{% include "src/site/includes/pagination.drupal.liquid" %}
{% include "src/site/includes/pagination.drupal.liquid" with entityUrl = path %}
<div class="usa-content">
<va-back-to-top></va-back-to-top>
<!-- Last updated & feedback button-->
Expand Down
20 changes: 7 additions & 13 deletions src/site/paragraphs/lists_of_links.drupal.liquid
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,16 @@
<!-- Links -->
{% for fieldLink in vaParagraph.entity.fieldLinks %}
<li class="vads-u-padding-y--1">
<a href="{{ fieldLink.url.path }}" rel="noreferrer noopener">
{{ fieldLink.title }}
</a>
<va-link href="{{ fieldLink.url.path }}" text="{{ fieldLink.title }}"></va-link>
</li>
{% endfor %}

<!-- See more articles link -->
{% if vaParagraph.entity.fieldLink.url.path %}
<li class="vads-u-padding-y--1">
<a class="vads-u-text-decoration--none" href="{{ vaParagraph.entity.fieldLink.url.path }}" rel="noreferrer noopener">
{{ vaParagraph.entity.fieldLink.title }} <i class="fa fa-chevron-right vads-u-padding-left--0p5 vads-u-font-size--sm" aria-hidden="true" role="presentation"></i>
</a>
<va-link active class="vads-u-text-decoration--none" href="{{ vaParagraph.entity.fieldLink.url.path }}" text="{{ vaParagraph.entity.fieldLink.title }}">
<i class="fa fa-chevron-right vads-u-padding-left--0p5 vads-u-font-size--sm" aria-hidden="true" role="presentation"></i>
</va-link>
</li>
{% endif %}
</ul>
Expand All @@ -49,18 +47,14 @@
<!-- Links -->
{% for fieldLink in vaParagraph.entity.fieldLinks %}
<li class="vads-u-padding-y--1">
<a href="{{ fieldLink.url.path }}" rel="noreferrer noopener">
{{ fieldLink.title }}
</a>
<va-link href="{{ fieldLink.url.path }}" text="{{ fieldLink.title }}"></va-link>
</li>
{% endfor %}

<!-- See more articles link -->
{% if vaParagraph.entity.fieldLink.url.path %}
<li class="vads-u-padding-y--1">
<a class="vads-u-text-decoration--none" href="{{ vaParagraph.entity.fieldLink.url.path }}" rel="noreferrer noopener">
{{ vaParagraph.entity.fieldLink.title }} <i class="fa fa-chevron-right vads-u-padding-left--0p5 vads-u-font-size--sm" aria-hidden="true" role="presentation"></i>
</a>
<va-link active href="{{ vaParagraph.entity.fieldLink.url.path }}" text="{{ vaParagraph.entity.fieldLink.title }}"></va-link>
</li>
{% endif %}
</ul>
Expand Down Expand Up @@ -91,6 +85,6 @@
</script>

<div aria-hidden="false" class="vads-u-display--flex vads-u-justify-content--center vads-u-margin-top--3" data-show-all-topics-button-lists_of_links-entity-id="{{ entity.entityId }}">
<button class="usa-button" onclick="onShowAllTopics()" type="button">Show all topics</button>
<va-button onclick="onShowAllTopics()" text="Show all topics" uswds></button>
</div>
{% endif %}

0 comments on commit 7d38181

Please sign in to comment.