- Fix: Notifiable-Trait zum User-Model hinzugefuegt (behebt notify()-500er) - Installer: SMTP-Verbindungstest mit EsmtpTransport + Ueberspringen-Link - Admin: Neuer E-Mail-Tab mit SMTP-Konfiguration + Verbindungstest - Admin: Lazy Quill-Initialisierung (nur sichtbare Locale wird geladen) - Uebersetzungen: 17 neue Mail-Keys in allen 6 Sprachen Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
150 lines
11 KiB
PHP
150 lines
11 KiB
PHP
<x-layouts.admin :title="__('admin.activity_log_title')">
|
||
<h1 class="text-2xl font-bold mb-6">{{ __('admin.activity_log_title') }}</h1>
|
||
|
||
{{-- Filter --}}
|
||
<form method="GET" class="bg-white rounded-lg shadow p-4 mb-6">
|
||
<div class="flex flex-wrap gap-4 items-end">
|
||
<div>
|
||
<label class="block text-xs font-medium text-gray-600 mb-1">{{ __('admin.log_category') }}</label>
|
||
<select name="category" class="px-3 py-2 border border-gray-300 rounded-md text-sm">
|
||
<option value="">{{ __('admin.log_all_categories') }}</option>
|
||
<option value="auth" {{ request('category') === 'auth' ? 'selected' : '' }}>{{ __('admin.log_cat_auth') }}</option>
|
||
<option value="users" {{ request('category') === 'users' ? 'selected' : '' }}>{{ __('admin.log_cat_users') }}</option>
|
||
<option value="players" {{ request('category') === 'players' ? 'selected' : '' }}>{{ __('admin.log_cat_players') }}</option>
|
||
<option value="events" {{ request('category') === 'events' ? 'selected' : '' }}>{{ __('admin.log_cat_events') }}</option>
|
||
<option value="files" {{ request('category') === 'files' ? 'selected' : '' }}>{{ __('admin.log_cat_files') }}</option>
|
||
<option value="settings" {{ request('category') === 'settings' ? 'selected' : '' }}>{{ __('admin.log_cat_settings') }}</option>
|
||
<option value="dsgvo" {{ request('category') === 'dsgvo' ? 'selected' : '' }}>{{ __('admin.log_cat_dsgvo') }}</option>
|
||
</select>
|
||
</div>
|
||
<div>
|
||
<label class="block text-xs font-medium text-gray-600 mb-1">{{ __('admin.log_from') }}</label>
|
||
<input type="date" name="from" value="{{ request('from') }}" class="px-3 py-2 border border-gray-300 rounded-md text-sm">
|
||
</div>
|
||
<div>
|
||
<label class="block text-xs font-medium text-gray-600 mb-1">{{ __('admin.log_to') }}</label>
|
||
<input type="date" name="to" value="{{ request('to') }}" class="px-3 py-2 border border-gray-300 rounded-md text-sm">
|
||
</div>
|
||
<div class="flex gap-2">
|
||
<button type="submit" class="bg-blue-600 text-white px-4 py-2 rounded-md text-sm font-medium hover:bg-blue-700">{{ __('admin.log_filter') }}</button>
|
||
<a href="{{ route('admin.activity-logs.index') }}" class="bg-gray-200 text-gray-700 px-4 py-2 rounded-md text-sm font-medium hover:bg-gray-300">{{ __('admin.log_reset') }}</a>
|
||
</div>
|
||
</div>
|
||
</form>
|
||
|
||
{{-- Tabelle --}}
|
||
<div class="bg-white rounded-lg shadow overflow-hidden overflow-x-auto">
|
||
<table class="w-full text-sm">
|
||
<thead class="bg-gray-50 border-b">
|
||
<tr>
|
||
<th class="text-left px-4 py-3 font-medium text-gray-700">{{ __('admin.log_time') }}</th>
|
||
<th class="text-left px-4 py-3 font-medium text-gray-700">{{ __('admin.log_user') }}</th>
|
||
<th class="text-center px-4 py-3 font-medium text-gray-700">{{ __('admin.log_action') }}</th>
|
||
<th class="text-left px-4 py-3 font-medium text-gray-700">{{ __('admin.log_description') }}</th>
|
||
<th class="text-right px-4 py-3 font-medium text-gray-700">{{ __('admin.log_ip') }}</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody class="divide-y divide-gray-100">
|
||
@forelse ($logs as $log)
|
||
@php
|
||
$actionColors = [
|
||
'login' => 'bg-green-100 text-green-800',
|
||
'logout' => 'bg-gray-100 text-gray-800',
|
||
'login_failed' => 'bg-red-100 text-red-800',
|
||
'registered' => 'bg-blue-100 text-blue-800',
|
||
'created' => 'bg-blue-100 text-blue-800',
|
||
'updated' => 'bg-yellow-100 text-yellow-800',
|
||
'deleted' => 'bg-red-100 text-red-800',
|
||
'restored' => 'bg-green-100 text-green-800',
|
||
'toggled_active' => 'bg-yellow-100 text-yellow-800',
|
||
'role_changed' => 'bg-purple-100 text-purple-800',
|
||
'password_reset' => 'bg-orange-100 text-orange-800',
|
||
'parent_assigned' => 'bg-blue-100 text-blue-800',
|
||
'parent_removed' => 'bg-red-100 text-red-800',
|
||
'participant_status_changed' => 'bg-yellow-100 text-yellow-800',
|
||
'status_changed' => 'bg-yellow-100 text-yellow-800',
|
||
'uploaded' => 'bg-blue-100 text-blue-800',
|
||
'reverted' => 'bg-orange-100 text-orange-800',
|
||
'bot_blocked' => 'bg-red-100 text-red-800',
|
||
'dsgvo_consent_uploaded' => 'bg-blue-100 text-blue-800',
|
||
'dsgvo_consent_confirmed' => 'bg-green-100 text-green-800',
|
||
'dsgvo_consent_revoked' => 'bg-yellow-100 text-yellow-800',
|
||
'dsgvo_consent_removed' => 'bg-orange-100 text-orange-800',
|
||
'dsgvo_consent_rejected' => 'bg-red-100 text-red-800',
|
||
'account_self_deleted' => 'bg-red-100 text-red-800',
|
||
'child_auto_deactivated' => 'bg-red-100 text-red-800',
|
||
];
|
||
$color = $actionColors[$log->action] ?? 'bg-gray-100 text-gray-800';
|
||
$hasDetails = !empty($log->properties);
|
||
@endphp
|
||
<tr class="hover:bg-gray-50" x-data="{ open: false }">
|
||
<td class="px-4 py-3 text-gray-500 whitespace-nowrap">{{ $log->created_at->format('d.m.Y H:i') }}</td>
|
||
<td class="px-4 py-3 text-gray-900">{{ $log->user?->name ?? __('admin.log_system') }}</td>
|
||
<td class="px-4 py-3 text-center">
|
||
<span class="inline-block px-2 py-0.5 rounded-full text-xs font-medium {{ $color }}">{{ $log->action }}</span>
|
||
</td>
|
||
<td class="px-4 py-3 text-gray-600">
|
||
<div>{{ $log->description }}</div>
|
||
@if ($hasDetails)
|
||
<button @click="open = !open" class="text-xs text-blue-600 hover:text-blue-800 mt-1 flex items-center gap-1">
|
||
<svg class="w-3 h-3 transition-transform" :class="open ? 'rotate-90' : ''" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/></svg>
|
||
{{ __('admin.log_details') }}
|
||
</button>
|
||
<div x-show="open" x-cloak x-transition class="mt-2 bg-gray-50 rounded-md p-3 text-xs space-y-1">
|
||
@php
|
||
$oldData = $log->properties['old'] ?? [];
|
||
$newData = $log->properties['new'] ?? [];
|
||
$allKeys = array_unique(array_merge(array_keys($oldData), array_keys($newData)));
|
||
@endphp
|
||
@if (count($allKeys) > 0)
|
||
<table class="w-full">
|
||
<thead>
|
||
<tr class="text-gray-500">
|
||
<th class="text-left font-medium pr-3 pb-1">{{ __('admin.log_field') }}</th>
|
||
<th class="text-left font-medium pr-3 pb-1">{{ __('admin.log_old_value') }}</th>
|
||
<th class="text-left font-medium pb-1">{{ __('admin.log_new_value') }}</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
@foreach ($allKeys as $key)
|
||
<tr>
|
||
<td class="pr-3 py-0.5 font-medium text-gray-600">{{ $key }}</td>
|
||
<td class="pr-3 py-0.5 {{ isset($oldData[$key]) ? 'text-red-600 line-through' : 'text-gray-400' }}">{{ $oldData[$key] ?? '–' }}</td>
|
||
<td class="py-0.5 {{ isset($newData[$key]) ? 'text-green-700' : 'text-gray-400' }}">{{ $newData[$key] ?? '–' }}</td>
|
||
</tr>
|
||
@endforeach
|
||
</tbody>
|
||
</table>
|
||
@endif
|
||
</div>
|
||
@endif
|
||
</td>
|
||
<td class="px-4 py-3 text-right whitespace-nowrap">
|
||
<span class="text-gray-400 text-xs">{{ $log->ip_address }}</span>
|
||
@php
|
||
$revertableActions = ['deleted', 'toggled_active', 'role_changed', 'status_changed', 'participant_status_changed'];
|
||
$canRevert = in_array($log->action, $revertableActions) && $log->model_id;
|
||
@endphp
|
||
@if ($canRevert)
|
||
<form method="POST" action="{{ route('admin.activity-logs.revert', $log) }}"
|
||
onsubmit="return confirm(@js(__('admin.log_revert_confirm')))" class="inline ml-2">
|
||
@csrf
|
||
<button type="submit" class="text-xs text-orange-600 hover:text-orange-800 font-medium">
|
||
{{ __('admin.log_revert') }}
|
||
</button>
|
||
</form>
|
||
@endif
|
||
</td>
|
||
</tr>
|
||
@empty
|
||
<tr>
|
||
<td colspan="5" class="px-4 py-8 text-center text-gray-500">{{ __('admin.log_empty') }}</td>
|
||
</tr>
|
||
@endforelse
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
<div class="mt-4">{{ $logs->links() }}</div>
|
||
</x-layouts.admin>
|