Watch
0
0
Fork
You've already forked hyperhive
0

swarm-ui, hive dashboard, agent page: one profile menu with the signed-in user, avatar and authelia links

The swarm UI's user menu moves to @hive/shared and takes the whoami URL and
authelia's URL as props; the swarm UI keeps a thin wrapper, and the hive
dashboard and the per-agent page mount the same component. The dashboard's
nginx vhost proxies /api/whoami to authelia (the agent page is served from
the same vhost), and hive-c0re's state carries authelia_public_url, set from
services.hyperhive.swarm.authelia.url. The agent page shows the menu only
behind the gateway.
This commit is contained in:
iris 2026-10-25 15:05:35 +01:00 • committed by mara
commit cd41e1d510
19 changed files with 417 additions and 154 deletions

View file

@ -7,6 +7,7 @@
@import "./system-sections.css";
@import "@hive/shared/jobq-rollup.css";
@import "@hive/shared/jobq-graph.css";
@import "@hive/shared/user-menu.css";
/* ─── tabbed dashboard chrome ──────────────────────────────────────
Top-of-page sticky header with banner + tab strip. SSE stays
@ -42,6 +43,12 @@ body.dashboard-shell {
padding: 0.3em 1em;
margin: 0 0 1em;
}
/* Profile menu (user-menu.js): the avatar at the right end of the chrome.
Its own look is `@hive/shared/user-menu.css`'s. */
.user-menu-slot {
flex: none;
margin-left: auto;
}
/* Pages menu (links-menu.js): one icon button at the left of the chrome
that opens a popover of the standalone pages and the swarm UI. Same
shape as the swarm UI's LinksMenu — quiet until hovered or open. The

View file

@ -86,6 +86,8 @@
menu at the left of this strip, not tabs — the strip holds only
in-page tabs. -->
</nav>
<!-- Profile menu: the signed-in user, filled by user-menu.js. -->
<div class="user-menu-slot" id="user-menu"></div>
</header>
<!-- Tab panes. createTabStrip (@hive/shared/tabs.js) keeps exactly one

View file

@ -40,6 +40,7 @@ import {
syncKeptFromSnapshot,
} from "./kept.js";
import { renderLinksMenu } from "./links-menu.js";
import { renderUserMenu } from "./user-menu.js";
(() => {
initStickyTop();
@ -164,6 +165,7 @@ import { renderLinksMenu } from "./links-menu.js";
renderContainers(s);
renderKept();
renderLinksMenu(s);
renderUserMenu(s);
renderHiveRev(s.hyperhive_rev);
restoreOpenDetails(openDetails);
// No periodic refresh timer. Phase 6 covers every container

View file

@ -0,0 +1,24 @@
// Profile menu in the dashboard chrome, at the right of the tab strip: the
// signed-in user's avatar, name, and links to authelia's settings and
// sign-out. It is `@hive/shared`'s `UserMenu`, the same component the swarm UI
// and the per-agent page mount, rendered with Preact like the job-queue
// graph. `/api/whoami` is proxied to authelia by this dashboard's own nginx
// vhost, so it needs no CORS; authelia's URL comes from `/api/state`.
import { h, render } from "preact";
import { UserMenu } from "@hive/shared/user-menu.js";
import { $ } from "./common.js";
/** (Re)render the menu into `#user-menu`. Safe to call on every state
* refresh: Preact diffs the same component, so an open popover stays open. */
export function renderUserMenu(state) {
const root = $("user-menu");
if (!root) return;
render(
h(UserMenu, {
whoamiUrl: "/api/whoami",
autheliaUrl: (state && state.authelia_public_url) || null,
}),
root,
);
}