From 41c41adb98798291bd4e1b280a0450aee24df995 Mon Sep 17 00:00:00 2001 From: matteoscrugli Date: Sun, 14 Dec 2025 19:50:30 +0100 Subject: [PATCH] Add UI settings API and improve context initialization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add /settings/ui GET and PUT endpoints for UI settings - Improve ThemeContext with better initialization and auto accent handling - Update SidebarContext with expanded state persistence - Fix context initialization in ModulesContext and ViewModeContext - Update components to use improved theme/sidebar contexts 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- backend/app/api/v1/settings.py | 42 ++++++++++++++ frontend/src/App.tsx | 18 +++--- frontend/src/components/Sidebar.tsx | 6 +- frontend/src/components/UserMenu.tsx | 6 +- frontend/src/contexts/ModulesContext.tsx | 10 +++- frontend/src/contexts/SidebarContext.tsx | 30 +++++++--- frontend/src/contexts/ThemeContext.tsx | 69 +++++++++++++++++------ frontend/src/contexts/ViewModeContext.tsx | 11 ++-- frontend/src/pages/Login.tsx | 18 ++++-- frontend/src/pages/admin/Features.tsx | 5 +- 10 files changed, 163 insertions(+), 52 deletions(-) diff --git a/backend/app/api/v1/settings.py b/backend/app/api/v1/settings.py index 8ae47e4..8f65748 100644 --- a/backend/app/api/v1/settings.py +++ b/backend/app/api/v1/settings.py @@ -10,6 +10,7 @@ from app.models.user import User from app.core.settings_registry import ( THEME_KEYS, MODULE_KEYS, + UI_KEYS, SETTINGS_REGISTRY, get_default_value, ) @@ -82,6 +83,47 @@ def get_module_settings( return result +@router.get("/ui", response_model=dict[str, Any]) +def get_ui_settings( + *, + db: Session = Depends(get_db), + current_user: User = Depends(get_current_user) +) -> Any: + """ + Get UI settings (accessible to all authenticated users). + + Returns UI/layout settings that apply to all users. + """ + result = {} + for key in UI_KEYS: + setting = crud.settings.get_setting(db, key=key) + if setting: + result[key] = setting.get_value() + else: + result[key] = get_default_value(key) + return result + + +@router.put("/ui", response_model=dict[str, Any]) +def update_ui_settings( + *, + db: Session = Depends(get_db), + ui_data: dict[str, Any], + current_user: User = Depends(get_current_superuser) +) -> Any: + """ + Update UI settings (admin only). + + Updates multiple UI/layout settings at once. + """ + result = {} + for key, value in ui_data.items(): + if key in UI_KEYS: + setting = crud.settings.update_setting(db, key=key, value=value) + result[key] = setting.get_value() + return result + + @router.put("/modules", response_model=dict[str, Any]) def update_module_settings( *, diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index ac12450..6b7a290 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -46,7 +46,11 @@ import MainLayout from './components/MainLayout'; // ... function AppRoutes() { - const { user } = useAuth(); + const { user, isLoading } = useAuth(); + + if (isLoading) { + return
Loading...
; + } return ( @@ -72,9 +76,9 @@ function App() { return ( - - - + + + @@ -82,9 +86,9 @@ function App() { - - - + + + ); diff --git a/frontend/src/components/Sidebar.tsx b/frontend/src/components/Sidebar.tsx index 1129be0..7bc7611 100644 --- a/frontend/src/components/Sidebar.tsx +++ b/frontend/src/components/Sidebar.tsx @@ -14,7 +14,7 @@ import '../styles/Sidebar.css'; export default function Sidebar() { const { t, language, setLanguage } = useTranslation(); const { config } = useSiteConfig(); - const { sidebarStyle, theme, toggleTheme, darkModeLocation, languageLocation, showDarkModeToggle, showLanguageToggle } = useTheme(); + const { sidebarStyle, theme, toggleTheme, darkModeLocation, languageLocation, showDarkModeToggle, showLanguageToggle, hasInitializedSettings: themeInitialized } = useTheme(); const { isCollapsed, isMobileOpen, @@ -235,7 +235,7 @@ export default function Sidebar() { )} - {showDarkModeToggle && darkModeLocation === 'sidebar' && ( + {themeInitialized && showDarkModeToggle && darkModeLocation === 'sidebar' && ( )} - {showLanguageToggle && languageLocation === 'sidebar' && ( + {themeInitialized && showLanguageToggle && languageLocation === 'sidebar' && ( )} - {showLanguageToggle && languageLocation === 'user_menu' && ( + {themeInitialized && showLanguageToggle && languageLocation === 'user_menu' && (