Skip to content

fix(frontend): UI bug pass (enable toggle, test result, detail sheet, nav, errors) - #146

Merged
EraPartner merged 2 commits into
mainfrom
claude/project-thread-rrq59f
Oct 28, 2026
Merged

EraPartner merged 2 commits into
mainfrom
claude/project-thread-rrq59f

Conversation

@EraPartner

Copy link
Copy Markdown
Owner

Requested by EraPartner · project thread

Frontend bug pass. I found these by reading the code, and each fix has a regression test. Nothing ran locally because the cloud env can't reach npm, so CI is the first run. I also skipped the visual check (no browser build possible).

Fixes

  1. Enable/Disable broke the service (Services.tsx, ServiceDetailSheet.tsx). PUT /config/services/:id replaces the config and only carries over secrets plus the base fields (ConfigStore.mergeSecretsWithExisting). The toggle sent just { enabled }, so the save failed validation or wiped optional fields. It now resends the stored config through the new lib/serviceInput.ts. The Settings button is also disabled while a save is pending.
  2. "Test connection" said OK for an unreachable service (ServiceEditor.tsx, ConfigPanel.tsx). ok: true with snapshot.reachable: false was shown as success. The new lib/connectionTest.ts checks both. It also works once fix(backend): service data-collection bugs across all 13 integrations #145 makes the endpoint return ok:false/UNREACHABLE.
  3. The detail sheet showed the previous tile's live events. The sheet is reused, so events are now cleared when kind or instance changes.
  4. "No renderer for this service." flashed while the sheet closed (BentoDashboard.tsx). The tile context was cleared on close, during the exit animation. The open flag is now separate from the context.
  5. Enter on a tile's quick link opened the sheet and blocked the link (ServiceTile.tsx). The tile's key handler now ignores keys from child elements.
  6. Sibling tiles had the same screen-reader name. The label now includes the instance id when it is not main.
  7. No navigation below 768px (TopNav.tsx). The nav was hidden md:flex. On small screens it now wraps to its own scrollable row. The status counts get an aria-label and the WebSocket dot gets role="img".
  8. Profile switch, auto-switch and network capture failed silently. useProfileQueries.ts now shows an error toast.
  9. A restore didn't refresh profiles or the failed-to-load rows (useImportConfig).
  10. WebSocket service_config_changed didn't refresh the Settings list or load errors (useWebSocket.ts, new queryKeys.configServices/configLoadErrors).
  11. A failed kinds/schema load showed "No kinds match “”" or "No schemas available." (KindPickerStep.tsx, ServiceEditor.tsx). These now show an error with a Retry button.
  12. Mutations were retried once (App.tsx). See Decisions.
  13. The Raspberry Pi tile stayed amber after one brown-out (raspberryPi.ts). vcgencmd's since-boot bits (16-19) stay set until reboot. The tone now uses throttledNow when the backend sends it (fix(backend): service data-collection bugs across all 13 integrations #145), and otherwise bits 0-3 of throttled.

Decisions (standing rule: take the recommended option, record it)

  • Mutation retry → retry: false. Other options were keeping retry: 1, or skipping retries on 4xx only. ApiClientCore deliberately retries only GET/HEAD. A retried create after a lost response fails as a duplicate, and a retried 4xx repeats the same error a second later. Users still see the error and can retry by hand.
  • Fix 1 on the frontend, not the backend. The PUT's replace semantics are what let the editor clear a field, so the toggle now sends the full config.
  • Fix 2: I left the backend side to fix(backend): service data-collection bugs across all 13 integrations #145 and only changed the frontend, so the two don't conflict.

