📝 🚀 "Refactor backend structure
This commit is contained in:
@ -969,36 +969,37 @@
|
||||
let icon = '';
|
||||
switch(type) {
|
||||
case 'success':
|
||||
icon = `<svg class="w-5 h-5 mr-3" fill="currentColor" viewBox="0 0 20 20">
|
||||
icon = `<svg class="w-5 h-5 mr-3 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/>
|
||||
</svg>`;
|
||||
break;
|
||||
case 'error':
|
||||
icon = `<svg class="w-5 h-5 mr-3" fill="currentColor" viewBox="0 0 20 20">
|
||||
icon = `<svg class="w-5 h-5 mr-3 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clip-rule="evenodd"/>
|
||||
</svg>`;
|
||||
break;
|
||||
case 'warning':
|
||||
icon = `<svg class="w-5 h-5 mr-3" fill="currentColor" viewBox="0 0 20 20">
|
||||
icon = `<svg class="w-5 h-5 mr-3 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd" d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z" clip-rule="evenodd"/>
|
||||
</svg>`;
|
||||
break;
|
||||
case 'info':
|
||||
default:
|
||||
icon = `<svg class="w-5 h-5 mr-3" fill="currentColor" viewBox="0 0 20 20">
|
||||
icon = `<svg class="w-5 h-5 mr-3 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z" clip-rule="evenodd"/>
|
||||
</svg>`;
|
||||
}
|
||||
|
||||
// Inhalt der Flash Message
|
||||
flashElement.innerHTML = `
|
||||
<div class="flex items-center">
|
||||
<div class="flex items-start">
|
||||
${icon}
|
||||
<div class="flex-1">
|
||||
<p class="font-medium text-sm">${message}</p>
|
||||
<div class="flex-1 min-w-0">
|
||||
<p class="font-medium text-sm leading-relaxed">${message}</p>
|
||||
</div>
|
||||
<button class="flash-close-btn ml-4 text-current opacity-70 hover:opacity-100 transition-opacity duration-200"
|
||||
onclick="closeFlashMessage('${messageId}')">
|
||||
<button class="flash-close-btn ml-4 flex-shrink-0 text-current opacity-70 hover:opacity-100 transition-opacity duration-200 focus:outline-none focus:opacity-100"
|
||||
onclick="closeFlashMessage('${messageId}')"
|
||||
aria-label="Nachricht schließen">
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
|
||||
</svg>
|
||||
@ -1012,6 +1013,12 @@
|
||||
// Flash Messages vertikal stapeln
|
||||
repositionFlashMessages();
|
||||
|
||||
// Einblende-Animation starten
|
||||
requestAnimationFrame(() => {
|
||||
flashElement.style.transform = 'translateX(0) translateY(0)';
|
||||
flashElement.style.opacity = '1';
|
||||
});
|
||||
|
||||
// Nach der angegebenen Zeit automatisch entfernen
|
||||
setTimeout(() => {
|
||||
closeFlashMessage(messageId);
|
||||
@ -1043,10 +1050,26 @@
|
||||
*/
|
||||
function repositionFlashMessages() {
|
||||
const flashMessages = document.querySelectorAll('.flash-message:not(.hiding)');
|
||||
const gap = 12; // Abstand zwischen Messages
|
||||
const startTop = 16; // Top-Offset
|
||||
|
||||
flashMessages.forEach((flash, index) => {
|
||||
flash.style.top = `${16 + (index * 80)}px`; // 16px base + 80px pro Message
|
||||
const yPosition = startTop + (index * (80 + gap)); // 80px Höhe + gap
|
||||
|
||||
// Position setzen
|
||||
flash.style.position = 'fixed';
|
||||
flash.style.top = `${yPosition}px`;
|
||||
flash.style.right = '16px';
|
||||
flash.style.zIndex = 50 - index; // Neueste Messages haben höheren z-index
|
||||
flash.style.zIndex = 50 + (flashMessages.length - index); // Neueste Messages haben höheren z-index
|
||||
flash.style.width = 'auto';
|
||||
flash.style.maxWidth = '420px';
|
||||
flash.style.minWidth = '320px';
|
||||
|
||||
// Initiale Position für Animation (nur bei neuen Messages)
|
||||
if (!flash.style.transform) {
|
||||
flash.style.transform = 'translateX(100%) translateY(-20px)';
|
||||
flash.style.opacity = '0';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -1485,6 +1508,11 @@
|
||||
* Einstellungs-Modal anzeigen
|
||||
*/
|
||||
showSettings() {
|
||||
// Prüfen ob Modal bereits offen ist
|
||||
if (document.querySelector('.dnd-modal')) {
|
||||
return; // Modal bereits offen, nicht doppelt öffnen
|
||||
}
|
||||
|
||||
const modal = document.createElement('div');
|
||||
modal.className = 'dnd-modal';
|
||||
modal.innerHTML = `
|
||||
@ -1493,7 +1521,8 @@
|
||||
<h3 class="text-lg font-semibold text-slate-900 dark:text-white">
|
||||
🔕 Nicht stören
|
||||
</h3>
|
||||
<button class="dnd-close-btn text-slate-500 hover:text-slate-700 dark:text-slate-400 dark:hover:text-slate-200">
|
||||
<button class="dnd-close-btn text-slate-500 hover:text-slate-700 dark:text-slate-400 dark:hover:text-slate-200 transition-colors duration-200"
|
||||
type="button">
|
||||
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
|
||||
</svg>
|
||||
@ -1503,16 +1532,16 @@
|
||||
<div class="space-y-4">
|
||||
<!-- Schnell-Aktionen -->
|
||||
<div class="grid grid-cols-2 gap-3">
|
||||
<button class="dnd-quick-btn btn-primary" data-duration="30">
|
||||
<button class="dnd-quick-btn btn-primary" data-duration="30" type="button">
|
||||
30 Min
|
||||
</button>
|
||||
<button class="dnd-quick-btn btn-primary" data-duration="60">
|
||||
<button class="dnd-quick-btn btn-primary" data-duration="60" type="button">
|
||||
1 Stunde
|
||||
</button>
|
||||
<button class="dnd-quick-btn btn-primary" data-duration="480">
|
||||
<button class="dnd-quick-btn btn-primary" data-duration="480" type="button">
|
||||
8 Stunden
|
||||
</button>
|
||||
<button class="dnd-quick-btn btn-primary" data-duration="0">
|
||||
<button class="dnd-quick-btn btn-primary" data-duration="0" type="button">
|
||||
Dauerhaft
|
||||
</button>
|
||||
</div>
|
||||
@ -1543,7 +1572,8 @@
|
||||
<h4 class="text-sm font-medium text-slate-900 dark:text-white">
|
||||
Unterdrückte Nachrichten (${this.suppressedMessages.length})
|
||||
</h4>
|
||||
<button class="dnd-clear-btn text-xs text-slate-500 hover:text-slate-700 dark:text-slate-400 dark:hover:text-slate-200">
|
||||
<button class="dnd-clear-btn text-xs text-slate-500 hover:text-slate-700 dark:text-slate-400 dark:hover:text-slate-200 transition-colors duration-200"
|
||||
type="button">
|
||||
Alle löschen
|
||||
</button>
|
||||
</div>
|
||||
@ -1573,11 +1603,11 @@
|
||||
<!-- Aktions-Buttons -->
|
||||
<div class="flex space-x-3 pt-4">
|
||||
${this.isActive ? `
|
||||
<button class="dnd-disable-btn btn-secondary flex-1">
|
||||
<button class="dnd-disable-btn btn-secondary flex-1" type="button">
|
||||
Deaktivieren
|
||||
</button>
|
||||
` : ''}
|
||||
<button class="dnd-close-btn btn-primary flex-1">
|
||||
<button class="dnd-close-btn-main btn-primary flex-1" type="button">
|
||||
Schließen
|
||||
</button>
|
||||
</div>
|
||||
@ -1585,43 +1615,91 @@
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Event Listeners
|
||||
// Event Listeners mit Event Delegation
|
||||
modal.addEventListener('click', (e) => {
|
||||
if (e.target === modal || e.target.classList.contains('dnd-close-btn')) {
|
||||
modal.remove();
|
||||
e.stopPropagation();
|
||||
|
||||
// Schließen bei Klick auf Hintergrund
|
||||
if (e.target === modal) {
|
||||
this.closeModal(modal);
|
||||
return;
|
||||
}
|
||||
|
||||
// Schließen-Buttons
|
||||
if (e.target.closest('.dnd-close-btn') || e.target.closest('.dnd-close-btn-main')) {
|
||||
e.preventDefault();
|
||||
this.closeModal(modal);
|
||||
return;
|
||||
}
|
||||
|
||||
// Schnell-Aktionen
|
||||
if (e.target.classList.contains('dnd-quick-btn')) {
|
||||
e.preventDefault();
|
||||
const duration = parseInt(e.target.dataset.duration);
|
||||
if (duration === 0) {
|
||||
this.enable();
|
||||
} else {
|
||||
this.enable(duration);
|
||||
}
|
||||
modal.remove();
|
||||
this.closeModal(modal);
|
||||
return;
|
||||
}
|
||||
|
||||
// Deaktivieren-Button
|
||||
if (e.target.classList.contains('dnd-disable-btn')) {
|
||||
e.preventDefault();
|
||||
this.disable();
|
||||
modal.remove();
|
||||
this.closeModal(modal);
|
||||
return;
|
||||
}
|
||||
|
||||
// Alle löschen
|
||||
if (e.target.classList.contains('dnd-clear-btn')) {
|
||||
e.preventDefault();
|
||||
this.clearSuppressedMessages();
|
||||
modal.remove();
|
||||
this.showSettings(); // Modal neu laden
|
||||
this.closeModal(modal);
|
||||
// Modal neu öffnen mit aktualisierten Daten
|
||||
setTimeout(() => this.showSettings(), 100);
|
||||
return;
|
||||
}
|
||||
|
||||
// Einstellungen-Checkboxen
|
||||
if (e.target.classList.contains('dnd-setting')) {
|
||||
const setting = e.target.dataset.setting;
|
||||
this.settings[setting] = e.target.checked;
|
||||
this.saveSettings();
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
// ESC-Taste zum Schließen
|
||||
const escapeHandler = (e) => {
|
||||
if (e.key === 'Escape') {
|
||||
this.closeModal(modal);
|
||||
document.removeEventListener('keydown', escapeHandler);
|
||||
}
|
||||
};
|
||||
document.addEventListener('keydown', escapeHandler);
|
||||
|
||||
// Modal zum DOM hinzufügen
|
||||
document.body.appendChild(modal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Modal schließen
|
||||
*/
|
||||
closeModal(modal) {
|
||||
if (modal && modal.parentNode) {
|
||||
modal.style.opacity = '0';
|
||||
modal.style.pointerEvents = 'none';
|
||||
setTimeout(() => {
|
||||
if (modal.parentNode) {
|
||||
modal.parentNode.removeChild(modal);
|
||||
}
|
||||
}, 200);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unterdrückte Nachrichten löschen
|
||||
*/
|
||||
@ -1851,6 +1929,23 @@
|
||||
});
|
||||
|
||||
console.log('✅ MYP UI Components erfolgreich initialisiert - Erweiterte Benutzeroberfläche mit Glassmorphism und Do Not Disturb bereit');
|
||||
|
||||
// Test der glasigen Flash Messages (nur im Development)
|
||||
if (window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1') {
|
||||
// Warten auf vollständige Initialisierung, dann Test-Messages anzeigen
|
||||
setTimeout(() => {
|
||||
console.log('🧪 Teste glasige Flash Messages...');
|
||||
showFlashMessage('Glassmorphism Flash Messages sind aktiv! ✨', 'success', 7000);
|
||||
|
||||
setTimeout(() => {
|
||||
showFlashMessage('Do Not Disturb System ist bereit. Probieren Sie es im Footer aus! 🔕', 'info', 7000);
|
||||
}, 1000);
|
||||
|
||||
setTimeout(() => {
|
||||
showFlashMessage('Warnung: Dies ist eine Test-Nachricht für das glasige Design.', 'warning', 7000);
|
||||
}, 2000);
|
||||
}, 2000);
|
||||
}
|
||||
});
|
||||
|
||||
// Globale Variablen für erweiterte Flash Messages
|
||||
|
Reference in New Issue
Block a user