mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-09-22 19:23:31 +00:00
fix: improve version API error handling and fix notification toggle listeners
- Add robust error handling to version API endpoint with fallback responses - Fix duplicate event listeners on notification toggles by cloning elements - Update toggle configuration keys to GLOBAL_EMAIL_ENABLED/GLOBAL_WEBHOOK_ENABLED - Add debug toggles for troubleshooting notification components - Remove visual feedback animations to prevent UI flashing 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
+26
-6
@@ -734,17 +734,37 @@ app.get('/api/version', async (req, res) => {
|
||||
const packageJson = require('../package.json');
|
||||
const currentVersion = packageJson.version || 'N/A';
|
||||
|
||||
// Use UpdateManager to check for updates respecting user's channel preference
|
||||
const updateInfo = await updateManager.checkForUpdates();
|
||||
let latestVersion = currentVersion;
|
||||
let updateAvailable = false;
|
||||
|
||||
try {
|
||||
// Try to check for updates, but don't fail if it doesn't work
|
||||
const updateInfo = await updateManager.checkForUpdates();
|
||||
latestVersion = updateInfo.latestVersion || currentVersion;
|
||||
updateAvailable = updateInfo.hasUpdate || false;
|
||||
} catch (updateError) {
|
||||
// Log the error but continue with current version info
|
||||
console.error("[Version API] Error checking for updates:", updateError.message);
|
||||
}
|
||||
|
||||
res.json({
|
||||
version: currentVersion,
|
||||
latestVersion: updateInfo.latestVersion,
|
||||
updateAvailable: updateInfo.hasUpdate
|
||||
latestVersion: latestVersion,
|
||||
updateAvailable: updateAvailable
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Error in version endpoint:", error);
|
||||
res.status(500).json({ error: "Could not retrieve version" });
|
||||
console.error("[Version API] Error in version endpoint:", error);
|
||||
// Still try to return current version if possible
|
||||
try {
|
||||
const packageJson = require('../package.json');
|
||||
res.json({
|
||||
version: packageJson.version || 'N/A',
|
||||
latestVersion: packageJson.version || 'N/A',
|
||||
updateAvailable: false
|
||||
});
|
||||
} catch (fallbackError) {
|
||||
res.status(500).json({ error: "Could not retrieve version" });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
// Debug function for notification toggles
|
||||
// Copy and paste this into the browser console when the alert modal is open
|
||||
|
||||
function debugToggles() {
|
||||
console.log('=== Toggle Debug Info ===');
|
||||
|
||||
// Check if modal is open
|
||||
const modal = document.getElementById('alert-management-modal');
|
||||
console.log('Modal found:', !!modal);
|
||||
console.log('Modal visible:', modal && !modal.classList.contains('hidden'));
|
||||
|
||||
// Check active tab
|
||||
const activeTab = document.querySelector('.alert-tab.active');
|
||||
console.log('Active tab:', activeTab ? activeTab.getAttribute('data-tab') : 'none');
|
||||
|
||||
// Check toggle elements
|
||||
const emailToggle = document.getElementById('global-email-toggle');
|
||||
const webhookToggle = document.getElementById('global-webhook-toggle');
|
||||
|
||||
console.log('\n--- Toggle Elements ---');
|
||||
console.log('Email toggle found:', !!emailToggle);
|
||||
if (emailToggle) {
|
||||
console.log('Email toggle checked:', emailToggle.checked);
|
||||
console.log('Email toggle disabled:', emailToggle.disabled);
|
||||
console.log('Email toggle parent:', emailToggle.parentElement);
|
||||
}
|
||||
|
||||
console.log('\nWebhook toggle found:', !!webhookToggle);
|
||||
if (webhookToggle) {
|
||||
console.log('Webhook toggle checked:', webhookToggle.checked);
|
||||
console.log('Webhook toggle disabled:', webhookToggle.disabled);
|
||||
console.log('Webhook toggle parent:', webhookToggle.parentElement);
|
||||
}
|
||||
|
||||
// Check config sections
|
||||
const emailSection = document.getElementById('email-config-section');
|
||||
const webhookSection = document.getElementById('webhook-config-section');
|
||||
|
||||
console.log('\n--- Config Sections ---');
|
||||
console.log('Email section found:', !!emailSection);
|
||||
if (emailSection) {
|
||||
console.log('Email section opacity:', emailSection.style.opacity);
|
||||
console.log('Email section inputs:', emailSection.querySelectorAll('input').length);
|
||||
}
|
||||
|
||||
console.log('\nWebhook section found:', !!webhookSection);
|
||||
if (webhookSection) {
|
||||
console.log('Webhook section opacity:', webhookSection.style.opacity);
|
||||
console.log('Webhook section inputs:', webhookSection.querySelectorAll('input').length);
|
||||
}
|
||||
|
||||
// Check current config
|
||||
console.log('\n--- Current Config ---');
|
||||
if (window.PulseApp && window.PulseApp.ui && window.PulseApp.ui.alertManagementModal) {
|
||||
console.log('PulseApp.ui.alertManagementModal available');
|
||||
}
|
||||
|
||||
// Test toggle click
|
||||
console.log('\n--- Testing Toggle Click ---');
|
||||
if (emailToggle) {
|
||||
console.log('Simulating email toggle click...');
|
||||
const event = new Event('change', { bubbles: true });
|
||||
emailToggle.checked = !emailToggle.checked;
|
||||
emailToggle.dispatchEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
// Run the debug function
|
||||
debugToggles();
|
||||
|
||||
// Additional helper to manually trigger toggle setup
|
||||
function manualSetupToggles() {
|
||||
if (window.PulseApp && window.PulseApp.ui && window.PulseApp.ui.alertManagementModal) {
|
||||
// Try to access the setupNotificationToggles function if it's exposed
|
||||
console.log('Attempting manual toggle setup...');
|
||||
|
||||
// Manually recreate the setup logic
|
||||
const emailToggle = document.getElementById('global-email-toggle');
|
||||
const webhookToggle = document.getElementById('global-webhook-toggle');
|
||||
|
||||
if (emailToggle) {
|
||||
emailToggle.addEventListener('change', (e) => {
|
||||
console.log('[Manual] Email toggle changed to:', e.target.checked);
|
||||
});
|
||||
}
|
||||
|
||||
if (webhookToggle) {
|
||||
webhookToggle.addEventListener('change', (e) => {
|
||||
console.log('[Manual] Webhook toggle changed to:', e.target.checked);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -165,7 +165,13 @@ PulseApp.ui.alertManagementModal = (() => {
|
||||
openAlertRuleModal,
|
||||
editAlertRule,
|
||||
toggleAlertRule,
|
||||
deleteAlertRule
|
||||
deleteAlertRule,
|
||||
// Debug functions
|
||||
debugToggles: () => {
|
||||
console.log('Email toggle:', document.getElementById('global-email-toggle'));
|
||||
console.log('Webhook toggle:', document.getElementById('global-webhook-toggle'));
|
||||
setupNotificationToggles();
|
||||
}
|
||||
};
|
||||
|
||||
Object.entries(functions).forEach(([name, func]) => {
|
||||
@@ -574,20 +580,20 @@ PulseApp.ui.alertManagementModal = (() => {
|
||||
<p class="text-sm text-gray-500 dark:text-gray-400 mt-1">Master switches for all alert notifications</p>
|
||||
</div>
|
||||
<div class="flex flex-wrap items-center gap-6">
|
||||
<label class="flex items-center gap-3">
|
||||
<div class="flex items-center gap-3">
|
||||
<span class="text-sm text-gray-700 dark:text-gray-300">Email Notifications</span>
|
||||
<label class="relative inline-flex items-center cursor-pointer">
|
||||
<input type="checkbox" id="global-email-toggle" class="sr-only peer">
|
||||
<div class="w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-300 dark:peer-focus:ring-blue-800 rounded-full peer dark:bg-gray-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-blue-600"></div>
|
||||
<label for="global-email-toggle" class="relative inline-flex items-center cursor-pointer focus:outline-none">
|
||||
<input type="checkbox" id="global-email-toggle" class="sr-only peer focus:outline-none">
|
||||
<div class="w-11 h-6 bg-gray-200 peer-focus:outline-none rounded-full peer dark:bg-gray-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-blue-600 focus:outline-none"></div>
|
||||
</label>
|
||||
</label>
|
||||
<label class="flex items-center gap-3">
|
||||
</div>
|
||||
<div class="flex items-center gap-3">
|
||||
<span class="text-sm text-gray-700 dark:text-gray-300">Webhook Notifications</span>
|
||||
<label class="relative inline-flex items-center cursor-pointer">
|
||||
<input type="checkbox" id="global-webhook-toggle" class="sr-only peer">
|
||||
<div class="w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-300 dark:peer-focus:ring-blue-800 rounded-full peer dark:bg-gray-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-blue-600"></div>
|
||||
<label for="global-webhook-toggle" class="relative inline-flex items-center cursor-pointer focus:outline-none">
|
||||
<input type="checkbox" id="global-webhook-toggle" class="sr-only peer focus:outline-none">
|
||||
<div class="w-11 h-6 bg-gray-200 peer-focus:outline-none rounded-full peer dark:bg-gray-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-blue-600 focus:outline-none"></div>
|
||||
</label>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -721,8 +727,10 @@ PulseApp.ui.alertManagementModal = (() => {
|
||||
// Load all alert rules (unified)
|
||||
loadAllAlertRules();
|
||||
|
||||
// Set up event listeners for notifications
|
||||
setupNotificationToggles();
|
||||
// Set up event listeners for notifications with a small delay to ensure DOM is ready
|
||||
setTimeout(() => {
|
||||
setupNotificationToggles();
|
||||
}, 10);
|
||||
// setupEmailTestButton(); // Redundant - handled in initializeNotificationsTab
|
||||
|
||||
// Create rule button now uses onclick attribute directly
|
||||
@@ -1276,8 +1284,13 @@ PulseApp.ui.alertManagementModal = (() => {
|
||||
const emailToggle = document.getElementById('global-email-toggle');
|
||||
const webhookToggle = document.getElementById('global-webhook-toggle');
|
||||
|
||||
|
||||
if (emailToggle) {
|
||||
emailToggle.addEventListener('change', async (e) => {
|
||||
// Remove any existing listeners first
|
||||
const newEmailToggle = emailToggle.cloneNode(true);
|
||||
emailToggle.parentNode.replaceChild(newEmailToggle, emailToggle);
|
||||
|
||||
newEmailToggle.addEventListener('change', async (e) => {
|
||||
try {
|
||||
await handleGlobalEmailToggle(e.target.checked);
|
||||
} catch (error) {
|
||||
@@ -1287,7 +1300,11 @@ PulseApp.ui.alertManagementModal = (() => {
|
||||
}
|
||||
|
||||
if (webhookToggle) {
|
||||
webhookToggle.addEventListener('change', async (e) => {
|
||||
// Remove any existing listeners first
|
||||
const newWebhookToggle = webhookToggle.cloneNode(true);
|
||||
webhookToggle.parentNode.replaceChild(newWebhookToggle, webhookToggle);
|
||||
|
||||
newWebhookToggle.addEventListener('change', async (e) => {
|
||||
try {
|
||||
await handleGlobalWebhookToggle(e.target.checked);
|
||||
} catch (error) {
|
||||
@@ -1302,7 +1319,7 @@ PulseApp.ui.alertManagementModal = (() => {
|
||||
const response = await fetch('/api/config', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ ALERT_EMAIL_ENABLED: enabled ? 'true' : 'false' })
|
||||
body: JSON.stringify({ GLOBAL_EMAIL_ENABLED: enabled ? 'true' : 'false' })
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
@@ -1311,17 +1328,20 @@ PulseApp.ui.alertManagementModal = (() => {
|
||||
|
||||
// Update currentConfig
|
||||
if (currentConfig) {
|
||||
currentConfig.ALERT_EMAIL_ENABLED = enabled ? 'true' : 'false';
|
||||
currentConfig.GLOBAL_EMAIL_ENABLED = enabled ? 'true' : 'false';
|
||||
}
|
||||
|
||||
// Show visual feedback
|
||||
const toggleEl = document.getElementById('global-email-toggle');
|
||||
if (toggleEl) {
|
||||
// Briefly flash the toggle to indicate success
|
||||
const parent = toggleEl.parentElement;
|
||||
parent.classList.add('ring-2', 'ring-green-500');
|
||||
setTimeout(() => parent.classList.remove('ring-2', 'ring-green-500'), 1000);
|
||||
}
|
||||
// Update visibility of email configuration section
|
||||
updateEmailConfigVisibility(enabled);
|
||||
|
||||
// Visual feedback disabled - remove this comment block to re-enable
|
||||
// const toggleEl = document.getElementById('global-email-toggle');
|
||||
// if (toggleEl) {
|
||||
// // Briefly flash the toggle to indicate success
|
||||
// const parent = toggleEl.parentElement;
|
||||
// parent.classList.add('ring-2', 'ring-green-500');
|
||||
// setTimeout(() => parent.classList.remove('ring-2', 'ring-green-500'), 1000);
|
||||
// }
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error updating email toggle:', error);
|
||||
@@ -1339,7 +1359,7 @@ PulseApp.ui.alertManagementModal = (() => {
|
||||
const response = await fetch('/api/config', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ ALERT_WEBHOOK_ENABLED: enabled ? 'true' : 'false' })
|
||||
body: JSON.stringify({ GLOBAL_WEBHOOK_ENABLED: enabled ? 'true' : 'false' })
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
@@ -1348,17 +1368,20 @@ PulseApp.ui.alertManagementModal = (() => {
|
||||
|
||||
// Update currentConfig
|
||||
if (currentConfig) {
|
||||
currentConfig.ALERT_WEBHOOK_ENABLED = enabled ? 'true' : 'false';
|
||||
currentConfig.GLOBAL_WEBHOOK_ENABLED = enabled ? 'true' : 'false';
|
||||
}
|
||||
|
||||
// Show visual feedback
|
||||
const toggleEl = document.getElementById('global-webhook-toggle');
|
||||
if (toggleEl) {
|
||||
// Briefly flash the toggle to indicate success
|
||||
const parent = toggleEl.parentElement;
|
||||
parent.classList.add('ring-2', 'ring-green-500');
|
||||
setTimeout(() => parent.classList.remove('ring-2', 'ring-green-500'), 1000);
|
||||
}
|
||||
// Update visibility of webhook configuration section
|
||||
updateWebhookConfigVisibility(enabled);
|
||||
|
||||
// Visual feedback disabled - remove this comment block to re-enable
|
||||
// const toggleEl = document.getElementById('global-webhook-toggle');
|
||||
// if (toggleEl) {
|
||||
// // Briefly flash the toggle to indicate success
|
||||
// const parent = toggleEl.parentElement;
|
||||
// parent.classList.add('ring-2', 'ring-green-500');
|
||||
// setTimeout(() => parent.classList.remove('ring-2', 'ring-green-500'), 1000);
|
||||
// }
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error updating webhook toggle:', error);
|
||||
@@ -1389,6 +1412,7 @@ PulseApp.ui.alertManagementModal = (() => {
|
||||
inputs.forEach(input => {
|
||||
input.disabled = !enabled;
|
||||
});
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1401,6 +1425,7 @@ PulseApp.ui.alertManagementModal = (() => {
|
||||
inputs.forEach(input => {
|
||||
input.disabled = !enabled;
|
||||
});
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1420,14 +1445,14 @@ PulseApp.ui.alertManagementModal = (() => {
|
||||
// });
|
||||
|
||||
if (emailToggle && currentConfig) {
|
||||
const emailEnabled = currentConfig.ALERT_EMAIL_ENABLED === 'true';
|
||||
const emailEnabled = currentConfig.GLOBAL_EMAIL_ENABLED === 'true';
|
||||
// console.log('[Global Toggles] Setting email toggle to:', emailEnabled);
|
||||
emailToggle.checked = emailEnabled;
|
||||
updateEmailConfigVisibility(emailEnabled);
|
||||
}
|
||||
|
||||
if (webhookToggle && currentConfig) {
|
||||
const webhookEnabled = currentConfig.ALERT_WEBHOOK_ENABLED === 'true';
|
||||
const webhookEnabled = currentConfig.GLOBAL_WEBHOOK_ENABLED === 'true';
|
||||
// console.log('[Global Toggles] Setting webhook toggle to:', webhookEnabled);
|
||||
webhookToggle.checked = webhookEnabled;
|
||||
updateWebhookConfigVisibility(webhookEnabled);
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Toggle Debug Test</title>
|
||||
<script>
|
||||
// Test function to debug toggle behavior
|
||||
function debugToggles() {
|
||||
console.log('=== Toggle Debug Info ===');
|
||||
|
||||
// Check for email toggle
|
||||
const emailToggle = document.getElementById('global-email-toggle');
|
||||
console.log('Email toggle found:', !!emailToggle);
|
||||
if (emailToggle) {
|
||||
console.log('Email toggle checked:', emailToggle.checked);
|
||||
console.log('Email toggle disabled:', emailToggle.disabled);
|
||||
}
|
||||
|
||||
// Check for webhook toggle
|
||||
const webhookToggle = document.getElementById('global-webhook-toggle');
|
||||
console.log('Webhook toggle found:', !!webhookToggle);
|
||||
if (webhookToggle) {
|
||||
console.log('Webhook toggle checked:', webhookToggle.checked);
|
||||
console.log('Webhook toggle disabled:', webhookToggle.disabled);
|
||||
}
|
||||
|
||||
// Check for config sections
|
||||
const emailSection = document.getElementById('email-config-section');
|
||||
console.log('Email config section found:', !!emailSection);
|
||||
if (emailSection) {
|
||||
console.log('Email section opacity:', emailSection.style.opacity);
|
||||
}
|
||||
|
||||
const webhookSection = document.getElementById('webhook-config-section');
|
||||
console.log('Webhook config section found:', !!webhookSection);
|
||||
if (webhookSection) {
|
||||
console.log('Webhook section opacity:', webhookSection.style.opacity);
|
||||
}
|
||||
|
||||
// Check if functions exist
|
||||
console.log('updateEmailConfigVisibility exists:', typeof updateEmailConfigVisibility === 'function');
|
||||
console.log('updateWebhookConfigVisibility exists:', typeof updateWebhookConfigVisibility === 'function');
|
||||
|
||||
console.log('=== End Debug Info ===');
|
||||
}
|
||||
|
||||
// Add this to the browser console
|
||||
window.debugToggles = debugToggles;
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Toggle Debug Test</h1>
|
||||
<p>Open the browser console and run: <code>debugToggles()</code></p>
|
||||
<p>Or add this to the alertManagementModal.js temporarily to debug</p>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user