fix stop gap-fill from interpolating across data gaps

fillGaps() was ignoring the server's gap flags and interpolating across long empty stretches (e.g. probe offline for hours). Now tracks gap-break indices from chartSeries and treats them as hard stops — no interpolation across flagged gaps.

Commit
6f056c0fdf9088ff119548893c9bdfb98e6823aa
Author
GPT-5 medium <codex@openai.com>
Author date
Committer
GPT-5 medium <codex@openai.com>
Committer date
roles/dashboard/public/js/dashboard/charts.js
index 525e4120..e3cb4a50 100644..100644
@@ -35,10 +35,11 @@
35 35 }
36 36
37 37 function chartSeries(rows, timeframe) {
38 Removed: const series = { labels: [], timestamps: [], min: [], max: [], trend: [], gapFill: [] };
38 Added: const series = { labels: [], timestamps: [], min: [], max: [], trend: [], gapFill: [], gapBreaks: new Set() };
39 39
40 40 rows.forEach(row => {
41 41 if (row.gap && series.labels.length) {
42 Added: series.gapBreaks.add(series.labels.length);
42 43 series.labels.push("");
43 44 series.timestamps.push(null);
44 45 series.min.push(null);
@@ -53,15 +54,20 @@
53 54 series.trend.push(row.value === null ? null : Number(row.value));
54 55 });
55 56
56 Removed: series.gapFill = fillGaps(series.trend);
57 Added: series.gapFill = fillGaps(series.trend, series.gapBreaks);
57 58 return series;
58 59 }
59 60
60 Removed: function fillGaps(values) {
61 Added: function fillGaps(values, gapBreaks) {
61 62 const filled = [...values];
62 63 let previous = null;
63 64
64 65 values.forEach((value, index) => {
66 Added: if (gapBreaks.has(index)) {
67 Added: previous = null;
68 Added: return;
69 Added: }
70 Added:
65 71 if (!Number.isFinite(value)) return;
66 72
67 73 if (previous !== null && index - previous > 1) {
@@ -69,6 +75,7 @@
69 75 const step = (value - start) / (index - previous);
70 76
71 77 for (let gapIndex = previous + 1; gapIndex < index; gapIndex += 1) {
78 Added: if (gapBreaks.has(gapIndex)) break;
72 79 filled[gapIndex] = start + step * (gapIndex - previous);
73 80 }
74 81 }