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:
@ -238,14 +238,6 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
Benutzer
|
||||
</a>
|
||||
|
||||
<a href="{{ url_for('admin.printers_overview') }}"
|
||||
class="group flex items-center px-6 py-3 text-sm font-medium rounded-xl transition-all duration-300 {{ 'bg-gradient-to-r from-blue-500 to-blue-600 text-white shadow-lg' if active_tab == 'printers' else 'text-slate-600 dark:text-slate-300 hover:bg-slate-100 dark:hover:bg-slate-700/50 hover:text-slate-900 dark:hover:text-white' }}">
|
||||
<svg class="w-5 h-5 mr-2 {{ 'text-white' if active_tab == 'printers' else 'text-slate-400 group-hover:text-slate-600 dark:group-hover:text-slate-300' }}" 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>
|
||||
Drucker-Steckdosen
|
||||
</a>
|
||||
|
||||
<a href="{{ url_for('jobs_page') }}"
|
||||
class="group flex items-center px-6 py-3 text-sm font-medium rounded-xl transition-all duration-300 {{ 'bg-gradient-to-r from-blue-500 to-blue-600 text-white shadow-lg' if active_tab == 'jobs' else 'text-slate-600 dark:text-slate-300 hover:bg-slate-100 dark:hover:bg-slate-700/50 hover:text-slate-900 dark:hover:text-white' }}">
|
||||
<svg class="w-5 h-5 mr-2 {{ 'text-white' if active_tab == 'jobs' else 'text-slate-400 group-hover:text-slate-600 dark:group-hover:text-slate-300' }}" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
@ -284,7 +276,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
<svg class="w-5 h-5 mr-2 {{ 'text-white' if active_tab == 'guest_otps' else 'text-slate-400 group-hover:text-slate-600 dark:group-hover:text-slate-300' }}" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 7a2 2 0 012 2m0 0a2 2 0 012 2m-4-4v8a2 2 0 01-2 2H9a2 2 0 01-2-2V9a2 2 0 012-2h2m0 0V6a2 2 0 012-2h2a2 2 0 012 2v1m-4 0h4"/>
|
||||
</svg>
|
||||
🔑 OTP-Codes
|
||||
🔑 Codes
|
||||
</a>
|
||||
|
||||
<a href="{{ url_for('admin.tapo_monitoring') }}"
|
||||
@ -292,7 +284,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
<svg class="w-5 h-5 mr-2 {{ 'text-white' if active_tab == 'tapo_monitoring' else 'text-slate-400 group-hover:text-slate-600 dark:group-hover:text-slate-300' }}" 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>
|
||||
Tapo-Monitoring
|
||||
Steckdosen
|
||||
</a>
|
||||
</nav>
|
||||
</div>
|
||||
|
223
backend/templates/admin_printer_configuration.html
Normal file
223
backend/templates/admin_printer_configuration.html
Normal file
@ -0,0 +1,223 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}{{ config_data.printer.name }} - Erweiterte Konfiguration - 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-7xl 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">{{ config_data.printer.name }} - Erweiterte Konfiguration</h1>
|
||||
<p class="text-slate-600 dark:text-slate-400 mt-2">Umfassende Drucker-Konfiguration und Hardware-Integration</p>
|
||||
</div>
|
||||
<div class="flex items-center space-x-4">
|
||||
<a href="{{ url_for('admin.admin_dashboard', 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 Verwaltung
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Connectivity Status -->
|
||||
<div class="mb-8">
|
||||
<div class="bg-white dark:bg-slate-800 rounded-2xl shadow-xl p-6">
|
||||
<h2 class="text-xl font-bold text-slate-900 dark:text-white mb-4 flex items-center">
|
||||
<svg class="w-6 h-6 mr-2 text-blue-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8.111 16.404a5.5 5.5 0 017.778 0M12 20h.01m-7.08-7.071c3.904-3.905 10.236-3.905 14.141 0M1.394 9.393c5.857-5.857 15.355-5.857 21.213 0"/>
|
||||
</svg>
|
||||
Verbindungsstatus
|
||||
</h2>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<!-- Drucker-Verbindung -->
|
||||
<div class="bg-gradient-to-r from-blue-50 to-blue-100 dark:from-blue-900/20 dark:to-blue-800/20 rounded-xl p-4 border border-blue-200 dark:border-blue-800">
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<span class="font-medium text-blue-900 dark:text-blue-300">Drucker ({{ config_data.printer.ip_address }})</span>
|
||||
<div class="flex items-center">
|
||||
<div class="w-3 h-3 bg-{% if config_data.connectivity.printer_reachable %}green{% else %}red{% endif %}-500 rounded-full mr-2 animate-pulse"></div>
|
||||
<span class="text-sm font-medium text-{% if config_data.connectivity.printer_reachable %}green{% else %}red{% endif %}-700 dark:text-{% if config_data.connectivity.printer_reachable %}green{% else %}red{% endif %}-400">
|
||||
{% if config_data.connectivity.printer_reachable %}Online{% else %}Offline{% endif %}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
{% if config_data.connectivity.response_time %}
|
||||
<p class="text-sm text-blue-600 dark:text-blue-400">Response: {{ config_data.connectivity.response_time }}ms</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- Smart-Plug-Verbindung -->
|
||||
<div class="bg-gradient-to-r from-purple-50 to-purple-100 dark:from-purple-900/20 dark:to-purple-800/20 rounded-xl p-4 border border-purple-200 dark:border-purple-800">
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<span class="font-medium text-purple-900 dark:text-purple-300">Smart-Plug ({{ config_data.printer.plug_ip or 'Nicht konfiguriert' }})</span>
|
||||
<div class="flex items-center">
|
||||
<div class="w-3 h-3 bg-{% if config_data.connectivity.plug_reachable %}green{% else %}red{% endif %}-500 rounded-full mr-2 animate-pulse"></div>
|
||||
<span class="text-sm font-medium text-{% if config_data.connectivity.plug_reachable %}green{% else %}red{% endif %}-700 dark:text-{% if config_data.connectivity.plug_reachable %}green{% else %}red{% endif %}-400">
|
||||
{% if config_data.connectivity.plug_reachable %}Online{% else %}Offline{% endif %}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
{% if config_data.connectivity.plug_status %}
|
||||
<p class="text-sm text-purple-600 dark:text-purple-400">Status: {{ config_data.connectivity.plug_status|title }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Konfigurationskategorien -->
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8">
|
||||
{% for category_key, category in config_data.config_categories.items() %}
|
||||
<div class="bg-white dark:bg-slate-800 rounded-2xl shadow-xl p-6 hover:shadow-2xl transition-all duration-300">
|
||||
<div class="flex items-center mb-4">
|
||||
<div class="p-3 bg-gradient-to-r from-blue-500 to-blue-600 rounded-xl mr-4">
|
||||
{% if category.icon == 'cog' %}
|
||||
<svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"/>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>
|
||||
</svg>
|
||||
{% elif category.icon == 'wifi' %}
|
||||
<svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8.111 16.404a5.5 5.5 0 017.778 0M12 20h.01m-7.08-7.071c3.904-3.905 10.236-3.905 14.141 0M1.394 9.393c5.857-5.857 15.355-5.857 21.213 0"/>
|
||||
</svg>
|
||||
{% elif category.icon == 'cpu' %}
|
||||
<svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<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>
|
||||
{% elif category.icon == 'zap' %}
|
||||
<svg class="w-6 h-6 text-white" 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>
|
||||
{% elif category.icon == 'tool' %}
|
||||
<svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"/>
|
||||
</svg>
|
||||
{% else %}
|
||||
<svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6V4m0 2a2 2 0 100 4m0-4a2 2 0 110 4m-6 8a2 2 0 100-4m0 4a2 2 0 100 4m0-4v2m0-6V4m6 6v10m6-2a2 2 0 100-4m0 4a2 2 0 100 4m0-4v2m0-6V4"/>
|
||||
</svg>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-lg font-bold text-slate-900 dark:text-white">{{ category.name }}</h3>
|
||||
<p class="text-sm text-slate-600 dark:text-slate-400">{{ category.description }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="space-y-4">
|
||||
<!-- Konfiguration für jede Kategorie -->
|
||||
{% if category_key == 'basic' %}
|
||||
<div class="space-y-3">
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-sm font-medium text-slate-700 dark:text-slate-300">Name:</span>
|
||||
<span class="text-sm text-slate-600 dark:text-slate-400">{{ config_data.printer.name }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-sm font-medium text-slate-700 dark:text-slate-300">Modell:</span>
|
||||
<span class="text-sm text-slate-600 dark:text-slate-400">{{ config_data.printer.model or 'Nicht gesetzt' }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-sm font-medium text-slate-700 dark:text-slate-300">Standort:</span>
|
||||
<span class="text-sm text-slate-600 dark:text-slate-400">{{ config_data.printer.location or 'Nicht gesetzt' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
{% elif category_key == 'network' %}
|
||||
<div class="space-y-3">
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-sm font-medium text-slate-700 dark:text-slate-300">Drucker-IP:</span>
|
||||
<span class="text-sm text-slate-600 dark:text-slate-400">{{ config_data.printer.ip_address or 'Nicht gesetzt' }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-sm font-medium text-slate-700 dark:text-slate-300">Smart-Plug-IP:</span>
|
||||
<span class="text-sm text-slate-600 dark:text-slate-400">{{ config_data.printer.plug_ip or 'Nicht gesetzt' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
{% elif category_key == 'hardware' %}
|
||||
<div class="space-y-3">
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-sm font-medium text-slate-700 dark:text-slate-300">Smart-Plug Status:</span>
|
||||
<span class="text-sm text-{% if config_data.connectivity.plug_reachable %}green{% else %}red{% endif %}-600 dark:text-{% if config_data.connectivity.plug_reachable %}green{% else %}red{% endif %}-400">
|
||||
{% if config_data.connectivity.plug_reachable %}Online{% else %}Offline{% endif %}
|
||||
</span>
|
||||
</div>
|
||||
{% if config_data.hardware_status.energy_usage %}
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-sm font-medium text-slate-700 dark:text-slate-300">Energieverbrauch:</span>
|
||||
<span class="text-sm text-slate-600 dark:text-slate-400">{{ config_data.hardware_status.energy_usage.power or 'N/A' }}W</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="mt-6 pt-4 border-t border-slate-200 dark:border-slate-700">
|
||||
<button class="w-full px-4 py-2 bg-gradient-to-r from-blue-500 to-blue-600 text-white rounded-xl hover:from-blue-600 hover:to-blue-700 transition-all duration-300">
|
||||
{{ category.name }} bearbeiten
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<!-- Schnellaktionen -->
|
||||
<div class="mt-8">
|
||||
<div class="bg-white dark:bg-slate-800 rounded-2xl shadow-xl p-6">
|
||||
<h2 class="text-xl font-bold text-slate-900 dark:text-white mb-6 flex items-center">
|
||||
<svg class="w-6 h-6 mr-2 text-green-500" 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>
|
||||
Schnellaktionen
|
||||
</h2>
|
||||
|
||||
<div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-6 gap-4">
|
||||
{% for action in config_data.available_actions %}
|
||||
<button class="flex flex-col items-center p-4 bg-gradient-to-br from-slate-50 to-slate-100 dark:from-slate-700 dark:to-slate-800 rounded-xl hover:from-blue-50 hover:to-blue-100 dark:hover:from-blue-800/20 dark:hover:to-blue-700/20 transition-all duration-300 border border-slate-200 dark:border-slate-600 hover:border-blue-300 dark:hover:border-blue-600">
|
||||
{% if action == 'test_connection' %}
|
||||
<svg class="w-8 h-8 text-blue-500 mb-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8.111 16.404a5.5 5.5 0 017.778 0M12 20h.01m-7.08-7.071c3.904-3.905 10.236-3.905 14.141 0M1.394 9.393c5.857-5.857 15.355-5.857 21.213 0"/>
|
||||
</svg>
|
||||
<span class="text-xs font-medium text-slate-700 dark:text-slate-300 text-center">Verbindung testen</span>
|
||||
{% elif action == 'reset_settings' %}
|
||||
<svg class="w-8 h-8 text-orange-500 mb-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<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 font-medium text-slate-700 dark:text-slate-300 text-center">Einstellungen zurücksetzen</span>
|
||||
{% elif action == 'calibrate' %}
|
||||
<svg class="w-8 h-8 text-green-500 mb-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/>
|
||||
</svg>
|
||||
<span class="text-xs font-medium text-slate-700 dark:text-slate-300 text-center">Kalibrieren</span>
|
||||
{% elif action == 'factory_reset' %}
|
||||
<svg class="w-8 h-8 text-red-500 mb-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L4.082 16.5c-.77.833.192 2.5 1.732 2.5z"/>
|
||||
</svg>
|
||||
<span class="text-xs font-medium text-slate-700 dark:text-slate-300 text-center">Werksreset</span>
|
||||
{% elif action == 'export_config' %}
|
||||
<svg class="w-8 h-8 text-purple-500 mb-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 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="text-xs font-medium text-slate-700 dark:text-slate-300 text-center">Konfiguration exportieren</span>
|
||||
{% elif action == 'import_config' %}
|
||||
<svg class="w-8 h-8 text-indigo-500 mb-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v6m0 0l3-3m-3 3L9 7m3 3l3-3m-3 3l-3-3m2 8H7a2 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="text-xs font-medium text-slate-700 dark:text-slate-300 text-center">Konfiguration importieren</span>
|
||||
{% endif %}
|
||||
</button>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
@ -421,7 +421,7 @@
|
||||
<p class="mb-4" style="color: var(--text-secondary);">
|
||||
Es wurden noch keine Drucker mit Tapo-Steckdosen eingerichtet.
|
||||
</p>
|
||||
<a href="{{ url_for('admin.printers_overview') }}" class="btn-primary inline-flex items-center">
|
||||
<a href="{{ url_for('admin.admin_dashboard') }}" class="btn-primary inline-flex items-center">
|
||||
<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="M12 6v6m0 0v6m0-6h6m-6 0H6"/>
|
||||
</svg>
|
||||
|
@ -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>
|
||||
|
Reference in New Issue
Block a user