Custom View: native sticky header, one-line Excel-style header; fixes

- Custom View header now uses the browser's sticky positioning like the
  other tables, so it no longer lags or bounces while scrolling. Because a
  sideways-scrolling box prevents sticky headers, the table is clipped and
  shifted sideways by a scrollbar pinned to the bottom of the window
  (shown only when the columns are wider than the page; trackpad,
  shift+wheel and touch swipes drive it too)
- Custom View header on one line like the other tables: drag grip, name,
  the combined sort/filter dropdown and copy icon (remove on hover)
- Workbench stack text boxes size to their contents on load and when the
  page is shown, not only while typing
- Demo sandbox waits for the worker's first sweep after a container
  restart instead of treating every device as unknown
This commit is contained in:
Johan Sandoval committed 2026-10-06 17:48:54 +00:00
1 parent b216ce43f2
commit 318c59e610
4 files changed
+114 -31

No files matched your search

+10 -2
View File
@@ -555,6 +555,12 @@
const tracked = await visitorTracked();
const applied = s.appliedTracked || tracked;
const snap = await serverSnapshot();
if (!snap.rows.length) { // container just started: nothing to sweep against yet
w([['[Waiting for the first worker sweep to finish...]', 'DarkGray']]);
Sim.again = kind;
await sleep(5000);
return;
}
const before = new Set(Object.keys(parseRoster(applied).tagMap));
const { rows } = buildRows(tracked, snap.rows, snap.adv);
const { tagMap } = parseRoster(tracked);
@@ -700,14 +706,16 @@
'GET Data.json': async () => {
const s = Store.state;
const snap = await serverSnapshot();
if (!s.appliedTracked) return jsonResponse(snap.data);
// Until the worker's first sweep there are no rows to merge with: pass through so
// the dashboard shows its "Waiting for Worker..." placeholders
if (!s.appliedTracked || !snap.rows.length) return jsonResponse(snap.data);
const { rows } = buildRows(s.appliedTracked, snap.rows, snap.adv);
return jsonResponse({ LastUpdated: snap.data.LastUpdated || psStamp(), Devices: rows });
},
'GET Advanced-Cache.json': async () => {
const s = Store.state;
const snap = await serverSnapshot();
if (!s.appliedTracked) return jsonResponse(snap.adv);
if (!s.appliedTracked || !snap.rows.length) return jsonResponse(snap.adv);
const { adv } = buildRows(s.appliedTracked, snap.rows, snap.adv);
for (const [k, val] of Object.entries(adv)) if (val) snap.adv[k] = val;
return jsonResponse(snap.adv);