-
Notifications
You must be signed in to change notification settings - Fork 38
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
MMT-3561: Adding Pagination to Table Component #1110
Merged
Merged
Changes from all commits
Commits
Show all changes
34 commits
Select commit
Hold shift + click to select a range
b89cbb1
MMT-3492: Saving progress on table component
mandyparson 10d76a5
MMT-3492: Adjusting RenderRows
mandyparson 205f9cc
MMT-3492: Finish writing tests
mandyparson 9f15d69
MMT-3492: Addressing PR Comments
mandyparson 6a6405f
Merge branch 'MMT-3492' into MMT-3561
mandyparson 4a3f8db
MMT-3492: Fixing 'data' structure
mandyparson 3de9b6d
Merge branch 'MMT-3492' into MMT-3561
mandyparson 4a6d7ac
MMT-3561: Adding Pagination to Table
mandyparson e003d4a
MMT-3492: eslint error fixes
mandyparson bd18c78
Merge branch 'MMT-3390' into MMT-3492
mandyparson 0a2ba21
MMT-3492: reverting changes to ManagePage
mandyparson 94fc6af
Merge branch 'MMT-3390' into MMT-3561
mandyparson 3fa0aec
MMT-3561: Adding Pagination to Table
mandyparson 3a1d179
MMT-3561: Adding tests
mandyparson abba026
Merge branch 'MMT-3390' into MMT-3561
mandyparson 606cf0d
Merge branch 'MMT-3390' into MMT-3492
mandyparson d8de076
MMT-3492: Fixing shortName and title
mandyparson bcef541
Merge branch 'MMT-3492' into MMT-3561
mandyparson 368a920
MMT-3561: Fixing conflict
mandyparson 9825156
Merge branch 'MMT-3390' into MMT-3561
mandyparson 7feb925
Merge branch 'MMT-3390' into MMT-3561
mandyparson c059d73
MMT-3561: Saving progress on limit and offset
mandyparson 9fb74c9
MMT-3561: Adding offset and limit
mandyparson 607d34b
MMT-3492: Editing table and ManagePage
mandyparson 23b301b
Merge branch 'MMT-3390' into MMT-3492
mandyparson 8cad2e6
MMT-3492: Trying to get tests to run on github
mandyparson 66ce18e
Merge branch 'MMT-3492' into MMT-3561
mandyparson 5190f2f
MMT-3492: Addressing comments
mandyparson 17c78c5
MMT-3492: Changing all conceptTypes to ummMetadata
mandyparson a57b864
MMT-3492: lint
mandyparson e0b8e6e
Merge branch 'MMT-3492' into MMT-3561
mandyparson a6e54e2
MMT-3561: Writing tests for pagination
mandyparson 868cbae
MMT-3561: Addressing Comments
mandyparson ac94889
Merge branch 'MMT-3390' into MMT-3561
mandyparson File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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 | ||
}) => { | ||
mandyparson marked this conversation as resolved.
Show resolved
Hide resolved
|
||
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.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These should be separate lines. Not sure why eslint didnt complain here 🤔