feat: Query history + saved queries (#5)
* fix: restore frontend test baseline (vitest jsdom env + tsc + mock fixes) * feat: v6 migration — favorite column + queries table (Task 1) * feat: extend TS types for favorites + saved queries (Task 2) * feat: dedup consecutive + prune to 500 in insert_query_history (Task 3) * feat: favorite column threading + set_history_favorite command (Task 4) * feat: saved queries store CRUD (Task 5) * feat: saved query commands + registration (Task 6) * feat: queryStore — Zustand cache for history + saved queries (Task 7) * feat: QueryHistoryDropdown — toolbar history dropdown (Task 8) * feat: SaveQueryDialog — save query modal (Task 9) * feat: QueryToolbar — add History + Save icons (Task 10) * feat: QueriesPanel — History + Saved tabs (Task 11) * feat: wire Queries view + toolbar to panel (Task 12) * fix: global scope wrappers, empty/spinner states, cache invalidation (Task 13) * feat: Queries view — history sidebar + tabbed query workspace (PR feedback) * fix: toolbar action order + view-specific empty state (PR feedback) * fix: view-specific empty state icon (PR feedback) * fix: portal Tooltip to body so it is never clipped by overflow containers (PR feedback) * feat: Queries sidebar — Explorer-style header + per-connection scoping (PR feedback) * fix: move History/Saved dropdown to right side of Queries header (PR feedback) * fix: History/Saved dropdown on its own row in Queries header (PR feedback) * fix: Queries header order (search above dropdown) + sidebar width matches Explorer (PR feedback) * fix: Queries header spacing — tight rows, pb-3 on container (PR feedback) * fix: Queries header spacing — space-y-2 on container, no mb on title row (PR feedback) * feat: history/saved rows click-to-load, remove sub-buttons (PR feedback) * feat: merge Functions/Triggers/Sequences/Enums/Extensions into single Objects view (PR feedback) * fix: Schema Visualizer nav icon — node graph glyph (PR feedback) * fix: Objects view — type dropdown replaces static header label (PR feedback) * fix: Objects empty state — remove bg circle, larger icon (PR feedback) * fix: center icon in Objects empty state (PR feedback) * feat: merge Backup/Restore/DB Sync into single Tools view (PR feedback) * docs: update AGENTS.md + README for query history/saved queries, merged Objects + Tools views
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useEffect, useState, useMemo, useCallback, useRef } from "react";
|
||||
import { useEffect, useState, useMemo, useCallback, useRef, cloneElement } from "react";
|
||||
import {
|
||||
ChevronRight,
|
||||
FunctionSquare,
|
||||
@@ -29,7 +29,6 @@ export type ObjectType =
|
||||
| "extensions";
|
||||
|
||||
interface ObjectExplorerPageProps {
|
||||
type: ObjectType;
|
||||
connectionId: string;
|
||||
}
|
||||
|
||||
@@ -41,6 +40,10 @@ const TYPE_LABELS: Record<ObjectType, string> = {
|
||||
extensions: "Extensions",
|
||||
};
|
||||
|
||||
const OBJECT_TYPE_OPTIONS = (Object.keys(TYPE_LABELS) as ObjectType[]).map(
|
||||
(t) => ({ value: t, label: TYPE_LABELS[t] }),
|
||||
);
|
||||
|
||||
const SINGULAR_LABELS: Record<ObjectType, string> = {
|
||||
functions: "function",
|
||||
triggers: "trigger",
|
||||
@@ -805,10 +808,8 @@ function renderDetail(type: ObjectType, item: AnyObject) {
|
||||
}
|
||||
}
|
||||
|
||||
export function ObjectExplorerPage({
|
||||
type,
|
||||
connectionId,
|
||||
}: ObjectExplorerPageProps) {
|
||||
export function ObjectExplorerPage({ connectionId }: ObjectExplorerPageProps) {
|
||||
const [type, setType] = useState<ObjectType>("functions");
|
||||
const [panelWidth, setPanelWidth] = useState(280);
|
||||
const panelResizeRef = useRef<{ startX: number; startW: number } | null>(
|
||||
null,
|
||||
@@ -943,6 +944,18 @@ export function ObjectExplorerPage({
|
||||
const label = TYPE_LABELS[type];
|
||||
const singular = SINGULAR_LABELS[type];
|
||||
|
||||
// Switching object type: reset selection/search, clear the stale list so
|
||||
// the loading state renders (no flash of the previous type's objects), and
|
||||
// reset the last-fetched-schema marker so the fetch effect re-runs.
|
||||
const handleTypeChange = (next: ObjectType) => {
|
||||
setType(next);
|
||||
setSearchQuery("");
|
||||
setSelectedItem(null);
|
||||
setItems(null);
|
||||
setLoading(true);
|
||||
lastSchemaRef.current = undefined;
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex flex-1 min-h-0 overflow-hidden">
|
||||
{/* Left panel: toolbar + object list */}
|
||||
@@ -952,9 +965,13 @@ export function ObjectExplorerPage({
|
||||
>
|
||||
<div className="p-3 border-b border-border space-y-2">
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-sm font-semibold text-text">
|
||||
{label}
|
||||
</span>
|
||||
<SelectDropdown
|
||||
value={type}
|
||||
onChange={(v) => handleTypeChange(v as ObjectType)}
|
||||
options={OBJECT_TYPE_OPTIONS}
|
||||
variant="ghost"
|
||||
aria-label="Object type"
|
||||
/>
|
||||
<div className="flex items-center gap-1">
|
||||
<button
|
||||
aria-label="Refresh"
|
||||
@@ -1144,8 +1161,8 @@ export function ObjectExplorerPage({
|
||||
) : (
|
||||
<div className="flex items-center justify-center h-full text-text-muted">
|
||||
<div className="text-center space-y-2">
|
||||
<div className="w-12 h-12 mx-auto rounded-full bg-surface flex items-center justify-center">
|
||||
{icon}
|
||||
<div className="flex justify-center">
|
||||
{cloneElement(icon as React.ReactElement<{ size?: number }>, { size: 20 })}
|
||||
</div>
|
||||
<p className="text-sm">
|
||||
Select a {singular} to view details
|
||||
|
||||
Reference in New Issue
Block a user