From 0efc5bb3462551a6fa8f4c8d26b8d0c7c97f607c Mon Sep 17 00:00:00 2001 From: Erik Thiele Date: Sun, 7 Jun 2026 12:27:19 +0200 Subject: [PATCH] Tabs in der Admin UI --- .DS_Store | Bin 14340 -> 14340 bytes AGENTS.md | 5 + README.md | 21 +- app.py | 7 +- config.json | 8 +- session-ses_1e96.md | 2724 +++++++++++++++++++++++++++++++++++++++ templates/admin.html | 359 +++--- templates/priority.html | 214 +-- 8 files changed, 3076 insertions(+), 262 deletions(-) create mode 100644 session-ses_1e96.md diff --git a/.DS_Store b/.DS_Store index dc112429e83577910a64a76033c8441a25ead0db..3b23d7883abae0df96a9b1016070beea299f90f1 100644 GIT binary patch delta 18 ZcmZoEXeromSAvmo@_q@i&0i!0` angelegt werden. - `delete_site` entfernt den Standort aus Config und löscht das Medienverzeichnis rekursiv. +- `config.json["server_url"]` (z. B. `http://signage.ccmake.de`) wird in der Admin-Ansicht für die Player-URLs verwendet. +- Screen-Card-Body hat Tabler-Tabs: **Playlist** (1, aktiv), **Einstellungen** (2), **Medien** (3); Priority-Seite ebenfalls Tabs **Playlist** und **Medien**. +- Tab-Reihenfolge in Screen-Cards: Playlist → Einstellungen → Medien. +- Player-URL im Screen-Header ist ein klickbarer Link in grauer Farbe. ## Repo Quirks @@ -67,3 +71,4 @@ Standorte (sites) sind die oberste Organisationsebene und gruppieren Screens. - Wichtige Helper-Funktionen in `app.py`: `load_config()`, `save_config()`, `get_site_list()`, `get_screen_config()`, `is_url()`, `normalize_url()`, `playlist_item_name()`, `playlist_item_enabled()`, `load_priority_files()`, `prio_redirect()`. - `welcome.html` wird in `media//lobby/` gespeichert. - `search_customer_logo` in `generate_welcome_page.py` nutzt OpenAI GPT-4 + Brandfetch CDN. +- `admin_priority` rendert `priority.html` mit `site_list`, `current_site`, `priority_files`, `server_url`. diff --git a/README.md b/README.md index 2ef1193..6cb6927 100755 --- a/README.md +++ b/README.md @@ -15,6 +15,8 @@ Browserbasiertes Digital-Signage-System für interne Info-Screens. - Auto-Reload bei Playlist-Änderungen - Newsticker pro Screen - **Custom-URL-Button**: pro Screen konfigurierbarer Aktions-Button oben links im Player (öffnet URL in iframe-Overlay mit Zurück-Button oder per Direkt-Weiterleitung) +- Tab-basierte Admin-UI pro Screen: Playlist, Einstellungen, Medien (Tabler Tabs) +- Priority-Seite ebenfalls mit Tabs: Playlist und Medien - Dark Mode (localStorage-persistiert) - CI-konformes Admin-UI (CANCOM-Design: `brand-surface`, `nav-surface` rot) @@ -118,11 +120,15 @@ docker compose up -d | `GET /admin` | Redirect zum ersten konfigurierten Standort | | `GET /admin/` | Admin-Dashboard für einen Standort | | `GET /admin//priority` | Priority-Playlist (separate Seite) | -| `GET /admin//update/` | Screen-Einstellungen speichern (POST) | -| `GET /admin//upload/` | Medien hochladen (POST) | -| `GET /admin//add-url/` | URL zur Playlist hinzufügen (POST) | -| `GET /admin//delete//` | Datei löschen (POST) | -| `GET /admin//playlist/` | Playlist-Reihenfolge speichern (POST JSON) | +| `POST /admin//update/` | Screen-Einstellungen speichern | +| `POST /admin//upload/` | Medien hochladen | +| `POST /admin//add-url/` | URL zur Playlist hinzufügen | +| `POST /admin//delete//` | Datei löschen | +| `POST /admin//playlist/` | Playlist-Reihenfolge speichern (JSON) | +| `POST /admin//delete-screen/` | Screen + Medien löschen | +| `GET /admin//add-screen?name=` | Neuen Screen anlegen | +| `GET /add-site?name=` | Neuen Standort anlegen | +| `POST /admin//delete-site` | Standort + alle Screens/Medien löschen | | `GET /player//` | Player-Ansicht | | `GET /playlist///hash` | Playlist-Checksumme (für Auto-Reload) | | `GET /willkommen?site=` | Willkommensseite-Formular (GET + POST) | @@ -138,10 +144,10 @@ docker compose up -d http://localhost:5005/admin/ ``` -- Screens konfigurieren +- Screens konfigurieren (Tab-basiert: Playlist, Einstellungen, Medien) - Medien hochladen / löschen - Playlist per Drag & Drop sortieren -- Priority-Playlist verwalten +- Priority-Playlist verwalten (ebenfalls mit Tabs) - Willkommensseite generieren (bis zu 3 Kundenlogos) - Custom-URL-Aktionsbutton pro Screen konfigurieren (iframe-Overlay oder Weiterleitung) - Standorte anlegen & löschen @@ -171,6 +177,7 @@ Maximal 3 Kunden eingeben → Logos werden via OpenAI + Brandfetch gesucht → ` ```json { + "server_url": "http://signage.ccmake.de", "admin": { "username": "...", "password": "..." }, "sites": { "stuttgart": { diff --git a/app.py b/app.py index 8c498d1..de498b5 100755 --- a/app.py +++ b/app.py @@ -625,7 +625,8 @@ def admin(site): screen_status=screen_status, version=APP_VERSION, year=datetime.now().year, - hostname=os.uname().nodename + hostname=os.uname().nodename, + server_url=cfg.get("server_url", "") ) @@ -637,17 +638,17 @@ def admin(site): def admin_priority(site): cfg = load_config() site_list = sorted(cfg.get("sites", {}).keys()) - priority_files = load_priority_files() return render_template( "priority.html", site_list=site_list, current_site=site, + priority_files=priority_files, version=APP_VERSION, year=datetime.now().year, hostname=os.uname().nodename, - priority_files=priority_files + server_url=cfg.get("server_url", "") ) diff --git a/config.json b/config.json index 362a31f..15c4481 100755 --- a/config.json +++ b/config.json @@ -1,4 +1,5 @@ { + "server_url": "http://localhost:5005", "priority": { "enabled": true, "playlist": [ @@ -89,12 +90,5 @@ "admin": { "username": "admin", "password": "cancom@2026!" - }, - "screens": { - "lobby": { - "playlist": [ - "welcome.html" - ] - } } } \ No newline at end of file diff --git a/session-ses_1e96.md b/session-ses_1e96.md new file mode 100644 index 0000000..2f31a77 --- /dev/null +++ b/session-ses_1e96.md @@ -0,0 +1,2724 @@ +# Heise Newsticker URL in Player-Playlist integrieren + +**Session ID:** ses_1e960c342ffePr43MUdvy02y6P +**Created:** 5/11/2026, 12:39:55 PM +**Updated:** 6/5/2026, 1:58:02 PM + +--- + +## Assistant (Build · DeepSeek V4 Flash Free · 4.8s) + +**Tool: edit** + +**Input:** +```json +{ + "filePath": "/Users/erik/Documents/DEV/signage/templates/admin.html", + "newString": "
\n \n \n
\n\n
\n

