Replace the static "recent requests" list with a proper table of all Jellyseerr
requests, sorted by date added (newest first by default) with standard sorting
and filtering.
Backend:
- JellyseerrClient.requests(max_count=500): paginated GET /api/v1/request
(sort=added), mapped with type (movie/tv), status, media_status, and
created_at labels. Returns up to 500 so the table can sort/filter client-side.
- fetch_jellyseer_requests(service) reuses the per-service cached client
(shared with the stats widgets).
- new GET /api/jellyseerr/requests endpoint.
Frontend:
- JellyseerRequestsTable: TanStack Table (sorting via getSortedRowModel,
pagination via getPaginationRowModel) reusing the Table primitives +
TablePagination. Columns: Name / Type / Status / Media / Requested, all
sortable; default sort Requested desc. A search box filters by name and a
status dropdown defaults to "Open" (pending+approved+processing) with
All/Pending/Approved/Declined options. (The shared DataTable is deliberately
visibility-only, so this is a dedicated sortable table.)
- RequestsTab renders the stats grid + the new table (the compact recent list
stays on the Requests overview widget).
- useJellyseerRequests hook + fetchJellyseerRequests API client.
Tests: client requests() mapping + single-page stop; fetch helper not-configured;
RequestsTab test mocks both hooks. 404/404 backend + 184/184 frontend pass;
build (tsc -b && vite build) + ESLint clean.
Consistent graph scaling across every line-chart widget. A new shared
frontend/src/lib/metricFormat.ts picks a decimal prefix (kB/MB/GB, kbps/Mbps,
Gbps, …) from the series magnitude and formats values; LineSeriesChart accepts
unit + scale and formats both the Y-axis ticks and the tooltip with the SAME
prefix (one consistent unit per axis). MetricChartWidget (Prometheus) and
QbittorrentSpeedWidget pass the widget config through; qBit speed defaults to
bytes/sec → MB/s.
WidgetConfigDialog now renders `enum` schema fields as a <Select> dropdown, so
the backend's unit/scale Literal enums become consistent pickers in every graph
widget's config (and any future enum option).
Decimal (x1000) prefixes by default (matches Mbps/MB/s/Grafana).
Tests: 13 new metricFormat tests (auto/fixed scaling, percent, seconds,
nulls, trailing-zero trimming). 179/179 frontend tests pass; tsc + ESLint clean.
The gauge rendered as multiple black rings. Two causes:
1. recharts RadialBarChart draws each data entry as a CONCENTRIC RING, not an
arc segment, so the 3 "track band" entries + value produced 4 nested rings.
Render a single value arc over a neutral background track instead, colored
by status, with the readout absolutely centered (replacing the -mt-12 hack).
2. The fills used hsl(var(--primary)) / hsl(var(--chart-1)) etc., but this
project's Tailwind v4 theme (index.css) defines colors as --color-* holding
full hex values (--color-primary: #4f8cff). So the references were doubly
invalid (wrong name + hsl() wrapping a hex) -> invalid SVG fill defaults to
black. Use var(--color-*) directly, with the semantically correct chart
colors: ok=--color-chart-2 (green), warn=--color-chart-3 (amber),
crit=--color-chart-4 (red).
Also fix the same hsl(var(--x)) -> var(--color-x) bug in LineSeriesChart's
tooltip contentStyle (popover/border/popover-foreground). The line stroke
palette already used the correct var(--color-chart-N) form.
166/166 frontend tests pass; typecheck + ESLint clean.
- Archive the completed observability-service-registry SDD change into
openspec/changes/archive/ (delivered across 5 slices; only
jellyfin-service-registry remains active).
- Stop ignoring .pi-map.md / .pi-map.index.md so the navigation maps are
versioned alongside the code, and add the regenerated map pairs repo-wide.