clusev/resources/views/livewire/patch/index.blade.php

71 lines
3.9 KiB
PHP

<div class="space-y-4" @if (! $ready) wire:init="scan" @endif>
{{-- Header --}}
<div>
<p class="font-mono text-[11px] uppercase tracking-[0.2em] text-accent-text">{{ __('patch.eyebrow') }}</p>
<h2 class="mt-0.5 font-display text-xl font-semibold text-ink sm:text-2xl">{{ __('patch.title') }}</h2>
<p class="mt-1 text-sm text-ink-3">{{ __('patch.subtitle') }}</p>
</div>
{{-- Fleet KPIs --}}
@if ($ready)
<div class="grid grid-cols-2 gap-3">
<x-kpi :label="__('patch.total_pending')" :value="$totalPending" icon="rotate" :tone="$totalPending > 0 ? 'warning' : 'online'" />
<x-kpi :label="__('patch.total_security')" :value="$totalSecurity" icon="shield-alert" :tone="$totalSecurity > 0 ? 'offline' : 'online'" />
</div>
@endif
@if ($servers->isEmpty())
<x-panel>
<div class="py-8 text-center">
<p class="font-display text-sm font-semibold text-ink">{{ __('patch.no_servers_title') }}</p>
<p class="mt-1 text-xs text-ink-3">{{ __('patch.no_servers') }}</p>
</div>
</x-panel>
@elseif (! $ready)
<div class="space-y-2">
@foreach ($servers as $s)
<div wire:key="pl-{{ $s->uuid }}" class="h-16 animate-pulse rounded-lg bg-raised/50"></div>
@endforeach
<p class="text-center font-mono text-[11px] text-ink-4">{{ __('patch.scan_hint') }}</p>
</div>
@else
<x-panel :padded="false">
<div class="divide-y divide-line">
@foreach ($servers as $s)
@php($c = $counts[$s->uuid] ?? null)
@php($result = $results[$s->uuid] ?? null)
<div wire:key="pr-{{ $s->uuid }}" class="px-4 py-3 sm:px-5">
<div class="flex flex-wrap items-center gap-3">
<div class="min-w-0 flex-1">
<a href="{{ route('servers.show', $s->uuid) }}" wire:navigate class="truncate font-mono text-sm text-ink hover:text-accent-text">{{ $s->name }}</a>
</div>
@if (! $c || isset($c['error']))
<span class="font-mono text-[11px] text-offline">{{ __('patch.scan_error') }}</span>
@elseif (is_null($c['pending']))
<span class="font-mono text-[11px] text-ink-4">{{ __('patch.unknown') }}</span>
@elseif ($c['pending'] === 0)
<x-status-pill status="online">{{ __('patch.up_to_date') }}</x-status-pill>
@else
<div class="flex items-center gap-1.5">
<x-status-pill status="warning">{{ __('patch.pending_label', ['count' => $c['pending']]) }}</x-status-pill>
@if (($c['security'] ?? 0) > 0)
<x-status-pill status="offline">{{ __('patch.security_label', ['count' => $c['security']]) }}</x-status-pill>
@endif
@can('operate')
<x-modal-trigger variant="accent" action="patch('{{ $s->uuid }}')" wire:loading.attr="disabled">{{ __('patch.apply') }}</x-modal-trigger>
@endcan
</div>
@endif
</div>
@if ($result)
<pre class="mt-2 max-h-40 overflow-auto rounded-md border border-line bg-void p-3 font-mono text-[11px] leading-relaxed {{ $result['ok'] ? 'text-ink-2' : 'text-offline' }}">{{ $result['output'] }}</pre>
@endif
</div>
@endforeach
</div>
</x-panel>
@endif
</div>