Compare commits

..
10 Commits
Author SHA1 Message Date
saherelm 335fd95d23 refactor and add using constants instead of hard coded strings ... 2026-07-30 14:27:17 +03:30
saherelm e37bad59ac Refactor Category Service ...
- Add all HardCoded Strings in Constants ...
- Apply Resolve Constant Replacement Side Affects ...
- add Support for Service Main Provider ...
2026-07-28 21:31:42 +03:30
saherelm 4e67edeb85 last ... 2026-07-26 21:19:29 +03:30
saherelm a029543b72 fix referencing issues ...
fix seeding issues ...
fix SubCategory Refresh and Add Support for handle Category Referesh and Referencing ...
2026-07-24 02:49:46 +03:30
saherelm a8e073901f fix Category and SubCategory Referencing and Providers ... 2026-07-24 01:13:38 +03:30
saherelm 234f39876b last works on Category and SubCategory Completion ... 2026-07-08 02:47:15 +03:30
saherelm fdd76137e0 last ... 2026-07-01 17:38:29 +03:30
saherelm 4c212ace1b add support for xCategorySubCategoryReferenceProvider in XCategory Provider ... 2026-06-28 14:11:58 +03:30
saherelm 196f3b1fe4 last ... 2026-06-28 10:45:39 +03:30
saherelm 4f8147e469 last ... 2026-06-20 21:52:38 +03:30
35 changed files with 3050 additions and 64 deletions
@@ -1,5 +1,6 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using xCategoryService.Constants;
using xCategoryService.Models.Entities;
using xDataService.Providers;
@@ -9,7 +10,7 @@ namespace xCategoryService.Configurations.Entities
{
public override void Configure(EntityTypeBuilder<XCategory> builder)
{
builder.ToTable("Categories");
builder.ToTable(XCategoryServiceConstants.XCategoryTable);
}
}
}
@@ -1,5 +1,6 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using xCategoryService.Constants;
using xCategoryService.Models.Entities;
using xDataService.Providers;
@@ -9,7 +10,7 @@ namespace xCategoryService.Configurations.Entities
{
public override void Configure(EntityTypeBuilder<XSubCategory> builder)
{
builder.ToTable("SubCategories");
builder.ToTable(XCategoryServiceConstants.XSubCategoryTable);
}
}
}
@@ -0,0 +1,20 @@
using xCategoryService.Models.Dtos;
namespace xCategoryService.Configurations
{
/// <summary>
/// a Configuration Class for Providing Data to Configure XCategoryService ...
/// </summary>
public class XCategoryServiceConfiguration
{
/// <summary>
/// a List of Categories for Seeding ...
/// </summary>
public XCategoryResourceDto[] Categories { get; set; } = [];
/// <summary>
/// a List of SubCategories for Seeding ...
/// </summary>
public XSubCategoryResourceDto[] SubCategories { get; set; } = [];
}
}
+7
View File
@@ -0,0 +1,7 @@
namespace xCategoryService.Constants
{
public partial struct ConfigurationNodeNames
{
public const string CATEGORY_SERVICE_NODE = "CategoryServiceConfiguration";
}
}
+41
View File
@@ -0,0 +1,41 @@
namespace xCategoryService.Constants
{
public struct XCategoryServiceConstants
{
//
// Service Extensions Log Tag ...
public const string XCategoryServiceDILogTag = "XCategoryService";
//
// Table Mapping Identifiers ...
public const string XCategoryTable = "Categories";
public const string XSubCategoryTable = "SubCategories";
//
// GraphQL Collection Mappings ...
public const string XCategorySingleName = "category";
public const string XCategoryCollectionName = "categories";
public const string XSubCategorySingleName = "subCategory";
public const string XSubCategoryCollectionName = "subCategories";
//
// Hubs ...
public const string XCategoryDtoHub = "categoryDto";
public const string XCategoryEntityHub = "categoryEntity";
public const string XSubCategoryDtoHub = "subCategoryDto";
public const string XSubCategoryEntityHub = "subCategoryEntity";
//
// Custome Constants ...
public const string SubCategoryReference = "SubCat";
public const string CategoryTitleResourceIdentifier = "CatT";
public const string CategoryDescriptionResourceIdentifier = "CatD";
public const string SubCategoryTitleResourceIdentifier = "SubCatT";
public const string SubCategoryDescriptionResourceIdentifier = "SubCatD";
//
// EF Repositories Helper Extensions ...
public const string GetXCategoryEFRepositoryDescriptor = "GetXCategoryEFRepositoryDescriptor";
public const string GetXSubCategoryEFRepositoryDescriptor = "GetXSubCategoryEFRepositoryDescriptor";
}
}
@@ -336,6 +336,58 @@ namespace xCategoryService.Controllers
}
}
/// <summary>
/// Add Category Item for by It's Locales ...
/// </summary>
/// <param name="item"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpPost("Resources/AddResource")]
public virtual async Task<ActionResult<XCategoryResourceDto>> AddResource(
[FromBody] XCategoryResourceDto item,
CancellationToken cancellationToken = default
)
{
//
try
{
//
// Validate ...
if (!ModelState.IsValid)
{
XException.InvalidArgs.Throw();
}
await ValidationProvider
.GroupValidationBuilder()
.AddNotNull(item)
.AddNotNull(item.Titles)
.AddNotZeroChilds(item.Titles.Locales)
.ValidateGroupAsync();
//
// Reading Requirements ...
var userInfo = await GetUserInfo();
var connectionId = GetConnectionId();
//
var result = await provider.AddResource(
item: item,
userInfo: userInfo,
connectionId: connectionId,
cancellationToken: cancellationToken
);
//
return Ok(result.ToDynamicObject());
}
catch (Exception ex)
{
//
var result = GetExceptionActionResult(ex);
return result;
}
}
/// <summary>
/// Remove Item for Specified Language ...
/// </summary>
@@ -336,6 +336,58 @@ namespace xCategoryService.Controllers
}
}
/// <summary>
/// Add Item by it's Locales and Reference ...
/// </summary>
/// <param name="item"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpPost("Resources/AddResource")]
public virtual async Task<ActionResult<XSubCategoryResourceDto>> AddResource(
[FromBody] XSubCategoryResourceDto item,
CancellationToken cancellationToken = default
)
{
//
try
{
//
// Validate ...
if (!ModelState.IsValid)
{
XException.InvalidArgs.Throw();
}
await ValidationProvider
.GroupValidationBuilder()
.AddNotNull(item)
.AddNotNull(item.Titles)
.AddNotZeroChilds(item.Titles.Locales)
.ValidateGroupAsync();
//
// Reading Requirements ...
var userInfo = await GetUserInfo();
var connectionId = GetConnectionId();
//
var result = await provider.AddResource(
item: item,
userInfo: userInfo,
connectionId: connectionId,
cancellationToken: cancellationToken
);
//
return Ok(result.ToDynamicObject());
}
catch (Exception ex)
{
//
var result = GetExceptionActionResult(ex);
return result;
}
}
/// <summary>
/// Remove Item for Specified Language ...
/// </summary>
+199 -16
View File
@@ -1,6 +1,10 @@
using System;
using System.Linq;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using xCategoryService.Configurations;
using xCategoryService.Constants;
using xCategoryService.Helpers;
using xCategoryService.Interfaces;
using xCategoryService.Interfaces.Dtos;
@@ -8,7 +12,6 @@ using xCategoryService.Interfaces.Entities;
using xCategoryService.Providers;
using xCategoryService.Providers.Dtos;
using xCategoryService.Providers.Entities;
using xCategoryService.Providers.GraphQL;
using xCommons.Extensions;
using xCommons.Helpers;
using xDataService.Constants;
@@ -23,6 +26,71 @@ namespace xCategoryService.DI
{
public static class XDIHelperExtension
{
/// <summary>
/// Extract Service Configurations ...
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static XCategoryServiceConfiguration GetXCategoryServiceConfigurations(
this IConfiguration source
)
{
//
XCategoryServiceConfiguration result = null;
//
var section = source.GetSection(Constants.ConfigurationNodeNames.CATEGORY_SERVICE_NODE);
var sectionJson = source.GetSectionAsJson(Constants.ConfigurationNodeNames.CATEGORY_SERVICE_NODE);
if (!section.IsNull())
{
result = sectionJson.FromJSON<XCategoryServiceConfiguration>();
}
//
return result;
}
/// <summary>
/// Register Service Configuration ...
/// </summary>
/// <param name="source"></param>
/// <param name="configuration"></param>
public static void AddXCategoryServiceConfiguration(
this IServiceCollection source,
IConfiguration configuration
)
{
//
// Extract Configuration Class ...
var config = configuration.GetXCategoryServiceConfigurations();
//
// Register Class as Service ...
source.AddXCategoryServiceConfiguration(config);
}
/// <summary>
/// Register Service Configuration ...
/// </summary>
/// <param name="source"></param>
/// <param name="configuration"></param>
public static void AddXCategoryServiceConfiguration(
this IServiceCollection source,
XCategoryServiceConfiguration configuration
)
{
//
// Normalize Configuration Class ...
if (configuration.IsNull())
{
configuration = new XCategoryServiceConfiguration();
}
//
// Register ...
source.AddSingleton(configuration);
}
/// <summary>
/// Register Service ...
/// </summary>
@@ -76,19 +144,19 @@ namespace xCategoryService.DI
)
{
//
#region Using Hubs ...
#region Using Hubs ...
//
var pushHelper = new XPushServiceHelper();
//
// Category ...
pushHelper.AddHub<XCategoryDtoHub>("categoryDto");
pushHelper.AddHub<XCategoryEntityHub>("categoryEntity");
pushHelper.AddHub<XCategoryDtoHub>(XCategoryServiceConstants.XCategoryDtoHub);
pushHelper.AddHub<XCategoryEntityHub>(XCategoryServiceConstants.XCategoryEntityHub);
//
// SubCategory ...
// pushHelper.AddHub<XSubCategoryDtoHub>("subCategoryDto");
// pushHelper.AddHub<XSubCategoryEntityHub>("subCategoryEntity");
pushHelper.AddHub<XSubCategoryDtoHub>(XCategoryServiceConstants.XSubCategoryDtoHub);
pushHelper.AddHub<XSubCategoryEntityHub>(XCategoryServiceConstants.XSubCategoryEntityHub);
//
app.UseXPushService(pushHelper);
@@ -109,11 +177,114 @@ namespace xCategoryService.DI
// Using XSubCategory Repository Descriptor ...
if (!subCategoryDescriptor.IsNull())
{
// //
// app.UseXRepository(
// descriptor: subCategoryDescriptor,
// isDevelopmentEnvironment: isDevelopmentEnvironment
// );
//
app.UseXRepository(
descriptor: subCategoryDescriptor,
isDevelopmentEnvironment: isDevelopmentEnvironment
);
}
//
// Create an Scope for Services Acces ...
// Handle Seeding Category/SubCategory Resources ...
using (var scope = app.ApplicationServices.CreateScope())
{
//
// Retrieve Configuratuions ...
var categoryProvider = scope.ServiceProvider.GetService<IXCategoryProvider>();
var subCategoryProvider = scope.ServiceProvider.GetService<IXSubCategoryProvider>();
var configuration = scope.ServiceProvider.GetService<XCategoryServiceConfiguration>();
if (!configuration.IsNullOrDefault() &&
!categoryProvider.IsNullOrDefault() &&
!subCategoryDescriptor.IsNullOrDefault()
)
{
//
// Logging ...
Log("Start Seeding ...");
//
// Count Data in Category ...
var hasCategory = categoryProvider.Count().GetAwaiter().GetResult() > 0;
var hasSubCategory = subCategoryProvider.Count().GetAwaiter().GetResult() > 0;
//
// Seed Category Resources ...
var canSeed =
!hasCategory &&
configuration.Categories.HasChild();
if (canSeed)
{
//
// Loop through Provided items ...
foreach (var cat in configuration.Categories)
{
//
try
{
//
Log($"Start Seeding Category: {cat.Titles.Locales.ToArray()[0].Value} ...");
//
categoryProvider.Refresh(
resource: cat,
userInfo: null,
connectionId: null,
cancellationToken: default
)
.GetAwaiter()
.GetResult();
//
Log($"Seeding Category: {cat.Titles.Locales.ToArray()[0].Value} Finished Successfully ...");
}
catch (Exception ex)
{
Log($"Seeding Category: {cat.Titles.Locales.ToArray()[0].Value} Failed due: {ex.Message} ...");
}
}
}
//
// Seed SubCategory Resources ...
canSeed =
!hasSubCategory &&
configuration.SubCategories.HasChild();
if (canSeed)
{
//
// Loop through Provided items ...
foreach (var subcat in configuration.SubCategories)
{
//
try
{
//
Log($"Start Seeding SubCategory: {subcat.Titles.Locales.ToArray()[0].Value} ...");
//
subCategoryProvider.Refresh(
userInfo: null,
resource: subcat,
connectionId: null,
cancellationToken: default
)
.GetAwaiter()
.GetResult();
//
Log($"Seeding SubCategory: {subcat.Titles.Locales.ToArray()[0].Value} Finished Successfully ...");
}
catch (Exception ex)
{
Log($"Seeding SubCategory: {subcat.Titles.Locales.ToArray()[0].Value} Failed due: {ex.Message} ...");
}
}
}
//
Log("Finish Seeding ...");
}
}
}
@@ -125,7 +296,7 @@ namespace xCategoryService.DI
/// <summary>
/// a LogTag for Service ...
/// </summary>
private static string XLogTag = "XCategoryService";
private static string XLogTag = XCategoryServiceConstants.XCategoryServiceDILogTag;
/// <summary>
/// print a log in Console ...
@@ -199,18 +370,18 @@ namespace xCategoryService.DI
// Category ...
categoryDescriptor = typeof(XCategoryServiceHelper)
.InvokeGenericMethod<XRepositoryDescriptor>(
methodName: "GetXCategoryEFRepositoryDescriptor",
args: null,
runtimeType: contextType,
args: null
methodName: XCategoryServiceConstants.GetXCategoryEFRepositoryDescriptor
);
//
// SubCategory ...
subCategoryDescriptor = typeof(XCategoryServiceHelper)
.InvokeGenericMethod<XRepositoryDescriptor>(
methodName: "GetXSubCategoryEFRepositoryDescriptor",
args: null,
runtimeType: contextType,
args: null
methodName: XCategoryServiceConstants.GetXSubCategoryEFRepositoryDescriptor
);
break;
@@ -284,6 +455,12 @@ namespace xCategoryService.DI
new ServiceDescriptor(typeof(IXCategoryDescriptionResourceProvider), typeof(XCategoryDescriptionResourceProvider), lifeTime)
);
//
// Reference Providers ...
services.Add(
new ServiceDescriptor(typeof(IXCategorySubCategoryReferenceProvider), typeof(XCategorySubCategoryReferenceProvider), lifeTime)
);
//
// Provider ...
services.Add(
@@ -322,6 +499,12 @@ namespace xCategoryService.DI
#endregion
#endregion
//
// Register Service Main Provider ...
services.Add(
new ServiceDescriptor(typeof(IXCategoryService), typeof(XCategoryService), lifeTime)
);
//
Log("Service Regitration Succeed ...");
}
+149
View File
@@ -0,0 +1,149 @@
using System.Collections.Generic;
using System.Linq;
using xCategoryService.Models.Dtos;
using xCategoryService.Models.Entities;
using xCommons.Extensions;
using xDataService.Extensions;
using xDataService.Models;
namespace xCategoryService.Extensions
{
public static class XModelExtensions
{
/// <summary>
/// Extract References of a Model ...
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static IList<XReference<string>> GetReferences(
this XCategory source
)
{
//
var result = new List<XReference<string>>();
//
if (
!source.IsNullOrDefault() &&
!source.References.IsNullOrEmpty()
)
{
//
result = source.References
.ParseXReferenceList<string>()
.ToList();
}
//
return result;
}
/// <summary>
/// Extract References of a Model ...
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static IList<XReference<string>> GetReferences(
this XCategoryDto source
)
{
//
var result = new List<XReference<string>>();
//
if (
!source.IsNullOrDefault() &&
!source.References.IsNullOrEmpty()
)
{
//
result = source.References
.ParseXReferenceList<string>()
.ToList();
}
//
return result;
}
/// <summary>
/// Update a Model's References by Providing References List ...
/// </summary>
/// <param name="source"></param>
/// <param name="references"></param>
/// <param name="forceClean"></param>
/// <returns></returns>
public static XCategory UpdateReferences(
this XCategory source,
IList<XReference<string>> references,
bool forceClean = true
)
{
//
XCategory result = source;
//
if (!source.IsNullOrDefault())
{
//
result = source;
//
if (forceClean)
{
result.References = string.Empty;
}
//
if (!references.IsNull() &&
references.HasChild())
{
result.References = references.ToXReferenceString();
}
}
//
return result;
}
/// <summary>
/// Update a Model's References by Providing References List ...
/// </summary>
/// <param name="source"></param>
/// <param name="references"></param>
/// <param name="forceClean"></param>
/// <returns></returns>
public static XCategoryDto UpdateReferences(
this XCategoryDto source,
IList<XReference<string>> references,
bool forceClean = true
)
{
//
XCategoryDto result = source;
//
if (!source.IsNullOrDefault())
{
//
result = source;
//
if (forceClean)
{
result.References = string.Empty;
}
//
if (!references.IsNull() &&
references.HasChild())
{
result.References = references.ToXReferenceString();
}
}
//
return result;
}
}
}
@@ -1,7 +1,7 @@
using xCategoryService.Models.Entities;
using xDataService.Interfaces;
namespace xCategoryService.Interfaces
namespace xCategoryService.Interfaces.Entities
{
public interface IXCategorySeeder : IXBaseDbSeeder<XCategory, int>
{ }
@@ -1,7 +1,7 @@
using xCategoryService.Models.Entities;
using xDataService.Interfaces;
namespace xCategoryService.Interfaces
namespace xCategoryService.Interfaces.Entities
{
public interface IXSubCategorySeeder : IXBaseDbSeeder<XSubCategory, int>
{ }
+8
View File
@@ -0,0 +1,8 @@
using xCategoryService.Models.Dtos;
using xDataService.Interfaces;
namespace xCategoryService.Interfaces
{
public interface IXBaseCategoryProvider<TKey> : IXBaseReferencedProvider<XCategoryDto, TKey>
{}
}
+17 -1
View File
@@ -13,7 +13,7 @@ using xPushService.Interfaces;
namespace xCategoryService.Interfaces
{
public interface IXCategoryProvider : IXBaseProvided<XCategory, XCategoryDto, int, XCategoryDtoHub>
public interface IXCategoryProvider : IXBaseProvided<XCategory, XCategoryDto, int, XCategoryDtoHub>, IXCategorySubCategoryReferenceProvider
{
/// <summary>
/// Check Has Specified Locale or not ...
@@ -56,6 +56,21 @@ namespace xCategoryService.Interfaces
CancellationToken cancellationToken = default
);
/// <summary>
/// Add Item by It's Locales ...
/// </summary>
/// <param name="item"></param>
/// <param name="connectionId"></param>
/// <param name="userInfo"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<XCategoryResourceDto> AddResource(
XCategoryResourceDto item,
string connectionId = null,
XUserClaimsInfoDto userInfo = null,
CancellationToken cancellationToken = default
);
/// <summary>
/// Remove Item for Specified Language ...
/// </summary>
@@ -131,6 +146,7 @@ namespace xCategoryService.Interfaces
/// Find Many Resource ...
/// </summary>
/// <param name="predicate"></param>
/// <param name="orderBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<IEnumerable<XCategoryResourceDto>> FindManyResource(
@@ -52,6 +52,18 @@ namespace xCategoryService.Interfaces
CancellationToken cancellationToken = default
);
/// <summary>
/// Add Item by It's Locales ...
/// </summary>
/// <param name="item"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpPost("Resources/AddResource")]
Task<ActionResult<XCategoryResourceDto>> AddResource(
[FromBody] XCategoryResourceDto item,
CancellationToken cancellationToken = default
);
/// <summary>
/// Remove Item for Specified Language ...
/// </summary>
+352
View File
@@ -0,0 +1,352 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using xCategoryService.Models.Dtos;
using xIdentityModels.Models;
using xModels.Dtos;
namespace xCategoryService.Interfaces
{
/// <summary>
/// Completely Exported Service ...
/// </summary>
public interface IXCategoryService
{
//
#region Category Provider ...
/// <summary>
/// Check Has Specified Locale or not ...
/// </summary>
/// <param name="id"></param>
/// <param name="language"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<bool> CategoryHasLocale(
int id,
string language,
CancellationToken cancellationToken = default
);
/// <summary>
/// Load an Item by all of it's Related Translations ...
/// </summary>
/// <param name="id"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<XCategoryResourceDto> GetCategoryResource(
int id,
CancellationToken cancellationToken = default
);
/// <summary>
/// Add Item for Specified Language ...
/// </summary>
/// <param name="item"></param>
/// <param name="language"></param>
/// <param name="connectionId"></param>
/// <param name="userInfo"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<XCategoryResourceDto> AddCategory(
XCategoryDto item,
string language = null,
string connectionId = null,
XUserClaimsInfoDto userInfo = null,
CancellationToken cancellationToken = default
);
/// <summary>
/// Add Item by It's Locales ...
/// </summary>
/// <param name="item"></param>
/// <param name="connectionId"></param>
/// <param name="userInfo"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<XCategoryResourceDto> AddCategoryResource(
XCategoryResourceDto item,
string connectionId = null,
XUserClaimsInfoDto userInfo = null,
CancellationToken cancellationToken = default
);
/// <summary>
/// Remove Item for Specified Language ...
/// </summary>
/// <param name="id"></param>
/// <param name="language">if null, Remove All</param>
/// <param name="connectionId"></param>
/// <param name="userInfo"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<XCategoryResourceDto> RemoveCategory(
int id,
string language = null,
string connectionId = null,
XUserClaimsInfoDto userInfo = null,
CancellationToken cancellationToken = default
);
/// <summary>
/// Update an Item for Specified Language ...
/// </summary>
/// <param name="id"></param>
/// <param name="item"></param>
/// <param name="language"></param>
/// <param name="connectionId"></param>
/// <param name="userInfo"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<XCategoryResourceDto> UpdateCategory(
int id,
XCategoryDto item,
string language = null,
string connectionId = null,
XUserClaimsInfoDto userInfo = null,
CancellationToken cancellationToken = default
);
/// <summary>
/// Refresh a Resource ...
/// </summary>
/// <param name="resource"></param>
/// <param name="connectionId"></param>
/// <param name="userInfo"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<XCategoryResourceDto> RefreshCategory(
XCategoryResourceDto resource,
string connectionId = null,
XUserClaimsInfoDto userInfo = null,
CancellationToken cancellationToken = default
);
/// <summary>
/// Get All Resources ...
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<IEnumerable<XCategoryResourceDto>> GetAllCategoryResources(
CancellationToken cancellationToken = default
);
/// <summary>
/// Find One Resource ...
/// </summary>
/// <param name="predicate"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<XCategoryResourceDto> FindOneCategoryResource(
Expression<Func<XCategoryResourceDto, bool>> predicate = null,
CancellationToken cancellationToken = default
);
/// <summary>
/// Find Many Resource ...
/// </summary>
/// <param name="predicate"></param>
/// <param name="orderBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<IEnumerable<XCategoryResourceDto>> FindManyCategoryResource(
Expression<Func<XCategoryResourceDto, bool>> predicate = null,
Func<IQueryable<XCategoryResourceDto>, IOrderedQueryable<XCategoryResourceDto>> orderBuilder = null,
CancellationToken cancellationToken = default
);
/// <summary>
/// Retrieve Resources by Query Pattern ...
/// </summary>
/// <param name="query"></param>
/// <param name="predicate"></param>
/// <param name="orderBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<XQueryResult<XCategoryResourceDto>> QueryCategoryResources(
XQuery query = null,
Expression<Func<XCategoryResourceDto, bool>> predicate = null,
Func<IQueryable<XCategoryResourceDto>, IOrderedQueryable<XCategoryResourceDto>> orderBuilder = null,
CancellationToken cancellationToken = default
);
/// <summary>
/// Get All Resources as Async Enumerable ...
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
IAsyncEnumerable<XCategoryResourceDto> GetAllCategoryResourcesAsAsyncEnumerable(
CancellationToken cancellationToken = default
);
#endregion
//
#region SubCategory Provider ...
/// <summary>
/// Check Has Specified Locale or not ...
/// </summary>
/// <param name="id"></param>
/// <param name="language"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<bool> SubCategoryHasLocale(
int id,
string language,
CancellationToken cancellationToken = default
);
/// <summary>
/// Load an Item by all of it's Related Translations ...
/// </summary>
/// <param name="id"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<XSubCategoryResourceDto> GetSubCategoryResource(
int id,
CancellationToken cancellationToken = default
);
/// <summary>
/// Add Item for Specified Language ...
/// </summary>
/// <param name="item"></param>
/// <param name="language"></param>
/// <param name="connectionId"></param>
/// <param name="userInfo"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<XSubCategoryResourceDto> AddSubCategory(
XSubCategoryDto item,
string language = null,
string connectionId = null,
XUserClaimsInfoDto userInfo = null,
CancellationToken cancellationToken = default
);
/// <summary>
/// Add Item by it's Locales and Reference ...
/// </summary>
/// <param name="item"></param>
/// <param name="connectionId"></param>
/// <param name="userInfo"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<XSubCategoryResourceDto> AddSubCategoryResource(
XSubCategoryResourceDto item,
string connectionId = null,
XUserClaimsInfoDto userInfo = null,
CancellationToken cancellationToken = default
);
/// <summary>
/// Remove Item for Specified Language ...
/// </summary>
/// <param name="id"></param>
/// <param name="language">if null, Remove All</param>
/// <param name="connectionId"></param>
/// <param name="userInfo"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<XSubCategoryResourceDto> RemoveSubCategory(
int id,
string language = null,
string connectionId = null,
XUserClaimsInfoDto userInfo = null,
CancellationToken cancellationToken = default
);
/// <summary>
/// Update an Item for Specified Language ...
/// </summary>
/// <param name="id"></param>
/// <param name="item"></param>
/// <param name="language"></param>
/// <param name="connectionId"></param>
/// <param name="userInfo"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<XSubCategoryResourceDto> UpdateSubCategory(
int id,
XSubCategoryDto item,
string language = null,
string connectionId = null,
XUserClaimsInfoDto userInfo = null,
CancellationToken cancellationToken = default
);
/// <summary>
/// Refresh a Resource ...
/// </summary>
/// <param name="resource"></param>
/// <param name="connectionId"></param>
/// <param name="userInfo"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<XSubCategoryResourceDto> RefreshSubCategory(
XSubCategoryResourceDto resource,
string connectionId = null,
XUserClaimsInfoDto userInfo = null,
CancellationToken cancellationToken = default
);
/// <summary>
/// Get All Resources ...
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<IEnumerable<XSubCategoryResourceDto>> GetAllSubCategoryResources(
CancellationToken cancellationToken = default
);
/// <summary>
/// Find One Resource ...
/// </summary>
/// <param name="predicate"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<XSubCategoryResourceDto> FindOneSubCategoryResource(
Expression<Func<XSubCategoryResourceDto, bool>> predicate = null,
CancellationToken cancellationToken = default
);
/// <summary>
/// Find Many Resource ...
/// </summary>
/// <param name="predicate"></param>
/// <param name="orderBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<IEnumerable<XSubCategoryResourceDto>> FindManySubCategoryResource(
Expression<Func<XSubCategoryResourceDto, bool>> predicate = null,
Func<IQueryable<XSubCategoryResourceDto>, IOrderedQueryable<XSubCategoryResourceDto>> orderBuilder = null,
CancellationToken cancellationToken = default
);
/// <summary>
/// Retrieve Resources by Query Pattern ...
/// </summary>
/// <param name="query"></param>
/// <param name="predicate"></param>
/// <param name="orderBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<XQueryResult<XSubCategoryResourceDto>> QuerySubCategoryResources(
XQuery query = null,
Expression<Func<XSubCategoryResourceDto, bool>> predicate = null,
Func<IQueryable<XSubCategoryResourceDto>, IOrderedQueryable<XSubCategoryResourceDto>> orderBuilder = null,
CancellationToken cancellationToken = default
);
/// <summary>
/// Get All Resources as Async Enumerable ...
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
IAsyncEnumerable<XSubCategoryResourceDto> GetAllSubCategoryResourcesAsAsyncEnumerable(
CancellationToken cancellationToken = default
);
#endregion
}
}
@@ -0,0 +1,8 @@
namespace xCategoryService.Interfaces
{
/// <summary>
/// a Service for SubCategory Referencing on Category ...
/// </summary>
public interface IXCategorySubCategoryReferenceProvider : IXBaseCategoryProvider<int>
{ }
}
+16
View File
@@ -56,6 +56,21 @@ namespace xCategoryService.Interfaces
CancellationToken cancellationToken = default
);
/// <summary>
/// Add Item by it's Locales and Reference ...
/// </summary>
/// <param name="item"></param>
/// <param name="connectionId"></param>
/// <param name="userInfo"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<XSubCategoryResourceDto> AddResource(
XSubCategoryResourceDto item,
string connectionId = null,
XUserClaimsInfoDto userInfo = null,
CancellationToken cancellationToken = default
);
/// <summary>
/// Remove Item for Specified Language ...
/// </summary>
@@ -131,6 +146,7 @@ namespace xCategoryService.Interfaces
/// Find Many Resource ...
/// </summary>
/// <param name="predicate"></param>
/// <param name="orderBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<IEnumerable<XSubCategoryResourceDto>> FindManyResource(
@@ -52,6 +52,18 @@ namespace xCategoryService.Interfaces
CancellationToken cancellationToken = default
);
/// <summary>
/// Add Item by it's Locales and Reference ...
/// </summary>
/// <param name="item"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpPost("Resources/AddResource")]
Task<ActionResult<XSubCategoryResourceDto>> AddResource(
[FromBody] XSubCategoryResourceDto item,
CancellationToken cancellationToken = default
);
/// <summary>
/// Remove Item for Specified Language ...
/// </summary>
@@ -1,16 +1,26 @@
using xCategoryService.Models.Dtos;
using xModels.Base;
using xModels.Dtos;
namespace xCategoryService.Providers.Dtos
namespace xCategoryService.Models.Dtos
{
/// <summary>
/// Represent a Category by all of it's Resources ...
/// </summary>
public class XCategoryResourceDto : XBaseDto
{
/// <summary>
/// Category Dto Item for Add or Update ...
/// </summary>
public XCategoryDto Item { get; set; }
/// <summary>
/// Exists Category Titles ...
/// </summary>
public XResourceDto Titles { get; set; }
/// <summary>
/// Exists Category Description ...
/// </summary>
public XResourceDto Descriptions { get; set; }
}
}
+29
View File
@@ -0,0 +1,29 @@
using xModels.Base;
using xModels.Dtos;
namespace xCategoryService.Models.Dtos
{
public class XSubCategoryResourceDto : XBaseDto
{
/// <summary>
/// SubCategory Dto Item for Add or Update ...
/// </summary>
public XSubCategoryDto Item { get; set; }
/// <summary>
/// Exists SubCategory Titles ...
/// </summary>
public XResourceDto Titles { get; set; }
/// <summary>
/// Exists SubCategory Description ...
/// </summary>
public XResourceDto Descriptions { get; set; }
/// <summary>
/// Exists Category Resource Dto for Add or Update Category or
/// Related Categopry ...
/// </summary>
public XCategoryResourceDto Category { get; set; }
}
}
-13
View File
@@ -1,13 +0,0 @@
using xCategoryService.Models.Dtos;
using xModels.Base;
using xModels.Dtos;
namespace xCategoryService.Providers.Dtos
{
public class XSubCategoryResourceDto : XBaseDto
{
public XSubCategoryDto Item { get; set; }
public XResourceDto Titles { get; set; }
public XResourceDto Descriptions { get; set; }
}
}
@@ -1,10 +1,9 @@
using xCategoryService.Interfaces;
using xCategoryService.Interfaces.Entities;
using xCategoryService.Models.Entities;
using xDataService.Configuration;
using xDataService.Providers;
namespace xCategoryService.Providers
namespace xCategoryService.Providers.Entities
{
public abstract class XCategorySeederBase : XBaseDbSeeder<XCategory, int>, IXCategorySeeder
{
@@ -1,10 +1,9 @@
using xCategoryService.Interfaces;
using xCategoryService.Interfaces.Entities;
using xCategoryService.Models.Entities;
using xDataService.Configuration;
using xDataService.Providers;
namespace xCategoryService.Providers
namespace xCategoryService.Providers.Entities
{
public abstract class XSubCategorySeederBase : XBaseDbSeeder<XSubCategory, int>, IXSubCategorySeeder
{
@@ -1,3 +1,4 @@
using xCategoryService.Constants;
using xCategoryService.Interfaces.Entities;
using xCategoryService.Models.Entities;
using xDataService.Configuration;
@@ -14,12 +15,12 @@ namespace xCategoryService.Providers.GraphQL
public override string GetInQueryCollectionName()
{
return "categories";
return XCategoryServiceConstants.XCategoryCollectionName;
}
public override string GetInQuerySingleName()
{
return "category";
return XCategoryServiceConstants.XCategorySingleName;
}
}
}
@@ -1,3 +1,4 @@
using xCategoryService.Constants;
using xCategoryService.Interfaces.Entities;
using xCategoryService.Models.Entities;
using xDataService.Configuration;
@@ -14,12 +15,12 @@ namespace xCategoryService.Providers.GraphQL
public override string GetInQueryCollectionName()
{
return "subCategories";
return XCategoryServiceConstants.XSubCategoryCollectionName;
}
public override string GetInQuerySingleName()
{
return "subCategory";
return XCategoryServiceConstants.XSubCategorySingleName;
}
}
}
+710
View File
@@ -0,0 +1,710 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using xCategoryService.Extensions;
using xCategoryService.Interfaces;
using xCategoryService.Interfaces.Dtos;
using xCategoryService.Models.Dtos;
using xCommons.Extensions;
using xDataService.Extensions;
using xDataService.Models;
using xExceptions.Constants;
using xModels.Dtos;
namespace xCategoryService.Providers
{
public abstract class XBaseCategoryProvider<TKey> : IXBaseCategoryProvider<TKey>
{
//
#region Props ...
/// <summary>
/// Provider Identifier ...
/// </summary>
public string Provider { get; }
/// <summary>
/// Tag Provider for Maipulating Tags ...
/// </summary>
public IXCategoryServiceProvider CategoryProvider { get; }
#endregion
//
#region Constructor ...
public XBaseCategoryProvider(
string providedFor,
IXCategoryServiceProvider categoryProvider
)
{
//
Provider = providedFor;
CategoryProvider = categoryProvider;
}
#endregion
//
#region Referenced Actions ...
/// <summary>
/// Get Specified Indexed Reference for Specific Provided ID ...
/// </summary>
/// <param name="providedForId"></param>
/// <param name="forIndex"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<XCategoryDto> GetReference(
TKey providedForId,
int forIndex = 0,
CancellationToken cancellationToken = default
)
{
//
// Validate ...
if (providedForId.IsNull())
{
XException.InvalidArgs.Throw();
}
//
// Normalize ...
if (forIndex < 0)
{
forIndex = 0;
}
//
// Retrieve Last Index ...
var indexes = await GetReferencingIndexes(
providedForId: providedForId,
cancellationToken: cancellationToken
);
var maxIndex = indexes.HasChild() ? indexes.Max() : -1;
if (forIndex > maxIndex)
{
XException.NotFound.Throw();
}
//
var indexedIdentifier = GetIndexedProvidedID(
forIndex: forIndex,
providedForId: providedForId
);
var result = await CategoryProvider.FindOneAsync(
includeBuilder: null,
ignoreSoftDeleteds: true,
cancellationToken: cancellationToken,
predicate: x => x.References.Contains(indexedIdentifier)
);
if (result.IsNullOrDefault())
{
XException.NotFound.Throw();
}
//
return result;
}
/// <summary>
/// Retrieve all Exists References of Specific Provided ID ...
/// </summary>
/// <param name="providedForId"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<IEnumerable<XCategoryDto>> GetAllReferences(
TKey providedForId,
CancellationToken cancellationToken = default
)
{
//
// Validate ...
if (providedForId.IsNull())
{
XException.InvalidArgs.Throw();
}
//
var identifier = GetProvidedID(providedForId);
var result = await CategoryProvider.FindManyAsync(
orderBuilder: null,
includeBuilder: null,
ignoreSoftDeleteds: true,
cancellationToken: cancellationToken,
predicate: x => x.References.Contains(identifier)
);
//
return result;
}
/// <summary>
/// Extract all Referencing Models for Specified Key ...
/// </summary>
/// <param name="providedForId"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<IEnumerable<XReference<TKey>>> GetAllReferencings(
TKey providedForId,
CancellationToken cancellationToken = default
)
{
//
// Validate ...
var isValid =
!providedForId.IsNull();
if (!isValid)
{
XException.InvalidArgs.Throw();
}
//
var identifier = GetProvidedID(providedForId);
//
var result = (await CategoryProvider.FindManyAsync(
orderBuilder: null,
includeBuilder: null,
ignoreSoftDeleteds: true,
cancellationToken: cancellationToken,
predicate: x => x.References.Contains(identifier)
))
.Select(x => x.References)
.ToList()
.SelectMany(x => x.ParseXReferenceList<TKey>())
.Where(x => x.ProvidedFor == Provider && $"{x.ReferencedTo}" == $"{providedForId}")
.OrderBy(x => x.Index)
.AsEnumerable();
//
return result;
}
/// <summary>
/// Count References ...
/// </summary>
/// <param name="providedForId"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<int> CountReferences(
TKey providedForId,
CancellationToken cancellationToken = default
)
{
//
// Validate ...
var isValid = !providedForId.IsNull();
if (!isValid)
{
XException.InvalidArgs.Throw();
}
//
var identifier = GetProvidedID(providedForId);
var result = (await CategoryProvider.FindManyAsync(
orderBuilder: null,
includeBuilder: null,
ignoreSoftDeleteds: true,
cancellationToken: cancellationToken,
predicate: x => x.References.Contains(identifier)
))
.Count();
//
return result;
}
/// <summary>
/// Retrieve References of Specific Provided ID as Query ...
/// </summary>
/// <param name="query"></param>
/// <param name="providedForId"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<XQueryResult<XCategoryDto>> QueryReferences(
XQuery query,
TKey providedForId,
CancellationToken cancellationToken = default
)
{
//
// Validate ...
if (query.IsNull() || providedForId.IsNull())
{
XException.InvalidArgs.Throw();
}
//
var identifier = GetProvidedID(providedForId);
var result = await CategoryProvider.QueryAsync(
query: query,
includeBuilder: null,
ignoreSoftDeleteds: true,
cancellationToken: cancellationToken,
orderBuilder: x => x.OrderBy(y => y.Id),
predicate: x => x.References.Contains(identifier)
);
//
return result;
}
/// <summary>
/// Add Reference a Model to Specific Provided ID ...
/// </summary>
/// <param name="model"></param>
/// <param name="providedForId"></param>
/// <param name="connectionId"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<bool> AddReference(
XCategoryDto model,
TKey providedForId,
string connectionId = null,
CancellationToken cancellationToken = default
)
{
//
var result = false;
//
// Validate ...
result = !model.IsNullOrDefault() &&
model.Id.IsValidIntId() &&
!providedForId.IsNull();
if (!result)
{
XException.InvalidArgs.Throw();
}
//
// Check Model Exists ...
result = await CategoryProvider.IsExistsAsync(model.Id);
if (!result)
{
XException.NotFound.Throw();
}
//
// Update Model by Retrieving ...
model = await CategoryProvider.GetAsync(
id: model.Id,
includeBuilder: null,
ignoreSoftDeleteds: true,
cancellationToken: cancellationToken
);
//
// Retrieve all References ...
var references = await GetAllReferences(
providedForId: providedForId,
cancellationToken: cancellationToken
);
//
// Check isReferenced or not ...
result = references
.Any(r =>
r.Id == model.Id &&
r.GetReferences()
.Any(rf =>
rf.ProvidedFor == Provider &&
rf.ReferencedTo == $"{providedForId}"));
if (result)
{
return result;
}
//
// Here means there is not any reference to ProvidedForId ...
int forIndex = await CountReferences(
providedForId: providedForId,
cancellationToken: cancellationToken
);
var modelReferences = model.GetReferences();
modelReferences.Add(new XReference<string>
{
Index = forIndex,
ProvidedFor = Provider,
ReferencedTo = $"{providedForId}"
});
modelReferences = modelReferences
.OrderBy(r => r.Index)
.ToList();
model = model.UpdateReferences(modelReferences);
//
// Update Data Base ...
model = await CategoryProvider.UpdateAsync(
id: model.Id,
item: model,
saveChanges: true,
connectionId: connectionId,
cancellationToken: cancellationToken
);
result = !model.IsNullOrDefault();
//
return result;
}
/// <summary>
/// Add Reference a Model to Specific XRefence<TKey/> ...
/// </summary>
/// <param name="model"></param>
/// <param name="reference"></param>
/// <param name="connectionId"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<bool> AddReference(
XCategoryDto model,
XReference<TKey> reference,
string connectionId = null,
CancellationToken cancellationToken = default
)
{
//
// Validate ...
// Since other Validations Handled in Calling, we Ignore them here ...
var result =
!model.IsNull() &&
!reference.IsNullOrDefault() &&
reference.ProvidedFor == Provider &&
!reference.ReferencedTo.IsNull();
if (!result)
{
XException.InvalidArgs.Throw();
}
//
result = await AddReference(
model: model,
connectionId: connectionId,
cancellationToken: cancellationToken,
providedForId: reference.ReferencedTo
);
//
return result;
}
/// <summary>
/// Remove Reference a Model for Specific Provided ID ...
/// </summary>
/// <param name="model"></param>
/// <param name="providedForId"></param>
/// <param name="connectionId"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<bool> RemoveReference(
XCategoryDto model,
TKey providedForId,
string connectionId = null,
CancellationToken cancellationToken = default
)
{
//
// Validate ...
var result =
!providedForId.IsNull() &&
!model.IsNullOrDefault() &&
model.Id.IsValidIntId();
if (!result)
{
XException.InvalidArgs.Throw();
}
//
// Retrieve Model ...
model = await CategoryProvider.GetAsync(
id: model.Id,
includeBuilder: null,
ignoreSoftDeleteds: true,
cancellationToken: cancellationToken
);
result = !model.IsNullOrDefault();
if (!result)
{
XException.NotFound.Throw();
}
//
// Reading Referencing Indexes ...
var indexes = await GetReferencingIndexes(
providedForId: providedForId,
cancellationToken: cancellationToken
);
//
// Check Model Reference to ID ...
var referencesCount = await CountReferences(
providedForId: providedForId,
cancellationToken: cancellationToken
);
result = referencesCount == 0;
if (result)
{
//
// There is not any Reference to Remove ...
return result;
}
//
// Check Model is Trully Referenced to ProvidedForId or not ...
var reference = model
.GetReferences()
.FirstOrDefault(r =>
r.ProvidedFor == Provider &&
r.ReferencedTo == $"{providedForId}");
result = !reference.IsNullOrDefault();
if (!result)
{
XException.ActionFailed.Throw();
}
//
// Remove Referenced Item from Model ...
var modelReferences = model
.GetReferences()
.Where(r =>
!(r.ProvidedFor == Provider &&
r.ReferencedTo == $"{providedForId}"))
.ToList();
model = model.UpdateReferences(modelReferences);
//
// Update DataBase ...
model = await CategoryProvider.UpdateAsync(
item: model,
id: model.Id,
saveChanges: true,
connectionId: connectionId,
cancellationToken: cancellationToken
);
//
result = !model.IsNullOrDefault();
if (!result)
{
XException.ActionFailed.Throw();
}
//
// Get Max Exists Indexes ...
var maxIndex = indexes.Max();
//
// Here We Have to Re Arrange Indexed ...
if (reference.Index < maxIndex)
{
//
var startIndex = reference.Index + 1;
for (int i = startIndex; i <= maxIndex; i++)
{
//
var dto = await GetReference(
forIndex: i,
providedForId: providedForId,
cancellationToken: cancellationToken
);
if (!dto.IsNullOrDefault())
{
//
var dtoReferences = dto.GetReferences();
dtoReferences
.ToList()
.ForEach(iref =>
{
//
if (
iref.Index == i &&
iref.ProvidedFor == Provider &&
iref.ReferencedTo == reference.ReferencedTo
)
{
iref.Index = i - 1;
}
});
dto = dto.UpdateReferences(dtoReferences);
//
dto = await CategoryProvider.UpdateAsync(
item: dto,
id: dto.Id,
saveChanges: true,
connectionId: connectionId,
cancellationToken: cancellationToken
);
}
}
}
//
return result;
}
/// <summary>
/// Remove Reference a Model for Specific XRefence<TKey/> ...
/// </summary>
/// <param name="model"></param>
/// <param name="reference"></param>
/// <param name="connectionId"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<bool> RemoveReference(
XCategoryDto model,
XReference<TKey> reference,
string connectionId = null,
CancellationToken cancellationToken = default
)
{
//
if (model.IsNullOrDefault() ||
reference.IsNullOrDefault() ||
reference.ReferencedTo.IsNull() ||
reference.ProvidedFor != Provider)
{
XException.InvalidArgs.Throw();
}
//
var result = await RemoveReference(
model: model,
connectionId: connectionId,
cancellationToken: cancellationToken,
providedForId: reference.ReferencedTo
);
//
return result;
}
/// <summary>
/// Remove All References to Specified Key ...
/// </summary>
/// <param name="providedForId"></param>
/// <param name="connectionId"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<bool> RemoveReferences(
TKey providedForId,
string connectionId = null,
CancellationToken cancellationToken = default
)
{
//
// Validate ...
if (providedForId.IsNull())
{
XException.InvalidArgs.Throw();
}
//
var result = false;
var references = await GetAllReferences(
providedForId: providedForId,
cancellationToken: cancellationToken
);
if (!references.IsNull() && references.HasChild())
{
//
foreach (var reference in references)
{
//
// Remove Reference ...
var itemReferences = reference.GetReferences()
.Where(r =>
r.ProvidedFor != Provider ||
(r.ProvidedFor == Provider &&
r.ReferencedTo != $"{providedForId}"))
.ToList();
var updatedModel = reference.UpdateReferences(itemReferences);
updatedModel = await CategoryProvider.UpdateAsync(
saveChanges: true,
item: updatedModel,
id: updatedModel.Id,
connectionId: connectionId,
cancellationToken: cancellationToken
);
if (!updatedModel.IsNullOrDefault())
{
result = true;
}
}
}
//
return result;
}
#endregion
//
#region Private ...
private string GetProvidedID(
TKey providedForId,
char splitter = '_'
)
{
//
// Validate ...
if (providedForId.IsNull())
{
XException.InvalidArgs.Throw();
}
//
var result = $"{Provider}{splitter}{providedForId}";
return result;
}
private string GetIndexedProvidedID(
TKey providedForId,
int forIndex,
char splitter = '_'
)
{
//
var result = $"{GetProvidedID(providedForId, splitter)}{splitter}{forIndex}";
//
return result;
}
private async Task<IEnumerable<int>> GetReferencingIndexes(
TKey providedForId,
CancellationToken cancellationToken = default
)
{
//
// Validate ...
var isValid =
!providedForId.IsNull();
if (!isValid)
{
XException.InvalidArgs.Throw();
}
//
var result = new List<int>();
var referencings = await GetAllReferencings(
providedForId: providedForId,
cancellationToken: cancellationToken
);
isValid =
!referencings.IsNull() &&
referencings.HasChild();
if (!isValid)
{
return result;
}
//
result =
referencings
.OrderBy(r => r.Index)
.Select(r => r.Index)
.ToList();
//
return result;
}
#endregion
}
}
@@ -1,3 +1,4 @@
using xCategoryService.Constants;
using xCategoryService.Interfaces;
using xStringService.Interfaces.Dtos;
using xStringService.Providers;
@@ -9,8 +10,8 @@ namespace xCategoryService.Providers
public XCategoryDescriptionResourceProvider(
IXStringServiceProvider stringProvider
) : base(
item: "CatD",
stringProvider
stringProvider: stringProvider,
item: XCategoryServiceConstants.CategoryDescriptionResourceIdentifier
)
{ }
}
+437 -1
View File
@@ -19,6 +19,7 @@ using xDataService.Extensions;
using xPushService.Constants;
using xPushService.Providers;
using xDataService.Configuration;
using xDataService.Models;
namespace xCategoryService.Providers
{
@@ -29,13 +30,17 @@ namespace xCategoryService.Providers
private readonly XDataServiceConfiguration dataServiceConfiguration;
private readonly IXCategoryTitleResourceProvider titleResourceProvider;
private readonly IXCategoryDescriptionResourceProvider descriptionResourceProvider;
private readonly IXCategorySubCategoryReferenceProvider categorySubCategoryReferenceProvider;
public string Provider => categorySubCategoryReferenceProvider.Provider;
public XCategoryProvider(
XAppConfiguration appConfiguration,
IXCategoryServiceProvider provider,
XDataServiceConfiguration dataServiceConfiguration,
IXCategoryTitleResourceProvider titleResourceProvider,
IXCategoryDescriptionResourceProvider descriptionResourceProvider
IXCategoryDescriptionResourceProvider descriptionResourceProvider,
IXCategorySubCategoryReferenceProvider categorySubCategoryReferenceProvider
) : base(
provider,
permittedRoles: new string[] { }
@@ -47,6 +52,7 @@ namespace xCategoryService.Providers
this.titleResourceProvider = titleResourceProvider;
this.dataServiceConfiguration = dataServiceConfiguration;
this.descriptionResourceProvider = descriptionResourceProvider;
this.categorySubCategoryReferenceProvider = categorySubCategoryReferenceProvider;
}
//
@@ -289,6 +295,179 @@ namespace xCategoryService.Providers
return result;
}
/// <summary>
/// Add Category by It's Locales ...
/// </summary>
/// <param name="item"></param>
/// <param name="connectionId"></param>
/// <param name="userInfo"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<XCategoryResourceDto> AddResource(
XCategoryResourceDto item,
string connectionId = null,
XUserClaimsInfoDto userInfo = null,
CancellationToken cancellationToken = default
)
{
//
// Validate ...
var isValid =
!item.IsNullOrDefault() &&
!item.Titles.IsNullOrDefault() &&
item.Titles.Locales.HasChild() &&
!item.Titles.Locales.Any(il =>
il.Language.IsNullOrEmpty() ||
il.Value.IsNullOrEmpty());
if (!isValid)
{
XException.InvalidArgs.Throw();
}
//
// Normalize ...
if (item.Item.IsNullOrDefault())
{
item.Item = new XCategoryDto();
}
//
// Check Permission ...
isValid = HasPermision(userInfo);
if (!isValid)
{
XException.NotAllowed.Throw();
}
//
var id = -1;
try
{
//
// Add Category for ID Generation ...
item.Item = await base.Add(
item: item.Item,
userInfo: userInfo,
connectionId: null, // Since here We dont want notification ...
cancellationToken: cancellationToken
);
isValid = !item.Item.IsNullOrDefault();
if (!isValid)
{
XException.ActionFailed.Throw();
}
id = item.Item.Id;
//
foreach (var il in item.Titles.Locales)
{
//
var title = il.Value;
var language = il.Language;
//
var descriptionItem =
item.Descriptions.IsNullOrDefault() ||
!item.Descriptions.Locales.HasChild()
? null
: item.Descriptions.Locales
.FirstOrDefault(ides =>
ides.Language
.Equals(
language,
StringComparison.InvariantCultureIgnoreCase));
var description =
descriptionItem.IsNullOrDefault()
? string.Empty
: descriptionItem.Value;
//
// Try to Add Resources ...
var titleResource = await titleResourceProvider
.AddOrUpdateLocale(
identifier: id,
locale: new XLocaleResourceDto
{
Value = title,
Language = language
},
connectionId: connectionId,
cancellationToken: cancellationToken
);
var descriptionResource = await descriptionResourceProvider
.AddOrUpdateLocale(
identifier: id,
locale: new XLocaleResourceDto
{
Value = description,
Language = language
},
connectionId: connectionId,
cancellationToken: cancellationToken
);
//
// Update Category Dto if not ...
if (item.Item.Title.IsNullOrEmpty() ||
!item.Item.Title
.Equals(
titleResource.Resource,
StringComparison.InvariantCultureIgnoreCase)
)
{
//
item.Item.Title = titleResource.Resource;
item.Item.Description = descriptionResource.Resource;
item.Item = await base.Update(
id: id,
item: item.Item,
userInfo: userInfo,
connectionId: null,
cancellationToken: cancellationToken
);
}
}
}
catch
{
XException.InvalidArgs.Throw();
}
//
// Validate Id ...
isValid = id.IsValidIntId();
if (!isValid)
{
XException.ActionFailed.Throw();
}
//
// Retrieve Category Resourv=ce ...
var result = await GetResource(
id: id,
cancellationToken: cancellationToken
);
//
// Sending Push Notification ...
isValid =
isValid &&
!result.IsNullOrDefault();
if (isValid)
{
//
await provider.SendPush(
connectionId: connectionId,
cancellationToken: cancellationToken,
payLoad: result.ToJSON(camelCase: true),
action: XBaseEntityHubAction.Add.GetStringValue()
);
}
//
return result;
}
/// <summary>
/// Remove Item for Specified Language ...
/// </summary>
@@ -1052,6 +1231,7 @@ namespace xCategoryService.Providers
/// Find Many Resource ...
/// </summary>
/// <param name="predicate"></param>
/// <param name="orderBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<IEnumerable<XCategoryResourceDto>> FindManyResource(
@@ -1179,5 +1359,261 @@ namespace xCategoryService.Providers
return result;
}
#endregion
//
#region SubCategory References ...
/// <summary>
/// Get Specified Indexed Reference for Specific Provided ID ...
/// </summary>
/// <param name="providedForId"></param>
/// <param name="forIndex"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<XCategoryDto> GetReference(
int providedForId,
int forIndex = 0,
CancellationToken cancellationToken = default
)
{
//
var result = await categorySubCategoryReferenceProvider
.GetReference(
forIndex: forIndex,
providedForId: providedForId,
cancellationToken: cancellationToken
);
//
return result;
}
/// <summary>
/// Retrieve all Exists References of Specific Provided ID ...
/// </summary>
/// <param name="providedForId"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<IEnumerable<XCategoryDto>> GetAllReferences(
int providedForId,
CancellationToken cancellationToken = default
)
{
//
var result = await categorySubCategoryReferenceProvider
.GetAllReferences(
providedForId: providedForId,
cancellationToken: cancellationToken
);
//
return result;
}
/// <summary>
/// Extract all Referencing Models for Specified Key ...
/// </summary>
/// <param name="providedForId"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<IEnumerable<XReference<int>>> GetAllReferencings(
int providedForId,
CancellationToken cancellationToken = default
)
{
//
var result = await categorySubCategoryReferenceProvider
.GetAllReferencings(
providedForId: providedForId,
cancellationToken: cancellationToken
);
//
return result;
}
/// <summary>
/// Count References ...
/// </summary>
/// <param name="providedForId"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<int> CountReferences(
int providedForId,
CancellationToken cancellationToken = default
)
{
//
var result = await categorySubCategoryReferenceProvider
.CountReferences(
providedForId: providedForId,
cancellationToken: cancellationToken
);
//
return result;
}
/// <summary>
/// Retrieve References of Specific Provided ID as Query ...
/// </summary>
/// <param name="query"></param>
/// <param name="providedForId"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<XQueryResult<XCategoryDto>> QueryReferences(
XQuery query,
int providedForId,
CancellationToken cancellationToken = default
)
{
//
var result = await categorySubCategoryReferenceProvider
.QueryReferences(
query: query,
providedForId: providedForId,
cancellationToken: cancellationToken
);
//
return result;
}
/// <summary>
/// Add Reference a Model to Specific Provided ID ...
/// </summary>
/// <param name="model"></param>
/// <param name="providedForId"></param>
/// <param name="connectionId"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<bool> AddReference(
XCategoryDto model,
int providedForId,
string connectionId = null,
CancellationToken cancellationToken = default
)
{
//
var result = await categorySubCategoryReferenceProvider
.AddReference(
model: model,
connectionId: connectionId,
providedForId: providedForId,
cancellationToken: cancellationToken
);
//
return result;
}
/// <summary>
/// Add Reference a Model to Specific XRefence<TKey/> ...
/// </summary>
/// <param name="model"></param>
/// <param name="reference"></param>
/// <param name="connectionId"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<bool> AddReference(
XCategoryDto model,
XReference<int> reference,
string connectionId = null,
CancellationToken cancellationToken = default
)
{
//
var result = await categorySubCategoryReferenceProvider
.AddReference(
model: model,
reference: reference,
connectionId: connectionId,
cancellationToken: cancellationToken
);
//
return result;
}
/// <summary>
/// Remove Reference a Model for Specific Provided ID ...
/// </summary>
/// <param name="model"></param>
/// <param name="providedForId"></param>
/// <param name="connectionId"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<bool> RemoveReference(
XCategoryDto model,
int providedForId,
string connectionId = null,
CancellationToken cancellationToken = default
)
{
//
var result = await categorySubCategoryReferenceProvider
.RemoveReference(
model: model,
connectionId: connectionId,
providedForId: providedForId,
cancellationToken: cancellationToken
);
//
return result;
}
/// <summary>
/// Remove Reference a Model for Specific XRefence<TKey/> ...
/// </summary>
/// <param name="model"></param>
/// <param name="reference"></param>
/// <param name="connectionId"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<bool> RemoveReference(
XCategoryDto model,
XReference<int> reference,
string connectionId = null,
CancellationToken cancellationToken = default
)
{
//
var result = await categorySubCategoryReferenceProvider
.RemoveReference(
model: model,
reference: reference,
connectionId: connectionId,
cancellationToken: cancellationToken
);
//
return result;
}
/// <summary>
/// Remove All References to Specified Key ...
/// </summary>
/// <param name="providedForId"></param>
/// <param name="connectionId"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<bool> RemoveReferences(
int providedForId,
string connectionId = null,
CancellationToken cancellationToken = default
)
{
//
var result = await categorySubCategoryReferenceProvider
.RemoveReferences(
connectionId: connectionId,
providedForId: providedForId,
cancellationToken: cancellationToken
);
//
return result;
}
#endregion
}
}
+589
View File
@@ -0,0 +1,589 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using xCategoryService.Interfaces;
using xCategoryService.Models.Dtos;
using xIdentityModels.Models;
using xModels.Dtos;
namespace xCategoryService.Providers
{
/// <summary>
/// Completely Exported Service ...
/// </summary>
public class XCategoryService : IXCategoryService
{
private readonly IXCategoryProvider categoryProvider;
private readonly IXSubCategoryProvider subCategoryProvider;
public XCategoryService(
IXCategoryProvider categoryProvider,
IXSubCategoryProvider subCategoryProvider
)
{
this.categoryProvider = categoryProvider;
this.subCategoryProvider = subCategoryProvider;
}
//
#region Category Provider ...
/// <summary>
/// Check Has Specified Locale or not ...
/// </summary>
/// <param name="id"></param>
/// <param name="language"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public virtual async Task<bool> CategoryHasLocale(
int id,
string language,
CancellationToken cancellationToken = default
)
{
//
return await categoryProvider
.HasLocale(
id: id,
language: language,
cancellationToken: cancellationToken
);
}
/// <summary>
/// Load an Item by all of it's Related Translations ...
/// </summary>
/// <param name="id"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public virtual async Task<XCategoryResourceDto> GetCategoryResource(
int id,
CancellationToken cancellationToken = default
)
{
//
return await categoryProvider
.GetResource(
id: id,
cancellationToken: cancellationToken
);
}
/// <summary>
/// Add Item for Specified Language ...
/// </summary>
/// <param name="item"></param>
/// <param name="language"></param>
/// <param name="connectionId"></param>
/// <param name="userInfo"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public virtual async Task<XCategoryResourceDto> AddCategory(
XCategoryDto item,
string language = null,
string connectionId = null,
XUserClaimsInfoDto userInfo = null,
CancellationToken cancellationToken = default
)
{
//
return await categoryProvider
.Add(
item: item,
language: language,
userInfo: userInfo,
connectionId: connectionId,
cancellationToken: cancellationToken
);
}
/// <summary>
/// Add Item by It's Locales ...
/// </summary>
/// <param name="item"></param>
/// <param name="connectionId"></param>
/// <param name="userInfo"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public virtual async Task<XCategoryResourceDto> AddCategoryResource(
XCategoryResourceDto item,
string connectionId = null,
XUserClaimsInfoDto userInfo = null,
CancellationToken cancellationToken = default
)
{
//
return await categoryProvider
.AddResource(
item: item,
userInfo: userInfo,
connectionId: connectionId,
cancellationToken: cancellationToken
);
}
/// <summary>
/// Remove Item for Specified Language ...
/// </summary>
/// <param name="id"></param>
/// <param name="language">if null, Remove All</param>
/// <param name="connectionId"></param>
/// <param name="userInfo"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public virtual async Task<XCategoryResourceDto> RemoveCategory(
int id,
string language = null,
string connectionId = null,
XUserClaimsInfoDto userInfo = null,
CancellationToken cancellationToken = default
)
{
//
return await categoryProvider
.Remove(
id: id,
language: language,
userInfo: userInfo,
connectionId: connectionId,
cancellationToken: cancellationToken
);
}
/// <summary>
/// Update an Item for Specified Language ...
/// </summary>
/// <param name="id"></param>
/// <param name="item"></param>
/// <param name="language"></param>
/// <param name="connectionId"></param>
/// <param name="userInfo"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public virtual async Task<XCategoryResourceDto> UpdateCategory(
int id,
XCategoryDto item,
string language = null,
string connectionId = null,
XUserClaimsInfoDto userInfo = null,
CancellationToken cancellationToken = default
)
{
//
return await categoryProvider
.Update(
id: id,
item: item,
language: language,
userInfo: userInfo,
connectionId: connectionId,
cancellationToken: cancellationToken
);
}
/// <summary>
/// Refresh a Resource ...
/// </summary>
/// <param name="resource"></param>
/// <param name="connectionId"></param>
/// <param name="userInfo"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public virtual async Task<XCategoryResourceDto> RefreshCategory(
XCategoryResourceDto resource,
string connectionId = null,
XUserClaimsInfoDto userInfo = null,
CancellationToken cancellationToken = default
)
{
//
return await categoryProvider
.Refresh(
resource: resource,
userInfo: userInfo,
connectionId: connectionId,
cancellationToken: cancellationToken
);
}
/// <summary>
/// Get All Resources ...
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public virtual async Task<IEnumerable<XCategoryResourceDto>> GetAllCategoryResources(
CancellationToken cancellationToken = default
)
{
//
return await categoryProvider
.GetAllResources(
cancellationToken: cancellationToken
);
}
/// <summary>
/// Find One Resource ...
/// </summary>
/// <param name="predicate"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public virtual async Task<XCategoryResourceDto> FindOneCategoryResource(
Expression<Func<XCategoryResourceDto, bool>> predicate = null,
CancellationToken cancellationToken = default
)
{
//
return await categoryProvider
.FindOneResource(
predicate: predicate,
cancellationToken: cancellationToken
);
}
/// <summary>
/// Find Many Resource ...
/// </summary>
/// <param name="predicate"></param>
/// <param name="orderBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public virtual async Task<IEnumerable<XCategoryResourceDto>> FindManyCategoryResource(
Expression<Func<XCategoryResourceDto, bool>> predicate = null,
Func<IQueryable<XCategoryResourceDto>, IOrderedQueryable<XCategoryResourceDto>> orderBuilder = null,
CancellationToken cancellationToken = default
)
{
//
return await categoryProvider
.FindManyResource(
predicate: predicate,
orderBuilder: orderBuilder,
cancellationToken: cancellationToken
);
}
/// <summary>
/// Retrieve Resources by Query Pattern ...
/// </summary>
/// <param name="query"></param>
/// <param name="predicate"></param>
/// <param name="orderBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public virtual async Task<XQueryResult<XCategoryResourceDto>> QueryCategoryResources(
XQuery query = null,
Expression<Func<XCategoryResourceDto, bool>> predicate = null,
Func<IQueryable<XCategoryResourceDto>, IOrderedQueryable<XCategoryResourceDto>> orderBuilder = null,
CancellationToken cancellationToken = default
)
{
//
return await categoryProvider
.QueryResources(
query: query,
predicate: predicate,
orderBuilder: orderBuilder,
cancellationToken: cancellationToken
);
}
/// <summary>
/// Get All Resources as Async Enumerable ...
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public virtual IAsyncEnumerable<XCategoryResourceDto> GetAllCategoryResourcesAsAsyncEnumerable(
CancellationToken cancellationToken = default
)
{
//
return categoryProvider
.GetAllResourcesAsAsyncEnumerable(
cancellationToken: cancellationToken
);
}
#endregion
//
#region SubCategory Provider ...
/// <summary>
/// Check Has Specified Locale or not ...
/// </summary>
/// <param name="id"></param>
/// <param name="language"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public virtual async Task<bool> SubCategoryHasLocale(
int id,
string language,
CancellationToken cancellationToken = default
)
{
//
return await subCategoryProvider
.HasLocale(
id: id,
language: language,
cancellationToken: cancellationToken
);
}
/// <summary>
/// Load an Item by all of it's Related Translations ...
/// </summary>
/// <param name="id"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public virtual async Task<XSubCategoryResourceDto> GetSubCategoryResource(
int id,
CancellationToken cancellationToken = default
)
{
//
return await subCategoryProvider
.GetResource(
id: id,
cancellationToken: cancellationToken
);
}
/// <summary>
/// Add Item for Specified Language ...
/// </summary>
/// <param name="item"></param>
/// <param name="language"></param>
/// <param name="connectionId"></param>
/// <param name="userInfo"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public virtual async Task<XSubCategoryResourceDto> AddSubCategory(
XSubCategoryDto item,
string language = null,
string connectionId = null,
XUserClaimsInfoDto userInfo = null,
CancellationToken cancellationToken = default
)
{
//
return await subCategoryProvider
.Add(
item: item,
language: language,
userInfo: userInfo,
connectionId: connectionId,
cancellationToken: cancellationToken
);
}
/// <summary>
/// Add Item by it's Locales and Reference ...
/// </summary>
/// <param name="item"></param>
/// <param name="connectionId"></param>
/// <param name="userInfo"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public virtual async Task<XSubCategoryResourceDto> AddSubCategoryResource(
XSubCategoryResourceDto item,
string connectionId = null,
XUserClaimsInfoDto userInfo = null,
CancellationToken cancellationToken = default
)
{
//
return await subCategoryProvider
.AddResource(
item: item,
userInfo: userInfo,
connectionId: connectionId,
cancellationToken: cancellationToken
);
}
/// <summary>
/// Remove Item for Specified Language ...
/// </summary>
/// <param name="id"></param>
/// <param name="language">if null, Remove All</param>
/// <param name="connectionId"></param>
/// <param name="userInfo"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public virtual async Task<XSubCategoryResourceDto> RemoveSubCategory(
int id,
string language = null,
string connectionId = null,
XUserClaimsInfoDto userInfo = null,
CancellationToken cancellationToken = default
)
{
//
return await subCategoryProvider
.Remove(
id: id,
language: language,
userInfo: userInfo,
connectionId: connectionId,
cancellationToken: cancellationToken
);
}
/// <summary>
/// Update an Item for Specified Language ...
/// </summary>
/// <param name="id"></param>
/// <param name="item"></param>
/// <param name="language"></param>
/// <param name="connectionId"></param>
/// <param name="userInfo"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public virtual async Task<XSubCategoryResourceDto> UpdateSubCategory(
int id,
XSubCategoryDto item,
string language = null,
string connectionId = null,
XUserClaimsInfoDto userInfo = null,
CancellationToken cancellationToken = default
)
{
//
return await subCategoryProvider
.Update(
id: id,
item: item,
language: language,
userInfo: userInfo,
connectionId: connectionId,
cancellationToken: cancellationToken
);
}
/// <summary>
/// Refresh a Resource ...
/// </summary>
/// <param name="resource"></param>
/// <param name="connectionId"></param>
/// <param name="userInfo"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public virtual async Task<XSubCategoryResourceDto> RefreshSubCategory(
XSubCategoryResourceDto resource,
string connectionId = null,
XUserClaimsInfoDto userInfo = null,
CancellationToken cancellationToken = default
)
{
//
return await subCategoryProvider
.Refresh(
resource: resource,
userInfo: userInfo,
connectionId: connectionId,
cancellationToken: cancellationToken
);
}
/// <summary>
/// Get All Resources ...
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public virtual async Task<IEnumerable<XSubCategoryResourceDto>> GetAllSubCategoryResources(
CancellationToken cancellationToken = default
)
{
//
return await subCategoryProvider
.GetAllResources(
cancellationToken: cancellationToken
);
}
/// <summary>
/// Find One Resource ...
/// </summary>
/// <param name="predicate"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public virtual async Task<XSubCategoryResourceDto> FindOneSubCategoryResource(
Expression<Func<XSubCategoryResourceDto, bool>> predicate = null,
CancellationToken cancellationToken = default
)
{
//
return await subCategoryProvider
.FindOneResource(
predicate: predicate,
cancellationToken: cancellationToken
);
}
/// <summary>
/// Find Many Resource ...
/// </summary>
/// <param name="predicate"></param>
/// <param name="orderBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public virtual async Task<IEnumerable<XSubCategoryResourceDto>> FindManySubCategoryResource(
Expression<Func<XSubCategoryResourceDto, bool>> predicate = null,
Func<IQueryable<XSubCategoryResourceDto>, IOrderedQueryable<XSubCategoryResourceDto>> orderBuilder = null,
CancellationToken cancellationToken = default
)
{
//
return await subCategoryProvider
.FindManyResource(
predicate: predicate,
orderBuilder: orderBuilder,
cancellationToken: cancellationToken
);
}
/// <summary>
/// Retrieve Resources by Query Pattern ...
/// </summary>
/// <param name="query"></param>
/// <param name="predicate"></param>
/// <param name="orderBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public virtual async Task<XQueryResult<XSubCategoryResourceDto>> QuerySubCategoryResources(
XQuery query = null,
Expression<Func<XSubCategoryResourceDto, bool>> predicate = null,
Func<IQueryable<XSubCategoryResourceDto>, IOrderedQueryable<XSubCategoryResourceDto>> orderBuilder = null,
CancellationToken cancellationToken = default
)
{
//
return await subCategoryProvider
.QueryResources(
query: query,
predicate: predicate,
orderBuilder: orderBuilder,
cancellationToken: cancellationToken
);
}
/// <summary>
/// Get All Resources as Async Enumerable ...
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public virtual IAsyncEnumerable<XSubCategoryResourceDto> GetAllSubCategoryResourcesAsAsyncEnumerable(
CancellationToken cancellationToken = default
)
{
//
return subCategoryProvider
.GetAllResourcesAsAsyncEnumerable(
cancellationToken: cancellationToken
);
}
#endregion
}
}
@@ -0,0 +1,17 @@
using xCategoryService.Constants;
using xCategoryService.Interfaces;
using xCategoryService.Interfaces.Dtos;
namespace xCategoryService.Providers
{
public class XCategorySubCategoryReferenceProvider : XBaseCategoryProvider<int>, IXCategorySubCategoryReferenceProvider
{
public XCategorySubCategoryReferenceProvider(
IXCategoryServiceProvider categoryProvider
) : base(
categoryProvider: categoryProvider,
providedFor: XCategoryServiceConstants.SubCategoryReference
)
{ }
}
}
+3 -2
View File
@@ -1,3 +1,4 @@
using xCategoryService.Constants;
using xCategoryService.Interfaces;
using xStringService.Interfaces.Dtos;
using xStringService.Providers;
@@ -9,8 +10,8 @@ namespace xCategoryService.Providers
public XCategoryTitleResourceProvider(
IXStringServiceProvider stringProvider
) : base(
item: "CatT",
stringProvider
stringProvider: stringProvider,
item: XCategoryServiceConstants.CategoryTitleResourceIdentifier
)
{ }
}
@@ -1,3 +1,4 @@
using xCategoryService.Constants;
using xCategoryService.Interfaces;
using xStringService.Interfaces.Dtos;
using xStringService.Providers;
@@ -9,8 +10,8 @@ namespace xCategoryService.Providers
public XSubCategoryDescriptionResourceProvider(
IXStringServiceProvider stringProvider
) : base(
item: "SubCatD",
stringProvider
stringProvider: stringProvider,
item: XCategoryServiceConstants.SubCategoryDescriptionResourceIdentifier
)
{ }
}
+276 -3
View File
@@ -25,6 +25,7 @@ namespace xCategoryService.Providers
public class XSubCategoryProvider : XBaseProvided<XSubCategory, XSubCategoryDto, int, XSubCategoryDtoHub>, IXSubCategoryProvider
{
private readonly XAppConfiguration appConfiguration;
private readonly IXCategoryProvider categoryProvider;
private readonly IXSubCategoryServiceProvider provider;
private readonly XDataServiceConfiguration dataServiceConfiguration;
private readonly IXSubCategoryTitleResourceProvider titleResourceProvider;
@@ -32,6 +33,7 @@ namespace xCategoryService.Providers
public XSubCategoryProvider(
XAppConfiguration appConfiguration,
IXCategoryProvider categoryProvider,
IXSubCategoryServiceProvider provider,
XDataServiceConfiguration dataServiceConfiguration,
IXSubCategoryTitleResourceProvider titleResourceProvider,
@@ -41,10 +43,11 @@ namespace xCategoryService.Providers
permittedRoles: new string[] { }
)
{
this.appConfiguration = appConfiguration;
this.provider = provider;
this.dataServiceConfiguration = dataServiceConfiguration;
this.appConfiguration = appConfiguration;
this.categoryProvider = categoryProvider;
this.titleResourceProvider = titleResourceProvider;
this.dataServiceConfiguration = dataServiceConfiguration;
this.descriptionResourceProvider = descriptionResourceProvider;
}
@@ -132,16 +135,36 @@ namespace xCategoryService.Providers
identifier: id,
cancellationToken: cancellationToken
);
var descriptionResource = await titleResourceProvider.GetResource(
var descriptionResource = await descriptionResourceProvider.GetResource(
identifier: id,
cancellationToken: cancellationToken
);
//
// Reading Category Resource ...
XCategoryResourceDto categoryResourceDto = null;
try
{
var categoryDto = await categoryProvider.GetReference(
providedForId: id,
cancellationToken: cancellationToken
);
if (!categoryDto.IsNullOrDefault())
{
categoryResourceDto = await categoryProvider.GetResource(
id: categoryDto.Id,
cancellationToken: cancellationToken
);
}
}
catch { }
//
var result = new XSubCategoryResourceDto
{
Item = item,
Titles = titleResource,
Category = categoryResourceDto,
Descriptions = descriptionResource
};
@@ -288,6 +311,207 @@ namespace xCategoryService.Providers
return result;
}
/// <summary>
/// Add Item by it's Locales and Reference ...
/// </summary>
/// <param name="item"></param>
/// <param name="connectionId"></param>
/// <param name="userInfo"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<XSubCategoryResourceDto> AddResource(
XSubCategoryResourceDto item,
string connectionId = null,
XUserClaimsInfoDto userInfo = null,
CancellationToken cancellationToken = default
)
{
//
// Validate ...
var isValid =
!item.IsNullOrDefault() &&
!item.Titles.IsNullOrDefault() &&
item.Titles.Locales.HasChild() &&
!item.Titles.Locales.Any(tl =>
tl.Value.IsNullOrEmpty() ||
tl.Language.IsNullOrEmpty());
if (!isValid)
{
XException.InvalidArgs.Throw();
}
//
// Normalize ...
if (item.Item.IsNullOrDefault())
{
item.Item = new XSubCategoryDto();
}
//
// Check Permission ...
isValid = HasPermision(userInfo);
if (!isValid)
{
XException.NotAllowed.Throw();
}
//
var id = -1;
try
{
//
// Handle Category Generation ...
if (!item.Category.IsNullOrDefault())
{
//
// Handle Category ...
try
{
// Try to Add Category ...
item.Category = await categoryProvider.Refresh(
resource: item.Category,
userInfo: userInfo,
connectionId: connectionId,
cancellationToken: cancellationToken
);
}
catch { }
}
//
// Add SubCategory for ID Generation ...
item.Item = await base.Add(
item: item.Item,
userInfo: userInfo,
connectionId: null, // Since here We dont want notification ...
cancellationToken: cancellationToken
);
isValid = !item.Item.IsNullOrDefault();
if (!isValid)
{
XException.ActionFailed.Throw();
}
id = item.Item.Id;
//
foreach (var il in item.Titles.Locales)
{
//
var title = il.Value;
var language = il.Language;
//
var descriptionItem =
item.Descriptions.IsNullOrDefault() ||
!item.Descriptions.Locales.HasChild()
? null
: item.Descriptions.Locales
.FirstOrDefault(ides =>
ides.Language
.Equals(
language,
StringComparison.InvariantCultureIgnoreCase));
var description =
descriptionItem.IsNullOrDefault()
? string.Empty
: descriptionItem.Value;
//
// Try to Add Resources ...
var titleResource = await titleResourceProvider
.AddOrUpdateLocale(
identifier: id,
locale: new XLocaleResourceDto
{
Value = title,
Language = language
},
connectionId: connectionId,
cancellationToken: cancellationToken
);
var descriptionResource = await descriptionResourceProvider
.AddOrUpdateLocale(
identifier: id,
locale: new XLocaleResourceDto
{
Value = description,
Language = language
},
connectionId: connectionId,
cancellationToken: cancellationToken
);
//
// Update Category Dto if not ...
if (item.Item.Title.IsNullOrEmpty() ||
!item.Item.Title
.Equals(
titleResource.Resource,
StringComparison.InvariantCultureIgnoreCase)
)
{
//
item.Item.Title = titleResource.Resource;
item.Item.Description = descriptionResource.Resource;
item.Item = await base.Update(
id: id,
item: item.Item,
userInfo: userInfo,
connectionId: null,
cancellationToken: cancellationToken
);
}
}
}
catch
{
XException.InvalidArgs.Throw();
}
//
// Validate Id ...
isValid = id.IsValidIntId();
if (!isValid)
{
XException.ActionFailed.Throw();
}
//
// Add Resource Reference to Category ...
isValid = await categoryProvider.AddReference(
providedForId: id,
connectionId: null,
model: item.Category.Item,
cancellationToken: cancellationToken
);
//
// Retrieve Category Resourv=ce ...
var result = await GetResource(
id: id,
cancellationToken: cancellationToken
);
//
// Sending Push Notification ...
isValid =
isValid &&
!result.IsNullOrDefault();
if (isValid)
{
//
await provider.SendPush(
connectionId: connectionId,
cancellationToken: cancellationToken,
payLoad: result.ToJSON(camelCase: true),
action: XBaseEntityHubAction.Add.GetStringValue()
);
}
//
return result;
}
/// <summary>
/// Remove Item for Specified Language ...
/// </summary>
@@ -451,6 +675,17 @@ namespace xCategoryService.Providers
isValid = true;
}
//
// Remove all Referencings ...
if (isValid)
{
await categoryProvider.RemoveReferences(
providedForId: id,
connectionId: connectionId,
cancellationToken: cancellationToken
);
}
//
if (isValid)
{
@@ -903,6 +1138,42 @@ namespace xCategoryService.Providers
}
}
//
// Handle Category ...
if (
!isDelete &&
(isNew || isExists) &&
!resource.Category.IsNullOrDefault())
{
//
// Refresh Category ...
var category = await categoryProvider.Refresh(
userInfo: userInfo,
resource: resource.Category,
connectionId: connectionId,
cancellationToken: cancellationToken
);
//
// Handle SubCategory Referencings ...
var references = await categoryProvider.GetAllReferences(
providedForId: id,
cancellationToken: cancellationToken
);
var hasReference =
references.HasChild() &&
references.Any(r => r.Id == category.Item.Id);
if (!hasReference)
{
await categoryProvider.AddReference(
providedForId: id,
model: category.Item,
connectionId: connectionId,
cancellationToken: cancellationToken
);
}
}
//
// Validate Action ...
isValid = id.IsValidIntId();
@@ -942,6 +1213,7 @@ namespace xCategoryService.Providers
//
return result;
}
/// <summary>
/// Get All Resources as Async Enumerable ...
/// </summary>
@@ -1050,6 +1322,7 @@ namespace xCategoryService.Providers
/// Find Many Resource ...
/// </summary>
/// <param name="predicate"></param>
/// <param name="orderBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<IEnumerable<XSubCategoryResourceDto>> FindManyResource(
@@ -1,3 +1,4 @@
using xCategoryService.Constants;
using xCategoryService.Interfaces;
using xStringService.Interfaces.Dtos;
using xStringService.Providers;
@@ -9,8 +10,8 @@ namespace xCategoryService.Providers
public XSubCategoryTitleResourceProvider(
IXStringServiceProvider stringProvider
) : base(
item: "SubCatT",
stringProvider
stringProvider: stringProvider,
item: XCategoryServiceConstants.SubCategoryTitleResourceIdentifier
)
{ }
}
+3 -2
View File
@@ -10,7 +10,7 @@
<PackageId>xDashboard.xCategoryService</PackageId>
<Description>
it is a Part of xDashboard on SaherElm IT Center which provides Category Futures ...
it is a Part of xDashboard on SaherElm IT Center which provides Category Futures ...
</Description>
<!-- Icon Definition -->
@@ -19,7 +19,8 @@
<!-- Icon Handling -->
<ItemGroup>
<None Include="../../Resources/Images/favicon.png" Link="icon.png" Pack="true" PackagePath="\icon.png" />
<None Include="../../Resources/Images/favicon.png" Link="icon.png" Pack="true"
PackagePath="\icon.png" />
</ItemGroup>
<!-- Local Modules -->