From da0c5d9efbfcec03849bf9a659fac1fe6d05f8ff Mon Sep 17 00:00:00 2001 From: triggermeelmo Date: Thu, 6 Nov 2025 17:29:54 +0100 Subject: [PATCH] =?UTF-8?q?Server=20Card=20sch=C3=B6ner=20gemacht?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Watcher/Views/Container/Overview.cshtml | 196 ++++++++++++++++++--- Watcher/Views/Server/Details.cshtml | 198 ++++++++++++++++++---- Watcher/wwwroot/css/server-detail.css | 69 +++++++- Watcher/wwwroot/css/services-overview.css | 117 ++++++++++++- 4 files changed, 508 insertions(+), 72 deletions(-) diff --git a/Watcher/Views/Container/Overview.cshtml b/Watcher/Views/Container/Overview.cshtml index 7e818fb..176d793 100644 --- a/Watcher/Views/Container/Overview.cshtml +++ b/Watcher/Views/Container/Overview.cshtml @@ -8,28 +8,180 @@ -
-
- - - - - - - - - - @foreach (Container container in Model.Containers) - { - - - - - - - - } -
Container-IDNameImageHostAktionen
@container.ContainerId@container.Name@container.Image@container.Server?.Namenicht verfügbar
+
+
+

Container & Services

