sqlite-hub 1.1.0 → 1.1.2
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 +17 -196
- package/bin/sqlite-hub.js +7 -2
- package/frontend/js/api.js +60 -0
- package/frontend/js/app.js +140 -10
- package/frontend/js/components/dropdownButton.js +92 -0
- package/frontend/js/components/modal.js +991 -876
- package/frontend/js/components/queryEditor.js +29 -18
- package/frontend/js/components/queryHistoryDetail.js +20 -1
- package/frontend/js/components/queryHistoryHeader.js +3 -2
- package/frontend/js/components/rowEditorPanel.js +1 -0
- package/frontend/js/components/sidebar.js +1 -0
- package/frontend/js/components/structureGraph.js +1 -0
- package/frontend/js/components/tableDesignerEditor.js +23 -42
- package/frontend/js/components/tableDesignerSidebar.js +7 -31
- package/frontend/js/components/tableDesignerSqlPreview.js +2 -1
- package/frontend/js/router.js +2 -0
- package/frontend/js/store.js +407 -38
- package/frontend/js/utils/riskySql.js +165 -0
- package/frontend/js/views/backups.js +176 -0
- package/frontend/js/views/charts.js +12 -11
- package/frontend/js/views/data.js +37 -35
- package/frontend/js/views/documents.js +231 -162
- package/frontend/js/views/mediaTagging.js +6 -5
- package/frontend/js/views/structure.js +47 -43
- package/frontend/js/views/tableDesigner.js +45 -1
- package/frontend/styles/components.css +237 -59
- package/frontend/styles/structure-graph.css +10 -2
- package/frontend/styles/tailwind.generated.css +1 -1
- package/frontend/styles/tokens.css +2 -0
- package/frontend/styles/views.css +84 -41
- package/package.json +2 -1
- package/server/routes/backups.js +120 -0
- package/server/routes/connections.js +26 -3
- package/server/routes/externalApi.js +6 -2
- package/server/server.js +3 -1
- package/server/services/databaseCommandService.js +4 -3
- package/server/services/sqlite/backupService.js +497 -66
- package/server/services/sqlite/connectionManager.js +2 -2
- package/server/services/sqlite/dataBrowserService.js +11 -3
- package/server/services/sqlite/importService.js +25 -0
- package/server/services/sqlite/sqlExecutor.js +2 -0
- package/server/services/storage/appStateStore.js +379 -88
- package/tests/api-token-auth.test.js +45 -2
- package/tests/backup-manager.test.js +140 -0
- package/tests/backups-view.test.js +64 -0
- package/tests/charts-height-preset-storage.test.js +60 -0
- package/tests/charts-route-state.test.js +144 -0
- package/tests/cli-service-delegation.test.js +97 -0
- package/tests/connection-removal.test.js +52 -0
- package/tests/database-command-service.test.js +38 -3
- package/tests/documents-view.test.js +132 -0
- package/tests/dropdown-button.test.js +75 -0
- package/tests/query-editor.test.js +28 -0
- package/tests/query-history-detail.test.js +37 -0
- package/tests/query-history-header.test.js +30 -0
- package/tests/risky-sql.test.js +30 -0
- package/tests/row-editor-null-values.test.js +24 -0
- package/tests/structure-view.test.js +56 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { renderDropdownButton } from '../components/dropdownButton.js';
|
|
1
2
|
import { escapeHtml, formatCompactDateTime, formatNumber } from '../utils/format.js';
|
|
2
3
|
import { renderMarkdownPreview } from '../utils/markdownDocuments.js';
|
|
3
4
|
|
|
@@ -24,7 +25,7 @@ function renderDocumentListItem(item, selectedId) {
|
|
|
24
25
|
|
|
25
26
|
return `
|
|
26
27
|
<button
|
|
27
|
-
class="documents-list-item ${isSelected ? 'is-selected' : ''}"
|
|
28
|
+
class="documents-list-item subnavi-item ${isSelected ? 'is-selected' : ''}"
|
|
28
29
|
data-action="select-document"
|
|
29
30
|
data-document-id="${escapeHtml(item.id)}"
|
|
30
31
|
type="button"
|
|
@@ -42,183 +43,249 @@ function renderDocumentListItem(item, selectedId) {
|
|
|
42
43
|
`;
|
|
43
44
|
}
|
|
44
45
|
|
|
46
|
+
function getFilteredDocuments(items, searchQuery) {
|
|
47
|
+
const normalizedSearch = String(searchQuery ?? '')
|
|
48
|
+
.trim()
|
|
49
|
+
.toLowerCase();
|
|
50
|
+
|
|
51
|
+
if (!normalizedSearch) {
|
|
52
|
+
return items;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return items.filter(item =>
|
|
56
|
+
[item.filename, item.title]
|
|
57
|
+
.filter(Boolean)
|
|
58
|
+
.some(value => String(value).toLowerCase().includes(normalizedSearch)),
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function renderDocumentsSearch(documents) {
|
|
63
|
+
return `
|
|
64
|
+
<label class="table-designer-sidebar__search">
|
|
65
|
+
<span class="material-symbols-outlined text-sm text-on-surface-variant/55">search</span>
|
|
66
|
+
<input
|
|
67
|
+
class="table-designer-sidebar__search-input"
|
|
68
|
+
data-bind="documents-search"
|
|
69
|
+
placeholder="Search documents..."
|
|
70
|
+
spellcheck="false"
|
|
71
|
+
type="search"
|
|
72
|
+
value="${escapeHtml(documents.searchQuery ?? '')}"
|
|
73
|
+
/>
|
|
74
|
+
</label>
|
|
75
|
+
`;
|
|
76
|
+
}
|
|
77
|
+
|
|
45
78
|
function renderDocumentsSidebar(documents) {
|
|
46
79
|
const items = documents.items ?? [];
|
|
80
|
+
const filteredItems = getFilteredDocuments(items, documents.searchQuery);
|
|
47
81
|
|
|
48
82
|
return `
|
|
49
|
-
<aside class="documents-view__sidebar">
|
|
50
|
-
<div class="documents-view__sidebar-header">
|
|
83
|
+
<aside class="documents-view__sidebar subnavi-panel">
|
|
84
|
+
<div class="documents-view__sidebar-header subnavi-header">
|
|
51
85
|
<div>
|
|
52
|
-
<div class="
|
|
53
|
-
|
|
54
|
-
</div>
|
|
55
|
-
<div class="mt-1 font-mono text-xs text-primary-container">${formatNumber(items.length)} files</div>
|
|
86
|
+
<div class="subnavi-header-title">Documents</div>
|
|
87
|
+
<div class="subnavi-header-details">${formatNumber(items.length)} files</div>
|
|
56
88
|
</div>
|
|
57
|
-
<button
|
|
58
|
-
class="icon-button"
|
|
59
|
-
data-action="create-document"
|
|
60
|
-
title="New document"
|
|
61
|
-
type="button"
|
|
62
|
-
${documents.saving ? 'disabled aria-disabled="true"' : ''}
|
|
63
|
-
>
|
|
64
|
-
<span class="material-symbols-outlined">add</span>
|
|
65
|
-
</button>
|
|
66
89
|
</div>
|
|
67
|
-
|
|
90
|
+
${renderDocumentsSearch(documents)}
|
|
91
|
+
<div class="documents-view__sidebar-body subnavi-list custom-scrollbar">
|
|
68
92
|
${
|
|
69
|
-
|
|
70
|
-
?
|
|
71
|
-
: `<div class="documents-list-empty"
|
|
93
|
+
filteredItems.length
|
|
94
|
+
? filteredItems.map(item => renderDocumentListItem(item, documents.selectedId)).join('')
|
|
95
|
+
: `<div class="documents-list-empty">${
|
|
96
|
+
items.length ? 'No documents match the current search.' : 'No documents yet'
|
|
97
|
+
}</div>`
|
|
72
98
|
}
|
|
73
99
|
</div>
|
|
74
100
|
</aside>
|
|
75
101
|
`;
|
|
76
102
|
}
|
|
77
103
|
|
|
78
|
-
function
|
|
104
|
+
function renderDocumentImportFileInput() {
|
|
105
|
+
return `
|
|
106
|
+
<input
|
|
107
|
+
accept=".md,.markdown,text/markdown,text/plain"
|
|
108
|
+
data-bind="document-import-file"
|
|
109
|
+
hidden
|
|
110
|
+
type="file"
|
|
111
|
+
/>
|
|
112
|
+
`;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function renderNewDocumentDropdown(documents, className = '') {
|
|
116
|
+
return `
|
|
117
|
+
<div class="${escapeHtml(className)}">
|
|
118
|
+
${renderDropdownButton({
|
|
119
|
+
disabled: documents.saving,
|
|
120
|
+
icon: 'add',
|
|
121
|
+
label: 'New Document',
|
|
122
|
+
title: 'New document',
|
|
123
|
+
items: [
|
|
124
|
+
{
|
|
125
|
+
action: 'create-document',
|
|
126
|
+
icon: 'draft',
|
|
127
|
+
label: 'Blank Page',
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
action: 'import-document-markdown',
|
|
131
|
+
icon: 'upload_file',
|
|
132
|
+
label: 'Import .md',
|
|
133
|
+
},
|
|
134
|
+
],
|
|
135
|
+
})}
|
|
136
|
+
</div>
|
|
137
|
+
`;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function renderDocumentsPanelToggle(documents) {
|
|
141
|
+
const visible = documents.documentsVisible !== false;
|
|
142
|
+
|
|
143
|
+
return `
|
|
144
|
+
<button
|
|
145
|
+
class="standard-button panel-toggle-button ${visible ? '' : 'is-active'}"
|
|
146
|
+
aria-pressed="${visible ? 'false' : 'true'}"
|
|
147
|
+
data-action="toggle-documents-panel"
|
|
148
|
+
type="button"
|
|
149
|
+
>
|
|
150
|
+
<span class="material-symbols-outlined">${visible ? 'visibility_off' : 'visibility'}</span>
|
|
151
|
+
${visible ? 'Hide Documents' : 'Show Documents'}
|
|
152
|
+
</button>
|
|
153
|
+
`;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function renderDocumentPaneToggle(documents, pane) {
|
|
157
|
+
const isEditor = pane === 'editor';
|
|
158
|
+
const visible = isEditor ? documents.editorVisible : documents.previewVisible;
|
|
159
|
+
const label = `${visible ? 'Hide' : 'Show'} ${isEditor ? 'Editor' : 'Preview'}`;
|
|
160
|
+
const icon = visible ? 'visibility_off' : isEditor ? 'edit_note' : 'visibility';
|
|
161
|
+
|
|
162
|
+
return `
|
|
163
|
+
<button
|
|
164
|
+
class="standard-button panel-toggle-button documents-pane__toggle ${visible ? '' : 'is-active'}"
|
|
165
|
+
aria-pressed="${visible ? 'false' : 'true'}"
|
|
166
|
+
data-action="toggle-document-pane"
|
|
167
|
+
data-pane="${escapeHtml(pane)}"
|
|
168
|
+
type="button"
|
|
169
|
+
>
|
|
170
|
+
<span class="material-symbols-outlined">${icon}</span>
|
|
171
|
+
${label}
|
|
172
|
+
</button>
|
|
173
|
+
`;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function renderDocumentsTitlebar(documents, options = {}) {
|
|
177
|
+
const { showDocumentActions = false, showFilename = true } = options;
|
|
79
178
|
const disabled = documents.saving || documents.detailLoading || !documents.selectedId;
|
|
80
179
|
|
|
81
|
-
return `
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
type="button"
|
|
146
|
-
${disabled ? 'disabled aria-disabled="true"' : ''}
|
|
147
|
-
>
|
|
148
|
-
<span class="material-symbols-outlined">download</span>
|
|
149
|
-
Export .md
|
|
150
|
-
</button>
|
|
151
|
-
<button
|
|
152
|
-
class="standard-button"
|
|
153
|
-
data-action="import-document-markdown"
|
|
154
|
-
type="button"
|
|
155
|
-
${documents.saving ? 'disabled aria-disabled="true"' : ''}
|
|
156
|
-
>
|
|
157
|
-
<span class="material-symbols-outlined">upload_file</span>
|
|
158
|
-
Import .md
|
|
159
|
-
</button>
|
|
160
|
-
</div>
|
|
161
|
-
<div class="documents-toolbar__actions">
|
|
162
|
-
<button
|
|
163
|
-
class="standard-button"
|
|
164
|
-
data-action="delete-document"
|
|
165
|
-
type="button"
|
|
166
|
-
${disabled || documents.deleting ? 'disabled aria-disabled="true"' : ''}
|
|
167
|
-
>
|
|
168
|
-
<span class="material-symbols-outlined">delete</span>
|
|
169
|
-
Delete
|
|
170
|
-
</button>
|
|
171
|
-
<button
|
|
172
|
-
class="signature-button"
|
|
173
|
-
data-action="save-document"
|
|
174
|
-
type="button"
|
|
175
|
-
${disabled || !documents.dirty ? 'disabled aria-disabled="true"' : ''}
|
|
176
|
-
>
|
|
177
|
-
<span class="material-symbols-outlined">save</span>
|
|
178
|
-
${documents.saving ? 'Saving...' : 'Save'}
|
|
179
|
-
</button>
|
|
180
|
-
</div>
|
|
180
|
+
return `
|
|
181
|
+
<div class="documents-titlebar">
|
|
182
|
+
${renderDocumentsPanelToggle(documents)}
|
|
183
|
+
${
|
|
184
|
+
showFilename
|
|
185
|
+
? `
|
|
186
|
+
<label class="documents-filename-field">
|
|
187
|
+
<input
|
|
188
|
+
class="control-input"
|
|
189
|
+
data-bind="document-field"
|
|
190
|
+
data-field="filename"
|
|
191
|
+
name="filename"
|
|
192
|
+
spellcheck="false"
|
|
193
|
+
type="text"
|
|
194
|
+
value="${escapeHtml(documents.draftFilename)}"
|
|
195
|
+
${!documents.selectedId ? 'disabled' : ''}
|
|
196
|
+
/>
|
|
197
|
+
</label>
|
|
198
|
+
`
|
|
199
|
+
: ''
|
|
200
|
+
}
|
|
201
|
+
${renderNewDocumentDropdown(documents, 'documents-create-button')}
|
|
202
|
+
${
|
|
203
|
+
showDocumentActions
|
|
204
|
+
? `
|
|
205
|
+
${renderDropdownButton({
|
|
206
|
+
disabled,
|
|
207
|
+
icon: 'add_box',
|
|
208
|
+
label: 'Insert',
|
|
209
|
+
title: 'Insert content',
|
|
210
|
+
items: [
|
|
211
|
+
{
|
|
212
|
+
action: 'open-document-insert-table-modal',
|
|
213
|
+
icon: 'table_chart',
|
|
214
|
+
label: 'Insert Table',
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
action: 'open-document-insert-note-modal',
|
|
218
|
+
icon: 'note_add',
|
|
219
|
+
label: 'Insert Note',
|
|
220
|
+
},
|
|
221
|
+
],
|
|
222
|
+
})}
|
|
223
|
+
<button
|
|
224
|
+
class="standard-button"
|
|
225
|
+
data-action="export-document-markdown"
|
|
226
|
+
type="button"
|
|
227
|
+
${disabled ? 'disabled aria-disabled="true"' : ''}
|
|
228
|
+
>
|
|
229
|
+
<span class="material-symbols-outlined">download</span>
|
|
230
|
+
Export .md
|
|
231
|
+
</button>
|
|
232
|
+
<button
|
|
233
|
+
class="delete-button"
|
|
234
|
+
data-action="delete-document"
|
|
235
|
+
type="button"
|
|
236
|
+
${disabled || documents.deleting ? 'disabled aria-disabled="true"' : ''}
|
|
237
|
+
>
|
|
238
|
+
<span class="material-symbols-outlined">delete</span>
|
|
239
|
+
Delete
|
|
240
|
+
</button>
|
|
241
|
+
`
|
|
242
|
+
: ''
|
|
243
|
+
}
|
|
181
244
|
</div>
|
|
182
245
|
`;
|
|
183
246
|
}
|
|
184
247
|
|
|
185
248
|
function renderDocumentEditor(documents) {
|
|
186
|
-
if (!documents.editorVisible) {
|
|
187
|
-
return '';
|
|
188
|
-
}
|
|
189
|
-
|
|
190
249
|
return `
|
|
191
|
-
<section class="documents-pane documents-pane--editor">
|
|
250
|
+
<section class="documents-pane documents-pane--editor ${documents.editorVisible ? '' : 'documents-pane--collapsed'}">
|
|
192
251
|
<div class="documents-pane__header">
|
|
193
|
-
|
|
194
|
-
<span>${formatNumber(documents.draftContent.length)} chars</span>
|
|
252
|
+
${renderDocumentPaneToggle(documents, 'editor')}
|
|
253
|
+
<span class="documents-pane__meta">${formatNumber(documents.draftContent.length)} chars</span>
|
|
195
254
|
</div>
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
255
|
+
${
|
|
256
|
+
documents.editorVisible
|
|
257
|
+
? `
|
|
258
|
+
<textarea
|
|
259
|
+
class="documents-editor-input custom-scrollbar"
|
|
260
|
+
data-bind="document-field"
|
|
261
|
+
data-field="content"
|
|
262
|
+
name="content"
|
|
263
|
+
spellcheck="true"
|
|
264
|
+
${!documents.selectedId ? 'disabled' : ''}
|
|
265
|
+
>${escapeHtml(documents.draftContent)}</textarea>
|
|
266
|
+
`
|
|
267
|
+
: ''
|
|
268
|
+
}
|
|
204
269
|
</section>
|
|
205
270
|
`;
|
|
206
271
|
}
|
|
207
272
|
|
|
208
273
|
function renderDocumentPreview(documents) {
|
|
209
|
-
if (!documents.previewVisible) {
|
|
210
|
-
return '';
|
|
211
|
-
}
|
|
212
|
-
|
|
213
274
|
return `
|
|
214
|
-
<section class="documents-pane documents-pane--preview">
|
|
275
|
+
<section class="documents-pane documents-pane--preview ${documents.previewVisible ? '' : 'documents-pane--collapsed'}">
|
|
215
276
|
<div class="documents-pane__header">
|
|
216
|
-
|
|
217
|
-
<span>${escapeHtml(documents.dirty ? 'unsaved' : 'saved')}</span>
|
|
218
|
-
</div>
|
|
219
|
-
<div class="document-markdown-preview custom-scrollbar" data-document-preview>
|
|
220
|
-
${renderMarkdownPreview(documents.draftContent)}
|
|
277
|
+
${renderDocumentPaneToggle(documents, 'preview')}
|
|
278
|
+
<span class="documents-pane__meta">${escapeHtml(documents.dirty ? 'unsaved' : 'saved')}</span>
|
|
221
279
|
</div>
|
|
280
|
+
${
|
|
281
|
+
documents.previewVisible
|
|
282
|
+
? `
|
|
283
|
+
<div class="document-markdown-preview custom-scrollbar" data-document-preview>
|
|
284
|
+
${renderMarkdownPreview(documents.draftContent)}
|
|
285
|
+
</div>
|
|
286
|
+
`
|
|
287
|
+
: ''
|
|
288
|
+
}
|
|
222
289
|
</section>
|
|
223
290
|
`;
|
|
224
291
|
}
|
|
@@ -230,15 +297,7 @@ function renderEmptyDocumentsState(documents) {
|
|
|
230
297
|
<p class="font-headline text-2xl font-black uppercase tracking-tight text-primary-container">
|
|
231
298
|
No Documents
|
|
232
299
|
</p>
|
|
233
|
-
|
|
234
|
-
class="signature-button mt-4"
|
|
235
|
-
data-action="create-document"
|
|
236
|
-
type="button"
|
|
237
|
-
${documents.saving ? 'disabled aria-disabled="true"' : ''}
|
|
238
|
-
>
|
|
239
|
-
<span class="material-symbols-outlined">add</span>
|
|
240
|
-
New Document
|
|
241
|
-
</button>
|
|
300
|
+
${renderNewDocumentDropdown(documents, 'mt-4')}
|
|
242
301
|
</div>
|
|
243
302
|
`;
|
|
244
303
|
}
|
|
@@ -247,6 +306,7 @@ function renderDocumentDetail(documents) {
|
|
|
247
306
|
if (documents.loading && !documents.items.length) {
|
|
248
307
|
return `
|
|
249
308
|
<main class="documents-view__detail">
|
|
309
|
+
${renderDocumentsTitlebar(documents, { showFilename: false })}
|
|
250
310
|
<div class="documents-empty-state">
|
|
251
311
|
<span class="material-symbols-outlined">sync</span>
|
|
252
312
|
<p class="font-headline text-2xl font-black uppercase tracking-tight text-primary-container">
|
|
@@ -260,18 +320,26 @@ function renderDocumentDetail(documents) {
|
|
|
260
320
|
if (!documents.selectedId) {
|
|
261
321
|
return `
|
|
262
322
|
<main class="documents-view__detail">
|
|
323
|
+
${renderDocumentsTitlebar(documents, { showFilename: false })}
|
|
263
324
|
${renderEmptyDocumentsState(documents)}
|
|
264
325
|
</main>
|
|
265
326
|
`;
|
|
266
327
|
}
|
|
267
328
|
|
|
268
|
-
const
|
|
329
|
+
const workspaceClasses = [
|
|
330
|
+
'documents-workspace',
|
|
331
|
+
documents.editorVisible && documents.previewVisible ? 'documents-workspace--split' : '',
|
|
332
|
+
!documents.editorVisible ? 'documents-workspace--editor-collapsed' : '',
|
|
333
|
+
!documents.previewVisible ? 'documents-workspace--preview-collapsed' : '',
|
|
334
|
+
]
|
|
335
|
+
.filter(Boolean)
|
|
336
|
+
.join(' ');
|
|
269
337
|
|
|
270
338
|
return `
|
|
271
339
|
<main class="documents-view__detail">
|
|
272
|
-
${
|
|
340
|
+
${renderDocumentsTitlebar(documents, { showDocumentActions: true })}
|
|
273
341
|
${documents.saveError ? `<div class="documents-error">${escapeHtml(documents.saveError.message)}</div>` : ''}
|
|
274
|
-
<div class="
|
|
342
|
+
<div class="${workspaceClasses}">
|
|
275
343
|
${renderDocumentEditor(documents)}
|
|
276
344
|
${renderDocumentPreview(documents)}
|
|
277
345
|
</div>
|
|
@@ -288,13 +356,14 @@ export function renderDocumentsView(state) {
|
|
|
288
356
|
}
|
|
289
357
|
|
|
290
358
|
const documents = state.documents;
|
|
359
|
+
const documentsVisible = documents.documentsVisible !== false;
|
|
291
360
|
|
|
292
361
|
return {
|
|
293
|
-
main: `<div class="documents-view">
|
|
294
|
-
${
|
|
362
|
+
main: `<div class="documents-view ${documentsVisible ? 'documents-view--with-subnavi' : ''}">
|
|
363
|
+
${renderDocumentImportFileInput()}
|
|
364
|
+
${documentsVisible ? renderDocumentsSidebar(documents) : ''}
|
|
295
365
|
${renderDocumentDetail(documents)}
|
|
296
|
-
</div
|
|
297
|
-
</div>`,
|
|
366
|
+
</div>`,
|
|
298
367
|
panel: '',
|
|
299
368
|
};
|
|
300
369
|
}
|
|
@@ -396,8 +396,8 @@ function renderPreviewMedia(
|
|
|
396
396
|
|
|
397
397
|
const metadata = getWorkflowMetadataEntries(currentItem);
|
|
398
398
|
const toggleLabel = detailsVisible
|
|
399
|
-
? '<span class="material-symbols-outlined">visibility_off</span>
|
|
400
|
-
: 'Show
|
|
399
|
+
? '<span class="material-symbols-outlined">visibility_off</span> Hide Viewer'
|
|
400
|
+
: '<span class="material-symbols-outlined">visibility</span> Show Viewer';
|
|
401
401
|
|
|
402
402
|
return `
|
|
403
403
|
<div class="media-tagging-preview ${detailsVisible ? '' : 'media-tagging-preview--meta-hidden'}">
|
|
@@ -450,11 +450,12 @@ function renderPreviewMedia(
|
|
|
450
450
|
: ''
|
|
451
451
|
}
|
|
452
452
|
<button
|
|
453
|
-
class="standard-button media-tagging-preview__toggle"
|
|
453
|
+
class="standard-button panel-toggle-button media-tagging-preview__toggle ${detailsVisible ? '' : 'is-active'}"
|
|
454
|
+
aria-pressed="${detailsVisible ? 'false' : 'true'}"
|
|
454
455
|
data-action="toggle-media-tagging-current-media"
|
|
455
456
|
data-next-value="${detailsVisible ? 'false' : 'true'}"
|
|
456
|
-
data-expanded-label="
|
|
457
|
-
data-collapsed-label="Show
|
|
457
|
+
data-expanded-label="Hide Viewer"
|
|
458
|
+
data-collapsed-label="Show Viewer"
|
|
458
459
|
aria-expanded="${detailsVisible ? 'true' : 'false'}"
|
|
459
460
|
type="button"
|
|
460
461
|
>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { clearInspector, renderDdlSection, renderInspector } from '../components/structureGraph.js';
|
|
2
|
+
import { renderDropdownButton } from '../components/dropdownButton.js';
|
|
2
3
|
import { escapeHtml, formatNumber } from '../utils/format.js';
|
|
3
4
|
|
|
4
5
|
function renderEntryGroup(title, entries, activeName, options = {}) {
|
|
@@ -22,7 +23,7 @@ function renderEntryGroup(title, entries, activeName, options = {}) {
|
|
|
22
23
|
: '';
|
|
23
24
|
|
|
24
25
|
return [
|
|
25
|
-
'<button class="
|
|
26
|
+
'<button class="subnavi-item border px-3 ',
|
|
26
27
|
compact ? 'py-2.5' : 'py-3',
|
|
27
28
|
' text-left transition-colors ',
|
|
28
29
|
isActive
|
|
@@ -217,10 +218,11 @@ function renderGraphSurface(structure, selectedName, detail, detailLoading, tabl
|
|
|
217
218
|
|
|
218
219
|
return `
|
|
219
220
|
<section class="structure-graph" data-structure-graph-root>
|
|
220
|
-
<div class="structure-graph__toolbar">
|
|
221
|
+
<div class="structure-graph__toolbar workspace-header">
|
|
221
222
|
<div class="structure-graph__toolbar-main">
|
|
222
223
|
<button
|
|
223
|
-
class="${toolbarButtonClass}"
|
|
224
|
+
class="${toolbarButtonClass} panel-toggle-button ${tablesVisible ? '' : 'is-active'}"
|
|
225
|
+
aria-pressed="${tablesVisible ? 'false' : 'true'}"
|
|
224
226
|
data-action="toggle-structure-tables"
|
|
225
227
|
type="button"
|
|
226
228
|
>
|
|
@@ -229,30 +231,31 @@ function renderGraphSurface(structure, selectedName, detail, detailLoading, tabl
|
|
|
229
231
|
</button>
|
|
230
232
|
</div>
|
|
231
233
|
<div class="structure-graph__toolbar-actions">
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
234
|
+
${renderDropdownButton({
|
|
235
|
+
icon: 'format_shapes',
|
|
236
|
+
label: 'Format',
|
|
237
|
+
title: 'Format graph',
|
|
238
|
+
items: [
|
|
239
|
+
{
|
|
240
|
+
action: 'fit',
|
|
241
|
+
actionAttribute: 'data-structure-graph-action',
|
|
242
|
+
icon: 'fit_screen',
|
|
243
|
+
label: 'Fit Graph',
|
|
244
|
+
},
|
|
245
|
+
{
|
|
246
|
+
action: 'relayout',
|
|
247
|
+
actionAttribute: 'data-structure-graph-action',
|
|
248
|
+
icon: 'device_hub',
|
|
249
|
+
label: 'Recalculate Layout',
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
action: 'clear',
|
|
253
|
+
actionAttribute: 'data-structure-graph-action',
|
|
254
|
+
icon: 'close',
|
|
255
|
+
label: 'Clear Selection',
|
|
256
|
+
},
|
|
257
|
+
],
|
|
258
|
+
})}
|
|
256
259
|
<button
|
|
257
260
|
class="${toolbarButtonClass}"
|
|
258
261
|
data-structure-graph-action="open-data"
|
|
@@ -265,7 +268,8 @@ function renderGraphSurface(structure, selectedName, detail, detailLoading, tabl
|
|
|
265
268
|
</div>
|
|
266
269
|
<div class="structure-graph__toolbar-inspector">
|
|
267
270
|
<button
|
|
268
|
-
class="${toolbarButtonClass}"
|
|
271
|
+
class="${toolbarButtonClass} panel-toggle-button"
|
|
272
|
+
aria-pressed="false"
|
|
269
273
|
data-structure-graph-action="toggle-inspector"
|
|
270
274
|
type="button"
|
|
271
275
|
>
|
|
@@ -321,24 +325,24 @@ export function renderStructureView(state) {
|
|
|
321
325
|
${
|
|
322
326
|
tablesVisible
|
|
323
327
|
? `
|
|
324
|
-
<aside class="structure-view__sidebar">
|
|
325
|
-
<div class="structure-view__sidebar-header">
|
|
326
|
-
<div
|
|
327
|
-
Objects
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
328
|
+
<aside class="structure-view__sidebar subnavi-panel">
|
|
329
|
+
<div class="structure-view__sidebar-header subnavi-header">
|
|
330
|
+
<div>
|
|
331
|
+
<div class="subnavi-header-title">Objects</div>
|
|
332
|
+
<div class="subnavi-header-details">
|
|
333
|
+
total ${escapeHtml(
|
|
334
|
+
formatNumber(
|
|
335
|
+
(structure?.grouped?.tables?.length ?? 0) +
|
|
336
|
+
(structure?.grouped?.views?.length ?? 0) +
|
|
337
|
+
(structure?.grouped?.indexes?.length ?? 0) +
|
|
338
|
+
(structure?.grouped?.triggers?.length ?? 0),
|
|
339
|
+
),
|
|
340
|
+
)}
|
|
341
|
+
</div>
|
|
338
342
|
</div>
|
|
339
343
|
</div>
|
|
340
344
|
${renderStructureTableSearch(state)}
|
|
341
|
-
<div class="structure-view__sidebar-body custom-scrollbar">
|
|
345
|
+
<div class="structure-view__sidebar-body subnavi-list custom-scrollbar">
|
|
342
346
|
${
|
|
343
347
|
structure
|
|
344
348
|
? `
|