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.