admindb 1.0.1 → 1.0.3

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.
@@ -1,123 +1,123 @@
1
- <div class="space-y-8">
2
- <!-- Header -->
3
- <div class="flex flex-wrap items-end justify-between gap-4">
4
- <div>
5
- <p class="text-sm font-semibold uppercase tracking-wider text-primary">Overview</p>
6
- <h1 class="mt-1 text-3xl font-extrabold tracking-tight">Database</h1>
7
- <p class="mt-1.5 text-sm text-base-content/55">Browse, edit, and query the connected SQLite database from your browser.</p>
8
- </div>
9
- <div class="flex gap-2">
10
- <a href="{{basePath}}/query" class="btn btn-ghost btn-sm gap-1.5">
11
- <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M13 10V3L4 14h7v7l9-11h-7z" /></svg>
12
- Query
13
- </a>
14
- {{#unless readonly}}
15
- <a href="{{basePath}}/designer" class="btn btn-primary btn-sm gap-1.5">
16
- <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M12 4v16m8-8H4" /></svg>
17
- New table
18
- </a>
19
- {{/unless}}
20
- </div>
21
- </div>
22
-
23
- <!-- Stat cards -->
24
- <div class="grid grid-cols-1 gap-4 sm:grid-cols-2 xl:grid-cols-4">
25
- <div class="stat-card">
26
- <span class="stat-icon bg-primary/10 text-primary">
27
- <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M3 10h18M3 14h18m-9-4v8m-7 0h14a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z" /></svg>
28
- </span>
29
- <div>
30
- <div class="text-2xl font-extrabold tabular-nums">{{tables.length}}</div>
31
- <div class="text-[13px] text-base-content/50">Tables</div>
32
- </div>
33
- </div>
34
- <div class="stat-card">
35
- <span class="stat-icon bg-secondary/10 text-secondary">
36
- <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M9 17v-2m3 2v-4m3 4v-6m2 10H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" /></svg>
37
- </span>
38
- <div>
39
- <div class="text-2xl font-extrabold tabular-nums">{{totalRows}}</div>
40
- <div class="text-[13px] text-base-content/50">Total rows</div>
41
- </div>
42
- </div>
43
- <div class="stat-card">
44
- <span class="stat-icon bg-accent/10 text-accent">
45
- <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M5 3v4M3 5h4M6 17v4m-2-2h4m5-16l2.286 6.857L21 12l-5.714 2.143L13 21l-2.286-6.857L5 12l5.714-2.143L13 3z" /></svg>
46
- </span>
47
- <div>
48
- <div class="text-2xl font-extrabold tabular-nums">{{savedQueries}}</div>
49
- <div class="text-[13px] text-base-content/50">Saved queries</div>
50
- </div>
51
- </div>
52
- <div class="stat-card">
53
- <span class="stat-icon bg-warning/10 text-warning">
54
- <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M4 7v10c0 1.1.9 2 2 2h12a2 2 0 002-2V7M4 7c0-1.1.9-2 2-2h12a2 2 0 012 2M4 7c0 1.1.9 2 2 2h12a2 2 0 002-2" /></svg>
55
- </span>
56
- <div>
57
- <div class="truncate font-mono text-lg font-bold" title="{{dbPath}}">{{dbPath}}</div>
58
- <div class="text-[13px] text-base-content/50">Database file</div>
59
- </div>
60
- </div>
61
- </div>
62
-
63
- <!-- Tables -->
64
- <div>
65
- <div class="mb-3 flex items-center justify-between">
66
- <h2 class="text-lg font-bold">Tables</h2>
67
- <span class="text-sm text-base-content/45">{{tables.length}} total</span>
68
- </div>
69
-
70
- {{#if tables.length}}
71
- <div class="app-card overflow-hidden">
72
- <div class="overflow-x-auto">
73
- <table class="table table-sm">
74
- <thead>
75
- <tr class="bg-base-200/70 text-xs uppercase tracking-wide text-base-content/50">
76
- <th class="font-semibold">Table</th>
77
- <th class="text-right font-semibold">Columns</th>
78
- <th class="text-right font-semibold">Rows</th>
79
- <th class="text-right font-semibold">Actions</th>
80
- </tr>
81
- </thead>
82
- <tbody>
83
- {{#each tables}}
84
- <tr class="group hover:bg-base-200/50">
85
- <td>
86
- <a href="{{../basePath}}/tables/{{this}}" class="inline-flex items-center gap-2.5 font-medium">
87
- <span class="grid h-8 w-8 place-items-center rounded-lg bg-primary/10 text-primary transition-colors group-hover:bg-primary/20">
88
- <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M3 10h18M3 14h18m-9-4v8m-7 0h14a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z" /></svg>
89
- </span>
90
- <span class="font-mono text-[13.5px]">{{this}}</span>
91
- </a>
92
- </td>
93
- <td class="text-right tabular-nums text-base-content/60">{{lookup ../cols this}}</td>
94
- <td class="text-right tabular-nums text-base-content/60">{{lookup ../counts this}}</td>
95
- <td class="text-right">
96
- <a href="{{../basePath}}/tables/{{this}}" class="btn btn-ghost btn-xs gap-1 text-base-content/70 hover:text-primary">
97
- Browse
98
- <svg xmlns="http://www.w3.org/2000/svg" class="h-3.5 w-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M13 7l5 5m0 0l-5 5m5-5H6" /></svg>
99
- </a>
100
- </td>
101
- </tr>
102
- {{/each}}
103
- </tbody>
104
- </table>
105
- </div>
106
- </div>
107
- {{else}}
108
- <div class="empty-state">
109
- <span class="empty-icon">
110
- <svg xmlns="http://www.w3.org/2000/svg" class="h-7 w-7" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M3 10h18M3 14h18m-9-4v8m-7 0h14a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z" /></svg>
111
- </span>
112
- <p class="text-sm font-medium text-base-content/70">No tables yet</p>
113
- <p class="max-w-sm text-sm text-base-content/45">Create one with the table designer, or run a SQL statement in the query editor to get started.</p>
114
- <div class="mt-2 flex gap-2">
115
- {{#unless readonly}}
116
- <a href="{{basePath}}/designer" class="btn btn-primary btn-sm">New table</a>
117
- {{/unless}}
118
- <a href="{{basePath}}/query" class="btn btn-outline btn-sm">Query editor</a>
119
- </div>
120
- </div>
121
- {{/if}}
122
- </div>
123
- </div>
1
+ <div class="space-y-8">
2
+ <!-- Header -->
3
+ <div class="flex flex-wrap items-end justify-between gap-4">
4
+ <div>
5
+ <p class="text-sm font-semibold uppercase tracking-wider text-primary">Overview</p>
6
+ <h1 class="mt-1 text-3xl font-extrabold tracking-tight">Database</h1>
7
+ <p class="mt-1.5 text-sm text-base-content/55">Browse, edit, and query the connected SQLite database from your browser.</p>
8
+ </div>
9
+ <div class="flex gap-2">
10
+ <a href="{{basePath}}/query" class="btn btn-ghost btn-sm gap-1.5">
11
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M13 10V3L4 14h7v7l9-11h-7z" /></svg>
12
+ Query
13
+ </a>
14
+ {{#unless readonly}}
15
+ <a href="{{basePath}}/designer" class="btn btn-primary btn-sm gap-1.5">
16
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M12 4v16m8-8H4" /></svg>
17
+ New table
18
+ </a>
19
+ {{/unless}}
20
+ </div>
21
+ </div>
22
+
23
+ <!-- Stat cards -->
24
+ <div class="grid grid-cols-1 gap-4 sm:grid-cols-2 xl:grid-cols-4">
25
+ <div class="stat-card">
26
+ <span class="stat-icon bg-primary/10 text-primary">
27
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M3 10h18M3 14h18m-9-4v8m-7 0h14a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z" /></svg>
28
+ </span>
29
+ <div>
30
+ <div class="text-2xl font-extrabold tabular-nums">{{tables.length}}</div>
31
+ <div class="text-[13px] text-base-content/50">Tables</div>
32
+ </div>
33
+ </div>
34
+ <div class="stat-card">
35
+ <span class="stat-icon bg-secondary/10 text-secondary">
36
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M9 17v-2m3 2v-4m3 4v-6m2 10H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" /></svg>
37
+ </span>
38
+ <div>
39
+ <div class="text-2xl font-extrabold tabular-nums">{{totalRows}}</div>
40
+ <div class="text-[13px] text-base-content/50">Total rows</div>
41
+ </div>
42
+ </div>
43
+ <div class="stat-card">
44
+ <span class="stat-icon bg-accent/10 text-accent">
45
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M5 3v4M3 5h4M6 17v4m-2-2h4m5-16l2.286 6.857L21 12l-5.714 2.143L13 21l-2.286-6.857L5 12l5.714-2.143L13 3z" /></svg>
46
+ </span>
47
+ <div>
48
+ <div class="text-2xl font-extrabold tabular-nums">{{savedQueries}}</div>
49
+ <div class="text-[13px] text-base-content/50">Saved queries</div>
50
+ </div>
51
+ </div>
52
+ <div class="stat-card">
53
+ <span class="stat-icon bg-warning/10 text-warning">
54
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M4 7v10c0 1.1.9 2 2 2h12a2 2 0 002-2V7M4 7c0-1.1.9-2 2-2h12a2 2 0 012 2M4 7c0 1.1.9 2 2 2h12a2 2 0 002-2" /></svg>
55
+ </span>
56
+ <div>
57
+ <div class="truncate font-mono text-lg font-bold" title="{{dbPath}}">{{dbPath}}</div>
58
+ <div class="text-[13px] text-base-content/50">Database file</div>
59
+ </div>
60
+ </div>
61
+ </div>
62
+
63
+ <!-- Tables -->
64
+ <div>
65
+ <div class="mb-3 flex items-center justify-between">
66
+ <h2 class="text-lg font-bold">Tables</h2>
67
+ <span class="text-sm text-base-content/45">{{tables.length}} total</span>
68
+ </div>
69
+
70
+ {{#if tables.length}}
71
+ <div class="app-card overflow-hidden">
72
+ <div class="overflow-x-auto">
73
+ <table class="table table-sm">
74
+ <thead>
75
+ <tr class="bg-base-200/70 text-xs uppercase tracking-wide text-base-content/50">
76
+ <th class="font-semibold">Table</th>
77
+ <th class="text-right font-semibold">Columns</th>
78
+ <th class="text-right font-semibold">Rows</th>
79
+ <th class="text-right font-semibold">Actions</th>
80
+ </tr>
81
+ </thead>
82
+ <tbody>
83
+ {{#each tables}}
84
+ <tr class="group hover:bg-base-200/50">
85
+ <td>
86
+ <a href="{{../basePath}}/tables/{{this}}" class="inline-flex items-center gap-2.5 font-medium">
87
+ <span class="grid h-8 w-8 place-items-center rounded-lg bg-primary/10 text-primary transition-colors group-hover:bg-primary/20">
88
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M3 10h18M3 14h18m-9-4v8m-7 0h14a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z" /></svg>
89
+ </span>
90
+ <span class="font-mono text-[13.5px]">{{this}}</span>
91
+ </a>
92
+ </td>
93
+ <td class="text-right tabular-nums text-base-content/60">{{lookup ../cols this}}</td>
94
+ <td class="text-right tabular-nums text-base-content/60">{{lookup ../counts this}}</td>
95
+ <td class="text-right">
96
+ <a href="{{../basePath}}/tables/{{this}}" class="btn btn-ghost btn-xs gap-1 text-base-content/70 hover:text-primary">
97
+ Browse
98
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-3.5 w-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M13 7l5 5m0 0l-5 5m5-5H6" /></svg>
99
+ </a>
100
+ </td>
101
+ </tr>
102
+ {{/each}}
103
+ </tbody>
104
+ </table>
105
+ </div>
106
+ </div>
107
+ {{else}}
108
+ <div class="empty-state">
109
+ <span class="empty-icon">
110
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-7 w-7" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M3 10h18M3 14h18m-9-4v8m-7 0h14a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z" /></svg>
111
+ </span>
112
+ <p class="text-sm font-medium text-base-content/70">No tables yet</p>
113
+ <p class="max-w-sm text-sm text-base-content/45">Create one with the table designer, or run a SQL statement in the query editor to get started.</p>
114
+ <div class="mt-2 flex gap-2">
115
+ {{#unless readonly}}
116
+ <a href="{{basePath}}/designer" class="btn btn-primary btn-sm">New table</a>
117
+ {{/unless}}
118
+ <a href="{{basePath}}/query" class="btn btn-outline btn-sm">Query editor</a>
119
+ </div>
120
+ </div>
121
+ {{/if}}
122
+ </div>
123
+ </div>
@@ -1,94 +1,94 @@
1
- <div class="space-y-6">
2
- <!-- Header -->
3
- <div class="flex flex-wrap items-center justify-between gap-3">
4
- <div>
5
- <p class="text-sm font-semibold uppercase tracking-wider text-primary">Workspace</p>
6
- <h1 class="mt-1 text-3xl font-extrabold tracking-tight">Query editor</h1>
7
- <p class="mt-1.5 text-sm text-base-content/55">Run arbitrary SQL — SELECT results render as a table, COUNT gives a summary, and write statements execute.</p>
8
- </div>
9
- <div class="flex flex-wrap gap-2">
10
- {{#unless readonly}}
11
- <button id="save-query" type="button" class="btn btn-outline btn-sm gap-1.5">
12
- <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M8 7H5a2 2 0 00-2 2v9a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-3m-1 4l-3 3m0 0l-3-3m3 3V4" /></svg>
13
- Save query
14
- </button>
15
- {{/unless}}
16
- <button id="run-query" type="button" class="btn btn-primary btn-sm gap-1.5">
17
- <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M14.752 11.168l-3.197-2.132A1 1 0 0010 9.87v4.263a1 1 0 001.555.832l3.197-2.132a1 1 0 000-1.664z" /><path stroke-linecap="round" stroke-linejoin="round" d="M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>
18
- Run
19
- </button>
20
- </div>
21
- </div>
22
-
23
- <!-- Saved queries row -->
24
- <div class="flex flex-wrap items-end gap-3">
25
- <div class="form-control w-full max-w-xs">
26
- <label class="field-label" for="saved-query-select">Saved queries</label>
27
- <select id="saved-query-select" class="field-select">
28
- <option value="">— select a saved query —</option>
29
- {{#each savedQueries}}
30
- <option value="{{this.id}}">{{this.name}}</option>
31
- {{/each}}
32
- </select>
33
- </div>
34
- {{#unless readonly}}
35
- <button id="delete-query" type="button" class="btn btn-ghost btn-sm mb-0.5 text-error" disabled>Delete saved</button>
36
- <div class="form-control w-full max-w-xs">
37
- <label class="field-label" for="save-query-name">Save current SQL as</label>
38
- <div class="join w-full">
39
- <input id="save-query-name" type="text" class="field-input join-item !rounded-r-none" placeholder="query name" autocomplete="off" />
40
- <button id="save-query-inline" type="button" class="btn btn-outline join-item">Save</button>
41
- </div>
42
- </div>
43
- {{/unless}}
44
- </div>
45
-
46
- <!-- Editor -->
47
- <div class="app-card overflow-hidden">
48
- <div class="flex items-center justify-between border-b border-base-200 bg-base-200/40 px-4 py-2.5">
49
- <span class="flex items-center gap-2 text-sm font-semibold text-base-content/60">
50
- <span class="grid h-5 w-5 place-items-center rounded-md bg-primary/10 text-primary">
51
- <svg xmlns="http://www.w3.org/2000/svg" class="h-3.5 w-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M13 10V3L4 14h7v7l9-11h-7z" /></svg>
52
- </span>
53
- query.sql
54
- </span>
55
- <span class="text-[11px] text-base-content/40">Ctrl/⌘ + Enter to run</span>
56
- </div>
57
- <div class="p-3">
58
- <div class="sql-editor-wrap">
59
- <pre id="query-gutter" class="sql-gutter" aria-hidden="true">1</pre>
60
- <textarea id="query-sql" class="sql-input" rows="10" placeholder="SELECT * FROM users WHERE …" spellcheck="false"></textarea>
61
- </div>
62
- <div id="query-message" class="mt-3"></div>
63
- </div>
64
- </div>
65
-
66
- <!-- Results -->
67
- <div id="query-result" class="hidden">
68
- <div class="app-card overflow-hidden">
69
- <div class="flex items-center gap-2 border-b border-base-200 px-4 py-3">
70
- <span id="result-kind" class="grid h-6 w-6 place-items-center rounded-md bg-success/10 text-success">
71
- <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7" /></svg>
72
- </span>
73
- <span id="result-summary" class="text-sm font-medium text-base-content/60"></span>
74
- <div class="ml-auto flex items-center gap-1.5">
75
- <button id="export-csv" type="button" class="btn btn-ghost btn-xs gap-1 text-base-content/70 hover:text-primary" disabled>
76
- <svg xmlns="http://www.w3.org/2000/svg" class="h-3.5 w-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" /></svg>
77
- CSV
78
- </button>
79
- <button id="export-json" type="button" class="btn btn-ghost btn-xs gap-1 text-base-content/70 hover:text-primary" disabled>
80
- <svg xmlns="http://www.w3.org/2000/svg" class="h-3.5 w-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" /></svg>
81
- JSON
82
- </button>
83
- </div>
84
- </div>
85
- <div class="overflow-x-auto">
86
- <table class="table table-sm table-pin-rows">
87
- <thead id="query-result-head" class="bg-base-200/70 text-xs uppercase tracking-wide text-base-content/50"></thead>
88
- <tbody id="query-result-body"></tbody>
89
- </table>
90
- </div>
91
- </div>
92
- </div>
93
- </div>
94
- <script src="{{basePath}}/js/query.js" defer></script>
1
+ <div class="space-y-6">
2
+ <!-- Header -->
3
+ <div class="flex flex-wrap items-center justify-between gap-3">
4
+ <div>
5
+ <p class="text-sm font-semibold uppercase tracking-wider text-primary">Workspace</p>
6
+ <h1 class="mt-1 text-3xl font-extrabold tracking-tight">Query editor</h1>
7
+ <p class="mt-1.5 text-sm text-base-content/55">Run arbitrary SQL — SELECT results render as a table, COUNT gives a summary, and write statements execute.</p>
8
+ </div>
9
+ <div class="flex flex-wrap gap-2">
10
+ {{#unless readonly}}
11
+ <button id="save-query" type="button" class="btn btn-outline btn-sm gap-1.5">
12
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M8 7H5a2 2 0 00-2 2v9a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-3m-1 4l-3 3m0 0l-3-3m3 3V4" /></svg>
13
+ Save query
14
+ </button>
15
+ {{/unless}}
16
+ <button id="run-query" type="button" class="btn btn-primary btn-sm gap-1.5">
17
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M14.752 11.168l-3.197-2.132A1 1 0 0010 9.87v4.263a1 1 0 001.555.832l3.197-2.132a1 1 0 000-1.664z" /><path stroke-linecap="round" stroke-linejoin="round" d="M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>
18
+ Run
19
+ </button>
20
+ </div>
21
+ </div>
22
+
23
+ <!-- Saved queries row -->
24
+ <div class="flex flex-wrap items-end gap-3">
25
+ <div class="form-control w-full max-w-xs">
26
+ <label class="field-label" for="saved-query-select">Saved queries</label>
27
+ <select id="saved-query-select" class="field-select">
28
+ <option value="">— select a saved query —</option>
29
+ {{#each savedQueries}}
30
+ <option value="{{this.id}}">{{this.name}}</option>
31
+ {{/each}}
32
+ </select>
33
+ </div>
34
+ {{#unless readonly}}
35
+ <button id="delete-query" type="button" class="btn btn-ghost btn-sm mb-0.5 text-error" disabled>Delete saved</button>
36
+ <div class="form-control w-full max-w-xs">
37
+ <label class="field-label" for="save-query-name">Save current SQL as</label>
38
+ <div class="join w-full">
39
+ <input id="save-query-name" type="text" class="field-input join-item !rounded-r-none" placeholder="query name" autocomplete="off" />
40
+ <button id="save-query-inline" type="button" class="btn btn-outline join-item">Save</button>
41
+ </div>
42
+ </div>
43
+ {{/unless}}
44
+ </div>
45
+
46
+ <!-- Editor -->
47
+ <div class="app-card overflow-hidden">
48
+ <div class="flex items-center justify-between border-b border-base-200 bg-base-200/40 px-4 py-2.5">
49
+ <span class="flex items-center gap-2 text-sm font-semibold text-base-content/60">
50
+ <span class="grid h-5 w-5 place-items-center rounded-md bg-primary/10 text-primary">
51
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-3.5 w-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M13 10V3L4 14h7v7l9-11h-7z" /></svg>
52
+ </span>
53
+ query.sql
54
+ </span>
55
+ <span class="text-[11px] text-base-content/40">Ctrl/⌘ + Enter to run</span>
56
+ </div>
57
+ <div class="p-3">
58
+ <div class="sql-editor-wrap">
59
+ <pre id="query-gutter" class="sql-gutter" aria-hidden="true">1</pre>
60
+ <textarea id="query-sql" class="sql-input" rows="10" placeholder="SELECT * FROM users WHERE …" spellcheck="false"></textarea>
61
+ </div>
62
+ <div id="query-message" class="mt-3"></div>
63
+ </div>
64
+ </div>
65
+
66
+ <!-- Results -->
67
+ <div id="query-result" class="hidden">
68
+ <div class="app-card overflow-hidden">
69
+ <div class="flex items-center gap-2 border-b border-base-200 px-4 py-3">
70
+ <span id="result-kind" class="grid h-6 w-6 place-items-center rounded-md bg-success/10 text-success">
71
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7" /></svg>
72
+ </span>
73
+ <span id="result-summary" class="text-sm font-medium text-base-content/60"></span>
74
+ <div class="ml-auto flex items-center gap-1.5">
75
+ <button id="export-csv" type="button" class="btn btn-ghost btn-xs gap-1 text-base-content/70 hover:text-primary" disabled>
76
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-3.5 w-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" /></svg>
77
+ CSV
78
+ </button>
79
+ <button id="export-json" type="button" class="btn btn-ghost btn-xs gap-1 text-base-content/70 hover:text-primary" disabled>
80
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-3.5 w-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" /></svg>
81
+ JSON
82
+ </button>
83
+ </div>
84
+ </div>
85
+ <div class="overflow-x-auto">
86
+ <table class="table table-sm table-pin-rows">
87
+ <thead id="query-result-head" class="bg-base-200/70 text-xs uppercase tracking-wide text-base-content/50"></thead>
88
+ <tbody id="query-result-body"></tbody>
89
+ </table>
90
+ </div>
91
+ </div>
92
+ </div>
93
+ </div>
94
+ <script src="{{basePath}}/js/query.js" defer></script>