Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(component): new builder paging control component #20

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<template lwc:render-mode="light">
<section
class="limitHitTextSection"
if:true={showMessageForResultsLimit}>
<p>{label.resultsLimitHitText}</p>
</section>

<nav class="pageControlPart">
<button
class="slds-m-horizontal_small slds-button slds-button_neutral nav-direction"
disabled={disablePaginationPrevious}
aria-disabled={disablePaginationPrevious}
onclick={handlePaginationPrevious}>
<lightning-icon
icon-name="utility:chevronleft"
size="xx-small"
alternative-text={label.previous}></lightning-icon>
</button>

<template
for:each={pageNumbers}
for:item="pageNumObj">
<template if:true={pageNumObj.isRange}>
<div
key={pageNumObj.id}
class="slds-m-horizontal_small range-symbol-container">
{rangeSymbol}
</div>
</template>
<template if:false={pageNumObj.isRange}>
<template if:true={pageNumObj.isCurrentPage}>
<span
class="slds-m-horizontal_small slds-button slds-button_brand nav-button-current"
key={pageNumObj.id}
aria-current="page">
{pageNumObj.pageNumber}
</span>
</template>
<template if:false={pageNumObj.isCurrentPage}>
<button
class="slds-m-horizontal_small slds-button slds-button_neutral nav-button"
key={pageNumObj.id}
value={pageNumObj.pageNumber}
onclick={handlePaginationPage}>
{pageNumObj.pageNumber}
</button>
</template>
</template>
</template>

<button
class="slds-m-horizontal_small slds-button slds-button_neutral nav-direction"
disabled={disablePaginationNext}
aria-disabled={disablePaginationNext}
onclick={handlePaginationNext}>
<lightning-icon
icon-name="utility:chevronright"
size="xx-small"
alternative-text={label.next}></lightning-icon>
</button>
</nav>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
/*
* Copyright (c) 2024, salesforce.com, inc.
* All rights reserved.
* SPDX-License-Identifier: Apache-2.0
* For full license text, see the LICENSE file in the repo
* root or https://opensource.org/licenses/apache-2-0/
*/
import { LightningElement, api } from 'lwc';
import { generatePagesForRange } from './pagingControlHelper';
import { PAGING_RANGE_SYMBOL, MAX_RESULTS_OFFSET } from './constants';
import { previous, next, resultsLimitHitText } from './labels';
export const ACTION_SEARCH_FILTERS_UPDATE = 'search:filterChange';
/**
* @param {*} value The value to check.
* @param {number} min The minimum value that _`value`_ needs to have.
* @returns {boolean} Whether the given _`value`_ is a number greater than _`min`_.
*/
function isNumber(value, min) {
return typeof value === 'number' && !Number.isNaN(value) && value > min;
}

/**
* An event fired when the user indicates a desire to go to the previous page.
* @event SearchPagingControl#pageprevious
* @type {CustomEvent}
*/

/**
* An event fired when the user indicates a desire to go to the next page.
* @event SearchPagingControl#pagenext
* @type {CustomEvent}
*/

/**
* An event fired when the user indicates a desire to go to a specific page.
* @event SearchPagingControl#pagegoto
* @type {CustomEvent}
* @property {object} detail CustomEvent details
* @property {number} detail.pageNumber
* The specific page number the user desires to go to.
*/

/**
* A page object to render the page item.
* @typedef {object} PageItem
* @property {number} id
* Identifier used as the key for the rendering element.
* @property {?number} pageNumber
* Page number
* @property {boolean} isCurrentPage
* Whether this page is the current page.
* @property {boolean} isRange
* Whether this page is a range element.
*/

