Files
tusk/src/App.tsx
A.Shakhmatov e8d99c645b feat: add Greenplum 7 compatibility and AI SQL generation
Greenplum 7 (PG12-based) compatibility:
- Auto-detect GP via version() string, store DbFlavor per connection
- connect returns ConnectResult with version + flavor
- Fix pg_total_relation_size to use c.oid (universal, safer on both PG/GP)
- Branch is_identity column query for GP (lacks the column)
- Branch list_sessions wait_event fields for GP
- Exclude gp_toolkit schema in schema listing, completion, lookup, AI context
- Smart StatusBar version display: GP shows "GP 7.0.0 (PG 12.4)"
- Fix connection list spinner showing on all cards during connect

AI SQL generation (Ollama):
- Add AI settings, model selection, and generate_sql command
- Frontend AI panel with prompt input and SQL output

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 18:24:06 +03:00

74 lines
2.3 KiB
TypeScript

import { useEffect, useCallback } from "react";
import {
ResizableHandle,
ResizablePanel,
ResizablePanelGroup,
} from "@/components/ui/resizable";
import { Toolbar } from "@/components/layout/Toolbar";
import { Sidebar } from "@/components/layout/Sidebar";
import { TabBar } from "@/components/layout/TabBar";
import { TabContent } from "@/components/workspace/TabContent";
import { StatusBar } from "@/components/layout/StatusBar";
import { useAppStore } from "@/stores/app-store";
import type { Tab } from "@/types";
export default function App() {
const { activeConnectionId, currentDatabase, addTab } = useAppStore();
const handleNewQuery = useCallback(() => {
if (!activeConnectionId) return;
const tab: Tab = {
id: crypto.randomUUID(),
type: "query",
title: "New Query",
connectionId: activeConnectionId,
database: currentDatabase ?? undefined,
sql: "",
};
addTab(tab);
}, [activeConnectionId, currentDatabase, addTab]);
const handleCloseTab = useCallback(() => {
const { activeTabId, closeTab } = useAppStore.getState();
if (activeTabId) closeTab(activeTabId);
}, []);
useEffect(() => {
const handleKeyDown = (e: KeyboardEvent) => {
if ((e.ctrlKey || e.metaKey) && e.key === "t") {
e.preventDefault();
handleNewQuery();
}
if ((e.ctrlKey || e.metaKey) && e.key === "w") {
e.preventDefault();
handleCloseTab();
}
};
window.addEventListener("keydown", handleKeyDown);
return () => window.removeEventListener("keydown", handleKeyDown);
}, [handleNewQuery, handleCloseTab]);
return (
<div className="flex h-screen flex-col">
<Toolbar />
<div className="flex-1 overflow-hidden">
<ResizablePanelGroup orientation="horizontal">
<ResizablePanel id="sidebar" defaultSize="20%" minSize="180px" maxSize="40%">
<Sidebar />
</ResizablePanel>
<ResizableHandle />
<ResizablePanel id="main" defaultSize="80%">
<div className="flex h-full flex-col">
<TabBar />
<div className="flex-1 overflow-hidden">
<TabContent />
</div>
</div>
</ResizablePanel>
</ResizablePanelGroup>
</div>
<StatusBar />
</div>
);
}