Extended ShortUrlsPaginator so that it allows appending current query string

This commit is contained in:
Alejandro Celaya 2021-11-08 22:13:37 +01:00
parent a2421ee2d3
commit 3bc5b4c154
2 changed files with 53 additions and 29 deletions

View file

@ -1,15 +1,24 @@
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { Pagination, PaginationItem, PaginationLink } from 'reactstrap'; import { Pagination, PaginationItem, PaginationLink } from 'reactstrap';
import { pageIsEllipsis, keyForPage, progressivePagination, prettifyPageNumber } from '../utils/helpers/pagination'; import {
pageIsEllipsis,
keyForPage,
progressivePagination,
prettifyPageNumber,
NumberOrEllipsis,
} from '../utils/helpers/pagination';
import { ShlinkPaginator } from '../api/types'; import { ShlinkPaginator } from '../api/types';
interface PaginatorProps { interface PaginatorProps {
paginator?: ShlinkPaginator; paginator?: ShlinkPaginator;
serverId: string; serverId: string;
currentQueryString?: string;
} }
const Paginator = ({ paginator, serverId }: PaginatorProps) => { const Paginator = ({ paginator, serverId, currentQueryString = '' }: PaginatorProps) => {
const { currentPage = 0, pagesCount = 0 } = paginator ?? {}; const { currentPage = 0, pagesCount = 0 } = paginator ?? {};
const urlForPage = (pageNumber: NumberOrEllipsis) =>
`/server/${serverId}/list-short-urls/${pageNumber}${currentQueryString}`;
if (pagesCount <= 1) { if (pagesCount <= 1) {
return null; return null;
@ -22,10 +31,7 @@ const Paginator = ({ paginator, serverId }: PaginatorProps) => {
disabled={pageIsEllipsis(pageNumber)} disabled={pageIsEllipsis(pageNumber)}
active={currentPage === pageNumber} active={currentPage === pageNumber}
> >
<PaginationLink <PaginationLink tag={Link} to={urlForPage(pageNumber)}>
tag={Link}
to={`/server/${serverId}/list-short-urls/${pageNumber}`}
>
{prettifyPageNumber(pageNumber)} {prettifyPageNumber(pageNumber)}
</PaginationLink> </PaginationLink>
</PaginationItem> </PaginationItem>
@ -34,19 +40,11 @@ const Paginator = ({ paginator, serverId }: PaginatorProps) => {
return ( return (
<Pagination className="sticky-card-paginator" listClassName="flex-wrap justify-content-center mb-0"> <Pagination className="sticky-card-paginator" listClassName="flex-wrap justify-content-center mb-0">
<PaginationItem disabled={currentPage === 1}> <PaginationItem disabled={currentPage === 1}>
<PaginationLink <PaginationLink previous tag={Link} to={urlForPage(currentPage - 1)} />
previous
tag={Link}
to={`/server/${serverId}/list-short-urls/${currentPage - 1}`}
/>
</PaginationItem> </PaginationItem>
{renderPages()} {renderPages()}
<PaginationItem disabled={currentPage >= pagesCount}> <PaginationItem disabled={currentPage >= pagesCount}>
<PaginationLink <PaginationLink next tag={Link} to={urlForPage(currentPage + 1)} />
next
tag={Link}
to={`/server/${serverId}/list-short-urls/${currentPage + 1}`}
/>
</PaginationItem> </PaginationItem>
</Pagination> </Pagination>
); );

View file

@ -1,28 +1,54 @@
import { shallow, ShallowWrapper } from 'enzyme'; import { shallow, ShallowWrapper } from 'enzyme';
import { PaginationItem } from 'reactstrap'; import { PaginationItem, PaginationLink } from 'reactstrap';
import { Mock } from 'ts-mockery';
import Paginator from '../../src/short-urls/Paginator'; import Paginator from '../../src/short-urls/Paginator';
import { ShlinkPaginator } from '../../src/api/types';
import { ELLIPSIS } from '../../src/utils/helpers/pagination';
describe('<Paginator />', () => { describe('<Paginator />', () => {
let wrapper: ShallowWrapper; let wrapper: ShallowWrapper;
const buildPaginator = (pagesCount?: number) => Mock.of<ShlinkPaginator>({ pagesCount, currentPage: 1 });
afterEach(() => wrapper?.unmount()); afterEach(() => wrapper?.unmount());
it('renders nothing if the number of pages is below 2', () => { it.each([
wrapper = shallow(<Paginator serverId="abc123" />); [ undefined ],
[ buildPaginator() ],
[ buildPaginator(0) ],
[ buildPaginator(1) ],
])('renders nothing if the number of pages is below 2', (paginator) => {
wrapper = shallow(<Paginator serverId="abc123" paginator={paginator} />);
expect(wrapper.text()).toEqual(''); expect(wrapper.text()).toEqual('');
}); });
it('renders previous, next and the list of pages', () => { it.each([
const paginator = { [ buildPaginator(2), 4, 0 ],
currentPage: 1, [ buildPaginator(3), 5, 0 ],
pagesCount: 5, [ buildPaginator(4), 6, 0 ],
totalItems: 10, [ buildPaginator(5), 7, 1 ],
}; [ buildPaginator(6), 7, 1 ],
const extraPagesPrevNext = 2; [ buildPaginator(23), 7, 1 ],
const expectedItems = paginator.pagesCount + extraPagesPrevNext; ])('renders previous, next and the list of pages, with ellipses when expected', (
paginator,
expectedPages,
expectedEllipsis,
) => {
wrapper = shallow(<Paginator serverId="abc123" paginator={paginator} />); wrapper = shallow(<Paginator serverId="abc123" paginator={paginator} />);
const items = wrapper.find(PaginationItem);
const ellipsis = items.filterWhere((item) => item.find(PaginationLink).prop('children') === ELLIPSIS);
expect(wrapper.find(PaginationItem)).toHaveLength(expectedItems); expect(items).toHaveLength(expectedPages);
expect(ellipsis).toHaveLength(expectedEllipsis);
});
it('appends query string to all pages', () => {
const paginator = buildPaginator(3);
const currentQueryString = '?foo=bar';
wrapper = shallow(<Paginator serverId="abc123" paginator={paginator} currentQueryString={currentQueryString} />);
const links = wrapper.find(PaginationLink);
expect(links).toHaveLength(5);
links.forEach((link) => expect(link.prop('to')).toContain(currentQueryString));
}); });
}); });