dashboard: new S3TT1NGS tab housing the notification toggle (closes #763)
Adds a fifth tab (◆ S3TT1NGS ◆) at the end of the dashboard tab strip; moves the browser-notification controls out of the chrome header into the new pane. ### Why The chrome was carrying the notification controls as 'always-on ergonomics' but the surface they belong on is operator preferences, not navigation. With #589 / #701 likely adding more per-browser preferences later (theme / density / etc.), having a dedicated S3TT1NGS pane gives them a home so the chrome strip doesn't keep accreting controls. ### Shape - index.html: new `#tab-pane-settings` section with H2 + intro + H3 'browser notifications' group; same notif-row DOM (same IDs) migrated from the chrome - flow.html: drops the duplicated notif-row from its chrome (FL0W reused the dashboard's strip); adds a `◆ S3TT1NGS ◆ →` cross-page link to `/#settings`. Notifications still fire on FL0W when enabled — NOTIF.show() reads Notification.permission + the hyperhive.notify.muted localStorage key directly, no buttons needed in the page DOM. - tabs.js: adds 'settings' to TABS array so hash routing activates the pane - dashboard.css: drops the chrome-anchoring `.tabbar #notif-row` rule and the flow-page reuse comment, both obsolete; the general `.notif-row` styling stays - docs/web-ui.md: new `### S3TT1NGS tab` section; Chrome-header bullet drops 'Notification controls' + adds S3TT1NGS; Browser notifications section pointers at the new pane ### No JS or backend changes Same IDs (notif-row, notif-enable, notif-mute, notif-unmute, notif-status) so `NOTIF.bind()` in common.js wires the new pane unchanged. NOTIF.show() dispatch is DOM-independent. ### Validation `npm run --workspace @hive/dashboard build` clean (tabs.js 167.8kb, flow.js 37.4kb, dashboard.css 50.2kb).
This commit is contained in:
parent
80dd4babd4
commit
6cf169d324
5 changed files with 92 additions and 52 deletions
|
|
@ -284,20 +284,22 @@ cross-page link (`◆ FL0W ◆ →`), not a pane swap.
|
|||
**Chrome header** (fixed, overlays the active tab pane):
|
||||
- **Tab strip**: `◆ SW4RM ◆`, `◆ Y3R C4LL ◆`, `◆ SYST3M ◆`,
|
||||
`◆ SCH3DUL3S ◆`, `◆ M4TR1X ◆ →` (optional page link, see below),
|
||||
and `◆ FL0W ◆ →` (page link). Count pills on SW4RM (container
|
||||
count), Y3R C4LL (pending approvals + questions), and SCH3DUL3S
|
||||
(active schedules); FL0W pill mirrors the operator inbox length
|
||||
(hidden when zero). The M4TR1X → entry is hidden when
|
||||
`◆ FL0W ◆ →` (page link), and `◆ S3TT1NGS ◆`. Count pills on
|
||||
SW4RM (container count), Y3R C4LL (pending approvals + questions),
|
||||
and SCH3DUL3S (active schedules); FL0W pill mirrors the operator
|
||||
inbox length (hidden when zero); S3TT1NGS has no count. The
|
||||
M4TR1X → entry is hidden when
|
||||
`services.hyperhive.matrix.gui.enable` is off (defaults to
|
||||
`matrix.enable`) so operators without the matrix GUI on don't
|
||||
see a dead link — tabs.js gates the `hidden` attribute on
|
||||
`state.matrix_gui_enabled` from `/api/state`.
|
||||
- **Notification controls**: `🔔 enable notifications` when
|
||||
permission ungranted; `🔕 mute / 🔔 unmute` toggle once granted.
|
||||
Always visible in the chrome regardless of active tab.
|
||||
- **Banner-thin** (`░▒▓█▓▒░ HYPERHIVE / HIVE-C0RE / WE ARE THE WIRED ░▒▓█▓▒░`)
|
||||
— sits below the tab strip.
|
||||
|
||||
The FL0W page reuses the same chrome strip but its `◆ S3TT1NGS ◆ →`
|
||||
entry is a cross-page link back to the dashboard
|
||||
(`/#settings`) since the settings pane only lives there.
|
||||
|
||||
### SW4RM tab
|
||||
|
||||
**C0NTAINERS** — live containers rendered as a depth-first
|
||||
|
|
@ -445,6 +447,32 @@ button hard-deletes (`POST /cancel-reminder/{id}`) and a
|
|||
Lives in the SCH3DUL3S tab alongside operator schedules so the
|
||||
operator has one place for everything time-fired.
|
||||
|
||||
### S3TT1NGS tab
|
||||
|
||||
Operator-local preferences. State lives in the browser's
|
||||
`localStorage` — preferences do NOT sync between devices and
|
||||
do NOT survive a profile wipe. Today the tab holds one section
|
||||
(browser notifications); future preferences (theme, density,
|
||||
inbox-pill threshold, etc.) land here as sibling `<h3>` blocks
|
||||
under the same `<section id="tab-pane-settings">`.
|
||||
|
||||
**◇ 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 FL0W page does NOT host this pane — its tab-strip
|
||||
`◆ S3TT1NGS ◆ →` entry is a cross-page link to the dashboard's
|
||||
`#settings` route. Notifications still fire on the FL0W page when
|
||||
they're enabled here, because `NOTIF.show()` in
|
||||
`common.js` depends on `Notification.permission` + the
|
||||
`hyperhive.notify.muted` localStorage key, not on the buttons
|
||||
existing in the page DOM.
|
||||
|
||||
### M4TR1X page (`/matrix/`, optional)
|
||||
|
||||
A static matrix web client (default `pkgs.fluffychat-web` rebuilt
|
||||
|
|
@ -755,6 +783,10 @@ Pure frontend (`Notification` API). Three signals trigger them:
|
|||
- new pending operator question (per id)
|
||||
- new broker message sent `to: "operator"` (live via SSE)
|
||||
|
||||
The toggle controls live in the `S3TT1NGS` tab (`#settings`); see
|
||||
that section above for the user-facing shape. Dispatch logic lives
|
||||
in `common.js::NOTIF`.
|
||||
|
||||
First `/api/state` after page load seeds "seen" sets without
|
||||
firing — only items that arrive while the page is open count.
|
||||
Per-event tags (`hyperhive:approval:<id>`, `hyperhive:question:<id>`,
|
||||
|
|
@ -762,12 +794,13 @@ Per-event tags (`hyperhive:approval:<id>`, `hyperhive:question:<id>`,
|
|||
notification center instead of overwriting each other.
|
||||
`console.debug` logs at every block point (unsupported,
|
||||
permission ungranted, muted) for in-browser debugging. Click
|
||||
focuses the dashboard tab. localStorage-backed mute toggle
|
||||
silences without revoking the OS permission. Requires a secure
|
||||
context (HTTPS or localhost); on other origins the controls hide
|
||||
themselves. Browsers typically suppress notifications while the
|
||||
originating tab is focused — that's a browser-level decision,
|
||||
not ours.
|
||||
focuses the dashboard tab. The localStorage key
|
||||
`hyperhive.notify.muted` (`"1"` = muted, absent = unmuted) backs
|
||||
the toggle and silences dispatch without revoking the OS
|
||||
permission. Requires a secure context (HTTPS or localhost); on
|
||||
other origins the controls hide themselves. Browsers typically
|
||||
suppress notifications while the originating tab is focused —
|
||||
that's a browser-level decision, not ours.
|
||||
|
||||
### Dashboard endpoints
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue