sqlite-hub 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/changelog.md +8 -0
- package/frontend/assets/mockups/connections.png +0 -0
- package/frontend/assets/mockups/data.png +0 -0
- package/frontend/assets/mockups/data_row_editor.png +0 -0
- package/frontend/assets/mockups/home.png +0 -0
- package/frontend/assets/mockups/sql_editor.png +0 -0
- package/frontend/assets/mockups/sql_editor_querydetail.png +0 -0
- package/frontend/assets/mockups/structure.png +0 -0
- package/frontend/assets/mockups/structure_inspector.png +0 -0
- package/frontend/js/api.js +15 -0
- package/frontend/js/app.js +279 -8
- package/frontend/js/components/queryEditor.js +2 -2
- package/frontend/js/components/sidebar.js +1 -0
- package/frontend/js/components/tableDesignerEditor.js +356 -0
- package/frontend/js/components/tableDesignerSidebar.js +126 -0
- package/frontend/js/components/tableDesignerSqlPreview.js +40 -0
- package/frontend/js/router.js +10 -0
- package/frontend/js/store.js +296 -1
- package/frontend/js/utils/tableDesigner.js +1192 -0
- package/frontend/js/views/data.js +253 -263
- package/frontend/js/views/tableDesigner.js +37 -0
- package/frontend/styles/base.css +87 -73
- package/frontend/styles/components.css +798 -251
- package/frontend/styles/views.css +40 -0
- package/package.json +1 -1
- package/server/routes/tableDesigner.js +60 -0
- package/server/server.js +4 -0
- package/server/services/sqlite/tableDesigner/changeAnalysis.js +295 -0
- package/server/services/sqlite/tableDesigner/schemaMapping.js +233 -0
- package/server/services/sqlite/tableDesigner/sql.js +63 -0
- package/server/services/sqlite/tableDesigner/validation.js +245 -0
- package/server/services/sqlite/tableDesignerService.js +181 -0
- package/frontend/assets/mockups/data_edit.png +0 -0
- package/frontend/assets/mockups/graph_visualize.png +0 -0
- package/frontend/assets/mockups/overview.png +0 -0
package/README.md
CHANGED
|
@@ -24,7 +24,7 @@ SQLite Hub keeps that workflow sharp:
|
|
|
24
24
|
|
|
25
25
|
### Structure view
|
|
26
26
|
|
|
27
|
-

|
|
28
28
|
|
|
29
29
|
Inspect tables, columns, types, and schema details without losing pace. Visualized in a graph.
|
|
30
30
|
|
|
@@ -36,7 +36,7 @@ Scan rows, sort fast, move through local data quickly, and export full tables as
|
|
|
36
36
|
|
|
37
37
|
### Row editing
|
|
38
38
|
|
|
39
|
-

