fix(dashboard): add cache-busting and defensive chartManager guards to fix empty charts
Some checks failed
CI / Check (push) Has been cancelled
CI / Clippy (push) Has been cancelled
CI / Formatting (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Release Build (push) Has been cancelled

This commit is contained in:
2026-03-02 13:28:29 -05:00
parent 8d50ce7c22
commit 1766a12ea2
8 changed files with 88 additions and 34 deletions

View File

@@ -50,6 +50,14 @@ class AnalyticsPage {
}
async loadCharts() {
const cm = window.chartManager || await window.waitForChartManager();
if (!cm) {
this.showEmptyChart('analytics-chart', 'Chart system unavailable');
this.showEmptyChart('clients-chart', 'Chart system unavailable');
this.showEmptyChart('models-chart', 'Chart system unavailable');
return;
}
// Fetch each data source independently so one failure doesn't kill the others
const [timeSeriesResult, breakdownResult] = await Promise.allSettled([
window.api.get('/usage/time-series'),
@@ -111,6 +119,8 @@ class AnalyticsPage {
}
renderAnalyticsChart(series) {
const cm = window.chartManager;
if (!cm) return;
const data = {
labels: series.map(s => s.time),
datasets: [
@@ -130,10 +140,12 @@ class AnalyticsPage {
]
};
window.chartManager.createLineChart('analytics-chart', data);
cm.createLineChart('analytics-chart', data);
}
renderClientsChart(clients) {
const cm = window.chartManager;
if (!cm) return;
const data = {
labels: clients.map(c => c.label),
datasets: [{
@@ -143,17 +155,19 @@ class AnalyticsPage {
}]
};
window.chartManager.createHorizontalBarChart('clients-chart', data);
cm.createHorizontalBarChart('clients-chart', data);
}
renderModelsChart(models) {
const cm = window.chartManager;
if (!cm) return;
const data = {
labels: models.map(m => m.label),
data: models.map(m => m.value),
colors: window.chartManager.defaultColors
colors: cm.defaultColors
};
window.chartManager.createDoughnutChart('models-chart', data);
cm.createDoughnutChart('models-chart', data);
}
async loadUsageData() {

View File

@@ -75,6 +75,9 @@ class ClientsPage {
async loadClientUsageChart() {
try {
const cm = window.chartManager || await window.waitForChartManager();
if (!cm) { this.showEmptyChart('client-usage-chart', 'Chart system unavailable'); return; }
const data = await window.api.get('/usage/clients');
if (!data || data.length === 0) {
@@ -91,7 +94,7 @@ class ClientsPage {
}]
};
window.chartManager.createHorizontalBarChart('client-usage-chart', chartData);
cm.createHorizontalBarChart('client-usage-chart', chartData);
} catch (error) {
console.error('Error loading client usage chart:', error);

View File

@@ -91,6 +91,9 @@ class CostsPage {
async loadCostsChart() {
try {
const cm = window.chartManager || await window.waitForChartManager();
if (!cm) { this.showEmptyChart('costs-chart', 'Chart system unavailable'); return; }
const data = await window.api.get('/usage/providers');
if (!data || data.length === 0) {
@@ -107,7 +110,7 @@ class CostsPage {
}]
};
window.chartManager.createBarChart('costs-chart', chartData);
cm.createBarChart('costs-chart', chartData);
} catch (error) {
console.error('Error loading costs chart:', error);

View File

@@ -153,6 +153,13 @@ class MonitoringPage {
}
async loadCharts() {
// Ensure chartManager is available
const cm = window.chartManager || await window.waitForChartManager();
if (!cm) {
console.warn('chartManager unavailable, skipping monitoring charts');
return;
}
// Fetch recent logs for chart data
try {
const logs = await window.api.get('/system/logs');
@@ -168,6 +175,8 @@ class MonitoringPage {
async loadResponseTimeChart() {
try {
const cm = window.chartManager;
if (!cm) return;
// Bucket recent logs by minute for latency chart
const buckets = this.bucketByMinute(this.recentLogs, 20);
const labels = buckets.map(b => b.label);
@@ -187,7 +196,7 @@ class MonitoringPage {
}]
};
window.chartManager.createLineChart('response-time-chart', data, {
cm.createLineChart('response-time-chart', data, {
scales: {
y: {
title: { display: true, text: 'Milliseconds' },
@@ -202,6 +211,8 @@ class MonitoringPage {
async loadErrorRateChart() {
try {
const cm = window.chartManager;
if (!cm) return;
const buckets = this.bucketByMinute(this.recentLogs, 20);
const labels = buckets.map(b => b.label);
const values = buckets.map(b => {
@@ -220,7 +231,7 @@ class MonitoringPage {
}]
};
window.chartManager.createLineChart('error-rate-chart', data, {
cm.createLineChart('error-rate-chart', data, {
scales: {
y: {
title: { display: true, text: 'Percentage' },
@@ -238,6 +249,8 @@ class MonitoringPage {
async loadRateLimitChart() {
try {
const cm = window.chartManager;
if (!cm) return;
// Show requests-per-client from recent logs
const clientCounts = {};
for (const log of this.recentLogs) {
@@ -257,7 +270,7 @@ class MonitoringPage {
}]
};
window.chartManager.createBarChart('rate-limit-chart', data, {
cm.createBarChart('rate-limit-chart', data, {
scales: {
y: {
title: { display: true, text: 'Request Count' },
@@ -452,22 +465,24 @@ class MonitoringPage {
}
updateCharts(metric) {
const cm = window.chartManager;
if (!cm) return;
// Update charts with new metric data
if (metric.type === 'response_time' && window.chartManager.charts.has('response-time-chart')) {
if (metric.type === 'response_time' && cm.charts.has('response-time-chart')) {
this.updateResponseTimeChart(metric.value);
}
if (metric.type === 'error_rate' && window.chartManager.charts.has('error-rate-chart')) {
if (metric.type === 'error_rate' && cm.charts.has('error-rate-chart')) {
this.updateErrorRateChart(metric.value);
}
}
updateResponseTimeChart(value) {
window.chartManager.addDataPoint('response-time-chart', value);
if (window.chartManager) window.chartManager.addDataPoint('response-time-chart', value);
}
updateErrorRateChart(value) {
window.chartManager.addDataPoint('error-rate-chart', value);
if (window.chartManager) window.chartManager.addDataPoint('error-rate-chart', value);
}
startDemoUpdates() {

View File

@@ -128,6 +128,9 @@ class OverviewPage {
async loadRequestsChart() {
try {
const cm = window.chartManager || await window.waitForChartManager();
if (!cm) { this.showEmptyChart('requests-chart', 'Chart system unavailable'); return; }
const data = await window.api.get('/usage/time-series');
const series = data.series || [];
@@ -148,7 +151,7 @@ class OverviewPage {
]
};
this.charts.requests = window.chartManager.createLineChart('requests-chart', chartData);
this.charts.requests = cm.createLineChart('requests-chart', chartData);
} catch (error) {
console.error('Error loading requests chart:', error);
this.showEmptyChart('requests-chart', 'Failed to load request data');
@@ -157,6 +160,9 @@ class OverviewPage {
async loadProvidersChart() {
try {
const cm = window.chartManager || await window.waitForChartManager();
if (!cm) { this.showEmptyChart('providers-chart', 'Chart system unavailable'); return; }
const data = await window.api.get('/usage/providers');
if (!data || data.length === 0) {
@@ -167,10 +173,10 @@ class OverviewPage {
const chartData = {
labels: data.map(item => item.provider),
data: data.map(item => item.requests),
colors: data.map((_, i) => window.chartManager.defaultColors[i % window.chartManager.defaultColors.length])
colors: data.map((_, i) => cm.defaultColors[i % cm.defaultColors.length])
};
this.charts.providers = window.chartManager.createDoughnutChart('providers-chart', chartData);
this.charts.providers = cm.createDoughnutChart('providers-chart', chartData);
} catch (error) {
console.error('Error loading providers chart:', error);
this.showEmptyChart('providers-chart', 'Failed to load provider data');