📝 "Refactor backend files
This commit is contained in:
@ -202,6 +202,53 @@
|
||||
.dark .dropdown-menu::-webkit-scrollbar-thumb {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
/* ===== DO NOT DISTURB BUTTON STYLES ===== */
|
||||
.dnd-toggle-button {
|
||||
/* Inaktiv (Standard) */
|
||||
background: linear-gradient(135deg, rgba(99, 102, 241, 0.1), rgba(59, 130, 246, 0.1));
|
||||
color: rgb(99, 102, 241);
|
||||
border: 1px solid rgba(99, 102, 241, 0.2);
|
||||
}
|
||||
|
||||
.dnd-toggle-button:hover {
|
||||
background: linear-gradient(135deg, rgba(99, 102, 241, 0.15), rgba(59, 130, 246, 0.15));
|
||||
border-color: rgba(99, 102, 241, 0.3);
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 12px rgba(99, 102, 241, 0.15);
|
||||
}
|
||||
|
||||
/* Aktiv (DND eingeschaltet) */
|
||||
.dnd-toggle-button.active {
|
||||
background: linear-gradient(135deg, rgba(249, 115, 22, 0.9), rgba(234, 88, 12, 0.9));
|
||||
color: white;
|
||||
border: 1px solid rgba(249, 115, 22, 0.8);
|
||||
box-shadow: 0 2px 8px rgba(249, 115, 22, 0.3);
|
||||
}
|
||||
|
||||
.dnd-toggle-button.active:hover {
|
||||
background: linear-gradient(135deg, rgba(249, 115, 22, 1), rgba(234, 88, 12, 1));
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 12px rgba(249, 115, 22, 0.4);
|
||||
}
|
||||
|
||||
/* Dark Mode Anpassungen */
|
||||
.dark .dnd-toggle-button {
|
||||
background: linear-gradient(135deg, rgba(99, 102, 241, 0.15), rgba(59, 130, 246, 0.15));
|
||||
color: rgb(147, 197, 253);
|
||||
border: 1px solid rgba(99, 102, 241, 0.3);
|
||||
}
|
||||
|
||||
.dark .dnd-toggle-button:hover {
|
||||
background: linear-gradient(135deg, rgba(99, 102, 241, 0.2), rgba(59, 130, 246, 0.2));
|
||||
border-color: rgba(99, 102, 241, 0.4);
|
||||
}
|
||||
|
||||
.dark .dnd-toggle-button.active {
|
||||
background: linear-gradient(135deg, rgba(249, 115, 22, 0.9), rgba(234, 88, 12, 0.9));
|
||||
color: white;
|
||||
border: 1px solid rgba(249, 115, 22, 0.8);
|
||||
}
|
||||
</style>
|
||||
|
||||
{% block head %}{% endblock %}
|
||||
@ -662,43 +709,30 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Do Not Disturb Controls -->
|
||||
<div class="flex flex-col space-y-4">
|
||||
<h3 class="text-lg font-semibold text-slate-900 dark:text-white transition-colors duration-300">Benachrichtigungen</h3>
|
||||
<div class="space-y-3">
|
||||
<!-- Do Not Disturb Toggle -->
|
||||
<!-- Do Not Disturb Toggle - Vereinfacht -->
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-xs text-slate-600 dark:text-slate-400">Nicht stören:</span>
|
||||
<button
|
||||
id="dndToggle"
|
||||
class="relative p-2 rounded-lg text-slate-700 dark:text-slate-300 hover:bg-slate-100/80 dark:hover:bg-slate-800/50 transition-all duration-300 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 group"
|
||||
class="dnd-toggle-button px-3 py-1.5 rounded-lg text-xs font-medium transition-all duration-300 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
|
||||
aria-label="Do Not Disturb umschalten"
|
||||
data-dnd-toggle
|
||||
title="Benachrichtigungen stumm schalten"
|
||||
>
|
||||
<!-- DND Icon (Stumm) -->
|
||||
<div class="dnd-icon-off transition-all duration-300">
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9"/>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<!-- DND Icon (Aktiv) - versteckt by default -->
|
||||
<div class="dnd-icon-on absolute inset-0 flex items-center justify-center transition-all duration-300 opacity-0 scale-75">
|
||||
<svg class="w-4 h-4 text-red-500" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
||||
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zM4 12c0-4.42 3.58-8 8-8 1.85 0 3.55.63 4.9 1.69L5.69 16.9C4.63 15.55 4 13.85 4 12zm8 8c-1.85 0-3.55-.63-4.9-1.69L18.31 7.1C19.37 8.45 20 10.15 20 12c0 4.42-3.58 8-8 8z"/>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<!-- Notification Counter für unterdrückte Messages -->
|
||||
<span id="dndCounter" class="dnd-counter hidden">0</span>
|
||||
<span class="dnd-text">Inaktiv</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- DND Status Anzeige -->
|
||||
<div id="dndStatus" class="text-xs text-slate-500 dark:text-slate-400 hidden">
|
||||
<span class="dnd-status-text">Inaktiv</span>
|
||||
<!-- 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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -810,6 +844,183 @@
|
||||
|
||||
console.log('🚀 MYP Platform UI erfolgreich initialisiert');
|
||||
});
|
||||
|
||||
/**
|
||||
* Do Not Disturb (DND) Funktionalität
|
||||
*/
|
||||
class DoNotDisturbManager {
|
||||
constructor() {
|
||||
this.storageKey = 'myp-dnd-mode';
|
||||
this.counterKey = 'myp-dnd-counter';
|
||||
this.suppressedMessages = [];
|
||||
this.isEnabled = this.loadDNDState();
|
||||
this.suppressedCount = this.loadSuppressedCount();
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
init() {
|
||||
const dndToggle = document.getElementById('dndToggle');
|
||||
const dndStatus = document.getElementById('dndStatus');
|
||||
const dndCounter = document.getElementById('dndCounter');
|
||||
|
||||
if (dndToggle) {
|
||||
dndToggle.addEventListener('click', () => this.toggle());
|
||||
this.updateUI();
|
||||
}
|
||||
|
||||
// Integration mit dem bestehenden Benachrichtigungssystem
|
||||
this.integrateWithNotificationSystem();
|
||||
}
|
||||
|
||||
toggle() {
|
||||
this.isEnabled = !this.isEnabled;
|
||||
this.saveDNDState();
|
||||
this.updateUI();
|
||||
|
||||
if (!this.isEnabled) {
|
||||
// Beim Deaktivieren alle unterdrückten Nachrichten anzeigen
|
||||
this.showSuppressedMessages();
|
||||
this.resetSuppressedCount();
|
||||
}
|
||||
|
||||
// Feedback für den Benutzer
|
||||
const message = this.isEnabled
|
||||
? 'Nicht stören aktiviert - Benachrichtigungen werden unterdrückt'
|
||||
: 'Nicht stören deaktiviert - Benachrichtigungen sind wieder aktiv';
|
||||
|
||||
if (typeof showFlashMessage === 'function') {
|
||||
showFlashMessage(message, 'info', 3000);
|
||||
}
|
||||
|
||||
console.log(`🔕 DND ${this.isEnabled ? 'aktiviert' : 'deaktiviert'}`);
|
||||
}
|
||||
|
||||
updateUI() {
|
||||
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');
|
||||
if (dndText) dndText.textContent = 'Aktiv';
|
||||
if (dndStatusText) dndStatusText.textContent = 'Benachrichtigungen unterdrückt';
|
||||
dndToggle?.setAttribute('title', 'Nicht stören deaktivieren');
|
||||
} else {
|
||||
dndToggle?.classList.remove('active');
|
||||
if (dndText) dndText.textContent = 'Inaktiv';
|
||||
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) {
|
||||
if (!this.isEnabled) return false;
|
||||
|
||||
// Wichtige Nachrichten (Fehler) nicht unterdrücken
|
||||
if (type === 'error' || type === 'danger') return false;
|
||||
|
||||
// Nachricht zur Liste der unterdrückten hinzufügen
|
||||
this.suppressedMessages.push({
|
||||
message,
|
||||
type,
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
|
||||
this.incrementSuppressedCount();
|
||||
return true;
|
||||
}
|
||||
|
||||
showSuppressedMessages() {
|
||||
if (this.suppressedMessages.length === 0) return;
|
||||
|
||||
// Sammelnachricht über unterdrückte Benachrichtigungen
|
||||
const count = this.suppressedMessages.length;
|
||||
const summaryMessage = `${count} Benachrichtigung${count > 1 ? 'en' : ''} während "Nicht stören" erhalten`;
|
||||
|
||||
if (typeof showFlashMessage === 'function') {
|
||||
showFlashMessage(summaryMessage, 'info', 4000);
|
||||
}
|
||||
|
||||
// Optional: Alle einzelnen Nachrichten anzeigen (mit Verzögerung)
|
||||
this.suppressedMessages.forEach((item, index) => {
|
||||
setTimeout(() => {
|
||||
if (typeof showFlashMessage === 'function') {
|
||||
showFlashMessage(item.message, item.type, 3000);
|
||||
}
|
||||
}, (index + 1) * 500);
|
||||
});
|
||||
|
||||
this.suppressedMessages = [];
|
||||
}
|
||||
|
||||
incrementSuppressedCount() {
|
||||
this.suppressedCount++;
|
||||
this.saveSuppressedCount();
|
||||
this.updateUI();
|
||||
}
|
||||
|
||||
resetSuppressedCount() {
|
||||
this.suppressedCount = 0;
|
||||
this.saveSuppressedCount();
|
||||
this.updateUI();
|
||||
}
|
||||
|
||||
integrateWithNotificationSystem() {
|
||||
// Überschreibe showFlashMessage wenn verfügbar
|
||||
if (typeof window.showFlashMessage === 'function') {
|
||||
const originalShowFlashMessage = window.showFlashMessage;
|
||||
window.showFlashMessage = (message, type, duration) => {
|
||||
if (this.shouldSuppressNotification(message, type)) {
|
||||
console.log(`🔕 Benachrichtigung unterdrückt: ${message}`);
|
||||
return;
|
||||
}
|
||||
return originalShowFlashMessage(message, type, duration);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
loadDNDState() {
|
||||
const saved = localStorage.getItem(this.storageKey);
|
||||
return saved === 'true';
|
||||
}
|
||||
|
||||
saveDNDState() {
|
||||
localStorage.setItem(this.storageKey, this.isEnabled.toString());
|
||||
}
|
||||
|
||||
loadSuppressedCount() {
|
||||
const saved = localStorage.getItem(this.counterKey);
|
||||
return saved ? parseInt(saved, 10) : 0;
|
||||
}
|
||||
|
||||
saveSuppressedCount() {
|
||||
localStorage.setItem(this.counterKey, this.suppressedCount.toString());
|
||||
}
|
||||
|
||||
// Public API
|
||||
getState() {
|
||||
return {
|
||||
enabled: this.isEnabled,
|
||||
suppressedCount: this.suppressedCount,
|
||||
suppressedMessages: this.suppressedMessages
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// DND Manager global verfügbar machen
|
||||
window.dndManager = new DoNotDisturbManager();
|
||||
</script>
|
||||
|
||||
{% block scripts %}{% endblock %}
|
||||
|
@ -183,7 +183,7 @@ async function loadBasicStats() {
|
||||
throw new Error(data.error || 'Fehler beim Laden der Statistiken');
|
||||
}
|
||||
|
||||
// Statistiken aktualisieren
|
||||
// Statistiken aktualisieren mit defensiven Checks
|
||||
updateStatsCounter('total-jobs-count', data.total_jobs);
|
||||
updateStatsCounter('completed-jobs-count', data.completed_jobs);
|
||||
updateStatsCounter('online-printers-count', data.online_printers);
|
||||
@ -192,6 +192,8 @@ async function loadBasicStats() {
|
||||
updateStatsCounter('failed-jobs-count', data.failed_jobs);
|
||||
updateStatsCounter('total-users-count', data.total_users);
|
||||
|
||||
console.log('✅ Basis-Statistiken erfolgreich geladen:', data);
|
||||
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Laden der Basis-Statistiken:', error);
|
||||
showToast('Fehler beim Laden der Statistiken', 'error');
|
||||
@ -200,7 +202,10 @@ async function loadBasicStats() {
|
||||
|
||||
function updateStatsCounter(elementId, value, animate = true) {
|
||||
const element = document.getElementById(elementId);
|
||||
if (!element) return;
|
||||
if (!element) {
|
||||
console.warn(`Element mit ID '${elementId}' nicht gefunden - wird übersprungen`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (animate) {
|
||||
// Animierte Zählung
|
||||
|
Reference in New Issue
Block a user