Skip to content

Commit

Permalink
feat(pagination): move code to controller & improve global code quali…
Browse files Browse the repository at this point in the history
…ty, replace min and max
  • Loading branch information
Leotheluck authored and dpellier committed Jul 29, 2024
1 parent fdd4ada commit 73d85f8
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 75 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { ODS_BUTTON_COLOR, ODS_BUTTON_SIZE, ODS_BUTTON_VARIANT } from '../../../
import { ODS_ICON_NAME } from '../../../../icon/src';
import { ODS_TEXT_PRESET } from '../../../../text/src';
import { ODS_PAGINATION_PER_PAGE, ODS_PAGINATION_PER_PAGE_OPTIONS } from '../../constants/pagination-per-page';
import { createPageList } from '../../controller/ods-pagination';
import { computeActualTotalPages, createPageList, getActualPage } from '../../controller/ods-pagination';

@Component({
shadow: true,
Expand All @@ -24,13 +24,13 @@ export class OdsPagination {

@Element() el!: HTMLElement;

@State() itemPerPage = ODS_PAGINATION_PER_PAGE.min;
@State() itemPerPage = ODS_PAGINATION_PER_PAGE.option_10;
@State() pageList: OdsPaginationPageList = [];
@State() current: number = 1;

@Prop({ reflect: true }) public defaultCurrentPage: number = 1;
/** @docType OdsPaginationPerPage */
@Prop({ reflect: true }) public defaultItemsPerPage: ODS_PAGINATION_PER_PAGE = ODS_PAGINATION_PER_PAGE.min;
@Prop({ reflect: true }) public defaultItemsPerPage: ODS_PAGINATION_PER_PAGE = ODS_PAGINATION_PER_PAGE.option_10;
@Prop({ reflect: true }) public isDisabled: boolean = false;
@Prop({ reflect: true }) public labelTooltipNext?: string;
@Prop({ reflect: true }) public labelTooltipPrevious?: string;
Expand All @@ -40,41 +40,6 @@ export class OdsPagination {
@Event() odsPaginationChanged!: EventEmitter<OdsPaginationChangedEventDetail>;
@Event() odsPaginationItemPerPageChanged!: EventEmitter<OdsPaginationItemPerPageChangedEventDetail>;

componentWillLoad(): void {
this.hostId = this.el.id || getRandomHTMLId();

this.itemPerPage = ODS_PAGINATION_PER_PAGE_OPTIONS.includes(this.defaultItemsPerPage) && this.defaultItemsPerPage || ODS_PAGINATION_PER_PAGE.min;

if (this.totalItems) {
this.actualTotalPages = this.computeActualTotalPages(this.itemPerPage);
} else {
this.actualTotalPages = this.totalPages;
}

if (this.defaultCurrentPage > this.actualTotalPages) {
this.current = this.actualTotalPages;
} else if (this.defaultCurrentPage < 1) {
this.current = 1;
} else {
this.current = this.defaultCurrentPage || this.current;
}

this.updatePageList();
this.isFirstLoad = false;
}

computeActualTotalPages(itemPerPage: number): number {
if (!this.totalItems) {
return this.totalPages;
}

return Math.ceil(this.totalItems / (itemPerPage || 1));
}

private updatePageList(): void {
this.pageList = createPageList(this.actualTotalPages, this.current);
}

@Listen('odsChange')
odsValueChangeHandler(event: CustomEvent<OdsSelectEventChangeDetail>): void {
event.preventDefault();
Expand Down Expand Up @@ -126,7 +91,7 @@ export class OdsPagination {
}

@Method()
async setPageIndex(current: number): Promise<void> {
async setCurrentPage(current: number): Promise<void> {
this.current = current;
}

Expand All @@ -135,6 +100,27 @@ export class OdsPagination {
return this.current;
}

componentWillLoad(): void {
this.hostId = this.el.id || getRandomHTMLId();

this.itemPerPage = ODS_PAGINATION_PER_PAGE_OPTIONS.includes(this.defaultItemsPerPage) && this.defaultItemsPerPage || ODS_PAGINATION_PER_PAGE.option_10;

if (this.totalItems) {
this.actualTotalPages = computeActualTotalPages(this.itemPerPage, this.totalItems, this.totalPages);
} else {
this.actualTotalPages = this.totalPages;
}

this.current = getActualPage(this.defaultCurrentPage, this.actualTotalPages, this.current);

this.updatePageList();
this.isFirstLoad = false;
}

private updatePageList(): void {
this.pageList = createPageList(this.actualTotalPages, this.current);
}

private emitChange(current: number, oldCurrent?: number): void {
this.odsPaginationChanged.emit({
current: current,
Expand All @@ -144,67 +130,71 @@ export class OdsPagination {
}

private async updatePagination(): Promise<void> {
this.actualTotalPages = this.computeActualTotalPages(this.itemPerPage);
this.actualTotalPages = computeActualTotalPages(this.itemPerPage, this.totalItems, this.totalPages);

if (this.current === 1) {
// If current is already 1 we don't want to emit a change event
this.updatePageList();
} else {
await this.setPageIndex(1);
await this.setCurrentPage(1);
}
}

handlePreviousClick(page: number): void {
this.setPageIndex(page - 1);
this.setCurrentPage(page - 1);
}

handleNextClick(page: number): void {
this.setPageIndex(page + 1);
this.setCurrentPage(page + 1);
}

handlePageClick(page: number): void {
this.setPageIndex(page);
this.setCurrentPage(page);
}

handlePreviousKeyDown(event: KeyboardEvent, page: number): void {
handlePreviousKeyUp(event: KeyboardEvent, page: number): void {
if (this.current > 1) {
this.onKeyDown(event, page - 1);
this.onKeyUp(event, page - 1);
}
}

handleNextKeyDown(event: KeyboardEvent, page: number): void {
handleNextKeyUp(event: KeyboardEvent, page: number): void {
if (this.current < this.pageList.length) {
this.onKeyDown(event, page + 1);
this.onKeyUp(event, page + 1);
}
}

handlePageKeyDown(event: KeyboardEvent, page: number): void {
this.onKeyDown(event, page);
handlePageKeyUp(event: KeyboardEvent, page: number): void {
this.onKeyUp(event, page);
}

onKeyDown(event: KeyboardEvent, page: number): void {
if (event.code === 'Enter' || event.code === 'Space') {
onKeyUp(event: KeyboardEvent, page: number): void {
if (event.key === ' ' || event.key === 'Enter') {
event.preventDefault();
this.setPageIndex(page);
this.setCurrentPage(page);
}
}

renderArrows(direction: 'left' | 'right'): typeof Fragment {
renderArrow(direction: 'left' | 'right'): typeof Fragment {
const isLeft = direction === 'left';
const tooltipLabel = isLeft ? this.labelTooltipPrevious : this.labelTooltipNext;
const arrowButtonId = isLeft ? this.leftArrowButtonId : this.rightArrowButtonId;

const checkArrowDisabled = (): boolean => {
return this.isDisabled || (isLeft && this.current === 1) || (!isLeft && this.current >= this.pageList.length);
};

return (
<li class="ods-pagination__list__arrow">
<ods-button
color={ODS_BUTTON_COLOR.primary}
class="ods-pagination__list__arrow__button"
icon={isLeft ? ODS_ICON_NAME.chevronLeft : ODS_ICON_NAME.chevronRight}
id={arrowButtonId}
isDisabled={this.isDisabled || (isLeft && this.current === 1) || (!isLeft && this.current >= this.pageList.length)}
isDisabled={checkArrowDisabled()}
label=""
onClick={() => {
if (this.isDisabled || (isLeft && this.current === 1) || (!isLeft && this.current >= this.pageList.length)) {
if (checkArrowDisabled()) {
return;
}

Expand All @@ -214,11 +204,11 @@ export class OdsPagination {
this.handleNextClick(Number(this.current));
}
}}
onKeyDown={(event: KeyboardEvent) => {
onKeyUp={(event: KeyboardEvent) => {
if (isLeft) {
this.handlePreviousKeyDown(event, Number(this.current));
this.handlePreviousKeyUp(event, Number(this.current));
} else {
this.handleNextKeyDown(event, Number(this.current));
this.handleNextKeyUp(event, Number(this.current));
}
}}
variant={ODS_BUTTON_VARIANT.ghost}
Expand Down Expand Up @@ -270,7 +260,7 @@ export class OdsPagination {
'ods-pagination__results--disabled': this.isDisabled,
}}>
{
this.totalItems >= ODS_PAGINATION_PER_PAGE.min &&
this.totalItems >= ODS_PAGINATION_PER_PAGE.option_10 &&
<ods-select isDisabled={this.isDisabled}
value={`${this.itemPerPage}`}
name="ods-pagination__items-per-page"
Expand All @@ -291,21 +281,21 @@ export class OdsPagination {
}

<ul class="ods-pagination__list">
{ this.renderArrows( 'left' ) }
{ this.renderArrow( 'left' ) }

{
this.pageList
.filter((page) => page.active)
.map((page) => {
const pageId = this.pageList.indexOf(page) + 1;
const shouldRenderLeftEllipsis = this.pageList.length > 6 && this.pageList.length - this.current > 3 && pageId === this.pageList.length;
const shouldRenderRightEllipsis = this.pageList.length > 6 && this.current > 4 && pageId === 1;

this.pageList.length > 6 && this.pageList.length - this.current > 3 && pageId === this.pageList.length && this.renderEllipsis();

this.pageList.length > 6 && this.current > 4 && pageId === 1 && this.renderEllipsis();
shouldRenderLeftEllipsis || shouldRenderRightEllipsis && this.renderEllipsis();

return (
<div class="ods-pagination__list__page">
{ this.pageList.length > 6 && this.pageList.length - this.current > 3 && pageId === this.pageList.length && this.renderEllipsis() }
{ shouldRenderLeftEllipsis && this.renderEllipsis() }

<li>
<ods-button
Expand All @@ -319,19 +309,19 @@ export class OdsPagination {
label={`${pageId}`}
color={ODS_BUTTON_COLOR.primary}
size={ODS_BUTTON_SIZE.md}
onClick={(): void => this.handlePageClick(Number(pageId))}
onKeyDown={(event: KeyboardEvent): void => this.handlePageKeyDown(event, Number(pageId))}
onClick={(): void => this.handlePageClick(pageId)}
onKeyUp={(event: KeyboardEvent): void => this.handlePageKeyUp(event, pageId)}
>
</ods-button>
</li>

{ this.pageList.length > 6 && this.current > 4 && pageId === 1 && this.renderEllipsis() }
{ shouldRenderRightEllipsis && this.renderEllipsis() }
</div>
);
})
}

{ this.renderArrows( 'right' ) }
{ this.renderArrow( 'right' ) }
</ul>
</Host>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
enum ODS_PAGINATION_PER_PAGE {
min = 10,
option_10 = 10,
option_25 = 25,
option_50 = 50,
option_100 = 100,
max = 300,
option_300 = 300,
}

const ODS_PAGINATION_PER_PAGE_OPTIONS = Object.freeze([
ODS_PAGINATION_PER_PAGE.min,
ODS_PAGINATION_PER_PAGE.option_10,
ODS_PAGINATION_PER_PAGE.option_25,
ODS_PAGINATION_PER_PAGE.option_50,
ODS_PAGINATION_PER_PAGE.option_100,
ODS_PAGINATION_PER_PAGE.max,
ODS_PAGINATION_PER_PAGE.option_300,
]);

export {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
import type { OdsPaginationPageList } from '../interfaces/pagination-page-list';

function computeActualTotalPages(itemPerPage: number, totalItems: number | undefined, totalPages: number): number {
if (!totalItems) {
return totalPages;
}

return Math.ceil(totalItems / (itemPerPage || 1));
}

function createPageList(totalPages: number, pageSelected: number): OdsPaginationPageList {
const pageList: OdsPaginationPageList = [];

Expand Down Expand Up @@ -48,6 +56,18 @@ function createPageList(totalPages: number, pageSelected: number): OdsPagination
return pageList;
}

function getActualPage(defaultCurrentPage: number, actualTotalPages: number, current: number): number {
if (defaultCurrentPage > actualTotalPages) {
return actualTotalPages;
} else if (defaultCurrentPage < 1) {
return 1;
} else {
return defaultCurrentPage || current;
}
}

export {
computeActualTotalPages,
createPageList,
getActualPage,
};
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ const totalItemsParam = {
defaultItemsPerPage: {
table: {
category: CONTROL_CATEGORY.general,
defaultValue: { summary: ODS_PAGINATION_PER_PAGE.min },
defaultValue: { summary: ODS_PAGINATION_PER_PAGE.option_10 },
type: { summary: 'number' },
},
control: 'select',
Expand Down Expand Up @@ -138,7 +138,7 @@ export const TotalItems: StoryObj = {
}),
args: {
defaultCurrentPage: 4,
defaultItemsPerPage: ODS_PAGINATION_PER_PAGE.min,
defaultItemsPerPage: ODS_PAGINATION_PER_PAGE.option_10,
isDisabled: false,
labelTooltipPrevious: 'Previous label',
labelTooltipNext: 'Next label',
Expand Down

0 comments on commit 73d85f8

Please sign in to comment.
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy