CluPilotCloud/resources/views/livewire/admin/instances.blade.php

199 lines
12 KiB
PHP

<div class="space-y-5">
<div class="animate-rise">
<h1 class="text-2xl font-bold tracking-tight text-ink">{{ __('admin.nav.instances') }}</h1>
<p class="mt-1 text-sm text-muted">{{ __('admin.instances_sub') }}</p>
</div>
{{-- Haengengebliebene Abbauten, ganz oben und in Rot.
Der wichtigste Kasten dieser Seite: jede Zeile hier ist eine Maschine,
die laengst weg sein sollte und weiter einen Platz auf ihrem Host
belegt. Siehe Instances::render() dazu, warum das nicht als Plakette
in der Zeile stehen kann (die Tabelle darunter ist geblaettert) und
warum die Liste sich von selbst abraeumt. --}}
@if ($stuck !== [])
<div class="overflow-hidden rounded-lg border border-danger-border bg-surface shadow-xs animate-rise [animation-delay:20ms]">
<div class="border-b border-danger-border bg-danger-bg px-4 py-3">
<h2 class="flex items-center gap-2 text-sm font-semibold text-danger">
<x-ui.icon name="alert-triangle" class="size-4" />{{ __('admin.teardown.stuck_title') }}
<span class="font-mono text-xs font-normal">{{ count($stuck) }}</span>
</h2>
<p class="mt-1 text-xs text-danger">{{ __('admin.teardown.stuck_sub') }}</p>
</div>
<div class="overflow-x-auto">
<table class="w-full text-sm">
<thead>
<tr class="border-b border-line bg-surface-2 text-left text-xs font-semibold text-muted">
<th class="px-4 py-3 font-semibold">{{ __('admin.col.customer') }}</th>
<th class="px-4 py-3 font-semibold">{{ __('admin.col.address') }}</th>
<th class="px-4 py-3 font-semibold">{{ __('admin.teardown.col_machine') }}</th>
<th class="px-4 py-3 font-semibold">{{ __('admin.teardown.col_attempt') }}</th>
<th class="px-4 py-3 font-semibold">{{ __('admin.teardown.col_reason') }}</th>
</tr>
</thead>
<tbody>
@foreach ($stuck as $s)
<tr class="border-b border-line last:border-0">
<td class="px-4 py-3 text-body">{{ $s['customer'] }}</td>
<td class="px-4 py-3 font-mono text-xs text-muted">{{ $s['address'] }}</td>
<td class="px-4 py-3 font-mono text-xs text-muted">{{ $s['machine'] }}</td>
<td class="px-4 py-3 text-xs text-muted">{{ $s['attempted'] }}</td>
<td class="px-4 py-3 text-xs text-body">
{{ $s['reason'] }}
@if ($s['archive'])
<span class="mt-1 block font-mono text-xs text-muted">{{ __('admin.teardown.col_archive') }}: {{ $s['archive'] }}</span>
@endif
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
@endif
{{-- Bestellte Datenexporte. Nur vorhanden, wenn wirklich einer bestellt
wurde ein dauerhaft leerer Kasten wird nach der zweiten Woche nicht
mehr gelesen. Siehe Instances::render(): das ist der einzige Ort in
der Konsole, an dem die Antwort aus dem Kuendigungsdialog ueberhaupt
sichtbar wird. --}}
@if ($exports !== [])
<div class="overflow-hidden rounded-lg border border-warning-border bg-surface shadow-xs animate-rise [animation-delay:40ms]">
<div class="border-b border-warning-border bg-warning-bg px-4 py-3">
<h2 class="flex items-center gap-2 text-sm font-semibold text-warning">
<x-ui.icon name="download" class="size-4" />{{ __('admin.export_wish.title') }}
<span class="font-mono text-xs font-normal">{{ count($exports) }}</span>
</h2>
<p class="mt-1 text-xs text-warning">{{ __('admin.export_wish.sub') }}</p>
</div>
<div class="overflow-x-auto">
<table class="w-full text-sm">
<thead>
<tr class="border-b border-line bg-surface-2 text-left text-xs font-semibold text-muted">
<th class="px-4 py-3 font-semibold">{{ __('admin.col.customer') }}</th>
<th class="px-4 py-3 font-semibold">{{ __('admin.col.address') }}</th>
<th class="px-4 py-3 font-semibold">{{ __('admin.export_wish.col_ends') }}</th>
</tr>
</thead>
<tbody>
@foreach ($exports as $e)
<tr class="border-b border-line last:border-0">
<td class="px-4 py-3 text-body">{{ $e['customer'] }}</td>
<td class="px-4 py-3 font-mono text-xs text-muted">{{ $e['address'] }}</td>
<td class="px-4 py-3 text-xs">
<span class="text-body">{{ $e['ends_at'] }}</span>
@if ($e['over'])
<span class="ml-1.5 font-semibold text-warning">{{ __('admin.export_wish.over') }}</span>
@endif
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
@endif
<div class="overflow-hidden rounded-lg border border-line bg-surface shadow-xs animate-rise [animation-delay:60ms]">
<div class="overflow-x-auto">
<table class="w-full text-sm">
<thead>
<tr class="border-b border-line bg-surface-2 text-left text-xs font-semibold text-muted">
<th class="px-4 py-3 font-semibold">{{ __('admin.col.address') }}</th>
<th class="px-4 py-3 font-semibold">{{ __('admin.col.customer') }}</th>
<th class="px-4 py-3 font-semibold">{{ __('admin.col.host') }}</th>
<th class="px-4 py-3 font-semibold">VMID</th>
<th class="px-4 py-3 font-semibold">{{ __('admin.col.plan') }}</th>
<th class="px-4 py-3 font-semibold">{{ __('admin.col.quota') }}</th>
<th class="px-4 py-3 font-semibold">{{ __('admin.col.status') }}</th>
@if ($canRestart)
<th class="px-4 py-3 text-right font-semibold">{{ __('admin.col.actions') }}</th>
@endif
</tr>
</thead>
<tbody>
@forelse ($rows as $r)
<tr class="border-b border-line last:border-0 hover:bg-surface-hover">
<td class="px-4 py-3 font-mono text-body">{{ $r['address'] }}</td>
<td class="px-4 py-3 text-body">{{ $r['customer'] }}</td>
<td class="px-4 py-3 font-mono text-xs text-muted">{{ $r['host'] }}</td>
<td class="px-4 py-3 font-mono text-xs text-muted">{{ $r['vmid'] }}</td>
<td class="px-4 py-3 text-xs text-muted">{{ $r['plan'] }}</td>
<td class="px-4 py-3 font-mono text-xs text-muted">{{ $r['quota'] }}</td>
<td class="px-4 py-3">
<div class="flex flex-wrap items-center gap-1.5">
<x-ui.badge :status="$r['status']">{{ $r['status_label'] }}</x-ui.badge>
@if ($r['restart'])
<span class="inline-flex items-center gap-1 rounded-pill border border-warning-border bg-warning-bg px-2 py-0.5 text-xs font-semibold text-warning"
title="{{ __('admin.restart_pending_hint') }}">
<x-ui.icon name="rotate-ccw" class="size-3.5" />{{ __('admin.restart_pending') }}
</span>
@endif
</div>
</td>
@if ($canRestart)
<td class="px-4 py-3 text-right">
@if ($r['live'])
<x-ui.button variant="secondary" size="sm"
@click="$dispatch('openModal', { component: 'admin.confirm-restart-instance', arguments: { uuid: '{{ $r['uuid'] }}' } })">
<x-ui.icon name="rotate-ccw" class="size-4" />{{ __('admin.restart') }}
</x-ui.button>
@endif
</td>
@endif
</tr>
@empty
<tr><td colspan="{{ $canRestart ? 8 : 7 }}" class="px-4 py-8 text-center text-sm text-muted">{{ __('admin.instances_empty') }}</td></tr>
@endforelse
</tbody>
</table>
</div>
</div>
@if ($instances->hasPages())
<div class="animate-rise [animation-delay:120ms]">{{ $instances->links() }}</div>
@endif
{{-- Was abgebaut wurde, und wo das Archiv liegt.
Unter der Liste und nicht darueber: das ist kein Alarm, sondern ein
Nachweis. Wer ihn braucht, sucht ihn wer ihn nicht braucht, soll
nicht jeden Tag daran vorbeiscrollen, um zur Instanzliste zu kommen.
`archive_volid` steht im Klartext da, weil genau diese Zeichenkette
eine Wiederherstellung von einer Suche unterscheidet. --}}
@if ($teardowns !== [])
<div class="overflow-hidden rounded-lg border border-line bg-surface shadow-xs animate-rise [animation-delay:140ms]">
<div class="border-b border-line bg-surface-2 px-4 py-3">
<h2 class="flex items-center gap-2 text-sm font-semibold text-ink">
<x-ui.icon name="box" class="size-4" />{{ __('admin.teardown.archive_title') }}
<span class="font-mono text-xs font-normal text-muted">{{ count($teardowns) }}</span>
</h2>
<p class="mt-1 text-xs text-muted">{{ __('admin.teardown.archive_sub') }}</p>
</div>
<div class="overflow-x-auto">
<table class="w-full text-sm">
<thead>
<tr class="border-b border-line bg-surface-2 text-left text-xs font-semibold text-muted">
<th class="px-4 py-3 font-semibold">{{ __('admin.col.customer') }}</th>
<th class="px-4 py-3 font-semibold">{{ __('admin.col.address') }}</th>
<th class="px-4 py-3 font-semibold">{{ __('admin.teardown.col_archived_at') }}</th>
<th class="px-4 py-3 font-semibold">{{ __('admin.teardown.col_archive') }}</th>
</tr>
</thead>
<tbody>
@foreach ($teardowns as $t)
<tr class="border-b border-line last:border-0">
<td class="px-4 py-3 text-body">{{ $t['customer'] }}</td>
<td class="px-4 py-3 font-mono text-xs text-muted">{{ $t['address'] }}</td>
<td class="px-4 py-3 text-xs text-muted">{{ $t['archived_at'] }}</td>
<td class="px-4 py-3 font-mono text-xs text-body">{{ $t['archive'] }}</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
@endif
</div>