root f03d46afb5 ui: Upload-Form & Jobs-Liste aufgeräumt
Upload-Form:
- Title-Label nicht mehr mit "(optional)" suffix — Hinweis wandert in
  den Placeholder. Labels haben jetzt einheitliches Spalten-Layout
  (flex-column + align-items: end), Inputs sind bündig
- "Standard: X" Hinweis unter dem Profil entfernt (Dropdown ist
  selbst-erklärend, das Header-Dropdown zeigt's eh schon)

Jobs-Liste:
- Wenn kein Titel gesetzt ist, wird der Dateiname nur 1× als Titel
  gezeigt (vorher: groß als Titel + nochmal klein darunter)
- Profile/Modell-Tags in eigene flex-Zeile statt margin-left-Hack
- Dateiname-Zeile mit Ellipsis bei zu langen Namen
- Tags 1px kleiner, weniger Padding
- Datumsformat: heute → nur HH:MM, sonst dd.mm HH:MM (statt langem
  dd.mm.yyyy HH:MM:SS) — col-updated von 120px auf 78px geschrumpft
- col-status von 110px auf 170px → Aktions-Buttons stapeln weniger

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 20:34:54 +00:00

190 lines
7.3 KiB
HTML

<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
<meta name="theme-color" content="#0f1115" />
<title>Voice-Agent — Transkription</title>
<link rel="stylesheet" href="/static/style.css" />
<link rel="manifest" href="/static/manifest.webmanifest" />
<link rel="icon" href="/static/icon.svg" type="image/svg+xml" />
<link rel="apple-touch-icon" href="/static/icon-192.png" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<meta name="apple-mobile-web-app-title" content="Voice-Agent" />
<meta name="mobile-web-app-capable" content="yes" />
</head>
<body>
<header>
<div class="header-row">
<div class="header-left">
<h1>Voice-Agent</h1>
<p class="sub desktop-only">Sitzungsaufnahmen automatisch transkribieren und protokollieren</p>
</div>
<div class="header-right">
<div id="mac-status" class="badge desktop-only">Mac-Backend: prüfe …</div>
<div id="user-bar" class="user-bar hidden">
<span class="muted desktop-only">Angemeldet als</span>
<strong id="user-name"></strong>
<span id="user-admin-badge" class="badge admin-badge hidden">Admin</span>
<span id="header-profile-wrap" class="header-profile-wrap hidden">
<span class="muted desktop-only">·</span>
<span class="muted desktop-only">Profil:</span>
<select id="header-profile" class="header-profile" title="Standard-Profil — wird sofort gespeichert"></select>
</span>
<span id="header-model-wrap" class="header-profile-wrap hidden">
<span class="muted desktop-only">·</span>
<span class="muted desktop-only">Modell:</span>
<select id="header-model" class="header-profile" title="Standard-LLM — wird sofort gespeichert. Leer = Worker-Default."></select>
</span>
<button type="button" id="logout-btn" class="btn-link">Abmelden</button>
</div>
</div>
</div>
</header>
<!-- Auth-Overlay (Login oder Erst-Setup) -->
<div id="auth-overlay" class="overlay hidden">
<div class="auth-card">
<h2 id="auth-title">Anmelden</h2>
<p id="auth-info" class="muted hidden"></p>
<form id="auth-form">
<label>
Benutzername
<input type="text" id="auth-username" autocomplete="username" required />
</label>
<label>
Passwort
<input type="password" id="auth-password" autocomplete="current-password" required />
</label>
<button type="submit" id="auth-submit">Anmelden</button>
</form>
<p id="auth-msg" class="msg"></p>
</div>
</div>
<main id="app" class="hidden">
<section class="card upload-card">
<h2 class="desktop-only">Neue Aufnahme hochladen</h2>
<form id="upload-form">
<!-- HERO: Aufnahme-Button (auf Mobile groß und zentriert) -->
<button type="button" id="record-toggle" class="btn-record">
<span class="rec-dot"></span>
<span id="record-toggle-label">Aufnahme starten</span>
</button>
<!-- Aufnahme-Bühne -->
<div id="record-pane" class="record-pane hidden">
<div class="record-timer" id="record-timer">00:00</div>
<div class="record-status" id="record-status">Aufnahme läuft</div>
<div class="record-controls">
<button type="button" id="rec-pause" class="btn-record-ctrl">Pause</button>
<button type="button" id="rec-stop" class="btn-record-ctrl danger">Stoppen</button>
</div>
</div>
<!-- Aufnahme bereit -->
<div id="record-result" class="record-result hidden">
<span class="muted">Aufnahme bereit:</span>
<span id="record-filename"></span>
<button type="button" id="record-discard" class="btn-link btn-danger">Verwerfen</button>
</div>
<!-- Profil + Titel -->
<div class="upload-meta">
<label id="profile-label" class="hidden">
Verarbeitungs-Profil
<select id="profile-select"></select>
</label>
<label>
Titel
<input type="text" name="title" id="title" placeholder="optional, z. B. Monatsbesprechung" />
</label>
</div>
<!-- Datei-Upload als Klappe (auf Mobile collapsed, auf Desktop offen) -->
<details class="audio-file-details" id="audio-file-details">
<summary>Lieber eine vorhandene Audio-Datei hochladen?</summary>
<label class="audio-file-label">
<span class="muted">MP3, WAV, M4A, MP4, OGG, FLAC, WebM</span>
<input type="file" name="audio" id="audio" accept="audio/*,.mp3,.wav,.m4a,.mp4,.ogg,.flac,.webm" />
</label>
</details>
<button type="submit" id="submit-btn">Hochladen &amp; verarbeiten</button>
</form>
<div id="upload-progress" class="hidden">
<div class="bar"><div class="bar-fill"></div></div>
<small class="muted">Upload läuft …</small>
</div>
<p id="upload-msg" class="msg"></p>
</section>
<section class="card jobs-card">
<h2>Jobs</h2>
<!-- Desktop: Tabelle -->
<table id="jobs-table" class="desktop-only">
<thead>
<tr>
<th class="col-id">#</th>
<th class="col-title">Titel / Datei</th>
<th class="col-status">Status</th>
<th class="col-progress">Fortschritt</th>
<th class="col-updated">Aktualisiert</th>
<th class="col-dl">Downloads</th>
</tr>
</thead>
<tbody id="jobs-body">
<tr><td colspan="6" class="muted">Noch keine Jobs.</td></tr>
</tbody>
</table>
<!-- Mobile: Card-Liste -->
<div id="jobs-cards" class="jobs-cards mobile-only">
<div class="muted">Noch keine Jobs.</div>
</div>
</section>
<!-- Nur sichtbar für Admins -->
<section id="admin-card" class="card hidden admin-collapsible">
<h2 class="admin-toggle" id="admin-toggle">Benutzer verwalten <span class="admin-toggle-icon"></span></h2>
<div class="admin-body">
<form id="user-form" class="user-form">
<label>
Benutzername
<input type="text" id="new-username" autocomplete="off" required pattern="[A-Za-z0-9._@\-]+" />
</label>
<label>
Passwort (min. 8 Zeichen)
<input type="password" id="new-password" autocomplete="new-password" required minlength="8" />
</label>
<label class="inline-check">
<input type="checkbox" id="new-is-admin" />
Admin-Rechte
</label>
<button type="submit">Anlegen</button>
</form>
<p id="user-msg" class="msg"></p>
<table id="users-table">
<thead>
<tr>
<th>#</th>
<th>Benutzer</th>
<th>Rolle</th>
<th>Angelegt</th>
<th>Aktionen</th>
</tr>
</thead>
<tbody id="users-body"></tbody>
</table>
</div>
</section>
</main>
<footer>
<small class="muted">DSGVO-konform, alles lokal verarbeitet.</small>
</footer>
<script src="/static/app.js"></script>
</body>
</html>