/**
* A simple pagination UI control for any record visualization controls.
*/
export default class SearchPagingControl extends LightningElement {
static renderMode = 'light';

/**
* Current page number.
*/
@api
currentPageNumber;

/**
* Number of items per page.
*/
@api
pageSize;

/**
* Total number of items.
*/
@api
totalItemCount;

/**
* The maximum quantity of numbered pages displayed to the user.
* This includes numbers and range symbol.
*/
@api
maximumPagesDisplayed;

/**
* Gets the required i18n labels
* @readonly
* @private
*/
label = {
previous,
next,
resultsLimitHitText,
};
get normalizedPageNumber() {
return isNumber(this.currentPageNumber, 1) ? this.currentPageNumber : 1;
}
get normalizedPageSize() {
return isNumber(this.pageSize, 1) ? this.pageSize : 1;
}
get normalizedItemCount() {
return isNumber(this.totalItemCount, 0) ? this.totalItemCount : 0;
}

/**
* Disable previous page navigation?
* @type {boolean}
* @readonly
* @private
*/
get disablePaginationPrevious() {
return this.normalizedPageNumber === 1;
}

/**
* Disable next page navigation?
* @type {boolean}
* @readonly
* @private
*/
get disablePaginationNext() {
return this.normalizedPageNumber >= this.totalPages;
}

/**
* only show a message if this is the last page we could possibly show while there are more results due to API limitation:
* true if totalItemCount > 5000 + pageSize and this is the last page (aNumber to 5000+pageSize)
* @type {boolean}
* @readonly
* @private
*/
get showMessageForResultsLimit() {
const pageSize = this.normalizedPageSize;
return (
this.normalizedItemCount > MAX_RESULTS_OFFSET + pageSize &&
this.normalizedPageNumber >= Math.ceil((MAX_RESULTS_OFFSET + pageSize) / pageSize)
);
}

/**
* Gets total number of pages.
* @type {number}
* @readonly
* @private
*/
get totalPages() {
return Math.ceil(this.normalizedItemCount / this.normalizedPageSize);
}

/**
* Gets page numbers as an array of objects.
* @type {PageItem[]}
* @readonly
* @private
*/
get pageNumbers() {
const max = isNumber(this.maximumPagesDisplayed, 0) ? this.maximumPagesDisplayed : 5;
return generatePagesForRange(this.normalizedPageNumber, this.totalPages, max);
}

/**
* Gets the symbol for range symbol.
* @type {string}
* @readonly
* @private
*/
get rangeSymbol() {
return PAGING_RANGE_SYMBOL;
}

/**
* Handler for the 'click' event from the previous button.
*/
handlePaginationPrevious() {
const previousPageNumber = Number(this.currentPageNumber) - 1;
this.dispatchUpdateCurrentPageEvent(previousPageNumber);
}

/**
* Handler for the 'click' event from the next button.
*/
handlePaginationNext() {
const nextPageNumber = Number(this.currentPageNumber) + 1;
this.dispatchUpdateCurrentPageEvent(nextPageNumber);
}

/**
* Handler for the 'click' event from the page number button.
* @param {Event} event The event object
*/
handlePaginationPage(event) {
let pageNumber = parseInt(event.target.value, 10);
this.dispatchUpdateCurrentPageEvent(pageNumber);
}

/**
* Dispatch filterChange action on search data provider.
* @param {number} newPageNumber
*/
dispatchUpdateCurrentPageEvent(newPageNumber) {
this.updatePageAndPageNumber(String(newPageNumber));
dispatchAction(this, new Action(ACTION_SEARCH_FILTERS_UPDATE, { page: newPageNumber }));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8" ?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<isExposed>true</isExposed>
<targets>
<target>lightningCommunity__Page</target>
<target>lightningCommunity__Default</target>
</targets>
<masterLabel>Custom Search Paging Control</masterLabel>
<description>Displays pagination control for search page.</description>
<targetConfigs>
<targetConfig targets="lightningCommunity__Default">
<property name="currentPageNumber" type="String" default="{!Search.Pagination.currentPage}" />
<property name="pageSize" type="String" default="{!Search.Pagination.totalPages}" />
<property name="totalItemCount" type="String" default="{!Search.Results.total}" />
<property name="maximumPagesDisplayed" type="String" default="5" />
</targetConfig>
</targetConfigs>
</LightningComponentBundle>
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* Copyright (c) 2024, salesforce.com, inc.
* All rights reserved.
* SPDX-License-Identifier: Apache-2.0
* For full license text, see the LICENSE file in the repo
* root or https://opensource.org/licenses/apache-2-0/
*/
export const PAGING_RANGE_SYMBOL = '...';

export const EVENT = {
PAGE_CHANGE_PREVIOUS_EVT: 'pageprevious',

PAGE_CHANGE_NEXT_EVT: 'pagenext',

PAGE_CHANGE_GOTOPAGE_EVT: 'pagegoto',
};

export const MAX_RESULTS_OFFSET = 5000;
11 changes: 11 additions & 0 deletions force-app/main/default/lwc/builderSearchPagingControl/labels.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*
* Copyright (c) 2024, salesforce.com, inc.
* All rights reserved.
* SPDX-License-Identifier: Apache-2.0
* For full license text, see the LICENSE file in the repo
* root or https://opensource.org/licenses/apache-2-0/
*/
import previous from '@salesforce/label/c.Search_Results_previous';
import next from '@salesforce/label/c.Search_Results_next';
import resultsLimitHitText from '@salesforce/label/c.Search_Results_resultsLimitHitText';
export { previous, next, resultsLimitHitText };
Loading
Loading