mailwolt/app/Livewire/Ui/Nx/Mail/MailboxList.php

170 lines
5.6 KiB
PHP

<?php
namespace App\Livewire\Ui\Nx\Mail;
use App\Models\Domain;
use App\Models\MailUser;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Livewire\Attributes\Layout;
use Livewire\Attributes\On;
use Livewire\Attributes\Title;
use Livewire\Component;
#[Layout('layouts.dvx')]
#[Title('Postfächer · Mailwolt')]
class MailboxList extends Component
{
public string $search = '';
public function mount(): void
{
Artisan::call('mail:update-stats');
}
#[On('mailbox:updated')]
#[On('mailbox:deleted')]
#[On('mailbox:created')]
public function refreshMailboxList(): void
{
$this->dispatch('$refresh');
}
public function openMailboxCreate(int $domainId): void
{
$this->dispatch('openModal', component: 'ui.mail.modal.mailbox-create-modal', arguments: [
'domainId' => $domainId,
]);
}
public function openMailboxEdit(int $mailUserId): void
{
$this->dispatch('openModal', component: 'ui.mail.modal.mailbox-edit-modal', arguments: [
$mailUserId,
]);
}
public function openMailboxDelete(int $mailUserId): void
{
$this->dispatch('openModal', component: 'ui.mail.modal.mailbox-delete-modal', arguments: [
$mailUserId,
]);
}
public function updateMailboxStats(): void
{
Artisan::call('mail:update-stats');
$this->dispatch('$refresh');
$this->dispatch('toast',
type: 'done',
badge: 'Mailbox',
title: 'Statistiken aktualisiert',
text: 'Alle Mailbox-Statistiken wurden neu berechnet.',
duration: 4000,
);
}
public function updateSingleStat(int $mailUserId): void
{
$u = MailUser::with('domain:id,domain')->find($mailUserId);
if (! $u) return;
$email = (string) ($u->getRawOriginal('email') ?? '');
if (! $email) return;
Artisan::call('mail:update-stats', ['--user' => $email]);
$this->dispatch('$refresh');
}
public function render()
{
$term = trim($this->search);
$hasTerm = $term !== '';
$needle = '%' . str_replace(['%', '_'], ['\%', '\_'], $term) . '%';
$domains = Domain::query()
->where('is_system', false)
->where('is_server', false)
->when($hasTerm, function ($q) use ($needle) {
$q->where(function ($w) use ($needle) {
$w->where('domain', 'like', $needle)
->orWhereHas('mailUsers', fn($u) => $u
->where('is_system', false)
->where('localpart', 'like', $needle)
);
});
})
->withCount(['mailUsers as mail_users_count' => fn($u) => $u
->where('is_system', false)
])
->with(['mailUsers' => function ($q) use ($hasTerm, $needle) {
$q->where('is_system', false);
if ($hasTerm) {
$q->where('localpart', 'like', $needle);
}
$q->orderBy('localpart');
}])
->orderBy('domain')
->get();
if ($hasTerm) {
$lower = Str::lower($term);
foreach ($domains as $d) {
if (Str::contains(Str::lower($d->domain), $lower)) {
$d->setRelation('mailUsers', $d->mailUsers()
->where('is_system', false)
->orderBy('localpart')
->get()
);
}
}
}
foreach ($domains as $d) {
$prepared = [];
$domainActive = (bool)($d->is_active ?? true);
foreach ($d->mailUsers as $u) {
$usedBytes = (int)($u->used_bytes ?? 0);
$messageCount = (int)($u->message_count ?? 0);
$quotaMiB = (int)($u->quota_mb ?? 0);
$usedMiB = round($usedBytes / 1048576, 2);
$usage = $quotaMiB > 0
? min(100, (int)round($usedBytes / ($quotaMiB * 1048576) * 100))
: 0;
$mailboxActive = (bool)($u->is_active ?? true);
$effective = $domainActive && $mailboxActive;
$reason = null;
if (!$effective) {
$reason = !$domainActive ? 'Domain inaktiv' : 'Postfach inaktiv';
}
$barClass = $usage > 85 ? 'mbx-bar-high' : ($usage > 60 ? 'mbx-bar-mid' : 'mbx-bar-low');
$prepared[] = [
'id' => $u->id,
'localpart' => (string)$u->localpart,
'quota_mb' => $quotaMiB,
'used_mb' => $usedMiB,
'usage_percent' => $usage,
'bar_class' => $barClass,
'message_count' => $messageCount,
'is_active' => $mailboxActive,
'is_effective_active' => $effective,
'inactive_reason' => $reason,
'last_login' => $u->last_login_at?->diffForHumans() ?? '—',
];
}
$d->prepared_mailboxes = $prepared;
}
return view('livewire.ui.nx.mail.mailbox-list', [
'domains' => $domains,
'totalMailboxes' => $domains->sum('mail_users_count'),
]);
}
}