"feat: Update database schema in myp.db-wal
This commit is contained in:
Binary file not shown.
@@ -1,401 +0,0 @@
|
|||||||
/**
|
|
||||||
* 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 = `
|
|
||||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;">
|
|
||||||
<strong>🔍 UI Debug Panel</strong>
|
|
||||||
<button onclick="this.parentElement.parentElement.style.display='none'" style="background: red; color: white; border: none; padding: 2px 6px; border-radius: 3px; cursor: pointer;">×</button>
|
|
||||||
</div>
|
|
||||||
<div id="debug-content">
|
|
||||||
<div>✅ Debug-Tool aktiv</div>
|
|
||||||
<div>👆 Klicks werden verfolgt</div>
|
|
||||||
<div>🔧 Auto-Fix aktiviert</div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
|
|
||||||
document.body.appendChild(panel);
|
|
||||||
|
|
||||||
// Toggle-Button für Debug-Panel
|
|
||||||
const toggleButton = document.createElement('button');
|
|
||||||
toggleButton.textContent = '🔍';
|
|
||||||
toggleButton.style.cssText = `
|
|
||||||
position: fixed;
|
|
||||||
bottom: 20px;
|
|
||||||
right: 20px;
|
|
||||||
width: 50px;
|
|
||||||
height: 50px;
|
|
||||||
border-radius: 50%;
|
|
||||||
background: #007bff;
|
|
||||||
color: white;
|
|
||||||
border: none;
|
|
||||||
font-size: 20px;
|
|
||||||
cursor: pointer;
|
|
||||||
z-index: 10001;
|
|
||||||
box-shadow: 0 2px 10px rgba(0,0,0,0.3);
|
|
||||||
`;
|
|
||||||
|
|
||||||
toggleButton.addEventListener('click', function() {
|
|
||||||
const panel = document.getElementById('debug-panel');
|
|
||||||
panel.style.display = panel.style.display === 'none' ? 'block' : 'none';
|
|
||||||
});
|
|
||||||
|
|
||||||
document.body.appendChild(toggleButton);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hilfsfunktionen
|
|
||||||
*/
|
|
||||||
function isElementClickable(element) {
|
|
||||||
const style = window.getComputedStyle(element);
|
|
||||||
return style.pointerEvents !== 'none' &&
|
|
||||||
style.display !== 'none' &&
|
|
||||||
style.visibility !== 'hidden' &&
|
|
||||||
!element.disabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
function hasEventListeners(element) {
|
|
||||||
// Vereinfachte Prüfung - in der Realität schwer zu detektieren
|
|
||||||
return element.onclick !== null ||
|
|
||||||
element.getAttribute('onclick') !== null ||
|
|
||||||
element.hasAttribute('data-action');
|
|
||||||
}
|
|
||||||
|
|
||||||
function isInternalLink(href) {
|
|
||||||
if (!href) return false;
|
|
||||||
return href.startsWith('/') ||
|
|
||||||
href.startsWith('./') ||
|
|
||||||
href.startsWith('../') ||
|
|
||||||
href.includes(window.location.hostname);
|
|
||||||
}
|
|
||||||
|
|
||||||
function makeElementClickable(element) {
|
|
||||||
if (!isElementClickable(element)) {
|
|
||||||
element.style.cursor = 'pointer';
|
|
||||||
element.style.pointerEvents = 'auto';
|
|
||||||
|
|
||||||
if (!hasEventListeners(element)) {
|
|
||||||
element.addEventListener('click', function(e) {
|
|
||||||
console.log('🔧 Auto-Fix Klick auf:', this);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function showClickFeedback(element) {
|
|
||||||
const feedback = document.createElement('div');
|
|
||||||
feedback.style.cssText = `
|
|
||||||
position: absolute;
|
|
||||||
background: rgba(0, 255, 0, 0.3);
|
|
||||||
border: 2px solid #00ff00;
|
|
||||||
pointer-events: none;
|
|
||||||
z-index: 9999;
|
|
||||||
border-radius: 3px;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const rect = element.getBoundingClientRect();
|
|
||||||
feedback.style.left = rect.left + 'px';
|
|
||||||
feedback.style.top = rect.top + 'px';
|
|
||||||
feedback.style.width = rect.width + 'px';
|
|
||||||
feedback.style.height = rect.height + 'px';
|
|
||||||
|
|
||||||
document.body.appendChild(feedback);
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
feedback.remove();
|
|
||||||
}, 500);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialisierung
|
|
||||||
*/
|
|
||||||
if (document.readyState === 'loading') {
|
|
||||||
document.addEventListener('DOMContentLoaded', initDebugTool);
|
|
||||||
} else {
|
|
||||||
initDebugTool();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Globale Debug-Funktionen
|
|
||||||
window.DEBUG_UI = {
|
|
||||||
diagnose: diagnoseElements,
|
|
||||||
fix: setupAutoFix,
|
|
||||||
toggle: function() {
|
|
||||||
const panel = document.getElementById('debug-panel');
|
|
||||||
if (panel) {
|
|
||||||
panel.style.display = panel.style.display === 'none' ? 'block' : 'none';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
console.log('✅ UI-Debug-Tool geladen');
|
|
||||||
|
|
||||||
})();
|
|
@@ -1,573 +0,0 @@
|
|||||||
/**
|
|
||||||
* MYP Platform - UI Issues Fix
|
|
||||||
* Behebt alle Klickbarkeits- und Interaktivitätsprobleme
|
|
||||||
* Version: 1.0.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
(function() {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
console.log('🔧 UI-Fix wird geladen...');
|
|
||||||
|
|
||||||
// Globale Variablen für bessere Kompatibilität
|
|
||||||
window.MYP_UI_FIXED = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hauptinitialisierung
|
|
||||||
*/
|
|
||||||
function initializeUIFixes() {
|
|
||||||
if (window.MYP_UI_FIXED) {
|
|
||||||
console.log('✅ UI bereits gefixt');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('🚀 Starte UI-Fixes...');
|
|
||||||
|
|
||||||
// 1. Event-Delegation für alle Klicks
|
|
||||||
setupGlobalClickHandlers();
|
|
||||||
|
|
||||||
// 2. Navigation-Fixes
|
|
||||||
fixNavigationClicks();
|
|
||||||
|
|
||||||
// 3. Button-Fixes
|
|
||||||
fixButtonClicks();
|
|
||||||
|
|
||||||
// 4. Form-Fixes
|
|
||||||
fixFormSubmissions();
|
|
||||||
|
|
||||||
// 5. Modal-Fixes
|
|
||||||
fixModalInteractions();
|
|
||||||
|
|
||||||
// 6. Dark Mode Fix
|
|
||||||
fixDarkModeToggle();
|
|
||||||
|
|
||||||
// 7. Mobile Menu Fix
|
|
||||||
fixMobileMenu();
|
|
||||||
|
|
||||||
// 8. Dropdown-Fixes
|
|
||||||
fixDropdowns();
|
|
||||||
|
|
||||||
// 9. CSRF-Token-Fixes
|
|
||||||
fixCSRFTokens();
|
|
||||||
|
|
||||||
// 10. Auto-Refresh-Fixes
|
|
||||||
setupAutoRefresh();
|
|
||||||
|
|
||||||
window.MYP_UI_FIXED = true;
|
|
||||||
console.log('✅ Alle UI-Fixes erfolgreich angewendet!');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 1. Globale Click-Handler mit Event-Delegation
|
|
||||||
*/
|
|
||||||
function setupGlobalClickHandlers() {
|
|
||||||
console.log('🎯 Richte globale Click-Handler ein...');
|
|
||||||
|
|
||||||
// Entferne alte Event-Listener
|
|
||||||
document.removeEventListener('click', handleGlobalClick);
|
|
||||||
|
|
||||||
// Füge neuen Event-Listener hinzu
|
|
||||||
document.addEventListener('click', handleGlobalClick, true);
|
|
||||||
|
|
||||||
function handleGlobalClick(event) {
|
|
||||||
const target = event.target;
|
|
||||||
const closest = target.closest('a, button, [role="button"], [data-action], .clickable');
|
|
||||||
|
|
||||||
if (!closest) return;
|
|
||||||
|
|
||||||
// Verhindere doppelte Events
|
|
||||||
if (event.defaultPrevented) return;
|
|
||||||
|
|
||||||
console.log('👆 Klick erkannt auf:', closest);
|
|
||||||
|
|
||||||
// Spezielle Handler für verschiedene Elemente
|
|
||||||
if (closest.matches('a[href]')) {
|
|
||||||
handleLinkClick(event, closest);
|
|
||||||
} else if (closest.matches('button, [role="button"]')) {
|
|
||||||
handleButtonClick(event, closest);
|
|
||||||
} else if (closest.hasAttribute('data-action')) {
|
|
||||||
handleDataActionClick(event, closest);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Link-Klicks behandeln
|
|
||||||
*/
|
|
||||||
function handleLinkClick(event, link) {
|
|
||||||
const href = link.getAttribute('href');
|
|
||||||
|
|
||||||
if (!href || href === '#') {
|
|
||||||
event.preventDefault();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Externe Links in neuem Tab öffnen
|
|
||||||
if (href.startsWith('http') && !href.includes(window.location.hostname)) {
|
|
||||||
event.preventDefault();
|
|
||||||
window.open(href, '_blank', 'noopener,noreferrer');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Interne Navigation
|
|
||||||
if (href.startsWith('/') || href.startsWith('./') || href.startsWith('../')) {
|
|
||||||
console.log('🔗 Navigiere zu:', href);
|
|
||||||
// Lass den Browser die Navigation normal handhaben
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Button-Klicks behandeln
|
|
||||||
*/
|
|
||||||
function handleButtonClick(event, button) {
|
|
||||||
// Verhindere doppelte Klicks
|
|
||||||
if (button.disabled || button.classList.contains('loading')) {
|
|
||||||
event.preventDefault();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Spezielle Button-Typen
|
|
||||||
const buttonType = button.getAttribute('data-type') || button.type;
|
|
||||||
|
|
||||||
switch (buttonType) {
|
|
||||||
case 'logout':
|
|
||||||
event.preventDefault();
|
|
||||||
handleLogoutClick();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'dark-mode-toggle':
|
|
||||||
event.preventDefault();
|
|
||||||
handleDarkModeToggle();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'mobile-menu-toggle':
|
|
||||||
event.preventDefault();
|
|
||||||
handleMobileMenuToggle();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'refresh':
|
|
||||||
event.preventDefault();
|
|
||||||
handleRefreshClick(button);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
// Normale Button-Behandlung
|
|
||||||
console.log('🔘 Button geklickt:', button);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Data-Action-Klicks behandeln
|
|
||||||
*/
|
|
||||||
function handleDataActionClick(event, element) {
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
const action = element.getAttribute('data-action');
|
|
||||||
const params = getDataActionParams(element);
|
|
||||||
|
|
||||||
console.log('⚡ Data-Action ausgeführt:', action, params);
|
|
||||||
|
|
||||||
switch (action) {
|
|
||||||
case 'logout':
|
|
||||||
handleLogoutClick();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'toggle-dark-mode':
|
|
||||||
handleDarkModeToggle();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'toggle-mobile-menu':
|
|
||||||
handleMobileMenuToggle();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'refresh-page':
|
|
||||||
window.location.reload();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'go-back':
|
|
||||||
window.history.back();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'close-modal':
|
|
||||||
closeModal(params.target);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
console.warn('⚠️ Unbekannte Data-Action:', action);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Data-Action-Parameter extrahieren
|
|
||||||
*/
|
|
||||||
function getDataActionParams(element) {
|
|
||||||
const params = {};
|
|
||||||
|
|
||||||
for (const attr of element.attributes) {
|
|
||||||
if (attr.name.startsWith('data-action-')) {
|
|
||||||
const key = attr.name.replace('data-action-', '');
|
|
||||||
params[key] = attr.value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return params;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 2. Navigation-Fixes
|
|
||||||
*/
|
|
||||||
function fixNavigationClicks() {
|
|
||||||
console.log('🧭 Fixe Navigation...');
|
|
||||||
|
|
||||||
// Alle Navigations-Links finden und reparieren
|
|
||||||
const navLinks = document.querySelectorAll('nav a, .navbar a, .nav-item');
|
|
||||||
|
|
||||||
navLinks.forEach(link => {
|
|
||||||
if (!link.href || link.href === '#') {
|
|
||||||
link.style.cursor = 'pointer';
|
|
||||||
link.addEventListener('click', function(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
console.log('🔗 Navigation-Link geklickt:', this);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 3. Button-Fixes
|
|
||||||
*/
|
|
||||||
function fixButtonClicks() {
|
|
||||||
console.log('🔘 Fixe Buttons...');
|
|
||||||
|
|
||||||
// Alle Buttons finden und Event-Listener hinzufügen
|
|
||||||
const buttons = document.querySelectorAll('button, [role="button"], .btn');
|
|
||||||
|
|
||||||
buttons.forEach(button => {
|
|
||||||
// Entferne alte Event-Listener
|
|
||||||
button.removeEventListener('click', handleButtonClickFix);
|
|
||||||
|
|
||||||
// Füge neuen Event-Listener hinzu
|
|
||||||
button.addEventListener('click', handleButtonClickFix);
|
|
||||||
});
|
|
||||||
|
|
||||||
function handleButtonClickFix(event) {
|
|
||||||
console.log('🔘 Button-Fix aktiviert für:', this);
|
|
||||||
|
|
||||||
// Verhindere doppelte Klicks
|
|
||||||
if (this.disabled) {
|
|
||||||
event.preventDefault();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Visuelles Feedback
|
|
||||||
this.style.transform = 'scale(0.95)';
|
|
||||||
setTimeout(() => {
|
|
||||||
this.style.transform = '';
|
|
||||||
}, 150);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 4. Form-Fixes
|
|
||||||
*/
|
|
||||||
function fixFormSubmissions() {
|
|
||||||
console.log('📝 Fixe Formulare...');
|
|
||||||
|
|
||||||
const forms = document.querySelectorAll('form');
|
|
||||||
|
|
||||||
forms.forEach(form => {
|
|
||||||
form.addEventListener('submit', function(event) {
|
|
||||||
console.log('📤 Formular wird abgesendet:', this);
|
|
||||||
|
|
||||||
// CSRF-Token prüfen
|
|
||||||
const csrfToken = this.querySelector('input[name="csrf_token"]');
|
|
||||||
if (!csrfToken) {
|
|
||||||
console.warn('⚠️ CSRF-Token fehlt in Formular');
|
|
||||||
addCSRFTokenToForm(this);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 5. Modal-Fixes
|
|
||||||
*/
|
|
||||||
function fixModalInteractions() {
|
|
||||||
console.log('🪟 Fixe Modals...');
|
|
||||||
|
|
||||||
// Modal-Close-Buttons
|
|
||||||
const closeButtons = document.querySelectorAll('[data-modal-close], .modal-close');
|
|
||||||
|
|
||||||
closeButtons.forEach(button => {
|
|
||||||
button.addEventListener('click', function(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
const modal = this.closest('.modal, .fixed');
|
|
||||||
if (modal) {
|
|
||||||
closeModal(modal);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Modal-Backdrop-Klicks
|
|
||||||
const modals = document.querySelectorAll('.modal, .fixed');
|
|
||||||
|
|
||||||
modals.forEach(modal => {
|
|
||||||
modal.addEventListener('click', function(event) {
|
|
||||||
if (event.target === this) {
|
|
||||||
closeModal(this);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 6. Dark Mode Fix
|
|
||||||
*/
|
|
||||||
function fixDarkModeToggle() {
|
|
||||||
console.log('🌙 Fixe Dark Mode...');
|
|
||||||
|
|
||||||
const darkModeToggle = document.getElementById('darkModeToggle') ||
|
|
||||||
document.querySelector('[data-action="toggle-dark-mode"]');
|
|
||||||
|
|
||||||
if (darkModeToggle) {
|
|
||||||
darkModeToggle.addEventListener('click', handleDarkModeToggle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleDarkModeToggle() {
|
|
||||||
console.log('🌙 Dark Mode Toggle aktiviert');
|
|
||||||
|
|
||||||
const html = document.documentElement;
|
|
||||||
const isDark = html.classList.contains('dark');
|
|
||||||
|
|
||||||
if (isDark) {
|
|
||||||
html.classList.remove('dark');
|
|
||||||
localStorage.setItem('myp-dark-mode', 'false');
|
|
||||||
} else {
|
|
||||||
html.classList.add('dark');
|
|
||||||
localStorage.setItem('myp-dark-mode', 'true');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Icons aktualisieren
|
|
||||||
updateDarkModeIcons(!isDark);
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateDarkModeIcons(isDark) {
|
|
||||||
const sunIcons = document.querySelectorAll('.sun-icon');
|
|
||||||
const moonIcons = document.querySelectorAll('.moon-icon');
|
|
||||||
|
|
||||||
sunIcons.forEach(icon => {
|
|
||||||
icon.classList.toggle('hidden', isDark);
|
|
||||||
});
|
|
||||||
|
|
||||||
moonIcons.forEach(icon => {
|
|
||||||
icon.classList.toggle('hidden', !isDark);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 7. Mobile Menu Fix
|
|
||||||
*/
|
|
||||||
function fixMobileMenu() {
|
|
||||||
console.log('📱 Fixe Mobile Menu...');
|
|
||||||
|
|
||||||
const mobileMenuToggle = document.getElementById('mobileMenuToggle') ||
|
|
||||||
document.querySelector('[data-action="toggle-mobile-menu"]');
|
|
||||||
const mobileMenu = document.getElementById('mobileMenu');
|
|
||||||
|
|
||||||
if (mobileMenuToggle && mobileMenu) {
|
|
||||||
mobileMenuToggle.addEventListener('click', handleMobileMenuToggle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleMobileMenuToggle() {
|
|
||||||
console.log('📱 Mobile Menu Toggle aktiviert');
|
|
||||||
|
|
||||||
const mobileMenu = document.getElementById('mobileMenu');
|
|
||||||
if (mobileMenu) {
|
|
||||||
mobileMenu.classList.toggle('hidden');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 8. Dropdown-Fixes
|
|
||||||
*/
|
|
||||||
function fixDropdowns() {
|
|
||||||
console.log('📋 Fixe Dropdowns...');
|
|
||||||
|
|
||||||
const dropdownToggles = document.querySelectorAll('[data-dropdown-toggle]');
|
|
||||||
|
|
||||||
dropdownToggles.forEach(toggle => {
|
|
||||||
toggle.addEventListener('click', function(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
const targetId = this.getAttribute('data-dropdown-toggle');
|
|
||||||
const dropdown = document.getElementById(targetId);
|
|
||||||
|
|
||||||
if (dropdown) {
|
|
||||||
dropdown.classList.toggle('hidden');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Schließe Dropdowns bei Klick außerhalb
|
|
||||||
document.addEventListener('click', function(event) {
|
|
||||||
const dropdowns = document.querySelectorAll('[data-dropdown-menu]');
|
|
||||||
|
|
||||||
dropdowns.forEach(dropdown => {
|
|
||||||
if (!dropdown.contains(event.target) &&
|
|
||||||
!event.target.matches('[data-dropdown-toggle]')) {
|
|
||||||
dropdown.classList.add('hidden');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 9. CSRF-Token-Fixes
|
|
||||||
*/
|
|
||||||
function fixCSRFTokens() {
|
|
||||||
console.log('🔒 Fixe CSRF-Tokens...');
|
|
||||||
|
|
||||||
const csrfToken = document.querySelector('meta[name="csrf-token"]');
|
|
||||||
if (!csrfToken) {
|
|
||||||
console.warn('⚠️ CSRF-Token Meta-Tag fehlt');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const tokenValue = csrfToken.getAttribute('content');
|
|
||||||
|
|
||||||
// Füge CSRF-Token zu allen Formularen hinzu
|
|
||||||
const forms = document.querySelectorAll('form');
|
|
||||||
forms.forEach(form => {
|
|
||||||
if (!form.querySelector('input[name="csrf_token"]')) {
|
|
||||||
addCSRFTokenToForm(form, tokenValue);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function addCSRFTokenToForm(form, tokenValue = null) {
|
|
||||||
if (!tokenValue) {
|
|
||||||
const csrfMeta = document.querySelector('meta[name="csrf-token"]');
|
|
||||||
tokenValue = csrfMeta ? csrfMeta.getAttribute('content') : '';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tokenValue) {
|
|
||||||
const input = document.createElement('input');
|
|
||||||
input.type = 'hidden';
|
|
||||||
input.name = 'csrf_token';
|
|
||||||
input.value = tokenValue;
|
|
||||||
form.appendChild(input);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 10. Auto-Refresh-Setup
|
|
||||||
*/
|
|
||||||
function setupAutoRefresh() {
|
|
||||||
console.log('🔄 Richte Auto-Refresh ein...');
|
|
||||||
|
|
||||||
// Auto-Refresh für bestimmte Seiten
|
|
||||||
const refreshInterval = 30000; // 30 Sekunden
|
|
||||||
|
|
||||||
if (window.location.pathname.includes('/dashboard') ||
|
|
||||||
window.location.pathname.includes('/printers') ||
|
|
||||||
window.location.pathname.includes('/jobs')) {
|
|
||||||
|
|
||||||
setInterval(() => {
|
|
||||||
refreshPageData();
|
|
||||||
}, refreshInterval);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function refreshPageData() {
|
|
||||||
// Implementierung für spezifische Seiten-Refreshs
|
|
||||||
console.log('🔄 Aktualisiere Seitendaten...');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Logout-Handler
|
|
||||||
*/
|
|
||||||
function handleLogoutClick() {
|
|
||||||
console.log('👋 Logout-Prozess gestartet');
|
|
||||||
|
|
||||||
if (confirm('Möchten Sie sich wirklich abmelden?')) {
|
|
||||||
// CSRF-Token holen
|
|
||||||
const csrfToken = document.querySelector('meta[name="csrf-token"]');
|
|
||||||
|
|
||||||
// Logout-Form erstellen
|
|
||||||
const form = document.createElement('form');
|
|
||||||
form.method = 'POST';
|
|
||||||
form.action = '/auth/logout';
|
|
||||||
form.style.display = 'none';
|
|
||||||
|
|
||||||
if (csrfToken) {
|
|
||||||
const input = document.createElement('input');
|
|
||||||
input.type = 'hidden';
|
|
||||||
input.name = 'csrf_token';
|
|
||||||
input.value = csrfToken.getAttribute('content');
|
|
||||||
form.appendChild(input);
|
|
||||||
}
|
|
||||||
|
|
||||||
document.body.appendChild(form);
|
|
||||||
form.submit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Refresh-Handler
|
|
||||||
*/
|
|
||||||
function handleRefreshClick(button) {
|
|
||||||
console.log('🔄 Refresh-Button geklickt');
|
|
||||||
|
|
||||||
// Button-State ändern
|
|
||||||
const originalText = button.textContent;
|
|
||||||
button.textContent = 'Wird aktualisiert...';
|
|
||||||
button.disabled = true;
|
|
||||||
|
|
||||||
// Seite neu laden
|
|
||||||
setTimeout(() => {
|
|
||||||
window.location.reload();
|
|
||||||
}, 500);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Modal schließen
|
|
||||||
*/
|
|
||||||
function closeModal(modal) {
|
|
||||||
if (typeof modal === 'string') {
|
|
||||||
modal = document.getElementById(modal) || document.querySelector(modal);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (modal) {
|
|
||||||
modal.classList.add('hidden');
|
|
||||||
modal.style.display = 'none';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialisierung bei DOM-Ready
|
|
||||||
*/
|
|
||||||
if (document.readyState === 'loading') {
|
|
||||||
document.addEventListener('DOMContentLoaded', initializeUIFixes);
|
|
||||||
} else {
|
|
||||||
initializeUIFixes();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Backup-Initialisierung nach 1 Sekunde
|
|
||||||
setTimeout(initializeUIFixes, 1000);
|
|
||||||
|
|
||||||
// Globale Funktionen für Kompatibilität
|
|
||||||
window.MYP_UI_FIXES = {
|
|
||||||
init: initializeUIFixes,
|
|
||||||
handleLogout: handleLogoutClick,
|
|
||||||
handleDarkMode: handleDarkModeToggle,
|
|
||||||
handleMobileMenu: handleMobileMenuToggle,
|
|
||||||
closeModal: closeModal
|
|
||||||
};
|
|
||||||
|
|
||||||
console.log('✅ UI-Fix-Script geladen');
|
|
||||||
|
|
||||||
})();
|
|
@@ -576,8 +576,6 @@
|
|||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<!-- JavaScript -->
|
<!-- JavaScript -->
|
||||||
<script src="{{ url_for('static', filename='js/fix-ui-issues.js') }}"></script>
|
|
||||||
<script src="{{ url_for('static', filename='js/debug-ui.js') }}"></script>
|
|
||||||
<script src="{{ url_for('static', filename='js/ui-components.js') }}"></script>
|
<script src="{{ url_for('static', filename='js/ui-components.js') }}"></script>
|
||||||
<script src="{{ url_for('static', filename='js/dark-mode-fix.js') }}"></script>
|
<script src="{{ url_for('static', filename='js/dark-mode-fix.js') }}"></script>
|
||||||
<script src="{{ url_for('static', filename='js/optimization-features.js') }}"></script>
|
<script src="{{ url_for('static', filename='js/optimization-features.js') }}"></script>
|
||||||
|
Reference in New Issue
Block a user