Commit Graph

76 Commits

Author SHA1 Message Date
Developer 38b2de54ff chore: archive observability-service-registry, track pi-map artifacts
- 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.
2026-06-24 13:28:23 +00:00
Developer c1610c93a1 docs(observability): refresh docs for service-registry end state
After the observability-service-registry slices removed the observability
env vars and the file-SD writer, several docs still instructed readers to
set vars that no longer exist. Updated the live config instructions;
historical decision-log entries are left intact.

- README.md: removed VITE_GRAFANA_URL/VITE_PROMETHEUS_URL/ALERTMANAGER_URL
  from compose examples and the env-var block; added a note that
  observability is configured on the Services page; updated Notes.
- frontend/README.md: dropped the stale VITE_* deep-link sentence.
- docs/REQUIREMENTS.md: fixed one stale trailing phrase in the
  externalization decision-log entry (VITE_* no longer "remain").
- docs/monitoring-logging-design.md: added a "Superseded mechanisms" note
  under Implementation Plan so the Phase 2/3 file-SD + alertmanager_url
  details read as historical, not current wiring.
- context.md: strengthened the status banner to cover the env->service-
  registry and file-SD->http_sd_configs shift; body marked historical.

.env.example is assistant-edit-blocked; updated replacement text provided
to the user separately.
2026-06-24 09:15:50 +00:00
Developer b1a66a1ab7 chore(observability): remove remaining observability env vars, docs
Slice 5 (final) of observability-service-registry. Completes the move to
service-registry-only observability config: no observability service env
vars remain.

- config.py: removed alertmanager_url + alertmanager_webhook_url fields.
- docker-compose.yml / docker-compose.dev.yml: removed ALERTMANAGER_URL,
  ALERTMANAGER_WEBHOOK_URL (backend env), and VITE_GRAFANA_URL,
  VITE_PROMETHEUS_URL (frontend build args / dev env).
- frontend/Dockerfile: removed the VITE_GRAFANA_URL / VITE_PROMETHEUS_URL
  ARG, build-stage ENV, and dev-stage ENV lines.
- docs: REQUIREMENTS decision-log entry; CHANGELOG Added/Changed/BREAKING
  for the observability service registry; backend/README monitoring
  section (Observability page, services page config, http_sd_configs,
  new health endpoints, log-only webhook).

The only observability env var remaining is PROMETHEUS_ENABLED (Manage's
own /metrics toggle). Grep-gated: no live references to the removed
vars/fields in backend src, frontend src, compose, or Dockerfile.

ruff clean; 239 backend tests pass; frontend 0 lint errors, build clean,
72 tests pass.

.env.example is assistant-edit-blocked; user follow-up noted in the SDD
tasks: drop the removed vars there too.
2026-06-24 08:49:53 +00:00
Developer b200025daa refactor(observability): drop file-SD writer for http_sd_configs
Slice 4 of observability-service-registry. Removes the shared-file
Prometheus bridge; external Prometheus now consumes node-exporter targets
via http_sd_configs against GET /api/monitoring/prometheus-targets.

- services/targets.py: removed write_prometheus_targets() (the file
  writer) and its json/Path/get_settings imports; updated module docstring.
  build_node_exporter_targets() is unchanged and still powers the HTTP
  endpoint.
- main.py: removed the startup write_prometheus_targets call.
- routers/settings.py: removed the _write_prometheus_targets helper and
  its three post machine create/update/delete call sites + the now-unused
  targets import.
- config.py: removed the prometheus_file_sd_dir field.
- docker-compose.yml / docker-compose.dev.yml: removed the
  PROMETHEUS_FILE_SD_DIR backend env var.
- tests: removed TestWritePrometheusTargets + the write_prometheus_targets
  import in test_targets.py; rewrote the two TestSettingsMachines tests to
  assert machines appear/disappear from /api/monitoring/prometheus-targets
  (the surviving HTTP path) instead of the removed file-writer side effect.

