From 720b0c20e7e25be5837d1fcf158b1f5d067b6a0f Mon Sep 17 00:00:00 2001 From: ghazi Date: Thu, 11 Dec 2025 08:52:26 +0100 Subject: [PATCH] track selected objects rather than their IDs This simplifies a little the code. It also ensures we always pass the right datatypes for each key field (in case the user changes the datatype after selecting a row). This is also in preparation for introducing bulk objects update (it will rely on the `tableMutationStore.selectedObjects`) --- .../object-store-view/DeleteObjectsButton.tsx | 41 ++++++------------- .../main-content/object-store-view/Table.tsx | 19 +++------ .../object-store-view/TableStateWrapper.tsx | 6 ++- .../table-mutation-context.tsx | 23 ++++------- src/devtools/utils/grid-options.ts | 21 +--------- 5 files changed, 33 insertions(+), 77 deletions(-) diff --git a/src/devtools/components/main-content/object-store-view/DeleteObjectsButton.tsx b/src/devtools/components/main-content/object-store-view/DeleteObjectsButton.tsx index d701da9..2ff9989 100644 --- a/src/devtools/components/main-content/object-store-view/DeleteObjectsButton.tsx +++ b/src/devtools/components/main-content/object-store-view/DeleteObjectsButton.tsx @@ -1,29 +1,25 @@ import { createMemo, Match, Show, Switch } from "solid-js"; import UnstyledButton from "@/devtools/components/buttons/UnstyledButton"; -import { - SelectedObjectID, - useTableMutationContext, -} from "@/devtools/components/main-content/object-store-view/table-mutation-context"; +import { useTableMutationContext } from "@/devtools/components/main-content/object-store-view/table-mutation-context"; import CloseIcon from "@/devtools/components/svg-icons/CloseIcon"; import DeleteIcon from "@/devtools/components/svg-icons/DeleteIcon"; import LoadingIcon from "@/devtools/components/svg-icons/LoadingIcon"; +import { getIndexedDBKey } from "@/devtools/utils/grid-options"; import { DATA_MUTATION_ERROR_MSG, generateRequestID, } from "@/devtools/utils/inspected-window-helpers"; -import { ActiveObjectStore, DataValue } from "@/devtools/utils/types"; +import { ActiveObjectStore, TableColumn } from "@/devtools/utils/types"; import styles from "./DeleteObjectsButton.module.css"; -export default function DeleteObjectsButton(props: { - activeStore: ActiveObjectStore; -}) { +export default function DeleteObjectsButton(props: DeleteObjectsButtonProps) { const { tableMutationStore, setErrorMsg, deleteOperation, deleteData } = useTableMutationContext(); - const canDelete = () => tableMutationStore.selectedObjectIDs.length > 0; + const canDelete = () => tableMutationStore.selectedObjects.length > 0; const deletionMsg = () => { - const count = tableMutationStore.selectedObjectIDs.length; + const count = tableMutationStore.selectedObjects.length; if (count === 1) { return "Are you sure you want to delete the selected object?"; } else if (count > 1) { @@ -34,7 +30,9 @@ export default function DeleteObjectsButton(props: { }; const validObjectKeys = createMemo(() => { try { - return getObjectKeys(tableMutationStore.selectedObjectIDs); + return tableMutationStore.selectedObjects.map((obj) => + getIndexedDBKey(props.keypath, props.columns, obj), + ); } catch { return []; } @@ -111,21 +109,8 @@ export default function DeleteObjectsButton(props: { ); } -function getObjectKeys(objectIDs: SelectedObjectID[]) { - return objectIDs.map((objectID) => { - return objectID.map((cell) => { - if ( - cell.datatype !== "string" && - cell.datatype !== "number" && - cell.datatype !== "timestamp" && - cell.datatype !== "json_data" && - cell.datatype !== "date" - ) { - throw new Error("Invalid key column datatype"); - } - if (cell.value == null) throw new Error("Invalid key column value"); - - return { datatype: cell.datatype, value: cell.value } as DataValue; - }); - }); +interface DeleteObjectsButtonProps { + activeStore: ActiveObjectStore; + keypath: string[]; + columns: TableColumn[]; } diff --git a/src/devtools/components/main-content/object-store-view/Table.tsx b/src/devtools/components/main-content/object-store-view/Table.tsx index 26db2e5..b750463 100644 --- a/src/devtools/components/main-content/object-store-view/Table.tsx +++ b/src/devtools/components/main-content/object-store-view/Table.tsx @@ -40,7 +40,6 @@ import { getUnsupportedColdef } from "@/devtools/utils/coldef-unsupported"; import { convertGetterValueToRowDataValue, getIndexedDBKey, - getSelectedObjectID, parseBooleanNull, updateRowData, } from "@/devtools/utils/grid-options"; @@ -64,7 +63,7 @@ export default function Table(props: TableProps) { const { setErrorMsg, - setSelectedObjectIDs, + setSelectedObjects, updateOperation, updateField, deleteOperation, @@ -178,10 +177,7 @@ export default function Table(props: TableProps) { }, onSelectionChanged(params: SelectionChangedEvent) { const nodes = params.selectedNodes || []; - const selectedObjectIDs = nodes.map((node) => { - return getSelectedObjectID(node, props.keypath, props.columns); - }); - setSelectedObjectIDs(selectedObjectIDs); + setSelectedObjects(nodes.map((node) => node.data)); }, readOnlyEdit: true, onCellEditRequest: async (params: CellEditRequestEvent) => { @@ -263,13 +259,10 @@ export default function Table(props: TableProps) { // delete the rows from the table on deletion success in indexedDB if (deleteOperation.isSuccess) { untrack(() => { - const rows = tableMutationStore.selectedObjectIDs.map((row) => { - return Object.fromEntries( - row.map(({ name, value }) => [name, value]), - ); + gridApi.applyTransaction({ + remove: tableMutationStore.selectedObjects, }); - gridApi.applyTransaction({ remove: rows }); - setSelectedObjectIDs([]); + setSelectedObjects([]); resetDeleteOperation(); }); } @@ -286,7 +279,7 @@ export default function Table(props: TableProps) { }); batch(() => { // reset selected rows and error msg on table reload - setSelectedObjectIDs([]); + setSelectedObjects([]); setErrorMsg(null); }); }); diff --git a/src/devtools/components/main-content/object-store-view/TableStateWrapper.tsx b/src/devtools/components/main-content/object-store-view/TableStateWrapper.tsx index 8fa0eb3..d952d08 100644 --- a/src/devtools/components/main-content/object-store-view/TableStateWrapper.tsx +++ b/src/devtools/components/main-content/object-store-view/TableStateWrapper.tsx @@ -27,7 +27,11 @@ export default function TableStateWrapper() { - + diff --git a/src/devtools/components/main-content/object-store-view/table-mutation-context.tsx b/src/devtools/components/main-content/object-store-view/table-mutation-context.tsx index 8591032..610e032 100644 --- a/src/devtools/components/main-content/object-store-view/table-mutation-context.tsx +++ b/src/devtools/components/main-content/object-store-view/table-mutation-context.tsx @@ -14,8 +14,7 @@ import { DataCreationRequest, DataDeletionRequest, DataUpdateRequest, - TableColumnDatatype, - TableColumnValue, + TableRow, } from "@/devtools/utils/types"; const TableMutationContext = createContext(); @@ -35,12 +34,12 @@ export function TableMutationContextProvider(props: FlowProps) { const [tableMutationStore, setTableMutationStore] = createStore({ errorMsg: null, - selectedObjectIDs: [], + selectedObjects: [], }); const setErrorMsg = (msg: string | null) => setTableMutationStore("errorMsg", msg); - const setSelectedObjectIDs = (selectedObjectIDs: SelectedObjectID[]) => { - setTableMutationStore("selectedObjectIDs", selectedObjectIDs); + const setSelectedObjects = (selectedObjects: TableRow[]) => { + setTableMutationStore("selectedObjects", selectedObjects); }; const { mutation: updateOperation, mutate: updateField } = @@ -78,7 +77,7 @@ export function TableMutationContextProvider(props: FlowProps) { const { activeObjectStore } = useActiveObjectStoreContext(); createEffect(() => { activeObjectStore(); - setTableMutationStore({ errorMsg: null, selectedObjectIDs: [] }); + setTableMutationStore({ errorMsg: null, selectedObjects: [] }); }); return ( @@ -86,7 +85,7 @@ export function TableMutationContextProvider(props: FlowProps) { value={{ tableMutationStore, setErrorMsg, - setSelectedObjectIDs, + setSelectedObjects, updateOperation, updateField, deleteOperation, @@ -105,7 +104,7 @@ export function TableMutationContextProvider(props: FlowProps) { interface TableMutationContextType { tableMutationStore: TableMutationStore; setErrorMsg: (msg: string | null) => void; - setSelectedObjectIDs: (selectedObjectIDs: SelectedObjectID[]) => void; + setSelectedObjects: (selectedObjects: TableRow[]) => void; updateOperation: Mutation; updateField: (params: DataUpdateRequest) => Promise; deleteOperation: Mutation; @@ -118,11 +117,5 @@ interface TableMutationContextType { interface TableMutationStore { errorMsg: string | null; - selectedObjectIDs: SelectedObjectID[]; + selectedObjects: TableRow[]; } - -export type SelectedObjectID = { - name: string; - datatype: TableColumnDatatype; - value: TableColumnValue; -}[]; diff --git a/src/devtools/utils/grid-options.ts b/src/devtools/utils/grid-options.ts index 2739653..c8dd099 100644 --- a/src/devtools/utils/grid-options.ts +++ b/src/devtools/utils/grid-options.ts @@ -1,6 +1,5 @@ -import { GridApi, IRowNode } from "ag-grid-community"; +import { GridApi } from "ag-grid-community"; -import { SelectedObjectID } from "@/devtools/components/main-content/object-store-view/table-mutation-context"; import { DataValue, TableColumn, @@ -97,21 +96,3 @@ export function convertGetterValueToRowDataValue( return value; } } - -export function getSelectedObjectID( - node: IRowNode, - keypath: string[], - columns: TableColumn[], -): SelectedObjectID { - const objectID = JSON.parse(node.id!) as TableColumnValue[]; - - return objectID.map((value, index) => { - const colName = keypath[index]; - const column = columns.find((col) => col.name === colName); - return { - value, - name: colName, - datatype: column!.datatype, - }; - }); -}