Die Priority-Playlist lag unter config["priority"] und wirkte damit auf
*alle* Standorte. In der Praxis lief so ein Stuttgart-spezifischer
Eintrag (wbxroompresence...find=Stuttgart) auch auf den Karlsruher
Screens.
Sie liegt jetzt unter sites.<site>.priority, die Medien unter
media/<site>/priority/:
- get_priority_config(cfg, site) liefert die Konfiguration des
Standorts. Ist dort nichts hinterlegt, wird ein globaler Altbestand
einmalig uebernommen - per deepcopy, damit spaetere Aenderungen nicht
zwischen Standorten durchschlagen.
- load_priority_files(site), priority_dir(site) sowie Player, Hash,
Upload, Loeschen, URL-Anlegen, Umsortieren und Einzeleintrag-
Bearbeitung arbeiten durchgaengig standortbezogen.
- Route /media/priority/<datei> -> /media/<site>/priority/<datei>,
Templates entsprechend.
- Der Ordnername "priority" ist wie "logos" in der Screen-Erkennung
ausgenommen. media/<site>/priority/ waere sonst als Screen in der
Konfiguration gelandet; "priority" ist in den Routen ohnehin als
Kennzeichen belegt, ein Screen dieses Namens war nie moeglich.
Migration der vorhandenen Konfiguration: der globale Block wurde in alle
drei Standorte uebernommen und der globale Schluessel entfernt. Der
leere globale Ordner media/priority/ ist entfallen.
README, AGENTS.md und Hilfeseite nachgezogen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Abgleich der Doku gegen den Code ergab:
- /admin/help und /customer fehlten in der Routen-Tabelle
- Der Verzeichnisbaum zeigte nur die Screen-Ordner, nicht die Dateien
auf Standort-Ebene (background.*, logo_<slot>.png, welcome.html) -
gerade die sind aber bewusst Dateien und keine Ordner, weil jeder
Unterordner als Screen interpretiert wird
- Der Docker-Abschnitt erwaehnte weder das noetige --build noch die
Log-Einstellungen (PYTHONUNBUFFERED, access-logfile), die fuer jede
Fehlersuche die Grundlage sind
AGENTS.md bekommt dazu einen Abschnitt "Betrieb / Diagnose".
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Ein helles Logo auf hellem Grund liegt innerhalb der Farbtoleranz des
Flood Fill. Der Fuellvorgang lief vom Rand in das Logo hinein und
loeschte es mit - das Ergebnis war ein vollstaendig transparentes PNG,
auf der Willkommensseite also gar kein Logo. Ohne jede Rueckmeldung:
die bisherige Pruefung schlug nur an, wenn *nichts* entfernt wurde, nicht
wenn alles entfernt wurde.
remove_logo_background() legt jetzt vor dem Eingriff eine Kopie an und
misst danach ueber das Alpha-Histogramm, wie viel sichtbar geblieben
ist. Unter 2% gilt der Versuch als misslungen: das unveraenderte Bild
wird zurueckgegeben und die Oberflaeche nennt den Grund samt Auswegen
(transparentes PNG hochladen oder "Hintergrund behalten" ankreuzen).
Getestet mit Logos von dunkelrot bis reinweiss auf weissem Grund sowie
einem dunklen Logo auf schwarzem Grund.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Hochgeladene Logos landeten unter media/<site>/logos/. admin() behandelt
aber jeden Unterordner von media/<site>/ als Screen und schreibt ihn per
get_screen_config() dauerhaft in die Konfiguration. Der Logo-Ordner
erschien dadurch als Screen in der Oberflaeche, bekam beim Generieren
eine eigene welcome.html und liess sich wie ein Screen bespielen - und
die darin liegenden Logos wie Screen-Medien loeschen. Genau so ist eines
der hochgeladenen Logos verschwunden.
Logos liegen jetzt als media/<site>/logo_<slot>.png direkt im
Standort-Verzeichnis, so wie das Hintergrundbild als
media/<site>/background.* - aus demselben Grund. Die URL bleibt
/media/<site>/logos/<datei>, die Route liest aus dem
Standort-Verzeichnis; bestehende welcome.html funktionieren damit
unveraendert weiter.
Zusaetzlich wird der Ordnername "logos" bei der Screen-Erkennung
uebersprungen, damit Altbestaende nicht erneut als Screen auftauchen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Ein hochgeladenes Logo erschien auf der Willkommensseite deutlich
kleiner als ein automatisch gefundenes. Ursache ist nicht die CSS -
beide nutzen dieselbe Klasse - sondern der Bildinhalt: nach dem
Freistellen ist der Rand zwar durchsichtig, zaehlt aber weiter zur
Bildflaeche. .customer-logo skaliert mit object-fit: contain auf 120px
Hoehe, ein Logo mit breitem Rand erscheint dadurch nur einen Bruchteil
davon gross (gemessen: 30px statt 120px). Brandfetch-Logos sind bereits
eng beschnitten und fuellen den Kasten aus.
trim_transparent_border() schneidet die durchsichtigen Raender nach dem
Freistellen weg. Greift auch bei bereits transparenten PNGs; bei
abgewaehltem Freistellen passiert nichts, da es dort keinen
transparenten Rand gibt.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die Willkommensseite ist je Standort identisch. Bisher musste man nach
dem Einschalten des Schalters "Willkommensseite hier anzeigen" erneut
generieren, damit sie auf dem Screen ankam - ein Handgriff ohne anderes
Ergebnis, und ohne Rueckmeldung, dass er noetig ist.
- sync_welcome_for_screen() kopiert beim Einschalten eine vorhandene
welcome.html in den Screen und setzt sie vorne in die Playlist; beim
Ausschalten werden Eintrag und Datei entfernt. Aufgerufen aus
update_screen(), nur wenn sich der Schalter wirklich aendert.
- save_welcome_page() legt zusaetzlich eine Standort-Kopie unter
media/<site>/welcome.html an, die nie geloescht wird. Ohne sie waere
nach dem Abschalten aller Screens keine Quelle mehr vorhanden und der
Schalter wuerde wieder stillschweigend nichts tun.
Nebenbei behoben: beim Generieren wurde welcome.html aus abgewaehlten
Screens nur aus der Playlist entfernt, die Datei blieb liegen. Bei
leerer Playlist spielt player() noch nicht verzeichnete Dateien aus dem
Ordner ab - die Begruessung waere dort also weiter zu sehen gewesen.
README, AGENTS.md und Hilfeseite nachgezogen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Findet die automatische Suche kein Logo, kann pro Kunde eine Bilddatei
hochgeladen werden. Ein Upload hat Vorrang vor der Suche.
Freistellen:
- remove_logo_background() entfernt den Hintergrund per Flood Fill von
den Bildraendern her. Bewusst kein globaler Farbvergleich - sonst
verschwindet auch Weiss innerhalb des Logos (etwa Text in einer
Flaeche). Weiche Kante gegen Treppeneffekte.
- Umgesetzt mit Pillow, das ueber qrcode[pil] ohnehin vorhanden ist.
Bewusst kein ML-Modell wie rembg: der Container laeuft mit read-only
Root-FS, ein Modell-Cache zur Laufzeit waere dort nicht moeglich.
- Bereits transparente Bilder bleiben unangetastet. Ist der Bildrand
nicht einfarbig, wird nicht freigestellt und die Oberflaeche weist
darauf hin, statt ein beschaedigtes Logo zu liefern.
- Checkbox "Hintergrund behalten" schaltet das Freistellen pro Kunde ab.
- Gespeichert wird immer als PNG (JPEG kann keine Transparenz), grosse
Bilder werden auf 800px verkleinert.
Ablage unter media/<site>/logos/logo_<slot>.png, neue Route
/media/<site>/logos/<datei>. Die URL traegt einen Zeitstempel, damit
Player kein altes Logo aus dem Cache zeigen.
Nebenbei behoben: welcome_data speicherte nur die erfolgreichen Kunden
statt der Felder 1-3. Fiel Kunde 1 aus, rutschte Kunde 2 beim naechsten
Aufruf in Feld 1 und Logo wie Ansprechpartner verschoben sich mit. Jetzt
feldweise - dadurch bleibt auch ein hochgeladenes Logo beim erneuten
Generieren erhalten, solange der Kundenname im selben Feld steht.
Die drei Kundenbloecke im Formular sind zu einer Schleife
zusammengefasst, damit die Upload-Felder nicht dreifach gepflegt werden
muessen.
README, AGENTS.md und Hilfeseite nachgezogen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die Willkommensseite ging bisher fest in die Lobby-Playlist. Welche
Screens Begruessungsschirme sind, ist aber eine Eigenschaft der
Installation und nicht des einzelnen Kundenbesuchs - deshalb ein Flag
pro Screen statt einer Auswahl bei jedem Vorgang.
- Neue Screen-Einstellung "welcome_enabled" (Checkbox im Tab
Einstellungen). Die generierte welcome.html wird in jeden markierten
Screen des Standorts geschrieben und dort an Position 0 gesetzt.
- welcome_target_screens() faellt nur auf "lobby" zurueck, wenn kein
Screen des Standorts den Schluessel besitzt. Bestehende Standorte
verhalten sich damit ohne Konfigurationsaufwand unveraendert.
- add_customer_to_playlists() (frueher add_customer_to_lobby_playlist)
raeumt welcome.html aus allen Screens des Standorts und fuegt sie nur
in den Zielscreens wieder ein. Ein abgewaehlter Screen bleibt so nicht
mit einer alten Begruessung stehen.
- Eingefuegt wird ein Dict statt eines Strings, damit der Eintrag
enabled und schedule tragen kann.
- Optionales "Anzeigen bis" im Formular: setzt eine Zeitsteuerung, die
Seite verschwindet danach auf allen Screens von selbst.
- Das Formular zeigt die aktuellen Zielscreens an und meldet
verstaendlich, wenn keiner markiert ist.
- screens.setdefault("lobby", {}) entfernt - das legte an Standorten
ohne Lobby stillschweigend einen Screen an. Es werden nur noch
vorhandene Screens bespielt.
Die Seite referenziert alle Bilder absolut (/static/..., /media/...),
ist also ortsunabhaengig; je Screen liegt eine identische Kopie.
README, AGENTS.md und die Hilfeseite nachgezogen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die Zeitsteuerung fuer Playlist-Eintraege ist seit 6.1.0 dazugekommen.
AGENTS.md versieht Feature-Abschnitte mit einer Versionsangabe - der
Abschnitt "Zeitsteuerung" traegt sie jetzt nach.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
AGENTS.md:
- Helper-Liste nannte playlist_item_enabled(), die es nicht mehr gibt;
ersetzt durch is_item_active() und die neuen Schedule-Helfer
- Playlist-Items: auch Datei-Eintraege koennen Dicts sein, save_playlist
kopiert bestehende Dicts, daher ueberlebt schedule das Umsortieren
- Neuer Abschnitt "Zeitsteuerung": Format, Auswertungsregeln,
Reload-Kopplung ueber playlist_hash() und die beteiligten Stellen.
Festgehalten sind besonders die Punkte, die man beim Umbau kaputt
macht: unlesbare Angaben blenden nicht aus, Mitternachtsfenster
gehoert zum Starttag, daily ignoriert days.
DESIGN.md:
- Playlist-Grid war mit 6 Spalten dokumentiert, tatsaechlich sind es 7
(Edit-Button fehlte). Dazu die Regel, dass Statusmarkierungen in den
.playlist-name-Span gehoeren - als Geschwisterelement verschieben sie
die gesamte Zeile.
- Cards: festgehalten, dass .card global gestylt ist und deshalb nicht
zum Gruppieren von Formularfeldern taugt; dafuer schlichte Zeilen mit
<hr> + <h3>.
- Schedule-Badge dokumentiert.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- Neue Config-Felder: passthrough_params (true/false) pro URL-Item
- Edit-Modal in admin.html + priority.html mit Checkbox
- Player checkt item.passthrough === true vor appendParams()
- Default: false (keine Parameter-Übergabe ohne Checkbox)
- Link-Icon (ti-link / ti-link-off) in Playlist-Zeile als Status-Indikator
- Doku: help.html, README.md, AGENTS.md
- User kann nach TOTP-Eingabe das Gerät für 1–30 Tage speichern
- Cookie mfa_trust mit zufälligem Token, gespeichert in trusted_devices[]
- Nächstes POST /login: Cookie prüfen → gültiges Token → MFA überspringen
- Abgelaufene Einträge werden beim Login automatisch bereinigt
- Logout + MFA-Deaktivierung löschen Cookie + trusted_devices
- mfa_verify.html: checkbox + days-select (1/3/7/14/30 Tage)