|
|
40
40
|
|
|
41
41
|
Open one record, edit it in place, commit, continue.
|
|
42
42
|
|
package/changelog.md
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/frontend/js/api.js
CHANGED
|
@@ -234,6 +234,21 @@ export function getStructureDetail(tableName) {
|
|
|
234
234
|
return request(`/api/structure/${encodeURIComponent(tableName)}`);
|
|
235
235
|
}
|
|
236
236
|
|
|
237
|
+
export function getTableDesignerOverview() {
|
|
238
|
+
return request("/api/table-designer");
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
export function getTableDesignerTable(tableName) {
|
|
242
|
+
return request(`/api/table-designer/${encodeURIComponent(tableName)}`);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
export function saveTableDesignerDraft(payload) {
|
|
246
|
+
return request("/api/table-designer/save", {
|
|
247
|
+
method: "POST",
|
|
248
|
+
body: payload,
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
|
|
237
252
|
export function getDataTables() {
|
|
238
253
|
return request("/api/data");
|
|
239
254
|
}
|
package/frontend/js/app.js
CHANGED
|
@@ -40,6 +40,7 @@ import {
|
|
|
40
40
|
selectConnection,
|
|
41
41
|
selectQueryHistoryItem,
|
|
42
42
|
selectStructureEntry,
|
|
43
|
+
setTableDesignerSearchQuery,
|
|
43
44
|
setDataPage,
|
|
44
45
|
setDataPageSize,
|
|
45
46
|
setDataSearchColumn,
|
|
@@ -53,6 +54,9 @@ import {
|
|
|
53
54
|
setRoute,
|
|
54
55
|
saveQueryHistoryNotes,
|
|
55
56
|
saveQueryHistoryTitle,
|
|
57
|
+
saveCurrentTableDesignerDraft,
|
|
58
|
+
queueTableDesignerCsvImport,
|
|
59
|
+
showToast,
|
|
56
60
|
submitCreateConnection,
|
|
57
61
|
submitDeleteRowConfirmation,
|
|
58
62
|
submitDataRowUpdate,
|
|
@@ -62,6 +66,10 @@ import {
|
|
|
62
66
|
submitOpenConnection,
|
|
63
67
|
subscribe,
|
|
64
68
|
toggleQueryHistorySavedState,
|
|
69
|
+
updateCurrentTableDesignerColumnField,
|
|
70
|
+
updateCurrentTableDesignerField,
|
|
71
|
+
addCurrentTableDesignerColumn,
|
|
72
|
+
removeCurrentTableDesignerColumn,
|
|
65
73
|
} from "./store.js";
|
|
66
74
|
import { renderConnectionsView } from "./views/connections.js";
|
|
67
75
|
import { renderDataView } from "./views/data.js";
|
|
@@ -70,6 +78,7 @@ import { renderLandingView } from "./views/landing.js";
|
|
|
70
78
|
import { renderOverviewView } from "./views/overview.js";
|
|
71
79
|
import { renderSettingsView } from "./views/settings.js";
|
|
72
80
|
import { renderStructureView } from "./views/structure.js";
|
|
81
|
+
import { renderTableDesignerView } from "./views/tableDesigner.js";
|
|
73
82
|
import { highlightSql } from "./utils/format.js";
|
|
74
83
|
|
|
75
84
|
const appRoot = document.querySelector("#app");
|
|
@@ -86,6 +95,8 @@ const shellRefs = {
|
|
|
86
95
|
modal: document.querySelector("#modal-root"),
|
|
87
96
|
toast: document.querySelector("#toast-root"),
|
|
88
97
|
};
|
|
98
|
+
let lastRenderedRoutePath = null;
|
|
99
|
+
let pendingNewTableDesignerAutofocus = false;
|
|
89
100
|
|
|
90
101
|
function resetStructureGraphForDatabaseChange() {
|
|
91
102
|
resetPersistedStructureGraphState();
|
|
@@ -146,6 +157,21 @@ function readFileAsBase64(file) {
|
|
|
146
157
|
});
|
|
147
158
|
}
|
|
148
159
|
|
|
160
|
+
function readFileAsText(file) {
|
|
161
|
+
return new Promise((resolve, reject) => {
|
|
162
|
+
const reader = new FileReader();
|
|
163
|
+
|
|
164
|
+
reader.onload = () => {
|
|
165
|
+
resolve(String(reader.result ?? ""));
|
|
166
|
+
};
|
|
167
|
+
reader.onerror = () => {
|
|
168
|
+
reject(reader.error ?? new Error("The selected CSV file could not be read."));
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
reader.readAsText(file);
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
|
|
149
175
|
async function buildConnectionLogoUpload(file) {
|
|
150
176
|
if (!(file instanceof File) || !file.size) {
|
|
151
177
|
return null;
|
|
@@ -200,6 +226,8 @@ function resolveView(state) {
|
|
|
200
226
|
return renderEditorView(state, { isResultsRoute: true });
|
|
201
227
|
case "structure":
|
|
202
228
|
return renderStructureView(state);
|
|
229
|
+
case "tableDesigner":
|
|
230
|
+
return renderTableDesignerView(state);
|
|
203
231
|
case "settings":
|
|
204
232
|
return renderSettingsView(state);
|
|
205
233
|
default:
|
|
@@ -212,7 +240,11 @@ function captureFocusedInputState() {
|
|
|
212
240
|
|
|
213
241
|
if (
|
|
214
242
|
!activeElement ||
|
|
215
|
-
!(
|
|
243
|
+
!(
|
|
244
|
+
activeElement instanceof HTMLInputElement ||
|
|
245
|
+
activeElement instanceof HTMLTextAreaElement ||
|
|
246
|
+
activeElement instanceof HTMLSelectElement
|
|
247
|
+
)
|
|
216
248
|
) {
|
|
217
249
|
return null;
|
|
218
250
|
}
|
|
@@ -224,6 +256,8 @@ function captureFocusedInputState() {
|
|
|
224
256
|
|
|
225
257
|
return {
|
|
226
258
|
bind,
|
|
259
|
+
field: activeElement.dataset.field ?? null,
|
|
260
|
+
columnId: activeElement.dataset.columnId ?? null,
|
|
227
261
|
selectionStart: activeElement.selectionStart,
|
|
228
262
|
selectionEnd: activeElement.selectionEnd,
|
|
229
263
|
selectionDirection: activeElement.selectionDirection,
|
|
@@ -232,24 +266,61 @@ function captureFocusedInputState() {
|
|
|
232
266
|
};
|
|
233
267
|
}
|
|
234
268
|
|
|
269
|
+
function buildFocusedInputSelectors(snapshot) {
|
|
270
|
+
if (!snapshot?.bind) {
|
|
271
|
+
return [];
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
const selectors = [];
|
|
275
|
+
const bindSelector = `[data-bind="${CSS.escape(snapshot.bind)}"]`;
|
|
276
|
+
|
|
277
|
+
if (snapshot.columnId && snapshot.field) {
|
|
278
|
+
selectors.push(
|
|
279
|
+
`${bindSelector}[data-column-id="${CSS.escape(snapshot.columnId)}"][data-field="${CSS.escape(snapshot.field)}"]`
|
|
280
|
+
);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
if (snapshot.field) {
|
|
284
|
+
selectors.push(`${bindSelector}[data-field="${CSS.escape(snapshot.field)}"]`);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
if (snapshot.columnId) {
|
|
288
|
+
selectors.push(`${bindSelector}[data-column-id="${CSS.escape(snapshot.columnId)}"]`);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
selectors.push(bindSelector);
|
|
292
|
+
return selectors;
|
|
293
|
+
}
|
|
294
|
+
|
|
235
295
|
function restoreFocusedInputState(snapshot) {
|
|
236
296
|
if (!snapshot) {
|
|
237
|
-
return;
|
|
297
|
+
return false;
|
|
238
298
|
}
|
|
239
299
|
|
|
240
|
-
const
|
|
241
|
-
|
|
300
|
+
const nextElement = buildFocusedInputSelectors(snapshot)
|
|
301
|
+
.map((selector) => document.querySelector(selector))
|
|
302
|
+
.find(
|
|
303
|
+
(candidate) =>
|
|
304
|
+
candidate instanceof HTMLInputElement ||
|
|
305
|
+
candidate instanceof HTMLTextAreaElement ||
|
|
306
|
+
candidate instanceof HTMLSelectElement
|
|
307
|
+
);
|
|
242
308
|
|
|
243
309
|
if (
|
|
244
310
|
!nextElement ||
|
|
245
|
-
!(
|
|
311
|
+
!(
|
|
312
|
+
nextElement instanceof HTMLInputElement ||
|
|
313
|
+
nextElement instanceof HTMLTextAreaElement ||
|
|
314
|
+
nextElement instanceof HTMLSelectElement
|
|
315
|
+
)
|
|
246
316
|
) {
|
|
247
|
-
return;
|
|
317
|
+
return false;
|
|
248
318
|
}
|
|
249
319
|
|
|
250
320
|
nextElement.focus({ preventScroll: true });
|
|
251
321
|
|
|
252
322
|
if (
|
|
323
|
+
(nextElement instanceof HTMLInputElement || nextElement instanceof HTMLTextAreaElement) &&
|
|
253
324
|
typeof snapshot.selectionStart === "number" &&
|
|
254
325
|
typeof snapshot.selectionEnd === "number"
|
|
255
326
|
) {
|
|
@@ -262,14 +333,97 @@ function restoreFocusedInputState(snapshot) {
|
|
|
262
333
|
|
|
263
334
|
nextElement.scrollTop = snapshot.scrollTop;
|
|
264
335
|
nextElement.scrollLeft = snapshot.scrollLeft;
|
|
336
|
+
return true;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
function focusNewTableDesignerNameField() {
|
|
340
|
+
const input = document.querySelector(
|
|
341
|
+
'[data-bind="table-designer-field"][data-field="tableName"]'
|
|
342
|
+
);
|
|
343
|
+
|
|
344
|
+
if (!(input instanceof HTMLInputElement)) {
|
|
345
|
+
return false;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
input.focus({ preventScroll: true });
|
|
349
|
+
input.setSelectionRange(input.value.length, input.value.length);
|
|
350
|
+
return true;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
function focusTableDesignerColumnNameField(columnId) {
|
|
354
|
+
if (!columnId) {
|
|
355
|
+
return false;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
const input = document.querySelector(
|
|
359
|
+
`[data-bind="table-designer-column-field"][data-column-id="${CSS.escape(columnId)}"][data-field="name"]`
|
|
360
|
+
);
|
|
361
|
+
|
|
362
|
+
if (!(input instanceof HTMLInputElement)) {
|
|
363
|
+
return false;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
input.focus({ preventScroll: true });
|
|
367
|
+
input.setSelectionRange(input.value.length, input.value.length);
|
|
368
|
+
return true;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
async function handleTableDesignerCsvImport(fileInput) {
|
|
372
|
+
if (!(fileInput instanceof HTMLInputElement)) {
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
const file = fileInput.files?.[0];
|
|
377
|
+
|
|
378
|
+
if (!(file instanceof File)) {
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
if (!file.size) {
|
|
383
|
+
showToast("The selected CSV file is empty.", "alert");
|
|
384
|
+
fileInput.value = "";
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
try {
|
|
389
|
+
const csvText = await readFileAsText(file);
|
|
390
|
+
const imported = queueTableDesignerCsvImport(file.name, csvText);
|
|
391
|
+
|
|
392
|
+
if (!imported) {
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
router.navigate("/table-designer/new");
|
|
397
|
+
showToast(
|
|
398
|
+
`Imported ${imported.columnCount} columns and ${imported.importedRowCount} row${
|
|
399
|
+
imported.importedRowCount === 1 ? "" : "s"
|
|
400
|
+
} from ${file.name}.`,
|
|
401
|
+
"success"
|
|
402
|
+
);
|
|
403
|
+
} catch (error) {
|
|
404
|
+
showToast(error?.message || "CSV import failed.", "alert");
|
|
405
|
+
} finally {
|
|
406
|
+
fileInput.value = "";
|
|
407
|
+
}
|
|
265
408
|
}
|
|
266
409
|
|
|
267
410
|
function renderApp(state) {
|
|
268
411
|
const focusedInput = captureFocusedInputState();
|
|
412
|
+
const previousRoutePath = lastRenderedRoutePath;
|
|
269
413
|
const { main, panel } = resolveView(state);
|
|
270
|
-
const isLockedRoute = ["editor", "editorResults", "data", "structure"].includes(
|
|
414
|
+
const isLockedRoute = ["editor", "editorResults", "data", "structure", "tableDesigner"].includes(
|
|
271
415
|
state.route.name
|
|
272
416
|
);
|
|
417
|
+
const isEnteringNewTableDesignerRoute =
|
|
418
|
+
state.route.name === "tableDesigner" &&
|
|
419
|
+
state.route.params?.isNew &&
|
|
420
|
+
previousRoutePath !== state.route.path;
|
|
421
|
+
|
|
422
|
+
if (isEnteringNewTableDesignerRoute) {
|
|
423
|
+
pendingNewTableDesignerAutofocus = true;
|
|
424
|
+
} else if (state.route.name !== "tableDesigner" || !state.route.params?.isNew) {
|
|
425
|
+
pendingNewTableDesignerAutofocus = false;
|
|
426
|
+
}
|
|
273
427
|
|
|
274
428
|
teardownStructureGraph();
|
|
275
429
|
shellRefs.topNav.innerHTML = renderTopNav(state);
|
|
@@ -281,7 +435,21 @@ function renderApp(state) {
|
|
|
281
435
|
shellRefs.modal.innerHTML = renderModal(state);
|
|
282
436
|
shellRefs.toast.innerHTML = renderToasts(state.toasts);
|
|
283
437
|
shellRefs.shell.classList.toggle("panel-open", Boolean(panel));
|
|
284
|
-
|
|
438
|
+
|
|
439
|
+
if (
|
|
440
|
+
pendingNewTableDesignerAutofocus &&
|
|
441
|
+
state.route.name === "tableDesigner" &&
|
|
442
|
+
state.route.params?.isNew &&
|
|
443
|
+
state.tableDesigner.draft?.mode === "create"
|
|
444
|
+
) {
|
|
445
|
+
if (focusNewTableDesignerNameField()) {
|
|
446
|
+
pendingNewTableDesignerAutofocus = false;
|
|
447
|
+
}
|
|
448
|
+
} else {
|
|
449
|
+
restoreFocusedInputState(focusedInput);
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
lastRenderedRoutePath = state.route.path;
|
|
285
453
|
|
|
286
454
|
if (state.route.name === "structure") {
|
|
287
455
|
mountStructureGraph(state).catch((error) => {
|
|
@@ -436,6 +604,53 @@ async function handleAction(actionNode) {
|
|
|
436
604
|
await selectStructureEntry(actionNode.dataset.entryName);
|
|
437
605
|
}
|
|
438
606
|
return;
|
|
607
|
+
case "add-table-designer-column":
|
|
608
|
+
{
|
|
609
|
+
const columnId = addCurrentTableDesignerColumn();
|
|
610
|
+
if (columnId) {
|
|
611
|
+
window.requestAnimationFrame(() => {
|
|
612
|
+
focusTableDesignerColumnNameField(columnId);
|
|
613
|
+
});
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
return;
|
|
617
|
+
case "remove-table-designer-column":
|
|
618
|
+
if (actionNode.dataset.columnId) {
|
|
619
|
+
removeCurrentTableDesignerColumn(actionNode.dataset.columnId);
|
|
620
|
+
}
|
|
621
|
+
return;
|
|
622
|
+
case "save-table-designer": {
|
|
623
|
+
const savedTableName = await saveCurrentTableDesignerDraft();
|
|
624
|
+
if (savedTableName) {
|
|
625
|
+
router.navigate(`/table-designer/${encodeURIComponent(savedTableName)}`);
|
|
626
|
+
}
|
|
627
|
+
return;
|
|
628
|
+
}
|
|
629
|
+
case "copy-table-designer-sql": {
|
|
630
|
+
const sqlPreview = getState().tableDesigner.draft?.sqlPreview ?? "";
|
|
631
|
+
if (!sqlPreview.trim()) {
|
|
632
|
+
return;
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
try {
|
|
636
|
+
await navigator.clipboard.writeText(sqlPreview);
|
|
637
|
+
showToast("SQL preview copied.", "success");
|
|
638
|
+
} catch (error) {
|
|
639
|
+
showToast("Clipboard access failed.", "alert");
|
|
640
|
+
}
|
|
641
|
+
return;
|
|
642
|
+
}
|
|
643
|
+
case "import-table-designer-csv": {
|
|
644
|
+
const fileInput = document.querySelector('[data-bind="table-designer-import-file"]');
|
|
645
|
+
|
|
646
|
+
if (!(fileInput instanceof HTMLInputElement)) {
|
|
647
|
+
return;
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
fileInput.value = "";
|
|
651
|
+
fileInput.click();
|
|
652
|
+
return;
|
|
653
|
+
}
|
|
439
654
|
case "select-data-row":
|
|
440
655
|
if (actionNode.dataset.rowIndex) {
|
|
441
656
|
selectDataRow(actionNode.dataset.rowIndex);
|
|
@@ -554,6 +769,29 @@ document.addEventListener("input", (event) => {
|
|
|
554
769
|
return;
|
|
555
770
|
}
|
|
556
771
|
|
|
772
|
+
if (bindNode.dataset.bind === "table-designer-search") {
|
|
773
|
+
setTableDesignerSearchQuery(bindNode.value);
|
|
774
|
+
return;
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
if (bindNode.dataset.bind === "table-designer-field") {
|
|
778
|
+
if (bindNode instanceof HTMLInputElement && bindNode.type === "checkbox") {
|
|
779
|
+
return;
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
updateCurrentTableDesignerField(bindNode.dataset.field, bindNode.value);
|
|
783
|
+
return;
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
if (bindNode.dataset.bind === "table-designer-column-field") {
|
|
787
|
+
updateCurrentTableDesignerColumnField(
|
|
788
|
+
bindNode.dataset.columnId,
|
|
789
|
+
bindNode.dataset.field,
|
|
790
|
+
bindNode.value
|
|
791
|
+
);
|
|
792
|
+
return;
|
|
793
|
+
}
|
|
794
|
+
|
|
557
795
|
if (bindNode.dataset.bind === "query-history-search") {
|
|
558
796
|
setQueryHistorySearchInput(bindNode.value);
|
|
559
797
|
}
|
|
@@ -582,6 +820,39 @@ document.addEventListener("change", (event) => {
|
|
|
582
820
|
|
|
583
821
|
if (bindNode.dataset.bind === "data-search-column") {
|
|
584
822
|
setDataSearchColumn(bindNode.value);
|
|
823
|
+
return;
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
if (bindNode.dataset.bind === "table-designer-import-file") {
|
|
827
|
+
void handleTableDesignerCsvImport(bindNode);
|
|
828
|
+
return;
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
if (bindNode.dataset.bind === "table-designer-field") {
|
|
832
|
+
if (bindNode instanceof HTMLInputElement && bindNode.type === "checkbox") {
|
|
833
|
+
updateCurrentTableDesignerField(bindNode.dataset.field, bindNode.checked);
|
|
834
|
+
return;
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
updateCurrentTableDesignerField(bindNode.dataset.field, bindNode.value);
|
|
838
|
+
return;
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
if (bindNode.dataset.bind === "table-designer-column-field") {
|
|
842
|
+
updateCurrentTableDesignerColumnField(
|
|
843
|
+
bindNode.dataset.columnId,
|
|
844
|
+
bindNode.dataset.field,
|
|
845
|
+
bindNode.value
|
|
846
|
+
);
|
|
847
|
+
return;
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
if (bindNode.dataset.bind === "table-designer-column-flag") {
|
|
851
|
+
updateCurrentTableDesignerColumnField(
|
|
852
|
+
bindNode.dataset.columnId,
|
|
853
|
+
bindNode.dataset.field,
|
|
854
|
+
bindNode.checked
|
|
855
|
+
);
|
|
585
856
|
}
|
|
586
857
|
});
|
|
587
858
|
|
|
@@ -28,11 +28,11 @@ function renderEditorSurface({ query }) {
|
|
|
28
28
|
<span class="material-symbols-outlined text-[120px] font-thin">terminal</span>
|
|
29
29
|
</div>
|
|
30
30
|
<div class="query-editor-layer relative z-10 h-full min-h-[140px]">
|
|
31
|
-
<
|
|
31
|
+
<div
|
|
32
32
|
aria-hidden="true"
|
|
33
33
|
class="query-editor-highlight"
|
|
34
34
|
data-query-editor-highlight
|
|
35
|
-
>${renderHighlightedQuery(query)}</
|
|
35
|
+
>${renderHighlightedQuery(query)}</div>
|
|
36
36
|
<textarea
|
|
37
37
|
class="query-editor-input custom-scrollbar relative z-10 h-full min-h-[140px] w-full resize-none border-none focus:ring-0"
|
|
38
38
|
data-bind="current-query"
|
|
@@ -7,6 +7,7 @@ const sidebarItems = [
|
|
|
7
7
|
{ label: "Data", href: "#/data", key: "data", icon: "table_rows" },
|
|
8
8
|
{ label: "SQL Editor", href: "#/editor", key: "editor", icon: "terminal" },
|
|
9
9
|
{ label: "Structure", href: "#/structure", key: "structure", icon: "account_tree" },
|
|
10
|
+
{ label: "Table Designer", href: "#/table-designer", key: "tableDesigner", icon: "table_chart" },
|
|
10
11
|
{ label: "Settings", href: "#/settings", key: "settings", icon: "settings" },
|
|
11
12
|
];
|
|
12
13
|
|