Not changed

  • docs/components/use-service-health.md documents a useAdGuardProtectionToggle write hook that doesn't exist in code (stale doc, read-only rule). I left it for the docs thread.
  • Mac mini disk metrics that become null (fix(backend): service data-collection bugs across all 13 integrations #145) already render as "—": toNumber and getNum reject null, and the formatters tests cover null.

Files

App.tsx, components/dashboard/{BentoDashboard,TopNav}.tsx, components/detail/{ConfigPanel,ServiceDetailSheet}.tsx, components/tile/ServiceTile.tsx, hooks/useWebSocket.ts, lib/queryKeys.ts, new lib/{serviceInput,connectionTest}.ts, pages/Settings/{ServiceEditor,Services,useConfigQueries,useProfileQueries}.ts(x), pages/setup/steps/KindPickerStep.tsx, services/renderers/raspberryPi.ts. Tests: new lib/{serviceInput,connectionTest}.test.ts, pages/Settings/useProfileQueries.test.tsx, components/detail/ServiceDetailSheet.events.test.tsx, plus additions to existing test files. Docs: CHANGELOG.md, docs/architecture/frontend-architecture.md.


Generated by Claude Code

@EraPartner EraPartner self-assigned this Oct 28, 2026
@github-actions

github-actions Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Coverage Report for backend

Status Category Percentage Covered / Total
🟢 Lines 92.32% (🎯 80%) 2573 / 2787
🟢 Statements 89.15% (🎯 80%) 2819 / 3162
🟢 Functions 86.13% (🎯 80%) 559 / 649
🟢 Branches 76.7% (🎯 72%) 1824 / 2378
File CoverageNo changed files found.
Generated in workflow #375 for commit 7f6935b by the Vitest Coverage Report Action

@github-actions

github-actions Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 86.51% 1732 / 2002
🔵 Statements 84.06% 1888 / 2246
🔵 Functions 79.09% 488 / 617
🔵 Branches 73.29% 1534 / 2093
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
apps/frontend/src/App.tsx 56.25% 66.66% 38.46% 70.83% 33-34, 35, 36, 37, 38, 39, 49-68
apps/frontend/src/components/dashboard/BentoDashboard.tsx 78.26% 78.12% 66.66% 81.81% 42, 153-163
apps/frontend/src/components/dashboard/TopNav.tsx 44.44% 28.94% 90% 44.44% 31-35, 41, 94-112
apps/frontend/src/components/detail/ConfigPanel.tsx 83.33% 75.75% 100% 88.88% 12, 18, 25, 29, 59
apps/frontend/src/components/detail/ServiceDetailSheet.tsx 74.48% 54.21% 69.56% 82.35% 53, 54, 56, 102, 149, 153, 163-168, 175, 178, 179, 212, 226, 231-233, 239-242, 346, 524-531
apps/frontend/src/components/tile/ServiceTile.tsx 89.65% 71.2% 82.35% 93.42% 70, 130, 165, 173, 179, 182-193, 240, 245, 256
apps/frontend/src/hooks/useWebSocket.ts 89.69% 79.16% 96.15% 89.52% 121-124, 136-138, 238-261, 394-403
apps/frontend/src/lib/connectionTest.ts 100% 91.66% 100% 100%
apps/frontend/src/lib/queryKeys.ts 100% 100% 100% 100%
apps/frontend/src/lib/serviceInput.ts 100% 100% 100% 100%
apps/frontend/src/pages/Settings/ServiceEditor.tsx 84% 77.64% 78.94% 86.15% 44, 54, 56, 57, 180, 205, 206, 215, 230, 239-240, 258-259, 268, 280, 325, 362-389, 461-466, 474-486
apps/frontend/src/pages/Settings/Services.tsx 43.33% 30.76% 23.52% 43.33% 49-93, 132-148, 173-229
apps/frontend/src/pages/Settings/useConfigQueries.ts 74.54% 33.33% 58.82% 74.54% 46-56, 64, 73-80, 88, 139-146, 152
apps/frontend/src/pages/Settings/useProfileQueries.ts 37.2% 100% 40% 35.71% 23-28, 34, 41, 48, 57, 67-93, 102-103, 113-114
apps/frontend/src/pages/setup/steps/KindPickerStep.tsx 90% 72% 80% 88.88% 46-50, 84
apps/frontend/src/services/renderers/raspberryPi.ts 93.1% 90% 100% 100% 92, 93
Generated in workflow #375 for commit 7f6935b by the Vitest Coverage Report Action

@EraPartner
EraPartner marked this pull request as ready for review October 28, 2026 08:17
@EraPartner
EraPartner enabled auto-merge (squash) October 28, 2026 08:17
…rrors)

