feat: improve error management when data are missing
This commit is contained in:
parent
319821ce59
commit
5f15002462
4 changed files with 95 additions and 43 deletions
|
|
@ -145,3 +145,9 @@ main {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#chart-message {
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
margin-top: 8rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
@ -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,6 +11,9 @@ 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;
|
||||||
|
|
||||||
|
if (!device_eui || !start || !end) return;
|
||||||
|
|
||||||
|
try {
|
||||||
const points = await fetchConsumption({
|
const points = await fetchConsumption({
|
||||||
device_eui: device_eui,
|
device_eui: device_eui,
|
||||||
start: start,
|
start: start,
|
||||||
|
|
@ -27,11 +21,16 @@ async function loadData() {
|
||||||
granularity: granularity,
|
granularity: granularity,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (chart) {
|
if (chart) { chart.destroy(); }
|
||||||
chart.destroy();
|
|
||||||
}
|
|
||||||
chart = renderChart(points, granularity);
|
chart = renderChart(points, granularity);
|
||||||
updateKPIs(points);
|
updateKPIs(points);
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
if (chart) { chart.destroy(); }
|
||||||
|
showMessage("Impossible de charger les données : " + err.message);
|
||||||
|
updateKPIs(null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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");
|
||||||
|
|
||||||
|
try {
|
||||||
const devices = await fetchDevices();
|
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();
|
||||||
}
|
}
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue