// Admin Dashboard JavaScript $(document).ready(function() { // Load initial data loadOverviewStats(); loadSystemHealth(); loadTTSStatus(); loadRequestChart('hour'); loadOperationStats(); loadLanguagePairs(); loadRecentErrors(); loadActiveSessions(); // Set up auto-refresh setInterval(loadOverviewStats, 30000); // Every 30 seconds setInterval(loadSystemHealth, 60000); // Every minute setInterval(loadTTSStatus, 60000); // Every minute // Set up real-time updates if available initializeEventStream(); }); // Charts let charts = { request: null, operations: null, language: null, performance: null, errors: null }; // Load overview statistics function loadOverviewStats() { $.ajax({ url: '/admin/api/stats/overview', method: 'GET', success: function(data) { // Update request stats $('#total-requests').text(data.requests.total.toLocaleString()); $('#today-requests').text(data.requests.today.toLocaleString()); $('#hourly-requests').text(data.requests.hour.toLocaleString()); // Update operation stats $('#total-translations').text(data.translations.total.toLocaleString()); $('#today-translations').text(data.translations.today.toLocaleString()); $('#total-transcriptions').text(data.transcriptions.total.toLocaleString()); $('#today-transcriptions').text(data.transcriptions.today.toLocaleString()); // Update other metrics $('#active-sessions').text(data.active_sessions.toLocaleString()); $('#error-rate').text(data.error_rate.toFixed(2) + '%'); $('#cache-hit-rate').text(data.cache_hit_rate.toFixed(2) + '%'); }, error: function(xhr, status, error) { console.error('Failed to load overview stats:', error); } }); } // Load system health status function loadSystemHealth() { $.ajax({ url: '/admin/api/health', method: 'GET', success: function(data) { // Update overall status const overallStatus = $('#overall-status'); overallStatus.removeClass('text-success text-warning text-danger'); if (data.status === 'healthy') { overallStatus.addClass('text-success').html(' All Systems Operational'); } else if (data.status === 'degraded') { overallStatus.addClass('text-warning').html(' Degraded Performance'); } else { overallStatus.addClass('text-danger').html(' System Issues'); } // Update component statuses updateComponentStatus('redis', data.components.redis); updateComponentStatus('postgresql', data.components.postgresql); updateComponentStatus('ml', data.components.tts || { status: 'healthy' }); }, error: function(xhr, status, error) { console.error('Failed to load system health:', error); } }); } // Update component status badge function updateComponentStatus(component, data) { const badge = $(`#${component}-status`); badge.removeClass('bg-success bg-warning bg-danger bg-secondary'); if (data.status === 'healthy') { badge.addClass('bg-success').text('Healthy'); } else if (data.status === 'not_configured') { badge.addClass('bg-secondary').text('Not Configured'); } else if (data.status === 'unreachable') { badge.addClass('bg-warning').text('Unreachable'); } else { badge.addClass('bg-danger').text('Unhealthy'); } // Update TTS details if applicable if (component === 'ml' && data.status) { const details = $('#tts-details'); if (data.status === 'healthy') { details.text('TTS Server Connected'); } else if (data.status === 'not_configured') { details.text('No TTS Server'); } else if (data.status === 'unreachable') { details.text('Cannot reach TTS server'); } else { details.text('TTS Server Error'); } } } // Load detailed TTS status function loadTTSStatus() { $.ajax({ url: '/admin/api/tts/status', method: 'GET', success: function(data) { // Configuration status if (data.configured) { $('#tts-config-status').removeClass().addClass('badge bg-success').text('Configured'); $('#tts-server-url').text(data.server_url || '-'); $('#tts-api-key-status').text(data.api_key_configured ? 'Configured' : 'Not Set'); } else { $('#tts-config-status').removeClass().addClass('badge bg-secondary').text('Not Configured'); $('#tts-server-url').text('-'); $('#tts-api-key-status').text('-'); } // Health status const healthBadge = $('#tts-health-status'); healthBadge.removeClass(); if (data.status === 'healthy') { healthBadge.addClass('badge bg-success').text('Healthy'); $('#tts-error-message').text('-'); } else if (data.status === 'unreachable') { healthBadge.addClass('badge bg-warning').text('Unreachable'); $('#tts-error-message').text(data.details.error || 'Cannot connect'); } else if (data.status === 'not_configured') { healthBadge.addClass('badge bg-secondary').text('Not Configured'); $('#tts-error-message').text('-'); } else { healthBadge.addClass('badge bg-danger').text('Error'); $('#tts-error-message').text(data.details.error || 'Unknown error'); } // Voice count and list if (data.details && data.details.voice_count !== undefined) { $('#tts-voice-count').text(data.details.voice_count); // Show voice list if available if (data.details.available_voices && data.details.available_voices.length > 0) { $('#tts-voices-container').show(); const voicesList = $('#tts-voices-list'); voicesList.empty(); data.details.available_voices.forEach(function(voice) { voicesList.append(`${voice}`); }); } } else { $('#tts-voice-count').text('-'); $('#tts-voices-container').hide(); } // Usage statistics if (data.usage) { $('#tts-usage-today').text(data.usage.today.toLocaleString()); $('#tts-usage-total').text(data.usage.total.toLocaleString()); } else { $('#tts-usage-today').text('-'); $('#tts-usage-total').text('-'); } // Performance metrics if (data.performance) { $('#tts-avg-response').text(data.performance.avg_response_time + ' ms'); } else { $('#tts-avg-response').text('-'); } }, error: function(xhr, status, error) { console.error('Failed to load TTS status:', error); $('#tts-config-status').removeClass().addClass('badge bg-danger').text('Error'); $('#tts-health-status').removeClass().addClass('badge bg-danger').text('Error'); $('#tts-error-message').text('Failed to load status'); } }); } // Load request chart function loadRequestChart(timeframe) { // Implementation would go here console.log('Loading request chart for timeframe:', timeframe); } // Load operation statistics function loadOperationStats() { // Implementation would go here console.log('Loading operation stats'); } // Load language pairs function loadLanguagePairs() { // Implementation would go here console.log('Loading language pairs'); } // Load recent errors function loadRecentErrors() { // Implementation would go here console.log('Loading recent errors'); } // Load active sessions function loadActiveSessions() { // Implementation would go here console.log('Loading active sessions'); } // Initialize event stream for real-time updates function initializeEventStream() { if (typeof(EventSource) === "undefined") { console.log("Server-sent events not supported"); return; } const source = new EventSource('/admin/api/stream/updates'); source.onmessage = function(event) { const data = JSON.parse(event.data); // Update real-time metrics if (data.requests_per_minute !== undefined) { $('#realtime-rpm').text(data.requests_per_minute); } if (data.active_sessions !== undefined) { $('#active-sessions').text(data.active_sessions); } if (data.recent_errors !== undefined) { $('#recent-errors-count').text(data.recent_errors); } }; source.onerror = function(error) { console.error('EventSource error:', error); }; } // Show toast notification function showToast(message, type = 'info') { // Implementation would go here console.log(`Toast [${type}]: ${message}`); }