Adopt shared WebUI structural primitives

This commit is contained in:
2026-08-18 13:17:32 +02:00
parent e13d95c843
commit 63ee29e222
3 changed files with 34 additions and 103 deletions
@@ -7,6 +7,7 @@ import { ContentGrid, ActionToolbar,
DismissibleAlert,
IconButton,
MetricCard,
StatePanel,
StatusBadge,
hasScope,
type ApiSettings,
@@ -175,7 +176,7 @@ export function ProviderReportWorkspace({ settings, auth, report }: {
</div>
{execution ?
<>
<ActionToolbar className="reporting-output-toolbar">
<ActionToolbar surface="panel-header" className="reporting-output-toolbar">
<span>Generated {formatDateTime(execution.generated_at)}</span>
{report.export_formats.includes("csv") &&
<IconButton label="Download CSV" icon={<Download size={17} />} variant="ghost" onClick={() => void download("csv")} />
@@ -188,7 +189,7 @@ export function ProviderReportWorkspace({ settings, auth, report }: {
<ProviderResult execution={execution} />
</div>
</> :
<div className="reporting-empty">Select the parameters and run this governed report.</div>
<StatePanel size="fill" description="Select the parameters and run this governed report." />
}
</>
);
+27 -27
View File
@@ -25,13 +25,19 @@ import { FormGrid, ActionToolbar,
Dialog,
DocumentationHelpLink,
DismissibleAlert,
FilterBar,
IconButton,
LoadingIndicator,
PageScrollViewport,
StatePanel,
SegmentedControl,
SelectionList,
SelectionListItem,
SelectionListItemContent,
StatusBadge,
ToggleSwitch,
hasScope,
WorkspaceFrame,
type DataGridColumn,
type PlatformRouteContext
} from "@govoplan/core-webui";
@@ -249,9 +255,9 @@ export default function ReportingPage({ settings, auth }: PlatformRouteContext)
return (
<main className="reporting-page">
<div className="reporting-shell">
<ActionToolbar className="reporting-toolbar">
<form className="reporting-search" onSubmit={submitSearch}>
<WorkspaceFrame className="reporting-shell" label="Reporting workspace" interfaceId="reporting.workspace" helpContextId="reporting.page.workspace" helpModuleId="reporting">
<ActionToolbar surface="panel-header" className="reporting-toolbar">
<FilterBar as="form" surface="control" wrap="never" width="compact" className="reporting-search" onSubmit={submitSearch}>
<Search size={17} aria-hidden="true" />
<input
value={search}
@@ -259,7 +265,7 @@ export default function ReportingPage({ settings, auth }: PlatformRouteContext)
aria-label="Search reports"
placeholder="Search reports"
/>
</form>
</FilterBar>
<span className="reporting-count">{reports.length + providerReports.length} reports</span>
<DocumentationHelpLink
reference={{ topicId: "reporting.governed-bi", documentationType: "user" }}
@@ -280,38 +286,32 @@ export default function ReportingPage({ settings, auth }: PlatformRouteContext)
<div className="reporting-workspace">
<PageScrollViewport className="reporting-catalogue">
{loading && <LoadingIndicator label="Loading reports" />}
{!loading && reports.length + providerReports.length === 0 && <div className="reporting-empty">No active reports are available.</div>}
<div className="reporting-report-list" role="list">
{providerReports.length > 0 && <div className="reporting-list-heading">Module reports</div>}
{!loading && reports.length + providerReports.length === 0 && <StatePanel size="compact" description="No active reports are available." />}
<SelectionList variant="navigation" label="Reports">
{providerReports.length > 0 && <div className="reporting-list-heading" role="presentation">Module reports</div>}
{providerReports.map((item) => {
const key = `${item.provider_id}:${item.report_id}`;
return (
<button
type="button"
role="listitem"
<SelectionListItem
key={key}
className={`reporting-report-row${selectedProviderKey === key ? " is-selected" : ""}`}
selected={selectedProviderKey === key}
onClick={() => { setSelectedProviderKey(key); setSelectedId(""); }}>
<BarChart3 size={17} aria-hidden="true" />
<span><strong>{item.title}</strong><small>{item.provider_id} · {item.revision}</small></span>
<SelectionListItemContent leading={<BarChart3 size={17} />} title={item.title} description={`${item.provider_id} · ${item.revision}`} />
<StatusBadge status={item.available ? "active" : "locked"} label={item.available ? "Available" : "Restricted"} />
</button>
</SelectionListItem>
);
})}
{reports.length > 0 && <div className="reporting-list-heading">Semantic reports</div>}
{reports.length > 0 && <div className="reporting-list-heading" role="presentation">Semantic reports</div>}
{reports.map((item) =>
<button
type="button"
role="listitem"
<SelectionListItem
key={item.definition_id}
className={`reporting-report-row${selectedId === item.definition_id ? " is-selected" : ""}`}
selected={selectedId === item.definition_id}
onClick={() => { setSelectedId(item.definition_id); setSelectedProviderKey(""); }}>
<BarChart3 size={17} aria-hidden="true" />
<span><strong>{item.name}</strong><small>{item.definition_key} · r{item.revision}</small></span>
<SelectionListItemContent leading={<BarChart3 size={17} />} title={item.name} description={`${item.definition_key} · r${item.revision}`} />
<StatusBadge status="active" label="Active" />
</button>
</SelectionListItem>
)}
</div>
</SelectionList>
</PageScrollViewport>
<section className="reporting-result-region">
{selectedProvider ?
@@ -345,7 +345,7 @@ export default function ReportingPage({ settings, auth }: PlatformRouteContext)
onQueryChange={setQuery}
onParametersChange={setParameters}
/>
<ActionToolbar className="reporting-output-toolbar">
<ActionToolbar surface="panel-header" className="reporting-output-toolbar">
<SegmentedControl
ariaLabel="Report output"
value={outputMode}
@@ -367,12 +367,12 @@ export default function ReportingPage({ settings, auth }: PlatformRouteContext)
}
</ActionToolbar>
<div className="reporting-output">
{!execution && <div className="reporting-empty">Run the report or select a previous execution.</div>}
{!execution && <StatePanel size="fill" description="Run the report or select a previous execution." />}
{execution && outputMode === "visual" && <ReportVisual execution={execution} onDrill={execution.query.mode === "detail" ? undefined : drill} />}
{execution && outputMode === "table" && <ReportTable execution={execution} onDrill={execution.query.mode === "detail" ? undefined : drill} />}
</div>
</> :
<div className="reporting-empty">Select a report.</div>
<StatePanel size="fill" title="Reports" description="Select a report." />
}
</section>
<PageScrollViewport className="reporting-inspector">
@@ -398,7 +398,7 @@ export default function ReportingPage({ settings, auth }: PlatformRouteContext)
/>}
</PageScrollViewport>
</div>
</div>
</WorkspaceFrame>
<SaveViewDialog
open={saveDialogOpen}
onClose={() => setSaveDialogOpen(false)}