feat: Willkommensseite auf mehreren Screens anzeigen
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>
This commit is contained in:
@@ -296,57 +296,134 @@ def generate_welcome_html(customer_names, logo_urls, contacts=None, site="stuttg
|
||||
# Speichern + Playlist-Einfügung
|
||||
# -------------------------------------------------
|
||||
|
||||
def save_welcome_page(customer_names, logo_urls, contacts=None, site="stuttgart", background_url=None):
|
||||
"""Speichert die generierte Willkommensseite als welcome.html im Lobby-Verzeichnis.
|
||||
def welcome_target_screens(config, site):
|
||||
"""Ermittelt die Screens eines Standorts, auf denen die Willkommensseite laufen soll.
|
||||
|
||||
Ein Screen ist Ziel, wenn "welcome_enabled" gesetzt ist. Ist der Schluessel bei
|
||||
keinem Screen des Standorts vorhanden, greift das alte Verhalten: nur "lobby".
|
||||
Damit bleiben bestehende Standorte ohne Konfigurationsaufwand unveraendert."""
|
||||
screens = config.get("sites", {}).get(site, {}).get("screens", {})
|
||||
|
||||
configured = [name for name, cfg in screens.items()
|
||||
if isinstance(cfg, dict) and cfg.get("welcome_enabled")]
|
||||
if configured:
|
||||
return sorted(configured)
|
||||
|
||||
# Kein Screen markiert: nur dann auf "lobby" zurückfallen, wenn noch nirgends
|
||||
# eine bewusste Entscheidung getroffen wurde. Wurde das Häkchen überall
|
||||
# entfernt, ist "keine Screens" das gewollte Ergebnis.
|
||||
entschieden = any(isinstance(cfg, dict) and "welcome_enabled" in cfg
|
||||
for cfg in screens.values())
|
||||
if entschieden:
|
||||
return []
|
||||
|
||||
return ["lobby"] if "lobby" in screens else []
|
||||
|
||||
|
||||
def save_welcome_page(customer_names, logo_urls, contacts=None, site="stuttgart",
|
||||
background_url=None, screens=None):
|
||||
"""Speichert die generierte Willkommensseite als welcome.html in den Zielscreens.
|
||||
|
||||
screens: Liste der Screen-Namen; None → Zielscreens aus der Konfiguration.
|
||||
contacts: Liste der Ansprechpartner-Texte (Markdown, optional)
|
||||
background_url: Benutzerdefiniertes Hintergrundbild oder None (Standard).
|
||||
Gibt den Dateinamen zurück oder None bei Fehler."""
|
||||
try:
|
||||
welcome_dir = os.path.join(MEDIA_DIR, site, "lobby")
|
||||
os.makedirs(welcome_dir, exist_ok=True)
|
||||
filepath = os.path.join(os.path.abspath(welcome_dir), WELCOME_FILENAME)
|
||||
html_content = generate_welcome_html(customer_names, logo_urls, contacts=contacts, site=site, background_url=background_url)
|
||||
Gibt den Dateinamen zurück oder None bei Fehler.
|
||||
|
||||
Die Seite referenziert alle Bilder absolut (/static/..., /media/<site>/...),
|
||||
ist also ortsunabhängig - eine Kopie je Screen rendert identisch."""
|
||||
try:
|
||||
from app import load_config
|
||||
|
||||
if screens is None:
|
||||
screens = welcome_target_screens(load_config(), site)
|
||||
|
||||
if not screens:
|
||||
print(f"⚠️ Generate - Kein Zielscreen für die Willkommensseite (site: {site})")
|
||||
return None
|
||||
|
||||
html_content = generate_welcome_html(customer_names, logo_urls, contacts=contacts,
|
||||
site=site, background_url=background_url)
|
||||
|
||||
for screen in screens:
|
||||
welcome_dir = os.path.join(MEDIA_DIR, site, screen)
|
||||
os.makedirs(welcome_dir, exist_ok=True)
|
||||
filepath = os.path.join(os.path.abspath(welcome_dir), WELCOME_FILENAME)
|
||||
|
||||
with open(filepath, "w", encoding="utf-8") as f:
|
||||
f.write(html_content)
|
||||
if os.path.getsize(filepath) == 0:
|
||||
raise IOError("File not written")
|
||||
print(f"✅ Generate - Willkommensseite gespeichert in: {filepath}")
|
||||
|
||||
with open(filepath, "w", encoding="utf-8") as f:
|
||||
f.write(html_content)
|
||||
if os.path.getsize(filepath) == 0:
|
||||
raise IOError("File not written")
|
||||
names_str = ", ".join(customer_names)
|
||||
print(f"✅ Generate - Willkommensseite generiert für: {names_str} (site: {site})")
|
||||
print(f"✅ Generate - Willkommensseite gespeichert in: {filepath}")
|
||||
print(f"✅ Generate - Willkommensseite generiert für: {names_str} "
|
||||
f"(site: {site}, screens: {', '.join(screens)})")
|
||||
return WELCOME_FILENAME
|
||||
except Exception as e:
|
||||
print(f"❌ Error saving welcome page: {e}")
|
||||
return None
|
||||
|
||||
|
||||
def add_customer_to_lobby_playlist(html_filename, site="stuttgart"):
|
||||
"""Fügt die Willkommensseite (welcome.html) an Position 0 in die Lobby-Playlist ein.
|
||||
Entfernt vorher alle vorhandenen welcome.html-Einträge (als String oder Dict).
|
||||
def _strip_welcome(playlist, filename):
|
||||
"""Entfernt alle welcome.html-Einträge aus einer Playlist (String- und Dict-Form)."""
|
||||
playlist[:] = [
|
||||
item for item in playlist
|
||||
if not (
|
||||
(isinstance(item, str) and item == filename) or
|
||||
(isinstance(item, dict) and item.get("name") == filename)
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
def add_customer_to_playlists(html_filename, site="stuttgart", screens=None, valid_until=None):
|
||||
"""Setzt die Willkommensseite an Position 0 der Playlist jedes Zielscreens.
|
||||
|
||||
screens: Liste der Zielscreens; None → aus der Konfiguration ermitteln.
|
||||
valid_until: optionales Datum "YYYY-MM-DD". Ist es gesetzt, bekommt der
|
||||
Eintrag eine Zeitsteuerung und verschwindet danach von selbst.
|
||||
|
||||
Aus allen übrigen Screens des Standorts wird die Seite entfernt, damit ein
|
||||
abgewählter Screen nicht mit einer alten Begrüßung stehen bleibt.
|
||||
Importiert load_config/save_config aus app.py (kein Zirkelimport)."""
|
||||
try:
|
||||
from app import load_config, save_config
|
||||
|
||||
config = load_config()
|
||||
sites_cfg = config.setdefault("sites", {})
|
||||
site_cfg = sites_cfg.setdefault(site, {"screens": {}})
|
||||
screens = site_cfg.setdefault("screens", {})
|
||||
lobby = screens.setdefault("lobby", {})
|
||||
playlist = lobby.setdefault("playlist", [])
|
||||
site_cfg = config.setdefault("sites", {}).setdefault(site, {"screens": {}})
|
||||
all_screens = site_cfg.setdefault("screens", {})
|
||||
|
||||
if screens is None:
|
||||
screens = welcome_target_screens(config, site)
|
||||
|
||||
# Nur Screens, die es wirklich gibt - kein stillschweigendes Anlegen
|
||||
targets = [name for name in screens if name in all_screens]
|
||||
|
||||
entry = {"name": html_filename, "enabled": True}
|
||||
if valid_until:
|
||||
# Ganztaegig bis einschliesslich valid_until
|
||||
entry["schedule"] = {
|
||||
"mode": "daily",
|
||||
"start": "00:00",
|
||||
"end": "23:59",
|
||||
"valid_until": valid_until
|
||||
}
|
||||
|
||||
for name, screen_cfg in all_screens.items():
|
||||
if not isinstance(screen_cfg, dict):
|
||||
continue
|
||||
playlist = screen_cfg.setdefault("playlist", [])
|
||||
_strip_welcome(playlist, html_filename)
|
||||
if name in targets:
|
||||
playlist.insert(0, dict(entry))
|
||||
|
||||
full_filename = f"{html_filename}"
|
||||
# Alte welcome.html-Einträge entfernen (sowohl String- als auch Dict-Form)
|
||||
playlist[:] = [
|
||||
item for item in playlist
|
||||
if not (
|
||||
(isinstance(item, str) and item == full_filename) or
|
||||
(isinstance(item, dict) and item.get("name") == full_filename)
|
||||
)
|
||||
]
|
||||
playlist.insert(0, full_filename)
|
||||
save_config(config)
|
||||
print(f"✅ Generate - Willkommensseite in Lobby-Playliste platziert (site: {site})")
|
||||
return True
|
||||
|
||||
if targets:
|
||||
print(f"✅ Generate - Willkommensseite platziert (site: {site}, "
|
||||
f"screens: {', '.join(targets)})")
|
||||
else:
|
||||
print(f"⚠️ Generate - Kein Zielscreen vorhanden (site: {site})")
|
||||
return bool(targets)
|
||||
except Exception as e:
|
||||
print(f"❌ Generate - Error adding to playlist: {e}")
|
||||
return False
|
||||
|
||||
Reference in New Issue
Block a user