Files
rowy/src/components/Table/Table.tsx

227 lines
7.5 KiB
TypeScript
Raw Normal View History

2022-06-06 15:58:17 +10:00
import React, { useMemo, useState, Suspense } from "react";
2022-05-19 16:37:56 +10:00
import { useAtom, useSetAtom } from "jotai";
import { useDebouncedCallback, useThrottledCallback } from "use-debounce";
2022-05-19 16:37:56 +10:00
import { DndProvider } from "react-dnd";
import { HTML5Backend } from "react-dnd-html5-backend";
import { findIndex } from "lodash-es";
2022-05-19 16:37:56 +10:00
2022-10-14 16:15:41 +11:00
import {
createColumnHelper,
flexRender,
getCoreRowModel,
useReactTable,
} from "@tanstack/react-table";
import { TOP_BAR_HEIGHT } from "@src/layouts/Navigation/TopBar";
import { TABLE_TOOLBAR_HEIGHT } from "@src/components/TableToolbar";
import { StyledTable } from "./Styled/StyledTable";
import { StyledRow } from "./Styled/StyledRow";
import ColumnHeaderComponent from "./Column";
2022-05-27 15:10:06 +10:00
import { LinearProgress } from "@mui/material";
2022-05-19 16:37:56 +10:00
import TableContainer, { OUT_OF_ORDER_MARGIN } from "./TableContainer";
2022-05-27 15:10:06 +10:00
import ColumnHeader, { COLUMN_HEADER_HEIGHT } from "./ColumnHeader";
2022-05-19 16:37:56 +10:00
import FinalColumnHeader from "./FinalColumnHeader";
import FinalColumn from "./formatters/FinalColumn";
2022-10-14 16:15:41 +11:00
// import TableRow from "./TableRow";
2022-05-27 15:10:06 +10:00
import EmptyState from "@src/components/EmptyState";
2022-05-19 16:37:56 +10:00
// import BulkActions from "./BulkActions";
2022-05-27 15:10:06 +10:00
import AddRow from "@src/components/TableToolbar/AddRow";
import { AddRow as AddRowIcon } from "@src/assets/icons";
2022-06-06 15:58:17 +10:00
import Loading from "@src/components/Loading";
import ContextMenu from "./ContextMenu";
2022-05-19 16:37:56 +10:00
import {
2022-07-18 14:40:46 +10:00
projectScope,
2022-05-19 16:37:56 +10:00
userRolesAtom,
userSettingsAtom,
2022-07-18 14:40:46 +10:00
} from "@src/atoms/projectScope";
2022-05-19 16:37:56 +10:00
import {
tableScope,
tableIdAtom,
tableSettingsAtom,
tableSchemaAtom,
tableColumnsOrderedAtom,
tableRowsAtom,
tableNextPageAtom,
2022-05-19 16:37:56 +10:00
tablePageAtom,
updateColumnAtom,
updateFieldAtom,
selectedCellAtom,
2022-05-19 16:37:56 +10:00
} from "@src/atoms/tableScope";
2022-05-24 20:34:28 +10:00
import { getFieldType, getFieldProp } from "@src/components/fields";
2022-05-19 16:37:56 +10:00
import { FieldType } from "@src/constants/fields";
import { formatSubTableName } from "@src/utils/table";
2022-10-14 16:15:41 +11:00
import { TableRow, ColumnConfig } from "@src/types/table";
import { StyledCell } from "./Styled/StyledCell";
2022-05-19 16:37:56 +10:00
export const DEFAULT_ROW_HEIGHT = 41;
export const DEFAULT_COL_WIDTH = 150;
export const MAX_COL_WIDTH = 380;
2022-05-19 16:37:56 +10:00
2022-10-14 16:15:41 +11:00
declare module "@tanstack/table-core" {
interface ColumnMeta<TData, TValue> extends ColumnConfig {}
}
const columnHelper = createColumnHelper<TableRow>();
const getRowId = (row: TableRow) => row._rowy_ref.path || row._rowy_ref.id;
2022-05-19 16:37:56 +10:00
2022-10-14 16:15:41 +11:00
export default function TableComponent() {
2022-07-18 14:40:46 +10:00
const [userRoles] = useAtom(userRolesAtom, projectScope);
const [userSettings] = useAtom(userSettingsAtom, projectScope);
2022-05-19 16:37:56 +10:00
const [tableId] = useAtom(tableIdAtom, tableScope);
const [tableSettings] = useAtom(tableSettingsAtom, tableScope);
const [tableSchema] = useAtom(tableSchemaAtom, tableScope);
const [tableColumnsOrdered] = useAtom(tableColumnsOrderedAtom, tableScope);
const [tableRows] = useAtom(tableRowsAtom, tableScope);
const [tableNextPage] = useAtom(tableNextPageAtom, tableScope);
const setTablePage = useSetAtom(tablePageAtom, tableScope);
const [selectedCell, setSelectedCell] = useAtom(selectedCellAtom, tableScope);
2022-05-19 16:37:56 +10:00
const updateColumn = useSetAtom(updateColumnAtom, tableScope);
const updateField = useSetAtom(updateFieldAtom, tableScope);
2022-10-14 16:15:41 +11:00
const canAddColumn = userRoles.includes("ADMIN");
2022-05-19 16:37:56 +10:00
const userDocHiddenFields =
userSettings.tables?.[formatSubTableName(tableId)]?.hiddenFields;
2022-10-14 16:15:41 +11:00
// Get column defs from table schema
// Also add end column for admins
2022-05-19 16:37:56 +10:00
const columns = useMemo(() => {
2022-10-14 16:15:41 +11:00
const _columns = tableColumnsOrdered
// .filter((column) => {
// if (column.hidden) return false;
// if (
// Array.isArray(userDocHiddenFields) &&
// userDocHiddenFields.includes(column.key)
// )
// return false;
// return true;
// })
.map((columnConfig) =>
columnHelper.accessor(columnConfig.fieldName, {
meta: columnConfig,
// draggable: true,
// resizable: true,
// frozen: columnConfig.fixed,
// headerRenderer: ColumnHeader,
// formatter:
// getFieldProp("TableCell", getFieldType(columnConfig)) ??
// function InDev() {
// return null;
// },
// editor:
// getFieldProp("TableEditor", getFieldType(columnConfig)) ??
// function InDev() {
// return null;
// },
// ...columnConfig,
// editable:
// tableSettings.readOnly && !userRoles.includes("ADMIN")
// ? false
// : columnConfig.editable ?? true,
// width: columnConfig.width ?? DEFAULT_COL_WIDTH,
})
);
// if (canAddColumn || !tableSettings.readOnly) {
// _columns.push({
// isNew: true,
// key: "new",
// fieldName: "_rowy_new",
// name: "Add column",
// type: FieldType.last,
// index: _columns.length ?? 0,
// width: 154,
// headerRenderer: FinalColumnHeader,
// headerCellClass: "final-column-header",
// cellClass: "final-column-cell",
// formatter: FinalColumn,
// editable: false,
// });
// }
2022-05-19 16:37:56 +10:00
return _columns;
}, [
tableColumnsOrdered,
2022-10-14 16:15:41 +11:00
// userDocHiddenFields,
// tableSettings.readOnly,
// canAddColumn,
2022-05-19 16:37:56 +10:00
]);
2022-10-14 16:15:41 +11:00
const table = useReactTable({
data: tableRows,
columns,
getCoreRowModel: getCoreRowModel(),
getRowId,
columnResizeMode: "onChange",
// debugRows: true,
});
console.log(table);
2022-10-14 16:15:41 +11:00
const handleKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {};
2022-05-19 16:37:56 +10:00
return (
2022-10-14 16:15:41 +11:00
<>
<StyledTable
role="grid"
style={{ width: table.getTotalSize(), userSelect: "none" }}
onKeyDown={handleKeyDown}
>
<div className="thead" style={{ position: "sticky", top: 0 }}>
{table.getHeaderGroups().map((headerGroup) => (
<StyledRow key={headerGroup.id} role="row">
{headerGroup.headers.map((header) => (
<ColumnHeaderComponent
key={header.id}
label={header.column.columnDef.meta?.name || header.id}
type={header.column.columnDef.meta?.type}
style={{ width: header.getSize() }}
>
{/* <div
{...{
onMouseDown: header.getResizeHandler(),
onTouchStart: header.getResizeHandler(),
className: `resizer ${
header.column.getIsResizing() ? "isResizing" : ""
}`,
// style: {
// transform:
// columnResizeMode === 'onEnd' &&
// header.column.getIsResizing()
// ? `translateX(${
// table.getState().columnSizingInfo.deltaOffset
// }px)`
// : '',
// },
}}
/> */}
</ColumnHeaderComponent>
))}
</StyledRow>
))}
</div>
<div className="tbody">
{table.getRowModel().rows.map((row) => (
<StyledRow key={row.id} role="row">
{row.getVisibleCells().map((cell) => (
<StyledCell
key={cell.id}
style={{ width: cell.column.getSize() }}
>
{flexRender(cell.column.columnDef.cell, cell.getContext())}
<button>f</button>
</StyledCell>
))}
</StyledRow>
))}
</div>
</StyledTable>
</>
2022-05-19 16:37:56 +10:00
);
}