feat: complete catalog-driven preprocessing
Publish documentation / publish (push) Successful in 2m12s
Publish documentation / publish (push) Successful in 2m12s
This commit is contained in:
@@ -50,7 +50,7 @@ interface DatabaseGridProps {
|
||||
rows: CatalogDatabase[],
|
||||
scope: Extract<DescriptionGenerationScope, "all" | "missing">,
|
||||
) => Promise<void>;
|
||||
onConsolidateColumnDescriptions: (rows: CatalogDatabase[]) => Promise<void>;
|
||||
onConsolidateDescriptions: (rows: CatalogDatabase[]) => Promise<void>;
|
||||
onSuggestSensitive: (rows: CatalogDatabase[]) => Promise<void>;
|
||||
onDeleteMetadataSelected: (
|
||||
rows: CatalogDatabase[],
|
||||
@@ -78,7 +78,7 @@ type DatabaseFleetAction =
|
||||
| "sync-all"
|
||||
| "generate-all"
|
||||
| "generate-missing"
|
||||
| "consolidate-columns"
|
||||
| "consolidate-descriptions"
|
||||
| "suggest-sensitive"
|
||||
| "clear-tables"
|
||||
| "clear-relationships";
|
||||
@@ -341,7 +341,7 @@ export function DatabaseGrid({
|
||||
descriptionGenerationActive,
|
||||
sensitivityAnalysisRuns = [],
|
||||
onGenerateDescriptions,
|
||||
onConsolidateColumnDescriptions,
|
||||
onConsolidateDescriptions,
|
||||
onSuggestSensitive,
|
||||
onDeleteMetadataSelected,
|
||||
onRefresh,
|
||||
@@ -435,7 +435,7 @@ export function DatabaseGrid({
|
||||
&& Boolean(selectedMetadataModel)
|
||||
&& !descriptionGenerationActive
|
||||
&& selectedRows.every((row) => row.configured && row.id && !row.activeSyncRun);
|
||||
const canConsolidateColumnDescriptions = canManage
|
||||
const canConsolidateDescriptions = canManage
|
||||
&& selectedRows.length === 1
|
||||
&& !descriptionGenerationActive
|
||||
&& selectedRows.every((row) => row.configured && row.id && !row.activeSyncRun);
|
||||
@@ -490,13 +490,13 @@ export function DatabaseGrid({
|
||||
{ id: "sync-all", label: "Synchronize all", group: "Synchronization", disabled: !canSyncSelection, disabledReason: syncReason },
|
||||
{ id: "generate-missing", label: "Generate missing descriptions", group: "Descriptions", disabled: !canGenerateDescriptions, disabledReason: generationReason },
|
||||
{ id: "generate-all", label: "Generate all descriptions", group: "Descriptions", disabled: !canGenerateDescriptions, disabledReason: generationReason, runLabel: "Review generation" },
|
||||
{ id: "consolidate-columns", label: "Copy generated descriptions to all columns", group: "Descriptions", disabled: !canConsolidateColumnDescriptions, disabledReason: consolidationReason, runLabel: "Review copy" },
|
||||
{ id: "consolidate-descriptions", label: "Copy generated description to descriptions", group: "Descriptions", disabled: !canConsolidateDescriptions, disabledReason: consolidationReason, runLabel: "Review copy" },
|
||||
{ id: "suggest-sensitive", label: "Analyze sensitive fields", group: "Sensitive data", disabled: !canSuggestSensitive, disabledReason: sensitiveReason, runLabel: "Open review" },
|
||||
{ id: "clear-tables", label: "Clear catalog tables and relationships", group: "Cleanup", disabled: !canDeleteMetadataSelection, disabledReason: cleanupReason, tone: "destructive", runLabel: "Review cleanup" },
|
||||
{ id: "clear-relationships", label: "Clear catalog relationships", group: "Cleanup", disabled: !canDeleteMetadataSelection, disabledReason: cleanupReason, tone: "destructive", runLabel: "Review cleanup" },
|
||||
];
|
||||
}, [
|
||||
canConsolidateColumnDescriptions,
|
||||
canConsolidateDescriptions,
|
||||
canDeleteMetadataSelection,
|
||||
canGenerateDescriptions,
|
||||
canManage,
|
||||
@@ -569,7 +569,7 @@ export function DatabaseGrid({
|
||||
setPendingDelete(selectedAction === "clear-tables" ? "tables" : "relationships");
|
||||
return;
|
||||
}
|
||||
if (selectedAction === "consolidate-columns") {
|
||||
if (selectedAction === "consolidate-descriptions") {
|
||||
setPendingConsolidation(true);
|
||||
return;
|
||||
}
|
||||
@@ -652,10 +652,10 @@ export function DatabaseGrid({
|
||||
>
|
||||
<div className="mr-auto min-w-56">
|
||||
<p id="database-consolidation-confirmation" className="text-sm font-semibold">
|
||||
Copy generated descriptions to all columns in {selectedRows[0]?.workspaceName}?
|
||||
Copy generated descriptions to Description fields in {selectedRows[0]?.workspaceName}?
|
||||
</p>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Every non-empty AI-generated column description will replace the current Description value. Generated descriptions are retained.
|
||||
Every non-empty AI-generated table and column description will replace its current Description value. Generated descriptions are retained.
|
||||
</p>
|
||||
</div>
|
||||
<Button type="button" variant="ghost" disabled={action !== null} onClick={closeConsolidationConfirmation}>Cancel</Button>
|
||||
@@ -666,10 +666,10 @@ export function DatabaseGrid({
|
||||
disabled={action !== null}
|
||||
onClick={() => void perform(
|
||||
"consolidate",
|
||||
() => onConsolidateColumnDescriptions(selectedRows),
|
||||
() => onConsolidateDescriptions(selectedRows),
|
||||
)}
|
||||
>
|
||||
Copy to all columns
|
||||
Copy to descriptions
|
||||
</Button>
|
||||
</div>
|
||||
) : pendingDelete ? (
|
||||
@@ -760,10 +760,10 @@ export function DatabaseGrid({
|
||||
</Menu.Item>
|
||||
<Menu.Item
|
||||
className="rounded-md px-3 py-2 text-sm outline-none data-[highlighted]:bg-muted data-[disabled]:opacity-45"
|
||||
disabled={!canConsolidateColumnDescriptions}
|
||||
disabled={!canConsolidateDescriptions}
|
||||
onClick={() => setPendingConsolidation(true)}
|
||||
>
|
||||
Copy generated descriptions to all columns
|
||||
Copy generated description to descriptions
|
||||
</Menu.Item>
|
||||
<Menu.Separator className="my-1 h-px bg-border" />
|
||||
<Menu.Item
|
||||
|
||||
@@ -103,7 +103,7 @@ test("replays ordered SSE events, reconnects from the latest sequence, and keeps
|
||||
http.get("/api/catalog/description-generation-runs/:runId/events-list", () => {
|
||||
eventReads += 1;
|
||||
return HttpResponse.json(eventReads === 1 ? [event(1, "Run queued")] : [
|
||||
event(2, "First description saved"),
|
||||
event(2, 'Generated description for Column "patients.birth_date".'),
|
||||
event(3, "Polling recovered this event"),
|
||||
]);
|
||||
}),
|
||||
@@ -127,11 +127,20 @@ test("replays ordered SSE events, reconnects from the latest sequence, and keeps
|
||||
|
||||
logHeight = 200;
|
||||
act(() => {
|
||||
FakeEventSource.instances[0].emitNamed("log", event(2, "First description saved"), "2");
|
||||
FakeEventSource.instances[0].emitNamed("log", event(2, "First description saved"), "2");
|
||||
FakeEventSource.instances[0].emitNamed(
|
||||
"log",
|
||||
event(2, 'Generated description for Column "patients.birth_date".'),
|
||||
"2",
|
||||
);
|
||||
FakeEventSource.instances[0].emitNamed(
|
||||
"log",
|
||||
event(2, 'Generated description for Column "patients.birth_date".'),
|
||||
"2",
|
||||
);
|
||||
FakeEventSource.instances[0].onerror?.();
|
||||
});
|
||||
await waitFor(() => expect(log.scrollTop).toBe(log.scrollHeight));
|
||||
expect(within(log).getByText('Generated description for Column "patients.birth_date".')).toBeVisible();
|
||||
|
||||
logHeight = 300;
|
||||
expect(await within(log).findByText("Polling recovered this event")).toBeVisible();
|
||||
@@ -154,7 +163,9 @@ test("replays ordered SSE events, reconnects from the latest sequence, and keeps
|
||||
FakeEventSource.instances[1].emitNamed("log", event(4, "Replay continued in order"), "4");
|
||||
});
|
||||
|
||||
await waitFor(() => expect(within(log).getAllByText("First description saved")).toHaveLength(1));
|
||||
await waitFor(() => expect(
|
||||
within(log).getAllByText('Generated description for Column "patients.birth_date".'),
|
||||
).toHaveLength(1));
|
||||
expect(within(log).getAllByText("Polling recovered this event")).toHaveLength(1);
|
||||
expect(within(log).getByText("Replay continued in order")).toBeVisible();
|
||||
expect(log.scrollTop).toBe(0);
|
||||
@@ -162,11 +173,11 @@ test("replays ordered SSE events, reconnects from the latest sequence, and keeps
|
||||
expect(log.scrollTop).toBe(log.scrollHeight);
|
||||
expect(screen.queryByRole("button", { name: "Jump to latest" })).not.toBeInTheDocument();
|
||||
expect(log.textContent!.indexOf("Run queued")).toBeLessThan(
|
||||
log.textContent!.indexOf("First description saved"),
|
||||
);
|
||||
expect(log.textContent!.indexOf("First description saved")).toBeLessThan(
|
||||
log.textContent!.indexOf("Polling recovered this event"),
|
||||
log.textContent!.indexOf('Generated description for Column "patients.birth_date".'),
|
||||
);
|
||||
expect(
|
||||
log.textContent!.indexOf('Generated description for Column "patients.birth_date".'),
|
||||
).toBeLessThan(log.textContent!.indexOf("Polling recovered this event"));
|
||||
});
|
||||
|
||||
test("stops queued or running work without hiding earlier results or events", async () => {
|
||||
|
||||
Reference in New Issue
Block a user