feat: add schema browser sidebar and app layout
Add SchemaTree with database/schema/category hierarchy, Sidebar with search, Toolbar, TabBar, StatusBar, and full app layout with resizable panels. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
86
src/components/layout/Toolbar.tsx
Normal file
86
src/components/layout/Toolbar.tsx
Normal file
@@ -0,0 +1,86 @@
|
||||
import { useState } from "react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import { ConnectionSelector } from "@/components/connections/ConnectionSelector";
|
||||
import { ConnectionList } from "@/components/connections/ConnectionList";
|
||||
import { ConnectionDialog } from "@/components/connections/ConnectionDialog";
|
||||
import { useAppStore } from "@/stores/app-store";
|
||||
import { Database, Plus } from "lucide-react";
|
||||
import type { ConnectionConfig, Tab } from "@/types";
|
||||
|
||||
export function Toolbar() {
|
||||
const [listOpen, setListOpen] = useState(false);
|
||||
const [dialogOpen, setDialogOpen] = useState(false);
|
||||
const [editingConn, setEditingConn] = useState<ConnectionConfig | null>(null);
|
||||
const { activeConnectionId, addTab } = useAppStore();
|
||||
|
||||
const handleNewQuery = () => {
|
||||
if (!activeConnectionId) return;
|
||||
const tab: Tab = {
|
||||
id: crypto.randomUUID(),
|
||||
type: "query",
|
||||
title: "New Query",
|
||||
connectionId: activeConnectionId,
|
||||
sql: "",
|
||||
};
|
||||
addTab(tab);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="flex h-10 items-center gap-2 border-b px-3 bg-card">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="h-7 gap-1.5"
|
||||
onClick={() => setListOpen(true)}
|
||||
>
|
||||
<Database className="h-3.5 w-3.5" />
|
||||
Connections
|
||||
</Button>
|
||||
|
||||
<Separator orientation="vertical" className="h-5" />
|
||||
|
||||
<ConnectionSelector />
|
||||
|
||||
<Separator orientation="vertical" className="h-5" />
|
||||
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="h-7 gap-1.5"
|
||||
onClick={handleNewQuery}
|
||||
disabled={!activeConnectionId}
|
||||
>
|
||||
<Plus className="h-3.5 w-3.5" />
|
||||
New Query
|
||||
</Button>
|
||||
|
||||
<div className="flex-1" />
|
||||
|
||||
<span className="text-xs font-semibold text-muted-foreground tracking-wide">
|
||||
TUSK
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<ConnectionList
|
||||
open={listOpen}
|
||||
onOpenChange={setListOpen}
|
||||
onEdit={(conn) => {
|
||||
setEditingConn(conn);
|
||||
setDialogOpen(true);
|
||||
}}
|
||||
onNew={() => {
|
||||
setEditingConn(null);
|
||||
setDialogOpen(true);
|
||||
}}
|
||||
/>
|
||||
|
||||
<ConnectionDialog
|
||||
open={dialogOpen}
|
||||
onOpenChange={setDialogOpen}
|
||||
connection={editingConn}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user