From d55490dd5180b65d889c07be7d671c7210afd5fe Mon Sep 17 00:00:00 2001 From: Baumgartner Marcel Date: Tue, 14 Nov 2023 17:54:15 +0100 Subject: [PATCH 1/5] Started working on service implementation api --- Moonlight/App/Actions/Dummy/DummyConfig.cs | 13 +++ .../Dummy/DummyServiceImplementation.cs | 34 +++++++ .../Actions/Dummy/Layouts/DummyAdmin.razor | 5 + .../App/Actions/Dummy/Layouts/DummyUser.razor | 5 + .../App/Actions/Dummy/Pages/DummyPage.razor | 5 + Moonlight/App/Helpers/ComponentHelper.cs | 10 +- .../Abstractions/ServiceImplementation.cs | 18 ++++ .../App/Models/Abstractions/ServiceUiPage.cs | 11 +++ Moonlight/App/Models/Enums/Permission.cs | 1 + .../App/Plugins/Contexts/PluginContext.cs | 7 +- .../Plugins/Contexts/ServiceManageContext.cs | 11 +++ Moonlight/App/Services/PluginService.cs | 17 ++++ .../ServiceManage/ServiceAdminService.cs | 25 ++--- .../ServiceManage/ServiceManageService.cs | 48 ++++++++++ .../Services/ServiceManage/ServiceService.cs | 2 + .../ServiceManage/ServiceTypeService.cs | 55 +++++++++++ .../App/Services/Store/StoreAdminService.cs | 48 +++++++++- .../App/Services/Users/UserDeleteService.cs | 16 +++- Moonlight/Program.cs | 7 +- .../Shared/Components/Forms/AutoForm.razor | 17 ++-- .../Components/Forms/AutoProperty.razor | 14 +-- .../Forms/DynamicTypedAutoForm.razor | 19 ++++ .../Shared/Components/Store/StoreModals.razor | 62 +++++++++---- .../Shared/Views/Admin/Sys/Settings.razor | 19 ++-- Moonlight/Shared/Views/Service/Index.razor | 92 +++++++++++++++++++ Moonlight/Shared/Views/Services/Index.razor | 2 +- 26 files changed, 494 insertions(+), 69 deletions(-) create mode 100644 Moonlight/App/Actions/Dummy/DummyConfig.cs create mode 100644 Moonlight/App/Actions/Dummy/DummyServiceImplementation.cs create mode 100644 Moonlight/App/Actions/Dummy/Layouts/DummyAdmin.razor create mode 100644 Moonlight/App/Actions/Dummy/Layouts/DummyUser.razor create mode 100644 Moonlight/App/Actions/Dummy/Pages/DummyPage.razor create mode 100644 Moonlight/App/Models/Abstractions/ServiceImplementation.cs create mode 100644 Moonlight/App/Models/Abstractions/ServiceUiPage.cs create mode 100644 Moonlight/App/Plugins/Contexts/ServiceManageContext.cs create mode 100644 Moonlight/App/Services/ServiceManage/ServiceManageService.cs create mode 100644 Moonlight/App/Services/ServiceManage/ServiceTypeService.cs create mode 100644 Moonlight/Shared/Components/Forms/DynamicTypedAutoForm.razor create mode 100644 Moonlight/Shared/Views/Service/Index.razor diff --git a/Moonlight/App/Actions/Dummy/DummyConfig.cs b/Moonlight/App/Actions/Dummy/DummyConfig.cs new file mode 100644 index 00000000..8d1c1842 --- /dev/null +++ b/Moonlight/App/Actions/Dummy/DummyConfig.cs @@ -0,0 +1,13 @@ +using System.ComponentModel; +using Moonlight.App.Database.Entities; +using Moonlight.App.Extensions.Attributes; + +namespace Moonlight.App.Actions.Dummy; + +public class DummyConfig +{ + [Description("Some description")] + public string String { get; set; } = ""; + public bool Boolean { get; set; } + public int Integer { get; set; } +} \ No newline at end of file diff --git a/Moonlight/App/Actions/Dummy/DummyServiceImplementation.cs b/Moonlight/App/Actions/Dummy/DummyServiceImplementation.cs new file mode 100644 index 00000000..6c33141e --- /dev/null +++ b/Moonlight/App/Actions/Dummy/DummyServiceImplementation.cs @@ -0,0 +1,34 @@ +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/Actions/Dummy/Layouts/DummyAdmin.razor b/Moonlight/App/Actions/Dummy/Layouts/DummyAdmin.razor new file mode 100644 index 00000000..0f7abae0 --- /dev/null +++ b/Moonlight/App/Actions/Dummy/Layouts/DummyAdmin.razor @@ -0,0 +1,5 @@ +

