From 302811fe29f969dec1464e562bd1506e34423a34 Mon Sep 17 00:00:00 2001 From: Erik Thiele Date: Wed, 23 Sep 2026 19:55:53 +0200 Subject: [PATCH] docs: README und Hilfeseite auf Stand 6.2.11 bringen Co-Authored-By: Claude Opus 5 --- README.md | 25 ++++++++++++++++++------- app.py | 2 +- templates/help.html | 7 +++++-- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index d22d7e9..597c01f 100755 --- a/README.md +++ b/README.md @@ -9,8 +9,8 @@ Browserbasiertes Digital-Signage-System für interne Info-Screens. - Browserbasierter Player (Kiosk-Modus, Chromium, Firefox) - Bilder, Videos (MP4/H.264), HTML-Seiten, URL-Playlist-Einträge - **Multi-Standort**: Standorte (sites) gruppieren Screens -- **Priority-Playlist**: pro Standort; die Inhalte laufen auf allen Screens **dieses** Standorts, nicht standortübergreifend -- **Willkommensseite**: bis zu 3 Kundenlogos via OpenAI + Brandfetch oder **manueller Upload mit automatischem Freistellen** (transparenter Hintergrund), pro Standort konfigurierbares Hintergrundbild; erscheint auf allen Screens mit `welcome_enabled` (mehrere möglich), optional mit Ablaufdatum +- **Priority-Playlist**: pro Standort; die Inhalte laufen auf allen Screens **dieses** Standorts, nicht standortübergreifend. Sie werden zusätzlich als **reine Vorschau** oberhalb jeder Screen-Playlist angezeigt (grau, mit „Prio"-Badge), damit sie beim Bearbeiten nicht übersehen werden – bedient wird weiterhin nur auf der Priority-Seite +- **Willkommensseite** (ohne Login erreichbar): bis zu 3 Kundenlogos via OpenAI + Brandfetch oder **manueller Upload mit automatischem Freistellen** (transparenter Hintergrund), pro Standort konfigurierbares Hintergrundbild; erscheint auf allen Screens mit `welcome_enabled` (mehrere möglich), optional mit Ablaufdatum - Pro Screen eigene Playlist mit Drag-&-Drop-Reihenfolge - Auto-Reload bei Playlist-Änderungen - Newsticker pro Screen @@ -22,8 +22,8 @@ Browserbasiertes Digital-Signage-System für interne Info-Screens. - **User-Verwaltung**: Mehrere User mit Rollen (Admin / Superuser / User), E-Mail als Login, Passwort-Hashing (scrypt), Berechtigungen pro Standort - **Passwort-Workflow**: First-Login-Änderung, Admin-Reset mit temporärem Passwort, Notfall-Login bei fehlendem Hash - **MFA (Multi-Faktor)**: Optionale TOTP-Authentifizierung (Google Authenticator, Authy) per User aktivierbar; QR-Code-Scan + Code-Verifikation, 8 Recovery-Codes, Deaktivierung mit Passwort-Bestätigung, **Trusted Device** (Gerät für 1–30 Tage speichern, überspringt MFA beim nächsten Login) -- **Admin Dashboard**: `/admin/dashboard` – Statistiken (Sites, Screens, User, Admins, Superuser) mit Sparkline-Charts + Trendanzeige, Aktivitätsverlauf -- **Aktivitätsverlauf**: Alle Erstell-/Lösch-/Änderungsaktionen sowie Login/Logout werden in `history.json` protokolliert und im Dashboard angezeigt +- **Admin Dashboard**: `/admin/dashboard` – Statistiken (Sites, Screens, User, Admins, Superuser) mit Sparkline-Charts + Trendanzeige, Aktivitätsverlauf mit Seitennavigation +- **Aktivitätsverlauf**: Alle Erstell-/Lösch-/Änderungsaktionen sowie Login/Logout werden in `history.json` protokolliert (bis zu 1000 Einträge) und im Dashboard seitenweise angezeigt (50 je Seite) - Tab-basierte Admin-UI pro Screen: Playlist, Einstellungen, Aktionen, Digital Voice Agent, Medien, Info (Tabler Tabs) - **Zeitsteuerung**: Pro Playlist-Eintrag (URL *und* Datei, auch in der Priority-Playlist) ein Zeitfenster festlegen – einmalig (Datum + Uhrzeit), täglich oder wöchentlich (Uhrzeit + optionaler Gültigkeitszeitraum, wöchentlich zusätzlich mit Wochentagen). Fenster über Mitternacht werden unterstützt. Ein "Zeit"-Badge in der Playlist-Zeile zeigt die Einstellung im Tooltip - **Query-Parameter-Passthrough**: Per Player-URL übergebene Query-Parameter (z. B. `/player/stuttgart/lobby?customer=acme`) können pro Playlist-URL im Edit-Modal aktiviert werden – standardmäßig aus. Link-Icon in der Playlist-Zeile zeigt Status (an/aus) an. @@ -207,7 +207,7 @@ Beides fehlte anfangs und machte die Fehlersuche unnötig schwer. | `GET /login` | Admin-Login | | `GET /logout` | Ausloggen | | `GET /admin` | Redirect zum ersten konfigurierten Standort | -| `GET /admin/dashboard` | Admin Dashboard (Statistiken + Verlauf) | +| `GET /admin/dashboard` | Admin Dashboard (Statistiken + Verlauf, `?page=`) | | `GET /admin/` | Admin-Dashboard für einen Standort | | `GET /admin//priority` | Priority-Playlist (separate Seite) | | `POST /admin//update/` | Allgemeine Screen-Einstellungen speichern (Intervall, Newsticker, Bilder/Videos, stay_on_first) | @@ -226,7 +226,7 @@ Beides fehlte anfangs und machte die Fehlersuche unnötig schwer. | `POST /admin//delete-background` | Hintergrundbild zurücksetzen | | `GET /player//` | Player-Ansicht | | `GET /playlist///hash` | Playlist-Checksumme (für Auto-Reload) + Heartbeat (Online-Status) | -| `GET /willkommen?site=` | Willkommensseite-Formular (GET + POST) | +| `GET /willkommen?site=` | Willkommensseite-Formular (GET + POST) – **ohne Login** | | `POST /api/customer` | API-Endpunkt für Willkommensseite (JSON) | | `GET /change-password` | Passwort ändern (First-Login / nach Admin-Reset) | | `GET /admin/users` | User-Liste (Admin) | @@ -287,6 +287,8 @@ http://localhost:5005/admin/dashboard - 5 Statistik-Cards (Standorte, Screens, User, Admins, Superuser) mit ApexCharts-Sparkline + Trendanzeige - Aktivitätsverlauf (History) als Liste mit Zeitstempel, Aktion und User - Alle Erstell-/Lösch-/Änderungsaktionen sowie Login/Logout werden protokolliert +- **Seitennavigation**: 50 Einträge je Seite (`HISTORY_PER_PAGE`), Aufruf über `?page=`; aufbewahrt werden 1000 Einträge (`HISTORY_MAX`) +- Kennzahlen und Sparklines beziehen sich immer auf die **jüngsten 30 Aktionen** und ändern sich beim Blättern bewusst nicht – sonst würden die Trendpfeile springen, obwohl sich nichts geändert hat ### Player-URL @@ -316,6 +318,8 @@ Beispiel: http://localhost:5005/willkommen?site=stuttgart ``` +**Ohne Login erreichbar:** Die Seite ist bewusst nicht durch `@login_required` geschützt, damit auch Mitarbeitende ohne Benutzerkonto eine Begrüßung erstellen können. Ein angemeldeter User sieht dabei weiterhin nur seine freigegebenen Standorte; ohne Anmeldung stehen alle Standorte zur Auswahl, ein unbekannter Standort führt zu 403. Im Aktivitätsverlauf erscheinen solche Einträge als „nicht angemeldet". Die programmatische Variante `POST /api/customer` bleibt angemeldet. + Maximal 3 Kunden eingeben → Logos werden via OpenAI + Brandfetch gesucht → `welcome.html` wird in den Playlists aller Zielscreens vorne eingefügt. Pro Standort kann ein eigenes Hintergrundbild hochgeladen werden (Fallback auf `static/wallpaper.png`). **Zielscreens:** Jeder Screen mit `welcome_enabled` (Schalter „Willkommensseite hier anzeigen" im Tab Einstellungen). Besitzt kein Screen des Standorts den Schlüssel, greift das alte Verhalten und die Seite geht nur in `lobby`. @@ -474,6 +478,8 @@ Liegt in `config.json` unter `sites..priority`, die Medien unter `media/`**, damit das Speichern der Reihenfolge (`savePlaylist()`) sie nicht mit einsammelt und in die Screen-Playlist schreibt. + > Früher lag die Priority-Playlist global unter `config.priority` und wirkte auf *alle* Standorte. `get_priority_config()` übernimmt einen solchen Altbestand beim ersten Zugriff einmalig in den jeweiligen Standort. Die Ordnernamen `priority` und `logos` sind unter `media//` **reserviert** und werden bei der Screen-Erkennung übersprungen – sonst würden sie als Screens in der Oberfläche auftauchen. @@ -490,7 +496,7 @@ Ein Eintrag ist entweder ein String (Dateiname oder URL, Altbestand) oder ein Di { "url": "https://example.com", "zoom": 1.0, // Zoom-Faktor im Player - "enabled": true, // Checkbox in der Playlist + "enabled": true, // Checkbox in der Playlist (nur der Schalter, nicht das Zeitfenster) "passthrough_params": false, // Query-Parameter der Player-URL durchreichen "schedule": { ... } // optional, siehe unten } @@ -535,6 +541,9 @@ Optional pro Eintrag. Ohne `schedule` läuft der Eintrag immer (sofern `enabled` - Unlesbare oder unvollständige Zeitangaben blenden den Eintrag **nicht** aus – ein Konfigurationsfehler soll nicht dazu führen, dass stillschweigend nichts mehr läuft. - `_schedule_time()` liest neben `"08:00"` auch volle ISO-Zeitstempel, damit Einträge aus älteren Versionen unverändert weiterlaufen. - Der Aktiv-Zustand fliesst in `/playlist///hash` ein, damit der Player beim Öffnen und Schliessen eines Zeitfensters von selbst neu lädt. +- **Checkbox und Zeitfenster sind getrennt:** Die Checkbox in der Playlist-Zeile zeigt ausschliesslich den gespeicherten Schalter `enabled`, nicht den momentanen Zeitfenster-Zustand. Sie bleibt also gesetzt, auch wenn ein zeitgesteuerter Eintrag gerade nicht läuft. Ob er gerade läuft, sagt das „Zeit"-Badge: blau = läuft, grau = ausserhalb des Fensters (Tooltip nennt den Grund). Abgespielt wird nur, was **beides** erfüllt – Haken gesetzt *und* im Zeitfenster. + +> Bis Version 6.2.4 zeigte die Checkbox den ausgewerteten Zustand. Wurde die Playlist ausserhalb des Zeitfensters gespeichert, schrieb die Oberfläche `enabled: false` in die Konfiguration und der Eintrag war dauerhaft abgeschaltet. Der Fehler ist behoben, wirkt aber nicht rückwirkend: bereits betroffene Einträge müssen einmal von Hand wieder aktiviert werden. --- @@ -552,6 +561,7 @@ Optional pro Eintrag. Ohne `schedule` läuft der Eintrag immer (sofern `enabled` - `_in_validity_range(schedule, day)` – optionalen Gültigkeitszeitraum prüfen - `schedule_text(schedule)` – Jinja-Filter: Klartext einer Zeitsteuerung für Tooltips - `load_priority_files(site)` – Priority-Playlist eines Standorts + Dateien laden +- `_load_history()` / `get_history(limit, offset)` / `get_history_count()` – Aktivitätsverlauf lesen, seitenweise ausschneiden, zählen - `get_priority_config(cfg, site)` – Priority-Konfiguration des Standorts (übernimmt einmalig einen globalen Altbestand) - `priority_dir(site)` – Pfad zu `media//priority/` - `welcome_target_screens(config, site)` – Zielscreens der Willkommensseite (Fallback `lobby`) @@ -581,6 +591,7 @@ Wird über `localStorage("signage-theme")` persistiert. Umschalt-Button im Heade ## Sicherheit - Admin-Bereich per Flask-Login geschützt (E-Mail + Passwort) +- **Ohne Login erreichbar** sind: Player und Medien (die Abspielgeräte melden sich nicht an) sowie das Formular der Willkommensseite. Letzteres legt Dateien an, schreibt in die Konfiguration und löst kostenpflichtige Logo-Abfragen aus – bei einer aus dem Internet erreichbaren Instanz empfiehlt sich eine Einschränkung auf das interne Netz im Reverse Proxy - Optionale MFA (TOTP) per User aktivierbar (Google Authenticator, Authy) - 8 Recovery-Codes pro User, einmalig bei Aktivierung angezeigt - Passwörter gehasht (scrypt) in `users.json` diff --git a/app.py b/app.py index 279167e..98258c4 100755 --- a/app.py +++ b/app.py @@ -53,7 +53,7 @@ HISTORY_FILE = os.path.join(BASE_DIR, "history.json") # Aktivitätsverlauf HISTORY_MAX = 1000 # so viele Einträge werden aufbewahrt HISTORY_PER_PAGE = 50 # Einträge je Seite im Dashboard-Verlauf -APP_VERSION = "6.2.10" +APP_VERSION = "6.2.11" UPLOAD_EXTENSIONS = {".jpg", ".jpeg", ".png", ".mp4"} app = Flask(__name__) diff --git a/templates/help.html b/templates/help.html index 7d32b8e..2d80258 100644 --- a/templates/help.html +++ b/templates/help.html @@ -104,8 +104,8 @@
  • Medien hochladen: Im Tab "Medien" eine Datei auswählen und hochladen. Unterstützt werden Bilder (JPG, PNG) und Videos (MP4).
  • URL hinzufügen: Im Tab "Playlist" eine URL eingeben und optional den Zoom-Faktor anpassen.
  • Sortieren: Per Drag & Drop die Reihenfolge der Playlist-Einträge ändern (Ziehgriff links).
  • -
  • Deaktivieren: Mit der Checkbox einzelne Einträge temporär ausblenden.
  • -
  • Löschen: Über den roten Papierkorb-Button.
  • +
  • Deaktivieren: Mit der Checkbox einzelne Einträge temporär ausblenden. Die Checkbox ist ein reiner Schalter und hat mit der Zeitsteuerung nichts zu tun: Bei einem zeitgesteuerten Eintrag bleibt der Haken gesetzt, auch wenn der Eintrag gerade nicht läuft. Ob er läuft, zeigt das Zeit-Badge – Zeit blau = läuft gerade, Zeit grau = ausserhalb des Zeitfensters. Abgespielt wird nur, was beides erfüllt: Haken gesetzt und im Zeitfenster.
  • +
  • Löschen: Über den roten Papierkorb-Button. Die Datei wird dabei entfernt und der Eintrag aus der Playlist genommen.
  • Bearbeiten: Der Edit-Button öffnet einen Dialog. Bei URLs lassen sich dort Adresse, Zoom, Query-Parameter-Passthrough und Zeitsteuerung ändern; bei Bildern, Videos und HTML-Seiten die Zeitsteuerung.
  • Zeitsteuerung: Einträge können nur zu bestimmten Zeiten laufen – siehe Zeitsteuerung. Ein Badge Zeit in der Playlist-Zeile zeigt an, dass ein Eintrag zeitgesteuert ist; der Tooltip nennt die Einstellung im Klartext.
  • Query-Parameter-Passthrough: Per URL-Edit-Button (Stift-Icon) im Playlist-Eintrag kann pro URL gesteuert werden, ob Query-Parameter von der Player-URL an die Playlist-URL übergeben werden. Standardmäßig aus – Checkbox "Query-Parameter an diese URL übergeben" aktivieren wenn gewünscht. Ein Link-Icon in der Playlist-Zeile zeigt den Status: = an, = aus.
  • @@ -177,6 +177,7 @@
  • Priority muss für den Standort aktiviert sein (config.json → sites.<standort>.priority.enabled)
  • Die Zeitsteuerung steht hier genauso zur Verfügung wie in den Screen-Playlists
  • Jeder Standort hat seine eigene Priority-Playlist – Inhalte eines Standorts erscheinen nie auf den Screens eines anderen.
  • +
  • Vorschau in den Screen-Playlisten: Die Priority-Einträge werden zusätzlich oberhalb jeder normalen Playlist angezeigt – ausgegraut und mit rotem Prio-Badge. Das ist eine reine Anzeige: Sie lässt sich dort nicht sortieren, bearbeiten oder löschen. So ist beim Bearbeiten einer Screen-Playlist sofort sichtbar, was dem Screen ohnehin noch vorweg läuft, ohne dass man in den anderen Menüpunkt wechseln muss. Geändert wird weiterhin ausschliesslich auf der Priority-Seite.
  • @@ -248,6 +249,7 @@

    Willkommensseite

    Auf der Willkommensseite können bis zu 3 Kundennamen eingegeben werden. Die Logos werden automatisch via OpenAI + Brandfetch gesucht.

    +

    Ohne Anmeldung nutzbar: Das Formular kann auch ohne Benutzerkonto aufgerufen werden – etwa am Empfang. Wer angemeldet ist, sieht weiterhin nur die eigenen Standorte; ohne Anmeldung stehen alle zur Auswahl. Im Aktivitätsverlauf erscheinen solche Einträge als „nicht angemeldet".

    • Aufruf über /willkommen?site=<standort> (oder Menüpunkt)
    • Zielscreens: Die generierte welcome.html wird automatisch an den Anfang der Playlist jedes Screens gesetzt, bei dem im Tab "Einstellungen" die Option Willkommensseite hier anzeigen aktiv ist. So lässt sich dieselbe Begrüßung auf mehreren Screens zeigen, ohne sie mehrfach anzulegen. Ist an einem Standort nichts eingestellt, geht sie wie bisher in die Lobby.
    • @@ -308,6 +310,7 @@
    • Sparkline: Kleine Liniendiagramme zeigen den Verlauf der letzten Änderungen
    • Trend: Pfeil nach oben/unten mit Netto-Änderung aus den letzten 30 Aktionen
    • Aktivitätsverlauf: Alle Erstell-, Lösch-, Änderungsaktionen sowie An-/Abmeldungen werden protokolliert
    • +
    • Blättern: Der Verlauf zeigt 50 Einträge je Seite; über die Leiste unter der Liste lässt sich weiter zurückblättern. Aufbewahrt werden die letzten 1000 Einträge. Statistik-Cards, Sparklines und Trendpfeile beziehen sich dabei immer auf die jüngsten 30 Aktionen und ändern sich beim Blättern nicht.