refactor(dashboard): drop the P33RS tab, fold peers + identity into SW4RM (#1535)

Removes the standalone P33RS tab + pane. Peer hives now render as a
headline section at the bottom of the SW4RM pane; the swarm/hive name
moves off the cramped strip above the tabbar into a headline at the top
of SW4RM. Both are quiet when nothing's configured:

- swarm/hive identity → `#swarm-identity` h2 in the SW4RM pane (hidden
  until hive_name/swarm_name are set), replacing the `#hive-identity`
  banner-thin line above the tabbar.
- peer hives → `#peers-block` headline + `#peers-section` cards in the
  SW4RM pane. When no peers are federated the headline block is hidden
  entirely and a grey "no peer hives configured" note shows in its place.
- drops `peers` from the tab list + the per-refresh peers-tab gating;
  renderPeerHives now toggles its own headline.

No backend change — still reads `state.peer_hives` + `hive_name` /
`swarm_name`. Build green.
This commit is contained in:
iris 2026-06-08 22:20:12 +02:00 committed by mara
commit 0a0038f23c
2 changed files with 30 additions and 36 deletions

View file

@ -22,10 +22,6 @@
dashboard all link back to the landing page rather than to each
other — H0M3 is the single navigation hub. -->
<a class="dash-home-back" href="/" title="back to the H0M3 menu">← home</a>
<!-- Hive identity line: swarm/hive label. Hidden until JS populates
it from /api/state (hive_name + swarm_name). Falls back to
hostname when only the domain is configured. -->
<p class="banner-thin" id="hive-identity" hidden></p>
<nav class="tabbar" id="tabbar" role="tablist">
<a class="tab" id="tab-swarm" href="#swarm" role="tab"
aria-controls="tab-pane-swarm"
@ -73,14 +69,8 @@
<span class="tab-label">◆ ST4TS ◆</span>
</a>
<!-- P33RS: peer hive navigation links. Hidden until at least one
peer is configured in `services.hyperhive.peers`. -->
<a class="tab" id="tab-peers" href="#peers" role="tab"
aria-controls="tab-pane-peers"
data-tab="peers" hidden>
<span class="tab-label">◆ P33RS ◆</span>
<span class="tab-count" id="tab-count-peers" hidden></span>
</a>
<!-- (Peer hives are no longer a tab — they render as a headline
under SW4RM. See tab-pane-swarm.) -->
<!-- FL0W, L0GS, and M4TR1X are separate pages reachable from the
H0M3 hub (served at /), not from the dashboard tab strip — the
@ -122,9 +112,21 @@
— the tab label SW4RM already says it. -->
<section class="tab-pane" id="tab-pane-swarm"
role="tabpanel" aria-labelledby="tab-swarm">
<!-- Swarm / hive identity headline. Populated by refreshState from
hive_name + swarm_name; stays hidden when neither is set. -->
<h2 id="swarm-identity" hidden></h2>
<div id="containers-section">
<p class="meta">loading…</p>
</div>
<!-- Peer hives (federated swarms). The headline block is hidden
entirely when nothing is federated; renderPeerHives then drops
a quiet "no peer hives configured" note into #peers-section. -->
<div id="peers-block" hidden>
<h2>◆ P33R H1V3S ◆</h2>
<div class="divider">══════════════════════════════════════════════════════════════</div>
<p class="meta">peer hives in this swarm. click a card to open that hive's dashboard.</p>
</div>
<div id="peers-section"></div>
</section>
<!-- Y3R C4LL: things blocked on operator decision. Approvals +
@ -221,18 +223,6 @@
</div>
</section>
<!-- P33RS: peer hive link cards. Rendered from state.peer_hives;
hidden when the list is empty. -->
<section class="tab-pane" id="tab-pane-peers"
role="tabpanel" aria-labelledby="tab-peers">
<h2>◆ P33R H1V3S ◆</h2>
<div class="divider">══════════════════════════════════════════════════════════════</div>
<p class="meta">peer hives in this swarm. click a card to open that hive's dashboard.</p>
<div id="peers-section">
<p class="meta">loading…</p>
</div>
</section>
<!-- SCH3DUL3S: scheduled prompts. Creation + edit are folded
into the same table — empty bottom row is the create form
(fill cells, click ), inline-edit-row expands on the `✎`

View file

@ -2141,13 +2141,18 @@ window.marked = marked;
selectBase('applied');
}
// P33RS tab: render peer hive link cards from state.peer_hives.
// Called on every state refresh; hides the tab when the list is empty.
// Peer hives: render link cards as a headline section under SW4RM
// (state.peer_hives). Called on every state refresh. When nothing is
// federated, the "P33R H1V3S" headline block is hidden entirely and a
// quiet grey note replaces the cards.
function renderPeerHives(peers) {
const block = $('peers-block');
const root = $('peers-section');
if (!root) return;
root.replaceChildren();
if (!peers || !peers.length) {
const hasPeers = Array.isArray(peers) && peers.length > 0;
if (block) block.hidden = !hasPeers;
if (!hasPeers) {
root.append(el('p', { class: 'empty' }, 'no peer hives configured'));
return;
}
@ -3897,20 +3902,19 @@ window.marked = marked;
// synchronous read (e.g. the compose autocomplete pulls agent
// names from here instead of refetching on every keystroke).
window.__hyperhive_state = s;
// Gate the P33RS tab — hidden when no peers are configured.
const peersTab = $('tab-peers');
const peers = s.peer_hives || [];
if (peersTab) peersTab.hidden = peers.length === 0;
renderPeerHives(peers);
// Peer hives render as a headline section under SW4RM (no longer
// a tab); renderPeerHives shows/hides its own headline block.
renderPeerHives(s.peer_hives || []);
renderServerWarnings(s.server_warnings);
// (The M4TR1X surface is reachable from the H0M3 hub now, not the
// dashboard tab strip — home.js gates its tile on matrix_gui_enabled.)
// Hive identity: update the chrome banner + page title once the
// Hive identity: render the swarm/hive name as a headline at the
// top of the SW4RM pane + update the page title once the
// server-side display names are known. `hive_name` / `swarm_name`
// come from HYPERHIVE_HIVE_NAME / HYPERHIVE_SWARM_NAME env vars
// (set by services.hyperhive.{hiveName,swarmName} nix options).
// When unset we fall back gracefully — no chrome change.
const hiveId = $('hive-identity');
// When unset we fall back gracefully — the headline stays hidden.
const hiveId = $('swarm-identity');
if (hiveId) {
const hive = s.hive_name;
const swarm = s.swarm_name;
@ -4053,7 +4057,7 @@ window.marked = marked;
// (`/flow.html`) reached via the tab-strip link. Tab routing only
// applies when the tab DOM is present (e.g. not on the flow page
// itself, where these elements don't exist and the loop no-ops).
const TABS = ['swarm', 'call', 'system', 'permissions', 'schedules', 'stats', 'peers', 'settings'];
const TABS = ['swarm', 'call', 'system', 'permissions', 'schedules', 'stats', 'settings'];
function activateTab(name) {
const target = TABS.includes(name) ? name : TABS[0];
for (const t of TABS) {