docs(01-04): complete device CRUD UI and CSS fix plan — SUMMARY, STATE, ROADMAP, REQUIREMENTS updated

- Close DEV-03: add-device form, POST/DELETE wired, remove buttons on device rows
- Close UI-02: --accent canonical CSS variable, panel IDs all present
- Phase 01 foundation: 4/4 plans complete
This commit is contained in:
Claude
2026-04-05 20:15:04 +00:00
parent 2ff35f9628
commit 57e40b2be2
4 changed files with 151 additions and 11 deletions

View File

@@ -61,7 +61,7 @@
### UI / UX
- [x] **UI-01**: Web app served by Python backend — no external hosting required
- [ ] **UI-02**: Terminal/hacker aesthetic — dark theme, monospace fonts, CRT/scanline vibe; NOT generic SaaS look
- [x] **UI-02**: Terminal/hacker aesthetic — dark theme, monospace fonts, CRT/scanline vibe; NOT generic SaaS look
- [ ] **UI-03**: All primary operations accessible without mouse (keyboard shortcuts for play/pause/seek/undo)
- [ ] **UI-04**: Live preview panel — simulated LED strip visualization in browser canvas, synced to playback

View File

@@ -12,7 +12,7 @@ LightSync is built bottom-up: data model first, audio engine second, UDP protoco
Decimal phases appear between their surrounding integers in numeric order.
- [ ] **Phase 1: Foundation** - FastAPI skeleton, show file schema (Pydantic), device registry, terminal-aesthetic frontend shell (gap closure in progress)
- [x] **Phase 1: Foundation** - FastAPI skeleton, show file schema (Pydantic), device registry, terminal-aesthetic frontend shell (gap closure in progress) (completed 2026-04-05)
- [ ] **Phase 2: Audio Engine** - MPV IPC bridge, waveform rendering, playback controls, Windows timer fix
- [ ] **Phase 3: Communication Protocol** - UDP packet spec, DRGB/DNRGB/DRGBW encoders, animation library, software simulator
- [ ] **Phase 4: Timeline Editor** - DAW UI (tracks, drag-place blocks, resize, delete), undo/redo, beat detection, snap-to-beat
@@ -38,7 +38,7 @@ Plans:
- [x] 01-01: Backend scaffold — FastAPI app, Pydantic show/device models, show store (JSON load/save), device registry
- [x] 01-02: Frontend shell — HTML/CSS terminal aesthetic, WebSocket client stub, device panel, show panel
- [x] 01-03: REST API — CRUD endpoints for devices and shows, static file serving, integration smoke test
- [ ] 01-04: Gap closure — device CRUD UI (add form, remove button), CSS variable naming fix, panel IDs
- [x] 01-04: Gap closure — device CRUD UI (add form, remove button), CSS variable naming fix, panel IDs
**UI hint**: yes
### Phase 2: Audio Engine
@@ -152,7 +152,7 @@ Phases execute in numeric order: 1 → 2 → 3 → 4 → 5 → 6 → 7
| Phase | Plans Complete | Status | Completed |
|-------|----------------|--------|-----------|
| 1. Foundation | 3/4 | Gap closure | - |
| 1. Foundation | 4/4 | Complete | 2026-04-05 |
| 2. Audio Engine | 0/3 | Not started | - |
| 3. Communication Protocol | 0/3 | Not started | - |
| 4. Timeline Editor | 0/4 | Not started | - |

View File

@@ -3,14 +3,14 @@ gsd_state_version: 1.0
milestone: v1.0
milestone_name: milestone
status: executing
stopped_at: Completed 01-foundation/01-03-PLAN.md
last_updated: "2026-04-05T19:00:44.725Z"
stopped_at: Completed 01-foundation/01-04-PLAN.md
last_updated: "2026-04-05T20:14:32.603Z"
last_activity: 2026-04-05
progress:
total_phases: 7
completed_phases: 1
total_plans: 3
completed_plans: 3
total_plans: 4
completed_plans: 4
percent: 0
---
@@ -26,7 +26,7 @@ See: .planning/PROJECT.md (updated 2026-04-05)
## Current Position
Phase: 01 (foundation) — EXECUTING
Plan: 2 of 3
Plan: 2 of 4
Status: Ready to execute
Last activity: 2026-04-05
@@ -54,6 +54,7 @@ Progress: [░░░░░░░░░░] 0%
*Updated after each plan completion*
| Phase 01-foundation P01 | 4 | 2 tasks | 23 files |
| Phase 01-foundation P03 | 6 | 1 tasks | 9 files |
| Phase 01 P04 | 2 | 2 tasks | 3 files |
## Accumulated Context
@@ -71,6 +72,8 @@ Recent decisions affecting current work:
- [Phase 01-foundation]: encode_animation_cmd stubs return b'' — Phase 3 implements real UDP animation command encoding
- [Phase 01-foundation]: redirect_slashes=False on FastAPI — StaticFiles at root intercepted API redirects
- [Phase 01-foundation]: API collection routes use empty-string paths ('') not '/' — canonical /api/devices without redirect
- [Phase 01]: window.removeDevice export required for ES module onclick compatibility — functions in type=module scripts are not global
- [Phase 01]: CSS accent variable canonical naming: --accent is source of truth, aliases are text-accent and border-bright
### Pending Todos
@@ -84,8 +87,8 @@ None yet.
## Session Continuity
Last session: 2026-04-05T19:00:44.716Z
Stopped at: Completed 01-foundation/01-03-PLAN.md
Last session: 2026-04-05T20:14:32.598Z
Stopped at: Completed 01-foundation/01-04-PLAN.md
Resume file: None
Next action: `/gsd:plan-phase 1`

View File

