sqlite-hub 1.2.0 → 1.5.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 +113 -71
- package/bin/sqlite-hub.js +723 -116
- package/docs/API.md +152 -0
- package/docs/CLI.md +249 -0
- package/docs/CLI_API_PARITY.md +61 -0
- package/docs/changelog.md +149 -0
- package/docs/guidelines/AGENTS.md +32 -0
- package/docs/guidelines/DESIGN.md +55 -0
- package/docs/shortkeys.md +27 -0
- package/docs/todo.md +4 -0
- package/examples/api/generate-types.js +52 -0
- package/frontend/assets/mockups/backups_1_1920.webp +0 -0
- package/frontend/assets/mockups/backups_2_create_backup_modal_1920.webp +0 -0
- package/frontend/assets/mockups/backups_3_edit_backup_modal_1920.webp +0 -0
- package/frontend/assets/mockups/backups_4_restore_backup_modal_1920.webp +0 -0
- package/frontend/assets/mockups/backups_5_delete_backup_modal_1920.webp +0 -0
- package/frontend/assets/mockups/charts_1_1920.webp +0 -0
- package/frontend/assets/mockups/charts_2_query_detail_1920.webp +0 -0
- package/frontend/assets/mockups/charts_3_create_query_chart_modal_1920.webp +0 -0
- package/frontend/assets/mockups/charts_4_edit_query_chart_modal_1920.webp +0 -0
- package/frontend/assets/mockups/charts_5_delete_query_chart_modal_1920.webp +0 -0
- package/frontend/assets/mockups/charts_6_copy_column_modal_1920.webp +0 -0
- package/frontend/assets/mockups/connections_1_1920.webp +0 -0
- package/frontend/assets/mockups/connections_2_create_connection_modal_1920.webp +0 -0
- package/frontend/assets/mockups/connections_3_open_connection_modal_1920.webp +0 -0
- package/frontend/assets/mockups/data_1_1920.webp +0 -0
- package/frontend/assets/mockups/data_2_roweditor_1920.webp +0 -0
- package/frontend/assets/mockups/data_3_data_export_modal_1920.webp +0 -0
- package/frontend/assets/mockups/documents_1_1920.webp +0 -0
- package/frontend/assets/mockups/documents_2_document_insert_table_modal_1920.webp +0 -0
- package/frontend/assets/mockups/documents_3_document_insert_note_modal_1920.webp +0 -0
- package/frontend/assets/mockups/media_tagging_queue_1_1920.webp +0 -0
- package/frontend/assets/mockups/media_tagging_setup_1_1920.webp +0 -0
- package/frontend/assets/mockups/media_tagging_setup_2_create_media_tagging_tag_table_modal_1920.webp +0 -0
- package/frontend/assets/mockups/media_tagging_setup_3_create_media_tagging_mapping_table_modal_1920.webp +0 -0
- package/frontend/assets/mockups/overview_1_1920.webp +0 -0
- package/frontend/assets/mockups/settings_1_1920.webp +0 -0
- package/frontend/assets/mockups/sql_editor_1_1920.webp +0 -0
- package/frontend/assets/mockups/sql_editor_2_query_detail_1920.webp +0 -0
- package/frontend/assets/mockups/sql_editor_3_query_export_modal_1920.webp +0 -0
- package/frontend/assets/mockups/structure_1_1920.webp +0 -0
- package/frontend/assets/mockups/structure_2_generate_types_modal_1920.webp +0 -0
- package/frontend/assets/mockups/structure_3_generate_types_modal_1920.webp +0 -0
- package/frontend/assets/mockups/table_designer_1_1920.webp +0 -0
- package/frontend/assets/mockups/table_designer_2_table_designer_constraints_modal_1920.webp +0 -0
- package/frontend/js/api.js +63 -0
- package/frontend/js/app.js +310 -10
- package/frontend/js/components/connectionCard.js +4 -2
- package/frontend/js/components/emptyState.js +4 -4
- package/frontend/js/components/generateTypesDropdown.js +33 -0
- package/frontend/js/components/metricCard.js +1 -1
- package/frontend/js/components/modal.js +555 -21
- package/frontend/js/components/pageHeader.js +1 -1
- package/frontend/js/components/queryHistoryDetail.js +3 -3
- package/frontend/js/components/queryHistoryHeader.js +1 -1
- package/frontend/js/components/queryHistoryPanel.js +1 -1
- package/frontend/js/components/rowEditorPanel.js +13 -3
- package/frontend/js/components/sidebar.js +41 -7
- package/frontend/js/components/topNav.js +2 -14
- package/frontend/js/router.js +38 -6
- package/frontend/js/store.js +870 -8
- package/frontend/js/utils/inputClear.js +36 -0
- package/frontend/js/utils/syntheticData.js +240 -0
- package/frontend/js/views/backups.js +581 -37
- package/frontend/js/views/charts.js +9 -9
- package/frontend/js/views/connections.js +2 -2
- package/frontend/js/views/data.js +17 -1
- package/frontend/js/views/documents.js +3 -3
- package/frontend/js/views/editor.js +6 -6
- package/frontend/js/views/logs.js +339 -0
- package/frontend/js/views/mediaTagging.js +7 -5
- package/frontend/js/views/overview.js +3 -3
- package/frontend/js/views/settings.js +80 -30
- package/frontend/js/views/structure.js +12 -1
- package/frontend/js/views/tableAdvisor.js +385 -0
- package/frontend/js/views/tableDesigner.js +6 -0
- package/frontend/styles/base.css +1 -40
- package/frontend/styles/components.css +258 -232
- package/frontend/styles/structure-graph.css +32 -68
- package/frontend/styles/tailwind.css +8 -4
- package/frontend/styles/tailwind.generated.css +1 -1
- package/frontend/styles/tokens.css +28 -21
- package/frontend/styles/views.css +102 -261
- package/package.json +18 -2
- package/server/routes/backups.js +18 -2
- package/server/routes/data.js +45 -0
- package/server/routes/externalApi.js +321 -2
- package/server/routes/logs.js +127 -0
- package/server/routes/structure.js +22 -0
- package/server/server.js +3 -0
- package/server/services/databaseCommandService.js +59 -0
- package/server/services/sqlite/backupDiff.js +914 -0
- package/server/services/sqlite/backupService.js +77 -1
- package/server/services/sqlite/dataBrowserService.js +36 -0
- package/server/services/sqlite/introspection.js +226 -22
- package/server/services/sqlite/structureService.js +7 -0
- package/server/services/sqlite/syntheticDataGenerator.js +728 -0
- package/server/services/sqlite/tableAdvisor.js +790 -0
- package/server/services/storage/appStateStore.js +773 -169
- package/server/services/typeGenerationService.js +663 -0
- package/tailwind.config.cjs +0 -1
- package/.github/funding.yml +0 -2
- package/.github/workflows/ci.yml +0 -36
- package/database.sqlite +0 -0
- package/frontend/assets/mockups/charts_1_bars_1200.webp +0 -0
- package/frontend/assets/mockups/charts_2_pie_1200.webp +0 -0
- package/frontend/assets/mockups/charts_3_scatter_plot_1200.webp +0 -0
- package/frontend/assets/mockups/connections_1200.webp +0 -0
- package/frontend/assets/mockups/data_1_1200.webp +0 -0
- package/frontend/assets/mockups/data_2_row_editor_1200.webp +0 -0
- package/frontend/assets/mockups/documents_1200.webp +0 -0
- package/frontend/assets/mockups/media_tagging_1_setup_1200.webp +0 -0
- package/frontend/assets/mockups/media_tagging_2_tagging_queue_1200.webp +0 -0
- package/frontend/assets/mockups/media_tagging_3_media_viewer_1200.webp +0 -0
- package/frontend/assets/mockups/overview_1200.webp +0 -0
- package/frontend/assets/mockups/settings_1200.webp +0 -0
- package/frontend/assets/mockups/sql_editor_1_1200.webp +0 -0
- package/frontend/assets/mockups/sql_editor_2_query_details_1200.webp +0 -0
- package/frontend/assets/mockups/sql_editor_3_export_column_1200.webp +0 -0
- package/frontend/assets/mockups/sql_editor_4_export_column_as_markdown_1200.webp +0 -0
- package/frontend/assets/mockups/sql_editor_5_export_query_result_1200.webp +0 -0
- package/frontend/assets/mockups/structure_1_1200.webp +0 -0
- package/frontend/assets/mockups/structure_2_inspector_1200.webp +0 -0
- package/frontend/assets/mockups/table_designer_1_1200.webp +0 -0
- package/frontend/assets/mockups/table_designer_2_checks_1200.webp +0 -0
- package/tests/api-token-auth.test.js +0 -279
- package/tests/backup-manager.test.js +0 -140
- package/tests/backups-view.test.js +0 -70
- package/tests/charts-height-preset-storage.test.js +0 -60
- package/tests/charts-route-state.test.js +0 -144
- package/tests/check-constraint-options.test.js +0 -90
- package/tests/cli-args.test.js +0 -113
- package/tests/cli-service-delegation.test.js +0 -140
- package/tests/connection-removal.test.js +0 -52
- package/tests/connections-file-dialog-route.test.js +0 -89
- package/tests/copy-column-modal.test.js +0 -131
- package/tests/database-command-service.test.js +0 -174
- package/tests/database-documents.test.js +0 -85
- package/tests/documents-view.test.js +0 -132
- package/tests/dropdown-button.test.js +0 -101
- package/tests/email-preview.test.js +0 -89
- package/tests/export-blob.test.js +0 -99
- package/tests/export-filenames.test.js +0 -38
- package/tests/file-path-preview.test.js +0 -165
- package/tests/form-controls.test.js +0 -34
- package/tests/json-preview.test.js +0 -49
- package/tests/local-request-security.test.js +0 -85
- package/tests/markdown-documents.test.js +0 -103
- package/tests/native-file-dialog.test.js +0 -105
- package/tests/query-editor.test.js +0 -28
- package/tests/query-history-detail.test.js +0 -37
- package/tests/query-history-header.test.js +0 -30
- package/tests/query-results-truncation.test.js +0 -20
- package/tests/risky-sql.test.js +0 -30
- package/tests/row-editor-json.test.js +0 -82
- package/tests/row-editor-null-values.test.js +0 -184
- package/tests/row-editor-timestamp-preview.test.js +0 -192
- package/tests/security-paths.test.js +0 -84
- package/tests/settings-api-tokens-route.test.js +0 -97
- package/tests/settings-metadata.test.js +0 -114
- package/tests/settings-view.test.js +0 -108
- package/tests/sql-formatter.test.js +0 -173
- package/tests/sql-highlight.test.js +0 -38
- package/tests/sql-identifier-safety.test.js +0 -171
- package/tests/sql-result-limit.test.js +0 -66
- package/tests/structure-view.test.js +0 -60
- package/tests/table-designer-v2-unique-constraints.test.js +0 -78
- package/tests/table-scroll-state.test.js +0 -70
- package/tests/text-cell-stats.test.js +0 -38
|
@@ -100,7 +100,7 @@ export function renderQueryHistoryDetail({
|
|
|
100
100
|
<section class="flex h-full min-h-0 flex-col bg-surface-low">
|
|
101
101
|
<div class="border-b border-outline-variant/10 px-5 py-4">
|
|
102
102
|
<div class="flex items-center justify-between gap-3">
|
|
103
|
-
<span class="font-
|
|
103
|
+
<span class="font-body text-sm font-black uppercase tracking-[0.18em] text-primary-container">
|
|
104
104
|
Query Detail
|
|
105
105
|
</span>
|
|
106
106
|
<button
|
|
@@ -124,7 +124,7 @@ export function renderQueryHistoryDetail({
|
|
|
124
124
|
<section class="flex h-full min-h-0 flex-col bg-surface-low">
|
|
125
125
|
<div class="border-b border-outline-variant/10 px-5 py-4">
|
|
126
126
|
<div class="flex items-center justify-between gap-3">
|
|
127
|
-
<span class="font-
|
|
127
|
+
<span class="font-body text-sm font-black uppercase tracking-[0.18em] text-primary-container">
|
|
128
128
|
Query Detail
|
|
129
129
|
</span>
|
|
130
130
|
<button
|
|
@@ -178,7 +178,7 @@ export function renderQueryHistoryDetail({
|
|
|
178
178
|
'<div class="border-b border-outline-variant/10 px-5 py-4">',
|
|
179
179
|
'<div class="flex items-center justify-between gap-3"><div>',
|
|
180
180
|
'<div class="text-[10px] font-mono uppercase tracking-[0.18em] text-primary-container/70">Query Detail</div>',
|
|
181
|
-
'<h2 class="mt-1 font-
|
|
181
|
+
'<h2 class="mt-1 font-body text-lg font-black uppercase tracking-tight text-on-surface">',
|
|
182
182
|
escapeHtml(item.displayTitle),
|
|
183
183
|
"</h2></div>",
|
|
184
184
|
'<button class="query-history-icon-button" data-action="clear-query-history-selection" type="button"><span class="material-symbols-outlined text-[18px]">close</span></button>',
|
|
@@ -11,7 +11,7 @@ export function renderQueryHistoryHeader({
|
|
|
11
11
|
<div class="flex items-center justify-between gap-3">
|
|
12
12
|
<div class="flex items-center gap-2">
|
|
13
13
|
<span class="material-symbols-outlined text-[18px] text-primary-container">${escapeHtml(icon)}</span>
|
|
14
|
-
<span class="font-
|
|
14
|
+
<span class="font-body text-xs font-black uppercase tracking-[0.18em] text-primary-container">
|
|
15
15
|
${escapeHtml(title)}
|
|
16
16
|
</span>
|
|
17
17
|
</div>
|
|
@@ -114,7 +114,7 @@ export function renderQueryHistoryPanel({
|
|
|
114
114
|
? `
|
|
115
115
|
<div class="flex h-full min-h-[240px] flex-col items-center justify-center px-6 text-center">
|
|
116
116
|
<span class="material-symbols-outlined text-4xl text-on-surface-variant/25">manage_search</span>
|
|
117
|
-
<p class="mt-4 font-
|
|
117
|
+
<p class="mt-4 font-body text-lg font-bold uppercase tracking-tight text-on-surface">
|
|
118
118
|
No Matching Queries
|
|
119
119
|
</p>
|
|
120
120
|
<p class="mt-2 max-w-xs text-sm leading-6 text-on-surface-variant/65">
|
|
@@ -176,6 +176,14 @@ function getFieldTimestampPreview(field = {}, tableMeta = {}) {
|
|
|
176
176
|
});
|
|
177
177
|
}
|
|
178
178
|
|
|
179
|
+
function isNumberInputCompatibleValue(value) {
|
|
180
|
+
if (value === null || value === undefined || value === "") {
|
|
181
|
+
return true;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return /^[-+]?(?:\d+|\d*\.\d+)(?:e[-+]?\d+)?$/i.test(String(value).trim());
|
|
185
|
+
}
|
|
186
|
+
|
|
179
187
|
function renderTimestampPreview(field = {}, tableMeta = {}) {
|
|
180
188
|
const preview = getFieldTimestampPreview(field, tableMeta);
|
|
181
189
|
|
|
@@ -361,7 +369,9 @@ function renderEditableField(field, tableMeta = {}) {
|
|
|
361
369
|
const baseBadges = withCheckBadge(Array.isArray(field.badges) ? field.badges : [], allowedValues);
|
|
362
370
|
const badges = withEmailBadge(withFilePathBadge(withUrlBadge(baseBadges, url), filePathPreview), email);
|
|
363
371
|
const jsonPreview = formatJsonPreview(field.value);
|
|
364
|
-
const
|
|
372
|
+
const canUseNumberInput =
|
|
373
|
+
field.inputType === "number" && isNumberInputCompatibleValue(getFieldRawValue(field));
|
|
374
|
+
const inputType = canUseNumberInput ? "number" : "text";
|
|
365
375
|
const numberStep = field.numberStep === "1" ? "1" : "any";
|
|
366
376
|
const valueState = getRowEditorValueState(getFieldRawValue(field));
|
|
367
377
|
|
|
@@ -577,7 +587,7 @@ export function renderRowEditorPanel({
|
|
|
577
587
|
<div class="text-[10px] font-bold uppercase tracking-[0.2em] text-primary-container">
|
|
578
588
|
${escapeHtml(sectionLabel)}
|
|
579
589
|
</div>
|
|
580
|
-
<h2 class="mt-2 font-
|
|
590
|
+
<h2 class="mt-2 font-body text-3xl font-black uppercase tracking-tight text-primary-container">
|
|
581
591
|
${escapeHtml(title)}
|
|
582
592
|
</h2>
|
|
583
593
|
${
|
|
@@ -647,7 +657,7 @@ export function renderRowEditorPanel({
|
|
|
647
657
|
saveError
|
|
648
658
|
? `
|
|
649
659
|
<div class="border border-error/20 bg-error-container/10 px-4 py-4 text-sm text-on-surface">
|
|
650
|
-
<div class="font-
|
|
660
|
+
<div class="font-body text-xs font-bold uppercase tracking-[0.18em] text-error">
|
|
651
661
|
${escapeHtml(saveError.code)}
|
|
652
662
|
</div>
|
|
653
663
|
<div class="mt-2">${escapeHtml(saveError.message)}</div>
|
|
@@ -3,13 +3,36 @@ import { renderConnectionLogo } from './connectionLogo.js';
|
|
|
3
3
|
|
|
4
4
|
const sidebarItems = [
|
|
5
5
|
{ label: 'Connections', href: '#/connections', key: 'connections', icon: 'database' },
|
|
6
|
-
{ label: 'Overview', href: '#/overview', key: 'overview', icon: 'dashboard' },
|
|
7
6
|
{ label: 'Data', href: '#/data', key: 'data', icon: 'table_rows' },
|
|
8
|
-
{ label: 'Structure', href: '#/structure', key: 'structure', icon: 'account_tree' },
|
|
9
7
|
{ label: 'SQL_Editor', href: '#/editor', key: 'editor', icon: 'terminal' },
|
|
10
|
-
{
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
{
|
|
9
|
+
label: 'SCHEMA',
|
|
10
|
+
key: 'schema',
|
|
11
|
+
icon: 'account_tree',
|
|
12
|
+
children: [
|
|
13
|
+
{ label: 'STRUCTURE', href: '#/structure', key: 'structure' },
|
|
14
|
+
{ label: 'ADVISOR', href: '#/table-advisor', key: 'tableAdvisor' },
|
|
15
|
+
{ label: 'DESIGNER', href: '#/table-designer', key: 'tableDesigner' },
|
|
16
|
+
],
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
label: 'Insights',
|
|
20
|
+
key: 'insights',
|
|
21
|
+
icon: 'monitoring',
|
|
22
|
+
children: [
|
|
23
|
+
{ label: 'CHARTS', href: '#/charts', key: 'charts' },
|
|
24
|
+
{ label: 'OVERVIEW', href: '#/overview', key: 'overview' },
|
|
25
|
+
],
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
label: 'Workspace',
|
|
29
|
+
key: 'workspace',
|
|
30
|
+
icon: 'folder_open',
|
|
31
|
+
children: [
|
|
32
|
+
{ label: 'DOCUMENTS', href: '#/documents', key: 'documents' },
|
|
33
|
+
{ label: 'BACKUPS', href: '#/backups', key: 'backups' },
|
|
34
|
+
],
|
|
35
|
+
},
|
|
13
36
|
{
|
|
14
37
|
label: 'MEDIA_TAGGING',
|
|
15
38
|
key: 'mediaTagging',
|
|
@@ -19,7 +42,6 @@ const sidebarItems = [
|
|
|
19
42
|
{ label: 'TAGGING_QUEUE', href: '#/media-tagging/queue', key: 'mediaTaggingQueue' },
|
|
20
43
|
],
|
|
21
44
|
},
|
|
22
|
-
{ label: 'Backups', href: '#/backups', key: 'backups', icon: 'inventory_2' },
|
|
23
45
|
{ label: 'Settings', href: '#/settings', key: 'settings', icon: 'settings' },
|
|
24
46
|
];
|
|
25
47
|
|
|
@@ -36,6 +58,18 @@ function getActiveSidebarKey(routeName) {
|
|
|
36
58
|
return 'mediaTagging';
|
|
37
59
|
}
|
|
38
60
|
|
|
61
|
+
if (routeName === 'structure' || routeName === 'tableAdvisor' || routeName === 'tableDesigner') {
|
|
62
|
+
return 'schema';
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (routeName === 'charts' || routeName === 'overview') {
|
|
66
|
+
return 'insights';
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (routeName === 'documents' || routeName === 'backups') {
|
|
70
|
+
return 'workspace';
|
|
71
|
+
}
|
|
72
|
+
|
|
39
73
|
return routeName;
|
|
40
74
|
}
|
|
41
75
|
|
|
@@ -140,7 +174,7 @@ function renderConnectionQuickPicker(state) {
|
|
|
140
174
|
|
|
141
175
|
export function renderSidebar(state) {
|
|
142
176
|
const activeKey = getActiveSidebarKey(state.route.name);
|
|
143
|
-
const expandedKey =
|
|
177
|
+
const expandedKey = sidebarItems.some(item => item.key === activeKey && item.children) ? activeKey : null;
|
|
144
178
|
|
|
145
179
|
return `
|
|
146
180
|
<nav class="sidebar-links">
|
|
@@ -3,20 +3,8 @@ export function renderTopNav() {
|
|
|
3
3
|
<div class="top-nav-shell">
|
|
4
4
|
<a class="top-nav-brand" href="#/">SQLite Hub</a>
|
|
5
5
|
<div class="top-nav-actions">
|
|
6
|
-
<button
|
|
7
|
-
class="
|
|
8
|
-
data-action="open-modal"
|
|
9
|
-
data-modal="open-connection"
|
|
10
|
-
type="button"
|
|
11
|
-
aria-label="Open Database"
|
|
12
|
-
>
|
|
13
|
-
<span class="material-symbols-outlined">folder_open</span>
|
|
14
|
-
</button>
|
|
15
|
-
<button class="top-nav-icon" data-action="navigate" data-to="/editor" type="button" aria-label="SQL Editor">
|
|
16
|
-
<span class="material-symbols-outlined">terminal</span>
|
|
17
|
-
</button>
|
|
18
|
-
<button class="top-nav-icon" data-action="navigate" data-to="/settings" type="button" aria-label="Settings">
|
|
19
|
-
<span class="material-symbols-outlined">settings</span>
|
|
6
|
+
<button class="top-nav-icon" data-action="navigate" data-to="/logs" type="button" aria-label="Logs">
|
|
7
|
+
<span class="material-symbols-outlined">receipt_long</span>
|
|
20
8
|
</button>
|
|
21
9
|
</div>
|
|
22
10
|
</div>
|
package/frontend/js/router.js
CHANGED
|
@@ -1,8 +1,29 @@
|
|
|
1
|
+
function decodeRouteValue(value) {
|
|
2
|
+
try {
|
|
3
|
+
return decodeURIComponent(value);
|
|
4
|
+
} catch {
|
|
5
|
+
return value;
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
|
|
1
9
|
export function parseHash(hash = window.location.hash) {
|
|
2
10
|
const normalized = hash.startsWith('#') ? hash.slice(1) : hash;
|
|
3
|
-
const
|
|
11
|
+
const queryIndex = normalized.indexOf('?');
|
|
12
|
+
const pathWithFragment = queryIndex >= 0 ? normalized.slice(0, queryIndex) : normalized;
|
|
13
|
+
const queryWithFragment = queryIndex >= 0 ? normalized.slice(queryIndex + 1) : '';
|
|
14
|
+
const pathFragmentIndex = pathWithFragment.indexOf('#');
|
|
15
|
+
const queryFragmentIndex = queryWithFragment.indexOf('#');
|
|
16
|
+
const pathname =
|
|
17
|
+
pathFragmentIndex >= 0 ? pathWithFragment.slice(0, pathFragmentIndex) : pathWithFragment || '/';
|
|
18
|
+
const routeFragment =
|
|
19
|
+
pathFragmentIndex >= 0
|
|
20
|
+
? pathWithFragment.slice(pathFragmentIndex + 1)
|
|
21
|
+
: queryFragmentIndex >= 0
|
|
22
|
+
? queryWithFragment.slice(queryFragmentIndex + 1)
|
|
23
|
+
: null;
|
|
4
24
|
const cleanPath = pathname || '/';
|
|
5
25
|
const segments = cleanPath.split('/').filter(Boolean);
|
|
26
|
+
const decodedRouteFragment = routeFragment ? decodeRouteValue(routeFragment) : null;
|
|
6
27
|
|
|
7
28
|
if (segments.length === 0) {
|
|
8
29
|
return { name: 'landing', path: '/', params: {} };
|
|
@@ -20,7 +41,7 @@ export function parseHash(hash = window.location.hash) {
|
|
|
20
41
|
name: 'charts',
|
|
21
42
|
path: cleanPath,
|
|
22
43
|
params: {
|
|
23
|
-
historyId: segments[1] ?
|
|
44
|
+
historyId: segments[1] ? decodeRouteValue(segments[1]) : null,
|
|
24
45
|
},
|
|
25
46
|
};
|
|
26
47
|
case 'documents':
|
|
@@ -28,7 +49,7 @@ export function parseHash(hash = window.location.hash) {
|
|
|
28
49
|
name: 'documents',
|
|
29
50
|
path: cleanPath,
|
|
30
51
|
params: {
|
|
31
|
-
documentId: segments[1] ?
|
|
52
|
+
documentId: segments[1] ? decodeRouteValue(segments[1]) : null,
|
|
32
53
|
},
|
|
33
54
|
};
|
|
34
55
|
case 'editor':
|
|
@@ -42,7 +63,8 @@ export function parseHash(hash = window.location.hash) {
|
|
|
42
63
|
name: 'data',
|
|
43
64
|
path: cleanPath,
|
|
44
65
|
params: {
|
|
45
|
-
tableName: segments[1] ?
|
|
66
|
+
tableName: segments[1] ? decodeRouteValue(segments[1]) : null,
|
|
67
|
+
rowPrimaryKey: decodedRouteFragment,
|
|
46
68
|
},
|
|
47
69
|
};
|
|
48
70
|
case 'structure':
|
|
@@ -50,7 +72,7 @@ export function parseHash(hash = window.location.hash) {
|
|
|
50
72
|
name: 'structure',
|
|
51
73
|
path: cleanPath,
|
|
52
74
|
params: {
|
|
53
|
-
tableName: segments[1] ?
|
|
75
|
+
tableName: segments[1] ? decodeRouteValue(segments[1]) : null,
|
|
54
76
|
},
|
|
55
77
|
};
|
|
56
78
|
case 'table-designer':
|
|
@@ -59,7 +81,15 @@ export function parseHash(hash = window.location.hash) {
|
|
|
59
81
|
path: cleanPath,
|
|
60
82
|
params: {
|
|
61
83
|
isNew: segments[1] === 'new',
|
|
62
|
-
tableName: segments[1] && segments[1] !== 'new' ?
|
|
84
|
+
tableName: segments[1] && segments[1] !== 'new' ? decodeRouteValue(segments[1]) : null,
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
case 'table-advisor':
|
|
88
|
+
return {
|
|
89
|
+
name: 'tableAdvisor',
|
|
90
|
+
path: cleanPath,
|
|
91
|
+
params: {
|
|
92
|
+
tableName: segments[1] ? decodeRouteValue(segments[1]) : null,
|
|
63
93
|
},
|
|
64
94
|
};
|
|
65
95
|
case 'media-tagging':
|
|
@@ -69,6 +99,8 @@ export function parseHash(hash = window.location.hash) {
|
|
|
69
99
|
return { name: 'mediaTaggingSetup', path: '/media-tagging', params: {} };
|
|
70
100
|
case 'settings':
|
|
71
101
|
return { name: 'settings', path: '/settings', params: {} };
|
|
102
|
+
case 'logs':
|
|
103
|
+
return { name: 'logs', path: '/logs', params: {} };
|
|
72
104
|
default:
|
|
73
105
|
return { name: 'notFound', path: cleanPath, params: {} };
|
|
74
106
|
}
|