Split the old monolithic Hardware card into dedicated Board, WiFi, and
Sensors cards, matching the structure of `show system` / `show hardware`
in the CLI:
- System Information: add Current Time row, rename Firmware → Boot Partition
- Board: model, manufacturer, Base MAC only (no sensors)
- WiFi (new, conditional): all radios with supported bands, standards
(11n/11ac/11ax), and max AP count; card spans 2 grid columns so the
table never needs horizontal scroll
- Sensors (new, conditional, collapsible): all hardware sensors grouped
by parent component (SFP sub-sensors indent under sfp1/sfp2 headings);
JS "Show more" button injected only when content overflows 300 px
- Disk Usage: replaced wide multi-column table with a per-mount widget
(path + % on one line, health bar, "X free of Y" below); health colour
follows the same warn/crit thresholds as the memory bar
- Fix humanKiB to output IEC units (MiB / GiB) with a space, matching
the memory display style
- Fix info-table th wrapping (width:1%; white-space:nowrap)
- Fix JS collapsible init to run on DOMContentLoaded, not immediately in
<head>, so scrollHeight check has a real DOM to inspect
- CSS scroll-shadow on data-table-wrap: pure-CSS right-edge shadow
indicates overflow without needing JS or a scroll listener
- Equal-height grid rows via align-items:stretch; info-grid-span-2 for
cards with wide tables
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Replace the RAUC-centric firmware page with a cleaner layout:
- Show software slots (primary/secondary) using their bootnames rather
than internal RAUC slot names; filter to rootfs-class slots only
- Add boot order display (mirrors `show software` in the CLI)
- Show installed timestamp per slot (truncated to second precision)
- Fix Booted flag comparison: compare against bootname not slot name
- Lay out all three cards (Software, Install from URL, Upload & Install)
in a responsive grid instead of full-width stacked sections
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Drop the useless 768–1024px icon-only sidebar mode; everything up to
1024px now uses the hamburger overlay and full-width sidebar.
Fix the user dropdown on touch devices: click now toggles aria-expanded
so CSS-driven visibility works without hover. A document click listener
closes the menu when tapping outside.
Give the sidebar proper light/dark tokens instead of hardcoded dark
values. Introduce --sidebar-hover-fg (primary in light, white in dark)
so nav-link hover text is legible in both themes.
Fix dropdown hover background using --border instead of --border-subtle,
which had zero contrast against the surface in dark mode.
Keep active nav link in sync with the current URL via JS so it updates
correctly after htmx navigation instead of staying on the initial
server-rendered page. Also, add YouTube-style progress when laoding
pages that take time, e.g., Dashboard.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Anonymise the login page: generic "Login" title, lock icon instead
of product logo — makes the device harder to fingerprint.
Add a floating theme toggle button to the login page so users can
switch theme before logging in (cycles auto→light→dark).
Replace the four cluttered sidebar footer buttons (theme, download
config, reboot, logout) with an always-visible topbar user menu.
The dropdown shows the username, three theme options with a checkmark
on the active one, download config, reboot, and logout.
Refactor all handler page-data structs to embed PageData instead of
repeating the four base fields, and add Username (sourced from the
request context) so the topbar can display the logged-in user.
Polish pass on the login card: spacing, focus styles, button weights.
Replace the AES-encrypted-cookie session model with an opaque random
token backed by an in-memory map. The vendored design embedded the
user's username, password, CSRF, and feature flags into the cookie
and persisted the AES key under /var/lib/misc, making the keyfile a
passive credential-recovery oracle — anyone who could read it could
decrypt any captured cookie and recover the plaintext admin password.
Now: cookie is 32 bytes of crypto/rand, base64-url-encoded; sessions
live only in process memory; reboot/respawn/upgrade drops every
active session and the UI's 401 handler bounces the user to /login.
Sliding-window refresh on user activity, janitor goroutine sweeps
expired entries. --session-key flag and /var/lib/misc/webui-session.key
are gone.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Replace flat nav-section-header labels with collapsible <details>/<summary>
accordion groups (Network, Wireless, VPN, Services, System). Groups default
open; user state persists via localStorage. Tablet icon-only mode always
shows all items regardless of open/closed state.
Add badge-up/down/warning/info/neutral utility classes with full dark mode
support, complementing the existing firewall-specific badge variants.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>