-
Notifications
You must be signed in to change notification settings - Fork 38
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
MMT-3561: Adding Pagination to Table Component (#1110)
* MMT-3492: Saving progress on table component * MMT-3492: Adjusting RenderRows * MMT-3492: Finish writing tests * MMT-3492: Addressing PR Comments * MMT-3492: Fixing 'data' structure * MMT-3561: Adding Pagination to Table * MMT-3492: eslint error fixes * MMT-3492: reverting changes to ManagePage * MMT-3561: Adding Pagination to Table * MMT-3561: Adding tests * MMT-3492: Fixing shortName and title * MMT-3561: Fixing conflict * MMT-3561: Saving progress on limit and offset * MMT-3561: Adding offset and limit * MMT-3492: Editing table and ManagePage * MMT-3492: Trying to get tests to run on github * MMT-3492: Addressing comments * MMT-3492: Changing all conceptTypes to ummMetadata * MMT-3492: lint * MMT-3561: Writing tests for pagination * MMT-3561: Addressing Comments
- Loading branch information
1 parent
18d0d12
commit 962742f
Showing
8 changed files
with
333 additions
and
46 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
import React, { useState } from 'react' | ||
import PropTypes from 'prop-types' | ||
import Pagination from 'react-bootstrap/Pagination' | ||
import Row from 'react-bootstrap/Row' | ||
import Col from 'react-bootstrap/Col' | ||
|
||
/** | ||
* Table | ||
* @typedef {Object} PaginationComponent | ||
* @property {Number} limit A number that is set in parent element of table | ||
* @property {Number} count A number that indicates how many results are in the total query | ||
* @property {function} setOffset A function that resets the offset of results to come back | ||
*/ | ||
|
||
const PaginationComponent = ({ | ||
limit, | ||
count, | ||
setOffset | ||
}) => { | ||
const [pageNum, setPageNum] = useState(1) | ||
|
||
const lastPageNum = parseInt(Math.ceil(count / limit), 10) | ||
|
||
const defaultPaginationStyles = { | ||
minWidth: '2.5rem', | ||
textAlign: 'center' | ||
} | ||
|
||
const handleItemClick = (currentPage) => { | ||
setPageNum(currentPage) | ||
setOffset((currentPage - 1) * limit) | ||
} | ||
|
||
const generatePaginationItems = () => { | ||
// Only show 3 pages, the current page and one before or after (within the valid range of pages) | ||
const pages = [pageNum - 1, pageNum, pageNum + 1] | ||
.filter((page) => page >= 1 && page <= lastPageNum) | ||
|
||
const returnItems = [] | ||
|
||
// If the first page is not 1, add the pagination item for page 1 | ||
if (pages[0] !== 1) { | ||
returnItems.push( | ||
<Pagination.Item | ||
key="page-1" | ||
onClick={() => handleItemClick(1)} | ||
active={pageNum === 1} | ||
style={defaultPaginationStyles} | ||
> | ||
{1} | ||
</Pagination.Item> | ||
) | ||
|
||
// And if the first page is not 2, add an ellipsis | ||
if (pages[0] !== 2) { | ||
returnItems.push( | ||
<Pagination.Ellipsis | ||
key="page-ellipsis-1" | ||
disabled | ||
/> | ||
) | ||
} | ||
} | ||
|
||
pages.forEach((page) => { | ||
returnItems.push( | ||
<Pagination.Item | ||
key={`page-${page}`} | ||
onClick={() => handleItemClick(page)} | ||
active={page === pageNum} | ||
style={defaultPaginationStyles} | ||
> | ||
{page} | ||
</Pagination.Item> | ||
) | ||
}) | ||
|
||
// If the last page is not lastPageNum, add the pagination item for the lastPageNum | ||
if (pages[pages.length - 1] !== lastPageNum) { | ||
// And if the last page is not lastPageNum - 1, add an ellipsis | ||
if (pages[pages.length - 1] !== lastPageNum - 1) { | ||
returnItems.push( | ||
<Pagination.Ellipsis | ||
key="page-ellipsis-2" | ||
disabled | ||
/> | ||
) | ||
} | ||
|
||
returnItems.push( | ||
<Pagination.Item | ||
key={`page-${lastPageNum}`} | ||
onClick={() => handleItemClick(lastPageNum)} | ||
active={pageNum === lastPageNum} | ||
style={defaultPaginationStyles} | ||
> | ||
{lastPageNum} | ||
</Pagination.Item> | ||
) | ||
} | ||
|
||
return returnItems | ||
} | ||
|
||
const handlePageChange = (direction) => { | ||
const newCurrentPage = pageNum + direction | ||
|
||
setPageNum(newCurrentPage) | ||
setOffset((newCurrentPage - 1) * limit) | ||
} | ||
|
||
return ( | ||
<Row> | ||
<Col xs="auto"> | ||
<div className="mx-auto"> | ||
<Pagination> | ||
<Pagination.Prev | ||
disabled={pageNum === 1} | ||
onClick={() => handlePageChange(-1)} | ||
/> | ||
{generatePaginationItems()} | ||
<Pagination.Next | ||
onClick={() => handlePageChange(1)} | ||
disabled={pageNum >= lastPageNum} | ||
/> | ||
</Pagination> | ||
</div> | ||
</Col> | ||
</Row> | ||
) | ||
} | ||
|
||
PaginationComponent.defaultProps = { | ||
count: null | ||
} | ||
|
||
PaginationComponent.propTypes = { | ||
setOffset: PropTypes.func.isRequired, | ||
limit: PropTypes.number.isRequired, | ||
count: PropTypes.number | ||
} | ||
|
||
export default PaginationComponent |
61 changes: 61 additions & 0 deletions
61
static/src/js/components/Pagination/__tests__/Pagination.test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import React from 'react' | ||
import { | ||
render, | ||
screen, | ||
fireEvent | ||
} from '@testing-library/react' | ||
import userEvent from '@testing-library/user-event' | ||
|
||
import PaginationComponent from '../Pagination' | ||
|
||
const setOffset = jest.fn() | ||
|
||
const setup = () => { | ||
const props = { | ||
limit: 2, | ||
count: 14, | ||
setOffset | ||
} | ||
render( | ||
<PaginationComponent {...props} /> | ||
) | ||
|
||
return { | ||
props, | ||
user: userEvent.setup() | ||
} | ||
} | ||
|
||
describe('Pagination', () => { | ||
describe('when pagination component is passed count < limit', () => { | ||
test('renders pagination bar', () => { | ||
setup() | ||
|
||
expect(screen.queryAllByRole('button')).toHaveLength(3) | ||
|
||
// Check individual buttons work | ||
fireEvent.click(screen.getByRole('button', { name: '2' })) | ||
|
||
// Check the next button works | ||
fireEvent.click(screen.getByRole('button', { name: 'Next' })) | ||
|
||
// // Click on Previous Page | ||
fireEvent.click(screen.getByRole('button', { name: 'Previous' })) | ||
|
||
// // Check pages[0] always stays at 1 and two ellipsis render | ||
fireEvent.click(screen.getByRole('button', { name: 'Next' })) | ||
fireEvent.click(screen.getByRole('button', { name: '4' })) | ||
expect(screen.getByRole('button', { name: '1' })) | ||
expect(screen.queryAllByText('More')).toHaveLength(2) | ||
|
||
// Make sure onclick for pages[0] function above works | ||
fireEvent.click(screen.getByRole('button', { name: '1' })) | ||
|
||
// Can click on last page | ||
fireEvent.click(screen.getByRole('button', { name: '7' })) | ||
fireEvent.click(screen.getByRole('button', { name: 'Previous' })) | ||
fireEvent.click(screen.getByRole('button', { name: 'Previous' })) | ||
expect(screen.queryAllByText('More')).toHaveLength(1) | ||
}) | ||
}) | ||
}) |
Oops, something went wrong.