Adopt shared WebUI layout primitives
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
import { useEffect, useMemo, useState } from "react";
|
import { useEffect, useMemo, useState } from "react";
|
||||||
import { Download, Eye, Play, Plus, RefreshCw, Search, ShieldCheck } from "lucide-react";
|
import { Download, Eye, Play, Plus, RefreshCw, Search, ShieldCheck } from "lucide-react";
|
||||||
import type { ApiSettings, DataGridColumn } from "@govoplan/core-webui";
|
import type { FormGrid, ApiSettings, DataGridColumn } from "@govoplan/core-webui";
|
||||||
import {
|
import {
|
||||||
AdminIconButton,
|
AdminIconButton,
|
||||||
AdminPageLayout,
|
AdminPageLayout,
|
||||||
@@ -378,17 +378,17 @@ export default function DataSubjectRequestsPanel({
|
|||||||
</> : <DismissibleAlert tone="info">{I18N.noSelection}</DismissibleAlert>}
|
</> : <DismissibleAlert tone="info">{I18N.noSelection}</DismissibleAlert>}
|
||||||
</AdminPageLayout>
|
</AdminPageLayout>
|
||||||
|
|
||||||
<Dialog
|
<Dialog variant="administration" size="wide"
|
||||||
open={creating}
|
open={creating}
|
||||||
title={I18N.createTitle}
|
title={I18N.createTitle}
|
||||||
className="admin-dialog admin-dialog-wide"
|
className=""
|
||||||
portal
|
portal
|
||||||
closeDisabled={busy}
|
closeDisabled={busy}
|
||||||
onClose={() => setCreating(false)}
|
onClose={() => setCreating(false)}
|
||||||
footer={<><Button onClick={() => setCreating(false)} disabled={busy}>{I18N.cancel}</Button><Button variant="primary" onClick={() => void create()} disabled={busy || !draft.reference.trim() || !draft.purpose.trim()}>{I18N.save}</Button></>}
|
footer={<><Button onClick={() => setCreating(false)} disabled={busy}>{I18N.cancel}</Button><Button variant="primary" onClick={() => void create()} disabled={busy || !draft.reference.trim() || !draft.purpose.trim()}>{I18N.save}</Button></>}
|
||||||
helpContextId="admin.privacy.data-subject-requests"
|
helpContextId="admin.privacy.data-subject-requests"
|
||||||
>
|
>
|
||||||
<div className="admin-form-grid two-columns">
|
<FormGrid columns={2} gap="small" collapseAt="workspace" className="">
|
||||||
<FormField label={I18N.reference}><input value={draft.reference} onChange={(event) => setDraft({ ...draft, reference: event.target.value })} /></FormField>
|
<FormField label={I18N.reference}><input value={draft.reference} onChange={(event) => setDraft({ ...draft, reference: event.target.value })} /></FormField>
|
||||||
<FormField label={I18N.kindLabel}><select value={draft.requestKind} onChange={(event) => setDraft({ ...draft, requestKind: event.target.value as Draft["requestKind"] })}><option value="access">{I18N.accessRequest}</option><option value="erasure">{I18N.erasureRequest}</option><option value="access_and_erasure">{I18N.combinedRequest}</option></select></FormField>
|
<FormField label={I18N.kindLabel}><select value={draft.requestKind} onChange={(event) => setDraft({ ...draft, requestKind: event.target.value as Draft["requestKind"] })}><option value="access">{I18N.accessRequest}</option><option value="erasure">{I18N.erasureRequest}</option><option value="access_and_erasure">{I18N.combinedRequest}</option></select></FormField>
|
||||||
<FormField label={I18N.email}><input type="email" value={draft.email} onChange={(event) => setDraft({ ...draft, email: event.target.value })} /></FormField>
|
<FormField label={I18N.email}><input type="email" value={draft.email} onChange={(event) => setDraft({ ...draft, email: event.target.value })} /></FormField>
|
||||||
@@ -400,13 +400,13 @@ export default function DataSubjectRequestsPanel({
|
|||||||
<FormField label={I18N.legalBasis}><input value={draft.legalBasis} onChange={(event) => setDraft({ ...draft, legalBasis: event.target.value })} /></FormField>
|
<FormField label={I18N.legalBasis}><input value={draft.legalBasis} onChange={(event) => setDraft({ ...draft, legalBasis: event.target.value })} /></FormField>
|
||||||
<FormField label={I18N.purpose}><textarea rows={3} value={draft.purpose} onChange={(event) => setDraft({ ...draft, purpose: event.target.value })} /></FormField>
|
<FormField label={I18N.purpose}><textarea rows={3} value={draft.purpose} onChange={(event) => setDraft({ ...draft, purpose: event.target.value })} /></FormField>
|
||||||
<FormField label={I18N.notes}><textarea rows={3} value={draft.notes} onChange={(event) => setDraft({ ...draft, notes: event.target.value })} /></FormField>
|
<FormField label={I18N.notes}><textarea rows={3} value={draft.notes} onChange={(event) => setDraft({ ...draft, notes: event.target.value })} /></FormField>
|
||||||
</div>
|
</FormGrid>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
|
||||||
<Dialog
|
<Dialog variant="administration" size="large"
|
||||||
open={executing && Boolean(selected)}
|
open={executing && Boolean(selected)}
|
||||||
title={I18N.executeTitle}
|
title={I18N.executeTitle}
|
||||||
className="admin-dialog"
|
className=""
|
||||||
portal
|
portal
|
||||||
role="alertdialog"
|
role="alertdialog"
|
||||||
closeDisabled={busy}
|
closeDisabled={busy}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useEffect, useMemo, useState } from "react";
|
import { useEffect, useMemo, useState } from "react";
|
||||||
import { Search, Pencil, Plus, Trash2 } from "lucide-react";
|
import { Search, Pencil, Plus, Trash2 } from "lucide-react";
|
||||||
import type { ApiSettings } from "@govoplan/core-webui";
|
import type { FormGrid, ApiSettings } from "@govoplan/core-webui";
|
||||||
import { Button } from "@govoplan/core-webui";
|
import { Button } from "@govoplan/core-webui";
|
||||||
import { ConfirmDialog } from "@govoplan/core-webui";
|
import { ConfirmDialog } from "@govoplan/core-webui";
|
||||||
import { DataGrid, type DataGridColumn } from "@govoplan/core-webui";
|
import { DataGrid, type DataGridColumn } from "@govoplan/core-webui";
|
||||||
@@ -216,19 +216,19 @@ export default function GovernanceTemplatesPanel({
|
|||||||
</div>
|
</div>
|
||||||
</AdminPageLayout>
|
</AdminPageLayout>
|
||||||
|
|
||||||
<Dialog
|
<Dialog variant="administration" size="wide"
|
||||||
open={editing !== null}
|
open={editing !== null}
|
||||||
title={editing === "new" ? kind === "group" ? "i18n:govoplan-admin.create_group_template.72407248" : "i18n:govoplan-admin.create_tenant_role.f58db104" : kind === "group" ? "i18n:govoplan-admin.edit_group_template.9bc72d21" : "i18n:govoplan-admin.edit_tenant_role.c15a260d"}
|
title={editing === "new" ? kind === "group" ? "i18n:govoplan-admin.create_group_template.72407248" : "i18n:govoplan-admin.create_tenant_role.f58db104" : kind === "group" ? "i18n:govoplan-admin.edit_group_template.9bc72d21" : "i18n:govoplan-admin.edit_tenant_role.c15a260d"}
|
||||||
onClose={() => !busy && setEditing(null)}
|
onClose={() => !busy && setEditing(null)}
|
||||||
className="admin-dialog admin-dialog-wide"
|
className=""
|
||||||
footer={<><Button onClick={() => setEditing(null)} disabled={busy} disabledReason={busy ? ADMIN_INTERFACE_I18N.busy : undefined}>i18n:govoplan-admin.cancel.77dfd213</Button><Button variant="primary" onClick={() => void save()} disabledReason={mutationDisabledReason({ busy, permitted: canWrite, complete: Boolean(draft.name.trim() && draft.slug.trim()) })}>{busy ? "i18n:govoplan-admin.saving.56a2285c" : kind === "group" ? "i18n:govoplan-admin.save_template.0885fab2" : "i18n:govoplan-admin.save_tenant_role.8fc0d37d"}</Button></>}>
|
footer={<><Button onClick={() => setEditing(null)} disabled={busy} disabledReason={busy ? ADMIN_INTERFACE_I18N.busy : undefined}>i18n:govoplan-admin.cancel.77dfd213</Button><Button variant="primary" onClick={() => void save()} disabledReason={mutationDisabledReason({ busy, permitted: canWrite, complete: Boolean(draft.name.trim() && draft.slug.trim()) })}>{busy ? "i18n:govoplan-admin.saving.56a2285c" : kind === "group" ? "i18n:govoplan-admin.save_template.0885fab2" : "i18n:govoplan-admin.save_tenant_role.8fc0d37d"}</Button></>}>
|
||||||
|
|
||||||
<div className="admin-form-grid two-columns">
|
<FormGrid columns={2} gap="small" collapseAt="workspace" className="">
|
||||||
<FormField label="i18n:govoplan-admin.name.709a2322"><input value={draft.name} onChange={(event) => setDraft({ ...draft, name: event.target.value })} /></FormField>
|
<FormField label="i18n:govoplan-admin.name.709a2322"><input value={draft.name} onChange={(event) => setDraft({ ...draft, name: event.target.value })} /></FormField>
|
||||||
<FormField label="i18n:govoplan-admin.slug.094da9b9"><input value={draft.slug} disabled={editing !== "new"} onChange={(event) => setDraft({ ...draft, slug: event.target.value })} /></FormField>
|
<FormField label="i18n:govoplan-admin.slug.094da9b9"><input value={draft.slug} disabled={editing !== "new"} onChange={(event) => setDraft({ ...draft, slug: event.target.value })} /></FormField>
|
||||||
<FormField label="i18n:govoplan-admin.status.bae7d5be"><select value={draft.isActive ? "active" : "inactive"} onChange={(event) => setDraft({ ...draft, isActive: event.target.value === "active" })}><option value="active">i18n:govoplan-admin.active.a733b809</option><option value="inactive">i18n:govoplan-admin.inactive.09af574c</option></select></FormField>
|
<FormField label="i18n:govoplan-admin.status.bae7d5be"><select value={draft.isActive ? "active" : "inactive"} onChange={(event) => setDraft({ ...draft, isActive: event.target.value === "active" })}><option value="active">i18n:govoplan-admin.active.a733b809</option><option value="inactive">i18n:govoplan-admin.inactive.09af574c</option></select></FormField>
|
||||||
<FormField label="i18n:govoplan-admin.description.55f8ebc8"><textarea rows={3} value={draft.description} onChange={(event) => setDraft({ ...draft, description: event.target.value })} /></FormField>
|
<FormField label="i18n:govoplan-admin.description.55f8ebc8"><textarea rows={3} value={draft.description} onChange={(event) => setDraft({ ...draft, description: event.target.value })} /></FormField>
|
||||||
</div>
|
</FormGrid>
|
||||||
{kind === "role" && <div className="form-field"><span className="form-label">i18n:govoplan-admin.tenant_permissions.246294bc</span><AdminSelectionList options={permissions.map((permission) => ({ id: permission.scope, label: permission.label, description: permission.description }))} selected={draft.permissions} onChange={(next) => setDraft({ ...draft, permissions: next })} /></div>}
|
{kind === "role" && <div className="form-field"><span className="form-label">i18n:govoplan-admin.tenant_permissions.246294bc</span><AdminSelectionList options={permissions.map((permission) => ({ id: permission.scope, label: permission.label, description: permission.description }))} selected={draft.permissions} onChange={(next) => setDraft({ ...draft, permissions: next })} /></div>}
|
||||||
<div className="form-field">
|
<div className="form-field">
|
||||||
<span className="form-label">i18n:govoplan-admin.tenant_availability.067a4f31</span>
|
<span className="form-label">i18n:govoplan-admin.tenant_availability.067a4f31</span>
|
||||||
@@ -239,7 +239,7 @@ export default function GovernanceTemplatesPanel({
|
|||||||
</div>
|
</div>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
|
||||||
<Dialog open={Boolean(viewing)} title={viewing?.name || "i18n:govoplan-admin.template_details.d5d75e4d"} onClose={() => setViewing(null)} className="admin-dialog admin-dialog-wide" footer={<Button onClick={() => setViewing(null)}>i18n:govoplan-admin.close.bbfa773e</Button>}>
|
<Dialog variant="administration" size="wide" open={Boolean(viewing)} title={viewing?.name || "i18n:govoplan-admin.template_details.d5d75e4d"} onClose={() => setViewing(null)} className="" footer={<Button onClick={() => setViewing(null)}>i18n:govoplan-admin.close.bbfa773e</Button>}>
|
||||||
{viewing && <dl className="admin-details-grid"><div><dt>i18n:govoplan-admin.kind.e00ac23f</dt><dd>{viewing.kind}</dd></div><div><dt>i18n:govoplan-admin.slug.094da9b9</dt><dd>{viewing.slug}</dd></div><div><dt>i18n:govoplan-admin.status.bae7d5be</dt><dd>{viewing.is_active ? "i18n:govoplan-admin.active.a733b809" : "i18n:govoplan-admin.inactive.09af574c"}</dd></div><div><dt>i18n:govoplan-admin.tenants.1f7ae776</dt><dd>{viewing.assignments.length || "i18n:govoplan-admin.none.6eef6648"}</dd></div><div><dt>i18n:govoplan-admin.description.55f8ebc8</dt><dd>{viewing.description || "—"}</dd></div><div><dt>i18n:govoplan-admin.permissions.d06d5557</dt><dd>{viewing.permissions.length ? <PermissionDetails scopes={viewing.permissions} permissionsByScope={permissionsByScope} /> : "—"}</dd></div></dl>}
|
{viewing && <dl className="admin-details-grid"><div><dt>i18n:govoplan-admin.kind.e00ac23f</dt><dd>{viewing.kind}</dd></div><div><dt>i18n:govoplan-admin.slug.094da9b9</dt><dd>{viewing.slug}</dd></div><div><dt>i18n:govoplan-admin.status.bae7d5be</dt><dd>{viewing.is_active ? "i18n:govoplan-admin.active.a733b809" : "i18n:govoplan-admin.inactive.09af574c"}</dd></div><div><dt>i18n:govoplan-admin.tenants.1f7ae776</dt><dd>{viewing.assignments.length || "i18n:govoplan-admin.none.6eef6648"}</dd></div><div><dt>i18n:govoplan-admin.description.55f8ebc8</dt><dd>{viewing.description || "—"}</dd></div><div><dt>i18n:govoplan-admin.permissions.d06d5557</dt><dd>{viewing.permissions.length ? <PermissionDetails scopes={viewing.permissions} permissionsByScope={permissionsByScope} /> : "—"}</dd></div></dl>}
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { useEffect, useMemo, useState } from "react";
|
import { useEffect, useMemo, useState } from "react";
|
||||||
import type { ApiSettings } from "@govoplan/core-webui";
|
import type { ActionToolbar, ApiSettings } from "@govoplan/core-webui";
|
||||||
import { ActionBlockerHint, AdminPageLayout, adminErrorMessage, Button, ConfirmDialog, dispatchPlatformModulesChanged, DocumentationHelpLink, formatDateTime, MetricCard, SegmentedControl, StageRail, StatusBadge, ToggleSwitch, i18nMessage, useUnsavedDraftGuard, type FormatDateTimeOptions } from "@govoplan/core-webui";
|
import { ActionBlockerHint, AdminPageLayout, adminErrorMessage, Button, ConfirmDialog, dispatchPlatformModulesChanged, DocumentationHelpLink, formatDateTime, MetricCard, SegmentedControl, StageRail, StatusBadge, ToggleSwitch, i18nMessage, useUnsavedDraftGuard, type FormatDateTimeOptions } from "@govoplan/core-webui";
|
||||||
import { Check, Clock, FileText, Pencil, Send } from "lucide-react";
|
import { Check, Clock, FileText, Pencil, Send } from "lucide-react";
|
||||||
import {
|
import {
|
||||||
@@ -520,7 +520,7 @@ export default function ModuleManagementPanel({ settings, canWrite, canAccessMai
|
|||||||
{packageCatalog.warnings.map((warning) => <p key={warning} className="alert warning">{warning}</p>)}
|
{packageCatalog.warnings.map((warning) => <p key={warning} className="alert warning">{warning}</p>)}
|
||||||
{!packageCatalog.configured && <div className="module-install-plan-empty">i18n:govoplan-admin.no_package_catalog_configured_set_govoplan_modul.2c5fceb3</div>}
|
{!packageCatalog.configured && <div className="module-install-plan-empty">i18n:govoplan-admin.no_package_catalog_configured_set_govoplan_modul.2c5fceb3</div>}
|
||||||
{packageCatalog.configured && packageCatalog.modules.length === 0 && !packageCatalog.error && <div className="module-install-plan-empty">i18n:govoplan-admin.package_catalog_is_configured_but_contains_no_en.b6b053cb</div>}
|
{packageCatalog.configured && packageCatalog.modules.length === 0 && !packageCatalog.error && <div className="module-install-plan-empty">i18n:govoplan-admin.package_catalog_is_configured_but_contains_no_en.b6b053cb</div>}
|
||||||
{packageCatalog.modules.length > 0 && <div className="module-package-catalog-toolbar">
|
{packageCatalog.modules.length > 0 && <ActionToolbar className="module-package-catalog-toolbar">
|
||||||
<label className="module-package-catalog-search">
|
<label className="module-package-catalog-search">
|
||||||
<span>i18n:govoplan-admin.search_module_directory.7c8f1001</span>
|
<span>i18n:govoplan-admin.search_module_directory.7c8f1001</span>
|
||||||
<input
|
<input
|
||||||
@@ -542,7 +542,7 @@ export default function ModuleManagementPanel({ settings, canWrite, canAccessMai
|
|||||||
{ id: "blocked", label: "i18n:govoplan-admin.blocked.7c8f1007" },
|
{ id: "blocked", label: "i18n:govoplan-admin.blocked.7c8f1007" },
|
||||||
]} />
|
]} />
|
||||||
|
|
||||||
</div>}
|
</ActionToolbar>}
|
||||||
{packageCatalog.modules.length > 0 && visibleCatalogModules.length === 0 && <div className="module-install-plan-empty">i18n:govoplan-admin.no_catalog_entries_match.7c8f1008</div>}
|
{packageCatalog.modules.length > 0 && visibleCatalogModules.length === 0 && <div className="module-install-plan-empty">i18n:govoplan-admin.no_catalog_entries_match.7c8f1008</div>}
|
||||||
{packageCatalog.modules.length > 0 && <div className="module-package-catalog-list">
|
{packageCatalog.modules.length > 0 && <div className="module-package-catalog-list">
|
||||||
{visibleCatalogModules.map((item) =>
|
{visibleCatalogModules.map((item) =>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import type { ApiSettings } from "@govoplan/core-webui";
|
import type { FormGrid, ApiSettings } from "@govoplan/core-webui";
|
||||||
import { Button } from "@govoplan/core-webui";
|
import { Button } from "@govoplan/core-webui";
|
||||||
import { Card } from "@govoplan/core-webui";
|
import { Card } from "@govoplan/core-webui";
|
||||||
import { FormField } from "@govoplan/core-webui";
|
import { FormField } from "@govoplan/core-webui";
|
||||||
@@ -163,7 +163,7 @@ export default function SystemSettingsPanel({ settings, canWrite, canAccessMaint
|
|||||||
selected={draft.enabled_language_codes}
|
selected={draft.enabled_language_codes}
|
||||||
onChange={setEnabledLanguages}
|
onChange={setEnabledLanguages}
|
||||||
/>
|
/>
|
||||||
<div className="form-grid">
|
<FormGrid columns={1} collapseAt="standard" className="">
|
||||||
<FormField label="i18n:govoplan-admin.language_code">
|
<FormField label="i18n:govoplan-admin.language_code">
|
||||||
<input value={packageDraft.code} disabled={!canWrite || busy} placeholder="fr" onChange={(event) => setPackageDraft({ ...packageDraft, code: event.target.value })} />
|
<input value={packageDraft.code} disabled={!canWrite || busy} placeholder="fr" onChange={(event) => setPackageDraft({ ...packageDraft, code: event.target.value })} />
|
||||||
</FormField>
|
</FormField>
|
||||||
@@ -176,7 +176,7 @@ export default function SystemSettingsPanel({ settings, canWrite, canAccessMaint
|
|||||||
<div className="button-row compact-actions">
|
<div className="button-row compact-actions">
|
||||||
<Button onClick={installLanguagePackage} disabledReason={mutationDisabledReason({ busy, permitted: canWrite, complete: Boolean(normalizeLanguageCode(packageDraft.code) && packageDraft.label.trim()) })}>i18n:govoplan-admin.install_language_package</Button>
|
<Button onClick={installLanguagePackage} disabledReason={mutationDisabledReason({ busy, permitted: canWrite, complete: Boolean(normalizeLanguageCode(packageDraft.code) && packageDraft.label.trim()) })}>i18n:govoplan-admin.install_language_package</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</FormGrid>
|
||||||
<p className="muted small-note">i18n:govoplan-admin.language_packages_help</p>
|
<p className="muted small-note">i18n:govoplan-admin.language_packages_help</p>
|
||||||
</Card>
|
</Card>
|
||||||
<Card title="i18n:govoplan-admin.tenant_administration_capabilities.5d265972">
|
<Card title="i18n:govoplan-admin.tenant_administration_capabilities.5d265972">
|
||||||
|
|||||||
Reference in New Issue
Block a user