Add CSPT entity, processed CSS source type, reverse filter, and UI improvements
- Add Color Strip Processing Template (CSPT) entity: reusable filter chains for 1D LED strip postprocessing (backend, storage, API, frontend CRUD) - Add "processed" color strip source type that wraps another CSS source and applies a CSPT filter chain (dataclass, stream, schema, modal, cards) - Add Reverse filter for strip LED order reversal - Add CSPT and processed CSS nodes/edges to visual graph editor - Add CSPT test preview WS endpoint with input source selection - Add device settings CSPT template selector (add + edit modals with hints) - Use icon grids for palette quantization preset selector in filter lists - Use EntitySelect for template references and test modal source selectors - Fix filters.css_filter_template.desc missing localization - Fix icon grid cell height inequality (grid-auto-rows: 1fr) - Rename "Processed" subtab to "Processing Templates" - Localize all new strings (en/ru/zh) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
33
TODO.md
33
TODO.md
@@ -28,6 +28,39 @@ Priority: `P1` quick win · `P2` moderate · `P3` large effort
|
||||
- [ ] `P2` **Distinguish "crashed" vs "stopped" in dashboard** — `metrics.last_error` is already populated
|
||||
- [ ] `P3` **CSS source import/export** — share individual sources without full config backup
|
||||
|
||||
## Backend Review Fixes (2026-03-14)
|
||||
|
||||
### Performance
|
||||
- [x] **P1** PIL blocking in async handlers → `asyncio.to_thread`
|
||||
- [x] **P2** `subprocess.run` blocking event loop → `asyncio.create_subprocess_exec`
|
||||
- [x] **P3** Audio enum blocking async → `asyncio.to_thread`
|
||||
- [x] **P4** Display enum blocking async → `asyncio.to_thread`
|
||||
- [x] **P5** `colorsys` scalar loop in hot path → vectorize numpy
|
||||
- [x] **P6** `MappedStream` per-frame allocation → double-buffer
|
||||
- [x] **P7** Audio/effect per-frame temp allocs → pre-allocate
|
||||
- [x] **P8** Blocking `httpx.get` in stream init → documented (callers use to_thread)
|
||||
- [x] **P9** No-cache middleware runs on all requests → scope to static
|
||||
- [x] **P10** Sync file I/O in async handlers (stores) → documented as accepted risk (< 5ms)
|
||||
- [x] **P11** `frame_time` float division every loop iter → cache field
|
||||
- [x] **P12** `_check_name_unique` O(N) + no lock → add threading.Lock
|
||||
- [x] **P13** Imports inside 1-Hz metrics loop → move to module level
|
||||
|
||||
### Code Quality
|
||||
|
||||
- [x] **Q1** `DeviceStore` not using `BaseJsonStore`
|
||||
- [x] **Q2** `ColorStripStore` 275-line god methods → factory dispatch
|
||||
- [x] **Q3** Layer violation: core imports from routes → extract to utility
|
||||
- [x] **Q4** 20+ field-by-field update in Device/routes → dataclass + generic update
|
||||
- [x] **Q5** WebSocket auth copy-pasted 9x → extract helper
|
||||
- [x] **Q6** `set_device_brightness` bypasses store → use update_device
|
||||
- [x] **Q7** DI via 16+ module globals → registry pattern
|
||||
- [x] **Q8** `_css_to_response` 30+ getattr → polymorphic to_response
|
||||
- [x] **Q9** Private attribute access across modules → expose as properties
|
||||
- [x] **Q10** `ColorStripSource.to_dict()` emits ~25 nulls → per-subclass override
|
||||
- [x] **Q11** `DeviceStore.get_device` returns None vs raises → raise ValueError
|
||||
- [x] **Q12** `list_all_tags` fragile method-name probing → use get_all()
|
||||
- [x] **Q13** Route create/update pass 30 individual fields → **kwargs
|
||||
|
||||
## UX
|
||||
|
||||
- [ ] `P1` **Collapse dashboard running target stats** — Show only FPS chart by default; uptime, errors, and pipeline timings in an expandable section collapsed by default
|
||||
|
||||
Reference in New Issue
Block a user