From 429a4c44a5ed7e0b7d4f6a1d3ccc87d4dd2b4d7e Mon Sep 17 00:00:00 2001 From: Anish Roy <6275anishroy@gmail.com> Date: Mon, 30 Oct 2023 13:12:21 +0530 Subject: [PATCH 1/8] fixed - JSON field update issue --- src/atoms/tableScope/rowActions.ts | 9 ++++++- src/hooks/useFirestoreCollectionWithAtom.ts | 29 ++++++++++++++------- src/types/table.d.ts | 6 ++++- 3 files changed, 33 insertions(+), 11 deletions(-) diff --git a/src/atoms/tableScope/rowActions.ts b/src/atoms/tableScope/rowActions.ts index 4185fa24..2a98fe9d 100644 --- a/src/atoms/tableScope/rowActions.ts +++ b/src/atoms/tableScope/rowActions.ts @@ -146,7 +146,14 @@ export const addRowAtom = atom( // Write to database if no required fields are missing else { - await updateRowDb(row._rowy_ref.path, omitRowyFields(rowValues)); + await updateRowDb( + row._rowy_ref.path, + omitRowyFields(rowValues), + undefined, + { + useSet: true, + } + ); } if (auditChange) auditChange("ADD_ROW", row._rowy_ref.path); diff --git a/src/hooks/useFirestoreCollectionWithAtom.ts b/src/hooks/useFirestoreCollectionWithAtom.ts index 16a7fb92..bbd638b7 100644 --- a/src/hooks/useFirestoreCollectionWithAtom.ts +++ b/src/hooks/useFirestoreCollectionWithAtom.ts @@ -1,7 +1,7 @@ import { useState, useEffect } from "react"; import useMemoValue from "use-memo-value"; import { useAtom, PrimitiveAtom, useSetAtom, SetStateAction } from "jotai"; -import { set } from "lodash-es"; +import { set, update } from "lodash-es"; import { Firestore, query, @@ -16,6 +16,7 @@ import { setDoc, doc, deleteDoc, + updateDoc, deleteField, CollectionReference, Query, @@ -35,6 +36,7 @@ import { TableFilter, TableSort, TableRow, + UpdateRowOptions, } from "@src/types/table"; import { firebaseDbAtom } from "@src/sources/ProjectSourceFirebase"; import { COLLECTION_PAGE_SIZE } from "@src/config/db"; @@ -255,17 +257,26 @@ export function useFirestoreCollectionWithAtom< // set the atom’s value to a function that updates a doc in the collection if (updateDocAtom) { setUpdateDocAtom( - () => (path: string, update: T, deleteFields?: string[]) => { - const updateToDb = { ...update }; + () => + ( + path: string, + update: T, + deleteFields?: string[], + options?: UpdateRowOptions + ) => { + const updateToDb = { ...update }; - if (Array.isArray(deleteFields)) { - for (const field of deleteFields) { - set(updateToDb as any, field, deleteField()); + if (Array.isArray(deleteFields)) { + for (const field of deleteFields) { + set(updateToDb as any, field, deleteField()); + } } + // console.log("update", updateToDb, path, options); + if (options?.useSet) { + return setDoc(doc(firebaseDb, path), updateToDb, { merge: true }); + } + return updateDoc(doc(firebaseDb, path), updateToDb); } - - return setDoc(doc(firebaseDb, path), updateToDb, { merge: true }); - } ); } diff --git a/src/types/table.d.ts b/src/types/table.d.ts index 3ed4b7c3..c294e054 100644 --- a/src/types/table.d.ts +++ b/src/types/table.d.ts @@ -32,7 +32,7 @@ export type UpdateCollectionDocFunction = ( path: string, update: Partial, deleteFields?: string[], - options?: ArrayTableRowData + options?: ArrayTableRowData & UpdateRowOptions ) => Promise; /** @@ -211,6 +211,10 @@ export type TableSort = { direction: Parameters[1]; }; +export type UpdateRowOptions = { + useSet?: boolean; +}; + export type ArrayTableRowData = { index?: number; parentField?: string; From 3a15b57fbaf9d6df08810b6dc3e0e9126b06de02 Mon Sep 17 00:00:00 2001 From: Anish Roy <6275anishroy@gmail.com> Date: Mon, 30 Oct 2023 22:19:34 +0530 Subject: [PATCH 2/8] using set by default instead of update --- src/atoms/tableScope/rowActions.ts | 12 ++++++------ src/components/SideDrawer/MemoizedField.tsx | 17 ++++++++++++----- src/components/SideDrawer/SideDrawerFields.tsx | 4 +++- .../Table/TableCell/EditorCellController.tsx | 4 +++- src/components/fields/Json/SideDrawerField.tsx | 10 ++++++++-- src/components/fields/types.ts | 10 ++++++++-- src/hooks/useFirestoreCollectionWithAtom.ts | 7 +++---- src/types/table.d.ts | 2 +- 8 files changed, 44 insertions(+), 22 deletions(-) diff --git a/src/atoms/tableScope/rowActions.ts b/src/atoms/tableScope/rowActions.ts index 2a98fe9d..df60ec0a 100644 --- a/src/atoms/tableScope/rowActions.ts +++ b/src/atoms/tableScope/rowActions.ts @@ -149,10 +149,7 @@ export const addRowAtom = atom( await updateRowDb( row._rowy_ref.path, omitRowyFields(rowValues), - undefined, - { - useSet: true, - } + undefined ); } @@ -344,6 +341,8 @@ export interface IUpdateFieldOptions { useArrayRemove?: boolean; /** Optionally, used to locate the row in ArraySubTable. */ arrayTableData?: ArrayTableRowData; + /** Optionally, explicitly specify to use firestore's update method. Required in case of JSON field update. */ + useUpdate?: boolean; } /** * Set function updates or deletes a field in a row. @@ -372,6 +371,7 @@ export const updateFieldAtom = atom( useArrayUnion, useArrayRemove, arrayTableData, + useUpdate, }: IUpdateFieldOptions ) => { const updateRowDb = get(_updateRowDbAtom); @@ -493,7 +493,7 @@ export const updateFieldAtom = atom( row._rowy_ref.path, omitRowyFields(newRowValues), deleteField ? [fieldName] : [], - arrayTableData + { ...arrayTableData, useUpdate } ); } } @@ -503,7 +503,7 @@ export const updateFieldAtom = atom( row._rowy_ref.path, omitRowyFields(dbUpdate), deleteField ? [fieldName] : [], - arrayTableData + { ...arrayTableData, useUpdate } ); } diff --git a/src/components/SideDrawer/MemoizedField.tsx b/src/components/SideDrawer/MemoizedField.tsx index ebf97b1c..641895e0 100644 --- a/src/components/SideDrawer/MemoizedField.tsx +++ b/src/components/SideDrawer/MemoizedField.tsx @@ -3,7 +3,11 @@ import useStateRef from "react-usestateref"; import { isEqual, isEmpty } from "lodash-es"; import FieldWrapper from "./FieldWrapper"; -import { FieldType, IFieldConfig } from "@src/components/fields/types"; +import { + FieldType, + IFieldConfig, + onSubmitOptions, +} from "@src/components/fields/types"; import { getFieldProp } from "@src/components/fields"; import { ColumnConfig, TableRowRef } from "@src/types/table"; import { TableRow } from "@src/types/table"; @@ -16,7 +20,7 @@ export interface IMemoizedFieldProps { _rowy_ref: TableRowRef; isDirty: boolean; onDirty: (fieldName: string) => void; - onSubmit: (fieldName: string, value: any) => void; + onSubmit: (fieldName: string, value: any, options?: onSubmitOptions) => void; row: TableRow; } @@ -39,9 +43,12 @@ export const MemoizedField = memo( if (!isDirty) setLocalValue(value); }, [isDirty, setLocalValue, value]); - const handleSubmit = useCallback(() => { - onSubmit(field.fieldName, localValueRef.current); - }, [field.fieldName, localValueRef, onSubmit]); + const handleSubmit = useCallback( + (options?: onSubmitOptions) => { + onSubmit(field.fieldName, localValueRef.current, options); + }, + [field.fieldName, localValueRef, onSubmit] + ); let type = field.type; if (field.type !== FieldType.formula && field.config?.renderFieldType) { diff --git a/src/components/SideDrawer/SideDrawerFields.tsx b/src/components/SideDrawer/SideDrawerFields.tsx index f2ce5964..f78047b3 100644 --- a/src/components/SideDrawer/SideDrawerFields.tsx +++ b/src/components/SideDrawer/SideDrawerFields.tsx @@ -24,6 +24,7 @@ import { } from "@src/atoms/tableScope"; import { formatSubTableName } from "@src/utils/table"; import { TableRow } from "@src/types/table"; +import { onSubmitOptions } from "@src/components/fields/types"; export interface ISideDrawerFieldsProps { row: TableRow; @@ -54,7 +55,7 @@ export default function SideDrawerFields({ row }: ISideDrawerFieldsProps) { }, []); // Called when an individual field is ready to be saved const onSubmit = useCallback( - async (fieldName: string, value: any) => { + async (fieldName: string, value: any, options?: onSubmitOptions) => { if (!selectedCell) return; const currentValue = get(row, fieldName); @@ -74,6 +75,7 @@ export default function SideDrawerFields({ row }: ISideDrawerFieldsProps) { arrayTableData: { index: selectedCell.arrayIndex, }, + useUpdate: options?.useUpdateFn ?? false, }); setSaveState("saved"); diff --git a/src/components/Table/TableCell/EditorCellController.tsx b/src/components/Table/TableCell/EditorCellController.tsx index 217c40eb..68e95996 100644 --- a/src/components/Table/TableCell/EditorCellController.tsx +++ b/src/components/Table/TableCell/EditorCellController.tsx @@ -8,6 +8,7 @@ import { tableScope, updateFieldAtom } from "@src/atoms/tableScope"; import type { IDisplayCellProps, IEditorCellProps, + onSubmitOptions, } from "@src/components/fields/types"; interface IEditorCellControllerProps extends IDisplayCellProps { @@ -56,7 +57,7 @@ export default function EditorCellController({ }, [isDirty, localValueRef, setLocalValue, value]); // This is where we update the documents - const handleSubmit = async () => { + const handleSubmit = async (options?: onSubmitOptions) => { // props.disabled should always be false as withRenderTableCell would // render DisplayCell instead of EditorCell if (props.disabled || !isDirtyRef.current) return; @@ -67,6 +68,7 @@ export default function EditorCellController({ value: localValueRef.current, deleteField: localValueRef.current === undefined, arrayTableData: props.row?._rowy_ref.arrayTableData, + useUpdate: options?.useUpdateFn, }); } catch (e) { enqueueSnackbar((e as Error).message, { variant: "error" }); diff --git a/src/components/fields/Json/SideDrawerField.tsx b/src/components/fields/Json/SideDrawerField.tsx index 03a451c6..bd2e8cb8 100644 --- a/src/components/fields/Json/SideDrawerField.tsx +++ b/src/components/fields/Json/SideDrawerField.tsx @@ -68,7 +68,9 @@ export default function Json({ const handleEdit = (edit: InteractionProps) => { onChange(edit.updated_src); - onSubmit(); + onSubmit({ + useUpdateFn: true, + }); }; return ( @@ -133,7 +135,11 @@ export default function Json({ }} onValidStatusUpdate={({ isValid }) => setCodeValid(isValid)} error={!codeValid} - onBlur={onSubmit} + onBlur={() => + onSubmit({ + useUpdateFn: true, + }) + } fullScreenTitle={ <> {config.icon} diff --git a/src/components/fields/types.ts b/src/components/fields/types.ts index d69a7be7..606382ce 100644 --- a/src/components/fields/types.ts +++ b/src/components/fields/types.ts @@ -75,6 +75,13 @@ export interface IEditorCellProps extends IDisplayCellProps { parentRef: PopoverProps["anchorEl"]; } +export type onSubmitOptions = { + /** Use the update function instead of the set function */ + useUpdateFn?: boolean; +}; + +export type onSubmitFunction = (options?: onSubmitOptions) => void; + /** Props to be passed to all SideDrawerFields */ export interface ISideDrawerFieldProps { /** The column config */ @@ -88,8 +95,7 @@ export interface ISideDrawerFieldProps { /** Update the local value. Also calls onDirty */ onChange: (value: T) => void; /** Call when user input is ready to be saved (e.g. onBlur) */ - onSubmit: () => void; - + onSubmit: onSubmitFunction; /** Field locked. Do NOT check `column.locked` */ disabled: boolean; diff --git a/src/hooks/useFirestoreCollectionWithAtom.ts b/src/hooks/useFirestoreCollectionWithAtom.ts index bbd638b7..9d256896 100644 --- a/src/hooks/useFirestoreCollectionWithAtom.ts +++ b/src/hooks/useFirestoreCollectionWithAtom.ts @@ -271,11 +271,10 @@ export function useFirestoreCollectionWithAtom< set(updateToDb as any, field, deleteField()); } } - // console.log("update", updateToDb, path, options); - if (options?.useSet) { - return setDoc(doc(firebaseDb, path), updateToDb, { merge: true }); + if (options?.useUpdate) { + return updateDoc(doc(firebaseDb, path), updateToDb); } - return updateDoc(doc(firebaseDb, path), updateToDb); + return setDoc(doc(firebaseDb, path), updateToDb, { merge: true }); } ); } diff --git a/src/types/table.d.ts b/src/types/table.d.ts index c294e054..a9b44d66 100644 --- a/src/types/table.d.ts +++ b/src/types/table.d.ts @@ -212,7 +212,7 @@ export type TableSort = { }; export type UpdateRowOptions = { - useSet?: boolean; + useUpdate?: boolean; }; export type ArrayTableRowData = { From 5666ba8fa22d097dc2d76d481052f71db2dbba6b Mon Sep 17 00:00:00 2001 From: Anish Roy <6275anishroy@gmail.com> Date: Mon, 30 Oct 2023 23:04:09 +0530 Subject: [PATCH 3/8] removed useUpdate; using try catch --- src/atoms/tableScope/rowActions.ts | 7 +++---- src/components/SideDrawer/MemoizedField.tsx | 17 +++++------------ src/components/SideDrawer/SideDrawerFields.tsx | 4 +--- .../Table/TableCell/EditorCellController.tsx | 4 +--- src/components/fields/Json/SideDrawerField.tsx | 10 ++-------- src/components/fields/types.ts | 9 +-------- src/hooks/useFirestoreCollectionWithAtom.ts | 11 +++++++---- 7 files changed, 20 insertions(+), 42 deletions(-) diff --git a/src/atoms/tableScope/rowActions.ts b/src/atoms/tableScope/rowActions.ts index df60ec0a..edcb8361 100644 --- a/src/atoms/tableScope/rowActions.ts +++ b/src/atoms/tableScope/rowActions.ts @@ -342,7 +342,7 @@ export interface IUpdateFieldOptions { /** Optionally, used to locate the row in ArraySubTable. */ arrayTableData?: ArrayTableRowData; /** Optionally, explicitly specify to use firestore's update method. Required in case of JSON field update. */ - useUpdate?: boolean; + // useUpdate?: boolean; } /** * Set function updates or deletes a field in a row. @@ -371,7 +371,6 @@ export const updateFieldAtom = atom( useArrayUnion, useArrayRemove, arrayTableData, - useUpdate, }: IUpdateFieldOptions ) => { const updateRowDb = get(_updateRowDbAtom); @@ -493,7 +492,7 @@ export const updateFieldAtom = atom( row._rowy_ref.path, omitRowyFields(newRowValues), deleteField ? [fieldName] : [], - { ...arrayTableData, useUpdate } + arrayTableData ); } } @@ -503,7 +502,7 @@ export const updateFieldAtom = atom( row._rowy_ref.path, omitRowyFields(dbUpdate), deleteField ? [fieldName] : [], - { ...arrayTableData, useUpdate } + arrayTableData ); } diff --git a/src/components/SideDrawer/MemoizedField.tsx b/src/components/SideDrawer/MemoizedField.tsx index 641895e0..ebf97b1c 100644 --- a/src/components/SideDrawer/MemoizedField.tsx +++ b/src/components/SideDrawer/MemoizedField.tsx @@ -3,11 +3,7 @@ import useStateRef from "react-usestateref"; import { isEqual, isEmpty } from "lodash-es"; import FieldWrapper from "./FieldWrapper"; -import { - FieldType, - IFieldConfig, - onSubmitOptions, -} from "@src/components/fields/types"; +import { FieldType, IFieldConfig } from "@src/components/fields/types"; import { getFieldProp } from "@src/components/fields"; import { ColumnConfig, TableRowRef } from "@src/types/table"; import { TableRow } from "@src/types/table"; @@ -20,7 +16,7 @@ export interface IMemoizedFieldProps { _rowy_ref: TableRowRef; isDirty: boolean; onDirty: (fieldName: string) => void; - onSubmit: (fieldName: string, value: any, options?: onSubmitOptions) => void; + onSubmit: (fieldName: string, value: any) => void; row: TableRow; } @@ -43,12 +39,9 @@ export const MemoizedField = memo( if (!isDirty) setLocalValue(value); }, [isDirty, setLocalValue, value]); - const handleSubmit = useCallback( - (options?: onSubmitOptions) => { - onSubmit(field.fieldName, localValueRef.current, options); - }, - [field.fieldName, localValueRef, onSubmit] - ); + const handleSubmit = useCallback(() => { + onSubmit(field.fieldName, localValueRef.current); + }, [field.fieldName, localValueRef, onSubmit]); let type = field.type; if (field.type !== FieldType.formula && field.config?.renderFieldType) { diff --git a/src/components/SideDrawer/SideDrawerFields.tsx b/src/components/SideDrawer/SideDrawerFields.tsx index f78047b3..f2ce5964 100644 --- a/src/components/SideDrawer/SideDrawerFields.tsx +++ b/src/components/SideDrawer/SideDrawerFields.tsx @@ -24,7 +24,6 @@ import { } from "@src/atoms/tableScope"; import { formatSubTableName } from "@src/utils/table"; import { TableRow } from "@src/types/table"; -import { onSubmitOptions } from "@src/components/fields/types"; export interface ISideDrawerFieldsProps { row: TableRow; @@ -55,7 +54,7 @@ export default function SideDrawerFields({ row }: ISideDrawerFieldsProps) { }, []); // Called when an individual field is ready to be saved const onSubmit = useCallback( - async (fieldName: string, value: any, options?: onSubmitOptions) => { + async (fieldName: string, value: any) => { if (!selectedCell) return; const currentValue = get(row, fieldName); @@ -75,7 +74,6 @@ export default function SideDrawerFields({ row }: ISideDrawerFieldsProps) { arrayTableData: { index: selectedCell.arrayIndex, }, - useUpdate: options?.useUpdateFn ?? false, }); setSaveState("saved"); diff --git a/src/components/Table/TableCell/EditorCellController.tsx b/src/components/Table/TableCell/EditorCellController.tsx index 68e95996..217c40eb 100644 --- a/src/components/Table/TableCell/EditorCellController.tsx +++ b/src/components/Table/TableCell/EditorCellController.tsx @@ -8,7 +8,6 @@ import { tableScope, updateFieldAtom } from "@src/atoms/tableScope"; import type { IDisplayCellProps, IEditorCellProps, - onSubmitOptions, } from "@src/components/fields/types"; interface IEditorCellControllerProps extends IDisplayCellProps { @@ -57,7 +56,7 @@ export default function EditorCellController({ }, [isDirty, localValueRef, setLocalValue, value]); // This is where we update the documents - const handleSubmit = async (options?: onSubmitOptions) => { + const handleSubmit = async () => { // props.disabled should always be false as withRenderTableCell would // render DisplayCell instead of EditorCell if (props.disabled || !isDirtyRef.current) return; @@ -68,7 +67,6 @@ export default function EditorCellController({ value: localValueRef.current, deleteField: localValueRef.current === undefined, arrayTableData: props.row?._rowy_ref.arrayTableData, - useUpdate: options?.useUpdateFn, }); } catch (e) { enqueueSnackbar((e as Error).message, { variant: "error" }); diff --git a/src/components/fields/Json/SideDrawerField.tsx b/src/components/fields/Json/SideDrawerField.tsx index bd2e8cb8..03a451c6 100644 --- a/src/components/fields/Json/SideDrawerField.tsx +++ b/src/components/fields/Json/SideDrawerField.tsx @@ -68,9 +68,7 @@ export default function Json({ const handleEdit = (edit: InteractionProps) => { onChange(edit.updated_src); - onSubmit({ - useUpdateFn: true, - }); + onSubmit(); }; return ( @@ -135,11 +133,7 @@ export default function Json({ }} onValidStatusUpdate={({ isValid }) => setCodeValid(isValid)} error={!codeValid} - onBlur={() => - onSubmit({ - useUpdateFn: true, - }) - } + onBlur={onSubmit} fullScreenTitle={ <> {config.icon} diff --git a/src/components/fields/types.ts b/src/components/fields/types.ts index 606382ce..0308112d 100644 --- a/src/components/fields/types.ts +++ b/src/components/fields/types.ts @@ -75,13 +75,6 @@ export interface IEditorCellProps extends IDisplayCellProps { parentRef: PopoverProps["anchorEl"]; } -export type onSubmitOptions = { - /** Use the update function instead of the set function */ - useUpdateFn?: boolean; -}; - -export type onSubmitFunction = (options?: onSubmitOptions) => void; - /** Props to be passed to all SideDrawerFields */ export interface ISideDrawerFieldProps { /** The column config */ @@ -95,7 +88,7 @@ export interface ISideDrawerFieldProps { /** Update the local value. Also calls onDirty */ onChange: (value: T) => void; /** Call when user input is ready to be saved (e.g. onBlur) */ - onSubmit: onSubmitFunction; + onSubmit: () => void; /** Field locked. Do NOT check `column.locked` */ disabled: boolean; diff --git a/src/hooks/useFirestoreCollectionWithAtom.ts b/src/hooks/useFirestoreCollectionWithAtom.ts index 9d256896..dc3520d2 100644 --- a/src/hooks/useFirestoreCollectionWithAtom.ts +++ b/src/hooks/useFirestoreCollectionWithAtom.ts @@ -258,7 +258,7 @@ export function useFirestoreCollectionWithAtom< if (updateDocAtom) { setUpdateDocAtom( () => - ( + async ( path: string, update: T, deleteFields?: string[], @@ -271,10 +271,13 @@ export function useFirestoreCollectionWithAtom< set(updateToDb as any, field, deleteField()); } } - if (options?.useUpdate) { - return updateDoc(doc(firebaseDb, path), updateToDb); + try { + return await updateDoc(doc(firebaseDb, path), updateToDb); + } catch (e) { + return await setDoc(doc(firebaseDb, path), updateToDb, { + merge: true, + }); } - return setDoc(doc(firebaseDb, path), updateToDb, { merge: true }); } ); } From 201c69a3864a5c300c3ea25a438ed9dacb967a3d Mon Sep 17 00:00:00 2001 From: Anish Roy <6275anishroy@gmail.com> Date: Mon, 30 Oct 2023 23:08:37 +0530 Subject: [PATCH 4/8] removed unwanted changes --- src/atoms/tableScope/rowActions.ts | 8 +---- src/components/fields/types.ts | 1 + src/hooks/useFirestoreCollectionWithAtom.ts | 35 +++++++++------------ src/types/table.d.ts | 6 +--- 4 files changed, 17 insertions(+), 33 deletions(-) diff --git a/src/atoms/tableScope/rowActions.ts b/src/atoms/tableScope/rowActions.ts index edcb8361..4185fa24 100644 --- a/src/atoms/tableScope/rowActions.ts +++ b/src/atoms/tableScope/rowActions.ts @@ -146,11 +146,7 @@ export const addRowAtom = atom( // Write to database if no required fields are missing else { - await updateRowDb( - row._rowy_ref.path, - omitRowyFields(rowValues), - undefined - ); + await updateRowDb(row._rowy_ref.path, omitRowyFields(rowValues)); } if (auditChange) auditChange("ADD_ROW", row._rowy_ref.path); @@ -341,8 +337,6 @@ export interface IUpdateFieldOptions { useArrayRemove?: boolean; /** Optionally, used to locate the row in ArraySubTable. */ arrayTableData?: ArrayTableRowData; - /** Optionally, explicitly specify to use firestore's update method. Required in case of JSON field update. */ - // useUpdate?: boolean; } /** * Set function updates or deletes a field in a row. diff --git a/src/components/fields/types.ts b/src/components/fields/types.ts index 0308112d..6fb37ed2 100644 --- a/src/components/fields/types.ts +++ b/src/components/fields/types.ts @@ -88,6 +88,7 @@ export interface ISideDrawerFieldProps { /** Update the local value. Also calls onDirty */ onChange: (value: T) => void; /** Call when user input is ready to be saved (e.g. onBlur) */ + onSubmit: () => void; /** Field locked. Do NOT check `column.locked` */ disabled: boolean; diff --git a/src/hooks/useFirestoreCollectionWithAtom.ts b/src/hooks/useFirestoreCollectionWithAtom.ts index dc3520d2..fd0fa39e 100644 --- a/src/hooks/useFirestoreCollectionWithAtom.ts +++ b/src/hooks/useFirestoreCollectionWithAtom.ts @@ -1,7 +1,7 @@ import { useState, useEffect } from "react"; import useMemoValue from "use-memo-value"; import { useAtom, PrimitiveAtom, useSetAtom, SetStateAction } from "jotai"; -import { set, update } from "lodash-es"; +import { set } from "lodash-es"; import { Firestore, query, @@ -36,7 +36,6 @@ import { TableFilter, TableSort, TableRow, - UpdateRowOptions, } from "@src/types/table"; import { firebaseDbAtom } from "@src/sources/ProjectSourceFirebase"; import { COLLECTION_PAGE_SIZE } from "@src/config/db"; @@ -257,28 +256,22 @@ export function useFirestoreCollectionWithAtom< // set the atom’s value to a function that updates a doc in the collection if (updateDocAtom) { setUpdateDocAtom( - () => - async ( - path: string, - update: T, - deleteFields?: string[], - options?: UpdateRowOptions - ) => { - const updateToDb = { ...update }; + () => async (path: string, update: T, deleteFields?: string[]) => { + const updateToDb = { ...update }; - if (Array.isArray(deleteFields)) { - for (const field of deleteFields) { - set(updateToDb as any, field, deleteField()); - } - } - try { - return await updateDoc(doc(firebaseDb, path), updateToDb); - } catch (e) { - return await setDoc(doc(firebaseDb, path), updateToDb, { - merge: true, - }); + if (Array.isArray(deleteFields)) { + for (const field of deleteFields) { + set(updateToDb as any, field, deleteField()); } } + try { + return await updateDoc(doc(firebaseDb, path), updateToDb); + } catch (e) { + return await setDoc(doc(firebaseDb, path), updateToDb, { + merge: true, + }); + } + } ); } diff --git a/src/types/table.d.ts b/src/types/table.d.ts index a9b44d66..3ed4b7c3 100644 --- a/src/types/table.d.ts +++ b/src/types/table.d.ts @@ -32,7 +32,7 @@ export type UpdateCollectionDocFunction = ( path: string, update: Partial, deleteFields?: string[], - options?: ArrayTableRowData & UpdateRowOptions + options?: ArrayTableRowData ) => Promise; /** @@ -211,10 +211,6 @@ export type TableSort = { direction: Parameters[1]; }; -export type UpdateRowOptions = { - useUpdate?: boolean; -}; - export type ArrayTableRowData = { index?: number; parentField?: string; From bb552a57d22460b671182c74ec0a800b27545ec9 Mon Sep 17 00:00:00 2001 From: janvi01 Date: Wed, 1 Nov 2023 16:17:48 +0530 Subject: [PATCH 5/8] Added confirmation for bulk deletion of rows --- src/components/TableToolbar/TableToolbar.tsx | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/components/TableToolbar/TableToolbar.tsx b/src/components/TableToolbar/TableToolbar.tsx index 77eb8749..2adb90f1 100644 --- a/src/components/TableToolbar/TableToolbar.tsx +++ b/src/components/TableToolbar/TableToolbar.tsx @@ -26,6 +26,8 @@ import { userRolesAtom, compatibleRowyRunVersionAtom, rowyRunModalAtom, + altPressAtom, + confirmDialogAtom, } from "@src/atoms/projectScope"; import { tableScope, @@ -91,6 +93,8 @@ function RowSelectedToolBar({ }) { const [serverDocCount] = useAtom(serverDocCountAtom, tableScope); const deleteRow = useSetAtom(deleteRowAtom, tableScope); + const [altPress] = useAtom(altPressAtom, projectScope); + const confirm = useSetAtom(confirmDialogAtom, projectScope); const handleDelete = async () => { await deleteRow({ path: Object.keys(selectedRows) }); @@ -107,7 +111,20 @@ function RowSelectedToolBar({ variant="outlined" startIcon={} color="error" - onClick={handleDelete} + onClick={ + altPress + ? handleDelete + : () => { + confirm({ + title: `Delete ${ + Object.values(selectedRows).length + } of ${serverDocCount} selected rows?`, + confirm: "Delete", + confirmColor: "error", + handleConfirm: handleDelete, + }); + } + } > Delete From 1d21a4b0732ce630b5d2ee2597d41db2ee4e3002 Mon Sep 17 00:00:00 2001 From: janvi01 Date: Mon, 6 Nov 2023 16:42:31 +0530 Subject: [PATCH 6/8] fix: paste updatation of the highlighted cell --- src/components/Table/useMenuAction.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/Table/useMenuAction.tsx b/src/components/Table/useMenuAction.tsx index 3a1d4599..6fc1b0bd 100644 --- a/src/components/Table/useMenuAction.tsx +++ b/src/components/Table/useMenuAction.tsx @@ -165,6 +165,7 @@ export function useMenuAction( async (e?: ClipboardEvent) => { try { if (!selectedCell || !selectedCol) return; + if (document.activeElement?.role !== "gridcell") return; let text: string; // Firefox doesn't allow for reading clipboard data, hence the workaround if (navigator.userAgent.includes("Firefox")) { From 7e68794afb1aac7df430675b7b53464b5f6fbe09 Mon Sep 17 00:00:00 2001 From: janvi01 Date: Mon, 6 Nov 2023 16:52:07 +0530 Subject: [PATCH 7/8] added comment --- src/components/Table/useMenuAction.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/components/Table/useMenuAction.tsx b/src/components/Table/useMenuAction.tsx index 6fc1b0bd..4cc20277 100644 --- a/src/components/Table/useMenuAction.tsx +++ b/src/components/Table/useMenuAction.tsx @@ -165,7 +165,10 @@ export function useMenuAction( async (e?: ClipboardEvent) => { try { if (!selectedCell || !selectedCol) return; + + // checks which element has focus, if it is not the gridcell it won't paste the copied content inside the gridcell if (document.activeElement?.role !== "gridcell") return; + let text: string; // Firefox doesn't allow for reading clipboard data, hence the workaround if (navigator.userAgent.includes("Firefox")) { From 36163262760733c164816e16b02147f009a3808e Mon Sep 17 00:00:00 2001 From: Anush Deokar Date: Mon, 6 Nov 2023 20:52:38 +0530 Subject: [PATCH 8/8] fix: selection column should be sticky especially when columns are frozen (#1466) * bulk selection bug fix * space lint fix --- src/components/Table/TableBody.tsx | 2 +- src/components/Table/TableHeader.tsx | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/Table/TableBody.tsx b/src/components/Table/TableBody.tsx index 04918f18..1a66a405 100644 --- a/src/components/Table/TableBody.tsx +++ b/src/components/Table/TableBody.tsx @@ -122,7 +122,7 @@ export const TableBody = memo(function TableBody({ if (cell.id.includes("_rowy_select")) { return ( - + {flexRender(cell.column.columnDef.cell, cell.getContext())} ); diff --git a/src/components/Table/TableHeader.tsx b/src/components/Table/TableHeader.tsx index ae763a60..709f8cc0 100644 --- a/src/components/Table/TableHeader.tsx +++ b/src/components/Table/TableHeader.tsx @@ -79,7 +79,8 @@ export const TableHeader = memo(function TableHeader({ {flexRender( header.column.columnDef.header,