DummyAdmin

+ +@code { + +} \ No newline at end of file diff --git a/Moonlight/App/Actions/Dummy/Layouts/DummyUser.razor b/Moonlight/App/Actions/Dummy/Layouts/DummyUser.razor new file mode 100644 index 00000000..fb0c0ca5 --- /dev/null +++ b/Moonlight/App/Actions/Dummy/Layouts/DummyUser.razor @@ -0,0 +1,5 @@ +

DummyUser

+ +@code { + +} \ No newline at end of file diff --git a/Moonlight/App/Actions/Dummy/Pages/DummyPage.razor b/Moonlight/App/Actions/Dummy/Pages/DummyPage.razor new file mode 100644 index 00000000..b465c859 --- /dev/null +++ b/Moonlight/App/Actions/Dummy/Pages/DummyPage.razor @@ -0,0 +1,5 @@ +

DummyPage

+ +@code { + +} \ No newline at end of file diff --git a/Moonlight/App/Helpers/ComponentHelper.cs b/Moonlight/App/Helpers/ComponentHelper.cs index 45871641..f3f3ad7f 100644 --- a/Moonlight/App/Helpers/ComponentHelper.cs +++ b/Moonlight/App/Helpers/ComponentHelper.cs @@ -4,9 +4,17 @@ namespace Moonlight.App.Helpers; public static class ComponentHelper { - public static RenderFragment FromType(Type type) => builder => + public static RenderFragment FromType(Type type, Action>? buildAttributes = null) => builder => { builder.OpenComponent(0, type); + + if (buildAttributes != null) + { + Dictionary parameters = new(); + buildAttributes.Invoke(parameters); + builder.AddMultipleAttributes(1, parameters); + } + builder.CloseComponent(); }; } \ No newline at end of file diff --git a/Moonlight/App/Models/Abstractions/ServiceImplementation.cs b/Moonlight/App/Models/Abstractions/ServiceImplementation.cs new file mode 100644 index 00000000..7478b6b9 --- /dev/null +++ b/Moonlight/App/Models/Abstractions/ServiceImplementation.cs @@ -0,0 +1,18 @@ +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/ServiceUiPage.cs b/Moonlight/App/Models/Abstractions/ServiceUiPage.cs new file mode 100644 index 00000000..b50d42ab --- /dev/null +++ b/Moonlight/App/Models/Abstractions/ServiceUiPage.cs @@ -0,0 +1,11 @@ +using Microsoft.AspNetCore.Components; + +namespace Moonlight.App.Models.Abstractions; + +public class ServiceUiPage +{ + public string Name { get; set; } + public string Route { get; set; } + public string Icon { get; set; } + public ComponentBase Component { get; set; } +} \ No newline at end of file diff --git a/Moonlight/App/Models/Enums/Permission.cs b/Moonlight/App/Models/Enums/Permission.cs index 677bf9d8..d342dde8 100644 --- a/Moonlight/App/Models/Enums/Permission.cs +++ b/Moonlight/App/Models/Enums/Permission.cs @@ -10,6 +10,7 @@ public enum Permission AdminUsersEdit = 1003, AdminTickets = 1004, AdminCommunity = 1030, + AdminServices = 1050, AdminStore = 1900, AdminViewExceptions = 1999, AdminRoot = 2000 diff --git a/Moonlight/App/Plugins/Contexts/PluginContext.cs b/Moonlight/App/Plugins/Contexts/PluginContext.cs index 90ba8324..22a052ea 100644 --- a/Moonlight/App/Plugins/Contexts/PluginContext.cs +++ b/Moonlight/App/Plugins/Contexts/PluginContext.cs @@ -1,4 +1,8 @@ -namespace Moonlight.App.Plugins.Contexts; +using Moonlight.App.Database.Entities; +using Moonlight.App.Database.Entities.Store; +using Moonlight.App.Models.Abstractions; + +namespace Moonlight.App.Plugins.Contexts; public class PluginContext { @@ -9,4 +13,5 @@ public class PluginContext public WebApplication WebApplication { get; set; } public List PreInitTasks = new(); public List PostInitTasks = new(); + public Action, ServiceManageContext>? BuildServiceUiPages = null; } \ No newline at end of file diff --git a/Moonlight/App/Plugins/Contexts/ServiceManageContext.cs b/Moonlight/App/Plugins/Contexts/ServiceManageContext.cs new file mode 100644 index 00000000..29aef27f --- /dev/null +++ b/Moonlight/App/Plugins/Contexts/ServiceManageContext.cs @@ -0,0 +1,11 @@ +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 81a3712d..33fa70cf 100644 --- a/Moonlight/App/Services/PluginService.cs +++ b/Moonlight/App/Services/PluginService.cs @@ -1,5 +1,8 @@ using System.Reflection; +using Moonlight.App.Database.Entities; +using Moonlight.App.Database.Entities.Store; using Moonlight.App.Helpers; +using Moonlight.App.Models.Abstractions; using Moonlight.App.Plugins; using Moonlight.App.Plugins.Contexts; @@ -105,6 +108,20 @@ public class PluginService } } + public Task BuildServiceUiPages(ServiceUiPage[] pages, ServiceManageContext 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); + } + + return Task.FromResult(list.ToArray()); + } + private string[] FindFiles(string dir) { var result = new List(); diff --git a/Moonlight/App/Services/ServiceManage/ServiceAdminService.cs b/Moonlight/App/Services/ServiceManage/ServiceAdminService.cs index 2fe7b46e..f427dc51 100644 --- a/Moonlight/App/Services/ServiceManage/ServiceAdminService.cs +++ b/Moonlight/App/Services/ServiceManage/ServiceAdminService.cs @@ -1,27 +1,25 @@ using Microsoft.EntityFrameworkCore; using Moonlight.App.Database.Entities; using Moonlight.App.Database.Entities.Store; -using Moonlight.App.Database.Enums; using Moonlight.App.Exceptions; -using Moonlight.App.Models.Abstractions; using Moonlight.App.Repositories; namespace Moonlight.App.Services.ServiceManage; public class ServiceAdminService { - public readonly Dictionary Actions = new(); private readonly IServiceScopeFactory ServiceScopeFactory; + private readonly ServiceTypeService ServiceTypeService; - public ServiceAdminService(IServiceScopeFactory serviceScopeFactory) + public ServiceAdminService(IServiceScopeFactory serviceScopeFactory, ServiceTypeService serviceTypeService) { ServiceScopeFactory = serviceScopeFactory; + ServiceTypeService = serviceTypeService; } public async Task Create(User u, Product p, Action? modifyService = null) { - if (!Actions.ContainsKey(p.Type)) - throw new DisplayException($"The product type {p.Type} is not registered"); + var impl = ServiceTypeService.Get(p); // Load models in new scope using var scope = ServiceScopeFactory.CreateScope(); @@ -49,8 +47,7 @@ public class ServiceAdminService var finishedService = serviceRepo.Add(service); // Call the action for the logic behind the service type - var actions = Actions[product.Type]; - await actions.Create(scope.ServiceProvider, finishedService); + await impl.Actions.Create(scope.ServiceProvider, finishedService); return finishedService; } @@ -63,17 +60,15 @@ public class ServiceAdminService var service = serviceRepo .Get() - .Include(x => x.Product) .Include(x => x.Shares) .FirstOrDefault(x => x.Id == s.Id); if (service == null) throw new DisplayException("Service does not exist anymore"); - if (!Actions.ContainsKey(service.Product.Type)) - throw new DisplayException($"The product type {service.Product.Type} is not registered"); + var impl = ServiceTypeService.Get(service); - await Actions[service.Product.Type].Delete(scope.ServiceProvider, service); + await impl.Actions.Delete(scope.ServiceProvider, service); foreach (var share in service.Shares.ToArray()) { @@ -82,10 +77,4 @@ public class ServiceAdminService serviceRepo.Delete(service); } - - public Task RegisterAction(ServiceType type, ServiceActions actions) // Use this function to register service types - { - Actions.Add(type, actions); - return Task.CompletedTask; - } } \ No newline at end of file diff --git a/Moonlight/App/Services/ServiceManage/ServiceManageService.cs b/Moonlight/App/Services/ServiceManage/ServiceManageService.cs new file mode 100644 index 00000000..140555b2 --- /dev/null +++ b/Moonlight/App/Services/ServiceManage/ServiceManageService.cs @@ -0,0 +1,48 @@ +using Microsoft.EntityFrameworkCore; +using Moonlight.App.Database.Entities; +using Moonlight.App.Database.Entities.Store; +using Moonlight.App.Models.Abstractions; +using Moonlight.App.Models.Enums; +using Moonlight.App.Repositories; + +namespace Moonlight.App.Services.ServiceManage; + +public class ServiceManageService +{ + private readonly IServiceScopeFactory ServiceScopeFactory; + + public ServiceManageService(IServiceScopeFactory serviceScopeFactory) + { + ServiceScopeFactory = serviceScopeFactory; + } + + public Task CheckAccess(Service s, User user) + { + var permissionStorage = new PermissionStorage(user.Permissions); + + // Is admin? + if(permissionStorage[Permission.AdminServices]) + return Task.FromResult(true); + + using var scope = ServiceScopeFactory.CreateScope(); + var serviceRepo = scope.ServiceProvider.GetRequiredService>(); + + var service = serviceRepo + .Get() + .Include(x => x.Owner) + .Include(x => x.Shares) + .ThenInclude(x => x.User) + .First(x => x.Id == s.Id); + + // Is owner? + if(service.Owner.Id == user.Id) + return Task.FromResult(true); + + // Is shared user + if(service.Shares.Any(x => x.User.Id == user.Id)) + return Task.FromResult(true); + + // No match + return Task.FromResult(false); + } +} \ No newline at end of file diff --git a/Moonlight/App/Services/ServiceManage/ServiceService.cs b/Moonlight/App/Services/ServiceManage/ServiceService.cs index c0e4a71c..b9420da9 100644 --- a/Moonlight/App/Services/ServiceManage/ServiceService.cs +++ b/Moonlight/App/Services/ServiceManage/ServiceService.cs @@ -13,6 +13,8 @@ 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 ServiceManageService Manage => ServiceProvider.GetRequiredService(); public ServiceService(IServiceProvider serviceProvider, Repository serviceRepository, Repository userRepository) { diff --git a/Moonlight/App/Services/ServiceManage/ServiceTypeService.cs b/Moonlight/App/Services/ServiceManage/ServiceTypeService.cs new file mode 100644 index 00000000..fe9b4971 --- /dev/null +++ b/Moonlight/App/Services/ServiceManage/ServiceTypeService.cs @@ -0,0 +1,55 @@ +using Microsoft.EntityFrameworkCore; +using Moonlight.App.Database.Entities.Store; +using Moonlight.App.Database.Enums; +using Moonlight.App.Models.Abstractions; +using Moonlight.App.Repositories; + +namespace Moonlight.App.Services.ServiceManage; + +public class ServiceTypeService +{ + private readonly Dictionary ServiceImplementations = new(); + + private readonly IServiceScopeFactory ServiceScopeFactory; + + public ServiceTypeService(IServiceScopeFactory serviceScopeFactory) + { + ServiceScopeFactory = serviceScopeFactory; + } + + public void Register(ServiceType type) where T : ServiceImplementation + { + var impl = Activator.CreateInstance() as ServiceImplementation; + + if (impl == null) + throw new ArgumentException("The provided type is not an service implementation"); + + if (ServiceImplementations.ContainsKey(type)) + throw new ArgumentException($"An implementation for {type} has already been registered"); + + ServiceImplementations.Add(type, impl); + } + + public ServiceImplementation Get(Service s) + { + using var scope = ServiceScopeFactory.CreateScope(); + var serviceRepo = scope.ServiceProvider.GetRequiredService>(); + + var service = serviceRepo + .Get() + .Include(x => x.Product) + .First(x => x.Id == s.Id); + + return Get(service.Product); + } + + public ServiceImplementation Get(Product p) => Get(p.Type); + + public ServiceImplementation Get(ServiceType type) + { + if (!ServiceImplementations.ContainsKey(type)) + throw new ArgumentException($"No service implementation found for {type}"); + + return ServiceImplementations[type]; + } +} \ No newline at end of file diff --git a/Moonlight/App/Services/Store/StoreAdminService.cs b/Moonlight/App/Services/Store/StoreAdminService.cs index 889708c2..a55ba7cb 100644 --- a/Moonlight/App/Services/Store/StoreAdminService.cs +++ b/Moonlight/App/Services/Store/StoreAdminService.cs @@ -2,6 +2,8 @@ using Moonlight.App.Database.Enums; using Moonlight.App.Exceptions; using Moonlight.App.Repositories; +using Moonlight.App.Services.ServiceManage; +using Newtonsoft.Json; namespace Moonlight.App.Services.Store; @@ -9,11 +11,16 @@ public class StoreAdminService { private readonly Repository ProductRepository; private readonly Repository CategoryRepository; + private readonly ServiceService ServiceService; - public StoreAdminService(Repository productRepository, Repository categoryRepository) + public StoreAdminService( + Repository productRepository, + Repository categoryRepository, + ServiceService serviceService) { ProductRepository = productRepository; CategoryRepository = categoryRepository; + ServiceService = serviceService; } public Task AddCategory(string name, string description, string slug) @@ -31,8 +38,7 @@ public class StoreAdminService return Task.FromResult(result); } - public Task AddProduct(string name, string description, string slug, ServiceType type, string configJson, - Action? modifyProduct = null) + public Task AddProduct(string name, string description, string slug, ServiceType type, Action? modifyProduct = null) { if (ProductRepository.Get().Any(x => x.Slug == slug)) throw new DisplayException("A product with that slug does already exist"); @@ -43,7 +49,7 @@ public class StoreAdminService Description = description, Slug = slug, Type = type, - ConfigJson = configJson + ConfigJson = "{}" }; if(modifyProduct != null) @@ -68,7 +74,7 @@ public class StoreAdminService { if (ProductRepository.Get().Any(x => x.Id != product.Id && x.Slug == product.Slug)) throw new DisplayException("A product with that slug does already exist"); - + ProductRepository.Update(product); return Task.CompletedTask; @@ -96,4 +102,36 @@ public class StoreAdminService return Task.CompletedTask; } + + // Product config + public Type GetProductConfigType(ServiceType type) + { + try + { + var impl = ServiceService.Type.Get(type); + return impl.ConfigType; + } + catch (ArgumentException) + { + return typeof(object); + } + } + public object CreateNewProductConfig(ServiceType type) + { + var config = Activator.CreateInstance(GetProductConfigType(type))!; + return config; + } + public object GetProductConfig(Product product) + { + var impl = ServiceService.Type.Get(product.Type); + + return JsonConvert.DeserializeObject(product.ConfigJson, impl.ConfigType) ?? + CreateNewProductConfig(product.Type); + } + + public void SaveProductConfig(Product product, object config) + { + product.ConfigJson = JsonConvert.SerializeObject(config); + ProductRepository.Update(product); + } } \ No newline at end of file diff --git a/Moonlight/App/Services/Users/UserDeleteService.cs b/Moonlight/App/Services/Users/UserDeleteService.cs index 025802cf..6280c16e 100644 --- a/Moonlight/App/Services/Users/UserDeleteService.cs +++ b/Moonlight/App/Services/Users/UserDeleteService.cs @@ -12,6 +12,7 @@ namespace Moonlight.App.Services.Users; public class UserDeleteService { private readonly Repository ServiceRepository; + private readonly Repository ServiceShareRepository; private readonly Repository PostRepository; private readonly Repository UserRepository; private readonly Repository TransactionRepository; @@ -32,7 +33,8 @@ public class UserDeleteService Repository couponUseRepository, Repository transactionRepository, Repository ticketRepository, - Repository ticketMessageRepository) + Repository ticketMessageRepository, + Repository serviceShareRepository) { ServiceRepository = serviceRepository; ServiceService = serviceService; @@ -44,6 +46,7 @@ public class UserDeleteService TransactionRepository = transactionRepository; TicketRepository = ticketRepository; TicketMessageRepository = ticketMessageRepository; + ServiceShareRepository = serviceShareRepository; } public async Task Perform(User user) @@ -83,6 +86,17 @@ public class UserDeleteService await ServiceService.Admin.Delete(service); } + // Service shares + var shares = ServiceShareRepository + .Get() + .Where(x => x.User.Id == user.Id) + .ToArray(); + + foreach (var share in shares) + { + ServiceShareRepository.Delete(share); + } + // Transactions - Coupons - Gift codes var userWithDetails = UserRepository .Get() diff --git a/Moonlight/Program.cs b/Moonlight/Program.cs index b33d43e3..957af06a 100644 --- a/Moonlight/Program.cs +++ b/Moonlight/Program.cs @@ -80,6 +80,8 @@ builder.Services.AddSingleton(); // Services / ServiceManage builder.Services.AddScoped(); builder.Services.AddSingleton(); +builder.Services.AddSingleton(); +builder.Services.AddSingleton(); // Services / Ticketing builder.Services.AddScoped(); @@ -121,8 +123,9 @@ app.MapControllers(); // Auto start background services app.Services.GetRequiredService(); -var serviceService = app.Services.GetRequiredService(); -await serviceService.RegisterAction(ServiceType.Server, new DummyActions()); +var serviceService = app.Services.GetRequiredService(); + +serviceService.Register(ServiceType.Server); await pluginService.RunPrePost(app); diff --git a/Moonlight/Shared/Components/Forms/AutoForm.razor b/Moonlight/Shared/Components/Forms/AutoForm.razor index 553c3d6e..3135cf1b 100644 --- a/Moonlight/Shared/Components/Forms/AutoForm.razor +++ b/Moonlight/Shared/Components/Forms/AutoForm.razor @@ -5,15 +5,16 @@ @foreach (var prop in typeof(TForm).GetProperties()) {
- - - @{ - var typeToCreate = typeof(AutoProperty<>).MakeGenericType(prop.PropertyType); - } + @{ + var typeToCreate = typeof(AutoProperty<>).MakeGenericType(prop.PropertyType); + var rf = ComponentHelper.FromType(typeToCreate, parameters => + { + parameters.Add("Data", Model); + parameters.Add("Property", prop); + }); + } - @ComponentHelper.FromType(typeToCreate) - - + @rf
} diff --git a/Moonlight/Shared/Components/Forms/AutoProperty.razor b/Moonlight/Shared/Components/Forms/AutoProperty.razor index ae7616dd..202b542a 100644 --- a/Moonlight/Shared/Components/Forms/AutoProperty.razor +++ b/Moonlight/Shared/Components/Forms/AutoProperty.razor @@ -94,14 +94,14 @@ var prop = typeof(TProp).GetProperties().First(x => x.Name == attribute.DisplayProp); return prop.GetValue(x) as string ?? "N/A"; }); - + var searchFunc = new Func(x => { var prop = typeof(TProp).GetProperties().First(x => x.Name == attribute.SelectorProp); return prop.GetValue(x) as string ?? "N/A"; }); - - + + } else { @@ -110,8 +110,8 @@ var prop = typeof(TProp).GetProperties().First(x => x.Name == attribute.DisplayProp); return prop.GetValue(x) as string ?? "N/A"; }); - - + + } } } @@ -119,10 +119,10 @@ @code { - [CascadingParameter(Name = "Data")] + [Parameter] public object Data { get; set; } - [CascadingParameter(Name = "Property")] + [Parameter] public PropertyInfo Property { get; set; } private PropBinder Binder; diff --git a/Moonlight/Shared/Components/Forms/DynamicTypedAutoForm.razor b/Moonlight/Shared/Components/Forms/DynamicTypedAutoForm.razor new file mode 100644 index 00000000..25047634 --- /dev/null +++ b/Moonlight/Shared/Components/Forms/DynamicTypedAutoForm.razor @@ -0,0 +1,19 @@ +@{ + var typeToCreate = typeof(AutoForm<>).MakeGenericType(Model.GetType()); + var rf = ComponentHelper.FromType(typeToCreate, parameter => + { + parameter.Add("Model", Model); + parameter.Add("Columns", Columns); + }); +} + +@rf + +@code +{ + [Parameter] + public object Model { get; set; } + + [Parameter] + public int Columns { get; set; } = 6; +} \ No newline at end of file diff --git a/Moonlight/Shared/Components/Store/StoreModals.razor b/Moonlight/Shared/Components/Store/StoreModals.razor index d75850ce..dc4bac30 100644 --- a/Moonlight/Shared/Components/Store/StoreModals.razor +++ b/Moonlight/Shared/Components/Store/StoreModals.razor @@ -109,14 +109,13 @@
- -
-
- - +
+
+ +
- -
-
- - +
+
+ +
From e8706cad1c5af66e7837937792ce7d2fde56111a Mon Sep 17 00:00:00 2001 From: Baumgartner Marcel Date: Wed, 15 Nov 2023 10:25:28 +0100 Subject: [PATCH 2/5] 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 (64%) 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 1970ddcb..ba00b190 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 8d1c1842..6076d0b9 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 00000000..1d386a10 --- /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 6c33141e..00000000 --- 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 f3f3ad7f..754bd6b9 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 6ae14d84..00000000 --- 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 7478b6b9..00000000 --- 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 00000000..dfc010ed --- /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 00000000..0aafded1 --- /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 64% rename from Moonlight/App/Models/Abstractions/ServiceUiPage.cs rename to Moonlight/App/Models/Abstractions/Services/ServiceUiPage.cs index b50d42ab..19a0ef0c 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 00000000..cc7bf805 --- /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 22a052ea..afdf874b 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 29aef27f..00000000 --- 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 33fa70cf..6179460f 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 f427dc51..a22bf95d 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 fe9b4971..20c59d50 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 b9420da9..24ab12df 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 a55ba7cb..5ebbb6b5 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 957af06a..580ca593 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 29313170..783ed240 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); } } From 0f989a38c3c4c4cf91f6e473c4b1f8ea8f41a142 Mon Sep 17 00:00:00 2001 From: Baumgartner Marcel Date: Wed, 15 Nov 2023 11:05:12 +0100 Subject: [PATCH 3/5] Implemented service admin view --- .../Shared/Components/Partials/Sidebar.razor | 17 +++- .../Shared/Views/Admin/Services/Index.razor | 71 ++++++++++++++++ .../Shared/Views/Admin/Services/View.razor | 81 +++++++++++++++++++ Moonlight/Shared/Views/Service/Index.razor | 1 - 4 files changed, 166 insertions(+), 4 deletions(-) create mode 100644 Moonlight/Shared/Views/Admin/Services/Index.razor create mode 100644 Moonlight/Shared/Views/Admin/Services/View.razor diff --git a/Moonlight/Shared/Components/Partials/Sidebar.razor b/Moonlight/Shared/Components/Partials/Sidebar.razor index eaec4317..e21c3e9b 100644 --- a/Moonlight/Shared/Components/Partials/Sidebar.razor +++ b/Moonlight/Shared/Components/Partials/Sidebar.razor @@ -84,6 +84,17 @@ + + - + - + - +