Willkommensseite: Kontaktinfo linksbündig mit Aufzählungen, Portrait-Modus verbessert
- md_to_html: Listen-Support (- /*) und Zeilenumbrüche erhalten - Kein Firmenname mehr unter den Logos (customer-name entfernt) - text-align: left + align-items: stretch für linksbündige Texte - Feste Logo-Höhe 120px für gleiche Text-Startposition - Portrait-Modus: Text links vom Logo (via order), gap 40px - Schrift 1.3rem, margin-top 24px, Listeneinzug entfernt - Reset-Button im Willkommensseite-Formular - Markdown-Hilfetext aktualisiert
This commit is contained in:
13
app.py
13
app.py
@@ -30,7 +30,7 @@ from werkzeug.middleware.proxy_fix import ProxyFix
|
|||||||
from flask import (
|
from flask import (
|
||||||
Flask, jsonify, render_template,
|
Flask, jsonify, render_template,
|
||||||
send_from_directory, redirect,
|
send_from_directory, redirect,
|
||||||
request, abort, flash, session
|
request, abort, flash, session, url_for
|
||||||
)
|
)
|
||||||
from flask_login import (
|
from flask_login import (
|
||||||
LoginManager, login_user, current_user,
|
LoginManager, login_user, current_user,
|
||||||
@@ -769,10 +769,19 @@ def add_customer():
|
|||||||
config = load_config()
|
config = load_config()
|
||||||
site_list = get_site_list(config)
|
site_list = get_site_list(config)
|
||||||
background_url = get_background_url(site)
|
background_url = get_background_url(site)
|
||||||
|
|
||||||
|
if request.args.get("reset") and site:
|
||||||
|
site_cfg = config.setdefault("sites", {}).setdefault(site, {})
|
||||||
|
site_cfg.pop("welcome_data", None)
|
||||||
|
save_config(config)
|
||||||
|
return redirect(url_for("add_customer", site=site))
|
||||||
|
|
||||||
welcome_data = config.get("sites", {}).get(site, {}).get("welcome_data", {})
|
welcome_data = config.get("sites", {}).get(site, {}).get("welcome_data", {})
|
||||||
saved_contacts = welcome_data.get("contacts", ["", "", ""])
|
saved_contacts = welcome_data.get("contacts", ["", "", ""])
|
||||||
if not contacts:
|
if request.method != "POST":
|
||||||
contacts = saved_contacts
|
contacts = saved_contacts
|
||||||
|
customer_names = welcome_data.get("names", ["", "", ""])
|
||||||
|
logo_urls = welcome_data.get("logo_urls", [None, None, None])
|
||||||
return render_template(
|
return render_template(
|
||||||
"customer.html",
|
"customer.html",
|
||||||
error=error,
|
error=error,
|
||||||
|
|||||||
@@ -98,13 +98,34 @@ def search_customer_logo(customer_name):
|
|||||||
# -------------------------------------------------
|
# -------------------------------------------------
|
||||||
|
|
||||||
def md_to_html(text):
|
def md_to_html(text):
|
||||||
"""Wandelt einfaches Markdown in HTML um (fett, kursiv, code, zeilenumbrüche)."""
|
"""Wandelt einfaches Markdown in HTML um (fett, kursiv, code, zeilenumbrüche, aufzählungen)."""
|
||||||
import re
|
import re
|
||||||
text = re.sub(r'\*\*(.+?)\*\*', r'<strong>\1</strong>', text)
|
text = re.sub(r'\*\*(.+?)\*\*', r'<strong>\1</strong>', text)
|
||||||
text = re.sub(r'\*(.+?)\*', r'<em>\1</em>', text)
|
text = re.sub(r'\*(.+?)\*', r'<em>\1</em>', text)
|
||||||
text = re.sub(r'`(.+?)`', r'<code>\1</code>', text)
|
text = re.sub(r'`(.+?)`', r'<code>\1</code>', text)
|
||||||
lines = text.split('\n')
|
lines = text.split('\n')
|
||||||
return '<br>'.join(line.strip() for line in lines)
|
parts = []
|
||||||
|
in_list = False
|
||||||
|
for line in lines:
|
||||||
|
stripped = line.strip()
|
||||||
|
is_li = stripped.startswith('- ') or stripped.startswith('* ')
|
||||||
|
if is_li:
|
||||||
|
if not in_list:
|
||||||
|
parts.append('<ul>')
|
||||||
|
in_list = True
|
||||||
|
parts.append(f'<li>{stripped[2:]}</li>')
|
||||||
|
else:
|
||||||
|
if in_list:
|
||||||
|
parts.append('</ul>')
|
||||||
|
in_list = False
|
||||||
|
if stripped:
|
||||||
|
parts.append(stripped)
|
||||||
|
parts.append('<br>')
|
||||||
|
if in_list:
|
||||||
|
parts.append('</ul>')
|
||||||
|
if parts and parts[-1] == '<br>':
|
||||||
|
parts.pop()
|
||||||
|
return ''.join(parts)
|
||||||
|
|
||||||
|
|
||||||
def generate_welcome_html(customer_names, logo_urls, contacts=None, site="stuttgart", background_url=None):
|
def generate_welcome_html(customer_names, logo_urls, contacts=None, site="stuttgart", background_url=None):
|
||||||
@@ -141,7 +162,6 @@ def generate_welcome_html(customer_names, logo_urls, contacts=None, site="stuttg
|
|||||||
<div class="customer-logo-item">
|
<div class="customer-logo-item">
|
||||||
<img src="{url}" alt="{name}" class="customer-logo" crossorigin="anonymous">
|
<img src="{url}" alt="{name}" class="customer-logo" crossorigin="anonymous">
|
||||||
<div class="customer-meta">
|
<div class="customer-meta">
|
||||||
<span class="customer-name">{name}</span>
|
|
||||||
{contact_html}
|
{contact_html}
|
||||||
</div>
|
</div>
|
||||||
</div>'''
|
</div>'''
|
||||||
@@ -193,41 +213,45 @@ def generate_welcome_html(customer_names, logo_urls, contacts=None, site="stuttg
|
|||||||
.customer-logo-item {{
|
.customer-logo-item {{
|
||||||
flex: 0 0 280px;
|
flex: 0 0 280px;
|
||||||
display: flex; flex-direction: column;
|
display: flex; flex-direction: column;
|
||||||
align-items: center; justify-content: flex-start;
|
align-items: stretch; justify-content: flex-start;
|
||||||
|
}}
|
||||||
|
.customer-meta {{
|
||||||
|
width: 100%; text-align: left;
|
||||||
}}
|
}}
|
||||||
.customer-logo {{
|
.customer-logo {{
|
||||||
width: 100%; height: auto;
|
width: 100%; height: 120px;
|
||||||
max-height: 180px;
|
|
||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
filter: drop-shadow(0 4px 12px rgba(0, 0, 0, 0.15));
|
filter: drop-shadow(0 4px 12px rgba(0, 0, 0, 0.15));
|
||||||
}}
|
display: block;
|
||||||
.customer-name {{
|
|
||||||
font-size: 1rem; font-weight: 600; color: #000;
|
|
||||||
margin-top: 8px; text-align: center;
|
|
||||||
}}
|
}}
|
||||||
.contact-info {{
|
.contact-info {{
|
||||||
font-size: 0.85rem; color: #333; line-height: 1.5;
|
font-size: 1.3rem; color: #333; line-height: 1.3;
|
||||||
margin-top: 6px; text-align: center;
|
margin-top: 24px; text-align: left;
|
||||||
}}
|
}}
|
||||||
.contact-info strong {{ color: #000; }}
|
.contact-info strong {{ color: #000; }}
|
||||||
.contact-info code {{
|
.contact-info code {{
|
||||||
font-size: 0.8rem; padding: 1px 4px;
|
font-size: 0.8rem; padding: 1px 4px;
|
||||||
background: rgba(0,0,0,0.06); border-radius: 3px;
|
background: rgba(0,0,0,0.06); border-radius: 3px;
|
||||||
}}
|
}}
|
||||||
|
.contact-info ul {{
|
||||||
|
margin: 0; padding-left: 0;
|
||||||
|
list-style-position: inside;
|
||||||
|
}}
|
||||||
|
.contact-info li {{
|
||||||
|
margin: 0; padding: 0;
|
||||||
|
}}
|
||||||
@media (orientation: portrait) {{
|
@media (orientation: portrait) {{
|
||||||
.customer-logos {{
|
.customer-logos {{
|
||||||
flex-direction: column; gap: 20px;
|
flex-direction: column; gap: 20px;
|
||||||
}}
|
}}
|
||||||
.customer-logo-item {{
|
.customer-logo-item {{
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
flex-direction: row; gap: 20px;
|
flex-direction: row; gap: 40px;
|
||||||
width: 100%; max-width: 600px;
|
width: 100%; max-width: 600px;
|
||||||
}}
|
}}
|
||||||
.customer-logo {{
|
.customer-logo {{
|
||||||
max-height: 100px; width: 180px; flex-shrink: 0;
|
max-height: 100px; width: 180px; flex-shrink: 0;
|
||||||
}}
|
order: 2;
|
||||||
.customer-name {{
|
|
||||||
margin-top: 0; text-align: left;
|
|
||||||
}}
|
}}
|
||||||
.contact-info {{
|
.contact-info {{
|
||||||
text-align: left;
|
text-align: left;
|
||||||
@@ -235,6 +259,7 @@ def generate_welcome_html(customer_names, logo_urls, contacts=None, site="stuttg
|
|||||||
.customer-meta {{
|
.customer-meta {{
|
||||||
display: flex; flex-direction: column;
|
display: flex; flex-direction: column;
|
||||||
align-items: flex-start; flex: 1;
|
align-items: flex-start; flex: 1;
|
||||||
|
order: 1;
|
||||||
}}
|
}}
|
||||||
}}
|
}}
|
||||||
.content {{
|
.content {{
|
||||||
|
|||||||
@@ -156,12 +156,15 @@
|
|||||||
<div class="mb-3 text-muted">
|
<div class="mb-3 text-muted">
|
||||||
<p class="mb-1">Das System sucht automatisch nach den Kundenlogos</p>
|
<p class="mb-1">Das System sucht automatisch nach den Kundenlogos</p>
|
||||||
<p class="mb-0">und erstellt eine angepasste Willkommensseite für die Lobby-Playlist.</p>
|
<p class="mb-0">und erstellt eine angepasste Willkommensseite für die Lobby-Playlist.</p>
|
||||||
<p class="mb-0 small"><i class="ti ti-markdown me-1"></i>Ansprechpartner unterstützen <strong>fett</strong>, <em>kursiv</em> und <code>Code</code> sowie Zeilenumbrüche.</p>
|
<p class="mb-0 small"><i class="ti ti-markdown me-1"></i>Ansprechpartner unterstützen <strong>fett</strong>, <em>kursiv</em>, <code>Code</code>, Aufzählungen (<code>- </code>) sowie Zeilenumbrüche.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button type="submit" class="btn btn-primary">
|
<button type="submit" class="btn btn-primary">
|
||||||
<i class="ti ti-file-plus me-1"></i>Logos & Willkommensseite generieren
|
<i class="ti ti-file-plus me-1"></i>Logos & Willkommensseite generieren
|
||||||
</button>
|
</button>
|
||||||
|
<a href="?reset=1&site={{ site }}" class="btn btn-outline-secondary ms-2">
|
||||||
|
<i class="ti ti-trash me-1"></i>Zurücksetzen
|
||||||
|
</a>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user