Commit Graph

6432 Commits

Author SHA1 Message Date
rcourtman f453d56607 Show native TrueNAS storage topology
Replace the generic embedded storage surface with a TrueNAS-owned topology table for pools, datasets, and physical disks.

Keep pool child inventory visible by default and route rows through the shared platform detail drawer.
2026-05-21 08:48:19 +01:00
rcourtman 497390ff95 Scope TrueNAS resources by appliance
Scope TrueNAS child source IDs under the system source key so duplicate pool, dataset, app, VM, share, and disk names from different appliances do not merge.

Use the resulting hierarchy for per-system TrueNAS overview counts and scoped mock metric targets.
2026-05-21 00:59:00 +01:00
rcourtman 0fb0287e86 Surface TrueNAS health alerts on overview 2026-05-21 00:34:00 +01:00
rcourtman 58a2ad8cc6 Add TrueNAS protection tab 2026-05-21 00:13:21 +01:00
rcourtman 0801ede8c3 Add native TrueNAS network share inventory 2026-05-20 23:50:37 +01:00
rcourtman 6d55ca531c Expose native TrueNAS details in resource drawer 2026-05-20 23:00:55 +01:00
rcourtman 3fa46aa836 Add native TrueNAS VM inventory to overview
Project TrueNAS vm.query inventory into canonical VM resources and render it on the TrueNAS overview.
2026-05-20 22:32:46 +01:00
rcourtman 2202f36674 Rebuild TrueNAS overview around native app API data
Project TrueNAS app.query data into the unified resource contract and render the TrueNAS overview apps table from that native facet.

Keep Docker metadata as the runtime compatibility fallback for shared container tooling.
2026-05-20 21:54:40 +01:00
rcourtman 557c5151f2 Share app-container column config between Docker and TrueNAS
TrueNAS apps are Docker containers running under the embedded daemon, so
the apps table on the TrueNAS overview should default to the same column
set as the Docker / Podman containers table: writable layer hidden by
default, tags hidden by default, and Net I/O and Disk I/O hidden when no
container in the set reports telemetry. Previously the TrueNAS surface
rendered the workload table with raw defaults, which exposed an empty
"Disk" column and an always-visible "Disk I/O" column that no real
TrueNAS app populates.

Extract APP_CONTAINER_BASE_DEFAULT_HIDDEN_COLUMNS,
APP_CONTAINER_COLUMN_LABEL_OVERRIDES, and the telemetry-aware
buildAppContainerDefaultHiddenColumnIds into a shared
appContainerColumns module under features/platformPage. The Docker page
keeps its context: 'Host' relabel on top of the shared overrides; the
TrueNAS page now scopes its column-visibility prefs under
truenas-app-containers and pulls the same hidden-column defaults from
its own app list. buildDockerContainerDefaultHiddenColumnIds is
preserved as an alias so the existing docker page tests still pass.
2026-05-20 21:27:40 +01:00
rcourtman 6708c6a2c7 Surface host OS family in Docker SYSTEM column
getInfrastructureSystemIdentityBadges never consulted resource.docker.os,
so plain Docker hosts (no Pulse host-agent overlay) fell through the
agent-identity and source paths to the runtime-only "Docker" badge, which
getDockerHostSystemBadge filters out — leaving the SYSTEM column blank on
the Containers overview for every host whose OS the docker-agent already
reported via info.OperatingSystem.

