Quick push: accept an arbitrary colour, not just a scheme ID (#48) #97

Merged
claude-bot merged 1 commit from feat/quick-push-color into main 2026-09-01 01:03:28 +00:00
Contributor

Batch C item 8 of #48 (frontend spec parity).

The gap

The spec has always described quick push as pushing "an arbitrary color or scheme" (docs/iris-spec.md, Manual / quick push), but only the scheme half was implemented. POST /wled/quick-push required a scheme_id and looked up a Scheme row, so there was no way to send a one-off colour to the lights without first creating a scheme for it.

Backend

QuickPushRequest now takes exactly one of scheme_id or color (an RGB triple). A model_validator rejects a body carrying both or neither, rather than letting one silently win, and range-checks the triple.

A colour is applied solid to every themed segment with effect and palette forced to 0, via a new scheme_translator.solid_color_state. dim_white_state now delegates to it — warm-white ambient was already the same operation with a fixed colour, so this removes a near-duplicate rather than adding one. (Its existing end-to-end coverage in test_no_event_default.py guards the refactor.)

quick_push_manager keeps one revert path for both kinds of push: start_quick_push and the new start_quick_push_color both funnel into _start, so saving the live state, superseding an active push, the duration_mins timer, scheduler revert and manual cancel behave identically whichever is active. QuickPushState and get_status() gained a color field alongside scheme_id.

No Scheme row is involved on the colour path, so an ad-hoc push leaves nothing behind in the library. The audit entry records it as target_type="color", target_id="#rrggbb".

Frontend

The toolbar's Quick push dialog gains a Scheme / Colour tab pair. The colour swatch always produces a valid hex; the text field beside it does not, and hexToRgb turns a typo into black — so Push is disabled until the field holds a 6-digit hex, with the helper text saying so.

Verification

  • Backend: 279 passed (11 new — manager, body validation, and endpoint-level), ruff check, ruff format --check, mypy all clean.
  • New endpoint tests cover the three boundary cases: a colour push needs no scheme row, an unknown scheme_id still 404s, and a body with both targets is rejected 422 without touching the controller.
  • Frontend, run in a node:22 container (no Node on this host): tsc -b, eslint, vitest (56 passed) and npm run build all clean.

🤖 Generated with Claude Code

Batch C item 8 of #48 (frontend spec parity). ## The gap The spec has always described quick push as pushing **"an arbitrary color or scheme"** (`docs/iris-spec.md`, *Manual / quick push*), but only the scheme half was implemented. `POST /wled/quick-push` required a `scheme_id` and looked up a `Scheme` row, so there was no way to send a one-off colour to the lights without first creating a scheme for it. ## Backend `QuickPushRequest` now takes exactly one of `scheme_id` or `color` (an RGB triple). A `model_validator` rejects a body carrying **both or neither**, rather than letting one silently win, and range-checks the triple. A colour is applied solid to every themed segment with effect and palette forced to 0, via a new `scheme_translator.solid_color_state`. `dim_white_state` now delegates to it — warm-white ambient was already the same operation with a fixed colour, so this removes a near-duplicate rather than adding one. (Its existing end-to-end coverage in `test_no_event_default.py` guards the refactor.) `quick_push_manager` keeps **one** revert path for both kinds of push: `start_quick_push` and the new `start_quick_push_color` both funnel into `_start`, so saving the live state, superseding an active push, the `duration_mins` timer, scheduler revert and manual cancel behave identically whichever is active. `QuickPushState` and `get_status()` gained a `color` field alongside `scheme_id`. No `Scheme` row is involved on the colour path, so an ad-hoc push leaves nothing behind in the library. The audit entry records it as `target_type="color"`, `target_id="#rrggbb"`. ## Frontend The toolbar's Quick push dialog gains a Scheme / Colour tab pair. The colour swatch always produces a valid hex; the text field beside it does not, and `hexToRgb` turns a typo into black — so Push is disabled until the field holds a 6-digit hex, with the helper text saying so. ## Verification - Backend: **279 passed** (11 new — manager, body validation, and endpoint-level), `ruff check`, `ruff format --check`, `mypy` all clean. - New endpoint tests cover the three boundary cases: a colour push needs no scheme row, an unknown `scheme_id` still 404s, and a body with both targets is rejected 422 without touching the controller. - Frontend, run in a `node:22` container (no Node on this host): `tsc -b`, `eslint`, `vitest` (56 passed) and `npm run build` all clean. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Quick push: accept an arbitrary colour, not just a scheme ID (#48)
All checks were successful
CI / Python lint & type-check (pull_request) Successful in 1m9s
CI / Alembic migration check (pull_request) Successful in 1m32s
CI / Frontend lint, test & build (pull_request) Successful in 2m18s
CI / Python tests (pull_request) Successful in 3m32s
CI / Docker build, health smoke & E2E (pull_request) Successful in 4m50s
deed585ff4
The spec has always described quick push as pushing "an arbitrary color or
scheme" (docs/iris-spec.md), but only the scheme half existed: the endpoint
required a scheme_id and looked up a Scheme row, so there was no way to send
a one-off colour to the lights without first creating a scheme for it.

POST /wled/quick-push now takes exactly one of scheme_id or color, and a
model validator rejects a body carrying both or neither rather than letting
one silently win. A colour is applied solid to every themed segment with
effect and palette forced to 0, via a new scheme_translator.solid_color_state
-- which dim_white_state now delegates to, since warm-white ambient was
already the same operation with a fixed colour.

quick_push_manager keeps one revert path for both: start_quick_push and the
new start_quick_push_color both funnel into _start, so saving the live state,
superseding an active push, the duration timer, scheduler revert and manual
cancel behave identically whichever kind of push is active. QuickPushState
and get_status() gained a color field alongside scheme_id.

In the toolbar, Quick push gains a Scheme / Colour tab pair. The colour
swatch always produces a valid hex; the text field beside it does not, and
hexToRgb turns a typo into black, so Push is disabled until the field holds
a 6-digit hex.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
claude-bot deleted branch feat/quick-push-color 2026-09-01 01:03:29 +00:00
Sign in to join this conversation.
No description provided.