82 lines
4.1 KiB
Markdown
82 lines
4.1 KiB
Markdown
---
|
|
phase: 11-ui-enhancements
|
|
plan: "04"
|
|
subsystem: navigation/client-detail
|
|
tags: [client-nav, routing, templates, tdd]
|
|
dependency_graph:
|
|
requires: [11-02, 11-03]
|
|
provides: [GET /clients/{id}, client_detail.html, client-name-links]
|
|
affects: [imptune/api/pages.py, printer_list.html, client_list.html]
|
|
tech_stack:
|
|
added: []
|
|
patterns: [grouped-dict-reuse, client_id-from-FK-field]
|
|
key_files:
|
|
created:
|
|
- imptune/templates/client_detail.html
|
|
modified:
|
|
- imptune/api/pages.py
|
|
- imptune/templates/partials/printer_list.html
|
|
- imptune/templates/partials/client_list.html
|
|
decisions:
|
|
- "client_id extracted from printers[0].client_id in Jinja2 template (no grouped structure change)"
|
|
- "Unassigned group renders plain text — condition is False when client_id is None"
|
|
- "client_detail route placed after /clients to avoid FastAPI path conflict ordering"
|
|
metrics:
|
|
duration_minutes: 4
|
|
completed_date: "2026-04-15"
|
|
tasks_completed: 2
|
|
files_changed: 4
|
|
---
|
|
|
|
# Phase 11 Plan 04: Client Name Navigation Summary
|
|
|
|
One-liner: Per-client filtered printer page at GET /clients/{id} with clickable client names in printer group headers and client table, using grouped-dict reuse pattern from existing printer_list partial.
|
|
|
|
## What Was Built
|
|
|
|
- **GET /clients/{client_id} route** in `imptune/api/pages.py`: queries client by id (404 if not found), builds `grouped = {client.name: [printers]}` dict, passes full context (clients, driver_data) so printer_list partial with Edit/Delete modals works identically to /printers.
|
|
- **client_detail.html template**: extends base.html, renders client name as `<h1>`, back-link to /clients, includes `partials/printer_list.html`.
|
|
- **printer_list.html updated**: added `{% set group_client_id = printers[0].client_id if printers else None %}` + conditional `<h3>` — assigned clients get anchor link, Unassigned group remains plain text.
|
|
- **client_list.html updated**: client name `<td>` now wraps name in `<a href="/clients/{{ c.id }}">`.
|
|
|
|
## Tasks Completed
|
|
|
|
| Task | Name | Commit | Files |
|
|
|------|------|--------|-------|
|
|
| 1 | GET /clients/{id} route + client_detail.html | f364479 | imptune/api/pages.py, imptune/templates/client_detail.html |
|
|
| 2 | Client name links in printer_list.html and client_list.html | 5bf152b | imptune/templates/partials/printer_list.html, imptune/templates/partials/client_list.html |
|
|
|
|
## Test Results
|
|
|
|
All 3 UIE-03 scaffolded tests now GREEN:
|
|
- `test_client_detail_returns_200` — PASSED
|
|
- `test_client_detail_not_found` — PASSED
|
|
- `test_client_links_in_printer_list` — PASSED
|
|
|
|
Full non-E2E suite: **122/122 PASSED**
|
|
|
|
E2E suite: 6/7 passed — `test_port_autofill[chromium]` FAILED (pre-existing failure, present before this plan's changes; deferred to deferred-items.md).
|
|
|
|
## Decisions Made
|
|
|
|
1. **client_id from printers[0].client_id**: Extracted in Jinja2 template rather than changing the grouped data structure. The `client_id` FK field on Printer returns raw integer when accessed as `.client_id`, avoiding FK object traversal. No changes to the route's grouped dict construction needed.
|
|
2. **Unassigned group is plain text**: `group_client_id` evaluates to None/falsy for unassigned printers; `{% if group_client_id %}` condition cleanly handles both cases.
|
|
3. **Route ordering**: `/clients/{client_id}` placed after `/clients` in pages.py to respect FastAPI path-specificity ordering — FastAPI matches literal `/clients` before the parameter route.
|
|
|
|
## Deviations from Plan
|
|
|
|
None — plan executed exactly as written. All recommended approaches in the plan's interfaces section worked as described without modification.
|
|
|
|
## Out-of-Scope Items Deferred
|
|
|
|
`test_port_autofill[chromium]` E2E failure: pre-existing, introduced when Plan 11-01 separated the add-printer form to `/printers/new` while the test still navigates to `/printers` expecting `input[name='ip_address']`. Logged in `.planning/phases/11-ui-enhancements/deferred-items.md`.
|
|
|
|
## Self-Check: PASSED
|
|
|
|
- imptune/api/pages.py — FOUND
|
|
- imptune/templates/client_detail.html — FOUND
|
|
- imptune/templates/partials/printer_list.html — FOUND
|
|
- imptune/templates/partials/client_list.html — FOUND
|
|
- Commit f364479 — FOUND
|
|
- Commit 5bf152b — FOUND
|