ruff clean; 239 backend tests pass.
2026-06-24 08:37:20 +00:00
Developer 0c5698c903 feat(observability): service discovery, health cards, alertmanager widget
Slice 3 of observability-service-registry (frontend). The Observability
page discovers Grafana from the service registry instead of env vars,
adds Grafana + Prometheus health cards, and ships an alertmanager
active_alerts dashboard widget.

- types: added GrafanaStatus + PrometheusStatus; added optional
  service_id/error to AlertmanagerStatus.
- api/client.ts + hooks/useObservability.ts: fetchGrafanaStatus,
  fetchPrometheusStatus, useGrafanaStatus, usePrometheusStatus.
- widgets/AlertmanagerAlertsWidget.tsx (new): presentational widget
  consuming the active_alerts summary shape (total/by_severity/alerts);
  exported from widgets/index.ts.
- integrations/registry.ts: alertmanager binding (active_alerts kind,
  30s refresh, optional severity_filter); registry.test.ts updated to
  6 service types incl alertmanager + a resolve test.
- components/ObservabilityPage.tsx: removed
  import.meta.env.VITE_GRAFANA_URL; derive GRAFANA_BASE_URL from the
  first enabled grafana service via useServiceInstances("grafana");
  added Grafana + Prometheus HealthCards (up/not-configured/unreachable)
  with QueryError retry blocks; machine dashboard shows a "No Grafana
  service configured" empty-state linking to /services when none is set.

npm run build (tsc -b + vite) clean; 0 lint errors; 72 frontend tests
pass. Reviewed fresh-context (read-only): no blockers.
2026-06-24 08:23:23 +00:00
Developer d4f95b64d4 chore(observability): externalize stack from root compose files
Manage now connects to existing Grafana/Prometheus/Alertmanager instances
and never deploys its own stack.

- docker-compose.yml / docker-compose.dev.yml: removed prometheus, loki,
  alloy, grafana, alertmanager, node-exporter services, the monitoring
  network, and observability named volumes; they now ship only backend +
  frontend. Dev frontend now joins the web network so the Vite dev proxy
  can reach the backend.
- backend: alertmanager_url default is now empty; /api/monitoring/alerts
  and /alertmanager-status return graceful "not configured" responses
  when ALERTMANAGER_URL is unset. Added not-configured tests.
- docker-compose.observability.yml: kept as the optional standalone
  example; header clarifies Manage does not deploy it.
- Removed orphaned combined monitoring/prometheus/prometheus.yml
  (standalone stack uses prometheus.standalone.yml).
- Docs (README, REQUIREMENTS decision log, monitoring-logging-design,
  observability-runbooks, context.md, MIGRATION_PLAN, frontend/README,
  CHANGELOG) updated to the connect-to-existing model.

VITE_GRAFANA_URL / VITE_PROMETHEUS_URL remain as optional frontend
deep-link overrides. .env.example still needs a manual update (safety
policy blocks assistant edits): set ALERTMANAGER_URL empty/optional and
move standalone-only vars out of the root file.
2026-06-23 21:20:07 +00:00
Developer 50eb76a10d feat(tasks): unify saved tasks on ssh_tasks services
- Add shared task_runner.run_saved_task helper used by routers/tasks.py and
  widgets/sources.py SshTaskWidgetSource.
- Saved tasks now target ssh_tasks service instances via default_service_id;
  the legacy default_machine_id and saved_task_runs are removed.
- Actions page lists ssh_tasks services for default and run-time selection.
- Update types, API client, hooks, tests, docs, and changelog.

Backend tests: 222 passed. Frontend lint/build/test: clean (71 passed).
2026-06-23 16:46:46 +00:00
Developer cfb9977532 chore: remove dead machine-level Jellyfin/Jellyseerr fields
Follow-up #1 to the service-registry change. Jellyfin/Jellyseerr now resolve
from the service registry, so the machine-level app fields are dead config.

- dependencies.py: drop dead _jellyseerr_client_for; simplify _resolve_machine
  to SSH-only.
- settings_store.py + routers/settings.py: remove jellyfin_*/jellyseerr_* from
  machine default config, get_machine_config, normalization, row mappers, and
  MachineInput.
