2020-06-03 10:50:10 +00:00
|
|
|
import React from "react";
|
|
|
|
|
import {
|
|
|
|
|
useTable,
|
|
|
|
|
usePagination,
|
|
|
|
|
useFlexLayout,
|
|
|
|
|
useResizeColumns,
|
|
|
|
|
useRowSelect,
|
|
|
|
|
} from "react-table";
|
2020-07-02 06:26:01 +00:00
|
|
|
import { TableWrapper } from "./TableStyledWrappers";
|
2020-06-03 10:50:10 +00:00
|
|
|
import {
|
|
|
|
|
ReactTableColumnProps,
|
|
|
|
|
ColumnMenuOptionProps,
|
|
|
|
|
} from "./ReactTableComponent";
|
2020-07-14 07:55:46 +00:00
|
|
|
import { TableHeaderCell, renderEmptyRows } from "./TableUtilities";
|
2020-07-02 06:26:01 +00:00
|
|
|
import TableHeader from "./TableHeader";
|
|
|
|
|
import { Classes } from "@blueprintjs/core";
|
2020-07-28 14:26:27 +00:00
|
|
|
import { ColumnAction } from "components/propertyControls/ColumnActionSelectorControl";
|
2020-08-10 10:01:36 +00:00
|
|
|
import {
|
|
|
|
|
CompactMode,
|
|
|
|
|
CompactModeTypes,
|
|
|
|
|
} from "components/designSystems/appsmith/TableCompactMode";
|
2020-06-03 10:50:10 +00:00
|
|
|
|
2020-08-10 10:01:36 +00:00
|
|
|
export type TableSizes = {
|
|
|
|
|
COLUMN_HEADER_HEIGHT: number;
|
|
|
|
|
TABLE_HEADER_HEIGHT: number;
|
|
|
|
|
ROW_HEIGHT: number;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export const TABLE_SIZES: { [key: string]: TableSizes } = {
|
|
|
|
|
[CompactModeTypes.DEFAULT]: {
|
|
|
|
|
COLUMN_HEADER_HEIGHT: 52,
|
|
|
|
|
TABLE_HEADER_HEIGHT: 61,
|
|
|
|
|
ROW_HEIGHT: 52,
|
|
|
|
|
},
|
|
|
|
|
[CompactModeTypes.SHORT]: {
|
|
|
|
|
COLUMN_HEADER_HEIGHT: 52,
|
|
|
|
|
TABLE_HEADER_HEIGHT: 61,
|
|
|
|
|
ROW_HEIGHT: 40,
|
|
|
|
|
},
|
|
|
|
|
};
|
2020-07-16 10:39:07 +00:00
|
|
|
|
2020-06-03 10:50:10 +00:00
|
|
|
interface TableProps {
|
|
|
|
|
width: number;
|
|
|
|
|
height: number;
|
|
|
|
|
pageSize: number;
|
|
|
|
|
widgetId: string;
|
2020-07-20 06:04:05 +00:00
|
|
|
widgetName: string;
|
2020-07-03 08:26:04 +00:00
|
|
|
searchKey: string;
|
2020-07-02 06:26:01 +00:00
|
|
|
isLoading: boolean;
|
2020-06-03 10:50:10 +00:00
|
|
|
columns: ReactTableColumnProps[];
|
2020-07-03 08:26:04 +00:00
|
|
|
hiddenColumns?: string[];
|
|
|
|
|
updateHiddenColumns: (hiddenColumns?: string[]) => void;
|
2020-06-03 10:50:10 +00:00
|
|
|
data: object[];
|
|
|
|
|
displayColumnActions: boolean;
|
|
|
|
|
columnNameMap?: { [key: string]: string };
|
2020-07-14 07:55:46 +00:00
|
|
|
getColumnMenu: (columnIndex: number) => ColumnMenuOptionProps[];
|
|
|
|
|
handleColumnNameUpdate: (columnIndex: number, columnName: string) => void;
|
2020-08-10 06:45:31 +00:00
|
|
|
sortTableColumn: (columnIndex: number, asc: boolean) => void;
|
2020-06-03 10:50:10 +00:00
|
|
|
handleResizeColumn: Function;
|
|
|
|
|
selectTableRow: (
|
|
|
|
|
row: { original: object; index: number },
|
|
|
|
|
isSelected: boolean,
|
|
|
|
|
) => void;
|
|
|
|
|
pageNo: number;
|
|
|
|
|
updatePageNo: Function;
|
|
|
|
|
nextPageClick: () => void;
|
|
|
|
|
prevPageClick: () => void;
|
|
|
|
|
serverSidePaginationEnabled: boolean;
|
|
|
|
|
selectedRowIndex: number;
|
|
|
|
|
disableDrag: () => void;
|
|
|
|
|
enableDrag: () => void;
|
2020-07-03 08:26:04 +00:00
|
|
|
searchTableData: (searchKey: any) => void;
|
2020-07-28 14:26:27 +00:00
|
|
|
columnActions?: ColumnAction[];
|
2020-08-10 10:01:36 +00:00
|
|
|
compactMode?: CompactMode;
|
|
|
|
|
updateCompactMode: (compactMode: CompactMode) => void;
|
2020-06-03 10:50:10 +00:00
|
|
|
}
|
|
|
|
|
|
2020-08-10 10:01:36 +00:00
|
|
|
const defaultColumn = {
|
|
|
|
|
minWidth: 30,
|
|
|
|
|
width: 150,
|
|
|
|
|
maxWidth: 400,
|
|
|
|
|
};
|
|
|
|
|
|
2020-06-03 10:50:10 +00:00
|
|
|
export const Table = (props: TableProps) => {
|
2020-07-14 07:55:46 +00:00
|
|
|
const pageCount = Math.ceil(props.data.length / props.pageSize);
|
2020-06-03 10:50:10 +00:00
|
|
|
const currentPageIndex = props.pageNo < pageCount ? props.pageNo : 0;
|
2020-07-14 07:55:46 +00:00
|
|
|
const data = React.useMemo(() => props.data, [JSON.stringify(props.data)]);
|
2020-08-10 10:01:36 +00:00
|
|
|
const columnMemoKey = JSON.stringify({
|
|
|
|
|
columns: props.columns,
|
|
|
|
|
columnActions: props.columnActions,
|
|
|
|
|
compactMode: props.compactMode,
|
|
|
|
|
});
|
|
|
|
|
const columns = React.useMemo(() => props.columns, [columnMemoKey]);
|
2020-06-03 10:50:10 +00:00
|
|
|
const {
|
|
|
|
|
getTableProps,
|
|
|
|
|
getTableBodyProps,
|
|
|
|
|
headerGroups,
|
|
|
|
|
prepareRow,
|
|
|
|
|
page,
|
|
|
|
|
pageOptions,
|
|
|
|
|
} = useTable(
|
|
|
|
|
{
|
2020-07-20 06:04:05 +00:00
|
|
|
columns: columns,
|
2020-06-03 10:50:10 +00:00
|
|
|
data,
|
|
|
|
|
defaultColumn,
|
|
|
|
|
initialState: {
|
|
|
|
|
pageIndex: currentPageIndex,
|
|
|
|
|
pageSize: props.pageSize,
|
|
|
|
|
},
|
|
|
|
|
manualPagination: true,
|
|
|
|
|
pageCount,
|
|
|
|
|
},
|
|
|
|
|
useFlexLayout,
|
|
|
|
|
useResizeColumns,
|
|
|
|
|
usePagination,
|
|
|
|
|
useRowSelect,
|
|
|
|
|
);
|
|
|
|
|
let startIndex = currentPageIndex * props.pageSize;
|
|
|
|
|
let endIndex = startIndex + props.pageSize;
|
|
|
|
|
if (props.serverSidePaginationEnabled) {
|
|
|
|
|
startIndex = 0;
|
2020-07-14 07:55:46 +00:00
|
|
|
endIndex = props.data.length;
|
2020-06-03 10:50:10 +00:00
|
|
|
}
|
|
|
|
|
const subPage = page.slice(startIndex, endIndex);
|
|
|
|
|
const selectedRowIndex = props.selectedRowIndex;
|
2020-08-10 10:01:36 +00:00
|
|
|
const tableSizes = TABLE_SIZES[props.compactMode || CompactModeTypes.DEFAULT];
|
|
|
|
|
/* Subtracting 9px to handling widget padding */
|
|
|
|
|
const tableRowHeight =
|
|
|
|
|
(props.height -
|
|
|
|
|
(tableSizes.COLUMN_HEADER_HEIGHT + tableSizes.TABLE_HEADER_HEIGHT + 9)) /
|
|
|
|
|
props.pageSize;
|
2020-06-03 10:50:10 +00:00
|
|
|
return (
|
|
|
|
|
<TableWrapper
|
|
|
|
|
width={props.width}
|
|
|
|
|
height={props.height}
|
2020-08-10 10:01:36 +00:00
|
|
|
tableSizes={tableSizes}
|
2020-06-03 10:50:10 +00:00
|
|
|
id={`table${props.widgetId}`}
|
2020-08-10 10:01:36 +00:00
|
|
|
tableRowHeight={tableRowHeight}
|
2020-06-03 10:50:10 +00:00
|
|
|
>
|
2020-07-02 06:26:01 +00:00
|
|
|
<TableHeader
|
2020-08-10 06:47:47 +00:00
|
|
|
width={props.width}
|
2020-07-20 06:04:05 +00:00
|
|
|
tableData={props.data}
|
|
|
|
|
tableColumns={props.columns}
|
2020-07-03 08:26:04 +00:00
|
|
|
searchTableData={props.searchTableData}
|
|
|
|
|
searchKey={props.searchKey}
|
2020-07-02 06:26:01 +00:00
|
|
|
updatePageNo={props.updatePageNo}
|
|
|
|
|
nextPageClick={props.nextPageClick}
|
|
|
|
|
prevPageClick={props.prevPageClick}
|
|
|
|
|
pageNo={props.pageNo}
|
|
|
|
|
pageCount={pageCount}
|
|
|
|
|
currentPageIndex={currentPageIndex}
|
|
|
|
|
pageOptions={pageOptions}
|
2020-07-20 06:04:05 +00:00
|
|
|
widgetName={props.widgetName}
|
2020-07-02 06:26:01 +00:00
|
|
|
serverSidePaginationEnabled={props.serverSidePaginationEnabled}
|
2020-07-03 08:26:04 +00:00
|
|
|
columns={props.columns.filter((column: ReactTableColumnProps) => {
|
|
|
|
|
return column.accessor !== "actions";
|
|
|
|
|
})}
|
|
|
|
|
hiddenColumns={props.hiddenColumns}
|
|
|
|
|
updateHiddenColumns={props.updateHiddenColumns}
|
2020-07-14 07:40:52 +00:00
|
|
|
displayColumnActions={props.displayColumnActions}
|
2020-08-10 10:01:36 +00:00
|
|
|
compactMode={props.compactMode}
|
|
|
|
|
updateCompactMode={props.updateCompactMode}
|
2020-07-02 06:26:01 +00:00
|
|
|
/>
|
|
|
|
|
<div className={props.isLoading ? Classes.SKELETON : "tableWrap"}>
|
2020-06-03 10:50:10 +00:00
|
|
|
<div {...getTableProps()} className="table">
|
|
|
|
|
<div onMouseOver={props.disableDrag} onMouseLeave={props.enableDrag}>
|
|
|
|
|
{headerGroups.map((headerGroup: any, index: number) => (
|
|
|
|
|
<div
|
|
|
|
|
{...headerGroup.getHeaderGroupProps()}
|
|
|
|
|
className="tr"
|
2020-07-14 07:55:46 +00:00
|
|
|
key={index}
|
2020-06-03 10:50:10 +00:00
|
|
|
>
|
|
|
|
|
{headerGroup.headers.map((column: any, columnIndex: number) => {
|
|
|
|
|
return (
|
2020-07-14 07:55:46 +00:00
|
|
|
<TableHeaderCell
|
2020-06-03 10:50:10 +00:00
|
|
|
key={columnIndex}
|
2020-07-14 07:55:46 +00:00
|
|
|
column={column}
|
|
|
|
|
columnName={
|
|
|
|
|
props.columnNameMap && props.columnNameMap[column.id]
|
|
|
|
|
? props.columnNameMap[column.id]
|
|
|
|
|
: column.id
|
|
|
|
|
}
|
|
|
|
|
columnIndex={columnIndex}
|
|
|
|
|
isHidden={column.isHidden}
|
|
|
|
|
displayColumnActions={props.displayColumnActions}
|
|
|
|
|
handleColumnNameUpdate={props.handleColumnNameUpdate}
|
|
|
|
|
getColumnMenu={props.getColumnMenu}
|
|
|
|
|
handleResizeColumn={props.handleResizeColumn}
|
2020-08-10 06:45:31 +00:00
|
|
|
sortTableColumn={props.sortTableColumn}
|
|
|
|
|
isAscOrder={column.isAscOrder}
|
2020-07-14 07:55:46 +00:00
|
|
|
/>
|
2020-06-03 10:50:10 +00:00
|
|
|
);
|
|
|
|
|
})}
|
|
|
|
|
</div>
|
|
|
|
|
))}
|
2020-06-17 06:00:43 +00:00
|
|
|
{headerGroups.length === 0 &&
|
2020-07-16 10:39:07 +00:00
|
|
|
renderEmptyRows(
|
|
|
|
|
1,
|
|
|
|
|
props.columns,
|
|
|
|
|
props.width,
|
|
|
|
|
subPage,
|
|
|
|
|
prepareRow,
|
|
|
|
|
)}
|
2020-06-03 10:50:10 +00:00
|
|
|
</div>
|
2020-07-16 10:39:07 +00:00
|
|
|
<div
|
|
|
|
|
{...getTableBodyProps()}
|
|
|
|
|
className={`tbody ${
|
|
|
|
|
props.pageSize > subPage.length ? "no-scroll" : ""
|
|
|
|
|
}`}
|
|
|
|
|
>
|
2020-07-14 07:55:46 +00:00
|
|
|
{subPage.map((row, rowIndex) => {
|
2020-06-03 10:50:10 +00:00
|
|
|
prepareRow(row);
|
|
|
|
|
return (
|
|
|
|
|
<div
|
|
|
|
|
{...row.getRowProps()}
|
|
|
|
|
className={
|
|
|
|
|
"tr" +
|
|
|
|
|
`${row.index === selectedRowIndex ? " selected-row" : ""}`
|
|
|
|
|
}
|
|
|
|
|
onClick={() => {
|
|
|
|
|
row.toggleRowSelected();
|
|
|
|
|
props.selectTableRow(row, row.index === selectedRowIndex);
|
|
|
|
|
}}
|
2020-07-14 07:55:46 +00:00
|
|
|
key={rowIndex}
|
2020-06-03 10:50:10 +00:00
|
|
|
>
|
|
|
|
|
{row.cells.map((cell, cellIndex) => {
|
|
|
|
|
return (
|
|
|
|
|
<div
|
|
|
|
|
{...cell.getCellProps()}
|
|
|
|
|
className="td"
|
2020-07-14 07:55:46 +00:00
|
|
|
key={cellIndex}
|
2020-07-23 05:33:12 +00:00
|
|
|
data-rowindex={rowIndex}
|
|
|
|
|
data-colindex={cellIndex}
|
2020-06-03 10:50:10 +00:00
|
|
|
>
|
|
|
|
|
{cell.render("Cell")}
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
})}
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
})}
|
2020-06-17 06:00:43 +00:00
|
|
|
{props.pageSize > subPage.length &&
|
|
|
|
|
renderEmptyRows(
|
|
|
|
|
props.pageSize - subPage.length,
|
|
|
|
|
props.columns,
|
|
|
|
|
props.width,
|
2020-07-16 10:39:07 +00:00
|
|
|
subPage,
|
|
|
|
|
prepareRow,
|
2020-06-17 06:00:43 +00:00
|
|
|
)}
|
2020-06-03 10:50:10 +00:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</TableWrapper>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export default Table;
|