238 lines
11 KiB
HTML
238 lines
11 KiB
HTML
{% extends "base.html" %}
|
||
|
||
{% block title %}Drucker verwalten - Mercedes-Benz MYP Platform{% endblock %}
|
||
|
||
{% block head %}
|
||
{{ super() }}
|
||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||
{% endblock %}
|
||
|
||
{% block content %}
|
||
<div class="min-h-screen bg-gradient-to-br from-slate-50 via-blue-50 to-indigo-50 dark:from-slate-900 dark:via-slate-800 dark:to-slate-900">
|
||
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
||
|
||
<!-- Header -->
|
||
<div class="mb-8">
|
||
<div class="flex items-center justify-between">
|
||
<div>
|
||
<h1 class="text-3xl font-bold text-slate-900 dark:text-white">{{ printer.name }} verwalten</h1>
|
||
<p class="text-slate-600 dark:text-slate-400 mt-2">Verwaltung und Überwachung des Druckers</p>
|
||
</div>
|
||
<a href="{{ url_for('admin_page', tab='printers') }}" class="inline-flex items-center px-4 py-2 bg-slate-200 dark:bg-slate-700 text-slate-700 dark:text-slate-300 rounded-xl hover:bg-slate-300 dark:hover:bg-slate-600 transition-all duration-300">
|
||
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18"/>
|
||
</svg>
|
||
Zurück zur Druckerverwaltung
|
||
</a>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Drucker-Info -->
|
||
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6 mb-8">
|
||
<!-- Status Card -->
|
||
<div class="bg-white dark:bg-slate-800 rounded-2xl shadow-xl p-6">
|
||
<h3 class="text-lg font-semibold text-slate-900 dark:text-white mb-4">Status</h3>
|
||
<div class="space-y-3">
|
||
<div class="flex items-center justify-between">
|
||
<span class="text-slate-600 dark:text-slate-400">Aktueller Status:</span>
|
||
<span class="px-3 py-1 rounded-full text-sm font-medium
|
||
{% if printer.status == 'available' %}bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200{% elif printer.status == 'busy' %}bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200{% elif printer.status == 'maintenance' %}bg-orange-100 text-orange-800 dark:bg-orange-900 dark:text-orange-200{% else %}bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200{% endif %}">
|
||
{{ printer.status|title }}
|
||
</span>
|
||
</div>
|
||
<div class="flex items-center justify-between">
|
||
<span class="text-slate-600 dark:text-slate-400">IP-Adresse:</span>
|
||
<span class="text-slate-900 dark:text-white font-mono">{{ printer.ip_address }}</span>
|
||
</div>
|
||
<div class="flex items-center justify-between">
|
||
<span class="text-slate-600 dark:text-slate-400">Standort:</span>
|
||
<span class="text-slate-900 dark:text-white">{{ printer.location or 'Nicht angegeben' }}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Aktionen Card -->
|
||
<div class="bg-white dark:bg-slate-800 rounded-2xl shadow-xl p-6">
|
||
<h3 class="text-lg font-semibold text-slate-900 dark:text-white mb-4">Aktionen</h3>
|
||
<div class="space-y-3">
|
||
<button onclick="togglePrinter({{ printer.id }})"
|
||
class="w-full px-4 py-2 bg-blue-500 text-white rounded-xl hover:bg-blue-600 transition-all duration-300">
|
||
{% if printer.status == 'available' %}Deaktivieren{% else %}Aktivieren{% endif %}
|
||
</button>
|
||
<button onclick="testConnection({{ printer.id }})"
|
||
class="w-full px-4 py-2 bg-green-500 text-white rounded-xl hover:bg-green-600 transition-all duration-300">
|
||
Verbindung testen
|
||
</button>
|
||
<a href="{{ url_for('admin_printer_settings_page', printer_id=printer.id) }}"
|
||
class="block w-full px-4 py-2 bg-slate-500 text-white rounded-xl hover:bg-slate-600 transition-all duration-300 text-center">
|
||
Einstellungen
|
||
</a>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Statistiken Card -->
|
||
<div class="bg-white dark:bg-slate-800 rounded-2xl shadow-xl p-6">
|
||
<h3 class="text-lg font-semibold text-slate-900 dark:text-white mb-4">Statistiken</h3>
|
||
<div class="space-y-3">
|
||
<div class="flex items-center justify-between">
|
||
<span class="text-slate-600 dark:text-slate-400">Gesamte Jobs:</span>
|
||
<span class="text-slate-900 dark:text-white font-semibold" id="total-jobs">-</span>
|
||
</div>
|
||
<div class="flex items-center justify-between">
|
||
<span class="text-slate-600 dark:text-slate-400">Aktive Jobs:</span>
|
||
<span class="text-slate-900 dark:text-white font-semibold" id="active-jobs">-</span>
|
||
</div>
|
||
<div class="flex items-center justify-between">
|
||
<span class="text-slate-600 dark:text-slate-400">Erfolgsrate:</span>
|
||
<span class="text-slate-900 dark:text-white font-semibold" id="success-rate">-</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Aktuelle Jobs -->
|
||
<div class="bg-white dark:bg-slate-800 rounded-2xl shadow-xl p-6">
|
||
<h3 class="text-lg font-semibold text-slate-900 dark:text-white mb-4">Aktuelle Jobs</h3>
|
||
<div id="current-jobs" class="space-y-4">
|
||
<div class="text-center text-slate-500 dark:text-slate-400 py-8">
|
||
Lade Jobs...
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
// CSRF Token
|
||
function getCsrfToken() {
|
||
const token = document.querySelector('meta[name="csrf-token"]');
|
||
return token ? token.getAttribute('content') : '';
|
||
}
|
||
|
||
// Notification anzeigen
|
||
function showNotification(message, type = 'info') {
|
||
if (type === 'success') {
|
||
alert('✓ ' + message);
|
||
} else if (type === 'error') {
|
||
alert('✗ ' + message);
|
||
} else {
|
||
alert('ℹ ' + message);
|
||
}
|
||
}
|
||
|
||
// Drucker aktivieren/deaktivieren
|
||
async function togglePrinter(printerId) {
|
||
try {
|
||
const response = await fetch(`/api/admin/printers/${printerId}/toggle`, {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
'X-CSRFToken': getCsrfToken()
|
||
}
|
||
});
|
||
|
||
const result = await response.json();
|
||
|
||
if (response.ok && result.success) {
|
||
showNotification('Drucker-Status erfolgreich geändert', 'success');
|
||
setTimeout(() => location.reload(), 1000);
|
||
} else {
|
||
showNotification(result.error || 'Fehler beim Ändern des Drucker-Status', 'error');
|
||
}
|
||
} catch (error) {
|
||
showNotification('Netzwerkfehler: ' + error.message, 'error');
|
||
}
|
||
}
|
||
|
||
// Verbindung testen
|
||
async function testConnection(printerId) {
|
||
try {
|
||
const response = await fetch(`/api/printers/${printerId}/test`, {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
'X-CSRFToken': getCsrfToken()
|
||
}
|
||
});
|
||
|
||
const result = await response.json();
|
||
|
||
if (response.ok) {
|
||
if (result.connected) {
|
||
showNotification('Verbindung erfolgreich', 'success');
|
||
} else {
|
||
showNotification('Verbindung fehlgeschlagen', 'error');
|
||
}
|
||
} else {
|
||
showNotification(result.error || 'Fehler beim Testen der Verbindung', 'error');
|
||
}
|
||
} catch (error) {
|
||
showNotification('Netzwerkfehler: ' + error.message, 'error');
|
||
}
|
||
}
|
||
|
||
// Statistiken laden
|
||
async function loadStats() {
|
||
try {
|
||
const response = await fetch(`/api/printers/{{ printer.id }}/stats`);
|
||
const stats = await response.json();
|
||
|
||
if (response.ok) {
|
||
document.getElementById('total-jobs').textContent = stats.total_jobs || 0;
|
||
document.getElementById('active-jobs').textContent = stats.active_jobs || 0;
|
||
document.getElementById('success-rate').textContent = (stats.success_rate || 0) + '%';
|
||
}
|
||
} catch (error) {
|
||
console.error('Fehler beim Laden der Statistiken:', error);
|
||
}
|
||
}
|
||
|
||
// Jobs laden
|
||
async function loadJobs() {
|
||
try {
|
||
const response = await fetch(`/api/printers/{{ printer.id }}/jobs`);
|
||
const jobs = await response.json();
|
||
|
||
const container = document.getElementById('current-jobs');
|
||
|
||
if (response.ok && jobs.length > 0) {
|
||
container.innerHTML = jobs.map(job => `
|
||
<div class="border border-slate-200 dark:border-slate-700 rounded-xl p-4">
|
||
<div class="flex items-center justify-between">
|
||
<div>
|
||
<h4 class="font-medium text-slate-900 dark:text-white">${job.name}</h4>
|
||
<p class="text-sm text-slate-600 dark:text-slate-400">von ${job.user_name}</p>
|
||
</div>
|
||
<div class="text-right">
|
||
<span class="px-3 py-1 rounded-full text-sm font-medium
|
||
${job.status === 'running' ? 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200' :
|
||
job.status === 'pending' ? 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200' :
|
||
'bg-slate-100 text-slate-800 dark:bg-slate-900 dark:text-slate-200'}">
|
||
${job.status}
|
||
</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
`).join('');
|
||
} else {
|
||
container.innerHTML = '<div class="text-center text-slate-500 dark:text-slate-400 py-8">Keine aktiven Jobs</div>';
|
||
}
|
||
} catch (error) {
|
||
console.error('Fehler beim Laden der Jobs:', error);
|
||
document.getElementById('current-jobs').innerHTML = '<div class="text-center text-red-500 py-8">Fehler beim Laden der Jobs</div>';
|
||
}
|
||
}
|
||
|
||
// Beim Laden der Seite
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
loadStats();
|
||
loadJobs();
|
||
|
||
// Alle 30 Sekunden aktualisieren
|
||
setInterval(() => {
|
||
loadStats();
|
||
loadJobs();
|
||
}, 30000);
|
||
});
|
||
</script>
|
||
{% endblock %} |