- frontend types + Settings.tsx: drop the fields and the Jellyfin/Jellyseerr
  form sections + service options.
- Update frontend test fixtures.

Existing DB rows may still carry these keys in config_json; they are inert and
drop on the next machine save. Verification: backend ruff clean, pytest 222;
frontend lint 0 errors, build success, 70 tests.
2026-06-23 12:54:27 +00:00
Developer 7ab9b1ac59 style(tests): apply formatter to Applications and Media tests 2026-06-23 12:28:53 +00:00
Developer cbb703341e feat(services): select Jellyfin via jellyfin_service_id on the frontend
Slice 4b frontend half. Jellyfin-touching pages now select a Jellyfin service
instance instead of a machine.

- api/client.ts: Jellyfin-backed calls (counts/libraries/activity/users, media
  status/build/stop/force-stop, queryMedia) send jellyfin_service_id.
- hooks/useDashboard, useUsers, useMedia: selector param renamed to
  jellyfinServiceId.
- pages/Media + Applications: list jellyfin service instances and persist
  jellyfin_service_id in the URL.
- Dashboard (widgets) and Users (default instance) need no selector change.
- Update Applications + Media tests for the new hook/param.

Files/SSH transport keeps machine_id. Verification: frontend lint 0 errors,
build success, 70 tests; backend ruff clean, 222 tests.
2026-06-23 12:10:27 +00:00
Developer 9a6cbfae68 style(services): apply formatter to App and ServicesPage 2026-06-23 11:07:19 +00:00
Developer c9c72be0b6 feat(services): cleanup, services admin UI, docs
PR 4a of the runtime service registry change.

