From e2e421835f9f60a99f71d969c3070957db287d2c Mon Sep 17 00:00:00 2001 From: John Lancaster <32917998+jsl12@users.noreply.github.com> Date: Sun, 28 Jun 2026 14:40:58 -0500 Subject: [PATCH] job_detail --- src/transcription/ui/components/job_detail.py | 91 ++++++++++++++++--- 1 file changed, 76 insertions(+), 15 deletions(-) diff --git a/src/transcription/ui/components/job_detail.py b/src/transcription/ui/components/job_detail.py index 3f1ea56..d93d503 100644 --- a/src/transcription/ui/components/job_detail.py +++ b/src/transcription/ui/components/job_detail.py @@ -9,22 +9,83 @@ from transcription.models import Job from transcription.models import Transcript +def _status_chip_classes(status: str) -> str: + if status == "queued": + return "bg-blue-1 text-blue-10" + if status == "processing": + return "bg-amber-1 text-amber-10" + if status == "transcribed": + return "bg-green-1 text-green-10" + if status == "failed": + return "bg-red-1 text-red-10" + return "bg-grey-2 text-grey-9" + + +def _metadata_row(label: str, value: str) -> None: + with ui.row().classes("w-full items-start justify-between no-wrap q-gutter-x-md"): + ui.label(label).classes("text-caption text-grey-7 text-uppercase") + ui.label(value).classes("text-body2 text-right") + + +def _render_document_section(document: Document) -> None: + with ui.card().classes("w-full bg-grey-1 q-pa-md"): + ui.label("Document").classes("text-subtitle1 text-weight-medium") + ui.separator().classes("q-my-sm") + with ui.column().classes("w-full q-gutter-y-xs"): + _metadata_row("Filename", document.filename) + _metadata_row("File path", document.file_path) + + +def _render_transcript_section(transcript: Transcript | None) -> None: + with ui.card().classes("w-full q-pa-md"): + ui.label("Transcript").classes("text-subtitle1 text-weight-medium") + ui.separator().classes("q-my-sm") + + if transcript is None: + ui.label("Transcript not available yet.").classes("text-body2 text-grey-8") + return + + with ui.column().classes("w-full q-gutter-y-xs"): + _metadata_row("Provider", transcript.provider) + _metadata_row("Prompt", transcript.prompt_name) + _metadata_row("Created", transcript.created_at.isoformat()) + + if transcript.text: + ui.separator().classes("q-my-sm") + with ui.card().classes("w-full bg-grey-1 q-pa-sm"): + ui.markdown(transcript.text) + return + + if transcript.error_detail: + ui.separator().classes("q-my-sm") + with ui.card().classes("w-full bg-red-1 text-red-10 q-pa-sm"): + ui.label("Failure detail").classes("text-caption text-uppercase") + ui.label(transcript.error_detail).classes("text-body2") + + def render_job_detail(*, job: Job, document: Document | None, transcript: Transcript | None) -> None: """Render all sections for the job detail page.""" - ui.label(f"Job ID: {job.id}") - ui.label(f"Status: {job.status.value}") - ui.label(f"Created: {job.created_at.isoformat()}") - ui.label(f"Updated: {job.updated_at.isoformat()}") + status_text = job.status.value + with ui.column().classes("w-full max-w-4xl q-gutter-md"): + with ui.card().classes("w-full q-pa-lg"): + with ui.row().classes("w-full items-center justify-between q-gutter-md"): + with ui.column().classes("q-gutter-none"): + ui.label("Job overview").classes("text-h6 text-weight-bold") + ui.label(str(job.id)).classes("text-caption text-grey-7") + status_chip_classes = ( + "q-px-sm q-py-xs rounded-borders " + "text-weight-medium text-capitalize " + f"{_status_chip_classes(status_text)}" + ) + ui.label(status_text).classes(status_chip_classes) - if document is not None: - ui.label(f"Filename: {document.filename}") - ui.label(f"File path: {document.file_path}") + ui.separator().classes("q-my-md") + with ui.column().classes("w-full q-gutter-y-xs"): + _metadata_row("Created", job.created_at.isoformat()) + _metadata_row("Updated", job.updated_at.isoformat()) + _metadata_row("Retries", str(job.retry_count)) - if transcript is None: - ui.label("Transcript not available yet.") - elif transcript.text: - ui.label("Transcript:") - ui.markdown(transcript.text) - elif transcript.error_detail: - ui.label("Failure detail:") - ui.label(transcript.error_detail) + if document is not None: + _render_document_section(document) + + _render_transcript_section(transcript)