blob: a6c441d5f95258c5b73a85de41dc5131aec4dcfc [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 React from 'react';
import { styled, t } from '@superset-ui/core';
import { useFilters, usePagination, useSortBy, useTable } from 'react-table';
import { Empty } from 'src/common/components';
import { TableCollection, Pagination } from 'src/components/dataViewCommon';
import { SortColumns } from './types';
const DEFAULT_PAGE_SIZE = 10;
export enum EmptyWrapperType {
Default,
Small,
}
export interface TableViewProps {
columns: any[];
data: any[];
pageSize?: number;
initialPageIndex?: number;
initialSortBy?: SortColumns;
loading?: boolean;
withPagination?: boolean;
emptyWrapperType?: EmptyWrapperType;
noDataText?: string;
className?: string;
isPaginationSticky?: boolean;
showRowCount?: boolean;
scrollTable?: boolean;
}
const EmptyWrapper = styled.div`
margin: ${({ theme }) => theme.gridUnit * 40}px 0;
`;
const TableViewStyles = styled.div<{
isPaginationSticky?: boolean;
scrollTable?: boolean;
}>`
${({ scrollTable, theme }) =>
scrollTable &&
`
height: 300px;
margin-bottom: ${theme.gridUnit * 4}px;
overflow: auto;
`}
.table-cell.table-cell {
vertical-align: top;
}
.pagination-container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: ${({ theme }) => theme.colors.grayscale.light5};
${({ theme, isPaginationSticky }) =>
isPaginationSticky &&
`
position: sticky;
bottom: ${theme.gridUnit * 4}px;
left: 0;
`};
}
.row-count-container {
margin-top: ${({ theme }) => theme.gridUnit * 2}px;
color: ${({ theme }) => theme.colors.grayscale.base};
}
`;
const TableView = ({
columns,
data,
pageSize: initialPageSize,
initialPageIndex,
initialSortBy = [],
loading = false,
withPagination = true,
emptyWrapperType = EmptyWrapperType.Default,
noDataText,
showRowCount = true,
...props
}: TableViewProps) => {
const initialState = {
pageSize: initialPageSize ?? DEFAULT_PAGE_SIZE,
pageIndex: initialPageIndex ?? 0,
sortBy: initialSortBy,
};
const {
getTableProps,
getTableBodyProps,
headerGroups,
page,
rows,
prepareRow,
pageCount,
gotoPage,
state: { pageIndex, pageSize },
} = useTable(
{
columns,
data,
initialState,
},
useFilters,
useSortBy,
usePagination,
);
const content = withPagination ? page : rows;
let EmptyWrapperComponent;
switch (emptyWrapperType) {
case EmptyWrapperType.Small:
EmptyWrapperComponent = ({ children }: any) => <>{children}</>;
break;
case EmptyWrapperType.Default:
default:
EmptyWrapperComponent = ({ children }: any) => (
<EmptyWrapper>{children}</EmptyWrapper>
);
}
const isEmpty = !loading && content.length === 0;
return (
<TableViewStyles {...props}>
<TableCollection
getTableProps={getTableProps}
getTableBodyProps={getTableBodyProps}
prepareRow={prepareRow}
headerGroups={headerGroups}
rows={content}
columns={columns}
loading={loading}
/>
{isEmpty && (
<EmptyWrapperComponent>
{noDataText ? (
<Empty
image={Empty.PRESENTED_IMAGE_SIMPLE}
description={noDataText}
/>
) : (
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
)}
</EmptyWrapperComponent>
)}
{pageCount > 1 && withPagination && (
<div className="pagination-container">
<Pagination
totalPages={pageCount || 0}
currentPage={pageCount ? pageIndex + 1 : 0}
onChange={(p: number) => gotoPage(p - 1)}
hideFirstAndLastPageLinks
/>
{showRowCount && (
<div className="row-count-container">
{!loading &&
t(
'%s-%s of %s',
pageSize * pageIndex + (page.length && 1),
pageSize * pageIndex + page.length,
data.length,
)}
</div>
)}
</div>
)}
</TableViewStyles>
);
};
export default React.memo(TableView);