893 lines
37 KiB
HTML
893 lines
37 KiB
HTML
{% extends "base.html" %}
|
||
|
||
{% block title %}Erweiterte Einstellungen - Mercedes-Benz TBA Marienfelde{% endblock %}
|
||
|
||
{% block head %}
|
||
{{ super() }}
|
||
<!-- CSRF Token für AJAX-Anfragen -->
|
||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||
<style>
|
||
/* Glasmorphismus und moderne Effekte */
|
||
.glass-card {
|
||
background: rgba(255, 255, 255, 0.1);
|
||
backdrop-filter: blur(20px);
|
||
border: 1px solid rgba(255, 255, 255, 0.2);
|
||
border-radius: 24px;
|
||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
|
||
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
||
}
|
||
|
||
.dark .glass-card {
|
||
background: rgba(30, 41, 59, 0.3);
|
||
border-color: rgba(148, 163, 184, 0.2);
|
||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
|
||
}
|
||
|
||
.glass-card:hover {
|
||
transform: translateY(-8px) scale(1.02);
|
||
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);
|
||
border-color: rgba(59, 130, 246, 0.4);
|
||
}
|
||
|
||
.dark .glass-card:hover {
|
||
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.4);
|
||
}
|
||
|
||
/* Gradient Backgrounds */
|
||
.gradient-bg {
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
}
|
||
|
||
.gradient-bg-alt {
|
||
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
|
||
}
|
||
|
||
.gradient-bg-success {
|
||
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
|
||
}
|
||
|
||
.gradient-bg-warning {
|
||
background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%);
|
||
}
|
||
|
||
/* Stat Cards mit Hover-Effekten */
|
||
.stat-card {
|
||
background: linear-gradient(135deg, rgba(255, 255, 255, 0.9) 0%, rgba(255, 255, 255, 0.7) 100%);
|
||
border: 1px solid rgba(255, 255, 255, 0.3);
|
||
border-radius: 20px;
|
||
padding: 2rem;
|
||
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
||
position: relative;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.dark .stat-card {
|
||
background: linear-gradient(135deg, rgba(30, 41, 59, 0.9) 0%, rgba(15, 23, 42, 0.7) 100%);
|
||
border-color: rgba(148, 163, 184, 0.2);
|
||
}
|
||
|
||
.stat-card::before {
|
||
content: '';
|
||
position: absolute;
|
||
top: 0;
|
||
left: -100%;
|
||
width: 100%;
|
||
height: 100%;
|
||
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
|
||
transition: left 0.5s;
|
||
}
|
||
|
||
.stat-card:hover::before {
|
||
left: 100%;
|
||
}
|
||
|
||
.stat-card:hover {
|
||
transform: translateY(-12px) rotateX(5deg);
|
||
box-shadow: 0 25px 50px rgba(0, 0, 0, 0.15);
|
||
}
|
||
|
||
/* Moderne Toggle Switches */
|
||
.modern-toggle {
|
||
position: relative;
|
||
display: inline-block;
|
||
width: 80px;
|
||
height: 40px;
|
||
}
|
||
|
||
.modern-toggle input {
|
||
opacity: 0;
|
||
width: 0;
|
||
height: 0;
|
||
}
|
||
|
||
.toggle-slider {
|
||
position: absolute;
|
||
cursor: pointer;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
background: linear-gradient(135deg, #e2e8f0, #cbd5e1);
|
||
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
||
border-radius: 40px;
|
||
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.1);
|
||
}
|
||
|
||
.toggle-slider:before {
|
||
position: absolute;
|
||
content: "";
|
||
height: 32px;
|
||
width: 32px;
|
||
left: 4px;
|
||
bottom: 4px;
|
||
background: linear-gradient(135deg, #ffffff, #f8fafc);
|
||
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
||
border-radius: 50%;
|
||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
||
}
|
||
|
||
input:checked + .toggle-slider {
|
||
background: linear-gradient(135deg, #3b82f6, #1d4ed8);
|
||
box-shadow: 0 0 20px rgba(59, 130, 246, 0.4);
|
||
}
|
||
|
||
input:checked + .toggle-slider:before {
|
||
transform: translateX(40px);
|
||
background: linear-gradient(135deg, #ffffff, #f0f9ff);
|
||
}
|
||
|
||
/* Animierte Buttons */
|
||
.modern-btn {
|
||
position: relative;
|
||
overflow: hidden;
|
||
border-radius: 16px;
|
||
padding: 1rem 2rem;
|
||
font-weight: 600;
|
||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||
border: none;
|
||
cursor: pointer;
|
||
text-transform: none;
|
||
}
|
||
|
||
.modern-btn::before {
|
||
content: '';
|
||
position: absolute;
|
||
top: 0;
|
||
left: -100%;
|
||
width: 100%;
|
||
height: 100%;
|
||
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent);
|
||
transition: left 0.5s;
|
||
}
|
||
|
||
.modern-btn:hover::before {
|
||
left: 100%;
|
||
}
|
||
|
||
.modern-btn:hover {
|
||
transform: translateY(-2px);
|
||
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2);
|
||
}
|
||
|
||
.btn-primary {
|
||
background: linear-gradient(135deg, #3b82f6, #1d4ed8);
|
||
color: white;
|
||
}
|
||
|
||
.btn-success {
|
||
background: linear-gradient(135deg, #10b981, #059669);
|
||
color: white;
|
||
}
|
||
|
||
.btn-warning {
|
||
background: linear-gradient(135deg, #f59e0b, #d97706);
|
||
color: white;
|
||
}
|
||
|
||
.btn-danger {
|
||
background: linear-gradient(135deg, #ef4444, #dc2626);
|
||
color: white;
|
||
}
|
||
|
||
.btn-purple {
|
||
background: linear-gradient(135deg, #8b5cf6, #7c3aed);
|
||
color: white;
|
||
}
|
||
|
||
.btn-indigo {
|
||
background: linear-gradient(135deg, #6366f1, #4f46e5);
|
||
color: white;
|
||
}
|
||
|
||
/* Floating Animation */
|
||
@keyframes float {
|
||
0%, 100% { transform: translateY(0px); }
|
||
50% { transform: translateY(-10px); }
|
||
}
|
||
|
||
.floating {
|
||
animation: float 3s ease-in-out infinite;
|
||
}
|
||
|
||
/* Pulse Animation für Status */
|
||
@keyframes pulse-glow {
|
||
0%, 100% { box-shadow: 0 0 20px rgba(34, 197, 94, 0.4); }
|
||
50% { box-shadow: 0 0 30px rgba(34, 197, 94, 0.8); }
|
||
}
|
||
|
||
.pulse-glow {
|
||
animation: pulse-glow 2s ease-in-out infinite;
|
||
}
|
||
|
||
/* Form Inputs */
|
||
.modern-input {
|
||
background: rgba(255, 255, 255, 0.1);
|
||
backdrop-filter: blur(10px);
|
||
border: 2px solid rgba(255, 255, 255, 0.2);
|
||
border-radius: 16px;
|
||
padding: 1rem 1.5rem;
|
||
transition: all 0.3s ease;
|
||
color: inherit;
|
||
}
|
||
|
||
.modern-input:focus {
|
||
outline: none;
|
||
border-color: #3b82f6;
|
||
box-shadow: 0 0 20px rgba(59, 130, 246, 0.3);
|
||
background: rgba(255, 255, 255, 0.15);
|
||
}
|
||
|
||
.dark .modern-input {
|
||
background: rgba(30, 41, 59, 0.3);
|
||
border-color: rgba(148, 163, 184, 0.3);
|
||
}
|
||
|
||
/* Icon Containers */
|
||
.icon-container {
|
||
background: linear-gradient(135deg, rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 0.1));
|
||
border-radius: 16px;
|
||
padding: 1rem;
|
||
backdrop-filter: blur(10px);
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
.icon-container:hover {
|
||
transform: scale(1.1) rotate(5deg);
|
||
}
|
||
|
||
/* Loading Overlay Enhancement */
|
||
.loading-content {
|
||
background: rgba(255, 255, 255, 0.1);
|
||
backdrop-filter: blur(20px);
|
||
border: 1px solid rgba(255, 255, 255, 0.2);
|
||
border-radius: 24px;
|
||
padding: 3rem;
|
||
}
|
||
|
||
.dark .loading-content {
|
||
background: rgba(30, 41, 59, 0.3);
|
||
border-color: rgba(148, 163, 184, 0.2);
|
||
}
|
||
|
||
/* Notification Enhancement */
|
||
.notification {
|
||
background: rgba(255, 255, 255, 0.1);
|
||
backdrop-filter: blur(20px);
|
||
border: 1px solid rgba(255, 255, 255, 0.2);
|
||
border-radius: 16px;
|
||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
|
||
}
|
||
</style>
|
||
{% endblock %}
|
||
|
||
{% block content %}
|
||
<div class="min-h-screen bg-gradient-to-br from-indigo-50 via-purple-50 to-pink-50 dark:from-slate-900 dark:via-purple-900 dark:to-slate-800">
|
||
|
||
<!-- Header mit Glasmorphismus -->
|
||
<div class="glass-card mx-4 mt-4 mb-8">
|
||
<div class="max-w-7xl mx-auto px-6 py-8">
|
||
<div class="flex items-center justify-between">
|
||
<div class="flex items-center space-x-6">
|
||
<a href="{{ url_for('admin_page') }}" class="p-3 hover:bg-white/20 dark:hover:bg-slate-700/30 rounded-2xl transition-all duration-300 group">
|
||
<svg class="w-7 h-7 text-slate-600 dark:text-slate-400 group-hover:text-indigo-600 dark:group-hover:text-indigo-400 transition-colors" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"/>
|
||
</svg>
|
||
</a>
|
||
<div>
|
||
<h1 class="text-4xl font-bold bg-gradient-to-r from-indigo-600 to-purple-600 bg-clip-text text-transparent">
|
||
Erweiterte Einstellungen
|
||
</h1>
|
||
<p class="text-slate-600 dark:text-slate-400 mt-2 text-lg">System-Optimierung und Wartungsoptionen</p>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Status Indicator mit Animation -->
|
||
<div class="flex items-center space-x-3 bg-gradient-to-r from-green-400 to-emerald-500 px-6 py-3 rounded-2xl pulse-glow">
|
||
<div class="w-4 h-4 bg-white rounded-full animate-pulse"></div>
|
||
<span class="text-white font-semibold">System Online</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 pb-12">
|
||
|
||
<!-- System-Übersicht mit verbessertem Design -->
|
||
<div class="glass-card p-8 mb-12 floating">
|
||
<div class="flex items-center space-x-4 mb-8">
|
||
<div class="icon-container">
|
||
<span class="text-3xl">📊</span>
|
||
</div>
|
||
<h2 class="text-3xl font-bold bg-gradient-to-r from-blue-600 to-cyan-600 bg-clip-text text-transparent">
|
||
System-Übersicht
|
||
</h2>
|
||
</div>
|
||
|
||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||
<div class="stat-card group">
|
||
<div class="flex items-center justify-between">
|
||
<div>
|
||
<p class="text-sm text-slate-600 dark:text-slate-400 mb-2">Registrierte Benutzer</p>
|
||
<p class="text-4xl font-bold text-slate-900 dark:text-white">{{ stats.total_users }}</p>
|
||
</div>
|
||
<div class="icon-container bg-gradient-to-br from-blue-500 to-blue-600 text-white">
|
||
<svg class="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197M13 7a4 4 0 11-8 0 4 4 0 018 0z"/>
|
||
</svg>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="stat-card group">
|
||
<div class="flex items-center justify-between">
|
||
<div>
|
||
<p class="text-sm text-slate-600 dark:text-slate-400 mb-2">Aktive Drucker</p>
|
||
<p class="text-4xl font-bold text-slate-900 dark:text-white">{{ stats.active_printers }}/{{ stats.total_printers }}</p>
|
||
</div>
|
||
<div class="icon-container bg-gradient-to-br from-green-500 to-emerald-600 text-white">
|
||
<svg class="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 17h2a2 2 0 002-2v-4a2 2 0 00-2-2H5a2 2 0 00-2 2v4a2 2 0 002 2m2 4h6a2 2 0 002-2v-4a2 2 0 00-2-2H9a2 2 0 00-2 2v4a2 2 0 002 2zm8-12V5a2 2 0 00-2-2H9a2 2 0 00-2 2v4h10z"/>
|
||
</svg>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="stat-card group">
|
||
<div class="flex items-center justify-between">
|
||
<div>
|
||
<p class="text-sm text-slate-600 dark:text-slate-400 mb-2">Warteschlange</p>
|
||
<p class="text-4xl font-bold text-slate-900 dark:text-white">{{ stats.pending_jobs }}</p>
|
||
</div>
|
||
<div class="icon-container bg-gradient-to-br from-purple-500 to-purple-600 text-white">
|
||
<svg class="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10"/>
|
||
</svg>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="grid grid-cols-1 xl:grid-cols-2 gap-12">
|
||
|
||
<!-- Optimierungs-Einstellungen -->
|
||
<div class="glass-card p-8">
|
||
<div class="flex items-center space-x-4 mb-8">
|
||
<div class="icon-container">
|
||
<span class="text-3xl">⚙️</span>
|
||
</div>
|
||
<h2 class="text-3xl font-bold bg-gradient-to-r from-orange-600 to-red-600 bg-clip-text text-transparent">
|
||
Optimierungs-Einstellungen
|
||
</h2>
|
||
</div>
|
||
|
||
<form id="optimization-form" class="space-y-8">
|
||
<!-- Algorithmus-Auswahl -->
|
||
<div>
|
||
<label class="block text-lg font-semibold text-slate-700 dark:text-slate-300 mb-4">Optimierungs-Algorithmus</label>
|
||
<select name="algorithm" id="algorithm" class="modern-input w-full">
|
||
<option value="round_robin" {{ 'selected' if optimization_settings.algorithm == 'round_robin' else '' }}>Round Robin (Gleichmäßige Verteilung)</option>
|
||
<option value="load_balance" {{ 'selected' if optimization_settings.algorithm == 'load_balance' else '' }}>Load Balancing (Lastverteilung)</option>
|
||
<option value="priority_based" {{ 'selected' if optimization_settings.algorithm == 'priority_based' else '' }}>Prioritätsbasiert</option>
|
||
</select>
|
||
</div>
|
||
|
||
<!-- Toggle-Optionen -->
|
||
<div class="space-y-6">
|
||
<div class="flex items-center justify-between p-4 bg-white/10 dark:bg-slate-800/30 rounded-2xl backdrop-blur-sm">
|
||
<div>
|
||
<label class="text-lg font-semibold text-slate-700 dark:text-slate-300">Entfernung berücksichtigen</label>
|
||
<p class="text-sm text-slate-500 dark:text-slate-400 mt-1">Drucker-Standort bei Optimierung einbeziehen</p>
|
||
</div>
|
||
<label class="modern-toggle">
|
||
<input type="checkbox" name="consider_distance" {{ 'checked' if optimization_settings.consider_distance else '' }}>
|
||
<span class="toggle-slider"></span>
|
||
</label>
|
||
</div>
|
||
|
||
<div class="flex items-center justify-between p-4 bg-white/10 dark:bg-slate-800/30 rounded-2xl backdrop-blur-sm">
|
||
<div>
|
||
<label class="text-lg font-semibold text-slate-700 dark:text-slate-300">Rüstzeiten minimieren</label>
|
||
<p class="text-sm text-slate-500 dark:text-slate-400 mt-1">Materialwechsel-Zeiten reduzieren</p>
|
||
</div>
|
||
<label class="modern-toggle">
|
||
<input type="checkbox" name="minimize_changeover" {{ 'checked' if optimization_settings.minimize_changeover else '' }}>
|
||
<span class="toggle-slider"></span>
|
||
</label>
|
||
</div>
|
||
|
||
<div class="flex items-center justify-between p-4 bg-white/10 dark:bg-slate-800/30 rounded-2xl backdrop-blur-sm">
|
||
<div>
|
||
<label class="text-lg font-semibold text-slate-700 dark:text-slate-300">Auto-Optimierung</label>
|
||
<p class="text-sm text-slate-500 dark:text-slate-400 mt-1">Automatische Optimierung alle 30 Minuten</p>
|
||
</div>
|
||
<label class="modern-toggle">
|
||
<input type="checkbox" name="auto_optimization_enabled" {{ 'checked' if optimization_settings.auto_optimization_enabled else '' }}>
|
||
<span class="toggle-slider"></span>
|
||
</label>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Numerische Einstellungen -->
|
||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||
<div>
|
||
<label class="block text-lg font-semibold text-slate-700 dark:text-slate-300 mb-3">Max. Batch-Größe</label>
|
||
<input type="number" name="max_batch_size" value="{{ optimization_settings.max_batch_size }}" min="1" max="50" class="modern-input w-full">
|
||
</div>
|
||
|
||
<div>
|
||
<label class="block text-lg font-semibold text-slate-700 dark:text-slate-300 mb-3">Zeitfenster (Stunden)</label>
|
||
<input type="number" name="time_window" value="{{ optimization_settings.time_window }}" min="1" max="168" class="modern-input w-full">
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Speichern Button -->
|
||
<button type="submit" class="modern-btn btn-primary w-full text-lg py-4">
|
||
💾 Einstellungen speichern
|
||
</button>
|
||
</form>
|
||
</div>
|
||
|
||
<!-- Wartungs-Aktionen -->
|
||
<div class="glass-card p-8">
|
||
<div class="flex items-center space-x-4 mb-8">
|
||
<div class="icon-container">
|
||
<span class="text-3xl">🔧</span>
|
||
</div>
|
||
<h2 class="text-3xl font-bold bg-gradient-to-r from-green-600 to-teal-600 bg-clip-text text-transparent">
|
||
Wartungs-Aktionen
|
||
</h2>
|
||
</div>
|
||
|
||
<!-- Wartungs-Informationen -->
|
||
<div class="bg-white/20 dark:bg-slate-800/40 backdrop-blur-sm rounded-2xl p-6 mb-8">
|
||
<h3 class="text-xl font-bold text-slate-900 dark:text-white mb-4">Wartungs-Status</h3>
|
||
<div class="space-y-3">
|
||
<div class="flex justify-between items-center">
|
||
<span class="text-slate-600 dark:text-slate-400">Letztes Backup:</span>
|
||
<span class="text-slate-900 dark:text-white font-semibold">{{ maintenance_info.last_backup }}</span>
|
||
</div>
|
||
<div class="flex justify-between items-center">
|
||
<span class="text-slate-600 dark:text-slate-400">Log-Dateien:</span>
|
||
<span class="text-slate-900 dark:text-white font-semibold">{{ maintenance_info.log_files_count }}</span>
|
||
</div>
|
||
<div class="flex justify-between items-center">
|
||
<span class="text-slate-600 dark:text-slate-400">Cache-Größe:</span>
|
||
<span class="text-slate-900 dark:text-white font-semibold">{{ maintenance_info.cache_size }}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Wartungs-Buttons -->
|
||
<div class="space-y-4">
|
||
<button id="advanced-clear-cache" class="modern-btn btn-primary w-full">
|
||
🗑️ System-Cache leeren
|
||
</button>
|
||
|
||
<button id="advanced-optimize-db" class="modern-btn btn-success w-full">
|
||
🔧 Datenbank optimieren
|
||
</button>
|
||
|
||
<button id="advanced-create-backup" class="modern-btn btn-purple w-full">
|
||
💾 Vollständiges Backup erstellen
|
||
</button>
|
||
|
||
<button id="advanced-cleanup-logs" class="modern-btn btn-warning w-full">
|
||
📋 Log-Dateien bereinigen
|
||
</button>
|
||
|
||
<button id="advanced-system-check" class="modern-btn btn-indigo w-full">
|
||
🔍 System-Integritätsprüfung
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Erweiterte Optionen -->
|
||
<div class="glass-card p-8 mt-12">
|
||
<div class="flex items-center space-x-4 mb-8">
|
||
<div class="icon-container">
|
||
<span class="text-3xl">🚀</span>
|
||
</div>
|
||
<h2 class="text-3xl font-bold bg-gradient-to-r from-purple-600 to-pink-600 bg-clip-text text-transparent">
|
||
Erweiterte Optionen
|
||
</h2>
|
||
</div>
|
||
|
||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||
<!-- Debug-Modus -->
|
||
<div class="glass-card p-6 hover:scale-105 transition-all duration-300">
|
||
<div class="text-center">
|
||
<div class="icon-container mx-auto mb-4 bg-gradient-to-br from-red-500 to-pink-600 text-white">
|
||
<span class="text-2xl">🐛</span>
|
||
</div>
|
||
<h3 class="text-xl font-bold text-slate-900 dark:text-white mb-3">Debug-Modus</h3>
|
||
<p class="text-sm text-slate-600 dark:text-slate-400 mb-6">Erweiterte Protokollierung für Fehlerdiagnose</p>
|
||
<label class="modern-toggle mx-auto">
|
||
<input type="checkbox" id="debug-mode">
|
||
<span class="toggle-slider"></span>
|
||
</label>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Wartungsmodus -->
|
||
<div class="glass-card p-6 hover:scale-105 transition-all duration-300">
|
||
<div class="text-center">
|
||
<div class="icon-container mx-auto mb-4 bg-gradient-to-br from-yellow-500 to-orange-600 text-white">
|
||
<span class="text-2xl">🚧</span>
|
||
</div>
|
||
<h3 class="text-xl font-bold text-slate-900 dark:text-white mb-3">Wartungsmodus</h3>
|
||
<p class="text-sm text-slate-600 dark:text-slate-400 mb-6">System für Wartungsarbeiten sperren</p>
|
||
<label class="modern-toggle mx-auto">
|
||
<input type="checkbox" id="maintenance-mode">
|
||
<span class="toggle-slider"></span>
|
||
</label>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Performance-Monitoring -->
|
||
<div class="glass-card p-6 hover:scale-105 transition-all duration-300">
|
||
<div class="text-center">
|
||
<div class="icon-container mx-auto mb-4 bg-gradient-to-br from-blue-500 to-cyan-600 text-white">
|
||
<span class="text-2xl">📈</span>
|
||
</div>
|
||
<h3 class="text-xl font-bold text-slate-900 dark:text-white mb-3">Performance-Monitoring</h3>
|
||
<p class="text-sm text-slate-600 dark:text-slate-400 mb-6">Detaillierte Leistungsüberwachung</p>
|
||
<label class="modern-toggle mx-auto">
|
||
<input type="checkbox" id="performance-monitoring">
|
||
<span class="toggle-slider"></span>
|
||
</label>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Enhanced Loading Overlay -->
|
||
<div id="loading-overlay" class="fixed inset-0 bg-black/50 backdrop-blur-sm z-50 hidden">
|
||
<div class="flex items-center justify-center h-full">
|
||
<div class="loading-content">
|
||
<div class="flex items-center space-x-6">
|
||
<div class="relative">
|
||
<div class="animate-spin rounded-full h-12 w-12 border-4 border-blue-200"></div>
|
||
<div class="animate-spin rounded-full h-12 w-12 border-4 border-blue-500 border-t-transparent absolute top-0 left-0"></div>
|
||
</div>
|
||
<span class="text-slate-900 dark:text-white font-semibold text-lg">Wird verarbeitet...</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
// ===== ERWEITERTE EINSTELLUNGEN JAVASCRIPT =====
|
||
|
||
class AdvancedSettings {
|
||
constructor() {
|
||
this.csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content');
|
||
this.initializeEventListeners();
|
||
this.initializeAnimations();
|
||
}
|
||
|
||
initializeEventListeners() {
|
||
// Optimierungs-Formular
|
||
const optimizationForm = document.getElementById('optimization-form');
|
||
if (optimizationForm) {
|
||
optimizationForm.addEventListener('submit', (e) => {
|
||
e.preventDefault();
|
||
this.saveOptimizationSettings(new FormData(optimizationForm));
|
||
});
|
||
}
|
||
|
||
// Wartungs-Buttons
|
||
document.getElementById('advanced-clear-cache')?.addEventListener('click', () => this.clearCache());
|
||
document.getElementById('advanced-optimize-db')?.addEventListener('click', () => this.optimizeDatabase());
|
||
document.getElementById('advanced-create-backup')?.addEventListener('click', () => this.createBackup());
|
||
document.getElementById('advanced-cleanup-logs')?.addEventListener('click', () => this.cleanupLogs());
|
||
document.getElementById('advanced-system-check')?.addEventListener('click', () => this.systemCheck());
|
||
|
||
// Erweiterte Optionen
|
||
document.getElementById('debug-mode')?.addEventListener('change', (e) => this.toggleDebugMode(e.target.checked));
|
||
document.getElementById('maintenance-mode')?.addEventListener('change', (e) => this.toggleMaintenanceMode(e.target.checked));
|
||
document.getElementById('performance-monitoring')?.addEventListener('change', (e) => this.togglePerformanceMonitoring(e.target.checked));
|
||
}
|
||
|
||
initializeAnimations() {
|
||
// Intersection Observer für Scroll-Animationen
|
||
const observer = new IntersectionObserver((entries) => {
|
||
entries.forEach(entry => {
|
||
if (entry.isIntersecting) {
|
||
entry.target.style.opacity = '1';
|
||
entry.target.style.transform = 'translateY(0)';
|
||
}
|
||
});
|
||
});
|
||
|
||
document.querySelectorAll('.glass-card').forEach(card => {
|
||
card.style.opacity = '0';
|
||
card.style.transform = 'translateY(20px)';
|
||
card.style.transition = 'opacity 0.6s ease, transform 0.6s ease';
|
||
observer.observe(card);
|
||
});
|
||
}
|
||
|
||
async saveOptimizationSettings(formData) {
|
||
try {
|
||
this.showLoading(true);
|
||
|
||
const settings = {
|
||
algorithm: formData.get('algorithm'),
|
||
consider_distance: formData.get('consider_distance') === 'on',
|
||
minimize_changeover: formData.get('minimize_changeover') === 'on',
|
||
auto_optimization_enabled: formData.get('auto_optimization_enabled') === 'on',
|
||
max_batch_size: parseInt(formData.get('max_batch_size')),
|
||
time_window: parseInt(formData.get('time_window'))
|
||
};
|
||
|
||
const response = await fetch('/api/optimization/settings', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
'X-CSRFToken': this.csrfToken
|
||
},
|
||
body: JSON.stringify(settings)
|
||
});
|
||
|
||
const result = await response.json();
|
||
|
||
if (result.success) {
|
||
this.showNotification('✅ Optimierungs-Einstellungen erfolgreich gespeichert!', 'success');
|
||
} else {
|
||
this.showNotification('❌ Fehler beim Speichern der Einstellungen', 'error');
|
||
}
|
||
|
||
} catch (error) {
|
||
console.error('Fehler beim Speichern der Optimierungs-Einstellungen:', error);
|
||
this.showNotification('❌ Fehler beim Speichern der Einstellungen', 'error');
|
||
} finally {
|
||
this.showLoading(false);
|
||
}
|
||
}
|
||
|
||
async clearCache() {
|
||
if (!confirm('🗑️ Möchten Sie wirklich den System-Cache leeren?')) return;
|
||
|
||
try {
|
||
this.showLoading(true);
|
||
|
||
const response = await fetch('/api/admin/maintenance/clear-cache', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
'X-CSRFToken': this.csrfToken
|
||
}
|
||
});
|
||
|
||
const result = await response.json();
|
||
|
||
if (result.success) {
|
||
this.showNotification('✅ System-Cache erfolgreich geleert!', 'success');
|
||
} else {
|
||
this.showNotification('❌ Fehler beim Leeren des Cache', 'error');
|
||
}
|
||
|
||
} catch (error) {
|
||
this.showNotification('❌ Fehler beim Leeren des Cache', 'error');
|
||
} finally {
|
||
this.showLoading(false);
|
||
}
|
||
}
|
||
|
||
async optimizeDatabase() {
|
||
if (!confirm('🔧 Möchten Sie die Datenbank optimieren? Dies kann einige Minuten dauern.')) return;
|
||
|
||
try {
|
||
this.showLoading(true);
|
||
|
||
const response = await fetch('/api/admin/maintenance/optimize-database', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
'X-CSRFToken': this.csrfToken
|
||
}
|
||
});
|
||
|
||
const result = await response.json();
|
||
|
||
if (result.success) {
|
||
this.showNotification('✅ Datenbank erfolgreich optimiert!', 'success');
|
||
} else {
|
||
this.showNotification('❌ Fehler bei der Datenbank-Optimierung', 'error');
|
||
}
|
||
|
||
} catch (error) {
|
||
this.showNotification('❌ Fehler bei der Datenbank-Optimierung', 'error');
|
||
} finally {
|
||
this.showLoading(false);
|
||
}
|
||
}
|
||
|
||
async createBackup() {
|
||
if (!confirm('💾 Möchten Sie ein vollständiges System-Backup erstellen?')) return;
|
||
|
||
try {
|
||
this.showLoading(true);
|
||
|
||
const response = await fetch('/api/admin/maintenance/create-backup', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
'X-CSRFToken': this.csrfToken
|
||
}
|
||
});
|
||
|
||
const result = await response.json();
|
||
|
||
if (result.success) {
|
||
this.showNotification('✅ Backup erfolgreich erstellt!', 'success');
|
||
} else {
|
||
this.showNotification('❌ Fehler beim Erstellen des Backups', 'error');
|
||
}
|
||
|
||
} catch (error) {
|
||
this.showNotification('❌ Fehler beim Erstellen des Backups', 'error');
|
||
} finally {
|
||
this.showLoading(false);
|
||
}
|
||
}
|
||
|
||
async cleanupLogs() {
|
||
if (!confirm('📋 Möchten Sie alte Log-Dateien bereinigen? (älter als 30 Tage)')) return;
|
||
|
||
try {
|
||
this.showLoading(true);
|
||
|
||
const response = await fetch('/api/admin/maintenance/cleanup-logs', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
'X-CSRFToken': this.csrfToken
|
||
}
|
||
});
|
||
|
||
const result = await response.json();
|
||
|
||
if (result.success) {
|
||
this.showNotification('✅ Log-Dateien erfolgreich bereinigt!', 'success');
|
||
} else {
|
||
this.showNotification('❌ Fehler beim Bereinigen der Log-Dateien', 'error');
|
||
}
|
||
|
||
} catch (error) {
|
||
this.showNotification('❌ Fehler beim Bereinigen der Log-Dateien', 'error');
|
||
} finally {
|
||
this.showLoading(false);
|
||
}
|
||
}
|
||
|
||
async systemCheck() {
|
||
try {
|
||
this.showLoading(true);
|
||
|
||
const response = await fetch('/api/admin/maintenance/system-check', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
'X-CSRFToken': this.csrfToken
|
||
}
|
||
});
|
||
|
||
const result = await response.json();
|
||
|
||
if (result.success) {
|
||
this.showNotification('✅ System-Integritätsprüfung abgeschlossen!', 'success');
|
||
} else {
|
||
this.showNotification('❌ Fehler bei der System-Integritätsprüfung', 'error');
|
||
}
|
||
|
||
} catch (error) {
|
||
this.showNotification('❌ Fehler bei der System-Integritätsprüfung', 'error');
|
||
} finally {
|
||
this.showLoading(false);
|
||
}
|
||
}
|
||
|
||
toggleDebugMode(enabled) {
|
||
console.log('Debug-Modus:', enabled ? 'aktiviert' : 'deaktiviert');
|
||
this.showNotification(`🐛 Debug-Modus ${enabled ? 'aktiviert' : 'deaktiviert'}`, 'info');
|
||
}
|
||
|
||
toggleMaintenanceMode(enabled) {
|
||
console.log('Wartungsmodus:', enabled ? 'aktiviert' : 'deaktiviert');
|
||
this.showNotification(`🚧 Wartungsmodus ${enabled ? 'aktiviert' : 'deaktiviert'}`, enabled ? 'warning' : 'info');
|
||
}
|
||
|
||
togglePerformanceMonitoring(enabled) {
|
||
console.log('Performance-Monitoring:', enabled ? 'aktiviert' : 'deaktiviert');
|
||
this.showNotification(`📈 Performance-Monitoring ${enabled ? 'aktiviert' : 'deaktiviert'}`, 'info');
|
||
}
|
||
|
||
showLoading(show) {
|
||
const overlay = document.getElementById('loading-overlay');
|
||
if (overlay) {
|
||
if (show) {
|
||
overlay.classList.remove('hidden');
|
||
} else {
|
||
overlay.classList.add('hidden');
|
||
}
|
||
}
|
||
}
|
||
|
||
showNotification(message, type = 'info') {
|
||
// Erstelle moderne Notification mit Glasmorphismus
|
||
const notification = document.createElement('div');
|
||
notification.className = `notification fixed top-6 right-6 z-50 p-6 max-w-sm transition-all duration-500 transform translate-x-full opacity-0 ${
|
||
type === 'success' ? 'border-green-400' :
|
||
type === 'error' ? 'border-red-400' :
|
||
type === 'warning' ? 'border-yellow-400' :
|
||
'border-blue-400'
|
||
}`;
|
||
|
||
notification.innerHTML = `
|
||
<div class="flex items-center space-x-4">
|
||
<div class="flex-shrink-0 text-2xl">
|
||
${type === 'success' ? '✅' : type === 'error' ? '❌' : type === 'warning' ? '⚠️' : 'ℹ️'}
|
||
</div>
|
||
<div class="text-slate-900 dark:text-white font-medium">${message}</div>
|
||
<button onclick="this.parentElement.parentElement.remove()" class="ml-auto text-slate-500 hover:text-slate-700 dark:text-slate-400 dark:hover:text-slate-200 transition-colors">
|
||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
`;
|
||
|
||
document.body.appendChild(notification);
|
||
|
||
// Animation einblenden
|
||
setTimeout(() => {
|
||
notification.style.transform = 'translateX(0)';
|
||
notification.style.opacity = '1';
|
||
}, 100);
|
||
|
||
// Automatisch entfernen nach 5 Sekunden
|
||
setTimeout(() => {
|
||
if (notification.parentNode) {
|
||
notification.style.transform = 'translateX(100%)';
|
||
notification.style.opacity = '0';
|
||
setTimeout(() => {
|
||
if (notification.parentNode) {
|
||
notification.parentNode.removeChild(notification);
|
||
}
|
||
}, 500);
|
||
}
|
||
}, 5000);
|
||
}
|
||
}
|
||
|
||
// Initialisierung nach DOM-Laden
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
new AdvancedSettings();
|
||
});
|
||
</script>
|
||
{% endblock %} |