10 KiB
phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, must_haves
| phase | plan | type | wave | depends_on | files_modified | autonomous | requirements | must_haves | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 07-dashboard-nav-polish | 01 | execute | 1 |
|
true |
|
Purpose: Close two visible integration gaps -- the /packages nav link returns 404 and the dashboard always shows empty lists despite real data existing in the database. Output: Working /packages page, dashboard with live recent printers and recent packages queries, integration tests proving all three success criteria.
<execution_context> @C:/Users/SebastienQUEROL/.claude/get-shit-done/workflows/execute-plan.md @C:/Users/SebastienQUEROL/.claude/get-shit-done/templates/summary.md </execution_context>
@.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @.planning/phases/07-dashboard-nav-polish/07-RESEARCH.mdFrom imptune/db/models.py:
class Client(BaseModel):
name = CharField(unique=True)
created_at = DateTimeField(default=datetime.utcnow)
class Driver(BaseModel):
sha256 = CharField(unique=True, index=True)
original_filename = CharField()
driver_desc = CharField(null=True)
uploaded_at = DateTimeField(default=datetime.utcnow)
class Printer(BaseModel):
name = CharField()
ip_address = CharField()
port_name = CharField()
client = ForeignKeyField(Client, null=True, backref="printers")
driver = ForeignKeyField(Driver, null=True, backref="printers")
created_at = DateTimeField(default=datetime.utcnow)
From imptune/api/pages.py (established pattern):
router = APIRouter()
templates = Jinja2Templates(directory=str(Path(__file__).parent.parent / "templates"))
# All routes use deferred imports inside function body
# All routes use: templates.TemplateResponse(request=request, name="...", context={...})
# All queries use: list(Model.select()...) — never Model.get()
From tests/conftest.py:
@pytest.fixture
def client(tmp_data_dir):
from imptune.main import app
with TestClient(app) as c:
yield c
For test_packages_returns_200: Simple GET /packages, assert status_code == 200.
For test_dashboard_shows_recent_printers:
- Import Client, Driver, Printer from imptune.db.models
- Create 2 Printer records with distinct names (e.g. "TestPrinter-Alpha", "TestPrinter-Beta") using Printer.create(name=..., ip_address="10.0.0.1", port_name="IP_10.0.0.1")
- GET /, assert both printer names appear in response.text
- Assert "No printers configured yet" NOT in response.text
For test_dashboard_shows_recent_packages:
- Create a Driver record: Driver.create(sha256="abc123", original_filename="test.zip", size_bytes=1000, driver_desc='["TestDriver"]')
- Create Printer with driver assigned: Printer.create(name="PkgPrinter-Assigned", ip_address="10.0.0.2", port_name="IP_10.0.0.2", driver=driver)
- Create Printer without driver: Printer.create(name="PkgPrinter-NoDriver", ip_address="10.0.0.3", port_name="IP_10.0.0.3")
- GET /, assert "PkgPrinter-Assigned" appears in response.text
- Assert "No packages exported yet" NOT in response.text
These tests will FAIL initially (RED) because /packages returns 404 and dashboard hardcodes empty lists. cd C:/Users/SebastienQUEROL/Documents/projets/ImpTune && pytest tests/test_static.py -x 2>&1 | tail -20 Three new test functions exist in test_static.py. test_packages_returns_200 fails with 404, dashboard tests fail because response contains "No printers configured yet" / "No packages exported yet".
Task 2: Add /packages route, fix dashboard queries, create packages.html template imptune/api/pages.py, imptune/templates/packages.html, imptune/templates/dashboard.html **imptune/api/pages.py** — Two changes:- Fix the
dashboardfunction (lines 16-25). Replace hardcoded empty lists with real queries using deferred imports inside the function body:
@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,
},
)
- Add a new
/packagesroute at the end of the file. Follow the exact same pattern asprinters_page— deferred imports, LEFT_OUTER joins, list() wrapper:
@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},
)
imptune/templates/packages.html — Create new file extending base.html. Show a table of printers that have drivers assigned, with columns: Printer Name (linked to /printers/{id}), Client, Driver, and download links for Intune (.intunewin) and NinjaRMM (ZIP). Use the existing download URL patterns: /printers/{id}/packages/intunewin and /printers/{id}/packages/ninja. Show an empty state message if no package-ready printers exist. Use Pico CSS table styling (no custom classes needed beyond what base.html provides).
imptune/templates/dashboard.html — Update the printer list items to be clickable links. Change:
<li>{{ printer.name }} — {{ printer.ip_address }}</li>to<li><a href="/printers/{{ printer.id }}">{{ printer.name }}</a> — {{ printer.ip_address }}</li>- For recent_packages section, change
<li>{{ package }}</li>to<li><a href="/printers/{{ package.id }}">{{ package.name }}</a>{% if package.client_id %} — {{ package.client.name }}{% endif %}</li>(the variable is a Printer object, not a string) - Also update the quick-action links: "New Printer" href to "/printers", "Upload Driver" href to "/drivers", "Export Package" href to "/packages" — remove aria-disabled="true" from all three. cd C:/Users/SebastienQUEROL/Documents/projets/ImpTune && pytest tests/ -x 2>&1 | tail -20 GET /packages returns 200 with a table of package-ready printers. Dashboard shows real recent printers and recent packages from the database. All tests in the full suite pass including the 3 new tests from Task 1.
<success_criteria>
- GET /packages returns 200 and renders a page listing printers with drivers assigned
- Dashboard recent_printers section shows real Printer records from the database
- Dashboard recent_packages section shows Printer records that have a driver assigned
- Full test suite (pytest tests/ -x) passes with zero failures
- No regressions in existing tests </success_criteria>