']
table_classes = ["table-styled"]
if classes:
table_classes.append(classes)
html_parts.append(f'
')
# Kopfzeilen
html_parts.append('
')
for header in headers:
html_parts.append(f'
{header}
')
html_parts.append('
')
# Zeilen
html_parts.append('')
for i, row in enumerate(rows):
row_classes = ""
if striped and i % 2 == 1:
row_classes = 'class="bg-slate-50 dark:bg-slate-800/50"'
html_parts.append(f'
')
for cell in row:
html_parts.append(f'
{cell}
')
html_parts.append('
')
html_parts.append('')
html_parts.append('
')
return Markup("".join(html_parts))
@staticmethod
def format_datetime_german(dt: datetime, format_str: str = "%d.%m.%Y %H:%M") -> str:
"""
Formatiert Datetime für deutsche Anzeige
Args:
dt: Datetime-Objekt
format_str: Format-String
"""
if not dt:
return ""
return dt.strftime(format_str)
@staticmethod
def format_duration(minutes: int) -> str:
"""
Formatiert Dauer in Minuten zu lesbarem Format
Args:
minutes: Dauer in Minuten
"""
if not minutes:
return "0 Min"
if minutes < 60:
return f"{minutes} Min"
hours = minutes // 60
remaining_minutes = minutes % 60
if remaining_minutes == 0:
return f"{hours} Std"
return f"{hours} Std {remaining_minutes} Min"
@staticmethod
def json_encode(data: Any) -> str:
"""
Enkodiert Python-Daten als JSON für JavaScript
Args:
data: Zu enkodierendes Objekt
"""
return json.dumps(data, default=str, ensure_ascii=False)
def register_template_helpers(app):
"""
Registriert alle Template-Helper bei der Flask-App
Args:
app: Flask-App-Instanz
"""
# Funktionen registrieren
app.jinja_env.globals['ui_button'] = UIHelpers.component_button
app.jinja_env.globals['ui_badge'] = UIHelpers.component_badge
app.jinja_env.globals['ui_status_badge'] = UIHelpers.component_status_badge
app.jinja_env.globals['ui_card'] = UIHelpers.component_card
app.jinja_env.globals['ui_alert'] = UIHelpers.component_alert
app.jinja_env.globals['ui_modal'] = UIHelpers.component_modal
app.jinja_env.globals['ui_table'] = UIHelpers.component_table
# Filter registrieren
app.jinja_env.filters['german_datetime'] = UIHelpers.format_datetime_german
app.jinja_env.filters['duration'] = UIHelpers.format_duration
app.jinja_env.filters['json'] = UIHelpers.json_encode
# Zusätzliche globale Variablen
app.jinja_env.globals['current_year'] = datetime.now().year
# Icons als globale Variablen
icons = {
'check': '',
'x': '',
'plus': '',
'edit': '',
'trash': '',
'printer': '',
'dashboard': '',
}
app.jinja_env.globals['icons'] = icons
@app.context_processor
def utility_processor():
"""Fügt nützliche Hilfsfunktionen zu Jinja hinzu."""
return dict(
active_page=active_page,
format_datetime=format_datetime,
format_date=format_date,
format_time=format_time,
random_avatar_color=random_avatar_color,
get_initials=get_initials,
render_progress_bar=render_progress_bar
)
def active_page(path):
"""
Überprüft, ob der aktuelle Pfad mit dem gegebenen Pfad übereinstimmt.
"""
if request.path == path:
return 'active'
return ''
def format_datetime(value, format='%d.%m.%Y %H:%M'):
"""
Formatiert ein Datum mit Uhrzeit nach deutschem Format.
"""
if value is None:
return ""
if isinstance(value, str):
try:
value = datetime.fromisoformat(value)
except ValueError:
return value
return value.strftime(format)
def format_date(value, format='%d.%m.%Y'):
"""
Formatiert ein Datum nach deutschem Format.
"""
if value is None:
return ""
if isinstance(value, str):
try:
value = datetime.fromisoformat(value)
except ValueError:
return value
return value.strftime(format)
def format_time(value, format='%H:%M'):
"""
Formatiert eine Uhrzeit nach deutschem Format.
"""
if value is None:
return ""
if isinstance(value, str):
try:
value = datetime.fromisoformat(value)
except ValueError:
return value
return value.strftime(format)
def random_avatar_color():
"""
Gibt eine zufällige Hintergrundfarbe für Avatare zurück.
"""
colors = [
'bg-blue-100 text-blue-800',
'bg-green-100 text-green-800',
'bg-yellow-100 text-yellow-800',
'bg-red-100 text-red-800',
'bg-indigo-100 text-indigo-800',
'bg-purple-100 text-purple-800',
'bg-pink-100 text-pink-800',
'bg-gray-100 text-gray-800',
]
return random.choice(colors)
def get_initials(name, max_length=2):
"""
Extrahiert die Initialen eines Namens.
"""
if not name:
return "?"
parts = name.split()
if len(parts) == 1:
return name[0:max_length].upper()
initials = ""
for part in parts:
if part and len(initials) < max_length:
initials += part[0].upper()
return initials
def render_progress_bar(value, color='blue'):
"""
Rendert einen Fortschrittsbalken ohne Inline-Styles.
Args:
value (int): Der Prozentwert für den Fortschrittsbalken (0-100)
color (str): Die Farbe des Balkens (blue, green, purple, red)
Returns:
str: HTML-Markup für den Fortschrittsbalken
"""
css_class = f"progress-bar-fill-{color}"
# Sicherstellen, dass der Wert im gültigen Bereich liegt
if value < 0:
value = 0
elif value > 100:
value = 100
# Erstellen des DOM-Struktur für den Fortschrittsbalken
html = f"""