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

278 lines
8.7 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 { InputGroup } from "@blueprintjs/core";
import { TableWrapper } from "./TableStyledWrappers";
2020-06-03 10:50:10 +00:00
import {
ReactTableColumnProps,
ColumnMenuOptionProps,
} from "./ReactTableComponent";
import { TableColumnMenuPopup } from "./TableColumnMenu";
import TableHeader from "./TableHeader";
import { Classes } from "@blueprintjs/core";
2020-06-03 10:50:10 +00:00
interface TableProps {
width: number;
height: number;
pageSize: number;
widgetId: string;
isLoading: boolean;
2020-06-03 10:50:10 +00:00
columns: ReactTableColumnProps[];
data: object[];
showMenu: (columnIndex: number) => void;
displayColumnActions: boolean;
columnNameMap?: { [key: string]: string };
columnMenuOptions: ColumnMenuOptionProps[];
columnIndex: number;
columnAction: string;
onColumnNameChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
handleColumnNameUpdate: (columnIndex: number) => 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;
onKeyPress: (columnIndex: number, key: string) => void;
2020-06-03 10:50:10 +00:00
serverSidePaginationEnabled: boolean;
selectedRowIndex: number;
disableDrag: () => void;
enableDrag: () => void;
}
export const Table = (props: TableProps) => {
const { data, columns } = props;
const defaultColumn = React.useMemo(
() => ({
minWidth: 30,
width: 150,
maxWidth: 400,
}),
[],
);
2020-06-17 06:00:43 +00:00
2020-06-03 10:50:10 +00:00
const pageCount = Math.ceil(data.length / props.pageSize);
const currentPageIndex = props.pageNo < pageCount ? props.pageNo : 0;
const {
getTableProps,
getTableBodyProps,
headerGroups,
prepareRow,
page,
pageOptions,
} = useTable(
{
columns,
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 = data.length;
}
const subPage = page.slice(startIndex, endIndex);
const selectedRowIndex = props.selectedRowIndex;
return (
<TableWrapper
width={props.width}
height={props.height}
id={`table${props.widgetId}`}
>
<TableHeader
updatePageNo={props.updatePageNo}
nextPageClick={props.nextPageClick}
prevPageClick={props.prevPageClick}
pageNo={props.pageNo}
pageCount={pageCount}
currentPageIndex={currentPageIndex}
pageOptions={pageOptions}
serverSidePaginationEnabled={props.serverSidePaginationEnabled}
/>
<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
key={index}
{...headerGroup.getHeaderGroupProps()}
className="tr"
>
{headerGroup.headers.map((column: any, columnIndex: number) => {
if (column.isResizing) {
props.handleResizeColumn(
columnIndex,
column.getHeaderProps().style.width,
);
}
return (
<div
key={columnIndex}
{...column.getHeaderProps()}
className="th header-reorder"
>
{props.columnIndex === columnIndex &&
props.columnAction === "rename_column" && (
<InputGroup
placeholder="Enter Column Name"
onChange={props.onColumnNameChange}
onKeyPress={event =>
props.onKeyPress(columnIndex, event.key)
}
2020-06-03 10:50:10 +00:00
type="text"
defaultValue={
props.columnNameMap &&
props.columnNameMap[column.id]
? props.columnNameMap[column.id]
: column.id
}
className="input-group"
onBlur={() =>
props.handleColumnNameUpdate(columnIndex)
}
2020-06-03 10:50:10 +00:00
/>
)}
{(props.columnIndex !== columnIndex ||
(props.columnIndex === columnIndex &&
"rename_column" !== props.columnAction)) && (
<div
className={
!column.isHidden
? "draggable-header"
: "hidden-header"
}
>
{column.render("Header")}
</div>
)}
{props.displayColumnActions && (
<div className="column-menu">
<TableColumnMenuPopup
showMenu={props.showMenu}
columnMenuOptions={props.columnMenuOptions}
columnIndex={columnIndex}
/>
</div>
)}
<div
{...column.getResizerProps()}
className={`resizer ${
column.isResizing ? "isResizing" : ""
}`}
/>
</div>
);
})}
</div>
))}
2020-06-17 06:00:43 +00:00
{headerGroups.length === 0 &&
renderEmptyRows(1, props.columns, props.width)}
2020-06-03 10:50:10 +00:00
</div>
<div {...getTableBodyProps()} className="tbody">
{subPage.map((row, index) => {
prepareRow(row);
return (
<div
key={index}
{...row.getRowProps()}
className={
"tr" +
`${row.index === selectedRowIndex ? " selected-row" : ""}`
}
onClick={() => {
row.toggleRowSelected();
props.selectTableRow(row, row.index === selectedRowIndex);
}}
>
{row.cells.map((cell, cellIndex) => {
return (
<div
key={cellIndex}
{...cell.getCellProps()}
className="td"
data-rowindex={index}
data-colindex={cellIndex}
>
{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-06-03 10:50:10 +00:00
</div>
</div>
</div>
</TableWrapper>
);
};
export default Table;
2020-06-17 06:00:43 +00:00
const renderEmptyRows = (
rowCount: number,
columns: any,
tableWidth: number,
) => {
const rows: string[] = new Array(rowCount).fill("");
const tableColumns = columns.length
? columns
: new Array(3).fill({ width: tableWidth / 3 });
return (
<React.Fragment>
{rows.map((row: string, index: number) => {
return (
<div
className="tr"
key={index}
style={{
display: "flex",
flex: "1 0 auto",
}}
>
{tableColumns.map((column: any, colIndex: number) => {
return (
<div
key={colIndex}
className="td"
style={{
width: column.width + "px",
boxSizing: "border-box",
flex: `${column.width} 0 auto`,
}}
/>
);
})}
</div>
);
})}
</React.Fragment>
);
};