Skip to content
This repository has been archived by the owner on May 24, 2024. It is now read-only.

Commit

Permalink
[terra-paginator] Add support for unknown total page count in the pro…
Browse files Browse the repository at this point in the history
…gressive paginator (#3190)

* Changed Progressive Paginattor to Support unknown page count data

* fixed unknown item count issue

* fixing lint errors

* Removed Terra-form-input

* addressed code review comments

* Apply suggestions from code review

* made controlled paginator example

* fixed linter

Co-authored-by: Matt Henkes <mjhenkes@gmail.com>
  • Loading branch information
supreethmr and mjhenkes authored Nov 18, 2020
1 parent 0e7146c commit 3c2548e
Show file tree
Hide file tree
Showing 52 changed files with 554 additions and 172 deletions.
6 changes: 6 additions & 0 deletions packages/terra-paginator/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
# Changelog

## Unreleased
* Changed
* Changed progressive paginator to support unknown total page count.
* Replaced `Terra.it()` with `Terra.validates.element()`.

* Fixed
* Fixed paginator not considering `totalCount` when `itemCountPerPage` was not provided.

## 2.66.0 - (November 17, 2020)

Expand Down
1 change: 0 additions & 1 deletion packages/terra-paginator/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
"prop-types": "^15.5.8",
"terra-button": "^3.50.0",
"terra-dialog": "^2.53.0",
"terra-form-input": "^4.8.0",
"terra-icon": "^3.38.0",
"terra-mixins": "^1.38.0",
"terra-responsive-element": "^5.26.0",
Expand Down
43 changes: 24 additions & 19 deletions packages/terra-paginator/src/ControlledPaginator.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ const propTypes = {
* Total number of all items being paginated.
* Required when using itemCountPerPage and selectedPage.
*/
totalCount: PropTypes.number.isRequired,
totalCount: PropTypes.number,
/**
* Total number of items per page.
* Required when using selectedPage and totalCount.
*/
itemCountPerPage: PropTypes.number.isRequired,
itemCountPerPage: PropTypes.number,
/**
* @private
* The intl object to be injected for translations.
Expand All @@ -44,7 +44,6 @@ class Paginator extends React.Component {
super(props);

this.handlePageChange = this.handlePageChange.bind(this);
this.hasNavContext = this.hasNavContext.bind(this);
this.buildPageButtons = this.buildPageButtons.bind(this);
this.reducedPaginator = this.reducedPaginator.bind(this);
this.setPaginator = this.setPaginator.bind(this);
Expand Down Expand Up @@ -114,21 +113,22 @@ class Paginator extends React.Component {
return pageButtons;
}

hasNavContext() {
return this.props.totalCount && this.props.itemCountPerPage;
}

defaultPaginator() {
const theme = this.context;
const totalPages = calculatePages(this.props.totalCount, this.props.itemCountPerPage);
const { selectedPage, intl } = this.props;
const {
selectedPage,
intl,
totalCount,
itemCountPerPage,
} = this.props;
const totalPages = calculatePages(totalCount, itemCountPerPage);
const previousPageIndex = selectedPage === 1 ? 1 : selectedPage - 1;
const nextPageIndex = selectedPage === totalPages ? totalPages : selectedPage + 1;

const fullView = (
<div className={cx('paginator', !this.hasNavContext() && 'pageless', theme.className)}>
<div className={cx('paginator', !totalCount && 'pageless', theme.className)}>
{
this.hasNavContext() && (
totalCount && (
<PaginatorButton
ariaDisabled={selectedPage === 1}
ariaLabel={intl.formatMessage({ id: 'Terra.paginator.first' })}
Expand All @@ -152,7 +152,7 @@ class Paginator extends React.Component {
<span className={cx('icon')} />
{intl.formatMessage({ id: 'Terra.paginator.previous' })}
</PaginatorButton>
{this.hasNavContext() && this.buildPageButtons(totalPages, this.handlePageChange)}
{totalCount && this.buildPageButtons(totalPages, this.handlePageChange)}
<PaginatorButton
ariaDisabled={selectedPage === totalPages}
ariaLabel={intl.formatMessage({ id: 'Terra.paginator.next' })}
Expand All @@ -165,7 +165,7 @@ class Paginator extends React.Component {
<span className={cx('icon')} />
</PaginatorButton>
{
this.hasNavContext() && (
totalCount && (
<PaginatorButton
ariaDisabled={selectedPage === totalPages}
ariaLabel={intl.formatMessage({ id: 'Terra.paginator.last' })}
Expand All @@ -186,15 +186,20 @@ class Paginator extends React.Component {

reducedPaginator() {
const theme = this.context;
const totalPages = calculatePages(this.props.totalCount, this.props.itemCountPerPage);
const { selectedPage, intl } = this.props;
const {
selectedPage,
intl,
totalCount,
itemCountPerPage,
} = this.props;
const totalPages = calculatePages(totalCount, itemCountPerPage);
const previousPageIndex = selectedPage === 1 ? 1 : selectedPage - 1;
const nextPageIndex = selectedPage === totalPages ? totalPages : selectedPage + 1;

const reducedView = (
<div className={cx('paginator', !this.hasNavContext() && 'pageless', theme.className)} role="navigation" aria-label="pagination">
<div className={cx('paginator', !totalCount && 'pageless', theme.className)} role="navigation" aria-label="pagination">
{
this.hasNavContext() && (
totalCount && (
<PaginatorButton
ariaDisabled={selectedPage === 1}
ariaLabel={intl.formatMessage({ id: 'Terra.paginator.first' })}
Expand All @@ -218,7 +223,7 @@ class Paginator extends React.Component {
<span className={cx('icon')} />
{intl.formatMessage({ id: 'Terra.paginator.previous' })}
</PaginatorButton>
{this.hasNavContext() && intl.formatMessage({ id: 'Terra.paginator.pageIndex' }, { pageNumber: selectedPage })}
{totalCount && intl.formatMessage({ id: 'Terra.paginator.pageIndex' }, { pageNumber: selectedPage })}
<PaginatorButton
ariaDisabled={selectedPage === totalPages}
ariaLabel={intl.formatMessage({ id: 'Terra.paginator.next' })}
Expand All @@ -231,7 +236,7 @@ class Paginator extends React.Component {
<span className={cx('icon')} />
</PaginatorButton>
{
this.hasNavContext() && (
totalCount && (
<PaginatorButton
ariaDisabled={selectedPage === totalPages}
ariaLabel={intl.formatMessage({ id: 'Terra.paginator.last' })}
Expand Down
132 changes: 80 additions & 52 deletions packages/terra-paginator/src/ControlledProgressivePaginator.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,19 @@ const propTypes = {
/**
* Total number of all items being paginated.
*/
totalCount: PropTypes.number.isRequired,
totalCount: PropTypes.number,
/**
* Total number of items per page.
*/
itemCountPerPage: PropTypes.number.isRequired,
itemCountPerPage: PropTypes.number,
/**
* @private
* The intl object to be injected for translations.
*/
intl: intlShape.isRequired,
};

class ProgressivePaginator extends React.Component {
class ControlledProgressivePaginator extends React.Component {
constructor(props) {
super(props);

Expand Down Expand Up @@ -68,27 +68,37 @@ class ProgressivePaginator extends React.Component {

defaultProgressivePaginator() {
const theme = this.context;
const totalPages = calculatePages(this.props.totalCount, this.props.itemCountPerPage);
const { selectedPage, intl } = this.props;
const {
selectedPage,
intl,
totalCount,
itemCountPerPage,
} = this.props;
const totalPages = (totalCount) ? calculatePages(totalCount, itemCountPerPage) : 0;
const previousPageIndex = selectedPage === 1 ? 1 : selectedPage - 1;
const nextPageIndex = selectedPage === totalPages ? totalPages : selectedPage + 1;

return (
<div className={cx('paginator', 'progressive', theme.className)} role="navigation" aria-label="pagination">
<div>
{intl.formatMessage({ id: 'Terra.paginator.pageCount' }, { pageNumber: selectedPage, pageNumberTotal: totalPages })}
{(totalCount) ? intl.formatMessage({ id: 'Terra.paginator.pageCount' }, { pageNumber: selectedPage, pageNumberTotal: totalPages })
: intl.formatMessage({ id: 'Terra.paginator.pageIndex' }, { pageNumber: selectedPage })}
</div>
<div>
<PaginatorButton
ariaDisabled={selectedPage === 1}
ariaLabel={intl.formatMessage({ id: 'Terra.paginator.first' })}
className={cx(['nav-link', selectedPage === 1 ? 'is-disabled' : null])}
disabled={selectedPage === 1}
onClick={this.handlePageChange(1)}
onKeyDown={this.handlePageChange(1)}
>
{intl.formatMessage({ id: 'Terra.paginator.first' })}
</PaginatorButton>
{
totalCount && (
<PaginatorButton
ariaDisabled={selectedPage === 1}
ariaLabel={intl.formatMessage({ id: 'Terra.paginator.first' })}
className={cx(['nav-link', selectedPage === 1 ? 'is-disabled' : null])}
disabled={selectedPage === 1}
onClick={this.handlePageChange(1)}
onKeyDown={this.handlePageChange(1)}
>
{intl.formatMessage({ id: 'Terra.paginator.first' })}
</PaginatorButton>
)
}
<PaginatorButton
ariaDisabled={selectedPage === 1}
ariaLabel={intl.formatMessage({ id: 'Terra.paginator.previous' })}
Expand All @@ -111,41 +121,54 @@ class ProgressivePaginator extends React.Component {
{intl.formatMessage({ id: 'Terra.paginator.next' })}
<span className={cx('icon')} />
</PaginatorButton>
<PaginatorButton
ariaDisabled={selectedPage === totalPages}
ariaLabel={intl.formatMessage({ id: 'Terra.paginator.last' })}
className={cx(['nav-link', selectedPage === totalPages ? 'is-disabled' : null])}
disabled={selectedPage === totalPages}
onClick={this.handlePageChange(totalPages)}
onKeyDown={this.handlePageChange(totalPages)}
>
{intl.formatMessage({ id: 'Terra.paginator.last' })}
</PaginatorButton>
{
(totalCount) && (
<PaginatorButton
ariaDisabled={selectedPage === totalPages}
ariaLabel={intl.formatMessage({ id: 'Terra.paginator.last' })}
className={cx(['nav-link', selectedPage === totalPages ? 'is-disabled' : null])}
disabled={selectedPage === totalPages}
onClick={this.handlePageChange(totalPages)}
onKeyDown={this.handlePageChange(totalPages)}
>
{intl.formatMessage({ id: 'Terra.paginator.last' })}
</PaginatorButton>
)
}
</div>
</div>
);
}

reducedProgressivePaginator() {
const theme = this.context;
const totalPages = calculatePages(this.props.totalCount, this.props.itemCountPerPage);
const { selectedPage, intl } = this.props;
const {
selectedPage,
intl,
totalCount,
itemCountPerPage,
} = this.props;
const totalPages = (totalCount) ? calculatePages(totalCount, itemCountPerPage) : 0;
const previousPageIndex = selectedPage === 1 ? 1 : selectedPage - 1;
const nextPageIndex = selectedPage === totalPages ? totalPages : selectedPage + 1;

return (
<div className={cx('paginator', theme.className)} role="navigation" aria-label="pagination">
<div>
<PaginatorButton
ariaDisabled={selectedPage === 1}
ariaLabel={intl.formatMessage({ id: 'Terra.paginator.first' })}
className={cx(['nav-link', selectedPage === 1 ? 'is-disabled' : null])}
disabled={selectedPage === 1}
onClick={this.handlePageChange(1)}
onKeyDown={this.handlePageChange(1)}
>
{intl.formatMessage({ id: 'Terra.paginator.first' })}
</PaginatorButton>
{
(totalCount) && (
<PaginatorButton
ariaDisabled={selectedPage === 1}
ariaLabel={intl.formatMessage({ id: 'Terra.paginator.first' })}
className={cx(['nav-link', selectedPage === 1 ? 'is-disabled' : null])}
disabled={selectedPage === 1}
onClick={this.handlePageChange(1)}
onKeyDown={this.handlePageChange(1)}
>
{intl.formatMessage({ id: 'Terra.paginator.first' })}
</PaginatorButton>
)
}
<PaginatorButton
ariaDisabled={selectedPage === 1}
ariaLabel={intl.formatMessage({ id: 'Terra.paginator.previous' })}
Expand All @@ -159,7 +182,8 @@ class ProgressivePaginator extends React.Component {
</PaginatorButton>
</div>
<div>
{intl.formatMessage({ id: 'Terra.paginator.pageCount' }, { pageNumber: selectedPage, pageNumberTotal: totalPages })}
{(totalCount) ? intl.formatMessage({ id: 'Terra.paginator.pageCount' }, { pageNumber: selectedPage, pageNumberTotal: totalPages })
: intl.formatMessage({ id: 'Terra.paginator.pageIndex' }, { pageNumber: selectedPage })}
</div>
<div>
<PaginatorButton
Expand All @@ -173,16 +197,20 @@ class ProgressivePaginator extends React.Component {
<VisuallyHiddenText text={intl.formatMessage({ id: 'Terra.paginator.next' })} />
<span className={cx('icon')} />
</PaginatorButton>
<PaginatorButton
ariaDisabled={selectedPage === totalPages}
ariaLabel={intl.formatMessage({ id: 'Terra.paginator.last' })}
className={cx(['nav-link', selectedPage === totalPages ? 'is-disabled' : null])}
disabled={selectedPage === totalPages}
onClick={this.handlePageChange(totalPages)}
onKeyDown={this.handlePageChange(totalPages)}
>
{intl.formatMessage({ id: 'Terra.paginator.last' })}
</PaginatorButton>
{
(totalCount) && (
<PaginatorButton
ariaDisabled={selectedPage === totalPages}
ariaLabel={intl.formatMessage({ id: 'Terra.paginator.last' })}
className={cx(['nav-link', selectedPage === totalPages ? 'is-disabled' : null])}
disabled={selectedPage === totalPages}
onClick={this.handlePageChange(totalPages)}
onKeyDown={this.handlePageChange(totalPages)}
>
{intl.formatMessage({ id: 'Terra.paginator.last' })}
</PaginatorButton>
)
}
</div>
</div>
);
Expand All @@ -199,7 +227,7 @@ class ProgressivePaginator extends React.Component {
}
}

ProgressivePaginator.propTypes = propTypes;
ProgressivePaginator.contextType = ThemeContext;
ControlledProgressivePaginator.propTypes = propTypes;
ControlledProgressivePaginator.contextType = ThemeContext;

export default injectIntl(ProgressivePaginator);
export default injectIntl(ControlledProgressivePaginator);
Loading

0 comments on commit 3c2548e

Please sign in to comment.