Skip to content

Commit f203b85

Browse files
committed
feat(QueryHistory): Enhance query deletion and integrate history management in DeploymentPage
1 parent 30126c4 commit f203b85

File tree

3 files changed

+55
-52
lines changed

3 files changed

+55
-52
lines changed

web/components/Filtre.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ export const FilterMenu = (
120120
<Filter class='h-4 w-4' />
121121
Filters
122122
</summary>
123-
<div class='dropdown-content z-10 w-110 mt-2'>
123+
<div class='dropdown-content w-110 mt-2'>
124124
<div class='bg-base-100 rounded-box shadow border border-base-300 p-3 space-y-3'>
125125
<div class='space-y-2 max-h-72 overflow-y-auto pr-1'>
126126
{rows.map((r) => (
@@ -201,7 +201,7 @@ export const SortMenu = ({ tag, sortKeyOptions }: {
201201
<ArrowUpDown class='h-4 w-4' />
202202
Sort
203203
</summary>
204-
<div class='dropdown-content z-10 w-80 mt-2'>
204+
<div class='dropdown-content w-80 mt-2'>
205205
<div class='bg-base-100 rounded-box shadow border border-base-300 p-3 space-y-3'>
206206
<div class='space-y-2 max-h-60 overflow-y-auto pr-1'>
207207
{rows.map((r) => (

web/components/QueryHistory.tsx

Lines changed: 14 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,29 @@
11
import { ChevronRight, Clock, Play, Search, Trash2 } from 'lucide-preact'
22
import { A } from '../lib/router.tsx'
3+
import { onRun, queriesHistory } from '../pages/DeploymentPage.tsx'
4+
import { log } from 'node:console'
35

4-
interface QueryHistoryItem {
6+
export type QueryHistoryItem = {
57
query: string
68
timestamp: string
79
columns?: number
810
rows?: number
911
}
1012

11-
const deleteQuery = (_hash: string) => {
12-
// TODO: implement delete functionality
13+
const deleteQuery = (hash: string) => {
14+
const updatedHistory = { ...queriesHistory.value }
15+
delete updatedHistory[hash]
16+
queriesHistory.value = updatedHistory
1317
}
1418

1519
export function QueryHistory({
1620
onRunQuery,
1721
}: {
1822
onRunQuery?: (query: string) => void
1923
}) {
20-
const filteredHistory = [
21-
{
22-
query: 'SELECT * FROM users;',
23-
timestamp: '2024-06-01T12:00:00Z',
24-
columns: 5,
25-
rows: 100,
26-
},
27-
{
28-
query: 'SELECT id, name FROM products WHERE price > 100;',
29-
timestamp: '2024-06-02T15:30:00Z',
30-
columns: 2,
31-
rows: 50,
32-
},
33-
{
34-
query: 'UPDATE orders SET status = "shipped" WHERE id = 123;',
35-
timestamp: '2024-06-03T09:45:00Z',
36-
columns: 1,
37-
rows: 1,
38-
},
39-
]
24+
const filteredHistory = Object.entries(queriesHistory.value).sort((a, b) =>
25+
new Date(b[1].timestamp).getTime() - new Date(a[1].timestamp).getTime()
26+
)
4027

4128
return (
4229
<div class='flex flex-col h-full'>
@@ -52,9 +39,9 @@ export function QueryHistory({
5239
</div>
5340
</div>
5441
<div class='flex-1 overflow-y-auto'>
55-
{filteredHistory.map((item, index) => (
42+
{filteredHistory.map(([hash, item]) => (
5643
<div
57-
key={index}
44+
key={hash}
5845
class='p-4 border-b border-base-300 hover:bg-base-200'
5946
>
6047
<div class='flex items-center justify-between'>
@@ -75,8 +62,7 @@ export function QueryHistory({
7562
type='button'
7663
class='btn btn-xs btn-ghost'
7764
title='Run query'
78-
onClick={() =>
79-
onRunQuery ? onRunQuery(item.query) : undefined}
65+
onClick={() => onRun(item.query)}
8066
>
8167
<Play class='w-4 h-4' />
8268
</button>
@@ -92,7 +78,7 @@ export function QueryHistory({
9278
class='btn btn-xs btn-ghost text-error'
9379
title='Delete from history'
9480
disabled={!deleteQuery}
95-
onClick={() => deleteQuery(item.timestamp)}
81+
onClick={() => deleteQuery(hash)}
9682
>
9783
<Trash2 class='w-4 h-4' />
9884
</button>

web/pages/DeploymentPage.tsx

Lines changed: 39 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import {
1010
Download,
1111
Eye,
1212
FileText,
13-
History,
1413
Info,
1514
MoreHorizontal,
1615
Play,
@@ -30,7 +29,9 @@ import {
3029
} from '../components/Filtre.tsx'
3130
import { effect, Signal } from '@preact/signals'
3231
import { api } from '../lib/api.ts'
33-
import { QueryHistory } from '../components/QueryHistory.tsx'
32+
import { QueryHistory, QueryHistoryItem } from '../components/QueryHistory.tsx'
33+
import { jsx } from 'preact/compat/jsx-dev-runtime'
34+
import { JSX } from 'preact'
3435

3536
type AnyRecord = Record<string, unknown>
3637

@@ -50,7 +51,7 @@ const comparators = {
5051

5152
const tableData = api['POST/api/deployment/table/data'].signal()
5253
const querier = api['GET/api/deployment/query'].signal()
53-
const queriesHistory = new Signal<AnyRecord>(
54+
export const queriesHistory = new Signal<Record<string, QueryHistoryItem>>(
5455
JSON.parse(localStorage.getItem('savedQueries') || '{}'),
5556
)
5657
type Order = 'ASC' | 'DESC'
@@ -112,18 +113,19 @@ effect(() => {
112113
}
113114
})
114115

115-
const onRun = () => {
116+
export const onRun = (query?: string) => {
116117
if (querier.pending) return
117118
const { dep, tab, q } = url.params
118-
if (dep && tab === 'queries' && q) {
119-
querier.fetch({ deployment: dep, sql: q })
119+
if (dep && tab === 'queries' && (query || q)) {
120+
querier.fetch({ deployment: dep, sql: query || q || '' })
120121
}
121122
}
122123

123124
function sha(message: string) {
124125
const data = new TextEncoder().encode(message)
125126
return crypto.subtle.digest('SHA-1', data)
126127
}
128+
127129
function hashQuery(query: string) {
128130
const hash = sha(query).then((hashBuffer) => {
129131
const hashArray = Array.from(new Uint8Array(hashBuffer))
@@ -138,10 +140,14 @@ function hashQuery(query: string) {
138140
const onSave = () => {
139141
const query = (url.params.q || '').trim()
140142
if (query) {
141-
console.log('queryHash', queryHash.value)
142-
143143
if (!queryHash.value) return
144-
queriesHistory.value = { ...queriesHistory.value, [queryHash.value]: query }
144+
queriesHistory.value = {
145+
...queriesHistory.value,
146+
[queryHash.value]: {
147+
query,
148+
timestamp: new Date().toISOString(),
149+
},
150+
}
145151
}
146152
}
147153

@@ -434,11 +440,14 @@ export function Header() {
434440
</div>
435441
<div class='flex-none'>
436442
<label
437-
htmlFor='my-drawer-4'
443+
htmlFor='drawer-right'
444+
onClick={() => {
445+
drawerTab.value = 'history'
446+
}}
438447
class='btn btn-outline btn-xs md:btn-sm drawer-button'
439448
>
440-
<History class='h-4 w-4 mr-2' />
441-
<span class='hidden sm:inline'>History</span>
449+
<FileText class='h-4 w-4 mr-2' />
450+
<span class='hidden sm:inline'>Saved Queries</span>
442451
</label>
443452
</div>
444453
</div>
@@ -669,7 +678,7 @@ export function TabNavigation({
669678
)}
670679
{activeTab !== 'logs' && (
671680
<label
672-
onClick={activeTab === 'queries' ? onRun : undefined}
681+
onClick={activeTab === 'queries' ? () => onRun() : undefined}
673682
htmlFor={activeTab === 'tables' ? 'my-drawer-4' : undefined}
674683
class='btn btn-primary btn-sm'
675684
>
@@ -751,7 +760,7 @@ export function LogsViewer() {
751760
<div class='flex-1 min-h-0 overflow-hidden'>
752761
<div class='w-full overflow-x-auto overflow-y-auto h-full'>
753762
<table class='table table-zebra w-full'>
754-
<thead class='sticky top-0 z-20 bg-base-100 shadow-sm'>
763+
<thead class='sticky top-0 bg-base-100 shadow-sm'>
755764
<tr class='border-b border-base-300'>
756765
{logThreads.map((header) => (
757766
<th
@@ -879,29 +888,37 @@ export function LogsViewer() {
879888
)
880889
}
881890

882-
const TabViews = {
883-
tables: <DataTable />,
884-
queries: <QueryEditor />,
885-
logs: <LogsViewer />,
886-
}
891+
type DrawerTab = 'history'
892+
893+
const drawerTab = new Signal<DrawerTab>('history')
894+
895+
const drawerViews: Record<DrawerTab, JSX.Element> = {
896+
history: <QueryHistory />,
897+
} as const
887898

888899
const Drawer = () => (
889900
<div class='drawer drawer-end'>
890-
<input id='my-drawer-4' type='checkbox' class='drawer-toggle' />
901+
<input id='drawer-right' type='checkbox' class='drawer-toggle' />
891902
<div class='drawer-side'>
892903
<label
893-
htmlFor='my-drawer-4'
904+
htmlFor='drawer-right'
894905
aria-label='close sidebar'
895906
class='drawer-overlay'
896907
>
897908
</label>
898909
<div class='bg-base-200 text-base-content min-h-full w-96'>
899-
<QueryHistory />
910+
{drawerViews[drawerTab.value]}
900911
</div>
901912
</div>
902913
</div>
903914
)
904915

916+
const TabViews = {
917+
tables: <DataTable />,
918+
queries: <QueryEditor />,
919+
logs: <LogsViewer />,
920+
}
921+
905922
export const DeploymentPage = () => {
906923
const tab = (url.params.tab as 'tables' | 'queries' | 'logs') || 'tables'
907924
const view = TabViews[tab]

0 commit comments

Comments
 (0)