feat: refine metadata catalog workflows
This commit is contained in:
@@ -330,13 +330,12 @@ export function DatabaseTables({
|
||||
| "sync-columns"
|
||||
| "consolidate-descriptions"
|
||||
| "suggest-sensitive"
|
||||
| "clear-columns"
|
||||
| "clear-relationships";
|
||||
| "clear-columns";
|
||||
|
||||
const fleetActions: readonly FleetActionOption<FleetTableAction>[] = [
|
||||
{
|
||||
id: "generate-descriptions",
|
||||
label: "Generate descriptions",
|
||||
label: "Generate table description",
|
||||
group: "Descriptions",
|
||||
runLabel: "Generate",
|
||||
disabled: !canManage || selectedIds.length === 0 || !selectedMetadataModel || descriptionGenerationActive || busy !== null || Boolean(currentRun),
|
||||
@@ -372,7 +371,7 @@ export function DatabaseTables({
|
||||
},
|
||||
{
|
||||
id: "consolidate-descriptions",
|
||||
label: "Move generated to Description",
|
||||
label: "Copy generated descriptions to Description",
|
||||
group: "Descriptions",
|
||||
runLabel: "Move",
|
||||
disabled: !canManage || selectedIds.length === 0 || busy !== null || Boolean(currentRun),
|
||||
@@ -386,22 +385,24 @@ export function DatabaseTables({
|
||||
},
|
||||
{
|
||||
id: "sync-tables",
|
||||
label: "Synchronize tables",
|
||||
label: "Synchronize database tables",
|
||||
group: "Synchronization",
|
||||
scopeLabel: "All tables in this database",
|
||||
scopeLabel: "Selected database",
|
||||
runLabel: "Synchronize",
|
||||
disabled: !canManage || !bindingReady || busy !== null || Boolean(currentRun),
|
||||
disabled: !canManage || selectedIds.length === 0 || !bindingReady || busy !== null || Boolean(currentRun),
|
||||
disabledReason: !canManage
|
||||
? "You do not have permission to synchronize the catalog."
|
||||
: !bindingReady
|
||||
? "Test the current database binding first."
|
||||
: busy !== null || Boolean(currentRun)
|
||||
? "Wait for the active catalog operation to finish."
|
||||
: undefined,
|
||||
: selectedIds.length === 0
|
||||
? "Select at least one table."
|
||||
: !bindingReady
|
||||
? "Test the current database binding first."
|
||||
: busy !== null || Boolean(currentRun)
|
||||
? "Wait for the active catalog operation to finish."
|
||||
: undefined,
|
||||
},
|
||||
{
|
||||
id: "sync-columns",
|
||||
label: "Synchronize columns",
|
||||
label: "Synchronize columns for selected tables",
|
||||
group: "Synchronization",
|
||||
runLabel: "Synchronize",
|
||||
disabled: !canManage || selectedIds.length === 0 || !bindingReady || busy !== null || Boolean(currentRun),
|
||||
@@ -435,22 +436,7 @@ export function DatabaseTables({
|
||||
},
|
||||
{
|
||||
id: "clear-columns",
|
||||
label: "Clear catalog columns",
|
||||
group: "Catalog cleanup",
|
||||
tone: "destructive",
|
||||
runLabel: "Review cleanup",
|
||||
disabled: !canManage || selectedIds.length === 0 || busy !== null || Boolean(currentRun),
|
||||
disabledReason: !canManage
|
||||
? "You do not have permission to clear catalog metadata."
|
||||
: selectedIds.length === 0
|
||||
? "Select at least one table."
|
||||
: busy !== null || Boolean(currentRun)
|
||||
? "Wait for the active catalog operation to finish."
|
||||
: undefined,
|
||||
},
|
||||
{
|
||||
id: "clear-relationships",
|
||||
label: "Clear catalog relationships",
|
||||
label: "Remove synchronized columns",
|
||||
group: "Catalog cleanup",
|
||||
tone: "destructive",
|
||||
runLabel: "Review cleanup",
|
||||
@@ -473,7 +459,6 @@ export function DatabaseTables({
|
||||
else if (action === "sync-columns") await synchronize("columns", selectedIds);
|
||||
else if (action === "suggest-sensitive") await suggestSensitive();
|
||||
else if (action === "clear-columns") setPendingDelete("columns");
|
||||
else setPendingDelete("relationships");
|
||||
};
|
||||
|
||||
const clearSelection = () => {
|
||||
@@ -544,10 +529,12 @@ export function DatabaseTables({
|
||||
<DatabaseColumns
|
||||
databaseId={databaseId}
|
||||
table={activeTable}
|
||||
databaseVersion={database.version}
|
||||
canManage={canManage}
|
||||
selectedMetadataModel={selectedMetadataModel}
|
||||
descriptionGenerationActive={descriptionGenerationActive}
|
||||
onDescriptionGenerationRunStarted={onDescriptionGenerationRunStarted}
|
||||
onCatalogSyncRunStarted={onRunStarted}
|
||||
onNavigationStateChange={setColumnNavigation}
|
||||
onSuggestSensitive={onSuggestSensitive}
|
||||
catalogOperationActive={Boolean(currentRun)}
|
||||
@@ -594,7 +581,7 @@ export function DatabaseTables({
|
||||
rowHeight={44}
|
||||
headerHeight={38}
|
||||
animateRows={false}
|
||||
overlayNoRowsTemplate="No catalog tables. Test the binding, then sync tables."
|
||||
overlayNoRowsTemplate="No catalog tables. Synchronize the schema from the database view."
|
||||
/>
|
||||
</div>
|
||||
</div>}
|
||||
@@ -655,10 +642,12 @@ export function DatabaseTables({
|
||||
<DatabaseColumns
|
||||
databaseId={databaseId}
|
||||
table={activeTable}
|
||||
databaseVersion={database.version}
|
||||
canManage={canManage}
|
||||
selectedMetadataModel={selectedMetadataModel}
|
||||
descriptionGenerationActive={descriptionGenerationActive}
|
||||
onDescriptionGenerationRunStarted={onDescriptionGenerationRunStarted}
|
||||
onCatalogSyncRunStarted={onRunStarted}
|
||||
onNavigationStateChange={setColumnNavigation}
|
||||
onSuggestSensitive={onSuggestSensitive}
|
||||
onCatalogMetricsChanged={onCatalogMetricsChanged}
|
||||
@@ -710,19 +699,11 @@ export function DatabaseTables({
|
||||
<div className="mr-auto min-w-56">
|
||||
<p id="table-cleanup-confirmation" className="text-sm font-semibold">
|
||||
{presentation === "fleet"
|
||||
? `Clear catalog ${pendingDelete} for ${selectedIds.length} table${selectedIds.length === 1 ? "" : "s"}?`
|
||||
: pendingDelete === "columns"
|
||||
? `Delete all catalog columns for ${selectedIds.length} table${selectedIds.length === 1 ? "" : "s"}?`
|
||||
: `Delete all relationships for ${selectedIds.length} table${selectedIds.length === 1 ? "" : "s"}?`}
|
||||
? `Remove synchronized columns for ${selectedIds.length} table${selectedIds.length === 1 ? "" : "s"}?`
|
||||
: `Remove synchronized columns for ${selectedIds.length} table${selectedIds.length === 1 ? "" : "s"}?`}
|
||||
</p>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{presentation === "fleet"
|
||||
? pendingDelete === "columns"
|
||||
? "Only synchronized catalog columns for these tables will be cleared. The source database is not modified."
|
||||
: "Only synchronized catalog relationships for these tables will be cleared. The source database is not modified."
|
||||
: pendingDelete === "columns"
|
||||
? "Only columns belonging to the selected catalog tables will be removed."
|
||||
: "All incoming and outgoing relationships for the selected catalog tables will be removed."}
|
||||
Only synchronized catalog columns for these tables will be removed. The source database is not modified.
|
||||
</p>
|
||||
</div>
|
||||
<Button type="button" variant="ghost" disabled={busy !== null} onClick={closeDeleteConfirmation}>Cancel</Button>
|
||||
@@ -733,7 +714,7 @@ export function DatabaseTables({
|
||||
disabled={busy !== null}
|
||||
onClick={() => void deleteMetadata(pendingDelete)}
|
||||
>
|
||||
<Trash2 />{presentation === "fleet" ? "Clear catalog" : pendingDelete === "columns" ? "Delete columns" : "Delete relationships"}
|
||||
<Trash2 />Remove synchronized columns
|
||||
</Button>
|
||||
</div>
|
||||
) : (
|
||||
@@ -760,13 +741,13 @@ export function DatabaseTables({
|
||||
<Menu.Portal>
|
||||
<Menu.Positioner side="bottom" align="start" sideOffset={4}>
|
||||
<Menu.Popup className="z-50 min-w-64 rounded-lg bg-popover p-1 text-popover-foreground shadow-md ring-1 ring-foreground/10 outline-none">
|
||||
<Menu.Item className="rounded-md px-3 py-2 text-sm outline-none data-[highlighted]:bg-muted data-[disabled]:opacity-45" disabled={!canManage || !selectedMetadataModel || descriptionGenerationActive || busy !== null || Boolean(currentRun)} onClick={() => void generateDescriptions()}>Generate {selectedIds.length === 1 ? "description" : "descriptions"}</Menu.Item>
|
||||
<Menu.Item className="rounded-md px-3 py-2 text-sm outline-none data-[highlighted]:bg-muted data-[disabled]:opacity-45" disabled={!canManage || !selectedMetadataModel || descriptionGenerationActive || busy !== null || Boolean(currentRun)} onClick={() => void generateDescriptions()}>Generate table description</Menu.Item>
|
||||
<Menu.Item className="rounded-md px-3 py-2 text-sm outline-none data-[highlighted]:bg-muted data-[disabled]:opacity-45" disabled={!canManage || !selectedMetadataModel || descriptionGenerationActive || busy !== null || Boolean(currentRun)} onClick={() => void generateColumnDescriptions()}>Generate descriptions for all columns</Menu.Item>
|
||||
<Menu.Item className="rounded-md px-3 py-2 text-sm outline-none data-[highlighted]:bg-muted data-[disabled]:opacity-45" disabled={!canManage || !bindingReady || busy !== null || Boolean(currentRun)} onClick={() => void synchronize("columns", selectedIds)}>Synchronize columns</Menu.Item>
|
||||
<Menu.Item className="rounded-md px-3 py-2 text-sm outline-none data-[highlighted]:bg-muted data-[disabled]:opacity-45" disabled={!canManage || busy !== null || Boolean(currentRun)} onClick={() => void consolidateDescriptions()}>Move generated description to Description</Menu.Item>
|
||||
<Menu.Item className="rounded-md px-3 py-2 text-sm outline-none data-[highlighted]:bg-muted data-[disabled]:opacity-45" disabled={!canManage || !bindingReady || busy !== null || Boolean(currentRun)} onClick={() => void synchronize("tables")}>Synchronize database tables</Menu.Item>
|
||||
<Menu.Item className="rounded-md px-3 py-2 text-sm outline-none data-[highlighted]:bg-muted data-[disabled]:opacity-45" disabled={!canManage || !bindingReady || busy !== null || Boolean(currentRun)} onClick={() => void synchronize("columns", selectedIds)}>Synchronize columns for selected tables</Menu.Item>
|
||||
<Menu.Item className="rounded-md px-3 py-2 text-sm outline-none data-[highlighted]:bg-muted data-[disabled]:opacity-45" disabled={!canManage || busy !== null || Boolean(currentRun)} onClick={() => void consolidateDescriptions()}>Copy generated descriptions to Description</Menu.Item>
|
||||
<Menu.Separator className="my-1 h-px bg-border" />
|
||||
<Menu.Item className="rounded-md px-3 py-2 text-sm text-destructive outline-none data-[highlighted]:bg-destructive/10 data-[disabled]:opacity-45" disabled={!canManage || busy !== null || Boolean(currentRun)} onClick={() => setPendingDelete("columns")}>Delete all columns</Menu.Item>
|
||||
<Menu.Item className="rounded-md px-3 py-2 text-sm text-destructive outline-none data-[highlighted]:bg-destructive/10 data-[disabled]:opacity-45" disabled={!canManage || busy !== null || Boolean(currentRun)} onClick={() => setPendingDelete("relationships")}>Delete all relationships</Menu.Item>
|
||||
<Menu.Item className="rounded-md px-3 py-2 text-sm text-destructive outline-none data-[highlighted]:bg-destructive/10 data-[disabled]:opacity-45" disabled={!canManage || busy !== null || Boolean(currentRun)} onClick={() => setPendingDelete("columns")}>Remove synchronized columns</Menu.Item>
|
||||
</Menu.Popup>
|
||||
</Menu.Positioner>
|
||||
</Menu.Portal>
|
||||
@@ -799,12 +780,11 @@ export function DatabaseTables({
|
||||
<input ref={searchInputRef} className="h-8 min-w-40 flex-1 rounded-md border border-input bg-background px-2.5 text-sm outline-none focus:border-primary/60 focus:ring-3 focus:ring-ring/15" aria-label="Search tables" placeholder="Search" value={search} onChange={(event) => setSearch(event.target.value)} />
|
||||
<span aria-live="polite" className="whitespace-nowrap text-xs tabular-nums text-muted-foreground">{search.trim() ? `${displayedCount} of ${data.length}` : displayedCount}</span>
|
||||
<Button type="button" variant="outline" disabled={isFetching || busy !== null} onClick={() => void refetch()}><RefreshCw className={isFetching ? "animate-spin" : ""} />Refresh</Button>
|
||||
<Button type="button" disabled={!canManage || !bindingReady || busy !== null || Boolean(currentRun)} title={!bindingReady ? "Test the current database binding before synchronizing tables" : undefined} onClick={() => void synchronize("tables")}><RefreshCw className={busy === "sync" ? "animate-spin" : ""} />Sync tables</Button>
|
||||
</>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
{!bindingReady ? <div className="border-b border-border bg-muted/35 px-4 py-3 text-sm text-muted-foreground">Test the current database binding from Overview before synchronizing tables.</div> : null}
|
||||
{!bindingReady ? <div className="border-b border-border bg-muted/35 px-4 py-3 text-sm text-muted-foreground">Test the current database binding from Overview before synchronizing columns.</div> : null}
|
||||
{fleetQueryError ?? <div className="relative min-h-[280px] flex-1">
|
||||
<div className={`thot-database-grid ${presentation === "fleet" ? "thot-fleet-ledger-grid " : ""}ag-theme-alpine absolute inset-0 h-full w-full`}>
|
||||
<AgGridReact<CatalogTable>
|
||||
@@ -825,7 +805,7 @@ export function DatabaseTables({
|
||||
rowHeight={44}
|
||||
headerHeight={38}
|
||||
animateRows={false}
|
||||
overlayNoRowsTemplate="No catalog tables. Test the binding, then sync tables."
|
||||
overlayNoRowsTemplate="No catalog tables. Synchronize the schema from the database view."
|
||||
/>
|
||||
</div>
|
||||
</div>}
|
||||
|
||||
Reference in New Issue
Block a user