feat(admin): configure system navigation defaults

This commit is contained in:
2026-08-20 01:47:03 +02:00
parent 8a75c82a5d
commit a1d7b649aa
5 changed files with 60 additions and 6 deletions
@@ -75,6 +75,11 @@ from govoplan_core.core.module_installer_notifications import (
installer_notification_subject,
)
from govoplan_core.core.module_license import module_license_decision, module_license_diagnostics
from govoplan_core.core.navigation import (
NavigationPreferences,
navigation_preferences_from_settings,
update_navigation_preferences,
)
from govoplan_core.core.module_package_catalog import (
record_module_package_catalog_acceptance,
validate_module_package_catalog,
@@ -153,6 +158,7 @@ SYSTEM_SETTINGS_SECTIONS = (
"languages",
"privacy_retention_policy",
"maintenance_mode",
"navigation",
"settings",
)
@@ -288,6 +294,7 @@ def _system_settings_item(session: Session) -> SystemSettingsItem:
policy = privacy_policy_from_settings(item)
maintenance_mode = saved_maintenance_mode(session)
i18n_payload = system_i18n_payload(item)
navigation = navigation_preferences_from_settings(item.settings)
return SystemSettingsItem(
default_locale=item.default_locale,
allow_tenant_custom_groups=item.allow_tenant_custom_groups,
@@ -298,6 +305,7 @@ def _system_settings_item(session: Session) -> SystemSettingsItem:
available_languages=i18n_payload["available_languages"],
enabled_language_codes=i18n_payload["enabled_languages"],
settings=item.settings or {},
navigation=navigation.as_dict() if navigation is not None else None,
)
@@ -316,6 +324,7 @@ def _system_settings_sections(item: SystemSettingsItem) -> dict[str, Any]:
},
"privacy_retention_policy": payload["privacy_retention_policy"],
"maintenance_mode": payload["maintenance_mode"],
"navigation": payload["navigation"],
"settings": payload["settings"],
}
@@ -1810,6 +1819,15 @@ def write_system_settings(
available_languages=available_languages,
enabled_language_codes=enabled_language_codes,
)
if "navigation" in payload.model_fields_set:
item.settings = update_navigation_preferences(
item.settings,
NavigationPreferences(
order=tuple(payload.navigation.order),
hidden=tuple(payload.navigation.hidden),
locked=tuple(payload.navigation.locked),
) if payload.navigation is not None else None,
)
if payload.privacy_retention_policy is not None:
set_privacy_policy(item, payload.privacy_retention_policy.model_dump(mode="json"))
if payload.maintenance_mode is not None:
+3 -1
View File
@@ -5,7 +5,7 @@ from typing import Any, Literal
from pydantic import BaseModel, ConfigDict, Field
from govoplan_core.api.v1.schemas import DeltaDeletedItem
from govoplan_core.api.v1.schemas import DeltaDeletedItem, NavigationPreferencesPayload
from govoplan_core.i18n import REFERENCE_LANGUAGE_CODE
from govoplan_core.privacy.schemas import PrivacyRetentionPolicyItem
@@ -50,6 +50,7 @@ class SystemSettingsItem(BaseModel):
available_languages: list[LanguagePackageItem] = Field(default_factory=list)
enabled_language_codes: list[str] = Field(default_factory=list)
settings: dict[str, Any] = Field(default_factory=dict)
navigation: NavigationPreferencesPayload | None = None
class SystemSettingsDeltaResponse(BaseModel):
@@ -73,6 +74,7 @@ class SystemSettingsUpdateRequest(BaseModel):
maintenance_mode: MaintenanceModeItem | None = None
available_languages: list[LanguagePackageItem] | None = None
enabled_language_codes: list[str] | None = None
navigation: NavigationPreferencesPayload | None = None
change_request_id: str | None = None
+15
View File
@@ -142,6 +142,21 @@ manifest = ModuleManifest(
],
},
),
DocumentationTopic(
id="admin.system-navigation",
title="Set the system navigation baseline",
summary="System administrators define the instance-wide side-rail order, visibility baseline, and entries that lower scopes must keep visible.",
body=(
"The system navigation setting starts from module-declared defaults. Tenant settings take precedence over the system order and visibility, and personal settings take precedence over both. A system lock prevents tenant and user preferences from hiding an entry but does not prevent them from moving it. Removing the system preference restores module defaults. Navigation policy changes presentation only: module entitlement, View policy, and permissions still decide whether a surface is accessible."
),
documentation_types=("admin",),
audience=("system_admin",),
related_modules=("tenancy", "access", "views"),
metadata={
"kind": "reference",
"help_contexts": ["admin.system-settings"],
},
),
DocumentationTopic(
id="admin.module-lifecycle-workflow",
title="Plan and supervise module lifecycle changes",
+4 -1
View File
@@ -1,4 +1,4 @@
import type { ApiSettings, DeltaDeletedItem, PrivacyRetentionPolicy } from "@govoplan/core-webui";
import type { ApiSettings, DeltaDeletedItem, NavigationPreferences, PrivacyRetentionPolicy } from "@govoplan/core-webui";
import { apiDownload, apiFetch, apiPath, apiQuery } from "@govoplan/core-webui";
export { fetchAdminOverview, fetchPermissionCatalog, fetchTenants } from "@govoplan/core-webui";
export type {
@@ -33,6 +33,7 @@ export type SystemSettingsItem = {
available_languages: LanguagePackage[];
enabled_language_codes: string[];
settings: Record<string, unknown>;
navigation: NavigationPreferences | null;
};
export type SystemSettingsDeltaSections = Partial<{
@@ -42,6 +43,7 @@ export type SystemSettingsDeltaSections = Partial<{
privacy_retention_policy: SystemSettingsItem["privacy_retention_policy"];
maintenance_mode: SystemSettingsItem["maintenance_mode"];
settings: SystemSettingsItem["settings"];
navigation: SystemSettingsItem["navigation"];
}>;
export type SystemSettingsUpdatePayload = {
@@ -53,6 +55,7 @@ export type SystemSettingsUpdatePayload = {
maintenance_mode?: MaintenanceMode | null;
available_languages?: LanguagePackage[] | null;
enabled_language_codes?: string[] | null;
navigation?: NavigationPreferences | null;
change_request_id?: string | null;
};
@@ -5,7 +5,7 @@ import { Card } from "@govoplan/core-webui";
import { FormField } from "@govoplan/core-webui";
import { ToggleSwitch } from "@govoplan/core-webui";
import { fetchSystemSettingsDelta, updateSystemSettings, type LanguagePackage, type PrivacyRetentionLimitPermissions, type PrivacyRetentionPolicy, type SystemSettingsDeltaSections, type SystemSettingsItem } from "../../api/admin";
import { AdminPageLayout, AdminSelectionList, DocumentationHelpLink, adminErrorMessage, useDeltaWatermarks, useUnsavedDraftGuard } from "@govoplan/core-webui";
import { AdminPageLayout, AdminSelectionList, DocumentationHelpLink, NavigationPreferenceEditor, adminErrorMessage, configurableNavigationItemsForModules, dispatchPlatformModulesChanged, useDeltaWatermarks, usePlatformModules, useUnsavedDraftGuard } from "@govoplan/core-webui";
import { ADMIN_GOVERNANCE_DOCUMENTATION, ADMIN_INTERFACE_I18N, mutationDisabledReason } from "./interfacePatterns";
const DELTA_KEY = "admin:system-settings";
@@ -43,10 +43,13 @@ const fallback: SystemSettingsItem = {
{ code: "en", label: "English", native_label: "English" }
],
enabled_language_codes: ["de", "en"],
settings: {}
settings: {},
navigation: null
};
export default function SystemSettingsPanel({ settings, canWrite, canAccessMaintenance }: {settings: ApiSettings;canWrite: boolean;canAccessMaintenance: boolean;}) {
const modules = usePlatformModules();
const navigationItems = configurableNavigationItemsForModules(modules);
const [draft, setDraft] = useState<SystemSettingsItem>(fallback);
const [savedDraft, setSavedDraft] = useState<SystemSettingsItem>(fallback);
const [loading, setLoading] = useState(true);
@@ -102,11 +105,13 @@ export default function SystemSettingsPanel({ settings, canWrite, canAccessMaint
allow_tenant_api_keys: draft.allow_tenant_api_keys,
maintenance_mode: draft.maintenance_mode,
available_languages: draft.available_languages,
enabled_language_codes: draft.enabled_language_codes
enabled_language_codes: draft.enabled_language_codes,
navigation: draft.navigation
});
setDraft(saved);
setSavedDraft(saved);
resetDeltaWatermark(DELTA_KEY);
dispatchPlatformModulesChanged();
setSuccess("i18n:govoplan-admin.system_settings_saved.dac4f17b");
return true;
} catch (err) {setError(adminErrorMessage(err));return false;} finally
@@ -187,6 +192,15 @@ export default function SystemSettingsPanel({ settings, canWrite, canAccessMaint
</div>
<p className="muted small-note">i18n:govoplan-admin.these_settings_are_enforced_by_the_backend_centr.8112ed6f</p>
</Card>
<Card title="System navigation order">
<NavigationPreferenceEditor
items={navigationItems}
value={draft.navigation}
onChange={(navigation) => setDraft({ ...draft, navigation })}
scope="system"
disabled={!canWrite || busy}
/>
</Card>
<Card title="i18n:govoplan-admin.maintenance_mode.98cca5c6">
<div className="settings-list">
<ToggleSwitch
@@ -232,7 +246,8 @@ function systemSettingsDraftKey(item: SystemSettingsItem): string {
allow_tenant_api_keys: item.allow_tenant_api_keys,
maintenance_mode: item.maintenance_mode,
available_languages: item.available_languages,
enabled_language_codes: item.enabled_language_codes
enabled_language_codes: item.enabled_language_codes,
navigation: item.navigation
});
}
@@ -244,6 +259,7 @@ function applySystemSettingsSections(item: SystemSettingsItem, sections: SystemS
...(sections.languages ?? {}),
...(sections.privacy_retention_policy ? { privacy_retention_policy: sections.privacy_retention_policy } : {}),
...(sections.maintenance_mode ? { maintenance_mode: sections.maintenance_mode } : {}),
...(sections.navigation !== undefined ? { navigation: sections.navigation } : {}),
...(sections.settings ? { settings: sections.settings } : {})
};
}