121 lines
6.2 KiB
PHP
121 lines
6.2 KiB
PHP
<div class="space-y-4">
|
|
{{-- Header --}}
|
|
<div class="flex flex-wrap items-end justify-between gap-3">
|
|
<div>
|
|
<p class="font-mono text-[11px] uppercase tracking-[0.2em] text-accent-text">{{ __('audit.eyebrow') }}</p>
|
|
<h2 class="mt-0.5 font-display text-xl font-semibold text-ink sm:text-2xl">{{ __('audit.heading') }}</h2>
|
|
</div>
|
|
<x-status-pill status="online">{{ __('audit.event_count', ['count' => $events->count()]) }}</x-status-pill>
|
|
</div>
|
|
|
|
{{-- Aufbewahrung (Retention) --}}
|
|
<x-panel :title="__('audit.retention_title')" :subtitle="__('audit.retention_subtitle')">
|
|
<div class="space-y-3">
|
|
{{-- Aktuelle Richtlinie --}}
|
|
<div class="flex items-start gap-3 rounded-md border border-line bg-raised/40 p-3">
|
|
<x-icon name="shield" class="mt-0.5 h-4 w-4 shrink-0 text-accent-text" />
|
|
<div class="min-w-0">
|
|
<p class="text-sm text-ink">
|
|
{{ __('audit.retention_label') }}
|
|
<span class="font-mono text-accent-text">
|
|
@if ($retentionPolicy > 0)
|
|
{{ __('audit.retention_days', ['count' => $retentionPolicy]) }}
|
|
@else
|
|
{{ __('audit.retention_unlimited') }}
|
|
@endif
|
|
</span>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
{{-- Eingabe + Speichern --}}
|
|
<div>
|
|
<label for="retentionDays" class="mb-1 block text-sm text-ink-2">{{ __('audit.retention_label') }}</label>
|
|
<div class="flex flex-col gap-2 sm:flex-row">
|
|
<input wire:model="retentionDays" id="retentionDays" type="text" inputmode="numeric"
|
|
autocomplete="off" autocapitalize="off" spellcheck="false"
|
|
placeholder="{{ __('audit.retention_unlimited') }}"
|
|
class="h-9 w-full rounded-md border border-line bg-inset px-3 font-mono text-sm text-ink placeholder:text-ink-4 focus:border-accent/40 focus:outline-none sm:max-w-[12rem]" />
|
|
<x-btn variant="secondary" wire:click="saveRetention" wire:loading.attr="disabled" class="shrink-0">
|
|
<x-icon name="save" class="h-3.5 w-3.5" /> {{ __('audit.retention_save') }}
|
|
</x-btn>
|
|
</div>
|
|
@error('retentionDays')
|
|
<p class="mt-1.5 font-mono text-[11px] text-offline">{{ $message }}</p>
|
|
@enderror
|
|
<p class="mt-1.5 font-mono text-[11px] leading-relaxed text-ink-4">{{ __('audit.retention_hint') }}</p>
|
|
</div>
|
|
</div>
|
|
</x-panel>
|
|
|
|
{{-- Ereignisliste --}}
|
|
<x-panel :title="__('audit.panel_title')" :subtitle="__('audit.panel_subtitle')" :padded="false">
|
|
<x-slot:actions>
|
|
<label class="relative block">
|
|
<span class="sr-only">{{ __('audit.search_label') }}</span>
|
|
<span class="pointer-events-none absolute inset-y-0 left-2.5 flex items-center text-ink-4">
|
|
<x-icon name="search" class="h-3.5 w-3.5" />
|
|
</span>
|
|
<input
|
|
type="search"
|
|
data-page-search
|
|
wire:model.live.debounce.300ms="q"
|
|
placeholder="{{ __('audit.search_placeholder') }}"
|
|
class="min-h-11 w-44 rounded-md border border-line bg-inset py-1.5 pl-8 pr-3 font-mono text-xs text-ink placeholder:text-ink-4 focus:border-accent/40 focus:outline-none sm:w-64"
|
|
/>
|
|
</label>
|
|
</x-slot:actions>
|
|
|
|
<div class="divide-y divide-line">
|
|
@forelse ($events as $e)
|
|
<div class="flex items-start gap-3 px-4 py-3 sm:px-5">
|
|
<span @class([
|
|
'mt-0.5 grid h-7 w-7 shrink-0 place-items-center rounded-sm',
|
|
'bg-offline/10 text-offline' => $e->is_error,
|
|
'bg-raised text-ink-3' => ! $e->is_error,
|
|
])>
|
|
<x-icon :name="$e->is_error ? 'alert' : 'audit'" class="h-3.5 w-3.5" />
|
|
</span>
|
|
|
|
<div class="min-w-0 flex-1">
|
|
<p class="text-sm text-ink">
|
|
<span class="text-ink-2">{{ $e->actor }}</span>
|
|
<span class="text-ink-4">·</span>
|
|
<span @class(['font-medium', 'text-offline' => $e->is_error, 'text-ink' => ! $e->is_error])>{{ $e->action_label }}</span>
|
|
</p>
|
|
@if ($e->target)
|
|
<p class="truncate font-mono text-[11px] text-ink-3">{{ $e->target }}</p>
|
|
@endif
|
|
@if ($e->server)
|
|
<div class="mt-1.5">
|
|
<x-badge tone="accent">
|
|
<x-icon name="server" class="h-3 w-3" />
|
|
{{ $e->server->name }}
|
|
</x-badge>
|
|
</div>
|
|
@endif
|
|
</div>
|
|
|
|
<span class="shrink-0 whitespace-nowrap font-mono text-[11px] text-ink-4">
|
|
{{ $e->created_at->diffForHumans() }}
|
|
</span>
|
|
</div>
|
|
@empty
|
|
<div class="flex flex-col items-center gap-2 px-4 py-12 text-center sm:px-5">
|
|
<span class="grid h-10 w-10 place-items-center rounded-md bg-raised text-ink-4">
|
|
<x-icon name="audit" class="h-5 w-5" />
|
|
</span>
|
|
<p class="font-display text-sm font-semibold text-ink-2">{{ __('audit.empty_title') }}</p>
|
|
<p class="max-w-xs text-[11px] text-ink-4">
|
|
@if (trim($q) !== '')
|
|
{{ __('audit.empty_filtered', ['query' => $q]) }}
|
|
@else
|
|
{{ __('audit.empty_none') }}
|
|
@endif
|
|
</p>
|
|
</div>
|
|
@endforelse
|
|
</div>
|
|
</x-panel>
|
|
</div>
|