Implemented server list and power state display

This commit is contained in:
2024-12-28 17:24:38 +01:00
parent 92e9f42fbc
commit 87e4172149
11 changed files with 514 additions and 2 deletions

View File

@@ -9,6 +9,13 @@ public class SidebarImplementation : ISidebarItemProvider
{
return
[
new SidebarItem()
{
Name = "Servers",
Path = "/servers",
Icon = "icon-server",
Priority = 4
},
new SidebarItem()
{
Name = "Servers",

View File

@@ -0,0 +1,174 @@
@using MoonCore.Helpers
@using MoonlightServers.Shared.Enums
@using MoonlightServers.Shared.Http.Responses.Users.Servers
@inject HttpApiClient ApiClient
@inject ILogger<ServerCard> Logger
@{
var gradient = "from-gray-600/20";
var border = "border-gray-600";
if (IsLoaded && !IsFailed)
{
gradient = Status.PowerState switch
{
ServerPowerState.Installing => "from-primary-600/20",
ServerPowerState.Offline => "from-danger-600/20",
ServerPowerState.Starting => "from-warning-600/20",
ServerPowerState.Stopping => "from-warning-600/20",
ServerPowerState.Online => "from-success-600/20",
_ => "from-gray-600/20"
};
border = Status.PowerState switch
{
ServerPowerState.Installing => "border-primary-600",
ServerPowerState.Offline => "border-danger-600",
ServerPowerState.Starting => "border-warning-600",
ServerPowerState.Stopping => "border-warning-600",
ServerPowerState.Online => "border-success-600",
_ => "border-gray-600"
};
}
}
<a href="/servers/@Server.Id"
class="w-full bg-gradient-to-r @gradient to-gray-750/65 to-25% px-5 py-3.5 rounded-xl border-l-8 @border">
<div class="grid grid-cols-6">
<div class="flex items-center col-span-6 sm:col-span-2 2xl:col-span-1">
<div class="bg-gray-900 bg-opacity-45 py-1 px-2 rounded-lg flex items-center">
<i class="icon-server me-3 align-middle"></i>
<div class="text-lg align-middle">
@Server.Name
</div>
</div>
</div>
<div class="hidden sm:flex items-center justify-end gap-x-3 sm:col-span-4 2xl:col-span-3">
@if (
IsLoaded &&
!IsFailed &&
Status.PowerState is ServerPowerState.Starting or ServerPowerState.Stopping or ServerPowerState.Online
)
{
<div class="bg-gray-900 bg-opacity-45 py-1 px-2 rounded-lg flex flex-row">
<div>
<i class="icon-cpu"></i>
</div>
<div class="ms-3">56,8%</div>
</div>
<div class="bg-gray-900 bg-opacity-45 py-1 px-2 rounded-lg flex flex-row">
<div>
<i class="icon-memory-stick"></i>
</div>
<div class="ms-3">4,2 GB / 8 GB</div>
</div>
<div class="bg-gray-900 bg-opacity-45 py-1 px-2 rounded-lg flex flex-row">
<div>
<i class="icon-hard-drive"></i>
</div>
<div class="ms-3">53 GB / 100GB</div>
</div>
}
else
{
if (!IsLoaded)
{
<div class="bg-gray-900 bg-opacity-45 py-1 px-2 rounded-lg flex flex-row text-gray-700">
<div>
<i class="icon-loader"></i>
</div>
<div class="ms-3">Loading</div>
</div>
}
else if (IsFailed)
{
<div class="bg-gray-900 bg-opacity-45 py-1 px-2 rounded-lg flex flex-row text-danger-500">
<div>
<i class="icon-cable"></i>
</div>
<div class="ms-3">Unreachable</div>
</div>
}
else if (IsLoaded && !IsFailed && Status.PowerState is ServerPowerState.Offline)
{
<div class="bg-gray-900 bg-opacity-45 py-1 px-2 rounded-lg flex flex-row text-danger-500">
<div>
<i class="icon-power-off"></i>
</div>
<div class="ms-3">Offline</div>
</div>
}
else if (IsLoaded && !IsFailed && Status.PowerState is ServerPowerState.Installing)
{
<div class="bg-gray-900 bg-opacity-45 py-1 px-2 rounded-lg flex flex-row text-primary-500">
<div>
<i class="icon-hammer"></i>
</div>
<div class="ms-3">Installing</div>
</div>
}
}
</div>
<div class="hidden 2xl:flex items-center justify-end gap-x-3 2xl:col-span-2">
<div class="bg-gray-900 bg-opacity-45 py-1 px-2 rounded-lg flex flex-row">
<div>
<i class="icon-sparkles"></i>
</div>
<div class="ms-3">@Server.StarName</div>
</div>
<div class="bg-gray-900 bg-opacity-45 py-1 px-2 rounded-lg flex flex-row">
<div>
<i class="icon-database"></i>
</div>
<div class="ms-3">@Server.NodeName</div>
</div>
</div>
</div>
</a>
@code
{
[Parameter] public ServerDetailResponse Server { get; set; }
private ServerStatusResponse Status;
private bool IsFailed = false;
private bool IsLoaded = false;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (!firstRender)
return;
try
{
Status = await ApiClient.GetJson<ServerStatusResponse>(
$"api/servers/{Server.Id}/status"
);
}
catch (Exception e)
{
IsFailed = true;
Logger.LogWarning("Unable to fetch status from server {id}: {e}", Server.Id, e);
}
IsLoaded = true;
await InvokeAsync(StateHasChanged);
}
}

View File

@@ -0,0 +1,125 @@
@using MoonlightServers.Shared.Http.Responses.Users.Servers
@{
var gradient = Status switch
{
4 => "from-primary-600/20",
3 => "from-danger-600/20",
2 => "from-warning-600/20",
1 => "from-success-600/20",
_ => "from-gray-600/20"
};
var border = Status switch
{
4 => "border-primary-600",
3 => "border-danger-600",
2 => "border-warning-600",
1 => "border-success-600",
_ => "border-gray-600"
};
}
<a href="/servers/@Server.Id" class="w-full bg-gradient-to-r @gradient to-gray-750/65 to-25% px-5 py-3.5 rounded-xl border-l-8 @border">
<div class="grid grid-cols-6">
<div class="flex items-center col-span-6 sm:col-span-2 2xl:col-span-1">
<div class="bg-gray-900 bg-opacity-45 py-1 px-2 rounded-lg flex items-center">
<i class="icon-server me-3 align-middle"></i>
<div class="text-lg align-middle">
@Server.Name
</div>
</div>
</div>
<div class="hidden sm:flex items-center justify-end gap-x-3 sm:col-span-4 2xl:col-span-3">
@if (Status >= 1 && Status <= 2)
{
<div class="bg-gray-900 bg-opacity-45 py-1 px-2 rounded-lg flex flex-row">
<div>
<i class="icon-cpu"></i>
</div>
<div class="ms-3">56,8%</div>
</div>
<div class="bg-gray-900 bg-opacity-45 py-1 px-2 rounded-lg flex flex-row">
<div>
<i class="icon-memory-stick"></i>
</div>
<div class="ms-3">4,2 GB / 8 GB</div>
</div>
<div class="bg-gray-900 bg-opacity-45 py-1 px-2 rounded-lg flex flex-row">
<div>
<i class="icon-hard-drive"></i>
</div>
<div class="ms-3">53 GB / 100GB</div>
</div>
}
else
{
if (Status == 0)
{
<div class="bg-gray-900 bg-opacity-45 py-1 px-2 rounded-lg flex flex-row text-gray-700">
<div>
<i class="icon-loader"></i>
</div>
<div class="ms-3">Loading</div>
</div>
}
else if (Status == 3)
{
<div class="bg-gray-900 bg-opacity-45 py-1 px-2 rounded-lg flex flex-row text-danger-500">
<div>
<i class="icon-power-off"></i>
</div>
<div class="ms-3">Offline</div>
</div>
}
else if (Status == 4)
{
<div class="bg-gray-900 bg-opacity-45 py-1 px-2 rounded-lg flex flex-row text-primary-500">
<div>
<i class="icon-hammer"></i>
</div>
<div class="ms-3">Installing</div>
</div>
}
}
</div>
<div class="hidden 2xl:flex items-center justify-end gap-x-3 2xl:col-span-2">
<div class="bg-gray-900 bg-opacity-45 py-1 px-2 rounded-lg flex flex-row">
<div>
<i class="icon-sparkles"></i>
</div>
<div class="ms-3">@Server.StarName</div>
</div>
<div class="bg-gray-900 bg-opacity-45 py-1 px-2 rounded-lg flex flex-row">
<div>
<i class="icon-database"></i>
</div>
<div class="ms-3">@Server.NodeName</div>
</div>
</div>
</div>
</a>
@code
{
[Parameter]
public ServerDetailResponse Server { get; set; }
[Parameter]
public int Status { get; set; }
}

View File

@@ -0,0 +1,32 @@
@page "/servers"
@using MoonCore.Helpers
@using MoonlightServers.Frontend.UI.Components.Servers
@using MoonCore.Blazor.Tailwind.Components
@using MoonCore.Models
@using MoonlightServers.Shared.Http.Responses.Users.Servers
@inject HttpApiClient ApiClient
<LazyLoader Load="Load">
<div class="flex flex-col gap-y-5">
@foreach (var server in Servers)
{
<ServerCard Server="server" />
}
</div>
</LazyLoader>
@code
{
private ServerDetailResponse[] Servers;
private async Task Load(LazyLoader lazyLoader)
{
Servers = await PagedData<ServerDetailResponse>.All(async (page, pageSize) =>
await ApiClient.GetJson<PagedData<ServerDetailResponse>>(
$"api/servers/list?page={page}&pageSize={pageSize}"
)
);
}
}