Phase C of the program viewer. Replaces the "panel coming soon" stub with a real Lit-based side panel that consumes the Phase-B websocket commands. Layout (top to bottom): * Header — title + total/filtered count * Filter bar — search box (substring match), trigger-type chips (TIMED / EVENT / YEARLY / WHEN / AT / EVERY / REMARK), a clearable "filtering on <ref>" pill when an entity filter is active * Two-column body: program list on the left, slide-in detail panel on the right. Collapses to single-column on `narrow` view. The program list renders one row per program (or per chain head, for clausal multi-record programs). Each row carries the slot number, the rendered one-line summary token stream, and meta pills for trigger type / condition count / multi-action count. The detail panel renders the full structured-English token stream inside a styled <pre>. A "Fire now" button calls ``omni_pca/programs/fire`` over the wire — the panel actually runs the program. For chain detail the spanned slot range is shown underneath. REF tokens are rendered as `<button>` elements that click to filter the list to "programs that mention this entity" — the most useful navigational affordance for the "why is this happening?" use case. Live-state badges (SECURE / NOT READY / ON 60% / Away / 72°F / …) are appended to REF tokens via the Phase-B coordinator-backed StateResolver. The panel polls ``programs/list`` every 5 seconds to refresh badges; switching to push-event subscriptions is a follow-up when polling overhead becomes visible. Theming uses HA's standard CSS variables (--primary-color, --card-background-color, --divider-color, etc.) so the panel inherits the user's HA theme automatically. Build pipeline: * TypeScript source under ``custom_components/omni_pca/frontend/src/`` * esbuild bundles entry → ESM in one self-contained file * Output at ``custom_components/omni_pca/www/panel.js`` (~34 KB minified) is committed so end-users don't need Node installed * ``npm run watch`` for HA-dev-time iteration * tsconfig has strict mode + noUnusedLocals; bundle currently type-checks clean Manifest declares deps on ``http`` and ``websocket_api``; ``frontend`` and ``panel_custom`` are loaded opportunistically (they require ``hass_frontend`` which the test harness doesn't ship — keeping them out of the manifest deps keeps tests green). Full suite: 634 passed, 1 skipped (no test changes; the integration side hasn't moved since Phase B).
45 lines
1.5 KiB
JavaScript
45 lines
1.5 KiB
JavaScript
// Bundle the omni_pca side panel into a single ESM file the HA static
|
|
// path serves at /api/omni_pca/panel.js.
|
|
//
|
|
// Usage:
|
|
// node build.mjs # one-shot production build
|
|
// node build.mjs --watch # rebuild on source change
|
|
//
|
|
// Output is intentionally placed at ../www/panel.js so the Python side
|
|
// (websocket.py:async_register_side_panel) finds it without extra
|
|
// configuration. The frontend dir + the Python integration sit in the
|
|
// same custom_components/omni_pca/ tree so end-users just install the
|
|
// integration; no separate HACS package needed.
|
|
|
|
import { build, context } from "esbuild";
|
|
import { fileURLToPath } from "node:url";
|
|
import { dirname, resolve } from "node:path";
|
|
|
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
const watch = process.argv.includes("--watch");
|
|
|
|
const opts = {
|
|
entryPoints: [resolve(__dirname, "src/omni-panel-programs.ts")],
|
|
bundle: true,
|
|
format: "esm",
|
|
target: "es2022",
|
|
minify: !watch,
|
|
sourcemap: watch ? "inline" : false,
|
|
outfile: resolve(__dirname, "../www/panel.js"),
|
|
// Lit ships its own ESM build; bundle it inline so the panel is a
|
|
// single self-contained file (matches how HACS-distributed cards work).
|
|
loader: { ".ts": "ts" },
|
|
banner: {
|
|
js: "// omni_pca side panel — generated by frontend/build.mjs. Edit src/, not this file.",
|
|
},
|
|
};
|
|
|
|
if (watch) {
|
|
const ctx = await context(opts);
|
|
await ctx.watch();
|
|
console.log("watching for changes…");
|
|
} else {
|
|
await build(opts);
|
|
console.log("built ->", opts.outfile);
|
|
}
|