From d1106bce11a5867d8ebf82ca62bb1311a099d138 Mon Sep 17 00:00:00 2001 From: Mario Mariete <11509521+melkati@users.noreply.github.com> Date: Sat, 1 Jun 2024 00:11:12 +0200 Subject: [PATCH] Fix: Server status dot red. Now shows correctly if connection is lost Fix: Close button in floating debug window (development aid) on web server was not working. Update: Renamed url parameter testCaptivePortal to forcedCaptivePortal (development aid) Fix: Many fixes to web server and Captive Server Update: Many general improvements to web server and Captive Server HTML, CSS, and JavaScript files Update: Only shows captivePortalSettings (development aid) when debug is set --- data/captiveportal.js | 306 ++++++++++++++++++++++++--------------- data/captiveportal.js.gz | Bin 3052 -> 3249 bytes data/index.html.gz | Bin 984 -> 984 bytes data/main.js.gz | Bin 569 -> 569 bytes data/ota.html.gz | Bin 797 -> 797 bytes data/preferences.html | 24 +-- data/preferences.html.gz | Bin 4789 -> 4805 bytes data/preferences.js.gz | Bin 3237 -> 3237 bytes data/status.html.gz | Bin 2948 -> 2948 bytes data/style.css | 97 +++++-------- data/style.css.gz | Bin 2480 -> 2412 bytes 11 files changed, 242 insertions(+), 185 deletions(-) diff --git a/data/captiveportal.js b/data/captiveportal.js index 14033eab..e118b10b 100644 --- a/data/captiveportal.js +++ b/data/captiveportal.js @@ -1,14 +1,16 @@ var captivePortalActive = false; -var testCaptivePortal = false; +var forcedCaptivePortal = false; var captivePortalStatusBarActive = false; var captivePortalDebug = false; +var forcedCaptivePortalDebug = false; var relaxedSecurity = false; var debugWindowActive = false; +var canPingServer = false; // Global variables to store the previous state var previousData = { captivePortalActive: false, - testCaptivePortal: false, + forcedCaptivePortal: false, captivePortalNoTimeout: false }; @@ -56,11 +58,11 @@ function updateStatusBar(content) { * @param {boolean} isInitialSetup - Whether this is the initial setup. */ function setCaptivePortalSettings(timeToWait, isInitialSetup = false) { - const disableTimeoutCheckbox = document.getElementById('disableTimeoutCheckbox'); + const disableTimeoutCheckbox = document.getElementById('cpNoTimeout'); let captivePortalNoTimeout = disableTimeoutCheckbox ? disableTimeoutCheckbox.checked : false; if (!disableTimeoutCheckbox && !isInitialSetup) { - console.error('Element with ID "disableTimeoutCheckbox" not found.'); + console.error('Element with ID "cpNoTimeout" not found.'); return; } @@ -81,7 +83,7 @@ function setCaptivePortalSettings(timeToWait, isInitialSetup = false) { timeToWaitForCaptivePortal: timeToWait, captivePortalActive, captivePortalNoTimeout, - testCaptivePortal, + forcedCaptivePortal, captivePortalDebug, relaxedSecurity: relaxedSecurity ? true : undefined }) @@ -92,7 +94,7 @@ function setCaptivePortalSettings(timeToWait, isInitialSetup = false) { } if (captivePortalDebug) { console.log('Captive Portal settings updated on server successfully:', { - testCaptivePortal, + forcedCaptivePortal, captivePortalActive, captivePortalNoTimeout, timeToWaitForCaptivePortal: timeToWait, @@ -112,7 +114,7 @@ function updateDebugWindow(data) { if (debugWindowActive) { const debugContent = document.getElementById('debug-content'); if (debugContent) { - if (captivePortalDebug) console.log('Updating debug window with data:', data); + // if (captivePortalDebug) console.log('Updating debug window with data:', data); let content = `
captivePortalActive: ${data.captivePortalActive}
captivePortalNoTimeout: ${data.captivePortalNoTimeout}
@@ -120,19 +122,24 @@ function updateDebugWindow(data) {
captivePortalTimeLeft: ${data.captivePortalTimeLeft}
captivePortalDebug: ${data.captivePortalDebug}
`; - if (data.testCaptivePortal !== undefined) { - if (captivePortalDebug) console.log('Adding testCaptivePortal to debug window:', data.testCaptivePortal); - content += `
testCaptivePortal: ${data.testCaptivePortal}
`; + + if (relaxedSecurity) { + // if (captivePortalDebug) console.log('Adding relaxedSecurity to debug window:', relaxedSecurity); + content += `
relaxedSecurity: ${relaxedSecurity}
`; + } + if (forcedCaptivePortal) { + // if (captivePortalDebug) console.log('Adding forcedCaptivePortal to debug window:', forcedCaptivePortal); + content += `
forcedCaptivePortal: ${forcedCaptivePortal}
`; } - if (data.relaxedSecurity !== undefined) { - if (captivePortalDebug) console.log('Adding relaxedSecurity to debug window:', data.relaxedSecurity); - content += `
relaxedSecurity: ${data.relaxedSecurity}
`; + if (forcedCaptivePortalDebug) { + // if (captivePortalDebug) console.log('Adding forcedCaptivePortalDebug to debug window:', forcedCaptivePortalDebug); + content += `
forcedCaptivePortalDebug: ${forcedCaptivePortalDebug}
`; } debugContent.innerHTML = content; - debugWindow.style.display = 'block'; + showDebugWindow(true); } } else { - debugWindow.style.display = 'none'; + showDebugWindow(false); } } @@ -141,91 +148,117 @@ function updateDebugWindow(data) { * @param {Object} data - The data received from the server. */ function handleCaptivePortalData(data) { - const changes = {}; - const propertiesToCheck = ['captivePortalActive', 'forceCaptivePortalActive', 'captivePortalNoTimeout', 'captivePortalDebug', 'relaxedSecurity']; - - if (captivePortalDebug) console.log('Received captive portal data from server:', data); - - // Check for changes in properties - propertiesToCheck.forEach(key => { - if (data[key] !== previousData[key]) { - changes[key] = { previous: previousData[key], current: data[key] }; - previousData[key] = data[key]; - } - }); - - if (Object.keys(changes).length > 0 && captivePortalDebug) { - console.log('Detected changes in captive portal data:', changes); - } + try { + const changes = {}; + const propertiesToCheck = ['captivePortalActive', 'forceCaptivePortalActive', 'captivePortalNoTimeout', 'captivePortalDebug', 'relaxedSecurity']; - // Update debug mode if present in data - if (data.captivePortalDebug !== undefined) { - captivePortalDebug = data.captivePortalDebug; - debugWindowActive = captivePortalDebug; - console.log('Captive portal debug mode set to:', captivePortalDebug); - } + console.log('Received captive portal data from server:', data); - // Update active states - forceCaptivePortalActive = data.forceCaptivePortalActive || false; - captivePortalActive = (data.captivePortalActive || false) || forceCaptivePortalActive; + // Check for changes in properties + propertiesToCheck.forEach(key => { + if (data[key] !== previousData[key]) { + changes[key] = { previous: previousData[key], current: data[key] }; + previousData[key] = data[key]; + } + }); - if (captivePortalActive) { - showCaptivePortalStatusBar(true); + if (Object.keys(changes).length > 0) { + console.log('Detected changes in captive portal data:', changes); + } - const newStatusContent = forceCaptivePortalActive ? 'Captive portal active (test mode)' : 'Captive portal active'; - updateStatusBar(newStatusContent); + // Update debug mode if present in data + if (data.captivePortalDebug !== undefined) { + captivePortalDebug = data.captivePortalDebug; + // debugWindowActive = captivePortalDebug; + console.log('Captive portal debug mode set to:', captivePortalDebug); + } - const statusContentElement = document.getElementById('status-content'); - if (statusContentElement) { - if (data.captivePortalNoTimeout) { - statusContentElement.innerHTML = ` - Timeout Disabled - - `; + // Update active states + forcedCaptivePortal = data.forceCaptivePortalActive || false; + captivePortalActive = (data.captivePortalActive || false) || forcedCaptivePortal; + + if (captivePortalActive) { + showCaptivePortalStatusBar(true); + + const newStatusContent = forcedCaptivePortal ? 'Captive portal active (test mode)' : 'Captive portal active'; + updateStatusBar(newStatusContent); + + const statusContentElement = document.getElementById('status-content'); + if (statusContentElement) { + if (data.captivePortalNoTimeout) { + statusContentElement.innerHTML = ` + Timeout Disabled + + `; + } else { + statusContentElement.innerHTML = ` + Timeout: ${data.captivePortalTimeLeft}s + + `; + } } else { - statusContentElement.innerHTML = ` - Timeout: ${data.captivePortalTimeLeft}s - - `; + console.error('Element with ID "status-content" not found.'); } - } else { - console.error('Element with ID "status-content" not found.'); - } - const disableTimeoutCheckbox = document.getElementById('disableTimeoutCheckbox'); - if (disableTimeoutCheckbox) { - disableTimeoutCheckbox.addEventListener('change', function () { - const timeToWait = this.checked ? 0 : data.timeToWaitForCaptivePortal; - console.log('Setting time to wait:', timeToWait); - setCaptivePortalSettings(timeToWait); - }); + const disableTimeoutCheckbox = document.getElementById('disableTimeoutCheckbox'); + if (disableTimeoutCheckbox) { + disableTimeoutCheckbox.addEventListener('change', function () { + const timeToWait = this.checked ? 0 : data.timeToWaitForCaptivePortal; + console.log('Setting time to wait:', timeToWait); + setCaptivePortalSettings(timeToWait); + }); + } + } else { + showCaptivePortalStatusBar(false); } - } else { - showCaptivePortalStatusBar(false); - } - updateServerStatusDot(); // Ensure the status dot is updated after handling captive portal data + updateServerStatusDot(); // Ensure the status dot is updated after handling captive portal data - if (debugWindowActive) { - updateDebugWindow(data); + if (debugWindowActive) { + updateDebugWindow(data); + } + } catch (error) { + console.error('Error in handleCaptivePortalData function:', error); + throw error; // Re-throw the error to be caught in the fetch catch block } } + /** * Fetches the captive portal settings from the server. */ function getCaptivePortalSettings() { - fetch('/getCaptivePortalStatusAsJson') - .then(response => response.json()) + fetch("/getCaptivePortalStatusAsJson") + .then(response => { + console.log("Received response:", response); + + // Check if the response status is OK + if (!response.ok) { + console.error("Response not OK:", response.status, response.statusText); + throw new Error("Network response was not ok " + response.statusText); + } + + // Convert the response body to JSON + return response.json(); + }) .then(captivePortalSettings => { - handleCaptivePortalData(captivePortalSettings); + console.log("Received JSON:", captivePortalSettings); + + // Handle the JSON data + try { + handleCaptivePortalData(captivePortalSettings); + } catch (e) { + console.error("Error in handleCaptivePortalData:", e); + throw e; // Re-throw the error to be caught in the catch block + } }) .catch(error => { - console.error('Error fetching captive portal status:', error); - showServerStatusDot(true, 'status-dot-red', 'Connection to server lost'); + console.error("Error fetching captive portal status:", error); + // showServerStatusDot(true, "status-dot-red", "Connection to server lost"); }); } + let previousServerStatusDotState = { show: null, colorClass: '', @@ -238,7 +271,7 @@ let previousServerStatusDotState = { * @param {string} [colorClass] - The color class to apply. * @param {string} [title] - The title to apply for hover text. */ -function showServerStatusDot(show, colorClass = 'status-dot-white', title = '') { +function displayServerStatusDot(show, colorClass = 'status-dot-cyan', title = '') { const serverStatusDot = document.getElementById('server-status-dot'); if (serverStatusDot) { const hasStateChanged = @@ -272,16 +305,15 @@ function checkServerConnection() { fetch('/pingServer') .then(response => { if (response.ok) { - updateServerStatusDot(); // Update status dot based on current state + canPingServer = true; } else { + canPingServer = false; captivePortalActive = false; // Mark captive portal as inactive - updateServerStatusDot(); // Update status dot to reflect the lost connection } }) .catch(error => { console.error('Error pinging server:', error); captivePortalActive = false; // Mark captive portal as inactive - updateServerStatusDot(); // Update status dot to reflect the lost connection }); } @@ -291,26 +323,30 @@ function checkServerConnection() { function updateServerStatusDot() { let show, colorClass, title; - if (!captivePortalActive) { + if (!canPingServer) { + show = true; + colorClass = 'status-dot-red'; + title = 'Connection to server lost'; + } else if (!captivePortalActive) { show = false; colorClass = 'status-dot-hidden'; title = 'Captive portal inactive'; - } else if (forceCaptivePortalActive) { + } else if (forcedCaptivePortal) { show = true; colorClass = 'status-dot-blue'; title = 'Captive portal active (test mode)'; } else { show = true; - colorClass = 'status-dot-white'; + colorClass = 'status-dot-cyan'; title = 'Captive portal active'; } - // Call showServerStatusDot with the new state - showServerStatusDot(show, colorClass, title); + // Call displayServerStatusDot with the new state + displayServerStatusDot(show, colorClass, title); if (captivePortalDebug) { console.log('Updated server status dot based on captive portal status'); - console.log('captivePortalActive:', captivePortalActive, 'forceCaptivePortalActive:', forceCaptivePortalActive); + console.log('captivePortalActive:', captivePortalActive, 'forcedCaptivePortal:', forcedCaptivePortal); } } @@ -333,7 +369,7 @@ function initializeCaptivePortalStatusBar() { `; - if (testCaptivePortal) showCaptivePortalStatusBar(true); + if (forcedCaptivePortal) showCaptivePortalStatusBar(true); } else { console.error('Element with ID "captive-portal-status-bar" not found.'); } @@ -344,13 +380,14 @@ function initializeCaptivePortalStatusBar() { */ function setupInitialSettings() { if (window.location.href.includes("debugCaptivePortal")) { + forcedCaptivePortalDebug = true; captivePortalDebug = true; - console.log('Forcing captive portal debug mode to be active by parameter in URL'); + console.log('Forcing captive portal debug mode to be active by debugCaptivePortal parameter in URL'); } - if (window.location.href.includes("testCaptivePortal")) { - if (captivePortalDebug) console.log('Forcing captive portal to be active in test mode by parameter in URL'); - testCaptivePortal = true; + if (window.location.href.includes("forcedCaptivePortal")) { + if (captivePortalDebug) console.log('Forcing captive portal to be active in test mode by forcedCaptivePortal parameter in URL'); + forcedCaptivePortal = true; captivePortalActive = true; } @@ -463,7 +500,7 @@ function initializeThemeSwitch() { function initializeCaptivePortal() { if (captivePortalDebug) console.log('Document loaded. Initializing captive portal for preferences.html'); - getCaptivePortalSettings(); // Fetch initial settings + // getCaptivePortalSettings(); // Fetch initial settings setupInitialSettings(); initializeCaptivePortalStatusBar(); updateStatusBarContent(); @@ -474,24 +511,6 @@ function initializeCaptivePortal() { highlightCurrentPage(); // Highlight the current page in the navigation } -/** - * Create the debug window and its content. - * @param {HTMLElement} debugWindow - The debug window element. - */ -function createDebugWindow(debugWindow) { - const closeButton = document.createElement('button'); - closeButton.id = 'close-debug-window'; - closeButton.innerHTML = '[X]'; - closeButton.onclick = () => { - debugWindow.style.display = 'none'; - }; - debugWindow.appendChild(closeButton); - - const debugContent = document.createElement('div'); - debugContent.id = 'debug-content'; - debugWindow.appendChild(debugContent); -} - document.addEventListener("DOMContentLoaded", function () { const currentPage = window.location.pathname.split("/").pop(); @@ -505,8 +524,8 @@ document.addEventListener("DOMContentLoaded", function () { if (captivePortalDebug) console.log('Not on preferences.html, skipping debug window initialization'); } + const debugWindow = document.getElementById('debug-window'); if (captivePortalDebug) { - const debugWindow = document.getElementById('debug-window'); if (debugWindow) { createDebugWindow(debugWindow); debugWindowActive = true; @@ -515,7 +534,68 @@ document.addEventListener("DOMContentLoaded", function () { console.error('Element with ID "debug-window" not found.'); } } else { - debugWindow.style.display = 'none'; - debugWindowActive = true; + if (debugWindow) { + debugWindow.style.display = 'none'; + debugWindowActive = false; + } } }); + +/** + * Shows or hides the captivePortalSettings fieldset based on the provided flag. + * @param {boolean} show - Determines whether to show or hide the captivePortalSettings fieldset. + */ +function showCaptivePortalSettings(show) { + const captivePortalSettings = document.getElementById('captivePortalSettings'); + if (captivePortalSettings) { + if (show) { + captivePortalSettings.classList.remove('hidden'); + } else { + captivePortalSettings.classList.add('hidden'); + } + } else { + console.error('Element with ID "captivePortalSettings" not found.'); + } +} + +/** + * Shows or hides the debug window based on the provided flag. + * @param {boolean} show - Flag indicating whether to show or hide the debug window. + */ +function showDebugWindow(show) { + const debugWindow = document.getElementById('debug-window'); + if (debugWindow) { + if (show) { + debugWindow.classList.remove('hidden-debug-window'); + debugWindow.style.display = 'block'; + debugWindowActive = true; + if (captivePortalDebug) console.log('Showing debug window'); + } else { + debugWindow.classList.add('hidden-debug-window'); + debugWindow.style.display = 'none'; + debugWindowActive = false; + if (captivePortalDebug) console.log('Hiding debug window'); + } + } else { + console.error('Element with ID "debug-window" not found.'); + } + showCaptivePortalSettings(show); // Show captive portal settings when debug window is shown (for development) +} + +/** + * Creates a debug window with a close button and debug content. + */ +function createDebugWindow() { + const debugWindow = document.getElementById('debug-window'); + const closeButton = document.createElement('button'); + closeButton.id = 'close-debug-window'; + closeButton.innerHTML = '[X]'; + closeButton.onclick = () => { + showDebugWindow(false); + }; + debugWindow.appendChild(closeButton); + + const debugContent = document.createElement('div'); + debugContent.id = 'debug-content'; + debugWindow.appendChild(debugContent); +} diff --git a/data/captiveportal.js.gz b/data/captiveportal.js.gz index 5eefc57aad2c528c0ac3ebf2e9bab6b2acb46def..8ebc67e7c869bed131964d01e0efd1632778bdd2 100644 GIT binary patch delta 3247 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 delta 3048 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 diff --git a/data/index.html.gz b/data/index.html.gz index 45a900f730b0f356b2edc2aac4e30da9415fe626..8432c18d77019d07f9a675fc75c0f098310e54d7 100644 GIT binary patch delta 16 Xcmcb?euJG|zMF%i*)wV*`$c8|Elve8 delta 16 Xcmcb?euJG|zMF%i>0ZP}_KVB_FuMiB diff --git a/data/main.js.gz b/data/main.js.gz index 8f5722c57fa34a2718b302f88ca431746df57a17..820727826c130bb13a769af6bd6e62b7574d32dc 100644 GIT binary patch delta 16 XcmdnVvXg~fzMF%i*)wV*yAcxrC>aD! delta 16 XcmdnVvXg~fzMF%i>0ZP}b|WSLD~1H% diff --git a/data/ota.html.gz b/data/ota.html.gz index bc472bfa59dc7be5fefde43dbe1083cea7702dbf..b6022e98321babeb590dc44cd68cf009cb3cb7a9 100644 GIT binary patch delta 16 XcmbQsHkXZEzMF%i#WQLnyBIS7B-sQ2 delta 16 XcmbQsHkXZEzMF%i`Ci0Eb}?oEC`JU5 diff --git a/data/preferences.html b/data/preferences.html index d6ba4ce6..deefcb7b 100644 --- a/data/preferences.html +++ b/data/preferences.html @@ -24,7 +24,7 @@ - - + -
+ + + +
@@ -340,7 +339,8 @@

CO2 Gadget Preferences

diff --git a/data/preferences.html.gz b/data/preferences.html.gz index c7b6ac9979b82fabc9961f88c78c054d44cc8054..0bff6b72e542bf31bb209258b3419ba4a45bb6df 100644 GIT binary patch literal 4805 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 literal 4789 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 PfBW%oDuX{NHBtZo$)+oO diff --git a/data/preferences.js.gz b/data/preferences.js.gz index a05641fc0df463492a3baf3b9748b8be395eb75b..39e6ba2048d56f4ba20593ceb046901dc5ffd989 100644 GIT binary patch delta 16 XcmZ1~xm1!}zMF%i#WQLn`#c^1DE0)$ delta 16 XcmZ1~xm1!}zMF%i`Ci0E_IW%2EMo;( diff --git a/data/status.html.gz b/data/status.html.gz index 3ea87da1ee5b38283129211331f28608d1b67a53..d1f6c5224e8b9eb714a96caeb93d9ff3e330a7e1 100644 GIT binary patch delta 16 XcmZn>ZxLsg@8;lW@r>HYUds&tB%K6b delta 16 XcmZn>ZxLsg@8;lWz8A5Py_OpQC<+Ae diff --git a/data/style.css b/data/style.css index 36c97e02..639e1b50 100644 --- a/data/style.css +++ b/data/style.css @@ -15,7 +15,7 @@ --input-background-color: #fff; --button-background-color: #4caf50; --button-hover-background-color: #45a049; - --tag-dark-bg-color: #2c3e50; /* Dark theme tag background color */ + --tag-dark-bg-color: #2c3e50; --popup-bg-color: #333; --popup-text-color: #fff; --tooltip-bg-color: #555; @@ -26,7 +26,6 @@ --close-button-hover-color: darkred; --status-bar-bg-color: #fbef83; --status-bar-text-color: #333; - --navbar-height: 60px; } [theme='dark'] { @@ -57,16 +56,13 @@ --close-button-hover-color: #c0392b; --status-bar-bg-color: #34495e; --status-bar-text-color: #ecf0f1; - --navbar-height: 60px; } -/* Body Styles */ body { font-family: 'Arial', sans-serif; background-color: var(--bg-color); color: var(--font-color); margin: 0; - padding-top: var(--navbar-height); } h1, h2, h3, h4 { @@ -92,21 +88,24 @@ h4 { font-size: 1.25em; } -/* Navigation Bar Styles */ .navbar { - overflow: hidden; - position: fixed; - top: 0; + display: flex; + flex-direction: column; width: 100%; - color: var(--navbar-text-color); background-color: var(--navbar-background-color); - padding: 15px 10px; + padding: 0; border-bottom: 1px solid var(--navbar-border-color); box-shadow: var(--navbar-shadow); z-index: 1000; + position: relative; +} + +.nav-content { display: flex; justify-content: space-between; align-items: center; + width: 100%; + padding: 15px 10px; } .navbar a { @@ -125,13 +124,6 @@ h4 { pointer-events: none; } -.nav-content { - display: flex; - justify-content: space-between; - align-items: center; - width: 100%; -} - .nav-links-left, .nav-links-right { display: flex; @@ -143,19 +135,11 @@ h4 { } .iconDarkLight { - position: absolute; - top: 1.2%; - right: 2%; - background-color: transparent; - transition: transform 0.05s; - z-index: 1000; + margin-left: 10px; + margin-right: 1rem; cursor: pointer; width: 24px; height: 24px; - /* background-image: url('data:image/svg+xml;charset=UTF-8,%3Csvg%20style%3D%22width%3A24px%3Bheight%3A24px%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20fill%3D%22var(--icon-color)%22%20d%3D%22M12%2C2A7%2C7%200%200%2C0%205%2C9C5%2C11.38%206.19%2C13.47%208%2C14.74V17A1%2C1%200%200%2C0%209%2C18H15A1%2C1%200%200%2C0%2016%2C17V14.74C17.81%2C13.47%2019%2C11.38%2019%2C9A7%2C7%200%200%2C0%2012%2C2M9%2C21A1%2C1%200%200%2C0%2010%2C22H14A1%2C1%200%200%2C0%2015%2C21V20H9V21Z%22%20%2F%3E%3C%2Fsvg%3E'); */ - background-repeat: no-repeat; - background-position: center; - background-size: contain; } .iconDarkLight:hover { @@ -166,7 +150,6 @@ h4 { transform: scale(1.5); } -/* Styles for the tag class */ .tag { font-size: 1.2em; color: var(--bg-color); @@ -186,7 +169,6 @@ h4 { background-color: var(--tag-dark-bg-color); } -/* Form Styles */ #preferencesForm { background-color: var(--bg-color); border-radius: 8px; @@ -247,7 +229,7 @@ button { border-radius: 4px; cursor: pointer; font-size: 16px; - margin: 5px; /* Ajuste del margen para un espaciado uniforme */ + margin: 5px; transition: background-color 0.3s ease; } @@ -264,12 +246,12 @@ button:hover { .buttonGroup { display: flex; justify-content: space-between; - flex-wrap: nowrap; /* Mantener los botones en una fila en pantallas anchas */ + flex-wrap: nowrap; } .buttonsBackupRestore, .buttonsRestartSave { display: flex; - gap: 10px; /* Añadir espacio entre los botones */ + gap: 10px; } #backupButton, #restoreButton { @@ -282,21 +264,21 @@ button:hover { @media screen and (max-width: 600px) { .buttonGroup { - display: grid; /* Usar grid layout para pantallas estrechas */ - grid-template-columns: 1fr 1fr; /* Dos columnas de igual ancho */ - gap: 20px; /* Espacio entre columnas y filas */ + display: grid; + grid-template-columns: 1fr 1fr; + gap: 20px; } .buttonsBackupRestore, .buttonsRestartSave { flex-direction: column; width: auto; margin-bottom: 0; - align-items: center; /* Centrar los botones en cada columna */ + align-items: center; } .buttonsBackupRestore button, .buttonsRestartSave button { - width: 100%; /* Asegurar que los botones ocupen todo el ancho de la columna */ - margin-bottom: 10px; /* Mayor separación vertical entre botones */ + width: 100%; + margin-bottom: 10px; } .buttonGroup button { @@ -319,19 +301,16 @@ button:hover { } } - .content { max-width: 600px; margin: 0 auto; - padding-top: var(--navbar-height); /* Add padding to ensure content is not hidden by navbar */ } -/* Circular Chart Styles */ .flex-wrapper { display: flex; flex-flow: row nowrap; justify-content: space-around; - align-items: center; /* Center items vertically */ + align-items: center; } .single-chart { @@ -339,7 +318,7 @@ button:hover { position: relative; display: flex; flex-direction: column; - align-items: center; /* Center items horizontally */ + align-items: center; } .circular-chart { @@ -415,7 +394,6 @@ button:hover { } } -/* Popup Styles */ #popup { display: none; position: fixed; @@ -480,24 +458,19 @@ button:hover { visibility: visible; } -/* Captive Portal Status Bar */ #captive-portal-status-bar { width: 100%; background-color: var(--status-bar-bg-color); color: var(--status-bar-text-color); - position: fixed; - top: 45px; - z-index: 999; + position: relative; + z-index: 1; display: flex; justify-content: space-between; align-items: center; font-size: 0.7em; -} - -@media (max-width: 600px) { - #captive-portal-status-bar { - top: 45px; - } + padding: 5px; + box-sizing: border-box; + overflow: hidden; } #hide-captive-portal-status-bar-button { @@ -506,6 +479,8 @@ button:hover { padding: 5px 10px; font-size: 0.7em; cursor: pointer; + display: flex; + align-items: center; } #hide-captive-portal-status-bar-button svg { @@ -524,7 +499,6 @@ button:hover { display: none !important; } -/* Status Dot Styles */ .status-dot { width: 10px; height: 10px; @@ -542,6 +516,10 @@ button:hover { background-color: white; } +.status-dot-cyan { + background-color: cyan; +} + .status-dot-blue { background-color: blue; } @@ -558,7 +536,6 @@ button:hover { font-weight: bold; } -/* Add a fade animation effect */ @keyframes fadeInOut { 0% { opacity: 0; @@ -583,21 +560,21 @@ button:hover { right: 10px; width: auto; height: auto; - pointer-events: none; + pointer-events: auto; /* Ensure interaction is possible */ font-size: 0.9em; background-color: var(--debug-bg-color); border: 1px solid var(--debug-border-color); border-radius: 10px; padding: 10px; box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1); - display: none; + display: none; /* Default state is hidden */ overflow: auto; z-index: 9998; animation: fadeInOut 2s ease-in-out; } .hidden-debug-window { - display: none; + display: none !important; } #close-debug-window { diff --git a/data/style.css.gz b/data/style.css.gz index 2d4439d0f04ff03d10ddd14f2a387124418f0eef..c8b3db1f035eaba64a211a0750031fa13da0db55 100644 GIT binary patch literal 2412 zcmV-y36u68iwFpWNm^zE0CRMCY-KKOX>KlKb8`UIS#7VAFckhPs4==Y7GB2OSWJA2 z#>7OUiC>H#3Y4wNfV9l1g#Yeo3lv(I({JYH-m&&@dd}1HenVOmRc+g8kymzHWCacH zZ8n>|ZAXXhdzz;3y&_eHyQSR*V~k*x#6{k}hxrdI#)QU-7ARpYN8ckv?Fhx+4zxJu zNzZ+o?oy;ED*U6D#P@x*aV)-L+U+<_u!#nnQ9%>6iy!kJwabnuDK4R7t;-+Q27c)w zLJys#_*uCNpgdv(3?vTf^ln2xAW0Igd|sX_Z6}W7en%-ghB7)=Rgq6@uVa)3PER3K zo}vqov)=JbK?gfQ^xNRJyx7NrM_H8Tl5Z$=x>W_Ty56G5Dl()Gf}mfYdLzNn`Jm_p zq^=(}z=%xrP>%1|SmZhf^o zVNT8G>WEMH$pg;n!57W)ahy7-3k-BPb^CWw6z}5J{>N_{_V2IPyWpw|xT%-;iRl80 zspbV^G3LC$jlHe!-|7XMu@`6pbbB*rn7*Jizv2#lv_=7%^9ZHkpFP6eAZHtx9-+kO zY=7QWOxTtEo9xt<`QD6o_`BuCS-S4yIp0w1H7`(sZ5{jZH5a)TJO0j#bQdwWtKA9t zo2W>B*1`%>bRyZ$@WC@mQ1)QSP|j?IDM|OnC45Kpp>mzYez?kcb?YZY4T$r={Lz|NT91}IzP6H%Rwsm&8TuKf8UC^7f9!-%99N{sLy+Wr z%J&zNRL9VDocl94n$bd2B6Kta+z|qkF<}9({OIDqkg8o{mM9$3~WW*P`t9ygSVqP$f^5LhdpSr{>_jtPYejf~KYw+ltT zLNUjq?#iLv4!|N@FB^Xc{TP?Cg)1ZZH)dxzt(JrDlpKy4geFLh{sI6ZJwfmbUCOPF z=b)Dm^4@Za@jh2yE{ON#8~gZ78Hmj#RyX0Tf%b?wm3Y?pwg?F<(}JEt7NZP5bfJ3E zDO+qz(f~*yK93y-9PLXDfL~)te86>1!8lNzDWtr5{9c7DXNjNOA%!IQ|B5 z_NtVBXk+4Da(Q~ za&h9&Zfg+54A<5SpnGHNY`qiWtbnD~2PW(*p1N z_stT1e?xOJ#h=eK&KaWZ2_2VVdX%sTqf%gOo%`ZjS6K$)>e~rP1hpW^GFjBKiWc9n z2twl#%A(zBIr^(@$3VS3Ch=C=ZhIKn+ zHBZ0cpD9Hr%&d;EcJ9|L&jc|5fr9$H6?GaN9k2<{YDH|{;X|`s3bZ;Y_jQAI9mkJ% zChhTjA_lD=?=TLU)pwMgB_MKwJM7+7*FLc5)nj~W>*YK?LgYS?B*~y@Ip?JMD@Oh# zqb?E_dG>QI9Qr#R4#&>X`$KDv7T@@@&EJqhTK8#9(f7U|WgwJ~>Rf(c->Jyj5mO6z zB{*j|v3AaV3-Ni#{z6H`2MVVm0n5d-BGBsCG?Q=?l)&NA-p-}SAx(2n44XP}h4Csc zP00^PpH)$Y0r(A1D&j%4QsRl{hKDw6Ecu_=8b=&7DD{oK$)5Y;mPw8!maRBChU8 z61XG@f4_*cjFgNp5r|Y$x+zsp$v8|?-XJYVSm27m|6ilzfU8fKGJs$lE^jQD|2$wb z($PP6b0+8}$jz!7c=C3?9v7x+le4P76GkGEk?Lo6BQ5M(IDJkr$zjf7&1vg|*ct#E zt%iVKpwgtI5%91PU?AEe1+4T155A(Jg1+&=q zLwj+a(@)Lh^GrQs4)YgU$#Ub_(&U5$vj=EHO9}cs=TR=Q?vRt9$idcInxv?DJ5}ns z6Mda?e|j)x++?3C#U=EmhdR)fQV(St?~4Fswx4`?Oc?(}6KyJA9g=~d=LvRvbwmd3 z?PSl}5ea*$&332Xms2KvHZ`m```E)v&H|i~hZ3jp0`<*p9*@4c&WN;G$^R@}z~75Y zt(6zU`HFI-K~LD;uz1$y+G1_!WIKGC4qW=bz!v7zWPDx%QfH{-Zc3=( e|2+N}MDEEqyJlA_$(q%axBdn>2bo%2A^-s9XREdV literal 2480 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