blob: 2a21b0d61f1cd4fa79b5be86664cfc55f680c8cb [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Button, ButtonGroup, Menu, MenuItem, Popover } from '@blueprintjs/core';
import { IconNames } from '@blueprintjs/icons';
import React, { useState } from 'react';
import { formatInteger, nonEmptyArray, tickIcon } from '../../utils';
import { PageJumpDialog } from './page-jump-dialog/page-jump-dialog';
import './react-table-pagination.scss';
interface ReactTablePaginationProps {
pages: number;
page: number;
showPageSizeOptions: boolean;
pageSizeOptions: number[];
pageSize: number;
showPageJump: boolean;
canPrevious: boolean;
canNext: boolean;
onPageSizeChange: any;
previousText: string;
nextText: string;
onPageChange: any;
ofText: string;
pageText: string;
rowsText: string;
sortedData?: any[];
style: Record<string, any>;
}
export const ReactTablePagination = React.memo(function ReactTablePagination(
props: ReactTablePaginationProps,
) {
const {
page,
pages,
onPageChange,
pageSize,
onPageSizeChange,
pageSizeOptions,
showPageJump,
showPageSizeOptions,
canPrevious,
canNext,
style,
ofText,
sortedData,
} = props;
const [showPageJumpDialog, setShowPageJumpDialog] = useState(false);
function changePage(newPage: number) {
newPage = Math.min(Math.max(newPage, 0), pages - 1);
if (page !== newPage) {
onPageChange(newPage);
}
}
function renderPageJumpMenuItem() {
if (!showPageJump) return;
return <MenuItem text="Jump to page..." onClick={() => setShowPageJumpDialog(true)} />;
}
function renderPageSizeChangeMenuItem() {
if (!showPageSizeOptions) return;
return (
<MenuItem text={`Page size: ${pageSize}`}>
{pageSizeOptions.map((option, i) => (
<MenuItem
key={i}
icon={tickIcon(option === pageSize)}
text={String(option)}
onClick={() => {
if (option === pageSize) return;
onPageSizeChange(option);
}}
/>
))}
</MenuItem>
);
}
const start = page * pageSize + 1;
let end = page * pageSize + pageSize;
if (nonEmptyArray(sortedData) && (page === 0 || sortedData.length > pageSize)) {
end = Math.min(end, sortedData.length);
}
let pageInfo = 'Showing';
if (end) {
pageInfo += ` ${formatInteger(start)}-${formatInteger(end)}`;
} else {
pageInfo += '...';
}
if (ofText === 'of' && nonEmptyArray(sortedData)) {
pageInfo += ` ${ofText} ${formatInteger(sortedData.length)}`;
} else if (ofText) {
pageInfo += ` ${ofText}`;
}
const pageJumpMenuItem = renderPageJumpMenuItem();
const pageSizeChangeMenuItem = renderPageSizeChangeMenuItem();
return (
<div className="react-table-pagination" style={style}>
<ButtonGroup>
<Button
icon={IconNames.CHEVRON_LEFT}
minimal
disabled={!canPrevious}
onClick={() => changePage(page - 1)}
/>
<Button
icon={IconNames.CHEVRON_RIGHT}
minimal
disabled={!canNext}
onClick={() => changePage(page + 1)}
/>
<Popover
position="top-left"
disabled={!pageJumpMenuItem && !pageSizeChangeMenuItem}
content={
<Menu>
{pageJumpMenuItem}
{pageSizeChangeMenuItem}
</Menu>
}
>
<Button minimal text={pageInfo} />
</Popover>
</ButtonGroup>
{showPageJumpDialog && (
<PageJumpDialog
initPage={page}
maxPage={pages}
onJump={changePage}
onClose={() => setShowPageJumpDialog(false)}
/>
)}
</div>
);
});