From 7e4c3a096355e6d10be85d080bf03c7d5a499a2b Mon Sep 17 00:00:00 2001 From: Sami Date: Sun, 17 May 2026 02:34:51 -0700 Subject: [PATCH] fix(frontend): container-logs misuse of wireModal blocked rest of features.js MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit container-logs.js called `wireModal(modal, null, closeModal)` — passing the local `closeModal()` function as a third arg where wireModal expects button elements. wireModal then did `closeModal.addEventListener('click',...)`, threw TypeError, and because each module's IIFE is a top-level statement in the concatenated features.js bundle, every IIFE *after* container-logs silently skipped: snapshot, smart-arr-connect, notification-settings, panel-tabs, backup-restore, resource-monitor, health-check, update- management, docker-resources, compose-import, container-exec, audit-log, weather, clock, card-badges, theme-builder, and license. Symptoms: "Customize Theme" did nothing on click, license badge stuck at "FREE TIER" (because license.js never ran), no weather, etc. - container-logs.js: drop the wireModal call, wire backdrop click directly to the local closeModal so the SSE log stream actually stops on close. - globals.js: harden wireModal — skip any closeBtn that isn't a real EventTarget. One typo upstream shouldn't take down the rest of features.js init silently. --- status/js/container-logs.js | 6 ++++-- status/js/globals.js | 10 +++++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/status/js/container-logs.js b/status/js/container-logs.js index 88bac91..7abe28a 100644 --- a/status/js/container-logs.js +++ b/status/js/container-logs.js @@ -398,8 +398,10 @@ } }); - // Wire modal (close on backdrop click) - wireModal(modal, null, closeModal); + // Wire backdrop click to closeModal so the log stream stops too. + // (Can't use wireModal here — it only does modal.classList.remove('show') + // on backdrop click, which would leak the SSE/stream connection.) + modal.addEventListener('click', (e) => { if (e.target === modal) closeModal(); }); // Expose for use by service card buttons (grid.js calls openContainerLogsModal) window.openContainerLogsModal = function(containerId, containerName) { diff --git a/status/js/globals.js b/status/js/globals.js index 31d4642..1e0a72e 100644 --- a/status/js/globals.js +++ b/status/js/globals.js @@ -293,7 +293,15 @@ function closeModal(id) { function wireModal(modal, ...closeBtns) { if (!modal) return; modal.addEventListener('click', (e) => { if (e.target === modal) modal.classList.remove('show'); }); - closeBtns.forEach(btn => btn?.addEventListener('click', () => modal.classList.remove('show'))); + // Skip anything that isn't a real listener target. Without this guard, a + // single typo (e.g. passing a function or null instead of a button element) + // throws and aborts the rest of the calling module's init — which can take + // down license.js (FREE TIER badge), TOTP wiring, etc. + closeBtns.forEach(btn => { + if (btn && typeof btn.addEventListener === 'function') { + btn.addEventListener('click', () => modal.classList.remove('show')); + } + }); } /** Toast-style notification (replaces all alert() usage) */