Files
watcher/Watcher/Views/Server/_ServerCard.cshtml
triggermeelmo 23cac83061
All checks were successful
Gitea CI/CD / dotnet-build-and-test (push) Successful in 45s
Gitea CI/CD / Set Tag Name (push) Successful in 5s
Gitea CI/CD / docker-build-and-push (push) Successful in 5m55s
Gitea CI/CD / Create Tag (push) Successful in 5s
Server-Übersicht Metric
2025-11-17 00:47:51 +01:00

189 lines
9.1 KiB
Plaintext

@model IEnumerable<Watcher.Models.Server>
<div class="row g-3">
@foreach (var server in Model)
{
<div class="col-12 col-lg-6 col-xl-4">
<div class="card server-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-hdd-network me-2 text-primary"></i>
<strong>@server.Name</strong>
</div>
<span class="badge @(server.IsOnline ? "bg-success" : "bg-danger")">
<i class="bi @(server.IsOnline ? "bi-check-circle" : "bi-x-circle")"></i>
@(server.IsOnline ? "Online" : "Offline")
</span>
</div>
<div class="card-body">
<!-- Server Info -->
<div class="server-info">
<div class="info-row">
<span class="info-label"><i class="bi bi-globe me-1"></i>IP:</span>
<span class="info-value">@server.IPAddress</span>
</div>
<div class="info-row">
<span class="info-label"><i class="bi bi-pc-display me-1"></i>Typ:</span>
<span class="info-value">@server.Type</span>
</div>
<div class="info-row">
<span class="info-label"><i class="bi bi-cpu me-1"></i>CPU:</span>
<span class="info-value">@(server.CpuCores > 0 ? $"{server.CpuCores} Cores" : "N/A")</span>
</div>
<div class="info-row">
<span class="info-label"><i class="bi bi-memory me-1"></i>RAM:</span>
<span class="info-value">
@if (server.RamSize > 0)
{
var ramGB = server.RamSize / (1024.0 * 1024.0 * 1024.0);
@($"{ramGB:F1} GB")
}
else
{
<text>N/A</text>
}
</span>
</div>
</div>
<!-- Current Metrics (wenn online) -->
@if (server.IsOnline)
{
<div class="mt-3 current-metrics">
<h6 class="mb-2"><i class="bi bi-activity me-1"></i>Aktuelle Last</h6>
<div class="metric-bars">
<div class="metric-bar-item">
<div class="d-flex justify-content-between mb-1">
<small>CPU</small>
<small class="metric-value" data-server-id="@server.Id" data-metric="cpu">--</small>
</div>
<div class="progress" style="height: 6px;">
<div class="progress-bar bg-info server-cpu-bar" role="progressbar" style="width: 0%"></div>
</div>
</div>
<div class="metric-bar-item mt-2">
<div class="d-flex justify-content-between mb-1">
<small>RAM</small>
<small class="metric-value" data-server-id="@server.Id" data-metric="ram">--</small>
</div>
<div class="progress" style="height: 6px;">
<div class="progress-bar bg-success server-ram-bar" role="progressbar" style="width: 0%"></div>
</div>
</div>
@if (!string.IsNullOrEmpty(server.GpuType))
{
<div class="metric-bar-item mt-2">
<div class="d-flex justify-content-between mb-1">
<small>GPU</small>
<small class="metric-value" data-server-id="@server.Id" data-metric="gpu">--</small>
</div>
<div class="progress" style="height: 6px;">
<div class="progress-bar bg-danger server-gpu-bar" role="progressbar" style="width: 0%"></div>
</div>
</div>
}
</div>
</div>
}
<!-- Action Buttons -->
<div class="action-buttons mt-3 d-flex gap-2">
<a asp-action="Details" asp-route-id="@server.Id" class="btn btn-sm btn-outline-primary flex-fill">
<i class="bi bi-bar-chart-fill"></i> Details
</a>
<button class="btn btn-sm btn-outline-warning flex-fill" onclick="rebootServer(@server.Id)">
<i class="bi bi-arrow-clockwise"></i> Reboot
</button>
<a asp-action="EditServer" asp-route-id="@server.Id" class="btn btn-sm btn-outline-secondary flex-fill">
<i class="bi bi-pencil"></i> Edit
</a>
</div>
<!-- Delete Button (separate row) -->
<div class="mt-2">
<form asp-action="Delete" asp-route-id="@server.Id" method="post" class="m-0"
onsubmit="return confirm('Server @server.Name wirklich löschen?');">
<button type="submit" class="btn btn-sm btn-outline-danger w-100">
<i class="bi bi-trash"></i> Server löschen
</button>
</form>
</div>
</div>
</div>
</div>
}
</div>
<script>
function rebootServer(serverId) {
if (confirm('Server wirklich neu starten?')) {
console.log('Rebooting server:', serverId);
// TODO: API Call zum Neustarten des Servers
alert('Reboot-Funktion wird implementiert');
}
}
// Lade aktuelle Metriken für alle Server
async function loadCurrentMetrics() {
// Sammle alle eindeutigen Server-IDs
const serverIds = new Set();
document.querySelectorAll('.metric-value').forEach(el => {
const serverId = el.getAttribute('data-server-id');
if (serverId) serverIds.add(serverId);
});
// Lade Metriken für jeden Server
for (const serverId of serverIds) {
try {
const response = await fetch(`/monitoring/current-metrics/${serverId}`);
if (response.ok) {
const data = await response.json();
if (data.hasData) {
// Update CPU
updateMetric(serverId, 'cpu', data.cpu, '.server-cpu-bar', 'bg-info');
// Update RAM
updateMetric(serverId, 'ram', data.ram, '.server-ram-bar', 'bg-success');
// Update GPU (falls vorhanden)
updateMetric(serverId, 'gpu', data.gpu, '.server-gpu-bar', 'bg-danger');
}
}
} catch (err) {
console.error(`Fehler beim Laden der Metriken für Server ${serverId}:`, err);
}
}
}
function updateMetric(serverId, metricType, value, barClass, defaultColorClass) {
// Finde das Element für diesen Server und Metrik-Typ
const metricElement = document.querySelector(`.metric-value[data-server-id="${serverId}"][data-metric="${metricType}"]`);
if (!metricElement) return;
// Update Text
metricElement.textContent = `${value.toFixed(1)}%`;
// Update Progress Bar
const card = metricElement.closest('.card');
const bar = card.querySelector(barClass);
if (bar) {
bar.style.width = `${value}%`;
// Optional: Farbe basierend auf Wert ändern
bar.className = 'progress-bar';
if (value >= 90) {
bar.classList.add('bg-danger');
} else if (value >= 75) {
bar.classList.add('bg-warning');
} else {
bar.classList.add(defaultColorClass);
}
}
}
// Initial laden und mit konfiguriertem Intervall aktualisieren
loadCurrentMetrics();
const refreshInterval = @(ViewBag.RefreshIntervalMilliseconds ?? 30000);
setInterval(loadCurrentMetrics, refreshInterval);
</script>