From 76263be05d6b277238131d3c31f4f2ed125a94e6 Mon Sep 17 00:00:00 2001 From: rcourtman Date: Thu, 23 Oct 2025 12:57:39 +0000 Subject: [PATCH] Add gradient banners to settings pages for visual consistency Adds polished gradient banner headers to all configuration pages: - System > General, Network, Updates, Backups - Security > Authentication (updated from gray to blue/indigo gradient) - API Access Resource management pages (PVE, PBS, Docker, etc.) intentionally left without banners to keep focus on node tables and operational content. --- .../src/components/Settings/Settings.tsx | 486 +++++++++++------- 1 file changed, 287 insertions(+), 199 deletions(-) diff --git a/frontend-modern/src/components/Settings/Settings.tsx b/frontend-modern/src/components/Settings/Settings.tsx index 04779d8..8cbdab2 100644 --- a/frontend-modern/src/components/Settings/Settings.tsx +++ b/frontend-modern/src/components/Settings/Settings.tsx @@ -25,8 +25,9 @@ import Server from 'lucide-solid/icons/server'; import HardDrive from 'lucide-solid/icons/hard-drive'; import Mail from 'lucide-solid/icons/mail'; import Container from 'lucide-solid/icons/container'; -import SettingsIcon from 'lucide-solid/icons/settings'; import Shield from 'lucide-solid/icons/shield'; +import Lock from 'lucide-solid/icons/lock'; +import Key from 'lucide-solid/icons/key'; import Activity from 'lucide-solid/icons/activity'; import Loader from 'lucide-solid/icons/loader'; import Boxes from 'lucide-solid/icons/boxes'; @@ -34,6 +35,9 @@ import Network from 'lucide-solid/icons/network'; import Terminal from 'lucide-solid/icons/terminal'; import Monitor from 'lucide-solid/icons/monitor'; import Laptop from 'lucide-solid/icons/laptop'; +import Sliders from 'lucide-solid/icons/sliders-horizontal'; +import RefreshCw from 'lucide-solid/icons/refresh-cw'; +import Clock from 'lucide-solid/icons/clock'; import { ApiIcon } from '@/components/icons/ApiIcon'; import type { NodeConfig } from '@/types/nodes'; import type { UpdateInfo, VersionInfo } from '@/api/updates'; @@ -233,9 +237,14 @@ type SettingsTab = | 'linuxServers' | 'windowsServers' | 'macServers' - | 'system' + | 'system-general' + | 'system-network' + | 'system-updates' + | 'system-backups' | 'api' - | 'security' + | 'security-overview' + | 'security-auth' + | 'security-sso' | 'diagnostics' | 'updates'; @@ -276,17 +285,37 @@ const SETTINGS_HEADER_META: Record = (props) => { if (path.includes('/settings/linuxServers')) return 'linuxServers'; if (path.includes('/settings/windowsServers')) return 'windowsServers'; if (path.includes('/settings/macServers')) return 'macServers'; - if (path.includes('/settings/system')) return 'system'; + if (path.includes('/settings/system-general')) return 'system-general'; + if (path.includes('/settings/system-network')) return 'system-network'; + if (path.includes('/settings/system-updates')) return 'system-updates'; + if (path.includes('/settings/system-backups')) return 'system-backups'; + // Legacy redirect: old /settings/system goes to general + if (path.includes('/settings/system')) return 'system-general'; if (path.includes('/settings/api')) return 'api'; - if (path.includes('/settings/security')) return 'security'; + if (path.includes('/settings/security-overview')) return 'security-overview'; + if (path.includes('/settings/security-auth')) return 'security-auth'; + if (path.includes('/settings/security-sso')) return 'security-sso'; + // Legacy redirect: old /settings/security goes to overview + if (path.includes('/settings/security')) return 'security-overview'; if (path.includes('/settings/diagnostics')) return 'diagnostics'; if (path.includes('/settings/updates')) return 'updates'; return 'pve'; @@ -350,7 +388,7 @@ const Settings: Component = (props) => { const setActiveTab = (tab: SettingsTab) => { const targetPath = `/settings/${tab}`; if (location.pathname !== targetPath) { - navigate(targetPath); + navigate(targetPath, { scroll: false }); return; } if (currentTab() !== tab) { @@ -730,7 +768,7 @@ const Settings: Component = (props) => { }; const tabGroups: { - id: 'platforms' | 'administration'; + id: 'platforms' | 'administration' | 'system' | 'security'; label: string; items: { id: SettingsTab; label: string; icon: JSX.Element; disabled?: boolean }[]; }[] = [ @@ -753,12 +791,29 @@ const Settings: Component = (props) => { id: 'administration', label: 'Administration', items: [ - { id: 'system', label: 'System', icon: }, { id: 'api', label: 'API access', icon: }, - { id: 'security', label: 'Security', icon: }, { id: 'diagnostics', label: 'Diagnostics', icon: }, ], }, + { + id: 'system', + label: 'System', + items: [ + { id: 'system-general', label: 'General', icon: }, + { id: 'system-network', label: 'Network', icon: }, + { id: 'system-updates', label: 'Updates', icon: }, + { id: 'system-backups', label: 'Backups', icon: }, + ], + }, + { + id: 'security', + label: 'Security', + items: [ + { id: 'security-overview', label: 'Overview', icon: }, + { id: 'security-auth', label: 'Authentication', icon: }, + { id: 'security-sso', label: 'Single Sign-On', icon: }, + ], + }, ]; const flatTabs = tabGroups.flatMap((group) => group.items); @@ -1440,7 +1495,8 @@ const Settings: Component = (props) => { const saveSettings = async () => { try { - if (activeTab() === 'system') { + if (activeTab() === 'system-general' || activeTab() === 'system-network' || + activeTab() === 'system-updates' || activeTab() === 'system-backups') { // Save system settings using typed API await SettingsAPI.updateSystemSettings({ // PBS polling interval is now fixed at 10 seconds @@ -1798,7 +1854,9 @@ const Settings: Component = (props) => {
@@ -1848,7 +1906,7 @@ const Settings: Component = (props) => { aria-label="Settings navigation" aria-expanded={!sidebarCollapsed()} > -
+
{(group) => ( @@ -3311,11 +3369,53 @@ const Settings: Component = (props) => { - {/* System Settings Tab */} - + {/* System General Tab */} +
- + +
+
+
+ +
+ +
+
+
+
+
+

Dark mode

+

+ Toggle to match your environment. Pulse remembers this preference on each browser. +

+
+ { + const desired = (event.currentTarget as HTMLInputElement).checked; + if (desired !== props.darkMode()) { + props.toggleDarkMode(); + } + }} + /> +
+
+
+
+
+ {/* System Network Tab */} + +
= (props) => {
- - + +
+
+
+ +
+ +
+
+
+
= (props) => { configuration and restart Pulse to change them here.
-
+ - - -
-
-

Dark mode

-

- Toggle to match your environment. Pulse remembers this preference on each browser. -

-
- { - const desired = (event.currentTarget as HTMLInputElement).checked; - if (desired !== props.darkMode()) { - props.toggleDarkMode(); - } - }} - /> -
-
- -
- -
+

= (props) => {

- +

+
+
+ - + {/* System Updates Tab */} + +
+ +
+
+
+ +
+ +
+
+
-

- - - - - - Updates -

-
@@ -4073,15 +4171,33 @@ const Settings: Component = (props) => {
- -
+
+
+
+ - {/* Backup & Restore - Moved from Security tab */} + {/* System Backups Tab */} + +
+
+
+
+ +
+ +
+
+

@@ -4366,6 +4482,7 @@ const Settings: Component = (props) => {

+
@@ -4373,21 +4490,38 @@ const Settings: Component = (props) => { {/* API Access */}
- - - -

- Generate scoped tokens for Docker agents, host agents, and automation pipelines. - Tokens are shown once—store them securely and rotate when infrastructure changes. -

- - View scope reference - + +
+
+
+ +
+ +
+
+
+

+ Generate scoped tokens for Docker agents, host agents, and automation pipelines. + Tokens are shown once—store them securely and rotate when infrastructure changes. +

+ + View scope reference + +
= (props) => {
- {/* Security Tab */} - + {/* Security Overview Tab */} +
@@ -4461,53 +4595,64 @@ const Settings: Component = (props) => {
+ +
+ {/* Security Authentication Tab */} + +
{/* Show message when auth is disabled */} -
-
-
- - - -
-

- Authentication disabled -

-

- DISABLE_AUTH is set, or auth isn't configured yet. -

+ + {/* Header */} +
+
+
+ + +
+ +
-
- -
+ + {/* Content */} +
+

+ DISABLE_AUTH is set, or auth isn't configured yet. Set up password authentication to protect your Pulse instance. +

+ + { setShowQuickSecuritySetup(false); loadSecurityStatus(); }} /> -
- -
+
+
+ {/* Authentication */} @@ -4523,24 +4668,17 @@ const Settings: Component = (props) => { border={false} > {/* Header */} -
+
-
- - - +
+
- +
@@ -4697,63 +4835,13 @@ const Settings: Component = (props) => {
+
+ - + {/* Security Single Sign-On Tab */} + +
- - {/* Security setup now handled by first-run wizard */} - - {/* API Token - Show always to allow API access even when auth is disabled */} - - {/* Header */} -
-
-
- - - -
- -
-
- - {/* Content */} -
-

- API tokens now live under the dedicated API workspace. Generate new scoped tokens, - review existing access, and rotate credentials from the API menu. -

- -
-
- - {/* Advanced - Only show if auth is enabled */} - {/* Advanced Options section removed - was only used for Registration Tokens */}