Skip to content

Commit fd37709

Browse files
committed
Allow bulk updating the selected objects from the table.
When the user selects one or more rows, the "Add objects" button becomes an "Edit Objects" button, allowing the user to buld update the selected rows
1 parent f6893e8 commit fd37709

File tree

4 files changed

+52
-31
lines changed

4 files changed

+52
-31
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/).
55

66
## [Unreleased]
77

8+
### Added
9+
10+
- Allow bulk updating the selected objects from the table.
11+
812
## [1.1.2] - 2025-12-10
913

1014
### Fixed

src/devtools/components/main-content/object-store-view/AddObjectsButton.tsx

Lines changed: 41 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
import { Schema, ValidationError, Validator } from "jsonschema";
22
import { PrismEditor } from "prism-code-editor";
3-
import { createEffect, createSignal, onMount, Show, untrack } from "solid-js";
3+
import {
4+
createEffect,
5+
createMemo,
6+
createSignal,
7+
onMount,
8+
Show,
9+
untrack,
10+
} from "solid-js";
411

512
import UnstyledButton from "@/devtools/components/buttons/UnstyledButton";
613
import DatatypeValidationCheckbox from "@/devtools/components/main-content/object-store-view/DatatypeValidationCheckbox";
@@ -17,7 +24,7 @@ import {
1724
parseJSONFromUser,
1825
} from "@/devtools/utils/json-editor";
1926
import {
20-
NewObject,
27+
SerializedObject,
2128
TableColumn,
2229
TableColumnValue,
2330
TableRow,
@@ -26,14 +33,20 @@ import {
2633
import styles from "./AddObjectsButton.module.css";
2734

2835
export default function AddObjectsButton() {
29-
const { createData } = useTableMutationContext();
36+
const { tableMutationStore, createData } = useTableMutationContext();
3037
const { query, refetch } = useTableContext();
3138
const [validateDatatypes, setValidateDatatypes] = createSignal(true);
3239
const [error, setError] = createSignal<string[]>([]);
3340
let dialogRef!: HTMLDialogElement;
3441
let editorRef!: HTMLDivElement;
3542
let editor: PrismEditor;
3643

44+
const title = () => {
45+
return tableMutationStore.selectedObjects.length > 0
46+
? "Edit Object(s)"
47+
: "Add Objects";
48+
};
49+
3750
const onSaveClick = async () => {
3851
setError([]);
3952
const value = editor.value.trim();
@@ -53,7 +66,7 @@ export default function AddObjectsButton() {
5366
}
5467

5568
if (!query.data?.columns?.length) {
56-
const msg = `Unable to add any object due to inability to determine the object store key.`;
69+
const msg = `Unable to save any object due to inability to determine the object store key.`;
5770
setError([msg]);
5871
return;
5972
}
@@ -69,7 +82,7 @@ export default function AddObjectsButton() {
6982
return;
7083
}
7184

72-
const newObjects = getNewObjects(parsedObj as TableRow[], cols);
85+
const newObjects = serializeObjects(parsedObj as TableRow[], cols);
7386
try {
7487
await createData({
7588
requestID: generateRequestID(),
@@ -79,58 +92,62 @@ export default function AddObjectsButton() {
7992
});
8093
refetch();
8194
dialogRef.close();
82-
editor.setOptions({ value: getSampleValue(cols) });
95+
editor.setOptions({ value: editorData() });
8396
} catch (e) {
8497
const msg = e instanceof Error ? e.message : DATA_MUTATION_ERROR_MSG;
8598
setError([msg]);
8699
}
87100
};
88101

89102
onMount(() => {
90-
editor = createJSONEditor(
91-
editorRef,
92-
getSampleValue(query.data?.columns || []),
93-
);
103+
editor = createJSONEditor(editorRef, "");
94104
});
95-
createEffect(() => {
105+
const editorData = createMemo(() => {
96106
const activeStore = query.data?.activeStore;
97-
if (activeStore) {
98-
const columns = untrack(() => query.data?.columns || []);
99-
editor.setOptions({ value: getSampleValue(columns) });
107+
if (tableMutationStore.selectedObjects.length > 0) {
108+
return JSON.stringify(tableMutationStore.selectedObjects, null, 2);
100109
} else {
101-
editor.setOptions({ value: "" });
110+
if (activeStore) {
111+
const columns = untrack(() => query.data?.columns || []);
112+
return getSampleValue(columns);
113+
} else {
114+
return "";
115+
}
102116
}
103117
});
118+
createEffect(() => {
119+
editor.setOptions({ value: editorData() });
120+
});
104121

105122
return (
106123
<>
107124
<UnstyledButton
108125
class={styles["dialog-trigger"]}
109126
command="show-modal"
110-
commandfor="add-objects-modal"
127+
commandfor="add-edit-objects-modal"
111128
>
112-
Add Objects
129+
{title()}
113130
</UnstyledButton>
114131
<dialog
115132
ref={dialogRef}
116-
id="add-objects-modal"
133+
id="add-edit-objects-modal"
117134
class={styles.dialog}
118135
onClose={() => setError([])}
119136
>
120137
<header>
121-
<h2>Add Objects</h2>
138+
<h2>{title()}</h2>
122139
<UnstyledButton
123140
title="Close Modal"
124141
aria-label="Close Modal"
125142
command="close"
126-
commandfor="add-objects-modal"
143+
commandfor="add-edit-objects-modal"
127144
>
128145
<CloseIcon />
129146
</UnstyledButton>
130147
</header>
131148
<div ref={editorRef} />
132149
<div class={styles.hint}>
133-
<div>The json value entered must be an array of objects.</div>
150+
<div>The JSON value entered must be an array of objects.</div>
134151
<div>
135152
Use ctrl+M/ctrl+shift+M(Mac) to toggle the use of Tab for
136153
indentation.
@@ -150,7 +167,7 @@ export default function AddObjectsButton() {
150167
/>
151168
</Show>
152169
<footer>
153-
<UnstyledButton command="close" commandfor="add-objects-modal">
170+
<UnstyledButton command="close" commandfor="add-edit-objects-modal">
154171
Cancel
155172
</UnstyledButton>
156173
<UnstyledButton
@@ -238,10 +255,10 @@ function generateErrorMsg(error: ValidationError) {
238255
return `${error.property.replace("instance", "object")} ${error.message}`;
239256
}
240257

241-
function getNewObjects(
258+
function serializeObjects(
242259
parsedObj: TableRow[],
243260
cols: TableColumn[],
244-
): NewObject[] {
261+
): SerializedObject[] {
245262
return parsedObj.map((row) => {
246263
return Object.entries(row).map(([colName, colValue]) => {
247264
const col = cols.find((col) => col.name === colName);

src/devtools/utils/inspected-window-data-create.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -86,14 +86,14 @@ function insertObjects(
8686
const objStore = tx.objectStore(storeName);
8787
objects.forEach((obj) => {
8888
try {
89-
const addRequest = objStore.add(obj);
90-
addRequest.onerror = () => {
91-
console.error("data-creation: add error", addRequest.error);
89+
const putRequest = objStore.put(obj);
90+
putRequest.onerror = () => {
91+
console.error("data-creation: put error", putRequest.error);
9292
// better to just return the indexedDB error given that many things
9393
// can go wrong
94-
// https://developer.mozilla.org/en-US/docs/Web/API/IDBObjectStore/add#exceptions
94+
// https://developer.mozilla.org/en-US/docs/Web/API/IDBObjectStore/put#exceptions
9595
const msg =
96-
addRequest.error?.message ??
96+
putRequest.error?.message ??
9797
`Unable to insert the object=${JSON.stringify(obj)}.`;
9898
reject(new Error(msg));
9999
};

src/devtools/utils/types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,10 +128,10 @@ export interface DataCreationRequest {
128128
requestID: string;
129129
dbName: string;
130130
storeName: string;
131-
objects: NewObject[];
131+
objects: SerializedObject[];
132132
}
133133

134-
export type NewObject = {
134+
export type SerializedObject = {
135135
name: string;
136136
value: JSONSerializable;
137137
datatype: TableColumnDatatype;

0 commit comments

Comments
 (0)