From 3270039a6adf4064d3fd8267a90fe60a6a130ee5 Mon Sep 17 00:00:00 2001 From: Moritz <101179677+Moritz-Deiaco@users.noreply.github.com> Date: Tue, 14 May 2024 14:43:54 +0200 Subject: [PATCH 1/3] improved admin page Added the logic for a more modular admin page, where every feature can add cards and components with just a call of a function --- Moonlight/Core/CoreFeature.cs | 3 + .../Abstractions/Feature/AdminComponent.cs | 12 +++ .../Abstractions/Feature/UiInitContext.cs | 43 +++++++++- .../UI/Components/Cards/AdminUserCard.razor | 35 ++++++++ Moonlight/Core/UI/Views/Admin/Index.razor | 79 ++++++------------- Moonlight/Features/Servers/ServersFeature.cs | 3 + .../Components/Cards/AdminServersCard.razor | 35 ++++++++ 7 files changed, 155 insertions(+), 55 deletions(-) create mode 100644 Moonlight/Core/Models/Abstractions/Feature/AdminComponent.cs create mode 100644 Moonlight/Core/UI/Components/Cards/AdminUserCard.razor create mode 100644 Moonlight/Features/Servers/UI/Components/Cards/AdminServersCard.razor diff --git a/Moonlight/Core/CoreFeature.cs b/Moonlight/Core/CoreFeature.cs index df698bf..3316b1e 100644 --- a/Moonlight/Core/CoreFeature.cs +++ b/Moonlight/Core/CoreFeature.cs @@ -15,6 +15,7 @@ using Moonlight.Core.Models.Abstractions.Feature; using Moonlight.Core.Models.Enums; using Moonlight.Core.Repositories; using Moonlight.Core.Services; +using Moonlight.Core.UI.Components.Cards; namespace Moonlight.Core; @@ -207,6 +208,8 @@ public class CoreFeature : MoonlightFeature context.AddSidebarItem("Users", "bxs-group", "/admin/users", needsExactMatch: false, isAdmin: true); context.AddSidebarItem("System", "bxs-component", "/admin/sys", needsExactMatch: false, isAdmin: true); + context.AddAdminCard(index: int.MinValue); + return Task.CompletedTask; } diff --git a/Moonlight/Core/Models/Abstractions/Feature/AdminComponent.cs b/Moonlight/Core/Models/Abstractions/Feature/AdminComponent.cs new file mode 100644 index 0000000..b17e9db --- /dev/null +++ b/Moonlight/Core/Models/Abstractions/Feature/AdminComponent.cs @@ -0,0 +1,12 @@ +using Microsoft.AspNetCore.Components; + +namespace Moonlight.Core.Models.Abstractions.Feature; + +public class AdminComponent +{ + public RenderFragment Component { get; set; } + + public int Index { get; set; } + + public int RequiredPermissionLevel { get; set; } +} \ No newline at end of file diff --git a/Moonlight/Core/Models/Abstractions/Feature/UiInitContext.cs b/Moonlight/Core/Models/Abstractions/Feature/UiInitContext.cs index c63fbc1..172885e 100644 --- a/Moonlight/Core/Models/Abstractions/Feature/UiInitContext.cs +++ b/Moonlight/Core/Models/Abstractions/Feature/UiInitContext.cs @@ -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; @@ -6,7 +11,9 @@ public class UiInitContext { public List SidebarItems { get; set; } = new(); public List RouteAssemblies { get; set; } = new(); - + public List AdminPageComponents { get; set; } = new(); + public List AdminPageCards { get; set; } = new(); + public void EnablePages() { var assembly = typeof(T).Assembly; @@ -15,6 +22,38 @@ public class UiInitContext RouteAssemblies.Add(assembly); } + public void AddAdminComponent(int index = 0, int requiredPermissionLevel = 0) where T : IComponent + { + AdminPageComponents.Add( + new AdminComponent() + { + Component = builder => + { + builder.OpenComponent(0); + builder.CloseComponent(); + }, + Index = index, + RequiredPermissionLevel = requiredPermissionLevel + } + ); + } + + public void AddAdminCard(int index = 0, int requiredPermissionLevel = 0) where T : IComponent + { + AdminPageCards.Add( + new AdminComponent() + { + Component = builder => + { + builder.OpenComponent(0); + builder.CloseComponent(); + }, + Index = index, + RequiredPermissionLevel = requiredPermissionLevel + } + ); + } + public void AddSidebarItem(string name, string icon, string target, bool isAdmin = false, bool needsExactMatch = false, int index = 0) { SidebarItems.Add(new SidebarItem() diff --git a/Moonlight/Core/UI/Components/Cards/AdminUserCard.razor b/Moonlight/Core/UI/Components/Cards/AdminUserCard.razor new file mode 100644 index 0000000..7194197 --- /dev/null +++ b/Moonlight/Core/UI/Components/Cards/AdminUserCard.razor @@ -0,0 +1,35 @@ +@using MoonCore.Abstractions +@using Moonlight.Core.Database.Entities + +@inject Repository UserRepository + + +
+
+
+
+ Users +
+ + @UserCount + +
+
+ + + +
+
+
+
+ +@code { + + private int UserCount; + + protected override async Task OnInitializedAsync() + { + UserCount = UserRepository.Get().Count(); + } + +} \ No newline at end of file diff --git a/Moonlight/Core/UI/Views/Admin/Index.razor b/Moonlight/Core/UI/Views/Admin/Index.razor index 2cb5718..8d46947 100644 --- a/Moonlight/Core/UI/Views/Admin/Index.razor +++ b/Moonlight/Core/UI/Views/Admin/Index.razor @@ -1,73 +1,46 @@ @page "/admin" @using MoonCore.Abstractions @using Moonlight.Core.Database.Entities +@using Moonlight.Core.Services @using Moonlight.Features.Servers.Entities @inject Repository ServerRepository -@inject Repository UserRepository + +@inject FeatureService FeatureService +@inject IdentityService IdentityService @attribute [RequirePermission(999)] -
-
- - + + @foreach (var adminComponent in FeatureService.UiContext.AdminPageComponents.OrderBy(x => x.Index).ToArray()) + { + if (IdentityService.CurrentUser.Permissions >= adminComponent.RequiredPermissionLevel) + { +
+ @adminComponent +
+ } + } -@* This is just the start of this admin page, there will still be added more during the developement process *@ @code { - private int ServerCount; - private int UserCount; - + private async Task Load(LazyLoader arg) { - await Task.Run(() => - { - arg.SetText("Loading Information..."); - ServerCount = ServerRepository.Get().Count(); - UserCount = UserRepository.Get().Count(); - }); + await arg.SetText("Loading Information..."); + } } \ No newline at end of file diff --git a/Moonlight/Features/Servers/ServersFeature.cs b/Moonlight/Features/Servers/ServersFeature.cs index acd1445..30422cb 100644 --- a/Moonlight/Features/Servers/ServersFeature.cs +++ b/Moonlight/Features/Servers/ServersFeature.cs @@ -10,6 +10,7 @@ using Moonlight.Features.Servers.Http.Middleware; using Moonlight.Features.Servers.Implementations.Diagnose; using Moonlight.Features.Servers.Models.Enums; using Moonlight.Features.Servers.Services; +using Moonlight.Features.Servers.UI.Components.Cards; namespace Moonlight.Features.Servers; @@ -104,6 +105,8 @@ public class ServersFeature : MoonlightFeature context.AddSidebarItem("Servers", "bx-server", "/servers", isAdmin: false, needsExactMatch: false); context.AddSidebarItem("Servers", "bx-server", "/admin/servers", isAdmin: true, needsExactMatch: false); + context.AddAdminCard(); + return Task.CompletedTask; } } \ No newline at end of file diff --git a/Moonlight/Features/Servers/UI/Components/Cards/AdminServersCard.razor b/Moonlight/Features/Servers/UI/Components/Cards/AdminServersCard.razor new file mode 100644 index 0000000..8c8ce49 --- /dev/null +++ b/Moonlight/Features/Servers/UI/Components/Cards/AdminServersCard.razor @@ -0,0 +1,35 @@ +@using MoonCore.Abstractions +@using Moonlight.Features.Servers.Entities + +@inject Repository ServerRepository + + +
+
+
+
+ Servers +
+ + @ServerCount + +
+
+ + + +
+
+
+
+ +@code { + + private int ServerCount; + + protected override async Task OnInitializedAsync() + { + ServerCount = ServerRepository.Get().Count(); + } + +} \ No newline at end of file From 7225db0bf12a324d058bc0171ae9313d74851889 Mon Sep 17 00:00:00 2001 From: Moritz <101179677+Moritz-Deiaco@users.noreply.github.com> Date: Tue, 14 May 2024 14:52:27 +0200 Subject: [PATCH 2/3] added some informations --- Moonlight/Core/CoreFeature.cs | 5 +++++ Moonlight/Core/Models/Abstractions/Feature/UiInitContext.cs | 2 ++ Moonlight/Core/UI/Views/Admin/Index.razor | 3 ++- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Moonlight/Core/CoreFeature.cs b/Moonlight/Core/CoreFeature.cs index 3316b1e..61870dd 100644 --- a/Moonlight/Core/CoreFeature.cs +++ b/Moonlight/Core/CoreFeature.cs @@ -208,8 +208,13 @@ public class CoreFeature : MoonlightFeature context.AddSidebarItem("Users", "bxs-group", "/admin/users", needsExactMatch: false, isAdmin: true); context.AddSidebarItem("System", "bxs-component", "/admin/sys", needsExactMatch: false, isAdmin: true); + // With this function, you can add an Admin Card to the Admin Page + // It references the Admin Card, which is a Razor component. context.AddAdminCard(index: int.MinValue); + // Same Thing could be used with the context.AddAdminComponent Function, which then renders the component + // under the cards, for fast informations + return Task.CompletedTask; } diff --git a/Moonlight/Core/Models/Abstractions/Feature/UiInitContext.cs b/Moonlight/Core/Models/Abstractions/Feature/UiInitContext.cs index 172885e..0a589b8 100644 --- a/Moonlight/Core/Models/Abstractions/Feature/UiInitContext.cs +++ b/Moonlight/Core/Models/Abstractions/Feature/UiInitContext.cs @@ -24,6 +24,7 @@ public class UiInitContext public void AddAdminComponent(int index = 0, int requiredPermissionLevel = 0) where T : IComponent { + // Loads the Component into a List of AdminComponents, with lots of more information for the Admin Page to render AdminPageComponents.Add( new AdminComponent() { @@ -40,6 +41,7 @@ public class UiInitContext public void AddAdminCard(int index = 0, int requiredPermissionLevel = 0) where T : IComponent { + // Loads the Card into a List of AdminComponents, with lots of more information for the Admin Page to render AdminPageCards.Add( new AdminComponent() { diff --git a/Moonlight/Core/UI/Views/Admin/Index.razor b/Moonlight/Core/UI/Views/Admin/Index.razor index 8d46947..2f1c8c6 100644 --- a/Moonlight/Core/UI/Views/Admin/Index.razor +++ b/Moonlight/Core/UI/Views/Admin/Index.razor @@ -15,6 +15,8 @@
@foreach (var adminCard in FeatureService.UiContext.AdminPageCards.OrderBy(x => x.Index).ToArray()) { + // basically renders the component if the permissions of the viewed item is lower or equal + // to the users permission, -> better developer experience for feature devs if (IdentityService.CurrentUser.Permissions >= adminCard.RequiredPermissionLevel) {
@@ -41,6 +43,5 @@ private async Task Load(LazyLoader arg) { await arg.SetText("Loading Information..."); - } } \ No newline at end of file From 56184a825407a4b469bc49592883269df94dde4a Mon Sep 17 00:00:00 2001 From: Moritz <101179677+Moritz-Deiaco@users.noreply.github.com> Date: Sat, 18 May 2024 22:11:58 +0200 Subject: [PATCH 3/3] Final admin Page Added Admin System To be as Modular as masu wants it to be --- Moonlight/Core/CoreFeature.cs | 11 ++-- .../Implementations/AdminColumns/UserCount.cs | 16 ++++++ .../Core/Interfaces/IAdminDashboardColumn.cs | 8 +++ .../Interfaces/IAdminDashboardComponent.cs | 8 +++ .../Abstractions/Feature/AdminComponent.cs | 12 ----- .../Abstractions/Feature/UiInitContext.cs | 34 ------------ .../UI/Components/Cards/AdminUserCard.razor | 20 +------ Moonlight/Core/UI/Views/Admin/Index.razor | 53 +++++++++++-------- .../AdminColumns/ServerCount.cs | 16 ++++++ Moonlight/Features/Servers/ServersFeature.cs | 5 +- .../Components/Cards/AdminServersCard.razor | 20 +------ Moonlight/Moonlight.csproj | 1 + 12 files changed, 90 insertions(+), 114 deletions(-) create mode 100644 Moonlight/Core/Implementations/AdminColumns/UserCount.cs create mode 100644 Moonlight/Core/Interfaces/IAdminDashboardColumn.cs create mode 100644 Moonlight/Core/Interfaces/IAdminDashboardComponent.cs delete mode 100644 Moonlight/Core/Models/Abstractions/Feature/AdminComponent.cs create mode 100644 Moonlight/Features/Servers/Implementations/AdminColumns/ServerCount.cs diff --git a/Moonlight/Core/CoreFeature.cs b/Moonlight/Core/CoreFeature.cs index 61870dd..ae4bc9c 100644 --- a/Moonlight/Core/CoreFeature.cs +++ b/Moonlight/Core/CoreFeature.cs @@ -7,6 +7,7 @@ using MoonCoreUI.Services; using Moonlight.Core.Configuration; using Moonlight.Core.Database; using Moonlight.Core.Database.Entities; +using Moonlight.Core.Implementations.AdminColumns; using Moonlight.Core.Implementations.Diagnose; using Moonlight.Core.Interfaces; using Moonlight.Core.Models; @@ -156,6 +157,9 @@ public class CoreFeature : MoonlightFeature await pluginService.RegisterImplementation(new FeatureDiagnoseAction()); await pluginService.RegisterImplementation(new LogDiagnoseAction()); + //Admin Page + await pluginService.RegisterImplementation(new UserCount()); + // Startup job services var startupJobService = app.Services.GetRequiredService(); @@ -208,13 +212,6 @@ public class CoreFeature : MoonlightFeature context.AddSidebarItem("Users", "bxs-group", "/admin/users", needsExactMatch: false, isAdmin: true); context.AddSidebarItem("System", "bxs-component", "/admin/sys", needsExactMatch: false, isAdmin: true); - // With this function, you can add an Admin Card to the Admin Page - // It references the Admin Card, which is a Razor component. - context.AddAdminCard(index: int.MinValue); - - // Same Thing could be used with the context.AddAdminComponent Function, which then renders the component - // under the cards, for fast informations - return Task.CompletedTask; } diff --git a/Moonlight/Core/Implementations/AdminColumns/UserCount.cs b/Moonlight/Core/Implementations/AdminColumns/UserCount.cs new file mode 100644 index 0000000..f4b5461 --- /dev/null +++ b/Moonlight/Core/Implementations/AdminColumns/UserCount.cs @@ -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 Get() + { + var res = ComponentHelper.FromType(); + + return Task.FromResult(res); + } +} \ No newline at end of file diff --git a/Moonlight/Core/Interfaces/IAdminDashboardColumn.cs b/Moonlight/Core/Interfaces/IAdminDashboardColumn.cs new file mode 100644 index 0000000..7e92eab --- /dev/null +++ b/Moonlight/Core/Interfaces/IAdminDashboardColumn.cs @@ -0,0 +1,8 @@ +using Microsoft.AspNetCore.Components; + +namespace Moonlight.Core.Interfaces; + +public interface IAdminDashboardColumn +{ + public Task Get(); +} \ No newline at end of file diff --git a/Moonlight/Core/Interfaces/IAdminDashboardComponent.cs b/Moonlight/Core/Interfaces/IAdminDashboardComponent.cs new file mode 100644 index 0000000..4f1e0e7 --- /dev/null +++ b/Moonlight/Core/Interfaces/IAdminDashboardComponent.cs @@ -0,0 +1,8 @@ +using Microsoft.AspNetCore.Components; + +namespace Moonlight.Core.Interfaces; + +public interface IAdminDashboardComponent +{ + public Task Get(); +} \ No newline at end of file diff --git a/Moonlight/Core/Models/Abstractions/Feature/AdminComponent.cs b/Moonlight/Core/Models/Abstractions/Feature/AdminComponent.cs deleted file mode 100644 index b17e9db..0000000 --- a/Moonlight/Core/Models/Abstractions/Feature/AdminComponent.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Microsoft.AspNetCore.Components; - -namespace Moonlight.Core.Models.Abstractions.Feature; - -public class AdminComponent -{ - public RenderFragment Component { get; set; } - - public int Index { get; set; } - - public int RequiredPermissionLevel { get; set; } -} \ No newline at end of file diff --git a/Moonlight/Core/Models/Abstractions/Feature/UiInitContext.cs b/Moonlight/Core/Models/Abstractions/Feature/UiInitContext.cs index 0a589b8..382c690 100644 --- a/Moonlight/Core/Models/Abstractions/Feature/UiInitContext.cs +++ b/Moonlight/Core/Models/Abstractions/Feature/UiInitContext.cs @@ -22,40 +22,6 @@ public class UiInitContext RouteAssemblies.Add(assembly); } - public void AddAdminComponent(int index = 0, int requiredPermissionLevel = 0) where T : IComponent - { - // Loads the Component into a List of AdminComponents, with lots of more information for the Admin Page to render - AdminPageComponents.Add( - new AdminComponent() - { - Component = builder => - { - builder.OpenComponent(0); - builder.CloseComponent(); - }, - Index = index, - RequiredPermissionLevel = requiredPermissionLevel - } - ); - } - - public void AddAdminCard(int index = 0, int requiredPermissionLevel = 0) where T : IComponent - { - // Loads the Card into a List of AdminComponents, with lots of more information for the Admin Page to render - AdminPageCards.Add( - new AdminComponent() - { - Component = builder => - { - builder.OpenComponent(0); - builder.CloseComponent(); - }, - Index = index, - RequiredPermissionLevel = requiredPermissionLevel - } - ); - } - public void AddSidebarItem(string name, string icon, string target, bool isAdmin = false, bool needsExactMatch = false, int index = 0) { SidebarItems.Add(new SidebarItem() diff --git a/Moonlight/Core/UI/Components/Cards/AdminUserCard.razor b/Moonlight/Core/UI/Components/Cards/AdminUserCard.razor index 7194197..c05cad8 100644 --- a/Moonlight/Core/UI/Components/Cards/AdminUserCard.razor +++ b/Moonlight/Core/UI/Components/Cards/AdminUserCard.razor @@ -3,24 +3,8 @@ @inject Repository UserRepository - -
-
-
-
- Users -
- - @UserCount - -
-
- - - -
-
-
+
+ @code { diff --git a/Moonlight/Core/UI/Views/Admin/Index.razor b/Moonlight/Core/UI/Views/Admin/Index.razor index 2f1c8c6..713a618 100644 --- a/Moonlight/Core/UI/Views/Admin/Index.razor +++ b/Moonlight/Core/UI/Views/Admin/Index.razor @@ -1,47 +1,54 @@ @page "/admin" @using MoonCore.Abstractions @using Moonlight.Core.Database.Entities +@using Moonlight.Core.Interfaces @using Moonlight.Core.Services @using Moonlight.Features.Servers.Entities -@inject Repository ServerRepository - -@inject FeatureService FeatureService -@inject IdentityService IdentityService +@inject PluginService PluginService @attribute [RequirePermission(999)] -
- @foreach (var adminCard in FeatureService.UiContext.AdminPageCards.OrderBy(x => x.Index).ToArray()) +
+ @foreach(var column in Columns) { - // basically renders the component if the permissions of the viewed item is lower or equal - // to the users permission, -> better developer experience for feature devs - if (IdentityService.CurrentUser.Permissions >= adminCard.RequiredPermissionLevel) - { -
- @adminCard.Component -
- } - } -
- - @foreach (var adminComponent in FeatureService.UiContext.AdminPageComponents.OrderBy(x => x.Index).ToArray()) - { - if (IdentityService.CurrentUser.Permissions >= adminComponent.RequiredPermissionLevel) - { -
- @adminComponent +
+ @column
} +
+ @foreach (var component in Components) + { +
+ @component +
} @code { + + private List Columns = new(); + private List Components = new(); private async Task Load(LazyLoader arg) { await arg.SetText("Loading Information..."); + + var componentImplementations = await PluginService.GetImplementations(); + + foreach (var implementation in componentImplementations) + { + Components.Add(await implementation.Get()); + } + + var columnImplementations = await PluginService.GetImplementations(); + + foreach (var implementation in columnImplementations) + { + Columns.Add(await implementation.Get()); + } + } } \ No newline at end of file diff --git a/Moonlight/Features/Servers/Implementations/AdminColumns/ServerCount.cs b/Moonlight/Features/Servers/Implementations/AdminColumns/ServerCount.cs new file mode 100644 index 0000000..2d743d4 --- /dev/null +++ b/Moonlight/Features/Servers/Implementations/AdminColumns/ServerCount.cs @@ -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 Get() + { + var res = ComponentHelper.FromType(); + + return Task.FromResult(res); + } +} \ No newline at end of file diff --git a/Moonlight/Features/Servers/ServersFeature.cs b/Moonlight/Features/Servers/ServersFeature.cs index 30422cb..89e0075 100644 --- a/Moonlight/Features/Servers/ServersFeature.cs +++ b/Moonlight/Features/Servers/ServersFeature.cs @@ -7,6 +7,7 @@ using Moonlight.Core.Services; using Moonlight.Features.Servers.Actions; using Moonlight.Features.Servers.Configuration; using Moonlight.Features.Servers.Http.Middleware; +using Moonlight.Features.Servers.Implementations.AdminColumns; using Moonlight.Features.Servers.Implementations.Diagnose; using Moonlight.Features.Servers.Models.Enums; using Moonlight.Features.Servers.Services; @@ -96,6 +97,8 @@ public class ServersFeature : MoonlightFeature var pluginService = app.Services.GetRequiredService(); await pluginService.RegisterImplementation(new NodesDiagnoseAction()); + + await pluginService.RegisterImplementation(new ServerCount()); } public override Task OnUiInitialized(UiInitContext context) @@ -105,8 +108,6 @@ public class ServersFeature : MoonlightFeature context.AddSidebarItem("Servers", "bx-server", "/servers", isAdmin: false, needsExactMatch: false); context.AddSidebarItem("Servers", "bx-server", "/admin/servers", isAdmin: true, needsExactMatch: false); - context.AddAdminCard(); - return Task.CompletedTask; } } \ No newline at end of file diff --git a/Moonlight/Features/Servers/UI/Components/Cards/AdminServersCard.razor b/Moonlight/Features/Servers/UI/Components/Cards/AdminServersCard.razor index 8c8ce49..978ff7b 100644 --- a/Moonlight/Features/Servers/UI/Components/Cards/AdminServersCard.razor +++ b/Moonlight/Features/Servers/UI/Components/Cards/AdminServersCard.razor @@ -3,24 +3,8 @@ @inject Repository ServerRepository - -
-
-
-
- Servers -
- - @ServerCount - -
-
- - - -
-
-
+
+ @code { diff --git a/Moonlight/Moonlight.csproj b/Moonlight/Moonlight.csproj index 1aad123..34bbe64 100644 --- a/Moonlight/Moonlight.csproj +++ b/Moonlight/Moonlight.csproj @@ -53,6 +53,7 @@ +