Some checks are pending
CI / PHP Lint (push) Waiting to run
CI / PHP Lint (pull_request) Waiting to run
CI / PHP Lint-1 (pull_request) Waiting to run
CI / PHP Lint-1 (push) Waiting to run
CI / Unit Tests & Static Analysis (pull_request) Waiting to run
CI / Unit Tests & Static Analysis (push) Waiting to run
Jede Display-Seite bringt jetzt ihr eigenes Erscheinungsbild mit – der Empfang sieht anders aus als der Tagungsraum nebenan: - eigenes Logo (leer = Logo aus den Einstellungen) - formatfüllendes Hintergrundbild mit einstellbarer Abdunklung (0–90 %), damit die Karte auf hellen Fotos lesbar bleibt - eigene Akzentfarbe für den Knopf (leer = Farbe aus dem Design-Tab) - Karte wahlweise hell oder dunkel; auf Fotos wirkt dunkel meist ruhiger Logo und Hintergrund lassen sich hochladen oder als URL hinterlegen; beim Löschen einer Display-Seite verschwinden die hochgeladenen Dateien mit. Nebenbei aufgeräumt: das Bildfeld (Vorschau + Upload + URL + Entfernen) lag als Funktion in admin/settings.php und wird jetzt von beiden Seiten genutzt – Ui::imageField() für die Darstellung, Upload::resolveField() für die Auswertung. Sicherheit: die Akzentfarbe landet in einem style-Attribut, deshalb wird sie sowohl beim Speichern als auch beim Ausgeben auf eine echte Hex-Farbe geprüft; ein Test hält das fest. Migration 0006, database.sql nachgezogen, 4 neue Tests (42 gesamt), Screenshots ergänzt, Version 2.8.0. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
83 lines
3.8 KiB
Python
Executable file
83 lines
3.8 KiB
Python
Executable file
#!/usr/bin/env python3
|
||
"""Erzeugt die Screenshots in docs/screenshots aus der laufenden Demo-Instanz.
|
||
|
||
Voraussetzung:
|
||
python3 tools/demo/build.py /tmp/uvt-demo
|
||
php -S 127.0.0.1:8123 -t /tmp/uvt-demo &
|
||
|
||
Aufruf:
|
||
python3 tools/screenshots.py [basis-url]
|
||
"""
|
||
import os
|
||
import shutil
|
||
import subprocess
|
||
import sys
|
||
|
||
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||
OUT = os.path.join(ROOT, 'docs', 'screenshots')
|
||
SCALE = 2
|
||
|
||
# (Datei, Pfad, Breite, Hoehe) – Breite/Hoehe in CSS-Pixeln, Ausgabe in 2x
|
||
SHOTS = [
|
||
('login.png', 'login.php?anon=1', 1200, 850),
|
||
('login-branding.png', 'login.php?anon=1&brand=custom', 1200, 850),
|
||
('voucher-form.png', 'index.php', 1200, 880),
|
||
('voucher-result.png', 'index.php?demo=result', 1200, 900),
|
||
('bulk-vouchers.png', 'index.php?demo=bulk', 1200, 800),
|
||
('admin-dashboard.png', 'admin/index.php', 1200, 1400),
|
||
('admin-dashboard-dark.png', 'admin/index.php?theme=dark', 1200, 1400),
|
||
('vouchers.png', 'admin/vouchers.php', 1200, 1120),
|
||
('settings.png', 'admin/settings.php', 1200, 950),
|
||
('settings-login.png', 'admin/settings.php?tab=login', 1200, 1000),
|
||
('settings-branding.png', 'admin/settings.php?tab=branding', 1200, 900),
|
||
('api-keys.png', 'admin/api_keys.php?demo=new', 1200, 830),
|
||
('integrations.png', 'admin/integrations.php', 1200, 900),
|
||
('two-factor.png', 'admin/security.php', 1200, 900),
|
||
('updater.png', 'admin/update.php', 1200, 780),
|
||
('updater-available.png', 'admin/update.php?demo=available', 1200, 780),
|
||
('kiosk-display.png', 'kiosk.php?k=0f1e2d3c4b5a69788796a5b4c3d2e1f0', 1200, 900),
|
||
('kiosk-code.png', 'kiosk.php?k=a1b2c3d4e5f60718293a4b5c6d7e8f90&demo=code', 1200, 900),
|
||
('kiosk-branded.png', 'kiosk.php?k=a1b2c3d4e5f60718293a4b5c6d7e8f90', 1200, 900),
|
||
('kiosks-admin.png', 'admin/kiosks.php', 1200, 780),
|
||
('kiosks-form.png', 'admin/kiosks.php?demo=form', 1200, 1150),
|
||
('mobile-vouchers.png', 'admin/users.php', 430, 860),
|
||
('maintenance.png', 'updater/templates/maintenance.html', 1200, 700),
|
||
]
|
||
|
||
CANDIDATES = [
|
||
os.environ.get('CHROME_BIN', ''),
|
||
'/usr/bin/chromium', '/usr/bin/chromium-browser', '/usr/bin/google-chrome',
|
||
'/opt/pw-browsers/chromium', shutil.which('chromium') or '',
|
||
]
|
||
|
||
|
||
def find_browser() -> str:
|
||
for path in CANDIDATES:
|
||
if path and os.path.isfile(path) and os.access(path, os.X_OK):
|
||
return path
|
||
raise SystemExit('Kein Chromium gefunden – Pfad ueber CHROME_BIN setzen.')
|
||
|
||
|
||
def main() -> int:
|
||
base = (sys.argv[1] if len(sys.argv) > 1 else 'http://127.0.0.1:8123').rstrip('/')
|
||
browser = find_browser()
|
||
os.makedirs(OUT, exist_ok=True)
|
||
|
||
for name, path, width, height in SHOTS:
|
||
target = os.path.join(OUT, name)
|
||
subprocess.run([
|
||
browser, '--headless', '--no-sandbox', '--disable-gpu', '--hide-scrollbars',
|
||
'--force-color-profile=srgb', '--disable-lcd-text', '--font-render-hinting=none',
|
||
'--virtual-time-budget=4000', '--force-prefers-reduced-motion',
|
||
'--force-device-scale-factor=%d' % SCALE,
|
||
'--window-size=%d,%d' % (width, height),
|
||
'--screenshot=%s' % target,
|
||
'%s/%s' % (base, path),
|
||
], check=False, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||
print('%-28s %s' % (name, 'ok' if os.path.exists(target) else 'FEHLER'))
|
||
|
||
return 0
|
||
|
||
|
||
if __name__ == '__main__':
|
||
raise SystemExit(main())
|