diff --git a/backend/app/app.py b/backend/app/app.py index 1ed7529a..493dc9a1 100644 --- a/backend/app/app.py +++ b/backend/app/app.py @@ -865,7 +865,7 @@ def user_update_settings(): contrast = "normal" # Benutzer aus der Datenbank laden - user = db_session.query(User).filter(User.id == current_user.id).first() + user = db_session.query(User).filter(User.id == int(current_user.id)).first() if not user: error = "Benutzer nicht gefunden." @@ -1016,7 +1016,7 @@ def user_change_password(): return redirect(url_for("user_profile")) db_session = get_db_session() - user = db_session.query(User).filter(User.id == current_user.id).first() + user = db_session.query(User).filter(User.id == int(current_user.id)).first() if user and user.check_password(current_password): # Passwort aktualisieren @@ -1059,7 +1059,7 @@ def user_export_data(): """Exportiert alle Benutzerdaten als JSON für DSGVO-Konformität""" try: db_session = get_db_session() - user = db_session.query(User).filter(User.id == current_user.id).first() + user = db_session.query(User).filter(User.id == int(current_user.id)).first() if not user: db_session.close() @@ -1109,7 +1109,7 @@ def user_update_profile_api(): data = request.get_json() db_session = get_db_session() - user = db_session.query(User).filter(User.id == current_user.id).first() + user = db_session.query(User).filter(User.id == int(current_user.id)).first() if not user: db_session.close() @@ -2430,7 +2430,7 @@ def get_current_job(): db_session = get_db_session() try: current_job = db_session.query(Job).filter( - Job.user_id == current_user.id, + Job.user_id == int(current_user.id), Job.status.in_(["scheduled", "running"]) ).order_by(Job.start_at).first() @@ -2741,9 +2741,9 @@ def get_stats(): # Benutzer-spezifische Statistiken (falls nicht Admin) user_stats = {} if not current_user.is_admin: - user_jobs = db_session.query(Job).filter(Job.user_id == current_user.id).count() + user_jobs = db_session.query(Job).filter(Job.user_id == int(current_user.id)).count() user_completed = db_session.query(Job).filter( - Job.user_id == current_user.id, + Job.user_id == int(current_user.id), Job.status == "completed" ).count() user_stats = { @@ -5039,7 +5039,7 @@ def perform_batch_operation(): else: jobs = db_session.query(Job).filter( Job.id.in_(job_ids), - Job.user_id == current_user.id + Job.user_id == int(current_user.id) ).all() if not jobs: @@ -6148,4 +6148,4 @@ if __name__ == "__main__": stop_queue_manager() except: pass - sys.exit(1) \ No newline at end of file + sys.exit(1) diff --git a/backend/app/database/myp.db-shm b/backend/app/database/myp.db-shm index 0ec1c0b3..977efdfd 100644 Binary files a/backend/app/database/myp.db-shm and b/backend/app/database/myp.db-shm differ diff --git a/backend/app/database/myp.db-wal b/backend/app/database/myp.db-wal index 465d21d7..284336af 100644 Binary files a/backend/app/database/myp.db-wal and b/backend/app/database/myp.db-wal differ diff --git a/backend/app/static/js/debug-ui.js b/backend/app/static/js/debug-ui.js index 0519ecba..4f5a96ff 100644 --- a/backend/app/static/js/debug-ui.js +++ b/backend/app/static/js/debug-ui.js @@ -1 +1,401 @@ - \ No newline at end of file +/** + * MYP Platform - UI Debug & Diagnostic Tool + * Diagnostiziert und behebt UI-Probleme in Echtzeit + */ + +(function() { + 'use strict'; + + console.log('🔍 UI-Debug-Tool wird geladen...'); + + // Debug-Konfiguration + const DEBUG_CONFIG = { + logClicks: true, + logErrors: true, + logNavigation: true, + showVisualFeedback: true, + autoFix: true + }; + + /** + * Hauptinitialisierung des Debug-Tools + */ + function initDebugTool() { + console.log('🚀 UI-Debug-Tool gestartet'); + + // 1. Click-Tracking + setupClickTracking(); + + // 2. Error-Tracking + setupErrorTracking(); + + // 3. Navigation-Tracking + setupNavigationTracking(); + + // 4. Element-Diagnostik + diagnoseElements(); + + // 5. Auto-Fix aktivieren + if (DEBUG_CONFIG.autoFix) { + setupAutoFix(); + } + + // 6. Debug-Panel erstellen + createDebugPanel(); + + console.log('✅ UI-Debug-Tool vollständig initialisiert'); + } + + /** + * Click-Tracking einrichten + */ + function setupClickTracking() { + if (!DEBUG_CONFIG.logClicks) return; + + document.addEventListener('click', function(event) { + const target = event.target; + const info = { + element: target.tagName, + id: target.id || 'keine ID', + classes: target.className || 'keine Klassen', + href: target.href || 'kein href', + type: target.type || 'kein type', + dataAction: target.getAttribute('data-action') || 'keine data-action', + clickable: isElementClickable(target), + hasEventListeners: hasEventListeners(target) + }; + + console.log('👆 KLICK ERKANNT:', info); + + // Visuelles Feedback + if (DEBUG_CONFIG.showVisualFeedback) { + showClickFeedback(target); + } + + // Auto-Fix für nicht-klickbare Elemente + if (!info.clickable && DEBUG_CONFIG.autoFix) { + makeElementClickable(target); + } + }, true); + } + + /** + * Error-Tracking einrichten + */ + function setupErrorTracking() { + if (!DEBUG_CONFIG.logErrors) return; + + window.addEventListener('error', function(event) { + console.error('🚨 JAVASCRIPT-FEHLER:', { + message: event.message, + filename: event.filename, + lineno: event.lineno, + colno: event.colno, + error: event.error + }); + }); + + window.addEventListener('unhandledrejection', function(event) { + console.error('🚨 UNHANDLED PROMISE REJECTION:', event.reason); + }); + } + + /** + * Navigation-Tracking einrichten + */ + function setupNavigationTracking() { + if (!DEBUG_CONFIG.logNavigation) return; + + // Link-Klicks verfolgen + document.addEventListener('click', function(event) { + const link = event.target.closest('a'); + if (link) { + console.log('🔗 NAVIGATION:', { + href: link.href, + text: link.textContent.trim(), + target: link.target, + internal: isInternalLink(link.href) + }); + } + }); + } + + /** + * Element-Diagnostik durchführen + */ + function diagnoseElements() { + console.log('🔍 Starte Element-Diagnostik...'); + + // Alle potentiell klickbaren Elemente finden + const clickableSelectors = [ + 'a', 'button', '[role="button"]', '[data-action]', + '.btn', '.clickable', '.nav-item', '.menu-item' + ]; + + clickableSelectors.forEach(selector => { + const elements = document.querySelectorAll(selector); + console.log(`📊 ${selector}: ${elements.length} Elemente gefunden`); + + elements.forEach((element, index) => { + const diagnosis = diagnoseElement(element); + if (diagnosis.issues.length > 0) { + console.warn(`⚠️ ${selector}[${index}] hat Probleme:`, diagnosis); + } + }); + }); + } + + /** + * Einzelnes Element diagnostizieren + */ + function diagnoseElement(element) { + const issues = []; + const info = { + tag: element.tagName, + id: element.id, + classes: element.className, + href: element.href, + type: element.type, + disabled: element.disabled, + hidden: element.hidden || element.style.display === 'none', + hasEventListeners: hasEventListeners(element), + clickable: isElementClickable(element) + }; + + // Probleme identifizieren + if (element.tagName === 'A' && (!element.href || element.href === '#')) { + issues.push('Link ohne gültiges href-Attribut'); + } + + if (element.tagName === 'BUTTON' && element.disabled) { + issues.push('Button ist deaktiviert'); + } + + if (!info.hasEventListeners && !element.href && !element.onclick) { + issues.push('Keine Event-Listener oder onclick-Handler gefunden'); + } + + if (info.hidden) { + issues.push('Element ist versteckt'); + } + + return { info, issues }; + } + + /** + * Auto-Fix einrichten + */ + function setupAutoFix() { + console.log('🔧 Auto-Fix aktiviert'); + + // Alle problematischen Elemente finden und reparieren + const problematicElements = document.querySelectorAll('a[href="#"], button:disabled, [data-action]:not([onclick])'); + + problematicElements.forEach(element => { + fixElement(element); + }); + + // Mutation Observer für dynamisch hinzugefügte Elemente + const observer = new MutationObserver(function(mutations) { + mutations.forEach(function(mutation) { + mutation.addedNodes.forEach(function(node) { + if (node.nodeType === Node.ELEMENT_NODE) { + const problematic = node.querySelectorAll('a[href="#"], button:disabled, [data-action]:not([onclick])'); + problematic.forEach(fixElement); + } + }); + }); + }); + + observer.observe(document.body, { childList: true, subtree: true }); + } + + /** + * Element reparieren + */ + function fixElement(element) { + console.log('🔧 Repariere Element:', element); + + if (element.tagName === 'A' && (!element.href || element.href === '#')) { + // Link ohne href reparieren + element.style.cursor = 'pointer'; + element.addEventListener('click', function(e) { + e.preventDefault(); + console.log('🔗 Reparierter Link geklickt:', this); + }); + } + + if (element.tagName === 'BUTTON' && element.disabled) { + // Deaktivierten Button aktivieren (falls sicher) + if (!element.hasAttribute('data-keep-disabled')) { + element.disabled = false; + console.log('🔘 Button aktiviert:', element); + } + } + + if (element.hasAttribute('data-action') && !hasEventListeners(element)) { + // Data-Action-Element ohne Event-Listener reparieren + element.addEventListener('click', function(e) { + e.preventDefault(); + const action = this.getAttribute('data-action'); + console.log('⚡ Data-Action ausgeführt:', action); + + // Versuche globale Handler zu finden + if (window.MYP_UI_FIXES && window.MYP_UI_FIXES[action]) { + window.MYP_UI_FIXES[action](); + } + }); + } + } + + /** + * Debug-Panel erstellen + */ + function createDebugPanel() { + const panel = document.createElement('div'); + panel.id = 'debug-panel'; + panel.style.cssText = ` + position: fixed; + top: 10px; + right: 10px; + width: 300px; + background: rgba(0, 0, 0, 0.9); + color: white; + padding: 10px; + border-radius: 5px; + font-family: monospace; + font-size: 12px; + z-index: 10000; + max-height: 400px; + overflow-y: auto; + display: none; + `; + + panel.innerHTML = ` +