refactor remove toolbar status pill, keep header LED only

The status-summary pill in the toolbar duplicated the header LED indicator. Remove it to declutter the toolbar. - Remove status pill from toolbar template and its show_overview_status stash variable from all controller actions - Remove loadOverview, setStatusPill, statusTitle from status.js - Remove .status-summary CSS rules - Remove data-sensor-status hidden spans (only used by loadOverview) - Header LED continues to indicate overall DAQ health

Commit
6076b70e307447de918bb83e69c0c3bfe0920be1
Author
GPT-5 medium <codex@openai.com>
Author date
Committer
GPT-5 medium <codex@openai.com>
Committer date
Changed files
roles/dashboard/lib/FAPG/DAQ/Dashboard/Controller/Dashboard.pm
index b7b4acf7..a55bd8e7 100644..100644
@@ -15,11 +15,10 @@
15 15
16 16 sub status ($self) {
17 17 $self->render(
18 Removed: template => 'dashboard/status',
19 Removed: items => $self->status_items,
20 Removed: nav_page => 'status',
21 Removed: show_overview_status => 1,
22 Removed: breadcrumbs =>
18 Added: template => 'dashboard/status',
19 Added: items => $self->status_items,
20 Added: nav_page => 'status',
21 Added: breadcrumbs =>
23 22 [ { label => 'Home', href => '/' }, { label => 'Status' }, ],
24 23 );
25 24 }
@@ -30,7 +29,6 @@
30 29 probes => $self->probes,
31 30 wide_layout => 1,
32 31 nav_page => 'probes',
33 Removed: show_overview_status => 1,
34 32 breadcrumbs =>
35 33 [ { label => 'Home', href => '/' }, { label => 'Probes' }, ],
36 34 graph_control_aria_label => 'All probe chart timeframes',
@@ -66,8 +64,7 @@
66 64 to => $to,
67 65 oldest => $oldest,
68 66 probes => $self->probes,
69 Removed: nav_page => 'downloads',
70 Removed: show_overview_status => 1,
67 Added: nav_page => 'downloads',
71 68 breadcrumbs =>
72 69 [ { label => 'Home', href => '/' }, { label => 'Downloads' }, ],
73 70 );
@@ -83,7 +80,6 @@
83 80 template => 'dashboard/graph',
84 81 probe => $probe,
85 82 nav_page => 'probes',
86 Removed: show_overview_status => 1,
87 83 single_probe => 1,
88 84 breadcrumbs => [
89 85 { label => 'Home', href => '/' },
roles/dashboard/public/css/app.css
index 5ec0aa3a..52a9069d 100644..100644
@@ -124,23 +124,6 @@
124 124 color: var(--fapg-unknown) !important;
125 125 }
126 126
127 Removed: /* Status summary pill in the toolbar */
128 Removed: .status-summary {
129 Removed: display: inline-flex;
130 Removed: align-items: center;
131 Removed: justify-content: center;
132 Removed: min-width: 11rem;
133 Removed: border-radius: 999px;
134 Removed: padding: 0.4rem 0.85rem;
135 Removed: font-size: 0.82rem;
136 Removed: font-weight: 700;
137 Removed: text-decoration: none;
138 Removed: }
139 Removed:
140 Removed: .status-summary[href]:hover {
141 Removed: filter: brightness(0.97);
142 Removed: }
143 Removed:
144 127 /* ----------------------------------------------------------------
145 128 Status node marker — LED dot on the status page
146 129 ---------------------------------------------------------------- */
roles/dashboard/public/js/dashboard/status.js
index 9f80b5cb..a90fe0de 100644..100644
@@ -26,56 +26,7 @@
26 26 return "unknown";
27 27 }
28 28
29 Removed: function setStatusPill(element, state, text = statusLabel(state)) {
30 Removed: element.classList.remove(
31 Removed: "is-online", "is-healthy", "is-stale", "is-probe-error",
32 Removed: "is-offline", "is-unreachable", "is-unknown"
33 Removed: );
34 Removed: element.classList.add(`is-${state}`);
35 Removed: element.querySelector("[data-status-text]").textContent = text;
36 Removed: }
37 Removed:
38 Removed: function statusTitle(nodeStatus) {
39 Removed: if (!nodeStatus) return "No recent node status message has been stored.";
40 Removed:
41 Removed: const detail = nodeStatus.error || nodeStatus.message || "";
42 Removed: const timestamp = nodeStatus.received_at || nodeStatus.timestamp;
43 Removed: const when = timestamp
44 Removed: ? `${formatDateTime(timestamp)} (${formatAge(ageMs(timestamp))})`
45 Removed: : "unknown time";
46 Removed:
47 Removed: return [detail, `Status received at ${when}`].filter(Boolean).join(" ");
48 Removed: }
49 Removed:
50 Removed: function loadOverview(statuses) {
51 Removed: const overview = document.querySelector("[data-overview-status]");
52 Removed: if (!overview) return;
53 Removed:
54 Removed: const rows = Array.from(document.querySelectorAll("[data-sensor-status]"));
55 Removed: const items = rows.map(row => {
56 Removed: const status = statuses[row.dataset.sensorStatus] || null;
57 Removed:
58 Removed: return { status, state: stateForNodeStatus(status) };
59 Removed: });
60 Removed: const unhealthy = items.filter(item => item.state !== "healthy");
61 Removed:
62 Removed: if (!items.length) {
63 Removed: setStatusPill(overview, "unknown", "No sensors configured");
64 Removed: } else if (!unhealthy.length) {
65 Removed: setStatusPill(overview, "healthy", "All sensors healthy");
66 Removed: overview.title = "Every sensor node has sent a recent healthy status.";
67 Removed: } else {
68 Removed: const state = unhealthy.some(item => item.state === "unreachable")
69 Removed: ? "unreachable"
70 Removed: : "probe-error";
71 Removed: const label = unhealthy.length === 1 ? "sensor needs" : "sensors need";
72 Removed:
73 Removed: setStatusPill(overview, state, `${unhealthy.length} ${label} attention`);
74 Removed: overview.title = unhealthy.map(item => statusTitle(item.status)).join(" ");
75 Removed: }
76 Removed: }
77 Removed:
78 Removed: function setHeaderStatus(state, text) {
29 Added: function loadHeaderStatus(statuses) {
79 30 const element = document.querySelector("[data-header-status]");
80 31 if (!element) return;
81 32
@@ -137,7 +88,7 @@
137 88 export function createStatusLoader() {
138 89 return async function loadStatuses() {
139 90 const hasStatusElements = document.querySelector(
140 Removed: "[data-overview-status], [data-header-status], [data-status-page-item]"
91 Added: "[data-header-status], [data-status-page-item]"
141 92 );
142 93 if (!hasStatusElements) return;
143 94
@@ -148,7 +99,6 @@
148 99 // Render every configured item as unreachable when the bulk request fails.
149 100 }
150 101
151 Removed: loadOverview(statuses);
152 102 loadHeaderStatus(statuses);
153 103 loadStatusPage(statuses);
154 104 };
roles/dashboard/t/01-graph-page.t
index decb5f7d..3efe9a4d 100644..100644
@@ -60,9 +60,7 @@
60 60 ->element_exists('main.container-wide')
61 61 ->element_exists('div.probes-grid')
62 62 ->element_exists('div.toolbar-items div.graph-control')
63 Removed: ->element_exists('.navbar-nav a.nav-link.active[href="/probes"][aria-current="page"]')
64 Removed: ->element_exists(
65 Removed: 'div.toolbar-items a.status-summary[href="/status"][data-overview-status]');
63 Added: ->element_exists('.navbar-nav a.nav-link.active[href="/probes"][aria-current="page"]');
66 64
67 65 for my $probe (qw(ph do orp ec)) {
68 66 $t->element_exists(qq{div.probes-grid .card-header h1 a[href="/probes/$probe"]});
roles/dashboard/templates/dashboard/index.html.ep
index 05b4001b..b98f50fa 100644..100644
@@ -5,13 +5,6 @@
5 5 % stash use_charts => 1;
6 6
7 7 <section class="mb-4" aria-label="DAQ status overview">
8 Removed: % for my $probe ($probes->@*) {
9 Removed: <span
10 Removed: hidden
11 Removed: data-sensor-status="<%= $probe->{key} %>"
12 Removed: data-sensor-label="<%= $probe->{label} %>"></span>
13 Removed: % }
14 Removed:
15 8 <div class="mb-3">
16 9 <h1 class="h4 fw-bold mb-1">FAPG DAQ Dashboard</h1>
17 10 <p class="text-muted mb-0">Live aquaponic sensor readings</p>
roles/dashboard/templates/dashboard/toolbar.html.ep
index 310990ed..7fd363fa 100644..100644
@@ -16,16 +16,9 @@
16 16 % }
17 17 </ol>
18 18 </nav>
19 Removed: % if (defined $graph_control_aria_label || $show_overview_status) {
19 Added: % if (defined $graph_control_aria_label) {
20 20 <div class="toolbar-items d-flex align-items-center gap-2 ms-auto">
21 Removed: % if (defined $graph_control_aria_label) {
22 21 %= include 'dashboard/graph-control', aria_label => $graph_control_aria_label
23 Removed: % }
24 Removed: % if ($show_overview_status) {
25 Removed: <a class="status-pill status-summary is-unknown" href="/status" data-overview-status>
26 Removed: <span data-status-text>Checking sensors</span>
27 Removed: </a>
28 Removed: % }
29 22 </div>
30 23 % }
31 24 </div>
roles/dashboard/templates/layouts/default.html.ep
index bd7ed4e9..9cb5de24 100644..100644
@@ -71,7 +71,7 @@
71 71 </nav>
72 72
73 73 <main class="<%= stash('wide_layout') ? 'container-wide' : 'container' %>">
74 Removed: %= include 'dashboard/toolbar', breadcrumbs => (stash('breadcrumbs') // []), graph_control_aria_label => stash('graph_control_aria_label'), show_overview_status => stash('show_overview_status')
74 Added: %= include 'dashboard/toolbar', breadcrumbs => (stash('breadcrumbs') // []), graph_control_aria_label => stash('graph_control_aria_label')
75 75 <%= content %>
76 76 </main>
77 77