Files
transcription/docs/step5.md
T

8.3 KiB
Raw Blame History

Step 5: app.py + UI Pages (NiceGUI + FastAPI composition)

Objective

Implement the MVP user-facing application layer so users can:

  1. Upload a document from the UI
  2. Trigger Step 4 upload/job creation flow
  3. See live job lifecycle status (queued, processing, transcribed, failed)
  4. Open a job detail view to read transcript text or failure details

This step composes Steps 14 into a usable UI.


Architecture Summary (NiceGUI-aligned)

Step 5 uses a FastAPI app factory + lifespan orchestration and mounts/registers NiceGUI pages via explicit page modules.

Core architecture decisions

  • App factory: create_app()
  • Lifespan-managed resources: worker start/stop managed in startup/shutdown
  • Modular pages: upload and jobs pages in separate modules (no monolithic UI file)
  • Health endpoint: FastAPI-side /healthz
  • Dependency direction (one-way):
    • app -> config/logging/db/worker/ui/api
    • ui/pages -> services
    • services -> db/models/providers
    • no reverse imports from services into UI/API

DB and AI stance (explicit)

  • DB: already enabled (SQLModel + SQLite), session lifecycle remains request/service-scoped as built in prior steps.
  • AI workflow: already in place via Step 3 transcription service + Step 4 worker; UI does not call provider SDK directly.

Scope

In scope

  • src/transcription/app.py
  • src/transcription/ui/upload_page.py
  • src/transcription/ui/jobs_page.py
  • src/transcription/ui/__init__.py
  • src/transcription/api/health.py (or equivalent FastAPI health route module)
  • UI/app tests with MCP scaffold->fill flow

Out of scope

  • Auth
  • advanced filtering/search UX
  • batch upload UX beyond MVP
  • deployment/container hardening

Planned Deliverables

Source files

  • src/transcription/app.py (app factory + lifespan wiring)
  • src/transcription/api/health.py (GET /healthz)
  • src/transcription/ui/upload_page.py (upload flow)
  • src/transcription/ui/jobs_page.py (status list + detail)
  • src/transcription/ui/__init__.py (explicit register_pages(...) export)

Test files

  • tests/test_app.py
  • tests/api/test_health.py
  • tests/ui/test_pages_registration.py
  • tests/ui/test_upload_page.py
  • tests/ui/test_jobs_page.py

Implementation Plan + Checklist

Phase A — App factory and lifespan orchestration

  • Create create_app() in src/transcription/app.py
  • Add FastAPI lifespan startup/shutdown handlers
  • Startup responsibilities:
    • setup_logging()
    • create_all()
    • ensure directories exist (upload_dir, prompt_dir)
    • create worker stop event
    • start worker background thread/task
  • Shutdown responsibilities:
    • signal stop event
    • join/cleanup worker thread/task cleanly
  • Register API router(s), including health route
  • Register NiceGUI pages via explicit page registration function

Phase B — FastAPI health endpoint

  • Create src/transcription/api/health.py
  • Add GET /healthz returning simple healthy payload
  • Wire route into app factory

Phase C — Upload page (ui/upload_page.py)

  • Add upload route/page registration function
  • Render file input accepting supported extensions
  • On submit:
    • show loading/progress state
    • call create_upload_job(filename, file_bytes, ...)
    • show success state with job reference/link
  • On error:
    • show user-safe error message
    • restore ready UI state
  • Ensure no blocking calls in UI event handlers beyond bounded service interaction

Phase D — Jobs page (ui/jobs_page.py)

  • Add jobs list route/page registration function
  • Display jobs with status + timestamps
  • Add job detail route/view
  • Show transcript on success, error detail on failure
  • Include explicit refresh action and loading state
  • Ensure error states are surfaced to user and logged

Phase E — UI registration module

  • Update src/transcription/ui/__init__.py
  • Export register_pages(...)
  • Ensure each page module exports register_page(...)
  • Keep page registration explicit and modular

