PromucFlow_constructor/app/client/src/components/designSystems/appsmith/Table.tsx

261 lines
8.5 KiB
TypeScript
Raw Normal View History

2020-06-03 10:50:10 +00:00
import React from "react";
import {
useTable,
usePagination,
useFlexLayout,
useResizeColumns,
useRowSelect,
} from "react-table";
import { TableWrapper } from "./TableStyledWrappers";
import { ColumnMenuOptionProps } from "./ReactTableComponent";
import { ReactTableFilter } from "components/designSystems/appsmith/TableFilters";
import { TableHeaderCell, renderEmptyRows } from "./TableUtilities";
import TableHeader from "./TableHeader";
import { Classes } from "@blueprintjs/core";
import { ColumnAction } from "components/propertyControls/ColumnActionSelectorControl";
import { ReactTableColumnProps } from "widgets/TableWidget";
import { Colors } from "constants/Colors";
import {
TABLE_SIZES,
CompactMode,
CompactModeTypes,
} from "widgets/TableWidget";
import { EventType } from "constants/ActionConstants";
2020-06-03 10:50:10 +00:00
interface TableProps {
width: number;
height: number;
pageSize: number;
widgetId: string;
widgetName: string;
searchKey: string;
isLoading: boolean;
2020-06-03 10:50:10 +00:00
columns: ReactTableColumnProps[];
hiddenColumns?: string[];
updateHiddenColumns: (hiddenColumns?: string[]) => void;
data: Array<Record<string, unknown>>;
editMode: boolean;
2020-06-03 10:50:10 +00:00
columnNameMap?: { [key: string]: string };
getColumnMenu: (columnIndex: number) => ColumnMenuOptionProps[];
handleColumnNameUpdate: (columnIndex: number, columnName: string) => void;
sortTableColumn: (columnIndex: number, asc: boolean) => void;
handleResizeColumn: (columnIndex: number, columnWidth: string) => void;
2020-06-03 10:50:10 +00:00
selectTableRow: (
row: { original: Record<string, unknown>; index: number },
2020-06-03 10:50:10 +00:00
isSelected: boolean,
) => void;
pageNo: number;
updatePageNo: (pageNo: number, event?: EventType) => void;
2020-06-03 10:50:10 +00:00
nextPageClick: () => void;
prevPageClick: () => void;
serverSidePaginationEnabled: boolean;
selectedRowIndex: number;
selectedRowIndices: number[];
2020-06-03 10:50:10 +00:00
disableDrag: () => void;
enableDrag: () => void;
triggerRowSelection: boolean;
searchTableData: (searchKey: any) => void;
filters?: ReactTableFilter[];
applyFilter: (filters: ReactTableFilter[]) => void;
columnActions?: ColumnAction[];
compactMode?: CompactMode;
updateCompactMode: (compactMode: CompactMode) => void;
2020-06-03 10:50:10 +00:00
}
const defaultColumn = {
minWidth: 30,
width: 150,
};
2020-06-03 10:50:10 +00:00
export const Table = (props: TableProps) => {
const data = React.useMemo(() => props.data, [props.data]);
const columnString = JSON.stringify({
columns: props.columns,
actions: props.columnActions,
columnActions: props.columnActions,
compactMode: props.compactMode,
});
2021-01-12 01:22:31 +00:00
const columns = React.useMemo(() => props.columns, [columnString]);
const pageCount = Math.ceil(props.data.length / props.pageSize);
const currentPageIndex = props.pageNo < pageCount ? props.pageNo : 0;
2020-06-03 10:50:10 +00:00
const {
getTableProps,
getTableBodyProps,
headerGroups,
prepareRow,
page,
pageOptions,
} = useTable(
{
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;
endIndex = props.data.length;
2020-06-03 10:50:10 +00:00
}
const subPage = page.slice(startIndex, endIndex);
const selectedRowIndex = props.selectedRowIndex;
const selectedRowIndices = props.selectedRowIndices || [];
const tableSizes = TABLE_SIZES[props.compactMode || CompactModeTypes.DEFAULT];
/* Subtracting 9px to handling widget padding */
2020-06-03 10:50:10 +00:00
return (
<TableWrapper
width={props.width}
height={props.height}
tableSizes={tableSizes}
2020-06-03 10:50:10 +00:00
id={`table${props.widgetId}`}
triggerRowSelection={props.triggerRowSelection}
backgroundColor={Colors.ATHENS_GRAY_DARKER}
2020-06-03 10:50:10 +00:00
>
<TableHeader
width={props.width}
tableData={props.data}
tableColumns={props.columns}
searchTableData={props.searchTableData}
searchKey={props.searchKey}
updatePageNo={props.updatePageNo}
nextPageClick={props.nextPageClick}
prevPageClick={props.prevPageClick}
pageNo={props.pageNo}
pageCount={pageCount}
currentPageIndex={currentPageIndex}
pageOptions={pageOptions}
widgetName={props.widgetName}
serverSidePaginationEnabled={props.serverSidePaginationEnabled}
columns={props.columns.filter((column: ReactTableColumnProps) => {
return column.accessor !== "actions";
})}
hiddenColumns={props.hiddenColumns}
updateHiddenColumns={props.updateHiddenColumns}
filters={props.filters}
applyFilter={props.applyFilter}
editMode={props.editMode}
compactMode={props.compactMode}
updateCompactMode={props.updateCompactMode}
tableSizes={tableSizes}
/>
<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}
className="thead"
>
2020-06-03 10:50:10 +00:00
{headerGroups.map((headerGroup: any, index: number) => (
<div
{...headerGroup.getHeaderGroupProps()}
className="tr"
key={index}
2020-06-03 10:50:10 +00:00
>
{headerGroup.headers.map((column: any, columnIndex: number) => {
return (
<TableHeaderCell
2020-06-03 10:50:10 +00:00
key={columnIndex}
column={column}
columnName={
props.columnNameMap && props.columnNameMap[column.id]
? props.columnNameMap[column.id]
: column.id
}
columnIndex={columnIndex}
isHidden={column.isHidden}
editMode={props.editMode}
handleColumnNameUpdate={props.handleColumnNameUpdate}
getColumnMenu={props.getColumnMenu}
handleResizeColumn={props.handleResizeColumn}
sortTableColumn={props.sortTableColumn}
isAscOrder={column.isAscOrder}
/>
2020-06-03 10:50:10 +00:00
);
})}
</div>
))}
2020-06-17 06:00:43 +00:00
{headerGroups.length === 0 &&
renderEmptyRows(
1,
props.columns,
props.width,
subPage,
prepareRow,
)}
2020-06-03 10:50:10 +00:00
</div>
<div
{...getTableBodyProps()}
className={`tbody ${
props.pageSize > subPage.length ? "no-scroll" : ""
}`}
>
{subPage.map((row, rowIndex) => {
2020-06-03 10:50:10 +00:00
prepareRow(row);
return (
<div
{...row.getRowProps()}
className={
"tr" +
`${
row.index === selectedRowIndex ||
selectedRowIndices.includes(row.index)
? " selected-row"
: ""
}`
2020-06-03 10:50:10 +00:00
}
onClick={() => {
row.toggleRowSelected();
props.selectTableRow(
row,
row.index === selectedRowIndex ||
selectedRowIndices.includes(row.index),
);
2020-06-03 10:50:10 +00:00
}}
key={rowIndex}
2020-06-03 10:50:10 +00:00
>
{row.cells.map((cell, cellIndex) => {
return (
<div
{...cell.getCellProps()}
className="td"
key={cellIndex}
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,
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;