mirror of
https://github.com/rowyio/rowy.git
synced 2025-12-29 00:16:39 +01:00
Merge pull request #1056 from rowyio/ROWY-831-preview-table
ROWY-831: Add preview table
This commit is contained in:
82
src/components/fields/Formula/PreviewTable.tsx
Normal file
82
src/components/fields/Formula/PreviewTable.tsx
Normal file
@@ -0,0 +1,82 @@
|
||||
import { Provider, useAtom } from "jotai";
|
||||
|
||||
import { currentUserAtom } from "@src/atoms/projectScope";
|
||||
import {
|
||||
tableRowsDbAtom,
|
||||
tableScope,
|
||||
tableSettingsAtom,
|
||||
} from "@src/atoms/tableScope";
|
||||
|
||||
import TablePage from "@src/pages/Table/TablePage";
|
||||
import { TableSchema } from "@src/types/table";
|
||||
import { Box, InputLabel } from "@mui/material";
|
||||
import TableSourcePreview from "./TableSourcePreview";
|
||||
|
||||
const PreviewTable = ({ tableSchema }: { tableSchema: TableSchema }) => {
|
||||
const [currentUser] = useAtom(currentUserAtom, tableScope);
|
||||
const [tableSettings] = useAtom(tableSettingsAtom, tableScope);
|
||||
return (
|
||||
<Box>
|
||||
<InputLabel>Preview table</InputLabel>
|
||||
<Provider
|
||||
key={"preview-table"}
|
||||
scope={tableScope}
|
||||
initialValues={[
|
||||
[currentUserAtom, currentUser],
|
||||
[
|
||||
tableSettingsAtom,
|
||||
{
|
||||
...tableSettings,
|
||||
id: "preview-table",
|
||||
collection: "preview-collection",
|
||||
},
|
||||
],
|
||||
[tableRowsDbAtom, []],
|
||||
]}
|
||||
>
|
||||
<TableSourcePreview tableSchema={tableSchema} />
|
||||
<Box
|
||||
sx={{
|
||||
maxHeight: 300,
|
||||
overflow: "auto",
|
||||
marginTop: 1,
|
||||
marginLeft: 0,
|
||||
|
||||
// table toolbar
|
||||
"& > div:first-child": {
|
||||
display: "none",
|
||||
},
|
||||
// table grid
|
||||
"& > div:nth-of-type(2)": {
|
||||
height: "unset",
|
||||
},
|
||||
// emtpy state
|
||||
"& .empty-state": {
|
||||
display: "none",
|
||||
},
|
||||
// column actions - add column
|
||||
'& [data-col-id="_rowy_column_actions"]': {
|
||||
display: "none",
|
||||
},
|
||||
// row headers - sort by, column settings
|
||||
'& [data-row-id="_rowy_header"] > button': {
|
||||
display: "none",
|
||||
},
|
||||
// row headers - drag handler
|
||||
'& [data-row-id="_rowy_header"] > .column-drag-handle': {
|
||||
display: "none !important",
|
||||
},
|
||||
// row headers - resize handler
|
||||
'& [data-row-id="_rowy_header"] >:last-child': {
|
||||
display: "none !important",
|
||||
},
|
||||
}}
|
||||
>
|
||||
<TablePage disableModals={true} disableSideDrawer={true} />
|
||||
</Box>
|
||||
</Provider>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default PreviewTable;
|
||||
@@ -1,4 +1,4 @@
|
||||
import { lazy, Suspense } from "react";
|
||||
import { lazy, Suspense, useMemo } from "react";
|
||||
import { useDebouncedCallback } from "use-debounce";
|
||||
import { useAtom } from "jotai";
|
||||
import MultiSelect from "@rowy/multiselect";
|
||||
@@ -12,12 +12,20 @@ import {
|
||||
Tooltip,
|
||||
} from "@mui/material";
|
||||
|
||||
import {
|
||||
tableColumnsOrderedAtom,
|
||||
tableSchemaAtom,
|
||||
tableScope,
|
||||
} from "@src/atoms/tableScope";
|
||||
|
||||
import FieldSkeleton from "@src/components/SideDrawer/FieldSkeleton";
|
||||
import { ISettingsProps } from "@src/components/fields/types";
|
||||
import { tableColumnsOrderedAtom, tableScope } from "@src/atoms/tableScope";
|
||||
import FieldsDropdown from "@src/components/ColumnModals/FieldsDropdown";
|
||||
import { DEFAULT_COL_WIDTH, DEFAULT_ROW_HEIGHT } from "@src/components/Table";
|
||||
import { ColumnConfig } from "@src/types/table";
|
||||
|
||||
import { defaultFn, listenerFieldTypes, outputFieldTypes } from "./util";
|
||||
import PreviewTable from "./PreviewTable";
|
||||
import { getFieldProp } from "..";
|
||||
|
||||
/* eslint-disable import/no-webpack-loader-syntax */
|
||||
@@ -38,14 +46,41 @@ const diagnosticsOptions = {
|
||||
|
||||
export default function Settings({
|
||||
config,
|
||||
fieldName,
|
||||
onChange,
|
||||
onBlur,
|
||||
errors,
|
||||
}: ISettingsProps) {
|
||||
const [tableSchema] = useAtom(tableSchemaAtom, tableScope);
|
||||
const [tableColumnsOrdered] = useAtom(tableColumnsOrderedAtom, tableScope);
|
||||
const returnType = getFieldProp("dataType", config.renderFieldType) ?? "any";
|
||||
const formulaFn = config?.formulaFn ? config.formulaFn : defaultFn;
|
||||
|
||||
const previewTableSchema = useMemo(() => {
|
||||
const columns = tableSchema.columns || {};
|
||||
return {
|
||||
...tableSchema,
|
||||
columns: Object.keys(columns).reduce((previewSchema, key) => {
|
||||
if ((config.listenerFields || []).includes(columns[key].fieldName)) {
|
||||
previewSchema[key] = {
|
||||
...columns[key],
|
||||
fixed: false,
|
||||
width: DEFAULT_COL_WIDTH,
|
||||
};
|
||||
}
|
||||
if (columns[key].fieldName === fieldName) {
|
||||
previewSchema[key] = {
|
||||
...columns[key],
|
||||
config,
|
||||
fixed: true,
|
||||
};
|
||||
}
|
||||
return previewSchema;
|
||||
}, {} as { [key: string]: ColumnConfig }),
|
||||
rowHeight: DEFAULT_ROW_HEIGHT,
|
||||
};
|
||||
}, [config, fieldName, tableSchema]);
|
||||
|
||||
return (
|
||||
<Stack spacing={1}>
|
||||
<Grid container direction="row" spacing={2} flexWrap="nowrap">
|
||||
@@ -125,6 +160,7 @@ export default function Settings({
|
||||
/>
|
||||
</Suspense>
|
||||
</div>
|
||||
<PreviewTable tableSchema={previewTableSchema} />
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
98
src/components/fields/Formula/TableSourcePreview.ts
Normal file
98
src/components/fields/Formula/TableSourcePreview.ts
Normal file
@@ -0,0 +1,98 @@
|
||||
import { useCallback, useEffect } from "react";
|
||||
import { useSetAtom } from "jotai";
|
||||
import { useAtomCallback } from "jotai/utils";
|
||||
import { cloneDeep, findIndex, initial, sortBy } from "lodash-es";
|
||||
|
||||
import {
|
||||
_deleteRowDbAtom,
|
||||
_updateRowDbAtom,
|
||||
tableNextPageAtom,
|
||||
tableRowsDbAtom,
|
||||
tableSchemaAtom,
|
||||
tableScope,
|
||||
} from "@src/atoms/tableScope";
|
||||
|
||||
import { TableRow, TableSchema } from "@src/types/table";
|
||||
import { updateRowData } from "@src/utils/table";
|
||||
|
||||
const initialRows = [
|
||||
{
|
||||
_rowy_ref: {
|
||||
id: "zzzzzzzzzzzzzzzzzzzw",
|
||||
path: "preview-collection/zzzzzzzzzzzzzzzzzzzw",
|
||||
},
|
||||
},
|
||||
{
|
||||
_rowy_ref: {
|
||||
id: "zzzzzzzzzzzzzzzzzzzx",
|
||||
path: "preview-collection/zzzzzzzzzzzzzzzzzzzx",
|
||||
},
|
||||
},
|
||||
{
|
||||
_rowy_ref: {
|
||||
id: "zzzzzzzzzzzzzzzzzzzy",
|
||||
path: "preview-collection/zzzzzzzzzzzzzzzzzzzy",
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const TableSourcePreview = ({ tableSchema }: { tableSchema: TableSchema }) => {
|
||||
const setTableSchemaAtom = useSetAtom(tableSchemaAtom, tableScope);
|
||||
const setRows = useSetAtom(tableRowsDbAtom, tableScope);
|
||||
|
||||
useEffect(() => {
|
||||
setRows(initialRows);
|
||||
}, [setRows]);
|
||||
|
||||
useEffect(() => {
|
||||
setTableSchemaAtom(() => ({
|
||||
...tableSchema,
|
||||
_rowy_ref: "preview",
|
||||
}));
|
||||
}, [tableSchema, setTableSchemaAtom]);
|
||||
|
||||
const readRowsDb = useAtomCallback(
|
||||
useCallback((get) => get(tableRowsDbAtom) || initialRows, []),
|
||||
tableScope
|
||||
);
|
||||
|
||||
const setUpdateRowDb = useSetAtom(_updateRowDbAtom, tableScope);
|
||||
setUpdateRowDb(() => async (path: string, update: Partial<TableRow>) => {
|
||||
const rows = await readRowsDb();
|
||||
const index = findIndex(rows, ["_rowy_ref.path", path]);
|
||||
if (index === -1) {
|
||||
setRows(
|
||||
sortBy(
|
||||
[
|
||||
...rows,
|
||||
{ ...update, _rowy_ref: { id: path.split("/").pop()!, path } },
|
||||
],
|
||||
["_rowy_ref.id"]
|
||||
)
|
||||
);
|
||||
} else {
|
||||
const updatedRows = [...rows];
|
||||
updatedRows[index] = cloneDeep(rows[index]);
|
||||
updatedRows[index] = updateRowData(updatedRows[index], update);
|
||||
setRows(updatedRows);
|
||||
}
|
||||
return Promise.resolve();
|
||||
});
|
||||
|
||||
const setDeleteRowDb = useSetAtom(_deleteRowDbAtom, tableScope);
|
||||
setDeleteRowDb(() => async (path: string) => {
|
||||
const rows = await readRowsDb();
|
||||
const index = findIndex(rows, ["_rowy_ref.path", path]);
|
||||
if (index > -1) {
|
||||
setRows(rows.filter((_, idx) => idx !== index));
|
||||
}
|
||||
return Promise.resolve();
|
||||
});
|
||||
|
||||
const setNextPageAtom = useSetAtom(tableNextPageAtom, tableScope);
|
||||
setNextPageAtom({ loading: false, available: false });
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
export default TableSourcePreview;
|
||||
@@ -60,7 +60,7 @@ export const useFormula = ({
|
||||
|
||||
worker.postMessage({
|
||||
formulaFn,
|
||||
row: availableFields,
|
||||
row: JSON.stringify(availableFields),
|
||||
});
|
||||
|
||||
return () => {
|
||||
|
||||
@@ -8,7 +8,7 @@ onmessage = async ({ data }) => {
|
||||
"row",
|
||||
`const fn = async () => \n${fnBody}\n return fn();`
|
||||
);
|
||||
const result = await fn(row);
|
||||
const result = await fn(JSON.parse(row));
|
||||
postMessage({ result });
|
||||
} catch (error: any) {
|
||||
console.error("Error: ", error);
|
||||
|
||||
Reference in New Issue
Block a user