Skip to content

Seven-item navigation, Home as the status page, one confirm dialog - #36

Merged
im-tyler merged 11 commits into
mainfrom
nav-rework
Nov 12, 2026
Merged

im-tyler merged 11 commits into
mainfrom
nav-rework

Conversation

@im-tyler

Copy link
Copy Markdown
Contributor

Reworks Dash's navigation and fixes the UI problems found in the 2026-11-11 review. No feature is removed and every existing URL and alias keeps working.

  • Header: thirteen destinations become seven: Home, Apps, Servers, Monitoring, Backups, Activity, Settings. Domains and Alerts are tabs under Monitoring; Restore tests is a tab under Backups (both lists merged); Cleanup is under Servers; Templates under Apps; Integrations (was Siblings) and Git sources (was Sources) under Settings. The nav tightens below 1100px and collapses below 900px.
  • Home: now a status page (needs attention, running now, servers) with the shortcut grid below. A source that fails to load shows as could-not-check, never as nothing wrong.
  • Tabs in the URL for app, server, Settings and Backups.
  • One confirm dialog replaces every browser confirm() and prompt(); remove app and remove server ask for the typed name, and Remove app moves to a Danger section.
  • Monitor dot follows the latest check or an open incident, not 24-hour uptime; running operations get their own dot; one date helper.
  • Phone layout: stacked rows for Domains, Backups and accessories; scroll hint on tab strips.
  • Git sources page rebuilt as a table with delete.
  • Fixes: console errors on Cleanup and Siblings, undefined CSS variables, owner-specific placeholder text.

Backend: /api/cleanup rows carry each server's disk line and /api/monitors carries last_check, each with a Go test.

Tested with 138 frontend tests, go test with the race detector, and the contracts job. Rendering was checked in headless Chromium at 1440px and 390px against fixture data, not a live Dash. Not checked in a browser: login and first-run setup, viewer and editor roles, the repository connect wizard, Safari.

🤖 Generated with Claude Code

im-tyler and others added 11 commits November 11, 2026 16:21
- cleanupPage and siblingsPage declare loading; guard the dismissed-by,
  sibling dashboard_url and cleanup detail.server reads that threw.
- Define --success, --success-bg, --warning, --danger and --bg-inset so
  chips stop rendering near-white on dark.
- Checkboxes inside .field keep their natural size; the Siblings probing
  consent line uses a neutral banner instead of the warning one.
- Backups cards get spacing; the Monitors header drops the unrelated CLI
  version chip.
- Public placeholders: git.example.com, example.com, shop-.
- New frontend-test/nav_rework.test.mjs holds the checks for this rework.

Co-Authored-By: Claude <noreply@anthropic.com>
The router gains setTab(tab, fallback): the tab rides the query string as
?tab=<name>, the default tab is left out, and the change replaces the
history entry so arrow-keying across a tab strip does not fill history.
App detail, server detail and Settings read the tab on open and follow it
when the URL changes, so reload, shared links and Back into a page land
on the tab.

Co-Authored-By: Claude <noreply@anthropic.com>
- Fleet reads Servers, Projects reads Apps, Siblings reads Integrations,
  Sources reads Git sources; the app tab Activity reads History (the
  global page keeps Activity); the monitors page title reads Uptime.
- /apps is a new alias for the apps page.
- Cleanup's ok state reads "Audited" with the open warning count instead
  of "Clean bill" (ok means the audit completed, not that it is clean).
- Restore-test intervals read hourly/daily/weekly, else "every N h".

Co-Authored-By: Claude <noreply@anthropic.com>
… tabs

The header is Home, Apps, Servers, Monitoring, Backups, Activity, then
Settings. Pages that had their own slot are now tabs, and every old URL
opens the page and tab it moved to:

- Monitoring: Uptime (/monitors), Domains (/domains), and a new Alerts tab
  (/alerts) holding incidents, silences and deliveries, which used to sit
  at the bottom of the monitors list, with a link to Settings >
  Notifications.
- Servers: Servers and Cleanup (/cleanup); a server's cleanup report is
  the Cleanup tab of its server page (/cleanup/:server opens it). The
  Servers page gains an Add server button that opens Settings > Servers.
- Apps: Apps and Templates (/templates); + Deploy offers "From an image"
  and "From a template".
- Backups: Coverage, Setup (the wizard and Advanced) and Restore tests
  (/restore-tests opens it), where the automatic and the hand-added tests
  are one table with an "Added by" column.
- Settings gains Integrations (/siblings) and Git sources (/sources).

Routes may carry fixed params, so an old path maps to a page and tab;
navigate() still accepts the old page names. The header was re-measured:
brand + seven destinations need 695px tightened and 857px with four
pinned icons, so the nav tightens below 1100px and collapses below 900px
(was 1400/1240). header_layout and ia_routes assert the new structure.
.table-wrap is positioned so sr-only header labels cannot widen a page.

Co-Authored-By: Claude <noreply@anthropic.com>
Home now opens on three status sections, each loading on its own from
the endpoints the other pages already read, with the shortcut grid kept
below (add, edit, drag unchanged):

