parent
0cb7212d4b
commit
a6945edc64
|
|
@ -103,13 +103,6 @@ class DomainDnsModal extends ModalComponent
|
||||||
['type' => 'TXT', 'name' => $dkimHost, 'value' => $dkimTxt],
|
['type' => 'TXT', 'name' => $dkimHost, 'value' => $dkimTxt],
|
||||||
];
|
];
|
||||||
|
|
||||||
// $this->optional = [
|
|
||||||
// ['type' => 'SRV', 'name' => "_autodiscover._tcp.{$this->domainName}", 'value' => "0 1 443 {$mailServerFqdn}."],
|
|
||||||
// ['type' => 'SRV', 'name' => "_imaps._tcp.{$this->domainName}", 'value' => "0 1 993 {$mailServerFqdn}."],
|
|
||||||
// ['type' => 'SRV', 'name' => "_pop3s._tcp.{$this->domainName}", 'value' => "0 1 995 {$mailServerFqdn}."],
|
|
||||||
// ['type' => 'SRV', 'name' => "_submission._tcp.{$this->domainName}", 'value' => "0 1 587 {$mailServerFqdn}."],
|
|
||||||
// ];
|
|
||||||
|
|
||||||
$this->optional = [
|
$this->optional = [
|
||||||
// --- Service-Erkennung ---
|
// --- Service-Erkennung ---
|
||||||
[
|
[
|
||||||
|
|
@ -587,6 +580,8 @@ class DomainDnsModal extends ModalComponent
|
||||||
return view('livewire.ui.domain.modal.domain-dns-modal');
|
return view('livewire.ui.domain.modal.domain-dns-modal');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//namespace App\Livewire\Ui\Domain\Modal;
|
//namespace App\Livewire\Ui\Domain\Modal;
|
||||||
//
|
//
|
||||||
//use App\Models\Domain;
|
//use App\Models\Domain;
|
||||||
|
|
|
||||||
|
|
@ -2,16 +2,16 @@
|
||||||
|
|
||||||
namespace App\Livewire\Ui\Mail;
|
namespace App\Livewire\Ui\Mail;
|
||||||
|
|
||||||
use Livewire\Attributes\On;
|
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
use App\Models\Domain;
|
use App\Models\Domain;
|
||||||
use Illuminate\Support\Facades\Cache;
|
use Illuminate\Support\Facades\Cache;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
class DnsHealthCard extends Component
|
class DnsHealthCard extends Component
|
||||||
{
|
{
|
||||||
public array $rows = []; // [{id,name,ok,missing:[...]}]
|
public array $rows = []; // [{id,name,ok,missing:[...]}]
|
||||||
public string $mtaHost = ''; // z.B. mx.nexlab.at
|
public string $mtaHost = '';
|
||||||
public bool $tlsa = false; // hostweit
|
public bool $tlsa = false;
|
||||||
|
|
||||||
public function mount(): void
|
public function mount(): void
|
||||||
{
|
{
|
||||||
|
|
@ -35,51 +35,66 @@ class DnsHealthCard extends Component
|
||||||
|
|
||||||
protected function load(bool $force = false): void
|
protected function load(bool $force = false): void
|
||||||
{
|
{
|
||||||
[$this->mtaHost, $this->tlsa, $this->rows] = Cache::remember('dash.dnshealth.v1', $force ? 1 : 600, function () {
|
[$this->mtaHost, $this->tlsa, $this->rows] = Cache::remember('dash.dnshealth.v2', $force ? 1 : 600, function () {
|
||||||
|
|
||||||
$base = trim((string)env('BASE_DOMAIN', ''));
|
$base = trim((string) env('BASE_DOMAIN', ''));
|
||||||
$mtaSub = trim((string)env('MTA_SUB', 'mx'));
|
$mtaSub = trim((string) env('MTA_SUB', 'mx'));
|
||||||
$mtaHost = $base !== '' ? "{$mtaSub}.{$base}" : $mtaSub;
|
$mtaHost = $base !== '' ? "{$mtaSub}.{$base}" : $mtaSub; // z.B. mx.nexlab.at
|
||||||
|
|
||||||
$rows = [];
|
// ▼ gewünschter Filter:
|
||||||
$domains = Domain::query()
|
$domains = Domain::query()
|
||||||
->where('is_system', false)
|
|
||||||
->where('is_active', true)
|
->where('is_active', true)
|
||||||
|
->where(function ($q) {
|
||||||
|
$q->where('is_system', false)
|
||||||
|
->orWhere(function ($q2) {
|
||||||
|
$q2->where('is_system', true)->where('is_server', false);
|
||||||
|
});
|
||||||
|
})
|
||||||
->orderBy('domain')
|
->orderBy('domain')
|
||||||
->get(['id', 'domain']);
|
->get(['id', 'domain']);
|
||||||
|
|
||||||
|
$rows = [];
|
||||||
foreach ($domains as $d) {
|
foreach ($domains as $d) {
|
||||||
$dom = $d->domain;
|
$dom = $d->domain;
|
||||||
|
|
||||||
|
// DKIM-Selector ermitteln: .env > DB > Fallback null
|
||||||
|
$selector = trim((string) env('DKIM_SELECTOR', ''));
|
||||||
|
if ($selector === '') {
|
||||||
|
$selector = (string) DB::table('dkim_keys')
|
||||||
|
->where('domain_id', $d->id)
|
||||||
|
->where('is_active', 1)
|
||||||
|
->orderByDesc('id')
|
||||||
|
->value('selector') ?? '';
|
||||||
|
}
|
||||||
|
|
||||||
$missing = [];
|
$missing = [];
|
||||||
|
|
||||||
// Pflicht-Checks
|
|
||||||
if (!$this->mxPointsTo($dom, [$mtaHost])) $missing[] = 'MX';
|
if (!$this->mxPointsTo($dom, [$mtaHost])) $missing[] = 'MX';
|
||||||
if (!$this->hasSpf($dom)) $missing[] = 'SPF';
|
if (!$this->hasSpf($dom)) $missing[] = 'SPF';
|
||||||
if (!$this->hasDkim($dom)) $missing[] = 'DKIM';
|
if (!$this->hasDkim($dom, $selector)) $missing[] = 'DKIM';
|
||||||
if (!$this->hasTxt("_dmarc.$dom")) $missing[] = 'DMARC';
|
if (!$this->hasTxt("_dmarc.$dom")) $missing[] = 'DMARC';
|
||||||
|
|
||||||
$rows[] = [
|
$rows[] = [
|
||||||
'id' => (int)$d->id,
|
'id' => (int) $d->id,
|
||||||
'name' => $dom,
|
'name' => $dom,
|
||||||
'ok' => empty($missing),
|
'ok' => empty($missing),
|
||||||
'missing' => $missing,
|
'missing' => $missing,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
// TLSA (hostweit, nur Info)
|
// Hostweites TLSA (nur Hinweis)
|
||||||
$tlsa = $this->hasTlsa("_25._tcp.$mtaHost") || $this->hasTlsa("_465._tcp.$mtaHost") || $this->hasTlsa("_587._tcp.$mtaHost");
|
$tlsa = $this->hasTlsa("_25._tcp.$mtaHost") || $this->hasTlsa("_465._tcp.$mtaHost") || $this->hasTlsa("_587._tcp.$mtaHost");
|
||||||
|
|
||||||
return [$mtaHost, $tlsa, $rows];
|
return [$mtaHost, $tlsa, $rows];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── DNS Helpers (mit Timeout, damit UI nicht hängt) ───────────────── */
|
/* ── DNS Helpers ───────────────────────────────────────────────────── */
|
||||||
|
|
||||||
protected function digShort(string $type, string $name): string
|
protected function digShort(string $type, string $name): string
|
||||||
{
|
{
|
||||||
$cmd = "timeout 2 dig +short " . escapeshellarg($name) . " " . escapeshellarg(strtoupper($type)) . " 2>/dev/null";
|
$cmd = "timeout 2 dig +short " . escapeshellarg($name) . ' ' . escapeshellarg(strtoupper($type)) . " 2>/dev/null";
|
||||||
return (string)@shell_exec($cmd) ?: '';
|
return (string) @shell_exec($cmd) ?: '';
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function hasTxt(string $name): bool
|
protected function hasTxt(string $name): bool
|
||||||
|
|
@ -101,11 +116,13 @@ class DnsHealthCard extends Component
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// DKIM: wenn spezifischer Selector vorhanden → prüfe den, sonst akzeptiere _domainkey-Policy als “vorhanden”
|
// ▼ DKIM: bevorzugt konkreten Selector prüfen; wenn leer, versuche Policy (_domainkey)
|
||||||
protected function hasDkim(string $domain): bool
|
protected function hasDkim(string $domain, string $selector = ''): bool
|
||||||
{
|
{
|
||||||
$sel = trim((string)env('DKIM_SELECTOR', ''));
|
if ($selector !== '') {
|
||||||
if ($sel !== '' && $this->hasTxt("{$sel}._domainkey.$domain")) return true;
|
return $this->hasTxt("{$selector}._domainkey.$domain");
|
||||||
|
}
|
||||||
|
// Manche Betreiber veröffentlichen eine Policy auf _domainkey.<dom>
|
||||||
return $this->hasTxt("_domainkey.$domain");
|
return $this->hasTxt("_domainkey.$domain");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -116,21 +133,153 @@ class DnsHealthCard extends Component
|
||||||
|
|
||||||
$targets = [];
|
$targets = [];
|
||||||
foreach (preg_split('/\R+/', trim($out)) as $line) {
|
foreach (preg_split('/\R+/', trim($out)) as $line) {
|
||||||
// Format: "10 mx.example.com."
|
|
||||||
if (preg_match('~\s+([A-Za-z0-9\.\-]+)\.?$~', trim($line), $m)) {
|
if (preg_match('~\s+([A-Za-z0-9\.\-]+)\.?$~', trim($line), $m)) {
|
||||||
$targets[] = strtolower($m[1]);
|
$targets[] = strtolower($m[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!$targets) return false;
|
if (!$targets) return false;
|
||||||
|
|
||||||
$allowed = array_map('strtolower', $allowedHosts);
|
$allowed = array_map(fn ($h) => strtolower(rtrim($h, '.')), $allowedHosts);
|
||||||
foreach ($targets as $t) {
|
foreach ($targets as $t) {
|
||||||
|
$t = rtrim($t, '.');
|
||||||
if (in_array($t, $allowed, true)) return true;
|
if (in_array($t, $allowed, true)) return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//namespace App\Livewire\Ui\Mail;
|
||||||
|
//
|
||||||
|
//use Livewire\Attributes\On;
|
||||||
|
//use Livewire\Component;
|
||||||
|
//use App\Models\Domain;
|
||||||
|
//use Illuminate\Support\Facades\Cache;
|
||||||
|
//
|
||||||
|
//class DnsHealthCard extends Component
|
||||||
|
//{
|
||||||
|
// public array $rows = []; // [{id,name,ok,missing:[...]}]
|
||||||
|
// public string $mtaHost = ''; // z.B. mx.nexlab.at
|
||||||
|
// public bool $tlsa = false; // hostweit
|
||||||
|
//
|
||||||
|
// public function mount(): void
|
||||||
|
// {
|
||||||
|
// $this->load();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// public function render()
|
||||||
|
// {
|
||||||
|
// return view('livewire.ui.mail.dns-health-card');
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// public function refresh(): void
|
||||||
|
// {
|
||||||
|
// $this->load(true);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// public function openDnsModal(int $domainId): void
|
||||||
|
// {
|
||||||
|
// $this->dispatch('openModal', component: 'ui.domain.modal.domain-dns-modal', arguments: ['domainId' => $domainId]);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// protected function load(bool $force = false): void
|
||||||
|
// {
|
||||||
|
// [$this->mtaHost, $this->tlsa, $this->rows] = Cache::remember('dash.dnshealth.v1', $force ? 1 : 600, function () {
|
||||||
|
//
|
||||||
|
// $base = trim((string)env('BASE_DOMAIN', ''));
|
||||||
|
// $mtaSub = trim((string)env('MTA_SUB', 'mx'));
|
||||||
|
// $mtaHost = $base !== '' ? "{$mtaSub}.{$base}" : $mtaSub;
|
||||||
|
//
|
||||||
|
// $rows = [];
|
||||||
|
// $domains = Domain::query()
|
||||||
|
// ->where('is_system', false)
|
||||||
|
// ->where('is_active', true)
|
||||||
|
// ->orderBy('domain')
|
||||||
|
// ->get(['id', 'domain']);
|
||||||
|
//
|
||||||
|
// foreach ($domains as $d) {
|
||||||
|
// $dom = $d->domain;
|
||||||
|
//
|
||||||
|
// $missing = [];
|
||||||
|
//
|
||||||
|
// // Pflicht-Checks
|
||||||
|
// if (!$this->mxPointsTo($dom, [$mtaHost])) $missing[] = 'MX';
|
||||||
|
// if (!$this->hasSpf($dom)) $missing[] = 'SPF';
|
||||||
|
// if (!$this->hasDkim($dom)) $missing[] = 'DKIM';
|
||||||
|
// if (!$this->hasTxt("_dmarc.$dom")) $missing[] = 'DMARC';
|
||||||
|
//
|
||||||
|
// $rows[] = [
|
||||||
|
// 'id' => (int)$d->id,
|
||||||
|
// 'name' => $dom,
|
||||||
|
// 'ok' => empty($missing),
|
||||||
|
// 'missing' => $missing,
|
||||||
|
// ];
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // TLSA (hostweit, nur Info)
|
||||||
|
// $tlsa = $this->hasTlsa("_25._tcp.$mtaHost") || $this->hasTlsa("_465._tcp.$mtaHost") || $this->hasTlsa("_587._tcp.$mtaHost");
|
||||||
|
//
|
||||||
|
// return [$mtaHost, $tlsa, $rows];
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /* ── DNS Helpers (mit Timeout, damit UI nicht hängt) ───────────────── */
|
||||||
|
//
|
||||||
|
// protected function digShort(string $type, string $name): string
|
||||||
|
// {
|
||||||
|
// $cmd = "timeout 2 dig +short " . escapeshellarg($name) . " " . escapeshellarg(strtoupper($type)) . " 2>/dev/null";
|
||||||
|
// return (string)@shell_exec($cmd) ?: '';
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// protected function hasTxt(string $name): bool
|
||||||
|
// {
|
||||||
|
// return trim($this->digShort('TXT', $name)) !== '';
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// protected function hasTlsa(string $name): bool
|
||||||
|
// {
|
||||||
|
// return trim($this->digShort('TLSA', $name)) !== '';
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// protected function hasSpf(string $domain): bool
|
||||||
|
// {
|
||||||
|
// $out = $this->digShort('TXT', $domain);
|
||||||
|
// foreach (preg_split('/\R+/', trim($out)) as $line) {
|
||||||
|
// if (stripos($line, 'v=spf1') !== false) return true;
|
||||||
|
// }
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // DKIM: wenn spezifischer Selector vorhanden → prüfe den, sonst akzeptiere _domainkey-Policy als “vorhanden”
|
||||||
|
// protected function hasDkim(string $domain): bool
|
||||||
|
// {
|
||||||
|
// $sel = trim((string)env('DKIM_SELECTOR', ''));
|
||||||
|
// if ($sel !== '' && $this->hasTxt("{$sel}._domainkey.$domain")) return true;
|
||||||
|
// return $this->hasTxt("_domainkey.$domain");
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// protected function mxPointsTo(string $domain, array $allowedHosts): bool
|
||||||
|
// {
|
||||||
|
// $out = $this->digShort('MX', $domain);
|
||||||
|
// if ($out === '') return false;
|
||||||
|
//
|
||||||
|
// $targets = [];
|
||||||
|
// foreach (preg_split('/\R+/', trim($out)) as $line) {
|
||||||
|
// // Format: "10 mx.example.com."
|
||||||
|
// if (preg_match('~\s+([A-Za-z0-9\.\-]+)\.?$~', trim($line), $m)) {
|
||||||
|
// $targets[] = strtolower($m[1]);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// if (!$targets) return false;
|
||||||
|
//
|
||||||
|
// $allowed = array_map('strtolower', $allowedHosts);
|
||||||
|
// foreach ($targets as $t) {
|
||||||
|
// if (in_array($t, $allowed, true)) return true;
|
||||||
|
// }
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
//namespace App\Livewire\Ui\Mail;
|
//namespace App\Livewire\Ui\Mail;
|
||||||
//
|
//
|
||||||
//use Livewire\Component;
|
//use Livewire\Component;
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,17 @@
|
||||||
<div wire:poll.60s="refresh" class="glass-card p-5 rounded-2xl border border-white/10 bg-white/5">
|
<div class="glass-card p-5 rounded-2xl border border-white/10 bg-white/5">
|
||||||
<div class="flex items-center justify-between mb-4">
|
<div class="flex items-center justify-between mb-4">
|
||||||
<div class="inline-flex items-center gap-2 bg-white/5 border border-white/10 px-2.5 py-1 rounded-full">
|
<div class="inline-flex items-center gap-2 bg-white/5 border border-white/10 px-2.5 py-1 rounded-full">
|
||||||
<i class="ph ph-globe-stand text-white/70 text-[13px]"></i>
|
<i class="ph ph-globe-stand text-white/70 text-[13px]"></i>
|
||||||
<span class="text-[11px] uppercase text-white/70 tracking-wide">Mail-DNS Health</span>
|
<span class="text-[11px] uppercase text-white/70 tracking-wide">Mail-DNS Health</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-xs text-white/60">
|
<div class="flex items-center gap-3">
|
||||||
<span class="opacity-70">TLSA:</span>
|
<button wire:click="refresh"
|
||||||
<span class="{{ $tlsa ? 'text-emerald-300' : 'text-rose-300' }}">
|
class="inline-flex items-center gap-1.5 rounded-full text-[12px] px-3 py-1.5
|
||||||
{{ $tlsa ? 'ok' : 'fehlend' }}
|
text-white/80 bg-white/10 border border-white/15
|
||||||
</span>
|
hover:bg-white/15 hover:text-white transition">
|
||||||
<span class="opacity-50">({{ $mtaHost }})</span>
|
<i class="ph ph-arrows-clockwise text-[13px]"></i>
|
||||||
|
Neu prüfen
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -17,7 +19,7 @@
|
||||||
@forelse($rows as $r)
|
@forelse($rows as $r)
|
||||||
<button type="button"
|
<button type="button"
|
||||||
wire:click="openDnsModal({{ $r['id'] }})"
|
wire:click="openDnsModal({{ $r['id'] }})"
|
||||||
class="w-full text-left py-3 flex items-center justify-between hover:bg-white/5/20 rounded-lg px-2 hover:bg-white/5">
|
class="w-full text-left py-3 flex items-center justify-between rounded-lg px-2 hover:bg-white/5">
|
||||||
<div class="text-white/85">{{ $r['name'] }}</div>
|
<div class="text-white/85">{{ $r['name'] }}</div>
|
||||||
|
|
||||||
@if($r['ok'])
|
@if($r['ok'])
|
||||||
|
|
@ -25,14 +27,9 @@
|
||||||
OK
|
OK
|
||||||
</span>
|
</span>
|
||||||
@else
|
@else
|
||||||
<div class="flex items-center gap-2">
|
<span class="px-2 py-0.5 rounded-full border text-amber-200 border-amber-400/30 bg-amber-500/10 text-xs">
|
||||||
<span class="px-2 py-0.5 rounded-full border text-amber-200 border-amber-400/30 bg-amber-500/10 text-xs">
|
Fertig konfigurieren
|
||||||
Fertig konfigurieren
|
</span>
|
||||||
</span>
|
|
||||||
{{-- <span class="text-[11px] text-white/45">--}}
|
|
||||||
{{-- fehlt: {{ implode(', ', $r['missing']) }}--}}
|
|
||||||
{{-- </span>--}}
|
|
||||||
</div>
|
|
||||||
@endif
|
@endif
|
||||||
</button>
|
</button>
|
||||||
@empty
|
@empty
|
||||||
|
|
@ -41,6 +38,49 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{{--<div wire:poll.60s="refresh" class="glass-card p-5 rounded-2xl border border-white/10 bg-white/5">--}}
|
||||||
|
{{-- <div class="flex items-center justify-between mb-4">--}}
|
||||||
|
{{-- <div class="inline-flex items-center gap-2 bg-white/5 border border-white/10 px-2.5 py-1 rounded-full">--}}
|
||||||
|
{{-- <i class="ph ph-globe-stand text-white/70 text-[13px]"></i>--}}
|
||||||
|
{{-- <span class="text-[11px] uppercase text-white/70 tracking-wide">Mail-DNS Health</span>--}}
|
||||||
|
{{-- </div>--}}
|
||||||
|
{{-- <div class="text-xs text-white/60">--}}
|
||||||
|
{{-- <span class="opacity-70">TLSA:</span>--}}
|
||||||
|
{{-- <span class="{{ $tlsa ? 'text-emerald-300' : 'text-rose-300' }}">--}}
|
||||||
|
{{-- {{ $tlsa ? 'ok' : 'fehlend' }}--}}
|
||||||
|
{{-- </span>--}}
|
||||||
|
{{-- <span class="opacity-50">({{ $mtaHost }})</span>--}}
|
||||||
|
{{-- </div>--}}
|
||||||
|
{{-- </div>--}}
|
||||||
|
|
||||||
|
{{-- <div class="divide-y divide-white/5">--}}
|
||||||
|
{{-- @forelse($rows as $r)--}}
|
||||||
|
{{-- <button type="button"--}}
|
||||||
|
{{-- wire:click="openDnsModal({{ $r['id'] }})"--}}
|
||||||
|
{{-- class="w-full text-left py-3 flex items-center justify-between hover:bg-white/5/20 rounded-lg px-2 hover:bg-white/5">--}}
|
||||||
|
{{-- <div class="text-white/85">{{ $r['name'] }}</div>--}}
|
||||||
|
|
||||||
|
{{-- @if($r['ok'])--}}
|
||||||
|
{{-- <span class="px-2 py-0.5 rounded-full border text-emerald-300 border-emerald-400/30 bg-emerald-500/10 text-xs">--}}
|
||||||
|
{{-- OK--}}
|
||||||
|
{{-- </span>--}}
|
||||||
|
{{-- @else--}}
|
||||||
|
{{-- <div class="flex items-center gap-2">--}}
|
||||||
|
{{-- <span class="px-2 py-0.5 rounded-full border text-amber-200 border-amber-400/30 bg-amber-500/10 text-xs">--}}
|
||||||
|
{{-- Fertig konfigurieren--}}
|
||||||
|
{{-- </span>--}}
|
||||||
|
{{-- <span class="text-[11px] text-white/45">--}}
|
||||||
|
{{-- fehlt: {{ implode(', ', $r['missing']) }}--}}
|
||||||
|
{{-- </span>--}}
|
||||||
|
{{-- </div>--}}
|
||||||
|
{{-- @endif--}}
|
||||||
|
{{-- </button>--}}
|
||||||
|
{{-- @empty--}}
|
||||||
|
{{-- <div class="py-4 text-sm text-white/60">Keine Domains.</div>--}}
|
||||||
|
{{-- @endforelse--}}
|
||||||
|
{{-- </div>--}}
|
||||||
|
{{--</div>--}}
|
||||||
|
|
||||||
{{--<div wire:poll.60s="refresh" class="glass-card p-5 rounded-2xl border border-white/10 bg-white/5">--}}
|
{{--<div wire:poll.60s="refresh" class="glass-card p-5 rounded-2xl border border-white/10 bg-white/5">--}}
|
||||||
{{-- <div class="flex items-center justify-between mb-4">--}}
|
{{-- <div class="flex items-center justify-between mb-4">--}}
|
||||||
{{-- <div class="inline-flex items-center gap-2 bg-white/5 border border-white/10 px-2.5 py-1 rounded-full">--}}
|
{{-- <div class="inline-flex items-center gap-2 bg-white/5 border border-white/10 px-2.5 py-1 rounded-full">--}}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue