diff --git a/Moonlight/Core/UI/Components/ColoredBar.razor b/Moonlight/Core/UI/Components/ColoredBar.razor
new file mode 100644
index 0000000..88ffbbe
--- /dev/null
+++ b/Moonlight/Core/UI/Components/ColoredBar.razor
@@ -0,0 +1,26 @@
+@{
+ var color = "primary";
+
+ if (Value >= PrimaryEnd && Value < DangerStart)
+ color = "warning";
+
+ if (Value >= DangerStart)
+ color = "danger";
+
+ var percent = Math.Round(Value);
+ var percentText = Math.Round(Value, 2) + "%";
+}
+
+
+
+@code
+{
+ [Parameter]
+ public double Value { get; set; }
+
+ [Parameter] public double PrimaryEnd { get; set; } = 60;
+ [Parameter] public double DangerStart { get; set; } = 80;
+}
diff --git a/Moonlight/Features/Servers/UI/Views/Admin/Nodes/Index.razor b/Moonlight/Features/Servers/UI/Views/Admin/Nodes/Index.razor
index c951ffb..0ca4b9d 100644
--- a/Moonlight/Features/Servers/UI/Views/Admin/Nodes/Index.razor
+++ b/Moonlight/Features/Servers/UI/Views/Admin/Nodes/Index.razor
@@ -4,52 +4,153 @@
@using Moonlight.Features.Servers.UI.Components
@using Moonlight.Features.Servers.Entities
@using MoonCore.Abstractions
-@using BlazorTable
@using Microsoft.EntityFrameworkCore
@using MoonCore.Exceptions
@using MoonCore.Helpers
@using System.Text.RegularExpressions;
+@using Moonlight.Features.Servers.Api.Resources
+@using Moonlight.Features.Servers.Services
@inject Repository ServerRepository
@inject Repository NodeRepository
+@inject NodeService NodeService
+@inject IServiceProvider ServiceProvider
+
+@implements IDisposable
@attribute [RequirePermission(5001)]
-
-
-
-
-
-
-
-
-
-
-
-
- N/A
-
-
-
-
-
- Add a new node in order to get started. Need help? Check out our documentation
-
-
-
+
+
+
+
+
+
+ @context!.Name
+
+
+
+
+
+ @if (NodeStats.ContainsKey(context!.Id))
+ {
+ if (NodeStats[context.Id] == null)
+ {
+ Offline
+ }
+ else
+ {
+ Online
+ }
+ }
+ else
+ {
+ N/A
+ }
+
+
+
+
+ @if (NodeStats.ContainsKey(context!.Id) && NodeStats[context.Id] != null)
+ {
+ var cores = NodeStats[context!.Id]!.Hardware.Cores;
+ var percent = Math.Round(cores.Average(x => x.Usage), 2);
+
+
+ }
+ else
+ {
+ N/A
+ }
+
+
+
+
+ @if (NodeStats.ContainsKey(context!.Id) && NodeStats[context.Id] != null)
+ {
+ var memory = NodeStats[context!.Id]!.Hardware.Memory;
+ var percent = Math.Round(((float)memory.Total - memory.Available - memory.Free) / memory.Total * 100, 2);
+
+
+ }
+ else
+ {
+ N/A
+ }
+
+
+
+
+ @if (NodeStats.ContainsKey(context!.Id) && NodeStats[context.Id] != null)
+ {
+ var disk = NodeStats[context!.Id]!.Hardware.Disk;
+ var percent = Math.Round((float)disk.Free / disk.Total * 100, 2);
+
+
+ }
+ else
+ {
+ N/A
+ }
+
+
+
+
+
+ Add a new node in order to get started. Need help? Check out our documentation
+
+
+
+
@code
{
- private ServerNode[] Load(Repository repository)
+ private Timer UpdateTimer;
+ private Dictionary NodeStats = new();
+
+ private Task Load(LazyLoader lazyLoader)
+ {
+ UpdateTimer = new(async _ =>
+ {
+ NodeStats.Clear();
+
+ using var scope = ServiceProvider.CreateScope();
+ var nodeRepo = scope.ServiceProvider.GetRequiredService>();
+ var nodes = nodeRepo.Get().ToArray();
+
+ foreach (var node in nodes)
+ {
+ try
+ {
+ var status = await NodeService.GetStatus(node);
+
+ NodeStats[node.Id] = status;
+ }
+ catch (Exception e)
+ {
+ Logger.Warn($"Unable to fetch system status for node '{node.Name}'");
+ Logger.Warn(e);
+
+ NodeStats[node.Id] = null;
+ }
+
+ await InvokeAsync(StateHasChanged);
+ }
+ }, null, TimeSpan.Zero, TimeSpan.FromSeconds(1));
+
+ return Task.CompletedTask;
+ }
+
+ private ServerNode[] LoadData(Repository repository)
{
return repository
.Get()
@@ -106,4 +207,9 @@
return false;
}
+
+ public void Dispose()
+ {
+ UpdateTimer?.Dispose();
+ }
}
\ No newline at end of file