+ @Model.Containers.Count Container
+ @if (!Model.Containers.Any()) + { +
+ Keine Container gefunden. Container werden automatisch von den Agents erkannt. +
+ } + else + { + var groupedContainers = Model.Containers.GroupBy(c => c.Server?.Name ?? "Unbekannt"); + + foreach (var serverGroup in groupedContainers.OrderBy(g => g.Key)) + { +
+
+ @serverGroup.Key + @serverGroup.Count() +
+ +
+ @foreach (var container in serverGroup) + { +
+
+
+
+ + @container.Name +
+ + + @(container.IsRunning ? "Running" : "Stopped") + +
+
+
+
+ ID: + @(container.ContainerId != null && container.ContainerId.Length > 12 ? container.ContainerId.Substring(0, 12) : container.ContainerId) +
+
+ Image: + @container.Image +
+ +
+ + +
+ + + +
+ + +
+ +
+
+
+
+ CPU + --% +
+
+
+
+
+
+
+ RAM + -- MB +
+
+
+
+
+
+
+ Network + + -- MB/s + -- MB/s + +
+
+
+ + + Metriken werden in Echtzeit aktualisiert + +
+
+
+
+
+
+
+ } +
+
+ } + }
+ +@section Scripts { + +} diff --git a/Watcher/Views/Server/Details.cshtml b/Watcher/Views/Server/Details.cshtml index 715bdb8..a2b9759 100644 --- a/Watcher/Views/Server/Details.cshtml +++ b/Watcher/Views/Server/Details.cshtml @@ -11,50 +11,176 @@
-
-
+ +
+
@Model.Name
- - - @(Model.IsOnline ? "Online" : "Offline") - +
+ + + @(Model.IsOnline ? "Online" : "Offline") + + + Bearbeiten + +
+ +
+
-
-
-
IP: @Model.IPAddress
-
Typ: @Model.Type
-
Erstellt: - @Model.CreatedAt.ToLocalTime().ToString("dd.MM.yyyy HH:mm")
-
Last-Seen: - @Model.LastSeen.ToLocalTime().ToString("dd.MM.yyyy HH:mm")
-
-
-
CPU: @(Model.CpuType ?? "not found")
-
CPU-Kerne: @Model.CpuCores
-
GPU: @(Model.GpuType ?? "not found") +
+
+ +
+
+ System +
+
+
+ + IP-Adresse + + @Model.IPAddress +
+
+ + Typ + + @Model.Type +
+
+ + Erstellt + + @Model.CreatedAt.ToLocalTime().ToString("dd.MM.yyyy") +
+
+ + Last Seen + + + @{ + var timeSinceLastSeen = DateTime.UtcNow - Model.LastSeen; + if (timeSinceLastSeen.TotalMinutes < 1) + { + Gerade eben + } + else if (timeSinceLastSeen.TotalMinutes < 60) + { + vor @((int)timeSinceLastSeen.TotalMinutes) Min + } + else if (timeSinceLastSeen.TotalHours < 24) + { + vor @((int)timeSinceLastSeen.TotalHours) Std + } + else + { + @Model.LastSeen.ToLocalTime().ToString("dd.MM.yyyy HH:mm") + } + } + +
+
-
RAM: @(Model.RamSize)
-
Disk Space: ...
-
-
- -
+ +
+
+ Prozessor & Grafik +
+
+
+ + CPU + + + @if (!string.IsNullOrWhiteSpace(Model.CpuType)) + { + @Model.CpuType + } + else + { + Unbekannt + } + +
+
+ + CPU-Kerne + + + @if (Model.CpuCores > 0) + { + @Model.CpuCores + Cores + } + else + { + Unbekannt + } + +
+
+ + GPU + + + @if (!string.IsNullOrWhiteSpace(Model.GpuType)) + { + @Model.GpuType + } + else + { + Keine / Unbekannt + } + +
+
+
+ + +
+
+ Speicher +
+
+
+ + RAM + + + @if (Model.RamSize > 0) + { + var ramGB = Model.RamSize / (1024.0 * 1024.0 * 1024.0); + @($"{ramGB:F1} GB") + } + else + { + Unbekannt + } + +
+
+
+ + + @if (!string.IsNullOrWhiteSpace(Model.Description)) + { +
+
+ Beschreibung +
+

@Model.Description

+
+ } +
-
diff --git a/Watcher/wwwroot/css/server-detail.css b/Watcher/wwwroot/css/server-detail.css index f531a0c..7f9683a 100644 --- a/Watcher/wwwroot/css/server-detail.css +++ b/Watcher/wwwroot/css/server-detail.css @@ -1,20 +1,75 @@ -.info { - margin: 2rem; - margin-top: 3rem; +/* Server Details - Info Card */ +.info-list { + display: flex; + flex-direction: column; + gap: 0.75rem; } -.hardware { - margin: 2rem; - margin-top: 3rem; +.info-item { + display: flex; + flex-direction: column; + gap: 0.25rem; } +.info-label { + font-size: 0.85rem; + font-weight: 500; + color: #6c757d; + display: flex; + align-items: center; +} + +.info-value { + font-size: 0.95rem; + color: var(--color-text, #212529); + font-weight: 400; + padding-left: 1.25rem; +} + +.info-value .text-muted { + font-style: italic; + font-size: 0.9rem; +} + +/* Section Headers in Info Card */ +.card-body h6.text-muted { + font-size: 0.9rem; + text-transform: uppercase; + letter-spacing: 0.5px; + font-weight: 600; +} + +.card-body h6.text-muted i { + font-size: 1rem; +} + +/* Graph Container */ .graphcontainer { height: 25rem; width: 100%; - background-color: var(--color-surface); + background-color: var(--color-surface, #f8f9fa); + border-radius: 0.375rem; } .graph { width: 100%; height: 22rem; +} + +/* Responsive adjustments */ +@media (max-width: 992px) { + .info-item { + margin-bottom: 0.5rem; + } +} + +@media (max-width: 768px) { + .card-header .d-flex.gap-2 { + flex-wrap: wrap; + } + + .card-header .btn-sm { + font-size: 0.75rem; + padding: 0.25rem 0.5rem; + } } \ No newline at end of file diff --git a/Watcher/wwwroot/css/services-overview.css b/Watcher/wwwroot/css/services-overview.css index f2a983e..cc0779a 100644 --- a/Watcher/wwwroot/css/services-overview.css +++ b/Watcher/wwwroot/css/services-overview.css @@ -1,12 +1,115 @@ -.ServiceList { - width: 80%; +/* Container Card Styling */ +.container-card { + transition: transform 0.2s ease, box-shadow 0.2s ease; + border: 1px solid rgba(0, 0, 0, 0.125); + background: var(--color-background-secondary, #fff); } -.ServiceRow { - border-style: solid; - border-color: var(--color-text); +.container-card:hover { + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15) !important; } -.ServiceEntry { - text-decoration: none; +.container-card .card-header { + background-color: rgba(0, 0, 0, 0.03); + border-bottom: 1px solid rgba(0, 0, 0, 0.125); + padding: 0.75rem 1rem; +} + +.container-card .card-body { + padding: 1rem; +} + +/* Container Info Rows */ +.container-info { + font-size: 0.9rem; +} + +.info-row { + display: flex; + justify-content: space-between; + padding: 0.4rem 0; + border-bottom: 1px solid rgba(0, 0, 0, 0.05); +} + +.info-row:last-child { + border-bottom: none; +} + +.info-label { + color: #6c757d; + font-weight: 500; +} + +.info-value { + color: var(--color-text, #212529); + word-break: break-all; +} + +/* Action Buttons */ +.action-buttons .btn { + font-size: 0.85rem; + padding: 0.4rem 0.6rem; +} + +/* Metrics Panel */ +.metrics-panel { + max-height: 0; + overflow: hidden; + transition: max-height 0.3s ease-out; +} + +.metrics-panel.show { + max-height: 500px; + transition: max-height 0.4s ease-in; +} + +.metrics-content { + background-color: #f8f9fa !important; + border: 1px solid #dee2e6; +} + +.metric-item { + margin-bottom: 0.5rem; +} + +.metric-item:last-child { + margin-bottom: 0; +} + +.progress { + background-color: rgba(0, 0, 0, 0.1); +} + +/* Toggle Button */ +.toggle-metrics { + transition: all 0.2s ease; +} + +.toggle-metrics:hover { + transform: scale(1.02); +} + +/* Responsive Adjustments */ +@media (max-width: 768px) { + .action-buttons { + flex-direction: column; + } + + .action-buttons .btn { + width: 100%; + } +} + +/* Badge Styling */ +.badge { + font-size: 0.75rem; + padding: 0.35em 0.65em; +} + +/* Server Group Header */ +h5.text-muted { + font-weight: 600; + border-bottom: 2px solid #dee2e6; + padding-bottom: 0.5rem; } \ No newline at end of file