generated from john/python-template
V4.7 Phase 2: Evidence Model Simplification
This commit is contained in:
@@ -1,131 +0,0 @@
|
|||||||
"""Reusable transcript UI components."""
|
|
||||||
|
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
from collections.abc import Awaitable
|
|
||||||
from collections.abc import Callable
|
|
||||||
from datetime import datetime
|
|
||||||
from typing import Any
|
|
||||||
|
|
||||||
from nicegui import ui
|
|
||||||
|
|
||||||
from transcription.db.models import Job
|
|
||||||
from transcription.db.models import Source
|
|
||||||
|
|
||||||
type RevisionAction = Callable[[Source], Awaitable[None] | None]
|
|
||||||
|
|
||||||
|
|
||||||
def render_original_transcription_card(*, job: Job, classes: str = "w-full") -> Any:
|
|
||||||
"""Render the immutable original job transcription output."""
|
|
||||||
latest_error_detail = _latest_job_error_detail(job)
|
|
||||||
status_label = "Failed" if latest_error_detail else "Transcribed"
|
|
||||||
header = f"Original Transcription | {status_label}"
|
|
||||||
provider = job.provider or "unknown"
|
|
||||||
model = job.model or "unknown"
|
|
||||||
caption = f"{provider} | {model} | {_format_created_at(job.date_updated)}"
|
|
||||||
|
|
||||||
card = ui.card().classes(f"{classes} q-pa-md ui-card-surface")
|
|
||||||
with card, ui.column().classes("w-full q-gutter-y-sm"):
|
|
||||||
ui.label(header).classes("text-subtitle1 text-weight-medium")
|
|
||||||
ui.label(caption).classes("text-caption ui-text-muted")
|
|
||||||
_metadata_row(label="Prompt", value=_latest_job_prompt(job) or "unknown")
|
|
||||||
_metadata_row(label="Updated", value=_format_created_at(job.date_updated))
|
|
||||||
|
|
||||||
latest_transcription = _latest_job_transcription(job)
|
|
||||||
|
|
||||||
if latest_transcription:
|
|
||||||
with ui.card().classes("w-full q-pa-sm ui-card-surface"):
|
|
||||||
ui.markdown(latest_transcription)
|
|
||||||
|
|
||||||
if latest_error_detail:
|
|
||||||
with ui.card().classes("w-full ui-card-error q-pa-sm"):
|
|
||||||
ui.label("Failure detail").classes("text-caption text-uppercase")
|
|
||||||
ui.label(latest_error_detail).classes("text-body2")
|
|
||||||
|
|
||||||
return card
|
|
||||||
|
|
||||||
|
|
||||||
def render_revision_row(
|
|
||||||
*,
|
|
||||||
revision: Source | None,
|
|
||||||
initially_expanded: bool = False,
|
|
||||||
classes: str = "w-full",
|
|
||||||
on_delete: RevisionAction | None = None,
|
|
||||||
) -> Any:
|
|
||||||
"""Render a collapsible row for the single optional source revision."""
|
|
||||||
if revision is None:
|
|
||||||
return None
|
|
||||||
|
|
||||||
header = "Source revision | User-authored"
|
|
||||||
caption = _format_created_at(revision.date_revised or revision.date_uploaded)
|
|
||||||
|
|
||||||
expansion = ui.expansion(value=initially_expanded, group="group").classes(f"{classes} ui-card-surface")
|
|
||||||
|
|
||||||
with expansion, ui.column().classes("w-full q-gutter-y-sm q-pa-sm"):
|
|
||||||
with expansion.add_slot("header"), ui.row().classes("w-full items-start justify-between q-gutter-md"):
|
|
||||||
with ui.column().classes("q-gutter-none"):
|
|
||||||
ui.label(header).classes("text-subtitle1 text-weight-medium")
|
|
||||||
ui.label(caption).classes("text-caption ui-text-muted")
|
|
||||||
|
|
||||||
if on_delete is not None:
|
|
||||||
with ui.dialog() as delete_dialog, ui.card().classes("q-pa-md ui-card-surface"):
|
|
||||||
ui.label("Delete this source revision?").classes("text-body1")
|
|
||||||
with ui.row().classes("w-full justify-end q-gutter-sm"):
|
|
||||||
ui.button("Cancel", on_click=lambda: delete_dialog.submit(False)).props("flat")
|
|
||||||
ui.button("Delete", on_click=lambda: delete_dialog.submit(True)).props(
|
|
||||||
'unelevated color="negative"'
|
|
||||||
)
|
|
||||||
|
|
||||||
async def delete_current_transcript() -> None:
|
|
||||||
delete_dialog.open()
|
|
||||||
confirmed = await delete_dialog
|
|
||||||
if not confirmed:
|
|
||||||
return
|
|
||||||
|
|
||||||
maybe_awaitable = on_delete(revision)
|
|
||||||
if isinstance(maybe_awaitable, Awaitable):
|
|
||||||
await maybe_awaitable
|
|
||||||
|
|
||||||
with ui.column(align_items="center").classes("self-center q-gutter-none"):
|
|
||||||
ui.button(icon="delete", on_click=delete_current_transcript).props(
|
|
||||||
'flat round dense color="negative"'
|
|
||||||
)
|
|
||||||
_metadata_row(label="Created", value=_format_created_at(revision.date_revised or revision.date_uploaded))
|
|
||||||
|
|
||||||
if revision.revised_text:
|
|
||||||
with ui.card().classes("w-full q-pa-sm ui-card-surface"):
|
|
||||||
ui.markdown(revision.revised_text)
|
|
||||||
|
|
||||||
return expansion
|
|
||||||
|
|
||||||
|
|
||||||
def _latest_job_transcription(job: Job) -> str | None:
|
|
||||||
for job_source in sorted(job.job_sources, key=lambda item: item.executed_at, reverse=True):
|
|
||||||
if job_source.raw_transcription:
|
|
||||||
return job_source.raw_transcription
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def _latest_job_error_detail(job: Job) -> str | None:
|
|
||||||
for job_source in sorted(job.job_sources, key=lambda item: item.executed_at, reverse=True):
|
|
||||||
if job_source.error_detail:
|
|
||||||
return job_source.error_detail
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def _latest_job_prompt(job: Job) -> str | None:
|
|
||||||
for job_source in sorted(job.job_sources, key=lambda item: item.executed_at, reverse=True):
|
|
||||||
if job_source.job and job_source.job.prompt_name:
|
|
||||||
return job_source.job.prompt_name
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def _format_created_at(value: datetime) -> str:
|
|
||||||
"""Return a compact UTC-like timestamp for row captions."""
|
|
||||||
return value.strftime("%Y-%m-%d %H:%M:%S %Z")
|
|
||||||
|
|
||||||
|
|
||||||
def _metadata_row(*, label: str, value: str) -> None:
|
|
||||||
with ui.row().classes("w-md items-start justify-between q-gutter-x-md"):
|
|
||||||
ui.label(label).classes("text-caption ui-text-muted text-uppercase")
|
|
||||||
ui.label(value).classes("text-body2 text-right break-all")
|
|
||||||
Reference in New Issue
Block a user