4.8 KiB
4.8 KiB
| phase | plan | subsystem | tags | dependency_graph | tech_stack | key_files | decisions | metrics | |||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 04-usb-manager-label-printing | 05 | frontend |
|
|
|
|
|
|
Phase 04 Plan 05: Frontend USB Status Bar and Print Label Summary
One-liner: SSE-backed useUSBEvents hook with USBStatusBar component and per-item print label button wired to POST /api/labels/:id/print with react-hot-toast feedback.
Tasks Completed
| Task | Description | Commit |
|---|---|---|
| 1 | useUSBEvents hook + USBStatusBar component | 8b88970 |
| 2 | Wire USBStatusBar + Print Label into dashboard | 3de1e4f |
What Was Built
useUSBEvents hook (web/src/hooks/useUSBEvents.ts)
- Subscribes to
GET /api/usb/eventsSSE stream vianew EventSource('/api/usb/events') - Maintains
connectedDevices: Map<string, DeviceSpec>in React state - Connect events add to map; disconnect events remove from map
- Malformed JSON silently ignored (T-04-14 mitigated)
- EventSource auto-reconnects on error (T-04-15 accepted)
- Exports:
useUSBEvents,DeviceEvent,DeviceSpec,StateConnected,StateDisconnected
USBStatusBar component (web/src/components/USBStatusBar.tsx)
- Consumes
useUSBEvents(), renders connected device list - Role icons: Printer (role=0), Cable (role=1), Usb (role=2/unknown)
- Green dot per connected device with device name
- Empty state: "No USB devices" with USB icon in muted text
- ClickHouse design: black bg,
border-white/10,text-white/80,bg-green-500status dots
api.ts additions (web/src/lib/api.ts)
printLabel(deviceId: number): Promise<PrintLabelResponse>— POST /api/labels/:id/printPrintLabelResponseinterface:{ status: string; print_skipped?: boolean }- Throws typed Error on non-OK response
ItemCard (web/src/components/inventory/ItemCard.tsx)
- Module-level
handlePrintLabel(e, itemId)usingprintLabel()from api.ts - Printer icon button in CardFooter alongside NetBox link
- Toast: loading → success / "queued — printer not connected" / error
ItemRow (web/src/components/inventory/ItemRow.tsx)
- Same
handlePrintLabelpattern - Print button added to quick-actions group (appears on hover with ExternalLink)
- Opacity transition matches existing group-hover pattern
DashboardPage (web/src/pages/DashboardPage.tsx)
- Imports and renders
<USBStatusBar />in page header (flex row, right-aligned) - No layout restructuring — additive change only
Deviations from Plan
Auto-fixed Issues
None — plan executed exactly as written with one minor deviation:
1. [Rule 2 - Deviation] Print button added to ItemCard/ItemRow rather than DashboardPage map
- Found during: Task 2
- Reason: DashboardPage passes items to
<ItemCard>and<ItemRow>as components — adding print logic inline in the map would duplicate code and break component encapsulation. Plan said "find where item quick actions are rendered" which is the card/row components. - Impact: Cleaner architecture; identical user-visible result
- Files modified: ItemCard.tsx, ItemRow.tsx (instead of DashboardPage.tsx map)
Known Stubs
None — all data flows wired. USBStatusBar connects to live SSE. Print button calls real endpoint.
Threat Flags
None — no new trust boundaries beyond those in the plan's threat model.
Self-Check
Files exist:
- web/src/hooks/useUSBEvents.ts — FOUND
- web/src/components/USBStatusBar.tsx — FOUND
- web/src/lib/api.ts (modified) — FOUND
- web/src/components/inventory/ItemCard.tsx (modified) — FOUND
- web/src/components/inventory/ItemRow.tsx (modified) — FOUND
- web/src/pages/DashboardPage.tsx (modified) — FOUND
Commits:
- 8b88970 — feat(04-05): add useUSBEvents hook and USBStatusBar component
- 3de1e4f — feat(04-05): wire USBStatusBar and Print Label button into dashboard
Build: npm run build — PASSED (tsc -b + vite build, 0 errors, 1965 modules)