Merge pull request #417 from Moonlight-Panel/v2_ImproveModularUI

Made user dashboard modular and extendable via plugins
This commit is contained in:
Masu Baumgartner 2024-05-21 21:50:43 +02:00 committed by GitHub
commit 257af8106d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 190 additions and 107 deletions

View file

@ -8,9 +8,12 @@ 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.Implementations.UI.Admin.AdminColumns;
using Moonlight.Core.Implementations.UI.Index;
using Moonlight.Core.Interfaces; using Moonlight.Core.Interfaces;
using Moonlight.Core.Interfaces.Ui.Admin;
using Moonlight.Core.Interfaces.UI.User;
using Moonlight.Core.Models; using Moonlight.Core.Models;
using Moonlight.Core.Models.Abstractions; using Moonlight.Core.Models.Abstractions;
using Moonlight.Core.Models.Abstractions.Feature; using Moonlight.Core.Models.Abstractions.Feature;
@ -160,8 +163,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 // UI
await pluginService.RegisterImplementation<IAdminDashboardColumn>(new UserCount()); await pluginService.RegisterImplementation<IAdminDashboardColumn>(new UserCount());
await pluginService.RegisterImplementation<IUserDashboardComponent>(new GreetingMessages());
// Startup job services // Startup job services
var startupJobService = app.Services.GetRequiredService<StartupJobService>(); var startupJobService = app.Services.GetRequiredService<StartupJobService>();

View file

@ -1,16 +0,0 @@
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,20 @@
using MoonCoreUI.Helpers;
using Moonlight.Core.Interfaces.Ui.Admin;
using Moonlight.Core.Models.Abstractions;
using Moonlight.Core.UI.Components.Cards;
namespace Moonlight.Core.Implementations.UI.Admin.AdminColumns;
public class UserCount : IAdminDashboardColumn
{
public Task<UiComponent> Get()
{
var res = new UiComponent()
{
Component = ComponentHelper.FromType<AdminUserCard>(),
Index = int.MinValue
};
return Task.FromResult(res);
}
}

View file

@ -0,0 +1,20 @@
using MoonCoreUI.Helpers;
using Moonlight.Core.Interfaces.UI.User;
using Moonlight.Core.Models.Abstractions;
using Moonlight.Core.UI.Components.Cards;
namespace Moonlight.Core.Implementations.UI.Index;
public class GreetingMessages : IUserDashboardComponent
{
public Task<UiComponent> Get()
{
var res = new UiComponent()
{
Component = ComponentHelper.FromType<TimeBasedGreetingMessages>(),
Index = int.MinValue
};
return Task.FromResult(res);
}
}

View file

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

View file

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

View file

@ -0,0 +1,8 @@
using Moonlight.Core.Models.Abstractions;
namespace Moonlight.Core.Interfaces.Ui.Admin;
public interface IAdminDashboardColumn
{
public Task<UiComponent> Get();
}

View file

@ -0,0 +1,8 @@
using Moonlight.Core.Models.Abstractions;
namespace Moonlight.Core.Interfaces.Ui.Admin;
public interface IAdminDashboardComponent
{
public Task<UiComponent> Get();
}

View file

@ -0,0 +1,8 @@
using Moonlight.Core.Models.Abstractions;
namespace Moonlight.Core.Interfaces.UI.User;
public interface IUserDashboardComponent
{
public Task<UiComponent> Get();
}

View file

@ -0,0 +1,10 @@
using Microsoft.AspNetCore.Components;
namespace Moonlight.Core.Models.Abstractions;
public class UiComponent
{
public required RenderFragment Component { get; set; }
public int Index { get; set; } = 0;
}

View file

@ -0,0 +1,57 @@
@using MoonCore.Services
@using Moonlight.Core.Configuration
@using Moonlight.Core.Services
@inject IdentityService IdentityService
@inject ConfigService<CoreConfiguration> ConfigService
<div class="card card-body p-8">
<div class="d-flex align-items-center">
<span class="fs-2 fw-semibold">
@{
var greeting = GetGreetingMessage();
}
@greeting.Item1
<span class="text-info">@IdentityService.CurrentUser.Username</span>
@greeting.Item2
</span>
</div>
</div>
@code {
// For explanation:
// The first value is the actual message
// end second value is for question marks and so on
//
// and yes, this "feature" is kinda useless but still i wanted to implement
// it. - Masu
private (string, string) GetGreetingMessage()
{
var config = ConfigService.Get().Customisation;
if (config.DisableTimeBasedGreetingMessages)
return ("Welcome back, ", "");
var time = DateTime.UtcNow.AddHours(config.GreetingTimezoneDifference);
if (time.Hour >= 23 || time.Hour < 5)
return ("\ud83d\ude34 Still awake, ", "?");
if (time.Hour >= 5 && time.Hour < 10)
return ("\ud83d\ude04 Good morning, ", "");
if (time.Hour >= 10 && time.Hour < 14)
return ("\u2600\ufe0f Have a nice day, ", "");
if (time.Hour >= 14 && time.Hour < 16)
return ("\ud83d\ude03 Good afternoon, ", "");
if (time.Hour >= 16 && time.Hour < 22)
return ("\ud83c\udf25\ufe0f Have a nice evening, ", "");
if (time.Hour >= 22 && time.Hour < 23)
return ("\ud83c\udf19 Sleep well, ", "");
return ("Welcome back ", "");
}
}

