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:
@@ -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',
|
||||
|
||||
@@ -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' });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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' });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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' });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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'));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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' });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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' }); }
|
||||
})();
|
||||
|
||||
})();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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';
|
||||
|
||||
Reference in New Issue
Block a user