🎉 Verbesserte Backend-Funktionalität durch Windows-sichere Disk-Usage-Bestimmung, Uptime-Berechnung und Einführung eines Kiosk-Timers. Dokumentation aktualisiert und nicht mehr benötigte Dateien entfernt. 🧹

This commit is contained in:
2025-06-01 03:00:04 +02:00
parent 486647fade
commit 8969cf6df6
70 changed files with 89065 additions and 85009 deletions

View File

@ -92,6 +92,12 @@
}
}
// User-Dropdown-Funktionalität initialisieren
initializeUserDropdown();
// Mobile Menu Toggle initialisieren
initializeMobileMenu();
// MYP App für Offline-Funktionalität initialisieren
if (typeof MYPApp !== 'undefined') {
window.mypApp = new MYPApp();
@ -729,10 +735,7 @@
<!-- DND Status und Counter -->
<div id="dndStatus" class="text-xs text-slate-500 dark:text-slate-400">
<div class="flex items-center justify-between">
<span class="dnd-status-text">Alle Benachrichtigungen aktiv</span>
<span id="dndCounter" class="dnd-counter hidden px-2 py-1 bg-orange-500 text-white rounded-full text-xs font-medium">0 unterdrückt</span>
</div>
<span class="dnd-status-text">Alle Benachrichtigungen aktiv</span>
</div>
</div>
</div>
@ -809,6 +812,12 @@
* Initialisierung aller UI-Komponenten nach DOM-Load
*/
document.addEventListener('DOMContentLoaded', function() {
// User-Dropdown-Funktionalität initialisieren
initializeUserDropdown();
// Mobile Menu Toggle initialisieren
initializeMobileMenu();
// MYP App für Offline-Funktionalität initialisieren
if (typeof MYPApp !== 'undefined') {
window.mypApp = new MYPApp();
@ -845,6 +854,159 @@
console.log('🚀 MYP Platform UI erfolgreich initialisiert');
});
/**
* User-Dropdown-Funktionalität
*/
function initializeUserDropdown() {
const userMenuButton = document.getElementById('user-menu-button');
const userDropdown = document.getElementById('user-dropdown');
const userMenuContainer = document.getElementById('user-menu-container');
if (!userMenuButton || !userDropdown) return;
// Toggle-Funktion
function toggleDropdown(e) {
e.stopPropagation();
const isExpanded = userMenuButton.getAttribute('aria-expanded') === 'true';
if (isExpanded) {
closeDropdown();
} else {
openDropdown();
}
}
// Dropdown öffnen
function openDropdown() {
userDropdown.classList.remove('hidden');
userMenuButton.setAttribute('aria-expanded', 'true');
// Animation für bessere UX
userDropdown.style.opacity = '0';
userDropdown.style.transform = 'scale(0.95) translateY(-5px)';
// Kleine Verzögerung für Animation
requestAnimationFrame(() => {
userDropdown.style.transition = 'all 0.15s ease-out';
userDropdown.style.opacity = '1';
userDropdown.style.transform = 'scale(1) translateY(0)';
});
}
// Dropdown schließen
function closeDropdown() {
userDropdown.style.transition = 'all 0.15s ease-in';
userDropdown.style.opacity = '0';
userDropdown.style.transform = 'scale(0.95) translateY(-5px)';
setTimeout(() => {
userDropdown.classList.add('hidden');
userMenuButton.setAttribute('aria-expanded', 'false');
}, 150);
}
// Event-Listener
userMenuButton.addEventListener('click', toggleDropdown);
// Außerhalb des Dropdowns klicken schließt es
document.addEventListener('click', function(e) {
if (!userMenuContainer.contains(e.target)) {
closeDropdown();
}
});
// Escape-Taste schließt das Dropdown
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape' && userMenuButton.getAttribute('aria-expanded') === 'true') {
closeDropdown();
userMenuButton.focus();
}
});
// Keyboard-Navigation im Dropdown
userDropdown.addEventListener('keydown', function(e) {
const focusableElements = userDropdown.querySelectorAll('a, button');
const currentIndex = Array.from(focusableElements).indexOf(document.activeElement);
switch(e.key) {
case 'ArrowDown':
e.preventDefault();
const nextIndex = (currentIndex + 1) % focusableElements.length;
focusableElements[nextIndex].focus();
break;
case 'ArrowUp':
e.preventDefault();
const prevIndex = currentIndex === 0 ? focusableElements.length - 1 : currentIndex - 1;
focusableElements[prevIndex].focus();
break;
case 'Tab':
// Tab schließt das Dropdown
if (!e.shiftKey && currentIndex === focusableElements.length - 1) {
closeDropdown();
} else if (e.shiftKey && currentIndex === 0) {
closeDropdown();
}
break;
}
});
}
/**
* Mobile Menu Toggle Funktionalität
*/
function initializeMobileMenu() {
const mobileMenuToggle = document.getElementById('mobileMenuToggle');
const mobileMenu = document.getElementById('mobileMenu');
if (!mobileMenuToggle || !mobileMenu) return;
mobileMenuToggle.addEventListener('click', function() {
const isExpanded = mobileMenuToggle.getAttribute('aria-expanded') === 'true';
if (isExpanded) {
// Menü schließen
mobileMenu.classList.add('hidden');
mobileMenuToggle.setAttribute('aria-expanded', 'false');
mobileMenuToggle.setAttribute('aria-label', 'Menü öffnen');
// Icon zu Hamburger ändern
mobileMenuToggle.innerHTML = `
<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>
`;
} else {
// Menü öffnen
mobileMenu.classList.remove('hidden');
mobileMenuToggle.setAttribute('aria-expanded', 'true');
mobileMenuToggle.setAttribute('aria-label', 'Menü schließen');
// Icon zu X ändern
mobileMenuToggle.innerHTML = `
<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="M6 18L18 6M6 6l12 12"/>
</svg>
`;
}
});
// Mobile Menu bei Resize auf Desktop schließen
window.addEventListener('resize', function() {
if (window.innerWidth >= 1024) { // lg breakpoint
mobileMenu.classList.add('hidden');
mobileMenuToggle.setAttribute('aria-expanded', 'false');
mobileMenuToggle.setAttribute('aria-label', 'Menü öffnen');
// Icon zurück zu Hamburger
mobileMenuToggle.innerHTML = `
<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>
`;
}
});
}
/**
* Do Not Disturb (DND) Funktionalität
*/
@ -862,7 +1024,6 @@
init() {
const dndToggle = document.getElementById('dndToggle');
const dndStatus = document.getElementById('dndStatus');
const dndCounter = document.getElementById('dndCounter');
if (dndToggle) {
dndToggle.addEventListener('click', () => this.toggle());
@ -900,7 +1061,6 @@
const dndToggle = document.getElementById('dndToggle');
const dndText = dndToggle?.querySelector('.dnd-text');
const dndStatusText = document.querySelector('.dnd-status-text');
const dndCounter = document.getElementById('dndCounter');
if (this.isEnabled) {
dndToggle?.classList.add('active');
@ -913,16 +1073,6 @@
if (dndStatusText) dndStatusText.textContent = 'Alle Benachrichtigungen aktiv';
dndToggle?.setAttribute('title', 'Nicht stören aktivieren');
}
// Counter aktualisieren
if (dndCounter) {
if (this.suppressedCount > 0 && this.isEnabled) {
dndCounter.textContent = `${this.suppressedCount} unterdrückt`;
dndCounter.classList.remove('hidden');
} else {
dndCounter.classList.add('hidden');
}
}
}
shouldSuppressNotification(message, type) {