feat: add connection colors, query history, SQL autocomplete, and EXPLAIN visualizer

Add four developer/QA features:
- Connection color coding: color picker in dialog, colored indicators across toolbar, tabs, status bar, and connection selectors
- Query history: Rust backend with JSON file storage (500 entry cap), sidebar panel with search/clear, auto-recording from workspace
- Schema-aware SQL autocomplete: backend fetches column metadata, CodeMirror receives schema namespace with public tables unprefixed
- EXPLAIN ANALYZE visualizer: recursive tree view with cost-colored bars, expand/collapse nodes, buffers info, Results/Explain tab toggle

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-11 20:22:10 +03:00
parent 72c362dfae
commit 3b3e225e8f
21 changed files with 791 additions and 37 deletions

View File

@@ -18,7 +18,18 @@ import {
import { useSaveConnection, useTestConnection } from "@/hooks/use-connections";
import { toast } from "sonner";
import type { ConnectionConfig } from "@/types";
import { Loader2 } from "lucide-react";
import { Loader2, X } from "lucide-react";
const CONNECTION_COLORS = [
{ name: "Red", value: "#ef4444" },
{ name: "Orange", value: "#f97316" },
{ name: "Yellow", value: "#eab308" },
{ name: "Green", value: "#22c55e" },
{ name: "Cyan", value: "#06b6d4" },
{ name: "Blue", value: "#3b82f6" },
{ name: "Purple", value: "#a855f7" },
{ name: "Pink", value: "#ec4899" },
];
interface Props {
open: boolean;
@@ -173,6 +184,37 @@ export function ConnectionDialog({ open, onOpenChange, connection }: Props) {
</SelectContent>
</Select>
</div>
<div className="grid grid-cols-4 items-center gap-3">
<label className="text-right text-sm text-muted-foreground">
Color
</label>
<div className="col-span-3 flex items-center gap-1.5">
<button
type="button"
className={`flex h-6 w-6 items-center justify-center rounded-full border-2 ${
!form.color ? "border-primary" : "border-transparent"
} bg-muted`}
onClick={() => setForm((f) => ({ ...f, color: undefined }))}
title="No color"
>
<X className="h-3 w-3 text-muted-foreground" />
</button>
{CONNECTION_COLORS.map((c) => (
<button
key={c.value}
type="button"
className={`h-6 w-6 rounded-full border-2 ${
form.color === c.value
? "border-primary"
: "border-transparent"
}`}
style={{ backgroundColor: c.value }}
onClick={() => setForm((f) => ({ ...f, color: c.value }))}
title={c.name}
/>
))}
</div>
</div>
</div>
<DialogFooter>