Feat: Quarantäne pro Zeile und pro Tab löschen (lokal via Cache)

main v1.1.432
boban 2026-04-27 06:16:03 +02:00
parent 0beb12569b
commit afce3d9687
2 changed files with 56 additions and 26 deletions

View File

@ -29,26 +29,46 @@ class QuarantineList extends Component
#[On('quarantine:updated')]
public function refresh(): void {}
public function clearHistory(): void
{
$password = env('RSPAMD_PASSWORD', '');
$opts = [
'http' => [
'method' => 'POST',
'timeout' => 5,
'ignore_errors' => true,
'content' => '',
'header' => "Content-Type: application/json\r\n" .
($password !== '' ? "Password: {$password}\r\n" : ''),
],
];
$ctx = stream_context_create($opts);
@file_get_contents('http://127.0.0.1:11334/historyreset', false, $ctx);
// ── Löschen (lokal via Cache, RSpamd hat keine per-entry API) ────────────
$this->dispatch('toast', type: 'done', badge: 'Quarantäne',
title: 'Verlauf geleert',
text: 'RSpamd-History wurde zurückgesetzt.',
duration: 3000);
private function hiddenKey(): string
{
return 'quarantine.hidden.' . session()->getId();
}
private function getHidden(): array
{
return \Cache::get($this->hiddenKey(), []);
}
private function saveHidden(array $ids): void
{
\Cache::put($this->hiddenKey(), array_values(array_unique($ids)), now()->addDays(7));
}
public function deleteEntry(string $id): void
{
$hidden = $this->getHidden();
$hidden[] = $id;
$this->saveHidden($hidden);
}
public function deleteCurrentTab(): void
{
$all = $this->fetchHistory();
$hidden = $this->getHidden();
$toHide = match($this->filter) {
'suspicious' => array_filter($all, fn($m) => $m['action'] !== 'no action'),
'all' => $all,
default => array_filter($all, fn($m) => $m['action'] === $this->filter),
};
foreach ($toHide as $m) {
$hidden[] = $m['id'];
}
$this->saveHidden($hidden);
$this->resetPage();
}
public function updatedFilter(): void { $this->resetPage(); }
@ -65,7 +85,11 @@ class QuarantineList extends Component
public function render()
{
$all = $this->fetchHistory();
$hidden = $this->getHidden();
$all = array_values(array_filter(
$this->fetchHistory(),
fn($m) => !in_array($m['id'], $hidden, true)
));
$suspicious = array_values(array_filter($all, fn($m) => $m['action'] !== 'no action'));

View File

@ -20,14 +20,14 @@
<option value="50">50 / Seite</option>
<option value="100">100 / Seite</option>
</select>
@if($counts['all'] > 0)
<button wire:click="clearHistory"
wire:confirm="Gesamten RSpamd-Verlauf löschen?"
class="mw-btn-del" title="Verlauf leeren">
@if($messages->total() > 0)
<button wire:click="deleteCurrentTab"
wire:confirm="Alle Einträge in diesem Tab ausblenden?"
class="mw-btn-del" title="Tab leeren">
<svg width="13" height="13" viewBox="0 0 14 14" fill="none">
<path d="M2 3.5h10M5.5 3.5V2.5h3v1M6 6v4M8 6v4M3 3.5l.7 8h6.6l.7-8" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
Verlauf leeren
Tab leeren
</button>
@endif
</div>
@ -104,10 +104,16 @@
@endif
</td>
<td class="mq-num">{{ $msg['time'] > 0 ? date('d.m H:i', $msg['time']) : '—' }}</td>
<td>
<td style="display:flex;gap:4px;align-items:center;justify-content:flex-end">
<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>
<button wire:click="deleteEntry('{{ $msg['id'] }}')" class="mq-btn-icon" title="Ausblenden"
style="color:var(--mw-t4);hover:color:var(--rose-400)">
<svg width="13" height="13" viewBox="0 0 14 14" fill="none">
<path d="M2 3.5h10M5.5 3.5V2.5h3v1M6 6v4M8 6v4M3 3.5l.7 8h6.6l.7-8" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</button>
</td>
</tr>
@endforeach