Frontend: let users stop a running preview carousel (#48) #88
No reviewers
Labels
No labels
area/ai
area/backend
area/frontend
area/infra
area/scheduler
area/wled
good-first-issue
priority/high
priority/low
priority/medium
type/bug
type/chore
type/ci-cd
type/docs
type/feature
type/qa
v1.0.0
v1.1.0
v1.2.0
v2.0.0
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
rbrooks/Iris-WLED!88
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/carousel-stop-and-regenerate-confirm"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
First item of batch C (#48). Closes the gap the 2026-07-15 review recorded as "no stop-carousel control (API exists, unused)".
The problem
stopCarouselexisted inapi/index.ts:141with no hook and no caller.SidePanelimporteduseStartCarouselonly. A user could start a carousel driving the real controller and had no way to end it short of waiting it out.Why it isn't a pure frontend change
A client-side "running" flag would be lost on reload — reproducing the exact bug. The carousel lives in
preview_manager's module state (_carousel_task), which nothing exposed. So the state is surfaced instead:preview_manager.carousel_active()reports whether the cycle task is live/wled/statuscarries it — on both the configured and unconfigured paths, so the field is never absent. An undefined value would read as "not running" and silently hide the control, which is the failure mode we're fixing./wled/statusfor the connection indicator, so this adds no new polling. Both carousel mutations invalidate that query, so the control flips immediately rather than after the next 30s poll.Two surfaces, deliberately
SidePanel— the Carousel button becomes a toggle, right where it's started.Header— a global stop control whenever one runs. A carousel outlives the day panel that started it, so if the only stop lived in the panel you'd have to find and reopen the right day. This makes it reachable from any page and after a reload.Verification
Run locally, not deferred to CI:
Three new tests cover
carousel_active()before start, while running, and after stop — there were no carousel tests at all previously.What I could not verify: there's no node toolchain on this machine, so
tsc,eslintandvitestare left to CI. The frontend changes are small and mechanical, but I'd rather say so than imply I checked them.Note on scope
While starting this I found item 6 of my batch-C audit was wrong — the regenerate confirmation dialog already exists (
SidePanel.tsx:307, with an explicit "approval is discarded … cannot be undone" warning). Corrected on #48; batch C is seven items, not eight. The branch name mentions it because it was created before I checked.stopCarousel existed in api/index.ts with no hook and no caller. A user could start a carousel driving the real controller and had no way to end it short of waiting it out -- spec 10.1 lists the carousel control, and the 2026-07-15 review flagged the missing stop as "API exists, unused". The fix could not be purely client-side. The carousel lives in preview_manager's module state, so a local "running" flag would be lost on reload -- reproducing the exact bug. Instead the state is exposed: - preview_manager.carousel_active() reports whether the cycle task is live - /wled/status carries it, on both the configured and unconfigured paths so the field is never absent (an undefined value would read as "not running" and hide the control) - the frontend already polls /wled/status for the connection indicator, so this needs no new polling; both carousel mutations invalidate that query so the control flips immediately rather than after the next 30s poll Two surfaces, deliberately: - SidePanel's Carousel button becomes a toggle, next to where it is started - Header shows a global stop control whenever one runs, because a carousel outlives the day panel that started it and must be reachable from any page and after a reload Verified locally: ruff, ruff format, mypy (61 files) and the full 253-test backend suite all pass, including three new tests covering carousel_active before start, while running, and after stop. The frontend could not be typechecked locally -- no node toolchain on this machine -- so tsc, eslint and vitest are left to CI. Refs #48. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>