"Update database schema for printer functionality (feat)"
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -142,116 +142,231 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Drucker Detail Modal - Komplett überarbeitet mit expliziter hidden-Klasse -->
|
||||
<div id="printerDetailModal" class="modal-new hidden" style="display: none !important; visibility: hidden !important;">
|
||||
<div class="modal-content-new max-w-lg">
|
||||
<div class="flex items-center justify-between mb-5">
|
||||
<h2 class="text-xl sm:text-2xl font-bold text-slate-900 dark:text-white">Drucker Details</h2>
|
||||
<button id="closePrinterDetailBtn" class="text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-white transition-colors">
|
||||
<svg class="h-5 w-5 sm:h-6 sm:w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
||||
<!-- Drucker Detail Modal -->
|
||||
<div id="printerDetailModal" class="fixed inset-0 bg-black/60 backdrop-blur-sm hidden z-50">
|
||||
<div class="flex items-center justify-center min-h-screen p-4">
|
||||
<div class="professional-container max-w-2xl w-full p-8 transform transition-all duration-500 scale-95 opacity-0" id="printerModalContent">
|
||||
<div class="flex justify-between items-center mb-8">
|
||||
<div>
|
||||
<h3 class="text-2xl font-bold text-professional-primary mb-2">Drucker Details</h3>
|
||||
<p class="text-professional-muted">Detaillierte Informationen zu Ihrem 3D-Drucker</p>
|
||||
</div>
|
||||
<button id="closePrinterDetailBtn" class="p-2 hover:bg-slate-100 dark:hover:bg-slate-700 rounded-xl transition-colors duration-200">
|
||||
<svg class="w-6 h-6 text-professional-muted hover:text-professional-primary" 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>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div id="printer-detail-content">
|
||||
<!-- Content will be loaded here -->
|
||||
<!-- Inhalt wird dynamisch geladen -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Add Printer Modal - Komplett überarbeitet mit expliziter hidden-Klasse -->
|
||||
<!-- Add Printer Modal -->
|
||||
{% if current_user.is_admin %}
|
||||
<div id="addPrinterModal" class="modal-new hidden" style="display: none !important; visibility: hidden !important;">
|
||||
<div class="modal-content-new">
|
||||
<div class="flex items-center justify-between mb-5">
|
||||
<h2 class="text-xl sm:text-2xl font-bold text-slate-900 dark:text-white">Neuen Drucker hinzufügen</h2>
|
||||
<button id="closeAddPrinterBtn" class="text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-white transition-colors">
|
||||
<svg class="h-5 w-5 sm:h-6 sm:w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
||||
<div id="addPrinterModal" class="fixed inset-0 bg-black/60 backdrop-blur-sm hidden z-50">
|
||||
<div class="flex items-center justify-center min-h-screen p-4">
|
||||
<div class="professional-container max-w-lg w-full p-8 transform transition-all duration-500 scale-95 opacity-0" id="addPrinterModalContent">
|
||||
<div class="flex justify-between items-center mb-8">
|
||||
<div>
|
||||
<h3 class="text-2xl font-bold text-professional-primary mb-2">Neuen Drucker hinzufügen</h3>
|
||||
<p class="text-professional-muted">Konfigurieren Sie einen neuen 3D-Drucker</p>
|
||||
</div>
|
||||
<button id="closeAddPrinterBtn" class="p-2 hover:bg-slate-100 dark:hover:bg-slate-700 rounded-xl transition-colors duration-200">
|
||||
<svg class="w-6 h-6 text-professional-muted hover:text-professional-primary" 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>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<form id="addPrinterForm" class="space-y-4">
|
||||
<div>
|
||||
<label for="printer-name" class="form-label-new">Name</label>
|
||||
<form id="addPrinterForm" class="space-y-6">
|
||||
<div class="grid grid-cols-1 gap-6">
|
||||
<div class="group">
|
||||
<label for="printer-name" class="block text-sm font-semibold text-professional-primary mb-3">
|
||||
Drucker Name <span class="text-red-500">*</span>
|
||||
</label>
|
||||
<input type="text" id="printer-name" name="name" required
|
||||
class="input-new" placeholder="z.B. Printer 1">
|
||||
class="input-professional" placeholder="z.B. Printer 1">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="printer-model" class="form-label-new">Modell</label>
|
||||
<div class="group">
|
||||
<label for="printer-model" class="block text-sm font-semibold text-professional-primary mb-3">
|
||||
Modell <span class="text-red-500">*</span>
|
||||
</label>
|
||||
<input type="text" id="printer-model" name="model" required
|
||||
class="input-new" placeholder="z.B. P115">
|
||||
class="input-professional" placeholder="z.B. P115">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="printer-location" class="form-label-new">Standort</label>
|
||||
<div class="group">
|
||||
<label for="printer-location" class="block text-sm font-semibold text-professional-primary mb-3">
|
||||
Standort <span class="text-red-500">*</span>
|
||||
</label>
|
||||
<input type="text" id="printer-location" name="location" required
|
||||
class="input-new" placeholder="z.B. Werk 040 - Berlin - TBA">
|
||||
class="input-professional" placeholder="z.B. Werk 040 - Berlin - TBA">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="printer-mac" class="form-label-new">MAC-Adresse</label>
|
||||
<div class="group">
|
||||
<label for="printer-mac" class="block text-sm font-semibold text-professional-primary mb-3">
|
||||
MAC-Adresse <span class="text-red-500">*</span>
|
||||
</label>
|
||||
<input type="text" id="printer-mac" name="mac_address" required
|
||||
placeholder="AA:BB:CC:DD:EE:FF"
|
||||
class="input-new">
|
||||
class="input-professional font-mono">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="printer-ip" class="form-label-new">Plug IP-Adresse</label>
|
||||
<div class="group">
|
||||
<label for="printer-ip" class="block text-sm font-semibold text-professional-primary mb-3">
|
||||
Plug IP-Adresse <span class="text-red-500">*</span>
|
||||
</label>
|
||||
<input type="text" id="printer-ip" name="plug_ip" required
|
||||
placeholder="192.168.1.100"
|
||||
class="input-new">
|
||||
class="input-professional font-mono">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="printer-plug-username" class="form-label-new">Plug Benutzername</label>
|
||||
<div class="group">
|
||||
<label for="printer-plug-username" class="block text-sm font-semibold text-professional-primary mb-3">
|
||||
Plug Benutzername <span class="text-red-500">*</span>
|
||||
</label>
|
||||
<input type="text" id="printer-plug-username" name="plug_username" required
|
||||
placeholder="admin"
|
||||
class="input-new">
|
||||
class="input-professional">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="printer-plug-password" class="form-label-new">Plug Passwort</label>
|
||||
<div class="group">
|
||||
<label for="printer-plug-password" class="block text-sm font-semibold text-professional-primary mb-3">
|
||||
Plug Passwort <span class="text-red-500">*</span>
|
||||
</label>
|
||||
<input type="password" id="printer-plug-password" name="plug_password" required
|
||||
placeholder="••••••••"
|
||||
class="input-new">
|
||||
class="input-professional">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex gap-3 pt-3">
|
||||
<div class="flex items-center justify-end space-x-4 pt-8 border-t border-slate-200 dark:border-slate-600">
|
||||
<button type="button" id="cancelAddPrinterBtn"
|
||||
class="flex-1 action-btn-new bg-slate-200 hover:bg-slate-300 text-slate-800 dark:bg-slate-700 dark:hover:bg-slate-600 dark:text-white">
|
||||
class="btn-secondary-professional">
|
||||
Abbrechen
|
||||
</button>
|
||||
<button type="submit"
|
||||
class="flex-1 action-btn-new success">
|
||||
Hinzufügen
|
||||
class="btn-success-professional group">
|
||||
<svg class="w-5 h-5 mr-3 group-hover:scale-110 transition-transform duration-300" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6"/>
|
||||
</svg>
|
||||
<span>Drucker hinzufügen</span>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<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
|
||||
// Live Time Update
|
||||
function updateLiveTime() {
|
||||
const now = new Date();
|
||||
const timeElement = document.getElementById('live-time');
|
||||
if (timeElement) {
|
||||
timeElement.textContent = now.toLocaleTimeString('de-DE');
|
||||
}
|
||||
}
|
||||
updateLiveTime();
|
||||
setInterval(updateLiveTime, 1000);
|
||||
|
||||
// Sicherstellen, dass alle Modals initial versteckt sind
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Filter Button Styling
|
||||
function setupFilterButtons() {
|
||||
const filterButtons = document.querySelectorAll('.filter-btn-mercedes');
|
||||
|
||||
filterButtons.forEach(btn => {
|
||||
btn.addEventListener('click', function() {
|
||||
// Remove active class from all buttons
|
||||
filterButtons.forEach(b => {
|
||||
b.classList.remove('active');
|
||||
b.classList.remove('bg-professional-accent', 'text-white');
|
||||
b.classList.add('text-professional-muted', 'hover:text-professional-primary');
|
||||
});
|
||||
|
||||
// Add active class to clicked button
|
||||
this.classList.add('active');
|
||||
this.classList.remove('text-professional-muted', 'hover:text-professional-primary');
|
||||
this.classList.add('bg-professional-accent', 'text-white');
|
||||
|
||||
// Update filter
|
||||
const filterId = this.id;
|
||||
if (filterId === 'filter-all') {
|
||||
currentFilter = 'all';
|
||||
} else if (filterId === 'filter-online') {
|
||||
currentFilter = 'online';
|
||||
} else if (filterId === 'filter-offline') {
|
||||
currentFilter = 'offline';
|
||||
}
|
||||
|
||||
// Re-render printers with new filter
|
||||
renderPrinters();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Modal Animations - Professional Mercedes Style
|
||||
function showModal(modalId) {
|
||||
const modal = document.getElementById(modalId);
|
||||
const content = modal.querySelector('.professional-container');
|
||||
|
||||
if (!modal || !content) {
|
||||
console.error('Modal or content not found:', modalId);
|
||||
return;
|
||||
}
|
||||
|
||||
modal.classList.remove('hidden');
|
||||
modal.style.display = '';
|
||||
modal.style.visibility = '';
|
||||
modal.setAttribute('aria-hidden', 'false');
|
||||
|
||||
setTimeout(() => {
|
||||
content.classList.remove('scale-95', 'opacity-0');
|
||||
content.classList.add('scale-100', 'opacity-100');
|
||||
}, 10);
|
||||
}
|
||||
|
||||
function hideModal(modalId) {
|
||||
const modal = document.getElementById(modalId);
|
||||
const content = modal.querySelector('.professional-container');
|
||||
|
||||
if (!modal || !content) {
|
||||
console.error('Modal or content not found:', modalId);
|
||||
return;
|
||||
}
|
||||
|
||||
content.classList.remove('scale-100', 'opacity-100');
|
||||
content.classList.add('scale-95', 'opacity-0');
|
||||
|
||||
setTimeout(() => {
|
||||
modal.classList.add('hidden');
|
||||
modal.style.display = 'none';
|
||||
modal.style.visibility = 'hidden';
|
||||
modal.setAttribute('aria-hidden', 'true');
|
||||
}, 200);
|
||||
}
|
||||
|
||||
// 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
|
||||
|
||||
// Sicherstellen, dass alle Modals initial versteckt sind
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
console.log("DOM vollständig geladen, initialisiere Seite...");
|
||||
|
||||
// WICHTIG: Sofort alle Modals verstecken (mit mehreren Methoden)
|
||||
const modalElements = document.querySelectorAll('.modal-new');
|
||||
const modalElements = document.querySelectorAll('[id$="Modal"]');
|
||||
modalElements.forEach(modal => {
|
||||
// Mehrere Ansätze kombinieren für maximale Sicherheit
|
||||
modal.classList.add('hidden');
|
||||
@@ -262,15 +377,15 @@
|
||||
|
||||
// Verzögerte Initialisierung
|
||||
setTimeout(initializePrintersPage, 500);
|
||||
});
|
||||
});
|
||||
|
||||
// Hauptinitialisierungsfunktion
|
||||
function initializePrintersPage() {
|
||||
// Hauptinitialisierungsfunktion
|
||||
function initializePrintersPage() {
|
||||
try {
|
||||
console.log("Initialisiere Drucker-Seite...");
|
||||
|
||||
// Filter-Buttons einrichten
|
||||
setupFilters();
|
||||
setupFilterButtons();
|
||||
|
||||
// Event-Listener für Buttons und Modals initialisieren
|
||||
setupEventListeners();
|
||||
@@ -297,10 +412,10 @@
|
||||
console.error("Kritischer Fehler bei der Initialisierung:", error);
|
||||
showError("Ein Fehler ist bei der Initialisierung aufgetreten. Bitte laden Sie die Seite neu.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Event-Listener für Buttons und Modals
|
||||
function setupEventListeners() {
|
||||
// Event-Listener für Buttons und Modals
|
||||
function setupEventListeners() {
|
||||
// "Drucker hinzufügen" Button
|
||||
const addPrinterBtn = document.getElementById('addPrinterBtn');
|
||||
if (addPrinterBtn) {
|
||||
@@ -336,28 +451,10 @@
|
||||
hideAllModals();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Refresh-Button
|
||||
const refreshBtn = document.querySelector('button[onclick="refreshPrinters()"]');
|
||||
if (refreshBtn) {
|
||||
refreshBtn.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
refreshPrinters();
|
||||
});
|
||||
}
|
||||
|
||||
// Auto-Refresh-Button
|
||||
const autoRefreshBtn = document.getElementById('auto-refresh-btn');
|
||||
if (autoRefreshBtn) {
|
||||
autoRefreshBtn.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
toggleAutoRefresh();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Hilfsfunktion für Schließen-Buttons
|
||||
function setupCloseButtons(buttonId, closeFunction) {
|
||||
// Hilfsfunktion für Schließen-Buttons
|
||||
function setupCloseButtons(buttonId, closeFunction) {
|
||||
const button = document.getElementById(buttonId);
|
||||
if (button) {
|
||||
button.addEventListener('click', function(e) {
|
||||
@@ -366,10 +463,10 @@
|
||||
closeFunction();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Hilfsfunktion für Klick außerhalb
|
||||
function setupOutsideClickHandler(modalId, closeFunction) {
|
||||
// Hilfsfunktion für Klick außerhalb
|
||||
function setupOutsideClickHandler(modalId, closeFunction) {
|
||||
const modal = document.getElementById(modalId);
|
||||
if (modal) {
|
||||
modal.addEventListener('click', function(e) {
|
||||
@@ -380,146 +477,36 @@
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Alle Modals ausblenden
|
||||
function hideAllModals() {
|
||||
// Alle Modals ausblenden
|
||||
function hideAllModals() {
|
||||
hideAddPrinterModal();
|
||||
hidePrinterDetailModal();
|
||||
}
|
||||
|
||||
// Modal-Steuerungsfunktionen
|
||||
function showAddPrinterModal() {
|
||||
const modal = document.getElementById('addPrinterModal');
|
||||
if (!modal) return;
|
||||
}
|
||||
|
||||
// Modal-Steuerungsfunktionen
|
||||
function showAddPrinterModal() {
|
||||
console.log("Öffne 'Drucker hinzufügen' Modal");
|
||||
modal.classList.remove('hidden');
|
||||
modal.style.display = '';
|
||||
modal.style.visibility = '';
|
||||
modal.setAttribute('aria-hidden', 'false');
|
||||
}
|
||||
|
||||
function hideAddPrinterModal() {
|
||||
const modal = document.getElementById('addPrinterModal');
|
||||
if (!modal) return;
|
||||
showModal('addPrinterModal');
|
||||
}
|
||||
|
||||
function hideAddPrinterModal() {
|
||||
console.log("Schließe 'Drucker hinzufügen' Modal");
|
||||
modal.classList.add('hidden');
|
||||
modal.style.display = 'none';
|
||||
modal.style.visibility = 'hidden';
|
||||
modal.setAttribute('aria-hidden', 'true');
|
||||
hideModal('addPrinterModal');
|
||||
|
||||
// Formular zurücksetzen
|
||||
const form = document.getElementById('addPrinterForm');
|
||||
if (form) form.reset();
|
||||
}
|
||||
|
||||
function showPrinterDetail(printerId) {
|
||||
// Drucker-Details finden
|
||||
const printer = printers.find(p => p.id === printerId);
|
||||
if (!printer) {
|
||||
console.error("Drucker nicht gefunden:", printerId);
|
||||
return;
|
||||
}
|
||||
|
||||
// Detail-Inhalt aktualisieren
|
||||
const content = document.getElementById('printer-detail-content');
|
||||
if (!content) {
|
||||
console.error("printer-detail-content Element nicht gefunden");
|
||||
return;
|
||||
}
|
||||
|
||||
// Prüfen, ob das Modal existiert
|
||||
const modal = document.getElementById('printerDetailModal');
|
||||
if (!modal) {
|
||||
console.error("printerDetailModal Element nicht gefunden");
|
||||
return;
|
||||
}
|
||||
|
||||
// Modal-Inhalt mit Drucker-Daten füllen
|
||||
const isOnline = printer.status === 'available' || printer.is_online;
|
||||
content.innerHTML = `
|
||||
<div class="space-y-4">
|
||||
<div class="${isOnline ? 'bg-green-50/80 dark:bg-green-900/30' : 'bg-slate-50/80 dark:bg-slate-700/30'} rounded-lg p-3 sm:p-4 backdrop-blur-sm border ${isOnline ? 'border-green-200 dark:border-green-800/30' : 'border-slate-200 dark:border-slate-600/30'}">
|
||||
<h3 class="font-semibold ${isOnline ? 'text-green-800 dark:text-green-300' : 'text-slate-900 dark:text-white'} text-lg mb-1">${printer.name}</h3>
|
||||
<p class="text-sm ${isOnline ? 'text-green-700 dark:text-green-400' : 'text-slate-600 dark:text-slate-400'}">${printer.model}</p>
|
||||
|
||||
<div class="mt-3 flex items-center gap-2">
|
||||
<span class="status-badge-new ${isOnline ? 'online' : 'offline'}">
|
||||
${isOnline ? '🟢' : '🔴'} ${getPrinterStatusText(printer.status)}
|
||||
</span>
|
||||
${printer.last_checked ?
|
||||
`<span class="text-xs ${isOnline ? 'text-green-600 dark:text-green-400' : 'text-slate-500 dark:text-slate-400'}">
|
||||
Zuletzt geprüft: ${formatDate(printer.last_checked)}
|
||||
</span>` : ''}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 gap-3 sm:gap-4">
|
||||
<div class="bg-white/60 dark:bg-slate-800/60 rounded-lg p-3 backdrop-blur-sm border border-slate-200/60 dark:border-slate-700/30">
|
||||
<div class="text-xs uppercase font-semibold text-slate-500 dark:text-slate-400 mb-1.5">Standort</div>
|
||||
<div class="text-sm text-slate-900 dark:text-white">${printer.location}</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-white/60 dark:bg-slate-800/60 rounded-lg p-3 backdrop-blur-sm border border-slate-200/60 dark:border-slate-700/30">
|
||||
<div class="text-xs uppercase font-semibold text-slate-500 dark:text-slate-400 mb-1.5">MAC-Adresse</div>
|
||||
<div class="text-sm text-slate-900 dark:text-white font-mono">${printer.mac_address}</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-white/60 dark:bg-slate-800/60 rounded-lg p-3 backdrop-blur-sm border border-slate-200/60 dark:border-slate-700/30">
|
||||
<div class="text-xs uppercase font-semibold text-slate-500 dark:text-slate-400 mb-1.5">Plug IP</div>
|
||||
<div class="text-sm text-slate-900 dark:text-white font-mono">${printer.plug_ip}</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-white/60 dark:bg-slate-800/60 rounded-lg p-3 backdrop-blur-sm border border-slate-200/60 dark:border-slate-700/30">
|
||||
<div class="text-xs uppercase font-semibold text-slate-500 dark:text-slate-400 mb-1.5">Erstellt am</div>
|
||||
<div class="text-sm text-slate-900 dark:text-white">${formatDate(printer.created_at)}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="border-t border-slate-200 dark:border-slate-700 pt-4 mt-4">
|
||||
<div class="flex gap-3">
|
||||
<button onclick="hidePrinterDetailModal()"
|
||||
class="flex-1 action-btn-new bg-slate-200 hover:bg-slate-300 text-slate-800 dark:bg-slate-700 dark:hover:bg-slate-600 dark:text-white">
|
||||
Schließen
|
||||
</button>
|
||||
|
||||
{% if current_user.is_admin %}
|
||||
<button onclick="deletePrinter(${printer.id}); hidePrinterDetailModal();"
|
||||
class="flex-1 action-btn-new danger">
|
||||
<svg class="h-4 w-4 mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
|
||||
</svg>
|
||||
Löschen
|
||||
</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Modal anzeigen
|
||||
console.log("Öffne Drucker-Details Modal für Drucker:", printerId);
|
||||
modal.classList.remove('hidden');
|
||||
modal.style.display = '';
|
||||
modal.style.visibility = '';
|
||||
modal.setAttribute('aria-hidden', 'false');
|
||||
}
|
||||
|
||||
function hidePrinterDetailModal() {
|
||||
const modal = document.getElementById('printerDetailModal');
|
||||
if (!modal) return;
|
||||
}
|
||||
|
||||
function hidePrinterDetailModal() {
|
||||
console.log("Schließe Drucker-Details Modal");
|
||||
modal.classList.add('hidden');
|
||||
modal.style.display = 'none';
|
||||
modal.style.visibility = 'hidden';
|
||||
modal.setAttribute('aria-hidden', 'true');
|
||||
}
|
||||
hideModal('printerDetailModal');
|
||||
}
|
||||
|
||||
// Render printers grid mit Filter-Unterstützung
|
||||
function renderPrinters() {
|
||||
// Render printers grid mit Filter-Unterstützung - Mercedes Professional Style
|
||||
function renderPrinters() {
|
||||
const grid = document.getElementById('printers-grid');
|
||||
if (!grid) {
|
||||
console.error('printers-grid Element nicht gefunden');
|
||||
@@ -550,32 +537,36 @@
|
||||
}
|
||||
|
||||
grid.innerHTML = `
|
||||
<div class="col-span-full text-center py-8 sm:py-12">
|
||||
<svg class="h-14 w-14 sm:h-16 sm:w-16 text-slate-300 dark:text-slate-600 mx-auto mb-4 sm:mb-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" 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" />
|
||||
<div class="col-span-full text-center py-12">
|
||||
<div class="mb-glass rounded-3xl p-12 max-w-md mx-auto">
|
||||
<svg class="h-16 w-16 text-professional-muted mx-auto mb-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" 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 font-medium">${emptyMessage}</p>
|
||||
<h3 class="text-xl font-bold text-professional-primary mb-3">${emptyMessage}</h3>
|
||||
<p class="text-professional-muted mb-6">
|
||||
${currentFilter === 'all' && printers.length === 0 ?
|
||||
'Fügen Sie Ihren ersten 3D-Drucker hinzu, um loszulegen.' :
|
||||
'Versuchen Sie einen anderen Filter oder aktualisieren Sie die Ansicht.'}
|
||||
</p>
|
||||
|
||||
${currentFilter === 'all' && printers.length === 0 ? `
|
||||
{% if current_user.is_admin %}
|
||||
<button id="addFirstPrinterBtn" class="mt-4 sm:mt-5 action-btn-new success">
|
||||
<svg class="h-4 w-4 sm:h-5 sm:w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6" />
|
||||
<button id="addFirstPrinterBtn" class="btn-success-professional group">
|
||||
<svg class="w-6 h-6 mr-3 group-hover:scale-110 transition-transform duration-300" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6"/>
|
||||
</svg>
|
||||
<span>Ersten Drucker hinzufügen</span>
|
||||
</button>
|
||||
{% endif %}
|
||||
` : ''}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Event-Listener für den "Ersten Drucker hinzufügen" Button
|
||||
const addFirstPrinterBtn = document.getElementById('addFirstPrinterBtn');
|
||||
if (addFirstPrinterBtn) {
|
||||
// Entferne vorherige Event-Listener, um doppelte Registrierung zu vermeiden
|
||||
const clonedBtn = addFirstPrinterBtn.cloneNode(true);
|
||||
addFirstPrinterBtn.parentNode.replaceChild(clonedBtn, addFirstPrinterBtn);
|
||||
|
||||
clonedBtn.addEventListener('click', function(e) {
|
||||
addFirstPrinterBtn.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
showAddPrinterModal();
|
||||
@@ -590,103 +581,85 @@
|
||||
const statusText = getPrinterStatusText(printer.status);
|
||||
|
||||
return `
|
||||
<div class="printer-card-new ${isOnline ? 'online' : ''}">
|
||||
${isOnline ? '<div class="online-indicator"></div>' : ''}
|
||||
<div class="mb-glass p-6 rounded-3xl border border-white/20 dark:border-white/10 hover:border-professional-accent/50 dark:hover:border-professional-accent/30 transition-all duration-300 group cursor-pointer transform hover:scale-105 ${isOnline ? 'ring-2 ring-green-500/20 dark:ring-green-400/20' : ''}" onclick="showPrinterDetail(${printer.id})">
|
||||
|
||||
<div class="flex items-start justify-between mb-4">
|
||||
<div>
|
||||
<h3 class="text-base sm:text-lg font-bold ${isOnline ? 'text-green-800 dark:text-green-300' : 'text-slate-900 dark:text-white'}">${printer.name}</h3>
|
||||
<p class="text-xs sm:text-sm ${isOnline ? 'text-green-700 dark:text-green-400' : 'text-slate-600 dark:text-slate-400'}">${printer.model}</p>
|
||||
</div>
|
||||
<div class="flex flex-col items-end">
|
||||
<span class="status-badge-new ${isOnline ? 'online' : 'offline'}">
|
||||
<!-- Status Indicator -->
|
||||
${isOnline ? '<div class="absolute -top-2 -right-2 w-6 h-6 bg-green-500 rounded-full border-4 border-white dark:border-slate-800 animate-pulse"></div>' : ''}
|
||||
|
||||
<!-- Header -->
|
||||
<div class="flex items-start justify-between mb-6">
|
||||
<div class="flex-1">
|
||||
<h3 class="text-xl font-bold text-professional-primary mb-2 group-hover:text-professional-accent transition-colors duration-300">${printer.name}</h3>
|
||||
<p class="text-professional-secondary mb-3">${printer.model}</p>
|
||||
|
||||
<!-- Status Badge -->
|
||||
<div class="inline-flex items-center px-3 py-1 rounded-full text-sm font-semibold ${isOnline ? 'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-300' : 'bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-300'}">
|
||||
${isOnline ? '🟢' : '🔴'} ${statusText}
|
||||
</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.5">
|
||||
Geprüft: ${formatTime(printer.last_checked)}
|
||||
</span>` : ''}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="space-y-2 mb-4">
|
||||
<div class="printer-info-row">
|
||||
<svg class="printer-info-icon" 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" />
|
||||
<!-- Action Icon -->
|
||||
<div class="w-10 h-10 bg-gradient-to-br from-professional-accent/20 to-professional-primary/20 rounded-xl flex items-center justify-center group-hover:from-professional-accent/30 group-hover:to-professional-primary/30 transition-all duration-300">
|
||||
<svg class="w-5 h-5 text-professional-accent group-hover:scale-110 transition-transform duration-300" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
|
||||
</svg>
|
||||
<span>${printer.location}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="printer-info-row">
|
||||
<svg class="printer-info-icon" 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" />
|
||||
<!-- Details -->
|
||||
<div class="space-y-3 mb-6">
|
||||
<div class="flex items-center space-x-3 text-sm text-professional-secondary">
|
||||
<svg class="w-4 h-4 text-professional-accent" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<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>
|
||||
<span class="truncate">${printer.location}</span>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center space-x-3 text-sm text-professional-muted">
|
||||
<svg class="w-4 h-4 text-professional-accent" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<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>
|
||||
<span class="font-mono text-xs">${printer.mac_address}</span>
|
||||
</div>
|
||||
|
||||
<div class="printer-info-row">
|
||||
<svg class="printer-info-icon" 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" />
|
||||
<div class="flex items-center space-x-3 text-sm text-professional-muted">
|
||||
<svg class="w-4 h-4 text-professional-accent" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<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>
|
||||
<span class="font-mono text-xs">${printer.plug_ip}</span>
|
||||
</div>
|
||||
|
||||
${printer.last_checked ?
|
||||
`<div class="flex items-center space-x-3 text-xs text-professional-muted">
|
||||
<svg class="w-4 h-4 text-professional-accent" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<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>
|
||||
<span>Geprüft: ${formatTime(printer.last_checked)}</span>
|
||||
</div>` : ''}
|
||||
</div>
|
||||
|
||||
<div class="flex gap-2">
|
||||
<button class="printer-detail-btn flex-1 action-btn-new primary text-xs" data-printer-id="${printer.id}">
|
||||
Details
|
||||
</button>
|
||||
<!-- Actions -->
|
||||
<div class="flex gap-3">
|
||||
<div class="flex-1 btn-professional-mini text-center opacity-80 group-hover:opacity-100 transition-opacity duration-300">
|
||||
Details anzeigen
|
||||
</div>
|
||||
|
||||
{% if current_user.is_admin %}
|
||||
<button class="delete-printer-btn flex-1 action-btn-new danger text-xs" data-printer-id="${printer.id}">
|
||||
<svg class="h-3.5 w-3.5 sm:h-4 sm:w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
|
||||
<button class="btn-danger-professional-mini" onclick="event.stopPropagation(); deletePrinter(${printer.id});">
|
||||
<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="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"/>
|
||||
</svg>
|
||||
Löschen
|
||||
</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}).join('');
|
||||
}
|
||||
|
||||
// Sichere Ereignisbehandlung: Alte Event-Listener entfernen, indem wir neue Listener hinzufügen
|
||||
document.querySelectorAll('.printer-detail-btn').forEach(btn => {
|
||||
// Entferne alte Listener durch Klon-Ersetzung
|
||||
const clonedBtn = btn.cloneNode(true);
|
||||
btn.parentNode.replaceChild(clonedBtn, btn);
|
||||
|
||||
// Füge neuen Listener hinzu
|
||||
clonedBtn.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
const printerId = parseInt(this.getAttribute('data-printer-id'));
|
||||
if (printerId) {
|
||||
showPrinterDetail(printerId);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
document.querySelectorAll('.delete-printer-btn').forEach(btn => {
|
||||
// Entferne alte Listener durch Klon-Ersetzung
|
||||
const clonedBtn = btn.cloneNode(true);
|
||||
btn.parentNode.replaceChild(clonedBtn, btn);
|
||||
|
||||
// Füge neuen Listener hinzu
|
||||
clonedBtn.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
const printerId = parseInt(this.getAttribute('data-printer-id'));
|
||||
if (printerId) {
|
||||
deletePrinter(printerId);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Helper functions
|
||||
function getPrinterStatusColor(status) {
|
||||
// Helper functions
|
||||
function getPrinterStatusColor(status) {
|
||||
switch (status) {
|
||||
case 'available': return 'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-300';
|
||||
case 'busy': return 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900/30 dark:text-yellow-300';
|
||||
@@ -694,9 +667,9 @@
|
||||
case 'maintenance': return 'bg-slate-200 text-slate-800 dark:bg-slate-700 dark:text-slate-300';
|
||||
default: return 'bg-slate-200 text-slate-800 dark:bg-slate-700 dark:text-slate-300';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getPrinterStatusText(status) {
|
||||
function getPrinterStatusText(status) {
|
||||
switch (status) {
|
||||
case 'available': return 'Steckdose AN';
|
||||
case 'busy': return 'Beschäftigt';
|
||||
@@ -704,10 +677,10 @@
|
||||
case 'maintenance': return 'Wartung';
|
||||
default: return 'Unbekannt';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Format date helper
|
||||
function formatDate(dateString) {
|
||||
// Format date helper
|
||||
function formatDate(dateString) {
|
||||
if (!dateString) return 'Unbekannt';
|
||||
try {
|
||||
const date = new Date(dateString);
|
||||
@@ -716,10 +689,10 @@
|
||||
console.error('Fehler beim Formatieren des Datums:', e);
|
||||
return 'Ungültiges Datum';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Format time helper für Status-Zeitstempel
|
||||
function formatTime(dateString) {
|
||||
// Format time helper für Status-Zeitstempel
|
||||
function formatTime(dateString) {
|
||||
if (!dateString) return 'Unbekannt';
|
||||
try {
|
||||
const date = new Date(dateString);
|
||||
@@ -739,10 +712,10 @@
|
||||
console.error('Fehler beim Formatieren der Zeit:', e);
|
||||
return 'Ungültige Zeit';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Refresh printers mit Status-Check - Make it globally available
|
||||
function refreshPrinters() {
|
||||
// Refresh printers mit Status-Check - Make it globally available
|
||||
function refreshPrinters() {
|
||||
console.log('refreshPrinters function called');
|
||||
const grid = document.getElementById('printers-grid');
|
||||
const refreshBtn = document.querySelector('button[onclick="refreshPrinters()"]');
|
||||
@@ -781,10 +754,10 @@
|
||||
`;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Show error message
|
||||
function showError(message) {
|
||||
// Show error message
|
||||
function showError(message) {
|
||||
const grid = document.getElementById('printers-grid');
|
||||
if (!grid) return;
|
||||
|
||||
@@ -814,10 +787,10 @@
|
||||
</p>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
// Show status message (success, info, warning, error)
|
||||
function showStatusMessage(message, type = 'info') {
|
||||
// Show status message (success, info, warning, error)
|
||||
function showStatusMessage(message, type = 'info') {
|
||||
// Vorzeitig beenden, wenn der Ladevorgang noch nicht abgeschlossen ist
|
||||
if (document.readyState !== 'complete') {
|
||||
console.log('Status-Nachricht unterdrückt während des Ladens:', message);
|
||||
@@ -879,10 +852,10 @@
|
||||
statusMessage.remove();
|
||||
}
|
||||
}, 5000);
|
||||
}
|
||||
}
|
||||
|
||||
// Load printers (schnelles Laden ohne Status-Check)
|
||||
async function loadPrinters() {
|
||||
// Load printers (schnelles Laden ohne Status-Check)
|
||||
async function loadPrinters() {
|
||||
const grid = document.getElementById('printers-grid');
|
||||
if (!grid) return;
|
||||
|
||||
@@ -950,10 +923,10 @@
|
||||
showError(errorMessage);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Status-Übersicht aktualisieren
|
||||
function updateStatusOverview(onlineCount, offlineCount, totalCount) {
|
||||
// Status-Übersicht aktualisieren
|
||||
function updateStatusOverview(onlineCount, offlineCount, totalCount) {
|
||||
const onlineElement = document.getElementById('online-count');
|
||||
const offlineElement = document.getElementById('offline-count');
|
||||
const totalElement = document.getElementById('total-count');
|
||||
@@ -968,10 +941,10 @@
|
||||
setTimeout(() => onlineElement.classList.remove('animate-pulse'), 1000);
|
||||
onlineElement.dataset.lastValue = String(onlineCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Erweiterte Funktion zum Laden der Drucker mit Live-Status
|
||||
async function loadPrintersWithLiveStatus() {
|
||||
// Erweiterte Funktion zum Laden der Drucker mit Live-Status
|
||||
async function loadPrintersWithLiveStatus() {
|
||||
try {
|
||||
const controller = new AbortController();
|
||||
const timeoutId = setTimeout(() => controller.abort(), 20000); // 20 Sekunden Timeout für Live-Status
|
||||
@@ -1039,10 +1012,10 @@
|
||||
return false; // Auch Fallback fehlgeschlagen
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Auto-Refresh-Funktionalität
|
||||
function toggleAutoRefresh() {
|
||||
// Auto-Refresh-Funktionalität
|
||||
function toggleAutoRefresh() {
|
||||
autoRefreshEnabled = !autoRefreshEnabled;
|
||||
const btn = document.getElementById('auto-refresh-btn');
|
||||
const icon = document.getElementById('auto-refresh-icon');
|
||||
@@ -1078,9 +1051,9 @@
|
||||
stopAutoRefresh();
|
||||
showStatusMessage('Auto-Update deaktiviert', 'info');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function startAutoRefresh() {
|
||||
function startAutoRefresh() {
|
||||
stopAutoRefresh(); // Stoppe vorherige Intervalle
|
||||
|
||||
nextUpdateTime = 30;
|
||||
@@ -1101,9 +1074,9 @@
|
||||
autoRefreshInterval = setInterval(() => {
|
||||
loadPrintersWithLiveStatus();
|
||||
}, 30000); // Alle 30 Sekunden
|
||||
}
|
||||
}
|
||||
|
||||
function stopAutoRefresh() {
|
||||
function stopAutoRefresh() {
|
||||
if (autoRefreshInterval) {
|
||||
clearInterval(autoRefreshInterval);
|
||||
autoRefreshInterval = null;
|
||||
@@ -1115,9 +1088,9 @@
|
||||
|
||||
const element = document.getElementById('next-update-time');
|
||||
if (element) element.textContent = '-';
|
||||
}
|
||||
}
|
||||
|
||||
function updateNextUpdateDisplay() {
|
||||
function updateNextUpdateDisplay() {
|
||||
const element = document.getElementById('next-update-time');
|
||||
if (!element) return;
|
||||
|
||||
@@ -1128,33 +1101,10 @@
|
||||
element.textContent = '-';
|
||||
element.parentElement.style.opacity = '0.5';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Filter-Funktionalität
|
||||
function setupFilters() {
|
||||
const filterButtons = document.querySelectorAll('.filter-btn-mercedes');
|
||||
|
||||
filterButtons.forEach(btn => {
|
||||
btn.addEventListener('click', function() {
|
||||
// Entferne active-Klasse von allen Buttons
|
||||
filterButtons.forEach(b => {
|
||||
b.classList.remove('active');
|
||||
});
|
||||
|
||||
// Füge active-Klasse zum geklickten Button hinzu
|
||||
this.classList.add('active');
|
||||
|
||||
// Setze aktuellen Filter
|
||||
currentFilter = this.id.replace('filter-', '');
|
||||
|
||||
// Rendere Drucker mit Filter
|
||||
renderPrinters();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Delete printer
|
||||
async function deletePrinter(printerId) {
|
||||
// Delete printer
|
||||
async function deletePrinter(printerId) {
|
||||
if (!confirm('Sind Sie sicher, dass Sie diesen Drucker löschen möchten?')) {
|
||||
return;
|
||||
}
|
||||
@@ -1180,10 +1130,10 @@
|
||||
console.error('Error deleting printer:', error);
|
||||
showStatusMessage('Fehler beim Löschen des Druckers: ' + error.message, 'error');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add printer
|
||||
async function handleAddPrinter(event) {
|
||||
// Add printer
|
||||
async function handleAddPrinter(event) {
|
||||
event.preventDefault();
|
||||
|
||||
const form = document.getElementById('addPrinterForm');
|
||||
@@ -1294,18 +1244,18 @@
|
||||
submitBtn.disabled = false;
|
||||
submitBtn.innerHTML = originalBtnText;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make all functions globally available for onclick handlers
|
||||
window.showPrinterDetail = showPrinterDetail;
|
||||
window.hidePrinterDetailModal = hidePrinterDetailModal;
|
||||
window.deletePrinter = deletePrinter;
|
||||
window.loadPrinters = loadPrinters;
|
||||
window.handleAddPrinter = handleAddPrinter;
|
||||
window.toggleAutoRefresh = toggleAutoRefresh;
|
||||
window.loadPrintersWithLiveStatus = loadPrintersWithLiveStatus;
|
||||
window.refreshPrinters = refreshPrinters;
|
||||
window.hideAddPrinterModal = hideAddPrinterModal;
|
||||
window.showAddPrinterModal = showAddPrinterModal;
|
||||
// Make all functions globally available for onclick handlers
|
||||
window.showPrinterDetail = showPrinterDetail;
|
||||
window.hidePrinterDetailModal = hidePrinterDetailModal;
|
||||
window.deletePrinter = deletePrinter;
|
||||
window.loadPrinters = loadPrinters;
|
||||
window.handleAddPrinter = handleAddPrinter;
|
||||
window.toggleAutoRefresh = toggleAutoRefresh;
|
||||
window.loadPrintersWithLiveStatus = loadPrintersWithLiveStatus;
|
||||
window.refreshPrinters = refreshPrinters;
|
||||
window.hideAddPrinterModal = hideAddPrinterModal;
|
||||
window.showAddPrinterModal = showAddPrinterModal;
|
||||
</script>
|
||||
{% endblock %}
|
Reference in New Issue
Block a user