feat(frontend): add database management surface

This commit is contained in:
Codex
2026-08-26 18:00:47 +02:00
parent 11f78c4467
commit a701b19a03
8 changed files with 708 additions and 8 deletions
+33 -3
View File
@@ -15,6 +15,7 @@ import { DeleteConfirmDialog } from "./DeleteConfirmDialog";
import { StopConfirmDialog } from "./StopConfirmDialog";
import { SteerInput, ComposerFooter } from "./SteerInput";
import { WorkflowBar } from "./WorkflowBar";
import { DatabaseManagementPage } from "./DatabaseManagementPage";
import { Pencil, ArrowLeft, ArrowRight, Trash2 } from "lucide-react";
import { Button } from "../components/ui/button";
import { Checkbox } from "../components/ui/checkbox";
@@ -39,6 +40,8 @@ interface AppShellProps {
canLogout: boolean;
}
type ActiveSurface = "core" | "database-management";
export function AppShell({ canLogout }: AppShellProps) {
const authenticatedUser = useAuthUser();
const [panelSession, setPanelSession] = useState<SessionSummary | null>(null);
@@ -118,6 +121,7 @@ export function AppShell({ canLogout }: AppShellProps) {
const queryClient = useQueryClient();
const [showActivity, setShowActivity] = useState(false);
const [activeSurface, setActiveSurface] = useState<ActiveSurface>("core");
const [workspaceManagerOpen, setWorkspaceManagerOpen] = useState(false);
const [piManagementOpen, setPiManagementOpen] = useState(false);
const [activeOpen, setActiveOpen] = useState(true);
@@ -195,6 +199,7 @@ export function AppShell({ canLogout }: AppShellProps) {
function openPanel(id: string) {
const s = sessions.find((x) => x.id === id);
if (!s) return;
setActiveSurface("core");
// A session with a live Pi runtime opens straight into its live view: doResume
// reconnects to the already-active runtime and replays its pending gate, so an
// in-progress session never shows an empty screen that reads as "stopped". Cold or
@@ -214,6 +219,7 @@ export function AppShell({ canLogout }: AppShellProps) {
});
}
async function doResume(id: string) {
setActiveSurface("core");
const guard = captureAuthOperation({ sessionId: id, disposalEpoch: operationEpochRef.current });
if (!guard) return;
const token = ++resumeInvocationRef.current;
@@ -495,6 +501,7 @@ export function AppShell({ canLogout }: AppShellProps) {
}, [lastSystemEvent]);
function startNewSession() {
setActiveSurface("core");
invalidateResumeIntent();
newSessionOperationRef.current = null;
resetSession();
@@ -580,9 +587,10 @@ export function AppShell({ canLogout }: AppShellProps) {
onClose={() => setPanelSession(null)}
onResume={doResume}
desktopSplit={sessionDesktopSplit}
hidden={activeSurface !== "core"}
/>
)}
{panelSession && sessionDesktopSplit && (
{activeSurface === "core" && panelSession && sessionDesktopSplit && (
<div className="relative w-0 shrink-0">
<div
{...sessionSeparatorProps}
@@ -594,8 +602,8 @@ export function AppShell({ canLogout }: AppShellProps) {
</div>
</div>
)}
{showActivity && <ModelActivityPanel desktopSplit={desktopSplit} onClose={() => setShowActivity(false)} onOpenWorkspaceManager={() => setWorkspaceManagerOpen(true)} />}
{showActivity && desktopSplit && (
{showActivity && <ModelActivityPanel desktopSplit={desktopSplit} onClose={() => setShowActivity(false)} onOpenWorkspaceManager={() => setWorkspaceManagerOpen(true)} hidden={activeSurface !== "core"} />}
{activeSurface === "core" && showActivity && desktopSplit && (
<div className="relative w-0 shrink-0">
<div
{...activitySeparatorProps}
@@ -610,6 +618,11 @@ export function AppShell({ canLogout }: AppShellProps) {
{/* Conversation column */}
<div data-testid="conversation-column" className="flex min-w-0 flex-1 flex-col">
{activeSurface === "database-management" && <DatabaseManagementPage />}
<div
aria-hidden={activeSurface !== "core"}
className={activeSurface === "core" ? "contents" : "hidden"}
>
{activeSessionId && (
<div className="relative shrink-0 border-b border-border/70 bg-background/80 px-6 py-2.5 backdrop-blur">
{/* Arrow toggle for the left Model-activity panel: → opens it, ← closes it. */}
@@ -686,6 +699,7 @@ export function AppShell({ canLogout }: AppShellProps) {
</div>
</div>
</div>
</div>
</div>
{/* Right session rail */}
@@ -731,6 +745,22 @@ export function AppShell({ canLogout }: AppShellProps) {
>
Workspace management
</Button>
{canManageWorkspace && (
<Button
variant="ghost"
size="sm"
className={[
"w-full justify-start hover:bg-sidebar-accent",
activeSurface === "database-management"
? "bg-sidebar-accent font-bold text-sidebar-accent-foreground"
: "",
].join(" ")}
aria-current={activeSurface === "database-management" ? "page" : undefined}
onClick={() => setActiveSurface("database-management")}
>
Database management
</Button>
)}
{canManagePi && (
<Button
variant="outline"