From 3853dbfdb9876da71beabd6dc699e35e5075ed0d Mon Sep 17 00:00:00 2001 From: Tobias Klika Date: Thu, 2 Dec 2021 14:44:48 +0100 Subject: [PATCH] flavors work with API now --- .../Countries/CountriesController.cs | 2 +- .../Languages/LanguagesController.cs | 2 +- .../Mails/MailTemplatesController.cs | 2 +- .../Translations/TranslationsController.cs | 2 +- .../Extensions/IMapperProfileExtensions.cs | 3 +++ zero.Api/Models/_new/BasicModel.cs | 7 +++++- zero.Api/Models/_new/DisplayModel.cs | 7 +++++- zero.Api/Models/_new/SaveModel.cs | 7 +++++- zero.Api/ZeroApiEntityStoreController.cs | 16 ++++++++++++- .../Resources/Localization/zero.en-us.json | 4 +++- zero.Core/Stores/Flavors/FlavorOptions.cs | 9 ++++++- zero.Core/Stores/StoreOperations.Write.cs | 24 ++++++++++++++++++- 12 files changed, 74 insertions(+), 11 deletions(-) diff --git a/zero.Api/Endpoints/Countries/CountriesController.cs b/zero.Api/Endpoints/Countries/CountriesController.cs index 50d2907f..38c0e466 100644 --- a/zero.Api/Endpoints/Countries/CountriesController.cs +++ b/zero.Api/Endpoints/Countries/CountriesController.cs @@ -12,7 +12,7 @@ public class CountriesController : ZeroApiEntityStoreController> Empty() => EmptyModel(); + public virtual Task> Empty(string flavor = null) => EmptyModel(flavor); [HttpGet("{id}")] diff --git a/zero.Api/Endpoints/Languages/LanguagesController.cs b/zero.Api/Endpoints/Languages/LanguagesController.cs index 790846f3..173bff7f 100644 --- a/zero.Api/Endpoints/Languages/LanguagesController.cs +++ b/zero.Api/Endpoints/Languages/LanguagesController.cs @@ -12,7 +12,7 @@ public class LanguagesController : ZeroApiEntityStoreController> Empty() => EmptyModel(); + public virtual Task> Empty(string flavor = null) => EmptyModel(flavor); [HttpGet("{id}")] diff --git a/zero.Api/Endpoints/Mails/MailTemplatesController.cs b/zero.Api/Endpoints/Mails/MailTemplatesController.cs index 15cf894d..aa459416 100644 --- a/zero.Api/Endpoints/Mails/MailTemplatesController.cs +++ b/zero.Api/Endpoints/Mails/MailTemplatesController.cs @@ -12,7 +12,7 @@ public class MailTemplatesController : ZeroApiEntityStoreController> Empty() => EmptyModel(); + public virtual Task> Empty(string flavor = null) => EmptyModel(flavor); [HttpGet("{id}")] diff --git a/zero.Api/Endpoints/Translations/TranslationsController.cs b/zero.Api/Endpoints/Translations/TranslationsController.cs index aa6d9991..2fc56f4f 100644 --- a/zero.Api/Endpoints/Translations/TranslationsController.cs +++ b/zero.Api/Endpoints/Translations/TranslationsController.cs @@ -12,7 +12,7 @@ public class TranslationsController : ZeroApiEntityStoreController> Empty() => EmptyModel(); + public virtual Task> Empty(string flavor = null) => EmptyModel(flavor); [HttpGet("{id}")] diff --git a/zero.Api/Extensions/IMapperProfileExtensions.cs b/zero.Api/Extensions/IMapperProfileExtensions.cs index 6cb8bfb2..a20c1eac 100644 --- a/zero.Api/Extensions/IMapperProfileExtensions.cs +++ b/zero.Api/Extensions/IMapperProfileExtensions.cs @@ -15,6 +15,7 @@ public static class IMapperProfileExtensions target.Key = source.Key; target.IsActive = source.IsActive; target.CreatedDate = source.CreatedDate; + target.Flavor = source.Flavor; } @@ -31,6 +32,7 @@ public static class IMapperProfileExtensions target.Key = source.Key; target.IsActive = source.IsActive; target.CreatedDate = source.CreatedDate; + target.Flavor = source.Flavor; target.Sort = source.Sort; target.Hash = source.Hash; @@ -53,5 +55,6 @@ public static class IMapperProfileExtensions target.Key = source.Key; target.Sort = source.Sort; target.IsActive = source.IsActive; + target.Flavor = source.Flavor; } } diff --git a/zero.Api/Models/_new/BasicModel.cs b/zero.Api/Models/_new/BasicModel.cs index 72d943f8..e2cfb06a 100644 --- a/zero.Api/Models/_new/BasicModel.cs +++ b/zero.Api/Models/_new/BasicModel.cs @@ -1,6 +1,6 @@ namespace zero.Api.Models; -public abstract class BasicModel : ZeroIdEntity where T : ZeroEntity +public abstract class BasicModel : ZeroIdEntity, ISupportsFlavors where T : ZeroEntity { /// /// Full name of the entity @@ -32,4 +32,9 @@ public abstract class BasicModel : ZeroIdEntity where T : ZeroEntity /// [JsonPropertyName("@link")] public string Link { get; set; } + + /// + /// Configured flavor of this entity + /// + public string Flavor { get; set; } } \ No newline at end of file diff --git a/zero.Api/Models/_new/DisplayModel.cs b/zero.Api/Models/_new/DisplayModel.cs index f362cf16..57f8daae 100644 --- a/zero.Api/Models/_new/DisplayModel.cs +++ b/zero.Api/Models/_new/DisplayModel.cs @@ -1,7 +1,7 @@ namespace zero.Api.Models; -public abstract class DisplayModel : ZeroIdEntity where T : ZeroEntity +public abstract class DisplayModel : ZeroIdEntity, ISupportsFlavors where T : ZeroEntity { /// /// Full name of the entity @@ -57,4 +57,9 @@ public abstract class DisplayModel : ZeroIdEntity where T : ZeroEntity /// Language of the entity /// public string LanguageId { get; set; } + + /// + /// Configured flavor of this entity + /// + public string Flavor { get; set; } } \ No newline at end of file diff --git a/zero.Api/Models/_new/SaveModel.cs b/zero.Api/Models/_new/SaveModel.cs index 02b10bfa..f0d27729 100644 --- a/zero.Api/Models/_new/SaveModel.cs +++ b/zero.Api/Models/_new/SaveModel.cs @@ -1,6 +1,6 @@ namespace zero.Api.Models; -public abstract class SaveModel : ZeroIdEntity where T : ZeroEntity +public abstract class SaveModel : ZeroIdEntity, ISupportsFlavors where T : ZeroEntity { /// /// Full name of the entity @@ -26,4 +26,9 @@ public abstract class SaveModel : ZeroIdEntity where T : ZeroEntity /// Whether the entity is visible in the frontend /// public bool IsActive { get; set; } + + /// + /// Configured flavor of this entity + /// + public string Flavor { get; set; } } \ No newline at end of file diff --git a/zero.Api/ZeroApiEntityStoreController.cs b/zero.Api/ZeroApiEntityStoreController.cs index 2d799520..4bbfd932 100644 --- a/zero.Api/ZeroApiEntityStoreController.cs +++ b/zero.Api/ZeroApiEntityStoreController.cs @@ -34,6 +34,19 @@ public abstract class ZeroApiEntityStoreController : ZeroApiCont } + protected async Task> EmptyModel(string flavor) where T : DisplayModel + { + TModel model = await Store.Empty(flavor); + + if (model == null) + { + return NotFound(); + } + + return Mapper.Map(model); + } + + protected async Task> GetModel(string id, string changeVector = null) where T : DisplayModel { TModel model = await Store.Load(id, changeVector); @@ -75,7 +88,8 @@ public abstract class ZeroApiEntityStoreController : ZeroApiCont protected async Task> CreateModel(T saveModel) where T : SaveModel where TEdit : DisplayModel { - TModel model = Mapper.Map(saveModel); + TModel emptyModel = saveModel.Flavor.IsNullOrEmpty() ? await Store.Empty() : await Store.Empty(saveModel.Flavor); + TModel model = Mapper.Map(saveModel, emptyModel); Result result = await Store.Create(model); bool minimalResponse = Hints.ResponsePreference == ApiResponsePreference.Minimal; diff --git a/zero.Backoffice/Resources/Localization/zero.en-us.json b/zero.Backoffice/Resources/Localization/zero.en-us.json index fd64b3fc..c10ab0c7 100644 --- a/zero.Backoffice/Resources/Localization/zero.en-us.json +++ b/zero.Backoffice/Resources/Localization/zero.en-us.json @@ -178,7 +178,9 @@ "idnotfound": "Could not find an entity for the given ID", "onsave": { "notallowed": "You are not allowed to edit this resource", - "empty": "You need to pass a model" + "empty": "You need to pass a model", + "noidmatch": "Do not fill out the Id field when creating a resource", + "flavornotfound": "Could not find a registration for this resource flavor" }, "ondelete": { "idnotfound": "Could not find an entity for the given ID" diff --git a/zero.Core/Stores/Flavors/FlavorOptions.cs b/zero.Core/Stores/Flavors/FlavorOptions.cs index 83418021..227c73c8 100644 --- a/zero.Core/Stores/Flavors/FlavorOptions.cs +++ b/zero.Core/Stores/Flavors/FlavorOptions.cs @@ -1,6 +1,6 @@ using System.Collections.Concurrent; -namespace zero.Pages; +namespace zero.Stores; public class FlavorOptions { @@ -45,6 +45,13 @@ public class FlavorOptions } + public bool Exists(string alias) + { + List flavors = Flavors.GetValueOrDefault(typeof(TEntity), new()); + return flavors.Any(x => x.Alias == alias); + } + + public void Provide() where TEntity : ISupportsFlavors, new() { diff --git a/zero.Core/Stores/StoreOperations.Write.cs b/zero.Core/Stores/StoreOperations.Write.cs index 7a82b402..e19a0367 100644 --- a/zero.Core/Stores/StoreOperations.Write.cs +++ b/zero.Core/Stores/StoreOperations.Write.cs @@ -18,7 +18,29 @@ public partial class StoreOperations : IStoreOperations return Result.Fail("@errors.onsave.empty"); } - bool isUpdate = !model.Id.IsNullOrEmpty() && await Session.Advanced.ExistsAsync(model.Id); + bool isUpdate = false; + + // check if the Id for a model already exists + if (!model.Id.IsNullOrEmpty()) + { + bool exists = await Session.Advanced.ExistsAsync(model.Id); + + if (!exists) + { + return Result.Fail("@errors.onsave.noidmatch"); + } + + isUpdate = true; + } + + // validate flavor + if (model is ISupportsFlavors flavorModel && !flavorModel.Flavor.IsNullOrEmpty()) + { + if (!Flavors.Exists(flavorModel.Flavor)) + { + return Result.Fail("@errors.onsave.flavornotfound"); + } + } // prepare model PrepareForSave(model);