feat: reorder project route registration to prioritize static UI paths and add pytest coverage for navigation endpoints
This commit is contained in:
@@ -13,3 +13,4 @@
|
|||||||
- Delivered a new dashboard experience with `templates/dashboard.html`, dedicated styling, and a FastAPI route supplying real project/scenario metrics via repository helpers.
|
- Delivered a new dashboard experience with `templates/dashboard.html`, dedicated styling, and a FastAPI route supplying real project/scenario metrics via repository helpers.
|
||||||
- Extended repositories with count/recency utilities and added pytest coverage, including a dashboard rendering smoke test validating empty-state messaging.
|
- Extended repositories with count/recency utilities and added pytest coverage, including a dashboard rendering smoke test validating empty-state messaging.
|
||||||
- Brought project and scenario detail pages plus their forms in line with the dashboard visuals, adding metric cards, layout grids, and refreshed CTA styles.
|
- Brought project and scenario detail pages plus their forms in line with the dashboard visuals, adding metric cards, layout grids, and refreshed CTA styles.
|
||||||
|
- Reordered project route registration to prioritize static UI paths, eliminating 422 errors on `/projects/ui` and `/projects/create`, and added pytest smoke coverage for the navigation endpoints.
|
||||||
|
|||||||
@@ -46,45 +46,6 @@ def create_project(
|
|||||||
return _to_read_model(created)
|
return _to_read_model(created)
|
||||||
|
|
||||||
|
|
||||||
@router.get("/{project_id}", response_model=ProjectRead)
|
|
||||||
def get_project(project_id: int, uow: UnitOfWork = Depends(get_unit_of_work)) -> ProjectRead:
|
|
||||||
try:
|
|
||||||
project = uow.projects.get(project_id)
|
|
||||||
except EntityNotFoundError as exc:
|
|
||||||
raise HTTPException(
|
|
||||||
status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)) from exc
|
|
||||||
return _to_read_model(project)
|
|
||||||
|
|
||||||
|
|
||||||
@router.put("/{project_id}", response_model=ProjectRead)
|
|
||||||
def update_project(
|
|
||||||
project_id: int,
|
|
||||||
payload: ProjectUpdate,
|
|
||||||
uow: UnitOfWork = Depends(get_unit_of_work),
|
|
||||||
) -> ProjectRead:
|
|
||||||
try:
|
|
||||||
project = uow.projects.get(project_id)
|
|
||||||
except EntityNotFoundError as exc:
|
|
||||||
raise HTTPException(
|
|
||||||
status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)) from exc
|
|
||||||
|
|
||||||
update_data = payload.model_dump(exclude_unset=True)
|
|
||||||
for field, value in update_data.items():
|
|
||||||
setattr(project, field, value)
|
|
||||||
|
|
||||||
uow.flush()
|
|
||||||
return _to_read_model(project)
|
|
||||||
|
|
||||||
|
|
||||||
@router.delete("/{project_id}", status_code=status.HTTP_204_NO_CONTENT)
|
|
||||||
def delete_project(project_id: int, uow: UnitOfWork = Depends(get_unit_of_work)) -> None:
|
|
||||||
try:
|
|
||||||
uow.projects.delete(project_id)
|
|
||||||
except EntityNotFoundError as exc:
|
|
||||||
raise HTTPException(
|
|
||||||
status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)) from exc
|
|
||||||
|
|
||||||
|
|
||||||
@router.get(
|
@router.get(
|
||||||
"/ui",
|
"/ui",
|
||||||
response_class=HTMLResponse,
|
response_class=HTMLResponse,
|
||||||
@@ -188,6 +149,48 @@ def create_project_submit(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/{project_id}", response_model=ProjectRead)
|
||||||
|
def get_project(project_id: int, uow: UnitOfWork = Depends(get_unit_of_work)) -> ProjectRead:
|
||||||
|
try:
|
||||||
|
project = uow.projects.get(project_id)
|
||||||
|
except EntityNotFoundError as exc:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)
|
||||||
|
) from exc
|
||||||
|
return _to_read_model(project)
|
||||||
|
|
||||||
|
|
||||||
|
@router.put("/{project_id}", response_model=ProjectRead)
|
||||||
|
def update_project(
|
||||||
|
project_id: int,
|
||||||
|
payload: ProjectUpdate,
|
||||||
|
uow: UnitOfWork = Depends(get_unit_of_work),
|
||||||
|
) -> ProjectRead:
|
||||||
|
try:
|
||||||
|
project = uow.projects.get(project_id)
|
||||||
|
except EntityNotFoundError as exc:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)
|
||||||
|
) from exc
|
||||||
|
|
||||||
|
update_data = payload.model_dump(exclude_unset=True)
|
||||||
|
for field, value in update_data.items():
|
||||||
|
setattr(project, field, value)
|
||||||
|
|
||||||
|
uow.flush()
|
||||||
|
return _to_read_model(project)
|
||||||
|
|
||||||
|
|
||||||
|
@router.delete("/{project_id}", status_code=status.HTTP_204_NO_CONTENT)
|
||||||
|
def delete_project(project_id: int, uow: UnitOfWork = Depends(get_unit_of_work)) -> None:
|
||||||
|
try:
|
||||||
|
uow.projects.delete(project_id)
|
||||||
|
except EntityNotFoundError as exc:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)
|
||||||
|
) from exc
|
||||||
|
|
||||||
|
|
||||||
@router.get(
|
@router.get(
|
||||||
"/{project_id}/view",
|
"/{project_id}/view",
|
||||||
response_class=HTMLResponse,
|
response_class=HTMLResponse,
|
||||||
|
|||||||
@@ -71,3 +71,15 @@ class TestDashboardRoute:
|
|||||||
assert "No simulation runs yet" in html
|
assert "No simulation runs yet" in html
|
||||||
assert "All scenarios look good" in html
|
assert "All scenarios look good" in html
|
||||||
assert "—" in html # Last data import placeholder
|
assert "—" in html # Last data import placeholder
|
||||||
|
|
||||||
|
|
||||||
|
class TestProjectUIRoutes:
|
||||||
|
def test_projects_ui_page_resolves(self, client: TestClient) -> None:
|
||||||
|
response = client.get("/projects/ui")
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert "Projects" in response.text
|
||||||
|
|
||||||
|
def test_projects_create_form_resolves(self, client: TestClient) -> None:
|
||||||
|
response = client.get("/projects/create")
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert "Create Project" in response.text
|
||||||
|
|||||||
Reference in New Issue
Block a user