Migrate Organizations interface patterns
This commit is contained in:
@@ -1,12 +1,15 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import {
|
||||
ActionBlockerHint,
|
||||
AdminPageLayout,
|
||||
Button,
|
||||
Card,
|
||||
DocumentationHelpLink,
|
||||
FormField,
|
||||
ToggleSwitch,
|
||||
adminErrorMessage,
|
||||
hasAnyScope,
|
||||
useUnsavedChanges,
|
||||
useUnsavedDraftGuard,
|
||||
type ApiSettings,
|
||||
type AuthInfo
|
||||
@@ -17,6 +20,12 @@ import {
|
||||
type OrganizationAuditDetailLevel,
|
||||
type OrganizationSettingsItem
|
||||
} from "../../api/organizations";
|
||||
import {
|
||||
ORGANIZATIONS_DOCUMENTATION,
|
||||
ORGANIZATIONS_FIELD_DOCUMENTATION,
|
||||
ORGANIZATIONS_INTERFACE_I18N,
|
||||
organizationWriteReason
|
||||
} from "./interfacePatterns";
|
||||
|
||||
const FALLBACK_SETTINGS: OrganizationSettingsItem = {
|
||||
tenant_id: "",
|
||||
@@ -40,8 +49,16 @@ export default function OrganizationsAdminPanel({ settings, auth }: { settings:
|
||||
const [busy, setBusy] = useState(false);
|
||||
const [error, setError] = useState("");
|
||||
const [success, setSuccess] = useState("");
|
||||
const { requestDiscard } = useUnsavedChanges();
|
||||
const canWrite = hasAnyScope(auth, ["organizations:settings:write", "admin:settings:write"]);
|
||||
const dirty = settingsKey(draft) !== settingsKey(savedDraft);
|
||||
const reloadDisabledReason = loading
|
||||
? ORGANIZATIONS_INTERFACE_I18N.loading
|
||||
: busy
|
||||
? ORGANIZATIONS_INTERFACE_I18N.busy
|
||||
: undefined;
|
||||
const saveDisabledReason = organizationWriteReason(canWrite, busy, "settings")
|
||||
?? (!dirty ? ORGANIZATIONS_INTERFACE_I18N.noChanges : undefined);
|
||||
|
||||
useUnsavedDraftGuard({
|
||||
dirty,
|
||||
@@ -99,20 +116,57 @@ export default function OrganizationsAdminPanel({ settings, auth }: { settings:
|
||||
loadingLabel="i18n:govoplan-organizations.loading_organization_settings.c6008db8"
|
||||
error={error}
|
||||
success={success}
|
||||
actions={<><Button onClick={() => void load()} disabled={loading || busy}>i18n:govoplan-organizations.reload.cce71553</Button><Button variant="primary" onClick={() => void save()} disabled={!canWrite || busy || !dirty}>{busy ? "i18n:govoplan-organizations.saving.56a2285c" : "i18n:govoplan-organizations.save_settings.913aba9f"}</Button></>}
|
||||
actions={(
|
||||
<>
|
||||
<DocumentationHelpLink reference={ORGANIZATIONS_DOCUMENTATION} />
|
||||
<Button
|
||||
onClick={() => requestDiscard(() => void load())}
|
||||
disabled={Boolean(reloadDisabledReason)}
|
||||
disabledReason={reloadDisabledReason}
|
||||
>
|
||||
i18n:govoplan-organizations.reload.cce71553
|
||||
</Button>
|
||||
<Button
|
||||
variant="primary"
|
||||
onClick={() => void save()}
|
||||
disabled={Boolean(saveDisabledReason)}
|
||||
disabledReason={saveDisabledReason}
|
||||
>
|
||||
{busy ? "i18n:govoplan-organizations.saving.56a2285c" : "i18n:govoplan-organizations.save_settings.913aba9f"}
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
>
|
||||
{!canWrite && (
|
||||
<ActionBlockerHint
|
||||
reason={{
|
||||
summary: ORGANIZATIONS_INTERFACE_I18N.readOnlySummary,
|
||||
requiredAction: ORGANIZATIONS_INTERFACE_I18N.permissionGuidance,
|
||||
actor: ORGANIZATIONS_INTERFACE_I18N.administrator,
|
||||
target: ORGANIZATIONS_INTERFACE_I18N.administrationTarget
|
||||
}}
|
||||
labels={{
|
||||
requiredAction: ORGANIZATIONS_INTERFACE_I18N.requiredAction,
|
||||
actor: ORGANIZATIONS_INTERFACE_I18N.actor,
|
||||
target: ORGANIZATIONS_INTERFACE_I18N.destination
|
||||
}}
|
||||
documentation={ORGANIZATIONS_DOCUMENTATION}
|
||||
/>
|
||||
)}
|
||||
<div className="organizations-settings-grid">
|
||||
<Card title="i18n:govoplan-organizations.model_governance.6aa18fd0">
|
||||
<div className="settings-list">
|
||||
<ToggleSwitch
|
||||
checked={draft.allow_tenant_model_customization}
|
||||
disabled={!canWrite || busy}
|
||||
help={organizationWriteReason(canWrite, busy, "settings")}
|
||||
onChange={(checked) => setDraft({ ...draft, allow_tenant_model_customization: checked })}
|
||||
label="i18n:govoplan-organizations.allow_tenant_model_customization.2425d751"
|
||||
/>
|
||||
<ToggleSwitch
|
||||
checked={draft.require_model_change_requests}
|
||||
disabled={!canWrite || busy}
|
||||
help={organizationWriteReason(canWrite, busy, "settings")}
|
||||
onChange={(checked) => setDraft({ ...draft, require_model_change_requests: checked })}
|
||||
label="i18n:govoplan-organizations.require_model_change_requests.83454cad"
|
||||
/>
|
||||
@@ -122,12 +176,20 @@ export default function OrganizationsAdminPanel({ settings, auth }: { settings:
|
||||
|
||||
<Card title="i18n:govoplan-organizations.audit_and_retention.3ba1d2fc">
|
||||
<div className="admin-form-grid two-columns">
|
||||
<FormField label="i18n:govoplan-organizations.audit_detail_level.7397355d">
|
||||
<FormField
|
||||
label="i18n:govoplan-organizations.audit_detail_level.7397355d"
|
||||
help={organizationWriteReason(canWrite, busy, "settings")}
|
||||
documentation={ORGANIZATIONS_FIELD_DOCUMENTATION}
|
||||
>
|
||||
<select value={draft.audit_detail_level} disabled={!canWrite || busy} onChange={(event) => setDraft({ ...draft, audit_detail_level: event.target.value as OrganizationAuditDetailLevel })}>
|
||||
{AUDIT_DETAIL_LEVELS.map((item) => <option key={item.value} value={item.value}>{item.label}</option>)}
|
||||
</select>
|
||||
</FormField>
|
||||
<FormField label="i18n:govoplan-organizations.change_retention_days.71bbd140">
|
||||
<FormField
|
||||
label="i18n:govoplan-organizations.change_retention_days.71bbd140"
|
||||
help={organizationWriteReason(canWrite, busy, "settings")}
|
||||
documentation={ORGANIZATIONS_FIELD_DOCUMENTATION}
|
||||
>
|
||||
<input
|
||||
type="number"
|
||||
min={0}
|
||||
|
||||
Reference in New Issue
Block a user