From d55490dd5180b65d889c07be7d671c7210afd5fe Mon Sep 17 00:00:00 2001 From: Baumgartner Marcel Date: Tue, 14 Nov 2023 17:54:15 +0100 Subject: [PATCH] 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 @@
- -
-
- - +
+
+ +
- -
-
- - +
+
+ +