- Needs attention: open incidents, unreachable servers, failing domains
  and certificate warnings, failing or uncovered backups, the "Protect my
  data" state (formerly a banner), and operations that failed in the last
  day. Each row links to its page. A source that failed to load is named
  with a Retry, so a failure never reads as "Nothing needs attention";
  that line carries the time of the oldest observation.
- Running now: operations in progress, linking to their live log.
- Servers: one row each with reachability, app count and disk.

Backend: /api/cleanup rows carry the root-disk line of each server's last
cached audit (path, available bytes, used percent; no attribution), so
Home and Servers show disk without opening every report. Test:
TestCleanupFleetRowCarriesDisk.

Co-Authored-By: Claude <noreply@anthropic.com>
Every browser confirm() (31) and prompt() (7) is replaced by one dialog
component, modelled on the Cleanup fix dialog (focus trapped, Escape and
the backdrop cancel, focus returns): askConfirm() for confirmations and
askForm() for questions that need an answer, with labelled fields. A
typed name gates removing an app, removing a server and resetting a git
watermark; the Cleanup destructive fix and backup restore keep their
existing typed-name dialogs. The confirm button is named by the action
(Remove, Delete, Roll back, ...) and is red for destructive ones.

- Remove app moves from beside Restart to a Danger section at the bottom
  of the app General tab; its confirm and the redirect question are one
  dialog.
- New project, new group, rename, and reset password ask in a dialog with
  form fields instead of prompt().
- The unlabelled 14px "x" on project and app cards becomes a named
  actions menu ("Actions for <name>") holding the same action; the
  shortcut remove button is named too.

Tests answer the dialog through frontend-test/dialog_bridge.mjs, which
routes it to their existing confirm/prompt stubs.

Co-Authored-By: Claude <noreply@anthropic.com>
- A monitor's dot was its 24-hour uptime: a monitor down right now could
  read green. It now reads the newest check (red when it failed or an
  incident is open, green when it passed, grey when paused or unchecked),
  with "Down now (checked 2 min ago)" as its label; the uptime percentage
  stays as text. Backend: GET /api/monitors carries each monitor's newest
  check as last_check. Test: TestMonitorListCarriesLastCheck.
- A running operation no longer shares the green dot of a succeeded one:
  in progress is a pulsing blue, canceled grey (Activity and operation
  detail).
- One date helper: relTime/ageText give relative text ("5 min ago",
  "in 3 h") and the x-time directive pairs it with the exact time in a
  title attribute. Every formatDate/formatWhen/ageLabel copy and the
  Activity times delegate to it; templates format no dates by hand.

Co-Authored-By: Claude <noreply@anthropic.com>
- Wide tables stack on phones (.stack-table): one block per row, the
  thing the row is about first, then the problem text, then the other
  cells with their column names. Applied to Domains (HTTP and "What is
  wrong" were cut off), Backups > Every target (everything after State
  was cut off), the merged restore tests, and the app's containers and
  accessories (Start/Stop were cut off).
- Status cards stay two to a row at 390px instead of one per row.
- Tab strips scroll sideways at every width and fade on the side that
  has more (x-scroll-hint), and the active tab scrolls into view; this
  covers the app's ten tabs, Settings, Backups and the hub tabs.

Co-Authored-By: Claude <noreply@anthropic.com>
…nitors

App General tab:
- The running/stopped state sits beside the app name; the server and the
  domain are links under it (the domain no longer overflows a card).
- Start or Stop is shown by state (both when the state is unknown).
- Port, Locked and Maintenance fold from three cards into one line.
- Links to the app's uptime monitor and its domain-health row, with their
  current state (read from the cached monitor and domain lists).

Servers:
- Each card shows its app count, disk use and a cleanup line ("Audited,
  2 warnings (3 days ago)") that opens the server's Cleanup tab.
- Server detail's Overview lists the apps on that server (from the fleet
  sweep) and links to its cleanup report, Backups and Domains.
- Domain rows link to their app; a monitor's detail names and links the
  app it watches, and its card names it.

The remaining relative times (observed age, deployed, last successful
observation) use the shared date helper.

Co-Authored-By: Claude <noreply@anthropic.com>
The Sources page read as unfinished; as Settings > Git sources it is now:
- a table like the other pages (repository, forge, branch, credential
  state as a coloured dot with a readable label and the degrade reason);
- the selected source's detail above the add form, with the full webhook
  URL, verify and rotate actions, and recent deliveries as a table;
- a Delete action through the confirm dialog (DELETE /api/sources/{id},
  which the API already had);
- help text for "Provider name" (an entry in the source-provider file on
  the Dash host; Dash stores only the name);
- a link to it from each app's Repository tab.

Also: tab strips keep the active tab in view when it changes or when
hidden tabs appear, and stacked rows bold only the row's name.

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
@im-tyler
im-tyler merged commit fffc2eb into main Nov 12, 2026
3 checks passed
@im-tyler im-tyler mentioned this pull request Nov 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant