189 lines
9.1 KiB
Plaintext
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> |