Projektarbeit-MYP/backend/templates/admin_advanced_settings.html

893 lines
37 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{% 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 %}