diff --git a/zero.Core/Attributes/CollectionAttribute.cs b/zero.Core/Attributes/CollectionAttribute.cs index 306fcc21..b6c4d9a6 100644 --- a/zero.Core/Attributes/CollectionAttribute.cs +++ b/zero.Core/Attributes/CollectionAttribute.cs @@ -5,7 +5,7 @@ namespace zero.Core.Attributes /// /// This attribute will allow the usage of custom collection names for Raven collections /// - [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] + [AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class, AllowMultiple = false)] public class CollectionAttribute : Attribute { public string Name { get; set; } diff --git a/zero.Core/Mapper/DefaultMapper.cs b/zero.Core/Mapper/DefaultMapper.cs index 59691fcf..3a5cb9af 100644 --- a/zero.Core/Mapper/DefaultMapper.cs +++ b/zero.Core/Mapper/DefaultMapper.cs @@ -32,9 +32,9 @@ namespace zero.Core.Mapper /// - public void Add() where T : IMapperConfig, new() + public void Add() where T : IMapperConfig { - T config = new T(); + T config = Activator.CreateInstance(); config.Configure(this); } @@ -54,19 +54,19 @@ namespace zero.Core.Mapper /// - public async Task Map(TSource source) where TTarget : class, new() + public async Task Map(TSource source) { if (source == null) { - return null; + return default; } - return await Map(source, new TTarget()); + return await Map(source, Activator.CreateInstance()); } /// - public async Task Map(TSource source, TTarget target) where TTarget : class, new() + public async Task Map(TSource source, TTarget target) { if (source == null) { @@ -85,13 +85,13 @@ namespace zero.Core.Mapper /// - public async Task> Map(IEnumerable source) where TTarget : class, new() + public async Task> Map(IEnumerable source) { IList target = new List(); foreach (TSource item in source) { - target.Add(await Map(item, new TTarget())); + target.Add(await Map(item, Activator.CreateInstance())); } return target; @@ -99,13 +99,13 @@ namespace zero.Core.Mapper /// - public async Task> Map(ListResult source) where TTarget : class, new() + public async Task> Map(ListResult source) { IList target = new List(); foreach (TSource item in source.Items) { - target.Add(await Map(item, new TTarget())); + target.Add(await Map(item, Activator.CreateInstance())); } return new ListResult(target, source.TotalItems, source.Page, source.PageSize) @@ -116,19 +116,19 @@ namespace zero.Core.Mapper /// - public async Task> Map(EntityResult source) where TTarget : class, new() + public async Task> Map(EntityResult source) { return new EntityResult() { IsSuccess = source.IsSuccess, Errors = source.Errors, - Model = await Map(source.Model, new TTarget()) + Model = await Map(source.Model, Activator.CreateInstance()) }; } /// - public void CreateMap(Action map) where TTarget : class, new() + public void CreateMap(Action map) { Maps.Add((source, target) => { @@ -139,7 +139,7 @@ namespace zero.Core.Mapper /// - public void CreateMap(Func map) where TTarget : class, new() + public void CreateMap(Func map) { Maps.Add(async (source, target) => { @@ -220,7 +220,7 @@ namespace zero.Core.Mapper public interface IMapper { /// - void Add() where T : IMapperConfig, new(); + void Add() where T : IMapperConfig; /// void Add(Assembly assembly); @@ -228,34 +228,34 @@ namespace zero.Core.Mapper /// /// Map an object to the target type /// - Task Map(TSource source) where TTarget : class, new(); + Task Map(TSource source); /// /// Map an object to the target type given an already existing target instance /// - Task Map(TSource source, TTarget target) where TTarget : class, new(); + Task Map(TSource source, TTarget target); /// /// Map a list of objects to the target type /// - Task> Map(IEnumerable source) where TTarget : class, new(); + Task> Map(IEnumerable source); /// /// Map a list result containing objects to the target type /// - Task> Map(ListResult source) where TTarget : class, new(); + Task> Map(ListResult source); /// /// Map an entity result to the target type /// - Task> Map(EntityResult source) where TTarget : class, new(); + Task> Map(EntityResult source); /// /// Create a mapping from source to target object /// - void CreateMap(Action map) where TTarget : class, new(); + void CreateMap(Action map); /// - void CreateMap(Func map) where TTarget : class, new(); + void CreateMap(Func map); } } \ No newline at end of file diff --git a/zero.Core/Options/TypeOptions.cs b/zero.Core/Options/TypeOptions.cs new file mode 100644 index 00000000..256c122c --- /dev/null +++ b/zero.Core/Options/TypeOptions.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; + +namespace zero.Core.Options +{ + public class TypeOptions : IZeroCollectionOptions + { + Dictionary Items { get; set; } = new Dictionary(); + + internal void Add() where TTarget : T + { + Items[typeof(T)] = typeof(TTarget); + } + } +} diff --git a/zero.Core/Options/ZeroOptions.cs b/zero.Core/Options/ZeroOptions.cs index 8cbbcf4f..94c487dd 100644 --- a/zero.Core/Options/ZeroOptions.cs +++ b/zero.Core/Options/ZeroOptions.cs @@ -1,5 +1,8 @@ -using System.Collections.Generic; +using FluentValidation; +using System.Collections.Generic; +using zero.Core.Mapper; using zero.Core.Plugins; +using zero.Core.Renderer; namespace zero.Core.Options { @@ -19,6 +22,7 @@ namespace zero.Core.Options Settings = new SettingsOptions(); Spaces = new SpaceOptions(); Mapper = new MapperOptions(); + Types = new TypeOptions(); } /// @@ -65,6 +69,20 @@ namespace zero.Core.Options /// public MapperOptions Mapper { get; private set; } + + /// + public TypeOptions Types { get; private set; } + + /// + public void Extend() where TTarget : T + { + Types.Add(); + } + + public ZeroExtend Extend() + { + return new ZeroExtend(); + } } @@ -149,10 +167,53 @@ namespace zero.Core.Options /// MapperOptions Mapper { get; } + /// + /// + /// + TypeOptions Types { get; } + + /// + void Extend() where TTarget : T; + + ZeroExtend Extend(); /// /// Default settings for the backoffice /// //IZeroPluginConfiguration Backoffice { get; set; } } + + + public class ZeroExtend + { + public ZeroExtend Use() where TTarget : T + { + return this; + } + + public ZeroExtend Use() + where TTarget : T + where TRenderer : IRenderer + { + return this; + } + + public ZeroExtend Use() + where TTarget : T + where TRenderer : IRenderer + where TValidator : IValidator + { + return this; + } + + + public ZeroExtend Use() + where TTarget : T + where TRenderer : IRenderer + where TValidator : IValidator + where TMapper : IMapperConfig + { + return this; + } + } } diff --git a/zero.Core/Renderer/AbstractRenderer.cs b/zero.Core/Renderer/AbstractRenderer.cs index cd272b87..8e0647e2 100644 --- a/zero.Core/Renderer/AbstractRenderer.cs +++ b/zero.Core/Renderer/AbstractRenderer.cs @@ -22,7 +22,7 @@ namespace zero.Core.Renderer } - public abstract class AbstractRenderer : IRenderer, IRenderer where T : new() + public abstract class AbstractRenderer : IRenderer, IRenderer { const string METHOD_FIELD = "field"; diff --git a/zero.Debug/Models/SalesChannel.cs b/zero.Debug/Models/SalesChannel.cs new file mode 100644 index 00000000..e530925f --- /dev/null +++ b/zero.Debug/Models/SalesChannel.cs @@ -0,0 +1,9 @@ +using zero.Commerce.Entities; + +namespace zero.Debug.Models +{ + public class SalesChannel : Channel + { + public string Description { get; set; } + } +} diff --git a/zero.Debug/Models/SalesChannelRenderer.cs b/zero.Debug/Models/SalesChannelRenderer.cs new file mode 100644 index 00000000..9501dd4b --- /dev/null +++ b/zero.Debug/Models/SalesChannelRenderer.cs @@ -0,0 +1,46 @@ +using zero.Commerce.Entities; +using zero.Core.Renderer; +using zero.Debug.Models; + +namespace zero.Commerce.Backoffice +{ + public class SalesChannelRenderer : AbstractRenderer + { + public SalesChannelRenderer() : base() + { + + Field(x => x.Name, required: false).Text(); + + //Field(x => x.Name, "@ui.name", required: true, noDescription: true).Text(); + + //Field(x => x.CheckoutType).State(opts => + //{ + // opts.Add("@channel.checkout_states.none", ChannelCheckoutType.None); + // opts.Add("@channel.checkout_states.order", ChannelCheckoutType.Order); + // opts.Add("@channel.checkout_states.request", ChannelCheckoutType.Request); + // opts.Add("@channel.checkout_states.both", ChannelCheckoutType.All); + //}); + //Field(x => x.ProductSorting).State(opts => + //{ + // opts.Add("@channel.sorting_states.relevance", ChannelProductSorting.Relevance); + // opts.Add("@channel.sorting_states.new", ChannelProductSorting.New); + // opts.Add("@channel.sorting_states.price", ChannelProductSorting.Price); + //}); + + //Tab("@channel.tabs.theme", () => + //{ + // Field(x => x.Theme.ImageId, required: true).Text(); + //}); + + //Tab("@channel.tabs.settings", () => + //{ + // Field(x => x.ClientNo).Text(); + // Field(x => x.SortLetter).Text(opts => + // { + // opts.Classes.Add("is-short"); + // opts.MaxLength = 1; + // }); + //}); + } + } +} diff --git a/zero.Debug/Startup.cs b/zero.Debug/Startup.cs index bebd2461..161c6ef2 100644 --- a/zero.Debug/Startup.cs +++ b/zero.Debug/Startup.cs @@ -1,3 +1,4 @@ +using FluentValidation; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; @@ -5,6 +6,10 @@ using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; +using zero.Commerce.Backoffice; +using zero.Commerce.Entities; +using zero.Core.Renderer; +using zero.Debug.Models; using zero.TestData; using zero.Web; @@ -39,6 +44,15 @@ namespace zero.Debug zero.AddPlugin(); zero.AddPlugin(); + zero.WithOptions(opts => + { + opts.Extend(); + + //IRenderer renderer = (IRenderer)new SalesChannelRenderer(); + //renderer. + //opts.Renderers.Extend(); + }); + services.AddMvc(); services.Configure(opts => opts.AutomaticAuthentication = false); diff --git a/zero.Web.UI/App/editor/editor.vue b/zero.Web.UI/App/editor/editor.vue index 1bfab858..a0321381 100644 --- a/zero.Web.UI/App/editor/editor.vue +++ b/zero.Web.UI/App/editor/editor.vue @@ -6,6 +6,9 @@