kafka-ui/kafka-ui-react-app/src/components/common/Pagination/Pagination.tsx

129 lines
3.3 KiB
TypeScript

import { PER_PAGE } from 'lib/constants';
import usePagination from 'lib/hooks/usePagination';
import range from 'lodash/range';
import React from 'react';
import PageControl from 'components/common/Pagination/PageControl';
import useSearch from 'lib/hooks/useSearch';
import * as S from './Pagination.styled';
export interface PaginationProps {
totalPages: number;
}
const NEIGHBOURS = 2;
const Pagination: React.FC<PaginationProps> = ({ totalPages }) => {
const { page, perPage, pathname } = usePagination();
const [searchText] = useSearch();
const currentPage = page || 1;
const currentPerPage = perPage || PER_PAGE;
const searchParam = searchText ? `&q=${searchText}` : '';
const getPath = (newPage: number) =>
`${pathname}?page=${Math.max(
newPage,
1
)}&perPage=${currentPerPage}${searchParam}`;
const pages = React.useMemo(() => {
// Total visible numbers: neighbours, current, first & last
const totalNumbers = NEIGHBOURS * 2 + 3;
// totalNumbers + `...`*2
const totalBlocks = totalNumbers + 2;
if (totalPages <= totalBlocks) {
return range(1, totalPages + 1);
}
const startPage = Math.max(
2,
Math.min(currentPage - NEIGHBOURS, totalPages)
);
const endPage = Math.min(
totalPages - 1,
Math.min(currentPage + NEIGHBOURS, totalPages)
);
let p = range(startPage, endPage + 1);
const hasLeftSpill = startPage > 2;
const hasRightSpill = totalPages - endPage > 1;
const spillOffset = totalNumbers - (p.length + 1);
switch (true) {
case hasLeftSpill && !hasRightSpill: {
p = [...range(startPage - spillOffset - 1, startPage - 1), ...p];
break;
}
case !hasLeftSpill && hasRightSpill: {
p = [...p, ...range(endPage + 1, endPage + spillOffset + 1)];
break;
}
default:
break;
}
return p;
}, [currentPage, totalPages]);
return (
<S.Wrapper role="navigation" aria-label="pagination">
{currentPage > 1 ? (
<S.PaginationButton to={getPath(currentPage - 1)}>
Previous
</S.PaginationButton>
) : (
<S.DisabledButton disabled>Previous</S.DisabledButton>
)}
{totalPages > 1 && (
<ul>
{!pages.includes(1) && (
<PageControl
page={1}
current={currentPage === 1}
url={getPath(1)}
/>
)}
{!pages.includes(2) && (
<li>
<span>&hellip;</span>
</li>
)}
{pages.map((p) => (
<PageControl
key={`page-${p}`}
page={p}
current={p === currentPage}
url={getPath(p)}
/>
))}
{!pages.includes(totalPages - 1) && (
<li>
<span>&hellip;</span>
</li>
)}
{!pages.includes(totalPages) && (
<PageControl
page={totalPages}
current={currentPage === totalPages}
url={getPath(totalPages)}
/>
)}
</ul>
)}
{currentPage < totalPages ? (
<S.PaginationButton to={getPath(currentPage + 1)}>
Next
</S.PaginationButton>
) : (
<S.DisabledButton disabled>Next</S.DisabledButton>
)}
</S.Wrapper>
);
};
export default Pagination;