📚 Improved documentation and logs structure for better maintainability and troubleshooting. 🖥️🔍

This commit is contained in:
2025-06-01 04:46:49 +02:00
parent f0fe4c29d5
commit 3501bbfddf
30 changed files with 721 additions and 167 deletions

View File

@ -10,6 +10,10 @@ class GlassmorphismNotificationSystem {
this.soundEnabled = localStorage.getItem('myp-notification-sound') !== 'false';
this.animationsEnabled = !window.matchMedia('(prefers-reduced-motion: reduce)').matches;
// Callback-Registry für Actions hinzufügen
this.actionCallbacks = new Map();
this.callbackCounter = 0;
this.init();
this.setupGlobalFunctions();
this.injectStyles();
@ -49,6 +53,9 @@ class GlassmorphismNotificationSystem {
window.showPersistentAlert = this.showPersistentAlert.bind(this);
window.showConfirmationToast = this.showConfirmationToast.bind(this);
window.showProgressToast = this.showProgressToast.bind(this);
// Globale Callback-Ausführungsfunktion
window.executeNotificationCallback = this.executeCallback.bind(this);
}
setupEventListeners() {
@ -162,14 +169,23 @@ class GlassmorphismNotificationSystem {
}
createActionButtons(actions, toastId) {
return actions.map(action => `
<button class="toast-action-btn toast-action-${action.type || 'secondary'}"
onclick="${action.onClick}; ${action.closeAfter !== false ? `glassNotificationSystem.closeToast('${toastId}')` : ''}"
title="${action.title || action.text}">
${action.icon ? `<svg class="w-4 h-4">${action.icon}</svg>` : ''}
${action.text}
</button>
`).join('');
return actions.map(action => {
// Callback in Registry speichern falls vorhanden
let callbackId = '';
if (action.callback && typeof action.callback === 'function') {
callbackId = `callback-${++this.callbackCounter}`;
this.actionCallbacks.set(callbackId, action.callback);
}
return `
<button class="toast-action-btn toast-action-${action.type || 'secondary'}"
onclick="glassNotificationSystem.handleActionClick('${callbackId}', '${toastId}', ${action.closeAfter !== false})"
title="${action.title || action.text}">
${action.icon ? `<svg class="w-4 h-4">${action.icon}</svg>` : ''}
${action.text}
</button>
`;
}).join('');
}
getIconSvg(type) {
@ -299,6 +315,14 @@ class GlassmorphismNotificationSystem {
}
this.notifications.delete(toastId);
// Alle zugehörigen Callbacks löschen
this.actionCallbacks.forEach((callback, callbackId) => {
if (callbackId.includes(toastId)) {
this.actionCallbacks.delete(callbackId);
}
});
this.repositionAllToasts();
}
@ -331,21 +355,49 @@ class GlassmorphismNotificationSystem {
* Spezielle Toast-Typen
*/
showConfirmationToast(message, onConfirm, onCancel = null, options = {}) {
const confirmCallback = () => {
if (typeof onConfirm === 'function') {
try {
onConfirm();
} catch (error) {
console.error('Fehler beim Ausführen der Bestätigungslogik:', error);
}
}
};
const cancelCallback = () => {
if (typeof onCancel === 'function') {
try {
onCancel();
} catch (error) {
console.error('Fehler beim Ausführen der Abbruchlogik:', error);
}
}
};
const actions = [
{
text: options.confirmText || 'Bestätigen',
type: 'primary',
callback: confirmCallback,
closeAfter: true
}
];
// Cancel-Button nur hinzufügen wenn Callback vorhanden ist
if (onCancel || options.cancelText) {
actions.push({
text: options.cancelText || 'Abbrechen',
type: 'secondary',
callback: cancelCallback,
closeAfter: true
});
}
return this.showToast(message, 'warning', 0, {
persistent: true,
title: options.title || 'Bestätigung erforderlich',
actions: [
{
text: options.confirmText || 'Bestätigen',
type: 'primary',
onClick: `(${onConfirm.toString()})()`
},
{
text: options.cancelText || 'Abbrechen',
type: 'secondary',
onClick: onCancel ? `(${onCancel.toString()})()` : ''
}
],
actions: actions,
...options
});
}
@ -1485,6 +1537,43 @@ class GlassmorphismNotificationSystem {
document.head.appendChild(styles);
}
/**
* Behandelt Action-Button-Klicks
*/
handleActionClick(callbackId, toastId, shouldClose = true) {
// Callback ausführen falls vorhanden
if (callbackId && this.actionCallbacks.has(callbackId)) {
const callback = this.actionCallbacks.get(callbackId);
try {
callback();
} catch (error) {
console.error('Fehler beim Ausführen des Action-Callbacks:', error);
}
// Callback nach Ausführung löschen
this.actionCallbacks.delete(callbackId);
}
// Toast schließen falls gewünscht
if (shouldClose) {
this.closeToast(toastId);
}
}
/**
* Für Rückwärtskompatibilität - führt Callback-Funktionen aus
*/
executeCallback(callbackId) {
if (this.actionCallbacks.has(callbackId)) {
const callback = this.actionCallbacks.get(callbackId);
try {
callback();
} catch (error) {
console.error('Fehler beim Ausführen des Callbacks:', error);
}
this.actionCallbacks.delete(callbackId);
}
}
}
// Globale Instanz erstellen

View File

@ -485,16 +485,25 @@ function updateStatsCounter(elementId, value, animate = true) {
return;
}
// Sichere Wert-Validierung hinzufügen
if (value === null || value === undefined) {
console.warn(`Ungültiger Wert für Element '${elementId}':`, value);
value = 0; // Fallback-Wert
}
if (animate) {
// Animierte Zählung
const currentValue = parseInt(element.textContent.replace(/[^\d]/g, '')) || 0;
const targetValue = parseInt(value.toString().replace(/[^\d]/g, '')) || 0;
if (currentValue !== targetValue) {
animateCounter(element, currentValue, targetValue, value.toString());
// Sichere String-Konvertierung
const finalTextValue = value !== null && value !== undefined ? value.toString() : '0';
animateCounter(element, currentValue, targetValue, finalTextValue);
}
} else {
element.textContent = value;
// Sichere Zuweisung ohne Animation
element.textContent = value !== null && value !== undefined ? value.toString() : '0';
}
}
@ -502,6 +511,26 @@ function updateStatsCounter(elementId, value, animate = true) {
* Animierte Counter-Funktion
*/
function animateCounter(element, start, end, finalText) {
// Sichere Parameter-Validierung
if (!element) {
console.warn('animateCounter: Kein gültiges Element übergeben');
return;
}
// Sichere finalText-Validierung mit optimiertem Logging
if (typeof finalText !== 'string') {
// Nur bei problematischen Werten warnen (null, undefined, objects)
if (finalText === null || finalText === undefined || (typeof finalText === 'object' && finalText !== null)) {
console.warn('animateCounter: Problematischer finalText-Wert:', finalText);
}
// Normale Numbers stille konvertieren
finalText = finalText !== null && finalText !== undefined ? String(finalText) : '0';
}
// Sichere start/end-Validierung
start = parseInt(start) || 0;
end = parseInt(end) || 0;
const duration = 1000; // 1 Sekunde
const startTime = performance.now();
@ -513,16 +542,28 @@ function animateCounter(element, start, end, finalText) {
const easeOut = 1 - Math.pow(1 - progress, 3);
const currentValue = Math.round(start + (end - start) * easeOut);
if (finalText.includes('%')) {
element.textContent = currentValue + '%';
} else {
// Sichere includes-Prüfung
try {
if (typeof finalText === 'string' && finalText.includes('%')) {
element.textContent = currentValue + '%';
} else {
element.textContent = currentValue;
}
} catch (error) {
console.warn('animateCounter: Fehler bei finalText.includes:', error, 'finalText:', finalText);
element.textContent = currentValue;
}
if (progress < 1) {
requestAnimationFrame(updateCounter);
} else {
element.textContent = finalText;
// Sichere Zuweisung des finalen Wertes
try {
element.textContent = finalText;
} catch (error) {
console.warn('animateCounter: Fehler bei finaler Zuweisung:', error);
element.textContent = String(end);
}
}
}

View File

@ -161,20 +161,43 @@ class PrinterMonitor {
// Drucker-Daten aktualisieren
this.printers.clear();
// Null-Check für data.printers hinzufügen
// Flexible Datenextraktion für verschiedene API-Response-Strukturen
let printersData = null;
if (data && data.printers && typeof data.printers === 'object') {
Object.values(data.printers).forEach(printer => {
this.printers.set(printer.id, {
...printer,
statusInfo: this.statusCategories[printer.status] || this.statusCategories['offline']
});
// Alte Struktur: data.printers
printersData = data.printers;
} else if (data && data.status && typeof data.status === 'object') {
// Neue Struktur: data.status
printersData = data.status;
} else if (data && typeof data === 'object' && !data.success && !data.error) {
// Direkte Drucker-Daten ohne Wrapper
printersData = data;
}
if (printersData && typeof printersData === 'object') {
// Drucker-Daten verarbeiten
Object.values(printersData).forEach(printer => {
// Sichere Validierung der Drucker-Objekte
if (printer && typeof printer === 'object' && printer.id) {
this.printers.set(printer.id, {
...printer,
statusInfo: this.statusCategories[printer.status] || this.statusCategories['offline']
});
} else {
console.warn('⚠️ Ungültiges Drucker-Objekt übersprungen:', printer);
}
});
console.log(`${this.printers.size} Drucker erfolgreich verarbeitet`);
} else {
console.warn('⚠️ Keine gültigen Drucker-Daten erhalten:', data);
// Benachrichtige Callbacks über Fehler
console.warn('⚠️ Keine gültigen Drucker-Daten in Response-Struktur gefunden');
console.debug('Response-Struktur:', data);
// Benachrichtige Callbacks über fehlende Daten (aber nicht als Fehler)
this.notifyCallbacks({
type: 'error',
message: 'Ungültige Drucker-Daten erhalten',
type: 'warning',
message: 'Keine Drucker-Daten verfügbar',
data: data
});
return;