sqlite-hub 0.7.0 → 0.9.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/changelog.md +25 -0
- package/docs/DESIGN_GUIDELINES.md +36 -0
- package/frontend/index.html +79 -0
- package/frontend/js/api.js +67 -0
- package/frontend/js/app.js +1401 -921
- package/frontend/js/components/connectionCard.js +3 -4
- package/frontend/js/components/emptyState.js +4 -4
- package/frontend/js/components/modal.js +239 -30
- package/frontend/js/components/queryEditor.js +11 -8
- package/frontend/js/components/queryHistoryDetail.js +27 -8
- package/frontend/js/components/queryHistoryPanel.js +6 -5
- package/frontend/js/components/rowEditorPanel.js +84 -58
- package/frontend/js/components/sidebar.js +76 -33
- package/frontend/js/components/structureGraph.js +629 -715
- package/frontend/js/components/tableDesignerEditor.js +9 -8
- package/frontend/js/components/tableDesignerSidebar.js +11 -10
- package/frontend/js/components/tableDesignerSqlPreview.js +61 -30
- package/frontend/js/lib/mediaTaggingDefaults.js +27 -0
- package/frontend/js/router.js +81 -71
- package/frontend/js/store.js +3095 -2165
- package/frontend/js/views/charts.js +68 -40
- package/frontend/js/views/connections.js +5 -17
- package/frontend/js/views/data.js +40 -27
- package/frontend/js/views/editor.js +172 -177
- package/frontend/js/views/mediaTagging.js +861 -0
- package/frontend/js/views/overview.js +149 -10
- package/frontend/js/views/settings.js +2 -2
- package/frontend/js/views/structure.js +74 -70
- package/frontend/js/views/tableDesigner.js +7 -2
- package/frontend/styles/base.css +73 -1
- package/frontend/styles/components.css +105 -105
- package/frontend/styles/structure-graph.css +19 -82
- package/frontend/styles/tokens.css +2 -0
- package/frontend/styles/views.css +823 -30
- package/package.json +1 -1
- package/server/routes/charts.js +4 -1
- package/server/routes/data.js +14 -0
- package/server/routes/mediaTagging.js +166 -0
- package/server/routes/sql.js +1 -0
- package/server/server.js +4 -0
- package/server/services/sqlite/dataBrowserService.js +25 -0
- package/server/services/sqlite/exportService.js +31 -1
- package/server/services/sqlite/mediaTaggingService.js +1689 -0
- package/server/services/sqlite/overviewService.js +68 -0
- package/server/services/storage/appStateStore.js +321 -2
|
@@ -58,7 +58,7 @@ function renderTopTables(overview) {
|
|
|
58
58
|
);
|
|
59
59
|
|
|
60
60
|
return `
|
|
61
|
-
<section class="shell-section
|
|
61
|
+
<section class="shell-section">
|
|
62
62
|
<div class="flex items-center justify-between bg-surface-container-highest px-4 py-2">
|
|
63
63
|
<span class="text-[10px] font-bold uppercase tracking-[0.25em]">Top Tables</span>
|
|
64
64
|
<span class="material-symbols-outlined text-xs text-on-surface-variant">table_rows</span>
|
|
@@ -131,7 +131,7 @@ function renderOperationalSurface(overview) {
|
|
|
131
131
|
? `
|
|
132
132
|
<div class="border-t border-outline-variant/10 px-4 py-3">
|
|
133
133
|
<button
|
|
134
|
-
class="
|
|
134
|
+
class="standard-button"
|
|
135
135
|
data-action="open-overview-in-finder"
|
|
136
136
|
type="button"
|
|
137
137
|
>
|
|
@@ -145,17 +145,154 @@ function renderOperationalSurface(overview) {
|
|
|
145
145
|
`;
|
|
146
146
|
}
|
|
147
147
|
|
|
148
|
+
function pluralize(count, singular, plural = `${singular}s`) {
|
|
149
|
+
return Number(count) === 1 ? singular : plural;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function getSchemaMapNarrative(preview) {
|
|
153
|
+
const relationshipCount = Number(preview.relationshipCount ?? 0);
|
|
154
|
+
const fkClusters = Number(preview.fkClusters ?? 0);
|
|
155
|
+
const isolatedTables = Number(preview.isolatedTables ?? 0);
|
|
156
|
+
const connectedTables = Math.max(0, Number(preview.tableCount ?? 0) - isolatedTables);
|
|
157
|
+
|
|
158
|
+
if (relationshipCount === 0 || fkClusters === 0) {
|
|
159
|
+
return {
|
|
160
|
+
title: "Mostly standalone schema",
|
|
161
|
+
body:
|
|
162
|
+
"There are no meaningful foreign-key groups yet. The Structure view will read more like a list of isolated tables than a connected graph.",
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (isolatedTables === 0) {
|
|
167
|
+
return {
|
|
168
|
+
title: "Connected schema",
|
|
169
|
+
body: `Foreign keys tie the whole schema together in ${formatNumber(
|
|
170
|
+
fkClusters
|
|
171
|
+
)} ${pluralize(fkClusters, "cluster")}. Structure is useful here because dependencies and joins are visible at a glance.`,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return {
|
|
176
|
+
title: "One connected core, several islands",
|
|
177
|
+
body: `${formatNumber(connectedTables)} ${pluralize(
|
|
178
|
+
connectedTables,
|
|
179
|
+
"table"
|
|
180
|
+
)} are connected through foreign keys, while ${formatNumber(
|
|
181
|
+
isolatedTables
|
|
182
|
+
)} ${pluralize(
|
|
183
|
+
isolatedTables,
|
|
184
|
+
"table"
|
|
185
|
+
)} stand alone. Structure helps most when you want to inspect the connected core and ignore the isolated tables.`,
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function renderSchemaMapPreview(overview) {
|
|
190
|
+
const preview = overview.schemaMap ?? {
|
|
191
|
+
tableCount: overview.counts?.tables ?? 0,
|
|
192
|
+
indexCount: overview.counts?.indexes ?? 0,
|
|
193
|
+
relationshipCount: 0,
|
|
194
|
+
fkClusters: 0,
|
|
195
|
+
isolatedTables: 0,
|
|
196
|
+
};
|
|
197
|
+
const narrative = getSchemaMapNarrative(preview);
|
|
198
|
+
const stats = [
|
|
199
|
+
{ label: "FK Links", value: formatNumber(preview.relationshipCount) },
|
|
200
|
+
{ label: "FK Clusters", value: formatNumber(preview.fkClusters) },
|
|
201
|
+
{ label: "Isolated Tables", value: formatNumber(preview.isolatedTables) },
|
|
202
|
+
];
|
|
203
|
+
|
|
204
|
+
return `
|
|
205
|
+
<section class="shell-section overflow-hidden bg-[radial-gradient(circle_at_top_left,rgba(45,250,255,0.12),transparent_34%),radial-gradient(circle_at_bottom_right,rgba(252,227,0,0.12),transparent_42%),linear-gradient(135deg,#1b1b19,#101111)]">
|
|
206
|
+
<div class="flex items-center justify-between border-b border-outline-variant/10 bg-surface-container-highest/60 px-4 py-2">
|
|
207
|
+
<span class="text-[10px] font-bold uppercase tracking-[0.25em]">Schema Map</span>
|
|
208
|
+
<span class="material-symbols-outlined text-xs text-on-surface-variant">account_tree</span>
|
|
209
|
+
</div>
|
|
210
|
+
<div class="space-y-5 p-4">
|
|
211
|
+
<div class="flex flex-col gap-5 xl:flex-row xl:items-end xl:justify-between">
|
|
212
|
+
<div>
|
|
213
|
+
<div class="font-headline text-xl font-black uppercase tracking-tight text-primary-container">
|
|
214
|
+
${escapeHtml(narrative.title)}
|
|
215
|
+
</div>
|
|
216
|
+
<p class="mt-2 max-w-3xl text-sm leading-6 text-on-surface-variant/70">
|
|
217
|
+
${escapeHtml(narrative.body)}
|
|
218
|
+
</p>
|
|
219
|
+
</div>
|
|
220
|
+
<div class="flex justify-start xl:justify-end">
|
|
221
|
+
<button
|
|
222
|
+
class="standard-button"
|
|
223
|
+
data-action="navigate"
|
|
224
|
+
data-to="/structure"
|
|
225
|
+
type="button"
|
|
226
|
+
>
|
|
227
|
+
<span class="material-symbols-outlined text-sm">account_tree</span>
|
|
228
|
+
Open Structure
|
|
229
|
+
</button>
|
|
230
|
+
</div>
|
|
231
|
+
</div>
|
|
232
|
+
<div class="grid grid-cols-1 gap-3 sm:grid-cols-3">
|
|
233
|
+
${stats
|
|
234
|
+
.map(
|
|
235
|
+
(stat) => `
|
|
236
|
+
<div class="border border-outline-variant/10 bg-surface-container-lowest/70 px-3 py-3">
|
|
237
|
+
<div class="text-[9px] font-mono uppercase tracking-[0.18em] text-on-surface-variant/55">
|
|
238
|
+
${escapeHtml(stat.label)}
|
|
239
|
+
</div>
|
|
240
|
+
<div class="mt-2 font-headline text-2xl font-black uppercase tracking-tight text-on-surface">
|
|
241
|
+
${escapeHtml(stat.value)}
|
|
242
|
+
</div>
|
|
243
|
+
</div>
|
|
244
|
+
`
|
|
245
|
+
)
|
|
246
|
+
.join("")}
|
|
247
|
+
</div>
|
|
248
|
+
<div class="border border-outline-variant/10 bg-surface-container-lowest/70 px-4 py-4">
|
|
249
|
+
<div class="text-[10px] font-mono uppercase tracking-[0.18em] text-primary-container/70">
|
|
250
|
+
Why It Helps
|
|
251
|
+
</div>
|
|
252
|
+
<div class="mt-3 grid gap-3 md:grid-cols-3">
|
|
253
|
+
<div class="border border-outline-variant/10 bg-surface-container px-3 py-3">
|
|
254
|
+
<div class="text-[9px] font-mono uppercase tracking-[0.16em] text-on-surface-variant/55">
|
|
255
|
+
FK Links
|
|
256
|
+
</div>
|
|
257
|
+
<div class="mt-2 text-sm leading-6 text-on-surface-variant/70">
|
|
258
|
+
Shows how many actual relationships exist between tables.
|
|
259
|
+
</div>
|
|
260
|
+
</div>
|
|
261
|
+
<div class="border border-outline-variant/10 bg-surface-container px-3 py-3">
|
|
262
|
+
<div class="text-[9px] font-mono uppercase tracking-[0.16em] text-on-surface-variant/55">
|
|
263
|
+
FK Clusters
|
|
264
|
+
</div>
|
|
265
|
+
<div class="mt-2 text-sm leading-6 text-on-surface-variant/70">
|
|
266
|
+
Tells you whether the schema is one connected area or split into separate groups.
|
|
267
|
+
</div>
|
|
268
|
+
</div>
|
|
269
|
+
<div class="border border-outline-variant/10 bg-surface-container px-3 py-3">
|
|
270
|
+
<div class="text-[9px] font-mono uppercase tracking-[0.16em] text-on-surface-variant/55">
|
|
271
|
+
Isolated Tables
|
|
272
|
+
</div>
|
|
273
|
+
<div class="mt-2 text-sm leading-6 text-on-surface-variant/70">
|
|
274
|
+
Highlights how many tables have no FK links and can usually be ignored during relationship analysis.
|
|
275
|
+
</div>
|
|
276
|
+
</div>
|
|
277
|
+
</div>
|
|
278
|
+
</div>
|
|
279
|
+
</div>
|
|
280
|
+
</section>
|
|
281
|
+
`;
|
|
282
|
+
}
|
|
283
|
+
|
|
148
284
|
function renderIntegrityCard(overview, readOnly) {
|
|
149
285
|
return `
|
|
150
|
-
<section class="relative overflow-hidden
|
|
151
|
-
<div class="
|
|
286
|
+
<section class="shell-section relative overflow-hidden bg-[radial-gradient(circle_at_top_right,rgba(252,227,0,0.14),transparent_30%),linear-gradient(135deg,#1c1b1b,#0e0e0e)]">
|
|
287
|
+
<div class="flex items-center justify-between border-b border-outline-variant/10 bg-surface-container-highest/60 px-4 py-2">
|
|
288
|
+
<span class="text-[10px] font-bold uppercase tracking-[0.25em]">Integrity Status</span>
|
|
289
|
+
<span class="material-symbols-outlined text-xs text-on-surface-variant">security</span>
|
|
290
|
+
</div>
|
|
291
|
+
<div class="pointer-events-none absolute inset-x-0 bottom-0 top-10 bg-[linear-gradient(to_top,rgba(32,31,31,0.95),rgba(32,31,31,0.2))]"></div>
|
|
152
292
|
<div class="relative flex min-h-[220px] flex-col justify-end p-6">
|
|
153
293
|
<div class="mb-6 flex h-16 w-16 items-center justify-center border border-primary-container/20 bg-primary-container/10">
|
|
154
294
|
<span class="material-symbols-outlined text-4xl text-primary-container">security</span>
|
|
155
295
|
</div>
|
|
156
|
-
<div class="text-[10px] font-black uppercase tracking-[0.25em] text-primary-container">
|
|
157
|
-
INTEGRITY_STATUS
|
|
158
|
-
</div>
|
|
159
296
|
<div class="mt-2 flex flex-wrap items-center gap-2">
|
|
160
297
|
${renderStatusBadge(overview.sqlite?.integrityCheck ?? "unknown", "success")}
|
|
161
298
|
${renderStatusBadge(
|
|
@@ -190,10 +327,9 @@ export function renderOverviewView(state) {
|
|
|
190
327
|
: "System Registry: NO_ACTIVE_DATABASE",
|
|
191
328
|
actions: `
|
|
192
329
|
<button
|
|
193
|
-
class="
|
|
330
|
+
class="signature-button"
|
|
194
331
|
data-action="navigate"
|
|
195
332
|
data-to="/editor"
|
|
196
|
-
style="--clip-path: polygon(0 0, calc(100% - 12px) 0, 100% 12px, 100% 100%, 0 100%);"
|
|
197
333
|
type="button"
|
|
198
334
|
>
|
|
199
335
|
<span class="material-symbols-outlined text-sm">terminal</span>
|
|
@@ -218,7 +354,10 @@ export function renderOverviewView(state) {
|
|
|
218
354
|
? `
|
|
219
355
|
${renderOverviewMetrics(overview)}
|
|
220
356
|
<div class="grid grid-cols-1 gap-6 xl:grid-cols-3">
|
|
221
|
-
|
|
357
|
+
<div class="space-y-6 xl:col-span-2">
|
|
358
|
+
${renderTopTables(overview)}
|
|
359
|
+
${renderSchemaMapPreview(overview)}
|
|
360
|
+
</div>
|
|
222
361
|
<div class="space-y-6">
|
|
223
362
|
${renderOperationalSurface(overview)}
|
|
224
363
|
${renderIntegrityCard(overview, readOnly)}
|
|
@@ -56,7 +56,7 @@ function renderSettingsContent(state) {
|
|
|
56
56
|
Copyright Oliver Jessner
|
|
57
57
|
</div>
|
|
58
58
|
<a
|
|
59
|
-
class="
|
|
59
|
+
class="standard-button"
|
|
60
60
|
href="https://oliverjessner.at"
|
|
61
61
|
rel="noreferrer"
|
|
62
62
|
target="_blank"
|
|
@@ -77,7 +77,7 @@ function renderSettingsContent(state) {
|
|
|
77
77
|
Open Source Code
|
|
78
78
|
</div>
|
|
79
79
|
<a
|
|
80
|
-
class="
|
|
80
|
+
class="standard-button"
|
|
81
81
|
href="https://github.com/oliverjessner/sqlite-hub"
|
|
82
82
|
rel="noreferrer"
|
|
83
83
|
target="_blank"
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { clearInspector, renderInspector } from "../components/structureGraph.js";
|
|
1
|
+
import { clearInspector, renderDdlSection, renderInspector } from "../components/structureGraph.js";
|
|
2
2
|
import { escapeHtml, formatNumber } from "../utils/format.js";
|
|
3
3
|
|
|
4
4
|
function renderEntryGroup(title, entries, activeName, options = {}) {
|
|
@@ -172,20 +172,16 @@ function renderObjectInspector(detail) {
|
|
|
172
172
|
: ""
|
|
173
173
|
}
|
|
174
174
|
|
|
175
|
-
|
|
176
|
-
<div class="structure-graph__section-title">DDL</div>
|
|
177
|
-
<pre class="structure-graph__ddl custom-scrollbar">${escapeHtml(
|
|
178
|
-
detail.ddl || "No DDL available."
|
|
179
|
-
)}</pre>
|
|
180
|
-
</section>
|
|
175
|
+
${renderDdlSection(detail.ddl)}
|
|
181
176
|
</div>
|
|
182
177
|
`;
|
|
183
178
|
}
|
|
184
179
|
|
|
185
|
-
function renderGraphSurface(structure, selectedName, detail, detailLoading) {
|
|
180
|
+
function renderGraphSurface(structure, selectedName, detail, detailLoading, tablesVisible = true) {
|
|
186
181
|
const graph = structure?.graph ?? { tables: [], relationshipCount: 0 };
|
|
187
182
|
const selectedGraphTable =
|
|
188
183
|
graph.tables?.find((table) => table.name === selectedName && table.type === "table") ?? null;
|
|
184
|
+
const toolbarButtonClass = "standard-button";
|
|
189
185
|
const inspectorMarkup = selectedGraphTable
|
|
190
186
|
? renderInspector(selectedGraphTable)
|
|
191
187
|
: detailLoading
|
|
@@ -198,20 +194,20 @@ function renderGraphSurface(structure, selectedName, detail, detailLoading) {
|
|
|
198
194
|
<section class="structure-graph" data-structure-graph-root>
|
|
199
195
|
<div class="structure-graph__toolbar">
|
|
200
196
|
<div class="structure-graph__toolbar-main">
|
|
201
|
-
<
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
</
|
|
197
|
+
<button
|
|
198
|
+
class="${toolbarButtonClass}"
|
|
199
|
+
data-action="toggle-structure-tables"
|
|
200
|
+
type="button"
|
|
201
|
+
>
|
|
202
|
+
<span class="material-symbols-outlined text-sm">${
|
|
203
|
+
tablesVisible ? "visibility_off" : "visibility"
|
|
204
|
+
}</span>
|
|
205
|
+
${tablesVisible ? "Hide Tables" : "Show Tables"}
|
|
206
|
+
</button>
|
|
211
207
|
</div>
|
|
212
208
|
<div class="structure-graph__toolbar-actions">
|
|
213
209
|
<button
|
|
214
|
-
class="
|
|
210
|
+
class="${toolbarButtonClass}"
|
|
215
211
|
data-structure-graph-action="fit"
|
|
216
212
|
type="button"
|
|
217
213
|
>
|
|
@@ -219,7 +215,7 @@ function renderGraphSurface(structure, selectedName, detail, detailLoading) {
|
|
|
219
215
|
Fit Graph
|
|
220
216
|
</button>
|
|
221
217
|
<button
|
|
222
|
-
class="
|
|
218
|
+
class="${toolbarButtonClass}"
|
|
223
219
|
data-structure-graph-action="relayout"
|
|
224
220
|
type="button"
|
|
225
221
|
>
|
|
@@ -227,7 +223,7 @@ function renderGraphSurface(structure, selectedName, detail, detailLoading) {
|
|
|
227
223
|
Recalculate Layout
|
|
228
224
|
</button>
|
|
229
225
|
<button
|
|
230
|
-
class="
|
|
226
|
+
class="${toolbarButtonClass}"
|
|
231
227
|
data-structure-graph-action="clear"
|
|
232
228
|
type="button"
|
|
233
229
|
>
|
|
@@ -235,7 +231,7 @@ function renderGraphSurface(structure, selectedName, detail, detailLoading) {
|
|
|
235
231
|
Clear Selection
|
|
236
232
|
</button>
|
|
237
233
|
<button
|
|
238
|
-
class="
|
|
234
|
+
class="${toolbarButtonClass}"
|
|
239
235
|
data-structure-graph-action="open-data"
|
|
240
236
|
disabled
|
|
241
237
|
type="button"
|
|
@@ -244,7 +240,7 @@ function renderGraphSurface(structure, selectedName, detail, detailLoading) {
|
|
|
244
240
|
Open Data
|
|
245
241
|
</button>
|
|
246
242
|
<button
|
|
247
|
-
class="
|
|
243
|
+
class="${toolbarButtonClass}"
|
|
248
244
|
data-structure-graph-action="toggle-inspector"
|
|
249
245
|
type="button"
|
|
250
246
|
>
|
|
@@ -310,57 +306,64 @@ export function renderStructureView(state) {
|
|
|
310
306
|
const structure = state.structure.data;
|
|
311
307
|
const detail =
|
|
312
308
|
state.structure.detail?.name === state.structure.selectedName ? state.structure.detail : null;
|
|
309
|
+
const tablesVisible = state.structure.tablesVisible !== false;
|
|
313
310
|
|
|
314
311
|
return {
|
|
315
312
|
main: `
|
|
316
313
|
<section class="view-surface structure-view">
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
(
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
<div class="structure-view__sidebar-body custom-scrollbar">
|
|
334
|
-
${
|
|
335
|
-
structure
|
|
336
|
-
? `
|
|
337
|
-
${renderEntryGroup(
|
|
338
|
-
"Tables",
|
|
339
|
-
structure.grouped.tables,
|
|
340
|
-
state.structure.selectedName,
|
|
341
|
-
{ compact: true, showMeta: false }
|
|
342
|
-
)}
|
|
343
|
-
${renderEntryGroup(
|
|
344
|
-
"Views",
|
|
345
|
-
structure.grouped.views,
|
|
346
|
-
state.structure.selectedName
|
|
347
|
-
)}
|
|
348
|
-
${renderEntryGroup(
|
|
349
|
-
"Indexes",
|
|
350
|
-
structure.grouped.indexes,
|
|
351
|
-
state.structure.selectedName,
|
|
352
|
-
{ compact: true, showMeta: false }
|
|
353
|
-
)}
|
|
354
|
-
${renderEntryGroup(
|
|
355
|
-
"Triggers",
|
|
356
|
-
structure.grouped.triggers,
|
|
357
|
-
state.structure.selectedName
|
|
314
|
+
${
|
|
315
|
+
tablesVisible
|
|
316
|
+
? `
|
|
317
|
+
<aside class="structure-view__sidebar">
|
|
318
|
+
<div class="structure-view__sidebar-header">
|
|
319
|
+
<div class="text-[10px] font-bold uppercase tracking-[0.2em] text-primary-container">
|
|
320
|
+
Objects
|
|
321
|
+
</div>
|
|
322
|
+
<div class="mt-2 text-[10px] font-mono uppercase tracking-[0.16em] text-on-surface-variant/55">
|
|
323
|
+
total ${escapeHtml(
|
|
324
|
+
formatNumber(
|
|
325
|
+
(structure?.grouped?.tables?.length ?? 0) +
|
|
326
|
+
(structure?.grouped?.views?.length ?? 0) +
|
|
327
|
+
(structure?.grouped?.indexes?.length ?? 0) +
|
|
328
|
+
(structure?.grouped?.triggers?.length ?? 0)
|
|
329
|
+
)
|
|
358
330
|
)}
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
331
|
+
</div>
|
|
332
|
+
</div>
|
|
333
|
+
<div class="structure-view__sidebar-body custom-scrollbar">
|
|
334
|
+
${
|
|
335
|
+
structure
|
|
336
|
+
? `
|
|
337
|
+
${renderEntryGroup(
|
|
338
|
+
"Tables",
|
|
339
|
+
structure.grouped.tables,
|
|
340
|
+
state.structure.selectedName,
|
|
341
|
+
{ compact: true, showMeta: false }
|
|
342
|
+
)}
|
|
343
|
+
${renderEntryGroup(
|
|
344
|
+
"Views",
|
|
345
|
+
structure.grouped.views,
|
|
346
|
+
state.structure.selectedName
|
|
347
|
+
)}
|
|
348
|
+
${renderEntryGroup(
|
|
349
|
+
"Indexes",
|
|
350
|
+
structure.grouped.indexes,
|
|
351
|
+
state.structure.selectedName,
|
|
352
|
+
{ compact: true, showMeta: false }
|
|
353
|
+
)}
|
|
354
|
+
${renderEntryGroup(
|
|
355
|
+
"Triggers",
|
|
356
|
+
structure.grouped.triggers,
|
|
357
|
+
state.structure.selectedName
|
|
358
|
+
)}
|
|
359
|
+
`
|
|
360
|
+
: ""
|
|
361
|
+
}
|
|
362
|
+
</div>
|
|
363
|
+
</aside>
|
|
364
|
+
`
|
|
365
|
+
: ""
|
|
366
|
+
}
|
|
364
367
|
|
|
365
368
|
<section class="structure-view__detail">
|
|
366
369
|
${renderStructureWorkspaceHeader(structure, state.structure.selectedName)}
|
|
@@ -390,7 +393,8 @@ export function renderStructureView(state) {
|
|
|
390
393
|
structure,
|
|
391
394
|
state.structure.selectedName,
|
|
392
395
|
detail,
|
|
393
|
-
state.structure.detailLoading
|
|
396
|
+
state.structure.detailLoading,
|
|
397
|
+
tablesVisible
|
|
394
398
|
)}
|
|
395
399
|
</div>
|
|
396
400
|
`
|
|
@@ -26,8 +26,13 @@ export function renderTableDesignerView(state) {
|
|
|
26
26
|
<div class="table-designer-workspace__top">
|
|
27
27
|
${renderTableDesignerEditor(state)}
|
|
28
28
|
</div>
|
|
29
|
-
<div class="table-designer-workspace__bottom
|
|
30
|
-
|
|
29
|
+
<div class="table-designer-workspace__bottom${
|
|
30
|
+
state.tableDesigner.sqlPreviewVisible ? "" : " is-collapsed"
|
|
31
|
+
}">
|
|
32
|
+
${renderTableDesignerSqlPreview(
|
|
33
|
+
state.tableDesigner.draft,
|
|
34
|
+
state.tableDesigner.sqlPreviewVisible
|
|
35
|
+
)}
|
|
31
36
|
</div>
|
|
32
37
|
</div>
|
|
33
38
|
</section>
|
package/frontend/styles/base.css
CHANGED
|
@@ -28,6 +28,72 @@ button {
|
|
|
28
28
|
cursor: pointer;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
.control-button {
|
|
32
|
+
align-items: center;
|
|
33
|
+
box-sizing: border-box;
|
|
34
|
+
display: inline-flex;
|
|
35
|
+
gap: var(--spacing-2);
|
|
36
|
+
height: var(--control-height);
|
|
37
|
+
line-height: 1;
|
|
38
|
+
min-height: var(--control-height);
|
|
39
|
+
padding: 0 var(--control-padding-inline);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.control-input,
|
|
43
|
+
.control-select {
|
|
44
|
+
box-sizing: border-box;
|
|
45
|
+
height: var(--control-height);
|
|
46
|
+
min-height: var(--control-height);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.control-input {
|
|
50
|
+
padding: 0 var(--control-padding-inline);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
input.control-input--ghost {
|
|
54
|
+
appearance: none;
|
|
55
|
+
background: transparent !important;
|
|
56
|
+
background-color: transparent !important;
|
|
57
|
+
background-image: none !important;
|
|
58
|
+
border: 0 !important;
|
|
59
|
+
border-color: transparent !important;
|
|
60
|
+
box-shadow: none !important;
|
|
61
|
+
-webkit-appearance: none;
|
|
62
|
+
padding: 0;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
input.control-input--ghost:focus,
|
|
66
|
+
input.control-input--ghost:not(:focus) {
|
|
67
|
+
background: transparent !important;
|
|
68
|
+
background-color: transparent !important;
|
|
69
|
+
border-color: transparent !important;
|
|
70
|
+
box-shadow: none !important;
|
|
71
|
+
outline: none;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.control-select {
|
|
75
|
+
padding: 0 var(--control-padding-inline);
|
|
76
|
+
-webkit-appearance: menulist;
|
|
77
|
+
-moz-appearance: menulist;
|
|
78
|
+
appearance: auto;
|
|
79
|
+
background-image: none;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.control-shell {
|
|
83
|
+
box-sizing: border-box;
|
|
84
|
+
min-height: var(--control-height);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.control-icon-button {
|
|
88
|
+
align-items: center;
|
|
89
|
+
box-sizing: border-box;
|
|
90
|
+
display: inline-flex;
|
|
91
|
+
height: var(--control-height);
|
|
92
|
+
justify-content: center;
|
|
93
|
+
min-height: var(--control-height);
|
|
94
|
+
width: var(--control-height);
|
|
95
|
+
}
|
|
96
|
+
|
|
31
97
|
a {
|
|
32
98
|
color: inherit;
|
|
33
99
|
text-decoration: none;
|
|
@@ -133,6 +199,7 @@ img {
|
|
|
133
199
|
|
|
134
200
|
.query-editor-layer {
|
|
135
201
|
display: grid;
|
|
202
|
+
height: 100%;
|
|
136
203
|
min-height: 140px;
|
|
137
204
|
overflow: hidden;
|
|
138
205
|
}
|
|
@@ -155,7 +222,7 @@ img {
|
|
|
155
222
|
|
|
156
223
|
.query-editor-highlight {
|
|
157
224
|
color: var(--color-on-surface);
|
|
158
|
-
overflow:
|
|
225
|
+
overflow: visible;
|
|
159
226
|
pointer-events: none;
|
|
160
227
|
}
|
|
161
228
|
|
|
@@ -169,6 +236,11 @@ img {
|
|
|
169
236
|
overflow: auto;
|
|
170
237
|
}
|
|
171
238
|
|
|
239
|
+
.query-editor-gutter-track {
|
|
240
|
+
min-height: 100%;
|
|
241
|
+
will-change: transform;
|
|
242
|
+
}
|
|
243
|
+
|
|
172
244
|
.query-editor-input::placeholder {
|
|
173
245
|
color: transparent;
|
|
174
246
|
}
|