Server (Website, Admin-Bereich, Player-API) und Player (raspotify + Controller) mit Install-Skripten für Debian-Systeme. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
177 lines
8.6 KiB
HTML
177 lines
8.6 KiB
HTML
<!doctype html>
|
||
<html lang="de">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
||
<meta name="theme-color" content="#121212">
|
||
<meta name="robots" content="noindex">
|
||
<title>Audiofy – Admin</title>
|
||
<link rel="stylesheet" href="/static/app.css">
|
||
<link rel="stylesheet" href="/static/admin.css">
|
||
<script src="/static/admin.js" defer></script>
|
||
</head>
|
||
<body>
|
||
<main>
|
||
<div class="kopf">
|
||
<h1>Audiofy Admin</h1>
|
||
<button id="abmelden" class="klein" type="button">Abmelden</button>
|
||
</div>
|
||
<div class="pillen" id="pillen"></div>
|
||
|
||
<nav class="reiter" role="tablist">
|
||
<button type="button" role="tab" data-reiter="wiedergabe" aria-selected="true">Wiedergabe</button>
|
||
<button type="button" role="tab" data-reiter="wuensche">Wünsche<span id="zahl-freigabe" class="zahl" hidden></span></button>
|
||
<button type="button" role="tab" data-reiter="gaeste">Gäste</button>
|
||
<button type="button" role="tab" data-reiter="einstellungen">Einstellungen</button>
|
||
<button type="button" role="tab" data-reiter="verlauf">Verlauf</button>
|
||
</nav>
|
||
|
||
<div id="notaus-hinweis" class="notaus-aktiv" hidden>Not-Aus aktiv – der Controller ist angehalten.</div>
|
||
|
||
<!-- ===== Wiedergabe ===== -->
|
||
<section data-seite="wiedergabe">
|
||
<div class="karte">
|
||
<h2>Läuft gerade</h2>
|
||
<div id="jetzt-inhalt" class="titel-zeile"></div>
|
||
<div class="fortschritt"><div id="fortschritt-balken"></div></div>
|
||
<p id="naechster" class="hinweis klein"></p>
|
||
<p id="pi-fehler" class="hinweis klein fehlertext" hidden></p>
|
||
<div class="knopfreihe">
|
||
<button class="gross mit-symbol" type="button" data-befehl="play"><span class="symbol" aria-hidden="true">▶</span><span>Play</span></button>
|
||
<button class="gross mit-symbol" type="button" data-befehl="pause"><span class="symbol" aria-hidden="true">⏸</span><span>Pause</span></button>
|
||
<button class="gross mit-symbol" type="button" data-befehl="skip"><span class="symbol" aria-hidden="true">⏭</span><span>Weiter</span></button>
|
||
</div>
|
||
<div class="lautstaerke">
|
||
<span aria-hidden="true">🔊</span>
|
||
<input id="lautstaerke" type="range" min="0" max="100" step="5" aria-label="Lautstärke">
|
||
<output id="lautstaerke-wert">–</output>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="karte">
|
||
<h2>Als Nächstes spielen</h2>
|
||
<input id="naechstes-suche" type="search" placeholder="Titel suchen …" autocomplete="off" maxlength="100">
|
||
<ul id="naechstes-treffer" class="liste"></ul>
|
||
</div>
|
||
|
||
<div class="karte">
|
||
<h2>Not-Aus</h2>
|
||
<p class="hinweis klein">Stoppt die Wiedergabe und hält den Controller an, bis du wieder freigibst.</p>
|
||
<button id="notaus" class="gross mit-symbol gefahr voll" type="button"><span class="symbol" aria-hidden="true">⛔</span><span>Not-Aus</span></button>
|
||
</div>
|
||
|
||
<div class="karte">
|
||
<h2>Letzte Befehle</h2>
|
||
<ul id="befehle" class="liste kompakt"></ul>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ===== Wünsche ===== -->
|
||
<section data-seite="wuensche" hidden>
|
||
<div class="karte">
|
||
<div class="schalter-zeile">
|
||
<div class="text"><span class="t">Wünsche annehmen</span><span class="m">Aus = Gäste sehen „pausiert“</span></div>
|
||
<label class="schalter"><input type="checkbox" id="s-annahme"><span></span></label>
|
||
</div>
|
||
<div class="schalter-zeile">
|
||
<div class="text"><span class="t">Moderation</span><span class="m">Wünsche erst nach deiner Freigabe spielen</span></div>
|
||
<label class="schalter"><input type="checkbox" id="s-moderation"><span></span></label>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="karte" id="freigabe-karte">
|
||
<h2>Zur Freigabe</h2>
|
||
<ul id="freigabe" class="liste"></ul>
|
||
<p id="freigabe-leer" class="hinweis">Nichts zu prüfen.</p>
|
||
<p class="legende"><span>✓ freigeben</span><span>✕ ablehnen</span><span>🚫 Gast sperren</span></p>
|
||
</div>
|
||
|
||
<div class="karte">
|
||
<h2>Warteschlange</h2>
|
||
<ul id="warteschlange" class="liste"></ul>
|
||
<p id="warteschlange-leer" class="hinweis">Keine Wünsche in der Warteschlange.</p>
|
||
<p class="legende"><span>↑ früher</span><span>↓ später</span><span>✕ löschen</span><span>🚫 Gast sperren</span></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ===== Gäste ===== -->
|
||
<section data-seite="gaeste" hidden>
|
||
<div class="karte">
|
||
<h2>Gastzugang</h2>
|
||
<div class="schalter-zeile">
|
||
<div class="text"><span class="t">Zugang offen</span><span class="m">Aus = niemand kommt auf die Wunschseite</span></div>
|
||
<label class="schalter"><input type="checkbox" id="s-zugang"><span></span></label>
|
||
</div>
|
||
<img id="qr" class="qr" alt="QR-Code zum Einladungslink">
|
||
<input id="einladungslink" class="link-feld" type="text" readonly aria-label="Einladungslink">
|
||
<div class="knopfreihe zwei">
|
||
<button id="link-kopieren" class="gross" type="button">Link kopieren</button>
|
||
<a id="qr-png" class="gross" href="/admin/api/access/qr?format=png" download>QR als Bild</a>
|
||
</div>
|
||
<button id="link-erneuern" class="gross voll" type="button">Neuen Link erzeugen</button>
|
||
<p class="hinweis klein">Ein neuer Link macht den alten und alle damit erteilten Zugänge ungültig.</p>
|
||
</div>
|
||
|
||
<div class="karte">
|
||
<h2>Limit pro Gast</h2>
|
||
<div class="feld-zeile"><span>Wünsche</span><input id="e-limit-anzahl" type="number" min="1" max="50"></div>
|
||
<div class="feld-zeile"><span>pro Minuten</span><input id="e-limit-minuten" type="number" min="1" max="1440"></div>
|
||
<button class="gross akzent voll" type="button" data-speichern="e-limit-anzahl:wish_limit_count,e-limit-minuten:wish_limit_minutes">Speichern</button>
|
||
</div>
|
||
|
||
<div class="karte">
|
||
<h2>Sperrliste</h2>
|
||
<div class="schalter-zeile">
|
||
<div class="text"><span class="t">Explizite Titel sperren</span></div>
|
||
<label class="schalter"><input type="checkbox" id="s-explizit"><span></span></label>
|
||
</div>
|
||
<input id="sperr-suche" type="search" placeholder="Titel oder Interpret zum Sperren suchen …" autocomplete="off" maxlength="100">
|
||
<ul id="sperr-treffer" class="liste"></ul>
|
||
<h2 class="abstand">Gesperrt</h2>
|
||
<ul id="sperrliste" class="liste"></ul>
|
||
<p id="sperrliste-leer" class="hinweis">Nichts gesperrt.</p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ===== Einstellungen ===== -->
|
||
<section data-seite="einstellungen" hidden>
|
||
<div class="karte">
|
||
<h2>Ablauf</h2>
|
||
<div class="feld-zeile"><span>Jeder wievielte Titel ist ein Wunsch (N)</span><input id="e-n" type="number" min="1" max="20"></div>
|
||
<div class="feld-zeile"><span>Sperrzeit für Wiederholungen (Min.)</span><input id="e-sperrzeit" type="number" min="0" max="1440"></div>
|
||
<button class="gross akzent voll" type="button" data-speichern="e-n:wish_every_n,e-sperrzeit:repeat_block_minutes">Speichern</button>
|
||
</div>
|
||
<div class="karte">
|
||
<h2>Lautsprecher</h2>
|
||
<div id="bt-aktuell" class="titel-zeile"></div>
|
||
<p class="hinweis klein">Neuen Bluetooth-Lautsprecher vorher in den Kopplungsmodus versetzen (meist Bluetooth-Taste gedrückt halten, bis die LED schnell blinkt). Während der Suche kann die Musik kurz stocken – WLAN und Bluetooth teilen sich oft einen Funkchip.</p>
|
||
<button id="bt-suchen" class="gross voll" type="button">Nach Lautsprechern suchen</button>
|
||
<p id="bt-status" class="hinweis klein"></p>
|
||
<ul id="bt-geraete" class="liste"></ul>
|
||
</div>
|
||
|
||
<div class="karte">
|
||
<h2>Grund-Playlist</h2>
|
||
<p class="hinweis klein">Aktuell: <a id="playlist-link" target="_blank" rel="noopener noreferrer"></a></p>
|
||
<input id="playlist-neu" type="text" placeholder="Spotify-Playlist-Link einfügen" autocomplete="off" maxlength="300">
|
||
<div class="knopfreihe zwei">
|
||
<button id="playlist-wechseln" class="gross akzent" type="button">Wechseln</button>
|
||
<button id="neu-mischen" class="gross" type="button">Neu mischen</button>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ===== Verlauf ===== -->
|
||
<section data-seite="verlauf" hidden>
|
||
<div class="karte">
|
||
<h2>Verlauf</h2>
|
||
<ul id="verlauf" class="liste"></ul>
|
||
<p id="verlauf-leer" class="hinweis">Noch nichts gespielt.</p>
|
||
</div>
|
||
</section>
|
||
</main>
|
||
|
||
<div id="toast" class="toast" role="status" aria-live="assertive" hidden></div>
|
||
</body>
|
||
</html>
|