Adopt shared WebUI layout primitives

This commit is contained in:
2026-08-18 10:42:53 +02:00
parent 0363e9f589
commit 3800ad4662
3 changed files with 13 additions and 13 deletions
@@ -1,5 +1,5 @@
import { useEffect, useState, type FormEvent } from "react"; import { useEffect, useState, type FormEvent } from "react";
import { import { DialogForm,
Button, Button,
Dialog, Dialog,
DismissibleAlert, DismissibleAlert,
@@ -146,7 +146,7 @@ export function RecordCatalogDialog({
footer={<><Button type="button" variant="ghost" onClick={onClose} disabled={saving}>Cancel</Button><Button type="submit" form="records-catalog-form" variant="primary" disabledReason={saving ? "The catalog revision is being saved." : !isValid ? "Complete all required catalog fields." : undefined}>{saving ? "Saving" : "Save revision"}</Button></>} footer={<><Button type="button" variant="ghost" onClick={onClose} disabled={saving}>Cancel</Button><Button type="submit" form="records-catalog-form" variant="primary" disabledReason={saving ? "The catalog revision is being saved." : !isValid ? "Complete all required catalog fields." : undefined}>{saving ? "Saving" : "Save revision"}</Button></>}
> >
{error && <DismissibleAlert tone="danger" resetKey={error}>{error}</DismissibleAlert>} {error && <DismissibleAlert tone="danger" resetKey={error}>{error}</DismissibleAlert>}
<form id="records-catalog-form" className="records-dialog-form" onSubmit={submit}> <DialogForm id="records-catalog-form" className="records-dialog-form" onSubmit={submit}>
<FormField label="Catalog object"> <FormField label="Catalog object">
<select value={kind} onChange={(event) => { setKind(event.target.value as typeof kind); setSelectedId(""); }}> <select value={kind} onChange={(event) => { setKind(event.target.value as typeof kind); setSelectedId(""); }}>
<option value="file-plan">File-plan node</option> <option value="file-plan">File-plan node</option>
@@ -164,7 +164,7 @@ export function RecordCatalogDialog({
<FormField label="Label"><input value={label} onChange={(event) => setLabel(event.target.value)} required /></FormField> <FormField label="Label"><input value={label} onChange={(event) => setLabel(event.target.value)} required /></FormField>
{kind === "file-plan" ? <FormField label="Parent node"><select value={parentId} onChange={(event) => setParentId(event.target.value)}><option value="">Top level</option>{catalog.file_plan.filter((item) => item.node_id !== identifier).map((item) => <option key={item.node_id} value={item.node_id}>{item.code} · {item.label}</option>)}</select></FormField> : <><FormField label="File-plan node"><select value={filePlanNodeId} onChange={(event) => setFilePlanNodeId(event.target.value)} required>{catalog.file_plan.map((item) => <option key={item.node_id} value={item.node_id}>{item.code} · {item.label}</option>)}</select></FormField><FormField label="Retention period (days)"><input type="number" min="0" value={retentionDays} onChange={(event) => setRetentionDays(event.target.value)} /></FormField><FormField label="Retention trigger"><select value={closureTrigger} onChange={(event) => setClosureTrigger(event.target.value)}><option value="record_closed">Record closure</option><option value="calendar_month_end">End of closure month</option><option value="calendar_year_end">End of closure year</option><option value="explicit">Explicit date at closure</option></select></FormField></>} {kind === "file-plan" ? <FormField label="Parent node"><select value={parentId} onChange={(event) => setParentId(event.target.value)}><option value="">Top level</option>{catalog.file_plan.filter((item) => item.node_id !== identifier).map((item) => <option key={item.node_id} value={item.node_id}>{item.code} · {item.label}</option>)}</select></FormField> : <><FormField label="File-plan node"><select value={filePlanNodeId} onChange={(event) => setFilePlanNodeId(event.target.value)} required>{catalog.file_plan.map((item) => <option key={item.node_id} value={item.node_id}>{item.code} · {item.label}</option>)}</select></FormField><FormField label="Retention period (days)"><input type="number" min="0" value={retentionDays} onChange={(event) => setRetentionDays(event.target.value)} /></FormField><FormField label="Retention trigger"><select value={closureTrigger} onChange={(event) => setClosureTrigger(event.target.value)}><option value="record_closed">Record closure</option><option value="calendar_month_end">End of closure month</option><option value="calendar_year_end">End of closure year</option><option value="explicit">Explicit date at closure</option></select></FormField></>}
<FormField label="Description"><textarea rows={4} value={description} onChange={(event) => setDescription(event.target.value)} /></FormField> <FormField label="Description"><textarea rows={4} value={description} onChange={(event) => setDescription(event.target.value)} /></FormField>
</form> </DialogForm>
</Dialog> </Dialog>
); );
} }
@@ -10,7 +10,7 @@ import {
RotateCcw RotateCcw
} from "lucide-react"; } from "lucide-react";
import { useEffect, useMemo, useState, type FormEvent } from "react"; import { useEffect, useMemo, useState, type FormEvent } from "react";
import { import { DialogForm,
Button, Button,
Dialog, Dialog,
DismissibleAlert, DismissibleAlert,
@@ -286,7 +286,7 @@ export function RecordLifecyclePanel({
> >
{error && <DismissibleAlert tone="danger" resetKey={error}>{error}</DismissibleAlert>} {error && <DismissibleAlert tone="danger" resetKey={error}>{error}</DismissibleAlert>}
{action === "recovery" ? <RecoveryResult value={recovery} loading={saving} /> : ( {action === "recovery" ? <RecoveryResult value={recovery} loading={saving} /> : (
<form id="records-lifecycle-form" className="records-dialog-form" onSubmit={submit}> <DialogForm id="records-lifecycle-form" className="records-dialog-form" onSubmit={submit}>
{action === "volume" && <FormField label="Volume label" helpContextId="records.field.volume-label"><input value={label} onChange={(event) => setLabel(event.target.value)} required /></FormField>} {action === "volume" && <FormField label="Volume label" helpContextId="records.field.volume-label"><input value={label} onChange={(event) => setLabel(event.target.value)} required /></FormField>}
{["appraise", "disposition"].includes(action ?? "") && <FormField label="Disposition" helpContextId="records.field.disposition"><select value={outcome} onChange={(event) => setOutcome(event.target.value as typeof outcome)}><option value="retain">Retain</option><option value="transfer">Transfer</option><option value="destroy">Destroy</option><option value="reclassify">Reclassify</option></select></FormField>} {["appraise", "disposition"].includes(action ?? "") && <FormField label="Disposition" helpContextId="records.field.disposition"><select value={outcome} onChange={(event) => setOutcome(event.target.value as typeof outcome)}><option value="retain">Retain</option><option value="transfer">Transfer</option><option value="destroy">Destroy</option><option value="reclassify">Reclassify</option></select></FormField>}
{action === "hold" && <FormField label="Authority" helpContextId="records.field.hold-authority"><input value={authority} onChange={(event) => setAuthority(event.target.value)} required /></FormField>} {action === "hold" && <FormField label="Authority" helpContextId="records.field.hold-authority"><input value={authority} onChange={(event) => setAuthority(event.target.value)} required /></FormField>}
@@ -296,7 +296,7 @@ export function RecordLifecyclePanel({
{action === "finalize" && currentDisposition?.approval_request_id && <DismissibleAlert tone="info" dismissible={false} compact>Approval request <a href="/approvals">{currentDisposition.approval_request_id}</a> must be approved by another account.</DismissibleAlert>} {action === "finalize" && currentDisposition?.approval_request_id && <DismissibleAlert tone="info" dismissible={false} compact>Approval request <a href="/approvals">{currentDisposition.approval_request_id}</a> must be approved by another account.</DismissibleAlert>}
{requiresReason(action) && <FormField label="Reason" helpContextId="records.field.lifecycle-reason"><textarea value={reason} onChange={(event) => setReason(event.target.value)} rows={4} required /></FormField>} {requiresReason(action) && <FormField label="Reason" helpContextId="records.field.lifecycle-reason"><textarea value={reason} onChange={(event) => setReason(event.target.value)} rows={4} required /></FormField>}
<FormField label="Purpose"><input value={purpose} onChange={(event) => setPurpose(event.target.value)} required /></FormField> <FormField label="Purpose"><input value={purpose} onChange={(event) => setPurpose(event.target.value)} required /></FormField>
</form> </DialogForm>
)} )}
</Dialog> </Dialog>
</> </>
+7 -7
View File
@@ -15,7 +15,7 @@ import {
type FormEvent type FormEvent
} from "react"; } from "react";
import { useSearchParams } from "react-router"; import { useSearchParams } from "react-router";
import { import { DialogForm, ActionToolbar,
Button, Button,
DataGrid, DataGrid,
Dialog, Dialog,
@@ -233,7 +233,7 @@ export default function RecordsPage({ settings, auth }: PlatformRouteContext) {
return ( return (
<main className="records-page" data-help-context-id="records.workspace"> <main className="records-page" data-help-context-id="records.workspace">
<div className="records-shell"> <div className="records-shell">
<div className="records-toolbar"> <ActionToolbar className="records-toolbar">
<Button <Button
type="button" type="button"
variant="primary" variant="primary"
@@ -273,7 +273,7 @@ export default function RecordsPage({ settings, auth }: PlatformRouteContext) {
/> />
)} )}
<DocumentationHelpLink reference={RECORDS_DOCUMENTATION} /> <DocumentationHelpLink reference={RECORDS_DOCUMENTATION} />
</div> </ActionToolbar>
{error && <DismissibleAlert tone="danger" resetKey={error}>{error}</DismissibleAlert>} {error && <DismissibleAlert tone="danger" resetKey={error}>{error}</DismissibleAlert>}
{filingPreset && {filingPreset &&
@@ -664,7 +664,7 @@ function RecordDialog({
} }
> >
{error && <DismissibleAlert tone="danger" resetKey={error}>{error}</DismissibleAlert>} {error && <DismissibleAlert tone="danger" resetKey={error}>{error}</DismissibleAlert>}
<form id="records-record-form" className="records-dialog-form" onSubmit={submit}> <DialogForm id="records-record-form" className="records-dialog-form" onSubmit={submit}>
<FormField label="Record number" helpContextId="records.field.record-number"> <FormField label="Record number" helpContextId="records.field.record-number">
<input value={recordNumber} onChange={(event) => setRecordNumber(event.target.value)} disabled={mode === "edit"} required /> <input value={recordNumber} onChange={(event) => setRecordNumber(event.target.value)} disabled={mode === "edit"} required />
</FormField> </FormField>
@@ -698,7 +698,7 @@ function RecordDialog({
<FormField label="Change reason" helpContextId="records.field.change-reason"> <FormField label="Change reason" helpContextId="records.field.change-reason">
<textarea value={changeReason} onChange={(event) => setChangeReason(event.target.value)} rows={3} required /> <textarea value={changeReason} onChange={(event) => setChangeReason(event.target.value)} rows={3} required />
</FormField> </FormField>
</form> </DialogForm>
</Dialog> </Dialog>
); );
} }
@@ -810,7 +810,7 @@ function FilingDialog({
<DismissibleAlert tone="info" dismissible={false} compact> <DismissibleAlert tone="info" dismissible={false} compact>
The source module verifies your current access and resolves this exact revision before Records stores the reference. The source module verifies your current access and resolves this exact revision before Records stores the reference.
</DismissibleAlert> </DismissibleAlert>
<form id="records-filing-form" className="records-dialog-form" onSubmit={submit}> <DialogForm id="records-filing-form" className="records-dialog-form" onSubmit={submit}>
<FormField label="Source module" helpContextId="records.field.source-module"> <FormField label="Source module" helpContextId="records.field.source-module">
<select value={sourceModule} onChange={(event) => setSourceModule(event.target.value)} required> <select value={sourceModule} onChange={(event) => setSourceModule(event.target.value)} required>
{providers.map((item) => <option key={item.source_module} value={item.source_module}>{humanize(item.source_module)}</option>)} {providers.map((item) => <option key={item.source_module} value={item.source_module}>{humanize(item.source_module)}</option>)}
@@ -839,7 +839,7 @@ function FilingDialog({
<FormField label="Filing reason" documentation={RECORDS_FIELD_DOCUMENTATION.filingReason}> <FormField label="Filing reason" documentation={RECORDS_FIELD_DOCUMENTATION.filingReason}>
<textarea value={filingReason} onChange={(event) => setFilingReason(event.target.value)} rows={4} required /> <textarea value={filingReason} onChange={(event) => setFilingReason(event.target.value)} rows={4} required />
</FormField> </FormField>
</form> </DialogForm>
</Dialog> </Dialog>
); );
} }