Aktions-Button (Player)

\n
\n \n \n
\n
\n \n \n
", + "oldString": "
\n \n \n
" +} +``` + +**Output:** +``` +Edit applied successfully. +``` + +--- + +## Assistant (Build · DeepSeek V4 Flash Free · 3.8s) + +_Thinking:_ + +Now add the floating button in player.html. I'll add it after the body tag, styled as a fixed-position button at the top-left: + +**Tool: todowrite** + +**Input:** +```json +{ + "todos": [ + { + "priority": "high", + "content": "app.py: add custom_url + custom_url_label to screen config", + "status": "completed" + }, + { + "priority": "high", + "content": "templates/admin.html: add input fields for URL + label in screen settings", + "status": "completed" + }, + { + "priority": "high", + "content": "templates/player.html: add floating button top-left", + "status": "in_progress" + }, + { + "priority": "medium", + "content": "Test and verify", + "status": "pending" + } + ] +} +``` + +**Output:** +``` +[ + { + "content": "app.py: add custom_url + custom_url_label to screen config", + "status": "completed", + "priority": "high" + }, + { + "content": "templates/admin.html: add input fields for URL + label in screen settings", + "status": "completed", + "priority": "high" + }, + { + "content": "templates/player.html: add floating button top-left", + "status": "in_progress", + "priority": "high" + }, + { + "content": "Test and verify", + "status": "pending", + "priority": "medium" + } +] +``` + +--- + +## Assistant (Build · DeepSeek V4 Flash Free · 4.3s) + +**Tool: edit** + +**Input:** +```json +{ + "filePath": "/Users/erik/Documents/DEV/signage/templates/player.html", + "newString": "\n\n{% if custom_url %}\n\n {{ custom_url_label or \"Info\" }}\n\n{% endif %}\n\n\n", + "oldString": "\n\n\n" +} +``` + +**Output:** +``` +Edit applied successfully. +``` + +--- + +## Assistant (Build · DeepSeek V4 Flash Free · 3.6s) + +_Thinking:_ + +Now test: + +**Tool: bash** + +**Input:** +```json +{ + "command": ".venv/bin/python3 -m py_compile app.py && echo \"OK\"", + "description": "Syntax check" +} +``` + +**Output:** +``` +OK + +``` + +--- + +## Assistant (Build · DeepSeek V4 Flash Free · 3.8s) + +**Tool: todowrite** + +**Input:** +```json +{ + "todos": [ + { + "priority": "high", + "content": "app.py: add custom_url + custom_url_label to screen config", + "status": "completed" + }, + { + "priority": "high", + "content": "templates/admin.html: add input fields for URL + label in screen settings", + "status": "completed" + }, + { + "priority": "high", + "content": "templates/player.html: add floating button top-left", + "status": "completed" + }, + { + "priority": "medium", + "content": "Test and verify", + "status": "completed" + } + ] +} +``` + +**Output:** +``` +[ + { + "content": "app.py: add custom_url + custom_url_label to screen config", + "status": "completed", + "priority": "high" + }, + { + "content": "templates/admin.html: add input fields for URL + label in screen settings", + "status": "completed", + "priority": "high" + }, + { + "content": "templates/player.html: add floating button top-left", + "status": "completed", + "priority": "high" + }, + { + "content": "Test and verify", + "status": "completed", + "priority": "medium" + } +] +``` + +--- + +## Assistant (Build · DeepSeek V4 Flash Free · 4.0s) + +Fertig. Im Admin-Bereich gibt es jetzt bei jedem Screen unter „Einstellungen" einen Abschnitt „Aktions-Button (Player)" mit zwei Feldern: + +- **Button-URL** – die Ziel-URL +- **Button-Beschriftung** – Text auf dem Button + +Im Player erscheint der Button oben links (`z-index: 99999`) in CANCOM-Rot und öffnet die URL in einem neuen Tab (`target="_blank"`). Nur sichtbar, wenn eine URL konfiguriert ist. + +--- + +## User + +kann die URL in einen iframe geladen werden, damit dann wieder einen zurück Button hat? + +--- + +## Assistant (Build · DeepSeek V4 Flash Free · 7.5s) + +_Thinking:_ + +The user wants the URL to open in an iframe overlay within the player page, with a back button to return to the playlist. Let me think about the best approach: + +1. When the custom button is clicked, instead of opening in a new tab (`target="_blank"`), it should load the URL into a fullscreen iframe overlay within the player +2. The overlay should have a back/close button to return to the playlist +3. The playlist should pause while the iframe is open + +Let me implement this: + +1. Change the `target="_blank"` link to a JavaScript handler +2. Add an iframe overlay that covers the full screen +3. Add a back button on the overlay +4. Pause the player while the overlay is shown + +I'll add the overlay HTML and JavaScript to player.html. + +**Tool: edit** + +**Input:** +```json +{ + "filePath": "/Users/erik/Documents/DEV/signage/templates/player.html", + "newString": "\n\n
\n \n \n
\n\n{% if custom_url %}\n\n{% endif %}", + "oldString": "\n\n{% if custom_url %}\n\n {{ custom_url_label or \"Info\" }}\n\n{% endif %}" +} +``` + +**Output:** +``` +Edit applied successfully. +``` + +--- + +## Assistant (Build · DeepSeek V4 Flash Free · 4.2s) + +_Thinking:_ + +Now add the JavaScript functions for openOverlay and closeOverlay. I need to: +1. Pause the player timer when overlay opens +2. Resume when overlay closes +3. Since the player uses `setTimeout(playNext, interval)`, I need to clear the timeout when opening overlay and restart when closing + +Let me add the JS functions. I'll add them at the beginning of the `