Files
ImpTune/imptune/api/pages.py
T
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

176 lines
5.2 KiB
Python

import json
from collections import defaultdict
from pathlib import Path
from fastapi import APIRouter, Request
from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates
from peewee import JOIN
router = APIRouter()
templates = Jinja2Templates(directory=str(Path(__file__).parent.parent / "templates"))
@router.get("/", response_class=HTMLResponse)
def dashboard(request: Request):
from imptune.db.models import Printer
recent_printers = list(
Printer.select().order_by(Printer.created_at.desc()).limit(5)
)
recent_packages = list(
Printer.select()
.where(Printer.driver.is_null(False))
.order_by(Printer.created_at.desc())
.limit(5)
)
return templates.TemplateResponse(
request=request,
name="dashboard.html",
context={
"recent_printers": recent_printers,
"recent_packages": recent_packages,
},
)
@router.get("/drivers", response_class=HTMLResponse)
def drivers_page(request: Request):
from imptune.db.models import Driver
drivers = list(Driver.select().order_by(Driver.uploaded_at.desc()))
driver_data = []
for d in drivers:
names = json.loads(d.driver_desc) if d.driver_desc else []
driver_data.append({"driver": d, "names": names})
return templates.TemplateResponse(
request=request,
name="drivers.html",
context={"driver_data": driver_data},
)
@router.get("/printers", response_class=HTMLResponse)
def printers_page(request: Request):
from imptune.db.models import Client, Driver, Printer
query = (
Printer.select(Printer, Client)
.join(Client, JOIN.LEFT_OUTER)
.order_by(Client.name, Printer.name)
)
grouped: dict[str, list] = defaultdict(list)
for p in query:
client_name = p.client.name if p.client_id else "Unassigned"
grouped[client_name].append(p)
clients = list(Client.select().order_by(Client.name))
all_drivers = list(Driver.select().order_by(Driver.uploaded_at.desc()))
driver_data = []
for d in all_drivers:
names = json.loads(d.driver_desc) if d.driver_desc else []
driver_data.append({"driver": d, "names": names})
return templates.TemplateResponse(
request=request,
name="printers.html",
context={
"grouped": grouped,
"clients": clients,
"driver_data": driver_data,
},
)
@router.get("/printers/new", response_class=HTMLResponse)
def printers_new_page(request: Request):
from imptune.db.models import Client, Driver
clients = list(Client.select().order_by(Client.name))
all_drivers = list(Driver.select().order_by(Driver.uploaded_at.desc()))
driver_data = [
{"driver": d, "names": json.loads(d.driver_desc) if d.driver_desc else []}
for d in all_drivers
]
return templates.TemplateResponse(
request=request,
name="printers_new.html",
context={"clients": clients, "driver_data": driver_data},
)
@router.get("/printers/{printer_id}", response_class=HTMLResponse)
def printer_detail(request: Request, printer_id: int):
from imptune.db.models import Client, Driver, Icon, Printer
printer = (
Printer.select(Printer, Client, Driver)
.join(Client, JOIN.LEFT_OUTER)
.switch(Printer)
.join(Driver, JOIN.LEFT_OUTER)
.where(Printer.id == printer_id)
.first()
)
if printer is None:
return HTMLResponse(
content="<h1>404 Not Found</h1><p>Printer not found.</p>",
status_code=404,
)
driver_names: list[str] = []
if printer.driver_id and printer.driver.driver_desc:
driver_names = json.loads(printer.driver.driver_desc)
has_driver = printer.driver_id is not None and bool(driver_names)
icon = Icon.get_or_none(Icon.printer == printer_id)
install_cmd = "powershell.exe -ExecutionPolicy Bypass -File install.ps1"
uninstall_cmd = "powershell.exe -ExecutionPolicy Bypass -File uninstall.ps1"
return templates.TemplateResponse(
request=request,
name="printer_detail.html",
context={
"printer": printer,
"driver_names": driver_names,
"has_driver": has_driver,
"has_icon": icon is not None,
"install_cmd": install_cmd,
"uninstall_cmd": uninstall_cmd,
},
)
@router.get("/clients", response_class=HTMLResponse)
def clients_page(request: Request):
from imptune.db.models import Client
clients = list(Client.select().order_by(Client.name))
return templates.TemplateResponse(
request=request,
name="clients.html",
context={"clients": clients},
)
@router.get("/packages", response_class=HTMLResponse)
def packages_page(request: Request):
from imptune.db.models import Client, Driver, Printer
printers = list(
Printer.select(Printer, Client, Driver)
.join(Client, JOIN.LEFT_OUTER)
.switch(Printer)
.join(Driver, JOIN.LEFT_OUTER)
.where(Printer.driver.is_null(False))
.order_by(Printer.name)
)
return templates.TemplateResponse(
request=request,
name="packages.html",
context={"printers": printers},
)