Server Card schöner gemacht

This commit is contained in:
2025-11-06 17:29:54 +01:00
parent 3d375f4792
commit da0c5d9efb
4 changed files with 508 additions and 72 deletions

View File

@@ -8,28 +8,180 @@
<link rel="stylesheet" href="~/css/services-overview.css" />
</head>
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
<div >
<table class="ServiceList">
<tr>
<th>Container-ID</th>
<th>Name</th>
<th>Image</th>
<th>Host</th>
<th>Aktionen</th>
</tr>
@foreach (Container container in Model.Containers)
{
<tr class="ServiceRow">
<td>@container.ContainerId</td>
<td>@container.Name</td>
<td>@container.Image</td>
<td><a class="ServiceEntry" href="/Server/Details/@container.ServerId">@container.Server?.Name</a></td>
<td>nicht verfügbar</td>
</tr>
}
</table>
<div class="container-fluid mt-4">
<div class="d-flex justify-content-between align-items-center mb-4">
<h4><i class="bi bi-box-seam me-2"></i>Container & Services</h4>
<span class="badge bg-primary">@Model.Containers.Count Container</span>
</div>
@if (!Model.Containers.Any())
{
<div class="alert alert-info">
<i class="bi bi-info-circle me-2"></i>Keine Container gefunden. Container werden automatisch von den Agents erkannt.
</div>
}
else
{
var groupedContainers = Model.Containers.GroupBy(c => c.Server?.Name ?? "Unbekannt");
foreach (var serverGroup in groupedContainers.OrderBy(g => g.Key))
{
<div class="mb-4">
<h5 class="text-muted mb-3">
<i class="bi bi-hdd-network me-2"></i>@serverGroup.Key
<span class="badge bg-secondary ms-2">@serverGroup.Count()</span>
</h5>
<div class="row g-3">
@foreach (var container in serverGroup)
{
<div class="col-12 col-lg-6 col-xl-4">
<div class="card container-card shadow-sm">
<div class="card-header d-flex justify-content-between align-items-center">
<div class="d-flex align-items-center">
<i class="bi bi-box me-2 text-primary"></i>
<strong>@container.Name</strong>
</div>
<span class="badge @(container.IsRunning ? "bg-success" : "bg-danger")">
<i class="bi @(container.IsRunning ? "bi-play-fill" : "bi-stop-fill")"></i>
@(container.IsRunning ? "Running" : "Stopped")
</span>
</div>
<div class="card-body">
<div class="container-info">
<div class="info-row">
<span class="info-label"><i class="bi bi-tag me-1"></i>ID:</span>
<span class="info-value">@(container.ContainerId != null && container.ContainerId.Length > 12 ? container.ContainerId.Substring(0, 12) : container.ContainerId)</span>
</div>
<div class="info-row">
<span class="info-label"><i class="bi bi-image me-1"></i>Image:</span>
<span class="info-value">@container.Image</span>
</div>
<div class="info-row">
<span class="info-label"><i class="bi bi-server me-1"></i>Host:</span>
<span class="info-value">
<a href="/Server/Details/@container.ServerId" class="text-decoration-none">
@container.Server?.Name
</a>
</span>
</div>
</div>
<!-- Action Buttons -->
<div class="action-buttons mt-3 d-flex gap-2">
<button class="btn btn-sm btn-outline-warning flex-fill" onclick="restartContainer('@container.ContainerId')">
<i class="bi bi-arrow-clockwise"></i> Restart
</button>
<button class="btn btn-sm btn-outline-danger flex-fill" onclick="stopContainer('@container.ContainerId')">
<i class="bi bi-stop-circle"></i> Stop
</button>
<button class="btn btn-sm btn-outline-info flex-fill" onclick="updateContainer('@container.ContainerId')">
<i class="bi bi-arrow-up-circle"></i> Update
</button>
</div>
<!-- Expandable Metrics Section -->
<div class="mt-3">
<button class="btn btn-sm btn-outline-secondary w-100 toggle-metrics"
data-container-id="@container.Id"
onclick="toggleMetrics(this, @container.Id)">
<i class="bi bi-graph-up me-1"></i>
Metriken anzeigen
<i class="bi bi-chevron-down float-end"></i>
</button>
<div class="metrics-panel collapse" id="metrics-@container.Id">
<div class="metrics-content mt-3 p-3 bg-light rounded">
<div class="metric-item">
<div class="d-flex justify-content-between mb-1">
<small><i class="bi bi-cpu me-1"></i>CPU</small>
<small class="text-muted"><span class="metric-value">--</span>%</small>
</div>
<div class="progress" style="height: 8px;">
<div class="progress-bar bg-info" role="progressbar" style="width: 0%"></div>
</div>
</div>
<div class="metric-item mt-3">
<div class="d-flex justify-content-between mb-1">
<small><i class="bi bi-memory me-1"></i>RAM</small>
<small class="text-muted"><span class="metric-value">--</span> MB</small>
</div>
<div class="progress" style="height: 8px;">
<div class="progress-bar bg-success" role="progressbar" style="width: 0%"></div>
</div>
</div>
<div class="metric-item mt-3">
<div class="d-flex justify-content-between mb-1">
<small><i class="bi bi-ethernet me-1"></i>Network</small>
<small class="text-muted">
<i class="bi bi-arrow-down text-success"></i> <span class="metric-value">--</span> MB/s
<i class="bi bi-arrow-up text-primary ms-2"></i> <span class="metric-value">--</span> MB/s
</small>
</div>
</div>
<div class="text-center mt-3">
<small class="text-muted">
<i class="bi bi-info-circle me-1"></i>
Metriken werden in Echtzeit aktualisiert
</small>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
}
</div>
</div>
}
}
</div>
@section Scripts {
<script>
function toggleMetrics(button, containerId) {
const panel = document.getElementById('metrics-' + containerId);
const icon = button.querySelector('.float-end');
if (panel.classList.contains('show')) {
panel.classList.remove('show');
button.innerHTML = '<i class="bi bi-graph-up me-1"></i>Metriken anzeigen<i class="bi bi-chevron-down float-end"></i>';
} else {
panel.classList.add('show');
button.innerHTML = '<i class="bi bi-graph-up me-1"></i>Metriken verbergen<i class="bi bi-chevron-up float-end"></i>';
// Hier könnten echte Metriken geladen werden
loadContainerMetrics(containerId);
}
}
function loadContainerMetrics(containerId) {
// Placeholder für zukünftige API-Calls
console.log('Loading metrics for container:', containerId);
// TODO: Echte Metriken vom Backend laden
}
function restartContainer(containerId) {
if (confirm('Container wirklich neu starten?')) {
console.log('Restarting container:', containerId);
// TODO: API Call zum Neustarten
alert('Restart-Funktion wird implementiert');
}
}
function stopContainer(containerId) {
if (confirm('Container wirklich stoppen?')) {
console.log('Stopping container:', containerId);
// TODO: API Call zum Stoppen
alert('Stop-Funktion wird implementiert');
}
}
function updateContainer(containerId) {
if (confirm('Container-Image aktualisieren?')) {
console.log('Updating container:', containerId);
// TODO: API Call zum Updaten
alert('Update-Funktion wird implementiert');
}
}
</script>
}