From e1ffcaa6965dc6f9ffd32ae94baa7265a079f008 Mon Sep 17 00:00:00 2001 From: John Haverlack Date: Sun, 1 Feb 2026 12:22:58 -0900 Subject: [PATCH] Light/Dark Mode Toggle --- sdl-mgr/html/conf/nav.json | 6 ++++ sdl-mgr/html/css/custom-styles.css | 11 +++++++ sdl-mgr/html/js/dash.js | 33 ++++++++++---------- sdl-mgr/html/js/settings.js | 50 ++++++++++++++++++++++++++++++ sdl-mgr/html/js/weblib.js | 4 +++ sdl-mgr/html/md/settings.md | 26 ++++++++++++++++ 6 files changed, 114 insertions(+), 16 deletions(-) create mode 100644 sdl-mgr/html/js/settings.js create mode 100644 sdl-mgr/html/md/settings.md diff --git a/sdl-mgr/html/conf/nav.json b/sdl-mgr/html/conf/nav.json index 63a48f5..919365a 100644 --- a/sdl-mgr/html/conf/nav.json +++ b/sdl-mgr/html/conf/nav.json @@ -31,6 +31,12 @@ "page": "docs", "enabled": true }, + { + "title": "Settings", + "icon": "fa-solid fa-gear", + "page": "settings", + "enabled": true + }, { "title": "API", "icon": "fa-solid fa-code", diff --git a/sdl-mgr/html/css/custom-styles.css b/sdl-mgr/html/css/custom-styles.css index 151ce0c..48d590e 100644 --- a/sdl-mgr/html/css/custom-styles.css +++ b/sdl-mgr/html/css/custom-styles.css @@ -213,6 +213,17 @@ json-viewer .property:hover { color: hwb(0 55% 45%); } +/* .dash-val { + color: hwb(116 7% 35%); +} */ + +[data-bs-theme="light"] .dash-val { + color: hwb(116 0% 46%); +} + +[data-bs-theme="dark"] .dash-val { + color: hwb(116 40% 0%); /* 40% lighter for dark backgrounds */ +} /* Dark Theme */ diff --git a/sdl-mgr/html/js/dash.js b/sdl-mgr/html/js/dash.js index c4a4c17..dfc2da2 100644 --- a/sdl-mgr/html/js/dash.js +++ b/sdl-mgr/html/js/dash.js @@ -35,7 +35,7 @@ if (Array.isArray(config.host.gpu) && config.host.gpu.length > 0) { gpu.memory?.type === 'dedicated' && Number.isFinite(gpu.memory.total_mb) ) { - memLabel = `(${Math.round(gpu.memory.total_mb / 1024)} GB VRAM)`; + memLabel = `(${Math.round(gpu.memory.total_mb / 1024)} GB VRAM)`; } else if (gpu.memory?.type === 'shared') { memLabel = '(shared VRAM)'; } else { @@ -54,11 +54,11 @@ if (Array.isArray(config.host.gpu) && config.host.gpu.length > 0) { // Hostinfo: hostname, cpu, cores, ram, os const hostinfo = { - "hostname": '' + config.host.hostname + '', - "sdl_id": '' + config.identity.sdl_id + '', - "cpu cores": '' + config.host.cpu.cores_logical + ' ' + config.host.cpu.model + '', + "hostname": '' + config.host.hostname + '', + "sdl_id": '' + config.identity.sdl_id + '', + "cpu cores": '' + config.host.cpu.cores_logical + ' ' + config.host.cpu.model + '', // "cores": config.host.cpu.cores_logical, - "ram": '' + config.host.memory.total_gb + ' GB ', + "ram": '' + config.host.memory.total_gb + ' GB ', "gpu": gpuSummary, "net": "", "os": config.host.os.pretty_name @@ -70,7 +70,7 @@ for (let intf in config.host.network) { if (intf != 'lo') { for (let addr in config.host.network[intf]) { if (config.host.network[intf][addr].family == 'IPv4') { - hostinfo["net"] += '' + config.host.network[intf][addr].cidr + '
'; + hostinfo["net"] += '' + config.host.network[intf][addr].cidr + '
'; } } } @@ -271,55 +271,56 @@ function renderModulesTable(msg) { sdl_html += ` SDL Version - v${msg.msg.sdl.version} + v${msg.msg.sdl.version} `; + sdl_html += ` Uptime (d.h.m.s) - ${msg.msg.sdl.uptime} + ${msg.msg.sdl.uptime} `; sdl_html += ` Cluster ID - ${msg.msg.cluster.id} + ${msg.msg.cluster.id} `; sdl_html += ` Cluster Name - ${msg.msg.cluster.name} + ${msg.msg.cluster.name} `; sdl_html += ` Cluster Desc - ${msg.msg.cluster.desc} + ${msg.msg.cluster.desc} `; sdl_html += ` CPU - + `; sdl_html += ` RAM - + `; sdl_html += ` GPU - + `; @@ -339,7 +340,7 @@ function renderModulesTable(msg) { for (const [name, info] of Object.entries(modules)) { const ok = info.enabled === true; const icon = ok - ? '' + ? '' : ''; html += ` @@ -386,7 +387,7 @@ function startStatusAgeMonitor() { markAllModulesDown(); } else { ageEl.innerHTML = - ` + ` SDL online (${Math.round(ageMs / 1000)}s ago) `; diff --git a/sdl-mgr/html/js/settings.js b/sdl-mgr/html/js/settings.js new file mode 100644 index 0000000..70a10f7 --- /dev/null +++ b/sdl-mgr/html/js/settings.js @@ -0,0 +1,50 @@ +console.log('Settings.js loaded'); + +// Get current theme from localStorage +const currentTheme = localStorage.getItem('theme') || 'dark'; +console.log('Current theme:', currentTheme); + +// Set the toggle to match current theme +const themeSwitch = document.getElementById('themeSwitch'); +const themeLabel = document.querySelector('label[for="themeSwitch"]'); + +console.log('Theme switch element found:', themeSwitch); + +if (themeSwitch && themeLabel) { + themeSwitch.checked = (currentTheme === 'dark'); + + // Update label based on current theme + updateLabel(currentTheme); + + console.log('Switch checked state:', themeSwitch.checked); + + // Listen for changes + themeSwitch.addEventListener('change', (e) => { + console.log('Switch toggled!', e.target.checked); + const newTheme = e.target.checked ? 'dark' : 'light'; + console.log('Setting new theme:', newTheme); + setTheme(newTheme); + updateLabel(newTheme); + }); +} else { + console.error('themeSwitch or themeLabel element not found!'); +} + +function setTheme(theme) { + console.log('setTheme called with:', theme); + document.documentElement.setAttribute('data-bs-theme', theme); + localStorage.setItem('theme', theme); + console.log('Theme set to:', theme); + console.log('HTML data-bs-theme attribute:', document.documentElement.getAttribute('data-bs-theme')); +} + +function updateLabel(theme) { + const themeLabel = document.querySelector('label[for="themeSwitch"]'); + if (themeLabel) { + if (theme === 'dark') { + themeLabel.innerHTML = 'Dark Mode'; + } else { + themeLabel.innerHTML = 'Light Mode'; + } + } +} \ No newline at end of file diff --git a/sdl-mgr/html/js/weblib.js b/sdl-mgr/html/js/weblib.js index 6b1ab8d..dc6b7c4 100644 --- a/sdl-mgr/html/js/weblib.js +++ b/sdl-mgr/html/js/weblib.js @@ -832,6 +832,9 @@ export async function getUTCTimestamp() { // Load on page load // =============================== window.addEventListener('DOMContentLoaded', async () => { + // Apply saved theme (default to dark) + const savedTheme = localStorage.getItem('theme') || 'dark'; + document.documentElement.setAttribute('data-bs-theme', savedTheme); const config = await loadConfig(); // console.log(`DEBUG: ${JSON.stringify(config)}`) @@ -849,6 +852,7 @@ window.addEventListener('DOMContentLoaded', async () => { loadFooter(); + // Load Markdown content const urlParams = new URLSearchParams(window.location.search); const page = urlParams.get('page') || 'index'; diff --git a/sdl-mgr/html/md/settings.md b/sdl-mgr/html/md/settings.md new file mode 100644 index 0000000..a88e16e --- /dev/null +++ b/sdl-mgr/html/md/settings.md @@ -0,0 +1,26 @@ +
+
+
+
+
+
Appearance
+
+
+
+
+ +

Toggle between light and dark theme

+
+
+
+ +
+
+
+
+
+
+
+
\ No newline at end of file