feat(ui): TDS migration stage 3 — integration fixes, legacy removal, docs
Lint / JS (eslint) (pull_request) Successful in 10s
Lint / Notify on failure (pull_request) Skipped
Lint / Deploy (pull_request) Skipped
Security / JS Security (npm audit) (pull_request) Failing after 10s
Test / JS Tests (jest) (pull_request) Successful in 14s
Lint / JS (eslint) (push) Successful in 11s
Lint / Notify on failure (push) Skipped
Lint / Deploy (push) Skipped
Security / JS Security (npm audit) (push) Failing after 11s
Test / JS Tests (jest) (push) Successful in 10s

- Fix design-system class names that do not exist in base.css (.lt-alert--error,
  .lt-form-hint); add shared .lt-modal-lg, .lt-field-error and .is-invalid rules
- Remove public/index.html and the public/base.js symlink
- package.json: start script, correct main
- README: vendored design system, Web UI section, new env vars, read-only dev mode

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HamVMDrA8RqhyxmUHgiqRp
This commit is contained in:
2026-09-08 22:17:15 -04:00
co-authored by Claude Fable 5.1
parent 68d0a906a6
commit eca5cb45b1
11 changed files with 129 additions and 3195 deletions
+34 -1
View File
@@ -131,7 +131,40 @@
.pulse-scroll-x { overflow-x: auto; -webkit-overflow-scrolling: touch; }
/* ---------------------------------------------------------------------
7. Light theme overrides for the additions above
7. Shared component gap-fillers (base.css does not ship these)
---------------------------------------------------------------------
`.lt-modal-lg` — base.css ships .lt-modal-xs/.lt-modal-sm only, but
several Pulse pages need a wide modal (JSON editors, log viewers,
side-by-side compare). Sized the same way base.css sizes its own
modifiers, and re-capped at the two breakpoints base.css caps
`.lt-modal` at, because this selector is more specific than those.
`.lt-field-error` / `.is-invalid` — base.css references a field-error
hook but ships no visual style for it.
Both are candidates for upstreaming into base.css.
--------------------------------------------------------------------- */
.lt-modal.lt-modal-lg {
width: min(900px, 95vw);
max-width: 900px;
}
@media (max-width: 767px) { .lt-modal.lt-modal-lg { max-width: 96vw; } }
@media (max-width: 479px) { .lt-modal.lt-modal-lg { max-width: 100vw; } }
.lt-field-error {
color: var(--accent-red);
font-size: 0.72rem;
letter-spacing: 0.02em;
margin-top: 4px;
}
.lt-input.is-invalid,
.lt-textarea.is-invalid,
.lt-select.is-invalid {
border-color: var(--accent-red);
}
/* ---------------------------------------------------------------------
8. Light theme overrides for the additions above
--------------------------------------------------------------------- */
html[data-theme="light"] #pulse-last-refreshed { color: var(--text-muted); }
+13 -2
View File
@@ -139,12 +139,23 @@
/* -------------------------------------------------------------------
Data loading
------------------------------------------------------------------- */
/* Toast a load failure at most once per outage, so the 30 s auto-refresh
does not stack a toast every cycle while the API is down. */
let _loadFailed = false;
function reportLoadError(what, e) {
console.error('[Pulse:dashboard] failed to load ' + what, e);
if (_loadFailed) return;
_loadFailed = true;
if (Pulse.toast) Pulse.toast.error((e && e.message) || ('Failed to load ' + what));
}
async function loadWorkers() {
try {
_workers = await Pulse.api.get('/api/workers') || [];
_loadFailed = false;
} catch (e) {
_workers = [];
console.error('[Pulse:dashboard] failed to load workers', e);
reportLoadError('workers', e);
}
renderWorkers(_workers);
return _workers;
@@ -156,7 +167,7 @@
_executions = (data && data.executions) || [];
} catch (e) {
_executions = [];
console.error('[Pulse:dashboard] failed to load executions', e);
reportLoadError('executions', e);
}
renderExecutions(_executions);
return _executions;
+3 -8
View File
@@ -8,15 +8,10 @@
===================================================================== */
/* ---------------------------------------------------------------------
1. Modal sizing — base.css has .lt-modal-sm but no .lt-modal-lg, so the
large variant is scoped to this page's two modals to avoid colliding
with any other page that defines the same class.
1. Modal sizing — width comes from the shared `.lt-modal-lg` rule in
/assets/app.css; only the scroll behaviour of these two modals is
page-specific.
--------------------------------------------------------------------- */
#ex-detail-modal .lt-modal,
#ex-compare-modal .lt-modal {
max-width: min(1100px, 94vw);
width: min(1100px, 94vw);
}
#ex-detail-modal .lt-modal-body,
#ex-compare-modal .lt-modal-body {
max-height: 72vh;
+1 -12
View File
@@ -23,15 +23,4 @@
color: var(--accent-red);
}
/* base.css defines .lt-field-error as a hook (see base.js field validation)
but ships no visual style for it — Workflows renders it directly for
JSON-parse / server-side errors, so give it one here. */
.lt-field-error {
color: var(--accent-red);
font-size: 0.72rem;
letter-spacing: 0.02em;
}
.wf-input-invalid {
border-color: var(--accent-red) !important;
}
/* `.lt-field-error` and `.is-invalid` live in /assets/app.css (shared). */
+2 -2
View File
@@ -290,11 +290,11 @@
var el = document.getElementById('wf-run-param-' + p.name);
var val = el ? el.value.trim() : '';
if (p.required && !val) {
el.classList.add('wf-input-invalid');
el.classList.add('is-invalid');
el.focus();
return;
}
el && el.classList.remove('wf-input-invalid');
el && el.classList.remove('is-invalid');
if (val) params[p.name] = val;
}
-1
View File
@@ -1 +0,0 @@
/root/code/web_template/base.js
-3162
View File
File diff suppressed because it is too large Load Diff