Die Dateien wurden wie folgt geändert und hinzugefügt:

1. backend/logs - 'admin', 'admin_api', 'app', 'calendar', 'data_management', 'drucker_steuerung', 'energy_monitoring', 'guest', 'hardware_integration', 'job_queue_system', 'jobs', 'models', 'monitoring_analytics', 'permissions', 'scheduler', 'security_suite', 'startup', '
This commit is contained in:
2025-06-20 01:06:37 +02:00
parent 0fcf04833f
commit 321626e9d3
754 changed files with 3013 additions and 174 deletions

View File

@ -215,78 +215,129 @@
</div>
{% else %}
<!-- Energy Overview Cards -->
<!-- Energy Overview Cards - Unified Dark/Light Mode -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
<!-- Total Power Consumption -->
<div class="energy-card p-6">
<div class="energy-metric">
<h3 class="text-sm font-semibold uppercase tracking-wider mb-2">Gesamtverbrauch</h3>
<p class="text-3xl font-bold" id="total-power">{{ stats.total_power_consumption or '0.0' }} kWh</p>
<div class="bg-white dark:bg-slate-800 rounded-2xl p-6 border border-slate-200 dark:border-slate-700 hover:border-blue-300 dark:hover:border-blue-600 transition-all duration-300 hover:shadow-lg">
<div class="flex items-center justify-between mb-4">
<div class="w-12 h-12 bg-blue-100 dark:bg-blue-900/30 rounded-xl flex items-center justify-center">
<svg class="w-6 h-6 text-blue-600 dark:text-blue-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"/>
</svg>
</div>
</div>
<h3 class="text-sm font-semibold text-slate-600 dark:text-slate-400 uppercase tracking-wider mb-2">Gesamtverbrauch</h3>
<p class="text-3xl font-bold text-slate-900 dark:text-white" id="total-power">{{ stats.total_power_consumption or '0.0' }} kWh</p>
<p class="text-sm text-slate-500 dark:text-slate-400 mt-2">24h Periode</p>
</div>
<!-- Current Power -->
<div class="energy-card p-6">
<div class="energy-metric">
<h3 class="text-sm font-semibold uppercase tracking-wider mb-2">Aktuelle Leistung</h3>
<p class="text-3xl font-bold" id="current-power">{{ stats.current_power or '0.0' }} W</p>
<div class="bg-white dark:bg-slate-800 rounded-2xl p-6 border border-slate-200 dark:border-slate-700 hover:border-green-300 dark:hover:border-green-600 transition-all duration-300 hover:shadow-lg">
<div class="flex items-center justify-between mb-4">
<div class="w-12 h-12 bg-green-100 dark:bg-green-900/30 rounded-xl flex items-center justify-center">
<svg class="w-6 h-6 text-green-600 dark:text-green-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"/>
</svg>
</div>
</div>
<h3 class="text-sm font-semibold text-slate-600 dark:text-slate-400 uppercase tracking-wider mb-2">Aktuelle Leistung</h3>
<p class="text-3xl font-bold text-slate-900 dark:text-white" id="current-power">{{ stats.current_power or '0.0' }} W</p>
<p class="text-sm text-slate-500 dark:text-slate-400 mt-2">Momentan</p>
</div>
<!-- Active Devices -->
<div class="energy-card p-6">
<div class="energy-metric">
<h3 class="text-sm font-semibold uppercase tracking-wider mb-2">Aktive Geräte</h3>
<p class="text-3xl font-bold" id="active-devices">{{ stats.active_devices or '0' }}</p>
<div class="bg-white dark:bg-slate-800 rounded-2xl p-6 border border-slate-200 dark:border-slate-700 hover:border-purple-300 dark:hover:border-purple-600 transition-all duration-300 hover:shadow-lg">
<div class="flex items-center justify-between mb-4">
<div class="w-12 h-12 bg-purple-100 dark:bg-purple-900/30 rounded-xl flex items-center justify-center">
<svg class="w-6 h-6 text-purple-600 dark:text-purple-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19.428 15.428a2 2 0 00-1.022-.547l-2.387-.477a6 6 0 00-3.86.517l-.318.158a6 6 0 01-3.86.517L6.05 15.21a2 2 0 00-1.806.547M8 4h8l-1 1v5.172a2 2 0 00.586 1.414l5 5c1.26 1.26.367 3.414-1.415 3.414H4.828c-1.782 0-2.674-2.154-1.414-3.414l5-5A2 2 0 009 10.172V5L8 4z"/>
</svg>
</div>
</div>
<h3 class="text-sm font-semibold text-slate-600 dark:text-slate-400 uppercase tracking-wider mb-2">Aktive Geräte</h3>
<p class="text-3xl font-bold text-slate-900 dark:text-white" id="active-devices">{{ stats.active_devices or '0' }}</p>
<p class="text-sm text-slate-500 dark:text-slate-400 mt-2">Von 6 Druckern</p>
</div>
<!-- Energy Cost -->
<div class="energy-card p-6">
<div class="energy-metric">
<h3 class="text-sm font-semibold uppercase tracking-wider mb-2">Kosten (€/kWh 0.30)</h3>
<p class="text-3xl font-bold" id="energy-cost">{{ "%.2f"|format((stats.total_power_consumption or 0) * 0.30) }} €</p>
<div class="bg-white dark:bg-slate-800 rounded-2xl p-6 border border-slate-200 dark:border-slate-700 hover:border-orange-300 dark:hover:border-orange-600 transition-all duration-300 hover:shadow-lg">
<div class="flex items-center justify-between mb-4">
<div class="w-12 h-12 bg-orange-100 dark:bg-orange-900/30 rounded-xl flex items-center justify-center">
<svg class="w-6 h-6 text-orange-600 dark:text-orange-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1"/>
</svg>
</div>
</div>
<h3 class="text-sm font-semibold text-slate-600 dark:text-slate-400 uppercase tracking-wider mb-2">Kosten (€/kWh 0.30)</h3>
<p class="text-3xl font-bold text-slate-900 dark:text-white" id="energy-cost">{{ "%.2f"|format((stats.total_power_consumption or 0) * 0.30) }} €</p>
<p class="text-sm text-slate-500 dark:text-slate-400 mt-2">24h Periode</p>
</div>
</div>
<!-- Charts Section -->
<!-- Charts Section - Unified Dark/Light Mode -->
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8 mb-8">
<!-- Power Consumption Over Time -->
<div class="energy-card p-6">
<h3 class="text-xl font-bold mb-4" style="color: var(--text-primary);">Verbrauch der letzten 24 Stunden</h3>
<div class="relative h-80">
<div class="bg-white dark:bg-slate-800 rounded-2xl p-6 border border-slate-200 dark:border-slate-700 hover:shadow-lg transition-all duration-300">
<div class="flex items-center justify-between mb-6">
<h3 class="text-xl font-bold text-slate-900 dark:text-white">Verbrauch der letzten 24 Stunden</h3>
<div class="w-10 h-10 bg-blue-100 dark:bg-blue-900/30 rounded-lg flex items-center justify-center">
<svg class="w-5 h-5 text-blue-600 dark:text-blue-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"/>
</svg>
</div>
</div>
<div class="relative h-80 bg-slate-50 dark:bg-slate-900 rounded-xl p-4">
<canvas id="powerChart"></canvas>
</div>
</div>
<!-- Device Comparison -->
<div class="energy-card p-6">
<h3 class="text-xl font-bold mb-4" style="color: var(--text-primary);">Verbrauch nach Gerät</h3>
<div class="relative h-80">
<div class="bg-white dark:bg-slate-800 rounded-2xl p-6 border border-slate-200 dark:border-slate-700 hover:shadow-lg transition-all duration-300">
<div class="flex items-center justify-between mb-6">
<h3 class="text-xl font-bold text-slate-900 dark:text-white">Verbrauch nach Gerät</h3>
<div class="w-10 h-10 bg-purple-100 dark:bg-purple-900/30 rounded-lg flex items-center justify-center">
<svg class="w-5 h-5 text-purple-600 dark:text-purple-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 3.055A9.001 9.001 0 1020.945 13H11V3.055z"/>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20.488 9H15V3.512A9.025 9.025 0 0120.488 9z"/>
</svg>
</div>
</div>
<div class="relative h-80 bg-slate-50 dark:bg-slate-900 rounded-xl p-4">
<canvas id="deviceChart"></canvas>
</div>
</div>
</div>
<!-- Device List -->
<div class="energy-card p-6">
<h3 class="text-xl font-bold mb-6" style="color: var(--text-primary);">Geräteübersicht</h3>
<!-- Device List - Unified Dark/Light Mode -->
<div class="bg-white dark:bg-slate-800 rounded-2xl border border-slate-200 dark:border-slate-700 overflow-hidden">
<div class="px-6 py-4 border-b border-slate-200 dark:border-slate-700">
<div class="flex items-center justify-between">
<h3 class="text-xl font-bold text-slate-900 dark:text-white">Geräteübersicht</h3>
<div class="flex items-center space-x-2">
<div class="w-8 h-8 bg-green-100 dark:bg-green-900/30 rounded-lg flex items-center justify-center">
<svg class="w-4 h-4 text-green-600 dark:text-green-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19.428 15.428a2 2 0 00-1.022-.547l-2.387-.477a6 6 0 00-3.86.517l-.318.158a6 6 0 01-3.86.517L6.05 15.21a2 2 0 00-1.806.547M8 4h8l-1 1v5.172a2 2 0 00.586 1.414l5 5c1.26 1.26.367 3.414-1.415 3.414H4.828c-1.782 0-2.674-2.154-1.414-3.414l5-5A2 2 0 009 10.172V5L8 4z"/>
</svg>
</div>
<span class="text-sm text-slate-500 dark:text-slate-400">Live-Updates</span>
</div>
</div>
</div>
<div class="overflow-x-auto">
<table class="energy-table min-w-full">
<thead>
<table class="min-w-full">
<thead class="bg-slate-50 dark:bg-slate-900">
<tr>
<th class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider">Gerät</th>
<th class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider">Status</th>
<th class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider">Aktuelle Leistung</th>
<th class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider">Tagesverbrauch</th>
<th class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider">Aktionen</th>
<th class="px-6 py-3 text-left text-xs font-medium text-slate-500 dark:text-slate-400 uppercase tracking-wider">Gerät</th>
<th class="px-6 py-3 text-left text-xs font-medium text-slate-500 dark:text-slate-400 uppercase tracking-wider">Status</th>
<th class="px-6 py-3 text-left text-xs font-medium text-slate-500 dark:text-slate-400 uppercase tracking-wider">Aktuelle Leistung</th>
<th class="px-6 py-3 text-left text-xs font-medium text-slate-500 dark:text-slate-400 uppercase tracking-wider">Tagesverbrauch</th>
<th class="px-6 py-3 text-left text-xs font-medium text-slate-500 dark:text-slate-400 uppercase tracking-wider">Aktionen</th>
</tr>
</thead>
<tbody id="device-table-body">
<tbody id="device-table-body" class="bg-white dark:bg-slate-800 divide-y divide-slate-200 dark:divide-slate-700">
<!-- Dynamisch geladen via JavaScript -->
</tbody>
</table>
@ -444,8 +495,14 @@ function updateDeviceTable(devices) {
if (devices.length === 0) {
tbody.innerHTML = `
<tr>
<td colspan="5" class="px-6 py-4 text-center" style="color: var(--text-muted);">
Keine Geräte gefunden
<td colspan="5" class="px-6 py-4 text-center text-slate-500 dark:text-slate-400">
<div class="flex flex-col items-center py-8">
<svg class="w-12 h-12 text-slate-300 dark:text-slate-600 mb-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19.428 15.428a2 2 0 00-1.022-.547l-2.387-.477a6 6 0 00-3.86.517l-.318.158a6 6 0 01-3.86.517L6.05 15.21a2 2 0 00-1.806.547M8 4h8l-1 1v5.172a2 2 0 00.586 1.414l5 5c1.26 1.26.367 3.414-1.415 3.414H4.828c-1.782 0-2.674-2.154-1.414-3.414l5-5A2 2 0 009 10.172V5L8 4z"/>
</svg>
<p class="text-lg font-medium">Keine Geräte gefunden</p>
<p class="text-sm">Überprüfen Sie die Hardware-Verbindungen</p>
</div>
</td>
</tr>
`;
@ -454,34 +511,46 @@ function updateDeviceTable(devices) {
devices.forEach(device => {
const row = document.createElement('tr');
row.className = '';
row.style.transition = 'background-color 0.2s ease';
row.addEventListener('mouseenter', () => row.style.backgroundColor = 'var(--hover-card)');
row.addEventListener('mouseleave', () => row.style.backgroundColor = 'transparent');
row.className = 'hover:bg-slate-50 dark:hover:bg-slate-700 transition-colors duration-200';
const statusClass = device.status === 'online' ? 'status-badge-online' : 'status-badge-offline';
const statusText = device.status === 'online' ? 'Online' : 'Offline';
const isOnline = device.status === 'online';
const statusClass = isOnline
? 'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-400'
: 'bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-400';
const statusText = isOnline ? 'Online' : 'Offline';
const statusIcon = isOnline
? '<div class="w-2 h-2 bg-green-400 rounded-full mr-1.5"></div>'
: '<div class="w-2 h-2 bg-red-400 rounded-full mr-1.5"></div>';
row.innerHTML = `
<td class="px-6 py-4 whitespace-nowrap">
<div class="flex items-center">
<div class="text-sm font-medium" style="color: var(--text-primary);">${device.name}</div>
<div class="text-sm" style="color: var(--text-tertiary);">${device.model || ''}</div>
<div class="w-10 h-10 bg-slate-100 dark:bg-slate-700 rounded-lg flex items-center justify-center mr-4">
<svg class="w-5 h-5 text-slate-600 dark:text-slate-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19.428 15.428a2 2 0 00-1.022-.547l-2.387-.477a6 6 0 00-3.86.517l-.318.158a6 6 0 01-3.86.517L6.05 15.21a2 2 0 00-1.806.547M8 4h8l-1 1v5.172a2 2 0 00.586 1.414l5 5c1.26 1.26.367 3.414-1.415 3.414H4.828c-1.782 0-2.674-2.154-1.414-3.414l5-5A2 2 0 009 10.172V5L8 4z"/>
</svg>
</div>
<div>
<div class="text-sm font-medium text-slate-900 dark:text-white">${device.name}</div>
<div class="text-sm text-slate-500 dark:text-slate-400">${device.model || 'Unbekanntes Modell'}</div>
</div>
</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${statusClass}">
${statusText}
${statusIcon}${statusText}
</span>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm" style="color: var(--text-primary);">
${device.current_power || '0.0'} W
<td class="px-6 py-4 whitespace-nowrap">
<div class="text-sm font-medium text-slate-900 dark:text-white">${device.current_power || '0.0'} W</div>
<div class="text-sm text-slate-500 dark:text-slate-400">Momentan</div>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm" style="color: var(--text-primary);">
${device.daily_consumption || '0.0'} kWh
<td class="px-6 py-4 whitespace-nowrap">
<div class="text-sm font-medium text-slate-900 dark:text-white">${device.daily_consumption || '0.0'} kWh</div>
<div class="text-sm text-slate-500 dark:text-slate-400">Heute</div>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
<a href="/energy/device/${device.id}" style="color: var(--text-accent); transition: color 0.2s ease;" onmouseover="this.style.color='var(--text-link-hover)'" onmouseout="this.style.color='var(--text-accent)'">
<a href="/energy/device/${device.id}" class="text-blue-600 dark:text-blue-400 hover:text-blue-800 dark:hover:text-blue-300 transition-colors duration-200">
Details anzeigen
</a>
</td>