diff --git a/Dockerfile b/Dockerfile index 61c3462..4950ca7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,11 +12,11 @@ RUN pip3 install --no-cache-dir \ pretix-pages \ /tmp/pretix-falkenthal-theme -# 3. Primäre Fallback-Farbwerte (#3b1c4a) im Quellbaum auf Royalblau/Indigo umstellen -# (Veranstalter können ihre Shop-Farben weiterhin frei im Web-Interface überschreiben) +# 3. Primäre Fallback-Farbwerte (#3b1c4a) im Quellbaum konsistent auf Indigo (#4f46e5) umstellen +# (Veranstalter können ihre Shop-Farben weiterhin frei im Web-Interface auf Veranstalter- & Event-Ebene überschreiben) RUN sed -i 's/#3b1c4a/#4f46e5/gI' /pretix/src/pretix/base/settings.py && \ find /pretix/src/pretix -type f \( -name "*.scss" -o -name "*.less" -o -name "*.css" \) -exec sed -i \ - -e 's/#3b1c4a/#2563eb/gI' \ + -e 's/#3b1c4a/#4f46e5/gI' \ -e 's/#5f2977/#4f46e5/gI' \ -e 's/#7f4a88/#475569/gI' \ -e 's/#8e44ad/#4f46e5/gI' \ @@ -36,7 +36,7 @@ USER root # 6. Vorkompilierte CSS-Dateien bereinigen & statische Theme-Assets bereitstellen RUN find /pretix/src/pretix/static.dist -type f -name "*.css" -exec sed -i \ - -e 's/#3b1c4a/#2563eb/gI' \ + -e 's/#3b1c4a/#4f46e5/gI' \ -e 's/#5f2977/#4f46e5/gI' \ -e 's/#7f4a88/#475569/gI' \ -e 's/#6c3386/#4f46e5/gI' \ diff --git a/patch_templates.py b/patch_templates.py index e7d0d9b..5badcfc 100644 --- a/patch_templates.py +++ b/patch_templates.py @@ -1,9 +1,11 @@ +import os import re +import sys THEME_REPO_URL = "https://git.falkenthal.me/falkenthal/pretix-falkenthal-theme" PLATFORM_IMPRINT_URL = "https://tickets.falkenthal.me/impressum" PLATFORM_PRIVACY_URL = "https://tickets.falkenthal.me/datenschutz" -ASSET_VERSION = "1.7.3" +ASSET_VERSION = "1.8.0" control_files = [ '/pretix/src/pretix/control/templates/pretixcontrol/base.html', @@ -25,36 +27,115 @@ platform_footer_html = ( '' ) +# 1. Control & Auth Templates patchen (Plattform-Backend: immer Falkenthal-Branding) for p in control_files: + if not os.path.exists(p): + print(f"ERROR: Expected template not found: {p}", file=sys.stderr) + sys.exit(1) + with open(p, 'r', encoding='utf-8') as f: c = f.read() + + # Standard-Pretix-Favicon im Backend durch Falkenthal-Favicon ersetzen c = re.sub(r']*rel=[\"\'](shortcut )?icon[\"\'][^>]*>', '', c, flags=re.I) + + # Eindeutige Body-Klasse für Auth/Login-Seiten setzen (verhindert CSS-Leaks im normalen Backend) + if p.endswith('auth/base.html') and 'falkenthal-auth-body' not in c: + if ']*)class=["\']([^"\']*)["\']', + r'' not in c: + print(f"ERROR: tag not found in {p}", file=sys.stderr) + sys.exit(1) c = c.replace( '', f'' f'' f'' ) + if 'falkenthal-platform-bar' not in c: + if '' not in c: + print(f"ERROR: tag not found in {p}", file=sys.stderr) + sys.exit(1) c = c.replace('', platform_footer_html) + with open(p, 'w', encoding='utf-8') as f: f.write(c) +# 2. Presale Template patchen (Ticketshop: Veranstalter-Favicons respektieren, Fallback = Falkenthal) presale_file = '/pretix/src/pretix/presale/templates/pretixpresale/base.html' +if not os.path.exists(presale_file): + print(f"ERROR: Expected template not found: {presale_file}", file=sys.stderr) + sys.exit(1) + with open(presale_file, 'r', encoding='utf-8') as f: c = f.read() -c = re.sub(r']*rel=[\"\'](shortcut )?icon[\"\'][^>]*>', '', c, flags=re.I) + +# Nur die statischen Standard-Pretix-Favicon-Fallbacks ersetzen, damit individuelle +# Veranstalter-/Event-Favicons ({% if request.event.settings.favicon %}) erhalten bleiben! +c = re.sub( + r']*rel=[\"\'](shortcut )?icon[\"\'][^>]*static\s+[\"\']pretixbase/img/favicon[^\"\']*[\"\'][^>]*>', + '', + c, + flags=re.I, +) +# Falls in einem {% else %}-Zweig der Standard-Favicon-Block nun leer wäre oder direkt vor : if '/static/whitelabel/presale.css' not in c: - c = c.replace( - '', + if '' not in c: + print(f"ERROR: tag not found in {presale_file}", file=sys.stderr) + sys.exit(1) + presale_head_inject = ( + '{% if not request.event or not request.event.settings.favicon %}' f'' f'' + '{% endif %}' f'' ) + c = c.replace('', presale_head_inject) + if 'falkenthal-platform-bar' not in c: + if '' not in c: + print(f"ERROR: tag not found in {presale_file}", file=sys.stderr) + sys.exit(1) c = c.replace('', platform_footer_html) + with open(presale_file, 'w', encoding='utf-8') as f: f.write(c) -print(f"Pretix templates patched successfully (v{ASSET_VERSION}).") +# 3. Globale Fehlerseiten (400, 403, 404, 500, 503) mit Plattform-Rechtstexten ausstatten +error_templates_dir = '/pretix/src/pretix/base/templates' +for err_name in ['400.html', '403.html', '403_csrf.html', '404.html', '500.html', '503.html']: + err_path = os.path.join(error_templates_dir, err_name) + if os.path.exists(err_path): + with open(err_path, 'r', encoding='utf-8') as f: + ec = f.read() + if 'falkenthal-platform-bar' not in ec and '' in ec: + error_footer = ( + '
' + 'Technischer Plattformbetrieb: FALKENTHAL' + ' · ' + f'Plattform-Impressum' + ' · ' + f'Plattform-Datenschutz' + ' · ' + f'Theme & Quellcode (AGPLv3)' + '
' + ) + ec = ec.replace('', error_footer) + with open(err_path, 'w', encoding='utf-8') as f: + f.write(ec) + +print(f"Pretix templates patched and verified successfully (v{ASSET_VERSION}).") + diff --git a/pretix_whitelabel/__init__.py b/pretix_whitelabel/__init__.py index b4a1b55..61d834a 100644 --- a/pretix_whitelabel/__init__.py +++ b/pretix_whitelabel/__init__.py @@ -13,7 +13,7 @@ class WhiteLabelApp(AppConfig): "Custom Slate & Blue-Violet theme plugin for pretix control and presale UI." ) visible = False - version = "1.7.3" + version = "1.8.0" category = "CUSTOMIZATION" diff --git a/pretix_whitelabel/signals.py b/pretix_whitelabel/signals.py index 7297b7c..14ec718 100644 --- a/pretix_whitelabel/signals.py +++ b/pretix_whitelabel/signals.py @@ -1,15 +1,17 @@ """ -Pretix signal receivers for pretix-falkenthal-theme. +Pretix signal receivers for pretix-falkenthal-theme (v1.8.0). Hinweis zur Architektur: Die Plattform-Pflichtangaben (Plattform-Impressum, Plattform-Datenschutz sowie der AGPLv3-Quellcode-Nachweis) werden server-seitig über patch_templates.py -beim Docker-Build direkt in die Basis-Templates (pretixcontrol & pretixpresale) -eingebettet. +beim Docker-Build direkt in die Basis-Templates (pretixcontrol, pretixpresale +sowie globale Fehlerseiten 400/403/404/500/503) eingebettet und durch Build-Checks +verifiziert. -Dadurch wird eine saubere 2-Ebenen-Footer-Trennung gewährleistet: -- Ebene 1: Nativer Pretix-Footer mit den individuellen Rechtstexten des jeweiligen - Veranstalters (Impressum, Datenschutz, AGB) & Pretix-Lizenzhinweis. -- Ebene 2: Falkenthal-Plattform-Leiste (.falkenthal-platform-bar) mit den Angaben - des technischen Plattform-Betreibers. +Dadurch wird eine saubere 2-Ebenen-Trennung gewährleistet: +- Ebene 1 (Veranstalter / Event): Nativer Pretix-Footer mit den individuellen + Rechtstexten des jeweiligen Veranstalters (Impressum, Datenschutz, AGB), + individuelle Veranstalter-Farben (inkl. Dark-Mode-Support) & Event-Favicons. +- Ebene 2 (Plattform): Falkenthal-Plattform-Leiste (.falkenthal-platform-bar) + mit den Angaben des technischen Plattform-Betreibers und Fallback-Favicon. """ diff --git a/pretix_whitelabel/static/whitelabel/control.css b/pretix_whitelabel/static/whitelabel/control.css index 5220b23..878199f 100644 --- a/pretix_whitelabel/static/whitelabel/control.css +++ b/pretix_whitelabel/static/whitelabel/control.css @@ -1,5 +1,5 @@ /* ========================================================================== - FALKENTHAL ADMIN BACKEND & LOGIN THEME (control.css - v7) + FALKENTHAL ADMIN BACKEND & LOGIN THEME (control.css - v1.8.0) ========================================================================== */ :root { @@ -62,7 +62,7 @@ nav.navbar-inverse { a.navbar-brand { font-size: 0 !important; color: transparent !important; - background-image: url('/static/whitelabel/logo.svg?v=7') !important; + background-image: url('/static/whitelabel/logo.svg?v=1.8.0') !important; background-repeat: no-repeat !important; background-position: 14px center !important; background-size: auto 34px !important; @@ -641,10 +641,12 @@ fieldset legend { /* ========================================================================== 4. LOGIN-SCREEN (EXAKT MITTIG ZENTRIERT & SYMMETRISCHES LOGO) + Abgesichert über .falkenthal-auth-body bzw. body:not(:has(#wrapper)):has(img.logo) ========================================================================== */ -body:has(img.logo), -body.login { +body.falkenthal-auth-body, +body.login, +body:not(:has(#wrapper)):has(img.logo) { background-color: #060b16 !important; background-image: radial-gradient(circle at 50% 35%, rgba(37, 99, 235, 0.22) 0%, rgba(124, 58, 237, 0.10) 45%, transparent 75%), @@ -661,28 +663,31 @@ body.login { align-items: center !important; } -body:has(img.logo) > .container { +body.falkenthal-auth-body > .container, +body:not(:has(#wrapper)):has(img.logo) > .container { width: 100% !important; max-width: 420px !important; margin: 0 auto !important; padding: 0 !important; } -body:has(img.logo) > .container .row { +body.falkenthal-auth-body > .container .row, +body:not(:has(#wrapper)):has(img.logo) > .container .row { margin: 0 !important; } -body:has(img.logo) > .container [class*="col-"] { +body.falkenthal-auth-body > .container [class*="col-"], +body:not(:has(#wrapper)):has(img.logo) > .container [class*="col-"] { width: 100% !important; margin: 0 !important; padding: 0 !important; float: none !important; } -.container img.logo, -.container-fluid img.logo, +body.falkenthal-auth-body .container img.logo, +body:not(:has(#wrapper)):has(img.logo) .container img.logo, .form-signin img.logo { - content: url('/static/whitelabel/login-logo.svg?v=7') !important; + content: url('/static/whitelabel/login-logo.svg?v=1.8.0') !important; height: 115px !important; max-height: 115px !important; width: auto !important; @@ -691,9 +696,12 @@ body:has(img.logo) > .container [class*="col-"] { filter: drop-shadow(0 0 18px rgba(0, 229, 255, 0.28)) !important; } -body:has(img.logo) .panel, -body:has(img.logo) .well, -body:has(img.logo) .form-signin, +body.falkenthal-auth-body .panel, +body.falkenthal-auth-body .well, +body.falkenthal-auth-body .form-signin, +body:not(:has(#wrapper)):has(img.logo) .panel, +body:not(:has(#wrapper)):has(img.logo) .well, +body:not(:has(#wrapper)):has(img.logo) .form-signin, .login-panel { background: rgba(15, 23, 42, 0.78) !important; backdrop-filter: blur(16px) !important; @@ -706,30 +714,66 @@ body:has(img.logo) .form-signin, margin-bottom: 18px !important; } -body:has(img.logo) label, -body:has(img.logo) .control-label, -body:has(img.logo) .checkbox label { +body.falkenthal-auth-body label, +body.falkenthal-auth-body .control-label, +body.falkenthal-auth-body .checkbox label, +body:not(:has(#wrapper)):has(img.logo) label, +body:not(:has(#wrapper)):has(img.logo) .control-label, +body:not(:has(#wrapper)):has(img.logo) .checkbox label { color: #cbd5e1 !important; } -body:has(img.logo) .form-control { +body.falkenthal-auth-body .form-control, +body:not(:has(#wrapper)):has(img.logo) .form-control { background-color: rgba(6, 11, 22, 0.78) !important; border: 1px solid rgba(148, 163, 184, 0.28) !important; color: #f8fafc !important; height: 42px !important; } -body:has(img.logo) .form-control:focus { +body.falkenthal-auth-body .form-control:focus, +body:not(:has(#wrapper)):has(img.logo) .form-control:focus { border-color: var(--fk-cyan) !important; box-shadow: 0 0 0 3px rgba(0, 229, 255, 0.18) !important; } -body:has(img.logo) a { +body.falkenthal-auth-body a, +body:not(:has(#wrapper)):has(img.logo) a { color: #60a5fa !important; } /* ========================================================================== - 14. FOOTER & PLATTFORM-BAR (CONTROL & AUTH) + 5. MOBILE UX & RESPONSIVE ANPASSUNGEN (BACKEND) + ========================================================================== */ + +@media (max-width: 767px) { + #page-wrapper { + padding: 16px 14px !important; + } + + #page-wrapper h1 { + font-size: 22px !important; + margin-bottom: 14px !important; + } + + .navbar-header .navbar-brand, + a.navbar-brand { + width: 180px !important; + background-size: auto 30px !important; + } + + body.falkenthal-auth-body .panel, + body.falkenthal-auth-body .well, + body.falkenthal-auth-body .form-signin, + body:not(:has(#wrapper)):has(img.logo) .panel, + body:not(:has(#wrapper)):has(img.logo) .well, + body:not(:has(#wrapper)):has(img.logo) .form-signin { + padding: 20px 18px !important; + } +} + +/* ========================================================================== + 6. FOOTER & PLATTFORM-BAR (CONTROL & AUTH) ========================================================================== */ footer { @@ -750,7 +794,12 @@ footer { } .falkenthal-platform-bar .falkenthal-platform-info { - display: inline-block; + display: flex; + flex-wrap: wrap; + justify-content: center; + align-items: center; + gap: 4px 0; + padding: 0 8px; } .falkenthal-platform-bar .ft-brand { @@ -777,24 +826,29 @@ footer { } /* Spezifische Footer-Anpassung für die Dark-Glassmorphism Loginseite */ -body:has(img.logo) .falkenthal-platform-bar { +body.falkenthal-auth-body .falkenthal-platform-bar, +body:not(:has(#wrapper)):has(img.logo) .falkenthal-platform-bar { border-top-color: rgba(99, 102, 241, 0.2) !important; color: #94a3b8 !important; } -body:has(img.logo) .falkenthal-platform-bar .ft-brand { +body.falkenthal-auth-body .falkenthal-platform-bar .ft-brand, +body:not(:has(#wrapper)):has(img.logo) .falkenthal-platform-bar .ft-brand { color: #cbd5e1 !important; } -body:has(img.logo) .falkenthal-platform-bar a { +body.falkenthal-auth-body .falkenthal-platform-bar a, +body:not(:has(#wrapper)):has(img.logo) .falkenthal-platform-bar a { color: #94a3b8 !important; } -body:has(img.logo) .falkenthal-platform-bar a:hover { +body.falkenthal-auth-body .falkenthal-platform-bar a:hover, +body:not(:has(#wrapper)):has(img.logo) .falkenthal-platform-bar a:hover { color: var(--fk-cyan) !important; } -body:has(img.logo) .falkenthal-platform-bar .ft-sep { +body.falkenthal-auth-body .falkenthal-platform-bar .ft-sep, +body:not(:has(#wrapper)):has(img.logo) .falkenthal-platform-bar .ft-sep { color: #475569 !important; } diff --git a/pretix_whitelabel/static/whitelabel/presale.css b/pretix_whitelabel/static/whitelabel/presale.css index 85c6cb6..26011b9 100644 --- a/pretix_whitelabel/static/whitelabel/presale.css +++ b/pretix_whitelabel/static/whitelabel/presale.css @@ -1,6 +1,7 @@ /* ========================================================================== - FALKENTHAL MODERN SHOP UI/UX UPGRADE (presale.css) - Farbneutral: Respektiert 100 % der Veranstalter-Farben, Logos & Hintergründe! + FALKENTHAL MODERN SHOP UI/UX UPGRADE (presale.css - v1.8.0) + Farb- & Kontrastneutral: Respektiert 100 % der Veranstalter-Farben, + Logos sowie helle UND dunkle Veranstalter-Hintergründe (Dark Themes)! ========================================================================== */ body { @@ -12,8 +13,9 @@ body { /* 1. MODERNE CARDS & PANELS IM TICKETSHOP */ .panel { border-radius: 12px; - border: 1px solid rgba(15, 23, 42, 0.08); - box-shadow: 0 4px 20px -2px rgba(15, 23, 42, 0.05); + border: 1px solid rgba(128, 128, 128, 0.16); + border-color: color-mix(in srgb, currentColor 12%, transparent); + box-shadow: 0 4px 20px -2px rgba(0, 0, 0, 0.06); overflow: hidden; transition: box-shadow 0.2s ease; } @@ -24,7 +26,7 @@ body { letter-spacing: -0.01em; } -/* 2. PRODUKT- & TICKETZEILEN (MICRO-INTERACTIONS) */ +/* 2. PRODUKT- & TICKETZEILEN (MICRO-INTERACTIONS FÜR LIGHT & DARK THEMES) */ .product-row, .variation-row { border-radius: 8px; @@ -33,7 +35,8 @@ body { } .product-row:hover { - background-color: rgba(15, 23, 42, 0.025); + background-color: rgba(128, 128, 128, 0.05); + background-color: color-mix(in srgb, currentColor 4%, transparent); } /* 3. BUTTONS & EINGABEFELDER (MODERNE GEOMETRIE OHNE FARB-ZWANG) */ @@ -47,7 +50,7 @@ body { .btn:hover, .btn:focus { transform: translateY(-1px); - box-shadow: 0 4px 12px rgba(15, 23, 42, 0.12); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.14); } .btn:active { @@ -57,13 +60,16 @@ body { .form-control { border-radius: 8px; height: 40px; - border: 1px solid rgba(15, 23, 42, 0.18); - box-shadow: 0 1px 2px rgba(15, 23, 42, 0.02); + border: 1px solid rgba(128, 128, 128, 0.28); + border-color: color-mix(in srgb, currentColor 22%, transparent); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.02); transition: border-color 0.2s ease, box-shadow 0.2s ease; } +/* Fokusring übernimmt automatisch die vom Veranstalter gesetzte Rahmen-/Primärfarbe */ .form-control:focus { - box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.15); + box-shadow: 0 0 0 3px rgba(128, 128, 128, 0.18); + box-shadow: 0 0 0 3px color-mix(in srgb, currentColor 16%, transparent); outline: none; } @@ -88,11 +94,11 @@ body { .alert { border-radius: 10px; border: none; - box-shadow: 0 2px 10px rgba(15, 23, 42, 0.05); + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.06); } /* ========================================================================== - 6. FOOTER & PLATTFORM-RECHTSTEXTE (FALKENTHAL WHITE-LABEL) + 6. FOOTER & PLATTFORM-RECHTSTEXTE (ADAPTIV FÜR HELLE & DUNKLE VERANSTALTER-SHOPS) ========================================================================== */ footer { display: flex; @@ -121,39 +127,55 @@ footer nav ul li a { width: 100%; margin-top: 14px; padding-top: 16px; - border-top: 1px solid rgba(15, 23, 42, 0.08); + border-top: 1px solid rgba(128, 128, 128, 0.2); + border-top-color: color-mix(in srgb, currentColor 15%, transparent); font-size: 12px; - color: #64748b; + color: inherit; + opacity: 0.78; text-align: center; line-height: 1.6; } .falkenthal-platform-bar .falkenthal-platform-info { - display: inline-block; + display: flex; + flex-wrap: wrap; + justify-content: center; + align-items: center; + gap: 4px 0; max-width: 100%; + padding: 0 8px; } .falkenthal-platform-bar .ft-brand { font-weight: 600; - color: #334155; + color: inherit; letter-spacing: 0.02em; } .falkenthal-platform-bar a { - color: #64748b !important; + color: inherit !important; text-decoration: none !important; font-weight: 500; - transition: color 0.15s ease, text-decoration 0.15s ease; + opacity: 0.92; + transition: opacity 0.15s ease, text-decoration 0.15s ease; } -.falkenthal-platform-bar a:hover { - color: #2563eb !important; +.falkenthal-platform-bar a:hover, +.falkenthal-platform-bar a:focus { + opacity: 1; text-decoration: underline !important; } .falkenthal-platform-bar .ft-sep { margin: 0 6px; - color: #94a3b8; + opacity: 0.55; +} + +/* Kompakter Modus für eingebettete Pretix-Widgets (iFrame) & Mobilgeräte */ +.is-iframe footer, +body.iframe footer { + margin-top: 20px; + padding-bottom: 14px; } @media (max-width: 767px) { @@ -165,3 +187,4 @@ footer nav ul li a { } } + diff --git a/setup.py b/setup.py index 316122f..97ece03 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ with open("README.md", encoding="utf-8") as f: setup( name="pretix-falkenthal-theme", - version="1.7.3", + version="1.8.0", description="Modern Slate & Blue-Violet White-Label Theme Plugin for pretix", long_description=long_description, long_description_content_type="text/markdown",