131 lines
6.6 KiB
PHP
131 lines
6.6 KiB
PHP
<x-slot:breadcrumbParent>Mail</x-slot:breadcrumbParent>
|
||
<x-slot:breadcrumb>Quarantäne</x-slot:breadcrumb>
|
||
|
||
<div wire:poll.30s>
|
||
|
||
<div class="mq-page-header">
|
||
<div class="mq-page-title">
|
||
<svg width="16" height="16" viewBox="0 0 14 14" fill="none"><circle cx="7" cy="7" r="5.5" stroke="currentColor" stroke-width="1.2"/><path d="M7 4v4l2.5 2" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/></svg>
|
||
Quarantäne
|
||
<span class="mq-total-badge">{{ $counts['all'] }}</span>
|
||
<span class="mq-page-sub">Rspamd · {{ $total }} Einträge</span>
|
||
</div>
|
||
<div class="mq-page-actions">
|
||
<div class="mq-search-wrap">
|
||
<svg width="12" height="12" viewBox="0 0 12 12" fill="none"><circle cx="5" cy="5" r="3.8" stroke="currentColor" stroke-width="1.2"/><path d="M8 8l2.5 2.5" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/></svg>
|
||
<input type="text" wire:model.live.debounce.300ms="search" class="mq-search-input" placeholder="Von, An, Betreff …">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{{-- Filter tabs --}}
|
||
<div class="mq-tabs">
|
||
<button wire:click="$set('filter','suspicious')" class="mq-tab {{ $filter === 'suspicious' ? 'active' : '' }}">
|
||
<span class="mq-dot warn"></span>Verdächtig <span class="mq-tab-n">{{ $counts['suspicious'] }}</span>
|
||
</button>
|
||
<button wire:click="$set('filter','reject')" class="mq-tab {{ $filter === 'reject' ? 'active' : '' }}">
|
||
<span class="mq-dot off"></span>Reject <span class="mq-tab-n">{{ $counts['reject'] }}</span>
|
||
</button>
|
||
<button wire:click="$set('filter','add header')" class="mq-tab {{ $filter === 'add header' ? 'active' : '' }}">
|
||
<span class="mq-dot warn"></span>Tagged <span class="mq-tab-n">{{ $counts['add header'] }}</span>
|
||
</button>
|
||
<button wire:click="$set('filter','greylist')" class="mq-tab {{ $filter === 'greylist' ? 'active' : '' }}">
|
||
<span class="mq-dot na"></span>Greylist <span class="mq-tab-n">{{ $counts['greylist'] }}</span>
|
||
</button>
|
||
<button wire:click="$set('filter','all')" class="mq-tab {{ $filter === 'all' ? 'active' : '' }}">
|
||
Alle <span class="mq-tab-n">{{ $counts['all'] }}</span>
|
||
</button>
|
||
</div>
|
||
|
||
{{-- Table --}}
|
||
@if(count($messages) > 0)
|
||
<div class="mq-card">
|
||
<table class="mq-table">
|
||
<thead>
|
||
<tr>
|
||
<th>Von</th>
|
||
<th>An</th>
|
||
<th>Betreff</th>
|
||
<th>Score</th>
|
||
<th>Aktion</th>
|
||
<th>Zeitpunkt</th>
|
||
<th style="width:40px;"></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
@foreach($messages as $msg)
|
||
@php
|
||
$actionClass = match($msg['action']) {
|
||
'reject' => 'off',
|
||
'add header' => 'warn',
|
||
'greylist' => 'na',
|
||
default => 'ok',
|
||
};
|
||
$scoreRatio = $msg['required'] > 0
|
||
? min(100, round($msg['score'] / $msg['required'] * 100))
|
||
: 0;
|
||
@endphp
|
||
<tr wire:key="qua-{{ $msg['id'] }}" class="mq-row">
|
||
<td class="mq-addr">{{ $msg['from'] }}</td>
|
||
<td class="mq-addr">{{ Str::limit($msg['rcpt'], 35) }}</td>
|
||
<td class="mq-subject">{{ Str::limit($msg['subject'], 50) }}</td>
|
||
<td>
|
||
<div class="mq-score-wrap">
|
||
<span class="mq-score {{ $actionClass }}">{{ $msg['score'] }}</span>
|
||
<div class="mq-score-bar"><div class="mq-score-fill {{ $actionClass }}" style="width:{{ $scoreRatio }}%"></div></div>
|
||
</div>
|
||
</td>
|
||
<td>
|
||
@if($msg['action'] === 'reject')
|
||
<span class="mq-badge off">Reject</span>
|
||
@elseif($msg['action'] === 'add header')
|
||
<span class="mq-badge warn">Tagged</span>
|
||
@elseif($msg['action'] === 'greylist')
|
||
<span class="mq-badge na">Greylist</span>
|
||
@elseif($msg['action'] === 'no action')
|
||
<span class="mq-badge ok">Passiert</span>
|
||
@else
|
||
<span class="mq-badge na">{{ $msg['action'] }}</span>
|
||
@endif
|
||
</td>
|
||
<td class="mq-num">{{ $msg['time'] > 0 ? date('d.m H:i', $msg['time']) : '—' }}</td>
|
||
<td>
|
||
<button wire:click="openMessage('{{ $msg['id'] }}')" class="mq-btn-icon" title="Details">
|
||
<svg width="13" height="13" viewBox="0 0 14 14" fill="none"><circle cx="7" cy="7" r="5.5" stroke="currentColor" stroke-width="1.2"/><path d="M7 6.5v4" stroke="currentColor" stroke-width="1.3" stroke-linecap="round"/><circle cx="7" cy="4.5" r=".7" fill="currentColor"/></svg>
|
||
</button>
|
||
</td>
|
||
</tr>
|
||
@endforeach
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
@if($totalPages > 1)
|
||
<div class="mq-pagination">
|
||
<span class="mq-pag-info">{{ ($page - 1) * $perPage + 1 }}–{{ min($page * $perPage, $total) }} von {{ $total }}</span>
|
||
<div class="mq-pag-btns">
|
||
<button wire:click="$set('page', {{ max(1, $page - 1) }})" class="mq-pag-btn" @if($page <= 1) disabled @endif>
|
||
<svg width="12" height="12" viewBox="0 0 12 12" fill="none"><path d="M7.5 2L3.5 6l4 4" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||
</button>
|
||
@for($i = max(1, $page - 2); $i <= min($totalPages, $page + 2); $i++)
|
||
<button wire:click="$set('page', {{ $i }})" class="mq-pag-btn {{ $i === $page ? 'active' : '' }}">{{ $i }}</button>
|
||
@endfor
|
||
<button wire:click="$set('page', {{ min($totalPages, $page + 1) }})" class="mq-pag-btn" @if($page >= $totalPages) disabled @endif>
|
||
<svg width="12" height="12" viewBox="0 0 12 12" fill="none"><path d="M4.5 2L8.5 6l-4 4" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
@endif
|
||
@elseif($counts['all'] === 0)
|
||
<div class="mq-empty">
|
||
<svg width="36" height="36" viewBox="0 0 14 14" fill="none"><circle cx="7" cy="7" r="5.5" stroke="currentColor" stroke-width="1" opacity=".3"/><path d="M7 4v4l2.5 2" stroke="currentColor" stroke-width="1" stroke-linecap="round" opacity=".3"/></svg>
|
||
<p>Keine Rspamd-History verfügbar</p>
|
||
<small>Prüfe ob Rspamd unter 127.0.0.1:11334 erreichbar ist.</small>
|
||
</div>
|
||
@else
|
||
<div class="mq-empty">
|
||
<p>Keine Treffer für „{{ $search }}"</p>
|
||
</div>
|
||
@endif
|
||
|
||
</div>
|