Merge pull request #407 from Moonlight-Panel/v2_ImprovedAdminPage

Improved admin page with extendable columns and components via plugin system
This commit is contained in:
Masu Baumgartner 2024-05-18 22:15:06 +02:00 committed by GitHub
commit 2950034a30
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 140 additions and 26 deletions

View file

@ -7,6 +7,7 @@ using MoonCoreUI.Services;
using Moonlight.Core.Configuration; using Moonlight.Core.Configuration;
using Moonlight.Core.Database; using Moonlight.Core.Database;
using Moonlight.Core.Database.Entities; using Moonlight.Core.Database.Entities;
using Moonlight.Core.Implementations.AdminColumns;
using Moonlight.Core.Implementations.Diagnose; using Moonlight.Core.Implementations.Diagnose;
using Moonlight.Core.Interfaces; using Moonlight.Core.Interfaces;
using Moonlight.Core.Models; using Moonlight.Core.Models;
@ -15,6 +16,7 @@ using Moonlight.Core.Models.Abstractions.Feature;
using Moonlight.Core.Models.Enums; using Moonlight.Core.Models.Enums;
using Moonlight.Core.Repositories; using Moonlight.Core.Repositories;
using Moonlight.Core.Services; using Moonlight.Core.Services;
using Moonlight.Core.UI.Components.Cards;
namespace Moonlight.Core; namespace Moonlight.Core;
@ -155,6 +157,9 @@ public class CoreFeature : MoonlightFeature
await pluginService.RegisterImplementation<IDiagnoseAction>(new FeatureDiagnoseAction()); await pluginService.RegisterImplementation<IDiagnoseAction>(new FeatureDiagnoseAction());
await pluginService.RegisterImplementation<IDiagnoseAction>(new LogDiagnoseAction()); await pluginService.RegisterImplementation<IDiagnoseAction>(new LogDiagnoseAction());
//Admin Page
await pluginService.RegisterImplementation<IAdminDashboardColumn>(new UserCount());
// Startup job services // Startup job services
var startupJobService = app.Services.GetRequiredService<StartupJobService>(); var startupJobService = app.Services.GetRequiredService<StartupJobService>();

View file

@ -0,0 +1,16 @@
using Microsoft.AspNetCore.Components;
using MoonCoreUI.Helpers;
using Moonlight.Core.Interfaces;
using Moonlight.Core.UI.Components.Cards;
namespace Moonlight.Core.Implementations.AdminColumns;
public class UserCount : IAdminDashboardColumn
{
public Task<RenderFragment> Get()
{
var res = ComponentHelper.FromType<AdminUserCard>();
return Task.FromResult(res);
}
}

View file

@ -0,0 +1,8 @@
using Microsoft.AspNetCore.Components;
namespace Moonlight.Core.Interfaces;
public interface IAdminDashboardColumn
{
public Task<RenderFragment> Get();
}

View file

@ -0,0 +1,8 @@
using Microsoft.AspNetCore.Components;
namespace Moonlight.Core.Interfaces;
public interface IAdminDashboardComponent
{
public Task<RenderFragment> Get();
}

View file

