cestina, UI, UX

This commit is contained in:
JiriUhlir
2026-05-29 11:34:07 +02:00
parent d145161e4e
commit 6109bdfe61
11 changed files with 354 additions and 131 deletions
+37 -29
View File
@@ -39,7 +39,15 @@ def render_job_status(status: str | None) -> str:
else:
class_name = "pill pill-muted"
return f'<span class="{class_name}">{html.escape(status_value)}</span>'
labels = {
"queued": "čeká",
"running": "běží",
"cancelled_requested": "žádost o zrušení",
"cancelled": "zrušeno",
"success": "úspěšné",
"failed": "selhalo",
}
return f'<span class="{class_name}">{html.escape(labels.get(normalized, status_value))}</span>'
def pretty_json(value: str | None) -> str:
@@ -195,7 +203,7 @@ def jobs_page(
"""
if not rows:
rows = '<tr><td colspan="9">Zatím nejsou evidované žádné joby.</td></tr>'
rows = '<tr><td colspan="9">Zatím nejsou evidované žádné úlohy.</td></tr>'
status_options = render_options(JOB_FILTER_STATUSES, selected_status, "Všechny statusy")
type_options = render_options(JOB_FILTER_TYPES, selected_type, "Všechny typy")
@@ -225,19 +233,19 @@ def jobs_page(
"""
return page(
"Joby",
"Úlohy",
f"""
{refresh}
<div class="card">
<h2>Joby</h2>
<h2>Úlohy</h2>
<p class="muted">Fronta portálových a webhook úloh připravená pro centrální worker.</p>
</div>
<div class="stats-grid">
<div class="stat-card stat-warning"><span>Queued</span><strong data-live-count="jobs.queued">{stats.get("queued") or 0}</strong></div>
<div class="stat-card stat-warning"><span>Running</span><strong data-live-count="jobs.running">{stats.get("running") or 0}</strong></div>
<div class="stat-card stat-danger"><span>Failed (24h)</span><strong data-live-count="jobs.failed_24h">{stats.get("failed_24h") or 0}</strong></div>
<div class="stat-card stat-success"><span>Success (24h)</span><strong data-live-count="jobs.success_24h">{stats.get("success_24h") or 0}</strong></div>
<div class="stat-card stat-warning"><span>Čekající</span><strong data-live-count="jobs.queued">{stats.get("queued") or 0}</strong></div>
<div class="stat-card stat-warning"><span>Běžící</span><strong data-live-count="jobs.running">{stats.get("running") or 0}</strong></div>
<div class="stat-card stat-danger"><span>Selhané (24 h)</span><strong data-live-count="jobs.failed_24h">{stats.get("failed_24h") or 0}</strong></div>
<div class="stat-card stat-success"><span>Úspěšné (24 h)</span><strong data-live-count="jobs.success_24h">{stats.get("success_24h") or 0}</strong></div>
</div>
<div class="card">
@@ -245,7 +253,7 @@ def jobs_page(
<form method="get" action="/portal/jobs" class="filter-form">
<select name="status">{status_options}</select>
<select name="type">{type_options}</select>
<input name="target" value="{target_value}" placeholder="Target">
<input name="target" value="{target_value}" placeholder="Cíl">
<input type="hidden" name="page" value="1">
<button type="submit">Filtrovat</button>
<a class="btn btn-secondary" href="/portal/jobs">Reset</a>
@@ -253,15 +261,15 @@ def jobs_page(
</div>
<div class="card">
<h2>Recent Jobs</h2>
<h2>Poslední úlohy</h2>
<table>
<tr>
<th>ID</th>
<th>Status</th>
<th>Type</th>
<th>Target</th>
<th>Source</th>
<th>Created At</th>
<th>Typ</th>
<th>Cíl</th>
<th>Zdroj</th>
<th>Vytvořeno</th>
</tr>
<tbody data-live-table="jobs.recent"></tbody>
</table>
@@ -274,10 +282,10 @@ def jobs_page(
<tr>
<th>ID</th>
<th>Status</th>
<th>Source</th>
<th>Target</th>
<th>Created by</th>
<th>Created at</th>
<th>Zdroj</th>
<th>Cíl</th>
<th>Vytvořil</th>
<th>Vytvořeno</th>
<th>Started at</th>
<th>Finished at</th>
<th>Akce</th>
@@ -300,7 +308,7 @@ def job_detail_page(job_id: int, request: Request, user=Depends(require_user)):
status_value = (job.get("status") or "").lower()
refresh = ""
title = f"Job #{html.escape(str(job.get('id', job_id)))}"
title = f"Úloha #{html.escape(str(job.get('id', job_id)))}"
status = render_job_status(job.get("status"))
target_type = job.get("target_type", "") or ""
target_id = job.get("target_id", "") or ""
@@ -315,7 +323,7 @@ def job_detail_page(job_id: int, request: Request, user=Depends(require_user)):
if status_value == "failed" and can_retry_job(job):
actions += f"""
<form method="post" action="/portal/jobs/{html.escape(str(job_id))}/retry" onsubmit="return confirm('Retry job #{html.escape(str(job_id))}?');">
<button type="submit">Retry Job</button>
<button type="submit">Spustit znovu</button>
</form>
"""
elif status_value == "failed" and (job.get("target_id") or "") in IGNORED_RETRY_REPOSITORIES:
@@ -323,7 +331,7 @@ def job_detail_page(job_id: int, request: Request, user=Depends(require_user)):
if status_value in {"queued", "running"}:
actions += f"""
<form method="post" action="/portal/jobs/{html.escape(str(job_id))}/cancel" onsubmit="return confirm('Cancel job #{html.escape(str(job_id))}?');">
<button type="submit" class="danger">Cancel Job</button>
<button type="submit" class="danger">Zrušit úlohu</button>
</form>
"""
if actions:
@@ -420,8 +428,8 @@ def job_detail_page(job_id: int, request: Request, user=Depends(require_user)):
<div class="card">
<h2>{title}</h2>
<p>
<a class="btn" href="/portal/jobs">&larr; Zpět na joby</a>
<a class="btn btn-secondary" href="{target_url}">Detail targetu</a>
<a class="btn" href="/portal/jobs">&larr; Zpět na úlohy</a>
<a class="btn btn-secondary" href="{target_url}">Detail cíle</a>
</p>
{retry_blocked_notice}
{actions}
@@ -432,10 +440,10 @@ def job_detail_page(job_id: int, request: Request, user=Depends(require_user)):
<table>
<tr><th>Typ</th><td>{html.escape(job.get("type", "") or "")}</td></tr>
<tr><th>Status</th><td>{status}</td></tr>
<tr><th>Source</th><td>{html.escape(job.get("source", "") or "")}</td></tr>
<tr><th>Target</th><td>{html.escape(target_type)}: {target_id_html}</td></tr>
<tr><th>Created by</th><td>{html.escape(job.get("created_by_display_name") or job.get("created_by_username") or "")}</td></tr>
<tr><th>Created at</th><td>{html.escape(job.get("created_at", "") or "")}</td></tr>
<tr><th>Zdroj</th><td>{html.escape(job.get("source", "") or "")}</td></tr>
<tr><th>Cíl</th><td>{html.escape(target_type)}: {target_id_html}</td></tr>
<tr><th>Vytvořil</th><td>{html.escape(job.get("created_by_display_name") or job.get("created_by_username") or "")}</td></tr>
<tr><th>Vytvořeno</th><td>{html.escape(job.get("created_at", "") or "")}</td></tr>
<tr><th>Started at</th><td>{html.escape(job.get("started_at", "") or "")}</td></tr>
<tr><th>Finished at</th><td>{html.escape(job.get("finished_at", "") or "")}</td></tr>
<tr><th>Duration</th><td>{duration}</td></tr>
@@ -456,8 +464,8 @@ def job_detail_page(job_id: int, request: Request, user=Depends(require_user)):
</div>
<div class="card">
<h2>Live logy</h2>
<p class="muted">WebSocket: <span id="live-log-status">Connecting</span></p>
<h2>Živé logy</h2>
<p class="muted">WebSocket: <span id="live-log-status">Připojování</span></p>
<div id="live-log-panel" class="log-viewer log-stdout"></div>
</div>