Move dashboard settings into Y3R C4LL tab, drop standalone S3TT1NGS page
mara (issue #3817): remove the home link + page, put the setting toggle into the Y3R C4LL tab. Deleted settings.html/.js/.css; the browser-notification toggle (the only content there) now renders as a ◆ PR3F3R3NC3S ◆ section under Y3R C4LL's approvals/inbox, wired the same way (NOTIF.bind()/NOTIF.show() in common.js — no behavior change, just a new mount point). Updated build.mjs's entry lists and every doc/comment that pointed at the old page.
This commit is contained in:
parent
146db58bab
commit
b33bb7a3d3
14 changed files with 106 additions and 175 deletions
|
|
@ -26,11 +26,12 @@ of your time. It's a single page with exactly four tabs:
|
||||||
Everything else lives on its own page instead, all reachable from the
|
Everything else lives on its own page instead, all reachable from the
|
||||||
H0M3 hub: **Flow** (`/flow.html`, the raw live message stream across
|
H0M3 hub: **Flow** (`/flow.html`, the raw live message stream across
|
||||||
the whole swarm), **Logs** (`/logs.html`, per-agent and host
|
the whole swarm), **Logs** (`/logs.html`, per-agent and host
|
||||||
journals), **Stats** (`/stats.html`, swarm-wide usage stats), **Settings**
|
journals), **Stats** (`/stats.html`, swarm-wide usage stats),
|
||||||
(`/settings.html`, your local browser preferences), **Builds** (`/builds.html`, the rebuild
|
**Builds** (`/builds.html`, the rebuild queue and build history),
|
||||||
queue and build history), **Core** (`/core.html`, tombstones and
|
**Core** (`/core.html`, tombstones and container resource use), and
|
||||||
container resource use), and **Credentials** (`/credentials.html`,
|
**Credentials** (`/credentials.html`, provisioning matrix/GitHub/forge
|
||||||
provisioning matrix/GitHub/forge accounts per agent).
|
accounts per agent). Your local browser preferences (notifications)
|
||||||
|
live in the dashboard's Y3R C4LL tab now, not a separate page.
|
||||||
|
|
||||||
Each agent also has its own page — a full terminal view of that
|
Each agent also has its own page — a full terminal view of that
|
||||||
agent's session, reachable by clicking its name anywhere in the
|
agent's session, reachable by clicking its name anywhere in the
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
The dashboard is served at `/dashboard.html` (with the home page at `/`).
|
The dashboard is served at `/dashboard.html` (with the home page at `/`).
|
||||||
It has a fixed chrome header at the top and a `<main>` that shows exactly
|
It has a fixed chrome header at the top and a `<main>` that shows exactly
|
||||||
one tab pane at a time. The URL hash (`#swarm`, `#call`, `#system`,
|
one tab pane at a time. The URL hash (`#swarm`, `#call`, `#system`,
|
||||||
`#permissions`, `#schedules`, `#settings`) drives which pane is
|
`#permissions`, `#schedules`) drives which pane is
|
||||||
active; hash changes don't reload the page. FL0W, L0GS, and the optional
|
active; hash changes don't reload the page. FL0W, L0GS, and the optional
|
||||||
M4TR1X client are separate pages reachable from the H0M3 hub at `/`, not
|
M4TR1X client are separate pages reachable from the H0M3 hub at `/`, not
|
||||||
from the dashboard tab strip.
|
from the dashboard tab strip.
|
||||||
|
|
@ -18,16 +18,15 @@ from the dashboard tab strip.
|
||||||
- **Tab strip**: `◆ SW4RM ◆`, `◆ Y3R C4LL ◆`, `◆ P3RM1SS10NS ◆`,
|
- **Tab strip**: `◆ SW4RM ◆`, `◆ Y3R C4LL ◆`, `◆ P3RM1SS10NS ◆`,
|
||||||
`◆ SCH3DUL3S ◆`. In-page tabs only — the SYST3M panels moved to the
|
`◆ SCH3DUL3S ◆`. In-page tabs only — the SYST3M panels moved to the
|
||||||
standalone **C0R3** page (`/core.html`), and FL0W / L0GS / ST4TS /
|
standalone **C0R3** page (`/core.html`), and FL0W / L0GS / ST4TS /
|
||||||
S3TT1NGS / M4TR1X live on their own pages too, all reachable from the
|
M4TR1X live on their own pages too, all reachable from the
|
||||||
H0M3 hub (not the tab strip). Count pills on SW4RM
|
H0M3 hub (not the tab strip). Count pills on SW4RM
|
||||||
(container count), Y3R C4LL (pending approvals + unread
|
(container count), Y3R C4LL (pending approvals + unread
|
||||||
operator messages), and SCH3DUL3S (active schedules); S3TT1NGS has no
|
operator messages), and SCH3DUL3S (active schedules).
|
||||||
count.
|
|
||||||
- **Banner-thin** (`░▒▓█▓▒░ HYPERHIVE / HIVE-C0RE / WE ARE THE WIRED ░▒▓█▓▒░`)
|
- **Banner-thin** (`░▒▓█▓▒░ HYPERHIVE / HIVE-C0RE / WE ARE THE WIRED ░▒▓█▓▒░`)
|
||||||
— sits below the tab strip.
|
— sits below the tab strip.
|
||||||
- **Server-warnings banner** — a generic, sticky top-of-page strip shown
|
- **Server-warnings banner** — a generic, sticky top-of-page strip shown
|
||||||
on **every** page (dashboard + every stand-alone page — FL0W, L0GS,
|
on **every** page (dashboard + every stand-alone page — FL0W, L0GS,
|
||||||
H0M3, C0R3, BU1LDS, CR3D3NTIALS, ST4TS, S3TT1NGS), injected at the top
|
H0M3, C0R3, BU1LDS, CR3D3NTIALS, ST4TS), injected at the top
|
||||||
of `<body>` by `renderServerWarnings` in `common.js`. Driven by
|
of `<body>` by `renderServerWarnings` in `common.js`. Driven by
|
||||||
`state.server_warnings` — a list of `{ kind, level, message }` — and
|
`state.server_warnings` — a list of `{ kind, level, message }` — and
|
||||||
coloured by `level` (`warn` amber / `crit` red). The backend owns the
|
coloured by `level` (`warn` amber / `crit` red). The backend owns the
|
||||||
|
|
@ -100,6 +99,27 @@ messages are visible from any tab even while inactive. Backed by
|
||||||
`GET /api/operator-inbox` → `{ messages: [...] }` (id, from, body, at,
|
`GET /api/operator-inbox` → `{ messages: [...] }` (id, from, body, at,
|
||||||
in_reply_to, file_refs).
|
in_reply_to, file_refs).
|
||||||
|
|
||||||
|
**◆ PR3F3R3NC3S ◆** — operator-local preferences. State lives in the
|
||||||
|
browser's `localStorage` — preferences do NOT sync between devices and
|
||||||
|
do NOT survive a profile wipe. One section today (browser
|
||||||
|
notifications); future preferences land here as sibling `<h3>` blocks
|
||||||
|
in `dashboard.html`. Was its own S3TT1NGS page/tile (`/settings.html`)
|
||||||
|
until mara moved it in here — a standalone page for one toggle didn't
|
||||||
|
earn its own tile.
|
||||||
|
|
||||||
|
**◇ browser notifications** — `🔔 enable notifications` button when
|
||||||
|
permission ungranted; `🔕 mute / 🔔 unmute` toggle once granted
|
||||||
|
(mute silences the dispatch without revoking the OS-level
|
||||||
|
permission). On unsupported origins (non-secure context, or
|
||||||
|
browsers without the `Notification` API) the controls hide and a
|
||||||
|
single status line explains why. See `### Browser notifications`
|
||||||
|
below for the dispatch model + the three signals the dashboard
|
||||||
|
emits OS notifications on.
|
||||||
|
|
||||||
|
The "expand tool output panels" toggle lives on the per-agent page's
|
||||||
|
own settings popover (`SettingsMenu`, `@hive/shared/settings-menu.js`)
|
||||||
|
instead — it's agent-terminal-only, unrelated to this section.
|
||||||
|
|
||||||
## C0R3 page (`/core.html`)
|
## C0R3 page (`/core.html`)
|
||||||
|
|
||||||
Passive / rare-interaction state. No longer a dashboard tab — it's a
|
Passive / rare-interaction state. No longer a dashboard tab — it's a
|
||||||
|
|
@ -595,32 +615,10 @@ the model id, longest match wins) mapping to
|
||||||
`{ input, output, cache_read, cache_write }` USD-per-million-token
|
`{ input, output, cache_read, cache_write }` USD-per-million-token
|
||||||
prices. Models not covered fall back to hive-c0re's built-in estimate.
|
prices. Models not covered fall back to hive-c0re's built-in estimate.
|
||||||
|
|
||||||
## S3TT1NGS tab
|
The FL0W page does NOT host the PR3F3R3NC3S pane — it lives only on the
|
||||||
|
dashboard's Y3R C4LL tab (reach it via the FL0W page's `← home`
|
||||||
Operator-local preferences. State lives in the browser's
|
|
||||||
`localStorage` — preferences do NOT sync between devices and
|
|
||||||
do NOT survive a profile wipe. One section today (browser
|
|
||||||
notifications); future preferences land here as sibling `<h3>`
|
|
||||||
blocks in `settings.html`.
|
|
||||||
|
|
||||||
**◇ browser notifications** — `🔔 enable notifications` button when
|
|
||||||
permission ungranted; `🔕 mute / 🔔 unmute` toggle once granted
|
|
||||||
(mute silences the dispatch without revoking the OS-level
|
|
||||||
permission). On unsupported origins (non-secure context, or
|
|
||||||
browsers without the `Notification` API) the controls hide and a
|
|
||||||
single status line explains why. See `### Browser notifications`
|
|
||||||
below for the dispatch model + the three signals the dashboard
|
|
||||||
emits OS notifications on.
|
|
||||||
|
|
||||||
The "expand tool output panels" toggle used to live here too; it
|
|
||||||
moved into the per-agent page's own settings popover (`SettingsMenu`,
|
|
||||||
`@hive/shared/settings-menu.js`) since it's agent-terminal-only and
|
|
||||||
this tab is shared with swarm-ui — see that component's file comment.
|
|
||||||
|
|
||||||
The FL0W page does NOT host this pane — settings live only on the
|
|
||||||
dashboard's S3TT1NGS tab (reach it via the FL0W page's `← home`
|
|
||||||
back-link → Dashboard). Notifications still fire on the FL0W page when
|
back-link → Dashboard). Notifications still fire on the FL0W page when
|
||||||
they're enabled here, because `NOTIF.show()` in
|
they're enabled there, because `NOTIF.show()` in
|
||||||
`common.js` depends on `Notification.permission` + the
|
`common.js` depends on `Notification.permission` + the
|
||||||
`hyperhive.notify.muted` localStorage key, not on the buttons
|
`hyperhive.notify.muted` localStorage key, not on the buttons
|
||||||
existing in the page DOM.
|
existing in the page DOM.
|
||||||
|
|
@ -1091,9 +1089,9 @@ Pure frontend (`Notification` API). Two signals trigger them:
|
||||||
- new pending approval (per id, delta on `/api/state`)
|
- new pending approval (per id, delta on `/api/state`)
|
||||||
- new broker message sent `to: "operator"` (live via SSE)
|
- new broker message sent `to: "operator"` (live via SSE)
|
||||||
|
|
||||||
The toggle controls live in the `S3TT1NGS` tab (`#settings`); see
|
The toggle controls live in the Y3R C4LL tab's ◆ PR3F3R3NC3S ◆
|
||||||
that section above for the user-facing shape. Dispatch logic lives
|
section; see that section above for the user-facing shape. Dispatch
|
||||||
in `common.js::NOTIF`.
|
logic lives in `common.js::NOTIF`.
|
||||||
|
|
||||||
First `/api/state` after page load seeds "seen" sets without
|
First `/api/state` after page load seeds "seen" sets without
|
||||||
firing — only items that arrive while the page is open count.
|
firing — only items that arrive while the page is open count.
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
CSS bundle per page (`colors.css` + `theme.css` + `common.css`,
|
CSS bundle per page (`colors.css` + `theme.css` + `common.css`,
|
||||||
loaded by every page, plus a page-specific bundle —
|
loaded by every page, plus a page-specific bundle —
|
||||||
`dashboard.css` / `flow.css` / `logs.css` / `home.css` /
|
`dashboard.css` / `flow.css` / `logs.css` / `home.css` /
|
||||||
`settings.css` / `stats.css` / `core.css` / `builds.css` /
|
`stats.css` / `core.css` / `builds.css` /
|
||||||
`credentials.css`); `common.css` inlines `@hive/shared`'s
|
`credentials.css`); `common.css` inlines `@hive/shared`'s
|
||||||
`base.css` + `terminal.css` + `tabs.css` + `chrome.css` +
|
`base.css` + `terminal.css` + `tabs.css` + `chrome.css` +
|
||||||
`pill.css` via esbuild's `@import` resolution.
|
`pill.css` via esbuild's `@import` resolution.
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ mkdirSync(staticDir(''), { recursive: true });
|
||||||
// follow-up once asset sizes warrant it). esbuild writes each entry
|
// follow-up once asset sizes warrant it). esbuild writes each entry
|
||||||
// to `static/<name>.js` based on the entryPoint basename.
|
// to `static/<name>.js` based on the entryPoint basename.
|
||||||
await build({
|
await build({
|
||||||
entryPoints: [src('tabs.js'), src('flow.js'), src('logs.js'), src('home.js'), src('settings.js'), src('stats.js'), src('core.js'), src('builds.js'), src('credentials.js')],
|
entryPoints: [src('tabs.js'), src('flow.js'), src('logs.js'), src('home.js'), src('stats.js'), src('core.js'), src('builds.js'), src('credentials.js')],
|
||||||
outdir: staticDir(''),
|
outdir: staticDir(''),
|
||||||
bundle: true,
|
bundle: true,
|
||||||
format: 'esm',
|
format: 'esm',
|
||||||
|
|
@ -122,7 +122,7 @@ await build({
|
||||||
// so a swap replaces only it) + theme.css (the semantic derivation
|
// so a swap replaces only it) + theme.css (the semantic derivation
|
||||||
// layer) + common.css (shared typography, badges, buttons, inbox, side
|
// layer) + common.css (shared typography, badges, buttons, inbox, side
|
||||||
// panel) plus its own page-specific bundle.
|
// panel) plus its own page-specific bundle.
|
||||||
for (const entry of ['colors.css', 'theme.css', 'common.css', 'dashboard.css', 'flow.css', 'logs.css', 'home.css', 'settings.css', 'stats.css', 'core.css', 'builds.css', 'credentials.css']) {
|
for (const entry of ['colors.css', 'theme.css', 'common.css', 'dashboard.css', 'flow.css', 'logs.css', 'home.css', 'stats.css', 'core.css', 'builds.css', 'credentials.css']) {
|
||||||
await build({
|
await build({
|
||||||
entryPoints: [src(entry)],
|
entryPoints: [src(entry)],
|
||||||
outfile: staticDir(entry),
|
outfile: staticDir(entry),
|
||||||
|
|
@ -132,7 +132,7 @@ for (const entry of ['colors.css', 'theme.css', 'common.css', 'dashboard.css', '
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const html of ['index.html', 'dashboard.html', 'flow.html', 'logs.html', 'settings.html', 'stats.html', 'core.html', 'builds.html', 'credentials.html']) {
|
for (const html of ['index.html', 'dashboard.html', 'flow.html', 'logs.html', 'stats.html', 'core.html', 'builds.html', 'credentials.html']) {
|
||||||
copyFileSync(src(html), dist(html));
|
copyFileSync(src(html), dist(html));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -434,7 +434,7 @@ hive-side-panel .md td {
|
||||||
server-warnings banner, the footer) then spans edge-to-edge for free,
|
server-warnings banner, the footer) then spans edge-to-edge for free,
|
||||||
with no negative-margin breakout hacks. Only matches on pages that opt
|
with no negative-margin breakout hacks. Only matches on pages that opt
|
||||||
in by adding the wrapper (dashboard.html, index.html); FL0W / L0GS /
|
in by adding the wrapper (dashboard.html, index.html); FL0W / L0GS /
|
||||||
ST4TS / S3TT1NGS are full-bleed with their own `.<page>-main` padding. */
|
ST4TS are full-bleed with their own `.<page>-main` padding. */
|
||||||
.page-content { padding: 0 1.5em; }
|
.page-content { padding: 0 1.5em; }
|
||||||
|
|
||||||
/* ─── sticky top region ───────────────────────────────────────────────
|
/* ─── sticky top region ───────────────────────────────────────────────
|
||||||
|
|
|
||||||
|
|
@ -461,8 +461,32 @@ hive-agent-menu {
|
||||||
`JobqRollup` Preact component (`.jqr-*` classes, imported above) —
|
`JobqRollup` Preact component (`.jqr-*` classes, imported above) —
|
||||||
mounted by swarm.js::initJobqRollup into #jobq-rollup-section. */
|
mounted by swarm.js::initJobqRollup into #jobq-rollup-section. */
|
||||||
|
|
||||||
/* .notif-row / .btn-notif moved to settings.css with the S3TT1NGS
|
/* Browser-notification toggle row, now living in the Y3R C4LL tab's
|
||||||
page. */
|
◆ PR3F3R3NC3S ◆ section (was its own S3TT1NGS page/tile; mara: a
|
||||||
|
standalone page for one toggle didn't earn its own tile). Buttons
|
||||||
|
wired by NOTIF.bind() in common.js. */
|
||||||
|
.notif-row {
|
||||||
|
display: flex;
|
||||||
|
gap: 0.5em;
|
||||||
|
align-items: center;
|
||||||
|
margin: 0.5em 0;
|
||||||
|
font-size: 0.85em;
|
||||||
|
}
|
||||||
|
.btn-notif {
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: 0.85em;
|
||||||
|
background: transparent;
|
||||||
|
color: var(--cyan);
|
||||||
|
border: 1px solid var(--cyan);
|
||||||
|
padding: 0.2em 0.7em;
|
||||||
|
border-radius: 999px;
|
||||||
|
cursor: pointer;
|
||||||
|
text-shadow: 0 0 4px currentColor;
|
||||||
|
}
|
||||||
|
.btn-notif:hover {
|
||||||
|
background: color-mix(in srgb, var(--cyan) 10%, transparent);
|
||||||
|
box-shadow: 0 0 10px -2px currentColor;
|
||||||
|
}
|
||||||
|
|
||||||
.pending-state {
|
.pending-state {
|
||||||
color: var(--amber);
|
color: var(--amber);
|
||||||
|
|
|
||||||
|
|
@ -72,9 +72,6 @@
|
||||||
into the log viewer (an agent's logs, a build entry's log)
|
into the log viewer (an agent's logs, a build entry's log)
|
||||||
still live inside the relevant dashboard content. -->
|
still live inside the relevant dashboard content. -->
|
||||||
|
|
||||||
<!-- S3TT1NGS lives on its own page now (`/settings.html`), reached
|
|
||||||
from the H0M3 hub — operator-local prefs don't need a slot in
|
|
||||||
the operational tab strip. -->
|
|
||||||
</nav>
|
</nav>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
|
@ -129,6 +126,24 @@
|
||||||
<div id="approvals-section">
|
<div id="approvals-section">
|
||||||
<p class="meta">loading…</p>
|
<p class="meta">loading…</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Operator-local preferences (browser notifications). Was its own
|
||||||
|
S3TT1NGS page (`/settings.html`); mara moved it in here since a
|
||||||
|
standalone page for one toggle didn't earn its own tile. State
|
||||||
|
lives in the browser's localStorage — NOTIF.bind() (common.js)
|
||||||
|
wires the buttons, same dispatch NOTIF.show() already used for
|
||||||
|
approval/inbox notifications above. -->
|
||||||
|
<h2>◆ PR3F3R3NC3S ◆</h2>
|
||||||
|
<div class="divider">══════════════════════════════════════════════════════════════</div>
|
||||||
|
<p class="meta">operator-local preferences. these live in the browser's localStorage — they do not sync between devices and do not survive a profile wipe.</p>
|
||||||
|
<h3>◇ browser notifications</h3>
|
||||||
|
<p class="meta">desktop notifications for new approvals and broker messages addressed to you. requires a secure context (https or localhost). mute silences the notifications without revoking the OS-level permission.</p>
|
||||||
|
<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>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- SYST3M pane moved to /core.html (the standalone "C0R3" page):
|
<!-- SYST3M pane moved to /core.html (the standalone "C0R3" page):
|
||||||
|
|
@ -210,12 +225,6 @@
|
||||||
tabs.js boots on this page the corresponding renderers
|
tabs.js boots on this page the corresponding renderers
|
||||||
no-op silently (each guard is `if (!el) return`). -->
|
no-op silently (each guard is `if (!el) return`). -->
|
||||||
|
|
||||||
<!-- S3TT1NGS: operator-local preferences (browser-notification
|
|
||||||
toggle) live on their own page now (`/settings.html`), reached
|
|
||||||
from the H0M3 hub. The notif buttons moved there verbatim;
|
|
||||||
`NOTIF.show()` on this page still fires (it reads the same
|
|
||||||
localStorage + browser permission the settings page sets). -->
|
|
||||||
|
|
||||||
</main>
|
</main>
|
||||||
</div><!-- /.page-content -->
|
</div><!-- /.page-content -->
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -76,14 +76,6 @@
|
||||||
<span class="home-tile-desc">hive-wide turn stats · cost · model mix</span>
|
<span class="home-tile-desc">hive-wide turn stats · cost · model mix</span>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a class="home-tile" href="/settings.html">
|
|
||||||
<span class="home-tile-head">
|
|
||||||
<span class="home-tile-icon" aria-hidden="true">⚙</span>
|
|
||||||
<span class="home-tile-label">Settings</span>
|
|
||||||
</span>
|
|
||||||
<span class="home-tile-desc">operator-local prefs · browser notifications</span>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<a class="home-tile" href="/core.html">
|
<a class="home-tile" href="/core.html">
|
||||||
<span class="home-tile-head">
|
<span class="home-tile-head">
|
||||||
<span class="home-tile-icon" aria-hidden="true">⬡</span>
|
<span class="home-tile-icon" aria-hidden="true">⬡</span>
|
||||||
|
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
/* ─── /settings.html — operator-local preferences ──────────────────
|
|
||||||
Extracted from the dashboard S3TT1NGS tab. Same
|
|
||||||
minimal-chrome pattern as /flow.html and /logs.html: the back-link
|
|
||||||
header + title (.page-header / .page-back / .page-title) live in
|
|
||||||
@hive/shared/chrome.css; only the page body padding + the notif-toggle
|
|
||||||
row are page-specific and live here. */
|
|
||||||
|
|
||||||
body.settings-shell {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.settings-main {
|
|
||||||
padding: 1.2em 1.5em 2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Browser-notification toggle row (moved verbatim from dashboard.css —
|
|
||||||
the buttons + status that NOTIF.bind() in common.js wires up). */
|
|
||||||
.notif-row {
|
|
||||||
display: flex;
|
|
||||||
gap: 0.5em;
|
|
||||||
align-items: center;
|
|
||||||
margin: 0.5em 0;
|
|
||||||
font-size: 0.85em;
|
|
||||||
}
|
|
||||||
.btn-notif {
|
|
||||||
font-family: inherit;
|
|
||||||
font-size: 0.85em;
|
|
||||||
background: transparent;
|
|
||||||
color: var(--cyan);
|
|
||||||
border: 1px solid var(--cyan);
|
|
||||||
padding: 0.2em 0.7em;
|
|
||||||
border-radius: 999px;
|
|
||||||
cursor: pointer;
|
|
||||||
text-shadow: 0 0 4px currentColor;
|
|
||||||
}
|
|
||||||
.btn-notif:hover {
|
|
||||||
background: color-mix(in srgb, var(--cyan) 10%, transparent);
|
|
||||||
box-shadow: 0 0 10px -2px currentColor;
|
|
||||||
}
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
||||||
<!doctype html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<title>hyperhive // S3TT1NGS</title>
|
|
||||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
|
|
||||||
<link rel="stylesheet" href="/static/colors.css">
|
|
||||||
<link rel="stylesheet" href="/static/theme.css">
|
|
||||||
<link rel="stylesheet" href="/static/common.css">
|
|
||||||
<link rel="stylesheet" href="/static/settings.css">
|
|
||||||
</head>
|
|
||||||
<body class="settings-shell">
|
|
||||||
|
|
||||||
<!-- Minimal chrome: back link + title. Same pattern as flow.html /
|
|
||||||
logs.html — no full dashboard tabbar. Back link points to the
|
|
||||||
H0M3 hub (served at /), not the dashboard. -->
|
|
||||||
<header class="page-header">
|
|
||||||
<a class="page-back" href="/">← home</a>
|
|
||||||
<span class="page-title">S3TT1NGS</span>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<main class="settings-main">
|
|
||||||
<p class="meta">operator-local preferences. these live in the browser's localStorage — they do not sync between devices and do not survive a profile wipe.</p>
|
|
||||||
|
|
||||||
<h3>◇ browser notifications</h3>
|
|
||||||
<p class="meta">desktop notifications for new approvals and broker messages addressed to you. requires a secure context (https or localhost). mute silences the notifications without revoking the OS-level permission.</p>
|
|
||||||
<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>
|
|
||||||
|
|
||||||
</main>
|
|
||||||
|
|
||||||
<script type="module" src="/static/settings.js" defer></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
// /settings.html — operator-local preferences page.
|
|
||||||
//
|
|
||||||
// Extracted from the dashboard S3TT1NGS tab. The browser-notification
|
|
||||||
// toggle: NOTIF.bind() wires the enable / mute / unmute buttons and
|
|
||||||
// persists state to localStorage. The dashboard's NOTIF.show() calls
|
|
||||||
// (approvals) read that same localStorage state + the
|
|
||||||
// browser-level permission, so firing still works from the dashboard
|
|
||||||
// even though the toggle UI now lives on its own page.
|
|
||||||
//
|
|
||||||
// initServerWarnings() renders the shared top-of-page warnings banner,
|
|
||||||
// matching the other stand-alone pages (FL0W / L0GS / H0M3).
|
|
||||||
import { NOTIF, initServerWarnings } from './common.js';
|
|
||||||
|
|
||||||
initServerWarnings();
|
|
||||||
NOTIF.bind();
|
|
||||||
|
|
@ -257,12 +257,14 @@ window.marked = marked;
|
||||||
// title reflect unread agent->operator messages immediately, before the
|
// title reflect unread agent->operator messages immediately, before the
|
||||||
// operator opens the tab. Live updates arrive via the broker stream.
|
// operator opens the tab. Live updates arrive via the broker stream.
|
||||||
refreshOperatorInbox();
|
refreshOperatorInbox();
|
||||||
// NOTIF.bind() (the enable/mute/unmute toggle UI) moved to /settings.html
|
// NOTIF.bind() wires the enable/mute/unmute toggle buttons that now
|
||||||
// with the S3TT1NGS page. The dashboard keeps NOTIF.show() for approval
|
// live in the Y3R C4LL tab's ◆ PR3F3R3NC3S ◆ section. NOTIF.show()
|
||||||
// notifications — it reads the browser permission + localStorage
|
// (approval/inbox notifications) reads the same browser permission +
|
||||||
// mute flag the settings page sets, so no bind() is needed here. The
|
// localStorage mute flag regardless of which page fires it — bind()
|
||||||
// side panel (<hive-side-panel>) wires its own internals in
|
// only needs to run once, here, where the buttons live. The side
|
||||||
// connectedCallback — no bind() step needed either.
|
// panel (<hive-side-panel>) wires its own internals in
|
||||||
|
// connectedCallback — no bind() step needed for it.
|
||||||
|
NOTIF.bind();
|
||||||
|
|
||||||
// ─── live updates: dashboard event stream ──────────────────────────────
|
// ─── live updates: dashboard event stream ──────────────────────────────
|
||||||
// The dashboard subscribes to /dashboard/stream for live mutation
|
// The dashboard subscribes to /dashboard/stream for live mutation
|
||||||
|
|
@ -349,9 +351,9 @@ window.marked = marked;
|
||||||
// ─── tab routing ───────────────────────────────────────────────────────
|
// ─── tab routing ───────────────────────────────────────────────────────
|
||||||
// Hash-based: `#swarm` / `#call` / `#system` / `#permissions` /
|
// Hash-based: `#swarm` / `#call` / `#system` / `#permissions` /
|
||||||
// `#schedules` activate the matching pane on the dashboard. Empty
|
// `#schedules` activate the matching pane on the dashboard. Empty
|
||||||
// hash defaults to SW4RM. FL0W, S3TT1NGS, and ST4TS are NOT tabs —
|
// hash defaults to SW4RM. FL0W and ST4TS are NOT tabs —
|
||||||
// they're separate pages (`/flow.html`, `/settings.html`,
|
// they're separate pages (`/flow.html`, `/stats.html`) reached from
|
||||||
// `/stats.html`) reached from the H0M3 hub. Tab routing only
|
// the H0M3 hub. Tab routing only
|
||||||
// applies when the tab DOM is present (e.g. not on the flow page
|
// 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).
|
// itself, where these elements don't exist and the loop no-ops).
|
||||||
// The shared hash-routed tab strip (@hive/shared/tabs.js) owns the
|
// The shared hash-routed tab strip (@hive/shared/tabs.js) owns the
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,9 @@
|
||||||
// Tiny browser-local (localStorage) preference helpers shared by the
|
// Tiny browser-local (localStorage) preference helper, in `@hive/shared`
|
||||||
// dashboard's /settings.html and the per-agent page — both need the
|
// so a future second consumer (e.g. swarm-ui's own terminal) gets the
|
||||||
// exact same key name to actually talk to each other via the browser's
|
// exact same key name for free via the browser's shared per-origin
|
||||||
// shared per-origin storage (settings.html is where the operator sets
|
// storage, rather than an independent copy that could drift.
|
||||||
// the preference; every per-agent page's terminal reads it), so the
|
// `ExpandDetailsSetting` (the per-agent page's own settings popover) is
|
||||||
// get/set pair — and the key itself — live here once rather than as
|
// the only writer today; `Row.tsx` is the only reader.
|
||||||
// independent copies in each package that could drift out of sync.
|
|
||||||
|
|
||||||
const EXPAND_DETAILS_KEY = 'hive-agent-expand-details';
|
const EXPAND_DETAILS_KEY = 'hive-agent-expand-details';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,10 @@
|
||||||
# $out/dashboard/ the hive-c0re dashboard assets (full layout in
|
# $out/dashboard/ the hive-c0re dashboard assets (full layout in
|
||||||
# frontend/packages/dashboard/build.mjs):
|
# frontend/packages/dashboard/build.mjs):
|
||||||
# index.html (H0M3 hub, served at /) dashboard.html (operator SPA,
|
# index.html (H0M3 hub, served at /) dashboard.html (operator SPA,
|
||||||
# served at /dashboard.html) flow.html logs.html settings.html
|
# served at /dashboard.html) flow.html logs.html
|
||||||
# stats.html favicon.svg
|
# stats.html favicon.svg
|
||||||
# static/{home,tabs,flow,logs,settings,stats,stream-worker}.js{,.map}
|
# static/{home,tabs,flow,logs,stats,stream-worker}.js{,.map}
|
||||||
# static/{colors,theme,common,home,dashboard,flow,logs,settings,stats}.css
|
# static/{colors,theme,common,home,dashboard,flow,logs,stats}.css
|
||||||
# $out/agent/ the per-agent default UI (layered with
|
# $out/agent/ the per-agent default UI (layered with
|
||||||
# hyperhive.frontend.extraFiles at activation time)
|
# hyperhive.frontend.extraFiles at activation time)
|
||||||
# index.html stats.html screen.html
|
# index.html stats.html screen.html
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue