[Perl] DAQ system for the FAPG.
feat tuck insight explainers behind info toggle
Replace always-visible explainer paragraphs with a collapsible panel toggled by an ⓘ button in each card header. Uses Bootstrap collapse with aria-expanded/aria-controls for WCAG compliance. The SVG info-circle icon has aria-hidden and the button carries an aria-label for screen readers.
Changed files
roles/dashboard/public/css/app.css
@@ -57,6 +57,19 @@
57
57
margin-bottom: 0.5rem;
58
58
}
59
59
60
Added:
/* Info toggle button in insight card headers */
61
Added:
.info-toggle {
62
Added:
line-height: 1;
63
Added:
opacity: 0.5;
64
Added:
transition: opacity 0.15s;
65
Added:
}
66
Added:
67
Added:
.info-toggle:hover,
68
Added:
.info-toggle:focus-visible,
69
Added:
.info-toggle[aria-expanded="true"] {
70
Added:
opacity: 1;
71
Added:
}
72
Added:
60
73
#toolbar .toolbar-items {
61
74
min-width: 0;
62
75
}
roles/dashboard/templates/dashboard/insights.html.ep
@@ -14,15 +14,31 @@
14
14
<div class="row g-3">
15
15
<div class="col-12" id="stability">
16
16
<div class="card">
17
Removed:
<div class="card-header">
17
Added:
<div class="card-header d-flex align-items-start justify-content-between">
18
18
<h2 class="h6 mb-0">System Stability</h2>
19
Removed:
<p class="text-body-secondary small mb-0 mt-1">
20
Removed:
A <strong>lower score means more stable</strong>.
21
Removed:
This index is the rolling standard deviation (σ) of all probe values
22
Removed:
over a 6-hour window, normalised to each probe's optimal range.
23
Removed:
Spikes indicate rapid or large deviations from normal operating conditions.
24
Removed:
</p>
19
Added:
<button class="btn btn-sm btn-link text-body-secondary p-0 ms-2 info-toggle"
20
Added:
type="button"
21
Added:
data-bs-toggle="collapse"
22
Added:
data-bs-target="#info-stability"
23
Added:
aria-expanded="false"
24
Added:
aria-controls="info-stability"
25
Added:
aria-label="About this chart">
26
Added:
<svg width="18" height="18" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true">
27
Added:
<path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14m0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16"/>
28
Added:
<path d="m8.93 6.588-2.29.287-.082.38.45.083c.294.07.352.176.288.469l-.738 3.468c-.194.897.105 1.319.808 1.319.545 0 1.178-.252 1.465-.598l.088-.416c-.2.176-.492.246-.686.246-.275 0-.375-.193-.304-.533zM9 4.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0"/>
29
Added:
</svg>
30
Added:
</button>
25
31
</div>
32
Added:
<div class="collapse" id="info-stability">
33
Added:
<div class="card-body border-bottom py-2">
34
Added:
<p class="text-body-secondary small mb-0">
35
Added:
A <strong>lower score means more stable</strong>.
36
Added:
This index is the rolling standard deviation (σ) of all probe values
37
Added:
over a 6-hour window, normalised to each probe's optimal range.
38
Added:
Spikes indicate rapid or large deviations from normal operating conditions.
39
Added:
</p>
40
Added:
</div>
41
Added:
</div>
26
42
<div class="card-body">
27
43
<div class="chart-wrap">
28
44
<canvas id="chart-stability" role="img" aria-label="System stability score — lower is better"></canvas>
@@ -33,13 +49,29 @@
33
49
34
50
<div class="col-12" id="rate-of-change">
35
51
<div class="card">
36
Removed:
<div class="card-header">
52
Added:
<div class="card-header d-flex align-items-start justify-content-between">
37
53
<h2 class="h6 mb-0">Rate of Change</h2>
38
Removed:
<p class="text-body-secondary small mb-0 mt-1">
39
Removed:
Normalised rate of change per probe (% of optimal range per hour).
40
Removed:
Values near zero mean the parameter is steady.
41
Removed:
</p>
54
Added:
<button class="btn btn-sm btn-link text-body-secondary p-0 ms-2 info-toggle"
55
Added:
type="button"
56
Added:
data-bs-toggle="collapse"
57
Added:
data-bs-target="#info-derivatives"
58
Added:
aria-expanded="false"
59
Added:
aria-controls="info-derivatives"
60
Added:
aria-label="About this chart">
61
Added:
<svg width="18" height="18" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true">
62
Added:
<path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14m0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16"/>
63
Added:
<path d="m8.93 6.588-2.29.287-.082.38.45.083c.294.07.352.176.288.469l-.738 3.468c-.194.897.105 1.319.808 1.319.545 0 1.178-.252 1.465-.598l.088-.416c-.2.176-.492.246-.686.246-.275 0-.375-.193-.304-.533zM9 4.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0"/>
64
Added:
</svg>
65
Added:
</button>
42
66
</div>
67
Added:
<div class="collapse" id="info-derivatives">
68
Added:
<div class="card-body border-bottom py-2">
69
Added:
<p class="text-body-secondary small mb-0">
70
Added:
Normalised rate of change per probe (% of optimal range per hour).
71
Added:
Values near zero mean the parameter is steady.
72
Added:
</p>
73
Added:
</div>
74
Added:
</div>
43
75
<div class="card-body">
44
76
<div class="chart-wrap">
45
77
<canvas id="chart-derivatives" role="img" aria-label="Normalised rate of change per probe"></canvas>
@@ -50,12 +82,28 @@
50
82
51
83
<div class="col-12" id="diurnal">
52
84
<div class="card">
53
Removed:
<div class="card-header">
85
Added:
<div class="card-header d-flex align-items-start justify-content-between">
54
86
<h2 class="h6 mb-0">DO Diurnal Pattern</h2>
55
Removed:
<p class="text-body-secondary small mb-0 mt-1">
56
Removed:
Day/night DO cycle — each line is one day, bold is the average
57
Removed:
</p>
87
Added:
<button class="btn btn-sm btn-link text-body-secondary p-0 ms-2 info-toggle"
88
Added:
type="button"
89
Added:
data-bs-toggle="collapse"
90
Added:
data-bs-target="#info-diurnal"
91
Added:
aria-expanded="false"
92
Added:
aria-controls="info-diurnal"
93
Added:
aria-label="About this chart">
94
Added:
<svg width="18" height="18" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true">
95
Added:
<path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14m0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16"/>
96
Added:
<path d="m8.93 6.588-2.29.287-.082.38.45.083c.294.07.352.176.288.469l-.738 3.468c-.194.897.105 1.319.808 1.319.545 0 1.178-.252 1.465-.598l.088-.416c-.2.176-.492.246-.686.246-.275 0-.375-.193-.304-.533zM9 4.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0"/>
97
Added:
</svg>
98
Added:
</button>
58
99
</div>
100
Added:
<div class="collapse" id="info-diurnal">
101
Added:
<div class="card-body border-bottom py-2">
102
Added:
<p class="text-body-secondary small mb-0">
103
Added:
Day/night DO cycle — each line is one day, bold is the average.
104
Added:
</p>
105
Added:
</div>
106
Added:
</div>
59
107
<div class="card-body">
60
108
<div class="chart-wrap">
61
109
<canvas id="chart-diurnal" role="img" aria-label="Dissolved oxygen diurnal overlay"></canvas>
@@ -66,12 +114,28 @@
66
114
67
115
<div class="col-12" id="do-orp-overlay">
68
116
<div class="card">
69
Removed:
<div class="card-header">
117
Added:
<div class="card-header d-flex align-items-start justify-content-between">
70
118
<h2 class="h6 mb-0">DO & ORP Over Time</h2>
71
Removed:
<p class="text-body-secondary small mb-0 mt-1">
72
Removed:
Dual-axis overlay — correlated drops indicate oxygen-driven redox shifts
73
Removed:
</p>
119
Added:
<button class="btn btn-sm btn-link text-body-secondary p-0 ms-2 info-toggle"
120
Added:
type="button"
121
Added:
data-bs-toggle="collapse"
122
Added:
data-bs-target="#info-do-orp"
123
Added:
aria-expanded="false"
124
Added:
aria-controls="info-do-orp"
125
Added:
aria-label="About this chart">
126
Added:
<svg width="18" height="18" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true">
127
Added:
<path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14m0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16"/>
128
Added:
<path d="m8.93 6.588-2.29.287-.082.38.45.083c.294.07.352.176.288.469l-.738 3.468c-.194.897.105 1.319.808 1.319.545 0 1.178-.252 1.465-.598l.088-.416c-.2.176-.492.246-.686.246-.275 0-.375-.193-.304-.533zM9 4.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0"/>
129
Added:
</svg>
130
Added:
</button>
74
131
</div>
132
Added:
<div class="collapse" id="info-do-orp">
133
Added:
<div class="card-body border-bottom py-2">
134
Added:
<p class="text-body-secondary small mb-0">
135
Added:
Dual-axis overlay — correlated drops indicate oxygen-driven redox shifts.
136
Added:
</p>
137
Added:
</div>
138
Added:
</div>
75
139
<div class="card-body">
76
140
<div class="chart-wrap">
77
141
<canvas id="chart-overlay-do-orp" role="img" aria-label="DO and ORP overlay chart"></canvas>
@@ -82,11 +146,27 @@
82
146
83
147
<div class="col-12" id="ph-do-lag">
84
148
<div class="card">
85
Removed:
<div class="card-header">
149
Added:
<div class="card-header d-flex align-items-start justify-content-between">
86
150
<h2 class="h6 mb-0">pH ↔ DO Relationship</h2>
87
Removed:
<p class="text-body-secondary small mb-0 mt-1">
88
Removed:
Nitrification link — DO drops often precede pH drops
89
Removed:
</p>
151
Added:
<button class="btn btn-sm btn-link text-body-secondary p-0 ms-2 info-toggle"
152
Added:
type="button"
153
Added:
data-bs-toggle="collapse"
154
Added:
data-bs-target="#info-ph-do"
155
Added:
aria-expanded="false"
156
Added:
aria-controls="info-ph-do"
157
Added:
aria-label="About this chart">
158
Added:
<svg width="18" height="18" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true">
159
Added:
<path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14m0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16"/>
160
Added:
<path d="m8.93 6.588-2.29.287-.082.38.45.083c.294.07.352.176.288.469l-.738 3.468c-.194.897.105 1.319.808 1.319.545 0 1.178-.252 1.465-.598l.088-.416c-.2.176-.492.246-.686.246-.275 0-.375-.193-.304-.533zM9 4.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0"/>
161
Added:
</svg>
162
Added:
</button>
163
Added:
</div>
164
Added:
<div class="collapse" id="info-ph-do">
165
Added:
<div class="card-body border-bottom py-2">
166
Added:
<p class="text-body-secondary small mb-0">
167
Added:
Nitrification link — DO drops often precede pH drops.
168
Added:
</p>
169
Added:
</div>
90
170
</div>
91
171
<div class="card-body">
92
172
<div class="chart-wrap">