@page "/admin/servers/nodes" @using Microsoft.Extensions.Logging @using MoonCore.Blazor.FlyonUi.Alerts @using MoonCore.Blazor.FlyonUi.Common @using MoonCore.Blazor.FlyonUi.Toasts @using MoonCore.Helpers @using MoonlightServers.Shared.Http.Responses.Admin.Nodes @using MoonlightServers.Frontend.Services @using MoonlightServers.Shared.Http.Responses.Admin.Nodes.Statistics @using MoonlightServers.Shared.Http.Responses.Admin.Nodes.Sys @using MoonCore.Blazor.FlyonUi.Components @using MoonCore.Blazor.FlyonUi.Grid @using MoonCore.Blazor.FlyonUi.Grid.Columns @using MoonCore.Common @inject HttpApiClient ApiClient @inject NodeService NodeService @inject AlertService AlertService @inject ToastService ToastService @inject ILogger Logger @attribute [Authorize(Policy = "permissions:admin.servers.nodes.get")]
Create
@context.Name @{ var isFetched = StatusResponses.TryGetValue(context.Id, out var data); } @if (isFetched) { if (data == null) {
API Error
} else { if (data.RoundtripSuccess) {
Online (@(data.Version))
} else {
Error Details
} } } else {
Loading
}
@{ var isFetched = Statistics.TryGetValue(context.Id, out var data); } @if (isFetched) { if (data == null) {
API Error
} else {
@(Math.Round(data.Cpu.Usage))%
@(Math.Round((data.Memory.Total - data.Memory.Free - data.Memory.Cached) / (double)data.Memory.Total * 100))%
} } else {
Loading
}
@code { private DataGrid Grid; private Dictionary StatusResponses = new(); private Dictionary Statistics = new(); private ItemSource ItemSource => ItemSourceFactory.From(LoadAsync); private async Task> LoadAsync(int startIndex, int count) { var query = $"?startIndex={startIndex}&count={count}"; var countedData = await ApiClient.GetJson>($"api/admin/servers/nodes{query}"); Statistics.Clear(); StatusResponses.Clear(); Task.Run(async () => { foreach (var item in countedData.Items) { try { Statistics[item.Id] = await NodeService.GetStatisticsAsync(item.Id); } catch (Exception e) { Logger.LogWarning( "An error occured while fetching statistics for node {nodeId}: {e}", item.Id, e ); Statistics[item.Id] = null; } await InvokeAsync(StateHasChanged); try { StatusResponses[item.Id] = await NodeService.GetSystemStatusAsync(item.Id); } catch (Exception e) { Logger.LogWarning( "An error occured while fetching status for node {nodeId}: {e}", item.Id, e ); StatusResponses[item.Id] = null; } await InvokeAsync(StateHasChanged); } }); return countedData; } private async Task DeleteAsync(NodeResponse response) { await AlertService.ConfirmDangerAsync( "Node deletion", $"Do you really want to delete the node '{response.Name}'", async () => { await ApiClient.Delete($"api/admin/servers/nodes/{response.Id}"); await ToastService.SuccessAsync("Successfully deleted node"); await Grid.RefreshAsync(); } ); } private async Task ShowErrorDetailsAsync(int id) { var data = StatusResponses.GetValueOrDefault(id); if (data == null) return; var message = $"Failed after {Math.Round(data.RoundtripTime.TotalSeconds, 2)} seconds: " + (data.RoundtripRemoteFailure ? "(Failed at node)" : "(Failed at api server)") + $" {data.RoundtripError}"; await AlertService.ErrorAsync("Node error details", message); } }