@@ -158,7 +158,6 @@ static const char VIEWER_DASHBOARD_HTML[] PROGMEM = R"HTML(
158158 --header-bg: #ffffff;
159159 --meta-color: #475569;
160160 --card-bg: #ffffff;
161- --filter-bg: #ffffff;
162161 --table-border: rgba(15,23,42,0.08);
163162 }
164163 body[data-theme="dark"] {
@@ -167,7 +166,6 @@ static const char VIEWER_DASHBOARD_HTML[] PROGMEM = R"HTML(
167166 --header-bg: #1e293b;
168167 --meta-color: #94a3b8;
169168 --card-bg: #1e293b;
170- --filter-bg: #1e293b;
171169 --table-border: rgba(255,255,255,0.08);
172170 }
173171 body { margin: 0; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; background: var(--bg); color: var(--text); transition: background 0.3s, color 0.3s; }
@@ -179,13 +177,6 @@ static const char VIEWER_DASHBOARD_HTML[] PROGMEM = R"HTML(
179177 .icon-button { width: 40px; height: 40px; border-radius: 50%; border: 1px solid rgba(148,163,184,0.4); background: var(--card-bg); color: var(--text); font-size: 1.1rem; cursor: pointer; }
180178 main { padding: 24px; max-width: 1400px; margin: 0 auto; }
181179 .card { background: var(--card-bg); border-radius: 16px; padding: 20px; box-shadow: 0 25px 60px rgba(15,23,42,0.15); border: 1px solid rgba(15,23,42,0.08); }
182- .filter-bar { display: flex; flex-wrap: wrap; gap: 16px; align-items: flex-end; margin-bottom: 20px; background: var(--filter-bg); padding: 12px 16px; border-radius: 12px; box-shadow: 0 10px 30px rgba(15,23,42,0.15); border: 1px solid rgba(15,23,42,0.08); }
183- .filter-bar label { display: flex; flex-direction: column; font-size: 0.9rem; color: var(--meta-color); }
184- .filter-bar select { margin-top: 6px; padding: 8px 10px; border-radius: 6px; border: 1px solid rgba(148,163,184,0.4); background: var(--bg); color: var(--text); min-width: 220px; }
185- .filter-actions { display: flex; gap: 12px; flex-wrap: wrap; }
186- .btn { padding: 10px 16px; border-radius: 999px; border: none; background: linear-gradient(135deg,#22d3ee,#818cf8); color: #0f172a; font-weight: 600; cursor: pointer; box-shadow: 0 15px 30px rgba(14,165,233,0.25); transition: transform 0.15s ease, box-shadow 0.15s ease; }
187- .btn:disabled { opacity: 0.55; cursor: not-allowed; box-shadow: none; }
188- .btn:not(:disabled):hover { transform: translateY(-1px); box-shadow: 0 20px 40px rgba(14,165,233,0.45); }
189180 table { width: 100%; border-collapse: collapse; margin-top: 12px; }
190181 th, td { text-align: left; padding: 10px 12px; border-bottom: 1px solid var(--table-border); }
191182 th { text-transform: uppercase; letter-spacing: 0.05em; font-size: 0.75rem; color: var(--meta-color); }
@@ -219,18 +210,6 @@ static const char VIEWER_DASHBOARD_HTML[] PROGMEM = R"HTML(
219210 </div>
220211 </header>
221212 <main>
222- <div class="filter-bar">
223- <label>
224- Site Filter
225- <select id="siteFilter">
226- <option value="">All Sites</option>
227- </select>
228- </label>
229- <div class="filter-actions">
230- <button class="btn" id="refreshSiteBtn">Refresh Selected Site</button>
231- <button class="btn" id="refreshAllBtn">Refresh All Sites</button>
232- </div>
233- </div>
234213 <section class="card">
235214 <div style="display:flex; justify-content: space-between; align-items: baseline; gap: 12px; flex-wrap: wrap;">
236215 <h2 style="margin:0; font-size:1.2rem;">Fleet Snapshot</h2>
@@ -280,19 +259,14 @@ static const char VIEWER_DASHBOARD_HTML[] PROGMEM = R"HTML(
280259 lastFetch: document.getElementById('lastFetch'),
281260 nextFetch: document.getElementById('nextFetch'),
282261 refreshHint: document.getElementById('refreshHint'),
283- tankBody: document.getElementById('tankBody'),
284- siteFilter: document.getElementById('siteFilter'),
285- refreshSiteBtn: document.getElementById('refreshSiteBtn'),
286- refreshAllBtn: document.getElementById('refreshAllBtn')
262+ tankBody: document.getElementById('tankBody')
287263 };
288264
289265 const state = {
290- tanks: [],
291- selected: '',
292- refreshing: false
266+ tanks: []
293267 };
294268
295- function applyTankData(data, preferredUid ) {
269+ function applyTankData(data) {
296270 els.viewerName.textContent = data.viewerName || 'Tank Alarm Viewer';
297271 els.viewerUid.textContent = data.viewerUid || '--';
298272 els.sourceServer.textContent = data.sourceServerName || 'Server';
@@ -302,78 +276,24 @@ static const char VIEWER_DASHBOARD_HTML[] PROGMEM = R"HTML(
302276 els.nextFetch.textContent = formatEpoch(data.nextFetchEpoch);
303277 els.refreshHint.textContent = describeCadence(data.refreshSeconds, data.baseHour);
304278 state.tanks = data.tanks || [];
305- const desired = preferredUid || state.selected;
306- populateSiteFilter(desired);
307279 renderTankRows();
308280 }
309281
310- async function fetchTanks(preferredUid ) {
282+ async function fetchTanks() {
311283 try {
312284 const res = await fetch('/api/tanks');
313285 if (!res.ok) throw new Error('HTTP ' + res.status);
314286 const data = await res.json();
315- applyTankData(data, preferredUid );
287+ applyTankData(data);
316288 } catch (err) {
317289 console.error('Viewer refresh failed', err);
318290 }
319291 }
320292
321- async function triggerManualRefresh(targetUid) {
322- const payload = targetUid ? { client: targetUid } : {};
323- setRefreshBusy(true);
324- try {
325- const res = await fetch('/api/refresh', {
326- method: 'POST',
327- headers: { 'Content-Type': 'application/json' },
328- body: JSON.stringify(payload)
329- });
330- if (!res.ok) {
331- const text = await res.text();
332- throw new Error(text || 'Refresh failed');
333- }
334- const data = await res.json();
335- applyTankData(data, targetUid || state.selected);
336- } catch (err) {
337- console.error('Manual refresh failed', err);
338- } finally {
339- setRefreshBusy(false);
340- }
341- }
342-
343- function populateSiteFilter(preferredUid) {
344- const uniqueClients = new Map();
345- state.tanks.forEach(tank => {
346- if (!tank.client) return;
347- if (!uniqueClients.has(tank.client)) {
348- const label = tank.site || `Client ${tank.client.slice(-4)}`;
349- uniqueClients.set(tank.client, label);
350- }
351- });
352- const select = els.siteFilter;
353- select.innerHTML = '<option value="">All Sites</option>';
354- uniqueClients.forEach((label, uid) => {
355- const option = document.createElement('option');
356- const suffix = uid.length > 6 ? uid.slice(-6) : uid;
357- option.value = uid;
358- option.textContent = `${label} (${suffix})`;
359- select.appendChild(option);
360- });
361- if (preferredUid && uniqueClients.has(preferredUid)) {
362- select.value = preferredUid;
363- state.selected = preferredUid;
364- } else if (!uniqueClients.has(state.selected)) {
365- select.value = '';
366- state.selected = '';
367- } else {
368- select.value = state.selected;
369- }
370- updateButtonState();
371- }
372-
373293 function renderTankRows() {
374294 const tbody = els.tankBody;
375295 tbody.innerHTML = '';
376- const rows = state.selected ? state.tanks.filter(t => t.client === state.selected) : state. tanks;
296+ const rows = state.tanks;
377297 if (!rows.length) {
378298 const tr = document.createElement('tr');
379299 tr.innerHTML = '<td colspan="5">No tank data available</td>';
@@ -443,36 +363,8 @@ static const char VIEWER_DASHBOARD_HTML[] PROGMEM = R"HTML(
443363 return String(value).replace(/[&<>"']/g, c => entityMap[c] || c);
444364 }
445365
446- function setRefreshBusy(busy) {
447- state.refreshing = busy;
448- updateButtonState();
449- }
450-
451- function updateButtonState() {
452- els.refreshAllBtn.disabled = state.refreshing;
453- els.refreshSiteBtn.disabled = state.refreshing || !state.selected;
454- }
455-
456- els.siteFilter.addEventListener('change', event => {
457- state.selected = event.target.value;
458- renderTankRows();
459- updateButtonState();
460- });
461-
462- els.refreshSiteBtn.addEventListener('click', () => {
463- if (!state.selected) {
464- alert('Select a site to refresh.');
465- return;
466- }
467- triggerManualRefresh(state.selected);
468- });
469-
470- els.refreshAllBtn.addEventListener('click', () => {
471- triggerManualRefresh(null);
472- });
473-
474366 fetchTanks();
475- setInterval(() => fetchTanks(state.selected ), REFRESH_SECONDS * 1000);
367+ setInterval(() => fetchTanks(), REFRESH_SECONDS * 1000);
476368 })();
477369 </script>
478370</body>
0 commit comments