generated from john/python-template
This commit is contained in:
@@ -109,7 +109,7 @@ def render_documents_table(rows: Sequence[DocumentTableRow]) -> None:
|
||||
],
|
||||
default_sort_by="name",
|
||||
search_placeholder="Search documents by title, type, or author...",
|
||||
on_row_click_id=lambda doc_id: ui.navigate.to(f"/documents/{doc_id}"),
|
||||
on_row_click_id=lambda doc_id: ui.navigate.to(f"/documents/{doc_id}?from=documents"),
|
||||
)
|
||||
|
||||
# Render document type using a subtle Quasar badge
|
||||
|
||||
@@ -57,13 +57,18 @@ def _serialize_rows(rows: Sequence[JobTableRow]) -> list[dict[str, Any]]:
|
||||
]
|
||||
|
||||
|
||||
def render_jobs_table(rows: Sequence[JobTableRow]) -> None:
|
||||
def render_jobs_table(rows: Sequence[JobTableRow], *, document_context_id: str | None = None) -> None:
|
||||
"""Render jobs table with search filtering and custom status chips."""
|
||||
if not rows:
|
||||
with archival_card(extra_classes="p-8 text-center"):
|
||||
render_empty_state("No job records found in repository.")
|
||||
return
|
||||
|
||||
def detail_target(job_id: str) -> str:
|
||||
if document_context_id is not None:
|
||||
return f"/jobs/{job_id}?from=document&document_id={document_context_id}"
|
||||
return f"/jobs/{job_id}?from=jobs"
|
||||
|
||||
table = build_table(
|
||||
rows=_serialize_rows(rows),
|
||||
columns=[
|
||||
@@ -117,7 +122,7 @@ def render_jobs_table(rows: Sequence[JobTableRow]) -> None:
|
||||
default_sort_by="updated_sort",
|
||||
default_descending=True,
|
||||
search_placeholder="Search jobs by ID, document, or status...",
|
||||
on_row_click_id=lambda job_id: ui.navigate.to(f"/jobs/{job_id}"),
|
||||
on_row_click_id=lambda job_id: ui.navigate.to(detail_target(job_id)),
|
||||
)
|
||||
|
||||
# Render job execution status using themed Quasar chips
|
||||
|
||||
@@ -94,7 +94,7 @@ def render_people_table(rows: Sequence[PersonTableRow]) -> None:
|
||||
],
|
||||
default_sort_by="name",
|
||||
search_placeholder="Search people by name, tags, FamilySearch ID, or dates...",
|
||||
on_row_click_id=lambda person_id: ui.navigate.to(f"/people/{person_id}"),
|
||||
on_row_click_id=lambda person_id: ui.navigate.to(f"/people/{person_id}?from=people"),
|
||||
)
|
||||
|
||||
# Custom column template adding an archival entity icon next to person's name
|
||||
|
||||
@@ -209,6 +209,19 @@ def register_page() -> None: # noqa: PLR0915
|
||||
document_service = DocumentService(session_factory=session_factory)
|
||||
render_navigation_header(current_path="/documents")
|
||||
settings = resolve_runtime_settings(request)
|
||||
back_label = "Back to Documents"
|
||||
back_target = "/documents"
|
||||
from_context = request.query_params.get("from")
|
||||
if from_context == "person":
|
||||
person_id = parse_uuid(request.query_params.get("person_id"))
|
||||
if person_id is not None:
|
||||
back_label = "Back to Person"
|
||||
back_target = f"/people/{person_id}"
|
||||
elif from_context == "job":
|
||||
job_id = parse_uuid(request.query_params.get("job_id"))
|
||||
if job_id is not None:
|
||||
back_label = "Back to Job"
|
||||
back_target = f"/jobs/{job_id}"
|
||||
|
||||
parsed_doc_id = parsed_record_id(document_id, noun="Document")
|
||||
if parsed_doc_id is None:
|
||||
@@ -229,6 +242,7 @@ def register_page() -> None: # noqa: PLR0915
|
||||
page_header(document.name, subtitle=f"Type: {type_display} | ID: {document.id}")
|
||||
|
||||
with ui.row().classes("items-center gap-2"):
|
||||
ui.button(back_label, on_click=lambda: ui.navigate.to(back_target), icon="arrow_back").props("flat")
|
||||
ui.button(
|
||||
"Print",
|
||||
on_click=lambda: ui.navigate.to(f"/documents/{document.id}/print"),
|
||||
@@ -584,7 +598,9 @@ def _render_related_people_card(document: Document) -> None:
|
||||
for person in grouped[role_label]:
|
||||
ui.button(
|
||||
person.full_name,
|
||||
on_click=lambda _=None, person_id=person.id: ui.navigate.to(f"/people/{person_id}"),
|
||||
on_click=lambda _=None, person_id=person.id: ui.navigate.to(
|
||||
f"/people/{person_id}?from=document&document_id={document.id}"
|
||||
),
|
||||
icon="person",
|
||||
).props("flat dense no-caps").classes("self-start text-xs font-semibold ui-link-primary")
|
||||
|
||||
|
||||
@@ -68,6 +68,12 @@ def register_page() -> None: # noqa: PLR0915
|
||||
"ui-btn-primary"
|
||||
)
|
||||
ui.button("Refresh", on_click=lambda: render_table.refresh(), icon="refresh").props("flat")
|
||||
elif parsed_document_id is not None:
|
||||
ui.button(
|
||||
"Back to Document",
|
||||
on_click=lambda: ui.navigate.to(f"/documents/{parsed_document_id}"),
|
||||
icon="arrow_back",
|
||||
).props("flat")
|
||||
|
||||
@ui.refreshable
|
||||
async def render_table() -> None:
|
||||
@@ -86,7 +92,7 @@ def register_page() -> None: # noqa: PLR0915
|
||||
)
|
||||
for job in jobs
|
||||
]
|
||||
render_jobs_table(rows)
|
||||
render_jobs_table(rows, document_context_id=str(parsed_document_id) if parsed_document_id else None)
|
||||
|
||||
await render_table()
|
||||
|
||||
@@ -241,9 +247,17 @@ def register_page() -> None: # noqa: PLR0915
|
||||
ui.button("Back to Jobs", on_click=lambda: ui.navigate.to("/jobs"), icon="arrow_back").props("flat")
|
||||
|
||||
@ui.page("/jobs/{job_id}")
|
||||
async def job_detail_page(job_id: str, session_factory: SessionFactoryDep) -> None:
|
||||
async def job_detail_page(job_id: str, request: Request, session_factory: SessionFactoryDep) -> None:
|
||||
jobs_service = JobService(session_factory=session_factory)
|
||||
render_navigation_header(current_path="/jobs")
|
||||
back_label = "Back to Jobs"
|
||||
back_target = "/jobs"
|
||||
from_context = request.query_params.get("from")
|
||||
if from_context == "document":
|
||||
document_id = parse_uuid(request.query_params.get("document_id"))
|
||||
if document_id is not None:
|
||||
back_label = "Back to Document"
|
||||
back_target = f"/documents/{document_id}"
|
||||
|
||||
parsed_job_id = parsed_record_id(job_id, noun="Job")
|
||||
if parsed_job_id is None:
|
||||
@@ -262,7 +276,7 @@ def register_page() -> None: # noqa: PLR0915
|
||||
@ui.refreshable
|
||||
def render_detail() -> None:
|
||||
active_job = current_job[0]
|
||||
_render_job_detail_header(active_job)
|
||||
_render_job_detail_header(active_job, back_label=back_label, back_target=back_target)
|
||||
with ui.grid().classes("w-full grid-cols-1 md:grid-cols-2 gap-4"):
|
||||
_render_job_logistics(active_job)
|
||||
_render_job_document_links(active_job)
|
||||
@@ -540,10 +554,11 @@ def _render_upload_section(uploaded_files: list[tuple[str, bytes]]) -> None:
|
||||
render_upload_list()
|
||||
|
||||
|
||||
def _render_job_detail_header(job: Job) -> None:
|
||||
def _render_job_detail_header(job: Job, *, back_label: str, back_target: str) -> None:
|
||||
with section_header_row(classes="justify-between items-center"):
|
||||
page_header(f"Job Record: {job.id}")
|
||||
with ui.row().classes("items-center gap-2"):
|
||||
ui.button(back_label, on_click=lambda: ui.navigate.to(back_target), icon="arrow_back").props("flat")
|
||||
archival_badge(job.status.value.upper())
|
||||
|
||||
if job.status in {JobStatus.QUEUED, JobStatus.PROCESSING}:
|
||||
@@ -584,7 +599,7 @@ def _render_job_document_links(job: Job) -> None:
|
||||
ui.label("Document Name:").classes("text-xs font-semibold ui-text-primary")
|
||||
ui.button(
|
||||
document_name,
|
||||
on_click=lambda: ui.navigate.to(f"/documents/{job.document_id}"),
|
||||
on_click=lambda: ui.navigate.to(f"/documents/{job.document_id}?from=job&job_id={job.id}"),
|
||||
icon="description",
|
||||
).props("flat dense no-caps").classes("ui-link-primary text-xs")
|
||||
|
||||
@@ -592,7 +607,7 @@ def _render_job_document_links(job: Job) -> None:
|
||||
with ui.row().classes("w-full gap-2 mt-2"):
|
||||
ui.button(
|
||||
"View Sources",
|
||||
on_click=lambda: ui.navigate.to(f"/sources?document_id={job.document_id}"),
|
||||
on_click=lambda: ui.navigate.to(f"/sources?job_id={job.id}"),
|
||||
icon="description",
|
||||
).props("flat dense text-xs").classes("ui-link-primary")
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ from transcription.ui.components.formatters import compact_date
|
||||
from transcription.ui.components.formatters import family_search_url
|
||||
from transcription.ui.components.formatters import google_maps_search_url
|
||||
from transcription.ui.components.formatters import parse_iso_date
|
||||
from transcription.ui.components.formatters import parse_uuid
|
||||
from transcription.ui.components.guards import parsed_record_id
|
||||
from transcription.ui.components.guards import render_record_not_found
|
||||
from transcription.ui.components.media_urls import resolve_media_url
|
||||
@@ -178,6 +179,14 @@ def register_page() -> None: # noqa: PLR0915
|
||||
people_service = PeopleService(session_factory=session_factory)
|
||||
photos_service = PhotosService(session_factory=session_factory)
|
||||
render_navigation_header(current_path="/people")
|
||||
back_label = "Back to People"
|
||||
back_target = "/people"
|
||||
from_context = request.query_params.get("from")
|
||||
if from_context == "document":
|
||||
document_id = parse_uuid(request.query_params.get("document_id"))
|
||||
if document_id is not None:
|
||||
back_label = "Back to Document"
|
||||
back_target = f"/documents/{document_id}"
|
||||
|
||||
parsed_person_id = parsed_record_id(person_id, noun="Person")
|
||||
if parsed_person_id is None:
|
||||
@@ -197,6 +206,7 @@ def register_page() -> None: # noqa: PLR0915
|
||||
page_header(person.full_name, subtitle=f"Person ID: {person.id}")
|
||||
|
||||
with ui.row().classes("items-center gap-2"):
|
||||
ui.button(back_label, on_click=lambda: ui.navigate.to(back_target), icon="arrow_back").props("flat")
|
||||
ui.button(
|
||||
"New Document",
|
||||
on_click=lambda: ui.navigate.to(f"/documents/new?person_id={person.id}"),
|
||||
@@ -812,7 +822,7 @@ def _render_linked_documents(person: Person) -> None:
|
||||
},
|
||||
],
|
||||
default_sort_by="document_name",
|
||||
on_row_click_id=lambda doc_id: ui.navigate.to(f"/documents/{doc_id}"),
|
||||
on_row_click_id=lambda doc_id: ui.navigate.to(f"/documents/{doc_id}?from=person&person_id={person.id}"),
|
||||
show_search=False,
|
||||
)
|
||||
table.add_slot(
|
||||
|
||||
Reference in New Issue
Block a user