talk2me/admin/static/js/admin.js
Adolfo Delorenzo c97d025acb Move TTS server status from frontend to admin dashboard
- Removed TTS server status popup from main frontend interface
- Commented out checkTtsServer() function and all its calls
- Removed TTS configuration UI elements from index.html
- Added comprehensive TTS server monitoring to admin dashboard:
  - Configuration status (URL, API key)
  - Server health monitoring
  - Available voices display
  - Usage statistics and performance metrics
  - Real-time status updates
- Enhanced system health check to include TTS server
- Created dedicated /api/tts/status endpoint for detailed info

The TTS functionality remains fully operational for users, but status
monitoring is now exclusive to the admin dashboard for cleaner UX.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-03 19:11:26 -06:00

261 lines
9.5 KiB
JavaScript

// 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('<i class="fas fa-check-circle"></i> All Systems Operational');
} else if (data.status === 'degraded') {
overallStatus.addClass('text-warning').html('<i class="fas fa-exclamation-triangle"></i> Degraded Performance');
} else {
overallStatus.addClass('text-danger').html('<i class="fas fa-times-circle"></i> 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(`<span class="badge bg-primary">${voice}</span>`);
});
}
} 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}`);
}