fix: route all console.error through ErrorHandler for consistent tracking

Converted 35+ raw console.error calls to use ErrorHandler.logError() across
12 files. ErrorHandler provides structured logging, local error storage,
and error tracking integration.

Files:
- app-selector.js: 4 errors (fetch templates, port check, suggested port, deploy)
- globals.js: 2 errors (CSRF token get/add)
- service-credentials.js: 2 errors (save/clear credentials)
- totp-settings.js: 4 errors (TOTP setup, session duration, disable, AuthCard)
- notification-settings.js: 2 errors (load config, load history)
- setup-wizard.js: 2 errors (save config to server)
- progress-tracker.js: 4 errors (storage read/write/session/fallback)
- tooltip-definitions.js: 2 errors (validation, condition eval)
- tour-manager.js: 2 errors (Driver.js not loaded, tooltip not found)
- theme-adapter.js: 1 error (theme change callback)
- weather.js: 1 error (weather update)
- onboarding.js: removed duplicate console.error, fixed 2 remaining calls

All console.error calls in the DashCaddy frontend now go through ErrorHandler.
This commit is contained in:
Krystie
2026-05-14 01:31:55 -07:00
parent 5d404f5733
commit f60a3370db
12 changed files with 48 additions and 32 deletions
+5 -4
View File
@@ -1,5 +1,6 @@
// App Selector System
(function () {
const errorHandler = new ErrorHandler();
injectModal('app-selector-modal', `<div id="app-selector-modal" class="weather-modal">
<div class="app-selector-content">
<h2 style="margin: 0 0 24px; color: var(--fg); text-align: center;">Choose an App</h2>
@@ -230,7 +231,7 @@
return true;
}
} catch (e) {
console.error('Failed to fetch app templates:', e);
errorHandler.logError('[AppSelector] Fetch Templates', e, { function: 'fetchApiTemplates' });
}
return false;
}
@@ -242,7 +243,7 @@
const data = await response.json();
return data;
} catch (e) {
console.error('Failed to check port:', e);
errorHandler.logError('[AppSelector] Check Port', e, { function: 'checkPortAvailability' });
return { available: true }; // Assume available on error
}
}
@@ -256,7 +257,7 @@
return data.suggestedPort;
}
} catch (e) {
console.error('Failed to get suggested port:', e);
errorHandler.logError('[AppSelector] Get Suggested Port', e, { function: 'getSuggestedPort' });
}
return basePort;
}
@@ -842,7 +843,7 @@
throw new Error(result.error || 'Deployment failed');
}
} catch (error) {
console.error('Deployment error:', error);
errorHandler.logError('[AppSelector] Deployment', error, { function: 'deploy' });
showNotification(
`Failed to deploy ${appTemplate.name}: ${error.message}`,
'error',
+5 -2
View File
@@ -24,6 +24,9 @@ const DC = {
},
};
// Error handler for tracking issues
const errorHandler = new ErrorHandler();
// ===== GLOBAL SITE CONFIG (loaded from server, cached in localStorage) =====
// Only non-sensitive display preferences are cached; DNS IPs/topology are fetched from API
const _cachedCfg = JSON.parse(localStorage.getItem('dashcaddy_site_config') || 'null');
@@ -160,7 +163,7 @@ async function getCSRFToken() {
csrfToken = data.token;
return csrfToken;
} catch (error) {
console.error('Failed to get CSRF token:', error);
errorHandler.logError('[CSRF] Get Token', error, { function: 'getCSRFToken' });
throw error;
}
}
@@ -185,7 +188,7 @@ async function secureFetch(url, options = {}) {
'X-CSRF-Token': token
};
} catch (error) {
console.error('Failed to add CSRF token to request:', error);
errorHandler.logError('[CSRF] Add to Request', error, { function: 'secureFetch' });
}
}
+3 -2
View File
@@ -1,5 +1,6 @@
// ========== NOTIFICATION SETTINGS ==========
(function() {
const errorHandler = new ErrorHandler();
// Inject modal HTML
injectModal('notifications-modal', `<div id="notifications-modal" class="weather-modal">
<div class="weather-modal-content" style="min-width: 550px; max-width: 650px;">
@@ -255,7 +256,7 @@
document.getElementById('event-deploy-failed').checked = config.events?.deploymentFailed !== false;
}
} catch (error) {
console.error('Failed to load notification config:', error);
errorHandler.logError('[Notifications] Load Config', error, { function: 'loadConfig' });
}
}
@@ -289,7 +290,7 @@
container.innerHTML = '<div style="color: var(--muted); text-align: center; padding: 20px;">No notifications yet</div>';
}
} catch (error) {
console.error('Failed to load notification history:', error);
errorHandler.logError('[Notifications] Load History', error, { function: 'loadHistory' });
}
}
+4 -6
View File
@@ -89,11 +89,8 @@
debug('[Onboarding] System initialized successfully');
} catch (error) {
console.error('[Onboarding] Initialization error:', error);
// Use error handler if available
if (errorHandler) {
errorHandler.logError('Initialization', error);
errorHandler.logError('[Onboarding] Initialization', error);
}
// Graceful degradation - don't break the dashboard
@@ -113,7 +110,9 @@
debug('[Onboarding] Starting tour via button click');
tourManager.restartTour();
} else {
console.error('[Onboarding] Tour manager not initialized');
if (errorHandler) {
errorHandler.logError('[Onboarding] Tour Manager Not Initialized', new Error('Tour manager not initialized'));
}
alert('Tour is not available. Check browser console for errors.\n\nPossible issues:\n- Driver.js library failed to load\n- JavaScript errors during initialization');
}
};
@@ -163,7 +162,6 @@
setTimeout(attemptInit, 500);
} else {
// Max retries reached, show fallback
console.error('[Onboarding] Driver.js failed to load after multiple attempts');
if (errorHandler) {
errorHandler.handleDriverLoadFailure();
} else {
+6 -4
View File
@@ -18,6 +18,8 @@
(function(window) {
'use strict';
const errorHandler = new ErrorHandler();
const debug = (...args) => {
if (window.DASHCADDY_DEBUG) { console.log(...args); }
};
@@ -72,7 +74,7 @@
const data = localStorage.getItem(this.storageKey);
return data ? JSON.parse(data) : null;
} catch (error) {
console.error('[ProgressTracker] Error reading from storage:', error);
errorHandler.logError('[ProgressTracker] Read Storage', error, { function: '_getStorage' });
return null;
}
}
@@ -86,7 +88,7 @@
try {
localStorage.setItem(this.storageKey, JSON.stringify(state));
} catch (error) {
console.error('[ProgressTracker] Error writing to storage:', error);
errorHandler.logError('[ProgressTracker] Write Storage', error, { function: '_setStorage' });
// Handle quota exceeded or storage unavailable
// Fall back to session storage or in-memory storage
this._handleStorageError(error);
@@ -104,7 +106,7 @@
sessionStorage.setItem(this.storageKey, JSON.stringify(this._getStorage()));
console.warn('[ProgressTracker] Falling back to session storage');
} catch (sessionError) {
console.error('[ProgressTracker] Session storage also unavailable:', sessionError);
errorHandler.logError('[ProgressTracker] Session Storage Unavailable', sessionError, { function: '_handleStorageError' });
// Could implement in-memory fallback here if needed
}
}
@@ -190,7 +192,7 @@
body: JSON.stringify({ onboardingCompleted: true })
});
} catch (error) {
console.error('[ProgressTracker] Failed to persist install onboarding state:', error);
errorHandler.logError('[ProgressTracker] Persist Install Onboarding', error, { function: 'markInstallOnboardingCompleted' });
}
}
+3 -2
View File
@@ -1,5 +1,6 @@
// ===== SERVICE CREDENTIALS =====
(function() {
const errorHandler = new ErrorHandler();
injectModal('folder-browser-modal', `<div id="folder-browser-modal" class="weather-modal">
<div class="weather-modal-content" style="min-width: 500px; max-width: 700px; max-height: 80vh;">
<h3>📂 Browse for Media Folders</h3>
@@ -433,7 +434,7 @@
await loadServiceCreds(currentService);
} catch (e) {
console.error('Failed to save credentials:', e);
errorHandler.logError('[ServiceCredentials] Save', e, { function: 'saveCredentials' });
showError('Failed to save: ' + (e.message || 'Unknown error'));
}
saveBtn.textContent = 'Save';
@@ -460,7 +461,7 @@
if (btn) btn.classList.remove('has-creds');
await loadServiceCreds(currentService);
} catch (e) {
console.error('Failed to clear credentials:', e);
errorHandler.logError('[ServiceCredentials] Clear', e, { function: 'clearCredentials' });
showError('Failed to clear: ' + (e.message || 'Unknown error'));
}
});
+4 -2
View File
@@ -1,4 +1,6 @@
// Shared timezone utility — used by setup wizard and settings modal
const errorHandler = new ErrorHandler();
window.populateTimezoneSelect = function(selectEl, selectedTz) {
const timezones = Intl.supportedValuesOf('timeZone');
const detected = selectedTz || Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC';
@@ -150,11 +152,11 @@ window.populateTimezoneSelect = function(selectEl, selectedTz) {
await response.json();
return true;
} else {
console.error('Failed to save config to server:', response.status);
errorHandler.logError('[SetupWizard] Save Config', new Error(`Server returned ${response.status}`), { function: 'saveConfigToServer' });
return false;
}
} catch (error) {
console.error('Error saving config to server:', error);
errorHandler.logError('[SetupWizard] Save Config', error, { function: 'saveConfigToServer' });
return false;
}
}
+3 -1
View File
@@ -7,6 +7,8 @@
(function(window) {
'use strict';
const errorHandler = new ErrorHandler();
const debug = (...args) => {
if (window.DASHCADDY_DEBUG) { console.log(...args); }
};
@@ -190,7 +192,7 @@
try {
callback(newTheme, oldTheme);
} catch (error) {
console.error('[ThemeAdapter] Error in theme change callback:', error);
errorHandler.logError('[ThemeAdapter] Theme Change Callback', error, { function: '_notifyThemeChange' });
}
});
}
+4 -2
View File
@@ -6,6 +6,8 @@
(function(window) {
'use strict';
const errorHandler = new ErrorHandler();
const debug = (...args) => {
if (window.DASHCADDY_DEBUG) { console.log(...args); }
};
@@ -151,7 +153,7 @@
`${e.tooltip}: ${e.errors.join(', ')}`
).join('\n');
console.error('[TooltipDefinitions] Validation errors:', errorMessages);
errorHandler.logError('[TooltipDefinitions] Validation', errorMessages, { function: 'validateTooltip' });
throw new TooltipError(`Tooltip validation failed:\n${errorMessages}`);
}
}
@@ -493,7 +495,7 @@ function getActiveTooltips() {
try {
return tooltip.condition();
} catch (error) {
console.error(`[TooltipDefinitions] Error evaluating condition for ${tooltip.id}:`, error);
errorHandler.logError('[TooltipDefinitions] Condition Eval', error, { function: 'evaluateCondition', tooltipId: tooltip.id });
return false;
}
}
+5 -4
View File
@@ -1,5 +1,6 @@
// ===== TOTP SETTINGS =====
(function() {
const errorHandler = new ErrorHandler();
injectModal('totp-settings-modal', `<div id="totp-settings-modal" class="weather-modal">
<div class="weather-modal-content" style="min-width: 420px; max-width: 520px;">
<h3 style="margin: 0 0 16px; font-size: 1.1rem;">Authentication Settings</h3>
@@ -185,7 +186,7 @@
document.getElementById('totp-setup-code').focus();
}
} catch (e) {
console.error('TOTP setup failed:', e);
errorHandler.logError('[TOTP] Setup Failed', e, { function: 'setupTOTP' });
}
});
@@ -274,7 +275,7 @@
});
loadTotpSettings(); // Refresh modal + card (handles "never" disabling TOTP)
} catch (err) {
console.error('Failed to update session duration:', err);
errorHandler.logError('[TOTP] Update Session Duration', err, { function: 'updateSessionDuration' });
}
});
@@ -290,7 +291,7 @@
const data = await res.json();
if (data.success) loadTotpSettings();
} catch (e) {
console.error('Failed to disable TOTP:', e);
errorHandler.logError('[TOTP] Disable Failed', e, { function: 'disableTOTP' });
}
});
@@ -322,7 +323,7 @@
const active = data.config.enabled && data.config.isSetUp;
updateAuthCard(active, data.config.sessionDuration);
}
} catch (e) { console.error('[AuthCard] Failed to update:', e); }
} catch (e) { errorHandler.logError('[TOTP] AuthCard Update', e, { function: 'authCardUpdate' }); }
})();
})();
+4 -2
View File
@@ -6,6 +6,8 @@
(function(window) {
'use strict';
const errorHandler = new ErrorHandler();
const debug = (...args) => {
if (window.DASHCADDY_DEBUG) { console.log(...args); }
};
@@ -30,7 +32,7 @@
const driverFactory = window.driver?.js?.driver || window.driver?.driver || window.driver;
if (typeof driverFactory !== 'function') {
console.error('[TourManager] Driver.js not loaded or invalid. window.driver:', window.driver);
errorHandler.logError('[TourManager] Driver.js Not Loaded', new Error('Driver.js not loaded or invalid'), { windowDriver: typeof window.driver });
return false;
}
@@ -202,7 +204,7 @@
async showTooltip(tooltipId) {
const tooltip = window.TooltipDefinitions.getTooltipById(tooltipId);
if (!tooltip) {
console.error(`[TourManager] Tooltip not found: ${tooltipId}`);
errorHandler.logError('[TourManager] Tooltip Not Found', new Error(`Tooltip not found: ${tooltipId}`), { tooltipId });
return;
}
+2 -1
View File
@@ -1,5 +1,6 @@
// ========== WEATHER WIDGET ==========
(function() {
const errorHandler = new ErrorHandler();
// Inject modal HTML
injectModal('weather-modal', `<div id="weather-modal" class="weather-modal"><div class="weather-modal-content"><h3>Weather Settings</h3>
<label for="weather-location-input">Location:</label>
@@ -166,7 +167,7 @@
weatherWidget.icon.innerHTML = `<span class="weather-emoji">${escapeHtml(weather.icon)}</span>`;
}
} catch (error) {
console.error('Weather update error:', error);
errorHandler.logError('[Weather] Update Error', error, { function: 'updateWeather' });
weatherWidget.location.textContent = 'Weather Error';
weatherWidget.temp.textContent = 'Error';
weatherWidget.condition.textContent = 'Failed to load';