View file

@ -2,6 +2,8 @@
@using MoonCore.Abstractions @using MoonCore.Abstractions
@using Moonlight.Core.Database.Entities @using Moonlight.Core.Database.Entities
@using Moonlight.Core.Interfaces @using Moonlight.Core.Interfaces
@using Moonlight.Core.Interfaces.Ui.Admin
@using Moonlight.Core.Models.Abstractions
@using Moonlight.Core.Services @using Moonlight.Core.Services
@using Moonlight.Features.Servers.Entities @using Moonlight.Features.Servers.Entities
@ -11,17 +13,17 @@
<LazyLoader Load="Load"> <LazyLoader Load="Load">
<div class="row mb-8"> <div class="row mb-8">
@foreach(var column in Columns) @foreach(var column in Columns.OrderBy(x => x.Index))
{ {
<div class="col-12 col-lg-6 col-xl"> <div class="col-12 col-lg-6 col-xl">
@column @column.Component
</div> </div>
} }
</div> </div>
@foreach (var component in Components) @foreach (var component in Components.OrderBy(x => x.Index))
{ {
<div class="mb-4"> <div class="mb-4">
@component @component.Component
</div> </div>
} }
</LazyLoader> </LazyLoader>
@ -29,8 +31,8 @@
@code { @code {
private List<RenderFragment> Columns = new(); private List<UiComponent> Columns = new();
private List<RenderFragment> Components = new(); private List<UiComponent> Components = new();
private async Task Load(LazyLoader arg) private async Task Load(LazyLoader arg)
{ {

View file

@ -1,60 +1,33 @@
@page "/" @page "/"
@using Moonlight.Core.Interfaces.UI.User
@using Moonlight.Core.Models.Abstractions
@using Moonlight.Core.Services @using Moonlight.Core.Services
@using MoonCore.Services
@using Moonlight.Core.Configuration
@inject IdentityService IdentityService @inject PluginService PluginService
@inject ConfigService<CoreConfiguration> ConfigService
<div class="card card-body p-8"> <LazyLoader Load="Load">
<div class="d-flex align-items-center"> @foreach (var component in Components.OrderBy(x => x.Index))
<span class="fs-2 fw-semibold"> {
@{ <div class="mb-4">
var greeting = GetGreetingMessage(); @component.Component
</div>
} }
@greeting.Item1 </LazyLoader>
<span class="text-info">@IdentityService.CurrentUser.Username</span>
@greeting.Item2
</span>
</div>
</div>
@code @code
{ {
// For explanation: private List<UiComponent> Components = new();
// The first value is the actual message
// end second value is for question marks and so on
// private async Task Load(LazyLoader arg)
// and yes, this "feature" is kinda useless but still i wanted to implement
// it. - Masu
private (string, string) GetGreetingMessage()
{ {
var config = ConfigService.Get().Customisation; await arg.SetText("Loading...");
if (config.DisableTimeBasedGreetingMessages) var implementations = await PluginService.GetImplementations<IUserDashboardComponent>();
return ("Welcome back, ", "");
var time = DateTime.UtcNow.AddHours(config.GreetingTimezoneDifference); foreach (var implementation in implementations)
{
if (time.Hour >= 23 || time.Hour < 5) Components.Add(await implementation.Get());
return ("\ud83d\ude34 Still awake, ", "?"); }
if (time.Hour >= 5 && time.Hour < 10)
return ("\ud83d\ude04 Good morning, ", "");
if (time.Hour >= 10 && time.Hour < 14)
return ("\u2600\ufe0f Have a nice day, ", "");
if (time.Hour >= 14 && time.Hour < 16)
return ("\ud83d\ude03 Good afternoon, ", "");
if (time.Hour >= 16 && time.Hour < 22)
return ("\ud83c\udf25\ufe0f Have a nice evening, ", "");
if (time.Hour >= 22 && time.Hour < 23)
return ("\ud83c\udf19 Sleep well, ", "");
return ("Welcome back ", "");
} }
} }

View file

@ -1,16 +0,0 @@
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

@ -0,0 +1,19 @@
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.AdminColumns;
public class ServerCount : IAdminDashboardColumn
{
public Task<UiComponent> Get()
{
var res = new UiComponent()
{
Component = ComponentHelper.FromType<AdminServersCard>()
};
return Task.FromResult(res);
}
}

View file

@ -2,13 +2,14 @@ using MoonCore.Helpers;
using MoonCore.Services; 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.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;
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.Implementations.UI.Admin.AdminColumns;
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;

View file

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