feat: consolidate database management work

Add catalog-owned logical relationships and runtime snapshots, extend the database-management UI and validation coverage, and document the updated operational workflow.

Keep active sensitive-generation status in a tooltip and indicator, and update the layout E2E to follow the history action in its new database-scoped location.
This commit is contained in:
Codex
2026-09-01 14:46:55 +02:00
parent f586152636
commit 076c9742c5
73 changed files with 6966 additions and 610 deletions
@@ -113,8 +113,6 @@ function SecretField({
interface DatabaseFormProps {
mode: DatabaseFormMode;
row: CatalogDatabase;
availableWorkspaces: CatalogDatabase[];
workspaceLocked: boolean;
draft: DatabaseFormDraft;
dirty: boolean;
canManage: boolean;
@@ -125,7 +123,6 @@ interface DatabaseFormProps {
partialSecretFailure: string | null;
headingRef: RefObject<HTMLHeadingElement>;
onBack: () => void;
onWorkspaceChange: (workspaceId: string) => void;
onFieldChange: (field: "databaseName" | "schema", value: string) => void;
onTransportChange: (transport: DatabaseTransport) => void;
onBindingChange: <K extends keyof DatabaseBinding>(key: K, value: DatabaseBinding[K]) => void;
@@ -140,16 +137,17 @@ interface DatabaseFormProps {
onOpenRelationships: () => void;
onSync: (scope: CatalogSyncScope) => void;
onOpenSync: () => void;
onOpenDescriptionHistory?: () => void;
onOpenSensitiveHistory?: () => void;
activeSyncRun?: CatalogSyncRun;
presentation?: "page" | "drawer";
}
export function databaseFormTitle(
mode: DatabaseFormMode,
workspaceLocked: boolean,
presentation: "page" | "drawer" = "page",
): string {
if (mode === "add") return workspaceLocked ? "Edit database" : "Add database";
if (mode === "configure") return "Configure catalog";
if (mode === "edit") return "Edit database";
if (mode === "delete") return presentation === "drawer" ? "Remove configuration" : "Delete database";
return "Database details";
@@ -158,8 +156,6 @@ export function databaseFormTitle(
export function DatabaseForm({
mode,
row,
availableWorkspaces,
workspaceLocked,
draft,
dirty,
canManage,
@@ -170,7 +166,6 @@ export function DatabaseForm({
partialSecretFailure,
headingRef,
onBack,
onWorkspaceChange,
onFieldChange,
onTransportChange,
onBindingChange,
@@ -185,12 +180,14 @@ export function DatabaseForm({
onOpenRelationships,
onSync,
onOpenSync,
onOpenDescriptionHistory,
onOpenSensitiveHistory,
activeSyncRun,
presentation = "page",
}: DatabaseFormProps) {
const title = databaseFormTitle(mode, workspaceLocked, presentation);
const title = databaseFormTitle(mode, presentation);
const readOnly = mode === "view" || mode === "delete";
const editable = mode === "add" || mode === "edit";
const editable = mode === "configure" || mode === "edit";
const busy = busyAction !== null;
const testDisabled = !canManage
|| !row.configured
@@ -268,27 +265,9 @@ export function DatabaseForm({
) : null}
<div className="grid gap-4 md:grid-cols-2">
{mode === "add" ? (
<Field label="Workspace">
<select
className={inputClass}
aria-label="Workspace"
value={draft.workspaceId}
disabled={workspaceLocked || busy}
onChange={(event) => onWorkspaceChange(event.target.value)}
>
{availableWorkspaces.map((workspace) => (
<option key={workspace.workspaceId} value={workspace.workspaceId}>
{workspace.workspaceName}
</option>
))}
</select>
</Field>
) : (
<Field label="Workspace">
<input className={inputClass} value={row.workspaceName} readOnly />
</Field>
)}
<Field label="Workspace">
<input className={inputClass} value={row.workspaceName} readOnly />
</Field>
<Field label="Workspace ID">
<input className={`${inputClass} font-mono text-xs`} value={row.workspaceId} readOnly />
</Field>
@@ -420,13 +399,13 @@ export function DatabaseForm({
<TestTube2 /> {busyAction === "test" ? "Testing…" : "Test connection"}
</Button>
) : null}
{mode === "add" || mode === "edit" ? (
{mode === "configure" || mode === "edit" ? (
<Button type="submit" disabled={saveDisabled}>
<Save />
{busyAction === "save"
? "Saving…"
: mode === "add"
? workspaceLocked ? "Save database" : "Add database"
: mode === "configure"
? "Save catalog configuration"
: "Save changes"}
</Button>
) : null}
@@ -459,6 +438,16 @@ export function DatabaseForm({
{activeSyncRun ? <RefreshCw className="animate-spin" /> : <History />} Sync history
</Button>
) : null}
{mode === "view" && row.configured && onOpenDescriptionHistory ? (
<Button type="button" variant="outline" size="sm" onClick={onOpenDescriptionHistory}>
<History /> Description history
</Button>
) : null}
{mode === "view" && row.configured && onOpenSensitiveHistory ? (
<Button type="button" variant="outline" size="sm" onClick={onOpenSensitiveHistory}>
<History /> Sensitive history
</Button>
) : null}
{mode === "view" ? (
<DatabaseSyncMenu
disabled={!canManage || !bindingReady || busy || Boolean(activeSyncRun)}
@@ -466,6 +455,8 @@ export function DatabaseForm({
onSelect={onSync}
/>
) : null}
{mode === "view" && row.configured && onOpenDescriptionHistory ? <Button type="button" variant="outline" onClick={onOpenDescriptionHistory}><History /> Description history</Button> : null}
{mode === "view" && row.configured && onOpenSensitiveHistory ? <Button type="button" variant="outline" onClick={onOpenSensitiveHistory}><History /> Sensitive history</Button> : null}
</div>
</div>
{row.lastTestedAt ? (