fix: close catalog review gaps
Publish documentation / publish (push) Successful in 38s

This commit is contained in:
Codex
2026-08-31 16:28:42 +02:00
parent 64fbe642ef
commit f586152636
7 changed files with 301 additions and 48 deletions
@@ -214,7 +214,9 @@ export function DatabaseGrid({
const [selectedRows, setSelectedRows] = useState<CatalogDatabase[]>([]);
const [action, setAction] = useState<"test" | "sync" | "generate" | "suggest" | "delete" | null>(null);
const [pendingDelete, setPendingDelete] = useState<CatalogDatabaseMetadataDeleteTarget | null>(null);
const [pendingGenerateAll, setPendingGenerateAll] = useState(false);
const [pendingGenerationScope, setPendingGenerationScope] = useState<
Extract<DescriptionGenerationScope, "all" | "missing"> | null
>(null);
const context = useMemo<DatabaseGridContext>(
() => ({ canManage, presentation, onView, onOpenTables, onEdit, onDelete, onOpenSync }),
[canManage, presentation, onView, onOpenTables, onEdit, onDelete, onOpenSync],
@@ -376,10 +378,10 @@ export function DatabaseGrid({
return () => window.clearTimeout(timer);
}, [pendingDelete]);
useEffect(() => {
if (!pendingGenerateAll) return;
const timer = window.setTimeout(() => document.getElementById("database-generate-all-confirm-button")?.focus(), 0);
if (!pendingGenerationScope) return;
const timer = window.setTimeout(() => document.getElementById("database-generation-confirm-button")?.focus(), 0);
return () => window.clearTimeout(timer);
}, [pendingGenerateAll]);
}, [pendingGenerationScope]);
const closeDeleteConfirmation = () => {
setPendingDelete(null);
window.setTimeout(() => {
@@ -387,8 +389,8 @@ export function DatabaseGrid({
else actionsTriggerRef.current?.focus();
}, 0);
};
const closeGenerateAllConfirmation = () => {
setPendingGenerateAll(false);
const closeGenerationConfirmation = () => {
setPendingGenerationScope(null);
window.setTimeout(() => {
if (presentation === "fleet") actionSelectRef.current?.focus();
else actionsTriggerRef.current?.focus();
@@ -407,16 +409,17 @@ export function DatabaseGrid({
setSelectedRows([]);
}
setPendingDelete(null);
setPendingGenerateAll(false);
setPendingGenerationScope(null);
if (kind === "delete") window.setTimeout(() => searchInputRef.current?.focus(), 0);
} catch {
// The page-level operation owns safe error feedback. Preserve the selection for retry.
if (kind === "generate") setPendingGenerationScope(null);
} finally { setAction(null); }
};
const runFleetAction = async (selectedAction: DatabaseFleetAction) => {
if (selectedAction === "generate-all") {
setPendingGenerateAll(true);
if (selectedAction === "generate-all" || selectedAction === "generate-missing") {
setPendingGenerationScope(selectedAction === "generate-all" ? "all" : "missing");
return;
}
if (selectedAction === "clear-tables" || selectedAction === "clear-relationships") {
@@ -432,10 +435,6 @@ export function DatabaseGrid({
await perform("sync", () => onSyncSelected(selectedRows, scope));
return;
}
if (selectedAction === "generate-missing") {
await perform("generate", () => onGenerateDescriptions(selectedRows, "missing"));
return;
}
await perform("suggest", () => onSuggestSensitive(selectedRows), false);
};
@@ -452,35 +451,47 @@ export function DatabaseGrid({
: "flex min-h-12 flex-wrap items-center gap-3 border-b border-border px-3 py-2"}
>
{selectedRows.length > 0 ? (
pendingGenerateAll ? (
pendingGenerationScope ? (
<div
role="group"
aria-labelledby="database-generate-all-confirmation"
aria-labelledby="database-generation-confirmation"
className="flex min-w-0 flex-1 flex-wrap items-center gap-2"
onKeyDown={(event) => {
if (event.key === "Escape" && action === null) closeGenerateAllConfirmation();
if (event.key === "Escape" && action === null) closeGenerationConfirmation();
}}
>
<div className="mr-auto min-w-56">
<p id="database-generate-all-confirmation" className="text-sm font-semibold">
Replace generated descriptions for {selectedRows[0]?.workspaceName}?
<p id="database-generation-confirmation" className="text-sm font-semibold">
{pendingGenerationScope === "all"
? `Replace generated descriptions for ${selectedRows[0]?.workspaceName}?`
: `Generate missing descriptions for ${selectedRows[0]?.workspaceName}?`}
</p>
<p className="text-xs text-muted-foreground">
Existing generated descriptions for eligible tables and columns will be replaced.
{pendingGenerationScope === "all" ? (
<p className="text-xs text-muted-foreground">
Existing generated descriptions for eligible tables and columns will be replaced.
</p>
) : null}
<p
role="note"
aria-label="Metadata generation source data disclosure"
className="mt-1 text-xs font-medium text-amber-800 dark:text-amber-300"
>
When available, up to five real source rows and five representative values from
columns not marked sensitive are sent to the selected provider.
</p>
</div>
<Button type="button" variant="ghost" disabled={action !== null} onClick={closeGenerateAllConfirmation}>Cancel</Button>
<Button type="button" variant="ghost" disabled={action !== null} onClick={closeGenerationConfirmation}>Cancel</Button>
<Button
id="database-generate-all-confirm-button"
id="database-generation-confirm-button"
type="button"
variant="destructive"
variant={pendingGenerationScope === "all" ? "destructive" : "default"}
disabled={action !== null}
onClick={() => void perform(
"generate",
() => onGenerateDescriptions(selectedRows, "all"),
() => onGenerateDescriptions(selectedRows, pendingGenerationScope),
)}
>
Generate All
{pendingGenerationScope === "all" ? "Generate All" : "Generate Missing"}
</Button>
</div>
) : pendingDelete ? (
@@ -564,17 +575,14 @@ export function DatabaseGrid({
<Menu.Item
className="rounded-md px-3 py-2 text-sm outline-none data-[highlighted]:bg-muted data-[disabled]:opacity-45"
disabled={!canGenerateDescriptions}
onClick={() => setPendingGenerateAll(true)}
onClick={() => setPendingGenerationScope("all")}
>
Generate All
</Menu.Item>
<Menu.Item
className="rounded-md px-3 py-2 text-sm outline-none data-[highlighted]:bg-muted data-[disabled]:opacity-45"
disabled={!canGenerateDescriptions}
onClick={() => void perform(
"generate",
() => onGenerateDescriptions(selectedRows, "missing"),
)}
onClick={() => setPendingGenerationScope("missing")}
>
Generate Missing
</Menu.Item>
@@ -649,7 +657,7 @@ export function DatabaseGrid({
selectionColumnDef={{ width: 44, maxWidth: 44, pinned: "left" }}
onSelectionChanged={({ api }) => {
if (pendingDelete && action === null) setPendingDelete(null);
if (pendingGenerateAll && action === null) setPendingGenerateAll(false);
if (pendingGenerationScope && action === null) setPendingGenerationScope(null);
setSelectedRows(api.getSelectedRows());
}}
rowHeight={44}