Commit Graph
18 Commits
Author SHA1 Message Date
kawa 4b212b6da9 feat(11-02): PATCH /printers/{id} route handler and updated _render_printer_list
- Add PATCH /{printer_id} route with validation and in-place update
- Optional ip_address/port_name fall back to existing values when not sent
- updated_at set explicitly on save (datetime.now(UTC))
- Update _render_printer_list to include clients and driver_data in context
- Import Driver at module level for use in both handler and helper
2026-04-15 11:08:02 +02:00
kawa c00ac80e6c docs(11-01): complete UIE-02 plan — Add Printer page separation
- Create 11-01-SUMMARY.md with full execution record
- Update STATE.md: advance plan to 3, add decisions, update session
- Update ROADMAP.md: phase 11 progress to 1/4 summaries (In Progress)
2026-04-15 11:05:23 +02:00
kawa 3d2cdc4e77 feat(11-01): UIE-02 — dedicated Add Printer page at GET /printers/new
- Create imptune/templates/printers_new.html: full page extending base.html
  with plain <form action="/printers" method="post"> (no HTMX, browser follows 303)
  and inline driver upload sub-form
- Update imptune/templates/printers.html: remove inline Add Printer form,
  add <a href="/printers/new" role="button">Add Printer</a> link
- Add GET /printers/new route in imptune/api/pages.py (placed before /{printer_id})
- Change POST /printers to always return RedirectResponse(url='/printers', status_code=303)
- Update existing POST /printers tests to assert 303 + follow_redirects=False
- Update test_printer_form.py to check /printers/new instead of /printers (UIE-02 arch)
- UIE-02 tests GREEN; UIE-01/03 scaffolds remain RED (expected — not yet implemented)
2026-04-15 11:03:41 +02:00
kawaandClaude Sonnet 4.6 036b048705 docs(phase-09): complete phase execution and human sign-off
All 3 UX defects fixed, 11/11 must-haves verified, human-approved.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 09:52:43 +02:00
kawa 10ee09a5aa fix(09-01): resolve driver upload 500 and add HTMX OOB refresh path
- Import Form from fastapi for mixed multipart + form field support
- Add caller: str = Form('') parameter to upload_driver handler
- Capture new_driver from Driver.get_or_create() return tuple
- Branch on caller == 'printer_form' to emit OOB-enabled response
- Create partials/driver_upload_with_oob.html with primary driver_list
  include + hx-swap-oob select targeting id=printer-form-driver-select
- New driver is auto-selected via new_driver_id context variable

All 13 driver upload tests pass including 4 new OOB contract tests.
Full non-e2e suite: 111 passed.
2026-04-13 10:50:27 +02:00
kawa 68a2935af2 feat(09-03): add .ps1 script download routes and detail-page links
- Refactor install/uninstall/detect handlers into shared _*_response() helpers
- Add .ps1 route aliases: /scripts/install.ps1, /scripts/uninstall.ps1, /scripts/detect.ps1
- Add Scripts section to printer_detail.html inside {% if has_driver %} with 3 download links
- All 6 new tests green, full suite 106/106 passing
2026-04-13 10:48:43 +02:00
kawaandClaude Opus 4.6 67a1cd66ec chore: complete v1.0 milestone
Archive v1.0 MVP: 7 phases, 13 plans, 27/27 requirements.

- Archive roadmap to milestones/v1.0-ROADMAP.md
- Archive requirements to milestones/v1.0-REQUIREMENTS.md
- Move milestone audit into milestones/
- Create MILESTONES.md with v1.0 entry
- Evolve PROJECT.md: move shipped requirements to Validated,
  update Context with stack/LOC, log Key Decisions with outcomes
