(data, options = {})
| 9199 | buttons.forEach(btn => { |
| 9200 | btn.addEventListener('click', () => { |
| 9201 | const status = btn.getAttribute('data-status'); |
| 9202 | setThreatIntelFilter(status); |
| 9203 | }); |
| 9204 | }); |
| 9205 | |
| 9206 | // Ensure initial visual state matches default filter without reloading data |
| 9207 | setThreatIntelFilter(threatIntelStatusFilter, { skipReload: true }); |
| 9208 | } |
| 9209 | |
| 9210 | // ============================================================================ |
| 9211 | // DATA LOADING |
| 9212 | // ============================================================================ |
| 9213 | |
| 9214 | async function loadInitialData() { |
| 9215 | try { |
| 9216 | // Check auth status to show/hide logout button and wait for DB if needed |
| 9217 | try { |
| 9218 | const authStatus = await fetchAPI('/api/auth/status'); |
| 9219 | const logoutBtn = document.getElementById('logout-btn'); |
| 9220 | if (logoutBtn) logoutBtn.classList.toggle('hidden', !authStatus.configured); |
| 9221 | const mobileLogoutBtn = document.getElementById('mobile-logout-btn'); |
| 9222 | if (mobileLogoutBtn) mobileLogoutBtn.classList.toggle('hidden', !authStatus.configured); |
| 9223 | |
| 9224 | } catch (e) { /* ignore - auth check is non-critical */ } |
| 9225 | |
| 9226 | // OPTIMIZATION: Use combined /api/dashboard/quick endpoint for fast loading |
| 9227 | // This eliminates multiple API calls and reduces load time from 5-10s to <2s on Pi Zero |
| 9228 | |
| 9229 | // Load critical dashboard data using optimized combined endpoint |
| 9230 | const quickData = await fetchAPI('/api/dashboard/quick'); |
| 9231 | if (quickData) { |
| 9232 | // Update both stats and status from single response |
| 9233 | updateDashboardStats(quickData); |
| 9234 | updateDashboardStatus(quickData); |
| 9235 | } |
| 9236 | |
| 9237 | // OPTIMIZATION: Defer WiFi + LAN status to after dashboard is visible |
| 9238 | setTimeout(() => { |
| 9239 | refreshWifiStatus().catch(err => console.warn('WiFi status load failed:', err)); |
| 9240 | refreshEthernetStatus().catch(err => console.warn('LAN status load failed:', err)); |
| 9241 | }, 200); |
| 9242 | |
| 9243 | // OPTIMIZATION: Defer console logs to much later (lowest priority) |
| 9244 | setTimeout(() => { |
| 9245 | loadConsoleLogs().then(() => { |
| 9246 | addConsoleMessage('Ragnar Modern Web Interface Initialized', 'success'); |
| 9247 | addConsoleMessage('Dashboard loaded successfully', 'info'); |
| 9248 | }).catch(err => { |
| 9249 | console.warn('Console logs load failed:', err); |
| 9250 | addConsoleMessage('Error loading console logs', 'warning'); |
| 9251 | }); |
| 9252 | }, 1000); |
| 9253 | |
| 9254 | // OPTIMIZATION: Completely defer tab preloading until user interacts or 10s passes |
| 9255 | // This prevents overwhelming the Pi Zero during initial page load |
| 9256 | let preloadTriggered = false; |
| 9257 | |
| 9258 | // Trigger preload on first user interaction (hover, click, scroll) |
no test coverage detected