From e8706cad1c5af66e7837937792ce7d2fde56111a Mon Sep 17 00:00:00 2001 From: Baumgartner Marcel Date: Wed, 15 Nov 2023 10:25:28 +0100 Subject: [PATCH] Made implementation api cleaner --- Moonlight/App/Actions/Dummy/DummyActions.cs | 1 + Moonlight/App/Actions/Dummy/DummyConfig.cs | 2 - .../Actions/Dummy/DummyServiceDefinition.cs | 25 +++++++++++ .../Dummy/DummyServiceImplementation.cs | 34 --------------- Moonlight/App/Helpers/ComponentHelper.cs | 3 ++ .../App/Models/Abstractions/ServiceActions.cs | 10 ----- .../Abstractions/ServiceImplementation.cs | 18 -------- .../Abstractions/Services/ServiceActions.cs | 8 ++++ .../Services/ServiceDefinition.cs | 15 +++++++ .../{ => Services}/ServiceUiPage.cs | 4 +- .../Services/ServiceViewContext.cs | 31 ++++++++++++++ .../App/Plugins/Contexts/PluginContext.cs | 7 ++-- .../Plugins/Contexts/ServiceManageContext.cs | 11 ----- Moonlight/App/Services/PluginService.cs | 21 ++++++---- .../ServiceManage/ServiceAdminService.cs | 10 ++--- ...Service.cs => ServiceDefinitionService.cs} | 17 ++++---- .../Services/ServiceManage/ServiceService.cs | 2 +- .../App/Services/Store/StoreAdminService.cs | 4 +- Moonlight/Program.cs | 6 +-- Moonlight/Shared/Views/Service/Index.razor | 41 ++++++++----------- 20 files changed, 139 insertions(+), 131 deletions(-) create mode 100644 Moonlight/App/Actions/Dummy/DummyServiceDefinition.cs delete mode 100644 Moonlight/App/Actions/Dummy/DummyServiceImplementation.cs delete mode 100644 Moonlight/App/Models/Abstractions/ServiceActions.cs delete mode 100644 Moonlight/App/Models/Abstractions/ServiceImplementation.cs create mode 100644 Moonlight/App/Models/Abstractions/Services/ServiceActions.cs create mode 100644 Moonlight/App/Models/Abstractions/Services/ServiceDefinition.cs rename Moonlight/App/Models/Abstractions/{ => Services}/ServiceUiPage.cs (63%) create mode 100644 Moonlight/App/Models/Abstractions/Services/ServiceViewContext.cs delete mode 100644 Moonlight/App/Plugins/Contexts/ServiceManageContext.cs rename Moonlight/App/Services/ServiceManage/{ServiceTypeService.cs => ServiceDefinitionService.cs} (69%) diff --git a/Moonlight/App/Actions/Dummy/DummyActions.cs b/Moonlight/App/Actions/Dummy/DummyActions.cs index 1970ddc..ba00b19 100644 --- a/Moonlight/App/Actions/Dummy/DummyActions.cs +++ b/Moonlight/App/Actions/Dummy/DummyActions.cs @@ -1,5 +1,6 @@ using Moonlight.App.Database.Entities.Store; using Moonlight.App.Models.Abstractions; +using Moonlight.App.Models.Abstractions.Services; namespace Moonlight.App.Actions.Dummy; diff --git a/Moonlight/App/Actions/Dummy/DummyConfig.cs b/Moonlight/App/Actions/Dummy/DummyConfig.cs index 8d1c184..6076d0b 100644 --- a/Moonlight/App/Actions/Dummy/DummyConfig.cs +++ b/Moonlight/App/Actions/Dummy/DummyConfig.cs @@ -1,6 +1,4 @@ using System.ComponentModel; -using Moonlight.App.Database.Entities; -using Moonlight.App.Extensions.Attributes; namespace Moonlight.App.Actions.Dummy; diff --git a/Moonlight/App/Actions/Dummy/DummyServiceDefinition.cs b/Moonlight/App/Actions/Dummy/DummyServiceDefinition.cs new file mode 100644 index 0000000..1d386a1 --- /dev/null +++ b/Moonlight/App/Actions/Dummy/DummyServiceDefinition.cs @@ -0,0 +1,25 @@ +using Moonlight.App.Actions.Dummy.Layouts; +using Moonlight.App.Actions.Dummy.Pages; +using Moonlight.App.Helpers; +using Moonlight.App.Models.Abstractions.Services; + +namespace Moonlight.App.Actions.Dummy; + +public class DummyServiceDefinition : ServiceDefinition +{ + public override ServiceActions Actions => new DummyActions(); + public override Type ConfigType => typeof(DummyConfig); + public override async Task BuildUserView(ServiceViewContext context) + { + context.Layout = ComponentHelper.FromType(); + + await context.AddPage("Demo", "/demo"); + } + + public override Task BuildAdminView(ServiceViewContext context) + { + context.Layout = ComponentHelper.FromType(); + + return Task.CompletedTask; + } +} \ No newline at end of file diff --git a/Moonlight/App/Actions/Dummy/DummyServiceImplementation.cs b/Moonlight/App/Actions/Dummy/DummyServiceImplementation.cs deleted file mode 100644 index 6c33141..0000000 --- a/Moonlight/App/Actions/Dummy/DummyServiceImplementation.cs +++ /dev/null @@ -1,34 +0,0 @@ -using Microsoft.AspNetCore.Components; -using Moonlight.App.Actions.Dummy.Layouts; -using Moonlight.App.Database.Entities; -using Moonlight.App.Database.Entities.Store; -using Moonlight.App.Helpers; -using Moonlight.App.Models.Abstractions; - -namespace Moonlight.App.Actions.Dummy; - -public class DummyServiceImplementation : ServiceImplementation -{ - public override ServiceActions Actions { get; } = new DummyActions(); - public override Type ConfigType { get; } = typeof(DummyConfig); - - public override RenderFragment GetAdminLayout() - { - return ComponentHelper.FromType(typeof(DummyAdmin)); - } - - public override RenderFragment GetUserLayout() - { - return ComponentHelper.FromType(typeof(DummyUser)); - } - - public override ServiceUiPage[] GetUserPages(Service service, User user) - { - return Array.Empty(); - } - - public override ServiceUiPage[] GetAdminPages(Service service, User user) - { - return Array.Empty(); - } -} \ No newline at end of file diff --git a/Moonlight/App/Helpers/ComponentHelper.cs b/Moonlight/App/Helpers/ComponentHelper.cs index f3f3ad7..754bd6b 100644 --- a/Moonlight/App/Helpers/ComponentHelper.cs +++ b/Moonlight/App/Helpers/ComponentHelper.cs @@ -17,4 +17,7 @@ public static class ComponentHelper builder.CloseComponent(); }; + + public static RenderFragment FromType(Action>? buildAttributes = null) where T : ComponentBase => + FromType(typeof(T), buildAttributes); } \ No newline at end of file diff --git a/Moonlight/App/Models/Abstractions/ServiceActions.cs b/Moonlight/App/Models/Abstractions/ServiceActions.cs deleted file mode 100644 index 6ae14d8..0000000 --- a/Moonlight/App/Models/Abstractions/ServiceActions.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Moonlight.App.Database.Entities.Store; - -namespace Moonlight.App.Models.Abstractions; - -public abstract class ServiceActions -{ - public abstract Task Create(IServiceProvider provider, Service service); - public abstract Task Update(IServiceProvider provider, Service service); - public abstract Task Delete(IServiceProvider provider, Service service); -} \ No newline at end of file diff --git a/Moonlight/App/Models/Abstractions/ServiceImplementation.cs b/Moonlight/App/Models/Abstractions/ServiceImplementation.cs deleted file mode 100644 index 7478b6b..0000000 --- a/Moonlight/App/Models/Abstractions/ServiceImplementation.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Microsoft.AspNetCore.Components; -using Moonlight.App.Database.Entities; -using Moonlight.App.Database.Entities.Store; - -namespace Moonlight.App.Models.Abstractions; - -public abstract class ServiceImplementation -{ - public abstract ServiceActions Actions { get; } - public abstract Type ConfigType { get; } - - public abstract RenderFragment GetAdminLayout(); - public abstract RenderFragment GetUserLayout(); - - // The service and user parameter can be used to only show certain pages to admins or other - public abstract ServiceUiPage[] GetUserPages(Service service, User user); - public abstract ServiceUiPage[] GetAdminPages(Service service, User user); -} \ No newline at end of file diff --git a/Moonlight/App/Models/Abstractions/Services/ServiceActions.cs b/Moonlight/App/Models/Abstractions/Services/ServiceActions.cs new file mode 100644 index 0000000..dfc010e --- /dev/null +++ b/Moonlight/App/Models/Abstractions/Services/ServiceActions.cs @@ -0,0 +1,8 @@ +namespace Moonlight.App.Models.Abstractions.Services; + +public abstract class ServiceActions +{ + public abstract Task Create(IServiceProvider provider, Database.Entities.Store.Service service); + public abstract Task Update(IServiceProvider provider, Database.Entities.Store.Service service); + public abstract Task Delete(IServiceProvider provider, Database.Entities.Store.Service service); +} \ No newline at end of file diff --git a/Moonlight/App/Models/Abstractions/Services/ServiceDefinition.cs b/Moonlight/App/Models/Abstractions/Services/ServiceDefinition.cs new file mode 100644 index 0000000..0aafded --- /dev/null +++ b/Moonlight/App/Models/Abstractions/Services/ServiceDefinition.cs @@ -0,0 +1,15 @@ +using Microsoft.AspNetCore.Components; +using Moonlight.App.Database.Entities; + +namespace Moonlight.App.Models.Abstractions.Services; + +public abstract class ServiceDefinition +{ + // Config + public abstract ServiceActions Actions { get; } + public abstract Type ConfigType { get; } + + // Methods + public abstract Task BuildUserView(ServiceViewContext context); + public abstract Task BuildAdminView(ServiceViewContext context); +} \ No newline at end of file diff --git a/Moonlight/App/Models/Abstractions/ServiceUiPage.cs b/Moonlight/App/Models/Abstractions/Services/ServiceUiPage.cs similarity index 63% rename from Moonlight/App/Models/Abstractions/ServiceUiPage.cs rename to Moonlight/App/Models/Abstractions/Services/ServiceUiPage.cs index b50d42a..19a0ef0 100644 --- a/Moonlight/App/Models/Abstractions/ServiceUiPage.cs +++ b/Moonlight/App/Models/Abstractions/Services/ServiceUiPage.cs @@ -1,11 +1,11 @@ using Microsoft.AspNetCore.Components; -namespace Moonlight.App.Models.Abstractions; +namespace Moonlight.App.Models.Abstractions.Services; public class ServiceUiPage { public string Name { get; set; } public string Route { get; set; } public string Icon { get; set; } - public ComponentBase Component { get; set; } + public RenderFragment Component { get; set; } } \ No newline at end of file diff --git a/Moonlight/App/Models/Abstractions/Services/ServiceViewContext.cs b/Moonlight/App/Models/Abstractions/Services/ServiceViewContext.cs new file mode 100644 index 0000000..cc7bf80 --- /dev/null +++ b/Moonlight/App/Models/Abstractions/Services/ServiceViewContext.cs @@ -0,0 +1,31 @@ +using Microsoft.AspNetCore.Components; +using Moonlight.App.Database.Entities; +using Moonlight.App.Database.Entities.Store; +using Moonlight.App.Helpers; + +namespace Moonlight.App.Models.Abstractions.Services; + +public class ServiceViewContext +{ + // Meta + public Service Service { get; set; } + public User User { get; set; } + public Product Product { get; set; } + + // Content + public List Pages { get; set; } = new(); + public RenderFragment Layout { get; set; } + + public Task AddPage(string name, string route, string icon = "") where T : ComponentBase + { + Pages.Add(new() + { + Name = name, + Route = route, + Icon = icon, + Component = ComponentHelper.FromType() + }); + + return Task.CompletedTask; + } +} \ No newline at end of file diff --git a/Moonlight/App/Plugins/Contexts/PluginContext.cs b/Moonlight/App/Plugins/Contexts/PluginContext.cs index 22a052e..afdf874 100644 --- a/Moonlight/App/Plugins/Contexts/PluginContext.cs +++ b/Moonlight/App/Plugins/Contexts/PluginContext.cs @@ -1,6 +1,4 @@ -using Moonlight.App.Database.Entities; -using Moonlight.App.Database.Entities.Store; -using Moonlight.App.Models.Abstractions; +using Moonlight.App.Models.Abstractions.Services; namespace Moonlight.App.Plugins.Contexts; @@ -13,5 +11,6 @@ public class PluginContext public WebApplication WebApplication { get; set; } public List PreInitTasks = new(); public List PostInitTasks = new(); - public Action, ServiceManageContext>? BuildServiceUiPages = null; + public Action? BuildUserServiceView { get; set; } = null; + public Action? BuildAdminServiceView { get; set; } = null; } \ No newline at end of file diff --git a/Moonlight/App/Plugins/Contexts/ServiceManageContext.cs b/Moonlight/App/Plugins/Contexts/ServiceManageContext.cs deleted file mode 100644 index 29aef27..0000000 --- a/Moonlight/App/Plugins/Contexts/ServiceManageContext.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Moonlight.App.Database.Entities; -using Moonlight.App.Database.Entities.Store; - -namespace Moonlight.App.Plugins.Contexts; - -public class ServiceManageContext -{ - public Service Service { get; set; } - public User User { get; set; } - public Product Product { get; set; } -} \ No newline at end of file diff --git a/Moonlight/App/Services/PluginService.cs b/Moonlight/App/Services/PluginService.cs index 33fa70c..6179460 100644 --- a/Moonlight/App/Services/PluginService.cs +++ b/Moonlight/App/Services/PluginService.cs @@ -3,6 +3,7 @@ using Moonlight.App.Database.Entities; using Moonlight.App.Database.Entities.Store; using Moonlight.App.Helpers; using Moonlight.App.Models.Abstractions; +using Moonlight.App.Models.Abstractions.Services; using Moonlight.App.Plugins; using Moonlight.App.Plugins.Contexts; @@ -108,18 +109,24 @@ public class PluginService } } - public Task BuildServiceUiPages(ServiceUiPage[] pages, ServiceManageContext context) + public Task BuildUserServiceView(ServiceViewContext context) { - var list = pages.ToList(); - foreach (var plugin in Plugins) { - // Only build if the plugin adds a page - if(plugin.Context.BuildServiceUiPages != null) - plugin.Context.BuildServiceUiPages.Invoke(list, context); + plugin.Context.BuildUserServiceView?.Invoke(context); } - return Task.FromResult(list.ToArray()); + return Task.CompletedTask; + } + + public Task BuildAdminServiceView(ServiceViewContext context) + { + foreach (var plugin in Plugins) + { + plugin.Context.BuildAdminServiceView?.Invoke(context); + } + + return Task.CompletedTask; } private string[] FindFiles(string dir) diff --git a/Moonlight/App/Services/ServiceManage/ServiceAdminService.cs b/Moonlight/App/Services/ServiceManage/ServiceAdminService.cs index f427dc5..a22bf95 100644 --- a/Moonlight/App/Services/ServiceManage/ServiceAdminService.cs +++ b/Moonlight/App/Services/ServiceManage/ServiceAdminService.cs @@ -9,17 +9,17 @@ namespace Moonlight.App.Services.ServiceManage; public class ServiceAdminService { private readonly IServiceScopeFactory ServiceScopeFactory; - private readonly ServiceTypeService ServiceTypeService; + private readonly ServiceDefinitionService ServiceDefinitionService; - public ServiceAdminService(IServiceScopeFactory serviceScopeFactory, ServiceTypeService serviceTypeService) + public ServiceAdminService(IServiceScopeFactory serviceScopeFactory, ServiceDefinitionService serviceDefinitionService) { ServiceScopeFactory = serviceScopeFactory; - ServiceTypeService = serviceTypeService; + ServiceDefinitionService = serviceDefinitionService; } public async Task Create(User u, Product p, Action? modifyService = null) { - var impl = ServiceTypeService.Get(p); + var impl = ServiceDefinitionService.Get(p); // Load models in new scope using var scope = ServiceScopeFactory.CreateScope(); @@ -66,7 +66,7 @@ public class ServiceAdminService if (service == null) throw new DisplayException("Service does not exist anymore"); - var impl = ServiceTypeService.Get(service); + var impl = ServiceDefinitionService.Get(service); await impl.Actions.Delete(scope.ServiceProvider, service); diff --git a/Moonlight/App/Services/ServiceManage/ServiceTypeService.cs b/Moonlight/App/Services/ServiceManage/ServiceDefinitionService.cs similarity index 69% rename from Moonlight/App/Services/ServiceManage/ServiceTypeService.cs rename to Moonlight/App/Services/ServiceManage/ServiceDefinitionService.cs index fe9b497..20c59d5 100644 --- a/Moonlight/App/Services/ServiceManage/ServiceTypeService.cs +++ b/Moonlight/App/Services/ServiceManage/ServiceDefinitionService.cs @@ -2,24 +2,25 @@ using Moonlight.App.Database.Entities.Store; using Moonlight.App.Database.Enums; using Moonlight.App.Models.Abstractions; +using Moonlight.App.Models.Abstractions.Services; using Moonlight.App.Repositories; namespace Moonlight.App.Services.ServiceManage; -public class ServiceTypeService +public class ServiceDefinitionService { - private readonly Dictionary ServiceImplementations = new(); + private readonly Dictionary ServiceImplementations = new(); private readonly IServiceScopeFactory ServiceScopeFactory; - public ServiceTypeService(IServiceScopeFactory serviceScopeFactory) + public ServiceDefinitionService(IServiceScopeFactory serviceScopeFactory) { ServiceScopeFactory = serviceScopeFactory; } - public void Register(ServiceType type) where T : ServiceImplementation + public void Register(ServiceType type) where T : ServiceDefinition { - var impl = Activator.CreateInstance() as ServiceImplementation; + var impl = Activator.CreateInstance() as ServiceDefinition; if (impl == null) throw new ArgumentException("The provided type is not an service implementation"); @@ -30,7 +31,7 @@ public class ServiceTypeService ServiceImplementations.Add(type, impl); } - public ServiceImplementation Get(Service s) + public ServiceDefinition Get(Service s) { using var scope = ServiceScopeFactory.CreateScope(); var serviceRepo = scope.ServiceProvider.GetRequiredService>(); @@ -43,9 +44,9 @@ public class ServiceTypeService return Get(service.Product); } - public ServiceImplementation Get(Product p) => Get(p.Type); + public ServiceDefinition Get(Product p) => Get(p.Type); - public ServiceImplementation Get(ServiceType type) + public ServiceDefinition Get(ServiceType type) { if (!ServiceImplementations.ContainsKey(type)) throw new ArgumentException($"No service implementation found for {type}"); diff --git a/Moonlight/App/Services/ServiceManage/ServiceService.cs b/Moonlight/App/Services/ServiceManage/ServiceService.cs index b9420da..24ab12d 100644 --- a/Moonlight/App/Services/ServiceManage/ServiceService.cs +++ b/Moonlight/App/Services/ServiceManage/ServiceService.cs @@ -13,7 +13,7 @@ public class ServiceService // This service is used for managing services and cr private readonly Repository UserRepository; public ServiceAdminService Admin => ServiceProvider.GetRequiredService(); - public ServiceTypeService Type => ServiceProvider.GetRequiredService(); + public ServiceDefinitionService Definition => ServiceProvider.GetRequiredService(); public ServiceManageService Manage => ServiceProvider.GetRequiredService(); public ServiceService(IServiceProvider serviceProvider, Repository serviceRepository, Repository userRepository) diff --git a/Moonlight/App/Services/Store/StoreAdminService.cs b/Moonlight/App/Services/Store/StoreAdminService.cs index a55ba7c..5ebbb6b 100644 --- a/Moonlight/App/Services/Store/StoreAdminService.cs +++ b/Moonlight/App/Services/Store/StoreAdminService.cs @@ -108,7 +108,7 @@ public class StoreAdminService { try { - var impl = ServiceService.Type.Get(type); + var impl = ServiceService.Definition.Get(type); return impl.ConfigType; } catch (ArgumentException) @@ -123,7 +123,7 @@ public class StoreAdminService } public object GetProductConfig(Product product) { - var impl = ServiceService.Type.Get(product.Type); + var impl = ServiceService.Definition.Get(product.Type); return JsonConvert.DeserializeObject(product.ConfigJson, impl.ConfigType) ?? CreateNewProductConfig(product.Type); diff --git a/Moonlight/Program.cs b/Moonlight/Program.cs index 957af06..580ca59 100644 --- a/Moonlight/Program.cs +++ b/Moonlight/Program.cs @@ -80,7 +80,7 @@ builder.Services.AddSingleton(); // Services / ServiceManage builder.Services.AddScoped(); builder.Services.AddSingleton(); -builder.Services.AddSingleton(); +builder.Services.AddSingleton(); builder.Services.AddSingleton(); // Services / Ticketing @@ -123,9 +123,9 @@ app.MapControllers(); // Auto start background services app.Services.GetRequiredService(); -var serviceService = app.Services.GetRequiredService(); +var serviceService = app.Services.GetRequiredService(); -serviceService.Register(ServiceType.Server); +serviceService.Register(ServiceType.Server); await pluginService.RunPrePost(app); diff --git a/Moonlight/Shared/Views/Service/Index.razor b/Moonlight/Shared/Views/Service/Index.razor index 2931317..783ed24 100644 --- a/Moonlight/Shared/Views/Service/Index.razor +++ b/Moonlight/Shared/Views/Service/Index.razor @@ -5,6 +5,7 @@ @using Moonlight.App.Services.ServiceManage @using Microsoft.EntityFrameworkCore @using Moonlight.App.Models.Abstractions +@using Moonlight.App.Models.Abstractions.Services @using Moonlight.App.Services @inject Repository ServiceRepository @@ -20,10 +21,10 @@ else { - + - - @Implementation.GetUserLayout() + + @ViewContext.Layout @@ -40,8 +41,8 @@ public string? Route { get; set; } private Service? Service; - private ServiceImplementation Implementation; - private ServiceUiPage[] ServiceUiPages; + private ServiceDefinition Definition; + private ServiceViewContext ViewContext; private async Task Load(LazyLoader lazyLoader) { @@ -64,29 +65,21 @@ if (Service == null) return; - + // Load implementation await lazyLoader.SetText("Loading implementation"); + Definition = ServiceService.Definition.Get(Service.Product.Type); + + // Build dynamic user interface + await lazyLoader.SetText("Building dynamic user interface"); - Implementation = ServiceService.Type.Get(Service.Product.Type); - - await lazyLoader.SetText("Building ui"); - - // Build ui pages - List pagesWithoutPlugins = new(); - - // -- Add default here -- - - // Add implementation pages - pagesWithoutPlugins.AddRange(Implementation.GetUserPages(Service, IdentityService.CurrentUser)); - - // Modify pages through plugins - ServiceUiPages = await PluginService.BuildServiceUiPages(pagesWithoutPlugins.ToArray(), new() + ViewContext = new ServiceViewContext() { - Product = Service.Product, Service = Service, + Product = Service.Product, User = IdentityService.CurrentUser - }); - - // Done :D + }; + + await Definition.BuildUserView(ViewContext); + await PluginService.BuildUserServiceView(ViewContext); } }