diff --git a/src/public/js/ui/alertManagementModal.js b/src/public/js/ui/alertManagementModal.js
index 87216f4b9..8b843cb67 100644
--- a/src/public/js/ui/alertManagementModal.js
+++ b/src/public/js/ui/alertManagementModal.js
@@ -1,12 +1,86 @@
PulseApp.ui = PulseApp.ui || {};
PulseApp.ui.alertManagementModal = (() => {
+ // Constants
+ const TIMEOUTS = {
+ SHORT: 1000,
+ MEDIUM: 2000,
+ LONG: 3000,
+ REFRESH: 2000
+ };
+
+ const VALIDATION = {
+ MIN_DURATION_MS: 5000,
+ MAX_DURATION_MS: 3600000,
+ MIN_THRESHOLD: 1,
+ MAX_THRESHOLD: 100
+ };
+
+ const DEFAULTS = {
+ THRESHOLD_CPU: 85,
+ THRESHOLD_MEMORY: 85,
+ THRESHOLD_DISK: 85,
+ THRESHOLD_TEMPERATURE: 70,
+ THRESHOLD_IOWAIT: 50,
+ SMTP_PORT: 587,
+ SMTP_PORT_STRING: '587'
+ };
+
+ const TIME_UNITS = {
+ SECOND: 1000,
+ MINUTE: 60 * 1000,
+ HOUR: 60 * 60 * 1000,
+ DAY: 24 * 60 * 60 * 1000
+ };
+
let isInitialized = false;
let activeTab = 'alerts';
let currentConfig = {};
let formDataCache = {};
let isLoading = false;
let refreshInterval = null;
+
+ // DOM element cache
+ const domCache = {};
+
+ // Event listener tracking
+ const eventListeners = [];
+
+ function getElement(id) {
+ if (!domCache[id]) {
+ domCache[id] = document.getElementById(id);
+ }
+ return domCache[id];
+ }
+
+ function clearDomCache() {
+ Object.keys(domCache).forEach(key => delete domCache[key]);
+ }
+
+ function addTrackedEventListener(element, event, handler, options) {
+ if (!element) return;
+ element.addEventListener(event, handler, options);
+ eventListeners.push({ element, event, handler, options });
+ }
+
+ function removeAllEventListeners() {
+ eventListeners.forEach(({ element, event, handler, options }) => {
+ if (element) {
+ element.removeEventListener(event, handler, options);
+ }
+ });
+ eventListeners.length = 0;
+ }
+
+ // Common error handling function
+ function handleError(component, error, userMessage) {
+ console.error(`[${component}] ${error.message || error}`);
+ if (userMessage) {
+ PulseApp.ui.toast.error(userMessage);
+ } else {
+ PulseApp.ui.toast.error(`Error in ${component}: ${error.message || 'Unknown error'}`);
+ }
+ }
function init() {
if (isInitialized) return;
@@ -29,7 +103,7 @@ PulseApp.ui.alertManagementModal = (() => {
coordinatedRefresh();
}
} catch (error) {
- console.error('[Alert Modal] Error handling alert event:', error);
+ handleError('Alert Modal', error, null);
}
});
@@ -69,7 +143,7 @@ PulseApp.ui.alertManagementModal = (() => {
if (isModalOpen()) {
coordinatedRefresh();
}
- }, 2000);
+ }, TIMEOUTS.MEDIUM);
isInitialized = true;
}
@@ -117,7 +191,7 @@ PulseApp.ui.alertManagementModal = (() => {
function openModal() {
- const modal = document.getElementById('alert-management-modal');
+ const modal = getElement('alert-management-modal');
if (modal) {
modal.classList.remove('hidden');
modal.classList.add('flex');
@@ -130,7 +204,7 @@ PulseApp.ui.alertManagementModal = (() => {
if (isModalOpen()) {
coordinatedRefresh();
}
- }, 2000);
+ }, TIMEOUTS.MEDIUM);
}
}
}
@@ -152,10 +226,13 @@ PulseApp.ui.alertManagementModal = (() => {
// Reset state
isLoading = false;
+
+ // Remove all tracked event listeners
+ removeAllEventListeners();
}
function closeModal() {
- const modal = document.getElementById('alert-management-modal');
+ const modal = getElement('alert-management-modal');
if (modal) {
modal.classList.add('hidden');
modal.classList.remove('flex');
@@ -163,10 +240,13 @@ PulseApp.ui.alertManagementModal = (() => {
// Clean up resources to prevent memory leaks
cleanup();
+
+ // Clear DOM cache when modal closes
+ clearDomCache();
}
function createModalHTML() {
- const existingModal = document.getElementById('alert-management-modal');
+ const existingModal = getElement('alert-management-modal');
if (existingModal) {
existingModal.remove();
}
@@ -224,21 +304,21 @@ PulseApp.ui.alertManagementModal = (() => {
}
function setupEventListeners() {
- const modal = document.getElementById('alert-management-modal');
- const closeButton = document.getElementById('alert-management-modal-close');
- const cancelButton = document.getElementById('alert-management-cancel-button');
+ const modal = getElement('alert-management-modal');
+ const closeButton = getElement('alert-management-modal-close');
+ const cancelButton = getElement('alert-management-cancel-button');
if (closeButton) {
closeButton.addEventListener('click', closeModal);
}
if (cancelButton) {
- cancelButton.addEventListener('click', closeModal);
+ addTrackedEventListener(cancelButton, 'click', closeModal);
}
// Close modal when clicking outside
if (modal) {
- modal.addEventListener('click', (e) => {
+ addTrackedEventListener(modal, 'click', (e) => {
if (e.target === modal) {
closeModal();
}
@@ -246,11 +326,12 @@ PulseApp.ui.alertManagementModal = (() => {
}
// Handle escape key
- document.addEventListener('keydown', (e) => {
+ const escapeHandler = (e) => {
if (e.key === 'Escape' && modal && !modal.classList.contains('hidden')) {
closeModal();
}
- });
+ };
+ addTrackedEventListener(document, 'keydown', escapeHandler);
// Set up tab navigation
setupTabNavigation();
@@ -329,11 +410,15 @@ PulseApp.ui.alertManagementModal = (() => {
loadEmailConfiguration();
await loadGlobalToggles();
}, 100);
+ }).catch(error => {
+ handleError('Configure Tab', error, 'Failed to load configuration');
});
}
} catch (error) {
console.error('[Alert Modal] Error rendering configure tab:', error);
- modalBody.innerHTML = '
Error loading configure tab: ' + error.message + '
';
+ modalBody.innerHTML = 'Error loading configure tab:
';
+ const errorSpan = modalBody.querySelector('#error-message');
+ if (errorSpan) errorSpan.textContent = error.message;
}
break;
default:
@@ -526,7 +611,7 @@ PulseApp.ui.alertManagementModal = (() => {
-
+
@@ -538,6 +623,33 @@ PulseApp.ui.alertManagementModal = (() => {
+
+
+
+
+
+
Email Provider Setup Guides
+
Most email providers require app-specific passwords for security. Follow these guides to set up your email:
+
+
+
+
+