Title: Enhanced System Logs and UI Updates
🎉 New system logs have been implemented for improved monitoring and debugging capabilities. These include:
- admin.log
- admin_api.log
- app.log
- data_management.log
- drucker_steuerung.log
- energy_monitoring.log
- hardware_integration.log
- job_queue_system.log
- monitoring_analytics.log
- permissions.
This commit is contained in:
@ -358,80 +358,234 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
|
||||
{% if active_tab == 'users' %}
|
||||
<!-- Benutzer Tab -->
|
||||
<div class="p-12">
|
||||
<div class="flex items-center justify-between mb-6">
|
||||
<h2 class="text-2xl font-bold text-slate-900 dark:text-white">Benutzerverwaltung</h2>
|
||||
<button id="add-user-btn" class="inline-flex items-center 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 shadow-lg hover:shadow-xl">
|
||||
<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>
|
||||
Neuer Benutzer
|
||||
</button>
|
||||
<div class="p-8">
|
||||
<!-- Header mit Statistiken -->
|
||||
<div class="flex items-center justify-between mb-8">
|
||||
<div>
|
||||
<h2 class="text-3xl font-bold text-slate-900 dark:text-white mb-2">Granulare Benutzerverwaltung</h2>
|
||||
<p class="text-slate-600 dark:text-slate-400">Verwalten Sie Benutzer und deren Berechtigungen direkt im Admin Panel</p>
|
||||
</div>
|
||||
<div class="flex items-center space-x-4">
|
||||
<div class="bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-xl px-4 py-2">
|
||||
<div class="text-sm text-blue-600 dark:text-blue-400">Benutzer gesamt</div>
|
||||
<div class="text-2xl font-bold text-blue-800 dark:text-blue-300">{{ users|length }}</div>
|
||||
</div>
|
||||
<button id="add-user-btn" class="inline-flex items-center px-6 py-3 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 shadow-lg hover:shadow-xl">
|
||||
<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>
|
||||
Neuer Benutzer
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Filter und Suche -->
|
||||
<div class="bg-slate-50 dark:bg-slate-800/50 rounded-xl p-6 mb-8">
|
||||
<div class="flex flex-wrap items-center justify-between gap-4">
|
||||
<div class="flex items-center space-x-4">
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Suche</label>
|
||||
<input type="text" id="user-search" placeholder="Benutzer suchen..."
|
||||
class="px-4 py-2 border border-slate-300 dark:border-slate-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-slate-700 dark:text-white">
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Rolle</label>
|
||||
<select id="role-filter" class="px-4 py-2 border border-slate-300 dark:border-slate-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-slate-700 dark:text-white">
|
||||
<option value="">Alle Rollen</option>
|
||||
<option value="admin">Administrator</option>
|
||||
<option value="user">Benutzer</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Status</label>
|
||||
<select id="status-filter" class="px-4 py-2 border border-slate-300 dark:border-slate-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-slate-700 dark:text-white">
|
||||
<option value="">Alle Status</option>
|
||||
<option value="active">Aktiv</option>
|
||||
<option value="inactive">Inaktiv</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center space-x-2">
|
||||
<button id="bulk-actions-btn" class="px-4 py-2 bg-slate-200 dark:bg-slate-600 text-slate-700 dark:text-slate-300 rounded-lg hover:bg-slate-300 dark:hover:bg-slate-500 transition-colors">
|
||||
Massenaktionen
|
||||
</button>
|
||||
<button id="export-users-btn" class="px-4 py-2 bg-green-500 text-white rounded-lg hover:bg-green-600 transition-colors">
|
||||
Export
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Benutzer Tabelle -->
|
||||
<div class="overflow-x-auto">
|
||||
<table class="min-w-full divide-y divide-slate-200 dark:divide-slate-700">
|
||||
<thead class="bg-slate-50 dark:bg-slate-900/50">
|
||||
<tr>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-slate-500 dark:text-slate-400 uppercase tracking-wider">Benutzer</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-slate-500 dark:text-slate-400 uppercase tracking-wider">E-Mail</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-slate-500 dark:text-slate-400 uppercase tracking-wider">Rolle</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">Letzte Aktivität</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 class="bg-white dark:bg-slate-800/50 divide-y divide-slate-200 dark:divide-slate-700">
|
||||
<!-- Erweiterte Benutzer-Management-Tabelle -->
|
||||
<div class="bg-white dark:bg-slate-800 rounded-xl shadow-lg overflow-hidden">
|
||||
<div class="overflow-x-auto">
|
||||
<table class="min-w-full divide-y divide-slate-200 dark:divide-slate-700">
|
||||
<thead class="bg-slate-50 dark:bg-slate-900/50">
|
||||
<tr>
|
||||
<th class="px-6 py-4 text-left">
|
||||
<input type="checkbox" id="select-all-users" class="rounded border-slate-300 text-blue-600 focus:ring-blue-500">
|
||||
</th>
|
||||
<th class="px-6 py-4 text-left text-xs font-medium text-slate-500 dark:text-slate-400 uppercase tracking-wider">Benutzer</th>
|
||||
<th class="px-6 py-4 text-left text-xs font-medium text-slate-500 dark:text-slate-400 uppercase tracking-wider">Kontakt</th>
|
||||
<th class="px-6 py-4 text-left text-xs font-medium text-slate-500 dark:text-slate-400 uppercase tracking-wider">Rolle & Status</th>
|
||||
<th class="px-6 py-4 text-left text-xs font-medium text-slate-500 dark:text-slate-400 uppercase tracking-wider">Berechtigungen</th>
|
||||
<th class="px-6 py-4 text-left text-xs font-medium text-slate-500 dark:text-slate-400 uppercase tracking-wider">Aktivität</th>
|
||||
<th class="px-6 py-4 text-left text-xs font-medium text-slate-500 dark:text-slate-400 uppercase tracking-wider">Schnellaktionen</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="bg-white dark:bg-slate-800 divide-y divide-slate-200 dark:divide-slate-700" id="users-table-body">
|
||||
{% for user in users %}
|
||||
<tr class="hover:bg-slate-50 dark:hover:bg-slate-700/50 transition-colors duration-200">
|
||||
<tr class="hover:bg-slate-50 dark:hover:bg-slate-700/50 transition-colors duration-200" data-user-id="{{ user.id }}">
|
||||
<!-- Checkbox -->
|
||||
<td class="px-6 py-4 whitespace-nowrap">
|
||||
<input type="checkbox" class="user-checkbox rounded border-slate-300 text-blue-600 focus:ring-blue-500" value="{{ user.id }}">
|
||||
</td>
|
||||
|
||||
<!-- Benutzer Info -->
|
||||
<td class="px-6 py-4 whitespace-nowrap">
|
||||
<div class="flex items-center">
|
||||
<div class="flex-shrink-0 h-10 w-10">
|
||||
<div class="h-10 w-10 rounded-full bg-gradient-to-br from-blue-500 to-purple-600 flex items-center justify-center text-white font-semibold">
|
||||
<div class="flex-shrink-0 h-12 w-12">
|
||||
<div class="h-12 w-12 rounded-full bg-gradient-to-br from-blue-500 to-purple-600 flex items-center justify-center text-white font-semibold text-lg">
|
||||
{{ user.username[0].upper() }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="ml-4">
|
||||
<div class="text-sm font-medium text-slate-900 dark:text-white">{{ user.username }}</div>
|
||||
<div class="text-sm text-slate-500 dark:text-slate-400">{{ user.name or 'Kein Name' }}</div>
|
||||
{% if user.department %}
|
||||
<div class="text-xs text-slate-400 dark:text-slate-500">{{ user.department }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-slate-900 dark:text-white">{{ user.email }}</td>
|
||||
|
||||
<!-- Kontakt -->
|
||||
<td class="px-6 py-4 whitespace-nowrap">
|
||||
<span class="inline-flex px-2 py-1 text-xs font-semibold rounded-full {{ 'bg-purple-100 text-purple-800 dark:bg-purple-900 dark:text-purple-200' if user.is_admin else 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200' }}">
|
||||
{{ 'Administrator' if user.is_admin else 'Benutzer' }}
|
||||
</span>
|
||||
<div class="text-sm text-slate-900 dark:text-white">{{ user.email }}</div>
|
||||
{% if user.phone %}
|
||||
<div class="text-sm text-slate-500 dark:text-slate-400">{{ user.phone }}</div>
|
||||
{% endif %}
|
||||
</td>
|
||||
|
||||
<!-- Rolle & Status -->
|
||||
<td class="px-6 py-4 whitespace-nowrap">
|
||||
<span class="inline-flex items-center px-2 py-1 text-xs font-semibold rounded-full {{ 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200' if user.is_active else 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200' }}">
|
||||
<span class="w-2 h-2 mr-1 rounded-full {{ 'bg-green-400' if user.is_active else 'bg-red-400' }}"></span>
|
||||
{{ 'Aktiv' if user.is_active else 'Inaktiv' }}
|
||||
</span>
|
||||
<div class="space-y-2">
|
||||
<!-- Rolle -->
|
||||
<div>
|
||||
<select class="role-select text-xs px-2 py-1 rounded-full border-0 {{ 'bg-purple-100 text-purple-800 dark:bg-purple-900 dark:text-purple-200' if user.is_admin else 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200' }}"
|
||||
data-user-id="{{ user.id }}" onchange="updateUserRole({{ user.id }}, this.value)">
|
||||
<option value="user" {{ 'selected' if not user.is_admin else '' }}>Benutzer</option>
|
||||
<option value="admin" {{ 'selected' if user.is_admin else '' }}>Administrator</option>
|
||||
</select>
|
||||
</div>
|
||||
<!-- Status Toggle -->
|
||||
<div>
|
||||
<label class="inline-flex items-center">
|
||||
<input type="checkbox" class="status-toggle rounded border-slate-300 text-green-600 focus:ring-green-500"
|
||||
data-user-id="{{ user.id }}" {{ 'checked' if user.active else '' }}
|
||||
onchange="toggleUserStatus({{ user.id }}, this.checked)">
|
||||
<span class="ml-2 text-xs {{ 'text-green-700 dark:text-green-400' if user.active else 'text-red-700 dark:text-red-400' }}">
|
||||
{{ 'Aktiv' if user.active else 'Inaktiv' }}
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-slate-500 dark:text-slate-400">
|
||||
{{ user.last_login | format_datetime if user.last_login else 'Nie' }}
|
||||
|
||||
<!-- Granulare Berechtigungen -->
|
||||
<td class="px-6 py-4 whitespace-nowrap">
|
||||
{% if user.is_admin %}
|
||||
<div class="inline-flex items-center px-3 py-1 rounded-full text-xs font-medium bg-purple-100 text-purple-800 dark:bg-purple-900 dark:text-purple-200">
|
||||
<svg class="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 3l14 9-14 9V3z"/>
|
||||
</svg>
|
||||
Alle Rechte
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="space-y-2">
|
||||
<!-- Jobs starten -->
|
||||
<div class="flex items-center">
|
||||
<input type="checkbox" class="permission-toggle rounded border-slate-300 text-blue-600 focus:ring-blue-500"
|
||||
data-user-id="{{ user.id }}" data-permission="can_start_jobs"
|
||||
{{ 'checked' if user.permissions and user.permissions.can_start_jobs else '' }}
|
||||
onchange="updateUserPermission({{ user.id }}, 'can_start_jobs', this.checked)">
|
||||
<span class="ml-2 text-xs text-slate-600 dark:text-slate-400">Jobs starten</span>
|
||||
</div>
|
||||
<!-- Genehmigung erforderlich -->
|
||||
<div class="flex items-center">
|
||||
<input type="checkbox" class="permission-toggle rounded border-slate-300 text-yellow-600 focus:ring-yellow-500"
|
||||
data-user-id="{{ user.id }}" data-permission="needs_approval"
|
||||
{{ 'checked' if user.permissions and user.permissions.needs_approval else '' }}
|
||||
onchange="updateUserPermission({{ user.id }}, 'needs_approval', this.checked)">
|
||||
<span class="ml-2 text-xs text-slate-600 dark:text-slate-400">Benötigt Genehmigung</span>
|
||||
</div>
|
||||
<!-- Jobs genehmigen -->
|
||||
<div class="flex items-center">
|
||||
<input type="checkbox" class="permission-toggle rounded border-slate-300 text-green-600 focus:ring-green-500"
|
||||
data-user-id="{{ user.id }}" data-permission="can_approve_jobs"
|
||||
{{ 'checked' if user.permissions and user.permissions.can_approve_jobs else '' }}
|
||||
onchange="updateUserPermission({{ user.id }}, 'can_approve_jobs', this.checked)">
|
||||
<span class="ml-2 text-xs text-slate-600 dark:text-slate-400">Jobs genehmigen</span>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
|
||||
<div class="flex space-x-2">
|
||||
<button class="edit-user-btn text-blue-600 hover:text-blue-900 dark:text-blue-400 dark:hover:text-blue-300 transition-colors" data-user-id="{{ user.id }}" title="Benutzer bearbeiten">
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
|
||||
<!-- Aktivität -->
|
||||
<td class="px-6 py-4 whitespace-nowrap">
|
||||
<div class="text-sm text-slate-900 dark:text-white">
|
||||
{% if user.last_login %}
|
||||
Letzte Anmeldung:
|
||||
<div class="text-xs text-slate-500 dark:text-slate-400">{{ user.last_login.strftime('%d.%m.%Y %H:%M') if user.last_login else 'Nie' }}</div>
|
||||
{% else %}
|
||||
<span class="text-slate-500 dark:text-slate-400">Nie angemeldet</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if user.last_activity %}
|
||||
<div class="text-xs text-slate-400 dark:text-slate-500 mt-1">
|
||||
Aktivität: {{ user.last_activity.strftime('%d.%m.%Y %H:%M') }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</td>
|
||||
|
||||
<!-- Schnellaktionen -->
|
||||
<td class="px-6 py-4 whitespace-nowrap">
|
||||
<div class="flex items-center space-x-2">
|
||||
<!-- Benutzer bearbeiten -->
|
||||
<button class="edit-user-btn text-blue-600 hover:text-blue-900 dark:text-blue-400 dark:hover:text-blue-300 transition-colors p-1 rounded"
|
||||
data-user-id="{{ user.id }}" title="Benutzer bearbeiten">
|
||||
<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="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"/>
|
||||
</svg>
|
||||
</button>
|
||||
{% if not user.is_admin %}
|
||||
<button class="permissions-user-btn text-green-600 hover:text-green-900 dark:text-green-400 dark:hover:text-green-300 transition-colors" data-user-id="{{ user.id }}" data-user-name="{{ user.username }}" title="Berechtigungen verwalten">
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"/>
|
||||
|
||||
<!-- Passwort zurücksetzen -->
|
||||
<button class="reset-password-btn text-orange-600 hover:text-orange-900 dark:text-orange-400 dark:hover:text-orange-300 transition-colors p-1 rounded"
|
||||
data-user-id="{{ user.id }}" data-user-name="{{ user.username }}" title="Passwort zurücksetzen">
|
||||
<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="M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1121 9z"/>
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<!-- Als Benutzer anmelden (Impersonation) -->
|
||||
{% if not user.is_admin and current_user.is_admin %}
|
||||
<button class="impersonate-user-btn text-purple-600 hover:text-purple-900 dark:text-purple-400 dark:hover:text-purple-300 transition-colors p-1 rounded"
|
||||
data-user-id="{{ user.id }}" data-user-name="{{ user.username }}" title="Als Benutzer anmelden">
|
||||
<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="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"/>
|
||||
</svg>
|
||||
</button>
|
||||
{% endif %}
|
||||
<button class="delete-user-btn text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300 transition-colors" data-user-id="{{ user.id }}" data-user-name="{{ user.username }}" title="Benutzer löschen">
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
|
||||
<!-- Benutzer löschen -->
|
||||
{% if user.id != current_user.id %}
|
||||
<button class="delete-user-btn text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300 transition-colors p-1 rounded"
|
||||
data-user-id="{{ user.id }}" data-user-name="{{ user.username }}" title="Benutzer löschen">
|
||||
<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>
|
||||
</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
Reference in New Issue
Block a user