MCP Testing Workflow (Required)

Use these resources directly:

  • resource://catalog/prompts/pytest-scaffold
  • resource://prompts/pytest-scaffold/document
  • resource://catalog/prompts/pytest-fill-scaffold
  • resource://prompts/pytest-fill-scaffold/document

E1 — Scaffold tests first (structure only)

Target modules:

  • src/transcription/app.py
  • src/transcription/api/health.py
  • src/transcription/ui/upload_page.py
  • src/transcription/ui/jobs_page.py

Scaffold test files:

  • tests/test_app.py
  • tests/api/test_health.py
  • tests/ui/test_pages_registration.py
  • tests/ui/test_upload_page.py
  • tests/ui/test_jobs_page.py

Scaffold constraints:

  • class/method skeletons only
  • one-line docstrings
  • concise behavior-focused names
  • no implementation assertions yet

Validation:

  • uv run pytest --collect-only -q

E2 — Fill scaffold tests

Fill constraints from MCP guidance:

  • preserve scaffold class/method names and docstrings (locked baseline)
  • one behavior target per method
  • deterministic tests preferred
  • minimal mocking; only nondeterministic boundaries

Stack:

  • fastapi (or mixed if needed for UI+DB fixture combination)

Suggested coverage:

tests/api/test_health.py

  • /healthz returns success status and expected payload shape

tests/ui/test_pages_registration.py

  • page registration wiring succeeds
  • expected routes are present

tests/test_app.py

  • startup path initializes runtime dependencies
  • worker start is invoked on startup
  • worker shutdown signal/cleanup is invoked on shutdown

tests/ui/test_upload_page.py

  • upload action calls upload service
  • success feedback displayed
  • error feedback displayed for UploadError
  • loading/progress state behavior covered

tests/ui/test_jobs_page.py

  • list renders job statuses
  • detail shows transcript text for successful job
  • detail shows error detail for failed job
  • refresh/loading state behavior covered

Marker strategy:

  • unit for pure helpers/state formatting
  • integration for app/page/service+DB contracts
  • external not required for default Step 5 lane

Validation Sequence (strict)

  • uv run pytest --collect-only -q
  • uv run pytest -m unit -q (if unit tests touched)
  • uv run pytest tests/api/test_health.py -q
  • uv run pytest tests/ui/test_pages_registration.py -q
  • uv run pytest tests/test_app.py -q
  • uv run pytest tests/ui/test_upload_page.py -q
  • uv run pytest tests/ui/test_jobs_page.py -q
  • uv run pytest -q

Guardrails (NiceGUI + MVP)

  • Do not collapse pages into one file.
  • Do not use implicit global side effects for runtime wiring.
  • Keep UI responsive with explicit loading/progress/error states.
  • Do not place provider SDK calls in UI handlers.
  • Keep dependency direction one-way and maintainable.

Definition of Done

  • App factory + lifespan are in place
  • Health endpoint exists and is tested
  • Upload page creates queued jobs through service boundary
  • Jobs list/detail pages render status/transcript/failure data
  • Worker lifecycle is started/stopped by app lifespan
  • Scaffold->fill testing flow completed and validated
  • Full suite passes: uv run pytest -q

PR Checklist (Integrated)

Implementation

  • app.py app factory + lifespan implemented
  • FastAPI health route (/healthz) implemented
  • ui/upload_page.py implemented
  • ui/jobs_page.py implemented
  • ui/__init__.py explicit page registration implemented
  • Worker startup/shutdown managed by lifespan

Testing (MCP-compliant)

  • Scaffold phase completed first for all Step 5 tests
  • --collect-only passed on scaffolds
  • Fill phase completed without renaming/re-nesting scaffolded tests
  • Marker decisions documented (unit vs integration)
  • Targeted tests passed
  • Full suite passed

Evidence

  • Validation command outputs captured
  • Files created/updated listed
  • MCP prompt resources referenced in implementation notes
  • Any residual risks/questions documented