Quelltext des aktuellen Standes
<?php
$this->layout('layouts/main', [
'page_title' => 'Cluster',
'current_route' => 'vms',
'full_width' => true,
]);
$clusters = $clusters ?? [];
$can_manage_clusters = $can_manage_clusters ?? false;
?>
<div class="vcl-wrap">
<div class="content-header">
<div>
<h1><?= $this->te('Cluster') ?></h1>
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="/"><?= $this->te('Home') ?></a></li>
<li class="breadcrumb-item"><a href="/vms"><?= $this->te('Virtualisierung') ?></a></li>
<li class="breadcrumb-item active"><?= $this->te('Cluster') ?></li>
</ol>
</div>
<?php if ($can_manage_clusters): ?>
<div class="content-header-actions">
<a href="/vms/clusters/create" class="btn btn-primary">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" width="15" height="15"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
<?= $this->te('Neuer Cluster') ?>
</a>
</div>
<?php endif; ?>
</div>
<div class="page-body">
<!-- Filter-Card: Sub-Navigation (wie /orders, /status, /xdr) -->
<div class="card card-outline card-primary mb-3">
<div class="filter-card-body">
<nav class="subnav" style="flex:1 1 100%;margin-bottom:0;">
<a href="/vms" class="subnav-tab">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="14" height="14"><rect x="2" y="3" width="20" height="14" rx="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg>
<?= $this->te('VMs') ?>
</a>
<a href="/vms/hosts" class="subnav-tab">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="14" height="14"><rect x="2" y="2" width="20" height="8" rx="2"/><rect x="2" y="14" width="20" height="8" rx="2"/><line x1="6" y1="6" x2="6.01" y2="6"/><line x1="6" y1="18" x2="6.01" y2="18"/></svg>
<?= $this->te('Hosts') ?>
</a>
<a href="/vms/clusters" class="subnav-tab active">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="14" height="14"><circle cx="12" cy="5" r="3"/><circle cx="5" cy="19" r="3"/><circle cx="19" cy="19" r="3"/><line x1="12" y1="8" x2="5" y2="16"/><line x1="12" y1="8" x2="19" y2="16"/></svg>
<?= $this->te('Cluster') ?>
</a>
</nav>
</div>
</div>
<?php if (empty($clusters)): ?>
<div class="empty-state">
<span class="empty-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.25" width="44" height="44"><circle cx="12" cy="5" r="3"/><circle cx="5" cy="19" r="3"/><circle cx="19" cy="19" r="3"/><line x1="12" y1="8" x2="5" y2="16"/><line x1="12" y1="8" x2="19" y2="16"/></svg>
</span>
<h2><?= $this->te('Noch keine Cluster angelegt') ?></h2>
<p><?= $this->te('Fassen Sie mehrere Hosts zu einem Cluster zusammen.') ?></p>
<?php if ($can_manage_clusters): ?>
<a href="/vms/clusters/create" class="btn btn-primary"><?= $this->te('Ersten Cluster anlegen') ?></a>
<?php endif; ?>
</div>
<?php else: ?>
<div class="table-wrapper">
<table class="data-table">
<thead>
<tr>
<th scope="col"><?= $this->te('Name') ?></th>
<th scope="col" style="width:80px;"><?= $this->te('Hosts') ?></th>
<th scope="col"><?= $this->te('CPU gesamt') ?></th>
<th scope="col"><?= $this->te('RAM gesamt') ?></th>
<th scope="col"><?= $this->te('Beschreibung') ?></th>
<th scope="col" style="width:80px;"></th>
</tr>
</thead>
<tbody>
<?php foreach ($clusters as $c): ?>
<tr class="clickable" onclick="window.location='/vms/clusters/<?= $c['id'] ?>/edit'">
<td>
<span class="vcl-name"><?= $this->e($c['name']) ?></span>
</td>
<td>
<span class="vcl-count-pill"><?= (int)($c['host_count'] ?? 0) ?></span>
</td>
<td class="vcl-muted">
<?= (int)($c['total_cpu'] ?? 0) > 0 ? (int)$c['total_cpu'] . ' Kerne' : '—' ?>
</td>
<td class="vcl-muted">
<?= (float)($c['total_ram_gb'] ?? 0) > 0 ? number_format((float)$c['total_ram_gb'], 0, ',', '.') . ' GB' : '—' ?>
</td>
<td class="vcl-muted"><?= $this->e($c['description'] ?: '—') ?></td>
<td class="vcl-actions" onclick="event.stopPropagation()">
<?php if ($can_manage_clusters): ?>
<a href="/vms/clusters/<?= $c['id'] ?>/edit" class="btn btn-xs btn-default" title="<?= $this->te('Bearbeiten') ?>">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="13" height="13"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/></svg>
</a>
<form method="POST" action="/vms/clusters/<?= $c['id'] ?>/delete" style="display:inline;"
onsubmit="return confirm('Cluster "<?= $this->e(addslashes($c['name'])) ?>" wirklich löschen?')">
<input type="hidden" name="_csrf" value="<?= $this->csrf() ?>">
<button class="btn btn-xs btn-danger" title="<?= $this->te('Löschen') ?>">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="13" height="13"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2"/></svg>
</button>
</form>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<div class="vcl-footer">
<span class="vcl-footcount"><?= $this->te('{anzahl} Cluster', ['anzahl' => count($clusters)]) ?></span>
</div>
<?php endif; ?>
</div>
</div>
<style>
/* ====================================================
Cluster-Übersicht · Prefix: vcl-
==================================================== */
.vcl-wrap { display:flex; flex-direction:column; }
.vcl-name { font-weight:500; color:var(--gray-900); }
.vcl-count-pill {
display:inline-flex; align-items:center; justify-content:center;
min-width:28px; height:20px; padding:0 0.4rem;
background:var(--color-primary-soft); color:var(--color-primary-strong); border-radius:9999px;
font-size:0.75rem; font-weight:700;
}
.vcl-muted { color:var(--gray-500); font-size:0.875rem; }
.vcl-actions { text-align:right; white-space:nowrap; }
.vcl-footer { display:flex; margin-top:0.75rem; padding:0 0.25rem; }
.vcl-footcount { font-size:0.8rem; color:var(--gray-400); }
</style>