generated from john/python-template
delete button on transcript header
This commit is contained in:
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from collections.abc import Awaitable
|
||||||
|
from collections.abc import Callable
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
@@ -9,12 +11,15 @@ from nicegui import ui
|
|||||||
|
|
||||||
from transcription.models import Transcript
|
from transcription.models import Transcript
|
||||||
|
|
||||||
|
type TranscriptAction = Callable[[Transcript], Awaitable[None] | None]
|
||||||
|
|
||||||
|
|
||||||
def render_transcript_revision_row(
|
def render_transcript_revision_row(
|
||||||
*,
|
*,
|
||||||
transcript: Transcript,
|
transcript: Transcript,
|
||||||
initially_expanded: bool = False,
|
initially_expanded: bool = False,
|
||||||
classes: str = "w-full",
|
classes: str = "w-full",
|
||||||
|
on_delete: TranscriptAction | None = None,
|
||||||
) -> Any:
|
) -> Any:
|
||||||
"""Render one collapsible row for a single transcript revision."""
|
"""Render one collapsible row for a single transcript revision."""
|
||||||
status_label = "Failed" if transcript.error_detail else "Transcribed"
|
status_label = "Failed" if transcript.error_detail else "Transcribed"
|
||||||
@@ -26,9 +31,34 @@ def render_transcript_revision_row(
|
|||||||
)
|
)
|
||||||
|
|
||||||
with expansion, ui.column().classes("w-full q-gutter-y-sm q-pa-sm"):
|
with expansion, ui.column().classes("w-full q-gutter-y-sm q-pa-sm"):
|
||||||
with expansion.add_slot("header"), ui.column().classes("w-full"):
|
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(header).classes("text-subtitle1 text-weight-medium")
|
||||||
ui.label(caption).classes("text-caption text-grey-5")
|
ui.label(caption).classes("text-caption text-grey-5")
|
||||||
|
|
||||||
|
if on_delete is not None:
|
||||||
|
with ui.dialog() as delete_dialog, ui.card().classes("q-pa-md"):
|
||||||
|
ui.label("Delete this transcript 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(transcript)
|
||||||
|
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="Provider", value=transcript.provider)
|
_metadata_row(label="Provider", value=transcript.provider)
|
||||||
_metadata_row(label="Model", value=transcript.model)
|
_metadata_row(label="Model", value=transcript.model)
|
||||||
_metadata_row(label="Created", value=_format_created_at(transcript.created_at))
|
_metadata_row(label="Created", value=_format_created_at(transcript.created_at))
|
||||||
|
|||||||
@@ -10,7 +10,9 @@ from nicegui import ui
|
|||||||
from transcription.app_state import resolve_session_factory
|
from transcription.app_state import resolve_session_factory
|
||||||
from transcription.models import JobStatus
|
from transcription.models import JobStatus
|
||||||
from transcription.services.jobs import JobService
|
from transcription.services.jobs import JobService
|
||||||
|
from transcription.services.transcription import TranscriptionService
|
||||||
from transcription.ui.components.app_shell import render_navigation_header
|
from transcription.ui.components.app_shell import render_navigation_header
|
||||||
|
from transcription.ui.components.error_presenter import show_error
|
||||||
from transcription.ui.components.table.jobs import render_jobs_table
|
from transcription.ui.components.table.jobs import render_jobs_table
|
||||||
|
|
||||||
from ..components.document_panzoom import render_document_panzoom
|
from ..components.document_panzoom import render_document_panzoom
|
||||||
@@ -49,6 +51,7 @@ def register_page() -> None:
|
|||||||
async def job_detail_page(job_id: str, request: Request) -> None:
|
async def job_detail_page(job_id: str, request: Request) -> None:
|
||||||
session_factory = resolve_session_factory(request.app.state)
|
session_factory = resolve_session_factory(request.app.state)
|
||||||
jobs_service = JobService(session_factory=session_factory)
|
jobs_service = JobService(session_factory=session_factory)
|
||||||
|
transcription_service = TranscriptionService(session_factory=session_factory)
|
||||||
render_navigation_header(current_path="/jobs")
|
render_navigation_header(current_path="/jobs")
|
||||||
|
|
||||||
job = await jobs_service.read_job(job_id=UUID(job_id))
|
job = await jobs_service.read_job(job_id=UUID(job_id))
|
||||||
@@ -66,5 +69,31 @@ def register_page() -> None:
|
|||||||
ui.chip(job.status.value.upper(), color="green", text_color="white").props("outline")
|
ui.chip(job.status.value.upper(), color="green", text_color="white").props("outline")
|
||||||
case _:
|
case _:
|
||||||
ui.label(f"{job.status.value}").classes("text-subtitle1 text-weight-medium")
|
ui.label(f"{job.status.value}").classes("text-subtitle1 text-weight-medium")
|
||||||
for i, transcript in enumerate(job.transcripts):
|
|
||||||
render_transcript_revision_row(transcript=transcript, initially_expanded=(i == 0))
|
async def delete_transcript_by_id(transcript_id: UUID, revision: int) -> None:
|
||||||
|
try:
|
||||||
|
transcript = await transcription_service.read_transcript(transcript_id=transcript_id)
|
||||||
|
await transcription_service.delete_transcript(transcript)
|
||||||
|
except Exception as exc: # noqa: BLE001
|
||||||
|
show_error(exc, title="Delete failed", operation="jobs.delete_transcript")
|
||||||
|
return
|
||||||
|
|
||||||
|
ui.notify(f"Deleted revision {revision}", type="positive")
|
||||||
|
await render_transcript_list.refresh()
|
||||||
|
|
||||||
|
@ui.refreshable
|
||||||
|
async def render_transcript_list() -> None:
|
||||||
|
refreshed_job = await jobs_service.read_job(job_id=UUID(job_id))
|
||||||
|
for i, transcript in enumerate(refreshed_job.transcripts):
|
||||||
|
render_transcript_revision_row(
|
||||||
|
transcript=transcript,
|
||||||
|
initially_expanded=(i == 0),
|
||||||
|
on_delete=(
|
||||||
|
lambda _transcript, tid=transcript.id, rev=transcript.revision: delete_transcript_by_id(
|
||||||
|
tid,
|
||||||
|
rev,
|
||||||
|
)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
await render_transcript_list()
|
||||||
|
|||||||
Reference in New Issue
Block a user