Adopt shared WebUI layout primitives

This commit is contained in:
2026-08-18 10:42:53 +02:00
parent c2c400a43a
commit 79fa45d14a
3 changed files with 14 additions and 23 deletions
@@ -1,6 +1,6 @@
import { Download, FileJson, Play, ShieldCheck } from "lucide-react";
import { useEffect, useMemo, useState } from "react";
import {
import { ContentGrid, ActionToolbar,
Button,
Card,
DismissibleAlert,
@@ -174,7 +174,7 @@ export function ProviderReportWorkspace({ settings, auth, report }: {
</div>
{execution ?
<>
<div className="reporting-output-toolbar">
<ActionToolbar 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")} />
@@ -182,7 +182,7 @@ export function ProviderReportWorkspace({ settings, auth, report }: {
{report.export_formats.includes("json") &&
<IconButton label="Download JSON" icon={<FileJson size={17} />} variant="ghost" onClick={() => void download("json")} />
}
</div>
</ActionToolbar>
<div className="reporting-provider-output">
<ProviderResult execution={execution} />
</div>
@@ -227,11 +227,11 @@ function ProviderResult({ execution }: { execution: ProviderReportExecution }) {
return (
<Card title={group} key={group}>
{metrics.length > 0 &&
<div className="dashboard-grid reporting-provider-metrics">
<ContentGrid columns={2} collapseAt="workspace" className="reporting-provider-metrics">
{metrics.map((field) =>
<MetricCard key={field.path} label={field.label} value={displayValue(pathValue(execution.result, field.path))} />
)}
</div>
</ContentGrid>
}
{details.length > 0 &&
<dl className="detail-list">
@@ -19,7 +19,7 @@ import {
useState,
type FormEvent
} from "react";
import {
import { FormGrid, ActionToolbar,
Button,
DataGrid,
Dialog,
@@ -250,7 +250,7 @@ export default function ReportingPage({ settings, auth }: PlatformRouteContext)
return (
<main className="reporting-page">
<div className="reporting-shell">
<div className="reporting-toolbar">
<ActionToolbar className="reporting-toolbar">
<form className="reporting-search" onSubmit={submitSearch}>
<Search size={17} aria-hidden="true" />
<input
@@ -271,7 +271,7 @@ export default function ReportingPage({ settings, auth }: PlatformRouteContext)
variant="ghost"
onClick={() => void reload()}
/>
</div>
</ActionToolbar>
{error &&
<DismissibleAlert tone="danger" resetKey={error}>
{error}
@@ -345,7 +345,7 @@ export default function ReportingPage({ settings, auth }: PlatformRouteContext)
onQueryChange={setQuery}
onParametersChange={setParameters}
/>
<div className="reporting-output-toolbar">
<ActionToolbar className="reporting-output-toolbar">
<SegmentedControl
ariaLabel="Report output"
value={outputMode}
@@ -365,7 +365,7 @@ export default function ReportingPage({ settings, auth }: PlatformRouteContext)
}
</>
}
</div>
</ActionToolbar>
<div className="reporting-output">
{!execution && <div className="reporting-empty">Run the report or select a previous execution.</div>}
{execution && outputMode === "visual" && <ReportVisual execution={execution} onDrill={execution.query.mode === "detail" ? undefined : drill} />}
@@ -757,7 +757,7 @@ function PublishDialog({ open, targets, onClose, onPublish }: {
</Button>
</>}>
{dialogError && <DismissibleAlert tone="danger" resetKey={dialogError}>{dialogError}</DismissibleAlert>}
<div className="reporting-dialog-grid">
<FormGrid columns={2} gap="small" collapseAt="narrow">
<label className="reporting-dialog-field">
<span>Target</span>
<select value={targetCapability} onChange={(event) => {
@@ -784,7 +784,7 @@ function PublishDialog({ open, targets, onClose, onPublish }: {
<label className="reporting-dialog-field"><span>Sender address</span><input type="email" value={fromAddress} onChange={(event) => setFromAddress(event.target.value)} /></label>
<label className="reporting-dialog-field reporting-dialog-span"><span>Subject</span><input value={subject} onChange={(event) => setSubject(event.target.value)} placeholder="Generated from report name" /></label>
</>}
</div>
</FormGrid>
{target?.reason && <DismissibleAlert tone="warning" dismissible={false}>{target.reason}</DismissibleAlert>}
</Dialog>
);
@@ -936,10 +936,10 @@ function ScheduleDialog({ open, onClose, onSave }: { open: boolean; onClose: ()
<Button onClick={onClose}>Cancel</Button>
<Button variant="primary" disabled={!name.trim() || saving} onClick={() => { setSaving(true); void onSave(name.trim(), Number(interval)).finally(() => setSaving(false)); }}>Schedule</Button>
</>}>
<div className="reporting-dialog-grid">
<FormGrid columns={2} gap="small" collapseAt="narrow">
<label className="reporting-dialog-field"><span>Name</span><input value={name} onChange={(event) => setName(event.target.value)} autoFocus /></label>
<label className="reporting-dialog-field"><span>Interval</span><select value={interval} onChange={(event) => setIntervalValue(event.target.value)}><option value="3600">Hourly</option><option value="86400">Daily</option><option value="604800">Weekly</option><option value="2592000">Every 30 days</option></select></label>
</div>
</FormGrid>
</Dialog>
);
}
-9
View File
@@ -611,12 +611,6 @@
overflow: auto;
}
.reporting-dialog-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 12px;
}
@media (max-width: 1100px) {
.reporting-workspace {
grid-template-columns: minmax(220px, 28%) minmax(0, 1fr);
@@ -647,7 +641,4 @@
width: 100%;
}
.reporting-dialog-grid {
grid-template-columns: 1fr;
}
}