Merge pull request #419 from Moonlight-Panel/v2_ModularUiImprovements
V2 modular UI improvements
This commit is contained in:
@@ -7,4 +7,6 @@ public class UiComponent
|
|||||||
public required RenderFragment Component { get; set; }
|
public required RenderFragment Component { get; set; }
|
||||||
|
|
||||||
public int Index { get; set; } = 0;
|
public int Index { get; set; } = 0;
|
||||||
|
|
||||||
|
public int RequiredPermissionLevel { get; set; } = 0;
|
||||||
}
|
}
|
||||||
@@ -11,9 +11,9 @@
|
|||||||
|
|
||||||
private int UserCount;
|
private int UserCount;
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
{
|
{
|
||||||
|
if (firstRender)
|
||||||
UserCount = UserRepository.Get().Count();
|
UserCount = UserRepository.Get().Count();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,31 +1,34 @@
|
|||||||
@page "/admin"
|
@page "/admin"
|
||||||
@using MoonCore.Abstractions
|
|
||||||
@using Moonlight.Core.Database.Entities
|
|
||||||
@using Moonlight.Core.Interfaces
|
|
||||||
@using Moonlight.Core.Interfaces.Ui.Admin
|
@using Moonlight.Core.Interfaces.Ui.Admin
|
||||||
@using Moonlight.Core.Models.Abstractions
|
@using Moonlight.Core.Models.Abstractions
|
||||||
@using Moonlight.Core.Services
|
@using Moonlight.Core.Services
|
||||||
@using Moonlight.Features.Servers.Entities
|
|
||||||
|
|
||||||
@inject PluginService PluginService
|
@inject PluginService PluginService
|
||||||
|
@inject IdentityService IdentityService
|
||||||
|
|
||||||
@attribute [RequirePermission(999)]
|
@attribute [RequirePermission(999)]
|
||||||
|
|
||||||
<LazyLoader Load="Load">
|
<LazyLoader Load="Load">
|
||||||
<div class="row mb-8">
|
<div class="row mb-8 gap-4">
|
||||||
@foreach(var column in Columns.OrderBy(x => x.Index))
|
@foreach (var column in Columns.OrderBy(x => x.Index))
|
||||||
|
{
|
||||||
|
if (column.RequiredPermissionLevel <= IdentityService.CurrentUser.Permissions)
|
||||||
{
|
{
|
||||||
<div class="col-12 col-lg-6 col-xl">
|
<div class="col-12 col-lg-6 col-xl">
|
||||||
@column.Component
|
@column.Component
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
@foreach (var component in Components.OrderBy(x => x.Index))
|
@foreach (var component in Components.OrderBy(x => x.Index))
|
||||||
|
{
|
||||||
|
if (component.RequiredPermissionLevel <= IdentityService.CurrentUser.Permissions)
|
||||||
{
|
{
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
@component.Component
|
@component.Component
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</LazyLoader>
|
</LazyLoader>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -4,14 +4,18 @@
|
|||||||
@using Moonlight.Core.Services
|
@using Moonlight.Core.Services
|
||||||
|
|
||||||
@inject PluginService PluginService
|
@inject PluginService PluginService
|
||||||
|
@inject IdentityService IdentityService
|
||||||
|
|
||||||
<LazyLoader Load="Load">
|
<LazyLoader Load="Load">
|
||||||
@foreach (var component in Components.OrderBy(x => x.Index))
|
@foreach (var component in Components.OrderBy(x => x.Index))
|
||||||
|
{
|
||||||
|
if (component.RequiredPermissionLevel <= IdentityService.CurrentUser.Permissions)
|
||||||
{
|
{
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
@component.Component
|
@component.Component
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</LazyLoader>
|
</LazyLoader>
|
||||||
|
|
||||||
@code
|
@code
|
||||||
|
|||||||
@@ -11,7 +11,8 @@ public class ServerCount : IAdminDashboardColumn
|
|||||||
{
|
{
|
||||||
var res = new UiComponent()
|
var res = new UiComponent()
|
||||||
{
|
{
|
||||||
Component = ComponentHelper.FromType<AdminServersCard>()
|
Component = ComponentHelper.FromType<AdminServersCard>(),
|
||||||
|
RequiredPermissionLevel = 5000
|
||||||
};
|
};
|
||||||
|
|
||||||
return Task.FromResult(res);
|
return Task.FromResult(res);
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
using MoonCoreUI.Helpers;
|
||||||
|
using Moonlight.Core.Interfaces.Ui.Admin;
|
||||||
|
using Moonlight.Core.Models.Abstractions;
|
||||||
|
using Moonlight.Features.Servers.UI.Components.Cards;
|
||||||
|
|
||||||
|
namespace Moonlight.Features.Servers.Implementations.UI.Admin.AdminComponents;
|
||||||
|
|
||||||
|
public class NodeOverview : IAdminDashboardComponent
|
||||||
|
{
|
||||||
|
public Task<UiComponent> Get()
|
||||||
|
{
|
||||||
|
var res = new UiComponent()
|
||||||
|
{
|
||||||
|
Component = ComponentHelper.FromType<AdminNodesComponent>(),
|
||||||
|
RequiredPermissionLevel = 5001
|
||||||
|
};
|
||||||
|
|
||||||
|
return Task.FromResult(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
using MoonCoreUI.Helpers;
|
||||||
|
using Moonlight.Core.Interfaces.UI.User;
|
||||||
|
using Moonlight.Core.Models.Abstractions;
|
||||||
|
using Moonlight.Features.Servers.UI.Components.Cards;
|
||||||
|
|
||||||
|
namespace Moonlight.Features.Servers.Implementations.UI.UserDashboard.Components;
|
||||||
|
|
||||||
|
public class UserDashboardServerCount : IUserDashboardComponent
|
||||||
|
{
|
||||||
|
public Task<UiComponent> Get()
|
||||||
|
{
|
||||||
|
var res = new UiComponent()
|
||||||
|
{
|
||||||
|
Component = ComponentHelper.FromType<Servers.UI.Components.Cards.UserDashboardServerCount>(),
|
||||||
|
Index = int.MinValue + 100
|
||||||
|
};
|
||||||
|
|
||||||
|
return Task.FromResult(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ using MoonCore.Services;
|
|||||||
using Moonlight.Core.Configuration;
|
using Moonlight.Core.Configuration;
|
||||||
using Moonlight.Core.Interfaces;
|
using Moonlight.Core.Interfaces;
|
||||||
using Moonlight.Core.Interfaces.Ui.Admin;
|
using Moonlight.Core.Interfaces.Ui.Admin;
|
||||||
|
using Moonlight.Core.Interfaces.UI.User;
|
||||||
using Moonlight.Core.Models.Abstractions.Feature;
|
using Moonlight.Core.Models.Abstractions.Feature;
|
||||||
using Moonlight.Core.Services;
|
using Moonlight.Core.Services;
|
||||||
using Moonlight.Features.Servers.Actions;
|
using Moonlight.Features.Servers.Actions;
|
||||||
@@ -10,9 +11,11 @@ using Moonlight.Features.Servers.Configuration;
|
|||||||
using Moonlight.Features.Servers.Http.Middleware;
|
using Moonlight.Features.Servers.Http.Middleware;
|
||||||
using Moonlight.Features.Servers.Implementations.Diagnose;
|
using Moonlight.Features.Servers.Implementations.Diagnose;
|
||||||
using Moonlight.Features.Servers.Implementations.UI.Admin.AdminColumns;
|
using Moonlight.Features.Servers.Implementations.UI.Admin.AdminColumns;
|
||||||
|
using Moonlight.Features.Servers.Implementations.UI.Admin.AdminComponents;
|
||||||
using Moonlight.Features.Servers.Models.Enums;
|
using Moonlight.Features.Servers.Models.Enums;
|
||||||
using Moonlight.Features.Servers.Services;
|
using Moonlight.Features.Servers.Services;
|
||||||
using Moonlight.Features.Servers.UI.Components.Cards;
|
using Moonlight.Features.Servers.UI.Components.Cards;
|
||||||
|
using UserDashboardServerCount = Moonlight.Features.Servers.Implementations.UI.UserDashboard.Components.UserDashboardServerCount;
|
||||||
|
|
||||||
namespace Moonlight.Features.Servers;
|
namespace Moonlight.Features.Servers;
|
||||||
|
|
||||||
@@ -100,6 +103,10 @@ public class ServersFeature : MoonlightFeature
|
|||||||
await pluginService.RegisterImplementation<IDiagnoseAction>(new NodesDiagnoseAction());
|
await pluginService.RegisterImplementation<IDiagnoseAction>(new NodesDiagnoseAction());
|
||||||
|
|
||||||
await pluginService.RegisterImplementation<IAdminDashboardColumn>(new ServerCount());
|
await pluginService.RegisterImplementation<IAdminDashboardColumn>(new ServerCount());
|
||||||
|
|
||||||
|
await pluginService.RegisterImplementation<IAdminDashboardComponent>(new NodeOverview());
|
||||||
|
|
||||||
|
await pluginService.RegisterImplementation<IUserDashboardComponent>(new UserDashboardServerCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Task OnUiInitialized(UiInitContext context)
|
public override Task OnUiInitialized(UiInitContext context)
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
@using MoonCore.Abstractions
|
||||||
|
@using Moonlight.Features.Servers.Api.Resources
|
||||||
|
@using Moonlight.Features.Servers.Entities
|
||||||
|
@using Moonlight.Features.Servers.Services
|
||||||
|
|
||||||
|
@inject NodeService NodeService
|
||||||
|
@inject Repository<ServerNode> NodeRepository
|
||||||
|
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<h4 class="card-title mb-4 d-flex align-items-center gap-3">
|
||||||
|
<i class="bx bx-md bx-microchip text-primary"></i>
|
||||||
|
<span>Nodes Overview</span>
|
||||||
|
</h4>
|
||||||
|
<div class="row mx-2">
|
||||||
|
<LazyLoader Load="Load">
|
||||||
|
@if (Nodes.Any())
|
||||||
|
{
|
||||||
|
foreach (var node in Nodes)
|
||||||
|
{
|
||||||
|
<div class="col-12 col-md-6 col-3">
|
||||||
|
<a href="/admin/servers/nodes/view/@node.Item1.Id">
|
||||||
|
<div class="row">
|
||||||
|
<span class="col-auto d-flex align-items-center">
|
||||||
|
<span class="badge text-bg-@(node.Item2 == null ? "danger" : "success") text-capitalize">@(node.Item2 == null ? "offline" : "online")</span>
|
||||||
|
</span>
|
||||||
|
<div class="col">
|
||||||
|
<span class="fs-5 fw-bold d-block text-white">@node.Item1.Name</span>
|
||||||
|
<span class="text-muted text-lowercase fs-6 d-block">@node.Item1.Fqdn</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<span class="text-muted fs-4">You dont have any nodes.</span>
|
||||||
|
}
|
||||||
|
</LazyLoader>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
|
||||||
|
private List<Tuple<ServerNode, SystemStatus?>> Nodes = new();
|
||||||
|
|
||||||
|
private async Task Load(LazyLoader arg)
|
||||||
|
{
|
||||||
|
foreach (var node in NodeRepository.Get().ToList())
|
||||||
|
{
|
||||||
|
SystemStatus? nodeStatus = null;
|
||||||
|
|
||||||
|
await arg.SetText("Fetching Nodes...");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
nodeStatus = await NodeService.GetStatus(node);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// Ignored
|
||||||
|
}
|
||||||
|
|
||||||
|
Nodes.Add(new Tuple<ServerNode, SystemStatus?>(node, nodeStatus));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -11,8 +11,9 @@
|
|||||||
|
|
||||||
private int ServerCount;
|
private int ServerCount;
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
{
|
{
|
||||||
|
if (firstRender)
|
||||||
ServerCount = ServerRepository.Get().Count();
|
ServerCount = ServerRepository.Get().Count();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
@using Microsoft.EntityFrameworkCore
|
||||||
|
@using MoonCore.Abstractions
|
||||||
|
@using Moonlight.Core.Services
|
||||||
|
@using Moonlight.Features.Servers.Entities
|
||||||
|
|
||||||
|
@inject Repository<Server> ServerRepository
|
||||||
|
@inject Repository<ServerNetwork> NetworkRepository
|
||||||
|
@inject IdentityService IdentityService
|
||||||
|
|
||||||
|
<div class="row mt-8">
|
||||||
|
<div class="col-12 col-md-6 mb-4">
|
||||||
|
<a href="/servers">
|
||||||
|
<StatCard Icon="bx-server" Description="Servers" Value="@ServerCount.ToString()">
|
||||||
|
</StatCard>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-12 col-md-6">
|
||||||
|
<a href="/servers/network">
|
||||||
|
<StatCard Icon="bx-network-chart" Description="Networks" Value="@NetworksCount.ToString()">
|
||||||
|
</StatCard>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
|
||||||
|
private int ServerCount = 0;
|
||||||
|
private int NetworksCount = 0;
|
||||||
|
|
||||||
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
|
{
|
||||||
|
if (firstRender)
|
||||||
|
{
|
||||||
|
ServerCount = await ServerRepository.Get().Where(x => x.Owner == IdentityService.CurrentUser).CountAsync();
|
||||||
|
NetworksCount = await NetworkRepository.Get().Where(x => x.User == IdentityService.CurrentUser).CountAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -53,7 +53,6 @@
|
|||||||
<Folder Include="Core\Database\Migrations\" />
|
<Folder Include="Core\Database\Migrations\" />
|
||||||
<Folder Include="Core\Http\Requests\" />
|
<Folder Include="Core\Http\Requests\" />
|
||||||
<Folder Include="Core\Http\Resources\" />
|
<Folder Include="Core\Http\Resources\" />
|
||||||
<Folder Include="Core\Implementations\UI\Admin\AdminComponents\" />
|
|
||||||
<Folder Include="Core\UI\Components\Forms\" />
|
<Folder Include="Core\UI\Components\Forms\" />
|
||||||
<Folder Include="Features\Dummy\Configuration\" />
|
<Folder Include="Features\Dummy\Configuration\" />
|
||||||
<Folder Include="Features\Dummy\Entities\" />
|
<Folder Include="Features\Dummy\Entities\" />
|
||||||
@@ -75,7 +74,6 @@
|
|||||||
<Folder Include="Features\FileManager\Http\Requests\" />
|
<Folder Include="Features\FileManager\Http\Requests\" />
|
||||||
<Folder Include="Features\FileManager\Http\Resources\" />
|
<Folder Include="Features\FileManager\Http\Resources\" />
|
||||||
<Folder Include="Features\Servers\Http\Resources\" />
|
<Folder Include="Features\Servers\Http\Resources\" />
|
||||||
<Folder Include="Features\Servers\Implementations\UI\Admin\" />
|
|
||||||
<Folder Include="storage\" />
|
<Folder Include="storage\" />
|
||||||
<Folder Include="Styles\" />
|
<Folder Include="Styles\" />
|
||||||
<Folder Include="wwwroot\css\" />
|
<Folder Include="wwwroot\css\" />
|
||||||
|
|||||||
Reference in New Issue
Block a user