- Enable/Disable resends the stored config; PUT replaces the config, so a
  bare { enabled } failed validation or dropped optional fields.
- Test connection reads snapshot.reachable; ok:true alone showed "OK" for
  an unreachable service.
- Detail sheet: clear live events when another tile opens; keep the last
  service while the sheet closes (no "No renderer" flash).
- Tile: Enter on the quick link follows the link; per-instance aria-label.
- TopNav: links wrap to their own row below md instead of disappearing;
  labelled status counts.
- Toast failed profile switch / auto-switch / capture network.
- Import refreshes profiles and load errors; service_config_changed
  refreshes the Settings list and load errors.
- Kinds/schema load failure shows an error with Retry.
- Mutations are not retried (the API client retries only GET/HEAD).
vcgencmd's since-boot bits (16-19) stay set until reboot, so one brown-out
kept the tile amber. Use throttledNow when the backend sends it, else the
current bits (0-3) of throttled.
@EraPartner
EraPartner force-pushed the claude/project-thread-rrq59f branch from db62f24 to 7f6935b Compare October 28, 2026 08:19
@EraPartner
EraPartner merged commit f0a6fd2 into main Oct 28, 2026
18 checks passed
@EraPartner
EraPartner deleted the claude/project-thread-rrq59f branch October 28, 2026 08:21
EraPartner pushed a commit that referenced this pull request Oct 28, 2026
#146 made Test connection report an unreachable service as Failed, so
the setup guides no longer need the known-issue callout.

docs/components/use-service-health.md described a protection-toggle
mutation hook and a cache-clear hook that don't exist; rewrite it from
apps/frontend/src/hooks/useServiceHealth.ts (read-only, ADR-032).
EraPartner pushed a commit that referenced this pull request Oct 28, 2026
#146 made Test connection report an unreachable service as Failed, so
the setup guides no longer need the known-issue callout.

docs/components/use-service-health.md described a protection-toggle
mutation hook and a cache-clear hook that don't exist; rewrite it from
apps/frontend/src/hooks/useServiceHealth.ts (read-only, ADR-032).
EraPartner added a commit that referenced this pull request Oct 28, 2026
…144)

* docs: add per-service setup guides with least-privilege credentials

Add docs/guides/service-setup/ with an index and one guide for each of
the 13 service kinds: what to enable on the service, which read-only or
least-privilege credentials to create, what to enter in Watchman, and
troubleshooting keyed to the error messages in the code.

Link the guides from the integration pages and indexes, and fix doc
drift found while checking against the code: AdGuard no longer claims
toggle control, the Homebridge health probe path, Bitcoin's Tor claim,
and the unused zmqRawtxEndpoint.

* docs: drop Test connection caveat, fix useServiceHealth hook doc

#146 made Test connection report an unreachable service as Failed, so
the setup guides no longer need the known-issue callout.

docs/components/use-service-health.md described a protection-toggle
mutation hook and a cache-clear hook that don't exist; rewrite it from
apps/frontend/src/hooks/useServiceHealth.ts (read-only, ADR-032).

* docs: update setup guides for the service bug fixes on main

Rebased onto #145/#147/#148: document SSH host-key pinning (Mac Mini,
Pi), the DSM certificate fingerprint and DSM-only health, the now-used
Bitcoin rawtx ZMQ endpoint, Roon pairing state in DATA_DIR, and the
new error messages and login backoffs.

---------

Co-authored-by: Claude <noreply@anthropic.com>
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.

2 participants