generated from john/python-template
started app shell
This commit is contained in:
@@ -0,0 +1 @@
|
|||||||
|
"""Reusable UI component exports."""
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
"""Reusable app shell primitives for page-level layout."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from nicegui import ui
|
||||||
|
|
||||||
|
|
||||||
|
def _nav_link_classes(*, is_active: bool) -> str:
|
||||||
|
base = "q-px-sm q-py-xs rounded-borders text-body2"
|
||||||
|
if is_active:
|
||||||
|
return f"{base} bg-primary text-white text-weight-medium"
|
||||||
|
return f"{base} text-primary"
|
||||||
|
|
||||||
|
|
||||||
|
def render_navigation_header(*, title: str, current_path: str | None = None) -> None:
|
||||||
|
"""Render a shared app header with links for top-level pages."""
|
||||||
|
normalized_path = (current_path or "").rstrip("/")
|
||||||
|
|
||||||
|
with (
|
||||||
|
ui.header(elevated=True).classes("bg-white text-dark q-px-md q-py-sm"),
|
||||||
|
ui.row().classes("w-full items-center justify-between q-gutter-sm"),
|
||||||
|
):
|
||||||
|
ui.label(title).classes("text-subtitle1 text-weight-bold")
|
||||||
|
with ui.row().classes("items-center q-gutter-xs"):
|
||||||
|
ui.link("Upload", "/upload").classes(_nav_link_classes(is_active=normalized_path == "/upload"))
|
||||||
|
ui.link("Jobs", "/jobs").classes(_nav_link_classes(is_active=normalized_path.startswith("/jobs")))
|
||||||
@@ -13,6 +13,7 @@ from transcription.db import get_session
|
|||||||
from transcription.models import Document
|
from transcription.models import Document
|
||||||
from transcription.models import Job
|
from transcription.models import Job
|
||||||
from transcription.models import Transcript
|
from transcription.models import Transcript
|
||||||
|
from transcription.ui.components.app_shell import render_navigation_header
|
||||||
from transcription.ui.components.error_presenter import show_error
|
from transcription.ui.components.error_presenter import show_error
|
||||||
from transcription.ui.components.error_presenter import summarize_error
|
from transcription.ui.components.error_presenter import summarize_error
|
||||||
from transcription.ui.components.job_detail import render_job_detail
|
from transcription.ui.components.job_detail import render_job_detail
|
||||||
@@ -59,6 +60,7 @@ def register_page() -> None:
|
|||||||
|
|
||||||
@ui.page("/jobs")
|
@ui.page("/jobs")
|
||||||
async def jobs_page() -> None:
|
async def jobs_page() -> None:
|
||||||
|
render_navigation_header(title="Transcription", current_path="/jobs")
|
||||||
ui.label("Transcription Jobs")
|
ui.label("Transcription Jobs")
|
||||||
status = ui.label("Ready")
|
status = ui.label("Ready")
|
||||||
|
|
||||||
@@ -82,6 +84,7 @@ def register_page() -> None:
|
|||||||
|
|
||||||
@ui.page("/jobs/{job_id}")
|
@ui.page("/jobs/{job_id}")
|
||||||
async def job_detail_page(job_id: str) -> None:
|
async def job_detail_page(job_id: str) -> None:
|
||||||
|
render_navigation_header(title="Transcription", current_path="/jobs")
|
||||||
ui.label("Job Detail")
|
ui.label("Job Detail")
|
||||||
try:
|
try:
|
||||||
parsed_id = UUID(job_id)
|
parsed_id = UUID(job_id)
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ from nicegui import ui
|
|||||||
from transcription.app_state import resolve_session_factory
|
from transcription.app_state import resolve_session_factory
|
||||||
from transcription.db import get_session
|
from transcription.db import get_session
|
||||||
from transcription.services.store import create_upload_job
|
from transcription.services.store import create_upload_job
|
||||||
|
from transcription.ui.components.app_shell import render_navigation_header
|
||||||
from transcription.ui.components.upload import render_upload_widget
|
from transcription.ui.components.upload import render_upload_widget
|
||||||
from transcription.worker import resolve_worker_notifier
|
from transcription.worker import resolve_worker_notifier
|
||||||
|
|
||||||
@@ -17,6 +18,7 @@ def register_page() -> None:
|
|||||||
|
|
||||||
@ui.page("/upload", title="Upload Document")
|
@ui.page("/upload", title="Upload Document")
|
||||||
def upload_page(request: Request) -> None:
|
def upload_page(request: Request) -> None:
|
||||||
|
render_navigation_header(title="Transcription", current_path="/upload")
|
||||||
session_factory = resolve_session_factory(request.app.state)
|
session_factory = resolve_session_factory(request.app.state)
|
||||||
|
|
||||||
async def submit_upload(filename: str, file_bytes: bytes):
|
async def submit_upload(filename: str, file_bytes: bytes):
|
||||||
@@ -29,6 +31,3 @@ def register_page() -> None:
|
|||||||
|
|
||||||
notify_worker = resolve_worker_notifier(request.app.state)
|
notify_worker = resolve_worker_notifier(request.app.state)
|
||||||
render_upload_widget(submitter=submit_upload, notifier=notify_worker)
|
render_upload_widget(submitter=submit_upload, notifier=notify_worker)
|
||||||
|
|
||||||
with ui.row():
|
|
||||||
ui.link("View jobs", "/jobs")
|
|
||||||
|
|||||||
Reference in New Issue
Block a user