feat: P33RS tab — peer hive link cards in dashboard
Adds the P33RS tab to the dashboard. The tab is hidden by default and only shown when at least one peer hive is configured in `services.hyperhive.peers`. When visible, it renders a card per peer with a link to that hive's dashboard. Backend (HYPERHIVE_PEERS env var, PeerHiveView in StateSnapshot) is wired by a separate PR. This commit is frontend only: - index.html: P33RS tab strip entry + tab-pane-peers section - tabs.js: renderPeerHives(), gate logic, 'peers' added to TABS array
This commit is contained in:
parent
d45b2f0293
commit
7a8b8fe266
2 changed files with 57 additions and 1 deletions
|
|
@ -48,6 +48,15 @@
|
|||
<span class="tab-count" id="tab-count-schedules" hidden></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>
|
||||
|
||||
<!-- M4TR1X: optional matrix web client (fluffychat-web by
|
||||
default) mounted at /matrix/ by the gateway when
|
||||
`hyperhive.matrix.gui.enable = true`. Same-origin
|
||||
|
|
@ -146,6 +155,18 @@
|
|||
</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 `✎`
|
||||
|
|
|
|||
|
|
@ -1722,6 +1722,36 @@ 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.
|
||||
function renderPeerHives(peers) {
|
||||
const root = $('peers-section');
|
||||
if (!root) return;
|
||||
root.innerHTML = '';
|
||||
if (!peers || !peers.length) {
|
||||
root.append(el('p', { class: 'empty' }, 'no peer hives configured'));
|
||||
return;
|
||||
}
|
||||
const ul = el('ul', { class: 'containers' });
|
||||
for (const p of peers) {
|
||||
const li = el('li', { class: 'container-row' });
|
||||
const head = el('div', { class: 'head' });
|
||||
const icon = el('span', { class: 'container-icon' }, '⬡');
|
||||
const nameEl = el('span', { class: 'name' }, p.name || p.url);
|
||||
const linkEl = el('a', {
|
||||
href: p.url,
|
||||
target: '_blank',
|
||||
rel: 'noopener noreferrer',
|
||||
class: 'meta',
|
||||
title: 'open ' + p.name + ' dashboard',
|
||||
}, p.url);
|
||||
head.append(icon, nameEl);
|
||||
li.append(head, el('div', { class: 'meta' }, linkEl));
|
||||
ul.append(li);
|
||||
}
|
||||
root.append(ul);
|
||||
}
|
||||
|
||||
function renderApprovals() {
|
||||
const root = $('approvals-section');
|
||||
// #approvals-section only lives on /index.html (Y3R C4LL tab);
|
||||
|
|
@ -3293,6 +3323,11 @@ 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);
|
||||
// Gate the M4TR1X → tab strip entry — see
|
||||
// docs/web-ui.md::Tab strip for the matrix_gui_enabled rationale.
|
||||
const matrixTab = $('tab-matrix');
|
||||
|
|
@ -3428,7 +3463,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', 'schedules', 'settings'];
|
||||
const TABS = ['swarm', 'call', 'system', 'schedules', 'peers', 'settings'];
|
||||
function activateTab(name) {
|
||||
const target = TABS.includes(name) ? name : TABS[0];
|
||||
for (const t of TABS) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue