Merge pull request #397 from Moonlight-Panel/v2_AddDetailsInNodeList
Added more details into the node list (like cpu, memory and disk)
This commit is contained in:
commit
e1fbf601f3
2 changed files with 163 additions and 31 deletions
26
Moonlight/Core/UI/Components/ColoredBar.razor
Normal file
26
Moonlight/Core/UI/Components/ColoredBar.razor
Normal file
|
@ -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) + "%";
|
||||
}
|
||||
|
||||
<div class="progress">
|
||||
<div class="progress-bar bg-@(color) fs-4" role="progressbar" aria-valuenow="@(percent)" aria-valuemin="0" aria-valuemax="100" style="width: @(percent)%">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@code
|
||||
{
|
||||
[Parameter]
|
||||
public double Value { get; set; }
|
||||
|
||||
[Parameter] public double PrimaryEnd { get; set; } = 60;
|
||||
[Parameter] public double DangerStart { get; set; } = 80;
|
||||
}
|
|
@ -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<Server> ServerRepository
|
||||
@inject Repository<ServerNode> NodeRepository
|
||||
@inject NodeService NodeService
|
||||
@inject IServiceProvider ServiceProvider
|
||||
|
||||
@implements IDisposable
|
||||
|
||||
@attribute [RequirePermission(5001)]
|
||||
|
||||
<AdminServersNavigation Index="1"/>
|
||||
|
||||
<AutoCrud TItem="ServerNode"
|
||||
TCreateForm="CreateNodeForm"
|
||||
TUpdateForm="UpdateNodeForm"
|
||||
Title=""
|
||||
Load="Load"
|
||||
ValidateAdd="ValidateAdd"
|
||||
ValidateUpdate="ValidateUpdate"
|
||||
ValidateDelete="ValidateDelete">
|
||||
<Actions>
|
||||
<a href="/admin/servers/nodes/view/@(context.Id)" class="btn btn-icon btn-info">
|
||||
<i class="bx bx-sm bx-wrench"></i>
|
||||
</a>
|
||||
</Actions>
|
||||
<View>
|
||||
<CrudColumn TItem="ServerNode" Field="@(x => x.Id)" Title="Id"/>
|
||||
<CrudColumn TItem="ServerNode" Field="@(x => x.Name)" Title="Name"/>
|
||||
<CrudColumn TItem="ServerNode" Field="@(x => x.Fqdn)" Title="Fqdn"/>
|
||||
<CrudColumn TItem="ServerNode" Field="@(x => x.Id)" Title="Status">
|
||||
<Template>
|
||||
<span class="text-muted">N/A</span>
|
||||
</Template>
|
||||
</CrudColumn>
|
||||
</View>
|
||||
<NoItemsView>
|
||||
<IconAlert Title="No nodes found" Color="primary" Icon="bx-search-alt">
|
||||
Add a new node in order to get started. Need help? Check out our <a href="https://docs.moonlightpanel.xyz">documentation</a>
|
||||
</IconAlert>
|
||||
</NoItemsView>
|
||||
</AutoCrud>
|
||||
<LazyLoader Load="Load">
|
||||
<AutoCrud TItem="ServerNode"
|
||||
TCreateForm="CreateNodeForm"
|
||||
TUpdateForm="UpdateNodeForm"
|
||||
Title=""
|
||||
Load="LoadData"
|
||||
ValidateAdd="ValidateAdd"
|
||||
ValidateUpdate="ValidateUpdate"
|
||||
ValidateDelete="ValidateDelete">
|
||||
<View>
|
||||
<CrudColumn TItem="ServerNode" Field="@(x => x.Id)" Title="Id"/>
|
||||
<CrudColumn TItem="ServerNode" Field="@(x => x.Name)" Title="Name">
|
||||
<Template>
|
||||
<a href="/admin/servers/nodes/view/@(context!.Id)">@context!.Name</a>
|
||||
</Template>
|
||||
</CrudColumn>
|
||||
<CrudColumn TItem="ServerNode" Field="@(x => x.Fqdn)" Title="Fqdn"/>
|
||||
<CrudColumn TItem="ServerNode" Title="Status">
|
||||
<Template>
|
||||
@if (NodeStats.ContainsKey(context!.Id))
|
||||
{
|
||||
if (NodeStats[context.Id] == null)
|
||||
{
|
||||
<span class="text-danger">Offline</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="text-success">Online</span>
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="text-muted">N/A</span>
|
||||
}
|
||||
</Template>
|
||||
</CrudColumn>
|
||||
<CrudColumn TItem="ServerNode" Title="CPU">
|
||||
<Template>
|
||||
@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);
|
||||
|
||||
<ColoredBar Value="percent"/>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="text-muted">N/A</span>
|
||||
}
|
||||
</Template>
|
||||
</CrudColumn>
|
||||
<CrudColumn TItem="ServerNode" Title="Memory">
|
||||
<Template>
|
||||
@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);
|
||||
|
||||
<ColoredBar Value="percent"/>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="text-muted">N/A</span>
|
||||
}
|
||||
</Template>
|
||||
</CrudColumn>
|
||||
<CrudColumn TItem="ServerNode" Title="Disk">
|
||||
<Template>
|
||||
@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);
|
||||
|
||||
<ColoredBar Value="percent"/>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="text-muted">N/A</span>
|
||||
}
|
||||
</Template>
|
||||
</CrudColumn>
|
||||
</View>
|
||||
<NoItemsView>
|
||||
<IconAlert Title="No nodes found" Color="primary" Icon="bx-search-alt">
|
||||
Add a new node in order to get started. Need help? Check out our <a href="https://docs.moonlightpanel.xyz">documentation</a>
|
||||
</IconAlert>
|
||||
</NoItemsView>
|
||||
</AutoCrud>
|
||||
</LazyLoader>
|
||||
|
||||
@code
|
||||
{
|
||||
private ServerNode[] Load(Repository<ServerNode> repository)
|
||||
private Timer UpdateTimer;
|
||||
private Dictionary<int, SystemStatus?> NodeStats = new();
|
||||
|
||||
private Task Load(LazyLoader lazyLoader)
|
||||
{
|
||||
UpdateTimer = new(async _ =>
|
||||
{
|
||||
NodeStats.Clear();
|
||||
|
||||
using var scope = ServiceProvider.CreateScope();
|
||||
var nodeRepo = scope.ServiceProvider.GetRequiredService<Repository<ServerNode>>();
|
||||
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<ServerNode> repository)
|
||||
{
|
||||
return repository
|
||||
.Get()
|
||||
|
@ -106,4 +207,9 @@
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
UpdateTimer?.Dispose();
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue