Commit initial
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
---
|
||||
phase: 11-ui-enhancements
|
||||
plan: "02"
|
||||
subsystem: printer-ui
|
||||
tags: [uie-01, htmx, patch, modal, pico-css, alpine-js, e2e, playwright]
|
||||
dependency_graph:
|
||||
requires: [11-01]
|
||||
provides: [PATCH /printers/{id}, printer_edit_modal.html, Edit button per row]
|
||||
affects: [imptune/api/printers.py, imptune/templates/partials/printer_list.html, imptune/templates/partials/printer_edit_modal.html, tests/e2e/test_printer_edit.py]
|
||||
tech_stack:
|
||||
added: []
|
||||
patterns: [HTMX PATCH in-place update, Pico CSS native dialog, Alpine.js portEdited guard, session-scoped E2E row targeting]
|
||||
key_files:
|
||||
created:
|
||||
- imptune/templates/partials/printer_edit_modal.html
|
||||
- tests/e2e/test_printer_edit.py
|
||||
modified:
|
||||
- imptune/api/printers.py
|
||||
- imptune/templates/partials/printer_list.html
|
||||
decisions:
|
||||
- "PATCH ip_address and port_name are optional Form fields (default empty string) that fall back to existing printer values — matches Wave 0 test scaffold that only sends name"
|
||||
- "E2E row targeting uses locator(tr, has=locator(a, has_text)) to handle session-scoped live_server accumulating multiple printers across tests"
|
||||
- "updated_at set explicitly via datetime.now(UTC).replace(tzinfo=None) inside PATCH handler"
|
||||
- "clients and driver_data added to _render_printer_list context for edit modal pre-population"
|
||||
metrics:
|
||||
duration: "~20 minutes"
|
||||
completed: "2026-04-15"
|
||||
tasks_completed: 2
|
||||
tasks_total: 2
|
||||
files_modified: 4
|
||||
---
|
||||
|
||||
# Phase 11 Plan 02: Printer Edit Modal (UIE-01) Summary
|
||||
|
||||
**One-liner:** HTMX PATCH route + Pico CSS native dialog edit modal with Alpine.js port guard and Playwright E2E coverage.
|
||||
|
||||
## What Was Built
|
||||
|
||||
UIE-01 is now complete: every printer row in the library has an Edit button that opens a pre-filled native `<dialog>` modal. Submitting the form sends a HTMX PATCH to `/printers/{id}`, closes the modal, and refreshes the printer list in-place without a page reload.
|
||||
|
||||
### Key Changes
|
||||
|
||||
- **`imptune/api/printers.py`** — Added `PATCH /{printer_id}` route handler with full validation (name/ip/port required, duplex/paper enum checks). Optional `ip_address` and `port_name` fall back to existing values when not submitted. Updated `_render_printer_list` to pass `clients` and `driver_data` in the template context for modal pre-population. Imported `Driver` at module level.
|
||||
|
||||
- **`imptune/templates/partials/printer_edit_modal.html`** (new, 98 lines) — Pico CSS native `<dialog>` with Edit trigger button and HTMX PATCH form. Uses `hx-on::after-request` to close the modal on success. Alpine.js `x-data` sets `portEdited: true` so editing IP does not overwrite a manually-set port. Pre-fills all printer fields including driver/client selects with `selected` conditional.
|
||||
|
||||
- **`imptune/templates/partials/printer_list.html`** — Actions `<td>` updated: `{% include "partials/printer_edit_modal.html" %}` inserted before the Delete button, inside the `{% for p in printers %}` loop so `p` is in scope.
|
||||
|
||||
- **`tests/e2e/test_printer_edit.py`** (new) — Two Playwright E2E tests: modal open and pre-fill verification; submit updates list via HTMX PATCH. Row targeting uses `page.locator("tr", has=page.locator("a", has_text="OriginalName"))` to handle session-scoped live_server accumulating data across tests.
|
||||
|
||||
## Test Results
|
||||
|
||||
| Suite | Status |
|
||||
|-------|--------|
|
||||
| test_patch_printer | GREEN |
|
||||
| test_patch_printer_not_found | GREEN |
|
||||
| test_printer_edit_modal_open_and_prefill | GREEN (E2E) |
|
||||
| test_printer_edit_submit_updates_list | GREEN (E2E) |
|
||||
| Full non-E2E suite | 120 passed, 2 expected RED (UIE-03 Wave 0) |
|
||||
|
||||
## Commits
|
||||
|
||||
| Hash | Message |
|
||||
|------|---------|
|
||||
| `4b212b6` | feat(11-02): PATCH /printers/{id} route handler and updated _render_printer_list |
|
||||
| `7b948b6` | feat(11-02): UIE-01 edit modal — Edit button per row, Pico dialog, E2E tests |
|
||||
|
||||
## Deviations from Plan
|
||||
|
||||
### Auto-fixed Issues
|
||||
|
||||
**1. [Rule 2 - Missing functionality] ip_address and port_name made optional in PATCH handler**
|
||||
- **Found during:** Task 1 — reviewing Wave 0 test scaffold `test_patch_printer`
|
||||
- **Issue:** The plan specified `ip_address: str = Form(...)` and `port_name: str = Form(...)` as required, but the existing RED scaffold test only sends `{"name": "Updated Name"}`. The handler would have returned 422 Unprocessable Entity.
|
||||
- **Fix:** Changed `ip_address` and `port_name` to `Form("")` with fallback to `printer.ip_address` / `printer.port_name` when empty, preserving validation logic while passing the test.
|
||||
- **Files modified:** `imptune/api/printers.py`
|
||||
- **Commit:** `4b212b6`
|
||||
|
||||
**2. [Rule 1 - Bug] E2E test_printer_edit_submit_updates_list used wrong selector for session-scope isolation**
|
||||
- **Found during:** Task 2 — E2E test run
|
||||
- **Issue:** `page.click("button:has-text('Edit')")` clicked the first Edit button in the list, which belonged to a printer from a previous test (session-scoped live_server). The targeted printer ("OriginalName") was not updated.
|
||||
- **Fix:** Changed to `page.locator("tr", has=page.locator("a", has_text="OriginalName")).locator("button:has-text('Edit')").click()` to target the specific row. Also updated assertion to check anchor text (`a:has-text`) rather than `td:first-child` inner text, and used `page.wait_for_selector("a:has-text('UpdatedName')")` for HTMX swap completion.
|
||||
- **Files modified:** `tests/e2e/test_printer_edit.py`
|
||||
- **Commit:** `7b948b6`
|
||||
|
||||
## Success Criteria Check
|
||||
|
||||
- [x] Every printer row has an Edit button
|
||||
- [x] Clicking Edit opens a native dialog pre-filled with that printer's current data
|
||||
- [x] Submitting the edit form sends HTMX PATCH, closes the modal, and updates the list
|
||||
- [x] PATCH /printers/{id} validated via test_patch_printer (GREEN)
|
||||
- [x] PATCH /printers/9999 returns 404 (confirmed by test_patch_printer_not_found)
|
||||
- [x] E2E tests pass: modal opens, name is pre-filled, submit updates list
|
||||
|
||||
## Self-Check: PASSED
|
||||
Reference in New Issue
Block a user