frontend: add npm workspace scaffold under frontend/
Phase 1 of the backend/frontend code split (#273). Additive — no existing code is touched; the legacy hive-c0re/assets, hive-ag3nt/ assets and hive-fr0nt/assets trees stay in place until the Rust cutover later in this branch. Layout: frontend/package.json npm workspaces root frontend/packages/shared/ @hive/shared src/{base,terminal}.css + terminal.js (ES module) src/index.js re-exports terminal.js frontend/packages/dashboard/ @hive/dashboard src/{index.html, app.js, dashboard.css} ported from hive-c0re/assets build.mjs esbuild config → dist/ frontend/packages/agent/ @hive/agent src/{index,stats,screen}.html + agent.css + {app,stats}.js ported from hive-ag3nt/assets build.mjs esbuild config → dist/ Changes vs the existing assets: - terminal.js is an ES module exporting { create, linkify } instead of assigning to window.HiveTerminal. The dashboard / agent app.js files re-expose them on window so the IIFE bodies keep working unchanged through Phase 1; the global aliases can be dropped in a follow-up once the IIFEs are unwrapped. - marked is imported from the marked@4.3.0 npm package (replacing the vendored hive-fr0nt/assets/marked.umd.js bundle). - chart.js is imported from chart.js@4.4.4 (replacing the jsDelivr CDN script tag on the per-agent stats page — page now works offline / on operator machines without internet egress). - dashboard.css and agent.css both gain @import lines at the top that pull base.css + terminal.css from @hive/shared, replacing the runtime string concatenation in serve_css. - index.html / stats.html collapse from three / two script tags to one type="module" tag pointing at the bundled output. package-lock.json is intentionally omitted from this commit — npm isn't available in the iris container yet (approval pending) and the lockfile will land in the next commit on this branch once the toolchain is in place. The PR will not be opened until it's there. Phase 2 (nix derivations), Phase 3 (container plumbing + the hyperhive.frontend.extraFiles option for per-agent layering), and Phase 4 (Rust cutover to tower_http::ServeDir, delete hive-fr0nt + legacy assets dirs) land as follow-up commits on this same branch. Refs #273.
This commit is contained in:
parent
d81b430136
commit
8bebd78895
21 changed files with 7214 additions and 0 deletions
54
frontend/packages/dashboard/build.mjs
Normal file
54
frontend/packages/dashboard/build.mjs
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
// esbuild build for @hive/dashboard. Outputs:
|
||||
//
|
||||
// dist/app.js bundled ES module (entrypoint = src/app.js,
|
||||
// pulls in @hive/shared + marked)
|
||||
// dist/dashboard.css bundled stylesheet (entrypoint = src/dashboard.css,
|
||||
// @import "@hive/shared/base.css" + terminal.css
|
||||
// get inlined here)
|
||||
// dist/index.html copy of src/index.html (esbuild doesn't process
|
||||
// HTML; the script/link tags reference the bundled
|
||||
// siblings by name)
|
||||
//
|
||||
// Both Rust binaries serve `dist/` via tower_http::ServeDir. The output
|
||||
// must keep the same filenames the existing index.html references, so
|
||||
// downstream changes are mechanical.
|
||||
|
||||
import { build } from 'esbuild';
|
||||
import { mkdirSync, copyFileSync, rmSync } from 'node:fs';
|
||||
import { dirname, resolve } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const here = dirname(fileURLToPath(import.meta.url));
|
||||
const src = (p) => resolve(here, 'src', p);
|
||||
const dist = (p) => resolve(here, 'dist', p);
|
||||
|
||||
rmSync(dist(''), { recursive: true, force: true });
|
||||
mkdirSync(dist(''), { recursive: true });
|
||||
|
||||
// Bundle the JS entry. ES-module output, browser target, no minify
|
||||
// (line-aligned source aids debugging; minification belongs in a later
|
||||
// follow-up once asset sizes warrant it).
|
||||
await build({
|
||||
entryPoints: [src('app.js')],
|
||||
outfile: dist('app.js'),
|
||||
bundle: true,
|
||||
format: 'esm',
|
||||
platform: 'browser',
|
||||
target: ['es2022'],
|
||||
sourcemap: true,
|
||||
logLevel: 'info',
|
||||
});
|
||||
|
||||
// Bundle the CSS — esbuild resolves @import including the package
|
||||
// re-exports from @hive/shared.
|
||||
await build({
|
||||
entryPoints: [src('dashboard.css')],
|
||||
outfile: dist('dashboard.css'),
|
||||
bundle: true,
|
||||
loader: { '.css': 'css' },
|
||||
logLevel: 'info',
|
||||
});
|
||||
|
||||
copyFileSync(src('index.html'), dist('index.html'));
|
||||
|
||||
console.log('dashboard build ok →', dist(''));
|
||||
14
frontend/packages/dashboard/package.json
Normal file
14
frontend/packages/dashboard/package.json
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"name": "@hive/dashboard",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"description": "hive-c0re dashboard SPA. Bundled by esbuild into a static dist; served by the hive-c0re Rust binary at runtime via tower_http::ServeDir.",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "node ./build.mjs"
|
||||
},
|
||||
"dependencies": {
|
||||
"@hive/shared": "*",
|
||||
"marked": "4.3.0"
|
||||
}
|
||||
}
|
||||
2322
frontend/packages/dashboard/src/app.js
Normal file
2322
frontend/packages/dashboard/src/app.js
Normal file
File diff suppressed because it is too large
Load diff
1146
frontend/packages/dashboard/src/dashboard.css
Normal file
1146
frontend/packages/dashboard/src/dashboard.css
Normal file
File diff suppressed because it is too large
Load diff
117
frontend/packages/dashboard/src/index.html
Normal file
117
frontend/packages/dashboard/src/index.html
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>hyperhive // h1ve-c0re</title>
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
|
||||
<link rel="stylesheet" href="/static/dashboard.css">
|
||||
</head>
|
||||
<body>
|
||||
<pre class="banner">
|
||||
░▒▓█▓▒░ HYPERHIVE ░▒▓█▓▒░ HIVE-C0RE ░▒▓█▓▒░ WE ARE THE WIRED ░▒▓█▓▒░
|
||||
</pre>
|
||||
|
||||
<div id="notif-row" class="notif-row">
|
||||
<button type="button" id="notif-enable" class="btn btn-notif" hidden>🔔 enable notifications</button>
|
||||
<button type="button" id="notif-mute" class="btn btn-notif" hidden>🔕 mute</button>
|
||||
<button type="button" id="notif-unmute" class="btn btn-notif" hidden>🔔 unmute</button>
|
||||
<span id="notif-status" class="meta" hidden></span>
|
||||
</div>
|
||||
|
||||
<!-- swarm: live containers, dormant state, meta input bumps that
|
||||
affect the whole swarm. -->
|
||||
<h2>◆ C0NTAINERS ◆</h2>
|
||||
<div class="divider">══════════════════════════════════════════════════════════════</div>
|
||||
<div id="containers-section">
|
||||
<p class="meta">loading…</p>
|
||||
</div>
|
||||
|
||||
<h2>◆ K3PT ST4T3 ◆</h2>
|
||||
<div class="divider">══════════════════════════════════════════════════════════════</div>
|
||||
<div id="tombstones-section">
|
||||
<p class="meta">loading…</p>
|
||||
</div>
|
||||
|
||||
<h2>◆ M3T4 1NPUTS ◆</h2>
|
||||
<div class="divider">══════════════════════════════════════════════════════════════</div>
|
||||
<p class="meta">select inputs to <code>nix flake update</code> in <code>/meta/</code>. selected agents rebuild in sequence after the lock bump; manager learns each outcome via the usual <code>rebuilt</code> system event.</p>
|
||||
<div id="meta-inputs-section">
|
||||
<p class="meta">loading…</p>
|
||||
</div>
|
||||
|
||||
<h2>◆ R3BU1LD QU3U3 ◆</h2>
|
||||
<div class="divider">══════════════════════════════════════════════════════════════</div>
|
||||
<p class="meta">pending + running rebuilds, meta-updates, and first-spawns. one runs at a time; meta-update cascades nest under their parent. dedup: re-enqueueing a still-queued op collapses into the existing entry.</p>
|
||||
<div id="rebuild-queue-section">
|
||||
<p class="meta">loading…</p>
|
||||
</div>
|
||||
|
||||
<!-- operator decisions: things waiting on you. -->
|
||||
<h2>◆ M1ND H4S QU3STI0NS ◆</h2>
|
||||
<div class="divider">══════════════════════════════════════════════════════════════</div>
|
||||
<div id="questions-section">
|
||||
<p class="meta">loading…</p>
|
||||
</div>
|
||||
|
||||
<h2>◆ QU3U3D R3M1ND3RS ◆</h2>
|
||||
<div class="divider">══════════════════════════════════════════════════════════════</div>
|
||||
<p class="meta">reminders agents have queued for themselves but not yet delivered. cancel to drop a stuck or unwanted entry.</p>
|
||||
<div id="reminders-section">
|
||||
<p class="meta">loading…</p>
|
||||
</div>
|
||||
|
||||
<h2>◆ P3NDING APPR0VALS ◆</h2>
|
||||
<div class="divider">══════════════════════════════════════════════════════════════</div>
|
||||
<div id="approvals-section">
|
||||
<p class="meta">loading…</p>
|
||||
</div>
|
||||
|
||||
<!-- messages: broker traffic + the compose box that produces it. -->
|
||||
<h2>◆ 0PER4T0R 1NB0X ◆</h2>
|
||||
<div class="divider">══════════════════════════════════════════════════════════════</div>
|
||||
<div id="inbox-section">
|
||||
<p class="meta">loading…</p>
|
||||
</div>
|
||||
|
||||
<h2>◆ MESS4GE FL0W ◆</h2>
|
||||
<div class="divider">══════════════════════════════════════════════════════════════</div>
|
||||
<p class="meta">live tail — newest at the top. tap on every <code>send</code> / <code>recv</code> through the broker. compose below: <code>@name</code> picks the recipient (sticky until you @ someone else); <code>tab</code> completes.</p>
|
||||
<div class="terminal-wrap">
|
||||
<div id="msgflow" class="live"><div class="meta">connecting…</div></div>
|
||||
<div id="op-compose" class="op-compose">
|
||||
<span id="op-compose-prompt" class="op-compose-prompt">@—></span>
|
||||
<textarea id="op-compose-input" class="op-compose-input"
|
||||
placeholder="@agent message… (enter sends, shift+enter newline, tab completes @-mention)"
|
||||
rows="1" autocomplete="off"></textarea>
|
||||
<div id="op-compose-suggest" class="op-compose-suggest" hidden></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer>
|
||||
<div class="divider">══════════════════════════════════════════════════════════════</div>
|
||||
<p>▲△▲ <a href="https://git.berlin.ccc.de/vinzenz/hyperhive">hyperhive</a> ▲△▲ hive-c0re on this host ▲△▲</p>
|
||||
</footer>
|
||||
|
||||
<!-- Slide-in detail panel. Long content (clicked file previews,
|
||||
approval diffs, journald logs, applied config) opens here
|
||||
instead of expanding inline. Singleton — JS swaps the title +
|
||||
body and toggles `.open`. -->
|
||||
<div id="side-panel" class="side-panel" aria-hidden="true">
|
||||
<div class="side-panel-backdrop" id="side-panel-backdrop"></div>
|
||||
<aside class="side-panel-drawer" role="dialog" aria-modal="true"
|
||||
aria-labelledby="side-panel-title">
|
||||
<header class="side-panel-head">
|
||||
<span class="side-panel-title" id="side-panel-title"></span>
|
||||
<button type="button" class="side-panel-close" id="side-panel-close"
|
||||
title="close (esc)">✕</button>
|
||||
</header>
|
||||
<div class="side-panel-body" id="side-panel-body"></div>
|
||||
</aside>
|
||||
</div>
|
||||
|
||||
<!-- Single bundled entry. esbuild folds @hive/shared/terminal.js and
|
||||
the marked npm package into app.js; load order is preserved by
|
||||
the module bundler. -->
|
||||
<script type="module" src="/static/app.js" defer></script>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Add table
Add a link
Reference in a new issue