feat(diarization-ui): add mobile burger menu/off-canvas nav and rename app branding to VoiceLog

This commit is contained in:
2026-03-22 07:47:08 +01:00
parent b20a459972
commit def9e7ac36

38
app.py
View File

@@ -132,7 +132,7 @@ def layout(title: str, body: str) -> str:
:root{{--bg:#0b1020;--panel:#070c1b;--panel2:#0b1222;--card:#ffffff;--txt:#0f172a;--muted:#64748b;--acc:#0ea5e9;--acc2:#2563eb;--ok:#14b8a6;--border:#e2e8f0}} :root{{--bg:#0b1020;--panel:#070c1b;--panel2:#0b1222;--card:#ffffff;--txt:#0f172a;--muted:#64748b;--acc:#0ea5e9;--acc2:#2563eb;--ok:#14b8a6;--border:#e2e8f0}}
*{{box-sizing:border-box}} *{{box-sizing:border-box}}
body{{font-family:Inter,system-ui,Arial;margin:0;background:#f1f5f9;color:var(--txt);display:flex;min-height:100vh}} body{{font-family:Inter,system-ui,Arial;margin:0;background:#f1f5f9;color:var(--txt);display:flex;min-height:100vh}}
nav{{width:236px;background:linear-gradient(180deg,#050a17,#0a1329);color:#e2e8f0;border-right:1px solid #0f172a;padding:14px 10px;position:sticky;top:0;height:100vh;overflow:auto}} nav{{width:236px;background:linear-gradient(180deg,#050a17,#0a1329);color:#e2e8f0;border-right:1px solid #0f172a;padding:14px 10px;position:sticky;top:0;height:100vh;overflow:auto;z-index:60}}
.brand{{font-weight:800;letter-spacing:.2px;margin:4px 8px 12px 8px;color:#c7d2fe}} .brand{{font-weight:800;letter-spacing:.2px;margin:4px 8px 12px 8px;color:#c7d2fe}}
.navsection{{margin:12px 8px 6px 8px;color:#94a3b8;font-size:12px;text-transform:uppercase;letter-spacing:.08em}} .navsection{{margin:12px 8px 6px 8px;color:#94a3b8;font-size:12px;text-transform:uppercase;letter-spacing:.08em}}
nav a{{display:flex;gap:10px;align-items:center;color:#e2e8f0;text-decoration:none;padding:10px 10px;border-radius:10px;margin:4px 6px;border:1px solid transparent}} nav a{{display:flex;gap:10px;align-items:center;color:#e2e8f0;text-decoration:none;padding:10px 10px;border-radius:10px;margin:4px 6px;border:1px solid transparent}}
@@ -140,6 +140,8 @@ nav a:hover{{background:#0f1b36;border-color:#1e2a4a}}
.app{{flex:1;display:flex;flex-direction:column;min-width:0}} .app{{flex:1;display:flex;flex-direction:column;min-width:0}}
.topbar{{height:56px;background:#fff;border-bottom:1px solid var(--border);display:flex;align-items:center;padding:0 16px;gap:10px;position:sticky;top:0;z-index:10}} .topbar{{height:56px;background:#fff;border-bottom:1px solid var(--border);display:flex;align-items:center;padding:0 16px;gap:10px;position:sticky;top:0;z-index:10}}
.topbar h1{{font-size:18px;margin:0;font-weight:700}} .topbar h1{{font-size:18px;margin:0;font-weight:700}}
.menu-btn{{display:none;border:1px solid #cbd5e1;background:#fff;color:#0f172a;border-radius:8px;padding:6px 10px;font-size:18px;line-height:1}}
.nav-backdrop{{display:none;position:fixed;inset:0;background:rgba(2,6,23,.35);z-index:55}}
.topbar .right{{margin-left:auto;display:flex;gap:8px;color:#64748b}} .topbar .right{{margin-left:auto;display:flex;gap:8px;color:#64748b}}
main{{padding:14px;max-width:1400px}} main{{padding:14px;max-width:1400px}}
.card{{background:#fff;border:1px solid var(--border);border-radius:12px;padding:14px;margin:10px 0;box-shadow:0 2px 10px rgba(15,23,42,.04)}} .card{{background:#fff;border:1px solid var(--border);border-radius:12px;padding:14px;margin:10px 0;box-shadow:0 2px 10px rgba(15,23,42,.04)}}
@@ -167,12 +169,14 @@ small{{color:var(--muted)}}
}} }}
@media (max-width:760px){{ @media (max-width:760px){{
body{{display:block}} body{{display:block}}
nav{{position:fixed;left:0;right:0;bottom:0;top:auto;height:64px;width:100%;display:flex;align-items:center;overflow:auto;white-space:nowrap;padding:6px 8px;z-index:50}} nav{{position:fixed;left:0;top:0;bottom:0;height:100vh;width:236px;transform:translateX(-105%);transition:transform .2s ease;box-shadow:0 18px 40px rgba(0,0,0,.35)}}
.brand,.navsection{{display:none}} body.nav-open nav{{transform:translateX(0)}}
nav a{{margin:0 4px;min-width:auto;padding:8px 10px}} body.nav-open .nav-backdrop{{display:block}}
.brand,.navsection{{display:block}}
nav a{{margin:4px 6px;padding:10px 10px}}
nav a span{{display:inline}} nav a span{{display:inline}}
nav a span:last-child{{display:none}} .menu-btn{{display:inline-block}}
.app{{padding-bottom:72px}} .app{{padding-bottom:0}}
.topbar{{position:sticky;top:0}} .topbar{{position:sticky;top:0}}
main{{padding:10px 8px}} main{{padding:10px 8px}}
.row{{flex-direction:column;align-items:stretch}} .row{{flex-direction:column;align-items:stretch}}
@@ -188,6 +192,8 @@ small{{color:var(--muted)}}
</style> </style>
<script> <script>
if ('serviceWorker' in navigator) {{ window.addEventListener('load', () => navigator.serviceWorker.register('/sw.js').catch(()=>{{}})); }} if ('serviceWorker' in navigator) {{ window.addEventListener('load', () => navigator.serviceWorker.register('/sw.js').catch(()=>{{}})); }}
window.toggleNav = function() {{ document.body.classList.toggle('nav-open'); }};
window.closeNav = function() {{ document.body.classList.remove('nav-open'); }};
window.showModal = function({{title='Eingabe', html='', ok='OK', cancel='Abbrechen'}}) {{ window.showModal = function({{title='Eingabe', html='', ok='OK', cancel='Abbrechen'}}) {{
return new Promise((resolve) => {{ return new Promise((resolve) => {{
@@ -219,20 +225,22 @@ window.uiSelect = async function(title, options, placeholder='') {{
</head> </head>
<body> <body>
<div id='modal-backdrop' class='modal-backdrop'><div id='modal-box' class='modal'></div></div> <div id='modal-backdrop' class='modal-backdrop'><div id='modal-box' class='modal'></div></div>
<div class='nav-backdrop' onclick='closeNav()'></div>
<nav> <nav>
<div class='brand'>🎙️ Audio Copilot</div> <div class='brand'>🎙️ VoiceLog</div>
<div class='navsection'>Navigation</div> <div class='navsection'>Navigation</div>
<a href='/'><span>🏠</span><span>Home / Upload</span></a> <a href='/' onclick='closeNav()'><span>🏠</span><span>Home / Upload</span></a>
<a href='/library'><span>📁</span><span>Projekte</span></a> <a href='/library' onclick='closeNav()'><span>📁</span><span>Projekte</span></a>
<a href='/prompts'><span>🧩</span><span>Vorlagen</span></a> <a href='/prompts' onclick='closeNav()'><span>🧩</span><span>Vorlagen</span></a>
<div class='navsection'>Automatisierung</div> <div class='navsection'>Automatisierung</div>
<a href='/run'><span>🤖</span><span>Prompt ausführen</span></a> <a href='/run' onclick='closeNav()'><span>🤖</span><span>Prompt ausführen</span></a>
<a href='/jobs'><span>⏳</span><span>Hintergrundjobs</span></a> <a href='/jobs' onclick='closeNav()'><span>⏳</span><span>Hintergrundjobs</span></a>
<div class='navsection'>System</div> <div class='navsection'>System</div>
<a href='/healthz'><span>💚</span><span>Health</span></a> <a href='/healthz' onclick='closeNav()'><span>💚</span><span>Health</span></a>
</nav> </nav>
<div class='app'> <div class='app'>
<div class='topbar'> <div class='topbar'>
<button class='menu-btn' type='button' onclick='toggleNav()'>☰</button>
<h1>{title}</h1> <h1>{title}</h1>
</div> </div>
<main>{body}</main> <main>{body}</main>
@@ -406,8 +414,8 @@ def startup():
@app.get("/manifest.webmanifest") @app.get("/manifest.webmanifest")
def manifest(): def manifest():
return { return {
"name": "Audio Copilot", "name": "VoiceLog",
"short_name": "Copilot", "short_name": "VoiceLog",
"start_url": "/", "start_url": "/",
"display": "standalone", "display": "standalone",
"background_color": "#020617", "background_color": "#020617",