- Collapse ROADMAP.md to one-line milestone summary
- Update STATE.md to shipped status
- Back-fill stale requirements-completed frontmatter on
  02-01, 04-01, 05-01, 06-01 SUMMARY.md files

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 09:47:37 +02:00
kawa 91910ad97d feat(07-01): wire dashboard data and add /packages listing page
- Dashboard queries 5 most recent Printer records and 5 most recent driver-assigned ones
- New /packages route lists printers with drivers, with intunewin/ninja download links
- packages.html template extends base.html with Pico grid table
- Dashboard printer/package items now link to detail pages
- Quick action buttons wired to real routes (removed aria-disabled)
2026-04-13 08:58:13 +02:00
kawa 6310be5e76 feat(06-01): wire icon into .intunewin staging before build
- Add shutil import and Icon import to packages.py
- After driver extraction, look up Icon record for printer
- If found and file exists on disk, copy to tmpdir/icon.png
- Missing icon (no DB record or missing file) silently skipped — export still succeeds
- PKG-04 requirement satisfied
2026-04-10 16:21:34 +02:00
kawa f96ea6fec9 feat(05-02): printer detail page with export buttons and command preview
- Update printer_detail() to pass install_cmd, uninstall_cmd, has_driver, has_icon to template
- Rewrite printer_detail.html with Intune Commands, Export, and Icon sections
- Show command strings with Alpine.js copy-to-clipboard buttons (install-cmd, uninstall-cmd)
- Show NinjaRMM ZIP and .intunewin download links when driver assigned
- Add HTMX icon upload form with #icon-status swap target
- Remove disabled placeholder Regenerate Package button
- Add TestCommandPreview class (4 tests) to test_packages.py
- All 94 tests pass
2026-04-10 15:06:45 +02:00
kawa f9e13ba96f feat(05-02): icon upload endpoint with validation
- Create imptune/api/icons.py with POST /printers/{printer_id}/icon
- Validate PNG format, 256x256 dimensions, 750KB max size
- Store icons SHA256-addressed under cfg.DATA_DIR/icons/
- Replace existing Icon record on re-upload
- Register icons.router in main.py with ICONS_DIR makedirs
- Patch cfg.ICONS_DIR in conftest.py for tests
- All 6 icon upload tests pass
2026-04-10 15:05:36 +02:00
kawa dd6cedfed9 feat(05-01): implement NinjaRMM ZIP and intunewin package export endpoints
- GET /printers/{id}/packages/ninja: in-memory ZIP with install.ps1 + driver files in named subfolder
- GET /printers/{id}/packages/intunewin: temp dir build of .intunewin via build_intunewin()
- _get_printer_and_driver() helper validates printer, driver, inf, desc
- Driver ZIP file existence check before processing (RESEARCH pitfall 3)
- TemporaryDirectory context manager for auto-cleanup (RESEARCH pitfall 1)
- Router registered in main.py after scripts router
- All 9 package tests pass, 84 total tests green
2026-04-10 15:05:29 +02:00
kawa b7b0d1b4a5 feat(04-02): add script download API endpoints and router registration
- imptune/api/scripts.py: GET /printers/{id}/scripts/{install,uninstall,detect}
- 404 for missing printer, 422 for missing driver/INF/driver_desc
- Content-Disposition attachment header on all responses
- imptune/main.py: register scripts.router
- 5 integration tests covering all endpoint cases (200/404/422)
2026-04-10 13:36:07 +02:00
kawa cad664c0f6 feat(03-02): implement printer detail page with driver info and regenerate placeholder
- Add GET /printers/{printer_id} route to pages.py with LEFT OUTER JOINs on Client and Driver
- Create printer_detail.html full-page template showing all config fields and driver info
- Display "No driver assigned" when driver FK is null
- Add disabled "Regenerate Package" button (Phase 4 placeholder)
- Make printer names in printer_list.html clickable links to detail page
2026-04-10 13:04:52 +02:00
kawa 356c2ee690 feat(03-01): implement printer and client CRUD with HTMX/Alpine.js UI
- imptune/api/printers.py: POST /printers (all form fields, checkbox->bool,
  FK resolution), DELETE /printers/{id}, grouped list renderer with LEFT JOIN
- imptune/api/clients.py: POST /clients with duplicate-name handling
- imptune/api/pages.py: GET /printers and GET /clients page routes
- imptune/main.py: register printers + clients routers; close db on shutdown
- imptune/db/database.py: close existing connection before re-init (test isolation)
- templates: printers.html, clients.html, printer_form.html (Alpine.js port
  auto-derivation), printer_list.html (grouped by client), client_list.html
- tests/conftest.py: close test-thread db connection in fixture teardown
- tests/test_printer_crud.py: updated to use list(select().where()) for DB
  queries (avoids Peewee thread-local cursor caching across test boundaries)

Auto-fix [Rule 1 - Bug]: DB test isolation — Peewee thread-local connections
persisted across tests causing stale DB reads; fixed via conftest teardown and
lifespan db.close() on shutdown.
2026-04-10 12:56:09 +02:00
kawa c648fc5793 feat(02-02): add driver upload endpoint with INF parsing and dedup
- POST /drivers/upload: validates ZIP, parses INF, persists via DriverStore + Peewee
- SHA256 dedup: get_or_create prevents duplicate Driver records
- GET /drivers route added to pages.py with driver_data context
- drivers.router registered in main.py
- drivers.html template with HTMX upload form
- partials/driver_list.html HTMX target with select dropdown and unused-file notice
- Fixed conftest client fixture to use context manager (triggers lifespan/init_db)
- [Rule 3] conftest: TestClient context manager required for lifespan trigger
- [Rule 1] drivers.py: dynamic DRIVERS_DIR read so monkeypatch works in tests
2026-04-10 12:02:00 +02:00
kawa 34c7cb30f1 feat(01-01): add test scaffold, health and static asset tests, fix deprecated APIs
- requirements-dev.txt with pytest and httpx
- tests/conftest.py: client and tmp_data_dir fixtures
- tests/test_health.py: GET /health returns 200 with {"status": "ok"}
- tests/test_static.py: no CDN URLs in templates, dashboard returns 200
- Fix imptune/api/pages.py: use request= kwarg in TemplateResponse (Starlette compat)
- Fix imptune/main.py: replace deprecated on_event with asynccontextmanager lifespan
2026-04-10 11:26:48 +02:00
kawa bd4e132f82 feat(01-01): create Docker scaffold, FastAPI app shell, and sidebar templates
- Dockerfile with python:3.12-slim-bookworm, curl downloads Pico CSS, HTMX, Alpine.js at build time
- docker-compose.yml with imptune_data:/data named volume and restart policy
- requirements.txt with all phase 1-5 dependencies
- imptune/config.py loading DATA_DIR/PORT from env with DB_PATH and DRIVERS_DIR derived paths
- imptune/main.py: FastAPI app with StaticFiles mount, health+pages routers, startup dir creation
- imptune/api/health.py: GET /health returning {"status": "ok"}
- imptune/api/pages.py: GET / returning dashboard.html with sync def handler
- imptune/templates/base.html: data-theme="auto", sidebar with 5 nav sections, /static/ paths only
- imptune/templates/dashboard.html: quick actions + empty state recent activity
- imptune/static/app.css: sidebar layout, active link highlight, quick action buttons
2026-04-10 11:25:08 +02:00