From 20d134898acf6f5c2764c88a3ffd7fb0b2e4da10 Mon Sep 17 00:00:00 2001 From: Albrecht Degering Date: Tue, 18 Aug 2026 13:17:31 +0200 Subject: [PATCH] Adopt shared WebUI structural primitives --- .../scripts/test-dataflow-page-structure.mjs | 9 +- .../src/features/dataflow/DataflowCanvas.tsx | 5 +- webui/src/features/dataflow/DataflowNode.tsx | 11 +- webui/src/features/dataflow/DataflowPage.tsx | 148 +++--- webui/src/features/dataflow/NodeInspector.tsx | 260 +++++------ webui/src/styles/dataflow.css | 432 +----------------- 6 files changed, 225 insertions(+), 640 deletions(-) diff --git a/webui/scripts/test-dataflow-page-structure.mjs b/webui/scripts/test-dataflow-page-structure.mjs index 7e80242..eb95bcc 100644 --- a/webui/scripts/test-dataflow-page-structure.mjs +++ b/webui/scripts/test-dataflow-page-structure.mjs @@ -60,11 +60,14 @@ const checks = [ moduleEntry.indexOf("./styles/dataflow.css"), "XyFlow base styles before GovOPlaN overrides" ], - [css.includes("height: calc(100vh - 115px)"), "full-height workspace"], + [ + page.includes(' { @@ -360,7 +361,7 @@ export default function DataflowCanvas({ {!graph.nodes.length ? ( -
Drop a source here
+ ) : null} ); diff --git a/webui/src/features/dataflow/DataflowNode.tsx b/webui/src/features/dataflow/DataflowNode.tsx index a52842d..30e31cf 100644 --- a/webui/src/features/dataflow/DataflowNode.tsx +++ b/webui/src/features/dataflow/DataflowNode.tsx @@ -1,4 +1,5 @@ import { Handle, Position, type Node, type NodeProps } from "@xyflow/react"; +import { CountBadge, DefinitionNodeIcon } from "@govoplan/core-webui"; import type { NodeTypeDefinition } from "../../api/dataflow"; import { dataflowNodeIcon } from "./nodeIcons"; @@ -31,7 +32,7 @@ export default function DataflowNode({ data, selected }: NodeProps ))} @@ -46,15 +47,15 @@ export default function DataflowNode({ data, selected }: NodeProps )) : null} - + {data.label} {data.definition.label} {typeof data.outputRows === "number" ? ( - {data.outputRows} + {data.outputRows} ) : null} {data.definition.output_ports.map((port, index) => ( ))} diff --git a/webui/src/features/dataflow/DataflowPage.tsx b/webui/src/features/dataflow/DataflowPage.tsx index 4293f24..ff8036e 100644 --- a/webui/src/features/dataflow/DataflowPage.tsx +++ b/webui/src/features/dataflow/DataflowPage.tsx @@ -30,16 +30,29 @@ import { DialogSection, ToolbarGroup, ActionToolbar, ActionBlockerHint, Button, ConfirmDialog, + ContentGrid, + ContentSection, Dialog, DismissibleAlert, + DefinitionPalette, + DefinitionPaletteGroup, + DefinitionPaletteItem, DocumentationHelpLink, + FilterBar, + FloatingStatus, FormField, IconButton, LoadingFrame, ReferenceSelect, SegmentedControl, + SelectionList, + SelectionListItem, + SelectionListItemContent, + StatePanel, StatusBadge, ToggleSwitch, + WorkspaceFrame, + WorkspaceLayout, hasScope, isApiError, useUnsavedChanges, @@ -584,10 +597,18 @@ export default function DataflowPage({ settings, auth }: { settings: ApiSettings }; return ( -
-
- - -
+ } + > {draft ? ( <> - +
{draft.editorMode === "graph" ? ( - + ) : null} -
+
{draft.editorMode === "graph" ? ( ) : (
- + Constrained Dataflow SQL -
+ } + /> )} - {working ?
Working...
: null} -
-
+ {working ? Working... : null} + setError(apiErrorMessage(sourceError))); }} /> -
+
); } @@ -1207,7 +1215,7 @@ function DefinitionSettingsDialog({ -
+ onChange({ allowAutomation: value })} /> -
+ {draft.governance?.derived_from_pipeline_id ? ( -
+ Derived from {draft.governance.derived_from_pipeline_id} @@ -1242,10 +1250,10 @@ function DefinitionSettingsDialog({ {draft.governance.derived_from_revision} {draft.governance.derived_from_hash} -
+ ) : null} {provenance.length ? ( -
+ Effective Policy path {provenance.map((item, index) => ( @@ -1255,7 +1263,7 @@ function DefinitionSettingsDialog({ {!editable && draft.governance?.actions.edit?.reason ? ( {draft.governance.actions.edit.reason} ) : null} -
+ ) : null} ) : null} @@ -2745,9 +2753,7 @@ function ReconciliationDecisionDialog({ {!rows.length ? ( -
- Run a preview of a reconciliation comparison that emits stable key and input hashes. -
+ ) : (
@@ -2844,9 +2850,7 @@ function ReconciliationDecisionDialog({
) : ( -
- {loading ? "Loading decision sets..." : "Create or select a decision set to review this row."} -
+ )}
@@ -2885,7 +2889,7 @@ function ResultPanel({ const previewRows = preview?.node_preview?.total_rows ?? preview?.total_rows; return (
- +
ariaLabel="Result view" @@ -2926,9 +2930,9 @@ function ResultPanel({ } function PreviewTable({ preview }: { preview: PipelinePreview | null }) { - if (!preview) return
No preview has been run.
; + if (!preview) return ; if (preview.status === "failed" && !preview.node_preview) { - return
Preview failed.
; + return ; } const result = preview.node_preview ?? preview; return ( @@ -2978,7 +2982,7 @@ function DiagnosticsPanel({ nodeDiagnostics: NodePreviewDiagnostic[]; }) { if (!diagnostics.length && !nodeDiagnostics.length) { - return
No diagnostics.
; + return ; } return (
diff --git a/webui/src/features/dataflow/NodeInspector.tsx b/webui/src/features/dataflow/NodeInspector.tsx index 5d166ca..5bba7cb 100644 --- a/webui/src/features/dataflow/NodeInspector.tsx +++ b/webui/src/features/dataflow/NodeInspector.tsx @@ -1,9 +1,11 @@ import { useEffect, useState, type ComponentProps } from "react"; import { Play, Trash2 } from "lucide-react"; import { + ActionToolbar, DismissibleAlert, FormField as CoreFormField, - IconButton + IconButton, + StatePanel } from "@govoplan/core-webui"; import type { NodeTypeDefinition, @@ -14,7 +16,7 @@ import { DATAFLOW_NODE_DOCUMENTATION } from "./interfacePatterns"; type NodeFormFieldProps = ComponentProps; -function FormField({ documentation, ...props }: NodeFormFieldProps) { +function NodeFormField({ documentation, ...props }: NodeFormFieldProps) { return ( -
+ Inspector -
-
No node selected
+ + ); } @@ -161,7 +163,7 @@ export default function NodeInspector({ return (