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 { 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";
|
2020-07-02 06:26:01 +00:00
|
|
|
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;
|
2020-07-02 06:26:01 +00:00
|
|
|
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;
|
2020-06-22 08:25:03 +00:00
|
|
|
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;
|
2020-06-22 08:25:03 +00:00
|
|
|
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}`}
|
|
|
|
|
>
|
2020-07-02 06:26:01 +00:00
|
|
|
<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}
|
2020-06-22 08:25:03 +00:00
|
|
|
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"
|
2020-06-22 08:25:03 +00:00
|
|
|
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>
|
|
|
|
|
);
|
|
|
|
|
};
|