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:
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user