119 lines
6.2 KiB
PHP
119 lines
6.2 KiB
PHP
@php
|
|
$total = count($servers);
|
|
$online = collect($servers)->where('status', 'online')->count();
|
|
$avgCpu = $total ? (int) round(collect($servers)->avg('cpu')) : 0;
|
|
$avgMem = $total ? (int) round(collect($servers)->avg('mem')) : 0;
|
|
|
|
$svcLabel = ['online' => 'aktiv', 'warning' => 'degradiert', 'offline' => 'gestoppt'];
|
|
|
|
$web = collect($servers)->firstWhere('name', 'web-01') ?? ($servers[0] ?? ['cpu' => 0, 'mem' => 0]);
|
|
$disk = 71; // mock until the SSH layer reports real disk usage
|
|
$ringTone = fn (int $v): string => $v >= 90 ? 'offline' : ($v >= 75 ? 'warning' : 'online');
|
|
@endphp
|
|
|
|
<div class="space-y-4">
|
|
{{-- Header --}}
|
|
<div class="flex flex-wrap items-end justify-between gap-3">
|
|
<div>
|
|
<p class="font-mono text-[11px] uppercase tracking-[0.2em] text-accent-text">Flotte</p>
|
|
<h2 class="mt-0.5 font-display text-xl font-semibold text-ink sm:text-2xl">Übersicht</h2>
|
|
</div>
|
|
<x-status-pill status="online">{{ $online }} / {{ $total }} online</x-status-pill>
|
|
</div>
|
|
|
|
{{-- KPI grid: 1 → 2 → 4 --}}
|
|
<div class="grid grid-cols-1 gap-3 sm:grid-cols-2 xl:grid-cols-4">
|
|
<x-kpi label="Server" :value="$total" icon="server" />
|
|
<x-kpi label="Online" :value="$online . ' / ' . $total" tone="online" icon="activity" />
|
|
<x-kpi label="Ø CPU-Last" :value="$avgCpu" unit="%" icon="cpu" :pct="$avgCpu" />
|
|
<x-kpi label="Ø RAM" :value="$avgMem" unit="%" :pct="$avgMem" />
|
|
</div>
|
|
|
|
{{-- Live chart (2/3) + resource rings (1/3) --}}
|
|
<div class="grid grid-cols-1 gap-3 lg:grid-cols-3">
|
|
<x-panel title="Live-Auslastung" :subtitle="($active?->name ?? '—') . ' · CPU %'" class="lg:col-span-2">
|
|
<x-slot:actions>
|
|
<x-badge tone="cyan">Reverb</x-badge>
|
|
</x-slot:actions>
|
|
|
|
<div class="text-accent" x-data="metricsChart(@js($metrics), 40)">
|
|
<svg viewBox="0 0 300 80" class="h-24 w-full" preserveAspectRatio="none" aria-hidden="true">
|
|
<defs>
|
|
<linearGradient id="spark" x1="0" x2="0" y1="0" y2="1">
|
|
<stop offset="0%" stop-color="currentColor" stop-opacity="0.25" />
|
|
<stop offset="100%" stop-color="currentColor" stop-opacity="0" />
|
|
</linearGradient>
|
|
</defs>
|
|
<polyline :points="areaPoints" fill="url(#spark)" stroke="none" />
|
|
<polyline :points="linePoints" fill="none" stroke="currentColor" stroke-width="1.5" />
|
|
</svg>
|
|
<p class="mt-2 flex items-center gap-2 font-mono text-[11px] text-ink-4">
|
|
<span class="inline-flex items-center gap-1.5">
|
|
<span class="h-1.5 w-1.5 rounded-full" :class="connected ? 'bg-online' : 'bg-ink-4'"></span>
|
|
<span x-text="connected ? 'Live über Reverb' : 'Verbindung…'"></span>
|
|
</span>
|
|
<span>· CPU <span class="tabular text-ink-2" x-text="last + '%'"></span></span>
|
|
</p>
|
|
</div>
|
|
</x-panel>
|
|
|
|
<x-panel title="Ressourcen" :subtitle="$active?->name ?? '—'">
|
|
<div class="grid grid-cols-3 gap-2">
|
|
<x-ring :value="$active?->cpu ?? 0" label="CPU" :tone="$ringTone($active?->cpu ?? 0)" />
|
|
<x-ring :value="$active?->mem ?? 0" label="RAM" :tone="$ringTone($active?->mem ?? 0)" />
|
|
<x-ring :value="$active?->disk ?? 0" label="Disk" :tone="$ringTone($active?->disk ?? 0)" />
|
|
</div>
|
|
</x-panel>
|
|
</div>
|
|
|
|
{{-- Server list + systemd services --}}
|
|
<div class="grid grid-cols-1 gap-3 lg:grid-cols-2">
|
|
<x-panel title="Server" :subtitle="$total . ' im Cluster'" :padded="false">
|
|
<x-slot:actions>
|
|
<button type="button" class="inline-flex min-h-11 items-center gap-1.5 rounded-md border border-accent/25 bg-accent/10 px-3 py-1.5 text-xs text-accent-text hover:bg-accent/15">
|
|
<x-icon name="plus" class="h-3.5 w-3.5" /> Hinzufügen
|
|
</button>
|
|
</x-slot:actions>
|
|
<div class="space-y-2 p-4 sm:p-5">
|
|
@foreach ($servers as $s)
|
|
<x-server-item :name="$s['name']" :ip="$s['ip']" :os="$s['os']"
|
|
:status="$s['status']" :cpu="$s['cpu']" :mem="$s['mem']" />
|
|
@endforeach
|
|
</div>
|
|
</x-panel>
|
|
|
|
<x-panel title="systemd-Dienste" :subtitle="$active?->name" :padded="false">
|
|
<div class="divide-y divide-line">
|
|
@foreach ($services as $svc)
|
|
<div class="flex items-center gap-3 px-4 py-2.5 sm:px-5">
|
|
<x-status-dot :status="$svc['status']" :ping="$svc['status'] === 'online'" />
|
|
<div class="min-w-0 flex-1">
|
|
<p class="truncate font-mono text-sm text-ink">{{ $svc['name'] }}</p>
|
|
<p class="truncate text-[11px] text-ink-3">{{ $svc['desc'] }}</p>
|
|
</div>
|
|
<x-status-pill :status="$svc['status']" class="shrink-0">{{ $svcLabel[$svc['status']] }}</x-status-pill>
|
|
</div>
|
|
@endforeach
|
|
</div>
|
|
</x-panel>
|
|
</div>
|
|
|
|
{{-- Audit --}}
|
|
<x-panel title="Audit-Log" subtitle="letzte Ereignisse" :padded="false">
|
|
<div class="divide-y divide-line">
|
|
@foreach ($events as $e)
|
|
<div class="flex items-start gap-3 px-4 py-2.5 sm:px-5">
|
|
<span class="mt-0.5 grid h-7 w-7 shrink-0 place-items-center rounded-sm bg-raised text-ink-3">
|
|
<x-icon name="audit" class="h-3.5 w-3.5" />
|
|
</span>
|
|
<div class="min-w-0 flex-1">
|
|
<p class="text-sm text-ink"><span class="text-ink-2">{{ $e['actor'] }}</span> · {{ $e['action'] }}</p>
|
|
<p class="truncate font-mono text-[11px] text-ink-3">{{ $e['target'] }}</p>
|
|
</div>
|
|
<span class="shrink-0 font-mono text-[11px] text-ink-4">{{ $e['when'] }}</span>
|
|
</div>
|
|
@endforeach
|
|
</div>
|
|
</x-panel>
|
|
</div>
|