mailwolt/resources/views/ui/dashboard/redesign.blade.php

276 lines
14 KiB
PHP

@extends('layouts.dvx')
@section('title', 'Dashboard · Mailwolt')
@section('breadcrumb-parent', 'Dashboard')
@section('breadcrumb', 'Übersicht')
@section('content')
{{-- Hero Banner --}}
<div class="mw-hero">
<div class="mw-hero-icon">
<svg width="18" height="18" viewBox="0 0 20 20" fill="none">
<rect x="1" y="5.5" width="18" height="4.5" rx="2" stroke="#6a7a96" stroke-width="1.3"/>
<rect x="1" y="12" width="18" height="4.5" rx="2" stroke="#6a7a96" stroke-width="1.3"/>
<circle cx="15.5" cy="7.75" r="1.1" fill="#22c55e"/>
<circle cx="15.5" cy="14.25" r="1.1" fill="#22c55e"/>
<circle cx="13" cy="7.75" r="1.1" fill="#22c55e"/>
<circle cx="13" cy="14.25" r="1.1" fill="#22c55e"/>
</svg>
</div>
<div>
<div class="mw-hero-title">Mail Server</div>
<div class="mw-hero-tags">
<span class="mw-hero-tag">Postfix</span>
<span class="mw-hero-tag">Dovecot</span>
<span class="mw-hero-tag">Rspamd</span>
<span class="mw-hero-tag">OpenDKIM</span>
<span class="mw-hero-tag">ClamAV</span>
</div>
</div>
<div class="mw-hero-divider"></div>
<div class="mw-hero-stats">
<div class="mw-hstat">
<div class="mw-hstat-n ok">{{ $domainCount ?? 0 }}</div>
<div class="mw-hstat-l">Domains</div>
</div>
<div class="mw-hstat">
<div class="mw-hstat-n">{{ $mailboxCount ?? 0 }}</div>
<div class="mw-hstat-l">Postfächer</div>
</div>
<div class="mw-hstat">
<div class="mw-hstat-n ok">{{ $servicesActive ?? 0 }}/{{ $servicesTotal ?? 0 }}</div>
<div class="mw-hstat-l">Dienste</div>
</div>
<div class="mw-hstat">
<div class="mw-hstat-n">{{ $alertCount ?? 0 }}</div>
<div class="mw-hstat-l">Warnungen</div>
</div>
</div>
<div class="mw-hero-host">{{ $mailHostname ?? gethostname() }}</div>
</div>
{{-- System-Ressourcen --}}
<div class="mw-section">
<span class="mw-section-title">System-Ressourcen</span>
<div class="mw-section-line"></div>
</div>
<div class="mw-metric-grid">
@php $cpuClass = ($cpu ?? 0) > 80 ? 'mw-bar-high' : (($cpu ?? 0) > 50 ? 'mw-bar-mid' : 'mw-bar-low'); @endphp
<div class="mw-metric-card">
<div class="mw-mc-top">
<span class="mw-mc-label">CPU</span>
<div class="mw-mc-icon"><svg width="12" height="12" viewBox="0 0 13 13" fill="none"><rect x=".5" y=".5" width="12" height="12" rx="2" stroke="#606880" stroke-width="1.1"/><rect x="3" y="3" width="7" height="7" rx="1" stroke="#606880" stroke-width="1"/></svg></div>
</div>
<div class="mw-mc-value">{{ $cpu ?? 0 }}<span style="font-size:15px;font-weight:600;">%</span></div>
<div class="mw-mc-sub">{{ $cpuCores ?? '—' }} Cores · {{ $cpuMhz ?? '—' }} GHz</div>
<div class="mw-bar {{ $cpuClass }}"><div class="mw-bar-fill" style="width:{{ $cpu ?? 0 }}%"></div></div>
</div>
@php $ramClass = ($ramPercent ?? 0) > 80 ? 'mw-bar-high' : (($ramPercent ?? 0) > 50 ? 'mw-bar-mid' : 'mw-bar-low'); @endphp
<div class="mw-metric-card">
<div class="mw-mc-top">
<span class="mw-mc-label">RAM</span>
<div class="mw-mc-icon"><svg width="12" height="12" viewBox="0 0 13 13" fill="none"><rect x=".5" y="3" width="12" height="7" rx="1.5" stroke="#606880" stroke-width="1.1"/><path d="M3.5 3V2M6.5 3V2M9.5 3V2" stroke="#606880" stroke-width="1" stroke-linecap="round"/></svg></div>
</div>
<div class="mw-mc-value">{{ $ramPercent ?? 0 }}<span style="font-size:15px;font-weight:600;">%</span></div>
<div class="mw-mc-sub">{{ $ramUsed ?? '—' }} GB / {{ $ramTotal ?? '—' }} GB</div>
<div class="mw-bar {{ $ramClass }}"><div class="mw-bar-fill" style="width:{{ $ramPercent ?? 0 }}%"></div></div>
</div>
@php
$loadVal = floatval($load1 ?? 0);
$loadMax = max(1, $cpuCores ?? 4);
$loadPct = min(100, round($loadVal / $loadMax * 100));
$loadClass = $loadPct > 80 ? 'mw-bar-high' : ($loadPct > 50 ? 'mw-bar-mid' : 'mw-bar-low');
@endphp
<div class="mw-metric-card">
<div class="mw-mc-top">
<span class="mw-mc-label">Load</span>
<div class="mw-mc-icon"><svg width="12" height="12" viewBox="0 0 13 13" fill="none"><path d="M1 10L4 6.5l3 2 3-5 2 1.5" stroke="#606880" stroke-width="1.1" stroke-linecap="round" stroke-linejoin="round"/></svg></div>
</div>
<div class="mw-mc-value" style="font-size:22px;letter-spacing:-.5px;">{{ $load1 ?? '0.00' }}</div>
<div class="mw-mc-sub">{{ $load5 ?? '—' }} · {{ $load15 ?? '—' }} (1/5/15m)</div>
<div class="mw-bar {{ $loadClass }}"><div class="mw-bar-fill" style="width:{{ $loadPct }}%"></div></div>
</div>
<div class="mw-metric-card">
<div class="mw-mc-top">
<span class="mw-mc-label">Uptime</span>
<div class="mw-mc-icon"><svg width="12" height="12" viewBox="0 0 13 13" fill="none"><circle cx="6.5" cy="6.5" r="5" stroke="#606880" stroke-width="1.1"/><path d="M6.5 3.5V6.5l2 1.5" stroke="#606880" stroke-width="1.1" stroke-linecap="round"/></svg></div>
</div>
<div class="mw-mc-value" style="font-size:20px;letter-spacing:-.5px;">{{ $uptimeDays ?? 0 }}d {{ $uptimeHours ?? 0 }}h</div>
<div class="mw-mc-sub">Stabil · kein Neustart</div>
<div class="mw-bar mw-bar-uptime"><div class="mw-bar-fill" style="width:100%"></div></div>
</div>
</div>
{{-- Dienste & Schutz --}}
<div class="mw-section">
<span class="mw-section-title">Dienste &amp; Schutz</span>
<div class="mw-section-line"></div>
</div>
<div class="mw-status-grid">
<div class="mw-status-card">
<div class="mw-sc-head">
<div class="mw-sc-icon" style="background:var(--mw-grbg);border:1px solid var(--mw-grbd);">
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M7 1.5L12.5 4v4.5c0 2.8-2.3 4.5-5.5 5C3.8 13 1.5 11.3 1.5 8.5V4L7 1.5Z" stroke="#22c55e" stroke-width="1.2" stroke-linejoin="round"/><path d="M4.5 7l2 2 3-3" stroke="#22c55e" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/></svg>
</div>
<div>
<div class="mw-sc-title">WoltGuard</div>
<div class="mw-sc-sub">System-Wächter</div>
</div>
<span class="mw-sc-badge mw-badge-ok">alle Dienste OK</span>
</div>
<div class="mw-sc-body"><b>{{ $servicesActive ?? 0 }}/{{ $servicesTotal ?? 0 }}</b> Dienste aktiv</div>
</div>
<div class="mw-status-card">
<div class="mw-sc-head">
<div class="mw-sc-icon" style="background:var(--mw-bg4);border:1px solid var(--mw-b2);">
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M12.5 7A5.5 5.5 0 1 1 7 1.5" stroke="#606880" stroke-width="1.2" stroke-linecap="round"/><path d="M7 .5l2.5 1.5L7 3.5" stroke="#606880" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/></svg>
</div>
<div>
<div class="mw-sc-title">Updates</div>
<div class="mw-sc-sub">{{ config('app.version', 'vdev') }}</div>
</div>
<span class="mw-sc-badge mw-badge-mute">aktuell</span>
</div>
<div class="mw-sc-body">System ist auf dem neuesten Stand.</div>
<div class="mw-sc-progress"><div class="mw-sc-progress-fill" style="width:100%"></div></div>
</div>
<div class="mw-status-card">
<div class="mw-sc-head">
<div class="mw-sc-icon" style="background:var(--mw-bg4);border:1px solid var(--mw-b2);">
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M2.5 9H2a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h10a1 1 0 0 1 1 1v4a1 1 0 0 1-1 1h-.5" stroke="#606880" stroke-width="1.2" stroke-linecap="round"/><rect x="3" y="8.5" width="8" height="5" rx="1.5" stroke="#606880" stroke-width="1.2"/></svg>
</div>
<div>
<div class="mw-sc-title">Backup</div>
<div class="mw-sc-sub">Letztes: {{ $lastBackup ?? '—' }}</div>
</div>
<span class="mw-sc-badge mw-badge-warn">unbekannt</span>
</div>
<div class="mw-sc-body">Größe: {{ $backupSize ?? '—' }} · Dauer: {{ $backupDuration ?? '—' }}</div>
<button class="mw-sc-btn" onclick="Livewire.dispatch('backup.run')">Jetzt sichern</button>
</div>
<div class="mw-status-card">
<div class="mw-sc-head">
<div class="mw-sc-icon" style="background:var(--mw-bg4);border:1px solid var(--mw-b2);">
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M7 2L13 12H1L7 2Z" stroke="#606880" stroke-width="1.2" stroke-linejoin="round"/><path d="M7 6.5v2.5" stroke="#606880" stroke-width="1.4" stroke-linecap="round"/><circle cx="7" cy="10.5" r=".6" fill="#606880"/></svg>
</div>
<div>
<div class="mw-sc-title">Alerts</div>
<div class="mw-sc-sub">System-Warnungen</div>
</div>
<span class="mw-sc-badge mw-badge-mute">{{ $alertCount ?? 0 }} offen</span>
</div>
<div class="mw-sc-body" style="font-style:italic;color:var(--mw-t4);">
{{ ($alertCount ?? 0) === 0 ? 'Keine Warnungen.' : ($alertCount . ' aktive Warnungen.') }}
</div>
</div>
</div>
{{-- Infrastruktur --}}
<div class="mw-section">
<span class="mw-section-title">Infrastruktur</span>
<div class="mw-section-line"></div>
</div>
<div class="mw-bottom-grid">
<div class="mw-card">
<div class="mw-card-title">Dienste &amp; Ports</div>
<div class="mw-svc-grid">
<div>
@foreach($services ?? [] as $svc)
@if($loop->index < 4)
<div class="mw-svc-row">
<div class="mw-svc-dot {{ $svc['online'] ? 'ok' : 'off' }}"></div>
<div class="mw-svc-name">{{ $svc['name'] }}<span class="mw-svc-type"> {{ $svc['type'] }}</span></div>
<span class="mw-svc-status" style="{{ $svc['online'] ? '' : 'color:var(--mw-rd);opacity:1;' }}">{{ $svc['online'] ? 'Online' : 'Offline' }}</span>
</div>
@endif
@endforeach
</div>
<div>
@foreach($services ?? [] as $svc)
@if($loop->index >= 4)
<div class="mw-svc-row">
<div class="mw-svc-dot {{ $svc['online'] ? 'ok' : 'off' }}"></div>
<div class="mw-svc-name">{{ $svc['name'] }}<span class="mw-svc-type"> {{ $svc['type'] }}</span></div>
<span class="mw-svc-status" style="{{ $svc['online'] ? '' : 'color:var(--mw-rd);opacity:1;' }}">{{ $svc['online'] ? 'Online' : 'Offline' }}</span>
</div>
@endif
@endforeach
</div>
</div>
<div class="mw-ports">
@foreach([25, 465, 587, 110, 143, 993, 995, 80, 443] as $port)
<span class="mw-port">:{{ $port }}</span>
@endforeach
</div>
</div>
<div class="mw-right-col">
<div class="mw-card">
<div class="mw-card-title">Storage</div>
<div class="mw-donut-wrap">
<svg width="68" height="68" viewBox="0 0 68 68" style="flex-shrink:0">
<circle cx="34" cy="34" r="26" fill="none" stroke="var(--mw-bg4)" stroke-width="8"/>
<circle cx="34" cy="34" r="26" fill="none" stroke="var(--mw-v)" stroke-width="8"
stroke-dasharray="{{ ($diskUsedPercent ?? 20) * 1.6336 }} 163.36"
stroke-dashoffset="40.84" stroke-linecap="round"
transform="rotate(-90 34 34)" opacity=".7"/>
<text x="34" y="38" text-anchor="middle" font-size="11" font-weight="700" fill="#edf0fc">{{ $diskUsedPercent ?? 0 }}%</text>
</svg>
<div style="flex:1">
<div class="mw-legend-row">
<div class="mw-legend-dot" style="background:var(--mw-v);opacity:.7"></div>
<div class="mw-legend-label">Belegt</div>
<div class="mw-legend-val">{{ $diskUsedGb ?? '—' }} GB</div>
</div>
<div class="mw-legend-row">
<div class="mw-legend-dot" style="background:var(--mw-bg4);border:1px solid var(--mw-b2)"></div>
<div class="mw-legend-label">Frei</div>
<div class="mw-legend-val">{{ $diskFreeGb ?? '—' }} GB</div>
</div>
<div class="mw-legend-row">
<div class="mw-legend-dot" style="background:var(--mw-b2)"></div>
<div class="mw-legend-label">Gesamt</div>
<div class="mw-legend-val">{{ $diskTotalGb ?? '—' }} GB</div>
</div>
</div>
</div>
</div>
<div class="mw-card">
<div class="mw-card-title">Mail &amp; Sicherheit</div>
<div class="mw-mini-grid">
<div class="mw-mini-card">
<div class="mw-mini-val" style="color:var(--mw-t1)">{{ $bounceCount ?? 0 }}</div>
<div class="mw-mini-label">Bounces</div>
</div>
<div class="mw-mini-card">
<div class="mw-mini-val" style="color:var(--mw-am)">{{ $spamCount ?? 0 }}</div>
<div class="mw-mini-label">Spam</div>
</div>
<div class="mw-mini-card">
<div class="mw-mini-val" style="color:var(--mw-gr)">OK</div>
<div class="mw-mini-label">RBL</div>
</div>
</div>
</div>
</div>
</div>
@endsection