diff --git a/zero.Core/Api/SpacesApi.cs b/zero.Core/Api/SpacesApi.cs index ff35cd56..bc98a965 100644 --- a/zero.Core/Api/SpacesApi.cs +++ b/zero.Core/Api/SpacesApi.cs @@ -1,4 +1,5 @@ -using Microsoft.Extensions.Options; +using FluentValidation.Results; +using Microsoft.Extensions.Options; using Raven.Client.Documents; using Raven.Client.Documents.Linq; using Raven.Client.Documents.Session; @@ -39,15 +40,32 @@ namespace zero.Core.Api } + /// + public async Task GetItem(string alias) where T : SpaceContent + { + using (IAsyncDocumentSession session = Raven.OpenAsyncSession()) + { + return await session.Query() + .Where(x => x.SpaceAlias == alias) + .ProjectInto() + .FirstOrDefaultAsync(); + } + } + + /// public async Task> GetList(string alias) where T : SpaceContent { using (IAsyncDocumentSession session = Raven.OpenAsyncSession()) { - return await session.Query().ProjectInto().ToListAsync(); + return await session.Query() + .Where(x => x.SpaceAlias == alias) + .ProjectInto() + .ToListAsync(); } } + /// public async Task> GetListByQuery(string alias, ListQuery query, string appId = null) where T : SpaceContent { @@ -57,10 +75,40 @@ namespace zero.Core.Api { return await session.Query() .ForApp(appId) - .Where(x => x.Alias == alias) + .Where(x => x.SpaceAlias == alias) .ToQueriedListAsync(query); } } + + + /// + public async Task> Save(string alias, T model) where T : SpaceContent + { + Space space = Options.Spaces.GetByAlias(alias); + //ValidationResult validation = await new CountryValidator().ValidateAsync(model); + + //if (!validation.IsValid) + //{ + // return EntityResult.Fail(validation); + //} + + if (model.Id.IsNullOrEmpty()) + { + model.AppId = "zero.applications.1-A"; // TODO real app id + model.CreatedDate = DateTimeOffset.Now; + } + + model.SpaceAlias = alias; + model.Alias = Alias.Generate(model.Name); + + using (IAsyncDocumentSession session = Raven.OpenAsyncSession()) + { + await session.StoreAsync(model); + await session.SaveChangesAsync(); + } + + return EntityResult.Success(model); + } } @@ -77,13 +125,23 @@ namespace zero.Core.Api SpaceCollection GetAll(); /// - /// Get all list items by a list collection alias + /// Get editor item for a space + /// + Task GetItem(string alias) where T : SpaceContent; + + /// + /// Get all list items by space alias /// Task> GetList(string alias) where T : SpaceContent; /// - /// Get all list items for a collection (with query) + /// Get all list items for a space (with query) /// Task> GetListByQuery(string alias, ListQuery query, string appId = null) where T : SpaceContent; + + /// + /// Saves a content item in a space + /// + Task> Save(string alias, T model) where T : SpaceContent; } } diff --git a/zero.Core/Entities/Spaces/SpaceCollection.cs b/zero.Core/Entities/Spaces/SpaceCollection.cs index 4b4b6251..b7d2c0f8 100644 --- a/zero.Core/Entities/Spaces/SpaceCollection.cs +++ b/zero.Core/Entities/Spaces/SpaceCollection.cs @@ -1,10 +1,17 @@ using System; using System.Collections.Generic; +using System.Linq; namespace zero.Core.Entities { public class SpaceCollection : List { + public Space GetByAlias(string alias) + { + return this.FirstOrDefault(x => x.Alias.Equals(alias, StringComparison.InvariantCultureIgnoreCase)); + } + + public void AddList(string alias, string name, string description, string icon) where T : SpaceContent, new() { Add(new Space() diff --git a/zero.Core/Entities/Spaces/SpaceContent.cs b/zero.Core/Entities/Spaces/SpaceContent.cs index ba423a00..270fc11e 100644 --- a/zero.Core/Entities/Spaces/SpaceContent.cs +++ b/zero.Core/Entities/Spaces/SpaceContent.cs @@ -6,6 +6,6 @@ /// public class SpaceContent : DatabaseEntity { - + public string SpaceAlias { get; set; } } } \ No newline at end of file diff --git a/zero.Core/Extensions/StringExtensions.cs b/zero.Core/Extensions/StringExtensions.cs index f3a7c784..0533b036 100644 --- a/zero.Core/Extensions/StringExtensions.cs +++ b/zero.Core/Extensions/StringExtensions.cs @@ -81,7 +81,11 @@ namespace zero.Core.Extensions public static string ToCamelCase(this string input) { - return Char.ToLowerInvariant(input[0]) + input.Substring(1); + if (!String.IsNullOrEmpty(input) && input.Length > 1) + { + return Char.ToLowerInvariant(input[0]) + input.Substring(1); + } + return input; } } } diff --git a/zero.Core/Renderer/AbstractRenderer.cs b/zero.Core/Renderer/AbstractRenderer.cs index c3d6da20..99bd2738 100644 --- a/zero.Core/Renderer/AbstractRenderer.cs +++ b/zero.Core/Renderer/AbstractRenderer.cs @@ -13,8 +13,11 @@ namespace zero.Core.Renderer { public class AbstractGenericRenderer : AbstractRenderer { + public Type TargetType { get; set; } + internal AbstractGenericRenderer(Type type, List properties) { + TargetType = type; Properties = properties; } } diff --git a/zero.Core/Renderer/RendererCollection.cs b/zero.Core/Renderer/RendererCollection.cs new file mode 100644 index 00000000..7ad5a894 --- /dev/null +++ b/zero.Core/Renderer/RendererCollection.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using zero.Core.Renderer; + +namespace zero.Core.Entities +{ + public class RendererCollection : List + { + public void Add() where TRenderer : IRenderer, new() + { + Add(new TRenderer().ToGenericRenderer()); + } + + + public void Add(TRenderer renderer) where TRenderer : IRenderer, new() + { + Add(renderer.ToGenericRenderer()); + } + } +} diff --git a/zero.Core/Renderer/RendererFinder.cs b/zero.Core/Renderer/RendererFinder.cs new file mode 100644 index 00000000..448fd32d --- /dev/null +++ b/zero.Core/Renderer/RendererFinder.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; + +namespace zero.Core.Renderer +{ + public class RendererFinder + { + static RendererFinder() + { + + } + + + public static IRenderer FindBy() + { + return null; + } + + + public static AbstractGenericRenderer FindBy(Type type) + { + //Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); + + //List types = assemblies + // .Where(assembly => !assembly.IsDynamic) + // .SelectMany(assembly => assembly.GetExportedTypes()) + // .ToList(); + + List types = Assembly.GetExecutingAssembly().GetExportedTypes().ToList(); + + return null; + } + } +} diff --git a/zero.Core/ZeroOptions.cs b/zero.Core/ZeroOptions.cs index 2607f50d..3a9b6c2d 100644 --- a/zero.Core/ZeroOptions.cs +++ b/zero.Core/ZeroOptions.cs @@ -12,6 +12,8 @@ namespace zero.Core public SpaceCollection Spaces { get; private set; } = new SpaceCollection(); + public RendererCollection Renderers { get; private set; } = new RendererCollection(); + public IList SettingsAreas { get; private set; } = new List(); public ZeroAuthorizationOptions Authorization { get; private set; } = new ZeroAuthorizationOptions(); diff --git a/zero.Web/App/Components/Buttons/state-button.vue b/zero.Web/App/Components/Buttons/state-button.vue index c0819f97..a7e99509 100644 --- a/zero.Web/App/Components/Buttons/state-button.vue +++ b/zero.Web/App/Components/Buttons/state-button.vue @@ -55,7 +55,7 @@ button.ui-state-button-item { background: var(--color-bg-mid); - border: 1px solid var(--color-line); + //border: 1px solid var(--color-line); padding: 6px 16px; &:first-of-type @@ -72,7 +72,7 @@ & + button { - border-left: none; + border-left: 1px solid var(--color-line); } &.is-active diff --git a/zero.Web/Controllers/SpacesController.cs b/zero.Web/Controllers/SpacesController.cs index ffe249d7..46dc672b 100644 --- a/zero.Web/Controllers/SpacesController.cs +++ b/zero.Web/Controllers/SpacesController.cs @@ -43,7 +43,7 @@ namespace zero.Web.Controllers /// public async Task GetList([FromQuery] string alias, [FromQuery] ListQuery query = null) { - return Json(await Api.GetListByQuery(alias, query)); + return Json(await Api.GetListByQuery(alias, query)); } } } diff --git a/zero.Web/Controllers/TestController.cs b/zero.Web/Controllers/TestController.cs index b1dad781..b8b7f021 100644 --- a/zero.Web/Controllers/TestController.cs +++ b/zero.Web/Controllers/TestController.cs @@ -1,11 +1,16 @@ using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Options; +using System; +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using zero.Core; using zero.Core.Api; using zero.Core.Entities; using zero.Core.Identity; +using zero.Core.Renderer; +using zero.TestData; using zero.TestData.Lists; namespace zero.Web.Controllers @@ -15,12 +20,18 @@ namespace zero.Web.Controllers { private IAuthenticationApi Api { get; set; } + private ISpacesApi SpacesApi { get; set; } + private SignInManager SignInManager; - public TestController(IZeroConfiguration config, IAuthenticationApi api, SignInManager signInManager) : base(config) + private ZeroOptions Options; + + public TestController(IZeroConfiguration config, IAuthenticationApi api, ISpacesApi spacesApi, SignInManager signInManager, IOptionsMonitor options) : base(config) { Api = api; + SpacesApi = spacesApi; SignInManager = signInManager; + Options = options.CurrentValue; } @@ -34,6 +45,55 @@ namespace zero.Web.Controllers } + [HttpGet] + [ZeroAuthorize(false)] + public async Task SaveSpaceContent() + { + TeamMember model = new TeamMember() + { + IsActive = true, + Email = "tobi@test.com", + Name = "Tobi", + Position = "Chef", + VideoUri = "https://swcs.pro" + }; + + model.Addresses.Add(new TeamMemberAddress() + { + City = "Braunau", + Street = "My street", + No = "23" + }); + + return Json(await SpacesApi.Save("team", model)); + } + + + [HttpGet] + [ZeroAuthorize(false)] + public async Task GetSpaceList() + { + return Json(await SpacesApi.GetList("team")); + } + + + [HttpGet] + [ZeroAuthorize(false)] + public IActionResult GetRenderer([FromQuery] string alias) + { + Space space = SpacesApi.GetByAlias(alias); + + AbstractGenericRenderer renderer = Options.Renderers.FirstOrDefault(x => x.TargetType == space.Type); + + if (renderer == null) + { + return NotFound(); + } + + return Json(renderer.Build()); + } + + [HttpPost] public async Task Login([FromQuery] string username, [FromQuery] string password) { diff --git a/zero.Web/Sass/Core/_settings.scss b/zero.Web/Sass/Core/_settings.scss index 12c60b1a..ce434fc5 100644 --- a/zero.Web/Sass/Core/_settings.scss +++ b/zero.Web/Sass/Core/_settings.scss @@ -2,7 +2,7 @@ :root, .theme-light { // accent colors - --color-primary: #2a68e7; + --color-primary: #1abbaa; --color-primary-fg: #fff; --color-secondary: #292b2c; --color-negative: #d82853; diff --git a/zero.Web/Startup.cs b/zero.Web/Startup.cs index 562faec3..3ee1116a 100644 --- a/zero.Web/Startup.cs +++ b/zero.Web/Startup.cs @@ -14,8 +14,10 @@ using Raven.Client.Documents.Conventions; using System; using zero.Core; using zero.Core.Api; +using zero.Core.Entities; using zero.Core.Extensions; using zero.TestData; +using zero.TestData.Lists; namespace zero.Web { @@ -63,7 +65,19 @@ namespace zero.Web store.Conventions.FindCollectionName = type => { - return Constants.Database.CollectionPrefix + DocumentConventions.DefaultGetCollectionName(type); + Type finalType = type; + + if (type.IsSubclassOf(typeof(SpaceContent))) + { + finalType = typeof(SpaceContent); + } + + return Constants.Database.CollectionPrefix + DocumentConventions.DefaultGetCollectionName(finalType); + }; + + store.Conventions.TransformTypeCollectionNameToDocumentIdPrefix = name => + { + return DocumentConventions.DefaultTransformCollectionNameToDocumentIdPrefix(name.ToCamelCase()); }; store.Conventions.IdentityPartsSeparator = "."; @@ -80,6 +94,9 @@ namespace zero.Web opts.Spaces.AddList("news", "News", "Articles about the company", "fth-edit"); opts.Spaces.AddEditor("social", "Social", "Links to social media", "fth-twitter"); + opts.Renderers.Add(); + opts.Renderers.Add(); + //var commercePermissions = new Core.Identity.PermissionCollection() //{ // Label = "Commerce"