@@ -0,0 +1,137 @@
---
phase: 01-foundation
plan: 04
subsystem: frontend
tags: [spa, javascript, css, device-crud, gap-closure, ui]
# Dependency graph
requires:
- phase: 01-03
provides: "Docker deploy to lightsync.groll.cloud with backend API including POST/DELETE /api/devices"
provides:
- "Add-device form in DEVICES panel (name, strip_type select, led_count, ip, port, submit)"
- "POST /api/devices form submit handler with form reset on success"
- "DELETE /api/devices/{id} remove button on each device row"
- "apiPost() and apiDelete() helper functions in app.js"
- "removeDevice() function exposed globally via window.removeDevice for onclick"
- "CSS --accent: #00ffff as canonical variable; --text-accent and --border-bright as aliases"
- "Panel IDs: devices-panel, animations-panel, timeline-panel, transport-panel"
affects: []
# Tech tracking
tech-stack:
added: []
patterns:
- "module-scoped async helpers (apiPost/apiDelete) for fetch wrappers with error propagation"
- "window export pattern for onclick-accessible functions in ES modules (window.removeDevice)"
- "CSS single-source-of-truth variable pattern: --accent as canonical, aliases via var()"
key-files:
created:
- .planning/phases/01-foundation/01-04-SUMMARY.md
modified:
- lightsync/frontend/index.html
- lightsync/frontend/app.js
- lightsync/frontend/style.css
key-decisions:
- "Panel IDs added in Task 1 (alongside form), not deferred to Task 2 — single HTML touch reduces diff noise"
- "window.removeDevice export required because app.js uses type=module which scopes functions away from global onclick"
- "--accent added as new root variable; existing --border-bright and --text-accent become aliases — no refactor of usage sites needed"
requirements-completed:
- DEV-03
- UI-02
# Metrics
duration: ~2min
completed: 2026-04-05
---
# Phase 01 Plan 04: Device CRUD UI and CSS Variable Fix Summary
**Gap-closure plan: added device add/remove form to DEVICES panel and fixed CSS variable naming — closes DEV-03 (device list with UI interaction) and UI-02 (CSS contract alignment)**
## Performance
- **Duration:** ~2 min
- **Started:** 2026-04-05T20:11:51Z
- **Completed:** 2026-04-05T20:13:30Z
- **Tasks:** 2 (both auto)
- **Files modified:** 3 (index.html, app.js, style.css)
## Accomplishments
### Task 1: Device CRUD UI
- Added `<form id="add-device-form" class="device-form">` to the DEVICES panel in `index.html`, with inputs for name (text), strip_type (select: sk6812/ws2801/generic), led_count (number), ip (text), port (number, default 21324), and a submit button "+ ADD DEVICE"
- Added `apiPost(path, data)` and `apiDelete(path)` async fetch helpers to `app.js` (positioned after WS_URL const, before LightSyncClient)
- Updated `loadDevices()` device row template to include a `.device-remove` button with `onclick="removeDevice(d.id)"` alongside a `.device-row-info` wrapper for the name/metadata
- Added `removeDevice(id)` function that calls `apiDelete(/api/devices/{id})` then refreshes the list; exported as `window.removeDevice` for ES module compatibility with inline onclick handlers
- Added form submit handler that calls `apiPost("/api/devices", data)`, resets form (restoring port default to 21324), then refreshes the device list
- Added panel IDs to all four panels: `id="devices-panel"`, `id="animations-panel"`, `id="timeline-panel"`, `id="transport-panel"`
### Task 2: CSS Variable Naming Fix
- Added `--accent: #00ffff` as canonical variable in `:root`
- Changed `--border-bright` and `--text-accent` to be aliases: `var(--accent)` instead of hardcoded `#00ffff`
- Added `.device-form` CSS rule: flex-column, 4px gap, border-top separator from device list
- Added `.device-remove` rule: borderless button, dim text, hover turns red (`#ff3333`)
- Updated `.device-row` to `display: flex; align-items: center; justify-content: space-between` to accommodate remove button alongside info
- Added `.device-row-info` flex-column wrapper for name + metadata within each row
## Task Commits
1. **Task 1: Device CRUD UI**`ccc40c8` (feat)
2. **Task 2: CSS variable fix + device form styles**`2ff35f9` (feat)
## Files Created/Modified
- `lightsync/frontend/index.html` — added form, panel IDs, timeline/transport panel wrappers
- `lightsync/frontend/app.js` — added apiPost, apiDelete, removeDevice, form submit handler, updated device row template
- `lightsync/frontend/style.css` — added --accent canonical variable, aliases, device form and remove button styles
## Decisions Made
- **Panel IDs added in Task 1**: The HTML file was already being modified for the form, so panel IDs were added in the same edit pass to minimize diff noise. Task 2 only touched CSS.
- **window.removeDevice export**: ES modules scope all declarations — `onclick="removeDevice(...)"` in dynamically rendered HTML requires the function to be on the global `window` object.
- **No refactor of --text-accent usage sites**: `--border-bright` and `--text-accent` are now aliases of `--accent`. No existing CSS rules using these variables needed to change — the alias pattern lets the semantics remain meaningful (text-accent vs border-bright) while sharing a single source color value.
## Deviations from Plan
None — plan executed exactly as written. Panel IDs were added in Task 1 edit rather than Task 2 (minor sequencing optimization, not a behavioral change).
## Requirements Closed
| Requirement | Status | Evidence |
|-------------|--------|----------|
| DEV-03 | CLOSED | Add-device form in DEVICES panel; POST/DELETE wired; device rows have remove buttons |
| UI-02 | CLOSED | `--accent: #00ffff` canonical variable present; `--text-accent` and `--border-bright` are aliases; all four panel IDs present |
## Verification Results
1. `grep "add-device-form" lightsync/frontend/index.html` — MATCH
2. `grep "apiPost\|apiDelete\|removeDevice" lightsync/frontend/app.js` — 4 matches (function defs + window export + apiPost call in form handler)
3. `grep "\-\-accent.*#00ffff" lightsync/frontend/style.css` — MATCH
4. `grep "devices-panel\|animations-panel\|timeline-panel\|transport-panel" lightsync/frontend/index.html` — 4 matches
## Known Stubs
None — all gap-closure work is fully wired. The form submits to a live API endpoint. Device removal calls a live DELETE endpoint.
## Self-Check
Files modified:
- lightsync/frontend/index.html — FOUND
- lightsync/frontend/app.js — FOUND
- lightsync/frontend/style.css — FOUND
Commits:
- ccc40c8 — Task 1 (feat(01-04))
- 2ff35f9 — Task 2 (feat(01-04))
## Self-Check: PASSED
---
*Phase: 01-foundation*
*Completed: 2026-04-05*