feat: Hinzufügen neuer API-Endpunkte zur erweiterten Drucker-Status-Verwaltung und Verbesserung der Benutzeroberfläche durch optimierte Lade- und Filtermechanismen. Implementierung von Caching für Online-Drucker und Live-Status sowie Auto-Update-Funktionalität zur Echtzeit-Überwachung. Anpassungen in den Templates zur Anzeige von Status-Übersichten und Filteroptionen für eine verbesserte Benutzererfahrung.
This commit is contained in:
@@ -2,22 +2,63 @@
|
||||
|
||||
{% block title %}Drucker - MYP Platform{% endblock %}
|
||||
|
||||
{% block extra_css %}
|
||||
<link href="{{ url_for('static', filename='css/printers.css') }}" rel="stylesheet">
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="max-w-7xl mx-auto px-3 sm:px-6 lg:px-8 py-4 sm:py-8">
|
||||
<!-- Header -->
|
||||
<!-- Header mit Status-Übersicht -->
|
||||
<div class="mb-4 sm:mb-8">
|
||||
<div class="flex flex-col sm:flex-row sm:items-center sm:justify-between">
|
||||
<div class="mb-4 sm:mb-0">
|
||||
<h1 class="text-2xl sm:text-3xl font-bold text-slate-900 dark:text-white">Drucker</h1>
|
||||
<p class="mt-1 sm:mt-2 text-sm sm:text-base text-slate-600 dark:text-slate-400">Verwalten Sie Ihre 3D-Drucker</p>
|
||||
|
||||
<!-- Live-Status-Übersicht -->
|
||||
<div id="status-overview" class="mt-3 flex flex-wrap gap-2 text-xs sm:text-sm">
|
||||
<div class="flex items-center space-x-1">
|
||||
<div class="w-2 h-2 bg-green-500 rounded-full animate-pulse"></div>
|
||||
<span class="text-slate-600 dark:text-slate-400">Online: <span id="online-count" class="font-semibold text-green-600 dark:text-green-400">-</span></span>
|
||||
</div>
|
||||
<div class="flex items-center space-x-1">
|
||||
<div class="w-2 h-2 bg-red-500 rounded-full"></div>
|
||||
<span class="text-slate-600 dark:text-slate-400">Offline: <span id="offline-count" class="font-semibold text-red-600 dark:text-red-400">-</span></span>
|
||||
</div>
|
||||
<div class="flex items-center space-x-1">
|
||||
<div class="w-2 h-2 bg-blue-500 rounded-full"></div>
|
||||
<span class="text-slate-600 dark:text-slate-400">Gesamt: <span id="total-count" class="font-semibold text-blue-600 dark:text-blue-400">-</span></span>
|
||||
</div>
|
||||
<div class="flex items-center space-x-1 ml-2">
|
||||
<svg id="auto-refresh-icon" class="w-3 h-3 text-slate-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
|
||||
</svg>
|
||||
<span class="text-xs text-slate-500 dark:text-slate-400">Auto-Update: <span id="next-update-time">-</span>s</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-wrap gap-2 sm:space-x-4">
|
||||
<!-- Filter-Buttons -->
|
||||
<div class="flex bg-slate-100 dark:bg-slate-700 rounded-lg p-1">
|
||||
<button id="filter-all" class="filter-btn active px-3 py-1 text-xs rounded-md transition-all duration-200">Alle</button>
|
||||
<button id="filter-online" class="filter-btn px-3 py-1 text-xs rounded-md transition-all duration-200">Online</button>
|
||||
<button id="filter-offline" class="filter-btn px-3 py-1 text-xs rounded-md transition-all duration-200">Offline</button>
|
||||
</div>
|
||||
|
||||
<button onclick="toggleAutoRefresh()" id="auto-refresh-btn" class="flex-1 sm:flex-none bg-blue-600 hover:bg-blue-700 dark:bg-blue-600 dark:hover:bg-blue-700 text-white px-3 sm:px-4 py-2 rounded-lg transition-all duration-200 text-sm sm:text-base flex items-center justify-center">
|
||||
<svg class="h-4 w-4 sm:h-5 sm:w-5 mr-1 sm:mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
Auto-Update
|
||||
</button>
|
||||
|
||||
<button onclick="refreshPrinters()" class="flex-1 sm:flex-none bg-indigo-600 hover:bg-indigo-700 dark:bg-indigo-600 dark:hover:bg-indigo-700 text-white px-3 sm:px-4 py-2 rounded-lg transition-all duration-200 text-sm sm:text-base flex items-center justify-center">
|
||||
<svg class="h-4 w-4 sm:h-5 sm:w-5 mr-1 sm:mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
|
||||
</svg>
|
||||
Aktualisieren
|
||||
Jetzt aktualisieren
|
||||
</button>
|
||||
|
||||
{% if current_user.is_admin %}
|
||||
<button id="addPrinterBtn" class="flex-1 sm:flex-none bg-green-600 hover:bg-green-700 dark:bg-green-600 dark:hover:bg-green-700 text-white px-3 sm:px-4 py-2 rounded-lg transition-all duration-200 text-sm sm:text-base flex items-center justify-center">
|
||||
<svg class="h-4 w-4 sm:h-5 sm:w-5 mr-1 sm:mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
@@ -143,6 +184,11 @@
|
||||
<script>
|
||||
// Globale Variablen für die Drucker-Verwaltung
|
||||
let printers = [];
|
||||
let currentFilter = 'all';
|
||||
let autoRefreshEnabled = false;
|
||||
let autoRefreshInterval = null;
|
||||
let nextUpdateCountdown = null;
|
||||
let nextUpdateTime = 30; // Sekunden bis zum nächsten Auto-Update
|
||||
|
||||
// Refresh printers mit Status-Check - Make it globally available
|
||||
function refreshPrinters() {
|
||||
@@ -171,8 +217,8 @@
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Drucker laden mit Status-Check
|
||||
loadPrintersWithStatusCheck().finally(() => {
|
||||
// Drucker laden mit Live-Status-Check
|
||||
loadPrintersWithLiveStatus().finally(() => {
|
||||
// Button wieder aktivieren
|
||||
if (refreshBtn) {
|
||||
refreshBtn.disabled = false;
|
||||
@@ -180,7 +226,7 @@
|
||||
<svg class="h-4 w-4 sm:h-5 sm:w-5 mr-1 sm:mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
|
||||
</svg>
|
||||
Aktualisieren
|
||||
Jetzt aktualisieren
|
||||
`;
|
||||
}
|
||||
});
|
||||
@@ -338,22 +384,46 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Render printers grid
|
||||
// Render printers grid mit Filter-Unterstützung
|
||||
function renderPrinters() {
|
||||
const grid = document.getElementById('printers-grid');
|
||||
|
||||
if (printers.length === 0) {
|
||||
// Filter anwenden
|
||||
let filteredPrinters = printers;
|
||||
if (currentFilter === 'online') {
|
||||
filteredPrinters = printers.filter(p => p.status === 'available' || p.is_online);
|
||||
} else if (currentFilter === 'offline') {
|
||||
filteredPrinters = printers.filter(p => p.status === 'offline' || !p.is_online);
|
||||
}
|
||||
|
||||
// Status-Übersicht aktualisieren falls nicht bereits gesetzt
|
||||
if (!document.getElementById('online-count').textContent || document.getElementById('online-count').textContent === '-') {
|
||||
const onlineCount = printers.filter(p => p.status === 'available' || p.is_online).length;
|
||||
const offlineCount = printers.length - onlineCount;
|
||||
updateStatusOverview(onlineCount, offlineCount, printers.length);
|
||||
}
|
||||
|
||||
if (filteredPrinters.length === 0) {
|
||||
let emptyMessage = 'Keine Drucker vorhanden';
|
||||
if (currentFilter === 'online') {
|
||||
emptyMessage = 'Keine Online-Drucker gefunden';
|
||||
} else if (currentFilter === 'offline') {
|
||||
emptyMessage = 'Keine Offline-Drucker gefunden';
|
||||
}
|
||||
|
||||
grid.innerHTML = `
|
||||
<div class="col-span-full text-center py-6 sm:py-12">
|
||||
<svg class="h-12 w-12 sm:h-16 sm:w-16 text-slate-400 dark:text-slate-500 mx-auto mb-3 sm:mb-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 3v2m6-2v2M9 19v2m6-2v2M5 9H3m2 6H3m18-6h-2m2 6h-2M7 19h10a2 2 0 002-2V7a2 2 0 00-2-2H7a2 2 0 00-2 2v10a2 2 0 002 2zM9 9h6v6H9V9z" />
|
||||
</svg>
|
||||
<p class="text-slate-700 dark:text-slate-300 text-base sm:text-lg">Keine Drucker vorhanden</p>
|
||||
{% if current_user.is_admin %}
|
||||
<button id="addFirstPrinterBtn" class="mt-3 sm:mt-4 bg-green-600 hover:bg-green-700 dark:bg-green-600 dark:hover:bg-green-500 text-white px-4 sm:px-6 py-1.5 sm:py-2 rounded-lg transition-all duration-200 text-sm sm:text-base">
|
||||
Ersten Drucker hinzufügen
|
||||
</button>
|
||||
{% endif %}
|
||||
<p class="text-slate-700 dark:text-slate-300 text-base sm:text-lg">${emptyMessage}</p>
|
||||
${currentFilter === 'all' && printers.length === 0 ? `
|
||||
{% if current_user.is_admin %}
|
||||
<button id="addFirstPrinterBtn" class="mt-3 sm:mt-4 bg-green-600 hover:bg-green-700 dark:bg-green-600 dark:hover:bg-green-500 text-white px-4 sm:px-6 py-1.5 sm:py-2 rounded-lg transition-all duration-200 text-sm sm:text-base">
|
||||
Ersten Drucker hinzufügen
|
||||
</button>
|
||||
{% endif %}
|
||||
` : ''}
|
||||
</div>
|
||||
`;
|
||||
|
||||
@@ -366,43 +436,55 @@
|
||||
return;
|
||||
}
|
||||
|
||||
grid.innerHTML = printers.map(printer => {
|
||||
grid.innerHTML = filteredPrinters.map(printer => {
|
||||
const statusColor = getPrinterStatusColor(printer.status);
|
||||
const statusText = getPrinterStatusText(printer.status);
|
||||
const isOnline = printer.status === 'available' || printer.is_online;
|
||||
|
||||
// Spezielle Styling für Online-Drucker
|
||||
const cardClasses = isOnline
|
||||
? 'bg-gradient-to-br from-green-50 to-white dark:from-green-900/20 dark:to-slate-800 border-green-200 dark:border-green-700 shadow-green-100 dark:shadow-green-900/20'
|
||||
: 'bg-white dark:bg-slate-800 border-slate-200 dark:border-slate-700';
|
||||
|
||||
const onlineIndicator = isOnline
|
||||
? '<div class="absolute top-2 right-2 w-3 h-3 bg-green-500 rounded-full animate-pulse shadow-lg"></div>'
|
||||
: '';
|
||||
|
||||
return `
|
||||
<div class="bg-white dark:bg-slate-800 rounded-xl p-4 sm:p-6 shadow-sm hover:shadow-lg transition-shadow duration-200 border border-slate-200 dark:border-slate-700">
|
||||
<div class="relative ${cardClasses} rounded-xl p-4 sm:p-6 shadow-sm hover:shadow-lg transition-all duration-200 border ${isOnline ? 'hover:shadow-green-200 dark:hover:shadow-green-900/30' : ''}">
|
||||
${onlineIndicator}
|
||||
|
||||
<div class="flex items-start justify-between mb-3 sm:mb-4">
|
||||
<div class="flex-1">
|
||||
<h3 class="text-base sm:text-lg font-bold text-slate-900 dark:text-white">${printer.name}</h3>
|
||||
<p class="text-xs sm:text-sm text-slate-600 dark:text-slate-400">${printer.model}</p>
|
||||
<h3 class="text-base sm:text-lg font-bold ${isOnline ? 'text-green-900 dark:text-green-100' : 'text-slate-900 dark:text-white'}">${printer.name}</h3>
|
||||
<p class="text-xs sm:text-sm ${isOnline ? 'text-green-700 dark:text-green-300' : 'text-slate-600 dark:text-slate-400'}">${printer.model}</p>
|
||||
</div>
|
||||
<div class="flex flex-col items-end">
|
||||
<span class="inline-flex items-center px-2 py-0.5 sm:px-2.5 sm:py-0.5 rounded-full text-xs font-medium ${statusColor}">
|
||||
${statusText}
|
||||
${isOnline ? '🟢 ' : '🔴 '}${statusText}
|
||||
</span>
|
||||
${printer.last_checked ? `<span class="text-xs text-slate-500 dark:text-slate-400 mt-1">Geprüft: ${formatTime(printer.last_checked)}</span>` : ''}
|
||||
${printer.last_checked ? `<span class="text-xs ${isOnline ? 'text-green-600 dark:text-green-400' : 'text-slate-500 dark:text-slate-400'} mt-1">Geprüft: ${formatTime(printer.last_checked)}</span>` : ''}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="space-y-1.5 sm:space-y-2 mb-3 sm:mb-4">
|
||||
<div class="flex items-center text-xs sm:text-sm text-slate-600 dark:text-slate-400">
|
||||
<svg class="h-3.5 w-3.5 sm:h-4 sm:w-4 mr-1.5 sm:mr-2 text-slate-500 dark:text-slate-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<div class="flex items-center text-xs sm:text-sm ${isOnline ? 'text-green-700 dark:text-green-300' : 'text-slate-600 dark:text-slate-400'}">
|
||||
<svg class="h-3.5 w-3.5 sm:h-4 sm:w-4 mr-1.5 sm:mr-2 ${isOnline ? 'text-green-600 dark:text-green-400' : 'text-slate-500 dark:text-slate-400'}" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z" />
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 11a3 3 0 11-6 0 3 3 0 016 0z" />
|
||||
</svg>
|
||||
${printer.location}
|
||||
</div>
|
||||
|
||||
<div class="flex items-center text-xs sm:text-sm text-slate-600 dark:text-slate-400">
|
||||
<svg class="h-3.5 w-3.5 sm:h-4 sm:w-4 mr-1.5 sm:mr-2 text-slate-500 dark:text-slate-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<div class="flex items-center text-xs sm:text-sm ${isOnline ? 'text-green-700 dark:text-green-300' : 'text-slate-600 dark:text-slate-400'}">
|
||||
<svg class="h-3.5 w-3.5 sm:h-4 sm:w-4 mr-1.5 sm:mr-2 ${isOnline ? 'text-green-600 dark:text-green-400' : 'text-slate-500 dark:text-slate-400'}" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
|
||||
</svg>
|
||||
${printer.mac_address}
|
||||
</div>
|
||||
|
||||
<div class="flex items-center text-xs sm:text-sm text-slate-600 dark:text-slate-400">
|
||||
<svg class="h-3.5 w-3.5 sm:h-4 sm:w-4 mr-1.5 sm:mr-2 text-slate-500 dark:text-slate-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<div class="flex items-center text-xs sm:text-sm ${isOnline ? 'text-green-700 dark:text-green-300' : 'text-slate-600 dark:text-slate-400'}">
|
||||
<svg class="h-3.5 w-3.5 sm:h-4 sm:w-4 mr-1.5 sm:mr-2 ${isOnline ? 'text-green-600 dark:text-green-400' : 'text-slate-500 dark:text-slate-400'}" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9v-9m0-9v9" />
|
||||
</svg>
|
||||
${printer.plug_ip}
|
||||
@@ -410,7 +492,7 @@
|
||||
</div>
|
||||
|
||||
<div class="flex space-x-2">
|
||||
<button class="printer-detail-btn flex-1 bg-indigo-600 hover:bg-indigo-700 dark:bg-indigo-600 dark:hover:bg-indigo-500 text-white py-1.5 sm:py-2 px-2 sm:px-3 rounded-lg text-xs sm:text-sm transition-all duration-200" data-printer-id="${printer.id}">
|
||||
<button class="printer-detail-btn flex-1 ${isOnline ? 'bg-green-600 hover:bg-green-700 dark:bg-green-600 dark:hover:bg-green-500' : 'bg-indigo-600 hover:bg-indigo-700 dark:bg-indigo-600 dark:hover:bg-indigo-500'} text-white py-1.5 sm:py-2 px-2 sm:px-3 rounded-lg text-xs sm:text-sm transition-all duration-200" data-printer-id="${printer.id}">
|
||||
Details
|
||||
</button>
|
||||
|
||||
@@ -720,14 +802,13 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Erweiterte Funktion zum Laden der Drucker mit Status-Check
|
||||
async function loadPrintersWithStatusCheck() {
|
||||
// Erweiterte Funktion zum Laden der Drucker mit Live-Status
|
||||
async function loadPrintersWithLiveStatus() {
|
||||
try {
|
||||
// Erstelle einen AbortController für Timeout
|
||||
const controller = new AbortController();
|
||||
const timeoutId = setTimeout(() => controller.abort(), 30000); // 30 Sekunden Timeout für Status-Check
|
||||
const timeoutId = setTimeout(() => controller.abort(), 20000); // 20 Sekunden Timeout für Live-Status
|
||||
|
||||
const response = await fetch('/api/printers/status', {
|
||||
const response = await fetch('/api/printers/status/live', {
|
||||
signal: controller.signal,
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
@@ -739,54 +820,205 @@
|
||||
|
||||
if (!response.ok) {
|
||||
if (response.status === 408) {
|
||||
throw new Error('Timeout beim Status-Check der Drucker. Versuchen Sie es später erneut.');
|
||||
throw new Error('Timeout beim Live-Status-Check der Drucker.');
|
||||
}
|
||||
throw new Error(`Fehler beim Laden der Drucker-Status: ${response.status} ${response.statusText}`);
|
||||
throw new Error(`Fehler beim Laden des Live-Status: ${response.status} ${response.statusText}`);
|
||||
}
|
||||
|
||||
const statusData = await response.json();
|
||||
const data = await response.json();
|
||||
|
||||
// Prüfe ob statusData ein Array ist
|
||||
if (!Array.isArray(statusData)) {
|
||||
console.error('Invalid response from /api/printers/status:', statusData);
|
||||
throw new Error('Ungültige Antwort vom Server (erwartet Array, erhalten: ' + typeof statusData + ')');
|
||||
if (data.error) {
|
||||
throw new Error(data.error);
|
||||
}
|
||||
|
||||
// Drucker-Daten mit Status-Informationen anreichern
|
||||
printers = statusData.map(printer => ({
|
||||
...printer,
|
||||
// Status ist bereits korrekt gemappt vom Backend
|
||||
status: printer.status || 'offline',
|
||||
last_checked: printer.last_checked || new Date().toISOString()
|
||||
}));
|
||||
// Drucker-Daten aktualisieren
|
||||
printers = data.printers || [];
|
||||
|
||||
// Status-Übersicht aktualisieren
|
||||
updateStatusOverview(data.online_count, data.offline_count, data.count);
|
||||
|
||||
// Drucker rendern
|
||||
renderPrinters();
|
||||
|
||||
// Erfolgs-Nachricht anzeigen
|
||||
const onlineCount = printers.filter(p => p.status === 'available').length;
|
||||
const totalCount = printers.length;
|
||||
// Auto-Update-Timer aktualisieren
|
||||
if (data.next_update) {
|
||||
nextUpdateTime = data.next_update;
|
||||
updateNextUpdateDisplay();
|
||||
}
|
||||
|
||||
if (totalCount > 0) {
|
||||
// Erfolgs-Nachricht nur bei manueller Aktualisierung
|
||||
if (!autoRefreshEnabled) {
|
||||
showStatusMessage(
|
||||
`Status-Check abgeschlossen: ${onlineCount} von ${totalCount} Drucker verfügbar`,
|
||||
onlineCount > 0 ? 'success' : 'warning'
|
||||
`Live-Status aktualisiert: ${data.online_count} von ${data.count} Drucker online`,
|
||||
data.online_count > 0 ? 'success' : 'warning'
|
||||
);
|
||||
} else {
|
||||
showStatusMessage('Keine Drucker gefunden', 'info');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error loading printer status:', error);
|
||||
showStatusMessage('Fehler beim Überprüfen der Drucker-Status: ' + error.message, 'error');
|
||||
console.error('Error loading live printer status:', error);
|
||||
if (!autoRefreshEnabled) {
|
||||
showStatusMessage('Fehler beim Live-Status-Check: ' + error.message, 'error');
|
||||
}
|
||||
// Fallback: Lade normale Drucker-Liste
|
||||
loadPrinters();
|
||||
}
|
||||
}
|
||||
|
||||
// Nur Online-Drucker laden (schnell)
|
||||
async function loadOnlinePrinters() {
|
||||
try {
|
||||
const response = await fetch('/api/printers/online');
|
||||
if (!response.ok) {
|
||||
throw new Error(`Fehler beim Laden der Online-Drucker: ${response.status}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.error) {
|
||||
throw new Error(data.error);
|
||||
}
|
||||
|
||||
return data.printers || [];
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error loading online printers:', error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
// Status-Übersicht aktualisieren
|
||||
function updateStatusOverview(onlineCount, offlineCount, totalCount) {
|
||||
document.getElementById('online-count').textContent = onlineCount || 0;
|
||||
document.getElementById('offline-count').textContent = offlineCount || 0;
|
||||
document.getElementById('total-count').textContent = totalCount || 0;
|
||||
|
||||
// Animiere die Online-Anzeige bei Änderungen
|
||||
const onlineElement = document.getElementById('online-count');
|
||||
if (onlineElement.dataset.lastValue !== String(onlineCount)) {
|
||||
onlineElement.classList.add('animate-pulse');
|
||||
setTimeout(() => onlineElement.classList.remove('animate-pulse'), 1000);
|
||||
onlineElement.dataset.lastValue = String(onlineCount);
|
||||
}
|
||||
}
|
||||
|
||||
// Auto-Refresh-Funktionalität
|
||||
function toggleAutoRefresh() {
|
||||
autoRefreshEnabled = !autoRefreshEnabled;
|
||||
const btn = document.getElementById('auto-refresh-btn');
|
||||
const icon = document.getElementById('auto-refresh-icon');
|
||||
|
||||
if (autoRefreshEnabled) {
|
||||
btn.classList.remove('bg-blue-600', 'hover:bg-blue-700');
|
||||
btn.classList.add('bg-green-600', 'hover:bg-green-700');
|
||||
btn.innerHTML = `
|
||||
<svg class="h-4 w-4 sm:h-5 sm:w-5 mr-1 sm:mr-2 animate-spin" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
|
||||
</svg>
|
||||
Auto-Update AN
|
||||
`;
|
||||
|
||||
// Starte Auto-Refresh
|
||||
startAutoRefresh();
|
||||
showStatusMessage('Auto-Update aktiviert - Drucker werden alle 30 Sekunden aktualisiert', 'info');
|
||||
} else {
|
||||
btn.classList.remove('bg-green-600', 'hover:bg-green-700');
|
||||
btn.classList.add('bg-blue-600', 'hover:bg-blue-700');
|
||||
btn.innerHTML = `
|
||||
<svg class="h-4 w-4 sm:h-5 sm:w-5 mr-1 sm:mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
Auto-Update
|
||||
`;
|
||||
|
||||
// Stoppe Auto-Refresh
|
||||
stopAutoRefresh();
|
||||
showStatusMessage('Auto-Update deaktiviert', 'info');
|
||||
}
|
||||
}
|
||||
|
||||
function startAutoRefresh() {
|
||||
stopAutoRefresh(); // Stoppe vorherige Intervalle
|
||||
|
||||
nextUpdateTime = 30;
|
||||
updateNextUpdateDisplay();
|
||||
|
||||
// Countdown-Timer
|
||||
nextUpdateCountdown = setInterval(() => {
|
||||
nextUpdateTime--;
|
||||
updateNextUpdateDisplay();
|
||||
|
||||
if (nextUpdateTime <= 0) {
|
||||
loadPrintersWithLiveStatus();
|
||||
nextUpdateTime = 30;
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
// Auto-Refresh-Interval
|
||||
autoRefreshInterval = setInterval(() => {
|
||||
loadPrintersWithLiveStatus();
|
||||
}, 30000); // Alle 30 Sekunden
|
||||
}
|
||||
|
||||
function stopAutoRefresh() {
|
||||
if (autoRefreshInterval) {
|
||||
clearInterval(autoRefreshInterval);
|
||||
autoRefreshInterval = null;
|
||||
}
|
||||
if (nextUpdateCountdown) {
|
||||
clearInterval(nextUpdateCountdown);
|
||||
nextUpdateCountdown = null;
|
||||
}
|
||||
document.getElementById('next-update-time').textContent = '-';
|
||||
}
|
||||
|
||||
function updateNextUpdateDisplay() {
|
||||
const element = document.getElementById('next-update-time');
|
||||
if (autoRefreshEnabled && nextUpdateTime > 0) {
|
||||
element.textContent = nextUpdateTime;
|
||||
element.parentElement.style.opacity = '1';
|
||||
} else {
|
||||
element.textContent = '-';
|
||||
element.parentElement.style.opacity = '0.5';
|
||||
}
|
||||
}
|
||||
|
||||
// Filter-Funktionalität
|
||||
function setupFilters() {
|
||||
const filterButtons = document.querySelectorAll('.filter-btn');
|
||||
|
||||
filterButtons.forEach(btn => {
|
||||
btn.addEventListener('click', function() {
|
||||
// Entferne active-Klasse von allen Buttons
|
||||
filterButtons.forEach(b => {
|
||||
b.classList.remove('active', 'bg-white', 'dark:bg-slate-600', 'shadow-sm');
|
||||
b.classList.add('text-slate-600', 'dark:text-slate-400');
|
||||
});
|
||||
|
||||
// Füge active-Klasse zum geklickten Button hinzu
|
||||
this.classList.add('active', 'bg-white', 'dark:bg-slate-600', 'shadow-sm');
|
||||
this.classList.remove('text-slate-600', 'dark:text-slate-400');
|
||||
|
||||
// Setze aktuellen Filter
|
||||
currentFilter = this.id.replace('filter-', '');
|
||||
|
||||
// Rendere Drucker mit Filter
|
||||
renderPrinters();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Erweiterte Funktion zum Laden der Drucker mit Status-Check (Legacy-Kompatibilität)
|
||||
async function loadPrintersWithStatusCheck() {
|
||||
return loadPrintersWithLiveStatus();
|
||||
}
|
||||
|
||||
// Initialize
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Lade Drucker beim Start
|
||||
loadPrinters();
|
||||
// Setup Filter-Buttons
|
||||
setupFilters();
|
||||
|
||||
// Lade Drucker beim Start mit Live-Status
|
||||
loadPrintersWithLiveStatus();
|
||||
|
||||
// Event-Listener für den "Drucker hinzufügen" Button
|
||||
const addPrinterBtn = document.getElementById('addPrinterBtn');
|
||||
@@ -837,6 +1069,19 @@
|
||||
hidePrinterDetailModal();
|
||||
}
|
||||
});
|
||||
|
||||
// Auto-Refresh bei Sichtbarkeitsänderung der Seite
|
||||
document.addEventListener('visibilitychange', function() {
|
||||
if (!document.hidden && autoRefreshEnabled) {
|
||||
// Seite ist wieder sichtbar und Auto-Refresh ist aktiv
|
||||
loadPrintersWithLiveStatus();
|
||||
}
|
||||
});
|
||||
|
||||
// Cleanup bei Seitenverlassen
|
||||
window.addEventListener('beforeunload', function() {
|
||||
stopAutoRefresh();
|
||||
});
|
||||
});
|
||||
|
||||
// Make all functions globally available for onclick handlers
|
||||
@@ -845,6 +1090,9 @@
|
||||
window.deletePrinter = deletePrinter;
|
||||
window.loadPrinters = loadPrinters;
|
||||
window.handleAddPrinter = handleAddPrinter;
|
||||
window.toggleAutoRefresh = toggleAutoRefresh;
|
||||
window.loadPrintersWithLiveStatus = loadPrintersWithLiveStatus;
|
||||
window.loadOnlinePrinters = loadOnlinePrinters;
|
||||
|
||||
// Debug: Log that functions are available
|
||||
console.log('All printer functions loaded and available globally:', {
|
||||
|
Reference in New Issue
Block a user