diff --git a/src/components/Table/ColumnHeader/useSaveTableSorts.tsx b/src/components/Table/ColumnHeader/useSaveTableSorts.tsx index 8ad053d5..c0c239ed 100644 --- a/src/components/Table/ColumnHeader/useSaveTableSorts.tsx +++ b/src/components/Table/ColumnHeader/useSaveTableSorts.tsx @@ -18,13 +18,13 @@ function useSaveTableSorts(canEditColumns: boolean) { const [updateTableSchema] = useAtom(updateTableSchemaAtom, tableScope); const [updateUserSettings] = useAtom(updateUserSettingsAtom, projectScope); const [tableId] = useAtom(tableIdAtom, tableScope); - if (!updateTableSchema) throw new Error("Cannot update table schema"); const { enqueueSnackbar, closeSnackbar } = useSnackbar(); const [snackbarId, setSnackbarId] = useState(null); // Offer to save when table sorts changes const trigger = useCallback( (sorts: TableSort[]) => { + if (!updateTableSchema) throw new Error("Cannot update table schema"); if (updateUserSettings) { updateUserSettings({ tables: { diff --git a/src/components/fields/Formula/PreviewTable.tsx b/src/components/fields/Formula/PreviewTable.tsx index 8b2107fc..6cf85c22 100644 --- a/src/components/fields/Formula/PreviewTable.tsx +++ b/src/components/fields/Formula/PreviewTable.tsx @@ -23,14 +23,7 @@ const PreviewTable = ({ tableSchema }: { tableSchema: TableSchema }) => { scope={tableScope} initialValues={[ [currentUserAtom, currentUser], - [ - tableSettingsAtom, - { - ...tableSettings, - id: "preview-table", - collection: "preview-collection", - }, - ], + [tableSettingsAtom, tableSettings], [tableRowsDbAtom, []], ]} > diff --git a/src/components/fields/Formula/TableSourcePreview.ts b/src/components/fields/Formula/TableSourcePreview.ts index c4536c01..07712f87 100644 --- a/src/components/fields/Formula/TableSourcePreview.ts +++ b/src/components/fields/Formula/TableSourcePreview.ts @@ -1,5 +1,5 @@ import { useCallback, useEffect } from "react"; -import { useSetAtom } from "jotai"; +import { useAtom, useSetAtom } from "jotai"; import { useAtomCallback } from "jotai/utils"; import { cloneDeep, findIndex, sortBy } from "lodash-es"; @@ -10,39 +10,24 @@ import { tableRowsDbAtom, tableSchemaAtom, tableScope, + tableSettingsAtom, } 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", - }, - }, -]; +import { serializeRef } from "./util"; const TableSourcePreview = ({ tableSchema }: { tableSchema: TableSchema }) => { + const [tableSettings] = useAtom(tableSettingsAtom, tableScope); const setTableSchemaAtom = useSetAtom(tableSchemaAtom, tableScope); const setRows = useSetAtom(tableRowsDbAtom, tableScope); - useEffect(() => { - setRows(initialRows); - }, [setRows]); + setRows( + ["preview-doc-1", "preview-doc-2", "preview-doc-3"].map((docId) => ({ + _rowy_ref: serializeRef(`${tableSettings.collection}/${docId}`), + })) + ); + }, [setRows, tableSettings.collection]); useEffect(() => { setTableSchemaAtom(() => ({ @@ -52,7 +37,7 @@ const TableSourcePreview = ({ tableSchema }: { tableSchema: TableSchema }) => { }, [tableSchema, setTableSchemaAtom]); const readRowsDb = useAtomCallback( - useCallback((get) => get(tableRowsDbAtom) || initialRows, []), + useCallback((get) => get(tableRowsDbAtom) || [], []), tableScope ); diff --git a/src/components/fields/Formula/formula.d.ts b/src/components/fields/Formula/formula.d.ts index 69fcde0d..8c6210c8 100644 --- a/src/components/fields/Formula/formula.d.ts +++ b/src/components/fields/Formula/formula.d.ts @@ -1,10 +1,9 @@ -type RowRef = Pick; +type RowRef = { id: string; path: string; parent: T }; +interface Ref extends RowRef {} type FormulaContext = { row: Row; - ref: RowRef; - // storage: firebasestorage.Storage; - // db: FirebaseFirestore.Firestore; + ref: Ref; }; type Formula = (context: FormulaContext) => "PLACEHOLDER_OUTPUT_TYPE"; diff --git a/src/components/fields/Formula/useFormula.tsx b/src/components/fields/Formula/useFormula.tsx index 64d0fa6a..f6c44b75 100644 --- a/src/components/fields/Formula/useFormula.tsx +++ b/src/components/fields/Formula/useFormula.tsx @@ -5,7 +5,11 @@ import { useAtom } from "jotai"; import { TableRow, TableRowRef } from "@src/types/table"; import { tableColumnsOrderedAtom, tableScope } from "@src/atoms/tableScope"; -import { listenerFieldTypes, useDeepCompareMemoize } from "./util"; +import { + listenerFieldTypes, + serializeRef, + useDeepCompareMemoize, +} from "./util"; export const useFormula = ({ row, @@ -60,11 +64,13 @@ export const useFormula = ({ setLoading(false); }; - worker.postMessage({ - formulaFn, - row: JSON.stringify(availableFields), - ref: { id: ref.id, path: ref.path }, - }); + worker.postMessage( + JSON.stringify({ + formulaFn, + row: availableFields, + ref: serializeRef(ref.path), + }) + ); return () => { worker.terminate(); diff --git a/src/components/fields/Formula/util.tsx b/src/components/fields/Formula/util.tsx index 46d8cbee..71973a2e 100644 --- a/src/components/fields/Formula/util.tsx +++ b/src/components/fields/Formula/util.tsx @@ -24,6 +24,8 @@ import JsonDisplayCell from "@src/components/fields/Json/DisplayCell"; import CodeDisplayCell from "@src/components/fields/Code/DisplayCell"; import MarkdownDisplayCell from "@src/components/fields/Markdown/DisplayCell"; import CreatedByDisplayCell from "@src/components/fields/CreatedBy/DisplayCell"; +import { TableRowRef } from "@src/types/table"; +import { DocumentData, DocumentReference } from "firebase/firestore"; export function useDeepCompareMemoize(value: T) { const ref = useRef(value); @@ -65,7 +67,7 @@ export const outputFieldTypes = Object.values(FieldType).filter( ].includes(type) ); -export const defaultFn = `const formula:Formula = async ({ row })=> { +export const defaultFn = `const formula:Formula = async ({ row, ref })=> { // WRITE YOUR CODE ONLY BELOW THIS LINE. DO NOT WRITE CODE/COMMENTS OUTSIDE THE FUNCTION BODY // Example: @@ -120,3 +122,23 @@ export const getDisplayCell = (type: FieldType) => { return ShortTextDisplayCell; } }; + +export const serializeRef = (path: string, maxDepth = 20) => { + const pathArr = path.split("/"); + const serializedRef = { + path: pathArr.join("/"), + id: pathArr.pop(), + } as any; + let curr: TableRowRef | Partial> = + serializedRef; + let depth = 0; + while (pathArr.length > 0 && curr && depth < maxDepth) { + (curr.parent as any) = { + path: pathArr.join("/"), + id: pathArr.pop(), + } as Partial>; + curr = curr.parent as any; + maxDepth++; + } + return serializedRef; +}; diff --git a/src/components/fields/Formula/worker.ts b/src/components/fields/Formula/worker.ts index a0d85fd3..2b0af366 100644 --- a/src/components/fields/Formula/worker.ts +++ b/src/components/fields/Formula/worker.ts @@ -1,6 +1,6 @@ onmessage = async ({ data }) => { try { - const { formulaFn, row, ref } = data; + const { formulaFn, row, ref } = JSON.parse(data); const AsyncFunction = async function () {}.constructor as any; const [_, fnBody] = formulaFn.match(/=>\s*({?[\s\S]*}?)$/); if (!fnBody) return; @@ -9,7 +9,7 @@ onmessage = async ({ data }) => { "ref", `const fn = async () => \n${fnBody}\n return fn();` ); - const result = await fn(JSON.parse(row), ref); + const result = await fn(row, ref); postMessage({ result }); } catch (error: any) { console.error("Error: ", error);