@ -1,4 +1,9 @@
using System.Reflection; using System.ComponentModel;
using System.Reflection;
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Options;
using Moonlight.Core.UI.Components.Partials;
using IComponent = Microsoft.AspNetCore.Components.IComponent;
namespace Moonlight.Core.Models.Abstractions.Feature; namespace Moonlight.Core.Models.Abstractions.Feature;
@ -6,7 +11,9 @@ public class UiInitContext
{ {
public List<SidebarItem> SidebarItems { get; set; } = new(); public List<SidebarItem> SidebarItems { get; set; } = new();
public List<Assembly> RouteAssemblies { get; set; } = new(); public List<Assembly> RouteAssemblies { get; set; } = new();
public List<AdminComponent> AdminPageComponents { get; set; } = new();
public List<AdminComponent> AdminPageCards { get; set; } = new();
public void EnablePages<T>() public void EnablePages<T>()
{ {
var assembly = typeof(T).Assembly; var assembly = typeof(T).Assembly;

View file

@ -0,0 +1,19 @@
@using MoonCore.Abstractions
@using Moonlight.Core.Database.Entities
@inject Repository<User> UserRepository
<a href="/admin/servers">
<StatCard Value="@UserCount.ToString()" Description="Users" Icon="bxs-group"></StatCard>
</a>
@code {
private int UserCount;
protected override async Task OnInitializedAsync()
{
UserCount = UserRepository.Get().Count();
}
}

View file

@ -1,43 +1,54 @@
@page "/admin" @page "/admin"
@using MoonCore.Abstractions @using MoonCore.Abstractions
@using Moonlight.Core.Database.Entities @using Moonlight.Core.Database.Entities
@using Moonlight.Core.Interfaces
@using Moonlight.Core.Services
@using Moonlight.Features.Servers.Entities @using Moonlight.Features.Servers.Entities
@inject Repository<Server> ServerRepository @inject PluginService PluginService
@inject Repository<User> UserRepository
@attribute [RequirePermission(999)] @attribute [RequirePermission(999)]
<LazyLoader Load="Load"> <LazyLoader Load="Load">
<div class="row g-4"> <div class="row mb-8">
<div class="col-12 col-lg-6 col-xl"> @foreach(var column in Columns)
<a href="/admin/servers"> {
<StatCard Value="@UserCount.ToString()" Description="Users" Icon="bxs-group"> <div class="col-12 col-lg-6 col-xl">
</StatCard> @column
</a> </div>
</div> }
<div class="col-12 col-lg-6 col-xl">
<a href="/admin/servers">
<StatCard Value="@ServerCount.ToString()" Description="Servers" Icon="bxs-server">
</StatCard>
</a>
</div>
</div> </div>
@foreach (var component in Components)
{
<div class="mb-4">
@component
</div>
}
</LazyLoader> </LazyLoader>
@* This is just the start of this admin page, there will still be added more during the developement process *@
@code { @code {
private int ServerCount;
private int UserCount;
private List<RenderFragment> Columns = new();
private List<RenderFragment> Components = new();
private async Task Load(LazyLoader arg) private async Task Load(LazyLoader arg)
{ {
await Task.Run(() => await arg.SetText("Loading statistics...");
{
arg.SetText("Loading Information..."); var componentImplementations = await PluginService.GetImplementations<IAdminDashboardComponent>();
ServerCount = ServerRepository.Get().Count();
UserCount = UserRepository.Get().Count(); foreach (var implementation in componentImplementations)
}); {
Components.Add(await implementation.Get());
}
var columnImplementations = await PluginService.GetImplementations<IAdminDashboardColumn>();
foreach (var implementation in columnImplementations)
{
Columns.Add(await implementation.Get());
}
} }
} }

View file

@ -0,0 +1,16 @@
using Microsoft.AspNetCore.Components;
using MoonCoreUI.Helpers;
using Moonlight.Core.Interfaces;
using Moonlight.Features.Servers.UI.Components.Cards;
namespace Moonlight.Features.Servers.Implementations.AdminColumns;
public class ServerCount : IAdminDashboardColumn
{
public Task<RenderFragment> Get()
{
var res = ComponentHelper.FromType<AdminServersCard>();
return Task.FromResult(res);
}
}

View file

@ -7,9 +7,11 @@ using Moonlight.Core.Services;
using Moonlight.Features.Servers.Actions; using Moonlight.Features.Servers.Actions;
using Moonlight.Features.Servers.Configuration; using Moonlight.Features.Servers.Configuration;
using Moonlight.Features.Servers.Http.Middleware; using Moonlight.Features.Servers.Http.Middleware;
using Moonlight.Features.Servers.Implementations.AdminColumns;
using Moonlight.Features.Servers.Implementations.Diagnose; using Moonlight.Features.Servers.Implementations.Diagnose;
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;
namespace Moonlight.Features.Servers; namespace Moonlight.Features.Servers;
@ -95,6 +97,8 @@ public class ServersFeature : MoonlightFeature
var pluginService = app.Services.GetRequiredService<PluginService>(); var pluginService = app.Services.GetRequiredService<PluginService>();
await pluginService.RegisterImplementation<IDiagnoseAction>(new NodesDiagnoseAction()); await pluginService.RegisterImplementation<IDiagnoseAction>(new NodesDiagnoseAction());
await pluginService.RegisterImplementation<IAdminDashboardColumn>(new ServerCount());
} }
public override Task OnUiInitialized(UiInitContext context) public override Task OnUiInitialized(UiInitContext context)

View file

@ -0,0 +1,19 @@
@using MoonCore.Abstractions
@using Moonlight.Features.Servers.Entities
@inject Repository<Server> ServerRepository
<a href="/admin/servers">
<StatCard Value="@ServerCount.ToString()" Description="Servers" Icon="bxs-server"></StatCard>
</a>
@code {
private int ServerCount;
protected override async Task OnInitializedAsync()
{
ServerCount = ServerRepository.Get().Count();
}
}

View file

@ -53,6 +53,7 @@
<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\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\" />