diff --git a/__pycache__/app.cpython-312.pyc b/__pycache__/app.cpython-312.pyc new file mode 100644 index 0000000..5453e33 Binary files /dev/null and b/__pycache__/app.cpython-312.pyc differ diff --git a/app.py b/app.py index 47e8b6f..b8657ec 100644 --- a/app.py +++ b/app.py @@ -5,7 +5,7 @@ import threading from concurrent.futures import ThreadPoolExecutor from datetime import datetime from pathlib import Path -from typing import List, Optional +from typing import Optional import markdown as md import requests @@ -127,68 +127,51 @@ def layout(title: str, body: str) -> str: + + {title} - +
- +

{title}

-
{body}
+
{body}
+ """ @@ -455,18 +462,28 @@ def upload_page(msg: str = ""): projects = get_projects() opts = "".join([f"" for p in projects]) body = f""" -

Audio Upload

-

Audio wird transkribiert + mit Sprechern angereichert und als Dokument gespeichert.

-{f"

{msg}

" if msg else ""} +
+

Audio Upload

+
+

Audio wird transkribiert + mit Sprechern angereichert und als Dokument gespeichert.

+{f"
{msg}
" if msg else ""}
-
- - - +
+
+ + +
+
+ + +
+
+ + +
-
- - +
+
""" @@ -561,66 +578,54 @@ def library(project_id: Optional[str] = None, q_title: str = "", q_content: str rows = "".join( [ f"" - f"" f"#{d['id']}" f"{d['title']}" f"{d['kind']}" f"{d['project']}" f"{d['created_at']}" - f"" - f"👁️" - f"⬇️" - f"✏️" - f"📁" - f"🗑️" - f"" + f"
" + f"👁️" + f"⬇️" + f"✏️" + f"📁" + f"🗑️" + f"
" f"" for d in docs ] ) project_js = json.dumps([{"value": p["id"], "label": p["name"]} for p in projects], ensure_ascii=False) body = f""" - -

Projekte · Dokumente

-
Ansicht im Projektlisten-Stil mit Schnellaktionen.
-
- - - - - -
- {len(docs)} Treffer +
+

Projekte · Dokumente

+ {len(docs)} Treffer +
+
Ansicht im Projektlisten-Stil mit Schnellaktionen.
+ +
+
+ + +
+
+ + +
+
+ + +
+
+ +
-
- 0 ausgewählt - - -
-
- - - - - - {rows or ""} -
IDTitelTypProjektErstelltAktionen
Keine Einträge.
-
-
- - +
+
+ + + {rows or ""} +
IDTitelTypProjektErstelltAktionen
Keine Einträge.
+
""" return layout("Library", body) @@ -726,15 +674,18 @@ def view_document(doc_id: int): projects = get_projects() body = f""" -

Dokument #{d['id']} – {d['title']}

-

- Projekt: {d['project']} · Typ: {d['kind']} · {d['created_at']} -    - ⬇️ - ✏️ - 📁 - 🗑️ -

+
+
+

Dokument #{d['id']} – {d['title']}

+
Projekt: {d['project']} · Typ: {d['kind']} · {d['created_at']}
+
+ +
{rendered}
+""" + return layout("Prompts & Projekte", body) + + +@app.get("/prompts/{prompt_id}/preview") +def prompt_preview(prompt_id: int): + with db() as c: + p = c.execute("SELECT id,name,prompt FROM prompts WHERE id=?", (prompt_id,)).fetchone() + if not p: + raise HTTPException(404, "Prompt nicht gefunden") + html = md.markdown(p["prompt"] or "", extensions=["fenced_code", "tables", "nl2br"]) + return {"id": p["id"], "name": p["name"], "html": html} @app.post("/prompts/add", response_class=HTMLResponse) def prompt_add(name: str = Form(...), prompt: str = Form(...)): @@ -977,45 +1041,68 @@ def jobs_delete_form(job_id: int): @app.get("/jobs", response_class=HTMLResponse) def jobs_page(queued: Optional[int] = None): items = _jobs_payload(200) - pre = "".join([ - ( - f"
Job #{it['id']} [{it['kind']}] · {it['status']} · läuft: {_fmt_elapsed(it.get('started_at') or it.get('created_at'), it.get('finished_at'))}
" - f"{it['created_at']}
" - f"
" - + ( - "" - if it["status"] in ("done", "error", "cancelled") - else ( - f"
" - f"
" - ) - ) - + ( - f"
" - f"
" - ) - + ( - f"Ergebnis öffnen" - if it.get("result_document_id") - else "" - ) - + "
" - ) - for it in items - ]) or "

Keine Jobs.

" - notice = f"

Job #{queued} wurde eingereiht.

" if queued else "" + def _badge(status: str) -> str: + s = (status or "").lower() + if s == "done": + return "success" + if s in ("running", "queued"): + return "primary" + if s == "cancelled": + return "warning" + return "danger" + + cards = [] + for it in items: + start_ts = it.get("started_at") or it.get("created_at") or "" + end_ts = it.get("finished_at") or "" + actions = "" + if it["status"] not in ("done", "error", "cancelled"): + actions += f" " + actions += f" " + if it.get("result_document_id"): + actions += f" Ergebnis" + + err = f"
{str(it['error']).replace('<','<')}
" if it.get("error") else "" + cards.append( + f"
" + f"
" + f"
Job #{it['id']} · {it['kind']}
" + f"
erstellt: {it['created_at']} · läuft: {_fmt_elapsed(start_ts, end_ts)}
" + f"{it['status']}
" + f"
" + f"{('Projekt: '+it['project_name']) if it.get('project_name') else ''}" + f"{('
Dokument: '+it['document_title']) if it.get('document_title') else ''}" + f"{('
Prompt: '+it['prompt_name']) if it.get('prompt_name') else ''}" + f"
" + f"
{actions}
" + f"{err}" + f"
" + ) + + pre = "".join(cards) or "

Keine Jobs.

" + + notice = f"
Job #{queued} wurde eingereiht.
" if queued else "" body = f""" -

Hintergrundverarbeitung

-

Maximal 2 Jobs gleichzeitig. Seite aktualisiert automatisch.

+

Hintergrundverarbeitung

+

Maximal 2 Jobs gleichzeitig. Seite aktualisiert automatisch.

{notice} -
Live-Update aktiv …
+
+
+ + + + + 0 ausgewählt +
+
+
Live-Update aktiv …
{pre}
""" return layout("Jobs", body) @@ -1087,13 +1173,17 @@ def run_page(): p_opts = "".join([f"" for p in prompts]) body = f""" -

Prompt ausführen

+

Prompt ausführen

-
-

-
-

- +
+ + +
+
+ + +
+
""" return layout("Run", body)