feat: govern tenant appearance overrides
This commit is contained in:
@@ -18,7 +18,14 @@ from govoplan_core.core.access import (
|
|||||||
TenantContextSwitcher,
|
TenantContextSwitcher,
|
||||||
)
|
)
|
||||||
from govoplan_core.core.change_sequence import ChangeSequenceEntry, decode_sequence_watermark, encode_sequence_watermark, record_change, sequence_watermark_is_expired
|
from govoplan_core.core.change_sequence import ChangeSequenceEntry, decode_sequence_watermark, encode_sequence_watermark, record_change, sequence_watermark_is_expired
|
||||||
from govoplan_core.core.appearance import APPEARANCE_SETTINGS_KEY, appearance_settings, resolve_effective_appearance, update_appearance_settings
|
from govoplan_core.core.appearance import (
|
||||||
|
APPEARANCE_SETTINGS_KEY,
|
||||||
|
appearance_custom_overrides_policy,
|
||||||
|
appearance_settings,
|
||||||
|
resolve_effective_appearance,
|
||||||
|
update_appearance_custom_overrides_policy,
|
||||||
|
update_appearance_settings,
|
||||||
|
)
|
||||||
from govoplan_core.core.module_entitlements import MODULE_ENTITLEMENTS_KEY
|
from govoplan_core.core.module_entitlements import MODULE_ENTITLEMENTS_KEY
|
||||||
from govoplan_core.core.navigation import (
|
from govoplan_core.core.navigation import (
|
||||||
navigation_preferences_from_settings,
|
navigation_preferences_from_settings,
|
||||||
@@ -259,6 +266,8 @@ def _tenant_settings_item(session: Session, tenant: Tenant) -> TenantSettingsIte
|
|||||||
navigation = navigation_preferences_from_settings(tenant.settings)
|
navigation = navigation_preferences_from_settings(tenant.settings)
|
||||||
system_palette, system_locked = appearance_settings(system_settings.settings)
|
system_palette, system_locked = appearance_settings(system_settings.settings)
|
||||||
tenant_palette, tenant_locked = appearance_settings(tenant.settings)
|
tenant_palette, tenant_locked = appearance_settings(tenant.settings)
|
||||||
|
system_custom_overrides_allowed = appearance_custom_overrides_policy(system_settings.settings) is True
|
||||||
|
tenant_custom_overrides_allowed = appearance_custom_overrides_policy(tenant.settings)
|
||||||
effective_appearance = resolve_effective_appearance(
|
effective_appearance = resolve_effective_appearance(
|
||||||
system_settings=system_settings.settings,
|
system_settings=system_settings.settings,
|
||||||
tenant_settings=tenant.settings,
|
tenant_settings=tenant.settings,
|
||||||
@@ -279,6 +288,9 @@ def _tenant_settings_item(session: Session, tenant: Tenant) -> TenantSettingsIte
|
|||||||
system_appearance_palette_locked=system_locked,
|
system_appearance_palette_locked=system_locked,
|
||||||
effective_appearance_palette=effective_appearance.palette,
|
effective_appearance_palette=effective_appearance.palette,
|
||||||
effective_appearance_source=effective_appearance.source,
|
effective_appearance_source=effective_appearance.source,
|
||||||
|
appearance_custom_overrides_allowed=tenant_custom_overrides_allowed,
|
||||||
|
system_appearance_custom_overrides_allowed=system_custom_overrides_allowed,
|
||||||
|
effective_appearance_custom_overrides_allowed=effective_appearance.custom_overrides_allowed,
|
||||||
settings=tenant.settings or {},
|
settings=tenant.settings or {},
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -301,6 +313,9 @@ def _tenant_settings_sections(item: TenantSettingsItem) -> dict[str, Any]:
|
|||||||
"system_appearance_palette_locked": payload["system_appearance_palette_locked"],
|
"system_appearance_palette_locked": payload["system_appearance_palette_locked"],
|
||||||
"effective_appearance_palette": payload["effective_appearance_palette"],
|
"effective_appearance_palette": payload["effective_appearance_palette"],
|
||||||
"effective_appearance_source": payload["effective_appearance_source"],
|
"effective_appearance_source": payload["effective_appearance_source"],
|
||||||
|
"appearance_custom_overrides_allowed": payload["appearance_custom_overrides_allowed"],
|
||||||
|
"system_appearance_custom_overrides_allowed": payload["system_appearance_custom_overrides_allowed"],
|
||||||
|
"effective_appearance_custom_overrides_allowed": payload["effective_appearance_custom_overrides_allowed"],
|
||||||
},
|
},
|
||||||
"settings": payload["settings"],
|
"settings": payload["settings"],
|
||||||
}
|
}
|
||||||
@@ -997,6 +1012,8 @@ def update_tenant_settings(
|
|||||||
system_settings = get_system_settings(session)
|
system_settings = get_system_settings(session)
|
||||||
tenant_palette, tenant_locked = appearance_settings(tenant.settings)
|
tenant_palette, tenant_locked = appearance_settings(tenant.settings)
|
||||||
system_palette, system_locked = appearance_settings(system_settings.settings)
|
system_palette, system_locked = appearance_settings(system_settings.settings)
|
||||||
|
system_custom_overrides_allowed = appearance_custom_overrides_policy(system_settings.settings) is True
|
||||||
|
tenant_custom_overrides_allowed = appearance_custom_overrides_policy(tenant.settings)
|
||||||
appearance_palette_changed = (
|
appearance_palette_changed = (
|
||||||
"appearance_palette" in payload.model_fields_set
|
"appearance_palette" in payload.model_fields_set
|
||||||
and payload.appearance_palette != tenant_palette
|
and payload.appearance_palette != tenant_palette
|
||||||
@@ -1005,17 +1022,26 @@ def update_tenant_settings(
|
|||||||
"appearance_palette_locked" in payload.model_fields_set
|
"appearance_palette_locked" in payload.model_fields_set
|
||||||
and payload.appearance_palette_locked != tenant_locked
|
and payload.appearance_palette_locked != tenant_locked
|
||||||
)
|
)
|
||||||
|
custom_overrides_policy_changed = (
|
||||||
|
"appearance_custom_overrides_allowed" in payload.model_fields_set
|
||||||
|
and payload.appearance_custom_overrides_allowed != tenant_custom_overrides_allowed
|
||||||
|
)
|
||||||
|
if payload.appearance_custom_overrides_allowed is True and not system_custom_overrides_allowed:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
||||||
|
detail="The system appearance policy does not allow personal custom overrides.",
|
||||||
|
)
|
||||||
if system_locked and (appearance_palette_changed or appearance_lock_changed):
|
if system_locked and (appearance_palette_changed or appearance_lock_changed):
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
||||||
detail=f"The system appearance policy locks palette {system_palette or 'default'}.",
|
detail=f"The system appearance policy locks palette {system_palette or 'default'}.",
|
||||||
)
|
)
|
||||||
if (
|
if (
|
||||||
appearance_lock_changed or (tenant_locked and appearance_palette_changed)
|
appearance_lock_changed or (tenant_locked and appearance_palette_changed) or custom_overrides_policy_changed
|
||||||
) and not has_scope(principal, "admin:policies:write"):
|
) and not has_scope(principal, "admin:policies:write"):
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
||||||
detail="Changing the tenant appearance lock or its locked value requires admin:policies:write.",
|
detail="Changing the tenant appearance policy requires admin:policies:write.",
|
||||||
)
|
)
|
||||||
system_enabled = system_enabled_language_codes(system_settings.settings, default_locale=system_settings.default_locale)
|
system_enabled = system_enabled_language_codes(system_settings.settings, default_locale=system_settings.default_locale)
|
||||||
current_i18n = i18n_settings(tenant.settings)
|
current_i18n = i18n_settings(tenant.settings)
|
||||||
@@ -1035,6 +1061,11 @@ def update_tenant_settings(
|
|||||||
default_palette=payload.appearance_palette if "appearance_palette" in payload.model_fields_set else current_palette,
|
default_palette=payload.appearance_palette if "appearance_palette" in payload.model_fields_set else current_palette,
|
||||||
palette_locked=payload.appearance_palette_locked if payload.appearance_palette_locked is not None else current_locked,
|
palette_locked=payload.appearance_palette_locked if payload.appearance_palette_locked is not None else current_locked,
|
||||||
)
|
)
|
||||||
|
if "appearance_custom_overrides_allowed" in payload.model_fields_set:
|
||||||
|
tenant.settings = update_appearance_custom_overrides_policy(
|
||||||
|
tenant.settings,
|
||||||
|
allowed=payload.appearance_custom_overrides_allowed,
|
||||||
|
)
|
||||||
if "navigation" in payload.model_fields_set:
|
if "navigation" in payload.model_fields_set:
|
||||||
tenant.settings = update_navigation_preferences(
|
tenant.settings = update_navigation_preferences(
|
||||||
tenant.settings,
|
tenant.settings,
|
||||||
@@ -1052,9 +1083,14 @@ def update_tenant_settings(
|
|||||||
"default_locale": tenant.default_locale,
|
"default_locale": tenant.default_locale,
|
||||||
"enabled_language_codes": enabled,
|
"enabled_language_codes": enabled,
|
||||||
"navigation_updated": "navigation" in payload.model_fields_set,
|
"navigation_updated": "navigation" in payload.model_fields_set,
|
||||||
"appearance_updated": bool({"appearance_palette", "appearance_palette_locked"}.intersection(payload.model_fields_set)),
|
"appearance_updated": bool(
|
||||||
|
{"appearance_palette", "appearance_palette_locked", "appearance_custom_overrides_allowed"}.intersection(
|
||||||
|
payload.model_fields_set
|
||||||
|
)
|
||||||
|
),
|
||||||
"appearance_palette": appearance_settings(tenant.settings)[0],
|
"appearance_palette": appearance_settings(tenant.settings)[0],
|
||||||
"appearance_palette_locked": appearance_settings(tenant.settings)[1],
|
"appearance_palette_locked": appearance_settings(tenant.settings)[1],
|
||||||
|
"appearance_custom_overrides_allowed": appearance_custom_overrides_policy(tenant.settings),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
after_sections = _tenant_settings_sections(_tenant_settings_item(session, tenant))
|
after_sections = _tenant_settings_sections(_tenant_settings_item(session, tenant))
|
||||||
|
|||||||
@@ -144,6 +144,9 @@ class TenantSettingsItem(BaseModel):
|
|||||||
system_appearance_palette_locked: bool = False
|
system_appearance_palette_locked: bool = False
|
||||||
effective_appearance_palette: Literal["default", "civic_blue", "forest", "plum"] = "default"
|
effective_appearance_palette: Literal["default", "civic_blue", "forest", "plum"] = "default"
|
||||||
effective_appearance_source: Literal["tenant", "system", "tenant_lock", "system_lock"] = "system"
|
effective_appearance_source: Literal["tenant", "system", "tenant_lock", "system_lock"] = "system"
|
||||||
|
appearance_custom_overrides_allowed: bool | None = None
|
||||||
|
system_appearance_custom_overrides_allowed: bool = False
|
||||||
|
effective_appearance_custom_overrides_allowed: bool = False
|
||||||
settings: dict[str, Any] = Field(default_factory=dict)
|
settings: dict[str, Any] = Field(default_factory=dict)
|
||||||
|
|
||||||
|
|
||||||
@@ -165,3 +168,4 @@ class TenantSettingsUpdateRequest(BaseModel):
|
|||||||
navigation: NavigationPreferencesPayload | None = None
|
navigation: NavigationPreferencesPayload | None = None
|
||||||
appearance_palette: Literal["default", "civic_blue", "forest", "plum"] | None = None
|
appearance_palette: Literal["default", "civic_blue", "forest", "plum"] | None = None
|
||||||
appearance_palette_locked: bool | None = None
|
appearance_palette_locked: bool | None = None
|
||||||
|
appearance_custom_overrides_allowed: bool | None = None
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ manifest = ModuleManifest(
|
|||||||
id="tenancy.lifecycle-and-settings",
|
id="tenancy.lifecycle-and-settings",
|
||||||
title="Administer tenant lifecycle and settings",
|
title="Administer tenant lifecycle and settings",
|
||||||
summary="Tenancy adds explicit tenant creation, activation, context resolution, and tenant-owned settings over Core's shared scope storage.",
|
summary="Tenancy adds explicit tenant creation, activation, context resolution, and tenant-owned settings over Core's shared scope storage.",
|
||||||
body="A tenant is a concrete administrative and data boundary. Tenant lifecycle changes must preserve ownership and recovery guarantees for module-owned records. New tenants default to the German reference language unless the administrator selects another enabled system language; existing tenant and user preferences remain unchanged. Tenant administrators can inherit or override the system side-rail order and visibility and can lock entries visible for users; system locks remain effective. Personal navigation preferences still take precedence except that they cannot hide locked entries. Tenant appearance likewise inherits the system palette until explicitly selected; an unlocked tenant default permits a personal palette, while a policy-authorized tenant lock suppresses it and a system lock always wins. Resetting the tenant palette restores inheritance rather than copying the current system value. Navigation and appearance changes never grant module entitlement, View visibility, or permissions. Tenancy contributes system tenant management and tenant settings to the shared administration workspace; without this module, the Core and Access baseline can operate in single-scope compatibility mode. Core-reserved module entitlement settings are managed only through the Admin module's tenant-module policy endpoints and are preserved when generic tenant settings are replaced.",
|
body="A tenant is a concrete administrative and data boundary. Tenant lifecycle changes must preserve ownership and recovery guarantees for module-owned records. New tenants default to the German reference language unless the administrator selects another enabled system language; existing tenant and user preferences remain unchanged. Tenant administrators can inherit or override the system side-rail order and visibility and can lock entries visible for users; system locks remain effective. Personal navigation preferences still take precedence except that they cannot hide locked entries. Tenant appearance likewise inherits the system palette until explicitly selected; an unlocked tenant default permits a personal palette, while a policy-authorized tenant lock suppresses it and a system lock always wins. Resetting the tenant palette restores inheritance rather than copying the current system value. When the system permits advanced personal color overrides, a policy-authorized tenant administrator may inherit, allow, or block them; the tenant cannot enable a system-denied policy, and palette locks still suppress the editor. Advanced documents cover both light and dark modes and are validated atomically by Core. Navigation and appearance changes never grant module entitlement, View visibility, or permissions. Tenancy contributes system tenant management and tenant settings to the shared administration workspace; without this module, the Core and Access baseline can operate in single-scope compatibility mode. Core-reserved module entitlement settings are managed only through the Admin module's tenant-module policy endpoints and are preserved when generic tenant settings are replaced.",
|
||||||
documentation_types=("admin",),
|
documentation_types=("admin",),
|
||||||
audience=("system_admin", "tenant_admin", "operator"),
|
audience=("system_admin", "tenant_admin", "operator"),
|
||||||
related_modules=("access", "admin", "audit"),
|
related_modules=("access", "admin", "audit"),
|
||||||
|
|||||||
@@ -50,6 +50,9 @@ export type TenantSettingsItem = {
|
|||||||
system_appearance_palette_locked: boolean;
|
system_appearance_palette_locked: boolean;
|
||||||
effective_appearance_palette: UserUiPalette;
|
effective_appearance_palette: UserUiPalette;
|
||||||
effective_appearance_source: "tenant" | "system" | "tenant_lock" | "system_lock";
|
effective_appearance_source: "tenant" | "system" | "tenant_lock" | "system_lock";
|
||||||
|
appearance_custom_overrides_allowed: boolean | null;
|
||||||
|
system_appearance_custom_overrides_allowed: boolean;
|
||||||
|
effective_appearance_custom_overrides_allowed: boolean;
|
||||||
settings: Record<string, unknown>;
|
settings: Record<string, unknown>;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -61,7 +64,7 @@ export type TenantSettingsDeltaSections = Partial<{
|
|||||||
"available_languages" | "system_enabled_language_codes" | "enabled_language_codes"
|
"available_languages" | "system_enabled_language_codes" | "enabled_language_codes"
|
||||||
>;
|
>;
|
||||||
navigation: TenantSettingsItem["navigation"];
|
navigation: TenantSettingsItem["navigation"];
|
||||||
appearance: Pick<TenantSettingsItem, "appearance_palette" | "appearance_palette_locked" | "system_appearance_palette" | "system_appearance_palette_locked" | "effective_appearance_palette" | "effective_appearance_source">;
|
appearance: Pick<TenantSettingsItem, "appearance_palette" | "appearance_palette_locked" | "system_appearance_palette" | "system_appearance_palette_locked" | "effective_appearance_palette" | "effective_appearance_source" | "appearance_custom_overrides_allowed" | "system_appearance_custom_overrides_allowed" | "effective_appearance_custom_overrides_allowed">;
|
||||||
settings: TenantSettingsItem["settings"];
|
settings: TenantSettingsItem["settings"];
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
@@ -161,6 +164,7 @@ export function updateTenantSettings(
|
|||||||
navigation?: NavigationPreferences | null;
|
navigation?: NavigationPreferences | null;
|
||||||
appearance_palette?: UserUiPalette | null;
|
appearance_palette?: UserUiPalette | null;
|
||||||
appearance_palette_locked?: boolean;
|
appearance_palette_locked?: boolean;
|
||||||
|
appearance_custom_overrides_allowed?: boolean | null;
|
||||||
}
|
}
|
||||||
): Promise<TenantSettingsItem> {
|
): Promise<TenantSettingsItem> {
|
||||||
return apiFetch(settings, "/api/v1/admin/tenant/settings", {
|
return apiFetch(settings, "/api/v1/admin/tenant/settings", {
|
||||||
|
|||||||
@@ -51,7 +51,10 @@ const fallback: TenantSettingsItem = {
|
|||||||
system_appearance_palette: "default",
|
system_appearance_palette: "default",
|
||||||
system_appearance_palette_locked: false,
|
system_appearance_palette_locked: false,
|
||||||
effective_appearance_palette: "default",
|
effective_appearance_palette: "default",
|
||||||
effective_appearance_source: "system"
|
effective_appearance_source: "system",
|
||||||
|
appearance_custom_overrides_allowed: null,
|
||||||
|
system_appearance_custom_overrides_allowed: false,
|
||||||
|
effective_appearance_custom_overrides_allowed: false
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function TenantSettingsPanel({
|
export default function TenantSettingsPanel({
|
||||||
@@ -76,6 +79,11 @@ export default function TenantSettingsPanel({
|
|||||||
const { getDeltaWatermark, setDeltaWatermark, resetDeltaWatermark } = useDeltaWatermarks();
|
const { getDeltaWatermark, setDeltaWatermark, resetDeltaWatermark } = useDeltaWatermarks();
|
||||||
const defaultLocaleOptions = localeOptions(draft.default_locale, draft.enabled_language_codes);
|
const defaultLocaleOptions = localeOptions(draft.default_locale, draft.enabled_language_codes);
|
||||||
const dirty = tenantSettingsDraftKey(draft) !== tenantSettingsDraftKey(savedDraft);
|
const dirty = tenantSettingsDraftKey(draft) !== tenantSettingsDraftKey(savedDraft);
|
||||||
|
const customOverridesEffectivelyAllowed =
|
||||||
|
draft.system_appearance_custom_overrides_allowed
|
||||||
|
&& draft.appearance_custom_overrides_allowed !== false
|
||||||
|
&& !draft.system_appearance_palette_locked
|
||||||
|
&& !draft.appearance_palette_locked;
|
||||||
const saveDisabledReason = tenantMutationDisabledReason({
|
const saveDisabledReason = tenantMutationDisabledReason({
|
||||||
busy,
|
busy,
|
||||||
permitted: canWrite,
|
permitted: canWrite,
|
||||||
@@ -127,7 +135,8 @@ export default function TenantSettingsPanel({
|
|||||||
enabled_language_codes: draft.enabled_language_codes,
|
enabled_language_codes: draft.enabled_language_codes,
|
||||||
navigation: draft.navigation,
|
navigation: draft.navigation,
|
||||||
appearance_palette: draft.appearance_palette,
|
appearance_palette: draft.appearance_palette,
|
||||||
appearance_palette_locked: draft.appearance_palette_locked
|
appearance_palette_locked: draft.appearance_palette_locked,
|
||||||
|
appearance_custom_overrides_allowed: draft.appearance_custom_overrides_allowed
|
||||||
});
|
});
|
||||||
setDraft(saved);
|
setDraft(saved);
|
||||||
setSavedDraft(saved);
|
setSavedDraft(saved);
|
||||||
@@ -230,10 +239,36 @@ export default function TenantSettingsPanel({
|
|||||||
help={!canWritePolicy ? "i18n:govoplan-tenancy.appearance_lock_policy_permission" : draft.system_appearance_palette_locked ? "i18n:govoplan-tenancy.system_palette_is_locked" : undefined}
|
help={!canWritePolicy ? "i18n:govoplan-tenancy.appearance_lock_policy_permission" : draft.system_appearance_palette_locked ? "i18n:govoplan-tenancy.system_palette_is_locked" : undefined}
|
||||||
label="i18n:govoplan-tenancy.lock_tenant_palette"
|
label="i18n:govoplan-tenancy.lock_tenant_palette"
|
||||||
/>
|
/>
|
||||||
|
<FormField
|
||||||
|
label="i18n:govoplan-tenancy.custom_overrides_policy"
|
||||||
|
help={!canWritePolicy ? "i18n:govoplan-tenancy.appearance_policy_permission" : "i18n:govoplan-tenancy.custom_overrides_policy_help"}
|
||||||
|
>
|
||||||
|
<select
|
||||||
|
value={draft.appearance_custom_overrides_allowed === null ? "inherit" : draft.appearance_custom_overrides_allowed ? "allow" : "block"}
|
||||||
|
disabled={!canWrite || !canWritePolicy || busy}
|
||||||
|
onChange={(event) => {
|
||||||
|
const appearance_custom_overrides_allowed = event.target.value === "inherit" ? null : event.target.value === "allow";
|
||||||
|
setDraft({
|
||||||
|
...draft,
|
||||||
|
appearance_custom_overrides_allowed,
|
||||||
|
effective_appearance_custom_overrides_allowed:
|
||||||
|
draft.system_appearance_custom_overrides_allowed
|
||||||
|
&& appearance_custom_overrides_allowed !== false
|
||||||
|
&& !draft.system_appearance_palette_locked
|
||||||
|
&& !draft.appearance_palette_locked
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<option value="inherit">i18n:govoplan-tenancy.inherit_system_policy</option>
|
||||||
|
<option value="allow" disabled={!draft.system_appearance_custom_overrides_allowed}>i18n:govoplan-tenancy.allow_for_tenant_users</option>
|
||||||
|
<option value="block">i18n:govoplan-tenancy.block_for_tenant_users</option>
|
||||||
|
</select>
|
||||||
|
</FormField>
|
||||||
<AppearancePalettePreview palette={draft.system_appearance_palette_locked ? draft.system_appearance_palette : draft.appearance_palette ?? draft.system_appearance_palette} />
|
<AppearancePalettePreview palette={draft.system_appearance_palette_locked ? draft.system_appearance_palette : draft.appearance_palette ?? draft.system_appearance_palette} />
|
||||||
<DescriptionList variant="inline">
|
<DescriptionList variant="inline">
|
||||||
<div><dt>i18n:govoplan-tenancy.effective_source</dt><dd>{draft.system_appearance_palette_locked ? "i18n:govoplan-tenancy.system_lock" : draft.appearance_palette ? "i18n:govoplan-tenancy.tenant_default" : "i18n:govoplan-tenancy.system_default"}</dd></div>
|
<div><dt>i18n:govoplan-tenancy.effective_source</dt><dd>{draft.system_appearance_palette_locked ? "i18n:govoplan-tenancy.system_lock" : draft.appearance_palette ? "i18n:govoplan-tenancy.tenant_default" : "i18n:govoplan-tenancy.system_default"}</dd></div>
|
||||||
<div><dt>i18n:govoplan-tenancy.user_override</dt><dd>{draft.system_appearance_palette_locked || draft.appearance_palette_locked ? "i18n:govoplan-tenancy.blocked_by_policy" : "i18n:govoplan-tenancy.allowed"}</dd></div>
|
<div><dt>i18n:govoplan-tenancy.user_override</dt><dd>{draft.system_appearance_palette_locked || draft.appearance_palette_locked ? "i18n:govoplan-tenancy.blocked_by_policy" : "i18n:govoplan-tenancy.allowed"}</dd></div>
|
||||||
|
<div><dt>i18n:govoplan-tenancy.advanced_color_overrides</dt><dd>{customOverridesEffectivelyAllowed ? "i18n:govoplan-tenancy.allowed" : "i18n:govoplan-tenancy.blocked_by_policy"}</dd></div>
|
||||||
</DescriptionList>
|
</DescriptionList>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
@@ -255,7 +290,8 @@ function tenantSettingsDraftKey(item: TenantSettingsItem): string {
|
|||||||
enabled_language_codes: item.enabled_language_codes,
|
enabled_language_codes: item.enabled_language_codes,
|
||||||
navigation: item.navigation,
|
navigation: item.navigation,
|
||||||
appearance_palette: item.appearance_palette,
|
appearance_palette: item.appearance_palette,
|
||||||
appearance_palette_locked: item.appearance_palette_locked
|
appearance_palette_locked: item.appearance_palette_locked,
|
||||||
|
appearance_custom_overrides_allowed: item.appearance_custom_overrides_allowed
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,13 @@ export const generatedTranslations: PlatformTranslations = {
|
|||||||
"i18n:govoplan-tenancy.tenant_palette_default": "Tenant palette default",
|
"i18n:govoplan-tenancy.tenant_palette_default": "Tenant palette default",
|
||||||
"i18n:govoplan-tenancy.tenant_palette_default_help": "Inherit the system palette or select the default for this tenant.",
|
"i18n:govoplan-tenancy.tenant_palette_default_help": "Inherit the system palette or select the default for this tenant.",
|
||||||
"i18n:govoplan-tenancy.appearance_lock_policy_permission": "Policy-write permission is required to change this lock.",
|
"i18n:govoplan-tenancy.appearance_lock_policy_permission": "Policy-write permission is required to change this lock.",
|
||||||
|
"i18n:govoplan-tenancy.custom_overrides_policy": "Personal color override policy",
|
||||||
|
"i18n:govoplan-tenancy.custom_overrides_policy_help": "Inherit the system decision, or explicitly allow or block the validated advanced editor for this tenant.",
|
||||||
|
"i18n:govoplan-tenancy.appearance_policy_permission": "Policy-write permission is required to change this appearance policy.",
|
||||||
|
"i18n:govoplan-tenancy.inherit_system_policy": "Inherit system policy",
|
||||||
|
"i18n:govoplan-tenancy.allow_for_tenant_users": "Allow for tenant users",
|
||||||
|
"i18n:govoplan-tenancy.block_for_tenant_users": "Block for tenant users",
|
||||||
|
"i18n:govoplan-tenancy.advanced_color_overrides": "Advanced color overrides",
|
||||||
"i18n:govoplan-tenancy.system_palette_is_locked": "The system palette is locked and takes precedence.",
|
"i18n:govoplan-tenancy.system_palette_is_locked": "The system palette is locked and takes precedence.",
|
||||||
"i18n:govoplan-tenancy.lock_tenant_palette": "Lock the tenant palette",
|
"i18n:govoplan-tenancy.lock_tenant_palette": "Lock the tenant palette",
|
||||||
"i18n:govoplan-tenancy.effective_source": "Effective source",
|
"i18n:govoplan-tenancy.effective_source": "Effective source",
|
||||||
@@ -118,6 +125,13 @@ export const generatedTranslations: PlatformTranslations = {
|
|||||||
"i18n:govoplan-tenancy.tenant_palette_default": "Mandantenstandard für die Farbpalette",
|
"i18n:govoplan-tenancy.tenant_palette_default": "Mandantenstandard für die Farbpalette",
|
||||||
"i18n:govoplan-tenancy.tenant_palette_default_help": "Systempalette übernehmen oder einen Standard für diesen Mandanten auswählen.",
|
"i18n:govoplan-tenancy.tenant_palette_default_help": "Systempalette übernehmen oder einen Standard für diesen Mandanten auswählen.",
|
||||||
"i18n:govoplan-tenancy.appearance_lock_policy_permission": "Zum Ändern dieser Sperre ist das Recht zum Bearbeiten von Richtlinien erforderlich.",
|
"i18n:govoplan-tenancy.appearance_lock_policy_permission": "Zum Ändern dieser Sperre ist das Recht zum Bearbeiten von Richtlinien erforderlich.",
|
||||||
|
"i18n:govoplan-tenancy.custom_overrides_policy": "Richtlinie für persönliche Farbanpassungen",
|
||||||
|
"i18n:govoplan-tenancy.custom_overrides_policy_help": "Die Systementscheidung übernehmen oder den geprüften erweiterten Editor für diesen Mandanten ausdrücklich zulassen oder sperren.",
|
||||||
|
"i18n:govoplan-tenancy.appearance_policy_permission": "Zum Ändern dieser Darstellungsrichtlinie ist das Recht zum Bearbeiten von Richtlinien erforderlich.",
|
||||||
|
"i18n:govoplan-tenancy.inherit_system_policy": "Systemrichtlinie übernehmen",
|
||||||
|
"i18n:govoplan-tenancy.allow_for_tenant_users": "Für Mandantenbenutzer zulassen",
|
||||||
|
"i18n:govoplan-tenancy.block_for_tenant_users": "Für Mandantenbenutzer sperren",
|
||||||
|
"i18n:govoplan-tenancy.advanced_color_overrides": "Erweiterte Farbanpassungen",
|
||||||
"i18n:govoplan-tenancy.system_palette_is_locked": "Die Systempalette ist verbindlich und hat Vorrang.",
|
"i18n:govoplan-tenancy.system_palette_is_locked": "Die Systempalette ist verbindlich und hat Vorrang.",
|
||||||
"i18n:govoplan-tenancy.lock_tenant_palette": "Mandantenpalette verbindlich festlegen",
|
"i18n:govoplan-tenancy.lock_tenant_palette": "Mandantenpalette verbindlich festlegen",
|
||||||
"i18n:govoplan-tenancy.effective_source": "Wirksame Quelle",
|
"i18n:govoplan-tenancy.effective_source": "Wirksame Quelle",
|
||||||
|
|||||||
Reference in New Issue
Block a user