log Benutzer Fix
Dieser Commit ist enthalten in:
37
JOURNAL.md
37
JOURNAL.md
@@ -1,5 +1,42 @@
|
|||||||
# v2-Docker Projekt Journal
|
# v2-Docker Projekt Journal
|
||||||
|
|
||||||
|
## Letzte Änderungen (22.06.2025 - 18:30 Uhr)
|
||||||
|
|
||||||
|
### Export-Funktionen komplett repariert ✅
|
||||||
|
|
||||||
|
**Probleme gefunden und behoben:**
|
||||||
|
|
||||||
|
1. **Parameter-Mismatch**: Templates übergaben `include_test`, Routes erwarteten `show_fake`
|
||||||
|
2. **Bootstrap Dropdowns funktionierten nicht**: JavaScript-Konflikt verhinderte Dropdown-Öffnung
|
||||||
|
3. **Excel Timezone-Fehler**: "Excel does not support datetimes with timezones"
|
||||||
|
|
||||||
|
**Implementierte Lösungen:**
|
||||||
|
|
||||||
|
1. **Nur echte Daten beim Export:**
|
||||||
|
- Alle Export-Queries filtern jetzt mit `WHERE is_fake = false`
|
||||||
|
- Keine Test/Fake-Daten mehr in Exporten
|
||||||
|
|
||||||
|
2. **Dropdown durch direkte Buttons ersetzt:**
|
||||||
|
- Statt problematischer Dropdowns: Einzelne Export-Buttons
|
||||||
|
- Funktioniert ohne JavaScript, zuverlässiger
|
||||||
|
- Übersichtlicher: alle Optionen sofort sichtbar
|
||||||
|
|
||||||
|
3. **Datetime-Formatierung für Excel-Kompatibilität:**
|
||||||
|
- `format_datetime_for_export()` entfernt Zeitzonen-Info
|
||||||
|
- Alle Datetime-Felder werden vor Export formatiert
|
||||||
|
- Einheitliches Format: `YYYY-MM-DD HH:MM:SS`
|
||||||
|
|
||||||
|
**Geänderte Dateien:**
|
||||||
|
- `templates/customers_licenses.html` - Export-Buttons statt Dropdown
|
||||||
|
- `templates/audit_log.html` - Export-Buttons statt Dropdown
|
||||||
|
- `templates/sessions.html` - Export-Buttons statt Dropdown
|
||||||
|
- `routes/export_routes.py` - Datetime-Formatierung für alle Exports
|
||||||
|
- `utils/export.py` - Timezone-Entfernung in format_datetime_for_export()
|
||||||
|
|
||||||
|
**Status:** Alle Export-Funktionen (Excel & CSV) funktionieren einwandfrei! ✅
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Letzte Änderungen (22.06.2025 - 16:49 Uhr)
|
## Letzte Änderungen (22.06.2025 - 16:49 Uhr)
|
||||||
|
|
||||||
### Export-Funktionen Analyse und Lösungsplan ✅
|
### Export-Funktionen Analyse und Lösungsplan ✅
|
||||||
|
|||||||
@@ -366,6 +366,7 @@ def audit_log():
|
|||||||
page = request.args.get('page', 1, type=int)
|
page = request.args.get('page', 1, type=int)
|
||||||
per_page = 50
|
per_page = 50
|
||||||
search = request.args.get('search', '')
|
search = request.args.get('search', '')
|
||||||
|
filter_user = request.args.get('user', '')
|
||||||
action_filter = request.args.get('action', '')
|
action_filter = request.args.get('action', '')
|
||||||
entity_filter = request.args.get('entity', '')
|
entity_filter = request.args.get('entity', '')
|
||||||
|
|
||||||
@@ -414,6 +415,11 @@ def audit_log():
|
|||||||
query += " AND entity_type = %s"
|
query += " AND entity_type = %s"
|
||||||
params.append(entity_filter)
|
params.append(entity_filter)
|
||||||
|
|
||||||
|
# User Filter
|
||||||
|
if filter_user:
|
||||||
|
query += " AND username = %s"
|
||||||
|
params.append(filter_user)
|
||||||
|
|
||||||
# Count total
|
# Count total
|
||||||
count_query = f"SELECT COUNT(*) FROM ({query}) as filtered"
|
count_query = f"SELECT COUNT(*) FROM ({query}) as filtered"
|
||||||
cur.execute(count_query, params)
|
cur.execute(count_query, params)
|
||||||
@@ -473,8 +479,9 @@ def audit_log():
|
|||||||
logs=audit_logs,
|
logs=audit_logs,
|
||||||
page=page,
|
page=page,
|
||||||
total_pages=total_pages,
|
total_pages=total_pages,
|
||||||
total_count=total_count,
|
total=total_count,
|
||||||
search=search,
|
search=search,
|
||||||
|
filter_user=filter_user,
|
||||||
action_filter=action_filter,
|
action_filter=action_filter,
|
||||||
entity_filter=entity_filter,
|
entity_filter=entity_filter,
|
||||||
actions=actions,
|
actions=actions,
|
||||||
|
|||||||
@@ -5,10 +5,10 @@
|
|||||||
{% macro sortable_header(label, field, current_sort, current_order) %}
|
{% macro sortable_header(label, field, current_sort, current_order) %}
|
||||||
<th>
|
<th>
|
||||||
{% if current_sort == field %}
|
{% if current_sort == field %}
|
||||||
<a href="{{ url_for('admin.audit_log', sort=field, order='desc' if current_order == 'asc' else 'asc', user=filter_user, action=filter_action, entity=filter_entity, page=1) }}"
|
<a href="{{ url_for('admin.audit_log', sort=field, order='desc' if current_order == 'asc' else 'asc', user=filter_user, action=action_filter, entity=entity_filter, page=1) }}"
|
||||||
class="server-sortable">
|
class="server-sortable">
|
||||||
{% else %}
|
{% else %}
|
||||||
<a href="{{ url_for('admin.audit_log', sort=field, order='asc', user=filter_user, action=filter_action, entity=filter_entity, page=1) }}"
|
<a href="{{ url_for('admin.audit_log', sort=field, order='asc', user=filter_user, action=action_filter, entity=entity_filter, page=1) }}"
|
||||||
class="server-sortable">
|
class="server-sortable">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{{ label }}
|
{{ label }}
|
||||||
@@ -111,83 +111,83 @@
|
|||||||
<div class="row g-3 align-items-end">
|
<div class="row g-3 align-items-end">
|
||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
<label for="user" class="form-label">Benutzer</label>
|
<label for="user" class="form-label">Benutzer</label>
|
||||||
<input type="text" class="form-control" id="user" name="user"
|
<select class="form-select" id="user" name="user">
|
||||||
placeholder="Benutzername..." value="{{ filter_user }}">
|
<option value="">Alle Benutzer</option>
|
||||||
|
<option value="rac00n" {% if filter_user == 'rac00n' %}selected{% endif %}>rac00n</option>
|
||||||
|
<option value="w@rh@mm3r" {% if filter_user == 'w@rh@mm3r' %}selected{% endif %}>w@rh@mm3r</option>
|
||||||
|
<option value="system" {% if filter_user == 'system' %}selected{% endif %}>System</option>
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
<label for="action" class="form-label">Aktion</label>
|
<label for="action" class="form-label">Aktion</label>
|
||||||
<select class="form-select" id="action" name="action">
|
<select class="form-select" id="action" name="action">
|
||||||
<option value="">Alle Aktionen</option>
|
<option value="">Alle Aktionen</option>
|
||||||
<optgroup label="CRUD-Operationen">
|
{% for action in actions %}
|
||||||
<option value="CREATE" {% if filter_action == 'CREATE' %}selected{% endif %}>➕ Erstellt</option>
|
<option value="{{ action }}" {% if action_filter == action %}selected{% endif %}>
|
||||||
<option value="UPDATE" {% if filter_action == 'UPDATE' %}selected{% endif %}>✏️ Bearbeitet</option>
|
{% if action == 'CREATE' %}➕ Erstellt
|
||||||
<option value="DELETE" {% if filter_action == 'DELETE' %}selected{% endif %}>🗑️ Gelöscht</option>
|
{% elif action == 'UPDATE' %}✏️ Bearbeitet
|
||||||
<option value="IMPORT" {% if filter_action == 'IMPORT' %}selected{% endif %}>📤 Import</option>
|
{% elif action == 'DELETE' %}🗑️ Gelöscht
|
||||||
</optgroup>
|
{% elif action == 'IMPORT' %}📤 Import
|
||||||
<optgroup label="Authentifizierung">
|
{% elif action == 'LOGIN' %}🔑 Anmeldung
|
||||||
<option value="LOGIN" {% if filter_action == 'LOGIN' %}selected{% endif %}>🔑 Anmeldung</option>
|
{% elif action == 'LOGIN_SUCCESS' %}✅ Anmeldung erfolgreich
|
||||||
<option value="LOGIN_SUCCESS" {% if filter_action == 'LOGIN_SUCCESS' %}selected{% endif %}>✅ Anmeldung erfolgreich</option>
|
{% elif action == 'LOGIN_FAILED' %}❌ Anmeldung fehlgeschlagen
|
||||||
<option value="LOGIN_FAILED" {% if filter_action == 'LOGIN_FAILED' %}selected{% endif %}>❌ Anmeldung fehlgeschlagen</option>
|
{% elif action == 'LOGIN_BLOCKED' %}🚫 Login blockiert
|
||||||
<option value="LOGIN_BLOCKED" {% if filter_action == 'LOGIN_BLOCKED' %}selected{% endif %}>🚫 Login blockiert</option>
|
{% elif action == 'LOGOUT' %}🚪 Abmeldung
|
||||||
<option value="LOGOUT" {% if filter_action == 'LOGOUT' %}selected{% endif %}>🚪 Abmeldung</option>
|
{% elif action == 'AUTO_LOGOUT' %}⏰ Auto-Logout
|
||||||
<option value="AUTO_LOGOUT" {% if filter_action == 'AUTO_LOGOUT' %}selected{% endif %}>⏰ Auto-Logout</option>
|
{% elif action == 'LOGIN_2FA_SUCCESS' %}🔐 2FA-Anmeldung
|
||||||
</optgroup>
|
{% elif action == 'LOGIN_2FA_FAILED' %}⛔ 2FA fehlgeschlagen
|
||||||
<optgroup label="2FA-Authentifizierung">
|
{% elif action == 'LOGIN_2FA_BACKUP' %}🔒 2FA-Backup-Code
|
||||||
<option value="LOGIN_2FA_SUCCESS" {% if filter_action == 'LOGIN_2FA_SUCCESS' %}selected{% endif %}>🔐 2FA-Anmeldung</option>
|
{% elif action == '2FA_ENABLED' %}✅ 2FA aktiviert
|
||||||
<option value="LOGIN_2FA_FAILED" {% if filter_action == 'LOGIN_2FA_FAILED' %}selected{% endif %}>⛔ 2FA fehlgeschlagen</option>
|
{% elif action == '2FA_DISABLED' %}❌ 2FA deaktiviert
|
||||||
<option value="LOGIN_2FA_BACKUP" {% if filter_action == 'LOGIN_2FA_BACKUP' %}selected{% endif %}>🔒 2FA-Backup-Code</option>
|
{% elif action == 'GENERATE_KEY' %}🔑 Key generiert
|
||||||
<option value="2FA_ENABLED" {% if filter_action == '2FA_ENABLED' %}selected{% endif %}>✅ 2FA aktiviert</option>
|
{% elif action == 'CREATE_BATCH' %}📦 Batch erstellt
|
||||||
<option value="2FA_DISABLED" {% if filter_action == '2FA_DISABLED' %}selected{% endif %}>❌ 2FA deaktiviert</option>
|
{% elif action == 'BATCH_UPDATE' %}🔄 Batch Update
|
||||||
</optgroup>
|
{% elif action == 'TOGGLE' %}🔄 Status geändert
|
||||||
<optgroup label="Lizenzverwaltung">
|
{% elif action == 'QUICK_EDIT' %}⚡ Schnellbearbeitung
|
||||||
<option value="GENERATE_KEY" {% if filter_action == 'GENERATE_KEY' %}selected{% endif %}>🔑 Key generiert</option>
|
{% elif action == 'BULK_ACTIVATE' %}✅ Bulk-Aktivierung
|
||||||
<option value="CREATE_BATCH" {% if filter_action == 'CREATE_BATCH' %}selected{% endif %}>📦 Batch erstellt</option>
|
{% elif action == 'BULK_DEACTIVATE' %}❌ Bulk-Deaktivierung
|
||||||
<option value="BATCH_UPDATE" {% if filter_action == 'BATCH_UPDATE' %}selected{% endif %}>🔄 Batch Update</option>
|
{% elif action == 'BULK_DELETE' %}🗑️ Bulk-Löschung
|
||||||
<option value="TOGGLE" {% if filter_action == 'TOGGLE' %}selected{% endif %}>🔄 Status geändert</option>
|
{% elif action == 'DEVICE_REGISTER' %}📱 Gerät registriert
|
||||||
<option value="QUICK_EDIT" {% if filter_action == 'QUICK_EDIT' %}selected{% endif %}>⚡ Schnellbearbeitung</option>
|
{% elif action == 'DEVICE_DEACTIVATE' %}📵 Gerät deaktiviert
|
||||||
<option value="BULK_ACTIVATE" {% if filter_action == 'BULK_ACTIVATE' %}selected{% endif %}>✅ Bulk-Aktivierung</option>
|
{% elif action == 'RESOURCE_ALLOCATE' %}📎 Ressource zugewiesen
|
||||||
<option value="BULK_DEACTIVATE" {% if filter_action == 'BULK_DEACTIVATE' %}selected{% endif %}>❌ Bulk-Deaktivierung</option>
|
{% elif action == 'QUARANTINE' %}⚠️ In Quarantäne
|
||||||
<option value="BULK_DELETE" {% if filter_action == 'BULK_DELETE' %}selected{% endif %}>🗑️ Bulk-Löschung</option>
|
{% elif action == 'RELEASE' %}✅ Freigegeben
|
||||||
</optgroup>
|
{% elif action == 'BULK_CREATE' %}➕ Bulk-Erstellung
|
||||||
<optgroup label="Geräteverwaltung">
|
{% elif action == 'SESSION_TERMINATE' %}🛑 Session beendet
|
||||||
<option value="DEVICE_REGISTER" {% if filter_action == 'DEVICE_REGISTER' %}selected{% endif %}>📱 Gerät registriert</option>
|
{% elif action == 'SESSION_TERMINATE_ALL' %}🛑 Alle Sessions beendet
|
||||||
<option value="DEVICE_DEACTIVATE" {% if filter_action == 'DEVICE_DEACTIVATE' %}selected{% endif %}>📵 Gerät deaktiviert</option>
|
{% elif action == 'SESSION_CLEANUP' %}🧹 Session-Bereinigung
|
||||||
</optgroup>
|
{% elif action == 'BACKUP' %}💾 Backup
|
||||||
<optgroup label="Ressourcenverwaltung">
|
{% elif action == 'BACKUP_DOWNLOAD' %}⬇️ Backup Download
|
||||||
<option value="RESOURCE_ALLOCATE" {% if filter_action == 'RESOURCE_ALLOCATE' %}selected{% endif %}>📎 Ressource zugewiesen</option>
|
{% elif action == 'BACKUP_DELETE' %}🗑️ Backup gelöscht
|
||||||
<option value="QUARANTINE" {% if filter_action == 'QUARANTINE' %}selected{% endif %}>⚠️ In Quarantäne</option>
|
{% elif action == 'RESTORE' %}🔄 Wiederhergestellt
|
||||||
<option value="RELEASE" {% if filter_action == 'RELEASE' %}selected{% endif %}>✅ Freigegeben</option>
|
{% elif action == 'EXPORT' %}📥 Export
|
||||||
<option value="BULK_CREATE" {% if filter_action == 'BULK_CREATE' %}selected{% endif %}>➕ Bulk-Erstellung</option>
|
{% elif action == 'PASSWORD_CHANGE' %}🔐 Passwort geändert
|
||||||
</optgroup>
|
{% elif action == 'UNBLOCK_IP' %}🔓 IP entsperrt
|
||||||
<optgroup label="Session-Verwaltung">
|
{% elif action == 'CLEAR_LOGIN_ATTEMPTS' %}🧹 Login-Versuche gelöscht
|
||||||
<option value="SESSION_TERMINATE" {% if filter_action == 'SESSION_TERMINATE' %}selected{% endif %}>🛑 Session beendet</option>
|
{% else %}{{ action }}
|
||||||
<option value="SESSION_TERMINATE_ALL" {% if filter_action == 'SESSION_TERMINATE_ALL' %}selected{% endif %}>🛑 Alle Sessions beendet</option>
|
{% endif %}
|
||||||
<option value="SESSION_CLEANUP" {% if filter_action == 'SESSION_CLEANUP' %}selected{% endif %}>🧹 Session-Bereinigung</option>
|
</option>
|
||||||
</optgroup>
|
{% endfor %}
|
||||||
<optgroup label="System-Operationen">
|
|
||||||
<option value="BACKUP" {% if filter_action == 'BACKUP' %}selected{% endif %}>💾 Backup</option>
|
|
||||||
<option value="BACKUP_DOWNLOAD" {% if filter_action == 'BACKUP_DOWNLOAD' %}selected{% endif %}>⬇️ Backup Download</option>
|
|
||||||
<option value="BACKUP_DELETE" {% if filter_action == 'BACKUP_DELETE' %}selected{% endif %}>🗑️ Backup gelöscht</option>
|
|
||||||
<option value="RESTORE" {% if filter_action == 'RESTORE' %}selected{% endif %}>🔄 Wiederhergestellt</option>
|
|
||||||
<option value="EXPORT" {% if filter_action == 'EXPORT' %}selected{% endif %}>📥 Export</option>
|
|
||||||
<option value="PASSWORD_CHANGE" {% if filter_action == 'PASSWORD_CHANGE' %}selected{% endif %}>🔐 Passwort geändert</option>
|
|
||||||
<option value="UNBLOCK_IP" {% if filter_action == 'UNBLOCK_IP' %}selected{% endif %}>🔓 IP entsperrt</option>
|
|
||||||
<option value="CLEAR_LOGIN_ATTEMPTS" {% if filter_action == 'CLEAR_LOGIN_ATTEMPTS' %}selected{% endif %}>🧹 Login-Versuche gelöscht</option>
|
|
||||||
</optgroup>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
<label for="entity" class="form-label">Entität</label>
|
<label for="entity" class="form-label">Entität</label>
|
||||||
<select class="form-select" id="entity" name="entity">
|
<select class="form-select" id="entity" name="entity">
|
||||||
<option value="">Alle Entitäten</option>
|
<option value="">Alle Entitäten</option>
|
||||||
<option value="license" {% if filter_entity == 'license' %}selected{% endif %}>Lizenz</option>
|
{% for entity in entities %}
|
||||||
<option value="customer" {% if filter_entity == 'customer' %}selected{% endif %}>Kunde</option>
|
<option value="{{ entity }}" {% if entity_filter == entity %}selected{% endif %}>
|
||||||
<option value="user" {% if filter_entity == 'user' %}selected{% endif %}>Benutzer</option>
|
{% if entity == 'license' %}Lizenz
|
||||||
<option value="session" {% if filter_entity == 'session' %}selected{% endif %}>Session</option>
|
{% elif entity == 'customer' %}Kunde
|
||||||
<option value="resource" {% if filter_entity == 'resource' %}selected{% endif %}>Ressource</option>
|
{% elif entity == 'user' %}Benutzer
|
||||||
<option value="backup" {% if filter_entity == 'backup' %}selected{% endif %}>Backup</option>
|
{% elif entity == 'session' %}Session
|
||||||
<option value="database" {% if filter_entity == 'database' %}selected{% endif %}>Datenbank</option>
|
{% elif entity == 'resource' %}Ressource
|
||||||
<option value="system" {% if filter_entity == 'system' %}selected{% endif %}>System</option>
|
{% elif entity == 'backup' %}Backup
|
||||||
|
{% elif entity == 'database' %}Datenbank
|
||||||
|
{% elif entity == 'system' %}System
|
||||||
|
{% else %}{{ entity|title }}
|
||||||
|
{% endif %}
|
||||||
|
</option>
|
||||||
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
@@ -195,10 +195,10 @@
|
|||||||
<a href="{{ url_for('admin.audit_log') }}" class="btn btn-outline-secondary">Zurücksetzen</a>
|
<a href="{{ url_for('admin.audit_log') }}" class="btn btn-outline-secondary">Zurücksetzen</a>
|
||||||
<!-- Export Buttons -->
|
<!-- Export Buttons -->
|
||||||
<div class="btn-group" role="group">
|
<div class="btn-group" role="group">
|
||||||
<a href="{{ url_for('export.export_audit', format='excel', user=filter_user, action=filter_action, entity=filter_entity) }}" class="btn btn-success btn-sm">
|
<a href="{{ url_for('export.export_audit', format='excel', user=filter_user, action=action_filter, entity=entity_filter) }}" class="btn btn-success btn-sm">
|
||||||
<i class="bi bi-file-earmark-excel"></i> Excel
|
<i class="bi bi-file-earmark-excel"></i> Excel
|
||||||
</a>
|
</a>
|
||||||
<a href="{{ url_for('export.export_audit', format='csv', user=filter_user, action=filter_action, entity=filter_entity) }}" class="btn btn-secondary btn-sm">
|
<a href="{{ url_for('export.export_audit', format='csv', user=filter_user, action=action_filter, entity=entity_filter) }}" class="btn btn-secondary btn-sm">
|
||||||
<i class="bi bi-file-earmark-text"></i> CSV
|
<i class="bi bi-file-earmark-text"></i> CSV
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
@@ -324,31 +324,31 @@
|
|||||||
<ul class="pagination justify-content-center">
|
<ul class="pagination justify-content-center">
|
||||||
<!-- Erste Seite -->
|
<!-- Erste Seite -->
|
||||||
<li class="page-item {% if page == 1 %}disabled{% endif %}">
|
<li class="page-item {% if page == 1 %}disabled{% endif %}">
|
||||||
<a class="page-link" href="{{ url_for('admin.audit_log', page=1, user=filter_user, action=filter_action, entity=filter_entity, sort=sort, order=order) }}">Erste</a>
|
<a class="page-link" href="{{ url_for('admin.audit_log', page=1, user=filter_user, action=action_filter, entity=entity_filter, sort=sort, order=order) }}">Erste</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<!-- Vorherige Seite -->
|
<!-- Vorherige Seite -->
|
||||||
<li class="page-item {% if page == 1 %}disabled{% endif %}">
|
<li class="page-item {% if page == 1 %}disabled{% endif %}">
|
||||||
<a class="page-link" href="{{ url_for('admin.audit_log', page=page-1, user=filter_user, action=filter_action, entity=filter_entity, sort=sort, order=order) }}">←</a>
|
<a class="page-link" href="{{ url_for('admin.audit_log', page=page-1, user=filter_user, action=action_filter, entity=entity_filter, sort=sort, order=order) }}">←</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<!-- Seitenzahlen -->
|
<!-- Seitenzahlen -->
|
||||||
{% for p in range(1, total_pages + 1) %}
|
{% for p in range(1, total_pages + 1) %}
|
||||||
{% if p >= page - 2 and p <= page + 2 %}
|
{% if p >= page - 2 and p <= page + 2 %}
|
||||||
<li class="page-item {% if p == page %}active{% endif %}">
|
<li class="page-item {% if p == page %}active{% endif %}">
|
||||||
<a class="page-link" href="{{ url_for('admin.audit_log', page=p, user=filter_user, action=filter_action, entity=filter_entity, sort=sort, order=order) }}">{{ p }}</a>
|
<a class="page-link" href="{{ url_for('admin.audit_log', page=p, user=filter_user, action=action_filter, entity=entity_filter, sort=sort, order=order) }}">{{ p }}</a>
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
<!-- Nächste Seite -->
|
<!-- Nächste Seite -->
|
||||||
<li class="page-item {% if page == total_pages %}disabled{% endif %}">
|
<li class="page-item {% if page == total_pages %}disabled{% endif %}">
|
||||||
<a class="page-link" href="{{ url_for('admin.audit_log', page=page+1, user=filter_user, action=filter_action, entity=filter_entity, sort=sort, order=order) }}">→</a>
|
<a class="page-link" href="{{ url_for('admin.audit_log', page=page+1, user=filter_user, action=action_filter, entity=entity_filter, sort=sort, order=order) }}">→</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<!-- Letzte Seite -->
|
<!-- Letzte Seite -->
|
||||||
<li class="page-item {% if page == total_pages %}disabled{% endif %}">
|
<li class="page-item {% if page == total_pages %}disabled{% endif %}">
|
||||||
<a class="page-link" href="{{ url_for('admin.audit_log', page=total_pages, user=filter_user, action=filter_action, entity=filter_entity, sort=sort, order=order) }}">Letzte</a>
|
<a class="page-link" href="{{ url_for('admin.audit_log', page=total_pages, user=filter_user, action=action_filter, entity=entity_filter, sort=sort, order=order) }}">Letzte</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p class="text-center text-muted">
|
<p class="text-center text-muted">
|
||||||
@@ -373,12 +373,9 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
// Debounce timer für Textfelder
|
// Debounce timer für Textfelder
|
||||||
let searchTimeout;
|
let searchTimeout;
|
||||||
|
|
||||||
// Live-Filter für Benutzer-Textfeld (mit 300ms Verzögerung)
|
// Live-Filter für Benutzer-Dropdown (sofort)
|
||||||
userInput.addEventListener('input', function() {
|
userInput.addEventListener('change', function() {
|
||||||
clearTimeout(searchTimeout);
|
filterForm.submit();
|
||||||
searchTimeout = setTimeout(() => {
|
|
||||||
filterForm.submit();
|
|
||||||
}, 300);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Live-Filter für Dropdowns (sofort)
|
// Live-Filter für Dropdowns (sofort)
|
||||||
|
|||||||
In neuem Issue referenzieren
Einen Benutzer sperren