Add getDockerHostOsIdentityBadge: when resource.docker.os is present,
match it through the same host-OS label patterns used for agent.osName
and emit a Debian / Ubuntu / Alpine / etc. badge with the full OS string
as the hover title. Inserted in the resolver chain after the agent
fallback so a Pulse host-agent still wins when both signals exist.
2026-05-20 21:20:01 +01:00
rcourtman ddad6108ae Classify runtime lenses in platform manifest 2026-05-20 20:45:53 +01:00
rcourtman 4a5873d49c Rename primary navigation model for runtime lenses
Rename the shared shell navigation contract from platform-only terminology to infrastructure navigation so it can represent both owning platform pages and the Docker / Podman container-runtime lens. Update mobile nav primitives, command palette, shortcuts, and governed docs to keep Docker as a Containers runtime lens without changing the /docker route.
2026-05-20 20:28:01 +01:00
rcourtman 16205bdd44 Align container runtime navigation with platform scopes
Prefer platformScopes for primary navigation evidence so TrueNAS app Docker metadata does not expose the container runtime lens. Label the Docker / Podman route as Containers in shell navigation while preserving the /docker route and runtime-specific copy.
2026-05-20 20:03:10 +01:00
rcourtman aabef9afd5 Add canonical platform scopes for runtime workloads
Teach unified resources to emit platformScopes so runtime workloads can belong to both Docker and their owning platform. Update workload filters to use platform scopes and keep TrueNAS app containers scoped to TrueNAS.
2026-05-20 19:30:55 +01:00
rcourtman 2f77e2680d Soften Duration column tone to canonical Pulse metric palette
The amber-500 / amber-400 / emerald-500 fills on the Duration bar
were all fully opaque, which read as a wall of saturated orange on
any tab with many slow tasks. Switch to the canonical bg-metric-*-bg
tokens that Storage and Ceph row bars already use — same 60%-alpha
palette, immediately calmer in the same column.

Also cap at `warning` (soft yellow) rather than going to `critical`
(red) for the worst case. A slow backup task is a perf outlier, not
a failure; failure is already conveyed by the Status column. Two
tiers — normal / slow — keeps the column from looking alarmed on
every long-running VM backup.

No-data slots stay neutral via slate-500/30 instead of slate-400, so
empty rows don't draw the eye.
2026-05-20 19:04:53 +01:00
rcourtman 350a913ea4 Add click-sort to all three Proxmox Backups tabs
Was a gap, not an intentional decision. Storage has full click-sort
with arrow indicators; Replication and Ceph don't, but those have
8 jobs / 1 cluster respectively — easy to eyeball. Backups has 184
tasks and 189 archives, which is past the scannable threshold for
"which backup is biggest? which task ran slowest? which guest is
hoarding snapshot disk?" — exactly the questions a sysadmin opens
the page to answer.

Reuse Storage's pattern: per-column sortKey + sortDirection signals,
default direction per key (desc for numeric/timestamp, asc for
strings, desc for booleans), `aria-sort` on the TH, idle / asc /
desc arrow trio rendered the same way as StoragePoolsTable.tsx.

Numeric/string comparators put undefined values last regardless of
direction — flipping a running task with no finished duration to
the top of a desc sort would never be what the user wants. Boolean
comparator follows direction so Protected/Verified sort cleanly.

Default sort per tab preserves the current behaviour (newest first):
- Snapshots: latest desc
- Backup files: created desc
- Recent tasks: started desc

Sortable columns:
- Snapshots: guest, node, latest, snapshot count, total size
- Backup files: volume, guest, storage, node, format, created,
  size, protection, verified
- Recent tasks: status, guest, node, started, duration, size
2026-05-20 18:41:37 +01:00
rcourtman 09bf209afd Use canonical ProgressBar for backup row metric bars
The Backups Size and Duration columns were rendering a bespoke
`InlineProgressBar` — a small fixed-width bar floating next to text.
Every other row metric in Pulse (Storage usage, Ceph pool usage,
Workloads CPU/Memory/Disk) is rendered by `ProgressBar` from
`@/components/shared`: full-cell-width fill with the value text
overlaid on top, via a foreignObject-clipped label. Introducing a
second pattern just for these two columns was a needless divergence
called out in the second consistency pass.

