[Perl] DAQ system for the FAPG.
insights: remove EC from rate-of-change visualisation
EC rate of change was declared irrelevant by the farmer. Remove EC from the derivatives chart (At a Glance section) and remove the EC Trend & Rate card from the Explore section.
Changed files
roles/dashboard/public/js/dashboard/insights.js
@@ -37,9 +37,11 @@
37
37
ph: READING_RANGES.ph.goodMax - READING_RANGES.ph.goodMin,
38
38
do: READING_RANGES.do.goodMax - READING_RANGES.do.goodMin,
39
39
orp: READING_RANGES.orp.goodMax - READING_RANGES.orp.goodMin,
40
Removed:
ec: READING_RANGES.ec.goodMax - READING_RANGES.ec.goodMin,
41
40
};
42
41
42
Added:
// Probes shown on the rate-of-change chart (EC excluded per farmer request)
43
Added:
const DERIVATIVE_PROBES = ["ph", "do", "orp"];
44
Added:
43
45
let charts = {};
44
46
45
47
async function fetchJson(url, signal) {
@@ -112,11 +114,12 @@
112
114
113
115
const hours = timeframeToHours(timeframe);
114
116
const data = await fetchJson(`/api/insights/derivatives?hours=${hours}`, signal);
115
Removed:
const probeKeys = Object.keys(data.probes);
116
Removed:
const refProbe = probeKeys.find(p => data.probes[p].length > 0);
117
Added:
118
Added:
// Only use the probes we want (no EC)
119
Added:
const refProbe = DERIVATIVE_PROBES.find(p => data.probes[p]?.length > 0);
117
120
const labels = refProbe ? data.probes[refProbe].map(p => formatDateTime(p.timestamp)) : [];
118
121
119
Removed:
const datasets = probeKeys.map(probe => {
122
Added:
const datasets = DERIVATIVE_PROBES.map(probe => {
120
123
const span = OPTIMAL_SPANS[probe] || 1;
121
124
const points = data.probes[probe] || [];
122
125
@@ -174,6 +177,7 @@
174
177
const canvas = document.getElementById("chart-diurnal");
175
178
if (!canvas) return;
176
179
180
Added:
// Diurnal always shows day overlay, but we use the timeframe range as days
177
181
const hours = timeframeToHours(timeframe);
178
182
const days = Math.max(1, Math.round(hours / 24));
179
183
@@ -311,89 +315,6 @@
311
315
}
312
316
}
313
317
314
Removed:
async function loadEcRate(timeframe, signal) {
315
Removed:
const canvas = document.getElementById("chart-ec-rate");
316
Removed:
if (!canvas) return;
317
Removed:
318
Removed:
const tf = timeframe.selected();
319
Removed:
const range = timeframe.range();
320
Removed:
const ecData = await fetchProbeData("ec", tf, range, false, signal);
321
Removed:
322
Removed:
const labels = ecData.points.map(p => formatChartTime(p.timestamp, tf));
323
Removed:
const ecValues = ecData.points.map(p => p.value);
324
Removed:
325
Removed:
// Compute rate from the series points directly
326
Removed:
const rateValues = ecValues.map((v, i) => {
327
Removed:
if (i === 0 || v === null || ecValues[i - 1] === null) return null;
328
Removed:
return v - ecValues[i - 1];
329
Removed:
});
330
Removed:
331
Removed:
if (!charts.ecRate) {
332
Removed:
charts.ecRate = new Chart(canvas, {
333
Removed:
type: "line",
334
Removed:
data: {
335
Removed:
labels,
336
Removed:
datasets: [
337
Removed:
{
338
Removed:
label: "EC (µS/cm)",
339
Removed:
data: ecValues,
340
Removed:
borderColor: PROBE_COLORS.ec.border,
341
Removed:
backgroundColor: PROBE_COLORS.ec.background,
342
Removed:
tension: 0.2,
343
Removed:
pointRadius: 0,
344
Removed:
pointHoverRadius: 4,
345
Removed:
yAxisID: "yEC",
346
Removed:
fill: true
347
Removed:
},
348
Removed:
{
349
Removed:
label: "EC change (Δ)",
350
Removed:
data: rateValues,
351
Removed:
borderColor: "#f59e0b",
352
Removed:
backgroundColor: "rgba(245, 158, 11, 0.1)",
353
Removed:
borderDash: [4, 3],
354
Removed:
tension: 0.3,
355
Removed:
pointRadius: 0,
356
Removed:
pointHoverRadius: 3,
357
Removed:
yAxisID: "yRate",
358
Removed:
fill: false
359
Removed:
}
360
Removed:
]
361
Removed:
},
362
Removed:
options: {
363
Removed:
responsive: true,
364
Removed:
maintainAspectRatio: false,
365
Removed:
animation: false,
366
Removed:
interaction: { mode: "index", intersect: false },
367
Removed:
scales: {
368
Removed:
x: { ticks: { maxTicksLimit: 8, font: { size: 10 } } },
369
Removed:
yEC: {
370
Removed:
type: "linear",
371
Removed:
position: "left",
372
Removed:
title: { display: true, text: "EC (µS/cm)", color: PROBE_COLORS.ec.border },
373
Removed:
ticks: { color: PROBE_COLORS.ec.border }
374
Removed:
},
375
Removed:
yRate: {
376
Removed:
type: "linear",
377
Removed:
position: "right",
378
Removed:
title: { display: true, text: "Δ per bucket", color: "#f59e0b" },
379
Removed:
ticks: { color: "#f59e0b" },
380
Removed:
grid: { drawOnChartArea: false }
381
Removed:
}
382
Removed:
},
383
Removed:
plugins: {
384
Removed:
legend: { display: true },
385
Removed:
tooltip: { ...TOOLTIP_DEFAULTS, callbacks: { title: () => "" } }
386
Removed:
}
387
Removed:
}
388
Removed:
});
389
Removed:
} else {
390
Removed:
charts.ecRate.data.labels = labels;
391
Removed:
charts.ecRate.data.datasets[0].data = ecValues;
392
Removed:
charts.ecRate.data.datasets[1].data = rateValues;
393
Removed:
charts.ecRate.update();
394
Removed:
}
395
Removed:
}
396
Removed:
397
318
async function loadPhDoLag(timeframe, signal) {
398
319
const canvas = document.getElementById("chart-ph-do-lag");
399
320
if (!canvas) return;
@@ -498,7 +419,6 @@
498
419
loadDerivatives(timeframe, signal),
499
420
loadDiurnal(timeframe, signal),
500
421
loadDoOrpOverlay(timeframe, signal),
501
Removed:
loadEcRate(timeframe, signal),
502
422
loadPhDoLag(timeframe, signal)
503
423
]);
504
424
}
roles/dashboard/t/08-insights.t
@@ -36,7 +36,6 @@
36
36
->element_exists('canvas#chart-derivatives')
37
37
->element_exists('canvas#chart-diurnal')
38
38
->element_exists('canvas#chart-overlay-do-orp')
39
Removed:
->element_exists('canvas#chart-ec-rate')
40
39
->element_exists('canvas#chart-ph-do-lag');
41
40
};
42
41
roles/dashboard/templates/dashboard/insights.html.ep
@@ -106,22 +106,6 @@
106
106
</div>
107
107
</div>
108
108
109
Removed:
<div class="col-12" id="ec-rate">
110
Removed:
<div class="card">
111
Removed:
<div class="card-header">
112
Removed:
<h3 class="h6 mb-0">EC Trend & Rate</h3>
113
Removed:
<p class="text-body-secondary small mb-0 mt-1">
114
Removed:
Electrical conductivity with rate of change — rising EC means nutrient buildup
115
Removed:
</p>
116
Removed:
</div>
117
Removed:
<div class="card-body">
118
Removed:
<div class="chart-wrap">
119
Removed:
<canvas id="chart-ec-rate" role="img" aria-label="EC trend with rate of change"></canvas>
120
Removed:
</div>
121
Removed:
</div>
122
Removed:
</div>
123
Removed:
</div>
124
Removed:
125
109
<div class="col-12" id="ph-do-lag">
126
110
<div class="card">
127
111
<div class="card-header">