- Remove addon pages (/addons/:addonId, AddonPage, addons/*) superseded by
  service pages.
- Remove grafana_url/prometheus_url from backend config, compose, .env.example,
  and README (URLs now live on service records; VITE_ frontend deep-link vars
  retained).
- Add Services page (/services) with create/list/delete + sidebar nav, so
  services are configurable in the tool itself and service pages are reachable.
- Update docs/REQUIREMENTS.md service-registry section; add CHANGELOG.md with
  the breaking-upgrade note (MANAGE_ENCRYPTION_KEY required; grafana/prometheus
  env vars removed; default widget seeding removed).

Verification: backend ruff clean, pytest 222 passed; frontend lint 0 errors,
build success, 70 tests passed.
2026-06-23 10:57:30 +00:00
Developer 739ad38e29 style(services): apply formatter to frontend services runtime 2026-06-22 19:13:59 +00:00
Developer 1da67f38c7 feat(services): frontend services runtime and widget rebind
PR 3 of 4 for the runtime service registry change.

- Add service + new-shape widget TypeScript types; widgets carry service_id
  + widget_kind (service-bound) or null (built-in).
- Add services API client + TanStack Query hooks; reconcile the widget API
  client/hooks to the new endpoints (remove sources/types; add builtin kinds).
- Add closed frontend service registry (integrations/registry.ts) mirroring the
  backend, with resolveWidget(widget, services) mapping a widget to its
  component + refresh interval.
- Add ServicePage at /services/:serviceType/:serviceId with config view,
  empty-on-edit secret inputs + 'set' badges, enable toggle, delete, and the
  service's widget-kind list.
- Register /services/:serviceType/:serviceId in App.tsx.
- Reconcile the six widget components to refreshIntervalMs + description props;
  rewrite WidgetConfigDialog around a service -> widget-kind picker.
- Update Dashboard test; add integrations/registry.test.ts.

Verification: frontend lint 0 errors, build success, 70 tests passed; backend
ruff clean, 222 tests passed.
2026-06-22 18:59:41 +00:00
Developer 75636c00d4 docs(deploy): update README and .env.example for Docker deployment
- Refresh README feature list and remove references to the legacy
  in-app monitoring charts / backend poller.
- Document configurable dashboard widgets, addon pages, and widget env vars.
- Add VITE_PROMETHEUS_URL support to frontend Dockerfile and both compose files.
- Add header comment to .env.example explaining shell-export workflow.
- Update remote server requirements to match current capabilities.
2026-06-22 09:28:06 +00:00
Developer 09eb76bf0f style(widgets): apply formatter to dashboard and addon files 2026-06-22 08:05:44 +00:00
Developer ed7a7a5ce0 feat(widgets): dashboard loop, widget config UI, and addon pages
PR 4 of 4 for configurable dashboard widgets.

- Replace hard-coded Jellyfin/Backups dashboard sections with a loop that
  renders enabled widget instances by sort_order.
- Add WidgetInstance renderer and WidgetConfigDialog for adding, editing,
  enabling/disabling, deleting, and reordering widgets.
- Add addon pages for grafana, prometheus, and ssh-tasks at /addons/:addonId.
- Register /addons/:addonId route in App.tsx.
- Update docs/REQUIREMENTS.md with the widget system design and API.

Verification:
- backend ruff clean; pytest 200 passed
- frontend npm run lint: 0 errors
- frontend npm run build: success
- frontend npm run test -- src/widgets/registry.test.ts: 3 passed
2026-06-21 20:45:42 +00:00
Developer 2557185fb7 style(widgets): apply formatter to widget runtime files 2026-06-21 16:55:12 +00:00
Developer e1356b20f1 feat(widgets): add frontend widget runtime (types, API, hooks, registry, components)
PR 3 of 4 for configurable dashboard widgets.

- Add TypeScript widget interfaces (WidgetInstance, WidgetInstanceInput,
  WidgetTypeInfo, WidgetDataResponse).
- Create widget API client for CRUD, registry metadata, and per-widget data.
- Create TanStack Query hooks for instances, data, sources, types, and mutations.
- Create closed frontend widget registry with metadata, source type, refresh
  intervals, and config fields.
- Add six shadcn/ui-based widget components: Jellyfin, Backups, Grafana link,
  Prometheus metric, SSH task output, and static text.
- Add Vitest unit tests for registry metadata.

Verification:
- backend ruff clean; pytest 200 passed
- frontend npm run lint: 0 errors
- frontend npm run build: success
- frontend npm run test -- src/widgets/registry.test.ts: 3 passed
2026-06-21 16:24:44 +00:00
Developer 24427b4869 chore(config): remove dead GRAFANA_URL and wire VITE_GRAFANA_URL
- Remove GRAFANA_URL from backend environment (backend never consumed it).
- Add VITE_GRAFANA_URL to frontend build-args (prod), dev environment, and
  frontend/Dockerfile ARG/ENV so Grafana deep-links resolve correctly.
- Add ALERTMANAGER_WEBHOOK_URL to backend environment so the documented
  alert-forwarding feature is reachable from compose.
- Document VITE_GRAFANA_URL in .env.example.
2026-06-19 20:07:47 +00:00
Developer a8eb751322 refactor(monitoring): remove orphaned frontend DiskSpaceCard (slice 2)
After slice 1 removed /api/monitoring/disk, the frontend DiskSpaceCard
component (and its DiskSpace type) had zero importers — it fed nothing.
Delete them.

Removed (frontend):
- components/DiskSpaceCard.tsx
- components/__tests__/DiskSpaceCard.test.tsx
- types/index.ts: DiskSpace interface

Gate: build + lint + vitest (22 files / 63 tests) green.
2026-06-17 20:51:54 +00:00
Developer 0ec2a8806b style(frontend): wrap long ResizeObserver assignment in test setup
Background linter/runner keeps re-applying this single-line wrap; commit it
so the working tree stays stable. No behavior change.
2026-06-17 19:44:57 +00:00
Developer 9de2d5b8d2 feat(frontend): slice 8 — remove MUI/@emotion deps + update REQUIREMENTS
Web UI rework. Final slice.
- Remove from package.json: @mui/material, @mui/icons-material,
  @mui/x-data-grid, @emotion/react, @emotion/styled (zero consumers
  remain in src after slices 1-7b; grep-verified).
- Update docs/REQUIREMENTS.md (+63 lines): single design system
  (shadcn/ui + Tailwind v4 + lucide-react), thin-dashboard observability
  model (no in-app charts; Grafana deep-links), TanStack tables
  (visibility-only parity), reconciled IA (Backups top-level nav;
  Media at /media with /applications redirect), repurposed chart-*
  status cues, removed deps list.
- Note: AGENTS.md 'node --test tests' invocation is a pre-existing
  broken command (treats tests/ as a module); correct form is
  'node --test' (auto-discover, 5/5 pass) — verified identical at
  pre-rework baseline ef5311b.

Gate: build + lint + vitest (23/64) + node --test (5/5) green.
Web UI rework complete.
2026-06-17 18:52:27 +00:00
Developer 3dc1b31fc3 feat(frontend): slice 7b — Media on TanStack Table (server pagination)
Web UI rework. Completes the DataGrid migration (7a + 7b):
- pages/Media.tsx off @mui/x-data-grid + @mui/material onto DataTable:
  15 locked columns (title/series/season/episode/type/year/runtime_min/
  size/bitrate/hdr/video/resolution/date_added/library/path);
  enablePagination + manualPagination + rowCount from queryResult.total;
  page state (pageIndex/pageSize) -> offset/limit into useMediaQuery;
  onRowClick -> navigate('/files?path=...') preserved; stable path-derived
  getRowId so selection survives server paging; column-visibility toggle.
  Hard rule honored: NO sorting, NO resizing (visibility-only).
- Migrate Media shell (Select/Input/Progress/Card/grid/Typography/Tabs).
- Media component tests (column set + row-click nav).
- Harness fix: polyfill ResizeObserver in test/setup.ts — jsdom lacks it
  and Radix primitives (Select/ScrollArea/etc.) reference it; was causing
  cross-test failures once Media pulled shadcn Select into the pool.

Gate: build + lint + test green (23 files / 64 tests).
2026-06-17 18:33:59 +00:00
Developer e8b0f1144b feat(frontend): slice 7a — DataTable wrapper + FileBrowser (TanStack Table)
Web UI rework. Highest-risk slice, part 1 of 2:
- New components/ui/data-table.tsx: generic TanStack Table wrapper on the
  shadcn Table primitive. Controlled rowSelection/columnVisibility/
  pagination, optional selection column (stopPropagation on cell click),
  row-click, column-visibility dropdown, manual-pagination support.
  Hard rule honored: NO getSortedRowModel, NO column resizing/sizing.
- Migrate pages/FileBrowser.impl.tsx off @mui/x-data-grid + @mui/material
  onto DataTable: 5 columns (type/name/ext/size/modified), row-click ->
  ffprobe preview preserved, column-visibility toggle, no pagination.
- DataTable + FileBrowser component tests (RED->GREEN).

Gate: build + lint + test green (22 files / 58 tests).
2026-06-17 18:02:47 +00:00
Developer 04f2e59c92 feat(frontend): slice 6b — Users compose dialog + 9 icons (finish Users)
Web UI rework. Completes the Users migration (6a directory + 6b compose):
- Compose dialog off @mui: shadcn Dialog family + Input (subject) +
  Textarea (html body) + Separator + Label; IconButton -> Button ghost
- 9 @mui/icons-material -> lucide-react: Close->X, AttachFile->Paperclip,
  FormatBold->Bold, FormatItalic->Italic, Link->Link,
  FormatListBulleted->List, MailOutlined->Mail, Send->Send,
  DeleteOutlined->Trash2
- Rich-text compose parity: markup insertion, attachments (FormData),
  queue-status polling, send via useSendUserMessage
- UsersPage.impl.tsx now has ZERO @mui imports

Gate: build + lint + test green (20 files / 46 tests).
2026-06-17 16:18:49 +00:00
Developer 1e23c07a20 feat(frontend): slice 6a — Users directory surface + drawer (shadcn)
Web UI rework. Slice 6a (force-split; 6b = compose dialog next):
- UsersPage.impl.tsx directory surface off @mui: shadcn Table family +
  Checkbox + Badge (status: success=chart-2/destructive/secondary) +
  Avatar + Tooltip + Progress + Alert/Button/Stack/Typography
- MUI Drawer -> shadcn Sheet side="right" for user detail drawer
  (buildUserDrawerModel rendering preserved)
- Selection-across-pagination + search/filter parity preserved
- Compose-dialog MUI subset (Dialog/TextField/Divider/IconButton +
  9 icons) intentionally LEFT for slice 6b

Gate: build + lint + test green.
2026-06-17 14:36:07 +00:00
Developer b6da7df7f9 feat(frontend): slice 5 — migrate Settings + Actions to shadcn/Tailwind
Web UI rework. Form-heavy pair (controlled useState parity, no form lib):
- pages/Settings.tsx off @mui: monitoring-machine CRUD, SSH-key mgmt,
  SSH test/validation feedback, danger-zone reset (ConfirmDialog), tabs
- pages/Actions.tsx off @mui: saved-task editor, machine selection,
  run history, tabs
- Both reuse migrated shared components (SectionCard/SelectionRailCard/
  TabbedCard/HoverEditButton/ConfirmDialog/DialogFooter) as before
- Behavioral tests added (mocked hooks; no live SSH)

Gate: build + lint + test green (19 files / 39 tests).
2026-06-17 13:47:57 +00:00
Developer c721f0dece feat(frontend): slice 4 — migrate Dashboard + Applications to shadcn/Tailwind
Web UI rework.
- Migrate pages/Dashboard.tsx off @mui (shortcut CRUD dialogs, machine
  switcher, BackupDashboardWidget mount; shortcuts reuse ConfirmDialog/
  DialogFooter from slice 2)
- Migrate pages/Applications.tsx shell off @mui (tabs + library counts);
  keeps <Media/> child intact (Media.tsx still MUI, deferred to slice 7
  with its DataGrid)
- Behavioral tests for both pages

Gate: build + lint + test green.
2026-06-17 13:15:51 +00:00
Developer 77c6b62ee2 feat(frontend): slice 3 — Backups cluster migration + nav/IA
Web UI rework.
- Migrate BackupAlertsTable, BackupJobsTable, BackupRunsTable,
  BackupsPage, BackupDashboardWidget off @mui (shadcn Table + Badge
  severity variants: success=chart-2, warning=chart-3, destructive)
- App.tsx IA: Backups now top-level nav (DatabaseBackup icon);
  Media surface primary at /media; /applications -> /media redirect
  in both route trees (mirrors /monitoring -> /observability)

Gate: build + lint + test green.
2026-06-17 12:53:36 +00:00
Developer 109e74db41 feat(frontend): slice 2 — migrate 11 shared components to shadcn/Tailwind
Web UI rework. Shared-components slice (drift prevention):
- Migrate SectionCard, SelectionRailCard, TabbedCard, MetricCard,
  DiskSpaceCard, HoverEditButton, DialogFooter, ConfirmDialog,
  LibraryOverview, NowPlaying, SessionActivityPanel off @mui
- HoverEditButton: MUI IconButton + EditOutlined -> Button + lucide Pencil
- Status mapping uses the success Badge variant (chart-2) for healthy
- Exported APIs preserved so consuming pages still compile (no page edits)
- 11 behavioral Vitest component tests added

Gate: build + lint + test green.
2026-06-17 12:33:47 +00:00
Developer dd778d8850 feat(frontend): slice 1 — foundation for MUI->shadcn migration
Web UI rework (openspec/changes/web-ui-rework). Foundation slice:
- Add @tanstack/react-table; remove orphaned recharts, d3
- Vendor shadcn primitives: tabs table dialog input label checkbox
  switch progress separator avatar textarea dropdown-menu scroll-area
- Add Vitest + @testing-library/react + jsdom harness; npm test script
- Delete no-op theme.ts shim; remove getAppTheme references
- Smoke test proves the harness

Gate: build + lint + test green.
2026-06-17 12:11:05 +00:00
Developer 53dcd16735 feat(observability): persist standalone stack data and expose ports via env
- Switch docker-compose.observability.yml from named volumes to host
  bind mounts under OBSERVABILITY_DATA_ROOT, defaulting to
  ./observability-data.
- Make all service ports configurable via environment variables
  (PROMETHEUS_PORT, LOKI_PORT, ALLOY_PORT, GRAFANA_PORT,
  ALERTMANAGER_PORT, NODE_EXPORTER_PORT).
- Add VITE_GRAFANA_URL handling to ObservabilityPage so Grafana links
  point to the configured standalone instance.
- Update docs/observability-runbooks.md with the env variable table,
  reachable-web-UI table, and backup/restore instructions for the new
  host-directory layout.
2026-06-16 15:37:41 +00:00
Developer e783d2c07b refactor(observability): decouple Grafana from Manage
- Replace embedded Grafana iframes in ObservabilityPage with external
  Grafana link cards. Grafana URL is configurable via VITE_GRAFANA_URL
  (frontend) or GRAFANA_URL (backend env exposed to frontend build).
- Remove the grafana scrape job from monitoring/prometheus/prometheus.yml
  so the main Prometheus stack no longer depends on Grafana.
- Pass GRAFANA_URL through docker-compose.yml and docker-compose.dev.yml.
2026-06-16 15:20:26 +00:00
Developer e2ad731b5f feat(observability): add Prometheus/Grafana/Loki/Alertmanager/Alloy stack and remove legacy Monitoring UI 2026-06-16 13:44:35 +00:00
alex 615e02e970 fix(frontend): make dark mode toggle actually work
The dark mode button was toggling React state but never applying it to the
DOM. Add a useDarkMode hook that:

- Persists the preference in localStorage
- Defaults to the OS prefers-color-scheme on first visit
- Adds/removes the 'dark' class on <html> to trigger CSS variable overrides

Also add dark-mode color overrides for all Tailwind v4 theme variables in
index.css.

Co-authored-by: openhands <openhands@all-hands.dev>
2026-06-11 21:50:13 +02:00
alex 43e132971b Build new shell layout with left sidebar (el-3po) 2026-05-12 11:08:33 +02:00
alex a748512d22 test: verify backup monitoring implementation 2026-05-11 21:57:31 +02:00
alex 322b3d1a3b feat(backups): wire up routes, nav, dashboard widget, and docs
- Add /backups route and navigation tab in App.tsx
- Add BackupDashboardWidget to Dashboard page
- Document backup monitoring feature in REQUIREMENTS.md
2026-05-11 21:54:50 +02:00
alex a7a66ff370 feat(frontend): add backup monitoring UI components
Add BackupJobsTable, BackupRunsTable, BackupAlertsTable,
BackupDashboardWidget, and BackupsPage components for
backup monitoring dashboard.
2026-05-11 21:52:04 +02:00
alex 36e5d85a82 feat: add backup monitoring TanStack Query hooks 2026-05-11 21:46:10 +02:00
alex f4085228f9 feat: add backup monitoring API client 2026-05-11 21:44:53 +02:00
alex 921914255b feat: add backup monitoring TypeScript types 2026-05-11 21:43:17 +02:00
alex 3718045d7b refactor(actions): unify add button placement with outline variant in list footer 2026-05-11 19:12:13 +02:00
alex 4940466054 fixes and improvements 2026-05-11 19:05:59 +02:00
alex 2a84553575 feat(settings): redesign SSH keys section with two-column layout
Refactor SSHKeyManager to match app layout pattern:
- List of SSH keys on the left (SelectionRailCard)
- Key details and form on the right (SectionCard)
- Add selectedSSHKeyId state to Settings component
- Click a key to select and populate the form
- New key button to create a new key
- Shows fingerprint and public key for selected key
- Delete button moved to the right panel
2026-05-11 18:54:00 +02:00
alex 8b26cd4fe0 fixes and improvements 2026-05-11 17:31:20 +02:00
alex 80d38ed86d fixes and improvements 2026-05-11 17:00:46 +02:00
alex 67a619e148 fixes and improvements 2026-05-11 16:27:07 +02:00
alex 7c704fc290 fixes and improvements 2026-05-11 15:45:59 +02:00