diff --git a/libs/blocks/mmm/mmm.css b/libs/blocks/mmm/mmm.css index 72a7aecee2..b7fe2baa90 100644 --- a/libs/blocks/mmm/mmm.css +++ b/libs/blocks/mmm/mmm.css @@ -491,14 +491,13 @@ dd .mep-popup-header .mep-close { pointer-events: none; } #mmm-pagination .arrow { - font-size: 1.5rem; font-weight: 600; } .mmm-pagination-summary { display: flex; justify-content: flex-end; - padding: 0 0 .5rem; + padding: 0 0; } main > .section > .share-mmm.inline { @@ -528,4 +527,49 @@ main > .section > .inline-wrapper > .share-mmm.inline { #mmm-pagination { padding: 2rem 4rem; } -} \ No newline at end of file +} + +/* pagination */ +#mmm-pagination-wrapper { + width: 100%; + display: flex; + gap: 10px; + justify-content: right; + flex-direction: row; +} + +#pagination-select { + align-items: center; +} + +#mmm-pagination-wrapper label, +#mmm-pagination-wrapper span { + font-size: 12px; + font-weight: 400; + text-align: left; +} + +#mmm-pagination-dropdown { + min-width: 90px; + height: 36px; + border-radius: 4px; + margin-right: 20px; +} + +#pagination-arrows, +#pagination-select { + display: flex; + gap: 10px; + align-items: center; +} + +#pagination-arrows a:not(.disabled) { + color: #000; + cursor: pointer; +} + +#pagination-arrows a.disabled svg { + opacity: .4; +} + + diff --git a/libs/blocks/mmm/mmm.js b/libs/blocks/mmm/mmm.js index 06f4e2ce0c..70c7878c44 100644 --- a/libs/blocks/mmm/mmm.js +++ b/libs/blocks/mmm/mmm.js @@ -49,6 +49,7 @@ const SEARCH_INITIAL_VALUES = getInitialValues() ?? { lastSeenManifest: LAST_SEEN_OPTIONS.threeMonths.key, pageNum: 1, subdomain: SUBDOMAIN_OPTIONS.www.key, + perPage: 25, }; async function toggleDrawer(target, dd, pageId) { @@ -123,7 +124,7 @@ function createButtonDetailsPair(mmmEl, page) { * @param {Number} pageNum - optional. Number of the clicked page. * @param {Event} event - optional. Page number click Event object. */ -function filterPageList(pageNum, event) { +function filterPageList(pageNum, perPage, event) { const shareUrl = new URL(`${window.location.origin}${window.location.pathname}`); const searchValues = {}; const activeSearchWithShortKeyword = event?.target?.value && event.target.value.length < 2; @@ -138,9 +139,9 @@ function filterPageList(pageNum, event) { if (value) shareUrl.searchParams.set(id, value); }); - // add page number to share url - shareUrl.searchParams.set('pageNum', pageNum || 1); + // add pageNum and perPage to args for api call searchValues.pageNum = { value: pageNum || 1, tagName: 'A' }; + searchValues.perPage = { value: perPage || 25, tagName: 'SELECT' }; // assemble event details object with all filter criterias const detail = {}; @@ -269,8 +270,8 @@ function createSearchField() { const searchField = searchForm.querySelector('textarea'); searchField.value = SEARCH_INITIAL_VALUES.filter || ''; - searchField.addEventListener('keyup', debounce((event) => filterPageList(null, event))); - searchField.addEventListener('change', debounce((event) => filterPageList(null, event))); + searchField.addEventListener('keyup', debounce((event) => filterPageList(null, null, event))); + searchField.addEventListener('change', debounce((event) => filterPageList(null, null, event))); searchField.addEventListener('input', function adjustHeight() { this.style.height = 'auto'; /* Reset height to auto to recalculate */ this.style.height = `${this.scrollHeight - 32}px`; @@ -314,51 +315,103 @@ async function createForm(el) { } function createPaginationEl({ data, el }) { - const paginationEl = createTag('div', { id: 'mmm-pagination', 'data-current-page': data.pageNum }); - const totalPages = Math.ceil(data.totalRecords / data.perPage); - const noResult = !data.totalRecords; - const prev = data.pageNum - 1 || 1; - const next = data.pageNum < totalPages ? data.pageNum + 1 : data.pageNum; - - const prevEl = createTag('a', { - 'data-page-num': prev, - class: `arrow ${data.pageNum === 1 ? 'disabled' : ''}`, - }, '<'); - const nextEl = createTag('a', { - 'data-page-num': next, - class: `arrow ${data.pageNum === totalPages ? 'disabled' : ''}`, - }, '>'); - - const paginationSummary = createTag('div', { class: 'mmm-pagination-summary' }); - const range = `${data.pageNum * data.perPage - (data.perPage - 1)}-${data.pageNum * data.perPage < data.totalRecords ? data.pageNum * data.perPage : data.totalRecords}`; - paginationSummary.innerHTML = ` -
- ${range} of ${data.totalRecords} -
- `; - if (!noResult) { - paginationEl.append(prevEl); - for (let i = 1; i <= totalPages; i += 1) { - const pageLink = createTag('a', { - class: `${i === data.pageNum ? 'current-page' : ''}`, - 'data-page-num': i, - }, i); - paginationEl.append(pageLink); - } - paginationEl.append(nextEl); - document.querySelector('#mmm').prepend(paginationSummary); + const { pageNum, perPage, totalRecords } = data; + const arrowIcons = { + first: '', + prev: '', + next: '', + last: '', + }; + const paginationEl = createTag('div', { + id: 'mmm-pagination', + 'data-current-page': pageNum, + 'data-perpage': perPage, + }); + if (totalRecords) { + const perPageOptions = [25, 50, 100]; // add more options as needed + const paginationWrapper = createTag('div', { id: 'mmm-pagination-wrapper' }); + const paginationLabel = createTag( + 'label', + { for: 'mmm-pagination-dropdown' }, + 'Items per page:', + ); + const paginationDropdown = createTag( + 'select', + { + id: 'mmm-pagination-dropdown', + value: perPage, + }, + ); + perPageOptions.forEach((option) => paginationDropdown.append(createTag('option', { + value: option, + ...(option === perPage ? { selected: 'selected' } : {}), + }, option))); + paginationEl.append(paginationWrapper); + const totalPages = Math.ceil(totalRecords / perPage); + const prev = pageNum - 1 || 1; + const next = pageNum < totalPages ? pageNum + 1 : pageNum; + const firstEl = createTag('a', { + 'data-page-num': '1', + class: `arrow ${pageNum === 1 ? 'disabled' : ''}`, + }, arrowIcons.first); + const prevEl = createTag('a', { + 'data-page-num': prev, + class: `arrow ${pageNum === 1 ? 'disabled' : ''}`, + }, arrowIcons.prev); + const nextEl = createTag('a', { + 'data-page-num': next, + class: `arrow ${pageNum === totalPages ? 'disabled' : ''}`, + }, arrowIcons.next); + const lastEl = createTag('a', { + 'data-page-num': totalPages, + class: `arrow ${pageNum === totalPages ? 'disabled' : ''}`, + }, arrowIcons.last); + const rangeStart = pageNum * perPage - (perPage - 1); + const rangeEnd = pageNum * perPage < totalRecords ? pageNum * perPage : totalRecords; + const range = `${rangeStart.toLocaleString()} - ${rangeEnd.toLocaleString()}`; + const paginationSummary = createTag( + 'div', + { class: 'mmm-pagination-summary' }, + `
${range} of ${totalRecords.toLocaleString()}
`, + ); + paginationWrapper.append( + createTag('div', { id: 'pagination-select' }, [paginationLabel, paginationDropdown]), + createTag('div', { id: 'pagination-arrows' }, [ + firstEl, + prevEl, + paginationSummary, + nextEl, + lastEl, + ]), + ); } else { - paginationEl.innerHTML = '
No results.
'; + paginationEl.append(createTag('h5', { id: 'mmm-pagination-no-results' }, 'No results')); } el.append(paginationEl); } +function handlePaginationDropdownChange() { + const paginationEl = document.querySelector('#mmm-pagination'); + paginationEl?.querySelector('select')?.addEventListener('change', (event) => { + paginationEl.dataset.perpage = event.target.value; + filterPageList( + paginationEl.dataset.pageNum, + paginationEl.dataset.perpage, + event, + ); + }); +} + function handlePaginationClicks() { const paginationEl = document.querySelector('#mmm-pagination'); paginationEl?.querySelectorAll('a').forEach((item) => { - item?.addEventListener('click', () => { - item.parentNode.setAttribute('data-current-page', item.getAttribute('data-page-num')); - filterPageList(item.getAttribute('data-page-num')); + item?.addEventListener('click', (event) => { + paginationEl.dataset.currentPage = item.dataset.pageNum; + filterPageList( + item.dataset.pageNum, + paginationEl.dataset.perpage, + event, + ); }); }); } @@ -388,11 +441,12 @@ async function createPageList(el, search) { el.replaceWith(mmmElContainer); main.append(section); createPaginationEl({ - el: mmmElContainer, data: response, + el: mmmElContainer, }); paginationEl?.classList.remove('mmm-hide'); handlePaginationClicks(); + handlePaginationDropdownChange(); } /**