Drop the bespoke component. Wrap shared `ProgressBar` in a
RowMetricBar helper that matches the Storage/Ceph convention
(`STORAGE_BAR_LABEL_WRAP_CLASS` shape) and use it for both columns.
The Size and Duration headers move to the `metric-bar` column kind
so alignment lines up with the bar's natural centring. Bars now
share the same shape, animation curve (320ms width transition from
`progress-fill`), and label-clipping behaviour as the rest of the
app — same code path, same look.
2026-05-20 18:21:03 +01:00
rcourtman 806a2331a3 Align inline progress bars so rows are visually comparable
The Size and Duration columns were rendering the bar to the LEFT of
the value text with `justify-end` on the whole flex group. Because
the text width varies row-to-row ("8 KB" vs "131 GB", "48m 0s" vs
"1h 23m 5s"), the bar's right edge shifted with the text, so two
bars in the same column did not share a common baseline. That
defeats the point of a comparison bar — you can't read relative
length when the bars are positioned differently per row.

Put the bar AFTER the text instead. Since the bar has a fixed width
and is now the rightmost element in the cell, every bar's left and
right edges land at the same x in every row, and the column reads
as a proper mini-chart. Always render the bar slot (empty track when
the underlying value is 0) so the column rhythm stays constant when
data is missing. Documented the invariant on the InlineProgressBar
helper.
2026-05-20 18:07:12 +01:00
rcourtman 2abb55f63f Second consistency pass on Proxmox backup tabs
Smaller details that diverged from sibling pages:

