From a7cef6b66126bbf746457225f060f6be62d94e54 Mon Sep 17 00:00:00 2001 From: Tyler <53561637+im-tyler@users.noreply.github.com> Date: Wed, 11 Nov 2026 16:21:07 -0700 Subject: [PATCH 01/11] dash: fix console errors, undefined colours and owner placeholders - cleanupPage and siblingsPage declare loading; guard the dismissed-by, sibling dashboard_url and cleanup detail.server reads that threw. - Define --success, --success-bg, --warning, --danger and --bg-inset so chips stop rendering near-white on dark. - Checkboxes inside .field keep their natural size; the Siblings probing consent line uses a neutral banner instead of the warning one. - Backups cards get spacing; the Monitors header drops the unrelated CLI version chip. - Public placeholders: git.example.com, example.com, shop-. - New frontend-test/nav_rework.test.mjs holds the checks for this rework. Co-Authored-By: Claude --- .../frontend-test/nav_rework.test.mjs | 43 +++++++++++++++++++ cmd/teploy-dash/frontend/css/style.css | 15 +++++++ cmd/teploy-dash/frontend/index.html | 36 +++++++--------- cmd/teploy-dash/frontend/js/app.js | 2 + 4 files changed, 76 insertions(+), 20 deletions(-) create mode 100644 cmd/teploy-dash/frontend-test/nav_rework.test.mjs diff --git a/cmd/teploy-dash/frontend-test/nav_rework.test.mjs b/cmd/teploy-dash/frontend-test/nav_rework.test.mjs new file mode 100644 index 0000000..f7bb1d6 --- /dev/null +++ b/cmd/teploy-dash/frontend-test/nav_rework.test.mjs @@ -0,0 +1,43 @@ +// Navigation and UI rework (2026-11-11): static checks over the shipped +// frontend that keep the fixed defects fixed. +// +// Run: node cmd/teploy-dash/frontend-test/nav_rework.test.mjs +import { readFileSync } from 'node:fs'; +import { fileURLToPath } from 'node:url'; +import { dirname, join } from 'node:path'; + +const here = dirname(fileURLToPath(import.meta.url)); +const read = (p) => readFileSync(join(here, '../frontend', p), 'utf8'); +const html = read('index.html'); +const js = read('js/app.js'); +const css = read('css/style.css'); +const failures = []; +const assert = (c, m) => { if (!c) failures.push(m); }; + +// Every CSS variable the frontend reads is defined. +{ + const used = new Set([...(html + js + css).matchAll(/var\((--[a-z0-9-]+)/g)].map((m) => m[1])); + const defined = new Set([...css.matchAll(/^\s*(--[a-z0-9-]+):/gm)].map((m) => m[1])); + for (const v of used) assert(defined.has(v), `CSS variable ${v} is used but never defined`); +} + +// No owner-specific addresses or product names in a public product. +for (const bad of [/100\.108\.\d+\.\d+/, /akiroo/i, /fylun/i, /:49152/]) { + assert(!bad.test(html) && !bad.test(js), `owner-specific text ${bad} in the frontend`); +} + +// Components whose templates read `loading` declare it. +for (const name of ['cleanupPage', 'siblingsPage']) { + const start = js.indexOf(`Alpine.data('${name}'`); + assert(start >= 0 && /loading: true/.test(js.slice(start, start + 300)), `${name} declares loading`); +} + +// Reads that used to throw on a missing object are guarded. +assert(!html.includes("x-text=\"'dismissed by ' + f.dismissed.actor\""), 'dismissed-by read is guarded'); +assert(!/:href="c\.doc\.dashboard_url"/.test(html), 'sibling dashboard_url read is guarded'); + +// Checkboxes inside form fields are not stretched into text-input boxes. +assert(/\.field input\[type="checkbox"\][^{]*\{[^}]*width: auto/.test(css), 'field checkboxes keep their natural size'); + +if (failures.length) { console.error(`FAIL (${failures.length}):`); failures.forEach((f) => console.error(' - ' + f)); process.exit(1); } +console.log('nav_rework.test: all assertions passed'); diff --git a/cmd/teploy-dash/frontend/css/style.css b/cmd/teploy-dash/frontend/css/style.css index 2e71a4f..6697f6c 100644 --- a/cmd/teploy-dash/frontend/css/style.css +++ b/cmd/teploy-dash/frontend/css/style.css @@ -20,6 +20,11 @@ --green: #3fb950; --yellow: #d29922; --red: #f85149; + --success: var(--green); + --warning: var(--yellow); + --danger: var(--red); + --success-bg: rgba(63, 185, 80, 0.15); + --bg-inset: rgba(139, 148, 158, 0.15); --font: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace; --mono: var(--font); --radius: 8px; @@ -163,6 +168,7 @@ a.nav-link:hover { background: var(--bg-card); } .form-group, .field { margin-bottom: 14px; } .form-label, .field label { display: block; margin-bottom: 5px; color: var(--text-muted); font-size: 12px; font-weight: 500; } .form-input, .field input, .field select, .search-input, .log-controls input, .log-controls select { width: 100%; min-height: 34px; padding: 6px 10px; border: 1px solid var(--border); border-radius: 6px; outline: none; background: var(--bg-input); color: var(--text); font-size: 13px; } +.field input[type="checkbox"], .field input[type="radio"], .form-input[type="checkbox"] { width: auto; min-height: 0; padding: 0; } .form-input::placeholder, .field input::placeholder, .search-input::placeholder { color: var(--text-muted); opacity: .7; } .form-input:focus, .field input:focus, .field select:focus, .search-input:focus, .log-controls input:focus, .log-controls select:focus { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-soft); } .field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } @@ -277,6 +283,15 @@ tbody tr:hover { background: var(--bg-card-hover); } background: var(--bg-card); color: var(--yellow); font-size: 12px; word-break: break-word; } +/* A neutral setting line (not a warning): same shape as the stale banner, + muted colours. */ +.info-banner { + display: flex; margin-bottom: 16px; padding: 8px 14px; gap: 12px; + align-items: center; justify-content: space-between; flex-wrap: wrap; + border: 1px solid var(--border); border-radius: var(--radius); + background: var(--bg-card); color: var(--text-secondary); font-size: 12px; +} +.backups-page .card { margin-bottom: 12px; cursor: default; } .empty-icon { margin-bottom: 12px; opacity: .4; } .loading, .spinner { display: none; } .back-link { display: inline-flex; margin-bottom: 14px; align-items: center; gap: 6px; color: var(--text-muted); font-size: 12px; text-decoration: none; } diff --git a/cmd/teploy-dash/frontend/index.html b/cmd/teploy-dash/frontend/index.html index 1cf74b7..5cdfa9c 100644 --- a/cmd/teploy-dash/frontend/index.html +++ b/cmd/teploy-dash/frontend/index.html @@ -189,7 +189,7 @@

Home

- +
@@ -290,8 +290,8 @@

Suggested groups

Apps that appear to belong together — they share a registrable domain - (akiroo.com), or a name prefix when they publish no domain - (fylun-). Accepting a suggestion uses the ordinary group + (example.com), or a name prefix when they publish no domain + (shop-). Accepting a suggestion uses the ordinary group assignment (server-bound); nothing is grouped until you accept it.

@@ -886,7 +886,7 @@

@@ -1788,7 +1788,7 @@

Domains

drill, one policy. Reads the cached fleet view; nothing probes a server on load. -->