feat: improve error management when data are missing

This commit is contained in:
Alexis Fourmaux 2026-05-12 23:24:31 +02:00
parent 319821ce59
commit 5f15002462
4 changed files with 95 additions and 43 deletions

View file

@ -145,3 +145,9 @@ main {
} }
} }
} }
#chart-message {
color: var(--color-text-muted);
margin-top: 8rem;
text-align: center;
}

View file

@ -1,4 +1,36 @@
const PERIOD_FORMATS = {
hour: { hour: "2-digit", minute: "2-digit", day: "2-digit", month: "short" },
day: { day: "2-digit", month: "short" },
week: { day: "2-digit", month: "short" },
month: { month: "short", year: "numeric" },
};
function formatPeriod(isoString, granularity) {
const date = new Date(isoString);
const opts = PERIOD_FORMATS[granularity] ?? PERIOD_FORMATS.day;
return date.toLocaleDateString("fr-FR", opts);
}
function showMessage(message) {
document.getElementById("consumption-chart").hidden = true;
const msg = document.getElementById("chart-message");
msg.textContent = message;
msg.hidden = false;
}
function hideMessage() {
document.getElementById("consumption-chart").hidden = false;
document.getElementById("chart-message").hidden = true;
}
function renderChart(points, granularity) { function renderChart(points, granularity) {
if (!points || points.length === 0){
showMessage("Aucune donnée à afficher sur cette période");
return null;
}
hideMessage();
const canvas = document.getElementById("consumption-chart"); const canvas = document.getElementById("consumption-chart");
const labels = points.map((p) => formatPeriod(p.period, granularity)); const labels = points.map((p) => formatPeriod(p.period, granularity));
@ -17,7 +49,7 @@ function renderChart(points, granularity) {
data, data,
backgroundColor: accent + 'cc', backgroundColor: accent + 'cc',
borderColor: accent, borderColor: accent,
borderWidth: '1px' borderWidth: 1
}, },
], ],
}, },
@ -44,16 +76,3 @@ function renderChart(points, granularity) {
return chart; return chart;
} }
const PERIOD_FORMATS = {
hour: { hour: "2-digit", minute: "2-digit", day: "2-digit", month: "short" },
day: { day: "2-digit", month: "short" },
week: { day: "2-digit", month: "short" },
month: { month: "short", year: "numeric" },
};
function formatPeriod(isoString, granularity) {
const date = new Date(isoString);
const opts = PERIOD_FORMATS[granularity] ?? PERIOD_FORMATS.day;
return date.toLocaleDateString("fr-FR", opts);
}

View file

@ -1,17 +1,8 @@
let chart = null; let chart = null;
window.onload = init; document.addEventListener("DOMContentLoaded", init);
async function init() { function showChartError() {
let start = new Date();
start.setDate(start.getDate() - 7);
const end = new Date();
document.getElementById("date-start").valueAsDate = start;
document.getElementById("date-end").valueAsDate = end;
document.getElementById("btn-refresh").addEventListener("click", loadData);
await loadDevices();
await loadData();
} }
async function loadData() { async function loadData() {
@ -20,18 +11,26 @@ async function loadData() {
const granularity = document.getElementById("granularity").value; const granularity = document.getElementById("granularity").value;
const device_eui = document.getElementById("device").value; const device_eui = document.getElementById("device").value;
const points = await fetchConsumption({ if (!device_eui || !start || !end) return;
device_eui: device_eui,
start: start,
end: end,
granularity: granularity,
});
if (chart) { try {
chart.destroy(); const points = await fetchConsumption({
device_eui: device_eui,
start: start,
end: end,
granularity: granularity,
});
if (chart) { chart.destroy(); }
chart = renderChart(points, granularity);
updateKPIs(points);
} catch (err) {
if (chart) { chart.destroy(); }
showMessage("Impossible de charger les données : " + err.message);
updateKPIs(null);
} }
chart = renderChart(points, granularity);
updateKPIs(points);
} }
function updateKPIs(points) { function updateKPIs(points) {
@ -40,9 +39,9 @@ function updateKPIs(points) {
const countDisplay = document.getElementById("kpi-count"); const countDisplay = document.getElementById("kpi-count");
if (!points || points.length === 0) { if (!points || points.length === 0) {
total.textContent = "-"; totalDisplay.textContent = "-";
avg.textContent = "-"; avgDisplay.textContent = "-";
count.textContent = "-"; countDisplay.textContent = "-";
return; return;
} }
@ -57,11 +56,38 @@ function updateKPIs(points) {
async function loadDevices() { async function loadDevices() {
const selectDeviceElmt = document.getElementById("device"); const selectDeviceElmt = document.getElementById("device");
const devices = await fetchDevices(); try {
const devices = await fetchDevices();
if (!devices.length) {
selectDeviceElmt.disabled = true;
selectDeviceElmt.add(new Option("Aucun appareil disponible", ""));
return;
}
devices.forEach((device) => { devices.forEach((device) => {
selectDeviceElmt.add(new Option(device.device_eui)) selectDeviceElmt.add(new Option(device.device_eui));
}); });
selectDeviceElmt.value = devices[0]?.device_eui ?? ""; selectDeviceElmt.value = devices[0].device_eui;
} catch(err) {
selectDeviceElmt.disabled = true;
selectDeviceElmt.add(new Option("Erreur de chargement", ""));
console.error("loadDevices :", err.message);
}
}
async function init() {
let start = new Date();
start.setDate(start.getDate() - 7);
const end = new Date();
document.getElementById("date-start").valueAsDate = start;
document.getElementById("date-end").valueAsDate = end;
document.getElementById("btn-refresh").addEventListener("click", loadData);
await loadDevices();
const device_eui = document.getElementById("device").value;
if (device_eui) await loadData();
} }

View file

@ -69,6 +69,7 @@
<section class="chart-section"> <section class="chart-section">
<div> <div>
<canvas id="consumption-chart"></canvas> <canvas id="consumption-chart"></canvas>
<p id="chart-message" hidden></p>
</div> </div>
</section> </section>
</main> </main>