From d1a13da8b01b4d54bfada5c9f0def209ca5c1433 Mon Sep 17 00:00:00 2001 From: Michael Reber Date: Sun, 15 Feb 2026 23:57:01 +0100 Subject: [PATCH] Reorganize console.js file --- pkg/web/static/js/console.js | 133 ++++++++++++++++------------------- 1 file changed, 61 insertions(+), 72 deletions(-) diff --git a/pkg/web/static/js/console.js b/pkg/web/static/js/console.js index e414df9..d7b3edd 100644 --- a/pkg/web/static/js/console.js +++ b/pkg/web/static/js/console.js @@ -1,26 +1,33 @@ -// Console Output Handler for Fail2ban UI +// Console output handler (websocket log stream and rendering). "use strict"; +// ========================================================================= +// Global Variables +// ========================================================================= + let consoleOutputContainer = null; let consoleOutputElement = null; -let maxConsoleLines = 1000; // Maximum number of lines to keep in console -let wasConsoleEnabledOnLoad = false; // Track if console was enabled when page loaded +let maxConsoleLines = 1000; +let wasConsoleEnabledOnLoad = false; +// ========================================================================= +// Initialization +// ========================================================================= + +// Initialize the console output container and connect to the websocket function initConsoleOutput() { consoleOutputContainer = document.getElementById('consoleOutputContainer'); consoleOutputElement = document.getElementById('consoleOutputWindow'); - + if (!consoleOutputContainer || !consoleOutputElement) { return; } - - // Register WebSocket callback for console logs if (typeof wsManager !== 'undefined' && wsManager) { wsManager.onConsoleLog(function(message, timestamp) { appendConsoleLog(message, timestamp); }); } else { - // Wait for WebSocket manager to be available + // Wait for websocket manager to be available const wsCheckInterval = setInterval(function() { if (typeof wsManager !== 'undefined' && wsManager) { wsManager.onConsoleLog(function(message, timestamp) { @@ -29,35 +36,32 @@ function initConsoleOutput() { clearInterval(wsCheckInterval); } }, 100); - - // Stop checking after 5 seconds + // Timeout after 5 seconds if websocket manager is not available setTimeout(function() { clearInterval(wsCheckInterval); }, 5000); } } +// Toggle the console output container function toggleConsoleOutput(userClicked) { const checkbox = document.getElementById('consoleOutput'); const container = document.getElementById('consoleOutputContainer'); - + if (!checkbox || !container) { return; } - + if (checkbox.checked) { + // Show the console output container container.classList.remove('hidden'); - // Initialize console if not already done if (!consoleOutputElement) { initConsoleOutput(); } else { - // Re-register WebSocket callback in case it wasn't registered before if (typeof wsManager !== 'undefined' && wsManager) { - // Remove any existing callbacks and re-register if (!wsManager.consoleLogCallbacks) { wsManager.consoleLogCallbacks = []; } - // Check if callback already exists let callbackExists = false; for (let i = 0; i < wsManager.consoleLogCallbacks.length; i++) { if (wsManager.consoleLogCallbacks[i].toString().includes('appendConsoleLog')) { @@ -72,17 +76,14 @@ function toggleConsoleOutput(userClicked) { } } } - - // Show save hint only if user just clicked to enable (not on page load) + const consoleEl = document.getElementById('consoleOutputWindow'); + // Show save hint only if user just clicked to enable (not on page load) if (consoleEl && userClicked && !wasConsoleEnabledOnLoad) { - // Clear initial placeholder message const placeholder = consoleEl.querySelector('.text-gray-500'); if (placeholder && placeholder.textContent === 'Console output will appear here...') { placeholder.remove(); } - - // Show save hint message const hintDiv = document.createElement('div'); hintDiv.className = 'text-yellow-400 italic text-center py-4'; hintDiv.id = 'consoleSaveHint'; @@ -90,59 +91,76 @@ function toggleConsoleOutput(userClicked) { hintDiv.textContent = hintText; consoleEl.appendChild(hintDiv); } else if (consoleEl) { - // Just clear initial placeholder if it exists const placeholder = consoleEl.querySelector('.text-gray-500'); + // Remove placeholder if it exists if (placeholder && placeholder.textContent === 'Console output will appear here...') { placeholder.remove(); } } } else { + // Hide the console output container container.classList.add('hidden'); } } +// Auto-start console if enabled on load +if (typeof window !== 'undefined') { + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', function() { + const checkbox = document.getElementById('consoleOutput'); + if (checkbox && checkbox.checked) { + wasConsoleEnabledOnLoad = true; + toggleConsoleOutput(false); + } + initConsoleOutput(); + }); + } else { + const checkbox = document.getElementById('consoleOutput'); + if (checkbox && checkbox.checked) { + wasConsoleEnabledOnLoad = true; + toggleConsoleOutput(false); + } + initConsoleOutput(); + } +} + +// ========================================================================= +// Log Rendering / Core Functionality +// ========================================================================= + function appendConsoleLog(message, timestamp) { if (!consoleOutputElement) { consoleOutputElement = document.getElementById('consoleOutputWindow'); } - if (!consoleOutputElement) { return; } - - // Remove initial placeholder message + // Remove placeholder if it exists const placeholder = consoleOutputElement.querySelector('.text-gray-500'); if (placeholder && placeholder.textContent === 'Console output will appear here...') { placeholder.remove(); } - - // Remove save hint when first log arrives + // Remove save hint if it exists const saveHint = document.getElementById('consoleSaveHint'); if (saveHint) { saveHint.remove(); } - - // Create log line + // Create new log line element with timestamp const logLine = document.createElement('div'); logLine.className = 'text-green-400 leading-relaxed'; - - // Format timestamp if provided let timeStr = ''; if (timestamp) { try { const date = new Date(timestamp); timeStr = '[' + date.toLocaleTimeString() + '] '; - } catch (e) { - // Ignore timestamp parsing errors - } + } catch (e) {} } - - // Escape HTML to prevent XSS (but preserve timestamp HTML) + + // Escape message to prevent XSS let escapedMessage = message; if (typeof escapeHtml === 'function') { escapedMessage = escapeHtml(escapedMessage); } else { - // Fallback HTML escaping escapedMessage = escapedMessage .replace(/&/g, '&') .replace(/ maxConsoleLines) { consoleOutputElement.removeChild(lines[0]); } - - // Auto-scroll to bottom consoleOutputElement.scrollTop = consoleOutputElement.scrollHeight; } +// Clear the console function clearConsole() { if (!consoleOutputElement) { consoleOutputElement = document.getElementById('consoleOutputWindow'); } - if (consoleOutputElement) { consoleOutputElement.textContent = ''; - // Note: wasConsoleEnabledOnLoad remains true, so hint won't show again after clear - } -} - -// Initialize on page load -if (typeof window !== 'undefined') { - if (document.readyState === 'loading') { - document.addEventListener('DOMContentLoaded', function() { - // Check if console output is already enabled on page load - const checkbox = document.getElementById('consoleOutput'); - if (checkbox && checkbox.checked) { - wasConsoleEnabledOnLoad = true; // Mark that it was enabled on load - toggleConsoleOutput(false); // false = not a user click - } - initConsoleOutput(); - }); - } else { - // Check if console output is already enabled on page load - const checkbox = document.getElementById('consoleOutput'); - if (checkbox && checkbox.checked) { - wasConsoleEnabledOnLoad = true; // Mark that it was enabled on load - toggleConsoleOutput(false); // false = not a user click - } - initConsoleOutput(); } }