- Tone-colour the Recent tasks STATUS word per state (emerald / red /
  amber / muted), matching Replication's `text-emerald-600 dark:
  text-emerald-300` per-state tone. Was rendering everything in
  default base-content white.

- Move the Snapshots row age dot from the GUEST column to the LATEST
  column so the timestamp-and-its-freshness-dot live together — same
  pattern Backup files already uses in its Created column. The
  leftmost GUEST cell is now just chevron + label.

- Tighten counter wording. "189 entries" / "184 entries" → "189
  archives" / "184 tasks", matching Replication's "8 jobs" and Ceph's
  "1 clusters" domain-noun convention.

- Pill-style the Verified column in Backup files (emerald chip) so it
  reads as a sibling of the existing amber Protected chip rather than
  dot+text. Both columns now signal an explicit positive state with
  the same chip shape.

- Tighten inner snapshot-drilldown table header padding to py-0.5 to
  match the outer table's getPlatformTableHeadClass (was py-1).
2026-05-20 17:57:03 +01:00
rcourtman 01618589fe Align Proxmox backup tabs with sibling page conventions
Consistency pass after the initial backup-pages rework. Row-dot
colours, coverage-strip segments, and filter-chip labels were
encoding the same data through three different threshold schemes;
all three now share the per-tab SLA buckets so a 14d archive shows
amber in the row, sits in the amber stale (7–30d) segment of the
strip, and lands under the "Stale" filter chip.

Other tightening: hide the single-segment chart legend when there's
nothing to disambiguate (Snapshots and Backup files); always render
the Error column on Recent tasks (matching Replication, where it
shows "—" rather than collapsing); reword the Backup-files strip
tail from the ambiguous "guests covered" to "guests with archives";
strip the redundant inner-table border in the snapshot drilldown so
it reads like Ceph's borderless sub-tables; terse "X guests" or
"X of Y guests" counter on the Snapshots tab matching Replication's
"8 jobs" style.

Adds classifyArchiveRowAge / classifySnapshotRowAge in the summary
module with unit coverage for the threshold breakpoints, and drops
a dead archiveMetricMode() reference left over from the earlier
patch.
2026-05-20 17:50:25 +01:00
rcourtman 9730460f8a Bring Proxmox backup sub-pages up to Storage/Ceph visual density
The three Backups tabs (Snapshots, Backup files, Recent tasks)
enumerated artifacts in flat tables with almost no graphic encoding,
while sibling Proxmox pages (Overview, Storage, Ceph) lead with
coverage-shaped summaries and per-row visual signal. Aligns them.

Snapshots gains a per-day chart, filter chips (All / Recent ≤7d /
Stale >30d / With RAM), a coverage strip splitting guests by newest-
snapshot bucket, and a guest-grouped table whose rows expand to show
the per-guest snapshot history (same drilldown pattern as Ceph).

Backup files gains a coverage strip (current / stale / uncovered
guests against a 7-day SLA), a Count/Volume toggle so the chart can
answer "how much disk did backups take" not just "how many files",
an age dot on the Created column, and an inline size bar in the Size
column (relative to the largest file in view).

Recent tasks gains a coverage strip (OK / failed / running plus
median duration), an inline duration bar tone-coded against the
median, and the Error column is hidden when no task in view has an
error. Shared row-level age presentation lives in the new
proxmoxBackupSummaryPresentation module with unit coverage.
2026-05-20 17:37:46 +01:00
rcourtman bfff0490e6 Fix assistant drawer close affordance on mobile 2026-05-20 17:21:06 +01:00
rcourtman 93ba610892 Hide Reset on storage filter row when source is externally forced
StoragePageControls.showClearAll fed the actual sourceFilter() into
hasActiveStorageFilters even when the parent forced the scope via
suppressSourceFilter (e.g. Proxmox/Storage mounts StorageSurface
with forcedSourceFilter='proxmox-pve'). Because 'proxmox-pve' is not
the global DEFAULT_STORAGE_SOURCE_FILTER ('all'), the active-filter
check returned true on first paint and the Reset button showed
unconditionally — even though no user-controllable filter had been
changed.

Treat the source filter as DEFAULT_STORAGE_SOURCE_FILTER inside the
active check when suppressSourceFilter is set; the user can't change
that filter on a scoped storage tab, so it must not surface Reset.
suppressNodeFilter was already handled symmetrically; this aligns
sourceFilter with that contract.
2026-05-20 17:15:00 +01:00
rcourtman 9cb698e736 Unify platform sub-page status toggles with overview compact pills
PlatformTableToolbar was rendering FilterButtonGroup with the default
variant (heavy bg-surface-alt box, border-heavy active state, fixed
blue active color) on every platform sub-page — Replication, Ceph,
Backups, Mail Gateway, Docker Hosts/Services, K8s Clusters/Nodes/
Deployments, TrueNAS Systems, vSphere Hosts. The Proxmox / Docker
overview WorkloadsFilter, by contrast, uses the compact variant with
per-option tone, so "Running" goes green, "Stopped" goes red, etc.

Switch the shared toolbar to compact and enrich the shared status
filter option arrays (PLATFORM_STATUS_FILTER_OPTIONS,
PLATFORM_HEALTH_FILTER_OPTIONS) with tone + leading status dot. Same
treatment for the bespoke filter arrays on Replication (Healthy /
Failed / Pending / Disabled), Ceph (Healthy / Warning / Critical),
and Backups archives + tasks (Protected / Verified / Unverified,
OK / Failed / Running). Backups archives and tasks also flip from
default to compact variant since they bypass PlatformTableToolbar.

Settings panel FilterButtonGroup usages stay default — different
context, intentionally heavier.
2026-05-20 17:08:27 +01:00
rcourtman f58a5f3290 Align platform storage filters with overview search 2026-05-20 16:56:09 +01:00
rcourtman 35399389a9 Handle Discovery missing-config diagnostics 2026-05-20 16:13:49 +01:00
rcourtman ba374da2ee Tighten Discovery drawer signal 2026-05-20 15:55:19 +01:00
rcourtman 59417a7da7 Hydrate shell navigation from protected state 2026-05-20 15:51:27 +01:00
rcourtman 45d958ff5d Remove redundant platform page headers 2026-05-20 15:39:43 +01:00
rcourtman 788cfcf53c Add platform page headings 2026-05-20 15:10:24 +01:00
rcourtman 0d33b50df6 Label notification and settings switches 2026-05-20 15:04:33 +01:00
rcourtman 6ebf0c6886 Label alert schedule toggles by section 2026-05-20 14:57:52 +01:00
rcourtman 142236d797 Seed mock Discovery fixtures 2026-05-20 14:54:19 +01:00
rcourtman 7b56ef17d1 Label Patrol configuration toggles 2026-05-20 14:50:49 +01:00
rcourtman 69263ff68b Bind alert schedule form labels 2026-05-20 14:35:14 +01:00
rcourtman bc5275b8d8 Color disk tooltip dots by utilization in vertical-bars mode 2026-05-20 14:30:16 +01:00
rcourtman d02b9ef7ff Bind alert notification form labels 2026-05-20 14:28:35 +01:00
rcourtman b8d23ae616 Name labeled toggle controls 2026-05-20 14:13:38 +01:00
rcourtman f83d25d155 Add Discovery provenance markers 2026-05-20 13:32:34 +01:00
rcourtman ba896a5366 Normalize PMG drawer tables 2026-05-20 13:25:35 +01:00
rcourtman 9c55c341e2 Implement Discovery observed context UX 2026-05-20 13:21:55 +01:00
rcourtman 74ec866498 Normalize Kubernetes drawer tables 2026-05-20 13:20:21 +01:00
rcourtman daa155c2d2 Normalize Docker swarm drawer table 2026-05-20 13:02:49 +01:00
rcourtman 4332129ac2 Fix Docker host header clipping 2026-05-20 12:52:57 +01:00
rcourtman 6ac02408c0 Normalize Proxmox drawer tables 2026-05-20 12:48:36 +01:00
rcourtman 435cf816fb Harden Discovery command-scan gating 2026-05-20 12:40:04 +01:00
rcourtman 18e62d3ed6 Normalize Proxmox backup tables 2026-05-20 12:37:55 +01:00
rcourtman 92b3116047 Use shared metric bars for Kubernetes clusters 2026-05-20 12:19:11 +01:00
rcourtman 300af43128 Move Uptime after the bar block in platform top tables
Uptime placement was the most visibly drifty ordering on platform top
tables: Proxmox and TrueNAS sat it at position 3 (before any bars),
Docker / vSphere at position 8 (after bars), Kubernetes Nodes at the
very end (after Capacity). Same monitoring concept rendered in three
different positions depending on the table.

Lock in the convention: Uptime is monitoring state, not identity. It
canonically sits between the bar block (CPU / Memory / Disk / Storage,
plus the Temp diagnostic) and the inventory counts.

Apply that rule:
  - Proxmox host model: Uptime moves from position 3 to position 7
    (Node, Version, CPU, Memory, Disk, Temp, Uptime, VMs, CTs, Cluster).
  - TrueNAS systems table: Uptime moves from position 3 to position 7
    (System, Version, CPU, Memory, Storage, Temp, Uptime, Pools,
    Datasets, Disks, Apps).
  - Kubernetes nodes table: Uptime swaps with Capacity so Uptime sits
    between the bars and the Capacity inventory string (Node, Cluster,
    Roles, Kubelet, Runtime, CPU, Memory, Uptime, Capacity).

The columnAlignment.ts docstring now documents the recommended column
ordering (identity → context → state → bars → diagnostic → time →
inventory → external) alongside the kind-to-align mapping, so the
ordering convention sits in the same source-of-truth file every agent
already reads when editing a platform table.

Other ordering questions (where integer counts sit relative to bars;
where the cluster-reference column sits) are left as each table's
current choice. They are defensible either way and have a real visible
UX cost to change. Revisit if drift surfaces.
2026-05-20 12:16:37 +01:00
rcourtman b94c6164d7 Normalize platform loading states 2026-05-20 12:13:54 +01:00