fix(dashboard): add COALESCE to SQL aggregations and empty-state handling for charts
Backend: wrap SUM() queries with COALESCE in handle_time_series, handle_clients_usage, and handle_detailed_usage to prevent NULL-induced panics when no data exists for a time window. Frontend: add showEmptyChart() empty-state messages and error feedback across overview, analytics, costs, and clients pages. Rewrite analytics loadCharts() to use Promise.allSettled() so each chart renders independently on partial API failures.
This commit is contained in:
@@ -92,6 +92,11 @@ class CostsPage {
|
||||
async loadCostsChart() {
|
||||
try {
|
||||
const data = await window.api.get('/usage/providers');
|
||||
|
||||
if (!data || data.length === 0) {
|
||||
this.showEmptyChart('costs-chart', 'No provider spending data yet');
|
||||
return;
|
||||
}
|
||||
|
||||
const chartData = {
|
||||
labels: data.map(item => item.provider),
|
||||
@@ -106,6 +111,24 @@ class CostsPage {
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error loading costs chart:', error);
|
||||
this.showEmptyChart('costs-chart', 'Failed to load spending data');
|
||||
}
|
||||
}
|
||||
|
||||
showEmptyChart(canvasId, message) {
|
||||
const canvas = document.getElementById(canvasId);
|
||||
if (!canvas) return;
|
||||
const container = canvas.closest('.chart-container');
|
||||
if (container) {
|
||||
canvas.style.display = 'none';
|
||||
let msg = container.querySelector('.empty-chart-msg');
|
||||
if (!msg) {
|
||||
msg = document.createElement('div');
|
||||
msg.className = 'empty-chart-msg';
|
||||
msg.style.cssText = 'display:flex;align-items:center;justify-content:center;height:200px;color:var(--fg4);font-size:0.9rem;';
|
||||
container.appendChild(msg);
|
||||
}
|
||||
msg.textContent = message;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user