From 1b1b8bc8c83819b890fda196be3e26d8c8fdb22c Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Fri, 12 Jun 2026 17:25:23 +0330 Subject: [PATCH] Complete Category and SubCategory Base Actions, and also ControllersBase and their Implemented Usages ... --- .../XCategoryProviderControllerBase.cs | 470 ++++++++++++++++++ .../XSubCategoryProviderControllerBase.cs | 470 ++++++++++++++++++ DI/XDIHelperExtension.cs | 50 +- Extensions/XCategoryResourceExtensions.cs | 116 +++-- Extensions/XSubCategoryResourceExtensions.cs | 121 +++++ Interfaces/IXCategoryProvider.cs | 12 +- Interfaces/IXCategoryProviderController.cs | 123 ++++- Interfaces/IXSubCategoryProvider.cs | 12 +- Interfaces/IXSubCategoryProviderController.cs | 123 ++++- Providers/XCategoryProvider.cs | 26 +- Providers/XSubCategoryProvider.cs | 26 +- 11 files changed, 1451 insertions(+), 98 deletions(-) create mode 100644 Controllers/XCategoryProviderControllerBase.cs create mode 100644 Controllers/XSubCategoryProviderControllerBase.cs create mode 100644 Extensions/XSubCategoryResourceExtensions.cs diff --git a/Controllers/XCategoryProviderControllerBase.cs b/Controllers/XCategoryProviderControllerBase.cs new file mode 100644 index 0000000..84bb36b --- /dev/null +++ b/Controllers/XCategoryProviderControllerBase.cs @@ -0,0 +1,470 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.Extensions.Logging; +using xCategoryService.Interfaces; +using xCategoryService.Models.Dtos; +using xCategoryService.Models.Entities; +using xCategoryService.Providers.Dtos; +using xCommons.Configurations; +using xCommons.Extensions; +using xCommons.Providers; +using xExceptions.Constants; +using xIdentityService.Interfaces; +using xModels.Dtos; +using xPushService.Controllers; + +namespace xCategoryService.Controllers +{ + public abstract class XCategoryProviderControllerBase : XBaseProvidedController, IXCategoryProviderController + { + private readonly IXCategoryProvider provider; + + protected XCategoryProviderControllerBase( + ILogger logger, + XAppConfiguration appConfiguration, + IXIdentityProvider identityProvider, + XValidationProvider validationProvider, + IXCategoryProvider provider, + Func, IOrderedQueryable> defaultOrderBuilder = null, + Func, IIncludableQueryable> defaultIncludeBuilder = null + ) : base( + logger, + appConfiguration, + identityProvider, + validationProvider, + provider, + defaultOrderBuilder, + defaultIncludeBuilder + ) + { + this.provider = provider; + } + + // + #region Actions ... + /// + /// Check Has Specified Locale or not ... + /// + /// + /// + /// + /// + [HttpGet("Resources/{id}/HasLocale")] + public virtual async Task> HasLocale( + [FromRoute] int id, + [FromQuery] string language, + CancellationToken cancellationToken = default + ) + { + // + try + { + // + // Validate ... + if (!ModelState.IsValid || + !id.IsValidIntId()) + { + XException.InvalidArgs.Throw(); + } + ValidationProvider.NotEmpty(language); + + // + var result = await provider.HasLocale( + id: id, + language: language, + cancellationToken: cancellationToken + ); + + // + return Ok(result); + } + catch (Exception ex) + { + // + var result = GetExceptionActionResult(ex); + return result; + } + } + + /// + /// Load an Item by all of it's Related Translations ... + /// + /// + /// + /// + [HttpGet("Resources/{id}")] + public virtual async Task> GetResource( + [FromRoute] int id, + CancellationToken cancellationToken = default + ) + { + // + try + { + // + // Validate ... + if (!ModelState.IsValid || + !id.IsValidIntId()) + { + XException.InvalidArgs.Throw(); + } + + // + var result = await provider.GetResource( + id: id, + cancellationToken: cancellationToken + ); + + // + return Ok(result.ToDynamicObject()); + } + catch (Exception ex) + { + // + var result = GetExceptionActionResult(ex); + return result; + } + } + + /// + /// Add Category Item for Specified Language ... + /// + /// + /// + /// + /// + [HttpPost("Resources")] + public virtual async Task> Add( + [FromBody] XCategoryDto item, + [FromQuery] string language = null, + CancellationToken cancellationToken = default + ) + { + // + try + { + // + // Validate ... + if (!ModelState.IsValid) + { + XException.InvalidArgs.Throw(); + } + await ValidationProvider + .GroupValidationBuilder() + .AddNotNull(item) + .AddNotEmpty(language) + .AddNotEmpty(item.Title) + .AddNotEmpty(item.Description) + .ValidateGroupAsync(); + + // + // Reading Requirements ... + var userInfo = await GetUserInfo(); + var connectionId = GetConnectionId(); + + // + var result = await provider.Add( + item: item, + language: language, + userInfo: userInfo, + connectionId: connectionId, + cancellationToken: cancellationToken + ); + + // + return Ok(result.ToDynamicObject()); + } + catch (Exception ex) + { + // + var result = GetExceptionActionResult(ex); + return result; + } + } + + /// + /// Update a Category Item for Specified Language ... + /// + /// + /// + /// + /// + /// + [HttpPut("Resources/{id}")] + public virtual async Task> Update( + [FromRoute] int id, + [FromBody] XCategoryDto item, + [FromQuery] string language = null, + CancellationToken cancellationToken = default + ) + { + // + try + { + // + // Validate ... + if (!ModelState.IsValid || + !id.IsValidIntId()) + { + XException.InvalidArgs.Throw(); + } + await ValidationProvider + .GroupValidationBuilder() + .AddNotNull(item) + .AddNotEmpty(language) + .AddNotEmpty(item.Title) + .AddNotEmpty(item.Description) + .ValidateGroupAsync(); + + // + // Reading Requirements ... + var userInfo = await GetUserInfo(); + var connectionId = GetConnectionId(); + + // + var result = await provider.Update( + id: id, + item: item, + language: language, + userInfo: userInfo, + connectionId: connectionId, + cancellationToken: cancellationToken + ); + + // + return Ok(result.ToDynamicObject()); + } + catch (Exception ex) + { + // + var result = GetExceptionActionResult(ex); + return result; + } + } + + /// + /// Refresh a Resource ... + /// + /// + /// + /// + [HttpPost("Resources/Refresh")] + public virtual async Task> Refresh( + [FromBody] XCategoryResourceDto resource, + CancellationToken cancellationToken = default + ) + { + // + try + { + // + // Validate ... + if (!ModelState.IsValid) + { + XException.InvalidArgs.Throw(); + } + await ValidationProvider + .GroupValidationBuilder() + .AddNotNull(resource) + .AddNotNull(resource.Item) + .ValidateGroupAsync(); + + // + // Reading Requirements ... + var userInfo = await GetUserInfo(); + var connectionId = GetConnectionId(); + + // + var result = await provider.Refresh( + resource: resource, + userInfo: userInfo, + connectionId: connectionId, + cancellationToken: cancellationToken + ); + + // + return Ok(result.ToDynamicObject()); + } + catch (Exception ex) + { + // + var result = GetExceptionActionResult(ex); + return result; + } + } + + /// + /// Get All Resources ... + /// + /// + /// + [HttpGet("Resources/All")] + public virtual async Task>> GetAllResources( + CancellationToken cancellationToken = default + ) + { + // + try + { + // + // Validate ... + if (!ModelState.IsValid) + { + XException.InvalidArgs.Throw(); + } + + // + var result = await provider.GetAllResources( + cancellationToken: cancellationToken + ); + + // + return Ok(result.ToDynamicObject()); + } + catch (Exception ex) + { + // + var result = GetExceptionActionResult(ex); + return result; + } + } + + /// + /// Find One Resource ... + /// + /// + /// + /// + [HttpGet("Resources/Find/One")] + public virtual async Task> FindOneResource( + [FromQuery] string query, + CancellationToken cancellationToken = default + ) + { + // + try + { + // + // Validate ... + if (!ModelState.IsValid) + { + XException.InvalidArgs.Throw(); + } + await ValidationProvider + .GroupValidationBuilder() + .AddNotEmpty(query) + .ValidateGroupAsync(); + + // + var result = await provider.FindOneResource( + cancellationToken: cancellationToken, + predicate: x => x.PropValuesContains(query) + ); + + // + return Ok(result.ToDynamicObject()); + } + catch (Exception ex) + { + // + var result = GetExceptionActionResult(ex); + return result; + } + } + + /// + /// Find Many Resource ... + /// + /// + /// + /// + [HttpGet("Resources/Find/Many")] + public virtual async Task>> FindManyResource( + [FromQuery] string query, + CancellationToken cancellationToken = default + ) + { + // + try + { + // + // Validate ... + if (!ModelState.IsValid) + { + XException.InvalidArgs.Throw(); + } + await ValidationProvider + .GroupValidationBuilder() + .AddNotEmpty(query) + .ValidateGroupAsync(); + + // + var result = await provider.FindManyResource( + cancellationToken: cancellationToken, + predicate: x => x.PropValuesContains(query), + orderBuilder: x => x.OrderBy(y => y.Item.Id) + ); + + // + return Ok(result.ToDynamicObject()); + } + catch (Exception ex) + { + // + var result = GetExceptionActionResult(ex); + return result; + } + } + + /// + /// Retrieve Resources by Query Pattern ... + /// + /// + /// + /// + [HttpGet("Resources/Query")] + public virtual async Task>> QueryResources( + [FromQuery] XQuery query = null, + CancellationToken cancellationToken = default + ) + { + // + try + { + // + // Validate ... + if (!ModelState.IsValid) + { + XException.InvalidArgs.Throw(); + } + await ValidationProvider + .GroupValidationBuilder() + .AddNotNull(query) + .ValidateGroupAsync(); + + // + var result = await provider.QueryResources( + query: query, + predicate: null, + cancellationToken: cancellationToken, + orderBuilder: x => x.OrderBy(y => y.Item.Id) + ); + + // + return Ok(result.ToDynamicObject()); + } + catch (Exception ex) + { + // + var result = GetExceptionActionResult(ex); + return result; + } + } + #endregion + } +} \ No newline at end of file diff --git a/Controllers/XSubCategoryProviderControllerBase.cs b/Controllers/XSubCategoryProviderControllerBase.cs new file mode 100644 index 0000000..536d3be --- /dev/null +++ b/Controllers/XSubCategoryProviderControllerBase.cs @@ -0,0 +1,470 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.Extensions.Logging; +using xCategoryService.Interfaces; +using xCategoryService.Models.Dtos; +using xCategoryService.Models.Entities; +using xCategoryService.Providers.Dtos; +using xCommons.Configurations; +using xCommons.Extensions; +using xCommons.Providers; +using xExceptions.Constants; +using xIdentityService.Interfaces; +using xModels.Dtos; +using xPushService.Controllers; + +namespace xCategoryService.Controllers +{ + public abstract class XSubCategoryProviderControllerBase : XBaseProvidedController, IXSubCategoryProviderController + { + private readonly IXSubCategoryProvider provider; + + protected XSubCategoryProviderControllerBase( + ILogger logger, + XAppConfiguration appConfiguration, + IXIdentityProvider identityProvider, + XValidationProvider validationProvider, + IXSubCategoryProvider provider, + Func, IOrderedQueryable> defaultOrderBuilder = null, + Func, IIncludableQueryable> defaultIncludeBuilder = null + ) : base( + logger, + appConfiguration, + identityProvider, + validationProvider, + provider, + defaultOrderBuilder, + defaultIncludeBuilder + ) + { + this.provider = provider; + } + + // + #region Actions ... + /// + /// Check Has Specified Locale or not ... + /// + /// + /// + /// + /// + [HttpGet("Resources/{id}/HasLocale")] + public virtual async Task> HasLocale( + [FromRoute] int id, + [FromQuery] string language, + CancellationToken cancellationToken = default + ) + { + // + try + { + // + // Validate ... + if (!ModelState.IsValid || + !id.IsValidIntId()) + { + XException.InvalidArgs.Throw(); + } + ValidationProvider.NotEmpty(language); + + // + var result = await provider.HasLocale( + id: id, + language: language, + cancellationToken: cancellationToken + ); + + // + return Ok(result); + } + catch (Exception ex) + { + // + var result = GetExceptionActionResult(ex); + return result; + } + } + + /// + /// Load an Item by all of it's Related Translations ... + /// + /// + /// + /// + [HttpGet("Resources/{id}")] + public virtual async Task> GetResource( + [FromRoute] int id, + CancellationToken cancellationToken = default + ) + { + // + try + { + // + // Validate ... + if (!ModelState.IsValid || + !id.IsValidIntId()) + { + XException.InvalidArgs.Throw(); + } + + // + var result = await provider.GetResource( + id: id, + cancellationToken: cancellationToken + ); + + // + return Ok(result.ToDynamicObject()); + } + catch (Exception ex) + { + // + var result = GetExceptionActionResult(ex); + return result; + } + } + + /// + /// Add Category Item for Specified Language ... + /// + /// + /// + /// + /// + [HttpPost("Resources")] + public virtual async Task> Add( + [FromBody] XSubCategoryDto item, + [FromQuery] string language = null, + CancellationToken cancellationToken = default + ) + { + // + try + { + // + // Validate ... + if (!ModelState.IsValid) + { + XException.InvalidArgs.Throw(); + } + await ValidationProvider + .GroupValidationBuilder() + .AddNotNull(item) + .AddNotEmpty(language) + .AddNotEmpty(item.Title) + .AddNotEmpty(item.Description) + .ValidateGroupAsync(); + + // + // Reading Requirements ... + var userInfo = await GetUserInfo(); + var connectionId = GetConnectionId(); + + // + var result = await provider.Add( + item: item, + language: language, + userInfo: userInfo, + connectionId: connectionId, + cancellationToken: cancellationToken + ); + + // + return Ok(result.ToDynamicObject()); + } + catch (Exception ex) + { + // + var result = GetExceptionActionResult(ex); + return result; + } + } + + /// + /// Update a Category Item for Specified Language ... + /// + /// + /// + /// + /// + /// + [HttpPut("Resources/{id}")] + public virtual async Task> Update( + [FromRoute] int id, + [FromBody] XSubCategoryDto item, + [FromQuery] string language = null, + CancellationToken cancellationToken = default + ) + { + // + try + { + // + // Validate ... + if (!ModelState.IsValid || + !id.IsValidIntId()) + { + XException.InvalidArgs.Throw(); + } + await ValidationProvider + .GroupValidationBuilder() + .AddNotNull(item) + .AddNotEmpty(language) + .AddNotEmpty(item.Title) + .AddNotEmpty(item.Description) + .ValidateGroupAsync(); + + // + // Reading Requirements ... + var userInfo = await GetUserInfo(); + var connectionId = GetConnectionId(); + + // + var result = await provider.Update( + id: id, + item: item, + language: language, + userInfo: userInfo, + connectionId: connectionId, + cancellationToken: cancellationToken + ); + + // + return Ok(result.ToDynamicObject()); + } + catch (Exception ex) + { + // + var result = GetExceptionActionResult(ex); + return result; + } + } + + /// + /// Refresh a Resource ... + /// + /// + /// + /// + [HttpPost("Resources/Refresh")] + public virtual async Task> Refresh( + [FromBody] XSubCategoryResourceDto resource, + CancellationToken cancellationToken = default + ) + { + // + try + { + // + // Validate ... + if (!ModelState.IsValid) + { + XException.InvalidArgs.Throw(); + } + await ValidationProvider + .GroupValidationBuilder() + .AddNotNull(resource) + .AddNotNull(resource.Item) + .ValidateGroupAsync(); + + // + // Reading Requirements ... + var userInfo = await GetUserInfo(); + var connectionId = GetConnectionId(); + + // + var result = await provider.Refresh( + resource: resource, + userInfo: userInfo, + connectionId: connectionId, + cancellationToken: cancellationToken + ); + + // + return Ok(result.ToDynamicObject()); + } + catch (Exception ex) + { + // + var result = GetExceptionActionResult(ex); + return result; + } + } + + /// + /// Get All Resources ... + /// + /// + /// + [HttpGet("Resources/All")] + public virtual async Task>> GetAllResources( + CancellationToken cancellationToken = default + ) + { + // + try + { + // + // Validate ... + if (!ModelState.IsValid) + { + XException.InvalidArgs.Throw(); + } + + // + var result = await provider.GetAllResources( + cancellationToken: cancellationToken + ); + + // + return Ok(result.ToDynamicObject()); + } + catch (Exception ex) + { + // + var result = GetExceptionActionResult(ex); + return result; + } + } + + /// + /// Find One Resource ... + /// + /// + /// + /// + [HttpGet("Resources/Find/One")] + public virtual async Task> FindOneResource( + [FromQuery] string query, + CancellationToken cancellationToken = default + ) + { + // + try + { + // + // Validate ... + if (!ModelState.IsValid) + { + XException.InvalidArgs.Throw(); + } + await ValidationProvider + .GroupValidationBuilder() + .AddNotEmpty(query) + .ValidateGroupAsync(); + + // + var result = await provider.FindOneResource( + cancellationToken: cancellationToken, + predicate: x => x.PropValuesContains(query) + ); + + // + return Ok(result.ToDynamicObject()); + } + catch (Exception ex) + { + // + var result = GetExceptionActionResult(ex); + return result; + } + } + + /// + /// Find Many Resource ... + /// + /// + /// + /// + [HttpGet("Resources/Find/Many")] + public virtual async Task>> FindManyResource( + [FromQuery] string query, + CancellationToken cancellationToken = default + ) + { + // + try + { + // + // Validate ... + if (!ModelState.IsValid) + { + XException.InvalidArgs.Throw(); + } + await ValidationProvider + .GroupValidationBuilder() + .AddNotEmpty(query) + .ValidateGroupAsync(); + + // + var result = await provider.FindManyResource( + cancellationToken: cancellationToken, + predicate: x => x.PropValuesContains(query), + orderBuilder: x => x.OrderBy(y => y.Item.Id) + ); + + // + return Ok(result.ToDynamicObject()); + } + catch (Exception ex) + { + // + var result = GetExceptionActionResult(ex); + return result; + } + } + + /// + /// Retrieve Resources by Query Pattern ... + /// + /// + /// + /// + [HttpGet("Resources/Query")] + public virtual async Task>> QueryResources( + [FromQuery] XQuery query = null, + CancellationToken cancellationToken = default + ) + { + // + try + { + // + // Validate ... + if (!ModelState.IsValid) + { + XException.InvalidArgs.Throw(); + } + await ValidationProvider + .GroupValidationBuilder() + .AddNotNull(query) + .ValidateGroupAsync(); + + // + var result = await provider.QueryResources( + query: query, + predicate: null, + cancellationToken: cancellationToken, + orderBuilder: x => x.OrderBy(y => y.Item.Id) + ); + + // + return Ok(result.ToDynamicObject()); + } + catch (Exception ex) + { + // + var result = GetExceptionActionResult(ex); + return result; + } + } + #endregion + } +} \ No newline at end of file diff --git a/DI/XDIHelperExtension.cs b/DI/XDIHelperExtension.cs index 2ca8da8..1e67500 100644 --- a/DI/XDIHelperExtension.cs +++ b/DI/XDIHelperExtension.cs @@ -283,30 +283,42 @@ namespace xCategoryService.DI services.Add( new ServiceDescriptor(typeof(IXCategoryDescriptionResourceProvider), typeof(XCategoryDescriptionResourceProvider), lifeTime) ); + + // + // Provider ... + services.Add( + new ServiceDescriptor(typeof(IXCategoryProvider), typeof(XCategoryProvider), lifeTime) + ); #endregion // #region SubCategory ... - // // - // // Models ... - // services.Add( - // new ServiceDescriptor(typeof(IXSubCategoryServiceProvider), typeof(XSubCategoryServiceProvider), lifeTime) - // ); - // services.Add( - // new ServiceDescriptor(typeof(IXSubCategoryRepositoryService), typeof(XSubCategoryRepositoryService), lifeTime) - // ); - // services.Add( - // new ServiceDescriptor(typeof(IXSubCategoryRepositoryProvider), typeof(XSubCategoryRepositoryProvider), lifeTime) - // ); + // + // Models ... + services.Add( + new ServiceDescriptor(typeof(IXSubCategoryServiceProvider), typeof(XSubCategoryServiceProvider), lifeTime) + ); + services.Add( + new ServiceDescriptor(typeof(IXSubCategoryRepositoryService), typeof(XSubCategoryRepositoryService), lifeTime) + ); + services.Add( + new ServiceDescriptor(typeof(IXSubCategoryRepositoryProvider), typeof(XSubCategoryRepositoryProvider), lifeTime) + ); - // // - // // Resource Providers ... - // services.Add( - // new ServiceDescriptor(typeof(IXSubCategoryTitleResourceProvider), typeof(XSubCategoryTitleResourceProvider), lifeTime) - // ); - // services.Add( - // new ServiceDescriptor(typeof(IXSubCategoryDescriptionResourceProvider), typeof(XSubCategoryDescriptionResourceProvider), lifeTime) - // ); + // + // Resource Providers ... + services.Add( + new ServiceDescriptor(typeof(IXSubCategoryTitleResourceProvider), typeof(XSubCategoryTitleResourceProvider), lifeTime) + ); + services.Add( + new ServiceDescriptor(typeof(IXSubCategoryDescriptionResourceProvider), typeof(XSubCategoryDescriptionResourceProvider), lifeTime) + ); + + // + // Provider ... + services.Add( + new ServiceDescriptor(typeof(IXSubCategoryProvider), typeof(XSubCategoryProvider), lifeTime) + ); #endregion #endregion diff --git a/Extensions/XCategoryResourceExtensions.cs b/Extensions/XCategoryResourceExtensions.cs index 17d4068..85b830d 100644 --- a/Extensions/XCategoryResourceExtensions.cs +++ b/Extensions/XCategoryResourceExtensions.cs @@ -1,4 +1,5 @@ using System.Linq; +using xCategoryService.Models.Dtos; using xCategoryService.Providers.Dtos; using xCommons.Extensions; @@ -9,36 +10,6 @@ namespace xCategoryService.Extensions /// public static class XCategoryResourceExtensions { - /// - /// Check a Resource is Valid or not ... - /// - /// - /// - public static bool IsValid( - this XCategoryResourceDto source - ) - { - // - return - !source.IsNullOrDefault() && - !source.Item.IsNullOrDefault(); - } - - /// - /// Check a Resource is a New Resource for Add or not ... - /// - /// - /// - public static bool IsNew( - this XCategoryResourceDto source - ) - { - // - return - source.IsValid() && - !source.Item.Id.IsValidIntId(); - } - /// /// Extract Available Languages ... /// @@ -53,7 +24,7 @@ namespace xCategoryService.Extensions // // Validate ... - if (!source.IsValid()) + if (!source.IsNullOrDefault()) { return result; } @@ -69,11 +40,82 @@ namespace xCategoryService.Extensions return result; } - // public static bool ValidateResources( - // this XCategoryResourceDto source - // ) - // { - // var result = - // } + /// + /// Check Has Locale or not ... + /// + /// + /// + /// + public static bool HasLocale( + this XCategoryResourceDto source, + string language + ) + { + // + var result = + !language.IsNullOrEmpty() && + !source.IsNullOrDefault() && + source.Titles.Locales + .Any(l => l.Language + .Equals( + language, + System.StringComparison.InvariantCultureIgnoreCase)); + + // + return result; + } + + /// + /// Get Item Translation ... + /// + /// + /// + /// + public static XCategoryDto GetTranslate( + this XCategoryResourceDto source, + string language + ) + { + // + XCategoryDto result = null; + + // + var isValid = source + .HasLocale(language); + if (!isValid) + { + return result; + } + + // + var titleLocale = source.Titles.Locales + .FirstOrDefault(l => l.Language + .Equals( + language, + System.StringComparison.InvariantCultureIgnoreCase)); + var descriptionLocale = source.Descriptions.Locales + .FirstOrDefault(l => l.Language + .Equals( + language, + System.StringComparison.InvariantCultureIgnoreCase)); + + // + isValid = !titleLocale.IsNullOrDefault(); + if (!isValid) + { + return result; + } + + // + result = source.Item; + result.Title = titleLocale.Value; + result.Description = + descriptionLocale.IsNullOrDefault() + ? string.Empty + : descriptionLocale.Value; + + // + return result; + } } } \ No newline at end of file diff --git a/Extensions/XSubCategoryResourceExtensions.cs b/Extensions/XSubCategoryResourceExtensions.cs new file mode 100644 index 0000000..a9dbda6 --- /dev/null +++ b/Extensions/XSubCategoryResourceExtensions.cs @@ -0,0 +1,121 @@ +using System.Linq; +using xCategoryService.Models.Dtos; +using xCategoryService.Providers.Dtos; +using xCommons.Extensions; + +namespace xCategoryService.Extensions +{ + /// + /// Extensions Method Related to XSubCategoryResourceDto ... + /// + public static class XSubCategoryResourceExtensions + { + /// + /// Extract Available Languages ... + /// + /// + /// + public static string[] ExtractLanguages( + this XSubCategoryResourceDto source + ) + { + // + var result = new string[] { }; + + // + // Validate ... + if (!source.IsNullOrDefault()) + { + return result; + } + + // + result = + source.Titles.Locales.Select(x => x.Language) + .Union(source.Descriptions.Locales.Select(x => x.Language)) + .Distinct() + .ToArray(); + + // + return result; + } + + /// + /// Check Has Locale or not ... + /// + /// + /// + /// + public static bool HasLocale( + this XSubCategoryResourceDto source, + string language + ) + { + // + var result = + !language.IsNullOrEmpty() && + !source.IsNullOrDefault() && + source.Titles.Locales + .Any(l => l.Language + .Equals( + language, + System.StringComparison.InvariantCultureIgnoreCase)); + + // + return result; + } + + /// + /// Get Item Translation ... + /// + /// + /// + /// + public static XSubCategoryDto GetTranslate( + this XSubCategoryResourceDto source, + string language + ) + { + // + XSubCategoryDto result = null; + + // + var isValid = source + .HasLocale(language); + if (!isValid) + { + return result; + } + + // + var titleLocale = source.Titles.Locales + .FirstOrDefault(l => l.Language + .Equals( + language, + System.StringComparison.InvariantCultureIgnoreCase)); + var descriptionLocale = source.Descriptions.Locales + .FirstOrDefault(l => l.Language + .Equals( + language, + System.StringComparison.InvariantCultureIgnoreCase)); + + // + isValid = !titleLocale.IsNullOrDefault(); + if (!isValid) + { + return result; + } + + // + result = source.Item; + result.Title = titleLocale.Value; + result.Description = + descriptionLocale.IsNullOrDefault() + ? string.Empty + : descriptionLocale.Value; + + // + return result; + } + } +} \ No newline at end of file diff --git a/Interfaces/IXCategoryProvider.cs b/Interfaces/IXCategoryProvider.cs index d7658fc..4bbac01 100644 --- a/Interfaces/IXCategoryProvider.cs +++ b/Interfaces/IXCategoryProvider.cs @@ -43,14 +43,14 @@ namespace xCategoryService.Interfaces /// Add Category Item for Specified Language ... /// /// - /// + /// /// /// /// /// Task Add( XCategoryDto item, - string langauge = null, + string language = null, string connectionId = null, XUserClaimsInfoDto userInfo = null, CancellationToken cancellationToken = default @@ -76,14 +76,14 @@ namespace xCategoryService.Interfaces ); /// - /// Referesh a Resource ... + /// Refresh a Resource ... /// /// /// /// /// /// - Task Referesh( + Task Refresh( XCategoryResourceDto resource, string connectionId = null, XUserClaimsInfoDto userInfo = null, @@ -105,7 +105,7 @@ namespace xCategoryService.Interfaces /// /// /// - Task FindOne( + Task FindOneResource( Expression> predicate = null, CancellationToken cancellationToken = default ); @@ -116,7 +116,7 @@ namespace xCategoryService.Interfaces /// /// /// - Task> FindMany( + Task> FindManyResource( Expression> predicate = null, Func, IOrderedQueryable> orderBuilder = null, CancellationToken cancellationToken = default diff --git a/Interfaces/IXCategoryProviderController.cs b/Interfaces/IXCategoryProviderController.cs index 60f2f55..6e37dfc 100644 --- a/Interfaces/IXCategoryProviderController.cs +++ b/Interfaces/IXCategoryProviderController.cs @@ -1,10 +1,129 @@ +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; using xCategoryService.Models.Dtos; using xCategoryService.Models.Entities; using xCategoryService.Providers.Dtos; +using xModels.Dtos; using xPushService.Interfaces; namespace xCategoryService.Interfaces { - public interface IXCategoryProviderController: IXBaseProvidedController - { } + public interface IXCategoryProviderController : IXBaseProvidedController + { + /// + /// Check Has Specified Locale or not ... + /// + /// + /// + /// + /// + [HttpGet("Resources/{id}/HasLocale")] + Task> HasLocale( + [FromRoute] int id, + [FromQuery] string language, + CancellationToken cancellationToken = default + ); + + /// + /// Load an Item by all of it's Related Translations ... + /// + /// + /// + /// + [HttpGet("Resources/{id}")] + Task> GetResource( + [FromRoute] int id, + CancellationToken cancellationToken = default + ); + + /// + /// Add Category Item for Specified Language ... + /// + /// + /// + /// + /// + [HttpPost("Resources")] + Task> Add( + [FromBody] XCategoryDto item, + [FromQuery] string language = null, + CancellationToken cancellationToken = default + ); + + /// + /// Update a Category Item for Specified Language ... + /// + /// + /// + /// + /// + /// + [HttpPut("Resources/{id}")] + Task> Update( + [FromRoute] int id, + [FromBody] XCategoryDto item, + [FromQuery] string language = null, + CancellationToken cancellationToken = default + ); + + /// + /// Refresh a Resource ... + /// + /// + /// + /// + [HttpPost("Resources/Refresh")] + Task> Refresh( + [FromBody] XCategoryResourceDto resource, + CancellationToken cancellationToken = default + ); + + /// + /// Get All Resources ... + /// + /// + /// + [HttpGet("Resources/All")] + Task>> GetAllResources( + CancellationToken cancellationToken = default + ); + + /// + /// Find One Resource ... + /// + /// + /// + /// + [HttpGet("Resources/Find/One")] + Task> FindOneResource( + [FromQuery] string query, + CancellationToken cancellationToken = default + ); + + /// + /// Find Many Resource ... + /// + /// + /// + /// + [HttpGet("Resources/Find/Many")] + Task>> FindManyResource( + [FromQuery] string query, + CancellationToken cancellationToken = default + ); + + /// + /// Retrieve Resources by Query Pattern ... + /// + /// + /// + /// + [HttpGet("Resources/Query")] + Task>> QueryResources( + [FromQuery] XQuery query = null, + CancellationToken cancellationToken = default + ); + } } \ No newline at end of file diff --git a/Interfaces/IXSubCategoryProvider.cs b/Interfaces/IXSubCategoryProvider.cs index efe8ef6..5cc7bbc 100644 --- a/Interfaces/IXSubCategoryProvider.cs +++ b/Interfaces/IXSubCategoryProvider.cs @@ -43,14 +43,14 @@ namespace xCategoryService.Interfaces /// Add Category Item for Specified Language ... /// /// - /// + /// /// /// /// /// Task Add( XSubCategoryDto item, - string langauge = null, + string language = null, string connectionId = null, XUserClaimsInfoDto userInfo = null, CancellationToken cancellationToken = default @@ -76,14 +76,14 @@ namespace xCategoryService.Interfaces ); /// - /// Referesh a Resource ... + /// Refresh a Resource ... /// /// /// /// /// /// - Task Referesh( + Task Refresh( XSubCategoryResourceDto resource, string connectionId = null, XUserClaimsInfoDto userInfo = null, @@ -105,7 +105,7 @@ namespace xCategoryService.Interfaces /// /// /// - Task FindOne( + Task FindOneResource( Expression> predicate = null, CancellationToken cancellationToken = default ); @@ -116,7 +116,7 @@ namespace xCategoryService.Interfaces /// /// /// - Task> FindMany( + Task> FindManyResource( Expression> predicate = null, Func, IOrderedQueryable> orderBuilder = null, CancellationToken cancellationToken = default diff --git a/Interfaces/IXSubCategoryProviderController.cs b/Interfaces/IXSubCategoryProviderController.cs index 15113b7..77fabe0 100644 --- a/Interfaces/IXSubCategoryProviderController.cs +++ b/Interfaces/IXSubCategoryProviderController.cs @@ -1,10 +1,129 @@ +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; using xCategoryService.Models.Dtos; using xCategoryService.Models.Entities; using xCategoryService.Providers.Dtos; +using xModels.Dtos; using xPushService.Interfaces; namespace xCategoryService.Interfaces { - public interface IXSubCategoryProviderController: IXBaseProvidedController - { } + public interface IXSubCategoryProviderController : IXBaseProvidedController + { + /// + /// Check Has Specified Locale or not ... + /// + /// + /// + /// + /// + [HttpGet("Resources/{id}/HasLocale")] + Task> HasLocale( + [FromRoute] int id, + [FromQuery] string language, + CancellationToken cancellationToken = default + ); + + /// + /// Load an Item by all of it's Related Translations ... + /// + /// + /// + /// + [HttpGet("Resources/{id}")] + Task> GetResource( + [FromRoute] int id, + CancellationToken cancellationToken = default + ); + + /// + /// Add Category Item for Specified Language ... + /// + /// + /// + /// + /// + [HttpPost("Resources")] + Task> Add( + [FromBody] XSubCategoryDto item, + [FromQuery] string language = null, + CancellationToken cancellationToken = default + ); + + /// + /// Update a Category Item for Specified Language ... + /// + /// + /// + /// + /// + /// + [HttpPut("Resources/{id}")] + Task> Update( + [FromRoute] int id, + [FromBody] XSubCategoryDto item, + [FromQuery] string language = null, + CancellationToken cancellationToken = default + ); + + /// + /// Refresh a Resource ... + /// + /// + /// + /// + [HttpPost("Resources/Refresh")] + Task> Refresh( + [FromBody] XSubCategoryResourceDto resource, + CancellationToken cancellationToken = default + ); + + /// + /// Get All Resources ... + /// + /// + /// + [HttpGet("Resources/All")] + Task>> GetAllResources( + CancellationToken cancellationToken = default + ); + + /// + /// Find One Resource ... + /// + /// + /// + /// + [HttpGet("Resources/Find/One")] + Task> FindOneResource( + [FromQuery] string query, + CancellationToken cancellationToken = default + ); + + /// + /// Find Many Resource ... + /// + /// + /// + /// + [HttpGet("Resources/Find/Many")] + Task>> FindManyResource( + [FromQuery] string query, + CancellationToken cancellationToken = default + ); + + /// + /// Retrieve Resources by Query Pattern ... + /// + /// + /// + /// + [HttpGet("Resources/Query")] + Task>> QueryResources( + [FromQuery] XQuery query = null, + CancellationToken cancellationToken = default + ); + } } \ No newline at end of file diff --git a/Providers/XCategoryProvider.cs b/Providers/XCategoryProvider.cs index eae1695..29fdf12 100644 --- a/Providers/XCategoryProvider.cs +++ b/Providers/XCategoryProvider.cs @@ -154,14 +154,14 @@ namespace xCategoryService.Providers /// Add an Item for Specified Language ... /// /// - /// + /// /// /// /// /// public async Task Add( XCategoryDto item, - string langauge = null, + string language = null, string connectionId = null, XUserClaimsInfoDto userInfo = null, CancellationToken cancellationToken = default @@ -169,9 +169,9 @@ namespace xCategoryService.Providers { // // Normalize ... - langauge = - !langauge.IsNullOrEmpty() - ? langauge + language = + !language.IsNullOrEmpty() + ? language : appConfiguration.DefaultLanguage; // @@ -220,7 +220,7 @@ namespace xCategoryService.Providers locale: new XLocaleResourceDto { Value = title, - Language = langauge + Language = language }, connectionId: connectionId, cancellationToken: cancellationToken @@ -231,7 +231,7 @@ namespace xCategoryService.Providers locale: new XLocaleResourceDto { Value = description, - Language = langauge + Language = language }, connectionId: connectionId, cancellationToken: cancellationToken @@ -415,7 +415,7 @@ namespace xCategoryService.Providers } // - resource = await Referesh( + resource = await Refresh( resource: resource, userInfo: userInfo, connectionId: connectionId, @@ -427,14 +427,14 @@ namespace xCategoryService.Providers } /// - /// Referesh a Resource ... + /// Refresh a Resource ... /// /// /// /// /// /// - public async Task Referesh( + public async Task Refresh( XCategoryResourceDto resource, string connectionId = null, XUserClaimsInfoDto userInfo = null, @@ -792,7 +792,7 @@ namespace xCategoryService.Providers /// /// /// - public async Task FindOne( + public async Task FindOneResource( Expression> predicate = null, CancellationToken cancellationToken = default ) @@ -831,7 +831,7 @@ namespace xCategoryService.Providers /// /// /// - public async Task> FindMany( + public async Task> FindManyResource( Expression> predicate = null, Func, IOrderedQueryable> orderBuilder = null, CancellationToken cancellationToken = default @@ -893,7 +893,7 @@ namespace xCategoryService.Providers query = query.NormalizeQuery(dataServiceConfiguration); // - var items = await FindMany( + var items = await FindManyResource( predicate: predicate, orderBuilder: orderBuilder, cancellationToken: cancellationToken diff --git a/Providers/XSubCategoryProvider.cs b/Providers/XSubCategoryProvider.cs index 51a3fb5..13609a9 100644 --- a/Providers/XSubCategoryProvider.cs +++ b/Providers/XSubCategoryProvider.cs @@ -153,14 +153,14 @@ namespace xCategoryService.Providers /// Add an Item for Specified Language ... /// /// - /// + /// /// /// /// /// public async Task Add( XSubCategoryDto item, - string langauge = null, + string language = null, string connectionId = null, XUserClaimsInfoDto userInfo = null, CancellationToken cancellationToken = default @@ -168,9 +168,9 @@ namespace xCategoryService.Providers { // // Normalize ... - langauge = - !langauge.IsNullOrEmpty() - ? langauge + language = + !language.IsNullOrEmpty() + ? language : appConfiguration.DefaultLanguage; // @@ -219,7 +219,7 @@ namespace xCategoryService.Providers locale: new XLocaleResourceDto { Value = title, - Language = langauge + Language = language }, connectionId: connectionId, cancellationToken: cancellationToken @@ -230,7 +230,7 @@ namespace xCategoryService.Providers locale: new XLocaleResourceDto { Value = description, - Language = langauge + Language = language }, connectionId: connectionId, cancellationToken: cancellationToken @@ -414,7 +414,7 @@ namespace xCategoryService.Providers } // - resource = await Referesh( + resource = await Refresh( resource: resource, userInfo: userInfo, connectionId: connectionId, @@ -426,14 +426,14 @@ namespace xCategoryService.Providers } /// - /// Referesh a Resource ... + /// Refresh a Resource ... /// /// /// /// /// /// - public async Task Referesh( + public async Task Refresh( XSubCategoryResourceDto resource, string connectionId = null, XUserClaimsInfoDto userInfo = null, @@ -791,7 +791,7 @@ namespace xCategoryService.Providers /// /// /// - public async Task FindOne( + public async Task FindOneResource( Expression> predicate = null, CancellationToken cancellationToken = default ) @@ -830,7 +830,7 @@ namespace xCategoryService.Providers /// /// /// - public async Task> FindMany( + public async Task> FindManyResource( Expression> predicate = null, Func, IOrderedQueryable> orderBuilder = null, CancellationToken cancellationToken = default @@ -892,7 +892,7 @@ namespace xCategoryService.Providers query = query.NormalizeQuery(dataServiceConfiguration); // - var items = await FindMany( + var items = await FindManyResource( predicate: predicate, orderBuilder: orderBuilder, cancellationToken: cancellationToken