/** * Allegro-Primus Dashboard JavaScript * Handles real-time updates, charts, and interactivity */ // Auto-refresh configuration const AUTO_REFRESH_INTERVAL = 30000; // 30 seconds let refreshTimer = null; // Initialize dashboard document.addEventListener('DOMContentLoaded', function() { initDashboard(); startAutoRefresh(); initCharts(); }); function initDashboard() { // Add click handlers for table rows document.querySelectorAll('.data-table tbody tr').forEach(row => { row.style.cursor = 'pointer'; row.addEventListener('click', function() { this.classList.toggle('selected'); }); }); // Initialize tooltips if needed initTooltips(); } function initTooltips() { // Simple tooltip implementation document.querySelectorAll('[title]').forEach(el => { el.addEventListener('mouseenter', showTooltip); el.addEventListener('mouseleave', hideTooltip); }); } function showTooltip(e) { const tooltip = document.createElement('div'); tooltip.className = 'tooltip'; tooltip.textContent = e.target.getAttribute('title'); document.body.appendChild(tooltip); const rect = e.target.getBoundingClientRect(); tooltip.style.left = rect.left + 'px'; tooltip.style.top = (rect.bottom + 5) + 'px'; } function hideTooltip() { document.querySelectorAll('.tooltip').forEach(t => t.remove()); } function initCharts() { // Charts are initialized in individual templates // This is for any global chart configuration Chart.defaults.color = '#94a3b8'; Chart.defaults.borderColor = '#334155'; } // Auto-refresh functionality function startAutoRefresh() { refreshTimer = setInterval(refreshData, AUTO_REFRESH_INTERVAL); } function stopAutoRefresh() { if (refreshTimer) { clearInterval(refreshTimer); refreshTimer = null; } } async function refreshData() { try { // Refresh metrics const metricsResponse = await fetch('/api/metrics'); if (metricsResponse.ok) { const data = await metricsResponse.json(); updateMetricsDisplay(data.current); } // Refresh status const statusResponse = await fetch('/api/status'); if (statusResponse.ok) { const status = await statusResponse.json(); updateStatusDisplay(status); } } catch (error) { console.error('Error refreshing data:', error); } } function updateMetricsDisplay(metrics) { // Update metric cards if they exist const successRateEl = document.querySelector('.metric-card.success .metric-value'); if (successRateEl) { successRateEl.textContent = (metrics.success_rate * 100).toFixed(1) + '%'; } } function updateStatusDisplay(status) { // Update status indicators console.log('Status updated:', status); } // API helper functions const API = { async getStatus() { const response = await fetch('/api/status'); return response.json(); }, async getMetrics() { const response = await fetch('/api/metrics'); return response.json(); }, async getJournal(limit = 50, offset = 0) { const response = await fetch(`/api/journal?limit=${limit}&offset=${offset}`); return response.json(); }, async getIssues(state = 'all') { const response = await fetch(`/api/issues?state=${state}`); return response.json(); }, async getKnowledge() { const response = await fetch('/api/knowledge'); return response.json(); }, async healthCheck() { const response = await fetch('/api/health'); return response.json(); } }; // Export data functionality function exportData(format) { window.location.href = `/export/${format}`; } // Search functionality for journal function searchJournal(query) { const rows = document.querySelectorAll('.journal-table tbody tr'); rows.forEach(row => { const text = row.textContent.toLowerCase(); row.style.display = text.includes(query.toLowerCase()) ? '' : 'none'; }); } // Filter functionality function filterByStatus(status) { const rows = document.querySelectorAll('.journal-table tbody tr'); rows.forEach(row => { const rowStatus = row.querySelector('.badge'); if (status === 'all' || (rowStatus && rowStatus.classList.contains(status))) { row.style.display = ''; } else { row.style.display = 'none'; } }); } // Modal functionality function showModal(content) { const modal = document.getElementById('entryModal'); const modalContent = document.getElementById('modalContent'); if (modal && modalContent) { modalContent.innerHTML = content; modal.style.display = 'block'; } } function hideModal() { const modal = document.getElementById('entryModal'); if (modal) { modal.style.display = 'none'; } } // Close modal when clicking outside document.addEventListener('click', function(e) { const modal = document.getElementById('entryModal'); if (e.target === modal) { hideModal(); } }); // Keyboard shortcuts document.addEventListener('keydown', function(e) { // ESC to close modal if (e.key === 'Escape') { hideModal(); } // R to refresh if (e.key === 'r' && !e.ctrlKey && !e.metaKey) { refreshData(); } }); // Notification system function showNotification(message, type = 'info') { const notification = document.createElement('div'); notification.className = `notification notification-${type}`; notification.innerHTML = ` ${message} `; document.body.appendChild(notification); setTimeout(() => { notification.classList.add('show'); }, 10); setTimeout(() => { notification.classList.remove('show'); setTimeout(() => notification.remove(), 300); }, 3000); } // Utility functions function formatDate(dateString) { const date = new Date(dateString); return date.toLocaleString(); } function formatDuration(ms) { if (ms < 1000) return ms + 'ms'; if (ms < 60000) return (ms / 1000).toFixed(1) + 's'; return (ms / 60000).toFixed(1) + 'm'; } function debounce(func, wait) { let timeout; return function executedFunction(...args) { const later = () => { clearTimeout(timeout); func(...args); }; clearTimeout(timeout); timeout = setTimeout(later, wait); }; } // Performance monitoring function measurePerformance() { const perfData = performance.getEntriesByType('navigation')[0]; console.log('Page load time:', perfData.loadEventEnd - perfData.loadEventStart, 'ms'); } // Log dashboard load console.log('🚀 Allegro-Primus Dashboard loaded'); console.log('Press R to refresh data');