feat(core): add layered side rail preferences
This commit is contained in:
@@ -2,7 +2,7 @@ import DescriptionList from "../../components/DescriptionList";
|
||||
import ContentGrid, { FormGrid } from "../../components/ContentGrid";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { useSearchParams } from "react-router";
|
||||
import type { ApiSettings, AuthInfo, AuthUpdate, FilesConnectorsUiCapability, MailProfilesUiCapability, SettingsSectionContribution, SettingsSectionsUiCapability, UserUiPreferences, UserUiTheme } from "../../types";
|
||||
import type { ApiSettings, AuthInfo, AuthUpdate, FilesConnectorsUiCapability, MailProfilesUiCapability, NavigationPreferences, SettingsSectionContribution, SettingsSectionsUiCapability, UserUiPreferences, UserUiTheme } from "../../types";
|
||||
import Card from "../../components/Card";
|
||||
import FormField from "../../components/FormField";
|
||||
import PasswordField from "../../components/PasswordField";
|
||||
@@ -12,11 +12,14 @@ import PageActionBar from "../../components/PageActionBar";
|
||||
import ToggleSwitch from "../../components/ToggleSwitch";
|
||||
import { apiFetch } from "../../api/client";
|
||||
import { fetchAuthProfile, fetchAuthRoles, updateProfile } from "../../api/auth";
|
||||
import { dispatchPlatformModulesChanged } from "../../platform/moduleEvents";
|
||||
import ModuleSubnav, { type ModuleSubnavGroup } from "../../layout/ModuleSubnav";
|
||||
import DismissibleAlert from "../../components/DismissibleAlert";
|
||||
import SegmentedControl from "../../components/SegmentedControl";
|
||||
import { useUnsavedChanges, useUnsavedDraftGuard } from "../../components/UnsavedChangesGuard";
|
||||
import { usePlatformUiCapabilities, usePlatformUiCapability } from "../../platform/ModuleContext";
|
||||
import { usePlatformModules, usePlatformUiCapabilities, usePlatformUiCapability } from "../../platform/ModuleContext";
|
||||
import { configurableNavigationItemsForModules } from "../../platform/modules";
|
||||
import NavigationPreferenceEditor from "../../components/NavigationPreferenceEditor";
|
||||
import { useEffectiveView, useViewSurfaces } from "../../platform/ViewContext";
|
||||
import { isViewSurfaceVisible } from "../../platform/views";
|
||||
import { hasAnyScope, hasScope } from "../../utils/permissions";
|
||||
@@ -103,6 +106,8 @@ export default function SettingsPage({
|
||||
const mailProfilesUi = usePlatformUiCapability<MailProfilesUiCapability>("mail.profiles");
|
||||
const fileConnectorsUi = usePlatformUiCapability<FilesConnectorsUiCapability>("files.connectors");
|
||||
const settingsSectionCapabilities = usePlatformUiCapabilities<SettingsSectionsUiCapability>("settings.sections");
|
||||
const platformModules = usePlatformModules();
|
||||
const navigationItems = useMemo(() => configurableNavigationItemsForModules(platformModules), [platformModules]);
|
||||
const effectiveView = useEffectiveView();
|
||||
const viewSurfaces = useViewSurfaces();
|
||||
const { language, languageLabel, selectableLanguages, availableLanguages, enabledLanguages, setLanguage } = usePlatformLanguage();
|
||||
@@ -150,6 +155,7 @@ export default function SettingsPage({
|
||||
const [reduceMotion, setReduceMotion] = useState(currentUiPreferences.reduce_motion);
|
||||
const [stickySections, setStickySections] = useState(currentUiPreferences.sticky_section_sidebars);
|
||||
const [theme, setTheme] = useState<UserUiTheme>(currentUiPreferences.theme);
|
||||
const [navigation, setNavigation] = useState<NavigationPreferences | null>(currentUiPreferences.navigation ?? null);
|
||||
const [uiBusy, setUiBusy] = useState(false);
|
||||
const [uiResult, setUiResult] = useState("");
|
||||
const [uiResultTone, setUiResultTone] = useState<"success" | "warning">("success");
|
||||
@@ -164,7 +170,8 @@ export default function SettingsPage({
|
||||
showHelpHints !== currentUiPreferences.show_inline_help_hints ||
|
||||
reduceMotion !== currentUiPreferences.reduce_motion ||
|
||||
stickySections !== currentUiPreferences.sticky_section_sidebars ||
|
||||
theme !== currentUiPreferences.theme;
|
||||
theme !== currentUiPreferences.theme ||
|
||||
JSON.stringify(navigation) !== JSON.stringify(currentUiPreferences.navigation ?? null);
|
||||
|
||||
useUnsavedDraftGuard({
|
||||
dirty: active === "profile" && profileDirty,
|
||||
@@ -218,12 +225,14 @@ export default function SettingsPage({
|
||||
setReduceMotion(currentUiPreferences.reduce_motion);
|
||||
setStickySections(currentUiPreferences.sticky_section_sidebars);
|
||||
setTheme(currentUiPreferences.theme);
|
||||
setNavigation(currentUiPreferences.navigation ?? null);
|
||||
}, [
|
||||
currentUiPreferences.compact_tables,
|
||||
currentUiPreferences.show_inline_help_hints,
|
||||
currentUiPreferences.reduce_motion,
|
||||
currentUiPreferences.sticky_section_sidebars,
|
||||
currentUiPreferences.theme
|
||||
currentUiPreferences.theme,
|
||||
currentUiPreferences.navigation
|
||||
]);
|
||||
|
||||
function selectSection(section: SettingsSection) {
|
||||
@@ -262,6 +271,7 @@ export default function SettingsPage({
|
||||
setReduceMotion(currentUiPreferences.reduce_motion);
|
||||
setStickySections(currentUiPreferences.sticky_section_sidebars);
|
||||
setTheme(currentUiPreferences.theme);
|
||||
setNavigation(currentUiPreferences.navigation ?? null);
|
||||
}
|
||||
|
||||
function uiPreferencePayload(): UserUiPreferences {
|
||||
@@ -270,7 +280,8 @@ export default function SettingsPage({
|
||||
show_inline_help_hints: showHelpHints,
|
||||
reduce_motion: reduceMotion,
|
||||
sticky_section_sidebars: stickySections,
|
||||
theme
|
||||
theme,
|
||||
navigation
|
||||
};
|
||||
}
|
||||
|
||||
@@ -280,6 +291,7 @@ export default function SettingsPage({
|
||||
try {
|
||||
const next = await updateProfile(settings, { ui_preferences: uiPreferencePayload() });
|
||||
onAuthChange(next);
|
||||
dispatchPlatformModulesChanged();
|
||||
setUiResultTone("success");
|
||||
setUiResult("i18n:govoplan-core.preferences_saved.c8cd3501");
|
||||
return true;
|
||||
@@ -503,6 +515,15 @@ export default function SettingsPage({
|
||||
<span>i18n:govoplan-core.template_placeholder_chips_and_preview_overlays.11634d55</span>
|
||||
</div>
|
||||
</Card>
|
||||
<Card title="Navigation order">
|
||||
<NavigationPreferenceEditor
|
||||
items={navigationItems}
|
||||
value={navigation}
|
||||
onChange={setNavigation}
|
||||
scope="user"
|
||||
disabled={uiBusy}
|
||||
/>
|
||||
</Card>
|
||||
</ContentGrid>
|
||||
}
|
||||
|
||||
@@ -594,7 +615,8 @@ function normalizeUiPreferences(value: Partial<UserUiPreferences> | null | undef
|
||||
show_inline_help_hints: Boolean(value?.show_inline_help_hints ?? DEFAULT_UI_PREFERENCES.show_inline_help_hints),
|
||||
reduce_motion: Boolean(value?.reduce_motion ?? DEFAULT_UI_PREFERENCES.reduce_motion),
|
||||
sticky_section_sidebars: Boolean(value?.sticky_section_sidebars ?? DEFAULT_UI_PREFERENCES.sticky_section_sidebars),
|
||||
theme
|
||||
theme,
|
||||
navigation: value?.navigation ?? null
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user