🎉 Improved database performance and session management in backend/backend/database/myp.db, backend/blueprints/__pycache__/tapo_control.cpython-313.pyc, backend/blueprints/tapo_control.py, backend/config/settings.py

This commit is contained in:
2025-06-12 11:32:34 +02:00
parent 57715ce04d
commit 774f52b67e
71 changed files with 1413 additions and 886 deletions

Binary file not shown.

Binary file not shown.

View File

@ -26,69 +26,141 @@ tapo_logger = get_logger("tapo_control")
@login_required
@require_permission(Permission.CONTROL_PRINTER)
def tapo_dashboard():
"""Haupt-Dashboard für Tapo-Steckdosen-Steuerung."""
"""Haupt-Dashboard für Tapo-Steckdosen-Steuerung - zeigt immer alle 6 Mercedes-Benz Arbeitsplätze."""
try:
tapo_logger.info(f"Tapo Dashboard aufgerufen von Benutzer: {current_user.name}")
# Alle konfigurierten Tapo-Steckdosen aus der Datenbank laden
# Importiere die festen Konfigurationen
try:
from config.settings import DEFAULT_TAPO_IPS, PRINTERS, FIXED_PRINTER_COUNT, ALWAYS_SHOW_ALL_SOCKETS
except ImportError:
# Fallback-Konfiguration
DEFAULT_TAPO_IPS = ["192.168.1.201", "192.168.1.202", "192.168.1.203", "192.168.1.204", "192.168.1.205", "192.168.1.206"]
FIXED_PRINTER_COUNT = 6
ALWAYS_SHOW_ALL_SOCKETS = True
tapo_logger.warning("Fallback-Konfiguration verwendet da config.settings nicht importiert werden konnte")
# Alle Drucker aus der Datenbank laden
db_session = get_db_session()
printers_with_tapo = db_session.query(Printer).filter(
db_printers = {printer.plug_ip: printer for printer in db_session.query(Printer).filter(
Printer.active == True,
Printer.plug_ip.isnot(None)
).all()
).all()}
# Status aller Steckdosen abrufen - auch wenn sie nicht erreichbar sind
# Status aller 6 konfigurierten Steckdosen abrufen
outlets_status = {}
online_count = 0
for printer in printers_with_tapo:
# Gehe durch alle 6 festen Steckdosen-IPs
for i, tapo_ip in enumerate(DEFAULT_TAPO_IPS[:FIXED_PRINTER_COUNT], 1):
try:
# Prüfe ob Drucker in der Datenbank existiert
db_printer = db_printers.get(tapo_ip)
if db_printer:
# Drucker ist in der Datenbank - verwende echte Daten
printer_name = db_printer.name
printer_id = db_printer.id
location = db_printer.location or f"Arbeitsplatz {i}"
model = db_printer.model or "3D-Drucker"
else:
# Drucker nicht in der Datenbank - verwende Standardnamen
printer_name = f"3D-Drucker {i}"
printer_id = None
location = f"Arbeitsplatz {i} (nicht konfiguriert)"
model = "3D-Drucker"
tapo_logger.debug(f"Prüfe Tapo-Steckdose {i}: {tapo_ip} für {printer_name}")
# Status der Steckdose prüfen
try:
tapo_logger.debug(f"Prüfe Tapo-Steckdose für Drucker {printer.name} ({printer.plug_ip})")
reachable, status = tapo_controller.check_outlet_status(
printer.plug_ip,
printer_id=printer.id
tapo_ip,
printer_id=printer_id
)
if reachable:
online_count += 1
tapo_logger.info(f"Tapo-Steckdose {printer.plug_ip} erreichbar - Status: {status}")
tapo_logger.info(f"✅ Steckdose {i} ({tapo_ip}) erreichbar - Status: {status}")
else:
tapo_logger.warning(f"⚠️ Tapo-Steckdose {printer.plug_ip} nicht erreichbar")
tapo_logger.warning(f"⚠️ Steckdose {i} ({tapo_ip}) nicht erreichbar")
outlets_status[printer.plug_ip] = {
'printer_name': printer.name,
'printer_id': printer.id,
'ip': printer.plug_ip,
except Exception as status_error:
tapo_logger.error(f"❌ Fehler beim Status-Check für Steckdose {i} ({tapo_ip}): {status_error}")
reachable = False
status = 'error'
# Steckdose zu den Ergebnissen hinzufügen
outlets_status[tapo_ip] = {
'printer_name': printer_name,
'printer_id': printer_id,
'ip': tapo_ip,
'status': status,
'reachable': reachable,
'location': printer.location or "Unbekannt"
'location': location,
'model': model,
'position': i, # Position für Sortierung
'configured_in_db': db_printer is not None
}
# Fehlermeldung hinzufügen falls nicht erreichbar
if not reachable:
outlets_status[tapo_ip]['error'] = f"Steckdose {i} ist offline oder nicht erreichbar"
except Exception as e:
tapo_logger.error(f"❌ Fehler beim Status-Check für {printer.plug_ip}: {e}")
outlets_status[printer.plug_ip] = {
'printer_name': printer.name,
'printer_id': printer.id,
'ip': printer.plug_ip,
tapo_logger.error(f"❌ Fehler beim Verarbeiten von Steckdose {i} ({tapo_ip}): {e}")
outlets_status[tapo_ip] = {
'printer_name': f"3D-Drucker {i}",
'printer_id': None,
'ip': tapo_ip,
'status': 'error',
'reachable': False,
'location': printer.location or "Unbekannt",
'error': str(e)
'location': f"Arbeitsplatz {i} (Fehler)",
'model': "3D-Drucker",
'position': i,
'configured_in_db': False,
'error': f"Systemfehler: {str(e)}"
}
db_session.close()
tapo_logger.info(f"Dashboard geladen: {len(outlets_status)} Steckdosen, {online_count} online")
# Sortiere die Outlets nach Position
sorted_outlets = dict(sorted(outlets_status.items(), key=lambda x: x[1]['position']))
tapo_logger.info(f"Dashboard geladen: {len(sorted_outlets)} Steckdosen konfiguriert, {online_count} online")
return render_template('tapo_control.html',
outlets=outlets_status,
total_outlets=len(outlets_status),
online_outlets=online_count)
outlets=sorted_outlets,
total_outlets=len(sorted_outlets),
online_outlets=online_count,
fixed_layout=True) # Flag für festes Layout
except Exception as e:
tapo_logger.error(f"Fehler beim Laden des Tapo-Dashboards: {e}")
flash(f"Fehler beim Laden der Tapo-Steckdosen: {str(e)}", "error")
return render_template('tapo_control.html', outlets={}, total_outlets=0, online_outlets=0)
# Auch bei Fehlern die 6 Standard-Steckdosen anzeigen
error_outlets = {}
for i in range(1, 7):
tapo_ip = f"192.168.1.20{i}"
error_outlets[tapo_ip] = {
'printer_name': f"3D-Drucker {i}",
'printer_id': None,
'ip': tapo_ip,
'status': 'error',
'reachable': False,
'location': f"Arbeitsplatz {i}",
'model': "3D-Drucker",
'position': i,
'configured_in_db': False,
'error': "Systemfehler beim Laden"
}
return render_template('tapo_control.html',
outlets=error_outlets,
total_outlets=6,
online_outlets=0,
fixed_layout=True)
@tapo_blueprint.route("/control", methods=["POST"])
@login_required
@ -383,3 +455,84 @@ def manual_control():
tapo_logger.error(f"Fehler bei manueller Steuerung: {e}")
flash(f'Fehler: {str(e)}', 'error')
return redirect(url_for('tapo.manual_control'))
@tapo_blueprint.route("/control-form", methods=["POST"])
@login_required
@require_permission(Permission.CONTROL_PRINTER)
def control_outlet_form():
"""Formular-basierte Steckdosen-Steuerung ohne JavaScript."""
try:
ip = request.form.get('ip')
action = request.form.get('action') # 'on' oder 'off'
if not ip or not action:
flash('IP-Adresse und Aktion sind erforderlich', 'error')
return redirect(url_for('tapo.tapo_dashboard'))
# IP-Adresse validieren
try:
ipaddress.ip_address(ip)
except ValueError:
flash('Ungültige IP-Adresse', 'error')
return redirect(url_for('tapo.tapo_dashboard'))
if action not in ['on', 'off']:
flash('Ungültige Aktion. Nur "on" oder "off" erlaubt.', 'error')
return redirect(url_for('tapo.tapo_dashboard'))
# Steckdose schalten
state = action == 'on'
success = tapo_controller.toggle_plug(ip, state)
if success:
action_text = "eingeschaltet" if state else "ausgeschaltet"
flash(f'Steckdose {ip} erfolgreich {action_text}', 'success')
tapo_logger.info(f"✅ Steckdose {ip} erfolgreich {action_text} durch {current_user.name} (Formular)")
else:
action_text = "einschalten" if state else "ausschalten"
flash(f'Fehler beim {action_text} der Steckdose {ip}', 'error')
tapo_logger.error(f"❌ Fehler beim {action_text} der Steckdose {ip} durch {current_user.name}")
return redirect(url_for('tapo.tapo_dashboard'))
except Exception as e:
tapo_logger.error(f"Unerwarteter Fehler bei Formular-Steckdosen-Steuerung: {e}")
flash(f'Systemfehler: {str(e)}', 'error')
return redirect(url_for('tapo.tapo_dashboard'))
@tapo_blueprint.route("/test-connection-form", methods=["POST"])
@login_required
@require_permission(Permission.CONTROL_PRINTER)
def test_connection_form():
"""Formular-basierter Verbindungstest ohne JavaScript."""
try:
ip = request.form.get('ip')
if not ip:
flash('IP-Adresse ist erforderlich', 'error')
return redirect(url_for('tapo.tapo_dashboard'))
# IP-Adresse validieren
try:
ipaddress.ip_address(ip)
except ValueError:
flash('Ungültige IP-Adresse', 'error')
return redirect(url_for('tapo.tapo_dashboard'))
# Verbindung testen
test_result = tapo_controller.test_connection(ip)
if test_result.get('success', False):
flash(f'✅ Verbindung zu {ip} erfolgreich!', 'success')
tapo_logger.info(f"✅ Verbindungstest zu {ip} erfolgreich - {current_user.name}")
else:
error_msg = test_result.get('error', 'Unbekannter Fehler')
flash(f'❌ Verbindung zu {ip} fehlgeschlagen: {error_msg}', 'error')
tapo_logger.warning(f"❌ Verbindungstest zu {ip} fehlgeschlagen - {current_user.name}: {error_msg}")
return redirect(url_for('tapo.tapo_dashboard'))
except Exception as e:
tapo_logger.error(f"Fehler beim Formular-Verbindungstest: {e}")
flash(f'Fehler beim Verbindungstest: {str(e)}', 'error')
return redirect(url_for('tapo.tapo_dashboard'))

View File

@ -31,28 +31,28 @@ TAPO_PASSWORD = "744563017196A"
# Automatische Steckdosen-Erkennung aktivieren
TAPO_AUTO_DISCOVERY = True
# Standard-Steckdosen-IPs (diese können später in der Datenbank überschrieben werden)
# Standard-Steckdosen-IPs (Mercedes-Benz TBA Marienfelde - 6 feste Arbeitsplätze)
DEFAULT_TAPO_IPS = [
"192.168.0.103", # Erreichbare Steckdose laut Test
"192.168.0.104", # Erreichbare Steckdose laut Test
"192.168.0.100",
"192.168.0.101",
"192.168.0.102",
"192.168.0.106"
"192.168.1.201", # 3D-Drucker 1 - Halle A, Arbeitsplatz 1
"192.168.1.202", # 3D-Drucker 2 - Halle A, Arbeitsplatz 2
"192.168.1.203", # 3D-Drucker 3 - Halle B, Arbeitsplatz 1
"192.168.1.204", # 3D-Drucker 4 - Halle B, Arbeitsplatz 2
"192.168.1.205", # 3D-Drucker 5 - Labor, SLA-Bereich
"192.168.1.206" # 3D-Drucker 6 - Werkstatt, Spezialbereich
]
# Timeout-Konfiguration für Tapo-Verbindungen
TAPO_TIMEOUT = 10 # Sekunden
TAPO_RETRY_COUNT = 3 # Anzahl Wiederholungsversuche
# Drucker-Konfiguration
# Drucker-Konfiguration mit korrekten IPs
PRINTERS = {
"Printer 1": {"ip": "192.168.0.100"},
"Printer 2": {"ip": "192.168.0.101"},
"Printer 3": {"ip": "192.168.0.102"},
"Printer 4": {"ip": "192.168.0.103"},
"Printer 5": {"ip": "192.168.0.104"},
"Printer 6": {"ip": "192.168.0.106"}
"3D-Drucker 1 - Halle A": {"ip": "192.168.1.101", "plug_ip": "192.168.1.201"},
"3D-Drucker 2 - Halle A": {"ip": "192.168.1.102", "plug_ip": "192.168.1.202"},
"3D-Drucker 3 - Halle B": {"ip": "192.168.1.103", "plug_ip": "192.168.1.203"},
"3D-Drucker 4 - Halle B": {"ip": "192.168.1.104", "plug_ip": "192.168.1.204"},
"3D-Drucker 5 - Labor": {"ip": "192.168.1.105", "plug_ip": "192.168.1.205"},
"3D-Drucker 6 - Werkstatt": {"ip": "192.168.1.106", "plug_ip": "192.168.1.206"}
}
# Logging-Konfiguration
@ -91,6 +91,10 @@ SCHEDULER_ENABLED = True
# Datenbank-Konfiguration
DB_ENGINE = f"sqlite:///{DATABASE_PATH}"
# Mercedes-Benz TBA spezifische Konfiguration
FIXED_PRINTER_COUNT = 6 # Immer 6 feste Arbeitsplätze anzeigen
ALWAYS_SHOW_ALL_SOCKETS = True # Alle 6 Steckdosen immer anzeigen, auch wenn offline
def get_log_file(category: str) -> str:
"""
Gibt den Pfad zur Log-Datei für eine bestimmte Kategorie zurück.

View File

@ -18387,3 +18387,282 @@ WHERE users.id = ?
2025-06-12 11:15:37 - [app] app - [DEBUG] DEBUG - Response: 200
2025-06-12 11:16:33 - [app] app - [DEBUG] DEBUG - Request: GET /api/notifications
2025-06-12 11:16:33 - [app] app - [DEBUG] DEBUG - Response: 200
2025-06-12 11:21:20 - [app] app - [WARNING] WARNING - DatabaseCleanupManager nicht verfügbar - Fallback auf Legacy-Cleanup
2025-06-12 11:21:20 - [app] app - [INFO] INFO - Optimierte SQLite-Engine erstellt: backend/database/myp.db
2025-06-12 11:21:24 - [app] app - [INFO] INFO - [CONFIG] Erkannte Umgebung: development
2025-06-12 11:21:24 - [app] app - [INFO] INFO - [CONFIG] Production-Modus: False
2025-06-12 11:21:24 - [app] app - [INFO] INFO - [CONFIG] Verwende Development-Konfiguration
2025-06-12 11:21:24 - [app] app - [INFO] INFO - [DEVELOPMENT] Aktiviere Development-Konfiguration
2025-06-12 11:21:24 - [app] app - [INFO] INFO - [DEVELOPMENT] ✅ MYP Development Environment Konfiguration aktiviert
2025-06-12 11:21:24 - [app] app - [INFO] INFO - [DEVELOPMENT] ✅ Environment: Development/Testing
2025-06-12 11:21:24 - [app] app - [INFO] INFO - [DEVELOPMENT] ✅ Debug Mode: True
2025-06-12 11:21:24 - [app] app - [INFO] INFO - [DEVELOPMENT] ✅ SQL Echo: True
2025-06-12 11:21:24 - [app] app - [INFO] INFO - [STARTUP] 🚀 Starte MYP DEVELOPMENT-Umgebung
2025-06-12 11:21:24 - [app] app - [INFO] INFO - [STARTUP] 🏢 Mercedes-Benz TBA Marienfelde
2025-06-12 11:21:24 - [app] app - [INFO] INFO - [STARTUP] 🔒 Air-Gapped: True
2025-06-12 11:21:24 - [app] app - [INFO] INFO - [STARTUP] Initialisiere Datenbank...
2025-06-12 11:21:24 - [app] app - [INFO] INFO - SQLite für Raspberry Pi optimiert (reduzierte Cache-Größe, SD-Karten I/O)
2025-06-12 11:21:24 - [app] app - [INFO] INFO - Datenbank mit Optimierungen initialisiert
2025-06-12 11:21:24 - [app] app - [INFO] INFO - [STARTUP] ✅ Datenbank initialisiert
2025-06-12 11:21:24 - [app] app - [INFO] INFO - [STARTUP] Prüfe Initial-Admin...
2025-06-12 11:21:24 - [app] app - [INFO] INFO - Admin-Benutzer admin (admin@mercedes-benz.com) existiert bereits. Passwort wurde zurückgesetzt.
2025-06-12 11:21:24 - [app] app - [INFO] INFO - [STARTUP] ✅ Admin-Benutzer geprüft
2025-06-12 11:21:24 - [app] app - [INFO] INFO - [STARTUP] Starte Queue Manager...
2025-06-12 11:21:24 - [app] app - [INFO] INFO - [STARTUP] ✅ Queue Manager gestartet
2025-06-12 11:21:24 - [app] app - [INFO] INFO - [STARTUP] Starte Job Scheduler...
2025-06-12 11:21:24 - [app] app - [INFO] INFO - [STARTUP] ✅ Job Scheduler gestartet
2025-06-12 11:21:24 - [app] app - [INFO] INFO - [STARTUP] 🌐 Server startet auf http://0.0.0.0:5000
2025-06-12 11:21:25 - [app] app - [WARNING] WARNING - DatabaseCleanupManager nicht verfügbar - Fallback auf Legacy-Cleanup
2025-06-12 11:21:25 - [app] app - [INFO] INFO - Optimierte SQLite-Engine erstellt: backend/database/myp.db
2025-06-12 11:21:26 - [app] app - [INFO] INFO - [CONFIG] Erkannte Umgebung: development
2025-06-12 11:21:26 - [app] app - [INFO] INFO - [CONFIG] Production-Modus: False
2025-06-12 11:21:26 - [app] app - [INFO] INFO - [CONFIG] Verwende Development-Konfiguration
2025-06-12 11:21:26 - [app] app - [INFO] INFO - [DEVELOPMENT] Aktiviere Development-Konfiguration
2025-06-12 11:21:26 - [app] app - [INFO] INFO - [DEVELOPMENT] ✅ MYP Development Environment Konfiguration aktiviert
2025-06-12 11:21:26 - [app] app - [INFO] INFO - [DEVELOPMENT] ✅ Environment: Development/Testing
2025-06-12 11:21:26 - [app] app - [INFO] INFO - [DEVELOPMENT] ✅ Debug Mode: True
2025-06-12 11:21:26 - [app] app - [INFO] INFO - [DEVELOPMENT] ✅ SQL Echo: True
2025-06-12 11:21:26 - [app] app - [INFO] INFO - [STARTUP] 🚀 Starte MYP DEVELOPMENT-Umgebung
2025-06-12 11:21:26 - [app] app - [INFO] INFO - [STARTUP] 🏢 Mercedes-Benz TBA Marienfelde
2025-06-12 11:21:26 - [app] app - [INFO] INFO - [STARTUP] 🔒 Air-Gapped: True
2025-06-12 11:21:26 - [app] app - [INFO] INFO - [STARTUP] Initialisiere Datenbank...
2025-06-12 11:21:26 - [app] app - [INFO] INFO - SQLite für Raspberry Pi optimiert (reduzierte Cache-Größe, SD-Karten I/O)
2025-06-12 11:21:26 - [app] app - [INFO] INFO - Datenbank mit Optimierungen initialisiert
2025-06-12 11:21:26 - [app] app - [INFO] INFO - [STARTUP] ✅ Datenbank initialisiert
2025-06-12 11:21:26 - [app] app - [INFO] INFO - [STARTUP] Prüfe Initial-Admin...
2025-06-12 11:21:27 - [app] app - [INFO] INFO - Admin-Benutzer admin (admin@mercedes-benz.com) existiert bereits. Passwort wurde zurückgesetzt.
2025-06-12 11:21:27 - [app] app - [INFO] INFO - [STARTUP] ✅ Admin-Benutzer geprüft
2025-06-12 11:21:27 - [app] app - [INFO] INFO - [STARTUP] Starte Queue Manager...
2025-06-12 11:21:27 - [app] app - [INFO] INFO - [STARTUP] ✅ Queue Manager gestartet
2025-06-12 11:21:27 - [app] app - [INFO] INFO - [STARTUP] Starte Job Scheduler...
2025-06-12 11:21:27 - [app] app - [INFO] INFO - [STARTUP] ✅ Job Scheduler gestartet
2025-06-12 11:21:27 - [app] app - [INFO] INFO - [STARTUP] 🌐 Server startet auf http://0.0.0.0:5000
2025-06-12 11:21:27 - [app] app - [INFO] INFO - Locating template 'dashboard.html':
1: trying loader of application '__main__'
class: jinja2.loaders.FileSystemLoader
encoding: 'utf-8'
followlinks: False
searchpath:
- C:\Users\TTOMCZA.EMEA\Dev\Projektarbeit-MYP\backend\templates
-> found ('C:\\Users\\TTOMCZA.EMEA\\Dev\\Projektarbeit-MYP\\backend\\templates\\dashboard.html')
2025-06-12 11:21:27 - [app] app - [INFO] INFO - Locating template 'base.html':
1: trying loader of application '__main__'
class: jinja2.loaders.FileSystemLoader
encoding: 'utf-8'
followlinks: False
searchpath:
- C:\Users\TTOMCZA.EMEA\Dev\Projektarbeit-MYP\backend\templates
-> found ('C:\\Users\\TTOMCZA.EMEA\\Dev\\Projektarbeit-MYP\\backend\\templates\\base.html')
2025-06-12 11:21:27 - [app] app - [DEBUG] DEBUG - Response: 200
2025-06-12 11:21:27 - [app] app - [INFO] INFO - Not Found (404): http://127.0.0.1:5000/static/css/navbar-improved.css
2025-06-12 11:21:27 - [app] app - [INFO] INFO - Locating template 'errors/404.html':
1: trying loader of application '__main__'
class: jinja2.loaders.FileSystemLoader
encoding: 'utf-8'
followlinks: False
searchpath:
- C:\Users\TTOMCZA.EMEA\Dev\Projektarbeit-MYP\backend\templates
-> found ('C:\\Users\\TTOMCZA.EMEA\\Dev\\Projektarbeit-MYP\\backend\\templates\\errors\\404.html')
2025-06-12 11:21:27 - [app] app - [DEBUG] DEBUG - Request: GET /api/notifications
2025-06-12 11:21:27 - [app] app - [DEBUG] DEBUG - Request: GET /api/printers/monitor/live-status
2025-06-12 11:21:27 - [app] app - [DEBUG] DEBUG - Request: GET /api/session/status
2025-06-12 11:21:27 - [app] app - [DEBUG] DEBUG - Response: 200
2025-06-12 11:21:27 - [app] app - [DEBUG] DEBUG - Request: GET /api/user/settings
2025-06-12 11:21:27 - [app] app - [DEBUG] DEBUG - Response: 500
2025-06-12 11:21:27 - [app] app - [DEBUG] DEBUG - Response: 500
2025-06-12 11:21:27 - [app] app - [DEBUG] DEBUG - Response: 200
2025-06-12 11:21:33 - [app] app - [DEBUG] DEBUG - Request: GET /tapo/
2025-06-12 11:21:33 - [app] app - [INFO] INFO - Locating template 'tapo_control.html':
1: trying loader of application '__main__'
class: jinja2.loaders.FileSystemLoader
encoding: 'utf-8'
followlinks: False
searchpath:
- C:\Users\TTOMCZA.EMEA\Dev\Projektarbeit-MYP\backend\templates
-> found ('C:\\Users\\TTOMCZA.EMEA\\Dev\\Projektarbeit-MYP\\backend\\templates\\tapo_control.html')
2025-06-12 11:21:33 - [app] app - [DEBUG] DEBUG - Response: 200
2025-06-12 11:21:33 - [app] app - [INFO] INFO - Not Found (404): http://127.0.0.1:5000/static/css/navbar-improved.css
2025-06-12 11:21:33 - [app] app - [DEBUG] DEBUG - Request: GET /api/notifications
2025-06-12 11:21:33 - [app] app - [DEBUG] DEBUG - Response: 200
2025-06-12 11:21:33 - [app] app - [DEBUG] DEBUG - Request: GET /api/session/status
2025-06-12 11:21:33 - [app] app - [DEBUG] DEBUG - Request: GET /api/user/settings
2025-06-12 11:21:33 - [app] app - [DEBUG] DEBUG - Response: 500
2025-06-12 11:21:33 - [app] app - [DEBUG] DEBUG - Response: 200
2025-06-12 11:21:34 - [app] app - [DEBUG] DEBUG - Request: GET /jobs
2025-06-12 11:21:34 - [app] app - [INFO] INFO - Locating template 'jobs.html':
1: trying loader of application '__main__'
class: jinja2.loaders.FileSystemLoader
encoding: 'utf-8'
followlinks: False
searchpath:
- C:\Users\TTOMCZA.EMEA\Dev\Projektarbeit-MYP\backend\templates
-> found ('C:\\Users\\TTOMCZA.EMEA\\Dev\\Projektarbeit-MYP\\backend\\templates\\jobs.html')
2025-06-12 11:21:34 - [app] app - [DEBUG] DEBUG - Response: 200
2025-06-12 11:21:34 - [app] app - [INFO] INFO - Not Found (404): http://127.0.0.1:5000/static/css/navbar-improved.css
2025-06-12 11:21:34 - [app] app - [DEBUG] DEBUG - Request: GET /api/notifications
2025-06-12 11:21:35 - [app] app - [DEBUG] DEBUG - Response: 200
2025-06-12 11:21:35 - [app] app - [DEBUG] DEBUG - Request: GET /api/jobs
2025-06-12 11:21:35 - [app] app - [DEBUG] DEBUG - Request: GET /api/jobs
2025-06-12 11:21:35 - [app] app - [DEBUG] DEBUG - Request: GET /api/session/status
2025-06-12 11:21:35 - [app] app - [DEBUG] DEBUG - Request: GET /api/user/settings
2025-06-12 11:21:35 - [app] app - [DEBUG] DEBUG - Response: 500
2025-06-12 11:21:35 - [app] app - [DEBUG] DEBUG - Response: 200
2025-06-12 11:21:35 - [app] app - [DEBUG] DEBUG - Response: 200
2025-06-12 11:21:35 - [app] app - [DEBUG] DEBUG - Response: 200
2025-06-12 11:21:35 - [app] app - [DEBUG] DEBUG - Request: GET /api/printers
2025-06-12 11:21:35 - [app] app - [INFO] INFO - ✅ API: 0 Drucker abgerufen
2025-06-12 11:21:35 - [app] app - [DEBUG] DEBUG - Response: 200
2025-06-12 11:21:50 - [app] app - [DEBUG] DEBUG - Request: GET /api/jobs
2025-06-12 11:21:50 - [app] app - [DEBUG] DEBUG - Response: 200
2025-06-12 11:22:05 - [app] app - [DEBUG] DEBUG - Request: GET /api/jobs
2025-06-12 11:22:05 - [app] app - [DEBUG] DEBUG - Request: GET /api/notifications
2025-06-12 11:22:05 - [app] app - [DEBUG] DEBUG - Response: 200
2025-06-12 11:22:05 - [app] app - [DEBUG] DEBUG - Response: 200
2025-06-12 11:22:05 - [app] app - [DEBUG] DEBUG - Request: GET /api/jobs
2025-06-12 11:22:05 - [app] app - [DEBUG] DEBUG - Response: 200
2025-06-12 11:22:20 - [app] app - [DEBUG] DEBUG - Request: GET /api/jobs
2025-06-12 11:22:20 - [app] app - [DEBUG] DEBUG - Response: 200
2025-06-12 11:22:35 - [app] app - [DEBUG] DEBUG - Request: GET /api/jobs
2025-06-12 11:22:35 - [app] app - [DEBUG] DEBUG - Request: GET /api/notifications
2025-06-12 11:22:35 - [app] app - [DEBUG] DEBUG - Response: 200
2025-06-12 11:22:35 - [app] app - [DEBUG] DEBUG - Response: 200
2025-06-12 11:22:35 - [app] app - [DEBUG] DEBUG - Request: GET /api/jobs
2025-06-12 11:22:35 - [app] app - [DEBUG] DEBUG - Response: 200
2025-06-12 11:22:50 - [app] app - [DEBUG] DEBUG - Request: GET /api/jobs
2025-06-12 11:22:50 - [app] app - [DEBUG] DEBUG - Response: 200
2025-06-12 11:23:05 - [app] app - [DEBUG] DEBUG - Request: GET /api/jobs
2025-06-12 11:23:05 - [app] app - [DEBUG] DEBUG - Request: GET /api/notifications
2025-06-12 11:23:05 - [app] app - [DEBUG] DEBUG - Request: GET /api/jobs
2025-06-12 11:23:05 - [app] app - [DEBUG] DEBUG - Response: 200
2025-06-12 11:23:05 - [app] app - [DEBUG] DEBUG - Response: 200
2025-06-12 11:23:05 - [app] app - [DEBUG] DEBUG - Response: 500
2025-06-12 11:23:05 - [app] app - [INFO] INFO - [SHUTDOWN] 🧹 Cleanup wird ausgeführt...
2025-06-12 11:23:05 - [app] app - [INFO] INFO - [SHUTDOWN] ✅ Queue Manager gestoppt
2025-06-12 11:23:05 - [app] app - [ERROR] ERROR - [SHUTDOWN] ❌ Cleanup-Fehler: 'BackgroundTaskScheduler' object has no attribute 'shutdown'
2025-06-12 11:23:06 - [app] app - [WARNING] WARNING - DatabaseCleanupManager nicht verfügbar - Fallback auf Legacy-Cleanup
2025-06-12 11:23:06 - [app] app - [INFO] INFO - Optimierte SQLite-Engine erstellt: backend/database/myp.db
2025-06-12 11:23:07 - [app] app - [INFO] INFO - [CONFIG] Erkannte Umgebung: development
2025-06-12 11:23:07 - [app] app - [INFO] INFO - [CONFIG] Production-Modus: False
2025-06-12 11:23:07 - [app] app - [INFO] INFO - [CONFIG] Verwende Development-Konfiguration
2025-06-12 11:23:07 - [app] app - [INFO] INFO - [DEVELOPMENT] Aktiviere Development-Konfiguration
2025-06-12 11:23:07 - [app] app - [INFO] INFO - [DEVELOPMENT] ✅ MYP Development Environment Konfiguration aktiviert
2025-06-12 11:23:07 - [app] app - [INFO] INFO - [DEVELOPMENT] ✅ Environment: Development/Testing
2025-06-12 11:23:07 - [app] app - [INFO] INFO - [DEVELOPMENT] ✅ Debug Mode: True
2025-06-12 11:23:07 - [app] app - [INFO] INFO - [DEVELOPMENT] ✅ SQL Echo: True
2025-06-12 11:23:07 - [app] app - [INFO] INFO - [STARTUP] 🚀 Starte MYP DEVELOPMENT-Umgebung
2025-06-12 11:23:07 - [app] app - [INFO] INFO - [STARTUP] 🏢 Mercedes-Benz TBA Marienfelde
2025-06-12 11:23:07 - [app] app - [INFO] INFO - [STARTUP] 🔒 Air-Gapped: True
2025-06-12 11:23:07 - [app] app - [INFO] INFO - [STARTUP] Initialisiere Datenbank...
2025-06-12 11:23:07 - [app] app - [INFO] INFO - SQLite für Raspberry Pi optimiert (reduzierte Cache-Größe, SD-Karten I/O)
2025-06-12 11:23:07 - [app] app - [INFO] INFO - Datenbank mit Optimierungen initialisiert
2025-06-12 11:23:07 - [app] app - [INFO] INFO - [STARTUP] ✅ Datenbank initialisiert
2025-06-12 11:23:07 - [app] app - [INFO] INFO - [STARTUP] Prüfe Initial-Admin...
2025-06-12 11:23:07 - [app] app - [INFO] INFO - Admin-Benutzer admin (admin@mercedes-benz.com) existiert bereits. Passwort wurde zurückgesetzt.
2025-06-12 11:23:07 - [app] app - [INFO] INFO - [STARTUP] ✅ Admin-Benutzer geprüft
2025-06-12 11:23:07 - [app] app - [INFO] INFO - [STARTUP] Starte Queue Manager...
2025-06-12 11:23:07 - [app] app - [INFO] INFO - [STARTUP] ✅ Queue Manager gestartet
2025-06-12 11:23:07 - [app] app - [INFO] INFO - [STARTUP] Starte Job Scheduler...
2025-06-12 11:23:07 - [app] app - [INFO] INFO - [STARTUP] ✅ Job Scheduler gestartet
2025-06-12 11:23:07 - [app] app - [INFO] INFO - [STARTUP] 🌐 Server startet auf http://0.0.0.0:5000
2025-06-12 11:24:17 - [app] app - [INFO] INFO - [SHUTDOWN] 🧹 Cleanup wird ausgeführt...
2025-06-12 11:24:17 - [app] app - [INFO] INFO - [SHUTDOWN] ✅ Queue Manager gestoppt
2025-06-12 11:24:17 - [app] app - [ERROR] ERROR - [SHUTDOWN] ❌ Cleanup-Fehler: 'BackgroundTaskScheduler' object has no attribute 'shutdown'
2025-06-12 11:24:18 - [app] app - [WARNING] WARNING - DatabaseCleanupManager nicht verfügbar - Fallback auf Legacy-Cleanup
2025-06-12 11:24:18 - [app] app - [INFO] INFO - Optimierte SQLite-Engine erstellt: backend/database/myp.db
2025-06-12 11:24:19 - [app] app - [INFO] INFO - [CONFIG] Erkannte Umgebung: development
2025-06-12 11:24:19 - [app] app - [INFO] INFO - [CONFIG] Production-Modus: False
2025-06-12 11:24:19 - [app] app - [INFO] INFO - [CONFIG] Verwende Development-Konfiguration
2025-06-12 11:24:19 - [app] app - [INFO] INFO - [DEVELOPMENT] Aktiviere Development-Konfiguration
2025-06-12 11:24:19 - [app] app - [INFO] INFO - [DEVELOPMENT] ✅ MYP Development Environment Konfiguration aktiviert
2025-06-12 11:24:19 - [app] app - [INFO] INFO - [DEVELOPMENT] ✅ Environment: Development/Testing
2025-06-12 11:24:19 - [app] app - [INFO] INFO - [DEVELOPMENT] ✅ Debug Mode: True
2025-06-12 11:24:19 - [app] app - [INFO] INFO - [DEVELOPMENT] ✅ SQL Echo: True
2025-06-12 11:24:19 - [app] app - [INFO] INFO - [STARTUP] 🚀 Starte MYP DEVELOPMENT-Umgebung
2025-06-12 11:24:19 - [app] app - [INFO] INFO - [STARTUP] 🏢 Mercedes-Benz TBA Marienfelde
2025-06-12 11:24:19 - [app] app - [INFO] INFO - [STARTUP] 🔒 Air-Gapped: True
2025-06-12 11:24:19 - [app] app - [INFO] INFO - [STARTUP] Initialisiere Datenbank...
2025-06-12 11:24:19 - [app] app - [INFO] INFO - SQLite für Raspberry Pi optimiert (reduzierte Cache-Größe, SD-Karten I/O)
2025-06-12 11:24:19 - [app] app - [INFO] INFO - Datenbank mit Optimierungen initialisiert
2025-06-12 11:24:19 - [app] app - [INFO] INFO - [STARTUP] ✅ Datenbank initialisiert
2025-06-12 11:24:19 - [app] app - [INFO] INFO - [STARTUP] Prüfe Initial-Admin...
2025-06-12 11:24:19 - [app] app - [INFO] INFO - Admin-Benutzer admin (admin@mercedes-benz.com) existiert bereits. Passwort wurde zurückgesetzt.
2025-06-12 11:24:19 - [app] app - [INFO] INFO - [STARTUP] ✅ Admin-Benutzer geprüft
2025-06-12 11:24:19 - [app] app - [INFO] INFO - [STARTUP] Starte Queue Manager...
2025-06-12 11:24:19 - [app] app - [INFO] INFO - [STARTUP] ✅ Queue Manager gestartet
2025-06-12 11:24:19 - [app] app - [INFO] INFO - [STARTUP] Starte Job Scheduler...
2025-06-12 11:24:19 - [app] app - [INFO] INFO - [STARTUP] ✅ Job Scheduler gestartet
2025-06-12 11:24:19 - [app] app - [INFO] INFO - [STARTUP] 🌐 Server startet auf http://0.0.0.0:5000
2025-06-12 11:24:46 - [app] app - [INFO] INFO - [SHUTDOWN] 🧹 Cleanup wird ausgeführt...
2025-06-12 11:24:46 - [app] app - [INFO] INFO - [SHUTDOWN] ✅ Queue Manager gestoppt
2025-06-12 11:24:46 - [app] app - [ERROR] ERROR - [SHUTDOWN] ❌ Cleanup-Fehler: 'BackgroundTaskScheduler' object has no attribute 'shutdown'
2025-06-12 11:24:47 - [app] app - [WARNING] WARNING - DatabaseCleanupManager nicht verfügbar - Fallback auf Legacy-Cleanup
2025-06-12 11:24:47 - [app] app - [INFO] INFO - Optimierte SQLite-Engine erstellt: backend/database/myp.db
2025-06-12 11:24:48 - [app] app - [INFO] INFO - [CONFIG] Erkannte Umgebung: development
2025-06-12 11:24:48 - [app] app - [INFO] INFO - [CONFIG] Production-Modus: False
2025-06-12 11:24:48 - [app] app - [INFO] INFO - [CONFIG] Verwende Development-Konfiguration
2025-06-12 11:24:48 - [app] app - [INFO] INFO - [DEVELOPMENT] Aktiviere Development-Konfiguration
2025-06-12 11:24:48 - [app] app - [INFO] INFO - [DEVELOPMENT] ✅ MYP Development Environment Konfiguration aktiviert
2025-06-12 11:24:48 - [app] app - [INFO] INFO - [DEVELOPMENT] ✅ Environment: Development/Testing
2025-06-12 11:24:48 - [app] app - [INFO] INFO - [DEVELOPMENT] ✅ Debug Mode: True
2025-06-12 11:24:48 - [app] app - [INFO] INFO - [DEVELOPMENT] ✅ SQL Echo: True
2025-06-12 11:24:48 - [app] app - [INFO] INFO - [STARTUP] 🚀 Starte MYP DEVELOPMENT-Umgebung
2025-06-12 11:24:48 - [app] app - [INFO] INFO - [STARTUP] 🏢 Mercedes-Benz TBA Marienfelde
2025-06-12 11:24:48 - [app] app - [INFO] INFO - [STARTUP] 🔒 Air-Gapped: True
2025-06-12 11:24:48 - [app] app - [INFO] INFO - [STARTUP] Initialisiere Datenbank...
2025-06-12 11:24:48 - [app] app - [INFO] INFO - SQLite für Raspberry Pi optimiert (reduzierte Cache-Größe, SD-Karten I/O)
2025-06-12 11:24:48 - [app] app - [INFO] INFO - Datenbank mit Optimierungen initialisiert
2025-06-12 11:24:48 - [app] app - [INFO] INFO - [STARTUP] ✅ Datenbank initialisiert
2025-06-12 11:24:48 - [app] app - [INFO] INFO - [STARTUP] Prüfe Initial-Admin...
2025-06-12 11:24:48 - [app] app - [INFO] INFO - Admin-Benutzer admin (admin@mercedes-benz.com) existiert bereits. Passwort wurde zurückgesetzt.
2025-06-12 11:24:48 - [app] app - [INFO] INFO - [STARTUP] ✅ Admin-Benutzer geprüft
2025-06-12 11:24:48 - [app] app - [INFO] INFO - [STARTUP] Starte Queue Manager...
2025-06-12 11:24:48 - [app] app - [INFO] INFO - [STARTUP] ✅ Queue Manager gestartet
2025-06-12 11:24:48 - [app] app - [INFO] INFO - [STARTUP] Starte Job Scheduler...
2025-06-12 11:24:48 - [app] app - [INFO] INFO - [STARTUP] ✅ Job Scheduler gestartet
2025-06-12 11:24:48 - [app] app - [INFO] INFO - [STARTUP] 🌐 Server startet auf http://0.0.0.0:5000
2025-06-12 11:26:13 - [app] app - [INFO] INFO - [SHUTDOWN] 🧹 Cleanup wird ausgeführt...
2025-06-12 11:26:13 - [app] app - [INFO] INFO - [SHUTDOWN] ✅ Queue Manager gestoppt
2025-06-12 11:26:13 - [app] app - [ERROR] ERROR - [SHUTDOWN] ❌ Cleanup-Fehler: 'BackgroundTaskScheduler' object has no attribute 'shutdown'
2025-06-12 11:26:14 - [app] app - [WARNING] WARNING - DatabaseCleanupManager nicht verfügbar - Fallback auf Legacy-Cleanup
2025-06-12 11:26:14 - [app] app - [INFO] INFO - Optimierte SQLite-Engine erstellt: backend/database/myp.db
2025-06-12 11:26:15 - [app] app - [INFO] INFO - [CONFIG] Erkannte Umgebung: development
2025-06-12 11:26:15 - [app] app - [INFO] INFO - [CONFIG] Production-Modus: False
2025-06-12 11:26:15 - [app] app - [INFO] INFO - [CONFIG] Verwende Development-Konfiguration
2025-06-12 11:26:15 - [app] app - [INFO] INFO - [DEVELOPMENT] Aktiviere Development-Konfiguration
2025-06-12 11:26:15 - [app] app - [INFO] INFO - [DEVELOPMENT] ✅ MYP Development Environment Konfiguration aktiviert
2025-06-12 11:26:15 - [app] app - [INFO] INFO - [DEVELOPMENT] ✅ Environment: Development/Testing
2025-06-12 11:26:15 - [app] app - [INFO] INFO - [DEVELOPMENT] ✅ Debug Mode: True
2025-06-12 11:26:15 - [app] app - [INFO] INFO - [DEVELOPMENT] ✅ SQL Echo: True
2025-06-12 11:26:15 - [app] app - [INFO] INFO - [STARTUP] 🚀 Starte MYP DEVELOPMENT-Umgebung
2025-06-12 11:26:15 - [app] app - [INFO] INFO - [STARTUP] 🏢 Mercedes-Benz TBA Marienfelde
2025-06-12 11:26:15 - [app] app - [INFO] INFO - [STARTUP] 🔒 Air-Gapped: True
2025-06-12 11:26:15 - [app] app - [INFO] INFO - [STARTUP] Initialisiere Datenbank...
2025-06-12 11:26:15 - [app] app - [INFO] INFO - SQLite für Raspberry Pi optimiert (reduzierte Cache-Größe, SD-Karten I/O)
2025-06-12 11:26:15 - [app] app - [INFO] INFO - Datenbank mit Optimierungen initialisiert
2025-06-12 11:26:15 - [app] app - [INFO] INFO - [STARTUP] ✅ Datenbank initialisiert
2025-06-12 11:26:15 - [app] app - [INFO] INFO - [STARTUP] Prüfe Initial-Admin...
2025-06-12 11:26:15 - [app] app - [INFO] INFO - Admin-Benutzer admin (admin@mercedes-benz.com) existiert bereits. Passwort wurde zurückgesetzt.
2025-06-12 11:26:15 - [app] app - [INFO] INFO - [STARTUP] ✅ Admin-Benutzer geprüft
2025-06-12 11:26:15 - [app] app - [INFO] INFO - [STARTUP] Starte Queue Manager...
2025-06-12 11:26:15 - [app] app - [INFO] INFO - [STARTUP] ✅ Queue Manager gestartet
2025-06-12 11:26:15 - [app] app - [INFO] INFO - [STARTUP] Starte Job Scheduler...
2025-06-12 11:26:15 - [app] app - [INFO] INFO - [STARTUP] ✅ Job Scheduler gestartet
2025-06-12 11:26:15 - [app] app - [INFO] INFO - [STARTUP] 🌐 Server startet auf http://0.0.0.0:5000
2025-06-12 11:26:32 - [app] app - [WARNING] WARNING - DatabaseCleanupManager nicht verfügbar - Fallback auf Legacy-Cleanup
2025-06-12 11:26:32 - [app] app - [INFO] INFO - Optimierte SQLite-Engine erstellt: backend/database/myp.db
2025-06-12 11:26:33 - [app] app - [INFO] INFO - [CONFIG] Erkannte Umgebung: development
2025-06-12 11:26:33 - [app] app - [INFO] INFO - [CONFIG] Production-Modus: False
2025-06-12 11:26:33 - [app] app - [INFO] INFO - [CONFIG] Verwende Development-Konfiguration
2025-06-12 11:26:33 - [app] app - [INFO] INFO - [DEVELOPMENT] Aktiviere Development-Konfiguration
2025-06-12 11:26:33 - [app] app - [INFO] INFO - [DEVELOPMENT] ✅ MYP Development Environment Konfiguration aktiviert
2025-06-12 11:26:33 - [app] app - [INFO] INFO - [DEVELOPMENT] ✅ Environment: Development/Testing
2025-06-12 11:26:33 - [app] app - [INFO] INFO - [DEVELOPMENT] ✅ Debug Mode: True
2025-06-12 11:26:33 - [app] app - [INFO] INFO - [DEVELOPMENT] ✅ SQL Echo: True
2025-06-12 11:26:33 - [app] app - [INFO] INFO - SQLite für Raspberry Pi optimiert (reduzierte Cache-Größe, SD-Karten I/O)
2025-06-12 11:26:33 - [app] app - [INFO] INFO - Datenbank mit Optimierungen initialisiert
2025-06-12 11:26:35 - [app] app - [INFO] INFO - Steckdosen-Status geloggt: Drucker 1, Status: unreachable, Quelle: system
2025-06-12 11:26:37 - [app] app - [INFO] INFO - Steckdosen-Status geloggt: Drucker 2, Status: unreachable, Quelle: system
2025-06-12 11:26:39 - [app] app - [INFO] INFO - Steckdosen-Status geloggt: Drucker 3, Status: unreachable, Quelle: system
2025-06-12 11:26:41 - [app] app - [INFO] INFO - Steckdosen-Status geloggt: Drucker 4, Status: unreachable, Quelle: system
2025-06-12 11:26:43 - [app] app - [INFO] INFO - Steckdosen-Status geloggt: Drucker 5, Status: unreachable, Quelle: system
2025-06-12 11:26:46 - [app] app - [INFO] INFO - Steckdosen-Status geloggt: Drucker 6, Status: unreachable, Quelle: system

View File

@ -100,3 +100,17 @@
2025-06-12 11:00:40 - [core_system] core_system - [INFO] INFO - 📊 Massive Konsolidierung: 6 Dateien → 1 Datei (88% Reduktion)
2025-06-12 11:00:45 - [core_system] core_system - [INFO] INFO - ✅ Core System Management Module erfolgreich initialisiert
2025-06-12 11:00:45 - [core_system] core_system - [INFO] INFO - 📊 Massive Konsolidierung: 6 Dateien → 1 Datei (88% Reduktion)
2025-06-12 11:21:20 - [core_system] core_system - [INFO] INFO - ✅ Core System Management Module erfolgreich initialisiert
2025-06-12 11:21:20 - [core_system] core_system - [INFO] INFO - 📊 Massive Konsolidierung: 6 Dateien → 1 Datei (88% Reduktion)
2025-06-12 11:21:25 - [core_system] core_system - [INFO] INFO - ✅ Core System Management Module erfolgreich initialisiert
2025-06-12 11:21:25 - [core_system] core_system - [INFO] INFO - 📊 Massive Konsolidierung: 6 Dateien → 1 Datei (88% Reduktion)
2025-06-12 11:23:06 - [core_system] core_system - [INFO] INFO - ✅ Core System Management Module erfolgreich initialisiert
2025-06-12 11:23:06 - [core_system] core_system - [INFO] INFO - 📊 Massive Konsolidierung: 6 Dateien → 1 Datei (88% Reduktion)
2025-06-12 11:24:18 - [core_system] core_system - [INFO] INFO - ✅ Core System Management Module erfolgreich initialisiert
2025-06-12 11:24:18 - [core_system] core_system - [INFO] INFO - 📊 Massive Konsolidierung: 6 Dateien → 1 Datei (88% Reduktion)
2025-06-12 11:24:47 - [core_system] core_system - [INFO] INFO - ✅ Core System Management Module erfolgreich initialisiert
2025-06-12 11:24:47 - [core_system] core_system - [INFO] INFO - 📊 Massive Konsolidierung: 6 Dateien → 1 Datei (88% Reduktion)
2025-06-12 11:26:14 - [core_system] core_system - [INFO] INFO - ✅ Core System Management Module erfolgreich initialisiert
2025-06-12 11:26:14 - [core_system] core_system - [INFO] INFO - 📊 Massive Konsolidierung: 6 Dateien → 1 Datei (88% Reduktion)
2025-06-12 11:26:32 - [core_system] core_system - [INFO] INFO - ✅ Core System Management Module erfolgreich initialisiert
2025-06-12 11:26:32 - [core_system] core_system - [INFO] INFO - 📊 Massive Konsolidierung: 6 Dateien → 1 Datei (88% Reduktion)

View File

@ -100,3 +100,17 @@
2025-06-12 11:00:40 - [data_management] data_management - [INFO] INFO - 📊 Massive Konsolidierung: 3 Dateien → 1 Datei (67% Reduktion)
2025-06-12 11:00:45 - [data_management] data_management - [INFO] INFO - ✅ Data Management Module initialisiert
2025-06-12 11:00:45 - [data_management] data_management - [INFO] INFO - 📊 Massive Konsolidierung: 3 Dateien → 1 Datei (67% Reduktion)
2025-06-12 11:21:21 - [data_management] data_management - [INFO] INFO - ✅ Data Management Module initialisiert
2025-06-12 11:21:21 - [data_management] data_management - [INFO] INFO - 📊 Massive Konsolidierung: 3 Dateien → 1 Datei (67% Reduktion)
2025-06-12 11:21:25 - [data_management] data_management - [INFO] INFO - ✅ Data Management Module initialisiert
2025-06-12 11:21:25 - [data_management] data_management - [INFO] INFO - 📊 Massive Konsolidierung: 3 Dateien → 1 Datei (67% Reduktion)
2025-06-12 11:23:06 - [data_management] data_management - [INFO] INFO - ✅ Data Management Module initialisiert
2025-06-12 11:23:06 - [data_management] data_management - [INFO] INFO - 📊 Massive Konsolidierung: 3 Dateien → 1 Datei (67% Reduktion)
2025-06-12 11:24:18 - [data_management] data_management - [INFO] INFO - ✅ Data Management Module initialisiert
2025-06-12 11:24:18 - [data_management] data_management - [INFO] INFO - 📊 Massive Konsolidierung: 3 Dateien → 1 Datei (67% Reduktion)
2025-06-12 11:24:47 - [data_management] data_management - [INFO] INFO - ✅ Data Management Module initialisiert
2025-06-12 11:24:47 - [data_management] data_management - [INFO] INFO - 📊 Massive Konsolidierung: 3 Dateien → 1 Datei (67% Reduktion)
2025-06-12 11:26:14 - [data_management] data_management - [INFO] INFO - ✅ Data Management Module initialisiert
2025-06-12 11:26:14 - [data_management] data_management - [INFO] INFO - 📊 Massive Konsolidierung: 3 Dateien → 1 Datei (67% Reduktion)
2025-06-12 11:26:32 - [data_management] data_management - [INFO] INFO - ✅ Data Management Module initialisiert
2025-06-12 11:26:32 - [data_management] data_management - [INFO] INFO - 📊 Massive Konsolidierung: 3 Dateien → 1 Datei (67% Reduktion)

View File

@ -206,3 +206,31 @@
2025-06-12 11:00:45 - [hardware_integration] hardware_integration - [INFO] INFO - ✅ Printer Monitor initialisiert
2025-06-12 11:00:45 - [hardware_integration] hardware_integration - [INFO] INFO - ✅ Hardware Integration Module initialisiert
2025-06-12 11:00:45 - [hardware_integration] hardware_integration - [INFO] INFO - 📊 Massive Konsolidierung: 2 Dateien → 1 Datei (50% Reduktion)
2025-06-12 11:21:21 - [hardware_integration] hardware_integration - [INFO] INFO - ✅ PyP100 (TP-Link Tapo) verfügbar
2025-06-12 11:21:21 - [hardware_integration] hardware_integration - [INFO] INFO - ✅ Printer Monitor initialisiert
2025-06-12 11:21:21 - [hardware_integration] hardware_integration - [INFO] INFO - ✅ Hardware Integration Module initialisiert
2025-06-12 11:21:21 - [hardware_integration] hardware_integration - [INFO] INFO - 📊 Massive Konsolidierung: 2 Dateien → 1 Datei (50% Reduktion)
2025-06-12 11:21:25 - [hardware_integration] hardware_integration - [INFO] INFO - ✅ PyP100 (TP-Link Tapo) verfügbar
2025-06-12 11:21:25 - [hardware_integration] hardware_integration - [INFO] INFO - ✅ Printer Monitor initialisiert
2025-06-12 11:21:25 - [hardware_integration] hardware_integration - [INFO] INFO - ✅ Hardware Integration Module initialisiert
2025-06-12 11:21:25 - [hardware_integration] hardware_integration - [INFO] INFO - 📊 Massive Konsolidierung: 2 Dateien → 1 Datei (50% Reduktion)
2025-06-12 11:23:06 - [hardware_integration] hardware_integration - [INFO] INFO - ✅ PyP100 (TP-Link Tapo) verfügbar
2025-06-12 11:23:06 - [hardware_integration] hardware_integration - [INFO] INFO - ✅ Printer Monitor initialisiert
2025-06-12 11:23:06 - [hardware_integration] hardware_integration - [INFO] INFO - ✅ Hardware Integration Module initialisiert
2025-06-12 11:23:06 - [hardware_integration] hardware_integration - [INFO] INFO - 📊 Massive Konsolidierung: 2 Dateien → 1 Datei (50% Reduktion)
2025-06-12 11:24:18 - [hardware_integration] hardware_integration - [INFO] INFO - ✅ PyP100 (TP-Link Tapo) verfügbar
2025-06-12 11:24:18 - [hardware_integration] hardware_integration - [INFO] INFO - ✅ Printer Monitor initialisiert
2025-06-12 11:24:18 - [hardware_integration] hardware_integration - [INFO] INFO - ✅ Hardware Integration Module initialisiert
2025-06-12 11:24:18 - [hardware_integration] hardware_integration - [INFO] INFO - 📊 Massive Konsolidierung: 2 Dateien → 1 Datei (50% Reduktion)
2025-06-12 11:24:47 - [hardware_integration] hardware_integration - [INFO] INFO - ✅ PyP100 (TP-Link Tapo) verfügbar
2025-06-12 11:24:47 - [hardware_integration] hardware_integration - [INFO] INFO - ✅ Printer Monitor initialisiert
2025-06-12 11:24:47 - [hardware_integration] hardware_integration - [INFO] INFO - ✅ Hardware Integration Module initialisiert
2025-06-12 11:24:47 - [hardware_integration] hardware_integration - [INFO] INFO - 📊 Massive Konsolidierung: 2 Dateien → 1 Datei (50% Reduktion)
2025-06-12 11:26:14 - [hardware_integration] hardware_integration - [INFO] INFO - ✅ PyP100 (TP-Link Tapo) verfügbar
2025-06-12 11:26:14 - [hardware_integration] hardware_integration - [INFO] INFO - ✅ Printer Monitor initialisiert
2025-06-12 11:26:14 - [hardware_integration] hardware_integration - [INFO] INFO - ✅ Hardware Integration Module initialisiert
2025-06-12 11:26:14 - [hardware_integration] hardware_integration - [INFO] INFO - 📊 Massive Konsolidierung: 2 Dateien → 1 Datei (50% Reduktion)
2025-06-12 11:26:32 - [hardware_integration] hardware_integration - [INFO] INFO - ✅ PyP100 (TP-Link Tapo) verfügbar
2025-06-12 11:26:32 - [hardware_integration] hardware_integration - [INFO] INFO - ✅ Printer Monitor initialisiert
2025-06-12 11:26:32 - [hardware_integration] hardware_integration - [INFO] INFO - ✅ Hardware Integration Module initialisiert
2025-06-12 11:26:32 - [hardware_integration] hardware_integration - [INFO] INFO - 📊 Massive Konsolidierung: 2 Dateien → 1 Datei (50% Reduktion)

View File

@ -195,3 +195,27 @@
2025-06-12 11:00:49 - [job_queue_system] job_queue_system - [INFO] INFO - Queue Manager gestartet (Legacy-Kompatibilität)
2025-06-12 11:18:03 - [job_queue_system] job_queue_system - [INFO] INFO - Queue Manager gestoppt (Legacy-Kompatibilität)
2025-06-12 11:18:03 - [job_queue_system] job_queue_system - [INFO] INFO - Queue Manager gestoppt (Legacy-Kompatibilität)
2025-06-12 11:21:21 - [job_queue_system] job_queue_system - [INFO] INFO - ✅ Job & Queue System Module initialisiert
2025-06-12 11:21:21 - [job_queue_system] job_queue_system - [INFO] INFO - 📊 MASSIVE Konsolidierung: 4 Dateien → 1 Datei (75% Reduktion)
2025-06-12 11:21:24 - [job_queue_system] job_queue_system - [INFO] INFO - Queue Manager gestartet (Legacy-Kompatibilität)
2025-06-12 11:21:25 - [job_queue_system] job_queue_system - [INFO] INFO - ✅ Job & Queue System Module initialisiert
2025-06-12 11:21:25 - [job_queue_system] job_queue_system - [INFO] INFO - 📊 MASSIVE Konsolidierung: 4 Dateien → 1 Datei (75% Reduktion)
2025-06-12 11:21:27 - [job_queue_system] job_queue_system - [INFO] INFO - Queue Manager gestartet (Legacy-Kompatibilität)
2025-06-12 11:23:05 - [job_queue_system] job_queue_system - [INFO] INFO - Queue Manager gestoppt (Legacy-Kompatibilität)
2025-06-12 11:23:06 - [job_queue_system] job_queue_system - [INFO] INFO - ✅ Job & Queue System Module initialisiert
2025-06-12 11:23:06 - [job_queue_system] job_queue_system - [INFO] INFO - 📊 MASSIVE Konsolidierung: 4 Dateien → 1 Datei (75% Reduktion)
2025-06-12 11:23:07 - [job_queue_system] job_queue_system - [INFO] INFO - Queue Manager gestartet (Legacy-Kompatibilität)
2025-06-12 11:24:17 - [job_queue_system] job_queue_system - [INFO] INFO - Queue Manager gestoppt (Legacy-Kompatibilität)
2025-06-12 11:24:18 - [job_queue_system] job_queue_system - [INFO] INFO - ✅ Job & Queue System Module initialisiert
2025-06-12 11:24:18 - [job_queue_system] job_queue_system - [INFO] INFO - 📊 MASSIVE Konsolidierung: 4 Dateien → 1 Datei (75% Reduktion)
2025-06-12 11:24:19 - [job_queue_system] job_queue_system - [INFO] INFO - Queue Manager gestartet (Legacy-Kompatibilität)
2025-06-12 11:24:46 - [job_queue_system] job_queue_system - [INFO] INFO - Queue Manager gestoppt (Legacy-Kompatibilität)
2025-06-12 11:24:47 - [job_queue_system] job_queue_system - [INFO] INFO - ✅ Job & Queue System Module initialisiert
2025-06-12 11:24:47 - [job_queue_system] job_queue_system - [INFO] INFO - 📊 MASSIVE Konsolidierung: 4 Dateien → 1 Datei (75% Reduktion)
2025-06-12 11:24:48 - [job_queue_system] job_queue_system - [INFO] INFO - Queue Manager gestartet (Legacy-Kompatibilität)
2025-06-12 11:26:13 - [job_queue_system] job_queue_system - [INFO] INFO - Queue Manager gestoppt (Legacy-Kompatibilität)
2025-06-12 11:26:14 - [job_queue_system] job_queue_system - [INFO] INFO - ✅ Job & Queue System Module initialisiert
2025-06-12 11:26:14 - [job_queue_system] job_queue_system - [INFO] INFO - 📊 MASSIVE Konsolidierung: 4 Dateien → 1 Datei (75% Reduktion)
2025-06-12 11:26:15 - [job_queue_system] job_queue_system - [INFO] INFO - Queue Manager gestartet (Legacy-Kompatibilität)
2025-06-12 11:26:32 - [job_queue_system] job_queue_system - [INFO] INFO - ✅ Job & Queue System Module initialisiert
2025-06-12 11:26:32 - [job_queue_system] job_queue_system - [INFO] INFO - 📊 MASSIVE Konsolidierung: 4 Dateien → 1 Datei (75% Reduktion)

View File

@ -159,3 +159,95 @@ TypeError: unsupported operand type(s) for +: 'NoneType' and 'int'
2025-06-12 11:04:10 - [jobs] jobs - [INFO] INFO - 📋 Jobs-Abfrage gestartet von Benutzer 1 (Admin: True)
2025-06-12 11:04:10 - [jobs] jobs - [INFO] INFO - ✅ Jobs erfolgreich abgerufen: 0 von 0 (Seite 1)
2025-06-12 11:04:10 - [jobs] jobs - [INFO] INFO - ✅ Jobs erfolgreich abgerufen: 0 von 0 (Seite 1)
2025-06-12 11:21:35 - [jobs] jobs - [INFO] INFO - 📋 Jobs-Abfrage gestartet von Benutzer 1 (Admin: True)
2025-06-12 11:21:35 - [jobs] jobs - [INFO] INFO - 📋 Jobs-Abfrage gestartet von Benutzer 1 (Admin: True)
2025-06-12 11:21:35 - [jobs] jobs - [INFO] INFO - ✅ Jobs erfolgreich abgerufen: 0 von 0 (Seite 1)
2025-06-12 11:21:35 - [jobs] jobs - [INFO] INFO - ✅ Jobs erfolgreich abgerufen: 0 von 0 (Seite 1)
2025-06-12 11:21:50 - [jobs] jobs - [INFO] INFO - 📋 Jobs-Abfrage gestartet von Benutzer 1 (Admin: True)
2025-06-12 11:21:50 - [jobs] jobs - [INFO] INFO - ✅ Jobs erfolgreich abgerufen: 0 von 0 (Seite 1)
2025-06-12 11:22:05 - [jobs] jobs - [INFO] INFO - 📋 Jobs-Abfrage gestartet von Benutzer 1 (Admin: True)
2025-06-12 11:22:05 - [jobs] jobs - [INFO] INFO - ✅ Jobs erfolgreich abgerufen: 0 von 0 (Seite 1)
2025-06-12 11:22:05 - [jobs] jobs - [INFO] INFO - 📋 Jobs-Abfrage gestartet von Benutzer 1 (Admin: True)
2025-06-12 11:22:05 - [jobs] jobs - [INFO] INFO - ✅ Jobs erfolgreich abgerufen: 0 von 0 (Seite 1)
2025-06-12 11:22:20 - [jobs] jobs - [INFO] INFO - 📋 Jobs-Abfrage gestartet von Benutzer 1 (Admin: True)
2025-06-12 11:22:20 - [jobs] jobs - [INFO] INFO - ✅ Jobs erfolgreich abgerufen: 0 von 0 (Seite 1)
2025-06-12 11:22:35 - [jobs] jobs - [INFO] INFO - 📋 Jobs-Abfrage gestartet von Benutzer 1 (Admin: True)
2025-06-12 11:22:35 - [jobs] jobs - [INFO] INFO - ✅ Jobs erfolgreich abgerufen: 0 von 0 (Seite 1)
2025-06-12 11:22:35 - [jobs] jobs - [INFO] INFO - 📋 Jobs-Abfrage gestartet von Benutzer 1 (Admin: True)
2025-06-12 11:22:35 - [jobs] jobs - [INFO] INFO - ✅ Jobs erfolgreich abgerufen: 0 von 0 (Seite 1)
2025-06-12 11:22:50 - [jobs] jobs - [INFO] INFO - 📋 Jobs-Abfrage gestartet von Benutzer 1 (Admin: True)
2025-06-12 11:22:50 - [jobs] jobs - [INFO] INFO - ✅ Jobs erfolgreich abgerufen: 0 von 0 (Seite 1)
2025-06-12 11:23:05 - [jobs] jobs - [INFO] INFO - 📋 Jobs-Abfrage gestartet von Benutzer 1 (Admin: True)
2025-06-12 11:23:05 - [jobs] jobs - [INFO] INFO - 📋 Jobs-Abfrage gestartet von Benutzer 1 (Admin: True)
2025-06-12 11:23:05 - [jobs] jobs - [INFO] INFO - ✅ Jobs erfolgreich abgerufen: 0 von 0 (Seite 1)
2025-06-12 11:23:05 - [jobs] jobs - [ERROR] ERROR - ❌ Fehler beim Abrufen von Jobs: tuple index out of range
Traceback (most recent call last):
File "C:\Users\TTOMCZA.EMEA\Dev\Projektarbeit-MYP\backend\blueprints\jobs.py", line 88, in get_jobs
total_count = query.count()
File "C:\Users\TTOMCZA.EMEA\AppData\Roaming\Python\Python313\site-packages\sqlalchemy\orm\query.py", line 3113, in count
self._legacy_from_self(col).enable_eagerloads(False).scalar()
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^
File "C:\Users\TTOMCZA.EMEA\AppData\Roaming\Python\Python313\site-packages\sqlalchemy\orm\query.py", line 2805, in scalar
ret = self.one()
File "C:\Users\TTOMCZA.EMEA\AppData\Roaming\Python\Python313\site-packages\sqlalchemy\orm\query.py", line 2778, in one
return self._iter().one() # type: ignore
~~~~~~~~~~~~~~~~^^
File "C:\Users\TTOMCZA.EMEA\AppData\Roaming\Python\Python313\site-packages\sqlalchemy\engine\result.py", line 1520, in one
return self._only_one_row(
~~~~~~~~~~~~~~~~~~^
raise_for_second_row=True, raise_for_none=True, scalar=False
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
)
^
File "C:\Users\TTOMCZA.EMEA\AppData\Roaming\Python\Python313\site-packages\sqlalchemy\engine\result.py", line 749, in _only_one_row
row: Optional[_InterimRowType[Any]] = onerow(hard_close=True)
~~~~~~^^^^^^^^^^^^^^^^^
File "C:\Users\TTOMCZA.EMEA\AppData\Roaming\Python\Python313\site-packages\sqlalchemy\engine\result.py", line 2259, in _fetchone_impl
row = next(self.iterator, _NO_ROW)
File "C:\Users\TTOMCZA.EMEA\AppData\Roaming\Python\Python313\site-packages\sqlalchemy\orm\loading.py", line 226, in chunks
tuple([proc(row) for proc in process]) for row in fetch
~~~~^^^^^
File "lib\\sqlalchemy\\cyextension\\resultproxy.pyx", line 54, in sqlalchemy.cyextension.resultproxy.BaseRow.__getitem__
IndexError: tuple index out of range
2025-06-12 11:23:20 - [jobs] jobs - [INFO] INFO - 📋 Jobs-Abfrage gestartet von Benutzer 1 (Admin: True)
2025-06-12 11:23:20 - [jobs] jobs - [INFO] INFO - ✅ Jobs erfolgreich abgerufen: 0 von 0 (Seite 1)
2025-06-12 11:23:35 - [jobs] jobs - [INFO] INFO - 📋 Jobs-Abfrage gestartet von Benutzer 1 (Admin: True)
2025-06-12 11:23:35 - [jobs] jobs - [INFO] INFO - ✅ Jobs erfolgreich abgerufen: 0 von 0 (Seite 1)
2025-06-12 11:23:35 - [jobs] jobs - [INFO] INFO - 📋 Jobs-Abfrage gestartet von Benutzer 1 (Admin: True)
2025-06-12 11:23:35 - [jobs] jobs - [INFO] INFO - ✅ Jobs erfolgreich abgerufen: 0 von 0 (Seite 1)
2025-06-12 11:23:50 - [jobs] jobs - [INFO] INFO - 📋 Jobs-Abfrage gestartet von Benutzer 1 (Admin: True)
2025-06-12 11:23:50 - [jobs] jobs - [INFO] INFO - ✅ Jobs erfolgreich abgerufen: 0 von 0 (Seite 1)
2025-06-12 11:24:05 - [jobs] jobs - [INFO] INFO - 📋 Jobs-Abfrage gestartet von Benutzer 1 (Admin: True)
2025-06-12 11:24:05 - [jobs] jobs - [INFO] INFO - ✅ Jobs erfolgreich abgerufen: 0 von 0 (Seite 1)
2025-06-12 11:24:35 - [jobs] jobs - [INFO] INFO - 📋 Jobs-Abfrage gestartet von Benutzer 1 (Admin: True)
2025-06-12 11:24:35 - [jobs] jobs - [INFO] INFO - ✅ Jobs erfolgreich abgerufen: 0 von 0 (Seite 1)
2025-06-12 11:24:37 - [jobs] jobs - [INFO] INFO - 📋 Jobs-Abfrage gestartet von Benutzer 1 (Admin: True)
2025-06-12 11:24:37 - [jobs] jobs - [INFO] INFO - ✅ Jobs erfolgreich abgerufen: 0 von 0 (Seite 1)
2025-06-12 11:25:37 - [jobs] jobs - [INFO] INFO - 📋 Jobs-Abfrage gestartet von Benutzer 1 (Admin: True)
2025-06-12 11:25:37 - [jobs] jobs - [INFO] INFO - 📋 Jobs-Abfrage gestartet von Benutzer 1 (Admin: True)
2025-06-12 11:25:37 - [jobs] jobs - [INFO] INFO - ✅ Jobs erfolgreich abgerufen: 0 von 0 (Seite 1)
2025-06-12 11:25:37 - [jobs] jobs - [INFO] INFO - ✅ Jobs erfolgreich abgerufen: 0 von 0 (Seite 1)
2025-06-12 11:26:37 - [jobs] jobs - [INFO] INFO - 📋 Jobs-Abfrage gestartet von Benutzer 1 (Admin: True)
2025-06-12 11:26:37 - [jobs] jobs - [INFO] INFO - ✅ Jobs erfolgreich abgerufen: 0 von 0 (Seite 1)
2025-06-12 11:26:37 - [jobs] jobs - [INFO] INFO - 📋 Jobs-Abfrage gestartet von Benutzer 1 (Admin: True)
2025-06-12 11:26:37 - [jobs] jobs - [INFO] INFO - ✅ Jobs erfolgreich abgerufen: 0 von 0 (Seite 1)
2025-06-12 11:27:37 - [jobs] jobs - [INFO] INFO - 📋 Jobs-Abfrage gestartet von Benutzer 1 (Admin: True)
2025-06-12 11:27:37 - [jobs] jobs - [INFO] INFO - 📋 Jobs-Abfrage gestartet von Benutzer 1 (Admin: True)
2025-06-12 11:27:37 - [jobs] jobs - [INFO] INFO - ✅ Jobs erfolgreich abgerufen: 0 von 0 (Seite 1)
2025-06-12 11:27:37 - [jobs] jobs - [INFO] INFO - ✅ Jobs erfolgreich abgerufen: 0 von 0 (Seite 1)
2025-06-12 11:28:37 - [jobs] jobs - [INFO] INFO - 📋 Jobs-Abfrage gestartet von Benutzer 1 (Admin: True)
2025-06-12 11:28:37 - [jobs] jobs - [INFO] INFO - ✅ Jobs erfolgreich abgerufen: 0 von 0 (Seite 1)
2025-06-12 11:28:37 - [jobs] jobs - [INFO] INFO - 📋 Jobs-Abfrage gestartet von Benutzer 1 (Admin: True)
2025-06-12 11:28:37 - [jobs] jobs - [INFO] INFO - ✅ Jobs erfolgreich abgerufen: 0 von 0 (Seite 1)
2025-06-12 11:29:37 - [jobs] jobs - [INFO] INFO - 📋 Jobs-Abfrage gestartet von Benutzer 1 (Admin: True)
2025-06-12 11:29:37 - [jobs] jobs - [INFO] INFO - ✅ Jobs erfolgreich abgerufen: 0 von 0 (Seite 1)
2025-06-12 11:29:37 - [jobs] jobs - [INFO] INFO - 📋 Jobs-Abfrage gestartet von Benutzer 1 (Admin: True)
2025-06-12 11:29:37 - [jobs] jobs - [INFO] INFO - ✅ Jobs erfolgreich abgerufen: 0 von 0 (Seite 1)
2025-06-12 11:30:37 - [jobs] jobs - [INFO] INFO - 📋 Jobs-Abfrage gestartet von Benutzer 1 (Admin: True)
2025-06-12 11:30:37 - [jobs] jobs - [INFO] INFO - 📋 Jobs-Abfrage gestartet von Benutzer 1 (Admin: True)
2025-06-12 11:30:37 - [jobs] jobs - [INFO] INFO - ✅ Jobs erfolgreich abgerufen: 0 von 0 (Seite 1)
2025-06-12 11:30:37 - [jobs] jobs - [INFO] INFO - ✅ Jobs erfolgreich abgerufen: 0 von 0 (Seite 1)
2025-06-12 11:31:37 - [jobs] jobs - [INFO] INFO - 📋 Jobs-Abfrage gestartet von Benutzer 1 (Admin: True)
2025-06-12 11:31:37 - [jobs] jobs - [INFO] INFO - ✅ Jobs erfolgreich abgerufen: 0 von 0 (Seite 1)
2025-06-12 11:31:37 - [jobs] jobs - [INFO] INFO - 📋 Jobs-Abfrage gestartet von Benutzer 1 (Admin: True)
2025-06-12 11:31:37 - [jobs] jobs - [INFO] INFO - ✅ Jobs erfolgreich abgerufen: 0 von 0 (Seite 1)

View File

@ -100,3 +100,17 @@
2025-06-12 11:00:42 - [monitoring_analytics] monitoring_analytics - [INFO] INFO - 📊 MASSIVE Konsolidierung: 3 Dateien → 1 Datei (67% Reduktion)
2025-06-12 11:00:48 - [monitoring_analytics] monitoring_analytics - [INFO] INFO - ✅ Monitoring & Analytics Module initialisiert
2025-06-12 11:00:48 - [monitoring_analytics] monitoring_analytics - [INFO] INFO - 📊 MASSIVE Konsolidierung: 3 Dateien → 1 Datei (67% Reduktion)
2025-06-12 11:21:24 - [monitoring_analytics] monitoring_analytics - [INFO] INFO - ✅ Monitoring & Analytics Module initialisiert
2025-06-12 11:21:24 - [monitoring_analytics] monitoring_analytics - [INFO] INFO - 📊 MASSIVE Konsolidierung: 3 Dateien → 1 Datei (67% Reduktion)
2025-06-12 11:21:26 - [monitoring_analytics] monitoring_analytics - [INFO] INFO - ✅ Monitoring & Analytics Module initialisiert
2025-06-12 11:21:26 - [monitoring_analytics] monitoring_analytics - [INFO] INFO - 📊 MASSIVE Konsolidierung: 3 Dateien → 1 Datei (67% Reduktion)
2025-06-12 11:23:07 - [monitoring_analytics] monitoring_analytics - [INFO] INFO - ✅ Monitoring & Analytics Module initialisiert
2025-06-12 11:23:07 - [monitoring_analytics] monitoring_analytics - [INFO] INFO - 📊 MASSIVE Konsolidierung: 3 Dateien → 1 Datei (67% Reduktion)
2025-06-12 11:24:19 - [monitoring_analytics] monitoring_analytics - [INFO] INFO - ✅ Monitoring & Analytics Module initialisiert
2025-06-12 11:24:19 - [monitoring_analytics] monitoring_analytics - [INFO] INFO - 📊 MASSIVE Konsolidierung: 3 Dateien → 1 Datei (67% Reduktion)
2025-06-12 11:24:48 - [monitoring_analytics] monitoring_analytics - [INFO] INFO - ✅ Monitoring & Analytics Module initialisiert
2025-06-12 11:24:48 - [monitoring_analytics] monitoring_analytics - [INFO] INFO - 📊 MASSIVE Konsolidierung: 3 Dateien → 1 Datei (67% Reduktion)
2025-06-12 11:26:15 - [monitoring_analytics] monitoring_analytics - [INFO] INFO - ✅ Monitoring & Analytics Module initialisiert
2025-06-12 11:26:15 - [monitoring_analytics] monitoring_analytics - [INFO] INFO - 📊 MASSIVE Konsolidierung: 3 Dateien → 1 Datei (67% Reduktion)
2025-06-12 11:26:33 - [monitoring_analytics] monitoring_analytics - [INFO] INFO - ✅ Monitoring & Analytics Module initialisiert
2025-06-12 11:26:33 - [monitoring_analytics] monitoring_analytics - [INFO] INFO - 📊 MASSIVE Konsolidierung: 3 Dateien → 1 Datei (67% Reduktion)

View File

@ -256,3 +256,6 @@
2025-06-12 11:04:05 - [printers] printers - [INFO] INFO - 🔄 Live-Status-Abfrage von Benutzer Administrator (ID: 1)
2025-06-12 11:04:05 - [printers] printers - [ERROR] ERROR - ❌ Fehler bei Live-Status-Abfrage: PrinterMonitor.get_live_printer_status() got an unexpected keyword argument 'use_session_cache'
2025-06-12 11:04:05 - [printers] printers - [INFO] INFO - [OK] API-Live-Drucker-Status-Abfrage 'get_live_printer_status' erfolgreich in 2.16ms
2025-06-12 11:21:27 - [printers] printers - [INFO] INFO - 🔄 Live-Status-Abfrage von Benutzer Administrator (ID: 1)
2025-06-12 11:21:27 - [printers] printers - [ERROR] ERROR - ❌ Fehler bei Live-Status-Abfrage: PrinterMonitor.get_live_printer_status() got an unexpected keyword argument 'use_session_cache'
2025-06-12 11:21:27 - [printers] printers - [INFO] INFO - [OK] API-Live-Drucker-Status-Abfrage 'get_live_printer_status' erfolgreich in 1.52ms

View File

@ -145,3 +145,22 @@
2025-06-12 11:00:45 - [scheduler] scheduler - [INFO] INFO - Task check_jobs registriert: Intervall 30s, Enabled: True
2025-06-12 11:00:49 - [scheduler] scheduler - [INFO] INFO - Scheduler-Thread gestartet
2025-06-12 11:00:49 - [scheduler] scheduler - [INFO] INFO - Scheduler gestartet
2025-06-12 11:21:21 - [scheduler] scheduler - [INFO] INFO - Task check_jobs registriert: Intervall 30s, Enabled: True
2025-06-12 11:21:24 - [scheduler] scheduler - [INFO] INFO - Scheduler-Thread gestartet
2025-06-12 11:21:24 - [scheduler] scheduler - [INFO] INFO - Scheduler gestartet
2025-06-12 11:21:25 - [scheduler] scheduler - [INFO] INFO - Task check_jobs registriert: Intervall 30s, Enabled: True
2025-06-12 11:21:27 - [scheduler] scheduler - [INFO] INFO - Scheduler-Thread gestartet
2025-06-12 11:21:27 - [scheduler] scheduler - [INFO] INFO - Scheduler gestartet
2025-06-12 11:23:06 - [scheduler] scheduler - [INFO] INFO - Task check_jobs registriert: Intervall 30s, Enabled: True
2025-06-12 11:23:07 - [scheduler] scheduler - [INFO] INFO - Scheduler-Thread gestartet
2025-06-12 11:23:07 - [scheduler] scheduler - [INFO] INFO - Scheduler gestartet
2025-06-12 11:24:18 - [scheduler] scheduler - [INFO] INFO - Task check_jobs registriert: Intervall 30s, Enabled: True
2025-06-12 11:24:19 - [scheduler] scheduler - [INFO] INFO - Scheduler-Thread gestartet
2025-06-12 11:24:19 - [scheduler] scheduler - [INFO] INFO - Scheduler gestartet
2025-06-12 11:24:47 - [scheduler] scheduler - [INFO] INFO - Task check_jobs registriert: Intervall 30s, Enabled: True
2025-06-12 11:24:48 - [scheduler] scheduler - [INFO] INFO - Scheduler-Thread gestartet
2025-06-12 11:24:48 - [scheduler] scheduler - [INFO] INFO - Scheduler gestartet
2025-06-12 11:26:14 - [scheduler] scheduler - [INFO] INFO - Task check_jobs registriert: Intervall 30s, Enabled: True
2025-06-12 11:26:15 - [scheduler] scheduler - [INFO] INFO - Scheduler-Thread gestartet
2025-06-12 11:26:15 - [scheduler] scheduler - [INFO] INFO - Scheduler gestartet
2025-06-12 11:26:32 - [scheduler] scheduler - [INFO] INFO - Task check_jobs registriert: Intervall 30s, Enabled: True

View File

@ -151,3 +151,24 @@
2025-06-12 11:00:45 - [security_suite] security_suite - [INFO] INFO - ✅ Security Suite Module initialisiert
2025-06-12 11:00:45 - [security_suite] security_suite - [INFO] INFO - 📊 Massive Konsolidierung: 3 Dateien → 1 Datei (67% Reduktion)
2025-06-12 11:00:48 - [security_suite] security_suite - [INFO] INFO - 🔒 Security Suite initialisiert
2025-06-12 11:21:21 - [security_suite] security_suite - [INFO] INFO - ✅ Security Suite Module initialisiert
2025-06-12 11:21:21 - [security_suite] security_suite - [INFO] INFO - 📊 Massive Konsolidierung: 3 Dateien → 1 Datei (67% Reduktion)
2025-06-12 11:21:24 - [security_suite] security_suite - [INFO] INFO - 🔒 Security Suite initialisiert
2025-06-12 11:21:25 - [security_suite] security_suite - [INFO] INFO - ✅ Security Suite Module initialisiert
2025-06-12 11:21:25 - [security_suite] security_suite - [INFO] INFO - 📊 Massive Konsolidierung: 3 Dateien → 1 Datei (67% Reduktion)
2025-06-12 11:21:26 - [security_suite] security_suite - [INFO] INFO - 🔒 Security Suite initialisiert
2025-06-12 11:23:06 - [security_suite] security_suite - [INFO] INFO - ✅ Security Suite Module initialisiert
2025-06-12 11:23:06 - [security_suite] security_suite - [INFO] INFO - 📊 Massive Konsolidierung: 3 Dateien → 1 Datei (67% Reduktion)
2025-06-12 11:23:07 - [security_suite] security_suite - [INFO] INFO - 🔒 Security Suite initialisiert
2025-06-12 11:24:18 - [security_suite] security_suite - [INFO] INFO - ✅ Security Suite Module initialisiert
2025-06-12 11:24:18 - [security_suite] security_suite - [INFO] INFO - 📊 Massive Konsolidierung: 3 Dateien → 1 Datei (67% Reduktion)
2025-06-12 11:24:19 - [security_suite] security_suite - [INFO] INFO - 🔒 Security Suite initialisiert
2025-06-12 11:24:47 - [security_suite] security_suite - [INFO] INFO - ✅ Security Suite Module initialisiert
2025-06-12 11:24:47 - [security_suite] security_suite - [INFO] INFO - 📊 Massive Konsolidierung: 3 Dateien → 1 Datei (67% Reduktion)
2025-06-12 11:24:48 - [security_suite] security_suite - [INFO] INFO - 🔒 Security Suite initialisiert
2025-06-12 11:26:14 - [security_suite] security_suite - [INFO] INFO - ✅ Security Suite Module initialisiert
2025-06-12 11:26:14 - [security_suite] security_suite - [INFO] INFO - 📊 Massive Konsolidierung: 3 Dateien → 1 Datei (67% Reduktion)
2025-06-12 11:26:15 - [security_suite] security_suite - [INFO] INFO - 🔒 Security Suite initialisiert
2025-06-12 11:26:32 - [security_suite] security_suite - [INFO] INFO - ✅ Security Suite Module initialisiert
2025-06-12 11:26:32 - [security_suite] security_suite - [INFO] INFO - 📊 Massive Konsolidierung: 3 Dateien → 1 Datei (67% Reduktion)
2025-06-12 11:26:33 - [security_suite] security_suite - [INFO] INFO - 🔒 Security Suite initialisiert

View File

@ -70,3 +70,6 @@
2025-06-12 11:04:05 - [sessions] sessions - [ERROR] ERROR - Fehler beim Abrufen des Session-Status: 'int' object has no attribute 'total_seconds'
2025-06-12 11:04:10 - [sessions] sessions - [ERROR] ERROR - Fehler beim Abrufen des Session-Status: 'int' object has no attribute 'total_seconds'
2025-06-12 11:04:11 - [sessions] sessions - [ERROR] ERROR - Fehler beim Abrufen des Session-Status: 'int' object has no attribute 'total_seconds'
2025-06-12 11:21:27 - [sessions] sessions - [ERROR] ERROR - Fehler beim Abrufen des Session-Status: 'int' object has no attribute 'total_seconds'
2025-06-12 11:21:33 - [sessions] sessions - [ERROR] ERROR - Fehler beim Abrufen des Session-Status: 'int' object has no attribute 'total_seconds'
2025-06-12 11:21:35 - [sessions] sessions - [ERROR] ERROR - Fehler beim Abrufen des Session-Status: 'int' object has no attribute 'total_seconds'

View File

@ -457,3 +457,66 @@
2025-06-12 11:00:48 - [startup] startup - [INFO] INFO - 🪟 Windows-Modus: Aktiviert
2025-06-12 11:00:48 - [startup] startup - [INFO] INFO - 🔒 Windows-sichere Log-Rotation: Aktiviert
2025-06-12 11:00:48 - [startup] startup - [INFO] INFO - ==================================================
2025-06-12 11:21:24 - [startup] startup - [INFO] INFO - ==================================================
2025-06-12 11:21:24 - [startup] startup - [INFO] INFO - [START] MYP Platform Backend wird gestartet...
2025-06-12 11:21:24 - [startup] startup - [INFO] INFO - 🐍 Python Version: 3.13.3 (tags/v3.13.3:6280bb5, Apr 8 2025, 14:47:33) [MSC v.1943 64 bit (AMD64)]
2025-06-12 11:21:24 - [startup] startup - [INFO] INFO - 💻 Betriebssystem: nt (win32)
2025-06-12 11:21:24 - [startup] startup - [INFO] INFO - 📁 Arbeitsverzeichnis: C:\Users\TTOMCZA.EMEA\Dev\Projektarbeit-MYP\backend
2025-06-12 11:21:24 - [startup] startup - [INFO] INFO - ⏰ Startzeit: 2025-06-12T11:21:24.383346
2025-06-12 11:21:24 - [startup] startup - [INFO] INFO - 🪟 Windows-Modus: Aktiviert
2025-06-12 11:21:24 - [startup] startup - [INFO] INFO - 🔒 Windows-sichere Log-Rotation: Aktiviert
2025-06-12 11:21:24 - [startup] startup - [INFO] INFO - ==================================================
2025-06-12 11:21:26 - [startup] startup - [INFO] INFO - ==================================================
2025-06-12 11:21:26 - [startup] startup - [INFO] INFO - [START] MYP Platform Backend wird gestartet...
2025-06-12 11:21:26 - [startup] startup - [INFO] INFO - 🐍 Python Version: 3.13.3 (tags/v3.13.3:6280bb5, Apr 8 2025, 14:47:33) [MSC v.1943 64 bit (AMD64)]
2025-06-12 11:21:26 - [startup] startup - [INFO] INFO - 💻 Betriebssystem: nt (win32)
2025-06-12 11:21:26 - [startup] startup - [INFO] INFO - 📁 Arbeitsverzeichnis: C:\Users\TTOMCZA.EMEA\Dev\Projektarbeit-MYP\backend
2025-06-12 11:21:26 - [startup] startup - [INFO] INFO - ⏰ Startzeit: 2025-06-12T11:21:26.706966
2025-06-12 11:21:26 - [startup] startup - [INFO] INFO - 🪟 Windows-Modus: Aktiviert
2025-06-12 11:21:26 - [startup] startup - [INFO] INFO - 🔒 Windows-sichere Log-Rotation: Aktiviert
2025-06-12 11:21:26 - [startup] startup - [INFO] INFO - ==================================================
2025-06-12 11:23:07 - [startup] startup - [INFO] INFO - ==================================================
2025-06-12 11:23:07 - [startup] startup - [INFO] INFO - [START] MYP Platform Backend wird gestartet...
2025-06-12 11:23:07 - [startup] startup - [INFO] INFO - 🐍 Python Version: 3.13.3 (tags/v3.13.3:6280bb5, Apr 8 2025, 14:47:33) [MSC v.1943 64 bit (AMD64)]
2025-06-12 11:23:07 - [startup] startup - [INFO] INFO - 💻 Betriebssystem: nt (win32)
2025-06-12 11:23:07 - [startup] startup - [INFO] INFO - 📁 Arbeitsverzeichnis: C:\Users\TTOMCZA.EMEA\Dev\Projektarbeit-MYP\backend
2025-06-12 11:23:07 - [startup] startup - [INFO] INFO - ⏰ Startzeit: 2025-06-12T11:23:07.517725
2025-06-12 11:23:07 - [startup] startup - [INFO] INFO - 🪟 Windows-Modus: Aktiviert
2025-06-12 11:23:07 - [startup] startup - [INFO] INFO - 🔒 Windows-sichere Log-Rotation: Aktiviert
2025-06-12 11:23:07 - [startup] startup - [INFO] INFO - ==================================================
2025-06-12 11:24:19 - [startup] startup - [INFO] INFO - ==================================================
2025-06-12 11:24:19 - [startup] startup - [INFO] INFO - [START] MYP Platform Backend wird gestartet...
2025-06-12 11:24:19 - [startup] startup - [INFO] INFO - 🐍 Python Version: 3.13.3 (tags/v3.13.3:6280bb5, Apr 8 2025, 14:47:33) [MSC v.1943 64 bit (AMD64)]
2025-06-12 11:24:19 - [startup] startup - [INFO] INFO - 💻 Betriebssystem: nt (win32)
2025-06-12 11:24:19 - [startup] startup - [INFO] INFO - 📁 Arbeitsverzeichnis: C:\Users\TTOMCZA.EMEA\Dev\Projektarbeit-MYP\backend
2025-06-12 11:24:19 - [startup] startup - [INFO] INFO - ⏰ Startzeit: 2025-06-12T11:24:19.571504
2025-06-12 11:24:19 - [startup] startup - [INFO] INFO - 🪟 Windows-Modus: Aktiviert
2025-06-12 11:24:19 - [startup] startup - [INFO] INFO - 🔒 Windows-sichere Log-Rotation: Aktiviert
2025-06-12 11:24:19 - [startup] startup - [INFO] INFO - ==================================================
2025-06-12 11:24:48 - [startup] startup - [INFO] INFO - ==================================================
2025-06-12 11:24:48 - [startup] startup - [INFO] INFO - [START] MYP Platform Backend wird gestartet...
2025-06-12 11:24:48 - [startup] startup - [INFO] INFO - 🐍 Python Version: 3.13.3 (tags/v3.13.3:6280bb5, Apr 8 2025, 14:47:33) [MSC v.1943 64 bit (AMD64)]
2025-06-12 11:24:48 - [startup] startup - [INFO] INFO - 💻 Betriebssystem: nt (win32)
2025-06-12 11:24:48 - [startup] startup - [INFO] INFO - 📁 Arbeitsverzeichnis: C:\Users\TTOMCZA.EMEA\Dev\Projektarbeit-MYP\backend
2025-06-12 11:24:48 - [startup] startup - [INFO] INFO - ⏰ Startzeit: 2025-06-12T11:24:48.617781
2025-06-12 11:24:48 - [startup] startup - [INFO] INFO - 🪟 Windows-Modus: Aktiviert
2025-06-12 11:24:48 - [startup] startup - [INFO] INFO - 🔒 Windows-sichere Log-Rotation: Aktiviert
2025-06-12 11:24:48 - [startup] startup - [INFO] INFO - ==================================================
2025-06-12 11:26:15 - [startup] startup - [INFO] INFO - ==================================================
2025-06-12 11:26:15 - [startup] startup - [INFO] INFO - [START] MYP Platform Backend wird gestartet...
2025-06-12 11:26:15 - [startup] startup - [INFO] INFO - 🐍 Python Version: 3.13.3 (tags/v3.13.3:6280bb5, Apr 8 2025, 14:47:33) [MSC v.1943 64 bit (AMD64)]
2025-06-12 11:26:15 - [startup] startup - [INFO] INFO - 💻 Betriebssystem: nt (win32)
2025-06-12 11:26:15 - [startup] startup - [INFO] INFO - 📁 Arbeitsverzeichnis: C:\Users\TTOMCZA.EMEA\Dev\Projektarbeit-MYP\backend
2025-06-12 11:26:15 - [startup] startup - [INFO] INFO - ⏰ Startzeit: 2025-06-12T11:26:15.091289
2025-06-12 11:26:15 - [startup] startup - [INFO] INFO - 🪟 Windows-Modus: Aktiviert
2025-06-12 11:26:15 - [startup] startup - [INFO] INFO - 🔒 Windows-sichere Log-Rotation: Aktiviert
2025-06-12 11:26:15 - [startup] startup - [INFO] INFO - ==================================================
2025-06-12 11:26:33 - [startup] startup - [INFO] INFO - ==================================================
2025-06-12 11:26:33 - [startup] startup - [INFO] INFO - [START] MYP Platform Backend wird gestartet...
2025-06-12 11:26:33 - [startup] startup - [INFO] INFO - 🐍 Python Version: 3.13.3 (tags/v3.13.3:6280bb5, Apr 8 2025, 14:47:33) [MSC v.1943 64 bit (AMD64)]
2025-06-12 11:26:33 - [startup] startup - [INFO] INFO - 💻 Betriebssystem: nt (win32)
2025-06-12 11:26:33 - [startup] startup - [INFO] INFO - 📁 Arbeitsverzeichnis: C:\Users\TTOMCZA.EMEA\Dev\Projektarbeit-MYP\backend
2025-06-12 11:26:33 - [startup] startup - [INFO] INFO - ⏰ Startzeit: 2025-06-12T11:26:33.239746
2025-06-12 11:26:33 - [startup] startup - [INFO] INFO - 🪟 Windows-Modus: Aktiviert
2025-06-12 11:26:33 - [startup] startup - [INFO] INFO - 🔒 Windows-sichere Log-Rotation: Aktiviert
2025-06-12 11:26:33 - [startup] startup - [INFO] INFO - ==================================================

View File

@ -27,3 +27,5 @@
2025-06-12 11:03:50 - [tapo_control] tapo_control - [INFO] INFO - Dashboard geladen: 0 Steckdosen, 0 online
2025-06-12 11:04:11 - [tapo_control] tapo_control - [INFO] INFO - Tapo Dashboard aufgerufen von Benutzer: Administrator
2025-06-12 11:04:11 - [tapo_control] tapo_control - [INFO] INFO - Dashboard geladen: 0 Steckdosen, 0 online
2025-06-12 11:21:33 - [tapo_control] tapo_control - [INFO] INFO - Tapo Dashboard aufgerufen von Benutzer: Administrator
2025-06-12 11:21:33 - [tapo_control] tapo_control - [INFO] INFO - Dashboard geladen: 0 Steckdosen, 0 online

View File

@ -50,3 +50,10 @@
2025-06-12 10:49:30 - [tapo_controller] tapo_controller - [INFO] INFO - ✅ tapo controller initialisiert
2025-06-12 11:00:40 - [tapo_controller] tapo_controller - [INFO] INFO - ✅ tapo controller initialisiert
2025-06-12 11:00:45 - [tapo_controller] tapo_controller - [INFO] INFO - ✅ tapo controller initialisiert
2025-06-12 11:21:21 - [tapo_controller] tapo_controller - [INFO] INFO - ✅ tapo controller initialisiert
2025-06-12 11:21:25 - [tapo_controller] tapo_controller - [INFO] INFO - ✅ tapo controller initialisiert
2025-06-12 11:23:06 - [tapo_controller] tapo_controller - [INFO] INFO - ✅ tapo controller initialisiert
2025-06-12 11:24:18 - [tapo_controller] tapo_controller - [INFO] INFO - ✅ tapo controller initialisiert
2025-06-12 11:24:47 - [tapo_controller] tapo_controller - [INFO] INFO - ✅ tapo controller initialisiert
2025-06-12 11:26:14 - [tapo_controller] tapo_controller - [INFO] INFO - ✅ tapo controller initialisiert
2025-06-12 11:26:32 - [tapo_controller] tapo_controller - [INFO] INFO - ✅ tapo controller initialisiert

View File

@ -8,3 +8,10 @@
2025-06-12 10:49:30 - [tapo_status_manager] tapo_status_manager - [INFO] INFO - TapoStatusManager initialisiert
2025-06-12 11:00:40 - [tapo_status_manager] tapo_status_manager - [INFO] INFO - TapoStatusManager initialisiert
2025-06-12 11:00:45 - [tapo_status_manager] tapo_status_manager - [INFO] INFO - TapoStatusManager initialisiert
2025-06-12 11:21:21 - [tapo_status_manager] tapo_status_manager - [INFO] INFO - TapoStatusManager initialisiert
2025-06-12 11:21:25 - [tapo_status_manager] tapo_status_manager - [INFO] INFO - TapoStatusManager initialisiert
2025-06-12 11:23:06 - [tapo_status_manager] tapo_status_manager - [INFO] INFO - TapoStatusManager initialisiert
2025-06-12 11:24:18 - [tapo_status_manager] tapo_status_manager - [INFO] INFO - TapoStatusManager initialisiert
2025-06-12 11:24:47 - [tapo_status_manager] tapo_status_manager - [INFO] INFO - TapoStatusManager initialisiert
2025-06-12 11:26:14 - [tapo_status_manager] tapo_status_manager - [INFO] INFO - TapoStatusManager initialisiert
2025-06-12 11:26:32 - [tapo_status_manager] tapo_status_manager - [INFO] INFO - TapoStatusManager initialisiert

View File

@ -62,3 +62,65 @@
2025-06-12 10:02:18 - [test_printer_setup] test_printer_setup - [INFO] INFO - ❓ Unbekannt: 0
2025-06-12 10:02:37 - [test_printer_setup] test_printer_setup - [INFO] INFO -
✅ Test abgeschlossen!
2025-06-12 11:26:33 - [test_printer_setup] test_printer_setup - [INFO] INFO - ============================================================
2025-06-12 11:26:33 - [test_printer_setup] test_printer_setup - [INFO] INFO - 🏭 Mercedes-Benz 3D-Druck-Management - Drucker-Setup & Test
2025-06-12 11:26:33 - [test_printer_setup] test_printer_setup - [INFO] INFO - ============================================================
2025-06-12 11:26:33 - [test_printer_setup] test_printer_setup - [INFO] INFO - 🚀 Starte Drucker-Setup...
2025-06-12 11:26:33 - [test_printer_setup] test_printer_setup - [INFO] INFO - 📋 Erstelle Drucker 1/6: 3D-Drucker 1 - Halle A
2025-06-12 11:26:33 - [test_printer_setup] test_printer_setup - [INFO] INFO - 📋 Erstelle Drucker 2/6: 3D-Drucker 2 - Halle A
2025-06-12 11:26:33 - [test_printer_setup] test_printer_setup - [INFO] INFO - 📋 Erstelle Drucker 3/6: 3D-Drucker 3 - Halle B
2025-06-12 11:26:33 - [test_printer_setup] test_printer_setup - [INFO] INFO - 📋 Erstelle Drucker 4/6: 3D-Drucker 4 - Halle B
2025-06-12 11:26:33 - [test_printer_setup] test_printer_setup - [INFO] INFO - 📋 Erstelle Drucker 5/6: 3D-Drucker 5 - Labor
2025-06-12 11:26:33 - [test_printer_setup] test_printer_setup - [INFO] INFO - 📋 Erstelle Drucker 6/6: 3D-Drucker 6 - Werkstatt
2025-06-12 11:26:33 - [test_printer_setup] test_printer_setup - [INFO] INFO - ✅ Alle 6 Drucker erfolgreich erstellt!
2025-06-12 11:26:33 - [test_printer_setup] test_printer_setup - [INFO] INFO -
🔍 Teste Drucker-Status...
2025-06-12 11:26:46 - [test_printer_setup] test_printer_setup - [INFO] INFO - 📊 Status für 6 Drucker abgerufen:
2025-06-12 11:26:46 - [test_printer_setup] test_printer_setup - [INFO] INFO - 🖨️ 3D-Drucker 1 - Halle A
2025-06-12 11:26:46 - [test_printer_setup] test_printer_setup - [INFO] INFO - 📍 Standort: Halle A - Arbeitsplatz 1
2025-06-12 11:26:46 - [test_printer_setup] test_printer_setup - [INFO] INFO - 🔌 Steckdosen-IP: 192.168.1.201
2025-06-12 11:26:46 - [test_printer_setup] test_printer_setup - [INFO] INFO - ⚡ Status: Nicht erreichbar
2025-06-12 11:26:46 - [test_printer_setup] test_printer_setup - [INFO] INFO - ❌ Steckdose nicht erreichbar
2025-06-12 11:26:46 - [test_printer_setup] test_printer_setup - [INFO] INFO - ⚠️ Fehler: Steckdose nicht erreichbar
2025-06-12 11:26:46 - [test_printer_setup] test_printer_setup - [INFO] INFO -
2025-06-12 11:26:46 - [test_printer_setup] test_printer_setup - [INFO] INFO - 🖨️ 3D-Drucker 2 - Halle A
2025-06-12 11:26:46 - [test_printer_setup] test_printer_setup - [INFO] INFO - 📍 Standort: Halle A - Arbeitsplatz 2
2025-06-12 11:26:46 - [test_printer_setup] test_printer_setup - [INFO] INFO - 🔌 Steckdosen-IP: 192.168.1.202
2025-06-12 11:26:46 - [test_printer_setup] test_printer_setup - [INFO] INFO - ⚡ Status: Nicht erreichbar
2025-06-12 11:26:46 - [test_printer_setup] test_printer_setup - [INFO] INFO - ❌ Steckdose nicht erreichbar
2025-06-12 11:26:46 - [test_printer_setup] test_printer_setup - [INFO] INFO - ⚠️ Fehler: Steckdose nicht erreichbar
2025-06-12 11:26:46 - [test_printer_setup] test_printer_setup - [INFO] INFO -
2025-06-12 11:26:46 - [test_printer_setup] test_printer_setup - [INFO] INFO - 🖨️ 3D-Drucker 3 - Halle B
2025-06-12 11:26:46 - [test_printer_setup] test_printer_setup - [INFO] INFO - 📍 Standort: Halle B - Arbeitsplatz 1
2025-06-12 11:26:46 - [test_printer_setup] test_printer_setup - [INFO] INFO - 🔌 Steckdosen-IP: 192.168.1.203
2025-06-12 11:26:46 - [test_printer_setup] test_printer_setup - [INFO] INFO - ⚡ Status: Nicht erreichbar
2025-06-12 11:26:46 - [test_printer_setup] test_printer_setup - [INFO] INFO - ❌ Steckdose nicht erreichbar
2025-06-12 11:26:46 - [test_printer_setup] test_printer_setup - [INFO] INFO - ⚠️ Fehler: Steckdose nicht erreichbar
2025-06-12 11:26:46 - [test_printer_setup] test_printer_setup - [INFO] INFO -
2025-06-12 11:26:46 - [test_printer_setup] test_printer_setup - [INFO] INFO - 🖨️ 3D-Drucker 4 - Halle B
2025-06-12 11:26:46 - [test_printer_setup] test_printer_setup - [INFO] INFO - 📍 Standort: Halle B - Arbeitsplatz 2
2025-06-12 11:26:46 - [test_printer_setup] test_printer_setup - [INFO] INFO - 🔌 Steckdosen-IP: 192.168.1.204
2025-06-12 11:26:46 - [test_printer_setup] test_printer_setup - [INFO] INFO - ⚡ Status: Nicht erreichbar
2025-06-12 11:26:46 - [test_printer_setup] test_printer_setup - [INFO] INFO - ❌ Steckdose nicht erreichbar
2025-06-12 11:26:46 - [test_printer_setup] test_printer_setup - [INFO] INFO - ⚠️ Fehler: Steckdose nicht erreichbar
2025-06-12 11:26:46 - [test_printer_setup] test_printer_setup - [INFO] INFO -
2025-06-12 11:26:46 - [test_printer_setup] test_printer_setup - [INFO] INFO - 🖨️ 3D-Drucker 5 - Labor
2025-06-12 11:26:46 - [test_printer_setup] test_printer_setup - [INFO] INFO - 📍 Standort: Labor - SLA-Bereich
2025-06-12 11:26:46 - [test_printer_setup] test_printer_setup - [INFO] INFO - 🔌 Steckdosen-IP: 192.168.1.205
2025-06-12 11:26:46 - [test_printer_setup] test_printer_setup - [INFO] INFO - ⚡ Status: Nicht erreichbar
2025-06-12 11:26:46 - [test_printer_setup] test_printer_setup - [INFO] INFO - ❌ Steckdose nicht erreichbar
2025-06-12 11:26:46 - [test_printer_setup] test_printer_setup - [INFO] INFO - ⚠️ Fehler: Steckdose nicht erreichbar
2025-06-12 11:26:46 - [test_printer_setup] test_printer_setup - [INFO] INFO -
2025-06-12 11:26:46 - [test_printer_setup] test_printer_setup - [INFO] INFO - 🖨️ 3D-Drucker 6 - Werkstatt
2025-06-12 11:26:46 - [test_printer_setup] test_printer_setup - [INFO] INFO - 📍 Standort: Werkstatt - Spezialbereich
2025-06-12 11:26:46 - [test_printer_setup] test_printer_setup - [INFO] INFO - 🔌 Steckdosen-IP: 192.168.1.206
2025-06-12 11:26:46 - [test_printer_setup] test_printer_setup - [INFO] INFO - ⚡ Status: Nicht erreichbar
2025-06-12 11:26:46 - [test_printer_setup] test_printer_setup - [INFO] INFO - ❌ Steckdose nicht erreichbar
2025-06-12 11:26:46 - [test_printer_setup] test_printer_setup - [INFO] INFO - ⚠️ Fehler: Steckdose nicht erreichbar
2025-06-12 11:26:46 - [test_printer_setup] test_printer_setup - [INFO] INFO -
2025-06-12 11:26:46 - [test_printer_setup] test_printer_setup - [INFO] INFO - 📈 Status-Zusammenfassung:
2025-06-12 11:26:46 - [test_printer_setup] test_printer_setup - [INFO] INFO - ✅ Eingeschaltet: 0
2025-06-12 11:26:46 - [test_printer_setup] test_printer_setup - [INFO] INFO - ⭕ Ausgeschaltet: 0
2025-06-12 11:26:46 - [test_printer_setup] test_printer_setup - [INFO] INFO - ❌ Nicht erreichbar: 6
2025-06-12 11:26:46 - [test_printer_setup] test_printer_setup - [INFO] INFO - ❓ Unbekannt: 0

View File

@ -68,3 +68,6 @@
2025-06-12 11:04:05 - [user] user - [INFO] INFO - User admin retrieved settings via API
2025-06-12 11:04:10 - [user] user - [INFO] INFO - User admin retrieved settings via API
2025-06-12 11:04:11 - [user] user - [INFO] INFO - User admin retrieved settings via API
2025-06-12 11:21:27 - [user] user - [INFO] INFO - User admin retrieved settings via API
2025-06-12 11:21:33 - [user] user - [INFO] INFO - User admin retrieved settings via API
2025-06-12 11:21:35 - [user] user - [INFO] INFO - User admin retrieved settings via API

View File

@ -104,3 +104,17 @@
2025-06-12 11:00:40 - [utilities_collection] utilities_collection - [INFO] INFO - 🚨 ALLERLETZTE MEGA-Konsolidierung: 12+ Dateien → 1 Datei (90%+ Reduktion)
2025-06-12 11:00:45 - [utilities_collection] utilities_collection - [INFO] INFO - ✅ Utilities Collection initialisiert
2025-06-12 11:00:45 - [utilities_collection] utilities_collection - [INFO] INFO - 🚨 ALLERLETZTE MEGA-Konsolidierung: 12+ Dateien → 1 Datei (90%+ Reduktion)
2025-06-12 11:21:20 - [utilities_collection] utilities_collection - [INFO] INFO - ✅ Utilities Collection initialisiert
2025-06-12 11:21:20 - [utilities_collection] utilities_collection - [INFO] INFO - 🚨 ALLERLETZTE MEGA-Konsolidierung: 12+ Dateien → 1 Datei (90%+ Reduktion)
2025-06-12 11:21:25 - [utilities_collection] utilities_collection - [INFO] INFO - ✅ Utilities Collection initialisiert
2025-06-12 11:21:25 - [utilities_collection] utilities_collection - [INFO] INFO - 🚨 ALLERLETZTE MEGA-Konsolidierung: 12+ Dateien → 1 Datei (90%+ Reduktion)
2025-06-12 11:23:06 - [utilities_collection] utilities_collection - [INFO] INFO - ✅ Utilities Collection initialisiert
2025-06-12 11:23:06 - [utilities_collection] utilities_collection - [INFO] INFO - 🚨 ALLERLETZTE MEGA-Konsolidierung: 12+ Dateien → 1 Datei (90%+ Reduktion)
2025-06-12 11:24:18 - [utilities_collection] utilities_collection - [INFO] INFO - ✅ Utilities Collection initialisiert
2025-06-12 11:24:18 - [utilities_collection] utilities_collection - [INFO] INFO - 🚨 ALLERLETZTE MEGA-Konsolidierung: 12+ Dateien → 1 Datei (90%+ Reduktion)
2025-06-12 11:24:47 - [utilities_collection] utilities_collection - [INFO] INFO - ✅ Utilities Collection initialisiert
2025-06-12 11:24:47 - [utilities_collection] utilities_collection - [INFO] INFO - 🚨 ALLERLETZTE MEGA-Konsolidierung: 12+ Dateien → 1 Datei (90%+ Reduktion)
2025-06-12 11:26:14 - [utilities_collection] utilities_collection - [INFO] INFO - ✅ Utilities Collection initialisiert
2025-06-12 11:26:14 - [utilities_collection] utilities_collection - [INFO] INFO - 🚨 ALLERLETZTE MEGA-Konsolidierung: 12+ Dateien → 1 Datei (90%+ Reduktion)
2025-06-12 11:26:32 - [utilities_collection] utilities_collection - [INFO] INFO - ✅ Utilities Collection initialisiert
2025-06-12 11:26:32 - [utilities_collection] utilities_collection - [INFO] INFO - 🚨 ALLERLETZTE MEGA-Konsolidierung: 12+ Dateien → 1 Datei (90%+ Reduktion)

View File

@ -103,3 +103,17 @@
2025-06-12 11:00:40 - [windows_fixes] windows_fixes - [INFO] INFO - ✅ Alle Windows-Fixes erfolgreich angewendet
2025-06-12 11:00:45 - [windows_fixes] windows_fixes - [INFO] INFO - 🔧 Wende Windows-spezifische Fixes an...
2025-06-12 11:00:45 - [windows_fixes] windows_fixes - [INFO] INFO - ✅ Alle Windows-Fixes erfolgreich angewendet
2025-06-12 11:21:20 - [windows_fixes] windows_fixes - [INFO] INFO - 🔧 Wende Windows-spezifische Fixes an...
2025-06-12 11:21:20 - [windows_fixes] windows_fixes - [INFO] INFO - ✅ Alle Windows-Fixes erfolgreich angewendet
2025-06-12 11:21:25 - [windows_fixes] windows_fixes - [INFO] INFO - 🔧 Wende Windows-spezifische Fixes an...
2025-06-12 11:21:25 - [windows_fixes] windows_fixes - [INFO] INFO - ✅ Alle Windows-Fixes erfolgreich angewendet
2025-06-12 11:23:06 - [windows_fixes] windows_fixes - [INFO] INFO - 🔧 Wende Windows-spezifische Fixes an...
2025-06-12 11:23:06 - [windows_fixes] windows_fixes - [INFO] INFO - ✅ Alle Windows-Fixes erfolgreich angewendet
2025-06-12 11:24:18 - [windows_fixes] windows_fixes - [INFO] INFO - 🔧 Wende Windows-spezifische Fixes an...
2025-06-12 11:24:18 - [windows_fixes] windows_fixes - [INFO] INFO - ✅ Alle Windows-Fixes erfolgreich angewendet
2025-06-12 11:24:47 - [windows_fixes] windows_fixes - [INFO] INFO - 🔧 Wende Windows-spezifische Fixes an...
2025-06-12 11:24:47 - [windows_fixes] windows_fixes - [INFO] INFO - ✅ Alle Windows-Fixes erfolgreich angewendet
2025-06-12 11:26:14 - [windows_fixes] windows_fixes - [INFO] INFO - 🔧 Wende Windows-spezifische Fixes an...
2025-06-12 11:26:14 - [windows_fixes] windows_fixes - [INFO] INFO - ✅ Alle Windows-Fixes erfolgreich angewendet
2025-06-12 11:26:32 - [windows_fixes] windows_fixes - [INFO] INFO - 🔧 Wende Windows-spezifische Fixes an...
2025-06-12 11:26:32 - [windows_fixes] windows_fixes - [INFO] INFO - ✅ Alle Windows-Fixes erfolgreich angewendet

View File

@ -1,115 +0,0 @@
/**
* Simplified Mobile Navigation Handler
* Minimaler Code für maximale Performance
*/
class SimpleMobileNav {
constructor() {
this.toggle = document.getElementById('mobileMenuToggle');
this.menu = document.getElementById('mobileMenu');
this.navbar = document.querySelector('.navbar');
this.isOpen = false;
this.init();
}
init() {
if (!this.toggle || !this.menu) return;
// Toggle Button
this.toggle.addEventListener('click', (e) => {
e.stopPropagation();
this.toggleMenu();
});
// Close on outside click
document.addEventListener('click', (e) => {
if (this.isOpen && !this.menu.contains(e.target)) {
this.closeMenu();
}
});
// Close on ESC
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && this.isOpen) {
this.closeMenu();
}
});
// Close on resize to desktop
let resizeTimer;
window.addEventListener('resize', () => {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(() => {
if (window.innerWidth >= 1024 && this.isOpen) {
this.closeMenu();
}
}, 250);
});
// Simple scroll effect
let lastScroll = 0;
window.addEventListener('scroll', () => {
const currentScroll = window.pageYOffset;
// Add/remove scrolled class
if (currentScroll > 50) {
this.navbar.classList.add('scrolled');
} else {
this.navbar.classList.remove('scrolled');
}
lastScroll = currentScroll;
}, { passive: true });
}
toggleMenu() {
this.isOpen ? this.closeMenu() : this.openMenu();
}
openMenu() {
this.isOpen = true;
this.menu.classList.remove('hidden');
// Force reflow
this.menu.offsetHeight;
this.menu.classList.add('active');
this.toggle.setAttribute('aria-expanded', 'true');
// Update icon
const path = this.toggle.querySelector('svg path');
if (path) path.setAttribute('d', 'M6 18L18 6M6 6l12 12');
// Prevent body scroll
document.body.style.overflow = 'hidden';
}
closeMenu() {
this.isOpen = false;
this.menu.classList.remove('active');
this.toggle.setAttribute('aria-expanded', 'false');
// Update icon
const path = this.toggle.querySelector('svg path');
if (path) path.setAttribute('d', 'M4 6h16M4 12h16M4 18h16');
// Restore body scroll
document.body.style.overflow = '';
// Hide after transition
setTimeout(() => {
if (!this.isOpen) {
this.menu.classList.add('hidden');
}
}, 200);
}
}
// Initialize on DOM ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => {
window.mobileNav = new SimpleMobileNav();
});
} else {
window.mobileNav = new SimpleMobileNav();
}

View File

@ -27,8 +27,8 @@
<!-- CSS - Performance Optimized -->
<link href="{{ url_for('static', filename='css/tailwind.min.css') }}" rel="stylesheet">
<!-- Verbesserte Navbar CSS ersetzt die alten Glassmorphism-Styles -->
<link href="{{ url_for('static', filename='css/navbar-improved.css') }}" rel="stylesheet">
<!-- Moderne Navbar CSS -->
<link href="{{ url_for('static', filename='css/navbar.css') }}" rel="stylesheet">
<link href="{{ url_for('static', filename='css/performance-optimized.min.css') }}" rel="stylesheet">
<link href="{{ url_for('static', filename='css/components.min.css') }}" rel="stylesheet">
<link href="{{ url_for('static', filename='css/professional-theme.min.css') }}" rel="stylesheet">
@ -272,373 +272,8 @@
<body class="min-h-screen flex flex-col bg-white text-slate-900 dark:bg-black dark:text-white transition-colors duration-300 text-base mercedes-background">
<!-- Navigation -->
<nav class="navbar">
<div class="max-w-7xl mx-auto px-3 sm:px-4 lg:px-6">
<div class="flex items-center justify-between h-16 sm:h-18 lg:h-20">
<!-- Brand Section -->
<div class="flex-shrink-0">
<a href="{{ url_for('dashboard') }}" class="navbar-brand group" aria-label="Zur Startseite">
<!-- Mercedes-Benz Logo -->
<div class="w-5 h-5 sm:w-6 sm:h-6 lg:w-7 lg:h-7">
<svg class="w-full h-full text-slate-900 dark:text-white transition-colors duration-300" fill="currentColor" viewBox="0 0 80 80" aria-hidden="true">
<path d="M58.6,4.5C53,1.6,46.7,0,40,0c-6.7,0-13,1.6-18.6,4.5v0C8.7,11.2,0,24.6,0,40c0,15.4,8.7,28.8,21.5,35.5
C27,78.3,33.3,80,40,80c6.7,0,12.9-1.7,18.5-4.6C71.3,68.8,80,55.4,80,40C80,24.6,71.3,11.2,58.6,4.5z M4,40
c0-13.1,7-24.5,17.5-30.9v0C26.6,6,32.5,4.2,39,4l-4.5,32.7L21.5,46.8v0L8.3,57.1C5.6,52,4,46.2,4,40z M58.6,70.8
C53.1,74.1,46.8,76,40,76c-6.8,0-13.2-1.9-18.6-5.2c-4.9-2.9-8.9-6.9-11.9-11.7l11.9-4.9v0L40,46.6l18.6,7.5v0l12,4.9
C67.6,63.9,63.4,67.9,58.6,70.8z M58.6,46.8L58.6,46.8l-12.9-10L41.1,4c6.3,0.2,12.3,2,17.4,5.1v0C69,15.4,76,26.9,76,40
c0,6.2-1.5,12-4.3,17.1L58.6,46.8z"/>
</svg>
</div>
<!-- Brand Text -->
<div class="flex flex-col ml-3">
<span class="text-sm lg:text-base font-bold text-slate-900 dark:text-white transition-colors duration-300 tracking-tight">Mercedes-Benz</span>
<span class="text-xs font-medium text-slate-600 dark:text-slate-400 transition-colors duration-300">Manage Your Printer - </span>
</div>
</a>
</div>
<!-- Desktop Navigation Menu - überarbeitetes Design -->
<div class="hidden lg:flex flex-1 justify-center">
<nav class="navbar-menu-new" role="navigation" aria-label="Hauptnavigation">
<a href="{{ url_for('dashboard') }}"
class="nav-item {{ 'active' if request.endpoint == 'dashboard' else '' }}">
<i class="fas fa-tachometer-alt w-5 h-5"></i>
<span>Dashboard</span>
</a>
<a href="{{ url_for('printers_page') }}"
class="nav-item {{ 'active' if request.endpoint == 'printers_page' else '' }}">
<i class="fas fa-print w-5 h-5"></i>
<span>Drucker</span>
</a>
{% if current_user.is_authenticated and current_user.has_permission('CONTROL_PRINTER') %}
<a href="{{ url_for('tapo.tapo_dashboard') }}"
class="nav-item {{ 'active' if request.endpoint == 'tapo.tapo_dashboard' else '' }}">
<i class="fas fa-plug w-5 h-5"></i>
<span>Tapo-Steckdosen</span>
</a>
{% endif %}
<a href="{{ url_for('jobs_page') }}"
class="nav-item {{ 'active' if request.endpoint == 'jobs_page' else '' }}">
<i class="fas fa-clipboard-list w-5 h-5"></i>
<span>Reservierungen</span>
</a>
<a href="{{ url_for('stats_page') }}"
class="nav-item {{ 'active' if request.endpoint == 'stats_page' else '' }}">
<i class="fas fa-chart-bar w-5 h-5"></i>
<span>Statistiken</span>
</a>
<a href="{{ url_for('calendar.calendar_view') }}"
class="nav-item {{ 'active' if request.endpoint == 'calendar.calendar_view' else '' }}">
<i class="fas fa-calendar-alt w-5 h-5"></i>
<span>Schichtplan</span>
</a>
<a href="{{ url_for('guest.guest_request_form') }}"
class="nav-item {{ 'active' if request.endpoint == 'guest.guest_request_form' else '' }}">
<i class="fas fa-user-plus w-5 h-5"></i>
<span>Antrag stellen</span>
</a>
<a href="{{ url_for('guest.guest_requests_overview') }}"
class="nav-item {{ 'active' if request.endpoint == 'guest.guest_requests_overview' else '' }}">
<i class="fas fa-file-alt w-5 h-5"></i>
<span>Meine Anträge</span>
</a>
{% if current_user.is_authenticated and current_user.is_admin %}
<a href="{{ url_for('admin.admin_dashboard') }}"
class="nav-item {{ 'active' if request.endpoint == 'admin.admin_dashboard' else '' }}">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"/>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>
</svg>
<span>Ausbilder-Bereich</span>
</a>
{% endif %}
</nav>
</div>
<!-- Rechte Seite der Navbar -->
<div class="flex items-center space-x-2 sm:space-x-3">
<!-- Mobile Menu Toggle (neu) -->
<button
id="mobileMenuToggle"
class="lg:hidden p-2 rounded-full text-slate-700 dark:text-slate-300 hover:bg-slate-100/80 dark:hover:bg-slate-800/50"
aria-label="Menü öffnen"
aria-expanded="false"
>
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"/>
</svg>
</button>
{% if current_user.is_authenticated %}
<!-- Benachrichtigungen - kompakteres Design -->
<div class="relative">
<button
id="notificationToggle"
class="relative p-1.5 rounded-full text-slate-700 dark:text-slate-300 hover:bg-slate-100/80 dark:hover:bg-slate-800/50 transition-all duration-200"
aria-label="Benachrichtigungen anzeigen"
title="Benachrichtigungen"
>
<i class="fas fa-bell text-lg"></i>
<!-- Badge für ungelesene Benachrichtigungen -->
<span id="notificationBadge" class="absolute -top-1 -right-1 bg-red-500 text-white text-xs rounded-full h-4 w-4 flex items-center justify-center font-medium hidden">
0
</span>
</button>
<!-- Benachrichtigungs-Dropdown -->
<div id="notificationDropdown" class="absolute right-0 mt-2 w-72 sm:w-80 bg-white dark:bg-slate-800 rounded-lg shadow-lg border border-slate-200 dark:border-slate-600 z-50 hidden">
<div class="p-3 border-b border-slate-200 dark:border-slate-600">
<h3 class="text-base font-semibold text-slate-900 dark:text-white">Benachrichtigungen</h3>
</div>
<div id="notificationList" class="max-h-80 overflow-y-auto">
<div class="p-3 text-center text-slate-500 dark:text-slate-400 text-sm">
Keine neuen Benachrichtigungen
</div>
</div>
<div class="p-2 border-t border-slate-200 dark:border-slate-600">
<button id="markAllRead" class="w-full text-xs text-blue-600 dark:text-blue-400 hover:text-blue-800 dark:hover:text-blue-300 transition-colors">
Alle als gelesen markieren
</button>
</div>
</div>
</div>
<!-- Dark Mode Toggle - Clean and Modern -->
<button
class="dark-mode-toggle darkModeToggle"
aria-label="Dark Mode umschalten"
title="Design wechseln"
>
<span class="dark-mode-toggle-slider">
<i class="fas fa-sun dark-mode-toggle-icon sun absolute inset-0 flex items-center justify-center"></i>
<i class="fas fa-moon dark-mode-toggle-icon moon absolute inset-0 flex items-center justify-center opacity-0"></i>
</span>
</button>
<!-- User Profile Dropdown - kompakteres Design -->
<div class="relative" id="user-menu-container">
<button
id="user-menu-button"
class="flex items-center space-x-1 rounded-full p-1 text-slate-700 dark:text-slate-300 hover:bg-slate-100/80 dark:hover:bg-slate-800/50 transition-all duration-200"
aria-expanded="false"
aria-haspopup="true"
aria-label="Benutzermenu öffnen"
>
<!-- Profile Avatar -->
<div class="w-6 h-6 rounded-full bg-blue-500 flex items-center justify-center text-white text-xs font-medium">
{{ current_user.email[0].upper() if current_user.email else 'U' }}
</div>
<!-- User Info (nur auf größeren Geräten) -->
<div class="hidden sm:block text-left ml-1">
<div class="text-xs font-medium text-slate-900 dark:text-white transition-colors duration-300">{{ current_user.email.split('@')[0] if current_user.email else 'Benutzer' }}</div>
</div>
</button>
<!-- User Menu Dropdown -->
<div id="user-dropdown" class="absolute right-0 mt-2 w-64 bg-white dark:bg-slate-800 rounded-lg shadow-lg border border-slate-200 dark:border-slate-600 z-50 hidden origin-top-right">
<!-- User Info Header -->
<div class="px-4 py-3 border-b border-slate-200 dark:border-slate-600">
<div class="flex items-center space-x-3">
<div class="w-10 h-10 rounded-full bg-blue-500 flex items-center justify-center text-white font-medium">
{{ current_user.email[0].upper() if current_user.email else 'U' }}
</div>
<div class="flex-1 min-w-0">
<p class="text-sm font-medium text-slate-900 dark:text-white truncate">
{{ current_user.full_name if current_user.full_name else current_user.email.split('@')[0] if current_user.email else 'Benutzer' }}
</p>
<p class="text-xs text-slate-500 dark:text-slate-400 truncate">
{{ current_user.email if current_user.email else 'Keine E-Mail' }}
</p>
{% if current_user.is_admin %}
<span class="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-purple-100 text-purple-800 dark:bg-purple-900 dark:text-purple-200 mt-1">
Ausbilder
</span>
{% endif %}
</div>
</div>
</div>
<!-- Menu Items -->
<div class="py-1">
<a href="{{ url_for('users.user_profile') }}"
class="flex items-center px-4 py-2 text-sm text-slate-700 dark:text-slate-300 hover:bg-slate-100 dark:hover:bg-slate-700 transition-colors duration-200">
<svg class="w-4 h-4 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"/>
</svg>
Mein Profil
</a>
<a href="{{ url_for('users.user_settings') }}"
class="flex items-center px-4 py-2 text-sm text-slate-700 dark:text-slate-300 hover:bg-slate-100 dark:hover:bg-slate-700 transition-colors duration-200">
<svg class="w-4 h-4 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"/>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>
</svg>
Einstellungen
</a>
<a href="{{ url_for('jobs_page') }}"
class="flex items-center px-4 py-2 text-sm text-slate-700 dark:text-slate-300 hover:bg-slate-100 dark:hover:bg-slate-700 transition-colors duration-200">
<svg class="w-4 h-4 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6"/>
</svg>
Neue Reservierung
</a>
<a href="{{ url_for('stats_page') }}"
class="flex items-center px-4 py-2 text-sm text-slate-700 dark:text-slate-300 hover:bg-slate-100 dark:hover:bg-slate-700 transition-colors duration-200">
<svg class="w-4 h-4 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"/>
</svg>
Analytik
</a>
</div>
<div class="border-t border-slate-200 dark:border-slate-600">
<a href="{{ url_for('privacy') }}"
class="flex items-center px-4 py-2 text-sm text-slate-500 dark:text-slate-400 hover:bg-slate-100 dark:hover:bg-slate-700 transition-colors duration-200">
<svg class="w-4 h-4 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2zm10-10V7a4 4 0 00-8 0v4h8z"/>
</svg>
Datenschutz
</a>
<a href="{{ url_for('terms') }}"
class="flex items-center px-4 py-2 text-sm text-slate-500 dark:text-slate-400 hover:bg-slate-100 dark:hover:bg-slate-700 transition-colors duration-200">
<svg class="w-4 h-4 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
</svg>
Nutzungsbedingungen
</a>
<button onclick="handleLogout()"
class="flex items-center w-full px-4 py-2 text-sm text-red-600 dark:text-red-400 hover:bg-red-50 dark:hover:bg-red-900/20 transition-colors duration-200">
<svg class="w-4 h-4 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1"/>
</svg>
Abmelden
</button>
</div>
</div>
</div>
{% else %}
<!-- Dark Mode Toggle für nicht angemeldete Benutzer -->
<button
id="darkModeToggle"
class="dark-mode-toggle"
aria-label="Dark Mode umschalten"
title="Design wechseln"
>
<span class="dark-mode-toggle-slider">
<i class="fas fa-sun dark-mode-toggle-icon sun absolute inset-0 flex items-center justify-center"></i>
<i class="fas fa-moon dark-mode-toggle-icon moon absolute inset-0 flex items-center justify-center opacity-0"></i>
</span>
</button>
<!-- Login Button - kompakteres Design -->
<a href="{{ url_for('auth.login') }}"
class="flex items-center space-x-1 py-1 px-2 rounded-md bg-blue-600 hover:bg-blue-700 text-white text-xs transition-colors duration-200">
<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 16l-4-4m0 0l4-4m-4 4h14m-5 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1"/>
</svg>
<span class="hidden sm:inline">Anmelden</span>
</a>
{% endif %}
</div>
</div>
</div>
</nav>
<!-- Mobile Menu (neu) -->
<div id="mobileMenu" class="mobile-menu-new hidden lg:hidden">
<nav class="flex flex-col space-y-1 px-3 py-4" role="navigation" aria-label="Mobile Navigation">
<a href="{{ url_for('dashboard') }}"
class="mobile-nav-item {{ 'active' if request.endpoint == 'dashboard' else '' }}">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2H5a2 2 0 00-2-2z"/>
</svg>
<span>Dashboard</span>
</a>
<a href="{{ url_for('printers_page') }}"
class="mobile-nav-item {{ 'active' if request.endpoint == 'printers_page' else '' }}">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"/>
</svg>
<span>Drucker</span>
</a>
{% if current_user.is_authenticated and current_user.has_permission('CONTROL_PRINTER') %}
<a href="{{ url_for('tapo.tapo_dashboard') }}"
class="mobile-nav-item {{ 'active' if request.endpoint == 'tapo.tapo_dashboard' else '' }}">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-3a2 2 0 00-2 2v1a2 2 0 002 2h3m4-6v1a2 2 0 01-2 2H9a2 2 0 01-2-2v-1m8-2V9a2 2 0 00-2-2H9a2 2 0 00-2 2v3.5M13 9h3l2 5H5l2-5h3"/>
</svg>
<span>Tapo-Steckdosen</span>
</a>
{% endif %}
<a href="{{ url_for('jobs_page') }}"
class="mobile-nav-item {{ 'active' if request.endpoint == 'jobs_page' else '' }}">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v10a2 2 0 002 2h8a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"/>
</svg>
<span>Reservierungen</span>
</a>
<a href="{{ url_for('stats_page') }}"
class="mobile-nav-item {{ 'active' if request.endpoint == 'stats_page' else '' }}">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"/>
</svg>
<span>Statistiken</span>
</a>
<a href="{{ url_for('calendar.calendar_view') }}"
class="mobile-nav-item {{ 'active' if request.endpoint == 'calendar.calendar_view' else '' }}">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"/>
</svg>
<span>Schichtplan</span>
</a>
<a href="{{ url_for('guest.guest_request_form') }}"
class="mobile-nav-item {{ 'active' if request.endpoint == 'guest.guest_request_form' else '' }}">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"/>
</svg>
<span>Antrag stellen</span>
</a>
<a href="{{ url_for('guest.guest_requests_overview') }}"
class="mobile-nav-item {{ 'active' if request.endpoint == 'guest.guest_requests_overview' else '' }}">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
</svg>
<span>Meine Anträge</span>
</a>
{% if current_user.is_authenticated and current_user.is_admin %}
<a href="{{ url_for('admin.admin_dashboard') }}"
class="mobile-nav-item {{ 'active' if request.endpoint == 'admin.admin_dashboard' else '' }}">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"/>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>
</svg>
<span>Ausbilder-Bereich</span>
</a>
{% endif %}
</nav>
</div>
<!-- Moderne MYP Platform Navbar -->
{% include 'includes/navbar.html' %}
<!-- Main Content -->
<main id="main-content" class="flex-grow max-w-7xl w-full mx-auto px-3 sm:px-6 lg:px-8 py-4 sm:py-8">
@ -784,8 +419,8 @@
<!-- Glassmorphism Notification System - Modernisiert -->
<script src="{{ url_for('static', filename='js/glassmorphism-notifications.min.js') }}"></script>
<!-- Mobile Navigation Handler -->
<script src="{{ url_for('static', filename='js/navbar-mobile.js') }}"></script>
<!-- Modern Navbar Controller -->
<script src="{{ url_for('static', filename='js/navbar.js') }}"></script>
<!-- Additional JavaScript Functions -->
<script>

View File

@ -0,0 +1,304 @@
<!-- =============================================
MYP Platform - Moderne Navbar
Mercedes-Benz Design System
============================================= -->
<nav class="navbar" role="navigation" aria-label="Hauptnavigation">
<div class="navbar-container">
<!-- Brand Section -->
<a href="{{ url_for('dashboard') }}" class="navbar-brand" aria-label="Zur Startseite">
<!-- Mercedes-Benz Logo -->
<svg class="brand-icon" viewBox="0 0 80 80" fill="currentColor" aria-hidden="true">
<path d="M58.6,4.5C53,1.6,46.7,0,40,0c-6.7,0-13,1.6-18.6,4.5v0C8.7,11.2,0,24.6,0,40c0,15.4,8.7,28.8,21.5,35.5C27,78.3,33.3,80,40,80c6.7,0,12.9-1.7,18.5-4.6C71.3,68.8,80,55.4,80,40C80,24.6,71.3,11.2,58.6,4.5z M4,40c0-13.1,7-24.5,17.5-30.9v0C26.6,6,32.5,4.2,39,4l-4.5,32.7L21.5,46.8v0L8.3,57.1C5.6,52,4,46.2,4,40z M58.6,70.8C53.1,74.1,46.8,76,40,76c-6.8,0-13.2-1.9-18.6-5.2c-4.9-2.9-8.9-6.9-11.9-11.7l11.9-4.9v0L40,46.6l18.6,7.5v0l12,4.9C67.6,63.9,63.4,67.9,58.6,70.8z M58.6,46.8L58.6,46.8l-12.9-10L41.1,4c6.3,0.2,12.3,2,17.4,5.1v0C69,15.4,76,26.9,76,40c0,6.2-1.5,12-4.3,17.1L58.6,46.8z"/>
</svg>
<!-- Brand Text -->
<div class="brand-text">
<span class="brand-title">Mercedes-Benz</span>
<span class="brand-subtitle">MYP Platform</span>
</div>
</a>
<!-- Desktop Navigation -->
<div class="navbar-nav">
<a href="{{ url_for('dashboard') }}"
class="nav-item {{ 'active' if request.endpoint == 'dashboard' else '' }}"
aria-label="Dashboard">
<i class="fas fa-tachometer-alt" aria-hidden="true"></i>
<span>Dashboard</span>
</a>
<a href="{{ url_for('printers_page') }}"
class="nav-item {{ 'active' if request.endpoint == 'printers_page' else '' }}"
aria-label="Drucker verwalten">
<i class="fas fa-print" aria-hidden="true"></i>
<span>Drucker</span>
</a>
{% if current_user.is_authenticated and current_user.has_permission('VIEW_JOBS') %}
<a href="{{ url_for('jobs.jobs_page') }}"
class="nav-item {{ 'active' if request.endpoint == 'jobs.jobs_page' else '' }}"
aria-label="Druckaufträge anzeigen">
<i class="fas fa-tasks" aria-hidden="true"></i>
<span>Aufträge</span>
</a>
{% endif %}
{% if current_user.is_authenticated and current_user.has_permission('CONTROL_PRINTER') %}
<a href="{{ url_for('tapo.tapo_dashboard') }}"
class="nav-item {{ 'active' if request.endpoint == 'tapo.tapo_dashboard' else '' }}"
aria-label="Smart-Plugs verwalten">
<i class="fas fa-plug" aria-hidden="true"></i>
<span>Smart-Plugs</span>
</a>
{% endif %}
{% if current_user.is_authenticated and current_user.has_permission('VIEW_CALENDAR') %}
<a href="{{ url_for('calendar') }}"
class="nav-item {{ 'active' if request.endpoint == 'calendar' else '' }}"
aria-label="Kalender anzeigen">
<i class="fas fa-calendar-alt" aria-hidden="true"></i>
<span>Kalender</span>
</a>
{% endif %}
{% if current_user.is_authenticated and current_user.has_role('admin') %}
<a href="{{ url_for('admin.admin_dashboard') }}"
class="nav-item {{ 'active' if request.endpoint == 'admin.admin_dashboard' else '' }}"
aria-label="Administrationsbereich">
<i class="fas fa-cog" aria-hidden="true"></i>
<span>Admin</span>
</a>
{% endif %}
</div>
<!-- Navbar Actions (Rechte Seite) -->
<div class="navbar-actions">
{% if current_user.is_authenticated %}
<!-- Benachrichtigungen -->
<div class="dropdown">
<button class="navbar-btn"
id="notificationToggle"
aria-label="Benachrichtigungen anzeigen"
aria-expanded="false">
<i class="fas fa-bell" aria-hidden="true"></i>
</button>
<div class="dropdown-menu" id="notificationDropdown">
<div class="dropdown-header">
<i class="fas fa-bell mr-2" aria-hidden="true"></i>
Benachrichtigungen
</div>
<div id="notificationList">
<!-- Wird dynamisch geladen -->
<div class="dropdown-item">
<i class="fas fa-info-circle text-blue-500" aria-hidden="true"></i>
<div>
<div class="font-medium">Keine neuen Benachrichtigungen</div>
<div class="text-sm text-gray-500">Alle Meldungen sind aktuell</div>
</div>
</div>
</div>
<div class="dropdown-divider"></div>
<a href="{{ url_for('notifications') }}" class="dropdown-item">
<i class="fas fa-eye" aria-hidden="true"></i>
Alle anzeigen
</a>
</div>
</div>
<!-- User Menu -->
<div class="dropdown">
<div class="user-avatar"
aria-label="Benutzerprofil öffnen"
aria-expanded="false">
{{ current_user.get_initials() }}
</div>
<div class="dropdown-menu" id="userDropdown">
<div class="dropdown-header">
<i class="fas fa-user mr-2" aria-hidden="true"></i>
{{ current_user.display_name or current_user.username }}
</div>
<a href="{{ url_for('users.profile') }}" class="dropdown-item">
<i class="fas fa-user-circle" aria-hidden="true"></i>
Mein Profil
</a>
<a href="{{ url_for('users.settings') }}" class="dropdown-item">
<i class="fas fa-cog" aria-hidden="true"></i>
Einstellungen
</a>
{% if current_user.has_role('admin') %}
<div class="dropdown-divider"></div>
<a href="{{ url_for('admin.admin_dashboard') }}" class="dropdown-item">
<i class="fas fa-shield-alt" aria-hidden="true"></i>
Administration
</a>
{% endif %}
<div class="dropdown-divider"></div>
<a href="{{ url_for('auth.logout') }}" class="dropdown-item">
<i class="fas fa-sign-out-alt" aria-hidden="true"></i>
Abmelden
</a>
</div>
</div>
{% else %}
<!-- Nicht angemeldet -->
<a href="{{ url_for('auth.login') }}" class="navbar-btn" aria-label="Anmelden">
<i class="fas fa-sign-in-alt" aria-hidden="true"></i>
</a>
{% endif %}
<!-- Dark Mode Toggle -->
<button class="navbar-btn"
id="darkModeToggle"
aria-label="Dark Mode umschalten"
title="Dark Mode umschalten">
<i class="fas fa-moon" aria-hidden="true"></i>
</button>
<!-- Mobile Menu Toggle -->
<button class="mobile-menu-toggle"
id="mobileMenuToggle"
aria-label="Menü öffnen/schließen"
aria-expanded="false">
<i class="fas fa-bars" aria-hidden="true"></i>
</button>
</div>
</div>
</nav>
<!-- Mobile Menu -->
<div class="mobile-menu" id="mobileMenu">
<div class="mobile-nav">
<a href="{{ url_for('dashboard') }}"
class="mobile-nav-item {{ 'active' if request.endpoint == 'dashboard' else '' }}">
<i class="fas fa-tachometer-alt" aria-hidden="true"></i>
<span>Dashboard</span>
</a>
<a href="{{ url_for('printers_page') }}"
class="mobile-nav-item {{ 'active' if request.endpoint == 'printers_page' else '' }}">
<i class="fas fa-print" aria-hidden="true"></i>
<span>Drucker</span>
</a>
{% if current_user.is_authenticated and current_user.has_permission('VIEW_JOBS') %}
<a href="{{ url_for('jobs.jobs_page') }}"
class="mobile-nav-item {{ 'active' if request.endpoint == 'jobs.jobs_page' else '' }}">
<i class="fas fa-tasks" aria-hidden="true"></i>
<span>Druckaufträge</span>
</a>
{% endif %}
{% if current_user.is_authenticated and current_user.has_permission('CONTROL_PRINTER') %}
<a href="{{ url_for('tapo.tapo_dashboard') }}"
class="mobile-nav-item {{ 'active' if request.endpoint == 'tapo.tapo_dashboard' else '' }}">
<i class="fas fa-plug" aria-hidden="true"></i>
<span>Smart-Plugs</span>
</a>
{% endif %}
{% if current_user.is_authenticated and current_user.has_permission('VIEW_CALENDAR') %}
<a href="{{ url_for('calendar') }}"
class="mobile-nav-item {{ 'active' if request.endpoint == 'calendar' else '' }}">
<i class="fas fa-calendar-alt" aria-hidden="true"></i>
<span>Kalender</span>
</a>
{% endif %}
{% if current_user.is_authenticated %}
<div class="dropdown-divider"></div>
<a href="{{ url_for('users.profile') }}"
class="mobile-nav-item">
<i class="fas fa-user-circle" aria-hidden="true"></i>
<span>Mein Profil</span>
</a>
<a href="{{ url_for('users.settings') }}"
class="mobile-nav-item">
<i class="fas fa-cog" aria-hidden="true"></i>
<span>Einstellungen</span>
</a>
{% if current_user.has_role('admin') %}
<a href="{{ url_for('admin.admin_dashboard') }}"
class="mobile-nav-item">
<i class="fas fa-shield-alt" aria-hidden="true"></i>
<span>Administration</span>
</a>
{% endif %}
<div class="dropdown-divider"></div>
<a href="{{ url_for('auth.logout') }}"
class="mobile-nav-item">
<i class="fas fa-sign-out-alt" aria-hidden="true"></i>
<span>Abmelden</span>
</a>
{% else %}
<a href="{{ url_for('auth.login') }}"
class="mobile-nav-item">
<i class="fas fa-sign-in-alt" aria-hidden="true"></i>
<span>Anmelden</span>
</a>
{% endif %}
</div>
</div>
<!-- Navbar JavaScript -->
<script>
// Dark Mode Toggle Funktionalität
document.addEventListener('DOMContentLoaded', function() {
const darkModeToggle = document.getElementById('darkModeToggle');
const icon = darkModeToggle.querySelector('i');
// Aktuellen Dark Mode Status prüfen
const isDark = document.documentElement.classList.contains('dark');
updateDarkModeIcon(isDark);
darkModeToggle.addEventListener('click', function() {
const htmlElement = document.documentElement;
const newIsDark = !htmlElement.classList.contains('dark');
htmlElement.classList.toggle('dark');
updateDarkModeIcon(newIsDark);
// Status in localStorage speichern
localStorage.setItem('darkMode', newIsDark ? 'true' : 'false');
// Optional: Server-Seite informieren
fetch('/api/user/theme', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': '{{ csrf_token() }}'
},
body: JSON.stringify({ theme: newIsDark ? 'dark' : 'light' })
}).catch(() => {
// Stumm fehlschlagen - Theme funktioniert auch offline
});
});
function updateDarkModeIcon(isDark) {
if (isDark) {
icon.className = 'fas fa-sun';
darkModeToggle.setAttribute('aria-label', 'Light Mode aktivieren');
} else {
icon.className = 'fas fa-moon';
darkModeToggle.setAttribute('aria-label', 'Dark Mode aktivieren');
}
}
});
</script>

View File

@ -14,7 +14,7 @@ Tapo-Steckdosen-Steuerung | MYP Platform
Tapo-Steckdosen-Steuerung
</h1>
<p class="text-slate-600 dark:text-slate-300">
Direkte Kontrolle aller TP-Link Tapo-Steckdosen
Mercedes-Benz TBA Marienfelde - 6 Arbeitsplätze für 3D-Drucker
</p>
</div>
</div>
@ -22,18 +22,19 @@ Tapo-Steckdosen-Steuerung | MYP Platform
{% block page_actions %}
<div class="flex flex-wrap gap-3">
<button onclick="refreshAllStatus()"
<a href="{{ url_for('tapo.tapo_dashboard') }}"
class="btn-secondary flex items-center space-x-2">
<i class="fas fa-sync-alt"></i>
<span>Status aktualisieren</span>
</button>
</a>
{% if current_user.is_authenticated and current_user.has_permission('ADMIN') %}
<button onclick="discoverOutlets()"
class="btn-primary flex items-center space-x-2">
<form method="POST" action="{{ url_for('tapo.discover_outlets') }}" class="inline">
<button type="submit" class="btn-primary flex items-center space-x-2">
<i class="fas fa-search"></i>
<span>Steckdosen suchen</span>
</button>
</form>
<a href="{{ url_for('tapo.manual_control') }}"
class="btn-outline flex items-center space-x-2">
@ -54,10 +55,10 @@ Tapo-Steckdosen-Steuerung | MYP Platform
</div>
<div>
<h3 class="text-lg font-semibold text-slate-700 dark:text-slate-300">
Gesamt
Arbeitsplätze Gesamt
</h3>
<p class="text-2xl font-bold text-slate-900 dark:text-white" id="total-count">
{{ total_outlets }}
<p class="text-2xl font-bold text-slate-900 dark:text-white">
{{ total_outlets or 6 }}
</p>
</div>
</div>
@ -72,8 +73,8 @@ Tapo-Steckdosen-Steuerung | MYP Platform
<h3 class="text-lg font-semibold text-slate-700 dark:text-slate-300">
Online
</h3>
<p class="text-2xl font-bold text-slate-900 dark:text-white" id="online-count">
{{ online_outlets }}
<p class="text-2xl font-bold text-slate-900 dark:text-white">
{{ online_outlets or 0 }}
</p>
</div>
</div>
@ -88,65 +89,79 @@ Tapo-Steckdosen-Steuerung | MYP Platform
<h3 class="text-lg font-semibold text-slate-700 dark:text-slate-300">
Aktive
</h3>
<p class="text-2xl font-bold text-slate-900 dark:text-white" id="active-count">
0
<p class="text-2xl font-bold text-slate-900 dark:text-white">
{{ outlets.values() | selectattr('status', 'equalto', 'on') | list | length }}
</p>
</div>
</div>
</div>
</div>
<!-- Steckdosen-Grid -->
<!-- Mercedes-Benz 6 Arbeitsplätze -->
<div class="card">
<div class="card-header">
<h2 class="text-xl font-semibold text-slate-800 dark:text-white flex items-center">
<i class="fas fa-list mr-3"></i>
Alle Tapo-Steckdosen
<i class="fas fa-industry mr-3"></i>
Mercedes-Benz TBA Marienfelde - 3D-Drucker Arbeitsplätze
</h2>
<p class="text-sm text-slate-600 dark:text-slate-400 mt-2">
Feste Installation mit 6 konfigurierten Arbeitsplätzen
</p>
</div>
<div class="card-body">
{% if outlets %}
<!-- Steckdosen-Grid - Immer 6 Arbeitsplätze anzeigen -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6" id="outlets-grid">
{% if outlets %}
{% for ip, outlet in outlets.items() %}
<div class="outlet-card border rounded-lg p-4 {{ 'border-green-300 bg-green-50 dark:bg-green-900/20' if outlet.reachable else 'border-red-300 bg-red-50 dark:bg-red-900/20' }}"
data-ip="{{ ip }}">
<!-- Steckdosen-Header -->
<!-- Arbeitsplatz-Header -->
<div class="flex items-center justify-between mb-4">
<div class="flex items-center space-x-3">
<div class="status-indicator w-4 h-4 rounded-full {{ 'bg-green-500' if outlet.reachable else 'bg-red-500' }}"
data-ip="{{ ip }}"></div>
<div class="status-indicator w-4 h-4 rounded-full {{ 'bg-green-500' if outlet.reachable else 'bg-red-500' }}"></div>
<div>
<h3 class="font-semibold text-slate-800 dark:text-white">
{{ outlet.printer_name }}
</h3>
<p class="text-sm text-slate-600 dark:text-slate-400">
{{ ip }}
IP: {{ ip }}
</p>
{% if outlet.model %}
<p class="text-xs text-slate-500 dark:text-slate-500">
{{ outlet.model }}
</p>
{% endif %}
</div>
</div>
<div class="flex items-center space-x-2">
<button onclick="refreshOutletStatus('{{ ip }}')"
class="p-2 text-slate-500 hover:text-slate-700 dark:text-slate-400 dark:hover:text-slate-200 transition-colors"
title="Status aktualisieren">
<i class="fas fa-sync-alt text-sm"></i>
</button>
<!-- Konfigurationsstatus -->
{% if outlet.configured_in_db %}
<span class="bg-blue-100 text-blue-800 text-xs px-2 py-1 rounded-full dark:bg-blue-900 dark:text-blue-300"
title="In Datenbank konfiguriert">
<i class="fas fa-database text-xs"></i>
</span>
{% else %}
<span class="bg-yellow-100 text-yellow-800 text-xs px-2 py-1 rounded-full dark:bg-yellow-900 dark:text-yellow-300"
title="Nicht in Datenbank konfiguriert">
<i class="fas fa-exclamation-triangle text-xs"></i>
</span>
{% endif %}
<button onclick="testConnection('{{ ip }}')"
class="p-2 text-slate-500 hover:text-slate-700 dark:text-slate-400 dark:hover:text-slate-200 transition-colors"
title="Verbindung testen">
<i class="fas fa-network-wired text-sm"></i>
</button>
<!-- Position-Badge -->
<span class="bg-slate-100 text-slate-700 text-xs px-2 py-1 rounded-full dark:bg-slate-700 dark:text-slate-300">
#{{ outlet.position or loop.index }}
</span>
</div>
</div>
<!-- Status-Info -->
<div class="mb-4">
<!-- Status-Informationen -->
<div class="mb-4 space-y-2">
<div class="flex items-center justify-between">
<span class="text-sm text-slate-600 dark:text-slate-400">Status:</span>
<span class="status-text font-medium" data-ip="{{ ip }}">
<span class="status-text font-medium">
{% if outlet.reachable %}
{% if outlet.status == 'on' %}
<span class="text-green-600 dark:text-green-400">
@ -169,29 +184,48 @@ Tapo-Steckdosen-Steuerung | MYP Platform
</span>
</div>
<div class="flex items-center justify-between mt-2">
<div class="flex items-center justify-between">
<span class="text-sm text-slate-600 dark:text-slate-400">Standort:</span>
<span class="text-sm font-medium text-slate-800 dark:text-white">
{{ outlet.location }}
</span>
</div>
{% if outlet.configured_in_db and outlet.printer_id %}
<div class="flex items-center justify-between">
<span class="text-sm text-slate-600 dark:text-slate-400">Drucker-ID:</span>
<span class="text-sm font-medium text-slate-800 dark:text-white">
#{{ outlet.printer_id }}
</span>
</div>
{% endif %}
</div>
<!-- Steuerungsbuttons -->
<div class="flex space-x-3">
<button onclick="controlOutlet('{{ ip }}', 'on')"
class="flex-1 py-2 px-3 bg-green-600 hover:bg-green-700 text-white rounded-lg transition-colors font-medium text-sm"
<!-- Steuerungsformen (ohne JavaScript) -->
<div class="grid grid-cols-2 gap-3">
<!-- EIN-Button -->
<form method="POST" action="{{ url_for('tapo.control_outlet_form') }}" class="inline">
<input type="hidden" name="ip" value="{{ ip }}">
<input type="hidden" name="action" value="on">
<button type="submit"
class="w-full py-2 px-3 bg-green-600 hover:bg-green-700 text-white rounded-lg transition-colors font-medium text-sm disabled:opacity-50 disabled:cursor-not-allowed"
{% if not outlet.reachable %}disabled{% endif %}>
<i class="fas fa-power-off mr-1"></i>
EIN
</button>
</form>
<button onclick="controlOutlet('{{ ip }}', 'off')"
class="flex-1 py-2 px-3 bg-slate-600 hover:bg-slate-700 text-white rounded-lg transition-colors font-medium text-sm"
<!-- AUS-Button -->
<form method="POST" action="{{ url_for('tapo.control_outlet_form') }}" class="inline">
<input type="hidden" name="ip" value="{{ ip }}">
<input type="hidden" name="action" value="off">
<button type="submit"
class="w-full py-2 px-3 bg-slate-600 hover:bg-slate-700 text-white rounded-lg transition-colors font-medium text-sm disabled:opacity-50 disabled:cursor-not-allowed"
{% if not outlet.reachable %}disabled{% endif %}>
<i class="fas fa-power-off mr-1"></i>
AUS
</button>
</form>
</div>
{% if outlet.error %}
@ -200,265 +234,93 @@ Tapo-Steckdosen-Steuerung | MYP Platform
{{ outlet.error }}
</div>
{% endif %}
<!-- Zusätzliche Aktionen für Administratoren -->
{% if current_user.has_permission('ADMIN') %}
<div class="mt-3 pt-3 border-t border-slate-200 dark:border-slate-600">
<div class="flex space-x-2">
<form method="POST" action="{{ url_for('tapo.test_connection_form') }}" class="flex-1">
<input type="hidden" name="ip" value="{{ ip }}">
<button type="submit"
class="w-full text-xs py-1 px-2 text-slate-600 hover:text-slate-800 dark:text-slate-400 dark:hover:text-slate-200 border border-slate-300 dark:border-slate-600 rounded transition-colors">
<i class="fas fa-network-wired mr-1"></i>Test
</button>
</form>
{% if not outlet.configured_in_db %}
<a href="{{ url_for('admin.add_printer') }}?preset_plug_ip={{ ip }}"
class="flex-1 text-xs py-1 px-2 text-center text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-200 border border-blue-300 dark:border-blue-600 rounded transition-colors">
<i class="fas fa-plus mr-1"></i>Setup
</a>
{% endif %}
</div>
</div>
{% endif %}
</div>
{% endfor %}
</div>
{% else %}
<div class="text-center py-12">
<div class="text-slate-400 dark:text-slate-500 mb-4">
<i class="fas fa-plug text-6xl"></i>
</div>
<h3 class="text-xl font-semibold text-slate-600 dark:text-slate-400 mb-2">
Keine Tapo-Steckdosen konfiguriert
</h3>
<p class="text-slate-500 dark:text-slate-400 mb-6">
Es wurden noch keine Drucker mit Tapo-Steckdosen eingerichtet.
</p>
{% if current_user.is_authenticated and current_user.has_permission('ADMIN') %}
<div class="flex justify-center space-x-4">
<button onclick="discoverOutlets()"
class="btn-primary">
<i class="fas fa-search mr-2"></i>
Steckdosen suchen
</button>
<a href="{{ url_for('admin.printers_overview') }}"
class="btn-secondary">
<i class="fas fa-plus mr-2"></i>
Drucker verwalten
</a>
</div>
{% endif %}
</div>
{% endif %}
</div>
</div>
<!-- Loading Overlay -->
<div id="loading-overlay" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden">
<div class="bg-white dark:bg-slate-800 p-6 rounded-lg shadow-lg">
<!-- Fallback: Zeige 6 Platzhalter-Arbeitsplätze -->
{% for i in range(1, 7) %}
<div class="outlet-card border border-red-300 bg-red-50 dark:bg-red-900/20 rounded-lg p-4">
<div class="flex items-center justify-between mb-4">
<div class="flex items-center space-x-3">
<i class="fas fa-spinner fa-spin text-blue-600 text-xl"></i>
<span class="text-slate-800 dark:text-white font-medium" id="loading-text">
Lädt...
<div class="status-indicator w-4 h-4 rounded-full bg-red-500"></div>
<div>
<h3 class="font-semibold text-slate-800 dark:text-white">
3D-Drucker {{ i }}
</h3>
<p class="text-sm text-slate-600 dark:text-slate-400">
192.168.1.20{{ i }}
</p>
</div>
</div>
<span class="bg-slate-100 text-slate-700 text-xs px-2 py-1 rounded-full dark:bg-slate-700 dark:text-slate-300">
#{{ i }}
</span>
</div>
<div class="mb-4">
<div class="flex items-center justify-between">
<span class="text-sm text-slate-600 dark:text-slate-400">Status:</span>
<span class="text-red-600 dark:text-red-400">
<i class="fas fa-exclamation-triangle mr-1"></i>NICHT KONFIGURIERT
</span>
</div>
<div class="flex items-center justify-between mt-2">
<span class="text-sm text-slate-600 dark:text-slate-400">Standort:</span>
<span class="text-sm font-medium text-slate-800 dark:text-white">
Arbeitsplatz {{ i }}
</span>
</div>
</div>
<div class="grid grid-cols-2 gap-3">
<button disabled class="w-full py-2 px-3 bg-slate-400 text-white rounded-lg opacity-50 cursor-not-allowed text-sm">
<i class="fas fa-power-off mr-1"></i>EIN
</button>
<button disabled class="w-full py-2 px-3 bg-slate-400 text-white rounded-lg opacity-50 cursor-not-allowed text-sm">
<i class="fas fa-power-off mr-1"></i>AUS
</button>
</div>
<div class="mt-3 p-2 bg-yellow-100 dark:bg-yellow-900/30 border border-yellow-300 dark:border-yellow-700 rounded text-sm text-yellow-700 dark:text-yellow-300">
<i class="fas fa-info-circle mr-1"></i>
Arbeitsplatz {{ i }} noch nicht eingerichtet
</div>
</div>
{% endfor %}
{% endif %}
</div>
</div>
</div>
<!-- Auto-Refresh nur falls explizit gewünscht (minimales JavaScript) -->
{% if request.args.get('auto_refresh') %}
<script>
// Globale Variablen
let outlets = {{ outlets | tojson }};
// Utility-Funktionen
function showLoading(text = 'Lädt...') {
document.getElementById('loading-text').textContent = text;
document.getElementById('loading-overlay').classList.remove('hidden');
}
function hideLoading() {
document.getElementById('loading-overlay').classList.add('hidden');
}
function updateOutletDisplay(ip, data) {
const card = document.querySelector(`[data-ip="${ip}"]`);
if (!card) return;
const statusIndicator = card.querySelector('.status-indicator');
const statusText = card.querySelector('.status-text');
const buttons = card.querySelectorAll('button[onclick*="controlOutlet"]');
// Status-Indikator aktualisieren
statusIndicator.className = `status-indicator w-4 h-4 rounded-full ${data.reachable ? 'bg-green-500' : 'bg-red-500'}`;
// Status-Text aktualisieren
if (data.reachable) {
let statusIcon, statusColor;
if (data.status === 'on') {
statusIcon = 'fas fa-power-off';
statusColor = 'text-green-600 dark:text-green-400';
statusText.innerHTML = `<span class="${statusColor}"><i class="${statusIcon} mr-1"></i>EIN</span>`;
} else if (data.status === 'off') {
statusIcon = 'fas fa-power-off';
statusColor = 'text-slate-600 dark:text-slate-400';
statusText.innerHTML = `<span class="${statusColor}"><i class="${statusIcon} mr-1"></i>AUS</span>`;
} else {
statusIcon = 'fas fa-question';
statusColor = 'text-yellow-600 dark:text-yellow-400';
statusText.innerHTML = `<span class="${statusColor}"><i class="${statusIcon} mr-1"></i>UNBEKANNT</span>`;
}
// Buttons aktivieren
buttons.forEach(btn => btn.disabled = false);
} else {
statusText.innerHTML = '<span class="text-red-600 dark:text-red-400"><i class="fas fa-exclamation-triangle mr-1"></i>OFFLINE</span>';
// Buttons deaktivieren
buttons.forEach(btn => btn.disabled = true);
}
// Kartenrand aktualisieren
card.className = card.className.replace(/border-\w+-300|bg-\w+-50|dark:bg-\w+-900\/20/g, '');
if (data.reachable) {
card.className += ' border-green-300 bg-green-50 dark:bg-green-900/20';
} else {
card.className += ' border-red-300 bg-red-50 dark:bg-red-900/20';
}
}
function updateStatistics() {
const totalCount = Object.keys(outlets).length;
const onlineCount = Object.values(outlets).filter(o => o.reachable).length;
const activeCount = Object.values(outlets).filter(o => o.status === 'on').length;
document.getElementById('total-count').textContent = totalCount;
document.getElementById('online-count').textContent = onlineCount;
document.getElementById('active-count').textContent = activeCount;
}
// API-Funktionen
async function controlOutlet(ip, action) {
try {
showLoading(`Steckdose wird ${action === 'on' ? 'eingeschaltet' : 'ausgeschaltet'}...`);
const response = await fetch('/tapo/control', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': '{{ csrf_token() }}'
},
body: JSON.stringify({ ip, action })
});
const data = await response.json();
if (data.success) {
showFlashMessage(data.message, 'success');
// Status in lokalen Daten aktualisieren
if (outlets[ip]) {
outlets[ip].status = action;
outlets[ip].reachable = true;
updateOutletDisplay(ip, outlets[ip]);
updateStatistics();
}
} else {
showFlashMessage(data.error, 'error');
}
} catch (error) {
showFlashMessage('Fehler bei der Steckdosen-Steuerung: ' + error.message, 'error');
} finally {
hideLoading();
}
}
async function refreshOutletStatus(ip) {
try {
const response = await fetch(`/tapo/status/${ip}`);
const data = await response.json();
if (data.success) {
if (outlets[ip]) {
outlets[ip].status = data.status;
outlets[ip].reachable = data.reachable;
updateOutletDisplay(ip, outlets[ip]);
updateStatistics();
}
} else {
showFlashMessage(`Fehler beim Status-Check für ${ip}: ${data.error}`, 'error');
}
} catch (error) {
showFlashMessage('Fehler beim Status-Check: ' + error.message, 'error');
}
}
async function refreshAllStatus() {
showLoading('Status aller Steckdosen wird aktualisiert...');
try {
const response = await fetch('/tapo/all-status');
const data = await response.json();
if (data.success) {
// Lokale Daten aktualisieren
for (const [ip, status] of Object.entries(data.outlets)) {
if (outlets[ip]) {
outlets[ip].status = status.status;
outlets[ip].reachable = status.reachable;
updateOutletDisplay(ip, outlets[ip]);
}
}
updateStatistics();
showFlashMessage('Status aller Steckdosen aktualisiert', 'success');
} else {
showFlashMessage('Fehler beim Aktualisieren: ' + data.error, 'error');
}
} catch (error) {
showFlashMessage('Fehler beim Status-Update: ' + error.message, 'error');
} finally {
hideLoading();
}
}
async function testConnection(ip) {
try {
showLoading(`Verbindung zu ${ip} wird getestet...`);
const response = await fetch(`/tapo/test/${ip}`, { method: 'POST' });
const data = await response.json();
if (data.success) {
const testResult = data.test_result;
if (testResult.success) {
showFlashMessage(`✅ Verbindung zu ${ip} erfolgreich!`, 'success');
} else {
showFlashMessage(`❌ Verbindung zu ${ip} fehlgeschlagen: ${testResult.error}`, 'error');
}
} else {
showFlashMessage(`Verbindungstest fehlgeschlagen: ${data.error}`, 'error');
}
} catch (error) {
showFlashMessage('Fehler beim Verbindungstest: ' + error.message, 'error');
} finally {
hideLoading();
}
}
async function discoverOutlets() {
try {
showLoading('Suche nach neuen Tapo-Steckdosen...');
const response = await fetch('/tapo/discover', { method: 'POST' });
const data = await response.json();
if (data.success) {
showFlashMessage(data.message, 'success');
// Seite neu laden wenn neue Steckdosen gefunden wurden
if (data.discovered_count > 0) {
setTimeout(() => {
// Minimales Auto-Refresh alle 30 Sekunden
setTimeout(function() {
window.location.reload();
}, 2000);
}
} else {
showFlashMessage('Fehler bei der Erkennung: ' + data.error, 'error');
}
} catch (error) {
showFlashMessage('Fehler bei der Steckdosen-Suche: ' + error.message, 'error');
} finally {
hideLoading();
}
}
// Auto-Refresh alle 30 Sekunden
setInterval(() => {
if (Object.keys(outlets).length > 0) {
refreshAllStatus();
}
}, 30000);
// Initial statistics update
document.addEventListener('DOMContentLoaded', function() {
updateStatistics();
});
</script>
{% endif %}
{% endblock %}

View File

@ -0,0 +1 @@