[Perl] DAQ system for the FAPG.
refactor flatten insights into a single list of charts
Remove the 'At a Glance' / 'Explore' section split and the nav pills with scroll spy. All charts are now presented as a flat vertical list. Grouping will be rationalised later.
Changed files
roles/dashboard/public/js/dashboard/insights.js
@@ -429,9 +429,6 @@
429
429
// Initial load
430
430
loadAll();
431
431
432
Removed:
// Scroll spy
433
Removed:
initScrollSpy();
434
Removed:
435
432
return {
436
433
reload() {
437
434
loadAll();
@@ -439,25 +436,3 @@
439
436
};
440
437
}
441
438
442
Removed:
// ──────────────────────────────────────────────────────────────────
443
Removed:
// Scroll spy: highlight active nav pill based on visible section
444
Removed:
// ──────────────────────────────────────────────────────────────────
445
Removed:
function initScrollSpy() {
446
Removed:
const navLinks = document.querySelectorAll(".insights-nav a.nav-link");
447
Removed:
const sections = document.querySelectorAll(".insight-theme[id]");
448
Removed:
449
Removed:
if (!navLinks.length || !sections.length) return;
450
Removed:
451
Removed:
const observer = new IntersectionObserver(entries => {
452
Removed:
for (const entry of entries) {
453
Removed:
if (entry.isIntersecting) {
454
Removed:
const id = entry.target.id;
455
Removed:
navLinks.forEach(link => {
456
Removed:
link.classList.toggle("active", link.getAttribute("href") === `#${id}`);
457
Removed:
});
458
Removed:
}
459
Removed:
}
460
Removed:
}, { rootMargin: "-20% 0px -60% 0px" });
461
Removed:
462
Removed:
sections.forEach(section => observer.observe(section));
463
Removed:
}
roles/dashboard/t/08-insights.t
@@ -19,16 +19,6 @@
19
19
->element_exists('[data-default-timeframe="day"]');
20
20
};
21
21
22
Removed:
subtest 'insights page has section anchors and nav' => sub {
23
Removed:
$t->get_ok('/insights')
24
Removed:
->status_is(200)
25
Removed:
->element_exists('nav.insights-nav')
26
Removed:
->element_exists('a.nav-link[href="#at-a-glance"]')
27
Removed:
->element_exists('a.nav-link[href="#explore"]')
28
Removed:
->element_exists('section#at-a-glance')
29
Removed:
->element_exists('section#explore');
30
Removed:
};
31
Removed:
32
22
subtest 'insights page has all chart canvases' => sub {
33
23
$t->get_ok('/insights')
34
24
->status_is(200)
roles/dashboard/templates/dashboard/insights.html.ep
@@ -11,116 +11,89 @@
11
11
%= include 'dashboard/graph-control', aria_label => 'Insights timeframe', default_timeframe => 'day'
12
12
</div>
13
13
14
Removed:
<nav class="insights-nav mb-4" aria-label="Insight sections">
15
Removed:
<ul class="nav nav-pills nav-fill flex-nowrap overflow-x-auto">
16
Removed:
<li class="nav-item">
17
Removed:
<a class="nav-link" href="#at-a-glance">At a Glance</a>
18
Removed:
</li>
19
Removed:
<li class="nav-item">
20
Removed:
<a class="nav-link" href="#explore">Explore</a>
21
Removed:
</li>
22
Removed:
</ul>
23
Removed:
</nav>
24
Removed:
25
Removed:
<!-- ════════════════════════════════════════════════════════════════
26
Removed:
AT A GLANCE
27
Removed:
════════════════════════════════════════════════════════════════ -->
28
Removed:
<section id="at-a-glance" class="insight-theme mb-5">
29
Removed:
<h2 class="h5 fw-bold mb-3 text-body-secondary">At a Glance</h2>
30
Removed:
31
Removed:
<div class="row g-3">
32
Removed:
<div class="col-12" id="stability">
33
Removed:
<div class="card">
34
Removed:
<div class="card-header">
35
Removed:
<h3 class="h6 mb-0">System Stability</h3>
36
Removed:
<p class="text-body-secondary small mb-0 mt-1">
37
Removed:
A <strong>lower score means more stable</strong>.
38
Removed:
This index is the rolling standard deviation (σ) of all probe values
39
Removed:
over a 6-hour window, normalised to each probe's optimal range.
40
Removed:
Spikes indicate rapid or large deviations from normal operating conditions.
41
Removed:
</p>
14
Added:
<div class="row g-3">
15
Added:
<div class="col-12" id="stability">
16
Added:
<div class="card">
17
Added:
<div class="card-header">
18
Added:
<h2 class="h6 mb-0">System Stability</h2>
19
Added:
<p class="text-body-secondary small mb-0 mt-1">
20
Added:
A <strong>lower score means more stable</strong>.
21
Added:
This index is the rolling standard deviation (σ) of all probe values
22
Added:
over a 6-hour window, normalised to each probe's optimal range.
23
Added:
Spikes indicate rapid or large deviations from normal operating conditions.
24
Added:
</p>
25
Added:
</div>
26
Added:
<div class="card-body">
27
Added:
<div class="chart-wrap">
28
Added:
<canvas id="chart-stability" role="img" aria-label="System stability score — lower is better"></canvas>
42
29
</div>
43
Removed:
<div class="card-body">
44
Removed:
<div class="chart-wrap">
45
Removed:
<canvas id="chart-stability" role="img" aria-label="System stability score — lower is better"></canvas>
46
Removed:
</div>
47
Removed:
</div>
48
30
</div>
49
31
</div>
32
Added:
</div>
50
33
51
Removed:
<div class="col-12" id="rate-of-change">
52
Removed:
<div class="card">
53
Removed:
<div class="card-header">
54
Removed:
<h3 class="h6 mb-0">Rate of Change</h3>
55
Removed:
<p class="text-body-secondary small mb-0 mt-1">
56
Removed:
Normalised rate of change per probe (% of optimal range per hour).
57
Removed:
Values near zero mean the parameter is steady.
58
Removed:
</p>
34
Added:
<div class="col-12" id="rate-of-change">
35
Added:
<div class="card">
36
Added:
<div class="card-header">
37
Added:
<h2 class="h6 mb-0">Rate of Change</h2>
38
Added:
<p class="text-body-secondary small mb-0 mt-1">
39
Added:
Normalised rate of change per probe (% of optimal range per hour).
40
Added:
Values near zero mean the parameter is steady.
41
Added:
</p>
42
Added:
</div>
43
Added:
<div class="card-body">
44
Added:
<div class="chart-wrap">
45
Added:
<canvas id="chart-derivatives" role="img" aria-label="Normalised rate of change per probe"></canvas>
59
46
</div>
60
Removed:
<div class="card-body">
61
Removed:
<div class="chart-wrap">
62
Removed:
<canvas id="chart-derivatives" role="img" aria-label="Normalised rate of change per probe"></canvas>
63
Removed:
</div>
64
Removed:
</div>
65
47
</div>
66
48
</div>
49
Added:
</div>
67
50
68
Removed:
<div class="col-12" id="diurnal">
69
Removed:
<div class="card">
70
Removed:
<div class="card-header">
71
Removed:
<h3 class="h6 mb-0">DO Diurnal Pattern</h3>
72
Removed:
<p class="text-body-secondary small mb-0 mt-1">
73
Removed:
Day/night DO cycle — each line is one day, bold is the average
74
Removed:
</p>
51
Added:
<div class="col-12" id="diurnal">
52
Added:
<div class="card">
53
Added:
<div class="card-header">
54
Added:
<h2 class="h6 mb-0">DO Diurnal Pattern</h2>
55
Added:
<p class="text-body-secondary small mb-0 mt-1">
56
Added:
Day/night DO cycle — each line is one day, bold is the average
57
Added:
</p>
58
Added:
</div>
59
Added:
<div class="card-body">
60
Added:
<div class="chart-wrap">
61
Added:
<canvas id="chart-diurnal" role="img" aria-label="Dissolved oxygen diurnal overlay"></canvas>
75
62
</div>
76
Removed:
<div class="card-body">
77
Removed:
<div class="chart-wrap">
78
Removed:
<canvas id="chart-diurnal" role="img" aria-label="Dissolved oxygen diurnal overlay"></canvas>
79
Removed:
</div>
80
Removed:
</div>
81
63
</div>
82
64
</div>
83
65
</div>
84
Removed:
</section>
85
66
86
Removed:
<!-- ════════════════════════════════════════════════════════════════
87
Removed:
EXPLORE — Same timeframe as above (page-level controls)
88
Removed:
════════════════════════════════════════════════════════════════ -->
89
Removed:
<section id="explore" class="insight-theme mb-5">
90
Removed:
<h2 class="h5 fw-bold mb-3 text-body-secondary">Explore</h2>
91
Removed:
92
Removed:
<div class="row g-3">
93
Removed:
<div class="col-12" id="do-orp-overlay">
94
Removed:
<div class="card">
95
Removed:
<div class="card-header">
96
Removed:
<h3 class="h6 mb-0">DO & ORP Over Time</h3>
97
Removed:
<p class="text-body-secondary small mb-0 mt-1">
98
Removed:
Dual-axis overlay — correlated drops indicate oxygen-driven redox shifts
99
Removed:
</p>
67
Added:
<div class="col-12" id="do-orp-overlay">
68
Added:
<div class="card">
69
Added:
<div class="card-header">
70
Added:
<h2 class="h6 mb-0">DO & ORP Over Time</h2>
71
Added:
<p class="text-body-secondary small mb-0 mt-1">
72
Added:
Dual-axis overlay — correlated drops indicate oxygen-driven redox shifts
73
Added:
</p>
74
Added:
</div>
75
Added:
<div class="card-body">
76
Added:
<div class="chart-wrap">
77
Added:
<canvas id="chart-overlay-do-orp" role="img" aria-label="DO and ORP overlay chart"></canvas>
100
78
</div>
101
Removed:
<div class="card-body">
102
Removed:
<div class="chart-wrap">
103
Removed:
<canvas id="chart-overlay-do-orp" role="img" aria-label="DO and ORP overlay chart"></canvas>
104
Removed:
</div>
105
Removed:
</div>
106
79
</div>
107
80
</div>
81
Added:
</div>
108
82
109
Removed:
<div class="col-12" id="ph-do-lag">
110
Removed:
<div class="card">
111
Removed:
<div class="card-header">
112
Removed:
<h3 class="h6 mb-0">pH ↔ DO Relationship</h3>
113
Removed:
<p class="text-body-secondary small mb-0 mt-1">
114
Removed:
Nitrification link — DO drops often precede pH drops
115
Removed:
</p>
83
Added:
<div class="col-12" id="ph-do-lag">
84
Added:
<div class="card">
85
Added:
<div class="card-header">
86
Added:
<h2 class="h6 mb-0">pH ↔ DO Relationship</h2>
87
Added:
<p class="text-body-secondary small mb-0 mt-1">
88
Added:
Nitrification link — DO drops often precede pH drops
89
Added:
</p>
90
Added:
</div>
91
Added:
<div class="card-body">
92
Added:
<div class="chart-wrap">
93
Added:
<canvas id="chart-ph-do-lag" role="img" aria-label="pH and DO relationship overlay"></canvas>
116
94
</div>
117
Removed:
<div class="card-body">
118
Removed:
<div class="chart-wrap">
119
Removed:
<canvas id="chart-ph-do-lag" role="img" aria-label="pH and DO relationship overlay"></canvas>
120
Removed:
</div>
121
Removed:
</div>
122
95
</div>
123
96
</div>
124
97
</div>
125
Removed:
</section>
98
Added:
</div>
126
99
</section>