sqlite-hub 1.0.0 → 1.1.1
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 +47 -33
- package/bin/sqlite-hub.js +127 -47
- package/frontend/js/api.js +6 -0
- package/frontend/js/app.js +229 -44
- package/frontend/js/components/modal.js +17 -1
- package/frontend/js/components/queryChartRenderer.js +28 -3
- package/frontend/js/components/queryEditor.js +24 -26
- package/frontend/js/components/queryHistoryDetail.js +1 -1
- package/frontend/js/components/queryHistoryHeader.js +48 -0
- package/frontend/js/components/queryHistoryList.js +132 -0
- package/frontend/js/components/queryHistoryPanel.js +72 -136
- package/frontend/js/components/structureGraph.js +700 -89
- package/frontend/js/components/tableDesignerEditor.js +26 -47
- package/frontend/js/components/tableDesignerSidebar.js +7 -31
- package/frontend/js/components/tableDesignerSqlPreview.js +2 -1
- package/frontend/js/store.js +97 -8
- package/frontend/js/utils/exportFilenames.js +3 -1
- package/frontend/js/views/charts.js +326 -174
- package/frontend/js/views/connections.js +59 -64
- package/frontend/js/views/data.js +48 -54
- package/frontend/js/views/documents.js +62 -23
- package/frontend/js/views/editor.js +0 -2
- package/frontend/js/views/mediaTagging.js +6 -5
- package/frontend/js/views/settings.js +78 -0
- package/frontend/js/views/structure.js +48 -32
- package/frontend/js/views/tableDesigner.js +45 -1
- package/frontend/styles/components.css +259 -54
- package/frontend/styles/structure-graph.css +150 -37
- package/frontend/styles/tailwind.generated.css +1 -1
- package/frontend/styles/tokens.css +2 -0
- package/frontend/styles/views.css +75 -38
- package/package.json +3 -2
- package/server/routes/export.js +89 -22
- package/server/routes/externalApi.js +84 -2
- package/server/routes/settings.js +37 -28
- package/server/services/appInfoService.js +215 -0
- package/server/services/databaseCommandService.js +50 -6
- package/server/services/sqlite/dataBrowserService.js +11 -3
- package/server/services/sqlite/exportService.js +307 -22
- package/tests/api-token-auth.test.js +110 -1
- package/tests/cli-args.test.js +16 -3
- package/tests/database-command-service.test.js +40 -3
- package/tests/export-blob.test.js +54 -1
- package/tests/export-filenames.test.js +4 -0
- package/tests/settings-api-tokens-route.test.js +22 -1
- package/tests/settings-metadata.test.js +99 -1
- package/tests/settings-view.test.js +28 -0
|
@@ -323,7 +323,6 @@ export function renderTableDesignerEditor(state) {
|
|
|
323
323
|
}
|
|
324
324
|
|
|
325
325
|
const catalogTables = state.tableDesigner.tables ?? [];
|
|
326
|
-
const visibleColumns = draft.columns.filter((column) => !column.deleted);
|
|
327
326
|
const saveLabel =
|
|
328
327
|
draft.mode === "create"
|
|
329
328
|
? state.tableDesigner.saving
|
|
@@ -335,11 +334,12 @@ export function renderTableDesignerEditor(state) {
|
|
|
335
334
|
|
|
336
335
|
return `
|
|
337
336
|
<section class="table-designer-main shell-section">
|
|
338
|
-
<
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
337
|
+
<div data-table-designer-feedback>
|
|
338
|
+
${renderTableDesignerFeedback(draft, state.tableDesigner.saveError)}
|
|
339
|
+
</div>
|
|
340
|
+
|
|
341
|
+
<section class="table-designer-main__section">
|
|
342
|
+
<div class="table-designer-main__section-header">
|
|
343
343
|
<div class="table-designer-main__title-row">
|
|
344
344
|
<input
|
|
345
345
|
class="table-designer-main__name"
|
|
@@ -351,49 +351,11 @@ export function renderTableDesignerEditor(state) {
|
|
|
351
351
|
value="${escapeHtml(draft.tableName)}"
|
|
352
352
|
/>
|
|
353
353
|
${
|
|
354
|
-
draft.mode === "
|
|
355
|
-
? `<div class="status-badge status-badge--
|
|
356
|
-
|
|
357
|
-
)}</div>`
|
|
358
|
-
: `<div class="status-badge status-badge--primary">CREATE</div>`
|
|
354
|
+
draft.mode === "create"
|
|
355
|
+
? `<div class="status-badge status-badge--primary">CREATE</div>`
|
|
356
|
+
: ""
|
|
359
357
|
}
|
|
360
358
|
</div>
|
|
361
|
-
<div class="table-designer-main__subtitle">
|
|
362
|
-
${escapeHtml(String(visibleColumns.length))} visible column${
|
|
363
|
-
visibleColumns.length === 1 ? "" : "s"
|
|
364
|
-
} // Table Designer v2 // SQLite-safe operations only
|
|
365
|
-
</div>
|
|
366
|
-
</div>
|
|
367
|
-
<div class="table-designer-main__actions">
|
|
368
|
-
${renderFillToggle(draft)}
|
|
369
|
-
<button
|
|
370
|
-
class="standard-button"
|
|
371
|
-
data-action="refresh-view"
|
|
372
|
-
type="button"
|
|
373
|
-
>
|
|
374
|
-
Reload Schema
|
|
375
|
-
</button>
|
|
376
|
-
<button
|
|
377
|
-
class="standard-button"
|
|
378
|
-
data-action="save-table-designer"
|
|
379
|
-
data-table-designer-save-button
|
|
380
|
-
${draft.canSave ? "" : "disabled"}
|
|
381
|
-
type="button"
|
|
382
|
-
>
|
|
383
|
-
${escapeHtml(saveLabel)}
|
|
384
|
-
</button>
|
|
385
|
-
</div>
|
|
386
|
-
</header>
|
|
387
|
-
|
|
388
|
-
<div data-table-designer-feedback>
|
|
389
|
-
${renderTableDesignerFeedback(draft, state.tableDesigner.saveError)}
|
|
390
|
-
</div>
|
|
391
|
-
|
|
392
|
-
<section class="table-designer-main__section">
|
|
393
|
-
<div class="table-designer-main__section-header">
|
|
394
|
-
<div>
|
|
395
|
-
<div class="table-designer-main__section-title">Columns</div>
|
|
396
|
-
</div>
|
|
397
359
|
<div class="table-designer-main__section-actions">
|
|
398
360
|
<button
|
|
399
361
|
class="standard-button"
|
|
@@ -402,6 +364,23 @@ export function renderTableDesignerEditor(state) {
|
|
|
402
364
|
>
|
|
403
365
|
+ Add Column
|
|
404
366
|
</button>
|
|
367
|
+
<button
|
|
368
|
+
class="standard-button"
|
|
369
|
+
data-action="refresh-view"
|
|
370
|
+
type="button"
|
|
371
|
+
>
|
|
372
|
+
Reload Schema
|
|
373
|
+
</button>
|
|
374
|
+
<button
|
|
375
|
+
class="standard-button"
|
|
376
|
+
data-action="save-table-designer"
|
|
377
|
+
data-table-designer-save-button
|
|
378
|
+
${draft.canSave ? "" : "disabled"}
|
|
379
|
+
type="button"
|
|
380
|
+
>
|
|
381
|
+
${escapeHtml(saveLabel)}
|
|
382
|
+
</button>
|
|
383
|
+
${renderFillToggle(draft)}
|
|
405
384
|
</div>
|
|
406
385
|
</div>
|
|
407
386
|
${renderColumnGrid(draft, catalogTables)}
|
|
@@ -18,38 +18,14 @@ export function renderTableDesignerSidebar(state) {
|
|
|
18
18
|
const isNewDraft = state.tableDesigner.draft?.mode === 'create';
|
|
19
19
|
|
|
20
20
|
return `
|
|
21
|
-
<aside class="table-designer-sidebar">
|
|
22
|
-
<div class="table-designer-sidebar__header">
|
|
21
|
+
<aside class="table-designer-sidebar subnavi-panel">
|
|
22
|
+
<div class="table-designer-sidebar__header subnavi-header">
|
|
23
23
|
<div>
|
|
24
|
-
<div class="
|
|
25
|
-
<div class="
|
|
24
|
+
<div class="subnavi-header-title">Table Designer</div>
|
|
25
|
+
<div class="subnavi-header-details">
|
|
26
26
|
${escapeHtml(formatNumber(tables.length))} table${tables.length === 1 ? '' : 's'}
|
|
27
27
|
</div>
|
|
28
28
|
</div>
|
|
29
|
-
<div class="table-designer-sidebar__header-actions">
|
|
30
|
-
<button
|
|
31
|
-
class="standard-button"
|
|
32
|
-
data-action="import-table-designer-csv"
|
|
33
|
-
type="button"
|
|
34
|
-
>
|
|
35
|
-
Import CSV
|
|
36
|
-
</button>
|
|
37
|
-
<input
|
|
38
|
-
accept=".csv,text/csv"
|
|
39
|
-
class="table-designer-sidebar__file-input"
|
|
40
|
-
data-bind="table-designer-import-file"
|
|
41
|
-
type="file"
|
|
42
|
-
/>
|
|
43
|
-
<button
|
|
44
|
-
class="signature-button"
|
|
45
|
-
data-action="navigate"
|
|
46
|
-
data-to="/table-designer/new"
|
|
47
|
-
type="button"
|
|
48
|
-
>
|
|
49
|
-
+ New Table
|
|
50
|
-
</button>
|
|
51
|
-
|
|
52
|
-
</div>
|
|
53
29
|
</div>
|
|
54
30
|
|
|
55
31
|
<label class="table-designer-sidebar__search">
|
|
@@ -64,7 +40,7 @@ export function renderTableDesignerSidebar(state) {
|
|
|
64
40
|
/>
|
|
65
41
|
</label>
|
|
66
42
|
|
|
67
|
-
<div class="table-designer-sidebar__list custom-scrollbar">
|
|
43
|
+
<div class="table-designer-sidebar__list subnavi-list custom-scrollbar">
|
|
68
44
|
${
|
|
69
45
|
state.tableDesigner.loading && !tables.length
|
|
70
46
|
? `
|
|
@@ -76,7 +52,7 @@ export function renderTableDesignerSidebar(state) {
|
|
|
76
52
|
: isNewDraft
|
|
77
53
|
? `
|
|
78
54
|
<button
|
|
79
|
-
class="table-designer-sidebar__item is-active
|
|
55
|
+
class="table-designer-sidebar__item subnavi-item is-active border border-primary-container/30 bg-surface-container-high px-4 py-3 text-left transition-colors"
|
|
80
56
|
data-action="navigate"
|
|
81
57
|
data-to="/table-designer/new"
|
|
82
58
|
type="button"
|
|
@@ -102,7 +78,7 @@ export function renderTableDesignerSidebar(state) {
|
|
|
102
78
|
.map(
|
|
103
79
|
table => `
|
|
104
80
|
<button
|
|
105
|
-
class="table-designer-sidebar__item
|
|
81
|
+
class="table-designer-sidebar__item subnavi-item border px-4 py-3 text-left transition-colors ${
|
|
106
82
|
!isNewDraft && table.name === state.tableDesigner.selectedTableName
|
|
107
83
|
? 'is-active border-primary-container/30 bg-surface-container-high'
|
|
108
84
|
: 'border-outline-variant/10 bg-surface-container-lowest hover:bg-surface-container-high'
|
|
@@ -23,7 +23,8 @@ function renderPreviewHeader(draft, isVisible) {
|
|
|
23
23
|
: ''
|
|
24
24
|
}
|
|
25
25
|
<button
|
|
26
|
-
class="standard-button"
|
|
26
|
+
class="standard-button panel-toggle-button ${isVisible ? '' : 'is-active'}"
|
|
27
|
+
aria-pressed="${isVisible ? 'false' : 'true'}"
|
|
27
28
|
data-action="toggle-table-designer-sql-preview"
|
|
28
29
|
data-next-value="${isVisible ? 'false' : 'true'}"
|
|
29
30
|
type="button"
|
package/frontend/js/store.js
CHANGED
|
@@ -49,10 +49,13 @@ const UI_PREFERENCE_STORAGE_KEYS = {
|
|
|
49
49
|
dataTablesVisible: 'sqlite_hub_data_tables_visible',
|
|
50
50
|
structureTablesVisible: 'sqlite_hub_structure_tables_visible',
|
|
51
51
|
chartsHistoryVisible: 'sqlite_hub_charts_history_visible',
|
|
52
|
+
chartsQueryVisible: 'sqlite_hub_charts_query_visible',
|
|
52
53
|
chartsResultsVisible: 'sqlite_hub_charts_results_visible',
|
|
54
|
+
tableDesignerTablesVisible: 'sqlite_hub_table_designer_tables_visible',
|
|
53
55
|
tableDesignerSqlPreviewVisible: 'sqlite_hub_table_designer_sql_preview_visible',
|
|
54
56
|
documentsEditorVisible: 'sqlite_hub_documents_editor_visible',
|
|
55
57
|
documentsPreviewVisible: 'sqlite_hub_documents_preview_visible',
|
|
58
|
+
mediaTaggingViewerVisible: 'sqlite_hub_media_tagging_viewer_visible',
|
|
56
59
|
};
|
|
57
60
|
const QUERY_HISTORY_PAGE_SIZE = 30;
|
|
58
61
|
const QUERY_HISTORY_RUN_LIMIT = 8;
|
|
@@ -63,6 +66,8 @@ const TEXT_EXPORT_FORMAT_LABELS = {
|
|
|
63
66
|
csv: 'CSV',
|
|
64
67
|
tsv: 'TSV',
|
|
65
68
|
md: 'Markdown',
|
|
69
|
+
json: 'JSON',
|
|
70
|
+
parquet: 'Parquet',
|
|
66
71
|
};
|
|
67
72
|
const MISSING_DATABASE_ERROR = {
|
|
68
73
|
code: 'ACTIVE_DATABASE_REQUIRED',
|
|
@@ -262,6 +267,9 @@ const state = {
|
|
|
262
267
|
error: null,
|
|
263
268
|
appVersion: null,
|
|
264
269
|
sqliteVersion: null,
|
|
270
|
+
versionCheck: null,
|
|
271
|
+
versionCheckLoading: false,
|
|
272
|
+
versionCheckError: null,
|
|
265
273
|
},
|
|
266
274
|
overview: {
|
|
267
275
|
data: null,
|
|
@@ -331,10 +339,13 @@ const state = {
|
|
|
331
339
|
loading: false,
|
|
332
340
|
error: null,
|
|
333
341
|
historyTab: readStoredChartsHistoryTab(),
|
|
342
|
+
historySearchInput: '',
|
|
343
|
+
historySearch: '',
|
|
334
344
|
historyPanelVisible: readStoredBoolean(UI_PREFERENCE_STORAGE_KEYS.chartsHistoryVisible, true),
|
|
345
|
+
detailPanelVisible: false,
|
|
335
346
|
selectedHistoryId: null,
|
|
336
347
|
chartHeightPreset: 'medium',
|
|
337
|
-
|
|
348
|
+
queryVisible: readStoredBoolean(UI_PREFERENCE_STORAGE_KEYS.chartsQueryVisible, true),
|
|
338
349
|
resultsVisible: readStoredBoolean(UI_PREFERENCE_STORAGE_KEYS.chartsResultsVisible, true),
|
|
339
350
|
detail: null,
|
|
340
351
|
detailLoading: false,
|
|
@@ -347,6 +358,7 @@ const state = {
|
|
|
347
358
|
items: [],
|
|
348
359
|
selectedId: null,
|
|
349
360
|
selected: null,
|
|
361
|
+
searchQuery: '',
|
|
350
362
|
draftFilename: '',
|
|
351
363
|
draftContent: '',
|
|
352
364
|
dirty: false,
|
|
@@ -363,6 +375,7 @@ const state = {
|
|
|
363
375
|
tables: [],
|
|
364
376
|
selectedTableName: null,
|
|
365
377
|
draft: null,
|
|
378
|
+
tablesVisible: readStoredBoolean(UI_PREFERENCE_STORAGE_KEYS.tableDesignerTablesVisible, true),
|
|
366
379
|
sqlPreviewVisible: readStoredBoolean(UI_PREFERENCE_STORAGE_KEYS.tableDesignerSqlPreviewVisible, true),
|
|
367
380
|
pendingImportedDraft: null,
|
|
368
381
|
loading: false,
|
|
@@ -415,7 +428,7 @@ const state = {
|
|
|
415
428
|
issues: [],
|
|
416
429
|
dismissedIssueKeys: [],
|
|
417
430
|
selectedTagKeys: [],
|
|
418
|
-
workflowMediaDetailsVisible: true,
|
|
431
|
+
workflowMediaDetailsVisible: readStoredBoolean(UI_PREFERENCE_STORAGE_KEYS.mediaTaggingViewerVisible, true),
|
|
419
432
|
workflowMediaRotationDegrees: 0,
|
|
420
433
|
skippedMediaKeys: [],
|
|
421
434
|
tagFormValues: {},
|
|
@@ -929,10 +942,13 @@ function resetChartsState() {
|
|
|
929
942
|
state.charts.loading = false;
|
|
930
943
|
state.charts.error = null;
|
|
931
944
|
state.charts.historyTab = readStoredChartsHistoryTab(state.charts.historyTab);
|
|
945
|
+
state.charts.historySearchInput = '';
|
|
946
|
+
state.charts.historySearch = '';
|
|
932
947
|
state.charts.historyPanelVisible = readStoredBoolean(UI_PREFERENCE_STORAGE_KEYS.chartsHistoryVisible, true);
|
|
948
|
+
state.charts.detailPanelVisible = false;
|
|
933
949
|
state.charts.selectedHistoryId = null;
|
|
934
950
|
state.charts.chartHeightPreset = 'medium';
|
|
935
|
-
state.charts.
|
|
951
|
+
state.charts.queryVisible = readStoredBoolean(UI_PREFERENCE_STORAGE_KEYS.chartsQueryVisible, true);
|
|
936
952
|
state.charts.resultsVisible = readStoredBoolean(UI_PREFERENCE_STORAGE_KEYS.chartsResultsVisible, true);
|
|
937
953
|
state.charts.detail = null;
|
|
938
954
|
state.charts.detailLoading = false;
|
|
@@ -947,6 +963,7 @@ function resetDocumentsState() {
|
|
|
947
963
|
state.documents.items = [];
|
|
948
964
|
state.documents.selectedId = null;
|
|
949
965
|
state.documents.selected = null;
|
|
966
|
+
state.documents.searchQuery = '';
|
|
950
967
|
state.documents.draftFilename = '';
|
|
951
968
|
state.documents.draftContent = '';
|
|
952
969
|
state.documents.dirty = false;
|
|
@@ -1019,7 +1036,7 @@ function normalizeChartsHeightPreset(value) {
|
|
|
1019
1036
|
}
|
|
1020
1037
|
|
|
1021
1038
|
function normalizeChartsHistoryTab(value) {
|
|
1022
|
-
return ['recent', 'saved'].includes(value) ? value : 'recent';
|
|
1039
|
+
return ['recent', 'saved', 'unsaved'].includes(value) ? value : 'recent';
|
|
1023
1040
|
}
|
|
1024
1041
|
|
|
1025
1042
|
function mergeQueryHistoryItemWithChartSummary(updatedItem, fallbackItem = null) {
|
|
@@ -1177,6 +1194,7 @@ function setMissingDatabaseState() {
|
|
|
1177
1194
|
state.tableDesigner.tables = [];
|
|
1178
1195
|
state.tableDesigner.selectedTableName = null;
|
|
1179
1196
|
state.tableDesigner.draft = null;
|
|
1197
|
+
state.tableDesigner.tablesVisible = readStoredBoolean(UI_PREFERENCE_STORAGE_KEYS.tableDesignerTablesVisible, true);
|
|
1180
1198
|
state.tableDesigner.sqlPreviewVisible = readStoredBoolean(UI_PREFERENCE_STORAGE_KEYS.tableDesignerSqlPreviewVisible, true);
|
|
1181
1199
|
state.tableDesigner.pendingImportedDraft = null;
|
|
1182
1200
|
state.tableDesigner.saving = false;
|
|
@@ -1358,6 +1376,33 @@ export function setSettingsSection(section) {
|
|
|
1358
1376
|
emitChange();
|
|
1359
1377
|
}
|
|
1360
1378
|
|
|
1379
|
+
export async function checkSettingsAppVersion() {
|
|
1380
|
+
state.settings.versionCheckLoading = true;
|
|
1381
|
+
state.settings.versionCheckError = null;
|
|
1382
|
+
emitChange();
|
|
1383
|
+
|
|
1384
|
+
try {
|
|
1385
|
+
const response = await api.checkAppVersion();
|
|
1386
|
+
const result = response.data ?? null;
|
|
1387
|
+
|
|
1388
|
+
state.settings.versionCheck = result;
|
|
1389
|
+
pushToast(
|
|
1390
|
+
result?.updateAvailable
|
|
1391
|
+
? `SQLite Hub v${result.latestVersion} is available.`
|
|
1392
|
+
: 'SQLite Hub is up to date.',
|
|
1393
|
+
'success',
|
|
1394
|
+
);
|
|
1395
|
+
return result;
|
|
1396
|
+
} catch (error) {
|
|
1397
|
+
state.settings.versionCheckError = normalizeError(error);
|
|
1398
|
+
pushToast('Version check failed.', 'alert');
|
|
1399
|
+
return null;
|
|
1400
|
+
} finally {
|
|
1401
|
+
state.settings.versionCheckLoading = false;
|
|
1402
|
+
emitChange();
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1405
|
+
|
|
1361
1406
|
export async function deleteSettingsApiToken(tokenId) {
|
|
1362
1407
|
state.settings.tokenSaving = true;
|
|
1363
1408
|
state.settings.error = null;
|
|
@@ -1557,7 +1602,8 @@ async function loadChartsDetail(historyId) {
|
|
|
1557
1602
|
|
|
1558
1603
|
if (!Number.isInteger(numericId) || numericId < 1) {
|
|
1559
1604
|
state.charts.selectedHistoryId = null;
|
|
1560
|
-
state.charts.
|
|
1605
|
+
state.charts.detailPanelVisible = false;
|
|
1606
|
+
state.charts.queryVisible = readStoredBoolean(UI_PREFERENCE_STORAGE_KEYS.chartsQueryVisible, true);
|
|
1561
1607
|
state.charts.resultsVisible = readStoredBoolean(UI_PREFERENCE_STORAGE_KEYS.chartsResultsVisible, true);
|
|
1562
1608
|
state.charts.detail = null;
|
|
1563
1609
|
state.charts.detailLoading = false;
|
|
@@ -1570,7 +1616,7 @@ async function loadChartsDetail(historyId) {
|
|
|
1570
1616
|
}
|
|
1571
1617
|
|
|
1572
1618
|
state.charts.selectedHistoryId = numericId;
|
|
1573
|
-
state.charts.
|
|
1619
|
+
state.charts.queryVisible = readStoredBoolean(UI_PREFERENCE_STORAGE_KEYS.chartsQueryVisible, true);
|
|
1574
1620
|
state.charts.resultsVisible = readStoredBoolean(UI_PREFERENCE_STORAGE_KEYS.chartsResultsVisible, true);
|
|
1575
1621
|
state.charts.detail = null;
|
|
1576
1622
|
state.charts.detailLoading = true;
|
|
@@ -2344,6 +2390,7 @@ function invalidateDatabaseCaches(options = {}) {
|
|
|
2344
2390
|
state.tableDesigner.tables = [];
|
|
2345
2391
|
state.tableDesigner.selectedTableName = null;
|
|
2346
2392
|
state.tableDesigner.draft = null;
|
|
2393
|
+
state.tableDesigner.tablesVisible = readStoredBoolean(UI_PREFERENCE_STORAGE_KEYS.tableDesignerTablesVisible, true);
|
|
2347
2394
|
state.tableDesigner.sqlPreviewVisible = readStoredBoolean(UI_PREFERENCE_STORAGE_KEYS.tableDesignerSqlPreviewVisible, true);
|
|
2348
2395
|
state.tableDesigner.pendingImportedDraft = null;
|
|
2349
2396
|
state.tableDesigner.saving = false;
|
|
@@ -2388,6 +2435,10 @@ function invalidateDatabaseCaches(options = {}) {
|
|
|
2388
2435
|
state.mediaTagging.issues = [];
|
|
2389
2436
|
state.mediaTagging.dismissedIssueKeys = [];
|
|
2390
2437
|
state.mediaTagging.selectedTagKeys = [];
|
|
2438
|
+
state.mediaTagging.workflowMediaDetailsVisible = readStoredBoolean(
|
|
2439
|
+
UI_PREFERENCE_STORAGE_KEYS.mediaTaggingViewerVisible,
|
|
2440
|
+
true,
|
|
2441
|
+
);
|
|
2391
2442
|
state.mediaTagging.workflowMediaRotationDegrees = 0;
|
|
2392
2443
|
state.mediaTagging.skippedMediaKeys = [];
|
|
2393
2444
|
state.mediaTagging.tagFormValues = {};
|
|
@@ -3448,7 +3499,8 @@ export async function openEditorRowUpdatePreview(rowIndex, values) {
|
|
|
3448
3499
|
}
|
|
3449
3500
|
|
|
3450
3501
|
export function toggleChartsSqlPanel() {
|
|
3451
|
-
state.charts.
|
|
3502
|
+
state.charts.queryVisible = !state.charts.queryVisible;
|
|
3503
|
+
storeBoolean(UI_PREFERENCE_STORAGE_KEYS.chartsQueryVisible, state.charts.queryVisible);
|
|
3452
3504
|
emitChange();
|
|
3453
3505
|
}
|
|
3454
3506
|
|
|
@@ -3470,6 +3522,17 @@ export function setChartsHistoryPanelVisibility(visible) {
|
|
|
3470
3522
|
emitChange();
|
|
3471
3523
|
}
|
|
3472
3524
|
|
|
3525
|
+
export function setChartsDetailPanelVisibility(visible) {
|
|
3526
|
+
const nextValue = typeof visible === 'boolean' ? visible : !Boolean(state.charts.detailPanelVisible);
|
|
3527
|
+
|
|
3528
|
+
if (state.charts.detailPanelVisible === nextValue) {
|
|
3529
|
+
return;
|
|
3530
|
+
}
|
|
3531
|
+
|
|
3532
|
+
state.charts.detailPanelVisible = nextValue;
|
|
3533
|
+
emitChange();
|
|
3534
|
+
}
|
|
3535
|
+
|
|
3473
3536
|
export function setChartsHeightPreset(preset) {
|
|
3474
3537
|
const nextPreset = normalizeChartsHeightPreset(preset);
|
|
3475
3538
|
|
|
@@ -3497,6 +3560,18 @@ export function setChartsHistoryTab(tab) {
|
|
|
3497
3560
|
emitChange();
|
|
3498
3561
|
}
|
|
3499
3562
|
|
|
3563
|
+
export function setChartsHistorySearchInput(query) {
|
|
3564
|
+
const nextQuery = String(query ?? '');
|
|
3565
|
+
|
|
3566
|
+
if (state.charts.historySearchInput === nextQuery && state.charts.historySearch === nextQuery.trim()) {
|
|
3567
|
+
return;
|
|
3568
|
+
}
|
|
3569
|
+
|
|
3570
|
+
state.charts.historySearchInput = nextQuery;
|
|
3571
|
+
state.charts.historySearch = nextQuery.trim();
|
|
3572
|
+
emitChange();
|
|
3573
|
+
}
|
|
3574
|
+
|
|
3500
3575
|
export function updateCurrentQueryChartDraftField(field, value) {
|
|
3501
3576
|
if (state.modal?.kind !== 'chart-editor' || !state.modal.draft) {
|
|
3502
3577
|
return;
|
|
@@ -3935,7 +4010,9 @@ export function openQueryHistoryInEditor(historyId, options = {}) {
|
|
|
3935
4010
|
clearQueryHistoryDetailState();
|
|
3936
4011
|
state.editor.sqlText = options.append ? [state.editor.sqlText.trim(), rawSql].filter(Boolean).join('\n\n') : rawSql;
|
|
3937
4012
|
storeString(UI_PREFERENCE_STORAGE_KEYS.sqlEditorQueryDraft, state.editor.sqlText);
|
|
3938
|
-
|
|
4013
|
+
if (options.notify !== false) {
|
|
4014
|
+
emitChange();
|
|
4015
|
+
}
|
|
3939
4016
|
return true;
|
|
3940
4017
|
}
|
|
3941
4018
|
|
|
@@ -4042,6 +4119,12 @@ export function setTableDesignerSearchQuery(query) {
|
|
|
4042
4119
|
emitChange();
|
|
4043
4120
|
}
|
|
4044
4121
|
|
|
4122
|
+
export function toggleTableDesignerTablesPanel() {
|
|
4123
|
+
state.tableDesigner.tablesVisible = state.tableDesigner.tablesVisible === false;
|
|
4124
|
+
storeBoolean(UI_PREFERENCE_STORAGE_KEYS.tableDesignerTablesVisible, state.tableDesigner.tablesVisible);
|
|
4125
|
+
emitChange();
|
|
4126
|
+
}
|
|
4127
|
+
|
|
4045
4128
|
export function setDataTableSearchQuery(query) {
|
|
4046
4129
|
state.dataBrowser.tableSearchQuery = String(query ?? '');
|
|
4047
4130
|
emitChange();
|
|
@@ -4052,6 +4135,11 @@ export function setStructureTableSearchQuery(query) {
|
|
|
4052
4135
|
emitChange();
|
|
4053
4136
|
}
|
|
4054
4137
|
|
|
4138
|
+
export function setDocumentsSearchQuery(query) {
|
|
4139
|
+
state.documents.searchQuery = String(query ?? '');
|
|
4140
|
+
emitChange();
|
|
4141
|
+
}
|
|
4142
|
+
|
|
4055
4143
|
export function setTableDesignerSqlPreviewVisibility(visible) {
|
|
4056
4144
|
const nextValue = typeof visible === 'boolean' ? visible : !Boolean(state.tableDesigner.sqlPreviewVisible);
|
|
4057
4145
|
|
|
@@ -4293,6 +4381,7 @@ export function setMediaTaggingWorkflowMediaDetailsVisible(value, options = {})
|
|
|
4293
4381
|
}
|
|
4294
4382
|
|
|
4295
4383
|
state.mediaTagging.workflowMediaDetailsVisible = nextValue;
|
|
4384
|
+
storeBoolean(UI_PREFERENCE_STORAGE_KEYS.mediaTaggingViewerVisible, nextValue);
|
|
4296
4385
|
|
|
4297
4386
|
if (options.notify !== false) {
|
|
4298
4387
|
emitChange();
|
|
@@ -2,6 +2,8 @@ export const TEXT_EXPORT_EXTENSIONS = {
|
|
|
2
2
|
csv: "csv",
|
|
3
3
|
tsv: "tsv",
|
|
4
4
|
md: "md",
|
|
5
|
+
json: "json",
|
|
6
|
+
parquet: "parquet",
|
|
5
7
|
};
|
|
6
8
|
|
|
7
9
|
export function normalizeTextExportFormat(format = "csv") {
|
|
@@ -10,7 +12,7 @@ export function normalizeTextExportFormat(format = "csv") {
|
|
|
10
12
|
}
|
|
11
13
|
|
|
12
14
|
function stripKnownTextExportExtension(value = "") {
|
|
13
|
-
return String(value).replace(/\.(csv|tsv|md)$/i, "");
|
|
15
|
+
return String(value).replace(/\.(csv|tsv|md|json|parquet)$/i, "");
|
|
14
16
|
}
|
|
15
17
|
|
|
16
18
|
export function sanitizeExportFilenameBase(value, fallback = "export") {
|