Four new killer features leveraging AI (Ollama) and PostgreSQL internals: - Data Validation: describe quality rules in natural language, AI generates SQL to find violations, run with pass/fail results and sample violations - Test Data Generator: right-click table to generate realistic FK-aware test data with AI, preview before inserting in a transaction - Index Advisor: analyze pg_stat tables + AI recommendations for CREATE/DROP INDEX with one-click apply - Data Snapshots: export selected tables to JSON (FK-ordered), restore from file with optional truncate in a transaction Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
125 lines
3.5 KiB
TypeScript
125 lines
3.5 KiB
TypeScript
import { useAppStore } from "@/stores/app-store";
|
|
import { WorkspacePanel } from "./WorkspacePanel";
|
|
import { TableDataView } from "@/components/table-viewer/TableDataView";
|
|
import { TableStructure } from "@/components/table-viewer/TableStructure";
|
|
import { RoleManagerView } from "@/components/management/RoleManagerView";
|
|
import { SessionsView } from "@/components/management/SessionsView";
|
|
import { EntityLookupPanel } from "@/components/lookup/EntityLookupPanel";
|
|
import { ErdDiagram } from "@/components/erd/ErdDiagram";
|
|
import { ValidationPanel } from "@/components/validation/ValidationPanel";
|
|
import { IndexAdvisorPanel } from "@/components/index-advisor/IndexAdvisorPanel";
|
|
import { SnapshotPanel } from "@/components/snapshots/SnapshotPanel";
|
|
|
|
export function TabContent() {
|
|
const { tabs, activeTabId, updateTab } = useAppStore();
|
|
|
|
if (tabs.length === 0) {
|
|
return (
|
|
<div className="flex h-full items-center justify-center text-sm text-muted-foreground">
|
|
Open a query tab or select a table to get started.
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<>
|
|
{tabs.map((tab) => {
|
|
const isActive = tab.id === activeTabId;
|
|
let content: React.ReactNode;
|
|
|
|
switch (tab.type) {
|
|
case "query":
|
|
content = (
|
|
<WorkspacePanel
|
|
connectionId={tab.connectionId}
|
|
initialSql={tab.sql}
|
|
onSqlChange={(sql) => updateTab(tab.id, { sql })}
|
|
/>
|
|
);
|
|
break;
|
|
case "table":
|
|
content = (
|
|
<TableDataView
|
|
connectionId={tab.connectionId}
|
|
schema={tab.schema!}
|
|
table={tab.table!}
|
|
/>
|
|
);
|
|
break;
|
|
case "structure":
|
|
content = (
|
|
<TableStructure
|
|
connectionId={tab.connectionId}
|
|
schema={tab.schema!}
|
|
table={tab.table!}
|
|
/>
|
|
);
|
|
break;
|
|
case "roles":
|
|
content = (
|
|
<RoleManagerView
|
|
connectionId={tab.connectionId}
|
|
/>
|
|
);
|
|
break;
|
|
case "sessions":
|
|
content = (
|
|
<SessionsView
|
|
connectionId={tab.connectionId}
|
|
/>
|
|
);
|
|
break;
|
|
case "lookup":
|
|
content = (
|
|
<EntityLookupPanel
|
|
connectionId={tab.connectionId}
|
|
/>
|
|
);
|
|
break;
|
|
case "erd":
|
|
content = (
|
|
<ErdDiagram
|
|
connectionId={tab.connectionId}
|
|
schema={tab.schema!}
|
|
/>
|
|
);
|
|
break;
|
|
case "validation":
|
|
content = (
|
|
<ValidationPanel
|
|
connectionId={tab.connectionId}
|
|
/>
|
|
);
|
|
break;
|
|
case "index-advisor":
|
|
content = (
|
|
<IndexAdvisorPanel
|
|
connectionId={tab.connectionId}
|
|
/>
|
|
);
|
|
break;
|
|
case "snapshots":
|
|
content = (
|
|
<SnapshotPanel
|
|
connectionId={tab.connectionId}
|
|
/>
|
|
);
|
|
break;
|
|
default:
|
|
content = null;
|
|
}
|
|
|
|
return (
|
|
<div
|
|
key={tab.id}
|
|
className="h-full"
|
|
style={{ display: isActive ? undefined : "none" }}
|
|
>
|
|
{content}
|
|
</div>
|
|
);
|
|
})}
|
|
</>
|
|
);
|
|
}
|