From 712d547c4b2ca4f90d0254dab4483454596afb5b Mon Sep 17 00:00:00 2001 From: maliming Date: Mon, 11 Dec 2023 10:56:11 +0800 Subject: [PATCH 001/154] Add `NormalizedName` property to `Tenant`. Resolve #18394 --- .../MauiBlazor/MauiBlazorRemoteTenantStore.cs | 14 +++--- .../Mvc/Client/MvcRemoteTenantStore.cs | 12 ++--- .../Mvc/MultiTenancy/FindTenantResultDto.cs | 2 + .../Abp/MultiTenancy/AbpTenantAppService.cs | 8 +++- .../MultiTenancy/TenantSwitchModal.cshtml.cs | 5 ++- .../Abp/MultiTenancy/ITenantNormalizer.cs | 6 +++ .../Volo/Abp/MultiTenancy/ITenantStore.cs | 4 +- .../Abp/MultiTenancy/TenantConfiguration.cs | 10 +++++ .../UpperInvariantTenantNormalizer.cs | 11 +++++ .../ConfigurationStore/DefaultTenantStore.cs | 8 ++-- .../TenantConfigurationProvider.cs | 7 ++- ...reMultiTenancy_WithDomainResolver_Tests.cs | 3 +- ...ltiTenancy_Without_DomainResolver_Tests.cs | 3 +- .../Serilog/Serilog_Enrichers_Tests.cs | 3 +- .../Abp/TenantManagement/ITenantRepository.cs | 4 +- .../Volo/Abp/TenantManagement/Tenant.cs | 12 ++++- ...TenantConfigurationCacheItemInvalidator.cs | 8 ++-- .../Abp/TenantManagement/TenantManager.cs | 24 ++++++---- .../Volo/Abp/TenantManagement/TenantStore.cs | 28 ++++++------ ...agementDbContextModelCreatingExtensions.cs | 1 + .../EfCoreTenantRepository.cs | 8 ++-- .../MongoDb/MongoTenantRepository.cs | 8 ++-- .../TenantCacheItemInvalidator_Tests.cs | 44 ++++++++++--------- .../TenantManagement/TenantManager_Tests.cs | 11 +++-- .../Abp/TenantManagement/TenantStore_Tests.cs | 7 ++- .../Volo/Abp/TenantManagement/Tenant_Tests.cs | 7 ++- .../Abp/TenantManagement/LazyLoad_Tests.cs | 5 ++- .../TenantRepository_Tests.cs | 17 ++++--- 28 files changed, 178 insertions(+), 102 deletions(-) create mode 100644 framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/ITenantNormalizer.cs create mode 100644 framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/UpperInvariantTenantNormalizer.cs diff --git a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor/Volo/Abp/AspNetCore/Components/MauiBlazor/MauiBlazorRemoteTenantStore.cs b/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor/Volo/Abp/AspNetCore/Components/MauiBlazor/MauiBlazorRemoteTenantStore.cs index d17a2b6f87..d06eb60566 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor/Volo/Abp/AspNetCore/Components/MauiBlazor/MauiBlazorRemoteTenantStore.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor/Volo/Abp/AspNetCore/Components/MauiBlazor/MauiBlazorRemoteTenantStore.cs @@ -23,13 +23,13 @@ public class MauiBlazorRemoteTenantStore : ITenantStore, ITransientDependency Cache = cache; } - public async Task FindAsync(string name) + public async Task FindAsync(string normalizedName) { - var cacheKey = CreateCacheKey(name); + var cacheKey = CreateCacheKey(normalizedName); var tenantConfiguration = await Cache.GetOrAddAsync( cacheKey, - async () => CreateTenantConfiguration(await TenantAppService.FindTenantByNameAsync(name))!, + async () => CreateTenantConfiguration(await TenantAppService.FindTenantByNameAsync(normalizedName))!, () => new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = @@ -57,13 +57,13 @@ public class MauiBlazorRemoteTenantStore : ITenantStore, ITransientDependency return tenantConfiguration; } - public TenantConfiguration? Find(string name) + public TenantConfiguration? Find(string normalizedName) { - var cacheKey = CreateCacheKey(name); + var cacheKey = CreateCacheKey(normalizedName); var tenantConfiguration = Cache.GetOrAdd( cacheKey, - () => AsyncHelper.RunSync(async () => CreateTenantConfiguration(await TenantAppService.FindTenantByNameAsync(name)))!, + () => AsyncHelper.RunSync(async () => CreateTenantConfiguration(await TenantAppService.FindTenantByNameAsync(normalizedName)))!, () => new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = @@ -110,4 +110,4 @@ public class MauiBlazorRemoteTenantStore : ITenantStore, ITransientDependency { return $"RemoteTenantStore_Id_{tenantId:N}"; } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcRemoteTenantStore.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcRemoteTenantStore.cs index e0c450b8b4..1bc7856ca6 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcRemoteTenantStore.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcRemoteTenantStore.cs @@ -29,9 +29,9 @@ public class MvcRemoteTenantStore : ITenantStore, ITransientDependency Options = options.Value; } - public async Task FindAsync(string name) + public async Task FindAsync(string normalizedName) { - var cacheKey = TenantConfigurationCacheItem.CalculateCacheKey(name); + var cacheKey = TenantConfigurationCacheItem.CalculateCacheKey(normalizedName); var httpContext = HttpContextAccessor?.HttpContext; if (httpContext != null && httpContext.Items[cacheKey] is TenantConfigurationCacheItem tenantConfigurationInHttpContext) @@ -42,7 +42,7 @@ public class MvcRemoteTenantStore : ITenantStore, ITransientDependency var tenantConfiguration = await Cache.GetAsync(cacheKey); if (tenantConfiguration == null) { - await TenantAppService.FindTenantByNameAsync(name); + await TenantAppService.FindTenantByNameAsync(normalizedName); tenantConfiguration = await Cache.GetAsync(cacheKey); } @@ -79,9 +79,9 @@ public class MvcRemoteTenantStore : ITenantStore, ITransientDependency return tenantConfiguration?.Value; } - public TenantConfiguration? Find(string name) + public TenantConfiguration? Find(string normalizedName) { - var cacheKey = TenantConfigurationCacheItem.CalculateCacheKey(name); + var cacheKey = TenantConfigurationCacheItem.CalculateCacheKey(normalizedName); var httpContext = HttpContextAccessor?.HttpContext; if (httpContext != null && httpContext.Items[cacheKey] is TenantConfigurationCacheItem tenantConfigurationInHttpContext) @@ -92,7 +92,7 @@ public class MvcRemoteTenantStore : ITenantStore, ITransientDependency var tenantConfiguration = Cache.Get(cacheKey); if (tenantConfiguration == null) { - AsyncHelper.RunSync(async () => await TenantAppService.FindTenantByNameAsync(name)); + AsyncHelper.RunSync(async () => await TenantAppService.FindTenantByNameAsync(normalizedName)); tenantConfiguration = Cache.Get(cacheKey); } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/MultiTenancy/FindTenantResultDto.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/MultiTenancy/FindTenantResultDto.cs index 599b0b8a67..1de5f942dc 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/MultiTenancy/FindTenantResultDto.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/MultiTenancy/FindTenantResultDto.cs @@ -11,5 +11,7 @@ public class FindTenantResultDto public string? Name { get; set; } + public string? NormalizedName { get; set; } + public bool IsActive { get; set; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/AbpTenantAppService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/AbpTenantAppService.cs index 279bcee8ad..75649c1f6b 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/AbpTenantAppService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/AbpTenantAppService.cs @@ -9,15 +9,17 @@ namespace Pages.Abp.MultiTenancy; public class AbpTenantAppService : ApplicationService, IAbpTenantAppService { protected ITenantStore TenantStore { get; } + protected ITenantNormalizer TenantNormalizer { get; } - public AbpTenantAppService(ITenantStore tenantStore) + public AbpTenantAppService(ITenantStore tenantStore, ITenantNormalizer tenantNormalizer) { TenantStore = tenantStore; + TenantNormalizer = tenantNormalizer; } public virtual async Task FindTenantByNameAsync(string name) { - var tenant = await TenantStore.FindAsync(name); + var tenant = await TenantStore.FindAsync(TenantNormalizer.NormalizeName(name)!); if (tenant == null) { @@ -29,6 +31,7 @@ public class AbpTenantAppService : ApplicationService, IAbpTenantAppService Success = true, TenantId = tenant.Id, Name = tenant.Name, + NormalizedName = tenant.NormalizedName, IsActive = tenant.IsActive }; } @@ -47,6 +50,7 @@ public class AbpTenantAppService : ApplicationService, IAbpTenantAppService Success = true, TenantId = tenant.Id, Name = tenant.Name, + NormalizedName = tenant.NormalizedName, IsActive = tenant.IsActive }; } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/TenantSwitchModal.cshtml.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/TenantSwitchModal.cshtml.cs index f6711be826..94a6760df3 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/TenantSwitchModal.cshtml.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/TenantSwitchModal.cshtml.cs @@ -18,13 +18,16 @@ public class TenantSwitchModalModel : AbpPageModel public TenantInfoModel Input { get; set; } = default!; protected ITenantStore TenantStore { get; } + protected ITenantNormalizer TenantNormalizer { get; } protected AbpAspNetCoreMultiTenancyOptions Options { get; } public TenantSwitchModalModel( ITenantStore tenantStore, + ITenantNormalizer tenantNormalizer, IOptions options) { TenantStore = tenantStore; + TenantNormalizer = tenantNormalizer; Options = options.Value; LocalizationResourceType = typeof(AbpUiMultiTenancyResource); } @@ -45,7 +48,7 @@ public class TenantSwitchModalModel : AbpPageModel Guid? tenantId = null; if (!Input.Name.IsNullOrEmpty()) { - var tenant = await TenantStore.FindAsync(Input.Name!); + var tenant = await TenantStore.FindAsync(TenantNormalizer.NormalizeName(Input.Name!)!); if (tenant == null) { throw new UserFriendlyException(L["GivenTenantIsNotExist", Input.Name!]); diff --git a/framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/ITenantNormalizer.cs b/framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/ITenantNormalizer.cs new file mode 100644 index 0000000000..1c5f0859f5 --- /dev/null +++ b/framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/ITenantNormalizer.cs @@ -0,0 +1,6 @@ +namespace Volo.Abp.MultiTenancy; + +public interface ITenantNormalizer +{ + string? NormalizeName(string? name); +} diff --git a/framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/ITenantStore.cs b/framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/ITenantStore.cs index 93dd609cc4..d97d438b01 100644 --- a/framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/ITenantStore.cs +++ b/framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/ITenantStore.cs @@ -5,12 +5,12 @@ namespace Volo.Abp.MultiTenancy; public interface ITenantStore { - Task FindAsync(string name); + Task FindAsync(string normalizedName); Task FindAsync(Guid id); [Obsolete("Use FindAsync method.")] - TenantConfiguration? Find(string name); + TenantConfiguration? Find(string normalizedName); [Obsolete("Use FindAsync method.")] TenantConfiguration? Find(Guid id); diff --git a/framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/TenantConfiguration.cs b/framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/TenantConfiguration.cs index 0e5faf9386..29b0971708 100644 --- a/framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/TenantConfiguration.cs +++ b/framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/TenantConfiguration.cs @@ -11,6 +11,8 @@ public class TenantConfiguration public string Name { get; set; } = default!; + public string NormalizedName { get; set; } = default!; + public ConnectionStrings? ConnectionStrings { get; set; } public bool IsActive { get; set; } @@ -30,4 +32,12 @@ public class TenantConfiguration ConnectionStrings = new ConnectionStrings(); } + + public TenantConfiguration(Guid id, [NotNull] string name, [NotNull] string normalizedName) + : this(id, name) + { + Check.NotNull(normalizedName, nameof(normalizedName)); + + NormalizedName = normalizedName; + } } diff --git a/framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/UpperInvariantTenantNormalizer.cs b/framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/UpperInvariantTenantNormalizer.cs new file mode 100644 index 0000000000..cba6b32349 --- /dev/null +++ b/framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/UpperInvariantTenantNormalizer.cs @@ -0,0 +1,11 @@ +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.MultiTenancy; + +public class UpperInvariantTenantNormalizer : ITenantNormalizer, ITransientDependency +{ + public virtual string? NormalizeName(string? name) + { + return name?.Normalize().ToUpperInvariant(); + } +} diff --git a/framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ConfigurationStore/DefaultTenantStore.cs b/framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ConfigurationStore/DefaultTenantStore.cs index d86d810d11..e91e749fe3 100644 --- a/framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ConfigurationStore/DefaultTenantStore.cs +++ b/framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ConfigurationStore/DefaultTenantStore.cs @@ -16,9 +16,9 @@ public class DefaultTenantStore : ITenantStore, ITransientDependency _options = options.CurrentValue; } - public Task FindAsync(string name) + public Task FindAsync(string normalizedName) { - return Task.FromResult(Find(name)); + return Task.FromResult(Find(normalizedName)); } public Task FindAsync(Guid id) @@ -26,9 +26,9 @@ public class DefaultTenantStore : ITenantStore, ITransientDependency return Task.FromResult(Find(id)); } - public TenantConfiguration? Find(string name) + public TenantConfiguration? Find(string normalizedName) { - return _options.Tenants?.FirstOrDefault(t => t.Name == name); + return _options.Tenants?.FirstOrDefault(t => t.NormalizedName == normalizedName); } public TenantConfiguration? Find(Guid id) diff --git a/framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantConfigurationProvider.cs b/framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantConfigurationProvider.cs index 7e93cf888a..79f07deb4a 100644 --- a/framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantConfigurationProvider.cs +++ b/framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantConfigurationProvider.cs @@ -10,6 +10,7 @@ public class TenantConfigurationProvider : ITenantConfigurationProvider, ITransi { protected virtual ITenantResolver TenantResolver { get; } protected virtual ITenantStore TenantStore { get; } + protected virtual ITenantNormalizer TenantNormalizer { get; } protected virtual ITenantResolveResultAccessor TenantResolveResultAccessor { get; } protected virtual IStringLocalizer StringLocalizer { get; } @@ -17,10 +18,12 @@ public class TenantConfigurationProvider : ITenantConfigurationProvider, ITransi ITenantResolver tenantResolver, ITenantStore tenantStore, ITenantResolveResultAccessor tenantResolveResultAccessor, - IStringLocalizer stringLocalizer) + IStringLocalizer stringLocalizer, + ITenantNormalizer tenantNormalizer) { TenantResolver = tenantResolver; TenantStore = tenantStore; + TenantNormalizer = tenantNormalizer; TenantResolveResultAccessor = tenantResolveResultAccessor; StringLocalizer = stringLocalizer; } @@ -69,7 +72,7 @@ public class TenantConfigurationProvider : ITenantConfigurationProvider, ITransi } else { - return await TenantStore.FindAsync(tenantIdOrName); + return await TenantStore.FindAsync(TenantNormalizer.NormalizeName(tenantIdOrName)!); } } } diff --git a/framework/test/Volo.Abp.AspNetCore.MultiTenancy.Tests/Volo/Abp/AspNetCore/MultiTenancy/AspNetCoreMultiTenancy_WithDomainResolver_Tests.cs b/framework/test/Volo.Abp.AspNetCore.MultiTenancy.Tests/Volo/Abp/AspNetCore/MultiTenancy/AspNetCoreMultiTenancy_WithDomainResolver_Tests.cs index e80b47b2a5..02d0288b4b 100644 --- a/framework/test/Volo.Abp.AspNetCore.MultiTenancy.Tests/Volo/Abp/AspNetCore/MultiTenancy/AspNetCoreMultiTenancy_WithDomainResolver_Tests.cs +++ b/framework/test/Volo.Abp.AspNetCore.MultiTenancy.Tests/Volo/Abp/AspNetCore/MultiTenancy/AspNetCoreMultiTenancy_WithDomainResolver_Tests.cs @@ -16,6 +16,7 @@ public class AspNetCoreMultiTenancy_WithDomainResolver_Tests : AspNetCoreMultiTe { private readonly Guid _testTenantId = Guid.NewGuid(); private readonly string _testTenantName = "acme"; + private readonly string _testTenantNormalizedName = "ACME"; private readonly AbpAspNetCoreMultiTenancyOptions _options; @@ -30,7 +31,7 @@ public class AspNetCoreMultiTenancy_WithDomainResolver_Tests : AspNetCoreMultiTe { options.Tenants = new[] { - new TenantConfiguration(_testTenantId, _testTenantName) + new TenantConfiguration(_testTenantId, _testTenantName, _testTenantNormalizedName) }; }); diff --git a/framework/test/Volo.Abp.AspNetCore.MultiTenancy.Tests/Volo/Abp/AspNetCore/MultiTenancy/AspNetCoreMultiTenancy_Without_DomainResolver_Tests.cs b/framework/test/Volo.Abp.AspNetCore.MultiTenancy.Tests/Volo/Abp/AspNetCore/MultiTenancy/AspNetCoreMultiTenancy_Without_DomainResolver_Tests.cs index 56da287ef8..71ee5f11df 100644 --- a/framework/test/Volo.Abp.AspNetCore.MultiTenancy.Tests/Volo/Abp/AspNetCore/MultiTenancy/AspNetCoreMultiTenancy_Without_DomainResolver_Tests.cs +++ b/framework/test/Volo.Abp.AspNetCore.MultiTenancy.Tests/Volo/Abp/AspNetCore/MultiTenancy/AspNetCoreMultiTenancy_Without_DomainResolver_Tests.cs @@ -17,6 +17,7 @@ public class AspNetCoreMultiTenancy_Without_DomainResolver_Tests : AspNetCoreMul { private readonly Guid _testTenantId = Guid.NewGuid(); private readonly string _testTenantName = "acme"; + private readonly string _testTenantNormalizedName = "ACME"; private readonly AbpAspNetCoreMultiTenancyOptions _options; @@ -31,7 +32,7 @@ public class AspNetCoreMultiTenancy_Without_DomainResolver_Tests : AspNetCoreMul { options.Tenants = new[] { - new TenantConfiguration(_testTenantId, _testTenantName) + new TenantConfiguration(_testTenantId, _testTenantName, _testTenantNormalizedName) }; }); diff --git a/framework/test/Volo.Abp.AspNetCore.Serilog.Tests/Volo/Abp/AspNetCore/Serilog/Serilog_Enrichers_Tests.cs b/framework/test/Volo.Abp.AspNetCore.Serilog.Tests/Volo/Abp/AspNetCore/Serilog/Serilog_Enrichers_Tests.cs index 4782a5e768..1fb1402b26 100644 --- a/framework/test/Volo.Abp.AspNetCore.Serilog.Tests/Volo/Abp/AspNetCore/Serilog/Serilog_Enrichers_Tests.cs +++ b/framework/test/Volo.Abp.AspNetCore.Serilog.Tests/Volo/Abp/AspNetCore/Serilog/Serilog_Enrichers_Tests.cs @@ -20,6 +20,7 @@ public class Serilog_Enrichers_Tests : AbpSerilogTestBase private readonly Guid _testTenantId = Guid.NewGuid(); private readonly string _testTenantName = "acme"; + private readonly string _testTenantNormalizedName = "ACME"; private readonly AbpAspNetCoreMultiTenancyOptions _tenancyOptions; private readonly AbpAspNetCoreSerilogOptions _serilogOptions; @@ -39,7 +40,7 @@ public class Serilog_Enrichers_Tests : AbpSerilogTestBase { options.Tenants = new[] { - new TenantConfiguration(_testTenantId, _testTenantName) + new TenantConfiguration(_testTenantId, _testTenantName, _testTenantNormalizedName) }; }); base.ConfigureServices(services); diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/ITenantRepository.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/ITenantRepository.cs index 6412993d14..41ea978524 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/ITenantRepository.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/ITenantRepository.cs @@ -9,13 +9,13 @@ namespace Volo.Abp.TenantManagement; public interface ITenantRepository : IBasicRepository { Task FindByNameAsync( - string name, + string normalizedName, bool includeDetails = true, CancellationToken cancellationToken = default); [Obsolete("Use FindByNameAsync method.")] Tenant FindByName( - string name, + string normalizedName, bool includeDetails = true ); diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/Tenant.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/Tenant.cs index 5275e39ab3..6567cf8efd 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/Tenant.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/Tenant.cs @@ -10,7 +10,9 @@ namespace Volo.Abp.TenantManagement; public class Tenant : FullAuditedAggregateRoot, IHasEntityVersion { public virtual string Name { get; protected set; } - + + public virtual string NormalizedName { get; protected set; } + public virtual int EntityVersion { get; protected set; } public virtual List ConnectionStrings { get; protected set; } @@ -20,10 +22,11 @@ public class Tenant : FullAuditedAggregateRoot, IHasEntityVersion } - protected internal Tenant(Guid id, [NotNull] string name) + protected internal Tenant(Guid id, [NotNull] string name, [CanBeNull] string normalizedTenantName) : base(id) { SetName(name); + SetNormalizedTenantName(normalizedTenantName); ConnectionStrings = new List(); } @@ -78,4 +81,9 @@ public class Tenant : FullAuditedAggregateRoot, IHasEntityVersion { Name = Check.NotNullOrWhiteSpace(name, nameof(name), TenantConsts.MaxNameLength); } + + protected internal virtual void SetNormalizedTenantName([CanBeNull] string normalizedTenantName) + { + NormalizedName = normalizedTenantName; + } } diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantConfigurationCacheItemInvalidator.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantConfigurationCacheItemInvalidator.cs index e629186e20..09c1a9368f 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantConfigurationCacheItemInvalidator.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantConfigurationCacheItemInvalidator.cs @@ -22,21 +22,21 @@ public class TenantConfigurationCacheItemInvalidator : public virtual async Task HandleEventAsync(EntityChangedEventData eventData) { - await ClearCacheAsync(eventData.Entity.Id, eventData.Entity.Name); + await ClearCacheAsync(eventData.Entity.Id, eventData.Entity.NormalizedName); } public virtual async Task HandleEventAsync(EntityDeletedEventData eventData) { - await ClearCacheAsync(eventData.Entity.Id, eventData.Entity.Name); + await ClearCacheAsync(eventData.Entity.Id, eventData.Entity.NormalizedName); } - protected virtual async Task ClearCacheAsync(Guid? id, string name) + protected virtual async Task ClearCacheAsync(Guid? id, string normalizedName) { await Cache.RemoveManyAsync( new[] { TenantConfigurationCacheItem.CalculateCacheKey(id, null), - TenantConfigurationCacheItem.CalculateCacheKey(null, name), + TenantConfigurationCacheItem.CalculateCacheKey(null, normalizedName), }); } } diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantManager.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantManager.cs index 1ad7324c35..43594dfde7 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantManager.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantManager.cs @@ -11,19 +11,22 @@ public class TenantManager : DomainService, ITenantManager protected ITenantRepository TenantRepository { get; } protected IDistributedCache Cache { get; } - public TenantManager(ITenantRepository tenantRepository, - IDistributedCache cache) + protected ITenantNormalizer TenantNormalizer { get; } + + public TenantManager(ITenantRepository tenantRepository, IDistributedCache cache, ITenantNormalizer tenantNormalizer) { TenantRepository = tenantRepository; Cache = cache; + TenantNormalizer = tenantNormalizer; } public virtual async Task CreateAsync(string name) { Check.NotNull(name, nameof(name)); - await ValidateNameAsync(name); - return new Tenant(GuidGenerator.Create(), name); + var normalizedTenantName = TenantNormalizer.NormalizeName(name); + await ValidateNameAsync(normalizedTenantName); + return new Tenant(GuidGenerator.Create(), name, normalizedTenantName); } public virtual async Task ChangeNameAsync(Tenant tenant, string name) @@ -31,17 +34,20 @@ public class TenantManager : DomainService, ITenantManager Check.NotNull(tenant, nameof(tenant)); Check.NotNull(name, nameof(name)); - await ValidateNameAsync(name, tenant.Id); - await Cache.RemoveAsync(TenantConfigurationCacheItem.CalculateCacheKey(tenant.Name)); + var normalizedTenantName = TenantNormalizer.NormalizeName(name); + + await ValidateNameAsync(normalizedTenantName, tenant.Id); + await Cache.RemoveAsync(TenantConfigurationCacheItem.CalculateCacheKey(tenant.NormalizedName)); tenant.SetName(name); + tenant.SetNormalizedTenantName(normalizedTenantName); } - protected virtual async Task ValidateNameAsync(string name, Guid? expectedId = null) + protected virtual async Task ValidateNameAsync(string normalizeName, Guid? expectedId = null) { - var tenant = await TenantRepository.FindByNameAsync(name); + var tenant = await TenantRepository.FindByNameAsync(normalizeName); if (tenant != null && tenant.Id != expectedId) { - throw new BusinessException("Volo.Abp.TenantManagement:DuplicateTenantName").WithData("Name", name); + throw new BusinessException("Volo.Abp.TenantManagement:DuplicateTenantName").WithData("Name", normalizeName); } } } diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantStore.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantStore.cs index 5fd23add6b..f2ef1ed066 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantStore.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantStore.cs @@ -27,9 +27,9 @@ public class TenantStore : ITenantStore, ITransientDependency Cache = cache; } - public virtual async Task FindAsync(string name) + public virtual async Task FindAsync(string normalizedName) { - return (await GetCacheItemAsync(null, name)).Value; + return (await GetCacheItemAsync(null, normalizedName)).Value; } public virtual async Task FindAsync(Guid id) @@ -38,9 +38,9 @@ public class TenantStore : ITenantStore, ITransientDependency } [Obsolete("Use FindAsync method.")] - public virtual TenantConfiguration Find(string name) + public virtual TenantConfiguration Find(string normalizedName) { - return (GetCacheItem(null, name)).Value; + return (GetCacheItem(null, normalizedName)).Value; } [Obsolete("Use FindAsync method.")] @@ -49,9 +49,9 @@ public class TenantStore : ITenantStore, ITransientDependency return (GetCacheItem(id, null)).Value; } - protected virtual async Task GetCacheItemAsync(Guid? id, string name) + protected virtual async Task GetCacheItemAsync(Guid? id, string normalizedName) { - var cacheKey = CalculateCacheKey(id, name); + var cacheKey = CalculateCacheKey(id, normalizedName); var cacheItem = await Cache.GetAsync(cacheKey, considerUow: true); if (cacheItem != null) @@ -68,11 +68,11 @@ public class TenantStore : ITenantStore, ITransientDependency } } - if (!name.IsNullOrWhiteSpace()) + if (!normalizedName.IsNullOrWhiteSpace()) { using (CurrentTenant.Change(null)) //TODO: No need this if we can implement to define host side (or tenant-independent) entities! { - var tenant = await TenantRepository.FindByNameAsync(name); + var tenant = await TenantRepository.FindByNameAsync(normalizedName); return await SetCacheAsync(cacheKey, tenant); } } @@ -89,9 +89,9 @@ public class TenantStore : ITenantStore, ITransientDependency } [Obsolete("Use GetCacheItemAsync method.")] - protected virtual TenantConfigurationCacheItem GetCacheItem(Guid? id, string name) + protected virtual TenantConfigurationCacheItem GetCacheItem(Guid? id, string normalizedName) { - var cacheKey = CalculateCacheKey(id, name); + var cacheKey = CalculateCacheKey(id, normalizedName); var cacheItem = Cache.Get(cacheKey, considerUow: true); if (cacheItem != null) @@ -108,11 +108,11 @@ public class TenantStore : ITenantStore, ITransientDependency } } - if (!name.IsNullOrWhiteSpace()) + if (!normalizedName.IsNullOrWhiteSpace()) { using (CurrentTenant.Change(null)) //TODO: No need this if we can implement to define host side (or tenant-independent) entities! { - var tenant = TenantRepository.FindByName(name); + var tenant = TenantRepository.FindByName(normalizedName); return SetCache(cacheKey, tenant); } } @@ -129,8 +129,8 @@ public class TenantStore : ITenantStore, ITransientDependency return cacheItem; } - protected virtual string CalculateCacheKey(Guid? id, string name) + protected virtual string CalculateCacheKey(Guid? id, string normalizedName) { - return TenantConfigurationCacheItem.CalculateCacheKey(id, name); + return TenantConfigurationCacheItem.CalculateCacheKey(id, normalizedName); } } diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/AbpTenantManagementDbContextModelCreatingExtensions.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/AbpTenantManagementDbContextModelCreatingExtensions.cs index 6b1d7f7e8e..bb189e72a1 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/AbpTenantManagementDbContextModelCreatingExtensions.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/AbpTenantManagementDbContextModelCreatingExtensions.cs @@ -23,6 +23,7 @@ public static class AbpTenantManagementDbContextModelCreatingExtensions b.ConfigureByConvention(); b.Property(t => t.Name).IsRequired().HasMaxLength(TenantConsts.MaxNameLength); + b.Property(t => t.NormalizedName).IsRequired().HasMaxLength(TenantConsts.MaxNameLength); b.HasMany(u => u.ConnectionStrings).WithOne().HasForeignKey(uc => uc.TenantId).IsRequired(); diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/EfCoreTenantRepository.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/EfCoreTenantRepository.cs index 34d350d242..e58512dc13 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/EfCoreTenantRepository.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/EfCoreTenantRepository.cs @@ -19,23 +19,23 @@ public class EfCoreTenantRepository : EfCoreRepository FindByNameAsync( - string name, + string normalizedName, bool includeDetails = true, CancellationToken cancellationToken = default) { return await (await GetDbSetAsync()) .IncludeDetails(includeDetails) .OrderBy(t => t.Id) - .FirstOrDefaultAsync(t => t.Name == name, GetCancellationToken(cancellationToken)); + .FirstOrDefaultAsync(t => t.NormalizedName == normalizedName, GetCancellationToken(cancellationToken)); } [Obsolete("Use FindByNameAsync method.")] - public virtual Tenant FindByName(string name, bool includeDetails = true) + public virtual Tenant FindByName(string normalizedName, bool includeDetails = true) { return DbSet .IncludeDetails(includeDetails) .OrderBy(t => t.Id) - .FirstOrDefault(t => t.Name == name); + .FirstOrDefault(t => t.NormalizedName == normalizedName); } [Obsolete("Use FindAsync method.")] diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.MongoDB/Volo/Abp/TenantManagement/MongoDb/MongoTenantRepository.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.MongoDB/Volo/Abp/TenantManagement/MongoDb/MongoTenantRepository.cs index 321dcf365f..049dc5e57c 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.MongoDB/Volo/Abp/TenantManagement/MongoDb/MongoTenantRepository.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.MongoDB/Volo/Abp/TenantManagement/MongoDb/MongoTenantRepository.cs @@ -20,19 +20,19 @@ public class MongoTenantRepository : MongoDbRepository FindByNameAsync( - string name, + string normalizedName, bool includeDetails = true, CancellationToken cancellationToken = default) { return await (await GetMongoQueryableAsync(cancellationToken)) - .FirstOrDefaultAsync(t => t.Name == name, GetCancellationToken(cancellationToken)); + .FirstOrDefaultAsync(t => t.NormalizedName == normalizedName, GetCancellationToken(cancellationToken)); } [Obsolete("Use FindByNameAsync method.")] - public virtual Tenant FindByName(string name, bool includeDetails = true) + public virtual Tenant FindByName(string normalizedName, bool includeDetails = true) { return GetMongoQueryable() - .FirstOrDefault(t => t.Name == name); + .FirstOrDefault(t => t.NormalizedName == normalizedName); } [Obsolete("Use FindAsync method.")] diff --git a/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantCacheItemInvalidator_Tests.cs b/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantCacheItemInvalidator_Tests.cs index 9671402560..2dc844d71e 100644 --- a/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantCacheItemInvalidator_Tests.cs +++ b/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantCacheItemInvalidator_Tests.cs @@ -12,6 +12,7 @@ public class TenantConfigurationCacheItemInvalidator_Tests : AbpTenantManagement private readonly ITenantStore _tenantStore; private readonly ITenantRepository _tenantRepository; private readonly ITenantManager _tenantManager; + private readonly ITenantNormalizer _tenantNormalizer; public TenantConfigurationCacheItemInvalidator_Tests() { @@ -19,86 +20,87 @@ public class TenantConfigurationCacheItemInvalidator_Tests : AbpTenantManagement _tenantStore = GetRequiredService(); _tenantRepository = GetRequiredService(); _tenantManager = GetRequiredService(); + _tenantNormalizer = GetRequiredService(); } [Fact] public async Task Get_Tenant_Should_Cached() { - var acme = await _tenantRepository.FindByNameAsync("acme"); + var acme = await _tenantRepository.FindByNameAsync(_tenantNormalizer.NormalizeName("acme")); acme.ShouldNotBeNull(); (await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(acme.Id, null))).ShouldBeNull(); - (await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(null, acme.Name))).ShouldBeNull(); + (await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(null, acme.NormalizedName))).ShouldBeNull(); await _tenantStore.FindAsync(acme.Id); (await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(acme.Id, null))).ShouldNotBeNull(); - await _tenantStore.FindAsync(acme.Name); - (await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(null, acme.Name))).ShouldNotBeNull(); + await _tenantStore.FindAsync(acme.NormalizedName); + (await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(null, acme.NormalizedName))).ShouldNotBeNull(); - var volosoft = _tenantRepository.FindByName("volosoft"); + var volosoft = _tenantRepository.FindByName(_tenantNormalizer.NormalizeName("volosoft")); volosoft.ShouldNotBeNull(); (_cache.Get(TenantConfigurationCacheItem.CalculateCacheKey(volosoft.Id, null))).ShouldBeNull(); - (_cache.Get(TenantConfigurationCacheItem.CalculateCacheKey(null, volosoft.Name))).ShouldBeNull(); + (_cache.Get(TenantConfigurationCacheItem.CalculateCacheKey(null, volosoft.NormalizedName))).ShouldBeNull(); _tenantStore.Find(volosoft.Id); (_cache.Get(TenantConfigurationCacheItem.CalculateCacheKey(volosoft.Id, null))).ShouldNotBeNull(); - _tenantStore.Find(volosoft.Name); - (_cache.Get(TenantConfigurationCacheItem.CalculateCacheKey(null, volosoft.Name))).ShouldNotBeNull(); + _tenantStore.Find(volosoft.NormalizedName); + (_cache.Get(TenantConfigurationCacheItem.CalculateCacheKey(null, volosoft.NormalizedName))).ShouldNotBeNull(); } [Fact] public async Task Cache_Should_Invalidator_When_Tenant_Changed() { - var acme = await _tenantRepository.FindByNameAsync("acme"); + var acme = await _tenantRepository.FindByNameAsync(_tenantNormalizer.NormalizeName("acme")); acme.ShouldNotBeNull(); // FindAsync will cache tenant. await _tenantStore.FindAsync(acme.Id); - await _tenantStore.FindAsync(acme.Name); + await _tenantStore.FindAsync(acme.NormalizedName); (await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(acme.Id, null))).ShouldNotBeNull(); - (await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(null, acme.Name))).ShouldNotBeNull(); + (await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(null, acme.NormalizedName))).ShouldNotBeNull(); await _tenantRepository.DeleteAsync(acme); (await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(acme.Id, null))).ShouldBeNull(); - (await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(null, acme.Name))).ShouldBeNull(); + (await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(null, acme.NormalizedName))).ShouldBeNull(); - var volosoft = await _tenantRepository.FindByNameAsync("volosoft"); + var volosoft = await _tenantRepository.FindByNameAsync(_tenantNormalizer.NormalizeName("volosoft")); volosoft.ShouldNotBeNull(); // Find will cache tenant. _tenantStore.Find(volosoft.Id); - _tenantStore.Find(volosoft.Name); + _tenantStore.Find(volosoft.NormalizedName); (_cache.Get(TenantConfigurationCacheItem.CalculateCacheKey(volosoft.Id, null))).ShouldNotBeNull(); - (_cache.Get(TenantConfigurationCacheItem.CalculateCacheKey(null, volosoft.Name))).ShouldNotBeNull(); + (_cache.Get(TenantConfigurationCacheItem.CalculateCacheKey(null, volosoft.NormalizedName))).ShouldNotBeNull(); await _tenantRepository.DeleteAsync(volosoft); (_cache.Get(TenantConfigurationCacheItem.CalculateCacheKey(volosoft.Id, null))).ShouldBeNull(); - (_cache.Get(TenantConfigurationCacheItem.CalculateCacheKey(null, volosoft.Name))).ShouldBeNull(); + (_cache.Get(TenantConfigurationCacheItem.CalculateCacheKey(null, volosoft.NormalizedName))).ShouldBeNull(); - var abp = await _tenantRepository.FindByNameAsync("abp"); + var abp = await _tenantRepository.FindByNameAsync(_tenantNormalizer.NormalizeName("abp")); abp.ShouldNotBeNull(); // Find will cache tenant. await _tenantStore.FindAsync(abp.Id); - await _tenantStore.FindAsync(abp.Name); + await _tenantStore.FindAsync(abp.NormalizedName); (await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(abp.Id, null))).ShouldNotBeNull(); - (await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(null, abp.Name))).ShouldNotBeNull(); + (await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(null, abp.NormalizedName))).ShouldNotBeNull(); await _tenantManager.ChangeNameAsync(abp, "abp2"); await _tenantRepository.UpdateAsync(abp); (await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(abp.Id, null))).ShouldBeNull(); - (await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(null, "abp"))).ShouldBeNull(); - (await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(null, "abp2"))).ShouldBeNull(); + (await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(null, _tenantNormalizer.NormalizeName("abp")))).ShouldBeNull(); + (await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(null, _tenantNormalizer.NormalizeName("abp2")))).ShouldBeNull(); } } diff --git a/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantManager_Tests.cs b/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantManager_Tests.cs index 161882e412..f46bcf8573 100644 --- a/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantManager_Tests.cs +++ b/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantManager_Tests.cs @@ -1,5 +1,6 @@ using System.Threading.Tasks; using Shouldly; +using Volo.Abp.MultiTenancy; using Xunit; namespace Volo.Abp.TenantManagement; @@ -8,19 +9,21 @@ public class TenantManager_Tests : AbpTenantManagementDomainTestBase { private readonly ITenantManager _tenantManager; private readonly ITenantRepository _tenantRepository; + private readonly ITenantNormalizer _tenantNormalizer; public TenantManager_Tests() { _tenantManager = GetRequiredService(); _tenantRepository = GetRequiredService(); + _tenantNormalizer = GetRequiredService(); } - [Fact] public async Task CreateAsync() { var tenant = await _tenantManager.CreateAsync("Test"); tenant.Name.ShouldBe("Test"); + tenant.NormalizedName.ShouldBe(_tenantNormalizer.NormalizeName("Test")); } [Fact] @@ -32,18 +35,20 @@ public class TenantManager_Tests : AbpTenantManagementDomainTestBase [Fact] public async Task ChangeNameAsync() { - var tenant = await _tenantRepository.FindByNameAsync("volosoft"); + var tenant = await _tenantRepository.FindByNameAsync(_tenantNormalizer.NormalizeName("volosoft")); tenant.ShouldNotBeNull(); + tenant.NormalizedName.ShouldBe(_tenantNormalizer.NormalizeName("volosoft")); await _tenantManager.ChangeNameAsync(tenant, "newVolosoft"); tenant.Name.ShouldBe("newVolosoft"); + tenant.NormalizedName.ShouldBe(_tenantNormalizer.NormalizeName("newVolosoft")); } [Fact] public async Task ChangeName_Tenant_Name_Can_Not_Duplicate() { - var tenant = await _tenantRepository.FindByNameAsync("acme"); + var tenant = await _tenantRepository.FindByNameAsync(_tenantNormalizer.NormalizeName("acme")); tenant.ShouldNotBeNull(); await Assert.ThrowsAsync(async () => await _tenantManager.ChangeNameAsync(tenant, "volosoft")); diff --git a/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantStore_Tests.cs b/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantStore_Tests.cs index 1af4ebd1ea..10f203eb43 100644 --- a/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantStore_Tests.cs +++ b/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantStore_Tests.cs @@ -9,25 +9,28 @@ public class TenantStore_Tests : AbpTenantManagementDomainTestBase { private readonly ITenantStore _tenantStore; private readonly ITenantRepository _tenantRepository; + private readonly ITenantNormalizer _tenantNormalizer; public TenantStore_Tests() { _tenantStore = GetRequiredService(); _tenantRepository = GetRequiredService(); + _tenantNormalizer = GetRequiredService(); } [Fact] public async Task FindAsyncByName() { - var acme = await _tenantStore.FindAsync("acme"); + var acme = await _tenantStore.FindAsync(_tenantNormalizer.NormalizeName("acme")!); acme.ShouldNotBeNull(); acme.Name.ShouldBe("acme"); + acme.NormalizedName.ShouldBe(_tenantNormalizer.NormalizeName("acme")!); } [Fact] public async Task FindAsyncById() { - var acme = await _tenantRepository.FindByNameAsync("acme"); + var acme = await _tenantRepository.FindByNameAsync(_tenantNormalizer.NormalizeName("acme")); acme.ShouldNotBeNull(); (await _tenantStore.FindAsync(acme.Id)).ShouldNotBeNull(); diff --git a/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/Tenant_Tests.cs b/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/Tenant_Tests.cs index dbe631d431..bcefc527e6 100644 --- a/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/Tenant_Tests.cs +++ b/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/Tenant_Tests.cs @@ -1,5 +1,6 @@ using System.Threading.Tasks; using Shouldly; +using Volo.Abp.MultiTenancy; using Xunit; namespace Volo.Abp.TenantManagement; @@ -7,16 +8,18 @@ namespace Volo.Abp.TenantManagement; public class Tenant_Tests : AbpTenantManagementDomainTestBase { private readonly ITenantRepository _tenantRepository; + private readonly ITenantNormalizer _tenantNormalizer; public Tenant_Tests() { _tenantRepository = GetRequiredService(); + _tenantNormalizer = GetRequiredService(); } [Fact] public async Task FindDefaultConnectionString() { - var acme = await _tenantRepository.FindByNameAsync("acme"); + var acme = await _tenantRepository.FindByNameAsync(_tenantNormalizer.NormalizeName("acme")); acme.ShouldNotBeNull(); acme.FindDefaultConnectionString().ShouldBe("DefaultConnString-Value"); @@ -25,7 +28,7 @@ public class Tenant_Tests : AbpTenantManagementDomainTestBase [Fact] public async Task FindConnectionString() { - var acme = await _tenantRepository.FindByNameAsync("acme"); + var acme = await _tenantRepository.FindByNameAsync(_tenantNormalizer.NormalizeName("acme")); acme.ShouldNotBeNull(); acme.FindConnectionString(Data.ConnectionStrings.DefaultConnectionStringName).ShouldBe("DefaultConnString-Value"); diff --git a/modules/tenant-management/test/Volo.Abp.TenantManagement.TestBase/Volo/Abp/TenantManagement/LazyLoad_Tests.cs b/modules/tenant-management/test/Volo.Abp.TenantManagement.TestBase/Volo/Abp/TenantManagement/LazyLoad_Tests.cs index 049d93cf65..9fe123d73b 100644 --- a/modules/tenant-management/test/Volo.Abp.TenantManagement.TestBase/Volo/Abp/TenantManagement/LazyLoad_Tests.cs +++ b/modules/tenant-management/test/Volo.Abp.TenantManagement.TestBase/Volo/Abp/TenantManagement/LazyLoad_Tests.cs @@ -2,6 +2,7 @@ using System.Threading.Tasks; using Shouldly; using Volo.Abp.Modularity; +using Volo.Abp.MultiTenancy; using Volo.Abp.Uow; using Xunit; @@ -11,10 +12,12 @@ public abstract class LazyLoad_Tests : TenantManagementTestBase< where TStartupModule : IAbpModule { public ITenantRepository TenantRepository { get; } + public ITenantNormalizer TenantNormalizer { get; } protected LazyLoad_Tests() { TenantRepository = GetRequiredService(); + TenantNormalizer = GetRequiredService(); } [Fact] @@ -22,7 +25,7 @@ public abstract class LazyLoad_Tests : TenantManagementTestBase< { using (var uow = GetRequiredService().Begin()) { - var role = await TenantRepository.FindByNameAsync("acme", includeDetails: false); + var role = await TenantRepository.FindByNameAsync(TenantNormalizer.NormalizeName("acme"), includeDetails: false); role.ConnectionStrings.ShouldNotBeNull(); role.ConnectionStrings.Any().ShouldBeTrue(); diff --git a/modules/tenant-management/test/Volo.Abp.TenantManagement.TestBase/Volo/Abp/TenantManagement/TenantRepository_Tests.cs b/modules/tenant-management/test/Volo.Abp.TenantManagement.TestBase/Volo/Abp/TenantManagement/TenantRepository_Tests.cs index c8ff94d069..6e4c3c8db5 100644 --- a/modules/tenant-management/test/Volo.Abp.TenantManagement.TestBase/Volo/Abp/TenantManagement/TenantRepository_Tests.cs +++ b/modules/tenant-management/test/Volo.Abp.TenantManagement.TestBase/Volo/Abp/TenantManagement/TenantRepository_Tests.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Threading.Tasks; using Shouldly; using Volo.Abp.Modularity; +using Volo.Abp.MultiTenancy; using Xunit; namespace Volo.Abp.TenantManagement; @@ -11,22 +12,24 @@ public abstract class TenantRepository_Tests : TenantManagementT where TStartupModule : IAbpModule { public ITenantRepository TenantRepository { get; } + public ITenantNormalizer TenantNormalizer { get; } protected TenantRepository_Tests() { TenantRepository = GetRequiredService(); + TenantNormalizer = GetRequiredService(); } [Fact] public async Task FindByNameAsync() { - var tenant = await TenantRepository.FindByNameAsync("acme"); + var tenant = await TenantRepository.FindByNameAsync(TenantNormalizer.NormalizeName("acme")); tenant.ShouldNotBeNull(); - tenant = await TenantRepository.FindByNameAsync("undefined-tenant"); + tenant = await TenantRepository.FindByNameAsync(TenantNormalizer.NormalizeName("undefined-tenant")); tenant.ShouldBeNull(); - tenant = await TenantRepository.FindByNameAsync("acme", includeDetails: true); + tenant = await TenantRepository.FindByNameAsync(TenantNormalizer.NormalizeName("acme"), includeDetails: true); tenant.ShouldNotBeNull(); tenant.ConnectionStrings.Count.ShouldBeGreaterThanOrEqualTo(2); } @@ -34,7 +37,7 @@ public abstract class TenantRepository_Tests : TenantManagementT [Fact] public async Task FindAsync() { - var tenantId = (await TenantRepository.FindByNameAsync("acme")).Id; + var tenantId = (await TenantRepository.FindByNameAsync(TenantNormalizer.NormalizeName("acme"))).Id; var tenant = await TenantRepository.FindAsync(tenantId); tenant.ShouldNotBeNull(); @@ -51,14 +54,14 @@ public abstract class TenantRepository_Tests : TenantManagementT public async Task GetListAsync() { var tenants = await TenantRepository.GetListAsync(); - tenants.ShouldContain(t => t.Name == "acme"); - tenants.ShouldContain(t => t.Name == "volosoft"); + tenants.ShouldContain(t => t.Name == "acme" && t.NormalizedName == TenantNormalizer.NormalizeName("acme")); + tenants.ShouldContain(t => t.Name == "volosoft" && t.NormalizedName == TenantNormalizer.NormalizeName("volosoft")); } [Fact] public async Task Should_Eager_Load_Tenant_Collections() { - var role = await TenantRepository.FindByNameAsync("acme"); + var role = await TenantRepository.FindByNameAsync(TenantNormalizer.NormalizeName("acme")); role.ConnectionStrings.ShouldNotBeNull(); role.ConnectionStrings.Any().ShouldBeTrue(); } From ecc0562c7c5d649f3c70ca7acdbf9d1eac7f6ced Mon Sep 17 00:00:00 2001 From: maliming Date: Mon, 11 Dec 2023 15:08:13 +0800 Subject: [PATCH 002/154] Rename `NormalizedTenantName` to `NormalizedName`. --- .../MauiBlazor/MauiBlazorRemoteTenantStore.cs | 6 +++--- .../Volo/Abp/TenantManagement/Tenant.cs | 8 ++++---- .../Volo/Abp/TenantManagement/TenantManager.cs | 13 ++++++------- .../Volo/Abp/TenantManagement/TenantStore.cs | 4 ++-- 4 files changed, 15 insertions(+), 16 deletions(-) diff --git a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor/Volo/Abp/AspNetCore/Components/MauiBlazor/MauiBlazorRemoteTenantStore.cs b/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor/Volo/Abp/AspNetCore/Components/MauiBlazor/MauiBlazorRemoteTenantStore.cs index d06eb60566..3873b48db3 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor/Volo/Abp/AspNetCore/Components/MauiBlazor/MauiBlazorRemoteTenantStore.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor/Volo/Abp/AspNetCore/Components/MauiBlazor/MauiBlazorRemoteTenantStore.cs @@ -98,12 +98,12 @@ public class MauiBlazorRemoteTenantStore : ITenantStore, ITransientDependency return null; } - return new TenantConfiguration(tenantResultDto.TenantId.Value, tenantResultDto.Name!); + return new TenantConfiguration(tenantResultDto.TenantId.Value, tenantResultDto.Name!, tenantResultDto.NormalizedName!); } - protected virtual string CreateCacheKey(string tenantName) + protected virtual string CreateCacheKey(string normalizedName) { - return $"RemoteTenantStore_Name_{tenantName}"; + return $"RemoteTenantStore_Name_{normalizedName}"; } protected virtual string CreateCacheKey(Guid tenantId) diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/Tenant.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/Tenant.cs index 6567cf8efd..c6c5c3edee 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/Tenant.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/Tenant.cs @@ -22,11 +22,11 @@ public class Tenant : FullAuditedAggregateRoot, IHasEntityVersion } - protected internal Tenant(Guid id, [NotNull] string name, [CanBeNull] string normalizedTenantName) + protected internal Tenant(Guid id, [NotNull] string name, [CanBeNull] string normalizedName) : base(id) { SetName(name); - SetNormalizedTenantName(normalizedTenantName); + SetNormalizedName(normalizedName); ConnectionStrings = new List(); } @@ -82,8 +82,8 @@ public class Tenant : FullAuditedAggregateRoot, IHasEntityVersion Name = Check.NotNullOrWhiteSpace(name, nameof(name), TenantConsts.MaxNameLength); } - protected internal virtual void SetNormalizedTenantName([CanBeNull] string normalizedTenantName) + protected internal virtual void SetNormalizedName([CanBeNull] string normalizedName) { - NormalizedName = normalizedTenantName; + NormalizedName = normalizedName; } } diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantManager.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantManager.cs index 43594dfde7..648e02d381 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantManager.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantManager.cs @@ -10,7 +10,6 @@ public class TenantManager : DomainService, ITenantManager { protected ITenantRepository TenantRepository { get; } protected IDistributedCache Cache { get; } - protected ITenantNormalizer TenantNormalizer { get; } public TenantManager(ITenantRepository tenantRepository, IDistributedCache cache, ITenantNormalizer tenantNormalizer) @@ -24,9 +23,9 @@ public class TenantManager : DomainService, ITenantManager { Check.NotNull(name, nameof(name)); - var normalizedTenantName = TenantNormalizer.NormalizeName(name); - await ValidateNameAsync(normalizedTenantName); - return new Tenant(GuidGenerator.Create(), name, normalizedTenantName); + var normalizedName = TenantNormalizer.NormalizeName(name); + await ValidateNameAsync(normalizedName); + return new Tenant(GuidGenerator.Create(), name, normalizedName); } public virtual async Task ChangeNameAsync(Tenant tenant, string name) @@ -34,12 +33,12 @@ public class TenantManager : DomainService, ITenantManager Check.NotNull(tenant, nameof(tenant)); Check.NotNull(name, nameof(name)); - var normalizedTenantName = TenantNormalizer.NormalizeName(name); + var normalizedName = TenantNormalizer.NormalizeName(name); - await ValidateNameAsync(normalizedTenantName, tenant.Id); + await ValidateNameAsync(normalizedName, tenant.Id); await Cache.RemoveAsync(TenantConfigurationCacheItem.CalculateCacheKey(tenant.NormalizedName)); tenant.SetName(name); - tenant.SetNormalizedTenantName(normalizedTenantName); + tenant.SetNormalizedName(normalizedName); } protected virtual async Task ValidateNameAsync(string normalizeName, Guid? expectedId = null) diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantStore.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantStore.cs index f2ef1ed066..d334c124a6 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantStore.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantStore.cs @@ -77,7 +77,7 @@ public class TenantStore : ITenantStore, ITransientDependency } } - throw new AbpException("Both id and name can't be invalid."); + throw new AbpException("Both id and normalizedName can't be invalid."); } protected virtual async Task SetCacheAsync(string cacheKey, [CanBeNull] Tenant tenant) @@ -117,7 +117,7 @@ public class TenantStore : ITenantStore, ITransientDependency } } - throw new AbpException("Both id and name can't be invalid."); + throw new AbpException("Both id and normalizedName can't be invalid."); } [Obsolete("Use SetCacheAsync method.")] From 8810906cdcb2132fbc8df81a9d2894270e29c79c Mon Sep 17 00:00:00 2001 From: maliming Date: Wed, 20 Dec 2023 10:09:16 +0800 Subject: [PATCH 003/154] Update the migrations for template projects. --- ...tial.Designer.cs => 20231220020330_Initial.Designer.cs} | 7 ++++++- ...20231207053812_Initial.cs => 20231220020330_Initial.cs} | 1 + .../Migrations/MyProjectNameDbContextModelSnapshot.cs | 5 +++++ ...tial.Designer.cs => 20231220020415_Initial.Designer.cs} | 7 ++++++- .../Server/Migrations/20231220020415_Initial.cs} | 1 + .../Migrations/MyProjectNameDbContextModelSnapshot.cs | 5 +++++ ...tial.Designer.cs => 20231220020502_Initial.Designer.cs} | 7 ++++++- ...20231207053820_Initial.cs => 20231220020502_Initial.cs} | 1 + .../Migrations/MyProjectNameDbContextModelSnapshot.cs | 5 +++++ ...tial.Designer.cs => 20231220020554_Initial.Designer.cs} | 7 ++++++- ...20231207053825_Initial.cs => 20231220020554_Initial.cs} | 1 + .../Migrations/MyProjectNameDbContextModelSnapshot.cs | 5 +++++ ...tial.Designer.cs => 20231220020240_Initial.Designer.cs} | 7 ++++++- ...20231207053523_Initial.cs => 20231220020240_Initial.cs} | 1 + .../Migrations/MyProjectNameDbContextModelSnapshot.cs | 5 +++++ ...tial.Designer.cs => 20231220020703_Initial.Designer.cs} | 7 ++++++- .../Migrations/20231220020703_Initial.cs} | 1 + .../Migrations/AuthServerDbContextModelSnapshot.cs | 5 +++++ ...tial.Designer.cs => 20231220020754_Initial.Designer.cs} | 7 ++++++- ...20231115065621_Initial.cs => 20231220020754_Initial.cs} | 1 + .../Migrations/UnifiedDbContextModelSnapshot.cs | 5 +++++ ...tial.Designer.cs => 20231220020817_Initial.Designer.cs} | 7 ++++++- ...20231115065707_Initial.cs => 20231220020817_Initial.cs} | 1 + .../Migrations/UnifiedDbContextModelSnapshot.cs | 5 +++++ 24 files changed, 96 insertions(+), 8 deletions(-) rename templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/{20231207053812_Initial.Designer.cs => 20231220020330_Initial.Designer.cs} (99%) rename templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/{20231207053812_Initial.cs => 20231220020330_Initial.cs} (99%) rename templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/{20231207053830_Initial.Designer.cs => 20231220020415_Initial.Designer.cs} (99%) rename templates/{module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20231207053828_Initial.cs => app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20231220020415_Initial.cs} (99%) rename templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/{20231207053820_Initial.Designer.cs => 20231220020502_Initial.Designer.cs} (99%) rename templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/{20231207053820_Initial.cs => 20231220020502_Initial.cs} (99%) rename templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/{20231207053825_Initial.Designer.cs => 20231220020554_Initial.Designer.cs} (99%) rename templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/{20231207053825_Initial.cs => 20231220020554_Initial.cs} (99%) rename templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/{20231207053523_Initial.Designer.cs => 20231220020240_Initial.Designer.cs} (99%) rename templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/{20231207053523_Initial.cs => 20231220020240_Initial.cs} (99%) rename templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/{20231207053828_Initial.Designer.cs => 20231220020703_Initial.Designer.cs} (99%) rename templates/{app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20231207053830_Initial.cs => module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20231220020703_Initial.cs} (99%) rename templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/{20231115065621_Initial.Designer.cs => 20231220020754_Initial.Designer.cs} (99%) rename templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/{20231115065621_Initial.cs => 20231220020754_Initial.cs} (99%) rename templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/{20231115065707_Initial.Designer.cs => 20231220020817_Initial.Designer.cs} (99%) rename templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/{20231115065707_Initial.cs => 20231220020817_Initial.cs} (99%) diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20231207053812_Initial.Designer.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20231220020330_Initial.Designer.cs similarity index 99% rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20231207053812_Initial.Designer.cs rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20231220020330_Initial.Designer.cs index 333df53077..b6afd36542 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20231207053812_Initial.Designer.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20231220020330_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Blazor.Server.Migrations { [DbContext(typeof(MyProjectNameDbContext))] - [Migration("20231207053812_Initial")] + [Migration("20231220020330_Initial")] partial class Initial { /// @@ -1687,6 +1687,11 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Migrations .HasMaxLength(64) .HasColumnType("nvarchar(64)"); + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + b.HasKey("Id"); b.HasIndex("Name"); diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20231207053812_Initial.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20231220020330_Initial.cs similarity index 99% rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20231207053812_Initial.cs rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20231220020330_Initial.cs index e993702885..8ce8dba759 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20231207053812_Initial.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20231220020330_Initial.cs @@ -296,6 +296,7 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Migrations { Id = table.Column(type: "uniqueidentifier", nullable: false), Name = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), + NormalizedName = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), EntityVersion = table.Column(type: "int", nullable: false), ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false), diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/MyProjectNameDbContextModelSnapshot.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/MyProjectNameDbContextModelSnapshot.cs index 1def4a0ee9..d65c2397b7 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/MyProjectNameDbContextModelSnapshot.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/MyProjectNameDbContextModelSnapshot.cs @@ -1684,6 +1684,11 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Migrations .HasMaxLength(64) .HasColumnType("nvarchar(64)"); + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + b.HasKey("Id"); b.HasIndex("Name"); diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20231207053830_Initial.Designer.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20231220020415_Initial.Designer.cs similarity index 99% rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20231207053830_Initial.Designer.cs rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20231220020415_Initial.Designer.cs index ac18b045c6..83eb21746a 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20231207053830_Initial.Designer.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20231220020415_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Migrations { [DbContext(typeof(MyProjectNameDbContext))] - [Migration("20231207053830_Initial")] + [Migration("20231220020415_Initial")] partial class Initial { /// @@ -1687,6 +1687,11 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(64) .HasColumnType("nvarchar(64)"); + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + b.HasKey("Id"); b.HasIndex("Name"); diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20231207053828_Initial.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20231220020415_Initial.cs similarity index 99% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20231207053828_Initial.cs rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20231220020415_Initial.cs index 7a0019fbf6..da36f3081f 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20231207053828_Initial.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20231220020415_Initial.cs @@ -296,6 +296,7 @@ namespace MyCompanyName.MyProjectName.Migrations { Id = table.Column(type: "uniqueidentifier", nullable: false), Name = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), + NormalizedName = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), EntityVersion = table.Column(type: "int", nullable: false), ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false), diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/MyProjectNameDbContextModelSnapshot.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/MyProjectNameDbContextModelSnapshot.cs index 20542b282c..3c61917830 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/MyProjectNameDbContextModelSnapshot.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/MyProjectNameDbContextModelSnapshot.cs @@ -1684,6 +1684,11 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(64) .HasColumnType("nvarchar(64)"); + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + b.HasKey("Id"); b.HasIndex("Name"); diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20231207053820_Initial.Designer.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20231220020502_Initial.Designer.cs similarity index 99% rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20231207053820_Initial.Designer.cs rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20231220020502_Initial.Designer.cs index 333258a426..249957c93c 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20231207053820_Initial.Designer.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20231220020502_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Host.Migrations { [DbContext(typeof(MyProjectNameDbContext))] - [Migration("20231207053820_Initial")] + [Migration("20231220020502_Initial")] partial class Initial { /// @@ -1687,6 +1687,11 @@ namespace MyCompanyName.MyProjectName.Host.Migrations .HasMaxLength(64) .HasColumnType("nvarchar(64)"); + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + b.HasKey("Id"); b.HasIndex("Name"); diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20231207053820_Initial.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20231220020502_Initial.cs similarity index 99% rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20231207053820_Initial.cs rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20231220020502_Initial.cs index 08eca1feca..ace742cda5 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20231207053820_Initial.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20231220020502_Initial.cs @@ -296,6 +296,7 @@ namespace MyCompanyName.MyProjectName.Host.Migrations { Id = table.Column(type: "uniqueidentifier", nullable: false), Name = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), + NormalizedName = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), EntityVersion = table.Column(type: "int", nullable: false), ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false), diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/MyProjectNameDbContextModelSnapshot.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/MyProjectNameDbContextModelSnapshot.cs index 6475d362fa..a972acadeb 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/MyProjectNameDbContextModelSnapshot.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/MyProjectNameDbContextModelSnapshot.cs @@ -1684,6 +1684,11 @@ namespace MyCompanyName.MyProjectName.Host.Migrations .HasMaxLength(64) .HasColumnType("nvarchar(64)"); + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + b.HasKey("Id"); b.HasIndex("Name"); diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20231207053825_Initial.Designer.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20231220020554_Initial.Designer.cs similarity index 99% rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20231207053825_Initial.Designer.cs rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20231220020554_Initial.Designer.cs index 11234086f3..143044a16c 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20231207053825_Initial.Designer.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20231220020554_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Mvc.Migrations { [DbContext(typeof(MyProjectNameDbContext))] - [Migration("20231207053825_Initial")] + [Migration("20231220020554_Initial")] partial class Initial { /// @@ -1687,6 +1687,11 @@ namespace MyCompanyName.MyProjectName.Mvc.Migrations .HasMaxLength(64) .HasColumnType("nvarchar(64)"); + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + b.HasKey("Id"); b.HasIndex("Name"); diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20231207053825_Initial.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20231220020554_Initial.cs similarity index 99% rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20231207053825_Initial.cs rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20231220020554_Initial.cs index ef1ec2fdd6..32fb8b2358 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20231207053825_Initial.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20231220020554_Initial.cs @@ -296,6 +296,7 @@ namespace MyCompanyName.MyProjectName.Mvc.Migrations { Id = table.Column(type: "uniqueidentifier", nullable: false), Name = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), + NormalizedName = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), EntityVersion = table.Column(type: "int", nullable: false), ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false), diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/MyProjectNameDbContextModelSnapshot.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/MyProjectNameDbContextModelSnapshot.cs index 1e8916ad04..bab3848fb5 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/MyProjectNameDbContextModelSnapshot.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/MyProjectNameDbContextModelSnapshot.cs @@ -1684,6 +1684,11 @@ namespace MyCompanyName.MyProjectName.Mvc.Migrations .HasMaxLength(64) .HasColumnType("nvarchar(64)"); + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + b.HasKey("Id"); b.HasIndex("Name"); diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20231207053523_Initial.Designer.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20231220020240_Initial.Designer.cs similarity index 99% rename from templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20231207053523_Initial.Designer.cs rename to templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20231220020240_Initial.Designer.cs index c52403afd3..cddfa265f4 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20231207053523_Initial.Designer.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20231220020240_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Migrations { [DbContext(typeof(MyProjectNameDbContext))] - [Migration("20231207053523_Initial")] + [Migration("20231220020240_Initial")] partial class Initial { /// @@ -1739,6 +1739,11 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(64) .HasColumnType("nvarchar(64)"); + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + b.HasKey("Id"); b.HasIndex("Name"); diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20231207053523_Initial.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20231220020240_Initial.cs similarity index 99% rename from templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20231207053523_Initial.cs rename to templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20231220020240_Initial.cs index a5027f58de..6c052b9dea 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20231207053523_Initial.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20231220020240_Initial.cs @@ -317,6 +317,7 @@ namespace MyCompanyName.MyProjectName.Migrations { Id = table.Column(type: "uniqueidentifier", nullable: false), Name = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), + NormalizedName = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), EntityVersion = table.Column(type: "int", nullable: false), ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false), diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/MyProjectNameDbContextModelSnapshot.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/MyProjectNameDbContextModelSnapshot.cs index 8a0febed15..17dcf3ad28 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/MyProjectNameDbContextModelSnapshot.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/MyProjectNameDbContextModelSnapshot.cs @@ -1736,6 +1736,11 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(64) .HasColumnType("nvarchar(64)"); + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + b.HasKey("Id"); b.HasIndex("Name"); diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20231207053828_Initial.Designer.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20231220020703_Initial.Designer.cs similarity index 99% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20231207053828_Initial.Designer.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20231220020703_Initial.Designer.cs index 389a2a8cc3..5b9f7049d4 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20231207053828_Initial.Designer.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20231220020703_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Migrations { [DbContext(typeof(AuthServerDbContext))] - [Migration("20231207053828_Initial")] + [Migration("20231220020703_Initial")] partial class Initial { /// @@ -1687,6 +1687,11 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(64) .HasColumnType("nvarchar(64)"); + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + b.HasKey("Id"); b.HasIndex("Name"); diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20231207053830_Initial.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20231220020703_Initial.cs similarity index 99% rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20231207053830_Initial.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20231220020703_Initial.cs index 7a0019fbf6..da36f3081f 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20231207053830_Initial.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20231220020703_Initial.cs @@ -296,6 +296,7 @@ namespace MyCompanyName.MyProjectName.Migrations { Id = table.Column(type: "uniqueidentifier", nullable: false), Name = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), + NormalizedName = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), EntityVersion = table.Column(type: "int", nullable: false), ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false), diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/AuthServerDbContextModelSnapshot.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/AuthServerDbContextModelSnapshot.cs index c63e7d13e1..780558fcbc 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/AuthServerDbContextModelSnapshot.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/AuthServerDbContextModelSnapshot.cs @@ -1684,6 +1684,11 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(64) .HasColumnType("nvarchar(64)"); + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + b.HasKey("Id"); b.HasIndex("Name"); diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20231115065621_Initial.Designer.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20231220020754_Initial.Designer.cs similarity index 99% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20231115065621_Initial.Designer.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20231220020754_Initial.Designer.cs index 86eca8fe53..cd7ee4b230 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20231115065621_Initial.Designer.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20231220020754_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Blazor.Server.Host.Migrations { [DbContext(typeof(UnifiedDbContext))] - [Migration("20231115065621_Initial")] + [Migration("20231220020754_Initial")] partial class Initial { /// @@ -1328,6 +1328,11 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Host.Migrations .HasMaxLength(64) .HasColumnType("nvarchar(64)"); + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + b.HasKey("Id"); b.HasIndex("Name"); diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20231115065621_Initial.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20231220020754_Initial.cs similarity index 99% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20231115065621_Initial.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20231220020754_Initial.cs index b21456cc73..6e5ae88b9f 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20231115065621_Initial.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20231220020754_Initial.cs @@ -296,6 +296,7 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Host.Migrations { Id = table.Column(type: "uniqueidentifier", nullable: false), Name = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), + NormalizedName = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), EntityVersion = table.Column(type: "int", nullable: false), ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false), diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/UnifiedDbContextModelSnapshot.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/UnifiedDbContextModelSnapshot.cs index 92a676f756..c32f89f163 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/UnifiedDbContextModelSnapshot.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/UnifiedDbContextModelSnapshot.cs @@ -1325,6 +1325,11 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Host.Migrations .HasMaxLength(64) .HasColumnType("nvarchar(64)"); + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + b.HasKey("Id"); b.HasIndex("Name"); diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20231115065707_Initial.Designer.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20231220020817_Initial.Designer.cs similarity index 99% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20231115065707_Initial.Designer.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20231220020817_Initial.Designer.cs index 16bf3345ff..ad8d576878 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20231115065707_Initial.Designer.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20231220020817_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Migrations { [DbContext(typeof(UnifiedDbContext))] - [Migration("20231115065707_Initial")] + [Migration("20231220020817_Initial")] partial class Initial { /// @@ -1328,6 +1328,11 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(64) .HasColumnType("nvarchar(64)"); + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + b.HasKey("Id"); b.HasIndex("Name"); diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20231115065707_Initial.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20231220020817_Initial.cs similarity index 99% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20231115065707_Initial.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20231220020817_Initial.cs index d19146cde5..695c5fc0ac 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20231115065707_Initial.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20231220020817_Initial.cs @@ -296,6 +296,7 @@ namespace MyCompanyName.MyProjectName.Migrations { Id = table.Column(type: "uniqueidentifier", nullable: false), Name = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), + NormalizedName = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), EntityVersion = table.Column(type: "int", nullable: false), ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false), diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/UnifiedDbContextModelSnapshot.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/UnifiedDbContextModelSnapshot.cs index 56d7b7e9bd..bb83f23368 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/UnifiedDbContextModelSnapshot.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/UnifiedDbContextModelSnapshot.cs @@ -1325,6 +1325,11 @@ namespace MyCompanyName.MyProjectName.Migrations .HasMaxLength(64) .HasColumnType("nvarchar(64)"); + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + b.HasKey("Id"); b.HasIndex("Name"); From 1c72ce1a3a361999dfd4bb9613f6b7cbf75bff2d Mon Sep 17 00:00:00 2001 From: Salih Date: Sat, 23 Dec 2023 20:05:54 +0300 Subject: [PATCH 004/154] add localizations --- .../Admin/Localization/Resources/en.json | 25 ++++++++++++++++++- .../Commercial/Localization/Resources/en.json | 18 ++++++++++++- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json index e2563fe684..e88dc12207 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json @@ -562,6 +562,29 @@ "SponsorLogo": "Sponsor Logo", "RegistrationUrl": "Registration Url", "AllowAbpStudioBetaAccess": "Allow ABP Studio Beta Access", - "TotalQuestionCanNotBeNullMessage": "Total Question can not be null" + "TotalQuestionCanNotBeNullMessage": "Total Question can not be null", + "Permission:OrganizationAutoRenewalPayments": "Organization Auto Renewal Payments", + "Permission:RetryFailedPayments": "Retry Failed Payments", + "AutoRenewalIsNotEnabled": "Auto Renewal is not enabled!", + "LicenseIsNotExpired": "License is not expired!", + "PaymentNotFound": "Payment not found!", + "PaymentAlreadyTried": "Payment already tried!", + "PaymentIsNotFailed": "Payment is not failed!", + "OrganizationIdIsNull": "OrganizationId is null!", + "Menu:OrganizationAutoRenewalPayments": "Organization Auto Renewal Payments", + "OrganizationAutoRenewalPayments": "Organization Auto Renewal Payments", + "PaymentDate": "Payment Date", + "TryCount": "Try Count", + "ErrorMessage": "Error Message", + "ErrorCode": "Error Code", + "CreditCard": "Credit Card", + "BuyerName": "Buyer Name", + "BuyerSurname": "Buyer Surname", + "BuyerEmail": "Buyer Email", + "AutoRenewalStartTime": "Auto Renewal Start Time", + "AutoRenewalEndTime": "Auto Renewal End Time", + "AutoRenewalEnabled": "Auto Renewal Enabled", + "LastAutoRenewalPaymentTime": "Last Auto Renewal Payment Time", + "OrganizationDoesNotHaveACreditCard": "Organization does not have a credit card!", } } diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json index 23e81238cd..217ca0fb34 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json @@ -1089,6 +1089,22 @@ "MultipleOrganizationInfo": "See All Your Organizations", "AbpStudioBetaAccessInfoTitle": "ABP Studio Beta Access", "AbpStudioBetaAccessInfoText": "We're thrilled to share with you the beta version of ABP Studio! This release marks a significant milestone in our development journey, and we're eager to gather your feedback to make the application even better.", - "YouAreNotAuthorizedToDownloadStudio": "You are not authorized to download ABP Studio." + "YouAreNotAuthorizedToDownloadStudio": "You are not authorized to download ABP Studio.", + "OrganizationHasNoDefaultCreditCard": "Your organization has no default credit card. Please add a credit card to your organization.", + "YouAreNotAuthorizedToPayThisPaymentRequest": "You are not authorized to pay this payment request.", + "YouAreNotAuthorizedToCreateBillingInfoForThisPaymentRequest": "You are not authorized to create billing info for this payment request.", + "OrganizationNotFound": "Organization not found.", + "CannotDeleteDefaultCardBecauseAutoRenewalEnabled": "You cannot delete this card because it is your default card and you have auto renewal enabled. Please disable auto renewal first.", + "AreYouSureWantToDeleteThisCard": "Are you sure you want to delete this card?", + "AreYouSureWantToSetThisCardAsDefault": "Are you sure you want to set this card as default?", + "OrganizationBillingInfoIsNotSuitableForIyzicoPayment": "Your organization's billing info is not suitable for iyzico payment.", + "AutomaticRenewal": "Automatic Renewal", + "AutomaticRenewal_Description": "Renewing a license before it expires lets you get a discount of up to %40. The auto-renewal process lets you renew your license without losing this discount, and your development will never interrupt. Auto-renewal is only available for credit cards. You can disable auto-renewal at any time by accessing your Organization Management page. ABP.io does not save your credit card information, but our global payment gateways do secure savings.", + "CardNotFoundMessage": "Do you want to add a new card?", + "CardNotFoundTitle": "Card Not Found", + "AutoRenewalEnabled": "Auto Renewal Enabled", + "AutoRenewalDisabled": "Auto Renewal Disabled", + "PaymentRequestIdIsNotProvided": "Payment request id is not provided.", + } } From 804fe525ad001781fbceaeeadd149f951814d66b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sinan=20=C3=96zt=C3=BCrk?= Date: Fri, 29 Dec 2023 13:05:33 +0300 Subject: [PATCH 005/154] vs-internal/issue-3466 ui improvements --- .../tree/src/lib/components/tree.component.scss | 4 ++++ .../feature-management-tab.component.html | 7 +++++-- .../feature-management.component.html | 2 +- .../email-setting-group.component.html | 10 +++++----- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/npm/ng-packs/packages/components/tree/src/lib/components/tree.component.scss b/npm/ng-packs/packages/components/tree/src/lib/components/tree.component.scss index d303c61d22..49b8a61e7f 100644 --- a/npm/ng-packs/packages/components/tree/src/lib/components/tree.component.scss +++ b/npm/ng-packs/packages/components/tree/src/lib/components/tree.component.scss @@ -43,4 +43,8 @@ abp-tree .ant-tree { top: 1px; cursor: pointer; } + + .ant-tree-checkbox-inner{ + background-color: transparent; + } } diff --git a/npm/ng-packs/packages/feature-management/src/lib/components/feature-management-tab/feature-management-tab.component.html b/npm/ng-packs/packages/feature-management/src/lib/components/feature-management-tab/feature-management-tab.component.html index 38912f7caa..6688fc5511 100644 --- a/npm/ng-packs/packages/feature-management/src/lib/components/feature-management-tab/feature-management-tab.component.html +++ b/npm/ng-packs/packages/feature-management/src/lib/components/feature-management-tab/feature-management-tab.component.html @@ -1,7 +1,10 @@ -

{{ 'AbpFeatureManagement::ManageHostFeaturesText' | abpLocalization }}

+

{{ 'AbpFeatureManagement::Menu:FeatureManagement' | abpLocalization }}

+ +
+

{{ 'AbpFeatureManagement::ManageHostFeaturesText' | abpLocalization }}

diff --git a/npm/ng-packs/packages/feature-management/src/lib/components/feature-management/feature-management.component.html b/npm/ng-packs/packages/feature-management/src/lib/components/feature-management/feature-management.component.html index 2e4e28fea8..4dce1433e5 100644 --- a/npm/ng-packs/packages/feature-management/src/lib/components/feature-management/feature-management.component.html +++ b/npm/ng-packs/packages/feature-management/src/lib/components/feature-management/feature-management.component.html @@ -107,7 +107,7 @@ {{ description }} -
+
diff --git a/npm/ng-packs/packages/setting-management/config/src/lib/components/email-setting-group/email-setting-group.component.html b/npm/ng-packs/packages/setting-management/config/src/lib/components/email-setting-group/email-setting-group.component.html index 03aeb21708..ba9dca17a9 100644 --- a/npm/ng-packs/packages/setting-management/config/src/lib/components/email-setting-group/email-setting-group.component.html +++ b/npm/ng-packs/packages/setting-management/config/src/lib/components/email-setting-group/email-setting-group.component.html @@ -1,8 +1,8 @@

{{ 'AbpSettingManagement::Menu:Emailing' | abpLocalization }}

-
+
-
+
-
+
@@ -75,9 +75,9 @@
- +
- + +
- {{ diff --git a/npm/ng-packs/packages/tenant-management/src/lib/components/tenants/tenants.component.html b/npm/ng-packs/packages/tenant-management/src/lib/components/tenants/tenants.component.html index bb0a27a6b2..1be0edefbc 100644 --- a/npm/ng-packs/packages/tenant-management/src/lib/components/tenants/tenants.component.html +++ b/npm/ng-packs/packages/tenant-management/src/lib/components/tenants/tenants.component.html @@ -39,7 +39,7 @@ - {{ diff --git a/npm/ng-packs/packages/theme-basic/src/lib/components/account-layout/tenant-box/tenant-box.component.html b/npm/ng-packs/packages/theme-basic/src/lib/components/account-layout/tenant-box/tenant-box.component.html index 1804050cf8..9e1466310d 100644 --- a/npm/ng-packs/packages/theme-basic/src/lib/components/account-layout/tenant-box/tenant-box.component.html +++ b/npm/ng-packs/packages/theme-basic/src/lib/components/account-layout/tenant-box/tenant-box.component.html @@ -49,7 +49,7 @@ - '}(r),toastr.options.tapToDismiss=!1),r||(++e===(o=["My name is Inigo Montoya. You killed my father. Prepare to die!",'
',"Are you the six fingered man?","Inconceivable!","I do not think that means what you think it means.","Have fun storming the castle!"]).length&&(e=0),r=o[e]),$("#toastrOptions").text('Command: toastr["'+i+'"]("'+r+(c?'", "'+c:"")+'")\n\ntoastr.options = '+JSON.stringify(toastr.options,null,2));var y=toastr[i](r,c);t=y,void 0!==y&&(y.find("#okBtn").length&&y.delegate("#okBtn","click",(function(){alert("you clicked me. i was toast #"+v+". goodbye!"),y.remove()})),y.find("#surpriseBtn").length&&y.delegate("#surpriseBtn","click",(function(){alert("Surprise! you clicked me. i was toast #"+v+". You could perform an action here.")})),y.find(".clear").length&&y.delegate(".clear","click",(function(){toastr.clear(y,{force:!0})})))})),$("#clearlasttoast").click((function(){toastr.clear(t)})),$("#cleartoasts").click((function(){toastr.clear()}))}))}))}.apply(e,o),void 0===i||(t.exports=i)},782:(t,e,n)=>{var o,i;o=[n,e,n(971)],i=function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.clickOutside=void 0,e.clickOutside=function(t,e,o){void 0===o&&(o=[]),n.EventHandler.onDocument("click",(function(n){!t.contains(n.target)&&o.filter(Boolean).every((function(t){return!t.contains(n.target)}))&&e()}))}}.apply(e,o),void 0===i||(t.exports=i)},466:(t,e,n)=>{var o,i;o=[n,e,n(962)],i=function(t,e,n){"use strict";function o(t){var e=document.cookie.split(";").find((function(e){return e.trim().startsWith("".concat((0,n.withCookiePrefix)(t),"="))}));return e?e.split("=")[1]:""}function i(t){return localStorage.getItem((0,n.withLocalStoragePrefix)(t))}function r(t,e,o){void 0===o&&(o=365);var i=new Date;i.setTime(i.getTime()+24*o*60*60*1e3),document.cookie="".concat((0,n.withCookiePrefix)(t),"=").concat(e,";expires=").concat(i.toUTCString(),";path=/")}function c(t,e){localStorage.setItem((0,n.withLocalStoragePrefix)(t),e)}Object.defineProperty(e,"__esModule",{value:!0}),e.readFromLocalStorageOrCookie=e.readFromCookieOrLocalStorage=e.setCookieAndLocalStorage=e.setLocalStorage=e.setCookie=e.localStorageResolver=e.cookieResolver=void 0,e.cookieResolver=o,e.localStorageResolver=i,e.setCookie=r,e.setLocalStorage=c,e.setCookieAndLocalStorage=function(t,e,n){void 0===n&&(n=365),r(t,e,n),c(t,e)},e.readFromCookieOrLocalStorage=function(t){return o(t)||i(t)},e.readFromLocalStorageOrCookie=function(t){return i(t)||o(t)}}.apply(e,o),void 0===i||(t.exports=i)},971:function(t,e,n){var o,i=this&&this.__assign||function(){return i=Object.assign||function(t){for(var e,n=1,o=arguments.length;n{var o;o=function(t,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.getLastElement=void 0,e.getLastElement=function(t){if(t&&0!==t.length){var e=t.length-1;return t.find((function(t,n){return n===e}))}}}.apply(e,[n,e]),void 0===o||(t.exports=o)},660:function(t,e,n){var o,i,r=this&&this.__createBinding||(Object.create?function(t,e,n,o){void 0===o&&(o=n);var i=Object.getOwnPropertyDescriptor(e,n);i&&!("get"in i?!e.__esModule:i.writable||i.configurable)||(i={enumerable:!0,get:function(){return e[n]}}),Object.defineProperty(t,o,i)}:function(t,e,n,o){void 0===o&&(o=n),t[o]=e[n]}),c=this&&this.__exportStar||function(t,e){for(var n in t)"default"===n||Object.prototype.hasOwnProperty.call(e,n)||r(e,t,n)};o=[n,e,n(782),n(466),n(971),n(57),n(387),n(384),n(521),n(491)],i=function(t,e,n,o,i,r,a,s,u,l){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),c(n,e),c(o,e),c(i,e),c(r,e),c(a,e),c(s,e),c(u,e),c(l,e)}.apply(e,o),void 0===i||(t.exports=i)},57:(t,e,n)=>{var o;o=function(t,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.parseJson=void 0,e.parseJson=function(t,e){var n;try{n=JSON.parse(t)||e}catch(t){n=e}return n}}.apply(e,[n,e]),void 0===o||(t.exports=o)},387:function(t,e,n){var o,i=this&&this.__assign||function(){return i=Object.assign||function(t){for(var e,n=1,o=arguments.length;n{var o;o=function(t,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.replaceStyleWith=void 0,e.replaceStyleWith=function(t,e,n){var o=document.createElement("link");o.href=t,o.type="text/css",o.rel="stylesheet",o.id=e;var i=document.querySelector("#".concat(n));return i?i.parentNode.insertBefore(o,i):document.getElementsByTagName("head")[0].appendChild(o),o.onload=function(){i&&i.remove()},o}}.apply(e,[n,e]),void 0===o||(t.exports=o)},521:(t,e,n)=>{var o,i;o=[n,e,n(217)],i=function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.lpxToggle=e.LpxToggle=void 0;var o=function(){function t(){}return t.init=function(){document.querySelectorAll(".lpx-toggle").forEach((function(t){t.addEventListener("click",(function(){Array.from(t.parentElement.children).filter((function(e){return e!==t})).forEach((function(t){var e=document.querySelector("#".concat(t.dataset.lpxToggle));e&&e.classList.add("d-none")}));var e=document.querySelector("#".concat(t.dataset.lpxToggle));e&&e.classList.toggle("d-none")}))}))},t}();e.LpxToggle=o,e.lpxToggle=new o,n.init.push("LpxToggleInit",(function(){o.init()}))}.apply(e,o),void 0===i||(t.exports=i)},937:(t,e,n)=>{var o,i;o=[n,e,n(508)],i=function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.BaseSideMenu=e.SideMenuToggle=void 0;var o=function(){function t(t,e){this.el=t,this.sideMenu=e}return t.create=function(e){return new t(e.el.querySelector('[data-lpx-toggle="sidebar"]'),e)},t.prototype.withClickListener=function(t){return this.el&&this.el.addEventListener("click",t),this},t}();e.SideMenuToggle=o;var i="#lpx-wrapper",r="hover-trigger",c="side-menu-state",a=function(){function t(t){this._el=t,this.menuItems=[],this.createMenuItems(),this.highlightCurrentPage()}return Object.defineProperty(t.prototype,"el",{get:function(){return this._el},enumerable:!1,configurable:!0}),t.create=function(){return new t(document.querySelector("#lpx-sidebar")).withToggle()},t.prototype.withToggle=function(){return this.sideMenuToggle=o.create(this).withClickListener(this.toggleSidebarHover.bind(this)),this.loadMenuState(),this},t.prototype.highlightCurrentPage=function(){var t=function(t){var e=window.location.pathname,n=t.el.getAttribute("href");return new RegExp("(^/side-menu|/top-menu|/|)?".concat(n,"$"),"ig").test(e)};this.menuItems.forEach((function(e){return e.setSelectedRecursive(t)}))},t.prototype.toggleSidebarHover=function(){var t=document.querySelector(i);t&&t.classList.toggle(r);var e=t.classList.contains(r)?"1":"";(0,n.setCookieAndLocalStorage)(c,e)},t.prototype.createMenuItems=function(){var t=this;this.el.querySelectorAll(".outer-menu-item > .lpx-menu-item").forEach((function(e){var o=new n.MenuItem(e);t.menuItems.push(o)}))},t.prototype.loadMenuState=function(){if((0,n.readFromCookieOrLocalStorage)(c)){var t=document.querySelector(i);t&&t.classList.toggle(r)}},t}();e.BaseSideMenu=a}.apply(e,o),void 0===i||(t.exports=i)},370:function(t,e,n){var o,i,r=this&&this.__createBinding||(Object.create?function(t,e,n,o){void 0===o&&(o=n);var i=Object.getOwnPropertyDescriptor(e,n);i&&!("get"in i?!e.__esModule:i.writable||i.configurable)||(i={enumerable:!0,get:function(){return e[n]}}),Object.defineProperty(t,o,i)}:function(t,e,n,o){void 0===o&&(o=n),t[o]=e[n]}),c=this&&this.__exportStar||function(t,e){for(var n in t)"default"===n||Object.prototype.hasOwnProperty.call(e,n)||r(e,t,n)};o=[n,e,n(937)],i=function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),c(n,e)}.apply(e,o),void 0===i||(t.exports=i)},259:function(t,e,n){var o,i,r=this&&this.__createBinding||(Object.create?function(t,e,n,o){void 0===o&&(o=n);var i=Object.getOwnPropertyDescriptor(e,n);i&&!("get"in i?!e.__esModule:i.writable||i.configurable)||(i={enumerable:!0,get:function(){return e[n]}}),Object.defineProperty(t,o,i)}:function(t,e,n,o){void 0===o&&(o=n),t[o]=e[n]}),c=this&&this.__exportStar||function(t,e){for(var n in t)"default"===n||Object.prototype.hasOwnProperty.call(e,n)||r(e,t,n)};o=[n,e,n(23)],i=function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),c(n,e)}.apply(e,o),void 0===i||(t.exports=i)},23:function(t,e,n){var o,i,r,c=this&&this.__extends||(r=function(t,e){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n])},r(t,e)},function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Class extends value "+String(e)+" is not a constructor or null");function n(){this.constructor=t}r(t,e),t.prototype=null===e?Object.create(e):(n.prototype=e.prototype,new n)});o=[n,e,n(508),n(370)],i=function(t,e,n,o){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.sideMenu=void 0;var i=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return c(e,t),e}(o.BaseSideMenu);n.init.push("initSideMenu",(function(){document.querySelector("#lpx-sidebar")&&(e.sideMenu=i.create())}))}.apply(e,o),void 0===i||(t.exports=i)},931:function(t,e,n){var o,i,r=this&&this.__createBinding||(Object.create?function(t,e,n,o){void 0===o&&(o=n);var i=Object.getOwnPropertyDescriptor(e,n);i&&!("get"in i?!e.__esModule:i.writable||i.configurable)||(i={enumerable:!0,get:function(){return e[n]}}),Object.defineProperty(t,o,i)}:function(t,e,n,o){void 0===o&&(o=n),t[o]=e[n]}),c=this&&this.__exportStar||function(t,e){for(var n in t)"default"===n||Object.prototype.hasOwnProperty.call(e,n)||r(e,t,n)};o=[n,e,n(213),n(600)],i=function(t,e,n,o){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),c(n,e),c(o,e)}.apply(e,o),void 0===i||(t.exports=i)},213:(t,e,n)=>{var o,i;o=[n,e,n(508)],i=function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.LanguageSelection=void 0;var o="[data-lpx-language-option]",i="[data-lpx-language-selected]",r=function(){function t(t){this.el=t;var e=(0,n.readFromCookieOrLocalStorage)("lang");e?(this.selected=document.querySelector(i),this.updateSelectedText(e)):this.selected=document.querySelector(i)}return t.create=function(e){return new t(e).withClickListener().withLanguageDirectionListener()},t.prototype.withClickListener=function(){var t=this;return document.querySelectorAll(o).forEach((function(e){return n.EventHandler.on(e,"click",t.onLanguageOptionClick.bind(t))})),this},t.prototype.withLanguageDirectionListener=function(){return document.querySelectorAll(o).forEach((function(t){t.addEventListener("click",(function(e){var o=t.dataset.lpxLanguageDirection||"ltr",i=document.querySelector("html");if(i.dir!==o){i.dir=o,(0,n.setCookieAndLocalStorage)("lang-dir",o);var r=n.LanguageDirectionEvent.create(n.LanguageDirectionEvent,o);n.EventHandler.dispatch(e.target,r)}}))})),this},t.prototype.onLanguageOptionClick=function(t){var e=t.target;this.updateSelected(e.dataset.lpxLanguageOption)},t.prototype.updateSelected=function(t){n.EventHandler.dispatch(this.el,new n.LanguageSettingEvent(t))&&(this.updateSelectedText(t),(0,n.setCookieAndLocalStorage)("lang",t))},t.prototype.updateSelectedText=function(t){this.selected&&(this.selected.innerText=t,this.selected.dataset.lpxLanguageSelected=t)},t}();e.LanguageSelection=r,n.init.push("initLanguageSelection",(function(){document.querySelectorAll("[data-lpx-language-selection]").forEach(r.create)}))}.apply(e,o),void 0===i||(t.exports=i)},600:(t,e,n)=>{var o,i;o=[n,e,n(508)],i=function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),n.init.push("initMobileMenu",(function(){document.querySelectorAll("#mobile-sidebar > .outer-menu-item > .lpx-menu-item").forEach((function(t){return n.MenuItem.create(t)}))}))}.apply(e,o),void 0===i||(t.exports=i)},522:function(t,e,n){var o,i,r=this&&this.__createBinding||(Object.create?function(t,e,n,o){void 0===o&&(o=n);var i=Object.getOwnPropertyDescriptor(e,n);i&&!("get"in i?!e.__esModule:i.writable||i.configurable)||(i={enumerable:!0,get:function(){return e[n]}}),Object.defineProperty(t,o,i)}:function(t,e,n,o){void 0===o&&(o=n),t[o]=e[n]}),c=this&&this.__exportStar||function(t,e){for(var n in t)"default"===n||Object.prototype.hasOwnProperty.call(e,n)||r(e,t,n)};o=[n,e,n(931)],i=function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),c(n,e)}.apply(e,o),void 0===i||(t.exports=i)},685:t=>{"use strict";t.exports=bootstrap}},e={},n=function n(o){var i=e[o];if(void 0!==i)return i.exports;var r=e[o]={exports:{}};return t[o].call(r.exports,r,r.exports,n),r.exports}(507);leptonx=n})(); - +(function(n,t){typeof exports=="object"&&typeof module!="undefined"?module.exports=t():typeof define=="function"&&define.amd?define(t):(n=typeof globalThis!="undefined"?globalThis:n||self,n.bootstrap=t())})(this,function(){"use strict";function oe(n,t){return t&&`${t}::${fe++}`||n.uidEvent||fe++}function se(n){const t=oe(n);return n.uidEvent=t,su[t]=su[t]||{},su[t]}function yl(t,i){return function r(u){return u.delegateTarget=t,r.oneOff&&n.off(t,u.type,i),i.apply(t,[u])}}function pl(t,i,r){return function u(f){const e=t.querySelectorAll(i);for(let{target:o}=f;o&&o!==this;o=o.parentNode)for(let s=e.length;s--;)if(e[s]===o)return f.delegateTarget=o,u.oneOff&&n.off(t,f.type,i,r),r.apply(o,[f]);return null}}function he(n,t,i=null){const r=Object.keys(n);for(let u=0,f=r.length;ufunction(t){if(!t.relatedTarget||t.relatedTarget!==t.delegateTarget&&!t.delegateTarget.contains(t.relatedTarget))return n.call(this,t)};r?r=n(r):i=n(i)}const[e,o,s]=ce(t,i,r),c=se(n),l=c[s]||(c[s]={}),h=he(l,o,e?i:null);if(h){h.oneOff=h.oneOff&&u;return}const a=oe(o,t.replace(hl,"")),f=e?pl(n,i,r):yl(n,i);f.delegationSelector=e?i:null;f.originalHandler=o;f.oneOff=u;f.uidEvent=a;l[a]=f;n.addEventListener(s,f,e)}}function hu(n,t,i,r,u){const f=he(t[i],r,u);f&&(n.removeEventListener(i,f,Boolean(u)),delete t[i][f.uidEvent])}function wl(n,t,i,r){const u=t[i]||{};Object.keys(u).forEach(f=>{if(f.includes(r)){const r=u[f];hu(n,t,i,r.originalHandler,r.delegationSelector)}})}function ae(n){return n=n.replace(cl,""),al[n]||n}function pe(n){return n==="true"?!0:n==="false"?!1:n===Number(n).toString()?Number(n):n===""||n==="null"?null:n}function cu(n){return n.replace(/[A-Z]/g,n=>`-${n.toLowerCase()}`)}function w(n){return n?(n.nodeName||"").toLowerCase():null}function y(n){if(n==null)return window;if(n.toString()!=="[object Window]"){var t=n.ownerDocument;return t?t.defaultView||window:window}return n}function yi(n){var t=y(n).Element;return n instanceof t||n instanceof Element}function c(n){var t=y(n).HTMLElement;return n instanceof t||n instanceof HTMLElement}function wo(n){if(typeof ShadowRoot=="undefined")return!1;var t=y(n).ShadowRoot;return n instanceof t||n instanceof ShadowRoot}function oy(n){var t=n.state;Object.keys(t.elements).forEach(function(n){var u=t.styles[n]||{},r=t.attributes[n]||{},i=t.elements[n];c(i)&&w(i)&&(Object.assign(i.style,u),Object.keys(r).forEach(function(n){var t=r[n];t===!1?i.removeAttribute(n):i.setAttribute(n,t===!0?"":t)}))})}function sy(n){var t=n.state,i={popper:{position:t.options.strategy,left:"0",top:"0",margin:"0"},arrow:{position:"absolute"},reference:{}};return Object.assign(t.elements.popper.style,i.popper),t.styles=i,t.elements.arrow&&Object.assign(t.elements.arrow.style,i.arrow),function(){Object.keys(t.elements).forEach(function(n){var r=t.elements[n],u=t.attributes[n]||{},f=Object.keys(t.styles.hasOwnProperty(n)?t.styles[n]:i[n]),e=f.reduce(function(n,t){return n[t]="",n},{});c(r)&&w(r)&&(Object.assign(r.style,e),Object.keys(u).forEach(function(n){r.removeAttribute(n)}))})}}function b(n){return n.split("-")[0]}function ri(n){var t=n.getBoundingClientRect(),i=1,r=1;return{width:t.width/i,height:t.height/r,top:t.top/r,right:t.right/i,bottom:t.bottom/r,left:t.left/i,x:t.left/i,y:t.top/r}}function bu(n){var t=ri(n),i=n.offsetWidth,r=n.offsetHeight;return Math.abs(t.width-i)<=1&&(i=t.width),Math.abs(t.height-r)<=1&&(r=t.height),{x:n.offsetLeft,y:n.offsetTop,width:i,height:r}}function bo(n,t){var r=t.getRootNode&&t.getRootNode(),i;if(n.contains(t))return!0;if(r&&wo(r)){i=t;do{if(i&&n.isSameNode(i))return!0;i=i.parentNode||i.host}while(i)}return!1}function nt(n){return y(n).getComputedStyle(n)}function hy(n){return["table","td","th"].indexOf(w(n))>=0}function ut(n){return((yi(n)?n.ownerDocument:n.document)||window.document).documentElement}function ar(n){return w(n)==="html"?n:n.assignedSlot||n.parentNode||(wo(n)?n.host:null)||ut(n)}function ko(n){return!c(n)||nt(n).position==="fixed"?null:n.offsetParent}function cy(n){var r=navigator.userAgent.toLowerCase().indexOf("firefox")!==-1,f=navigator.userAgent.indexOf("Trident")!==-1,u,i,t;if(f&&c(n)&&(u=nt(n),u.position==="fixed"))return null;for(i=ar(n);c(i)&&["html","body"].indexOf(w(i))<0;){if(t=nt(i),t.transform!=="none"||t.perspective!=="none"||t.contain==="paint"||["transform","perspective"].indexOf(t.willChange)!==-1||r&&t.willChange==="filter"||r&&t.filter&&t.filter!=="none")return i;i=i.parentNode}return null}function pi(n){for(var i=y(n),t=ko(n);t&&hy(t)&&nt(t).position==="static";)t=ko(t);return t&&(w(t)==="html"||w(t)==="body"&&nt(t).position==="static")?i:t||cy(n)||i}function ku(n){return["top","bottom"].indexOf(n)>=0?"x":"y"}function yr(n,t,i){return ft(n,wi(t,i))}function go(){return{top:0,right:0,bottom:0,left:0}}function ns(n){return Object.assign({},go(),n)}function ts(n,t){return t.reduce(function(t,i){return t[i]=n,t},{})}function ly(n){var r,t=n.state,d=n.name,g=n.options,h=t.elements.arrow,c=t.modifiersData.popperOffsets,a=b(t.placement),i=ku(a),nt=[f,s].indexOf(a)>=0,e=nt?"height":"width";if(h&&c){var v=is(g.padding,t),y=bu(h),tt=i==="y"?u:f,it=i==="y"?o:s,rt=t.rects.reference[e]+t.rects.reference[i]-c[i]-t.rects.popper[e],ut=c[i]-t.rects.reference[i],l=pi(h),p=l?i==="y"?l.clientHeight||0:l.clientWidth||0:0,ft=rt/2-ut/2,et=v[tt],ot=p-y[e]-v[it],w=p/2-y[e]/2+ft,k=yr(et,w,ot),st=i;t.modifiersData[d]=(r={},r[st]=k,r.centerOffset=k-w,r)}}function ay(n){var i=n.state,u=n.options,r=u.element,t=r===void 0?"[data-popper-arrow]":r;t!=null&&(typeof t!="string"||(t=i.elements.popper.querySelector(t),t))&&bo(i.elements.popper,t)&&(i.elements.arrow=t)}function ui(n){return n.split("-")[1]}function vy(n){var i=n.x,r=n.y,u=window,t=u.devicePixelRatio||1;return{x:vr(vr(i*t)/t)||0,y:vr(vr(r*t)/t)||0}}function fs(n){var r,a=n.popper,d=n.popperRect,i=n.placement,g=n.variation,e=n.offsets,tt=n.position,v=n.gpuAcceleration,it=n.adaptive,p=n.roundOffsets,rt=p===!0?vy(e):typeof p=="function"?p(e):e,ft=rt.x,h=ft===void 0?0:ft,et=rt.y,c=et===void 0?0:et,ot=e.hasOwnProperty("x"),st=e.hasOwnProperty("y"),w=f,b=u,lt=window,k,l;if(it){var t=pi(a),ht="clientHeight",ct="clientWidth";t===y(a)&&(t=ut(a),nt(t).position!=="static"&&tt==="absolute"&&(ht="scrollHeight",ct="scrollWidth"));t=t;(i===u||(i===f||i===s)&&g===ti)&&(b=o,c-=t[ht]-d.height,c*=v?1:-1);(i===f||(i===u||i===o)&&g===ti)&&(w=s,h-=t[ct]-d.width,h*=v?1:-1)}return(k=Object.assign({position:tt},it&&us),v)?Object.assign({},k,(l={},l[b]=st?"0":"",l[w]=ot?"0":"",l.transform=(lt.devicePixelRatio||1)<=1?"translate("+h+"px, "+c+"px)":"translate3d("+h+"px, "+c+"px, 0)",l)):Object.assign({},k,(r={},r[b]=st?c+"px":"",r[w]=ot?h+"px":"",r.transform="",r))}function yy(n){var t=n.state,i=n.options,r=i.gpuAcceleration,s=r===void 0?!0:r,u=i.adaptive,h=u===void 0?!0:u,f=i.roundOffsets,e=f===void 0?!0:f,o={placement:b(t.placement),variation:ui(t.placement),popper:t.elements.popper,popperRect:t.rects.popper,gpuAcceleration:s};t.modifiersData.popperOffsets!=null&&(t.styles.popper=Object.assign({},t.styles.popper,fs(Object.assign({},o,{offsets:t.modifiersData.popperOffsets,position:t.options.strategy,adaptive:h,roundOffsets:e}))));t.modifiersData.arrow!=null&&(t.styles.arrow=Object.assign({},t.styles.arrow,fs(Object.assign({},o,{offsets:t.modifiersData.arrow,position:"absolute",adaptive:!1,roundOffsets:e}))));t.attributes.popper=Object.assign({},t.attributes.popper,{"data-popper-placement":t.placement})}function py(n){var i=n.state,t=n.instance,r=n.options,u=r.scroll,f=u===void 0?!0:u,e=r.resize,o=e===void 0?!0:e,s=y(i.elements.popper),h=[].concat(i.scrollParents.reference,i.scrollParents.popper);return f&&h.forEach(function(n){n.addEventListener("scroll",t.update,bi)}),o&&s.addEventListener("resize",t.update,bi),function(){f&&h.forEach(function(n){n.removeEventListener("scroll",t.update,bi)});o&&s.removeEventListener("resize",t.update,bi)}}function pr(n){return n.replace(/left|right|bottom|top/g,function(n){return es[n]})}function ss(n){return n.replace(/start|end/g,function(n){return os[n]})}function nf(n){var t=y(n),i=t.pageXOffset,r=t.pageYOffset;return{scrollLeft:i,scrollTop:r}}function tf(n){return ri(ut(n)).left+nf(n).scrollLeft}function wy(n){var o=y(n),i=ut(n),t=o.visualViewport,r=i.clientWidth,u=i.clientHeight,f=0,e=0;return t&&(r=t.width,u=t.height,/^((?!chrome|android).)*safari/i.test(navigator.userAgent)||(f=t.offsetLeft,e=t.offsetTop)),{width:r,height:u,x:f+tf(n),y:e}}function by(n){var r,i=ut(n),u=nf(n),t=(r=n.ownerDocument)==null?void 0:r.body,f=ft(i.scrollWidth,i.clientWidth,t?t.scrollWidth:0,t?t.clientWidth:0),o=ft(i.scrollHeight,i.clientHeight,t?t.scrollHeight:0,t?t.clientHeight:0),e=-u.scrollLeft+tf(n),s=-u.scrollTop;return nt(t||i).direction==="rtl"&&(e+=ft(i.clientWidth,t?t.clientWidth:0)-f),{width:f,height:o,x:e,y:s}}function rf(n){var t=nt(n),i=t.overflow,r=t.overflowX,u=t.overflowY;return/auto|scroll|overlay|hidden/.test(i+u+r)}function hs(n){return["html","body","#document"].indexOf(w(n))>=0?n.ownerDocument.body:c(n)&&rf(n)?n:hs(ar(n))}function ki(n,t){var r;t===void 0&&(t=[]);var i=hs(n),u=i===((r=n.ownerDocument)==null?void 0:r.body),f=y(i),e=u?[f].concat(f.visualViewport||[],rf(i)?i:[]):i,o=t.concat(e);return u?o:o.concat(ki(ar(e)))}function uf(n){return Object.assign({},n,{left:n.x,top:n.y,right:n.x+n.width,bottom:n.y+n.height})}function ky(n){var t=ri(n);return t.top=t.top+n.clientTop,t.left=t.left+n.clientLeft,t.bottom=t.top+n.clientHeight,t.right=t.left+n.clientWidth,t.width=n.clientWidth,t.height=n.clientHeight,t.x=t.left,t.y=t.top,t}function cs(n,t){return t===vu?uf(wy(n)):c(t)?ky(t):uf(by(ut(n)))}function dy(n){var i=ki(ar(n)),r=["absolute","fixed"].indexOf(nt(n).position)>=0,t=r&&c(n)?pi(n):n;return yi(t)?i.filter(function(n){return yi(n)&&bo(n,t)&&w(n)!=="body"}):[]}function gy(n,t,i){var f=t==="clippingParents"?dy(n):[].concat(t),u=[].concat(f,[i]),e=u[0],r=u.reduce(function(t,i){var r=cs(n,i);return t.top=ft(r.top,t.top),t.right=wi(r.right,t.right),t.bottom=wi(r.bottom,t.bottom),t.left=ft(r.left,t.left),t},cs(n,e));return r.width=r.right-r.left,r.height=r.bottom-r.top,r.x=r.left,r.y=r.top,r}function ls(n){var t=n.reference,e=n.element,c=n.placement,l=c?b(c):null,y=c?ui(c):null,a=t.x+t.width/2-e.width/2,v=t.y+t.height/2-e.height/2,i,r,h;switch(l){case u:i={x:a,y:t.y-e.height};break;case o:i={x:a,y:t.y+t.height};break;case s:i={x:t.x+t.width,y:v};break;case f:i={x:t.x-e.width,y:v};break;default:i={x:t.x,y:t.y}}if(r=l?ku(l):null,r!=null){h=r==="y"?"height":"width";switch(y){case yt:i[r]=i[r]-(t[h]/2-e[h]/2);break;case ti:i[r]=i[r]+(t[h]/2-e[h]/2)}}return i}function fi(n,t){var it;t===void 0&&(t={});var i=t,v=i.placement,y=v===void 0?n.placement:v,p=i.boundary,rt=p===void 0?uo:p,w=i.rootBoundary,ft=w===void 0?vu:w,b=i.elementContext,r=b===void 0?ii:b,k=i.altBoundary,et=k===void 0?!1:k,d=i.padding,c=d===void 0?0:d,f=ns(typeof c!="number"?c:ts(c,ni)),ot=r===ii?fo:ii,g=n.rects.popper,l=n.elements[et?ot:r],e=gy(yi(l)?l:l.contextElement||ut(n.elements.popper),rt,ft),nt=ri(n.elements.reference),st=ls({reference:nt,element:g,strategy:"absolute",placement:y}),ht=uf(Object.assign({},g,st)),h=r===ii?ht:nt,a={top:e.top-h.top+f.top,bottom:h.bottom-e.bottom+f.bottom,left:e.left-h.left+f.left,right:h.right-e.right+f.right},tt=n.modifiersData.offset;return r===ii&&tt&&(it=tt[y],Object.keys(a).forEach(function(n){var t=[s,o].indexOf(n)>=0?1:-1,i=[u,o].indexOf(n)>=0?"y":"x";a[n]+=it[i]*t})),a}function np(n,t){var r;t===void 0&&(t={});var i=t,s=i.placement,h=i.boundary,c=i.rootBoundary,l=i.padding,a=i.flipVariations,f=i.allowedAutoPlacements,v=f===void 0?pu:f,e=ui(s),o=e?a?yu:yu.filter(function(n){return ui(n)===e}):ni,u=o.filter(function(n){return v.indexOf(n)>=0});return u.length===0&&(u=o),r=u.reduce(function(t,i){return t[i]=fi(n,{placement:i,boundary:h,rootBoundary:c,padding:l})[b(i)],t},{}),Object.keys(r).sort(function(n,t){return r[n]-r[t]})}function tp(n){if(b(n)===lr)return[];var t=pr(n);return[ss(n),t,ss(t)]}function ip(n){var t=n.state,i=n.options,k=n.name,a,ct,h,lt,at,y,vt;if(!t.modifiersData[k]._skip){var d=i.mainAxis,pt=d===void 0?!0:d,g=i.altAxis,wt=g===void 0?!0:g,bt=i.fallbackPlacements,nt=i.padding,tt=i.boundary,it=i.rootBoundary,kt=i.altBoundary,rt=i.flipVariations,p=rt===void 0?!0:rt,dt=i.allowedAutoPlacements,r=t.options.placement,gt=b(r),ni=gt===r,ti=bt||(ni||!p?[pr(r)]:tp(r)),c=[r].concat(ti).reduce(function(n,i){return n.concat(b(i)===lr?np(t,{placement:i,boundary:tt,rootBoundary:it,padding:nt,flipVariations:p,allowedAutoPlacements:dt}):i)},[]),ii=t.rects.reference,ri=t.rects.popper,ut=new Map,ft=!0,l=c[0];for(a=0;a=0,ht=st?"width":"height",w=fi(t,{placement:e,boundary:tt,rootBoundary:it,altBoundary:kt,padding:nt}),v=st?ot?s:f:ot?o:u;if(ii[ht]>ri[ht]&&(v=pr(v)),ct=pr(v),h=[],pt&&h.push(w[et]<=0),wt&&h.push(w[v]<=0,w[ct]<=0),h.every(function(n){return n})){l=e;ft=!1;break}ut.set(e,h)}if(ft)for(lt=p?3:1,at=function(n){var t=c.find(function(t){var i=ut.get(t);if(i)return i.slice(0,n).every(function(n){return n})});if(t)return l=t,"break"},y=lt;y>0;y--)if(vt=at(y),vt==="break")break;t.placement!==l&&(t.modifiersData[k]._skip=!0,t.placement=l,t.reset=!0)}}function vs(n,t,i){return i===void 0&&(i={x:0,y:0}),{top:n.top-t.height-i.y,right:n.right-t.width+i.x,bottom:n.bottom-t.height+i.y,left:n.left-t.width-i.x}}function ys(n){return[u,s,o,f].some(function(t){return n[t]>=0})}function rp(n){var t=n.state,e=n.name,o=t.rects.reference,s=t.rects.popper,h=t.modifiersData.preventOverflow,c=fi(t,{elementContext:"reference"}),l=fi(t,{altBoundary:!0}),i=vs(c,o),r=vs(l,s,h),u=ys(i),f=ys(r);t.modifiersData[e]={referenceClippingOffsets:i,popperEscapeOffsets:r,isReferenceHidden:u,hasPopperEscaped:f};t.attributes.popper=Object.assign({},t.attributes.popper,{"data-popper-reference-hidden":u,"data-popper-escaped":f})}function up(n,t,i){var o=b(n),c=[f,u].indexOf(o)>=0?-1:1,h=typeof i=="function"?i(Object.assign({},t,{placement:n})):i,r=h[0],e=h[1];return r=r||0,e=(e||0)*c,[f,s].indexOf(o)>=0?{x:e,y:r}:{x:r,y:e}}function fp(n){var t=n.state,f=n.options,e=n.name,i=f.offset,o=i===void 0?[0,0]:i,r=pu.reduce(function(n,i){return n[i]=up(i,t.rects,o),n},{}),u=r[t.placement],s=u.x,h=u.y;t.modifiersData.popperOffsets!=null&&(t.modifiersData.popperOffsets.x+=s,t.modifiersData.popperOffsets.y+=h);t.modifiersData[e]=r}function ep(n){var t=n.state,i=n.name;t.modifiersData[i]=ls({reference:t.rects.reference,element:t.rects.popper,strategy:"absolute",placement:t.placement})}function op(n){return n==="x"?"y":"x"}function sp(n){var t=n.state,h=n.options,hi=n.name,rt=h.mainAxis,ut=rt===void 0?!0:rt,et=h.altAxis,ot=et===void 0?!1:et,ci=h.boundary,li=h.rootBoundary,ai=h.altBoundary,vi=h.padding,st=h.tether,c=st===void 0?!0:st,ht=h.tetherOffset,w=ht===void 0?0:ht,a=fi(t,{boundary:ci,rootBoundary:li,padding:vi,altBoundary:ai}),yi=b(t.placement),k=ui(t.placement),ct=!k,i=ku(yi),d=op(i),r=t.modifiersData.popperOffsets,l=t.rects.reference,g=t.rects.popper,v=typeof w=="function"?w(Object.assign({},t.rects,{placement:t.placement})):w,nt={x:0,y:0},it;if(r){if(ut||ot){var lt=i==="y"?u:f,at=i==="y"?o:s,e=i==="y"?"height":"width",vt=r[i],pt=r[i]+a[lt],wt=r[i]-a[at],bt=c?-g[e]/2:0,bi=k===yt?l[e]:g[e],ki=k===yt?-g[e]:-l[e],kt=t.elements.arrow,di=c&&kt?bu(kt):{width:0,height:0},dt=t.modifiersData["arrow#persistent"]?t.modifiersData["arrow#persistent"].padding:go(),gt=dt[lt],ni=dt[at],y=yr(0,l[e],di[e]),gi=ct?l[e]/2-bt-y-gt-v:bi-y-gt-v,nr=ct?-l[e]/2+bt+y+ni+v:ki+y+ni+v,tt=t.elements.arrow&&pi(t.elements.arrow),tr=tt?i==="y"?tt.clientTop||0:tt.clientLeft||0:0,ti=t.modifiersData.offset?t.modifiersData.offset[t.placement][i]:0,ii=r[i]+gi-ti-tr,ri=r[i]+nr-ti;if(ut&&(it=yr(c?wi(pt,ii):pt,vt,c?ft(wt,ri):wt),r[i]=it,nt[i]=it-vt),ot){var ir=i==="x"?u:f,rr=i==="x"?o:s,p=r[d],ei=p+a[ir],oi=p-a[rr],si=yr(c?wi(ei,ii):ei,p,c?ft(oi,ri):oi);r[d]=si;nt[d]=si-p}}t.modifiersData[hi]=nt}}function hp(n){return{scrollLeft:n.scrollLeft,scrollTop:n.scrollTop}}function cp(n){return n!==y(n)&&c(n)?hp(n):nf(n)}function lp(n){var t=n.getBoundingClientRect(),i=t.width/n.offsetWidth||1,r=t.height/n.offsetHeight||1;return i!==1||r!==1}function ap(n,t,i){var f;i===void 0&&(i=!1);f=c(t);c(t)&&lp(t);var e=ut(t),u=ri(n),o={scrollLeft:0,scrollTop:0},r={x:0,y:0};return!f&&(f||i)||((w(t)!=="body"||rf(e))&&(o=cp(t)),c(t)?(r=ri(t),r.x+=t.clientLeft,r.y+=t.clientTop):e&&(r.x=tf(e))),{x:u.left+o.scrollLeft-r.x,y:u.top+o.scrollTop-r.y,width:u.width,height:u.height}}function vp(n){function u(n){t.add(n.name);var f=[].concat(n.requires||[],n.requiresIfExists||[]);f.forEach(function(n){if(!t.has(n)){var r=i.get(n);r&&u(r)}});r.push(n)}var i=new Map,t=new Set,r=[];return n.forEach(function(n){i.set(n.name,n)}),n.forEach(function(n){t.has(n.name)||u(n)}),r}function yp(n){var t=vp(n);return po.reduce(function(n,i){return n.concat(t.filter(function(n){return n.phase===i}))},[])}function pp(n){var t;return function(){return t||(t=new Promise(function(i){Promise.resolve().then(function(){t=undefined;i(n())})})),t}}function wp(n){var t=n.reduce(function(n,t){var i=n[t.name];return n[t.name]=i?Object.assign({},i,t,{options:Object.assign({},i.options,t.options),data:Object.assign({},i.data,t.data)}):t,n},{});return Object.keys(t).map(function(n){return t[n]})}function ks(){for(var t=arguments.length,i=new Array(t),n=0;n{lk(n,e)||i.removeAttribute(n.nodeName)})}return r.body.innerHTML}var is,us,bi,es,os,ef;const rl=1e6,ul=1e3,fu="transitionend",fl=n=>n===null||n===undefined?`${n}`:{}.toString.call(n).match(/\s([a-z]+)/i)[1].toLowerCase(),el=n=>{do n+=Math.floor(Math.random()*rl);while(document.getElementById(n));return n},gf=n=>{let t=n.getAttribute("data-bs-target");if(!t||t==="#"){let i=n.getAttribute("href");if(!i||!i.includes("#")&&!i.startsWith("."))return null;i.includes("#")&&!i.startsWith("#")&&(i=`#${i.split("#")[1]}`);t=i&&i!=="#"?i.trim():null}return t},eu=n=>{const t=gf(n);return t?document.querySelector(t)?t:null:null},tt=n=>{const t=gf(n);return t?document.querySelector(t):null},ol=n=>{if(!n)return 0;let{transitionDuration:t,transitionDelay:i}=window.getComputedStyle(n);const r=Number.parseFloat(t),u=Number.parseFloat(i);return!r&&!u?0:(t=t.split(",")[0],i=i.split(",")[0],(Number.parseFloat(t)+Number.parseFloat(i))*ul)},ne=n=>{n.dispatchEvent(new Event(fu))},ot=n=>!n||typeof n!="object"?!1:(typeof n.jquery!="undefined"&&(n=n[0]),typeof n.nodeType!="undefined"),it=n=>ot(n)?n.jquery?n[0]:n:typeof n=="string"&&n.length>0?document.querySelector(n):null,p=(n,t,i)=>{Object.keys(i).forEach(r=>{const f=i[r],u=t[r],e=u&&ot(u)?"element":fl(u);if(!new RegExp(f).test(e))throw new TypeError(`${n.toUpperCase()}: Option "${r}" provided type "${e}" but expected type "${f}".`);})},ci=n=>!ot(n)||n.getClientRects().length===0?!1:getComputedStyle(n).getPropertyValue("visibility")==="visible",st=n=>!n||n.nodeType!==Node.ELEMENT_NODE?!0:n.classList.contains("disabled")?!0:typeof n.disabled!="undefined"?n.disabled:n.hasAttribute("disabled")&&n.getAttribute("disabled")!=="false",te=n=>{if(!document.documentElement.attachShadow)return null;if(typeof n.getRootNode=="function"){const t=n.getRootNode();return t instanceof ShadowRoot?t:null}return n instanceof ShadowRoot?n:n.parentNode?te(n.parentNode):null},fr=()=>{},kt=n=>{n.offsetHeight},ie=()=>{const{jQuery:n}=window;return n&&!document.body.hasAttribute("data-bs-no-jquery")?n:null},ou=[],sl=n=>{document.readyState==="loading"?(ou.length||document.addEventListener("DOMContentLoaded",()=>{ou.forEach(n=>n())}),ou.push(n)):n()},r=()=>document.documentElement.dir==="rtl",h=n=>{sl(()=>{const t=ie();if(t){const i=n.NAME,r=t.fn[i];t.fn[i]=n.jQueryInterface;t.fn[i].Constructor=n;t.fn[i].noConflict=()=>(t.fn[i]=r,n.jQueryInterface)}})},ht=n=>{typeof n=="function"&&n()},re=(n,t,i=true)=>{if(!i){ht(n);return}const f=ol(t)+5;let r=!1;const u=({target:i})=>{i===t&&(r=!0,t.removeEventListener(fu,u),ht(n))};t.addEventListener(fu,u);setTimeout(()=>{r||ne(t)},f)},ue=(n,t,i,r)=>{let u=n.indexOf(t);if(u===-1)return n[!i&&r?n.length-1:0];const f=n.length;return u+=i?1:-1,r&&(u=(u+f)%f),n[Math.max(0,Math.min(u,f-1))]},hl=/[^.]*(?=\..*)\.|.*/,cl=/\..*/,ll=/::\d+$/,su={};let fe=1;const al={mouseenter:"mouseover",mouseleave:"mouseout"},vl=/^(mouseenter|mouseleave)/i,ee=new Set(["click","dblclick","mouseup","mousedown","contextmenu","mousewheel","DOMMouseScroll","mouseover","mouseout","mousemove","selectstart","selectend","keydown","keypress","keyup","orientationchange","touchstart","touchmove","touchend","touchcancel","pointerdown","pointermove","pointerup","pointerleave","pointercancel","gesturestart","gesturechange","gestureend","focus","blur","change","reset","select","submit","focusin","focusout","load","unload","beforeunload","resize","move","DOMContentLoaded","readystatechange","error","abort","scroll"]);const n={on(n,t,i,r){le(n,t,i,r,!1)},one(n,t,i,r){le(n,t,i,r,!0)},off(n,t,i,r){if(typeof t=="string"&&n){const[s,e,f]=ce(t,i,r),h=f!==t,u=se(n),c=t.startsWith(".");if(typeof e!="undefined"){if(!u||!u[f])return;hu(n,u,f,e,s?i:null);return}c&&Object.keys(u).forEach(i=>{wl(n,u,i,t.slice(1))});const o=u[f]||{};Object.keys(o).forEach(i=>{const r=i.replace(ll,"");if(!h||t.includes(r)){const t=o[i];hu(n,u,f,t.originalHandler,t.delegationSelector)}})}},trigger(n,t,i){if(typeof t!="string"||!n)return null;const f=ie(),e=ae(t),c=t!==e,l=ee.has(e);let u,o=!0,s=!0,h=!1,r=null;return c&&f&&(u=f.Event(t,i),f(n).trigger(u),o=!u.isPropagationStopped(),s=!u.isImmediatePropagationStopped(),h=u.isDefaultPrevented()),l?(r=document.createEvent("HTMLEvents"),r.initEvent(e,o,!0)):r=new CustomEvent(t,{bubbles:o,cancelable:!0}),typeof i!="undefined"&&Object.keys(i).forEach(n=>{Object.defineProperty(r,n,{get(){return i[n]}})}),h&&r.preventDefault(),s&&n.dispatchEvent(r),r.defaultPrevented&&typeof u!="undefined"&&u.preventDefault(),r}},rt=new Map,li={set(n,t,i){rt.has(n)||rt.set(n,new Map);const r=rt.get(n);if(!r.has(t)&&r.size!==0){console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${Array.from(r.keys())[0]}.`);return}r.set(t,i)},get(n,t){return rt.has(n)?rt.get(n).get(t)||null:null},remove(n,t){if(rt.has(n)){const i=rt.get(n);i.delete(t);i.size===0&&rt.delete(n)}}},bl="5.1.3";class v{constructor(n){(n=it(n),n)&&(this._element=n,li.set(this._element,this.constructor.DATA_KEY,this))}dispose(){li.remove(this._element,this.constructor.DATA_KEY);n.off(this._element,this.constructor.EVENT_KEY);Object.getOwnPropertyNames(this).forEach(n=>{this[n]=null})}_queueCallback(n,t,i=true){re(n,t,i)}static getInstance(n){return li.get(it(n),this.DATA_KEY)}static getOrCreateInstance(n,t={}){return this.getInstance(n)||new this(n,typeof t=="object"?t:null)}static get VERSION(){return bl}static get NAME(){throw new Error('You have to implement the static method "NAME", for each component!');}static get DATA_KEY(){return`bs.${this.NAME}`}static get EVENT_KEY(){return`.${this.DATA_KEY}`}}const er=(t,i="hide")=>{const u=`click.dismiss${t.EVENT_KEY}`,r=t.NAME;n.on(document,u,`[data-bs-dismiss="${r}"]`,function(n){if(["A","AREA"].includes(this.tagName)&&n.preventDefault(),!st(this)){const u=tt(this)||this.closest(`.${r}`),f=t.getOrCreateInstance(u);f[i]()}})},kl="alert",ve=`.${"bs.alert"}`,dl=`close${ve}`,gl=`closed${ve}`,na="fade",ta="show";class or extends v{static get NAME(){return kl}close(){const t=n.trigger(this._element,dl);if(!t.defaultPrevented){this._element.classList.remove(ta);const i=this._element.classList.contains(na);this._queueCallback(()=>this._destroyElement(),this._element,i)}}_destroyElement(){this._element.remove();n.trigger(this._element,gl);this.dispose()}static jQueryInterface(n){return this.each(function(){const t=or.getOrCreateInstance(this);if(typeof n=="string"){if(t[n]===undefined||n.startsWith("_")||n==="constructor")throw new TypeError(`No method named "${n}"`);t[n](this)}})}}er(or,"close");h(or);const ia="button",ra=`.${"bs.button"}`,ua="active",ye='[data-bs-toggle="button"]',fa=`click${ra}${".data-api"}`;class sr extends v{static get NAME(){return ia}toggle(){this._element.setAttribute("aria-pressed",this._element.classList.toggle(ua))}static jQueryInterface(n){return this.each(function(){const t=sr.getOrCreateInstance(this);n==="toggle"&&t[n]()})}}n.on(document,fa,ye,n=>{n.preventDefault();const t=n.target.closest(ye),i=sr.getOrCreateInstance(t);i.toggle()});h(sr);const i={setDataAttribute(n,t,i){n.setAttribute(`data-bs-${cu(t)}`,i)},removeDataAttribute(n,t){n.removeAttribute(`data-bs-${cu(t)}`)},getDataAttributes(n){if(!n)return{};const t={};return Object.keys(n.dataset).filter(n=>n.startsWith("bs")).forEach(i=>{let r=i.replace(/^bs/,"");r=r.charAt(0).toLowerCase()+r.slice(1,r.length);t[r]=pe(n.dataset[i])}),t},getDataAttribute(n,t){return pe(n.getAttribute(`data-bs-${cu(t)}`))},offset(n){const t=n.getBoundingClientRect();return{top:t.top+window.pageYOffset,left:t.left+window.pageXOffset}},position(n){return{top:n.offsetTop,left:n.offsetLeft}}},ea=3,t={find(n,t=document.documentElement){return[].concat(...Element.prototype.querySelectorAll.call(t,n))},findOne(n,t=document.documentElement){return Element.prototype.querySelector.call(t,n)},children(n,t){return[].concat(...n.children).filter(n=>n.matches(t))},parents(n,t){const r=[];let i=n.parentNode;while(i&&i.nodeType===Node.ELEMENT_NODE&&i.nodeType!==ea)i.matches(t)&&r.push(i),i=i.parentNode;return r},prev(n,t){let i=n.previousElementSibling;while(i){if(i.matches(t))return[i];i=i.previousElementSibling}return[]},next(n,t){let i=n.nextElementSibling;while(i){if(i.matches(t))return[i];i=i.nextElementSibling}return[]},focusableChildren(n){const t=["a","button","input","textarea","select","details","[tabindex]",'[contenteditable="true"]'].map(n=>`${n}:not([tabindex^="-"])`).join(", ");return this.find(t,n).filter(n=>!st(n)&&ci(n))}},we="carousel",e=`.${"bs.carousel"}`,be=".data-api",oa=500,sa=40,ke={interval:5e3,keyboard:!0,slide:!1,pause:"hover",wrap:!0,touch:!0},ha={interval:"(number|boolean)",keyboard:"boolean",slide:"(boolean|string)",pause:"(string|boolean)",wrap:"boolean",touch:"boolean"},ct="next",lt="prev",at="left",ai="right",ca={["ArrowLeft"]:ai,["ArrowRight"]:at},la=`slide${e}`,de=`slid${e}`,aa=`keydown${e}`,va=`mouseenter${e}`,ya=`mouseleave${e}`,pa=`touchstart${e}`,wa=`touchmove${e}`,ba=`touchend${e}`,ka=`pointerdown${e}`,da=`pointerup${e}`,ga=`dragstart${e}`,nv=`load${e}${be}`,tv=`click${e}${be}`,iv="carousel",vt="active",rv="slide",uv="carousel-item-end",fv="carousel-item-start",ev="carousel-item-next",ov="carousel-item-prev",sv="pointer-event",hv=".active",hr=".active.carousel-item",cv=".carousel-item",lv=".carousel-item img",av=".carousel-item-next, .carousel-item-prev",vv=".carousel-indicators",yv="[data-bs-target]",pv='[data-bs-ride="carousel"]',wv="touch",bv="pen";class g extends v{constructor(n,i){super(n);this._items=null;this._interval=null;this._activeElement=null;this._isPaused=!1;this._isSliding=!1;this.touchTimeout=null;this.touchStartX=0;this.touchDeltaX=0;this._config=this._getConfig(i);this._indicatorsElement=t.findOne(vv,this._element);this._touchSupported="ontouchstart"in document.documentElement||navigator.maxTouchPoints>0;this._pointerEvent=Boolean(window.PointerEvent);this._addEventListeners()}static get Default(){return ke}static get NAME(){return we}next(){this._slide(ct)}nextWhenVisible(){!document.hidden&&ci(this._element)&&this.next()}prev(){this._slide(lt)}pause(n){n||(this._isPaused=!0);t.findOne(av,this._element)&&(ne(this._element),this.cycle(!0));clearInterval(this._interval);this._interval=null}cycle(n){n||(this._isPaused=!1);this._interval&&(clearInterval(this._interval),this._interval=null);this._config&&this._config.interval&&!this._isPaused&&(this._updateInterval(),this._interval=setInterval((document.visibilityState?this.nextWhenVisible:this.next).bind(this),this._config.interval))}to(i){this._activeElement=t.findOne(hr,this._element);const r=this._getItemIndex(this._activeElement);if(!(i>this._items.length-1)&&!(i<0)){if(this._isSliding){n.one(this._element,de,()=>this.to(i));return}if(r===i){this.pause();this.cycle();return}const u=i>r?ct:lt;this._slide(u,this._items[i])}}_getConfig(n){return n={...ke,...i.getDataAttributes(this._element),...(typeof n=="object"?n:{})},p(we,n,ha),n}_handleSwipe(){const n=Math.abs(this.touchDeltaX);if(!(n<=sa)){const t=n/this.touchDeltaX;(this.touchDeltaX=0,t)&&this._slide(t>0?ai:at)}}_addEventListeners(){if(this._config.keyboard)n.on(this._element,aa,n=>this._keydown(n));if(this._config.pause==="hover"){n.on(this._element,va,n=>this.pause(n));n.on(this._element,ya,n=>this.cycle(n))}this._config.touch&&this._touchSupported&&this._addTouchEventListeners()}_addTouchEventListeners(){const i=n=>this._pointerEvent&&(n.pointerType===bv||n.pointerType===wv),r=n=>{i(n)?this.touchStartX=n.clientX:this._pointerEvent||(this.touchStartX=n.touches[0].clientX)},f=n=>{this.touchDeltaX=n.touches&&n.touches.length>1?0:n.touches[0].clientX-this.touchStartX},u=n=>{i(n)&&(this.touchDeltaX=n.clientX-this.touchStartX),this._handleSwipe(),this._config.pause==="hover"&&(this.pause(),this.touchTimeout&&clearTimeout(this.touchTimeout),this.touchTimeout=setTimeout(n=>this.cycle(n),oa+this._config.interval))};if(t.find(lv,this._element).forEach(t=>{n.on(t,ga,n=>n.preventDefault())}),this._pointerEvent){n.on(this._element,ka,n=>r(n));n.on(this._element,da,n=>u(n));this._element.classList.add(sv)}else{n.on(this._element,pa,n=>r(n));n.on(this._element,wa,n=>f(n));n.on(this._element,ba,n=>u(n))}}_keydown(n){if(!/input|textarea/i.test(n.target.tagName)){const t=ca[n.key];t&&(n.preventDefault(),this._slide(t))}}_getItemIndex(n){return this._items=n&&n.parentNode?t.find(cv,n.parentNode):[],this._items.indexOf(n)}_getItemByOrder(n,t){const i=n===ct;return ue(this._items,t,i,this._config.wrap)}_triggerSlideEvent(i,r){const u=this._getItemIndex(i),f=this._getItemIndex(t.findOne(hr,this._element));return n.trigger(this._element,la,{relatedTarget:i,direction:r,from:f,to:u})}_setActiveIndicatorElement(n){if(this._indicatorsElement){const r=t.findOne(hv,this._indicatorsElement);r.classList.remove(vt);r.removeAttribute("aria-current");const i=t.find(yv,this._indicatorsElement);for(let t=0;t{n.trigger(this._element,de,{relatedTarget:u,direction:l,from:v,to:y})};if(this._element.classList.contains(rv)){u.classList.add(s);kt(u);f.classList.add(e);u.classList.add(e);const n=()=>{u.classList.remove(e,s),u.classList.add(vt),f.classList.remove(vt,s,e),this._isSliding=!1,setTimeout(a,0)};this._queueCallback(n,f,!0)}else f.classList.remove(vt),u.classList.add(vt),this._isSliding=!1,a();h&&this.cycle()}}}_directionToOrder(n){return[ai,at].includes(n)?r()?n===at?lt:ct:n===at?ct:lt:n}_orderToDirection(n){return[ct,lt].includes(n)?r()?n===lt?at:ai:n===lt?ai:at:n}static carouselInterface(n,t){const i=g.getOrCreateInstance(n,t);let{_config:r}=i;typeof t=="object"&&(r={...r,...t});const u=typeof t=="string"?t:r.slide;if(typeof t=="number")i.to(t);else if(typeof u=="string"){if(typeof i[u]=="undefined")throw new TypeError(`No method named "${u}"`);i[u]()}else r.interval&&r.ride&&(i.pause(),i.cycle())}static jQueryInterface(n){return this.each(function(){g.carouselInterface(this,n)})}static dataApiClickHandler(n){const t=tt(this);if(t&&t.classList.contains(iv)){const u={...i.getDataAttributes(t),...i.getDataAttributes(this)},r=this.getAttribute("data-bs-slide-to");r&&(u.interval=!1);g.carouselInterface(t,u);r&&g.getInstance(t).to(r);n.preventDefault()}}}n.on(document,tv,"[data-bs-slide], [data-bs-slide-to]",g.dataApiClickHandler);n.on(window,nv,()=>{const n=t.find(pv);for(let t=0,i=n.length;tn===this._element);i!==null&&f.length&&(this._selector=i,this._triggerArray.push(u))}this._initializeChildren();this._config.parent||this._addAriaAndCollapsedClass(this._triggerArray,this._isShown());this._config.toggle&&this.toggle()}static get Default(){return to}static get NAME(){return ge}toggle(){this._isShown()?this.hide():this.show()}show(){if(!this._isTransitioning&&!this._isShown()){let r=[],u;if(this._config.parent){const n=t.find(ro,this._config.parent);r=t.find(ey,this._config.parent).filter(t=>!n.includes(t))}const f=t.findOne(this._selector);if(r.length){const n=r.find(n=>f!==n);if(u=n?gt.getInstance(n):null,u&&u._isTransitioning)return}const e=n.trigger(this._element,dv);if(!e.defaultPrevented){r.forEach(n=>{f!==n&>.getOrCreateInstance(n,{toggle:!1}).hide(),u||li.set(n,no,null)});const i=this._getDimension();this._element.classList.remove(dt);this._element.classList.add(cr);this._element.style[i]=0;this._addAriaAndCollapsedClass(this._triggerArray,!0);this._isTransitioning=!0;const o=()=>{this._isTransitioning=!1,this._element.classList.remove(cr),this._element.classList.add(dt,lu),this._element.style[i]="",n.trigger(this._element,gv)},s=i[0].toUpperCase()+i.slice(1),h=`scroll${s}`;this._queueCallback(o,this._element,!0);this._element.style[i]=`${this._element[h]}px`}}}hide(){if(!this._isTransitioning&&this._isShown()){const i=n.trigger(this._element,ny);if(!i.defaultPrevented){const t=this._getDimension();this._element.style[t]=`${this._element.getBoundingClientRect()[t]}px`;kt(this._element);this._element.classList.add(cr);this._element.classList.remove(dt,lu);const r=this._triggerArray.length;for(let n=0;n{this._isTransitioning=!1,this._element.classList.remove(cr),this._element.classList.add(dt),n.trigger(this._element,ty)};this._element.style[t]="";this._queueCallback(u,this._element,!0)}}}_isShown(n=this._element){return n.classList.contains(lu)}_getConfig(n){return n={...to,...i.getDataAttributes(this._element),...n},n.toggle=Boolean(n.toggle),n.parent=it(n.parent),p(ge,n,kv),n}_getDimension(){return this._element.classList.contains(ry)?uy:fy}_initializeChildren(){if(this._config.parent){const n=t.find(ro,this._config.parent);t.find(au,this._config.parent).filter(t=>!n.includes(t)).forEach(n=>{const t=tt(n);t&&this._addAriaAndCollapsedClass([n],this._isShown(t))})}}_addAriaAndCollapsedClass(n,t){n.length&&n.forEach(n=>{t?n.classList.remove(io):n.classList.add(io),n.setAttribute("aria-expanded",t)})}static jQueryInterface(n){return this.each(function(){const t={};typeof n=="string"&&/show|hide/.test(n)&&(t.toggle=!1);const i=gt.getOrCreateInstance(this,t);if(typeof n=="string"){if(typeof i[n]=="undefined")throw new TypeError(`No method named "${n}"`);i[n]()}})}}n.on(document,iy,au,function(n){(n.target.tagName==="A"||n.delegateTarget&&n.delegateTarget.tagName==="A")&&n.preventDefault();const i=eu(this),r=t.find(i);r.forEach(n=>{gt.getOrCreateInstance(n,{toggle:!1}).toggle()})});h(gt);var u="top",o="bottom",s="right",f="left",lr="auto",ni=[u,o,s,f],yt="start",ti="end",uo="clippingParents",vu="viewport",ii="popper",fo="reference",yu=ni.reduce(function(n,t){return n.concat([t+"-"+yt,t+"-"+ti])},[]),pu=[].concat(ni,[lr]).reduce(function(n,t){return n.concat([t,t+"-"+yt,t+"-"+ti])},[]),eo="beforeRead",oo="read",so="afterRead",ho="beforeMain",co="main",lo="afterMain",ao="beforeWrite",vo="write",yo="afterWrite",po=[eo,oo,so,ho,co,lo,ao,vo,yo];const wu={name:"applyStyles",enabled:!0,phase:"write",fn:oy,effect:sy,requires:["computeStyles"]};var ft=Math.max,wi=Math.min,vr=Math.round;is=function(n,t){return n=typeof n=="function"?n(Object.assign({},t.rects,{placement:t.placement})):n,ns(typeof n!="number"?n:ts(n,ni))};const rs={name:"arrow",enabled:!0,phase:"main",fn:ly,effect:ay,requires:["popperOffsets"],requiresIfExists:["preventOverflow"]};us={top:"auto",right:"auto",bottom:"auto",left:"auto"};const du={name:"computeStyles",enabled:!0,phase:"beforeWrite",fn:yy,data:{}};bi={passive:!0};const gu={name:"eventListeners",enabled:!0,phase:"write",fn:function(){},effect:py,data:{}};es={left:"right",right:"left",bottom:"top",top:"bottom"};os={start:"end",end:"start"};const as={name:"flip",enabled:!0,phase:"main",fn:ip,requiresIfExists:["offset"],data:{_skip:!1}};const ps={name:"hide",enabled:!0,phase:"main",requiresIfExists:["preventOverflow"],fn:rp};const ws={name:"offset",enabled:!0,phase:"main",requires:["popperOffsets"],fn:fp};const ff={name:"popperOffsets",enabled:!0,phase:"read",fn:ep,data:{}};const bs={name:"preventOverflow",enabled:!0,phase:"main",fn:sp,requiresIfExists:["offset"]};ef={placement:"bottom",modifiers:[],strategy:"absolute"};var bp=wr(),kp=[gu,ff,du,wu],dp=wr({defaultModifiers:kp}),gp=[gu,ff,du,wu,ws,as,bs,rs,ps],sf=wr({defaultModifiers:gp});const ds=Object.freeze({__proto__:null,popperGenerator:wr,detectOverflow:fi,createPopperBase:bp,createPopper:sf,createPopperLite:dp,top:u,bottom:o,right:s,left:f,auto:lr,basePlacements:ni,start:yt,end:ti,clippingParents:uo,viewport:vu,popper:ii,reference:fo,variationPlacements:yu,placements:pu,beforeRead:eo,read:oo,afterRead:so,beforeMain:ho,main:co,afterMain:lo,beforeWrite:ao,write:vo,afterWrite:yo,modifierPhases:po,applyStyles:wu,arrow:rs,computeStyles:du,eventListeners:gu,flip:as,hide:ps,offset:ws,popperOffsets:ff,preventOverflow:bs}),hf="dropdown",pt=`.${"bs.dropdown"}`,cf=".data-api",br="Escape",gs="Space",nh="Tab",lf="ArrowUp",kr="ArrowDown",nw=2,tw=new RegExp(`${lf}|${kr}|${br}`),iw=`hide${pt}`,rw=`hidden${pt}`,uw=`show${pt}`,fw=`shown${pt}`,th=`click${pt}${cf}`,ih=`keydown${pt}${cf}`,ew=`keyup${pt}${cf}`,ei="show",ow="dropup",sw="dropend",hw="dropstart",cw="navbar",di='[data-bs-toggle="dropdown"]',af=".dropdown-menu",lw=".navbar-nav",aw=".dropdown-menu .dropdown-item:not(.disabled):not(:disabled)",vw=r()?"top-end":"top-start",yw=r()?"top-start":"top-end",pw=r()?"bottom-end":"bottom-start",ww=r()?"bottom-start":"bottom-end",bw=r()?"left-start":"right-start",kw=r()?"right-start":"left-start",dw={offset:[0,2],boundary:"clippingParents",reference:"toggle",display:"dynamic",popperConfig:null,autoClose:!0},gw={offset:"(array|string|function)",boundary:"(string|element)",reference:"(string|element|object)",display:"string",popperConfig:"(null|object|function)",autoClose:"(boolean|string)"};class l extends v{constructor(n,t){super(n);this._popper=null;this._config=this._getConfig(t);this._menu=this._getMenuElement();this._inNavbar=this._detectNavbar()}static get Default(){return dw}static get DefaultType(){return gw}static get NAME(){return hf}toggle(){return this._isShown()?this.hide():this.show()}show(){if(!st(this._element)&&!this._isShown(this._menu)){const t={relatedTarget:this._element},u=n.trigger(this._element,uw,t);if(!u.defaultPrevented){const r=l.getParentFromElement(this._element);this._inNavbar?i.setDataAttribute(this._menu,"popper","none"):this._createPopper(r);"ontouchstart"in document.documentElement&&!r.closest(lw)&&[].concat(...document.body.children).forEach(t=>n.on(t,"mouseover",fr));this._element.focus();this._element.setAttribute("aria-expanded",!0);this._menu.classList.add(ei);this._element.classList.add(ei);n.trigger(this._element,fw,t)}}}hide(){if(!st(this._element)&&this._isShown(this._menu)){const n={relatedTarget:this._element};this._completeHide(n)}}dispose(){this._popper&&this._popper.destroy();super.dispose()}update(){this._inNavbar=this._detectNavbar();this._popper&&this._popper.update()}_completeHide(t){const r=n.trigger(this._element,iw,t);r.defaultPrevented||("ontouchstart"in document.documentElement&&[].concat(...document.body.children).forEach(t=>n.off(t,"mouseover",fr)),this._popper&&this._popper.destroy(),this._menu.classList.remove(ei),this._element.classList.remove(ei),this._element.setAttribute("aria-expanded","false"),i.removeDataAttribute(this._menu,"popper"),n.trigger(this._element,rw,t))}_getConfig(n){if(n={...this.constructor.Default,...i.getDataAttributes(this._element),...n},p(hf,n,this.constructor.DefaultType),typeof n.reference=="object"&&!ot(n.reference)&&typeof n.reference.getBoundingClientRect!="function")throw new TypeError(`${hf.toUpperCase()}: Option "reference" provided type "object" without a required "getBoundingClientRect" method.`);return n}_createPopper(n){if(typeof ds=="undefined")throw new TypeError("Bootstrap's dropdowns require Popper (https://popper.js.org)");let t=this._element;this._config.reference==="parent"?t=n:ot(this._config.reference)?t=it(this._config.reference):typeof this._config.reference=="object"&&(t=this._config.reference);const r=this._getPopperConfig(),u=r.modifiers.find(n=>n.name==="applyStyles"&&n.enabled===!1);this._popper=sf(t,this._menu,r);u&&i.setDataAttribute(this._menu,"popper","static")}_isShown(n=this._element){return n.classList.contains(ei)}_getMenuElement(){return t.next(this._element,af)[0]}_getPlacement(){const n=this._element.parentNode;if(n.classList.contains(sw))return bw;if(n.classList.contains(hw))return kw;const t=getComputedStyle(this._menu).getPropertyValue("--bs-position").trim()==="end";return n.classList.contains(ow)?t?yw:vw:t?ww:pw}_detectNavbar(){return this._element.closest(`.${cw}`)!==null}_getOffset(){const{offset:n}=this._config;return typeof n=="string"?n.split(",").map(n=>Number.parseInt(n,10)):typeof n=="function"?t=>n(t,this._element):n}_getPopperConfig(){const n={placement:this._getPlacement(),modifiers:[{name:"preventOverflow",options:{boundary:this._config.boundary}},{name:"offset",options:{offset:this._getOffset()}}]};return this._config.display==="static"&&(n.modifiers=[{name:"applyStyles",enabled:!1}]),{...n,...(typeof this._config.popperConfig=="function"?this._config.popperConfig(n):this._config.popperConfig)}}_selectMenuItem({key:n,target:i}){const r=t.find(aw,this._menu).filter(ci);r.length&&ue(r,i,n===kr,!r.includes(i)).focus()}static jQueryInterface(n){return this.each(function(){const t=l.getOrCreateInstance(this,n);if(typeof n=="string"){if(typeof t[n]=="undefined")throw new TypeError(`No method named "${n}"`);t[n]()}})}static clearMenus(n){if(!n||n.button!==nw&&(n.type!=="keyup"||n.key===nh)){const i=t.find(di);for(let t=0,r=i.length;tt+n);this._setElementAttributes(rh,"paddingRight",t=>t+n);this._setElementAttributes(uh,"marginRight",t=>t-n)}_disableOverFlow(){this._saveInitialAttribute(this._element,"overflow");this._element.style.overflow="hidden"}_setElementAttributes(n,t,i){const r=this.getWidth(),u=n=>{if(n===this._element||!(window.innerWidth>n.clientWidth+r)){this._saveInitialAttribute(n,t);const u=window.getComputedStyle(n)[t];n.style[t]=`${i(Number.parseFloat(u))}px`}};this._applyManipulationCallback(n,u)}reset(){this._resetElementAttributes(this._element,"overflow");this._resetElementAttributes(this._element,"paddingRight");this._resetElementAttributes(rh,"paddingRight");this._resetElementAttributes(uh,"marginRight")}_saveInitialAttribute(n,t){const r=n.style[t];r&&i.setDataAttribute(n,t,r)}_resetElementAttributes(n,t){const r=n=>{const r=i.getDataAttribute(n,t);typeof r=="undefined"?n.style.removeProperty(t):(i.removeDataAttribute(n,t),n.style[t]=r)};this._applyManipulationCallback(n,r)}_applyManipulationCallback(n,i){ot(n)?i(n):t.find(n,this._element).forEach(i)}isOverflowing(){return this.getWidth()>0}}const nb={className:"modal-backdrop",isVisible:!0,isAnimated:!1,rootElement:"body",clickCallback:null},tb={className:"string",isVisible:"boolean",isAnimated:"boolean",rootElement:"(element|string)",clickCallback:"(function|null)"},fh="backdrop",ib="fade",eh="show",oh=`mousedown.bs.${fh}`;class sh{constructor(n){this._config=this._getConfig(n);this._isAppended=!1;this._element=null}show(n){if(!this._config.isVisible){ht(n);return}this._append();this._config.isAnimated&&kt(this._getElement());this._getElement().classList.add(eh);this._emulateAnimation(()=>{ht(n)})}hide(n){if(!this._config.isVisible){ht(n);return}this._getElement().classList.remove(eh);this._emulateAnimation(()=>{this.dispose(),ht(n)})}_getElement(){if(!this._element){const n=document.createElement("div");n.className=this._config.className;this._config.isAnimated&&n.classList.add(ib);this._element=n}return this._element}_getConfig(n){return n={...nb,...(typeof n=="object"?n:{})},n.rootElement=it(n.rootElement),p(fh,n,tb),n}_append(){if(!this._isAppended){this._config.rootElement.append(this._getElement());n.on(this._getElement(),oh,()=>{ht(this._config.clickCallback)});this._isAppended=!0}}dispose(){this._isAppended&&(n.off(this._element,oh),this._element.remove(),this._isAppended=!1)}_emulateAnimation(n){re(n,this._getElement(),this._config.isAnimated)}}const rb={trapElement:null,autofocus:!0},ub={trapElement:"element",autofocus:"boolean"},fb="focustrap",dr=`.${"bs.focustrap"}`,eb=`focusin${dr}`,ob=`keydown.tab${dr}`,sb="Tab",hb="forward",hh="backward";class ch{constructor(n){this._config=this._getConfig(n);this._isActive=!1;this._lastTabNavDirection=null}activate(){const{trapElement:t,autofocus:i}=this._config;if(!this._isActive){i&&t.focus();n.off(document,dr);n.on(document,eb,n=>this._handleFocusin(n));n.on(document,ob,n=>this._handleKeydown(n));this._isActive=!0}}deactivate(){this._isActive&&(this._isActive=!1,n.off(document,dr))}_handleFocusin(n){const{target:u}=n,{trapElement:i}=this._config;if(u!==document&&u!==i&&!i.contains(u)){const r=t.focusableChildren(i);r.length===0?i.focus():this._lastTabNavDirection===hh?r[r.length-1].focus():r[0].focus()}}_handleKeydown(n){n.key===sb&&(this._lastTabNavDirection=n.shiftKey?hh:hb)}_getConfig(n){return n={...rb,...(typeof n=="object"?n:{})},p(fb,n,ub),n}}const lh="modal",a=`.${"bs.modal"}`,ah="Escape",vh={backdrop:!0,keyboard:!0,focus:!0},cb={backdrop:"(boolean|string)",keyboard:"boolean",focus:"boolean"},lb=`hide${a}`,ab=`hidePrevented${a}`,yh=`hidden${a}`,ph=`show${a}`,vb=`shown${a}`,wh=`resize${a}`,bh=`click.dismiss${a}`,kh=`keydown.dismiss${a}`,yb=`mouseup.dismiss${a}`,dh=`mousedown.dismiss${a}`,pb=`click${a}${".data-api"}`,gh="modal-open",wb="fade",nc="show",yf="modal-static",bb=".modal.show",kb=".modal-dialog",db=".modal-body";class oi extends v{constructor(n,i){super(n);this._config=this._getConfig(i);this._dialog=t.findOne(kb,this._element);this._backdrop=this._initializeBackDrop();this._focustrap=this._initializeFocusTrap();this._isShown=!1;this._ignoreBackdropClick=!1;this._isTransitioning=!1;this._scrollBar=new vf}static get Default(){return vh}static get NAME(){return lh}toggle(n){return this._isShown?this.hide():this.show(n)}show(t){if(!this._isShown&&!this._isTransitioning){const i=n.trigger(this._element,ph,{relatedTarget:t});if(!i.defaultPrevented){this._isShown=!0;this._isAnimated()&&(this._isTransitioning=!0);this._scrollBar.hide();document.body.classList.add(gh);this._adjustDialog();this._setEscapeEvent();this._setResizeEvent();n.on(this._dialog,dh,()=>{n.one(this._element,yb,n=>{n.target===this._element&&(this._ignoreBackdropClick=!0)})});this._showBackdrop(()=>this._showElement(t))}}}hide(){if(this._isShown&&!this._isTransitioning){const i=n.trigger(this._element,lb);if(!i.defaultPrevented){this._isShown=!1;const t=this._isAnimated();t&&(this._isTransitioning=!0);this._setEscapeEvent();this._setResizeEvent();this._focustrap.deactivate();this._element.classList.remove(nc);n.off(this._element,bh);n.off(this._dialog,dh);this._queueCallback(()=>this._hideModal(),this._element,t)}}}dispose(){[window,this._dialog].forEach(t=>n.off(t,a));this._backdrop.dispose();this._focustrap.deactivate();super.dispose()}handleUpdate(){this._adjustDialog()}_initializeBackDrop(){return new sh({isVisible:Boolean(this._config.backdrop),isAnimated:this._isAnimated()})}_initializeFocusTrap(){return new ch({trapElement:this._element})}_getConfig(n){return n={...vh,...i.getDataAttributes(this._element),...(typeof n=="object"?n:{})},p(lh,n,cb),n}_showElement(i){const r=this._isAnimated(),u=t.findOne(db,this._dialog);this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE||document.body.append(this._element);this._element.style.display="block";this._element.removeAttribute("aria-hidden");this._element.setAttribute("aria-modal",!0);this._element.setAttribute("role","dialog");this._element.scrollTop=0;u&&(u.scrollTop=0);r&&kt(this._element);this._element.classList.add(nc);const f=()=>{this._config.focus&&this._focustrap.activate(),this._isTransitioning=!1,n.trigger(this._element,vb,{relatedTarget:i})};this._queueCallback(f,this._dialog,r)}_setEscapeEvent(){if(this._isShown)n.on(this._element,kh,n=>{this._config.keyboard&&n.key===ah?(n.preventDefault(),this.hide()):this._config.keyboard||n.key!==ah||this._triggerBackdropTransition()});else n.off(this._element,kh)}_setResizeEvent(){if(this._isShown)n.on(window,wh,()=>this._adjustDialog());else n.off(window,wh)}_hideModal(){this._element.style.display="none";this._element.setAttribute("aria-hidden",!0);this._element.removeAttribute("aria-modal");this._element.removeAttribute("role");this._isTransitioning=!1;this._backdrop.hide(()=>{document.body.classList.remove(gh),this._resetAdjustments(),this._scrollBar.reset(),n.trigger(this._element,yh)})}_showBackdrop(t){n.on(this._element,bh,n=>{if(this._ignoreBackdropClick){this._ignoreBackdropClick=!1;return}n.target===n.currentTarget&&(this._config.backdrop===!0?this.hide():this._config.backdrop==="static"&&this._triggerBackdropTransition())});this._backdrop.show(t)}_isAnimated(){return this._element.classList.contains(wb)}_triggerBackdropTransition(){const u=n.trigger(this._element,ab);if(!u.defaultPrevented){const{classList:t,scrollHeight:f,style:i}=this._element,r=f>document.documentElement.clientHeight;(r||i.overflowY!=="hidden")&&!t.contains(yf)&&(r||(i.overflowY="hidden"),t.add(yf),this._queueCallback(()=>{t.remove(yf),r||this._queueCallback(()=>{i.overflowY=""},this._dialog)},this._dialog),this._element.focus())}}_adjustDialog(){const n=this._element.scrollHeight>document.documentElement.clientHeight,i=this._scrollBar.getWidth(),t=i>0;(!t&&n&&!r()||t&&!n&&r())&&(this._element.style.paddingLeft=`${i}px`);(t&&!n&&!r()||!t&&n&&r())&&(this._element.style.paddingRight=`${i}px`)}_resetAdjustments(){this._element.style.paddingLeft="";this._element.style.paddingRight=""}static jQueryInterface(n,t){return this.each(function(){const i=oi.getOrCreateInstance(this,n);if(typeof n=="string"){if(typeof i[n]=="undefined")throw new TypeError(`No method named "${n}"`);i[n](t)}})}}n.on(document,pb,'[data-bs-toggle="modal"]',function(i){const r=tt(this);["A","AREA"].includes(this.tagName)&&i.preventDefault();n.one(r,ph,t=>{if(!t.defaultPrevented)n.one(r,yh,()=>{ci(this)&&this.focus()})});const u=t.findOne(bb);u&&oi.getInstance(u).hide();const f=oi.getOrCreateInstance(r);f.toggle(this)});er(oi);h(oi);const tc="offcanvas",wt=`.${"bs.offcanvas"}`,ic=".data-api",gb=`load${wt}${ic}`,nk="Escape",rc={backdrop:!0,keyboard:!0,scroll:!1},tk={backdrop:"boolean",keyboard:"boolean",scroll:"boolean"},uc="show",ik="offcanvas-backdrop",fc=".offcanvas.show",rk=`show${wt}`,uk=`shown${wt}`,fk=`hide${wt}`,ec=`hidden${wt}`,ek=`click${wt}${ic}`,ok=`keydown.dismiss${wt}`;class bt extends v{constructor(n,t){super(n);this._config=this._getConfig(t);this._isShown=!1;this._backdrop=this._initializeBackDrop();this._focustrap=this._initializeFocusTrap();this._addEventListeners()}static get NAME(){return tc}static get Default(){return rc}toggle(n){return this._isShown?this.hide():this.show(n)}show(t){if(!this._isShown){const i=n.trigger(this._element,rk,{relatedTarget:t});if(!i.defaultPrevented){this._isShown=!0;this._element.style.visibility="visible";this._backdrop.show();this._config.scroll||(new vf).hide();this._element.removeAttribute("aria-hidden");this._element.setAttribute("aria-modal",!0);this._element.setAttribute("role","dialog");this._element.classList.add(uc);const r=()=>{this._config.scroll||this._focustrap.activate(),n.trigger(this._element,uk,{relatedTarget:t})};this._queueCallback(r,this._element,!0)}}}hide(){if(this._isShown){const t=n.trigger(this._element,fk);if(!t.defaultPrevented){this._focustrap.deactivate();this._element.blur();this._isShown=!1;this._element.classList.remove(uc);this._backdrop.hide();const i=()=>{this._element.setAttribute("aria-hidden",!0),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._element.style.visibility="hidden",this._config.scroll||(new vf).reset(),n.trigger(this._element,ec)};this._queueCallback(i,this._element,!0)}}}dispose(){this._backdrop.dispose();this._focustrap.deactivate();super.dispose()}_getConfig(n){return n={...rc,...i.getDataAttributes(this._element),...(typeof n=="object"?n:{})},p(tc,n,tk),n}_initializeBackDrop(){return new sh({className:ik,isVisible:this._config.backdrop,isAnimated:!0,rootElement:this._element.parentNode,clickCallback:()=>this.hide()})}_initializeFocusTrap(){return new ch({trapElement:this._element})}_addEventListeners(){n.on(this._element,ok,n=>{this._config.keyboard&&n.key===nk&&this.hide()})}static jQueryInterface(n){return this.each(function(){const t=bt.getOrCreateInstance(this,n);if(typeof n=="string"){if(t[n]===undefined||n.startsWith("_")||n==="constructor")throw new TypeError(`No method named "${n}"`);t[n](this)}})}}n.on(document,ek,'[data-bs-toggle="offcanvas"]',function(i){const r=tt(this);if(["A","AREA"].includes(this.tagName)&&i.preventDefault(),!st(this)){n.one(r,ec,()=>{ci(this)&&this.focus()});const u=t.findOne(fc);u&&u!==r&&bt.getInstance(u).hide();const f=bt.getOrCreateInstance(r);f.toggle(this)}});n.on(window,gb,()=>t.find(fc).forEach(n=>bt.getOrCreateInstance(n).show()));er(bt);h(bt);const sk=new Set(["background","cite","href","itemtype","longdesc","poster","src","xlink:href"]),hk=/^(?:(?:https?|mailto|ftp|tel|file|sms):|[^#&/:?]*(?:[#/?]|$))/i,ck=/^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[\d+/a-z]+=*$/i,lk=(n,t)=>{const i=n.nodeName.toLowerCase();if(t.includes(i))return sk.has(i)?Boolean(hk.test(n.nodeValue)||ck.test(n.nodeValue)):!0;const r=t.filter(n=>n instanceof RegExp);for(let n=0,t=r.length;n
<\/div>
<\/div><\/div>',trigger:"hover focus",title:"",delay:0,html:!1,selector:!1,placement:"top",offset:[0,0],container:!1,fallbackPlacements:["top","right","bottom","left"],boundary:"clippingParents",customClass:"",sanitize:!0,sanitizeFn:null,allowList:{"*":["class","dir","id","lang","role",/^aria-[\w-]*$/i],a:["target","href","title","rel"],area:[],b:[],br:[],col:[],code:[],div:[],em:[],hr:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],i:[],img:["src","srcset","alt","title","width","height"],li:[],ol:[],p:[],pre:[],s:[],small:[],span:[],sub:[],sup:[],strong:[],u:[],ul:[]},popperConfig:null},bk={HIDE:`hide${k}`,HIDDEN:`hidden${k}`,SHOW:`show${k}`,SHOWN:`shown${k}`,INSERTED:`inserted${k}`,CLICK:`click${k}`,FOCUSIN:`focusin${k}`,FOCUSOUT:`focusout${k}`,MOUSEENTER:`mouseenter${k}`,MOUSELEAVE:`mouseleave${k}`},gr="fade",gi="show",nr="show",pf="out",hc=".tooltip-inner",cc=`.${"modal"}`,lc="hide.bs.modal",tr="hover",wf="focus",kk="click",dk="manual";class si extends v{constructor(n,t){if(typeof ds=="undefined")throw new TypeError("Bootstrap's tooltips require Popper (https://popper.js.org)");super(n);this._isEnabled=!0;this._timeout=0;this._hoverState="";this._activeTrigger={};this._popper=null;this._config=this._getConfig(t);this.tip=null;this._setListeners()}static get Default(){return wk}static get NAME(){return sc}static get Event(){return bk}static get DefaultType(){return yk}enable(){this._isEnabled=!0}disable(){this._isEnabled=!1}toggleEnabled(){this._isEnabled=!this._isEnabled}toggle(n){if(this._isEnabled)if(n){const t=this._initializeOnDelegatedTarget(n);t._activeTrigger.click=!t._activeTrigger.click;t._isWithActiveTrigger()?t._enter(null,t):t._leave(null,t)}else{if(this.getTipElement().classList.contains(gi)){this._leave(null,this);return}this._enter(null,this)}}dispose(){clearTimeout(this._timeout);n.off(this._element.closest(cc),lc,this._hideModalHandler);this.tip&&this.tip.remove();this._disposePopper();super.dispose()}show(){if(this._element.style.display==="none")throw new Error("Please use show on visible elements");if(this.isWithContent()&&this._isEnabled){const e=n.trigger(this._element,this.constructor.Event.SHOW),i=te(this._element),o=i===null?this._element.ownerDocument.documentElement.contains(this._element):i.contains(this._element);if(!e.defaultPrevented&&o){this.constructor.NAME==="tooltip"&&this.tip&&this.getTitle()!==this.tip.querySelector(hc).innerHTML&&(this._disposePopper(),this.tip.remove(),this.tip=null);const t=this.getTipElement(),r=el(this.constructor.NAME);t.setAttribute("id",r);this._element.setAttribute("aria-describedby",r);this._config.animation&&t.classList.add(gr);const s=typeof this._config.placement=="function"?this._config.placement.call(this,t,this._element):this._config.placement,u=this._getAttachment(s);this._addAttachmentClass(u);const{container:h}=this._config;li.set(t,this.constructor.DATA_KEY,this);this._element.ownerDocument.documentElement.contains(this.tip)||(h.append(t),n.trigger(this._element,this.constructor.Event.INSERTED));this._popper?this._popper.update():this._popper=sf(this._element,t,this._getPopperConfig(u));t.classList.add(gi);const f=this._resolvePossibleFunction(this._config.customClass);f&&t.classList.add(...f.split(" "));"ontouchstart"in document.documentElement&&[].concat(...document.body.children).forEach(t=>{n.on(t,"mouseover",fr)});const c=()=>{const t=this._hoverState;this._hoverState=null;n.trigger(this._element,this.constructor.Event.SHOWN);t===pf&&this._leave(null,this)},l=this.tip.classList.contains(gr);this._queueCallback(c,this.tip,l)}}}hide(){if(this._popper){const t=this.getTipElement(),i=()=>{this._isWithActiveTrigger()||(this._hoverState!==nr&&t.remove(),this._cleanTipClass(),this._element.removeAttribute("aria-describedby"),n.trigger(this._element,this.constructor.Event.HIDDEN),this._disposePopper())},r=n.trigger(this._element,this.constructor.Event.HIDE);if(!r.defaultPrevented){t.classList.remove(gi);"ontouchstart"in document.documentElement&&[].concat(...document.body.children).forEach(t=>n.off(t,"mouseover",fr));this._activeTrigger[kk]=!1;this._activeTrigger[wf]=!1;this._activeTrigger[tr]=!1;const u=this.tip.classList.contains(gr);this._queueCallback(i,this.tip,u);this._hoverState=""}}}update(){this._popper!==null&&this._popper.update()}isWithContent(){return Boolean(this.getTitle())}getTipElement(){if(this.tip)return this.tip;const t=document.createElement("div");t.innerHTML=this._config.template;const n=t.children[0];return this.setContent(n),n.classList.remove(gr,gi),this.tip=n,this.tip}setContent(n){this._sanitizeAndSetContent(n,this.getTitle(),hc)}_sanitizeAndSetContent(n,i,r){const u=t.findOne(r,n);if(!i&&u){u.remove();return}this.setElementContent(u,i)}setElementContent(n,t){if(n!==null){if(ot(t)){t=it(t);this._config.html?t.parentNode!==n&&(n.innerHTML="",n.append(t)):n.textContent=t.textContent;return}this._config.html?(this._config.sanitize&&(t=oc(t,this._config.allowList,this._config.sanitizeFn)),n.innerHTML=t):n.textContent=t}}getTitle(){const n=this._element.getAttribute("data-bs-original-title")||this._config.title;return this._resolvePossibleFunction(n)}updateAttachment(n){return n==="right"?"end":n==="left"?"start":n}_initializeOnDelegatedTarget(n,t){return t||this.constructor.getOrCreateInstance(n.delegateTarget,this._getDelegateConfig())}_getOffset(){const{offset:n}=this._config;return typeof n=="string"?n.split(",").map(n=>Number.parseInt(n,10)):typeof n=="function"?t=>n(t,this._element):n}_resolvePossibleFunction(n){return typeof n=="function"?n.call(this._element):n}_getPopperConfig(n){const t={placement:n,modifiers:[{name:"flip",options:{fallbackPlacements:this._config.fallbackPlacements}},{name:"offset",options:{offset:this._getOffset()}},{name:"preventOverflow",options:{boundary:this._config.boundary}},{name:"arrow",options:{element:`.${this.constructor.NAME}-arrow`}},{name:"onChange",enabled:!0,phase:"afterWrite",fn:n=>this._handlePopperPlacementChange(n)}],onFirstUpdate:n=>{n.options.placement!==n.placement&&this._handlePopperPlacementChange(n)}};return{...t,...(typeof this._config.popperConfig=="function"?this._config.popperConfig(t):this._config.popperConfig)}}_addAttachmentClass(n){this.getTipElement().classList.add(`${this._getBasicClassPrefix()}-${this.updateAttachment(n)}`)}_getAttachment(n){return pk[n.toUpperCase()]}_setListeners(){const t=this._config.trigger.split(" ");t.forEach(t=>{if(t==="click")n.on(this._element,this.constructor.Event.CLICK,this._config.selector,n=>this.toggle(n));else if(t!==dk){const i=t===tr?this.constructor.Event.MOUSEENTER:this.constructor.Event.FOCUSIN,r=t===tr?this.constructor.Event.MOUSELEAVE:this.constructor.Event.FOCUSOUT;n.on(this._element,i,this._config.selector,n=>this._enter(n));n.on(this._element,r,this._config.selector,n=>this._leave(n))}});this._hideModalHandler=()=>{this._element&&this.hide()};n.on(this._element.closest(cc),lc,this._hideModalHandler);this._config.selector?this._config={...this._config,trigger:"manual",selector:""}:this._fixTitle()}_fixTitle(){const n=this._element.getAttribute("title"),t=typeof this._element.getAttribute("data-bs-original-title");(n||t!=="string")&&(this._element.setAttribute("data-bs-original-title",n||""),!n||this._element.getAttribute("aria-label")||this._element.textContent||this._element.setAttribute("aria-label",n),this._element.setAttribute("title",""))}_enter(n,t){if(t=this._initializeOnDelegatedTarget(n,t),n&&(t._activeTrigger[n.type==="focusin"?wf:tr]=!0),t.getTipElement().classList.contains(gi)||t._hoverState===nr){t._hoverState=nr;return}if(clearTimeout(t._timeout),t._hoverState=nr,!t._config.delay||!t._config.delay.show){t.show();return}t._timeout=setTimeout(()=>{t._hoverState===nr&&t.show()},t._config.delay.show)}_leave(n,t){if(t=this._initializeOnDelegatedTarget(n,t),n&&(t._activeTrigger[n.type==="focusout"?wf:tr]=t._element.contains(n.relatedTarget)),!t._isWithActiveTrigger()){if(clearTimeout(t._timeout),t._hoverState=pf,!t._config.delay||!t._config.delay.hide){t.hide();return}t._timeout=setTimeout(()=>{t._hoverState===pf&&t.hide()},t._config.delay.hide)}}_isWithActiveTrigger(){for(const n in this._activeTrigger)if(this._activeTrigger[n])return!0;return!1}_getConfig(n){const t=i.getDataAttributes(this._element);return Object.keys(t).forEach(n=>{vk.has(n)&&delete t[n]}),n={...this.constructor.Default,...t,...(typeof n=="object"&&n?n:{})},n.container=n.container===!1?document.body:it(n.container),typeof n.delay=="number"&&(n.delay={show:n.delay,hide:n.delay}),typeof n.title=="number"&&(n.title=n.title.toString()),typeof n.content=="number"&&(n.content=n.content.toString()),p(sc,n,this.constructor.DefaultType),n.sanitize&&(n.template=oc(n.template,n.allowList,n.sanitizeFn)),n}_getDelegateConfig(){const n={};for(const t in this._config)this.constructor.Default[t]!==this._config[t]&&(n[t]=this._config[t]);return n}_cleanTipClass(){const t=this.getTipElement(),i=new RegExp(`(^|\\s)${this._getBasicClassPrefix()}\\S+`,"g"),n=t.getAttribute("class").match(i);n!==null&&n.length>0&&n.map(n=>n.trim()).forEach(n=>t.classList.remove(n))}_getBasicClassPrefix(){return ak}_handlePopperPlacementChange(n){const{state:t}=n;t&&(this.tip=t.elements.popper,this._cleanTipClass(),this._addAttachmentClass(this._getAttachment(t.placement)))}_disposePopper(){this._popper&&(this._popper.destroy(),this._popper=null)}static jQueryInterface(n){return this.each(function(){const t=si.getOrCreateInstance(this,n);if(typeof n=="string"){if(typeof t[n]=="undefined")throw new TypeError(`No method named "${n}"`);t[n]()}})}}h(si);const gk="popover",d=`.${"bs.popover"}`,nd="bs-popover",td={...si.Default,placement:"right",offset:[0,8],trigger:"click",content:"",template:' - + From 3e47be48f8baad3dbe40f0b2f1ab7babedf9f2a0 Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Thu, 18 Jan 2024 12:51:38 +0300 Subject: [PATCH 063/154] Fix MongoDB tests --- .../test/Volo.CmsKit.TestBase/CmsKitDataSeedContributor.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/cms-kit/test/Volo.CmsKit.TestBase/CmsKitDataSeedContributor.cs b/modules/cms-kit/test/Volo.CmsKit.TestBase/CmsKitDataSeedContributor.cs index a51741bdeb..19b51ccf7c 100644 --- a/modules/cms-kit/test/Volo.CmsKit.TestBase/CmsKitDataSeedContributor.cs +++ b/modules/cms-kit/test/Volo.CmsKit.TestBase/CmsKitDataSeedContributor.cs @@ -418,10 +418,10 @@ public class CmsKitDataSeedContributor : IDataSeedContributor, ITransientDepende private async Task SeedMenusAsync() { - var menuItem4 = await _menuItemRepository.InsertAsync(new MenuItem( + var menuItem4 = new MenuItem( _cmsKitTestData.MenuItem_4_With_Page_1_Id, _cmsKitTestData.MenuItem_4_With_Page_1_Name, - _cmsKitTestData.Page_1_Slug.EnsureStartsWith('/'))); + _cmsKitTestData.Page_1_Slug.EnsureStartsWith('/')); menuItem4.SetPageId(_cmsKitTestData.Page_1_Id); From 10bc25820839d48617b9c24f21c328b80c95425c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?SAL=C4=B0H=20=C3=96ZKARA?= Date: Thu, 18 Jan 2024 13:45:38 +0300 Subject: [PATCH 064/154] Update docs-nav.json --- docs/en/docs-nav.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/docs-nav.json b/docs/en/docs-nav.json index 8e766c7430..86b58938aa 100644 --- a/docs/en/docs-nav.json +++ b/docs/en/docs-nav.json @@ -1085,7 +1085,7 @@ }, { "text": "Account Module", - "path": "UI/Angular/Account-Module" + "path": "UI/Angular/Account-Module.md" } ] }, From d906c6832170d131dc93fa53be2172564e7b0a8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sinan=20=C3=96zt=C3=BCrk?= Date: Thu, 18 Jan 2024 14:19:08 +0300 Subject: [PATCH 065/154] add new methods to abstract class and oauth.service --- .../core/src/lib/abstracts/auth.service.ts | 30 ++++++++++++++++++- .../oauth/src/lib/services/oauth.service.ts | 16 ++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/npm/ng-packs/packages/core/src/lib/abstracts/auth.service.ts b/npm/ng-packs/packages/core/src/lib/abstracts/auth.service.ts index 8527232d5f..024f4ba413 100644 --- a/npm/ng-packs/packages/core/src/lib/abstracts/auth.service.ts +++ b/npm/ng-packs/packages/core/src/lib/abstracts/auth.service.ts @@ -31,7 +31,7 @@ export class AuthService implements IAuthService { return of(undefined); } - navigateToLogin(queryParams?: Params): void {} + navigateToLogin(queryParams?: Params): void { } get isInternalAuth(): boolean { throw new Error('not implemented'); @@ -50,6 +50,26 @@ export class AuthService implements IAuthService { console.log({ grantType, parameters, headers }); return Promise.reject(new Error('not implemented')); } + + getAccessTokenExpiration(): number { + this.warningMessage(); + return 0; + } + + getRefreshToken(): string { + this.warningMessage(); + return ''; + } + + getAccessToken(): string { + this.warningMessage(); + return ''; + } + + refreshToken(): Promise { + this.warningMessage(); + return Promise.resolve(undefined); + } } export interface IAuthService { @@ -70,4 +90,12 @@ export interface IAuthService { parameters: object, headers?: HttpHeaders, ): Promise; + + getAccessTokenExpiration(): number; + + getRefreshToken(): string; + + getAccessToken(): string; + + refreshToken(): void; } diff --git a/npm/ng-packs/packages/oauth/src/lib/services/oauth.service.ts b/npm/ng-packs/packages/oauth/src/lib/services/oauth.service.ts index 2e615c95a5..aea8fa1167 100644 --- a/npm/ng-packs/packages/oauth/src/lib/services/oauth.service.ts +++ b/npm/ng-packs/packages/oauth/src/lib/services/oauth.service.ts @@ -83,4 +83,20 @@ export class AbpOAuthService implements IAuthService { return this.oAuthService.fetchTokenUsingGrant(grantType, p, headers); } + + getRefreshToken(): string { + return this.oAuthService.getRefreshToken(); + } + + getAccessToken(): string { + return this.oAuthService.getAccessToken(); + } + + refreshToken(): Promise { + return this.oAuthService.refreshToken(); + } + + getAccessTokenExpiration(): number { + return this.oAuthService.getAccessTokenExpiration(); + } } From 77c134e78fef762db7efe60bfccfa11d7b2dafb7 Mon Sep 17 00:00:00 2001 From: halimekarayay Date: Thu, 18 Jan 2024 15:24:31 +0300 Subject: [PATCH 066/154] customScroll right value changed --- .../Pages/Documents/Shared/Styles/vs.css | 11 +++++++---- .../Pages/Documents/Shared/Styles/vs.css.map | 2 +- .../Pages/Documents/Shared/Styles/vs.scss | 4 ++++ 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.css b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.css index 5d8178c46c..1f0d159922 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.css +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.css @@ -303,6 +303,9 @@ body.scrolledMore .alert-criteria p.alert-p { .docs-page .docs-sidebar .docs-tree-list ul li.selected-tree.last-link > span .fa { transform: rotate(0deg); } +.docs-page .docs-sidebar .docs-tree-list .mCSB_scrollTools { + right: -20px; +} .docs-page .docs-content { display: inline-block; overflow-x: scroll; @@ -479,7 +482,7 @@ body.scrolledMore .alert-criteria p.alert-p { margin-bottom: 1rem; margin-left: 0; padding: 1em 1.5em; - background-color: rgb(227, 237, 242); + background-color: #e3edf2; font-size: 1em; border-radius: 12px; color: #385766; @@ -546,7 +549,7 @@ body.scrolledMore .alert-criteria p.alert-p { background-color: #f4f6fa; border-color: #f4f6fa; border-radius: 12px; - background: hsla(199, 59%, 84%, 0.82); + background: rgba(190, 223, 238, 0.82); -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px); z-index: 3; @@ -664,7 +667,7 @@ body.scrolledMore .alert-criteria p.alert-p { display: none; } body .close-mmenu, - body .close-dmenu { +body .close-dmenu { position: absolute; top: -78px; left: 25px; @@ -717,7 +720,7 @@ body.scrolledMore .alert-criteria p.alert-p { display: none; } .docs-page .docs-sidebar .docs-top .navbar.navbar-logo .navbar-collapse { - background: rgb(56, 0, 61); + background: #38003d; position: fixed; top: 86px; left: 0; diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.css.map b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.css.map index de45ccb3da..9892f76098 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.css.map +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.css.map @@ -1 +1 @@ -{"version":3,"sourceRoot":"","sources":["vs.scss"],"names":[],"mappings":"AAGA;EACI;EACA;;AAEA;EACI;EACA;;AAIJ;EACI;;AAGJ;EACI;EACA;;AAGJ;EACI;;AAGJ;EACI;;AAGJ;EACI;EACA;EACA;;AAIA;EACI;;AAGJ;AAAA;AAAA;AAAA;EAII;;AAIR;AAAA;EAEI;;AAGJ;EACI;;AAEA;EACI;;AAEJ;EACI;;AAIR;AAAA;EAEI;EACA;EACA;;AAGJ;EACI;;AAEA;EACI;EACA;EACA;EACA;EACA;;AAEA;EACI;;;AAMhB;EACI;;AAEA;EACI;EACA;EACA,KA9FK;EA+FL,QA/FK;EAgGL;EACA;EACA;EACA;EACA;EACA;EACA;;AAIQ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA;;AAIR;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;;AAMhB;EACI;;AAEA;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;;AAGJ;EACI;EACA;;AAEJ;EACI;;AAEA;EACI;EACA;;AAGJ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;;AAIR;AAAA;EAEI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;AAAA;AAAA;AAAA;AAAA;EAII;;AAIR;EACI;EACA;;AAEJ;EACI;EACA;;AAEA;EACI;;AAIR;EACI;;AAEA;EAII;;AAIR;EACI;EACA;EACA;;AAIR;EACI;;AAIR;EAEI;EACA;;AAEA;EACI;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;;AAKZ;EACI;EACA;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA;EACA;;AAEA;EACI;;AAGJ;EACI;EACA;;AAIR;EACI;EACA;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGI;EACI;;AAIR;EACI;;AAIR;EACI;;AAGI;EACI;;AAGJ;EACI;;AAGI;EACI;;AAQhB;EACI;EACA;;AAIA;EACI;EACA;;AAMA;EACI;;AAUhC;EACI;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;;AAGJ;EACI;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;;AACA;EACI;EACA;EACA;EACA;EACA;;AAMA;EACI;EACA;EACA;EACA;EACA;;AACA;EACI;;AAEJ;EACI;EACA;;AAMhB;EACI;EACA;EACA;EACA;EACA;;AAEA;EACI;;AAEJ;EACI;;AAGJ;EACI;EACA;;AAKZ;EACI;EACA;;AAEA;EACI;;AAEA;EACI;;AAGJ;EACI;EACA;;AAIR;EACI;EACA;EACA;;AAEA;EACI;;AAGJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;EACA;EACA;;AAKJ;EACI;EACA;EACA;;AAGJ;EACI;;AAEA;EACI;EACA;EACA;EACA;EACA;EACA;EACA;;AAMA;EACI;;AAQhB;EACI;;AAGJ;EACI;EACA;;AAEA;EACI;EACA;EACA;;AAGJ;EACI;EACA;EACA;;AAGJ;AAAA;AAAA;AAAA;EAII;EACA;EACA;;AAGJ;AAAA;AAAA;AAAA;AAAA;AAAA;EAMI;EACA;;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;EACI;EACA;EACA;EACA;EACA;EACA;EACA;;AAIA;AAAA;AAAA;AAAA;AAAA;AAAA;EACI;;AAKZ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;;AAGI;EACI;;AAIR;EACI;;AAGJ;AAAA;EAEI;EACA;;AAGJ;EACI;EACA;;AAGJ;EACI;;AAGJ;EACI;;AAKZ;EACI;EACA;EACA;EACA;;AACA;EACI;EACA;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AACA;EACI;;AAKZ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;;AAMR;EACI;EACA;;AAEA;EACI;;AAIR;EACI;EACA;EACA;;AAKZ;EACI;EACA;;AAEA;EACI;EACA;EACA,KAnsBC;EAosBD;EACA;EACA;;AAGI;EACI;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA;;AAMA;EACI;;AAMA;EACI;;AAQxB;EACI;;AAIR;EACI;;AAGJ;EACI;EACA;EACA;EACA;EACA;;AAEA;EACI;;AAIR;EACI;EACA;EACA;EACA;EACA,eA/wBC;EAgxBD;;AAEA;EACI;EACA;EACA;;AACA;EACI;;AAGR;EACI;EACA,SA7xBH;;AA+xBD;EACI;EACA;EACA;;AAGJ;EACI;;;AAMhB;EACI;IACI;;EAEA;IACI;;EAGJ;IACI;;EAGJ;AAAA;IAEI;IACA;IACA;IACA;IACA;IACA;IACA;;EAQR;IACI;;EAEA;IACI;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;;EAGI;IACI;IACA;IACA;IACA;;EAEA;IACI;IACA;IACA;IACA;IACA;IACA;IACA;IACA;;EAEA;IACI;;EAIR;IACI;;EAGJ;IACI;IACA;;EAGJ;IACI;IACA;IACA;IACA;IACA;IACA;IACA;IACA;;EAEA;IACI;IACA;IACA;;EAEA;IACI;;EAKZ;IACI;IACA;IACA;IACA;IACA;IACA;IACA;IACA;;EAIR;IACI;IACA;IACA;;EAIR;IACI;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;;EAEA;IACI;;EAKZ;IACI;IACA;IACA;IACA;IACA;;EAEA;IACI;;EAGJ;IACI;;EAIA;IACI;;EAEJ;IACI;;EAGJ;IACI;IACA;IACA;IACA;;EAGJ;IACI;IACA;IACA;IACA;;EAKZ;IACI;IACA;IACA;;EAEA;IACI;IACA;;EAIR;IACI;;EAEA;IACI;;;AAMhB;EAIgB;IACI;;EAEJ;IACI;;EAMI;IACI;IACA;;;AAS5B;EAEQ;IACI;IACA;;EAEJ;IAII;;EAHA;IACI;;;AAOhB;EAEQ;IACI;IACA;IACA;IACA;;EAEA;IACI;IACA;IACA","file":"vs.css"} \ No newline at end of file +{"version":3,"sourceRoot":"","sources":["vs.scss"],"names":[],"mappings":"AAGA;EACI;EACA;;AAEA;EACI;EACA;;AAIJ;EACI;;AAGJ;EACI;EACA;;AAGJ;EACI;;AAGJ;EACI;;AAGJ;EACI;EACA;EACA;;AAIA;EACI;;AAGJ;AAAA;AAAA;AAAA;EAII;;AAIR;AAAA;EAEI;;AAGJ;EACI;;AAEA;EACI;;AAEJ;EACI;;AAIR;AAAA;EAEI;EACA;EACA;;AAGJ;EACI;;AAEA;EACI;EACA;EACA;EACA;EACA;;AAEA;EACI;;;AAMhB;EACI;;AAEA;EACI;EACA;EACA,KA9FK;EA+FL,QA/FK;EAgGL;EACA;EACA;EACA;EACA;EACA;EACA;;AAIQ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA;;AAIR;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;;AAMhB;EACI;;AAEA;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;;AAGJ;EACI;EACA;;AAEJ;EACI;;AAEA;EACI;EACA;;AAGJ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;;AAIR;AAAA;EAEI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;AAAA;AAAA;AAAA;AAAA;EAII;;AAIR;EACI;EACA;;AAEJ;EACI;EACA;;AAEA;EACI;;AAIR;EACI;;AAEA;EAII;;AAIR;EACI;EACA;EACA;;AAIR;EACI;;AAIR;EAEI;EACA;;AAEA;EACI;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;;AAKZ;EACI;EACA;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA;EACA;;AAEA;EACI;;AAGJ;EACI;EACA;;AAIR;EACI;EACA;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGI;EACI;;AAIR;EACI;;AAIR;EACI;;AAGI;EACI;;AAGJ;EACI;;AAGI;EACI;;AAQhB;EACI;EACA;;AAIA;EACI;EACA;;AAMA;EACI;;AAOpB;EACI;;AAKhB;EACI;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;;AAGJ;EACI;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;;AACA;EACI;EACA;EACA;EACA;EACA;;AAMA;EACI;EACA;EACA;EACA;EACA;;AACA;EACI;;AAEJ;EACI;EACA;;AAMhB;EACI;EACA;EACA;EACA;EACA;;AAEA;EACI;;AAEJ;EACI;;AAGJ;EACI;EACA;;AAKZ;EACI;EACA;;AAEA;EACI;;AAEA;EACI;;AAGJ;EACI;EACA;;AAIR;EACI;EACA;EACA;;AAEA;EACI;;AAGJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;EACA;EACA;;AAKJ;EACI;EACA;EACA;;AAGJ;EACI;;AAEA;EACI;EACA;EACA;EACA;EACA;EACA;EACA;;AAMA;EACI;;AAQhB;EACI;;AAGJ;EACI;EACA;;AAEA;EACI;EACA;EACA;;AAGJ;EACI;EACA;EACA;;AAGJ;AAAA;AAAA;AAAA;EAII;EACA;EACA;;AAGJ;AAAA;AAAA;AAAA;AAAA;AAAA;EAMI;EACA;;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;EACI;EACA;EACA;EACA;EACA;EACA;EACA;;AAIA;AAAA;AAAA;AAAA;AAAA;AAAA;EACI;;AAKZ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;;AAGI;EACI;;AAIR;EACI;;AAGJ;AAAA;EAEI;EACA;;AAGJ;EACI;EACA;;AAGJ;EACI;;AAGJ;EACI;;AAKZ;EACI;EACA;EACA;EACA;;AACA;EACI;EACA;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AACA;EACI;;AAKZ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;;AAMR;EACI;EACA;;AAEA;EACI;;AAIR;EACI;EACA;EACA;;AAKZ;EACI;EACA;;AAEA;EACI;EACA;EACA,KAtsBC;EAusBD;EACA;EACA;;AAGI;EACI;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA;;AAMA;EACI;;AAMA;EACI;;AAQxB;EACI;;AAIR;EACI;;AAGJ;EACI;EACA;EACA;EACA;EACA;;AAEA;EACI;;AAIR;EACI;EACA;EACA;EACA;EACA,eAlxBC;EAmxBD;;AAEA;EACI;EACA;EACA;;AACA;EACI;;AAGR;EACI;EACA,SAhyBH;;AAkyBD;EACI;EACA;EACA;;AAGJ;EACI;;;AAMhB;EACI;IACI;;EAEA;IACI;;EAGJ;IACI;;EAGJ;AAAA;IAEI;IACA;IACA;IACA;IACA;IACA;IACA;;EAQR;IACI;;EAEA;IACI;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;;EAGI;IACI;IACA;IACA;IACA;;EAEA;IACI;IACA;IACA;IACA;IACA;IACA;IACA;IACA;;EAEA;IACI;;EAIR;IACI;;EAGJ;IACI;IACA;;EAGJ;IACI;IACA;IACA;IACA;IACA;IACA;IACA;IACA;;EAEA;IACI;IACA;IACA;;EAEA;IACI;;EAKZ;IACI;IACA;IACA;IACA;IACA;IACA;IACA;IACA;;EAIR;IACI;IACA;IACA;;EAIR;IACI;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;;EAEA;IACI;;EAMZ;IACI;IACA;IACA;IACA;IACA;;EAEA;IACI;;EAGJ;IACI;;EAIA;IACI;;EAEJ;IACI;;EAGJ;IACI;IACA;IACA;IACA;;EAGJ;IACI;IACA;IACA;IACA;;EAKZ;IACI;IACA;IACA;;EAEA;IACI;IACA;;EAIR;IACI;;EAEA;IACI;;;AAMhB;EAIgB;IACI;;EAEJ;IACI;;EAMI;IACI;IACA;;;AAS5B;EAEQ;IACI;IACA;;EAEJ;IAII;;EAHA;IACI;;;AAOhB;EAEQ;IACI;IACA;IACA;IACA;;EAEA;IACI;IACA;IACA","file":"vs.css"} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.scss b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.scss index 85ea8092b9..5e5b11804b 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.scss +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.scss @@ -382,6 +382,9 @@ body { } } } + .mCSB_scrollTools{ + right: -20px; + } } } @@ -941,6 +944,7 @@ body { .docs-filter { padding: 0 0 1rem !important; } + } } From a20526255866275bfa0bb1262ad004d83aef5cf9 Mon Sep 17 00:00:00 2001 From: halimekarayay Date: Thu, 18 Jan 2024 17:04:32 +0300 Subject: [PATCH 067/154] improvements for docs module --- .../Pages/Documents/Shared/Styles/vs.css | 12 ++++++------ .../Pages/Documents/Shared/Styles/vs.scss | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.css b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.css index 5d8178c46c..304dad0c4e 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.css +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.css @@ -371,7 +371,7 @@ body.scrolledMore .alert-criteria p.alert-p { color: #3e9fcb; } .docs-page .docs-content .docs-link-btns a .text-muted { - color: rgba(11, 22, 33, 0.3) !important; + color: rgba(11, 22, 33, 0.6) !important; } .docs-page .docs-content .docs-link-btns a:hover { color: #3e9fcb; @@ -479,7 +479,7 @@ body.scrolledMore .alert-criteria p.alert-p { margin-bottom: 1rem; margin-left: 0; padding: 1em 1.5em; - background-color: rgb(227, 237, 242); + background-color: #e3edf2; font-size: 1em; border-radius: 12px; color: #385766; @@ -546,7 +546,7 @@ body.scrolledMore .alert-criteria p.alert-p { background-color: #f4f6fa; border-color: #f4f6fa; border-radius: 12px; - background: hsla(199, 59%, 84%, 0.82); + background: rgba(190, 223, 238, 0.82); -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px); z-index: 3; @@ -585,7 +585,7 @@ body.scrolledMore .alert-criteria p.alert-p { } .docs-page .docs-page-index .docs-inner-anchors .navbar .nav-pills .nav-link { padding: 3px 14px 4px; - color: #aaa; + color: #726d6d; line-height: 1.2; position: relative; border-left: 1px solid #eee; @@ -664,7 +664,7 @@ body.scrolledMore .alert-criteria p.alert-p { display: none; } body .close-mmenu, - body .close-dmenu { +body .close-dmenu { position: absolute; top: -78px; left: 25px; @@ -717,7 +717,7 @@ body.scrolledMore .alert-criteria p.alert-p { display: none; } .docs-page .docs-sidebar .docs-top .navbar.navbar-logo .navbar-collapse { - background: rgb(56, 0, 61); + background: #38003d; position: fixed; top: 86px; left: 0; diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.scss b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.scss index 85ea8092b9..4575d96c1f 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.scss +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.scss @@ -464,7 +464,7 @@ body { color: #3e9fcb; .text-muted { - color: rgb(11 22 33 / 30%) !important; + color: rgb(11 22 33 / 60%) !important; } &:hover { @@ -719,7 +719,7 @@ body { .nav-link { padding: 3px 14px 4px; - color: #aaa; + color: #726d6d; line-height: 1.2; position: relative; border-left: 1px solid #eee; From 9a1f489dbadd8d7605886c1c882d0e2f33e45f19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sinan=20=C3=96zt=C3=BCrk?= Date: Fri, 19 Jan 2024 10:16:22 +0300 Subject: [PATCH 068/154] set return type of refreshToken() method in interface --- npm/ng-packs/packages/core/src/lib/abstracts/auth.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/npm/ng-packs/packages/core/src/lib/abstracts/auth.service.ts b/npm/ng-packs/packages/core/src/lib/abstracts/auth.service.ts index 024f4ba413..fd28a88e68 100644 --- a/npm/ng-packs/packages/core/src/lib/abstracts/auth.service.ts +++ b/npm/ng-packs/packages/core/src/lib/abstracts/auth.service.ts @@ -97,5 +97,5 @@ export interface IAuthService { getAccessToken(): string; - refreshToken(): void; + refreshToken(): Promise; } From 3214c802fb087fee11b16acadee61ad5b550730d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sinan=20=C3=96zt=C3=BCrk?= Date: Fri, 19 Jan 2024 11:16:52 +0300 Subject: [PATCH 069/154] remove remember_me from localstorage before routing and use double exclamation --- .../oauth/src/lib/strategies/auth-code-flow-strategy.ts | 4 ++-- .../oauth/src/lib/strategies/auth-password-flow-strategy.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/npm/ng-packs/packages/oauth/src/lib/strategies/auth-code-flow-strategy.ts b/npm/ng-packs/packages/oauth/src/lib/strategies/auth-code-flow-strategy.ts index 5a1b2c3d05..ced281253d 100644 --- a/npm/ng-packs/packages/oauth/src/lib/strategies/auth-code-flow-strategy.ts +++ b/npm/ng-packs/packages/oauth/src/lib/strategies/auth-code-flow-strategy.ts @@ -25,9 +25,9 @@ export class AuthCodeFlowStrategy extends AuthFlowStrategy { const rememberMeValue = this.rememberMeService.getFromToken(accessToken); if (rememberMeValue) { - this.rememberMeService.set(true); + this.rememberMeService.set(!!rememberMeValue); } else { - this.rememberMeService.set(false) + this.rememberMeService.set(!!rememberMeValue) } } diff --git a/npm/ng-packs/packages/oauth/src/lib/strategies/auth-password-flow-strategy.ts b/npm/ng-packs/packages/oauth/src/lib/strategies/auth-password-flow-strategy.ts index eddf38a03e..9c38c64e27 100644 --- a/npm/ng-packs/packages/oauth/src/lib/strategies/auth-password-flow-strategy.ts +++ b/npm/ng-packs/packages/oauth/src/lib/strategies/auth-password-flow-strategy.ts @@ -74,8 +74,8 @@ export class AuthPasswordFlowStrategy extends AuthFlowStrategy { return from(this.oAuthService.revokeTokenAndLogout(noRedirectToLogoutUrl)).pipe( switchMap(() => this.configState.refreshAppState()), tap(() => { - router.navigateByUrl('/'); this.rememberMeService.remove(); + router.navigateByUrl('/'); }), ); } From 254ff8c52e3291a65ab90747448f71a4466856d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sinan=20=C3=96zt=C3=BCrk?= Date: Fri, 19 Jan 2024 11:52:06 +0300 Subject: [PATCH 070/154] remove unnecesarry if block --- .../oauth/src/lib/strategies/auth-code-flow-strategy.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/npm/ng-packs/packages/oauth/src/lib/strategies/auth-code-flow-strategy.ts b/npm/ng-packs/packages/oauth/src/lib/strategies/auth-code-flow-strategy.ts index ced281253d..f648be47c6 100644 --- a/npm/ng-packs/packages/oauth/src/lib/strategies/auth-code-flow-strategy.ts +++ b/npm/ng-packs/packages/oauth/src/lib/strategies/auth-code-flow-strategy.ts @@ -24,11 +24,7 @@ export class AuthCodeFlowStrategy extends AuthFlowStrategy { if (accessToken && !rememberMe) { const rememberMeValue = this.rememberMeService.getFromToken(accessToken); - if (rememberMeValue) { - this.rememberMeService.set(!!rememberMeValue); - } else { - this.rememberMeService.set(!!rememberMeValue) - } + this.rememberMeService.set(!!rememberMeValue); } rememberMe = this.rememberMeService.get(); From 1c98a3bc3105ba96d427876eae5fd5113137f0a4 Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Fri, 19 Jan 2024 16:09:31 +0300 Subject: [PATCH 071/154] Make Url of MenuItem as Required in DTOs --- .../Volo/CmsKit/Admin/Menus/MenuItemCreateInput.cs | 1 + .../Volo/CmsKit/Admin/Menus/MenuItemUpdateInput.cs | 1 + 2 files changed, 2 insertions(+) diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Menus/MenuItemCreateInput.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Menus/MenuItemCreateInput.cs index f5ec9c6444..ebb312699a 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Menus/MenuItemCreateInput.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Menus/MenuItemCreateInput.cs @@ -14,6 +14,7 @@ public class MenuItemCreateInput : ExtensibleObject public bool IsActive { get; set; } + [Required] public string Url { get; set; } public string Icon { get; set; } diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Menus/MenuItemUpdateInput.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Menus/MenuItemUpdateInput.cs index 8767a6192a..b51903359c 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Menus/MenuItemUpdateInput.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Menus/MenuItemUpdateInput.cs @@ -13,6 +13,7 @@ public class MenuItemUpdateInput : ExtensibleObject, IHasConcurrencyStamp public bool IsActive { get; set; } + [Required] public string Url { get; set; } public string Icon { get; set; } From 2c37566528661e66fd814c837b47915cda4633ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sinan=20=C3=96zt=C3=BCrk?= Date: Fri, 19 Jan 2024 18:36:59 +0300 Subject: [PATCH 072/154] update documentation, deprecate HTTP_ERROR_HANDLER injection token --- docs/en/UI/Angular/HTTP-Error-Handling.md | 100 +++++++++++++ docs/en/UI/Angular/HTTP-Requests.md | 140 +----------------- docs/en/docs-nav.json | 15 +- .../src/lib/handlers/error.handler.ts | 12 +- .../lib/providers/error-handlers.provider.ts | 8 +- .../src/lib/tokens/http-error.token.ts | 3 + 6 files changed, 132 insertions(+), 146 deletions(-) create mode 100644 docs/en/UI/Angular/HTTP-Error-Handling.md diff --git a/docs/en/UI/Angular/HTTP-Error-Handling.md b/docs/en/UI/Angular/HTTP-Error-Handling.md new file mode 100644 index 0000000000..8bf2589204 --- /dev/null +++ b/docs/en/UI/Angular/HTTP-Error-Handling.md @@ -0,0 +1,100 @@ +# HTTP Error Handling + +When the `RestService` is used, all HTTP errors are reported to the [`HttpErrorReporterService`](./HTTP-Error-Reporter-Service), and then `ErrorHandler`, a service exposed by the `@abp/ng.theme.shared` package automatically handles the errors. + +## Custom HTTP Error Handler + +A custom HTTP error handler service can be registered to an injection token named **`CUSTOM_ERROR_HANDLERS`**. ABP has some default error handlers, you can see them [here](https://github.com/abpframework/abp/blob/dev/npm/ng-packs/packages/theme-shared/src/lib/providers/error-handlers.provider.ts). + +### How ABP handles errors and How to add new one? + +- First of all it will be better to understand how ABP handles errors. +- ABP error handler services are implements the interface of **CustomHttpErrorHandlerService**. + +**Interface of `CUSTOM_ERROR_HANDLERS`** + +```ts +interface CustomHttpErrorHandlerService { + readonly priority: number; + canHandle(error: unknown): boolean; + execute(): void; +} +``` + +- **`priority`** ABP sorts the services according to the number of the priority variable. Higher priority will be checked first. You can think this as a z-index property in CSS. +- **`canHandle(error: unknown): boolean :`** Check if the service can handle the error. Returns boolean. +- **`execute(): void :`** If the service can handle the error, then run the execute method. + +**In Summarry** + +- Services are sorted by their priority number. +- Start from highest priority service and run canHandle() method. Pick the service if can handle the error, if not check next service. +- If the service found, run the execute method of a service. Done. + +See an example: + +```ts +// custom-error-handler.service.ts +import { inject, Injectable } from "@angular/core"; +import { HttpErrorResponse } from "@angular/common/http"; +import { CustomHttpErrorHandlerService } from "@abp/ng.theme.shared"; +import { CUSTOM_HTTP_ERROR_HANDLER_PRIORITY } from "@abp/ng.theme.shared"; +import { ToasterService } from "@abp/ng.theme.shared"; + +@Injectable({ providedIn: "root" }) +export class MyCustomErrorHandlerService + implements CustomHttpErrorHandlerService +{ + + // You can write any number here, ex: 9999 + readonly priority = CUSTOM_HTTP_ERROR_HANDLER_PRIORITY.veryHigh; + private toaster = inject(ToasterService); + private error: HttpErrorResponse | undefined = undefined; + + // What kind of error should be handled by this service? You can decide it in this method. If error is suitable to your case then return true; otherwise return false. + canHandle(error: unknown): boolean { + if (error instanceof HttpErrorResponse && error.status === 400) { + this.error = error; + return true; + } + return false; + } + + // If this service is picked from ErrorHandler, this execute method will be called. + execute() { + this.toaster.error( + this.error.error?.error?.message || "Bad request!", + "400" + ); + } +} +``` + +```ts + +// app.module.ts +import { CUSTOM_ERROR_HANDLERS, ... } from '@abp/ng.theme.shared'; +import { MyCustomErrorHandlerService } from './custom-error-handler.service'; + +@NgModule({ + // ... + providers: [ + // ... + { provide: CUSTOM_ERROR_HANDLERS, useExisting: MyCustomErrorHandlerService, multi: true } + ] +}) +export class AppModule {} +``` + +In the example above: + +- Created a service named `MyCustomErrorHandlerService`, and provided via `useExisting` key because we dont want another instance of it. And set `multi` key to true because ABP default error handlers are also provided with **CUSTOM_ERROR_HANDLERS** injection token. + +- 400 errors are handled from custom `MyCustomErrorHandlerService`. When a 400 error occurs, backend error message will be displayed as shown below: + +![custom-error-handler-toaster-message](images/custom-error-handler-toaster-message.jpg) + +**Note 1:** If your service cannot handle the error. Then ABP will check the next Error Service. +**Note 2:** If none of the service handle the error. Then basic confirmation message about the error will be shown to the user. +**Note 3:** You can provide more than one service, with CUSTOM_ERROR_HANDLER injection token. +**Note 4:** If you want your custom service to be evaluated (checked) earlier, set the priority variable high. diff --git a/docs/en/UI/Angular/HTTP-Requests.md b/docs/en/UI/Angular/HTTP-Requests.md index b524b4a8ee..c58e35fc51 100644 --- a/docs/en/UI/Angular/HTTP-Requests.md +++ b/docs/en/UI/Angular/HTTP-Requests.md @@ -1,7 +1,5 @@ # How to Make HTTP Requests - - ## About HttpClient Angular has the amazing [HttpClient](https://angular.io/guide/http) for communication with backend services. It is a layer on top and a simplified representation of [XMLHttpRequest Web API](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest). It also is the recommended agent by Angular for any HTTP request. There is nothing wrong with using the `HttpClient` in your ABP project. @@ -23,14 +21,10 @@ Although clear and flexible, handling errors this way is repetitive work, even w An `HttpInterceptor` is able to catch `HttpErrorResponse` and can be used for a centralized error handling. Nevertheless, cases where default error handler, therefore the interceptor, must be disabled require additional work and comprehension of Angular internals. Check [this issue](https://github.com/angular/angular/issues/20203) for details. - - ## RestService ABP core module has a utility service for HTTP requests: `RestService`. Unless explicitly configured otherwise, it catches HTTP errors and dispatches a `RestOccurError` action. This action is then captured by the `ErrorHandler` introduced by the `ThemeSharedModule`. Since you should already import this module in your app, when the `RestService` is used, all HTTP errors get automatically handled by default. - - ### Getting Started with RestService In order to use the `RestService`, you must inject it in your class as a dependency. @@ -48,11 +42,9 @@ class DemoService { You do not have to provide the `RestService` at module or component/directive level, because it is already **provided in root**. - - ### How to Make a Request with RestService -You can use the `request` method of the `RestService` is for HTTP requests. Here is an example: +You can use the `request` method of the `RestService` is for HTTP requests. Here is an example: ```js getFoo(id: number) { @@ -65,8 +57,6 @@ getFoo(id: number) { } ``` - - The `request` method always returns an `Observable`. Therefore you can do the following wherever you use `getFoo` method: ```js @@ -79,12 +69,8 @@ doSomethingWithFoo(id: number) { } ``` - - **You do not have to worry about unsubscription.** The `RestService` uses `HttpClient` behind the scenes, so every observable it returns is a finite observable, i.e. it closes subscriptions automatically upon success or error. - - As you see, `request` method gets a request options object with `Rest.Request` type. This generic type expects the interface of the request body. You may pass `null` when there is no body, like in a `GET` or a `DELETE` request. Here is an example where there is one: ```js @@ -99,11 +85,7 @@ postFoo(body: Foo) { } ``` - - -You may [check here](https://github.com/abpframework/abp/blob/dev/npm/ng-packs/packages/core/src/lib/models/rest.ts#L23) for complete `Rest.Request` type, which has only a few changes compared to [HttpRequest](https://angular.io/api/common/http/HttpRequest) class in Angular. - - +You may [check here](https://github.com/abpframework/abp/blob/dev/npm/ng-packs/packages/core/src/lib/models/rest.ts#L23) for complete `Rest.Request` type, which has only a few changes compared to [HttpRequest](https://angular.io/api/common/http/HttpRequest) class in Angular. ### How to Disable Default Error Handler of RestService @@ -120,8 +102,6 @@ deleteFoo(id: number) { } ``` - - `skipHandleError` config option, when set to `true`, disables the error handler and the returned observable starts throwing an error that you can catch in your subscription. ```js @@ -137,14 +117,10 @@ removeFooFromList(id: number) { } ``` - - ### How to Get a Specific API Endpoint From Application Config Another nice config option that `request` method receives is `apiName` (available as of v2.4), which can be used to get a specific module endpoint from application configuration. - - ```js putFoo(body: Foo, id: string) { const request: Rest.Request = { @@ -157,8 +133,6 @@ putFoo(body: Foo, id: string) { } ``` - - `putFoo` above will request `https://localhost:44305/api/some/path/to/foo/{id}` as long as the environment variables are as follows: ```js @@ -167,19 +141,17 @@ putFoo(body: Foo, id: string) { export const environment = { apis: { default: { - url: 'https://localhost:44305', + url: "https://localhost:44305", }, foo: { - url: 'https://localhost:44305/api/some/path/to/foo', + url: "https://localhost:44305/api/some/path/to/foo", }, }, - + /* rest of the environment variables here */ -} +}; ``` - - ### How to Observe Response Object or HTTP Events Instead of Body `RestService` assumes you are generally interested in the body of a response and, by default, sets `observe` property as `'body'`. However, there may be times you are rather interested in something else, such as a custom proprietary header. For that, the `request` method receives `observe` property in its config object. @@ -202,104 +174,6 @@ getSomeCustomHeaderValue() { You may find `Rest.Observe` enum [here](https://github.com/abpframework/abp/blob/dev/npm/ng-packs/packages/core/src/lib/models/rest.ts#L10). - -## HTTP Error Handling - -When the `RestService` is used, all HTTP errors are reported to the [`HttpErrorReporterService`](./HTTP-Error-Reporter-Service), and then `ErrorHandler`, a service exposed by the `@abp/ng.theme.shared` package automatically handles the errors. - -### Custom HTTP Error Handler - -A custom HTTP error handler can be registered to an injection token named `HTTP_ERROR_HANDLER`. If a custom handler function is registered, the `ErrorHandler` executes that function. - -See an example: - -```js -// http-error-handler.ts -import { ContentProjectionService, PROJECTION_STRATEGY } from '@abp/ng.core'; -import { ToasterService } from '@abp/ng.theme.shared'; -import { HttpErrorResponse } from '@angular/common/http'; -import { Injector } from '@angular/core'; -import { of, EMPTY } from 'rxjs'; -import { Error404Component } from './error404/error404.component'; - -export function handleHttpErrors(injector: Injector, httpError: HttpErrorResponse) { - if (httpError.status === 400) { - const toaster = injector.get(ToasterService); - toaster.error(httpError.error?.error?.message || 'Bad request!', '400'); - return EMPTY; - } - - if (httpError.status === 404) { - const contentProjection = injector.get(ContentProjectionService); - contentProjection.projectContent(PROJECTION_STRATEGY.AppendComponentToBody(Error404Component)); - return EMPTY; - } - - return of(httpError); -} - -// app.module.ts -import { Error404Component } from './error404/error404.component'; -import { handleHttpErrors } from './http-error-handling'; -import { HTTP_ERROR_HANDLER, ... } from '@abp/ng.theme.shared'; - -@NgModule({ - // ... - providers: [ - // ... - { provide: HTTP_ERROR_HANDLER, useValue: handleHttpErrors } - ], - declarations: [ - //... - Error404Component], -}) -export class AppModule {} -``` - -In the example above: - - - Created a function named `handleHttpErrors` and defined as value of the `HTTP_ERROR_HANDLER` provider in app.module. After this, the function executes when an HTTP error occurs. - - 400 bad request errors is handled. When a 400 error occurs, backend error message will be displayed as shown below: - - ![custom-error-handler-toaster-message](images/custom-error-handler-toaster-message.jpg) - - - 404 not found errors is handled. When a 404 error occurs, `Error404Component` will be appended to the `` as shown below: - -![custom-error-handler-404-component](images/custom-error-handler-404-component.jpg) - - - Since `of(httpError)` is returned at bottom of the `handleHttpErrors`, the `ErrorHandler` will handle the HTTP errors except 400 and 404 errors. - - -**Note 1:** If you put `return EMPTY` to next line of handling an error, default error handling will not work for that error. `EMPTY` can be imported from `rxjs` - -```js -export function handleHttpErrors(injector: Injector, httpError: HttpErrorResponse) { - if (httpError.status === 403) { - // handle 403 errors here - return EMPTY; // put return to skip default error handling - } -} -``` - -**Note 2:** If you put `return of(httpError)`, default error handling will work. - - `of` is a function. It can be imported from `rxjs`. - - `httpError` is the second parameter of the error handler function which is registered to the `HTTP_ERROR_HANDLER` provider. Type of the `httpError` is `HttpErrorResponse`. - -```js -import { throwError } from 'rxjs'; - -export function handleHttpErrors(injector: Injector, httpError: HttpErrorResponse) { - if (httpError.status === 500) { - // handle 500 errors here - return EMPTY; - } - - // you can return the of(httpError) at bottom of the function to run the default handler of ABP for HTTP errors that you didn't handle above. - return of(httpError) -} -``` - - ### How to Skip HTTP interceptors and ABP headers The ABP Framework adds several HTTP headers to the HttpClient, such as the "Auth token" or "tenant Id". @@ -309,4 +183,4 @@ The ABP Http interceptors check the value of the `IS_EXTERNAL_REQUEST` token. If The `ExternalHttpClient` extends from `HTTPClient` and sets the `IS_EXTERNAL_REQUEST` context token to true. When you are using `ExternalHttpClient` as HttpClient in your components, it does not add ABP-specific headers. -Note: With `IS_EXTERNAL_REQUEST` or without it, ABP loading service works. +Note: With `IS_EXTERNAL_REQUEST` or without it, ABP loading service works. diff --git a/docs/en/docs-nav.json b/docs/en/docs-nav.json index 8e766c7430..be988b795c 100644 --- a/docs/en/docs-nav.json +++ b/docs/en/docs-nav.json @@ -1053,7 +1053,16 @@ }, { "text": "HTTP Requests", - "path": "UI/Angular/HTTP-Requests.md" + "items": [ + { + "text": "How to Make HTTP Requests", + "path": "UI/Angular/HTTP-Requests.md" + }, + { + "text": "HTTP Error Handling / Customization", + "path": "UI/Angular/HTTP-Error-Handling.md" + } + ] }, { "text": "Localization", @@ -1173,8 +1182,8 @@ "path": "UI/Angular/Content-Security-Strategy.md" }, { - "text":"Abp Window Service", - "path":"UI/Angular/Abp-Window-Service.md" + "text": "Abp Window Service", + "path": "UI/Angular/Abp-Window-Service.md" } ] }, diff --git a/npm/ng-packs/packages/theme-shared/src/lib/handlers/error.handler.ts b/npm/ng-packs/packages/theme-shared/src/lib/handlers/error.handler.ts index a3417900a2..168fef1f53 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/handlers/error.handler.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/handlers/error.handler.ts @@ -21,7 +21,7 @@ export class ErrorHandler { protected readonly confirmationService = inject(ConfirmationService); protected readonly routerErrorHandlerService = inject(RouterErrorHandlerService); protected readonly httpErrorConfig = inject(HTTP_ERROR_CONFIG); - protected readonly defaultErrorHandlers = inject(CUSTOM_ERROR_HANDLERS); + protected readonly customErrorHandlers = inject(CUSTOM_ERROR_HANDLERS); protected readonly httpErrorHandler = inject(HTTP_ERROR_HANDLER, { optional: true }); constructor(protected injector: Injector) { @@ -43,7 +43,7 @@ export class ErrorHandler { if (this.httpErrorHandler) { return this.httpErrorHandler(this.injector, error); } - + return of(error); }; @@ -55,17 +55,17 @@ export class ErrorHandler { } protected handleError(err: unknown) { - if (this.defaultErrorHandlers && this.defaultErrorHandlers.length) { - const errorHandlerService = this.defaultErrorHandlers + if (this.customErrorHandlers && this.customErrorHandlers.length) { + const errorHandlerService = this.customErrorHandlers .sort(this.sortHttpErrorHandlers) .find(service => service.canHandle(err)); - + if (errorHandlerService) { errorHandlerService.execute(); return; } } - + this.showError().subscribe(); } diff --git a/npm/ng-packs/packages/theme-shared/src/lib/providers/error-handlers.provider.ts b/npm/ng-packs/packages/theme-shared/src/lib/providers/error-handlers.provider.ts index 61a2a25fcd..d456c82912 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/providers/error-handlers.provider.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/providers/error-handlers.provider.ts @@ -9,21 +9,21 @@ export const DEFAULT_HANDLERS_PROVIDERS: Provider[] = [ { provide: CUSTOM_ERROR_HANDLERS, multi: true, - useClass: TenantResolveErrorHandlerService, + useExisting: TenantResolveErrorHandlerService, }, { provide: CUSTOM_ERROR_HANDLERS, multi: true, - useClass: AbpFormatErrorHandlerService, + useExisting: AbpFormatErrorHandlerService, }, { provide: CUSTOM_ERROR_HANDLERS, multi: true, - useClass: StatusCodeErrorHandlerService, + useExisting: StatusCodeErrorHandlerService, }, { provide: CUSTOM_ERROR_HANDLERS, multi: true, - useClass: UnknownStatusCodeErrorHandlerService, + useExisting: UnknownStatusCodeErrorHandlerService, }, ]; diff --git a/npm/ng-packs/packages/theme-shared/src/lib/tokens/http-error.token.ts b/npm/ng-packs/packages/theme-shared/src/lib/tokens/http-error.token.ts index a2784f4332..64245680db 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/tokens/http-error.token.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/tokens/http-error.token.ts @@ -15,6 +15,9 @@ export function httpErrorConfigFactory(config = {} as HttpErrorConfig) { export const HTTP_ERROR_CONFIG = new InjectionToken('HTTP_ERROR_CONFIG'); +/** + @deprecated use **`CUSTOM_ERROR_HANDLERS`** injection token instead of this, see more info https://docs.abp.io/en/abp/latest/UI/Angular/HTTP-Requests +*/ export const HTTP_ERROR_HANDLER = new InjectionToken('HTTP_ERROR_HANDLER'); export const CUSTOM_ERROR_HANDLERS = new InjectionToken( From 8e139403feb7f0660c3940d1adc6a2cf09c39506 Mon Sep 17 00:00:00 2001 From: maliming Date: Sat, 20 Jan 2024 09:44:44 +0800 Subject: [PATCH 073/154] Use the `ServiceIdentifier` structure to represent keyed services. --- .../ServiceProviderKeyedServiceExtensions.cs | 19 +++++++ .../CachedServiceDescriptor.cs | 45 +++++++++++++---- .../CachedServiceProviderBase.cs | 50 ++++++------------- .../ICachedServiceProviderBase.cs | 4 -- .../RootServiceProvider.cs | 16 ++---- 5 files changed, 72 insertions(+), 62 deletions(-) create mode 100644 framework/src/Volo.Abp.Core/Microsoft/Extensions/DependencyInjection/ServiceProviderKeyedServiceExtensions.cs diff --git a/framework/src/Volo.Abp.Core/Microsoft/Extensions/DependencyInjection/ServiceProviderKeyedServiceExtensions.cs b/framework/src/Volo.Abp.Core/Microsoft/Extensions/DependencyInjection/ServiceProviderKeyedServiceExtensions.cs new file mode 100644 index 0000000000..f31923f68c --- /dev/null +++ b/framework/src/Volo.Abp.Core/Microsoft/Extensions/DependencyInjection/ServiceProviderKeyedServiceExtensions.cs @@ -0,0 +1,19 @@ +using System; +using Volo.Abp; + +namespace Microsoft.Extensions.DependencyInjection; + +public static class ServiceProviderKeyedServiceExtensions +{ + public static object? GetKeyedService(this IServiceProvider provider, Type serviceType, object? serviceKey) + { + Check.NotNull(provider, nameof(provider)); + + if (provider is IKeyedServiceProvider keyedServiceProvider) + { + return keyedServiceProvider.GetKeyedService(serviceType, serviceKey); + } + + throw new InvalidOperationException("This service provider doesn't support keyed services."); + } +} diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/CachedServiceDescriptor.cs b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/CachedServiceDescriptor.cs index 1b812fc4a2..b6dbcd8a02 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/CachedServiceDescriptor.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/CachedServiceDescriptor.cs @@ -2,28 +2,53 @@ using System; namespace Volo.Abp.DependencyInjection; -public class CachedServiceDescriptor +/// +/// https://github.com/dotnet/runtime/blob/release/8.0/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceIdentifier.cs#L9 +/// +public readonly struct ServiceIdentifier : IEquatable { - private object? Key { get; } + public object? ServiceKey { get; } - private Type ServiceType { get; } + public Type ServiceType { get; } - public CachedServiceDescriptor(object? key, Type serviceType) + public ServiceIdentifier(Type serviceType) { - Key = key; ServiceType = serviceType; } + public ServiceIdentifier(object? serviceKey, Type serviceType) + { + ServiceKey = serviceKey; + ServiceType = serviceType; + } + + public bool Equals(ServiceIdentifier other) + { + if (ServiceKey == null && other.ServiceKey == null) + { + return ServiceType == other.ServiceType; + } + else if (ServiceKey != null && other.ServiceKey != null) + { + return ServiceType == other.ServiceType && ServiceKey.Equals(other.ServiceKey); + } + return false; + } + public override bool Equals(object? obj) { - return obj is CachedServiceDescriptor descriptor && - Key == descriptor.Key && - ServiceType == descriptor.ServiceType; + return obj is ServiceIdentifier && Equals((ServiceIdentifier)obj); } public override int GetHashCode() { - var keyHashCode = Key?.GetHashCode() ?? 0; - return keyHashCode ^ ServiceType.GetHashCode(); + if (ServiceKey == null) + { + return ServiceType.GetHashCode(); + } + unchecked + { + return (ServiceType.GetHashCode() * 397) ^ ServiceKey.GetHashCode(); + } } } diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/CachedServiceProviderBase.cs b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/CachedServiceProviderBase.cs index 774efedb9a..770355428e 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/CachedServiceProviderBase.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/CachedServiceProviderBase.cs @@ -7,19 +7,19 @@ namespace Volo.Abp.DependencyInjection; public abstract class CachedServiceProviderBase : ICachedServiceProviderBase { protected IServiceProvider ServiceProvider { get; } - protected ConcurrentDictionary> CachedServices { get; } + protected ConcurrentDictionary> CachedServices { get; } protected CachedServiceProviderBase(IServiceProvider serviceProvider) { ServiceProvider = serviceProvider; - CachedServices = new ConcurrentDictionary>(); - CachedServices.TryAdd(new CachedServiceDescriptor(null, typeof(IServiceProvider)), new Lazy(() => ServiceProvider)); + CachedServices = new ConcurrentDictionary>(); + CachedServices.TryAdd(new ServiceIdentifier(typeof(IServiceProvider)), new Lazy(() => ServiceProvider)); } public virtual object? GetService(Type serviceType) { return CachedServices.GetOrAdd( - new CachedServiceDescriptor(null, serviceType), + new ServiceIdentifier(serviceType), _ => new Lazy(() => ServiceProvider.GetService(serviceType)) ).Value; } @@ -42,44 +42,24 @@ public abstract class CachedServiceProviderBase : ICachedServiceProviderBase public object GetService(Type serviceType, Func factory) { return CachedServices.GetOrAdd( - new CachedServiceDescriptor(null, serviceType), + new ServiceIdentifier(serviceType), _ => new Lazy(() => factory(ServiceProvider)) ).Value!; } - public virtual T GetKeyedService(object? serviceKey) + public object? GetKeyedService(Type serviceType, object? serviceKey) { - return (T)GetKeyedService(typeof(T), serviceKey)!; - } - - public virtual object? GetKeyedService(Type serviceType, object? serviceKey) - { - if (ServiceProvider is IKeyedServiceProvider requiredServiceSupportingProvider) - { - return CachedServices.GetOrAdd( - new CachedServiceDescriptor(serviceKey, serviceType), - _ => new Lazy(() => requiredServiceSupportingProvider.GetKeyedService(serviceType, serviceKey)) - ).Value; - } - - throw new InvalidOperationException("This service provider doesn't support keyed services."); - } - - public virtual T GetRequiredKeyedService(object? serviceKey) - { - return (T)GetRequiredKeyedService(typeof(T), serviceKey); + return CachedServices.GetOrAdd( + new ServiceIdentifier(serviceKey, serviceType), + _ => new Lazy(() => ServiceProvider.GetKeyedService(serviceType, serviceKey)) + ).Value; } - public virtual object GetRequiredKeyedService(Type serviceType, object? serviceKey) + public object GetRequiredKeyedService(Type serviceType, object? serviceKey) { - if (ServiceProvider is IKeyedServiceProvider requiredServiceSupportingProvider) - { - return CachedServices.GetOrAdd( - new CachedServiceDescriptor(serviceKey, serviceType), - _ => new Lazy(() => requiredServiceSupportingProvider.GetRequiredKeyedService(serviceType, serviceKey)) - ).Value!; - } - - throw new InvalidOperationException("This service provider doesn't support keyed services."); + return CachedServices.GetOrAdd( + new ServiceIdentifier(serviceKey, serviceType), + _ => new Lazy(() => ServiceProvider.GetRequiredKeyedService(serviceType, serviceKey)) + ).Value!; } } diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/ICachedServiceProviderBase.cs b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/ICachedServiceProviderBase.cs index 6fc281f430..ceec3326cc 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/ICachedServiceProviderBase.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/ICachedServiceProviderBase.cs @@ -12,8 +12,4 @@ public interface ICachedServiceProviderBase : IKeyedServiceProvider T GetService(Func factory); object GetService(Type serviceType, Func factory); - - T GetKeyedService(object? serviceKey); - - T GetRequiredKeyedService(object? serviceKey); } diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/RootServiceProvider.cs b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/RootServiceProvider.cs index 53d5878ea4..7ba378d76a 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/RootServiceProvider.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/RootServiceProvider.cs @@ -18,23 +18,13 @@ public class RootServiceProvider : IRootServiceProvider, ISingletonDependency return ServiceProvider.GetService(serviceType); } - public virtual object? GetKeyedService(Type serviceType, object? serviceKey) + public object? GetKeyedService(Type serviceType, object? serviceKey) { - if (ServiceProvider is IKeyedServiceProvider requiredServiceSupportingProvider) - { - return requiredServiceSupportingProvider.GetKeyedService(serviceType, serviceKey); - } - - throw new InvalidOperationException("This service provider doesn't support keyed services."); + return ServiceProvider.GetKeyedService(serviceType, serviceKey); } public virtual object GetRequiredKeyedService(Type serviceType, object? serviceKey) { - if (ServiceProvider is IKeyedServiceProvider requiredServiceSupportingProvider) - { - return requiredServiceSupportingProvider.GetRequiredKeyedService(serviceType, serviceKey); - } - - throw new InvalidOperationException("This service provider doesn't support keyed services."); + return ServiceProvider.GetRequiredKeyedService(serviceType, serviceKey); } } From 98c5decc6a5347425ad890a71976016b29431a4a Mon Sep 17 00:00:00 2001 From: maliming Date: Sat, 20 Jan 2024 09:51:25 +0800 Subject: [PATCH 074/154] Rename CachedServiceDescriptor.cs to ServiceIdentifier.cs --- .../{CachedServiceDescriptor.cs => ServiceIdentifier.cs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/{CachedServiceDescriptor.cs => ServiceIdentifier.cs} (100%) diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/CachedServiceDescriptor.cs b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/ServiceIdentifier.cs similarity index 100% rename from framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/CachedServiceDescriptor.cs rename to framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/ServiceIdentifier.cs From 2218e9d7a1cb606b7b487ae771f04b2cc13c0ebb Mon Sep 17 00:00:00 2001 From: maliming Date: Sat, 20 Jan 2024 11:24:52 +0800 Subject: [PATCH 075/154] Introduce `ExposeKeyedServicesAttribute`. --- docs/en/Dependency-Injection.md | 30 +++++++++ .../ConventionalRegistrarBase.cs | 61 +++++++++++++------ .../DefaultConventionalRegistrar.cs | 17 ++++-- .../ExposeKeyedServiceAttribute.cs | 25 ++++++++ .../ExposeServicesAttribute.cs | 1 + .../ExposedServiceExplorer.cs | 21 ++++++- .../IExposedKeyedServiceTypesProvider.cs | 8 +++ .../IOnServiceExposingContext.cs | 2 +- .../OnServiceExposingContext.cs | 8 ++- .../ObjectMapping/AbpObjectMappingModule.cs | 7 ++- .../Serialization/AbpSerializationModule.cs | 7 ++- .../DependencyInjection_Tests.cs | 53 ++++++++++++++++ 12 files changed, 207 insertions(+), 33 deletions(-) create mode 100644 framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/ExposeKeyedServiceAttribute.cs create mode 100644 framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/IExposedKeyedServiceTypesProvider.cs diff --git a/docs/en/Dependency-Injection.md b/docs/en/Dependency-Injection.md index 143ec8cc19..2d042a2b2a 100644 --- a/docs/en/Dependency-Injection.md +++ b/docs/en/Dependency-Injection.md @@ -143,6 +143,36 @@ public class TaxCalculator : ITaxCalculator, ITransientDependency } ```` +### ExposeKeyedService Attribute + +``ExposeKeyedServiceAttribute`` is used to control which keyed services are provided by the related class. Example: + +````C# +[ExposeKeyedService("taxCalculator")] +[ExposeKeyedService("calculator")] +public class TaxCalculator: ICalculator, ITaxCalculator, ICanCalculate, ITransientDependency +{ +} +```` + +``TaxCalculator`` class exposes ``ITaxCalculator`` interface with the key ``tax`` and ``ICalculator`` interface with the key ``calculator``. That means you can get keyed services from the ``IServiceProvider`` as shown below: + +````C# +var taxCalculator = ServiceProvider.GetRequiredKeyedService("taxCalculator"); +var calculator = ServiceProvider.GetRequiredKeyedService("calculator"); +```` + +> Notice that the ``ExposeKeyedServiceAttribute`` is only expose keyed services. So, you can not inject ``ITaxCalculator`` or ``ICalculator`` in your application. If you want to expose both keyed and non-keyed services, you can use ``ExposeServicesAttribute`` and ``ExposeKeyedServiceAttribute`` together as shown below: + +````C# +[ExposeKeyedService("taxCalculator")] +[ExposeKeyedService("calculator")] +[ExposeServices(typeof(ITaxCalculator), typeof(ICalculator))] +public class TaxCalculator: ICalculator, ITaxCalculator, ICanCalculate, ITransientDependency +{ +} +```` + ### Manually Registering In some cases, you may need to register a service to the `IServiceCollection` manually, especially if you need to use custom factory methods or singleton instances. In that case, you can directly add services just as [Microsoft documentation](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection) describes. Example: diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/ConventionalRegistrarBase.cs b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/ConventionalRegistrarBase.cs index c7190e6c4d..6d1c345840 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/ConventionalRegistrarBase.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/ConventionalRegistrarBase.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; -using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Reflection; @@ -40,6 +39,11 @@ public abstract class ConventionalRegistrarBase : IConventionalRegistrar } protected virtual void TriggerServiceExposing(IServiceCollection services, Type implementationType, List serviceTypes) + { + TriggerServiceExposing(services, implementationType, serviceTypes.ConvertAll(t => new ServiceIdentifier(t))); + } + + protected virtual void TriggerServiceExposing(IServiceCollection services, Type implementationType, List serviceTypes) { var exposeActions = services.GetExposingActionList(); if (exposeActions.Any()) @@ -92,10 +96,16 @@ public abstract class ConventionalRegistrarBase : IConventionalRegistrar return ExposedServiceExplorer.GetExposedServices(type); } + protected virtual List GetExposedKeyedServiceTypes(Type type) + { + return ExposedServiceExplorer.GetExposedKeyedServices(type); + } + protected virtual ServiceDescriptor CreateServiceDescriptor( Type implementationType, + object? serviceKey, Type exposingServiceType, - List allExposingServiceTypes, + List allExposingServiceTypes, ServiceLifetime lifeTime) { if (lifeTime.IsIn(ServiceLifetime.Singleton, ServiceLifetime.Scoped)) @@ -108,27 +118,41 @@ public abstract class ConventionalRegistrarBase : IConventionalRegistrar if (redirectedType != null) { - return ServiceDescriptor.Describe( - exposingServiceType, - provider => provider.GetService(redirectedType)!, - lifeTime - ); + return serviceKey == null + ? ServiceDescriptor.Describe( + exposingServiceType, + provider => provider.GetService(redirectedType)!, + lifeTime + ) + : ServiceDescriptor.DescribeKeyed( + exposingServiceType, + serviceKey, + (provider, key) => provider.GetKeyedService(redirectedType, key)!, + lifeTime + ); } } - return ServiceDescriptor.Describe( - exposingServiceType, - implementationType, - lifeTime - ); + return serviceKey == null + ? ServiceDescriptor.Describe( + exposingServiceType, + implementationType, + lifeTime + ) + : ServiceDescriptor.DescribeKeyed( + exposingServiceType, + serviceKey, + implementationType, + lifeTime + ); } protected virtual Type? GetRedirectedTypeOrNull( Type implementationType, Type exposingServiceType, - List allExposingServiceTypes) + List allExposingKeyedServiceTypes) { - if (allExposingServiceTypes.Count < 2) + if (allExposingKeyedServiceTypes.Count < 2) { return null; } @@ -138,14 +162,13 @@ public abstract class ConventionalRegistrarBase : IConventionalRegistrar return null; } - if (allExposingServiceTypes.Contains(implementationType)) + if (allExposingKeyedServiceTypes.Any(t => t.ServiceType == implementationType)) { return implementationType; } - return allExposingServiceTypes.FirstOrDefault( - t => t != exposingServiceType && exposingServiceType.IsAssignableFrom(t) - ); + return allExposingKeyedServiceTypes.FirstOrDefault( + t => t.ServiceType != exposingServiceType && exposingServiceType.IsAssignableFrom(t.ServiceType) + ).ServiceType; } - } diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/DefaultConventionalRegistrar.cs b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/DefaultConventionalRegistrar.cs index 18f36bfb48..0356ab450b 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/DefaultConventionalRegistrar.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/DefaultConventionalRegistrar.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Linq; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; @@ -22,16 +24,21 @@ public class DefaultConventionalRegistrar : ConventionalRegistrarBase return; } - var exposedServiceTypes = GetExposedServiceTypes(type); + var exposedServiceAndKeyedServiceTypes = GetExposedKeyedServiceTypes(type).Concat(GetExposedServiceTypes(type).Select(t => new ServiceIdentifier(t))).ToList(); - TriggerServiceExposing(services, type, exposedServiceTypes); + TriggerServiceExposing(services, type, exposedServiceAndKeyedServiceTypes); - foreach (var exposedServiceType in exposedServiceTypes) + foreach (var exposedServiceType in exposedServiceAndKeyedServiceTypes) { + var allExposingServiceTypes = exposedServiceType.ServiceKey == null + ? exposedServiceAndKeyedServiceTypes.Where(x => x.ServiceKey == null).ToList() + : exposedServiceAndKeyedServiceTypes.Where(x => x.ServiceKey?.ToString() == exposedServiceType.ServiceKey?.ToString()).ToList(); + var serviceDescriptor = CreateServiceDescriptor( type, - exposedServiceType, - exposedServiceTypes, + exposedServiceType.ServiceKey, + exposedServiceType.ServiceType, + allExposingServiceTypes, lifeTime.Value ); diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/ExposeKeyedServiceAttribute.cs b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/ExposeKeyedServiceAttribute.cs new file mode 100644 index 0000000000..a7af4d0a79 --- /dev/null +++ b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/ExposeKeyedServiceAttribute.cs @@ -0,0 +1,25 @@ +using System; + +namespace Volo.Abp.DependencyInjection; + +[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] +public class ExposeKeyedServiceAttribute : Attribute, IExposedKeyedServiceTypesProvider + where TServiceType : class +{ + public ServiceIdentifier ServiceIdentifier { get; } + + public ExposeKeyedServiceAttribute(object serviceKey) + { + if (serviceKey == null) + { + throw new AbpException($"{nameof(serviceKey)} can not be null! Use {nameof(ExposeServicesAttribute)} instead."); + } + + ServiceIdentifier = new ServiceIdentifier(serviceKey, typeof(TServiceType)); + } + + public ServiceIdentifier[] GetExposedServiceTypes(Type targetType) + { + return new[] { ServiceIdentifier }; + } +} diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/ExposeServicesAttribute.cs b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/ExposeServicesAttribute.cs index 286b9a8c76..f05ce07239 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/ExposeServicesAttribute.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/ExposeServicesAttribute.cs @@ -5,6 +5,7 @@ using System.Reflection; namespace Volo.Abp.DependencyInjection; +[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] public class ExposeServicesAttribute : Attribute, IExposedServiceTypesProvider { public Type[] ServiceTypes { get; } diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/ExposedServiceExplorer.cs b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/ExposedServiceExplorer.cs index 126c56fca2..318af5f96e 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/ExposedServiceExplorer.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/ExposedServiceExplorer.cs @@ -15,12 +15,31 @@ public static class ExposedServiceExplorer public static List GetExposedServices(Type type) { - return type + var exposedServiceTypesProviders = type .GetCustomAttributes(true) .OfType() + .ToList(); + + if (exposedServiceTypesProviders.IsNullOrEmpty() && type.GetCustomAttributes(true).OfType().Any()) + { + // If there is any IExposedKeyedServiceTypesProvider but no IExposedServiceTypesProvider, we will not expose the default services. + return Array.Empty().ToList(); + } + + return exposedServiceTypesProviders .DefaultIfEmpty(DefaultExposeServicesAttribute) .SelectMany(p => p.GetExposedServiceTypes(type)) .Distinct() .ToList(); } + + public static List GetExposedKeyedServices(Type type) + { + return type + .GetCustomAttributes(true) + .OfType() + .SelectMany(p => p.GetExposedServiceTypes(type)) + .Distinct() + .ToList(); + } } diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/IExposedKeyedServiceTypesProvider.cs b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/IExposedKeyedServiceTypesProvider.cs new file mode 100644 index 0000000000..84879904b5 --- /dev/null +++ b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/IExposedKeyedServiceTypesProvider.cs @@ -0,0 +1,8 @@ +using System; + +namespace Volo.Abp.DependencyInjection; + +public interface IExposedKeyedServiceTypesProvider +{ + ServiceIdentifier[] GetExposedServiceTypes(Type targetType); +} diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/IOnServiceExposingContext.cs b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/IOnServiceExposingContext.cs index 5a96160be2..0dc1c42fe2 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/IOnServiceExposingContext.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/IOnServiceExposingContext.cs @@ -7,5 +7,5 @@ public interface IOnServiceExposingContext { Type ImplementationType { get; } - List ExposedTypes { get; } + List ExposedTypes { get; } } diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/OnServiceExposingContext.cs b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/OnServiceExposingContext.cs index 7ce197aea8..2b09430222 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/OnServiceExposingContext.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/OnServiceExposingContext.cs @@ -8,9 +8,15 @@ public class OnServiceExposingContext : IOnServiceExposingContext { public Type ImplementationType { get; } - public List ExposedTypes { get; } + public List ExposedTypes { get; } public OnServiceExposingContext([NotNull] Type implementationType, List exposedTypes) + { + ImplementationType = Check.NotNull(implementationType, nameof(implementationType)); + ExposedTypes = Check.NotNull(exposedTypes, nameof(exposedTypes)).ConvertAll(t => new ServiceIdentifier(t)); + } + + public OnServiceExposingContext([NotNull] Type implementationType, List exposedTypes) { ImplementationType = Check.NotNull(implementationType, nameof(implementationType)); ExposedTypes = Check.NotNull(exposedTypes, nameof(exposedTypes)); diff --git a/framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/AbpObjectMappingModule.cs b/framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/AbpObjectMappingModule.cs index cfd82a5547..e572d6e155 100644 --- a/framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/AbpObjectMappingModule.cs +++ b/framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/AbpObjectMappingModule.cs @@ -1,4 +1,5 @@ using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.DependencyInjection; using Volo.Abp.Modularity; using Volo.Abp.Reflection; @@ -10,12 +11,12 @@ public class AbpObjectMappingModule : AbpModule { context.Services.OnExposing(onServiceExposingContext => { - //Register types for IObjectMapper if implements - onServiceExposingContext.ExposedTypes.AddRange( + //Register types for IObjectMapper if implements + onServiceExposingContext.ExposedTypes.AddRange( ReflectionHelper.GetImplementedGenericTypes( onServiceExposingContext.ImplementationType, typeof(IObjectMapper<,>) - ) + ).ConvertAll(t => new ServiceIdentifier(t)) ); }); } diff --git a/framework/src/Volo.Abp.Serialization/Volo/Abp/Serialization/AbpSerializationModule.cs b/framework/src/Volo.Abp.Serialization/Volo/Abp/Serialization/AbpSerializationModule.cs index 428f0415c8..5a178ba01b 100644 --- a/framework/src/Volo.Abp.Serialization/Volo/Abp/Serialization/AbpSerializationModule.cs +++ b/framework/src/Volo.Abp.Serialization/Volo/Abp/Serialization/AbpSerializationModule.cs @@ -1,4 +1,5 @@ using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.DependencyInjection; using Volo.Abp.Modularity; using Volo.Abp.Reflection; @@ -10,12 +11,12 @@ public class AbpSerializationModule : AbpModule { context.Services.OnExposing(onServiceExposingContext => { - //Register types for IObjectSerializer if implements - onServiceExposingContext.ExposedTypes.AddRange( + //Register types for IObjectSerializer if implements + onServiceExposingContext.ExposedTypes.AddRange( ReflectionHelper.GetImplementedGenericTypes( onServiceExposingContext.ImplementationType, typeof(IObjectSerializer<>) - ) + ).ConvertAll(t => new ServiceIdentifier(t)) ); }); } diff --git a/framework/test/Volo.Abp.Core.Tests/Microsoft/Extensions/DependencyInjection/DependencyInjection_Tests.cs b/framework/test/Volo.Abp.Core.Tests/Microsoft/Extensions/DependencyInjection/DependencyInjection_Tests.cs index be6b6d68f5..8e3975708c 100644 --- a/framework/test/Volo.Abp.Core.Tests/Microsoft/Extensions/DependencyInjection/DependencyInjection_Tests.cs +++ b/framework/test/Volo.Abp.Core.Tests/Microsoft/Extensions/DependencyInjection/DependencyInjection_Tests.cs @@ -79,6 +79,25 @@ public abstract class DependencyInjection_Standard_Tests : AbpIntegratedTest>().DisablePropertyInjectionService.ShouldBeNull(); } + + [Fact] + public void ExposeKeyedServices_Should_Expose_Correct_Services() + { + GetService().ShouldBeNull(); + GetService().ShouldBeNull(); + GetService().ShouldBeNull(); + + GetRequiredKeyedService("k1").ShouldNotBeNull(); + GetRequiredKeyedService("k1").ShouldNotBeNull(); + + GetRequiredKeyedService("k2").ShouldNotBeNull(); + GetRequiredKeyedService("k2").ShouldNotBeNull(); + + GetService().ShouldNotBeNull(); + GetRequiredKeyedService("k3").ShouldNotBeNull(); + GetRequiredKeyedService("k3").ShouldNotBeNull(); + } + [Fact] public void Singletons_Exposing_Multiple_Services_Should_Returns_The_Same_Instance() { @@ -86,6 +105,11 @@ public abstract class DependencyInjection_Standard_Tests : AbpIntegratedTest(); ReferenceEquals(objectByInterfaceRef, objectByClassRef).ShouldBeTrue(); + + objectByInterfaceRef = GetRequiredKeyedService("k1"); + objectByClassRef = GetRequiredKeyedService("k1"); + + ReferenceEquals(objectByInterfaceRef, objectByClassRef).ShouldBeTrue(); } [Fact] @@ -166,11 +190,40 @@ public abstract class DependencyInjection_Standard_Tests : AbpIntegratedTest("k1")] + [ExposeKeyedService("k1")] public class MySingletonExposingMultipleServices : IMySingletonExposingMultipleServices, ISingletonDependency { } + public interface IMyExposingKeyedServices + { + + } + + [ExposeKeyedService("k1")] + [ExposeKeyedService("k1")] + public class MyExposingKeyedService1 : IMyExposingKeyedServices, ITransientDependency + { + + } + + [ExposeKeyedService("k2")] + [ExposeKeyedService("k2")] + public class MyExposingKeyedService2 : IMyExposingKeyedServices, ITransientDependency + { + + } + + [ExposeServices(typeof(MyExposingKeyedService3))] + [ExposeKeyedService("k3")] + [ExposeKeyedService("k3")] + public class MyExposingKeyedService3 : IMyExposingKeyedServices, ITransientDependency + { + + } + public class TestModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) From 0fc4f67e456b6935621b75e89ecd99a709efbffd Mon Sep 17 00:00:00 2001 From: maliming Date: Sat, 20 Jan 2024 14:19:29 +0800 Subject: [PATCH 076/154] Update OpenIddict to `5.1.0`. https://github.com/openiddict/openiddict-core/releases/tag/5.1.0 --- Directory.Packages.props | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index a402f01450..b073237216 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -114,11 +114,11 @@ - - - - - + + + + + From 9a63970c45cc3c53c83fb85fe4d930c0683b2abe Mon Sep 17 00:00:00 2001 From: Mark Cilia Vincenti Date: Sat, 20 Jan 2024 16:38:04 +0100 Subject: [PATCH 077/154] Bump AsyncKeyedLock to 6.3.3 --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index a402f01450..58661cd2db 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -6,7 +6,7 @@ - + From 39d6ba0010180fdd525b62b3c4fb3ba49b8dc9e0 Mon Sep 17 00:00:00 2001 From: maliming Date: Sun, 21 Jan 2024 21:12:21 +0800 Subject: [PATCH 078/154] Update `AbpDynamicClaimsPrincipalContributorBase_Tests` to fix unit test in CI pipeline. --- ...micClaimsPrincipalContributorBase_Tests.cs | 46 ++++++++++++------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/framework/test/Volo.Abp.Security.Tests/Volo/Abp/Security/Claims/AbpDynamicClaimsPrincipalContributorBase_Tests.cs b/framework/test/Volo.Abp.Security.Tests/Volo/Abp/Security/Claims/AbpDynamicClaimsPrincipalContributorBase_Tests.cs index 7054319dfa..4d0fc8ff6d 100644 --- a/framework/test/Volo.Abp.Security.Tests/Volo/Abp/Security/Claims/AbpDynamicClaimsPrincipalContributorBase_Tests.cs +++ b/framework/test/Volo.Abp.Security.Tests/Volo/Abp/Security/Claims/AbpDynamicClaimsPrincipalContributorBase_Tests.cs @@ -3,28 +3,55 @@ using System.Collections.Generic; using System.Linq; using System.Security.Claims; using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; using Shouldly; +using Volo.Abp.DependencyInjection; using Volo.Abp.Testing; using Xunit; namespace Volo.Abp.Security.Claims; +[DisableConventionalRegistration] class TestAbpDynamicClaimsPrincipalContributor : AbpDynamicClaimsPrincipalContributorBase { + private readonly List _claims; + + public TestAbpDynamicClaimsPrincipalContributor(List claims) + { + _claims = claims; + } + public async override Task ContributeAsync(AbpClaimsPrincipalContributorContext context) { var identity = context.ClaimsPrincipal.Identities.FirstOrDefault(); Check.NotNull(identity, nameof(identity)); - await AddDynamicClaimsAsync(context, identity, AbpDynamicClaimsPrincipalContributorBase_Tests.DynamicClaims.Claims); + await AddDynamicClaimsAsync(context, identity, _claims); } } public class AbpDynamicClaimsPrincipalContributorBase_Tests : AbpIntegratedTest { - private readonly TestAbpDynamicClaimsPrincipalContributor _dynamicClaimsPrincipalContributorBase = new TestAbpDynamicClaimsPrincipalContributor(); + private readonly TestAbpDynamicClaimsPrincipalContributor _dynamicClaimsPrincipalContributorBase; - public readonly static AbpDynamicClaimCacheItem DynamicClaims = new AbpDynamicClaimCacheItem(); + private readonly AbpDynamicClaimCacheItem _dynamicClaims; + + public AbpDynamicClaimsPrincipalContributorBase_Tests() + { + _dynamicClaims = new AbpDynamicClaimCacheItem(new List() + { + new AbpDynamicClaim("preferred_username", "test-preferred_username"), + new AbpDynamicClaim(ClaimTypes.GivenName, "test-given_name"), + new AbpDynamicClaim("family_name", "test-family_name"), + new AbpDynamicClaim("role", "test-role1"), + new AbpDynamicClaim("roles", "test-role2"), + new AbpDynamicClaim(ClaimTypes.Role, "test-role3"), + new AbpDynamicClaim("email", "test-email"), + new AbpDynamicClaim(AbpClaimTypes.EmailVerified, "test-email-verified"), + new AbpDynamicClaim(AbpClaimTypes.PhoneNumberVerified, null), + }); + _dynamicClaimsPrincipalContributorBase = new TestAbpDynamicClaimsPrincipalContributor(_dynamicClaims.Claims); + } protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) { @@ -46,19 +73,6 @@ public class AbpDynamicClaimsPrincipalContributorBase_Tests : AbpIntegratedTest< claimsPrincipal.Identities.First().AddClaim(new Claim(AbpClaimTypes.PhoneNumberVerified, "test-source-phoneNumberVerified")); claimsPrincipal.Identities.First().AddClaim(new Claim("my-claim", "test-source-my-claim")); - DynamicClaims.Claims.AddRange(new [] - { - new AbpDynamicClaim("preferred_username", "test-preferred_username"), - new AbpDynamicClaim(ClaimTypes.GivenName, "test-given_name"), - new AbpDynamicClaim("family_name", "test-family_name"), - new AbpDynamicClaim("role", "test-role1"), - new AbpDynamicClaim("roles", "test-role2"), - new AbpDynamicClaim(ClaimTypes.Role, "test-role3"), - new AbpDynamicClaim("email", "test-email"), - new AbpDynamicClaim(AbpClaimTypes.EmailVerified, "test-email-verified"), - new AbpDynamicClaim(AbpClaimTypes.PhoneNumberVerified, null), - }); - await _dynamicClaimsPrincipalContributorBase.ContributeAsync(new AbpClaimsPrincipalContributorContext(claimsPrincipal, GetRequiredService())); claimsPrincipal.Identities.First().Claims.ShouldContain(c => c.Type == AbpClaimTypes.UserName && c.Value == "test-preferred_username"); From 037c013427cf0b4518f8f012e0dd3909bd9024cf Mon Sep 17 00:00:00 2001 From: maliming Date: Mon, 22 Jan 2024 11:25:34 +0800 Subject: [PATCH 079/154] Return `NotFoundFileInfo` or `NotFoundDirectoryContents` when `subpach` is `null`. --- .../VirtualFileSystem/WebContentFileProvider.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/VirtualFileSystem/WebContentFileProvider.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/VirtualFileSystem/WebContentFileProvider.cs index ba9240d48b..fffc35792a 100644 --- a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/VirtualFileSystem/WebContentFileProvider.cs +++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/VirtualFileSystem/WebContentFileProvider.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using JetBrains.Annotations; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.Options; @@ -34,7 +33,10 @@ public class WebContentFileProvider : IWebContentFileProvider, ISingletonDepende public virtual IFileInfo GetFileInfo(string subpath) { - Check.NotNullOrEmpty(subpath, nameof(subpath)); + if (string.IsNullOrEmpty(subpath)) + { + return new NotFoundFileInfo(subpath); + } if (PathUtils.PathNavigatesAboveRoot(subpath)) { @@ -53,11 +55,9 @@ public class WebContentFileProvider : IWebContentFileProvider, ISingletonDepende return _fileProvider.GetFileInfo(_rootPath + subpath); } - public virtual IDirectoryContents GetDirectoryContents([NotNull] string subpath) + public virtual IDirectoryContents GetDirectoryContents(string subpath) { - Check.NotNullOrEmpty(subpath, nameof(subpath)); - - if (PathUtils.PathNavigatesAboveRoot(subpath)) + if (subpath == null || PathUtils.PathNavigatesAboveRoot(subpath)) { return NotFoundDirectoryContents.Singleton; } From 2d69007ea314348729ff6c422cddab1e6642d8f7 Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Mon, 22 Jan 2024 09:48:57 +0300 Subject: [PATCH 080/154] Update MenuItemAdminAppService_Tests.cs --- .../Menus/MenuItemAdminAppService_Tests.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Menus/MenuItemAdminAppService_Tests.cs b/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Menus/MenuItemAdminAppService_Tests.cs index 5ff1e85161..7dd89ba9d0 100644 --- a/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Menus/MenuItemAdminAppService_Tests.cs +++ b/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Menus/MenuItemAdminAppService_Tests.cs @@ -48,7 +48,8 @@ public class MenuItemAdminAppService_Tests : CmsKitApplicationTestBase var name = "My Awesome Menu"; var menu = await MenuAdminAppService.CreateAsync(new MenuItemCreateInput { - DisplayName = name + DisplayName = name, + Url = "#" }); menu.ShouldNotBeNull(); From c4cde819ba45380773242dc36ad5ac2ecfc866ec Mon Sep 17 00:00:00 2001 From: Engincan VESKE <43685404+EngincanV@users.noreply.github.com> Date: Mon, 22 Jan 2024 10:43:19 +0300 Subject: [PATCH 081/154] Update DependencyInjection_Tests.cs --- .../DependencyInjection/DependencyInjection_Tests.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/framework/test/Volo.Abp.Core.Tests/Microsoft/Extensions/DependencyInjection/DependencyInjection_Tests.cs b/framework/test/Volo.Abp.Core.Tests/Microsoft/Extensions/DependencyInjection/DependencyInjection_Tests.cs index 8e3975708c..0dfe473ee5 100644 --- a/framework/test/Volo.Abp.Core.Tests/Microsoft/Extensions/DependencyInjection/DependencyInjection_Tests.cs +++ b/framework/test/Volo.Abp.Core.Tests/Microsoft/Extensions/DependencyInjection/DependencyInjection_Tests.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using Shouldly; using Volo.Abp.DependencyInjection; using Volo.Abp.Modularity; @@ -96,6 +97,10 @@ public abstract class DependencyInjection_Standard_Tests : AbpIntegratedTest().ShouldNotBeNull(); GetRequiredKeyedService("k3").ShouldNotBeNull(); GetRequiredKeyedService("k3").ShouldNotBeNull(); + + //resolving multiple keyed services + GetKeyedServices>("k1").ShouldNotBeEmpty(); + GetKeyedServices>("k1").Count().ShouldBeGreaterThanOrEqualTo(2); } [Fact] @@ -222,6 +227,12 @@ public abstract class DependencyInjection_Standard_Tests : AbpIntegratedTest("k1")] + public class MyExposingKeyedService4 : IMyExposingKeyedServices, ITransientDependency + { + } public class TestModule : AbpModule From 0e0c4611ff9cf6a1156c69690b3fda4f7ffd514b Mon Sep 17 00:00:00 2001 From: Engincan VESKE <43685404+EngincanV@users.noreply.github.com> Date: Mon, 22 Jan 2024 11:03:48 +0300 Subject: [PATCH 082/154] Update Dependency-Injection.md --- docs/en/Dependency-Injection.md | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/docs/en/Dependency-Injection.md b/docs/en/Dependency-Injection.md index 2d042a2b2a..58522c98cf 100644 --- a/docs/en/Dependency-Injection.md +++ b/docs/en/Dependency-Injection.md @@ -145,7 +145,7 @@ public class TaxCalculator : ITaxCalculator, ITransientDependency ### ExposeKeyedService Attribute -``ExposeKeyedServiceAttribute`` is used to control which keyed services are provided by the related class. Example: +`ExposeKeyedServiceAttribute` is used to control which keyed services are provided by the related class. Example: ````C# [ExposeKeyedService("taxCalculator")] @@ -155,14 +155,28 @@ public class TaxCalculator: ICalculator, ITaxCalculator, ICanCalculate, ITransie } ```` -``TaxCalculator`` class exposes ``ITaxCalculator`` interface with the key ``tax`` and ``ICalculator`` interface with the key ``calculator``. That means you can get keyed services from the ``IServiceProvider`` as shown below: +In the example above, the `TaxCalculator` class exposes the `ITaxCalculator` interface with the key `taxCalculator` and the `ICalculator` interface with the key `calculator`. That means you can get keyed services from the `IServiceProvider` as shown below: ````C# var taxCalculator = ServiceProvider.GetRequiredKeyedService("taxCalculator"); var calculator = ServiceProvider.GetRequiredKeyedService("calculator"); ```` -> Notice that the ``ExposeKeyedServiceAttribute`` is only expose keyed services. So, you can not inject ``ITaxCalculator`` or ``ICalculator`` in your application. If you want to expose both keyed and non-keyed services, you can use ``ExposeServicesAttribute`` and ``ExposeKeyedServiceAttribute`` together as shown below: +Also, you can use the [`FromKeyedServicesAttribute`](https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.fromkeyedservicesattribute?view=dotnet-plat-ext-8.0) to resolve a certain keyed service in the constructor: + +```csharp +public class MyClass +{ + //... + + public MyClass([FromKeyedServices("taxCalculator")] ITaxCalculator taxCalculator) + { + TaxCalculator = taxCalculator; + } +} +``` + +> Notice that the `ExposeKeyedServiceAttribute` only exposes the keyed services. So, you can not inject the `ITaxCalculator` or `ICalculator` interfaces in your application without using the `FromKeyedServicesAttribute` as shown in the example above. If you want to expose both keyed and non-keyed services, you can use the `ExposeServicesAttribute` and `ExposeKeyedServiceAttribute` attributes together as shown below: ````C# [ExposeKeyedService("taxCalculator")] From b34c01616418a8012ab7307ac87844d770885c10 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Mon, 22 Jan 2024 17:02:04 +0800 Subject: [PATCH 083/154] Throw exception if provder was not found --- .../Volo/Abp/SettingManagement/SettingManager.cs | 2 +- .../SettingManagement/SettingManager_Basic_Tests.cs | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/SettingManager.cs b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/SettingManager.cs index 5439c1213a..68d66ee4b0 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/SettingManager.cs +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/SettingManager.cs @@ -125,7 +125,7 @@ public class SettingManager : ISettingManager, ISingletonDependency if (!providers.Any()) { - return; + throw new AbpException($"Could not find a setting provider named '{providerName}'."); } if (setting.IsEncrypted) diff --git a/modules/setting-management/test/Volo.Abp.SettingManagement.Tests/Volo/Abp/SettingManagement/SettingManager_Basic_Tests.cs b/modules/setting-management/test/Volo.Abp.SettingManagement.Tests/Volo/Abp/SettingManagement/SettingManager_Basic_Tests.cs index 44655c8cb0..00dc337c0f 100644 --- a/modules/setting-management/test/Volo.Abp.SettingManagement.Tests/Volo/Abp/SettingManagement/SettingManager_Basic_Tests.cs +++ b/modules/setting-management/test/Volo.Abp.SettingManagement.Tests/Volo/Abp/SettingManagement/SettingManager_Basic_Tests.cs @@ -63,4 +63,15 @@ public class SettingManager_Basic_Tests : SettingsTestBase (await _settingManager.GetOrNullGlobalAsync("MySetting1")).ShouldBe("43"); (await _settingProvider.GetOrNullAsync("MySetting1")).ShouldBe("43"); } + + [Fact] + public async Task Should_Throw_Exception_If_Provider_Not_Found() + { + var exception = await Assert.ThrowsAsync(async () => + { + await _settingManager.SetAsync("MySetting1", "43", "UndefinedProvider", "UndefinedProviderKey"); + }); + + exception.Message.ShouldBe("Could not find a setting provider named 'UndefinedProvider'."); + } } \ No newline at end of file From dc33781ed7addfcde378ebc2b3370921b4e5d6f3 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Mon, 22 Jan 2024 17:39:09 +0800 Subject: [PATCH 084/154] SettingValueProvider with duplicate names is not allowed --- .../Settings/SettingValueProviderManager.cs | 16 ++++- .../SettingValueProviderManager_Tests.cs | 64 +++++++++++++++++++ 2 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 framework/test/Volo.Abp.Settings.Tests/Volo/Abp/Settings/SettingValueProviderManager_Tests.cs diff --git a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingValueProviderManager.cs b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingValueProviderManager.cs index d0300357dc..c13f884e98 100644 --- a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingValueProviderManager.cs +++ b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingValueProviderManager.cs @@ -9,7 +9,8 @@ namespace Volo.Abp.Settings; public class SettingValueProviderManager : ISettingValueProviderManager, ISingletonDependency { - public List Providers => _lazyProviders.Value; + public List Providers => GetProviders(); + protected AbpSettingOptions Options { get; } private readonly Lazy> _lazyProviders; @@ -28,4 +29,17 @@ public class SettingValueProviderManager : ISettingValueProviderManager, ISingle true ); } + + protected virtual List GetProviders() + { + var providers = _lazyProviders.Value; + + var multipleProviders = providers.GroupBy(p => p.Name).FirstOrDefault(x => x.Count() > 1); + if(multipleProviders != null) + { + throw new AbpException($"Duplicate setting value provider name detected: {multipleProviders.Key}. Providers:{Environment.NewLine}{multipleProviders.Select(p => p.GetType().FullName!).JoinAsString(Environment.NewLine)}"); + } + + return providers; + } } diff --git a/framework/test/Volo.Abp.Settings.Tests/Volo/Abp/Settings/SettingValueProviderManager_Tests.cs b/framework/test/Volo.Abp.Settings.Tests/Volo/Abp/Settings/SettingValueProviderManager_Tests.cs new file mode 100644 index 0000000000..93bf26431a --- /dev/null +++ b/framework/test/Volo.Abp.Settings.Tests/Volo/Abp/Settings/SettingValueProviderManager_Tests.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using NSubstitute.Extensions; +using Shouldly; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Testing; +using Xunit; + +namespace Volo.Abp.Settings; + +public class SettingValueProviderManager_Tests: AbpIntegratedTest +{ + private readonly ISettingValueProviderManager _settingValueProviderManager; + + public SettingValueProviderManager_Tests() + { + _settingValueProviderManager = GetRequiredService(); + } + + protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) + { + options.UseAutofac(); + options.Services.Configure(settingOptions => + { + settingOptions.ValueProviders.Add(); + }); + } + + [Fact] + public void Should_Throw_Exception_If_Duplicate_Provider_Name_Detected() + { + var exception = Assert.Throws(() => + { + var providers = _settingValueProviderManager.Providers; + }); + + exception.Message.ShouldBe($"Duplicate setting value provider name detected: Test. Providers:{Environment.NewLine}Volo.Abp.Settings.Test2SettingValueProvider{Environment.NewLine}Volo.Abp.Settings.TestSettingValueProvider"); + } +} + +public class Test2SettingValueProvider : ISettingValueProvider, ITransientDependency +{ + public const string ProviderName = "Test"; + + + public string Name => ProviderName; + + public Test2SettingValueProvider() + { + } + + public Task GetOrNullAsync(SettingDefinition setting) + { + throw new NotImplementedException(); + } + + public Task> GetAllAsync(SettingDefinition[] settings) + { + throw new NotImplementedException(); + } +} \ No newline at end of file From 64e19acd89ee090f5ae7aedf157e6cad5588143c Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Mon, 22 Jan 2024 13:49:04 +0300 Subject: [PATCH 085/154] Fix parent-selector in create modal --- .../Pages/CmsKit/Menus/MenuItems/CreateModal.cshtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/CreateModal.cshtml b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/CreateModal.cshtml index 57d0dca5f1..a79912e51c 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/CreateModal.cshtml +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Menus/MenuItems/CreateModal.cshtml @@ -44,7 +44,7 @@ data-autocomplete-items-property="items" data-autocomplete-filter-param-name="filter" data-autocomplete-allow-clear="true" - data-autocomplete-parent-selector="#menu-create-modal'"> + data-autocomplete-parent-selector="#menu-create-modal"> From 594b644089c07cc51c2807e603652f16f085bf03 Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Mon, 22 Jan 2024 14:16:57 +0300 Subject: [PATCH 086/154] Remove [Required] attribute from MenuItem DTOs --- .../Volo/CmsKit/Admin/Menus/MenuItemCreateInput.cs | 1 - .../Volo/CmsKit/Admin/Menus/MenuItemUpdateInput.cs | 1 - .../Menus/MenuItemAdminAppService_Tests.cs | 1 - 3 files changed, 3 deletions(-) diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Menus/MenuItemCreateInput.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Menus/MenuItemCreateInput.cs index ebb312699a..f5ec9c6444 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Menus/MenuItemCreateInput.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Menus/MenuItemCreateInput.cs @@ -14,7 +14,6 @@ public class MenuItemCreateInput : ExtensibleObject public bool IsActive { get; set; } - [Required] public string Url { get; set; } public string Icon { get; set; } diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Menus/MenuItemUpdateInput.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Menus/MenuItemUpdateInput.cs index b51903359c..8767a6192a 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Menus/MenuItemUpdateInput.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Menus/MenuItemUpdateInput.cs @@ -13,7 +13,6 @@ public class MenuItemUpdateInput : ExtensibleObject, IHasConcurrencyStamp public bool IsActive { get; set; } - [Required] public string Url { get; set; } public string Icon { get; set; } diff --git a/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Menus/MenuItemAdminAppService_Tests.cs b/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Menus/MenuItemAdminAppService_Tests.cs index 7dd89ba9d0..d349623c2d 100644 --- a/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Menus/MenuItemAdminAppService_Tests.cs +++ b/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Menus/MenuItemAdminAppService_Tests.cs @@ -49,7 +49,6 @@ public class MenuItemAdminAppService_Tests : CmsKitApplicationTestBase var menu = await MenuAdminAppService.CreateAsync(new MenuItemCreateInput { DisplayName = name, - Url = "#" }); menu.ShouldNotBeNull(); From db2809e4a854ecaf5549607afb8daead214cc9eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sinan=20=C3=96zt=C3=BCrk?= Date: Mon, 22 Jan 2024 16:09:44 +0300 Subject: [PATCH 087/154] capitalize setting tab titles --- .../Volo/Abp/FeatureManagement/Localization/Domain/cs.json | 2 +- .../Volo/Abp/FeatureManagement/Localization/Domain/en-GB.json | 2 +- .../Volo/Abp/FeatureManagement/Localization/Domain/en.json | 2 +- .../Volo/Abp/FeatureManagement/Localization/Domain/es.json | 2 +- .../Volo/Abp/FeatureManagement/Localization/Domain/fi.json | 2 +- .../Volo/Abp/FeatureManagement/Localization/Domain/fr.json | 2 +- .../Volo/Abp/FeatureManagement/Localization/Domain/hr.json | 2 +- .../Volo/Abp/FeatureManagement/Localization/Domain/it.json | 2 +- .../Volo/Abp/FeatureManagement/Localization/Domain/pl-PL.json | 2 +- .../Volo/Abp/FeatureManagement/Localization/Domain/pt-BR.json | 2 +- .../Volo/Abp/FeatureManagement/Localization/Domain/ro-RO.json | 2 +- .../Volo/Abp/FeatureManagement/Localization/Domain/sk.json | 2 +- .../Volo/Abp/FeatureManagement/Localization/Domain/sl.json | 2 +- .../Volo/Abp/FeatureManagement/Localization/Domain/tr.json | 2 +- .../Localization/Resources/AbpSettingManagement/cs.json | 2 +- .../Localization/Resources/AbpSettingManagement/en.json | 2 +- .../Localization/Resources/AbpSettingManagement/es.json | 2 +- .../Localization/Resources/AbpSettingManagement/fr.json | 2 +- .../Localization/Resources/AbpSettingManagement/hr.json | 2 +- .../Localization/Resources/AbpSettingManagement/it.json | 2 +- .../Localization/Resources/AbpSettingManagement/pl-PL.json | 2 +- .../Localization/Resources/AbpSettingManagement/pt-BR.json | 2 +- .../Localization/Resources/AbpSettingManagement/ro-RO.json | 2 +- .../Localization/Resources/AbpSettingManagement/sk.json | 2 +- .../Localization/Resources/AbpSettingManagement/sl.json | 2 +- .../Localization/Resources/AbpSettingManagement/tr.json | 2 +- .../Localization/Resources/AbpSettingManagement/vi.json | 2 +- 27 files changed, 27 insertions(+), 27 deletions(-) diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/cs.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/cs.json index 148066d769..ffe5744826 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/cs.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/cs.json @@ -5,7 +5,7 @@ "NoFeatureFoundMessage": "Nejsou zde dostupné žádné funkce.", "ManageHostFeatures": "Správa funkcí hostitele", "ManageHostFeaturesText": "Funkce na straně hostitele můžete spravovat kliknutím na následující tlačítko.", - "Permission:FeatureManagement": "Správa funkcí", + "Permission:FeatureManagement": "Správa Funkcí", "Permission:FeatureManagement.ManageHostFeatures": "Správa funkcí hostitele", "Volo.Abp.FeatureManagement:InvalidFeatureValue": "Hodnota funkce {0} není platná!", "Menu:FeatureManagement": "Správa Funkcí", diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/en-GB.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/en-GB.json index 7f123744a7..7888423261 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/en-GB.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/en-GB.json @@ -4,7 +4,7 @@ "Features": "Features", "NoFeatureFoundMessage": "There isn't any available feature.", "ManageHostFeatures": "Manage Host features", - "Permission:FeatureManagement": "Feature management", + "Permission:FeatureManagement": "Feature Management", "Permission:FeatureManagement.ManageHostFeatures": "Manage Host features", "Volo.Abp.FeatureManagement:InvalidFeatureValue": "{0} feature value is not valid!", "Menu:FeatureManagement": "Feature Management", diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/en.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/en.json index 9ee58766c6..29e6ec85a1 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/en.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/en.json @@ -5,7 +5,7 @@ "NoFeatureFoundMessage": "There isn't any available feature.", "ManageHostFeatures": "Manage Host features", "ManageHostFeaturesText": "You can manage the host side features by clicking the following button.", - "Permission:FeatureManagement": "Feature management", + "Permission:FeatureManagement": "Feature Management", "Permission:FeatureManagement.ManageHostFeatures": "Manage Host features", "Volo.Abp.FeatureManagement:InvalidFeatureValue": "{0} feature value is not valid!", "Menu:FeatureManagement": "Feature Management", diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/es.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/es.json index bb0e807be1..618bd8b128 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/es.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/es.json @@ -5,7 +5,7 @@ "NoFeatureFoundMessage": "No hay ninguna característica disponible.", "ManageHostFeatures": "Administrar funciones de host", "ManageHostFeaturesText": "Puede administrar las funciones del lado del host haciendo clic en el siguiente botón.", - "Permission:FeatureManagement": "Gestión de características", + "Permission:FeatureManagement": "Gestión de Características", "Permission:FeatureManagement.ManageHostFeatures": "Gestionar características del Host", "Volo.Abp.FeatureManagement:InvalidFeatureValue": "{0} valor de característica no es valido!", "Menu:FeatureManagement": "Gestión de características", diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/fi.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/fi.json index 215b3289e6..ecf4da045a 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/fi.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/fi.json @@ -5,7 +5,7 @@ "NoFeatureFoundMessage": "Käytettävissä olevia ominaisuuksia ei löydy.", "ManageHostFeatures": "Hallinnoi isäntäominaisuuksia", "ManageHostFeaturesText": "Voit hallita isäntäpuolen ominaisuuksia napsauttamalla seuraavaa painiketta.", - "Permission:FeatureManagement": "Ominaisuuden hallinta", + "Permission:FeatureManagement": "Ominaisuuden Hallinta", "Permission:FeatureManagement.ManageHostFeatures": "Hallinnoi isäntäominaisuuksia", "Volo.Abp.FeatureManagement:InvalidFeatureValue": "Ominaisuuden {0} arvo ei kelpaa!", "Menu:FeatureManagement": "Ominaisuuden hallinta", diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/fr.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/fr.json index 3abe19289a..9cf4e60352 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/fr.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/fr.json @@ -5,7 +5,7 @@ "NoFeatureFoundMessage": "Il n'y a aucune fonctionnalité disponible.", "ManageHostFeatures": "Gérer les fonctionnalités de l’hôte", "ManageHostFeaturesText": "Vous pouvez gérer les fonctionnalités côté hôte en cliquant sur le bouton suivant.", - "Permission:FeatureManagement": "Gestion des fonctionnalités", + "Permission:FeatureManagement": "Gestion des Fonctionnalités", "Permission:FeatureManagement.ManageHostFeatures": "Gérer les fonctionnalités de l'hôte", "Volo.Abp.FeatureManagement:InvalidFeatureValue": "La valeur de la fonctionnalité {0} n'est pas valide!", "Menu:FeatureManagement": "Gestion des fonctionnalités", diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/hr.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/hr.json index 316becb968..5252d5dbd5 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/hr.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/hr.json @@ -5,7 +5,7 @@ "NoFeatureFoundMessage": "Ne postoji nijedna dostupna značajka.", "ManageHostFeatures": "Upravljanje značajkama domaćina", "ManageHostFeaturesText": "Možete upravljati značajkama strane domaćina klikom na sljedeći gumb.", - "Permission:FeatureManagement": "Upravljanje značajkama", + "Permission:FeatureManagement": "Upravljanje Značajkama", "Permission:FeatureManagement.ManageHostFeatures": "Upravljanje značajkama domaćina", "Volo.Abp.FeatureManagement:InvalidFeatureValue": "Vrijednost značajke {0} nije važeća!", "Menu:FeatureManagement": "Upravljanje značajkama", diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/it.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/it.json index 19feb848cd..6ce7b79ec0 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/it.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/it.json @@ -5,7 +5,7 @@ "NoFeatureFoundMessage": "Non ci sono funzioni disponibili.", "ManageHostFeatures": "Gestisci le funzionalità dell'host", "ManageHostFeaturesText": "È possibile gestire le funzionalità lato host facendo clic sul pulsante seguente.", - "Permission:FeatureManagement": "Gestione funzionalità", + "Permission:FeatureManagement": "Gestione Funzionalità", "Permission:FeatureManagement.ManageHostFeatures": "Gestisci le funzionalità dell'host", "Volo.Abp.FeatureManagement:InvalidFeatureValue": "Il valore dell'elemento {0} non è valido!", "Menu:FeatureManagement": "Gestione delle funzionalità", diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/pl-PL.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/pl-PL.json index cfc411b938..84b546cc4e 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/pl-PL.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/pl-PL.json @@ -5,7 +5,7 @@ "NoFeatureFoundMessage": "Brak dostępnej funkcji.", "ManageHostFeatures": "Zarządzaj funkcjami hosta", "ManageHostFeaturesText": "Możesz zarządzać funkcjami po stronie hosta, klikając poniższy przycisk.", - "Permission:FeatureManagement": "Zarządzanie funkcjami", + "Permission:FeatureManagement": "Zarządzanie Funkcjami", "Permission:FeatureManagement.ManageHostFeatures": "Zarządzaj funkcjami hosta", "Volo.Abp.FeatureManagement:InvalidFeatureValue": "{0} wartość funkcji jest nieprawidłowa!", "Menu:FeatureManagement": "Zarządzanie funkcjami", diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/pt-BR.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/pt-BR.json index 25d1040866..f9094d19f6 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/pt-BR.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/pt-BR.json @@ -5,7 +5,7 @@ "NoFeatureFoundMessage": "Não há nenhuma funcionalidade disponivel.", "ManageHostFeatures": "Gerenciar recursos do Host", "ManageHostFeaturesText": "Você pode gerenciar os recursos do host clicando no botão a seguir.", - "Permission:FeatureManagement": "Gerenciamento de recursos", + "Permission:FeatureManagement": "Gerenciamento de Recursos", "Permission:FeatureManagement.ManageHostFeatures": "Gerenciar recursos do Host", "Volo.Abp.FeatureManagement:InvalidFeatureValue": "O valor do recurso {0} não é válido!", "Menu:FeatureManagement": "Gerenciamento de recursos", diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/ro-RO.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/ro-RO.json index 9d7d78150c..b4adea69db 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/ro-RO.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/ro-RO.json @@ -5,7 +5,7 @@ "NoFeatureFoundMessage": "Nu există nicio caracteristică disponibilă.", "ManageHostFeatures": "Administraţi caracteristicile de host", "ManageHostFeaturesText": "Puteți gestiona funcțiile din partea gazdă făcând clic pe următorul buton.", - "Permission:FeatureManagement": "Administrare caracteristici", + "Permission:FeatureManagement": "Administrare Caracteristici", "Permission:FeatureManagement.ManageHostFeatures": "Gestionare caracteristici gazdă", "Volo.Abp.FeatureManagement:InvalidFeatureValue": "Valoarea {0} a caracteristicii nu este validă!", "Menu:FeatureManagement": "Managementul caracteristicilor", diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/sk.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/sk.json index 2d0d8fa5d6..e384bcba35 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/sk.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/sk.json @@ -5,7 +5,7 @@ "NoFeatureFoundMessage": "Nie je k dispozícii žiadna funkcia.", "ManageHostFeatures": "Spravovať funkcie poskytovateľa", "ManageHostFeaturesText": "Funkcie na strane hostiteľa môžete spravovať kliknutím na nasledujúce tlačidlo.", - "Permission:FeatureManagement": "Správa funkcií", + "Permission:FeatureManagement": "Správa Funkcií", "Permission:FeatureManagement.ManageHostFeatures": "Správa funkcií poskytovateľa", "Volo.Abp.FeatureManagement:InvalidFeatureValue": "Hodnota funkcie {0} nie je platná!", "Menu:FeatureManagement": "Správa funkcií", diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/sl.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/sl.json index d99f053a83..4d6d037b2b 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/sl.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/sl.json @@ -5,7 +5,7 @@ "NoFeatureFoundMessage": "Na voljo ni nobene funkcionalnosti.", "ManageHostFeatures": "Upravljajte funkcije gostitelja", "ManageHostFeaturesText": "Funkcije gostiteljske strani lahko upravljate s klikom na naslednji gumb.", - "Permission:FeatureManagement": "Upravljanje funkcij", + "Permission:FeatureManagement": "Upravljanje Funkcij", "Permission:FeatureManagement.ManageHostFeatures": "Upravljajte funkcije gostitelja", "Volo.Abp.FeatureManagement:InvalidFeatureValue": "Vrednost funkcije {0} ni veljavna!", "Menu:FeatureManagement": "Upravljanje funkcij", diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/tr.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/tr.json index 47025ff97e..936e999af4 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/tr.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/tr.json @@ -5,7 +5,7 @@ "NoFeatureFoundMessage": "Hiç özellik yok.", "ManageHostFeatures": "Host özelliklerini yönetin", "ManageHostFeaturesText": "Aşağıdaki butona tıklayarak host özelliklerini yönetebilirsiniz.", - "Permission:FeatureManagement": "Özellik yönetimi", + "Permission:FeatureManagement": "Özellik Yönetimi", "Permission:FeatureManagement.ManageHostFeatures": "Host özelliklerini düzenle", "Volo.Abp.FeatureManagement:InvalidFeatureValue": "{0} özellik değeri geçerli değil!", "Menu:FeatureManagement": "Özellik Yönetimi", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/cs.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/cs.json index 1d1839f017..88fb2a454d 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/cs.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/cs.json @@ -17,7 +17,7 @@ "SuccessfullySent": "Úspěšně odesláno", "Send": "Poslat", "Menu:Emailing": "Zasílání e-mailem", - "Menu:TimeZone": "Časové pásmo", + "Menu:TimeZone": "Časové Pásmo", "DisplayName:Timezone": "Časové pásmo", "TimezoneHelpText": "Toto nastavení se používá pro celou aplikaci nebo pro klienty.", "SmtpHost": "Hostitel", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/en.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/en.json index 752980849d..a62db50469 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/en.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/en.json @@ -17,7 +17,7 @@ "SuccessfullySent": "Successfully sent", "Send": "Send", "Menu:Emailing": "Emailing", - "Menu:TimeZone": "Time zone", + "Menu:TimeZone": "Time Zone", "DisplayName:Timezone": "Time zone", "TimezoneHelpText": "This setting is used for application-wide or tenant-based.", "SmtpHost": "Host", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/es.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/es.json index f5af4e2168..5c9176f39a 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/es.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/es.json @@ -17,7 +17,7 @@ "SuccessfullySent": "Enviado exitosamente", "Send": "Enviar", "Menu:Emailing": "Configuración", - "Menu:TimeZone": "Zona horaria", + "Menu:TimeZone": "Zona Horaria", "DisplayName:Timezone": "Zona horaria", "TimezoneHelpText": "Esta configuración se utiliza para toda la aplicación o basada en inquilinos.", "SmtpHost": "Host", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/fr.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/fr.json index 66aea3c898..5d25cffcba 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/fr.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/fr.json @@ -17,7 +17,7 @@ "SuccessfullySent": "Envoyé avec succès", "Send": "Envoyer", "Menu:Emailing": "Envoi par e-mail", - "Menu:TimeZone": "Fuseau horaire", + "Menu:TimeZone": "Fuseau Horaire", "DisplayName:Timezone": "Fuseau horaire", "TimezoneHelpText": "Ce paramètre est utilisé à l’échelle de l’application ou basé sur le client.", "SmtpHost": "Hôte", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/hr.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/hr.json index 2be0afddaa..cd74569b30 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/hr.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/hr.json @@ -17,7 +17,7 @@ "SuccessfullySent": "Uspješno poslano", "Send": "Poslati", "Menu:Emailing": "Slanje e-poštom", - "Menu:TimeZone": "Vremenska zona", + "Menu:TimeZone": "Vremenska Zona", "DisplayName:Timezone": "Vremenska zona", "TimezoneHelpText": "Ova se postavka koristi za cijelu aplikaciju ili zakupce.", "SmtpHost": "Domaćin", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/it.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/it.json index 8921456e05..e578e2cc5a 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/it.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/it.json @@ -17,7 +17,7 @@ "SuccessfullySent": "Inviato con successo", "Send": "Inviare", "Menu:Emailing": "Invio di e-mail", - "Menu:TimeZone": "Fuso orario", + "Menu:TimeZone": "Fuso Orario", "DisplayName:Timezone": "Fuso orario", "TimezoneHelpText": "Questa impostazione viene utilizzata per l'intera applicazione o in base al tenant.", "SmtpHost": "Host", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/pl-PL.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/pl-PL.json index d456e92344..b3283a2e4d 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/pl-PL.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/pl-PL.json @@ -17,7 +17,7 @@ "SuccessfullySent": "Pomyślnie wysłane", "Send": "Wysłać", "Menu:Emailing": "Wysyłanie e-maili", - "Menu:TimeZone": "Strefa czasowa", + "Menu:TimeZone": "Strefa Czasowa", "DisplayName:Timezone": "Strefa czasowa", "TimezoneHelpText": "To ustawienie jest używane w przypadku całej aplikacji lub opartej na dzierżawie.", "SmtpHost": "Gospodarz", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/pt-BR.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/pt-BR.json index 2d33b4224d..bb612b6add 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/pt-BR.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/pt-BR.json @@ -17,7 +17,7 @@ "SuccessfullySent": "Enviado com sucesso", "Send": "Enviar", "Menu:Emailing": "Enviando por e-mail", - "Menu:TimeZone": "Fuso horário", + "Menu:TimeZone": "Fuso Horário", "DisplayName:Timezone": "Fuso horário", "TimezoneHelpText": "Essa configuração é usada para todo o aplicativo ou com base em locatário.", "SmtpHost": "Hospedeiro", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/ro-RO.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/ro-RO.json index b1ebd0ae62..cc5d27fad1 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/ro-RO.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/ro-RO.json @@ -17,7 +17,7 @@ "SuccessfullySent": "Trimis cu succes", "Send": "Trimite", "Menu:Emailing": "Emailing", - "Menu:TimeZone": "Fus orar", + "Menu:TimeZone": "Fus Orar", "DisplayName:Timezone": "Fus orar", "TimezoneHelpText": "Această setare este utilizată pentru aplicație sau pentru chiriași.", "SmtpHost": "Host", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/sk.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/sk.json index d9e3b1eca3..f4542c3e3f 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/sk.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/sk.json @@ -17,7 +17,7 @@ "SuccessfullySent": "Úspešne odoslané", "Send": "Odoslať", "Menu:Emailing": "Posielanie emailov", - "Menu:TimeZone": "Časové pásmo", + "Menu:TimeZone": "Časové Pásmo", "DisplayName:Timezone": "Časové pásmo", "TimezoneHelpText": "Toto nastavenie sa používa pre celú aplikáciu alebo pre nájomníkov.", "SmtpHost": "Host", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/sl.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/sl.json index 3b3faeccd0..e89803e78c 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/sl.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/sl.json @@ -17,7 +17,7 @@ "SuccessfullySent": "Uspešno poslano", "Send": "Pošlji", "Menu:Emailing": "Pošiljanje po e-pošti", - "Menu:TimeZone": "Časovni pas", + "Menu:TimeZone": "Časovni Pas", "DisplayName:Timezone": "Časovni pas", "TimezoneHelpText": "Ta nastavitev se uporablja za celotno aplikacijo ali za najemnika.", "SmtpHost": "Gostitelj", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/tr.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/tr.json index c9b2dbe601..727da6e5e2 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/tr.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/tr.json @@ -17,7 +17,7 @@ "SuccessfullySent": "Başarıyla gönderildi", "Send": "Gönder", "Menu:Emailing": "Email", - "Menu:TimeZone": "Zaman dilimi", + "Menu:TimeZone": "Zaman Dilimi", "DisplayName:Timezone": "Zaman dilimi", "TimezoneHelpText": "Bu ayar uygulama genelinde veya kiracı tabanlı olarak kullanılır.", "SmtpHost": "Sunucu", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/vi.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/vi.json index 8989bd2fef..41ecdd5e56 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/vi.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/vi.json @@ -17,7 +17,7 @@ "SuccessfullySent": "Đã gửi thành công", "Send": "Gửi", "Menu:Emailing": "Gửi email", - "Menu:TimeZone": "Múi giờ", + "Menu:TimeZone": "Múi Giờ", "DisplayName:Timezone": "Múi giờ", "TimezoneHelpText": "Cài đặt này được sử dụng cho toàn bộ ứng dụng hoặc dựa trên đối tượng thuê.", "SmtpHost": "Tổ chức", From 2fc31f0ea935fa958c4dfb6b3b6090e21015d49b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sinan=20=C3=96zt=C3=BCrk?= Date: Mon, 22 Jan 2024 17:09:53 +0300 Subject: [PATCH 088/154] remove style from tree.component.scss --- .../components/tree/src/lib/components/tree.component.scss | 4 ---- 1 file changed, 4 deletions(-) diff --git a/npm/ng-packs/packages/components/tree/src/lib/components/tree.component.scss b/npm/ng-packs/packages/components/tree/src/lib/components/tree.component.scss index 49b8a61e7f..d303c61d22 100644 --- a/npm/ng-packs/packages/components/tree/src/lib/components/tree.component.scss +++ b/npm/ng-packs/packages/components/tree/src/lib/components/tree.component.scss @@ -43,8 +43,4 @@ abp-tree .ant-tree { top: 1px; cursor: pointer; } - - .ant-tree-checkbox-inner{ - background-color: transparent; - } } From bbe9b1034558f994f8eb75083078ac8e8e15fa1b Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Tue, 23 Jan 2024 08:49:56 +0300 Subject: [PATCH 089/154] Update MaxLength parameters in DynamicMaxLength for CreatePageViewModel --- .../Pages/CmsKit/Pages/Create.cshtml.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/Create.cshtml.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/Create.cshtml.cs index 4397398b8e..de69405690 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/Create.cshtml.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/Create.cshtml.cs @@ -44,15 +44,15 @@ public class CreateModel : CmsKitAdminPageModel public string Slug { get; set; } [HiddenInput] - [DynamicMaxLength(typeof(PageConsts), nameof(PageConsts.MaxSlugLength))] + [DynamicMaxLength(typeof(PageConsts), nameof(PageConsts.MaxContentLength))] public string Content { get; set; } [TextArea(Rows = 6)] - [DynamicMaxLength(typeof(PageConsts), nameof(PageConsts.MaxSlugLength))] + [DynamicMaxLength(typeof(PageConsts), nameof(PageConsts.MaxScriptLength))] public string Script { get; set; } [TextArea(Rows = 6)] - [DynamicMaxLength(typeof(PageConsts), nameof(PageConsts.MaxSlugLength))] + [DynamicMaxLength(typeof(PageConsts), nameof(PageConsts.MaxStyleLength))] public string Style { get; set; } } } From b147b4d1764406d02931ac8649c5803b96ad6b00 Mon Sep 17 00:00:00 2001 From: masumulu28 Date: Tue, 23 Jan 2024 09:12:26 +0300 Subject: [PATCH 090/154] fix: navigate url with params after redirect from auth server --- .../oauth/src/lib/strategies/auth-flow-strategy.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/npm/ng-packs/packages/oauth/src/lib/strategies/auth-flow-strategy.ts b/npm/ng-packs/packages/oauth/src/lib/strategies/auth-flow-strategy.ts index e5189966bd..256b4b38fa 100644 --- a/npm/ng-packs/packages/oauth/src/lib/strategies/auth-flow-strategy.ts +++ b/npm/ng-packs/packages/oauth/src/lib/strategies/auth-flow-strategy.ts @@ -99,10 +99,10 @@ export abstract class AuthFlowStrategy { filter(event => event.type === 'token_received' && !!this.oAuthService.state), take(1), map(() => { - const redirect_uri = decodeURIComponent(this.oAuthService.state); + const redirectUri = decodeURIComponent(this.oAuthService.state); - if (redirect_uri && redirect_uri !== '/') { - return redirect_uri; + if (redirectUri && redirectUri !== '/') { + return redirectUri; } return '/'; @@ -110,7 +110,7 @@ export abstract class AuthFlowStrategy { switchMap(redirectUri => this.configState.getOne$('currentUser').pipe( filter(user => !!user?.isAuthenticated), - tap(() => this.router.navigate([redirectUri])), + tap(() => this.router.navigateByUrl(redirectUri)), ), ), ) From 858ab407a2dd6c171c0e8075567a9a65a4ccf995 Mon Sep 17 00:00:00 2001 From: maliming Date: Tue, 23 Jan 2024 16:15:58 +0800 Subject: [PATCH 091/154] Should not update user's `PhoneNumber ` if input's `PhoneNumber` is `NullOrWhiteSpace`. --- .../Volo/Abp/Account/ProfileAppService.cs | 5 ++++ .../Abp/Account/ProfileAppService_Tests.cs | 30 +++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/modules/account/src/Volo.Abp.Account.Application/Volo/Abp/Account/ProfileAppService.cs b/modules/account/src/Volo.Abp.Account.Application/Volo/Abp/Account/ProfileAppService.cs index 88d2ccbf5a..9749a607d5 100644 --- a/modules/account/src/Volo.Abp.Account.Application/Volo/Abp/Account/ProfileAppService.cs +++ b/modules/account/src/Volo.Abp.Account.Application/Volo/Abp/Account/ProfileAppService.cs @@ -58,6 +58,11 @@ public class ProfileAppService : IdentityAppServiceBase, IProfileAppService } } + if (user.PhoneNumber.IsNullOrWhiteSpace() && input.PhoneNumber.IsNullOrWhiteSpace()) + { + input.PhoneNumber = user.PhoneNumber; + } + if (!string.Equals(user.PhoneNumber, input.PhoneNumber, StringComparison.InvariantCultureIgnoreCase)) { (await UserManager.SetPhoneNumberAsync(user, input.PhoneNumber)).CheckErrors(); diff --git a/modules/account/test/Volo.Abp.Account.Application.Tests/Volo/Abp/Account/ProfileAppService_Tests.cs b/modules/account/test/Volo.Abp.Account.Application.Tests/Volo/Abp/Account/ProfileAppService_Tests.cs index d5536c9ad9..62ad4e4bc8 100644 --- a/modules/account/test/Volo.Abp.Account.Application.Tests/Volo/Abp/Account/ProfileAppService_Tests.cs +++ b/modules/account/test/Volo.Abp.Account.Application.Tests/Volo/Abp/Account/ProfileAppService_Tests.cs @@ -73,6 +73,36 @@ public class ProfileAppService_Tests : AbpAccountApplicationTestBase result.Name.ShouldBe(input.Name); } + [Fact] + public async Task Should_Not_UpdatePhoneNumber_If_Input_PhoneNumber_IsNullOrWhiteSpace_Test() + { + //Arrange + _currentUser.Id.Returns(_testData.UserJohnId); + _currentUser.IsAuthenticated.Returns(true); + + //Act + var result = await _profileAppService.UpdateAsync(new UpdateProfileDto + { + UserName = CreateRandomString(), + Email = CreateRandomEmail(), + PhoneNumber = "" + }); + + //Assert + result.PhoneNumber.ShouldBe(null); + + //Act + result = await _profileAppService.UpdateAsync(new UpdateProfileDto + { + UserName = CreateRandomString(), + Email = CreateRandomEmail(), + PhoneNumber = "123" + }); + + //Assert + result.PhoneNumber.ShouldBe("123"); + } + [Fact] public async Task ChangePasswordAsync_FailsForSamePassword() { From 9546cdf0d02a0308835d9def1b76a8bfb0de4d99 Mon Sep 17 00:00:00 2001 From: masumulu28 Date: Tue, 23 Jan 2024 11:26:35 +0300 Subject: [PATCH 092/154] remove unused import --- .../packages/theme-shared/src/lib/handlers/error.handler.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/npm/ng-packs/packages/theme-shared/src/lib/handlers/error.handler.ts b/npm/ng-packs/packages/theme-shared/src/lib/handlers/error.handler.ts index 168fef1f53..30f9f7b3cb 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/handlers/error.handler.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/handlers/error.handler.ts @@ -5,7 +5,7 @@ import { filter, switchMap } from 'rxjs/operators'; import { HttpErrorReporterService } from '@abp/ng.core'; -import { CustomHttpErrorHandlerService, HttpErrorHandler } from '../models/common'; +import { CustomHttpErrorHandlerService } from '../models/common'; import { Confirmation } from '../models/confirmation'; import { CUSTOM_ERROR_HANDLERS, HTTP_ERROR_HANDLER } from '../tokens/http-error.token'; From 075a51a2bd9ce74c000d42e0a69bc540b5ff47ac Mon Sep 17 00:00:00 2001 From: honurbu Date: Tue, 23 Jan 2024 12:38:11 +0300 Subject: [PATCH 093/154] NoActiveLicence localization added en.json --- .../Commercial/Localization/Resources/en.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json index cdbd5e693d..a1fa38028b 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json @@ -1091,6 +1091,7 @@ "AbpStudioBetaAccessInfoText": "We're thrilled to share with you the beta version of ABP Studio! This release marks a significant milestone in our development journey, and we're eager to gather your feedback to make the application even better.", "YouAreNotAuthorizedToDownloadStudio": "You are not authorized to download ABP Studio.", "PaymentFailedInfo": "Sorry, payment failed! This could be due to insufficient funds, invalid credit card numbers or invalid pin", - "UsedPayment": "This payment has been already used" + "UsedPayment": "This payment has been already used", + "NoActiveLicence": "You are not eligible for this action! You have no active license." } } From e9b0932bb112b9c8c7151fb070b5a09f866da285 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sinan=20=C3=96zt=C3=BCrk?= Date: Tue, 23 Jan 2024 13:21:43 +0300 Subject: [PATCH 094/154] update localizations --- .../Volo/Abp/FeatureManagement/Localization/Domain/cs.json | 2 +- .../Volo/Abp/FeatureManagement/Localization/Domain/de-DE.json | 2 +- .../Volo/Abp/FeatureManagement/Localization/Domain/de.json | 2 +- .../Volo/Abp/FeatureManagement/Localization/Domain/en-GB.json | 2 +- .../Volo/Abp/FeatureManagement/Localization/Domain/en.json | 2 +- .../Volo/Abp/FeatureManagement/Localization/Domain/es.json | 2 +- .../Volo/Abp/FeatureManagement/Localization/Domain/fi.json | 2 +- .../Volo/Abp/FeatureManagement/Localization/Domain/fr.json | 2 +- .../Volo/Abp/FeatureManagement/Localization/Domain/hr.json | 2 +- .../Volo/Abp/FeatureManagement/Localization/Domain/hu.json | 2 +- .../Volo/Abp/FeatureManagement/Localization/Domain/it.json | 2 +- .../Volo/Abp/FeatureManagement/Localization/Domain/nl.json | 2 +- .../Volo/Abp/FeatureManagement/Localization/Domain/pl-PL.json | 2 +- .../Volo/Abp/FeatureManagement/Localization/Domain/pt-BR.json | 2 +- .../Volo/Abp/FeatureManagement/Localization/Domain/ro-RO.json | 2 +- .../Volo/Abp/FeatureManagement/Localization/Domain/sk.json | 2 +- .../Volo/Abp/FeatureManagement/Localization/Domain/sl.json | 2 +- .../Volo/Abp/FeatureManagement/Localization/Domain/tr.json | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/cs.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/cs.json index ffe5744826..480a67e42a 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/cs.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/cs.json @@ -3,7 +3,7 @@ "texts": { "Features": "Funkce", "NoFeatureFoundMessage": "Nejsou zde dostupné žádné funkce.", - "ManageHostFeatures": "Správa funkcí hostitele", + "ManageHostFeatures": "Správa Funkcí Hostitele", "ManageHostFeaturesText": "Funkce na straně hostitele můžete spravovat kliknutím na následující tlačítko.", "Permission:FeatureManagement": "Správa Funkcí", "Permission:FeatureManagement.ManageHostFeatures": "Správa funkcí hostitele", diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/de-DE.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/de-DE.json index 0b6d85af5f..5938622c4a 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/de-DE.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/de-DE.json @@ -3,7 +3,7 @@ "texts": { "Features": "Features", "NoFeatureFoundMessage": "Es ist kein Feature verfügbar.", - "ManageHostFeatures": "Host-Features verwalten", + "ManageHostFeatures": "Host-Features Verwalten", "Permission:FeatureManagement": "Feature-Verwaltung", "Permission:FeatureManagement.ManageHostFeatures": "Host-Features verwalten", "Volo.Abp.FeatureManagement:InvalidFeatureValue": "{0} Feature-Wert ist ungültig!", diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/de.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/de.json index 9a9a5b2338..87d31ff00b 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/de.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/de.json @@ -3,7 +3,7 @@ "texts": { "Features": "Funktionen", "NoFeatureFoundMessage": "Es ist keine Funktion verfügbar.", - "ManageHostFeatures": "Hostfunktionen verwalten", + "ManageHostFeatures": "Hostfunktionen Verwalten", "ManageHostFeaturesText": "Sie können die hostseitigen Funktionen verwalten, indem Sie auf die folgende Schaltfläche klicken.", "Permission:FeatureManagement": "Funktionsverwaltung", "Permission:FeatureManagement.ManageHostFeatures": "Hostfunktionen verwalten", diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/en-GB.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/en-GB.json index 7888423261..5259b2ef2d 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/en-GB.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/en-GB.json @@ -3,8 +3,8 @@ "texts": { "Features": "Features", "NoFeatureFoundMessage": "There isn't any available feature.", - "ManageHostFeatures": "Manage Host features", "Permission:FeatureManagement": "Feature Management", + "ManageHostFeatures": "Manage Host Features", "Permission:FeatureManagement.ManageHostFeatures": "Manage Host features", "Volo.Abp.FeatureManagement:InvalidFeatureValue": "{0} feature value is not valid!", "Menu:FeatureManagement": "Feature Management", diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/en.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/en.json index 29e6ec85a1..e222db62b8 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/en.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/en.json @@ -3,7 +3,7 @@ "texts": { "Features": "Features", "NoFeatureFoundMessage": "There isn't any available feature.", - "ManageHostFeatures": "Manage Host features", + "ManageHostFeatures": "Manage Host Features", "ManageHostFeaturesText": "You can manage the host side features by clicking the following button.", "Permission:FeatureManagement": "Feature Management", "Permission:FeatureManagement.ManageHostFeatures": "Manage Host features", diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/es.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/es.json index 618bd8b128..92e0ca98a7 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/es.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/es.json @@ -3,7 +3,7 @@ "texts": { "Features": "Características", "NoFeatureFoundMessage": "No hay ninguna característica disponible.", - "ManageHostFeatures": "Administrar funciones de host", + "ManageHostFeatures": "Administrar Funciones de Host", "ManageHostFeaturesText": "Puede administrar las funciones del lado del host haciendo clic en el siguiente botón.", "Permission:FeatureManagement": "Gestión de Características", "Permission:FeatureManagement.ManageHostFeatures": "Gestionar características del Host", diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/fi.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/fi.json index ecf4da045a..c76042de73 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/fi.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/fi.json @@ -3,7 +3,7 @@ "texts": { "Features": "Ominaisuudet", "NoFeatureFoundMessage": "Käytettävissä olevia ominaisuuksia ei löydy.", - "ManageHostFeatures": "Hallinnoi isäntäominaisuuksia", + "ManageHostFeatures": "Hallinnoi Isäntä Ominaisuuksia", "ManageHostFeaturesText": "Voit hallita isäntäpuolen ominaisuuksia napsauttamalla seuraavaa painiketta.", "Permission:FeatureManagement": "Ominaisuuden Hallinta", "Permission:FeatureManagement.ManageHostFeatures": "Hallinnoi isäntäominaisuuksia", diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/fr.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/fr.json index 9cf4e60352..d381820f3e 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/fr.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/fr.json @@ -3,7 +3,7 @@ "texts": { "Features": "Fonctionnalités", "NoFeatureFoundMessage": "Il n'y a aucune fonctionnalité disponible.", - "ManageHostFeatures": "Gérer les fonctionnalités de l’hôte", + "ManageHostFeatures": "Gérer les Fonctionnalités de l’hôte", "ManageHostFeaturesText": "Vous pouvez gérer les fonctionnalités côté hôte en cliquant sur le bouton suivant.", "Permission:FeatureManagement": "Gestion des Fonctionnalités", "Permission:FeatureManagement.ManageHostFeatures": "Gérer les fonctionnalités de l'hôte", diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/hr.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/hr.json index 5252d5dbd5..7fad950146 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/hr.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/hr.json @@ -3,7 +3,7 @@ "texts": { "Features": "Značajke", "NoFeatureFoundMessage": "Ne postoji nijedna dostupna značajka.", - "ManageHostFeatures": "Upravljanje značajkama domaćina", + "ManageHostFeatures": "Upravljanje Značajkama Domaćina", "ManageHostFeaturesText": "Možete upravljati značajkama strane domaćina klikom na sljedeći gumb.", "Permission:FeatureManagement": "Upravljanje Značajkama", "Permission:FeatureManagement.ManageHostFeatures": "Upravljanje značajkama domaćina", diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/hu.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/hu.json index 1a3ceb5fed..e787cf7ec4 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/hu.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/hu.json @@ -3,7 +3,7 @@ "texts": { "Features": "Funkciók", "NoFeatureFoundMessage": "Nincs elérhető funkció.", - "ManageHostFeatures": "Host funkciók kezelése", + "ManageHostFeatures": "Host Funkciók Kezelése", "ManageHostFeaturesText": "A gazdaoldali funkciókat a következő gombra kattintva kezelheti.", "Permission:FeatureManagement": "Funkciókezelés", "Permission:FeatureManagement.ManageHostFeatures": "Host funkciók kezelése", diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/it.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/it.json index 6ce7b79ec0..669c4d64e9 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/it.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/it.json @@ -3,7 +3,7 @@ "texts": { "Features": "Funzionalità", "NoFeatureFoundMessage": "Non ci sono funzioni disponibili.", - "ManageHostFeatures": "Gestisci le funzionalità dell'host", + "ManageHostFeatures": "Gestisci le Funzionalità Dell'host", "ManageHostFeaturesText": "È possibile gestire le funzionalità lato host facendo clic sul pulsante seguente.", "Permission:FeatureManagement": "Gestione Funzionalità", "Permission:FeatureManagement.ManageHostFeatures": "Gestisci le funzionalità dell'host", diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/nl.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/nl.json index cb7643ca78..0db4130a7b 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/nl.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/nl.json @@ -3,7 +3,7 @@ "texts": { "Features": "Functies", "NoFeatureFoundMessage": "Er is geen functie beschikbaar.", - "ManageHostFeatures": "Beheer host functies", + "ManageHostFeatures": "Beheer Host Functies", "ManageHostFeaturesText": "U kunt de functies aan de hostzijde beheren door op de volgende knop te klikken.", "Permission:FeatureManagement": "Functiebeheer", "Permission:FeatureManagement.ManageHostFeatures": "Beheer host functies", diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/pl-PL.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/pl-PL.json index 84b546cc4e..2073ba01c1 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/pl-PL.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/pl-PL.json @@ -3,7 +3,7 @@ "texts": { "Features": "Funkcje", "NoFeatureFoundMessage": "Brak dostępnej funkcji.", - "ManageHostFeatures": "Zarządzaj funkcjami hosta", + "ManageHostFeatures": "Zarządzaj Funkcjami Hosta", "ManageHostFeaturesText": "Możesz zarządzać funkcjami po stronie hosta, klikając poniższy przycisk.", "Permission:FeatureManagement": "Zarządzanie Funkcjami", "Permission:FeatureManagement.ManageHostFeatures": "Zarządzaj funkcjami hosta", diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/pt-BR.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/pt-BR.json index f9094d19f6..c2e90f0172 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/pt-BR.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/pt-BR.json @@ -3,7 +3,7 @@ "texts": { "Features": "Funcionalidades", "NoFeatureFoundMessage": "Não há nenhuma funcionalidade disponivel.", - "ManageHostFeatures": "Gerenciar recursos do Host", + "ManageHostFeatures": "Gerenciar Recursos do Host", "ManageHostFeaturesText": "Você pode gerenciar os recursos do host clicando no botão a seguir.", "Permission:FeatureManagement": "Gerenciamento de Recursos", "Permission:FeatureManagement.ManageHostFeatures": "Gerenciar recursos do Host", diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/ro-RO.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/ro-RO.json index b4adea69db..41f9221fbf 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/ro-RO.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/ro-RO.json @@ -3,7 +3,7 @@ "texts": { "Features": "Caracteristici", "NoFeatureFoundMessage": "Nu există nicio caracteristică disponibilă.", - "ManageHostFeatures": "Administraţi caracteristicile de host", + "ManageHostFeatures": "Administraţi Caracteristicile de Host", "ManageHostFeaturesText": "Puteți gestiona funcțiile din partea gazdă făcând clic pe următorul buton.", "Permission:FeatureManagement": "Administrare Caracteristici", "Permission:FeatureManagement.ManageHostFeatures": "Gestionare caracteristici gazdă", diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/sk.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/sk.json index e384bcba35..d5cc33428f 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/sk.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/sk.json @@ -3,7 +3,7 @@ "texts": { "Features": "Funkcie", "NoFeatureFoundMessage": "Nie je k dispozícii žiadna funkcia.", - "ManageHostFeatures": "Spravovať funkcie poskytovateľa", + "ManageHostFeatures": "Spravovať Funkcie Poskytovateľa", "ManageHostFeaturesText": "Funkcie na strane hostiteľa môžete spravovať kliknutím na nasledujúce tlačidlo.", "Permission:FeatureManagement": "Správa Funkcií", "Permission:FeatureManagement.ManageHostFeatures": "Správa funkcií poskytovateľa", diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/sl.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/sl.json index 4d6d037b2b..684a1f065c 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/sl.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/sl.json @@ -3,7 +3,7 @@ "texts": { "Features": "Funkcionalnosti", "NoFeatureFoundMessage": "Na voljo ni nobene funkcionalnosti.", - "ManageHostFeatures": "Upravljajte funkcije gostitelja", + "ManageHostFeatures": "Upravljajte Funkcije Gostitelja", "ManageHostFeaturesText": "Funkcije gostiteljske strani lahko upravljate s klikom na naslednji gumb.", "Permission:FeatureManagement": "Upravljanje Funkcij", "Permission:FeatureManagement.ManageHostFeatures": "Upravljajte funkcije gostitelja", diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/tr.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/tr.json index 936e999af4..44adad1dc3 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/tr.json +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/tr.json @@ -3,7 +3,7 @@ "texts": { "Features": "Özellikler", "NoFeatureFoundMessage": "Hiç özellik yok.", - "ManageHostFeatures": "Host özelliklerini yönetin", + "ManageHostFeatures": "Host Özelliklerini Yönetin", "ManageHostFeaturesText": "Aşağıdaki butona tıklayarak host özelliklerini yönetebilirsiniz.", "Permission:FeatureManagement": "Özellik Yönetimi", "Permission:FeatureManagement.ManageHostFeatures": "Host özelliklerini düzenle", From 165885e5813e03d4ac21ae99272218dcc1c68674 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sinan=20=C3=96zt=C3=BCrk?= Date: Tue, 23 Jan 2024 14:14:58 +0300 Subject: [PATCH 095/154] prettify --- .../src/lib/services/remember-me.service.ts | 38 +++++++++---------- .../lib/strategies/auth-code-flow-strategy.ts | 2 +- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/npm/ng-packs/packages/oauth/src/lib/services/remember-me.service.ts b/npm/ng-packs/packages/oauth/src/lib/services/remember-me.service.ts index 7c099c5166..84d40d982a 100644 --- a/npm/ng-packs/packages/oauth/src/lib/services/remember-me.service.ts +++ b/npm/ng-packs/packages/oauth/src/lib/services/remember-me.service.ts @@ -1,27 +1,27 @@ -import { AbpLocalStorageService } from "@abp/ng.core"; -import { Injectable, inject } from "@angular/core"; +import { AbpLocalStorageService } from '@abp/ng.core'; +import { Injectable, inject } from '@angular/core'; @Injectable({ - providedIn: 'root' + providedIn: 'root', }) export class RememberMeService { - readonly #rememberMe = 'remember_me' - protected readonly localStorageService = inject(AbpLocalStorageService); + readonly #rememberMe = 'remember_me'; + protected readonly localStorageService = inject(AbpLocalStorageService); - set(remember: boolean) { - this.localStorageService.setItem(this.#rememberMe, JSON.stringify(remember)); - } + set(remember: boolean) { + this.localStorageService.setItem(this.#rememberMe, JSON.stringify(remember)); + } - remove() { - this.localStorageService.removeItem(this.#rememberMe); - } + remove() { + this.localStorageService.removeItem(this.#rememberMe); + } - get() { - return Boolean(JSON.parse(this.localStorageService.getItem(this.#rememberMe))); - } + get() { + return Boolean(JSON.parse(this.localStorageService.getItem(this.#rememberMe))); + } - getFromToken(accessToken: string) { - let parsedToken = JSON.parse(atob(accessToken.split(".")[1])); - return Boolean(parsedToken[this.#rememberMe]); - } -} \ No newline at end of file + getFromToken(accessToken: string) { + const parsedToken = JSON.parse(atob(accessToken.split('.')[1])); + return Boolean(parsedToken[this.#rememberMe]); + } +} diff --git a/npm/ng-packs/packages/oauth/src/lib/strategies/auth-code-flow-strategy.ts b/npm/ng-packs/packages/oauth/src/lib/strategies/auth-code-flow-strategy.ts index f648be47c6..7b1e0c108a 100644 --- a/npm/ng-packs/packages/oauth/src/lib/strategies/auth-code-flow-strategy.ts +++ b/npm/ng-packs/packages/oauth/src/lib/strategies/auth-code-flow-strategy.ts @@ -13,7 +13,7 @@ export class AuthCodeFlowStrategy extends AuthFlowStrategy { return super .init() .then(() => this.oAuthService.tryLogin().catch(noop)) - .then(() => this.oAuthService.setupAutomaticSilentRefresh()) + .then(() => this.oAuthService.setupAutomaticSilentRefresh()); } private checkRememberMeOption() { From af1cc0ffbae1a435c409bec1fe9259b39b02f5e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sinan=20=C3=96zt=C3=BCrk?= Date: Tue, 23 Jan 2024 14:39:54 +0300 Subject: [PATCH 096/154] update documentation --- docs/en/UI/Angular/HTTP-Error-Handling.md | 107 ++++++++++++++++++++-- docs/en/UI/Angular/HTTP-Requests.md | 4 + 2 files changed, 105 insertions(+), 6 deletions(-) diff --git a/docs/en/UI/Angular/HTTP-Error-Handling.md b/docs/en/UI/Angular/HTTP-Error-Handling.md index 8bf2589204..1b4de9c38a 100644 --- a/docs/en/UI/Angular/HTTP-Error-Handling.md +++ b/docs/en/UI/Angular/HTTP-Error-Handling.md @@ -4,11 +4,107 @@ When the `RestService` is used, all HTTP errors are reported to the [`HttpErrorR ## Custom HTTP Error Handler -A custom HTTP error handler service can be registered to an injection token named **`CUSTOM_ERROR_HANDLERS`**. ABP has some default error handlers, you can see them [here](https://github.com/abpframework/abp/blob/dev/npm/ng-packs/packages/theme-shared/src/lib/providers/error-handlers.provider.ts). +### (Deprecated!) Function Method; -### How ABP handles errors and How to add new one? +A custom HTTP error handler can be registered to an injection token named `HTTP_ERROR_HANDLER`. If a custom handler function is registered, the `ErrorHandler` executes that function. + +See an example: + +```ts +// http-error-handler.ts +import { ContentProjectionService, PROJECTION_STRATEGY } from '@abp/ng.core'; +import { ToasterService } from '@abp/ng.theme.shared'; +import { HttpErrorResponse } from '@angular/common/http'; +import { Injector } from '@angular/core'; +import { of, EMPTY } from 'rxjs'; +import { Error404Component } from './error404/error404.component'; + +export function handleHttpErrors(injector: Injector, httpError: HttpErrorResponse) { + if (httpError.status === 400) { + const toaster = injector.get(ToasterService); + toaster.error(httpError.error?.error?.message || 'Bad request!', '400'); + return EMPTY; + } + + if (httpError.status === 404) { + const contentProjection = injector.get(ContentProjectionService); + contentProjection.projectContent(PROJECTION_STRATEGY.AppendComponentToBody(Error404Component)); + return EMPTY; + } + + return of(httpError); +} + +// app.module.ts +import { Error404Component } from './error404/error404.component'; +import { handleHttpErrors } from './http-error-handling'; +import { HTTP_ERROR_HANDLER, ... } from '@abp/ng.theme.shared'; + +@NgModule({ + // ... + providers: [ + // ... + { provide: HTTP_ERROR_HANDLER, useValue: handleHttpErrors } + ], + declarations: [ + //... + Error404Component], +}) +export class AppModule {} +``` + +In the example above: + +- Created a function named `handleHttpErrors` and defined as value of the `HTTP_ERROR_HANDLER` provider in app.module. After this, the function executes when an HTTP error occurs. +- 400 bad request errors is handled. When a 400 error occurs. + +- Since `of(httpError)` is returned at bottom of the `handleHttpErrors`, the `ErrorHandler` will handle the HTTP errors except 400 and 404 errors. + +**Note 1:** If you put `return EMPTY` to next line of handling an error, default error handling will not work for that error. [EMPTY](https://rxjs.dev/api/index/const/EMPTY) can be imported from `rxjs`. + +```ts +export function handleHttpErrors( + injector: Injector, + httpError: HttpErrorResponse +) { + if (httpError.status === 403) { + // handle 403 errors here + return EMPTY; // put return EMPTY to skip default error handling + } +} +``` + +**Note 2:** If you put `return of(httpError)`, default error handling will work. + +- `of` is a function. It can be imported from `rxjs`. +- `httpError` is the second parameter of the error handler function which is registered to the `HTTP_ERROR_HANDLER` provider. Type of the `httpError` is `HttpErrorResponse`. + +```ts +import { of } from "rxjs"; + +export function handleHttpErrors( + injector: Injector, + httpError: HttpErrorResponse +) { + if (httpError.status === 500) { + // handle 500 errors here + } + + // you can return the of(httpError) at bottom of the function to run the default handler of ABP for HTTP errors that you didn't handle above. + return of(httpError); +} +``` + +### Service Method; + +With Services you can provide **more than one handler**. + +A custom HTTP error handler service can be registered to an injection token named **`CUSTOM_ERROR_HANDLERS`**. + +ABP has some default error handlers, you can see them [here](https://github.com/abpframework/abp/blob/dev/npm/ng-packs/packages/theme-shared/src/lib/providers/error-handlers.provider.ts). + +### How To Add New Handler Service? -- First of all it will be better to understand how ABP handles errors. - ABP error handler services are implements the interface of **CustomHttpErrorHandlerService**. **Interface of `CUSTOM_ERROR_HANDLERS`** @@ -25,7 +121,7 @@ interface CustomHttpErrorHandlerService { - **`canHandle(error: unknown): boolean :`** Check if the service can handle the error. Returns boolean. - **`execute(): void :`** If the service can handle the error, then run the execute method. -**In Summarry** +**In Summary** - Services are sorted by their priority number. - Start from highest priority service and run canHandle() method. Pick the service if can handle the error, if not check next service. @@ -45,9 +141,8 @@ import { ToasterService } from "@abp/ng.theme.shared"; export class MyCustomErrorHandlerService implements CustomHttpErrorHandlerService { - // You can write any number here, ex: 9999 - readonly priority = CUSTOM_HTTP_ERROR_HANDLER_PRIORITY.veryHigh; + readonly priority = CUSTOM_HTTP_ERROR_HANDLER_PRIORITY.veryHigh; private toaster = inject(ToasterService); private error: HttpErrorResponse | undefined = undefined; diff --git a/docs/en/UI/Angular/HTTP-Requests.md b/docs/en/UI/Angular/HTTP-Requests.md index c58e35fc51..9bef5cb8f2 100644 --- a/docs/en/UI/Angular/HTTP-Requests.md +++ b/docs/en/UI/Angular/HTTP-Requests.md @@ -184,3 +184,7 @@ The `ExternalHttpClient` extends from `HTTPClient` and sets the `IS_EXTERNAL_REQ When you are using `ExternalHttpClient` as HttpClient in your components, it does not add ABP-specific headers. Note: With `IS_EXTERNAL_REQUEST` or without it, ABP loading service works. + +## See Also + +- [HTTP Error Handling / Customization](./HTTP-Error-Handling) From 8b2c5693dedf06ec14822ed27656910ed7a248c3 Mon Sep 17 00:00:00 2001 From: Mark Cilia Vincenti Date: Tue, 23 Jan 2024 13:02:58 +0100 Subject: [PATCH 097/154] Bump AsyncKeyedLock to 6.3.4; performance improvement --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 6842c542ce..3a2a7b5aaa 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -6,7 +6,7 @@ - + From d3d7e1bd761ebad3f2bae35108a45ef35669c321 Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Tue, 23 Jan 2024 15:03:08 +0300 Subject: [PATCH 098/154] Add test-case for related page title --- .../Menus/MenuItemAdminAppService_Tests.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Menus/MenuItemAdminAppService_Tests.cs b/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Menus/MenuItemAdminAppService_Tests.cs index d349623c2d..28e2c8b087 100644 --- a/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Menus/MenuItemAdminAppService_Tests.cs +++ b/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Menus/MenuItemAdminAppService_Tests.cs @@ -32,6 +32,15 @@ public class MenuItemAdminAppService_Tests : CmsKitApplicationTestBase menu.ShouldNotBeNull(); } + [Fact] + public async Task GetAsync_PageTitleShouldBeCorrect_WithRelatedPage() + { + var menu = await MenuAdminAppService.GetAsync(TestData.MenuItem_4_With_Page_1_Id); + + menu.ShouldNotBeNull(); + menu.PageTitle.ShouldBe(TestData.Page_1_Title); + } + [Fact] public async Task GetListAsync_ShouldWorkProperly() { From 2184b532c5881c48fd756a574d7f9aa29b8f8c73 Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Tue, 23 Jan 2024 15:03:29 +0300 Subject: [PATCH 099/154] Fix FindTitleAsync return type --- .../Volo/CmsKit/MongoDB/Pages/MongoPageRepository.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Pages/MongoPageRepository.cs b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Pages/MongoPageRepository.cs index 565530fcb7..1b49ac48bb 100644 --- a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Pages/MongoPageRepository.cs +++ b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Pages/MongoPageRepository.cs @@ -77,7 +77,7 @@ public class MongoPageRepository : MongoDbRepository x.IsHomePage, cancellationToken: GetCancellationToken(cancellationToken)); } - public async Task FindTitleAsync(Guid pageId, CancellationToken cancellationToken = default) + public async Task FindTitleAsync(Guid pageId, CancellationToken cancellationToken = default) { return await (await GetMongoQueryableAsync(cancellationToken)).Where(x => x.Id == pageId).Select(x => x.Title) .FirstOrDefaultAsync(cancellationToken); From 39eeba55e588a8594e53c6db4c587f50cbf0bd45 Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Tue, 23 Jan 2024 15:26:55 +0300 Subject: [PATCH 100/154] Use outline variation for Cancel in Modals --- .../TagHelpers/Modal/AbpModalFooterTagHelperService.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalFooterTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalFooterTagHelperService.cs index 671b00e094..8b46f6e78c 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalFooterTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalFooterTagHelperService.cs @@ -90,13 +90,13 @@ public class AbpModalFooterTagHelperService : AbpTagHelperService Date: Tue, 23 Jan 2024 16:00:12 +0300 Subject: [PATCH 101/154] use outline variation for sweetalert modals --- .../sweetalert2/abp-sweetalert2.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/sweetalert2/abp-sweetalert2.js b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/sweetalert2/abp-sweetalert2.js index 51c7db5cd9..44ef812995 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/sweetalert2/abp-sweetalert2.js +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/sweetalert2/abp-sweetalert2.js @@ -103,6 +103,13 @@ var abp = abp || {}; abp.libs.sweetAlert.config.default.confirmButtonText = l('Ok'); abp.libs.sweetAlert.config.default.denyButtonText = l('No'); abp.libs.sweetAlert.config.default.cancelButtonText = l('Cancel'); + abp.libs.sweetAlert.config.default.buttonsStyling = false; + abp.libs.sweetAlert.config.default.customClass = { + confirmButton: "btn btn-primary", + cancelButton: "btn btn-outline-primary me-1", + denyButton: "btn btn-outline-primary me-1" + }; + abp.libs.sweetAlert.config.confirm.title = l('AreYouSure'); abp.libs.sweetAlert.config.confirm.confirmButtonText = l('Yes'); abp.libs.sweetAlert.config.confirm.showCancelButton = true; From a240717e4c1f74bb0ed7f66ec73b09068b678514 Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Tue, 23 Jan 2024 16:10:51 +0300 Subject: [PATCH 102/154] Update Default.cshtml --- .../Components/EmailSettingGroup/Default.cshtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Components/EmailSettingGroup/Default.cshtml b/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Components/EmailSettingGroup/Default.cshtml index f653ec54a0..61d4dbe996 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Components/EmailSettingGroup/Default.cshtml +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Components/EmailSettingGroup/Default.cshtml @@ -31,7 +31,7 @@ @if (await PermissionChecker.IsGrantedAsync(SettingManagementPermissions.EmailingTest)) { - + @L["SendTestEmail"] } From c95dbaac17bbf6e8b6a7daed85f8ead66b09e922 Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Tue, 23 Jan 2024 16:30:49 +0300 Subject: [PATCH 103/154] Update abp-sweetalert2.js --- .../sweetalert2/abp-sweetalert2.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/sweetalert2/abp-sweetalert2.js b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/sweetalert2/abp-sweetalert2.js index 44ef812995..4a11feeda2 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/sweetalert2/abp-sweetalert2.js +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/sweetalert2/abp-sweetalert2.js @@ -106,8 +106,8 @@ var abp = abp || {}; abp.libs.sweetAlert.config.default.buttonsStyling = false; abp.libs.sweetAlert.config.default.customClass = { confirmButton: "btn btn-primary", - cancelButton: "btn btn-outline-primary me-1", - denyButton: "btn btn-outline-primary me-1" + cancelButton: "btn btn-outline-primary mx-2", + denyButton: "btn btn-outline-primary mx-2" }; abp.libs.sweetAlert.config.confirm.title = l('AreYouSure'); From 6d33639fec8f3540997142837afa5471992c3ace Mon Sep 17 00:00:00 2001 From: denizdemirkan Date: Tue, 23 Jan 2024 17:16:26 +0300 Subject: [PATCH 104/154] Update Getting-Started-Running-Solution.md --- docs/en/Getting-Started-Running-Solution.md | 33 +++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/docs/en/Getting-Started-Running-Solution.md b/docs/en/Getting-Started-Running-Solution.md index 921fb2b247..d71c0a64da 100644 --- a/docs/en/Getting-Started-Running-Solution.md +++ b/docs/en/Getting-Started-Running-Solution.md @@ -127,6 +127,29 @@ abp bundle > **Note**: Before starting the application, run `abp install-libs` command in your Web directory to restore the client-side libraries. This will populate the `libs` folder. +{{ if UI == "BlazorServer" }} + +> **Important:** The `.AuthServer` application serves as the **Authentication Server** for the `.Blazor` application. It is essential to have the `.AuthServer` application running in the background to ensure the proper functioning of the `.Blazor` application. + +To do this, open terminal in `.AuthServer` project folder and run the following command. + +````bash +dotnet run +```` + +Once the `.AuthServer`application has started, it is time to run `.HttpApi.Host` application. + +> **Important:** Prior to launching the `.Blazor` project, it is essential to execute the `.HttpApi.Host` application as well. + +To do this, open terminal in `.HttpApi.Host` project folder and run the following command. + +````bash +dotnet run +```` +Once the `.AuthServer` and `.HttpApi.Host` applications has started, you can proceed to run the `.Blazor` project. + +{{ end # UI }} + {{ if Tiered == "Yes" }} > Tiered solutions use **Redis** as the distributed cache. Ensure that it is installed and running in your local computer. If you are using a remote Redis Server, set the configuration in the `appsettings.json` files of the projects below. @@ -195,6 +218,16 @@ You can see the application APIs and test them here. Get [more info](https://swa ### Running the Blazor Application (Client Side) +> **Important:** The `.HttpApi.Host` application serves as the **Authentication Server** for the `.Blazor` application. It is essential to have the `.HttpApi.Host` application running in the background to ensure the proper functioning of the `.Blazor` application. + +To do this, you can open terminal in `.HttpApi.Host` project folder and run the following command. + +````bash +dotnet run +```` + +Once the `.HttpApi.Host` application has started, you can proceed to run the `.Blazor` application. + Ensure that the `.Blazor` project is the startup project and run the application. > Use Ctrl+F5 in Visual Studio (instead of F5) to run the application without debugging. If you don't have a debug purpose, this will be faster. From 45e9a0da2df2a0bbf5dc7564fc08fa02782d0175 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Wed, 24 Jan 2024 11:20:45 +0800 Subject: [PATCH 105/154] FeatureValueProvider and PermissionValueProvider with duplicate names is not allowed --- .../PermissionValueProviderManager.cs | 15 ++++- .../Volo/Abp/Features/FeatureChecker.cs | 20 ++----- .../Features/FeatureValueProviderManager.cs | 44 ++++++++++++++ .../Features/IFeatureValueProviderManager.cs | 8 +++ .../PermissionValueProviderManager_Tests.cs | 59 +++++++++++++++++++ .../FeatureValueProviderManager_Tests.cs | 54 +++++++++++++++++ .../SettingValueProviderManager_Tests.cs | 10 ++-- 7 files changed, 189 insertions(+), 21 deletions(-) create mode 100644 framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureValueProviderManager.cs create mode 100644 framework/src/Volo.Abp.Features/Volo/Abp/Features/IFeatureValueProviderManager.cs create mode 100644 framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/PermissionValueProviderManager_Tests.cs create mode 100644 framework/test/Volo.Abp.Features.Tests/Volo/Abp/Features/FeatureValueProviderManager_Tests.cs diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionValueProviderManager.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionValueProviderManager.cs index 84d0ad0b2c..09b2da2acb 100644 --- a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionValueProviderManager.cs +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionValueProviderManager.cs @@ -9,7 +9,7 @@ namespace Volo.Abp.Authorization.Permissions; public class PermissionValueProviderManager : IPermissionValueProviderManager, ISingletonDependency { - public IReadOnlyList ValueProviders => _lazyProviders.Value; + public IReadOnlyList ValueProviders => GetProviders(); private readonly Lazy> _lazyProviders; protected AbpPermissionOptions Options { get; } @@ -28,4 +28,17 @@ public class PermissionValueProviderManager : IPermissionValueProviderManager, I true ); } + + protected virtual List GetProviders() + { + var providers = _lazyProviders.Value; + + var multipleProviders = providers.GroupBy(p => p.Name).FirstOrDefault(x => x.Count() > 1); + if(multipleProviders != null) + { + throw new AbpException($"Duplicate permission value provider name detected: {multipleProviders.Key}. Providers:{Environment.NewLine}{multipleProviders.Select(p => p.GetType().FullName!).JoinAsString(Environment.NewLine)}"); + } + + return providers; + } } diff --git a/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureChecker.cs b/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureChecker.cs index c2a4a71ab3..66e145563d 100644 --- a/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureChecker.cs +++ b/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureChecker.cs @@ -12,34 +12,26 @@ public class FeatureChecker : FeatureCheckerBase protected AbpFeatureOptions Options { get; } protected IServiceProvider ServiceProvider { get; } protected IFeatureDefinitionManager FeatureDefinitionManager { get; } - protected List Providers => _providers.Value; - - private readonly Lazy> _providers; + protected IFeatureValueProviderManager FeatureValueProviderManager { get; } public FeatureChecker( IOptions options, IServiceProvider serviceProvider, - IFeatureDefinitionManager featureDefinitionManager) + IFeatureDefinitionManager featureDefinitionManager, + IFeatureValueProviderManager featureValueProviderManager) { ServiceProvider = serviceProvider; FeatureDefinitionManager = featureDefinitionManager; + FeatureValueProviderManager = featureValueProviderManager; Options = options.Value; - - _providers = new Lazy>( - () => Options - .ValueProviders - .Select(type => (ServiceProvider.GetRequiredService(type) as IFeatureValueProvider)!) - .ToList(), - true - ); } public override async Task GetOrNullAsync(string name) { var featureDefinition = await FeatureDefinitionManager.GetAsync(name); - var providers = Enumerable - .Reverse(Providers); + var providers = FeatureValueProviderManager.ValueProviders + .Reverse(); if (featureDefinition.AllowedProviders.Any()) { diff --git a/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureValueProviderManager.cs b/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureValueProviderManager.cs new file mode 100644 index 0000000000..98d73dd4e4 --- /dev/null +++ b/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureValueProviderManager.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Features; + +public class FeatureValueProviderManager : IFeatureValueProviderManager, ISingletonDependency +{ + public IReadOnlyList ValueProviders => GetProviders(); + private readonly Lazy> _lazyProviders; + + protected AbpFeatureOptions Options { get; } + + public FeatureValueProviderManager( + IServiceProvider serviceProvider, + IOptions options) + { + Options = options.Value; + + _lazyProviders = new Lazy>( + () => Options + .ValueProviders + .Select(c => serviceProvider.GetRequiredService(c) as IFeatureValueProvider) + .ToList()!, + true + ); + } + + protected virtual List GetProviders() + { + var providers = _lazyProviders.Value; + + var multipleProviders = providers.GroupBy(p => p.Name).FirstOrDefault(x => x.Count() > 1); + if(multipleProviders != null) + { + throw new AbpException($"Duplicate feature value provider name detected: {multipleProviders.Key}. Providers:{Environment.NewLine}{multipleProviders.Select(p => p.GetType().FullName!).JoinAsString(Environment.NewLine)}"); + } + + return providers; + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Features/Volo/Abp/Features/IFeatureValueProviderManager.cs b/framework/src/Volo.Abp.Features/Volo/Abp/Features/IFeatureValueProviderManager.cs new file mode 100644 index 0000000000..56de662a99 --- /dev/null +++ b/framework/src/Volo.Abp.Features/Volo/Abp/Features/IFeatureValueProviderManager.cs @@ -0,0 +1,8 @@ +using System.Collections.Generic; + +namespace Volo.Abp.Features; + +public interface IFeatureValueProviderManager +{ + IReadOnlyList ValueProviders { get; } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/PermissionValueProviderManager_Tests.cs b/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/PermissionValueProviderManager_Tests.cs new file mode 100644 index 0000000000..d4af25ad3a --- /dev/null +++ b/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/PermissionValueProviderManager_Tests.cs @@ -0,0 +1,59 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Shouldly; +using Volo.Abp.Authorization; +using Volo.Abp.Authorization.Permissions; +using Volo.Abp.Authorization.TestServices; +using Xunit; + +namespace Volo.Abp; + +public class PermissionValueProviderManager_Tests: AuthorizationTestBase +{ + private readonly IPermissionValueProviderManager _permissionValueProviderManager; + + public PermissionValueProviderManager_Tests() + { + _permissionValueProviderManager = GetRequiredService(); + } + + protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) + { + options.Services.Configure(permissionOptions => + { + permissionOptions.ValueProviders.Add(); + }); + } + + [Fact] + public void Should_Throw_Exception_If_Duplicate_Provider_Name_Detected() + { + var exception = Assert.Throws(() => + { + var providers = _permissionValueProviderManager.ValueProviders; + }); + + exception.Message.ShouldBe($"Duplicate permission value provider name detected: TestPermissionValueProvider1. Providers:{Environment.NewLine}{typeof(TestDuplicatePermissionValueProvider).FullName}{Environment.NewLine}{typeof(TestPermissionValueProvider1).FullName}"); + } +} + +public class TestDuplicatePermissionValueProvider : PermissionValueProvider +{ + public TestDuplicatePermissionValueProvider(IPermissionStore permissionStore) : base(permissionStore) + { + } + + public override string Name => "TestPermissionValueProvider1"; + + public override Task CheckAsync(PermissionValueCheckContext context) + { + throw new NotImplementedException(); + } + + public override Task CheckAsync(PermissionValuesCheckContext context) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Features.Tests/Volo/Abp/Features/FeatureValueProviderManager_Tests.cs b/framework/test/Volo.Abp.Features.Tests/Volo/Abp/Features/FeatureValueProviderManager_Tests.cs new file mode 100644 index 0000000000..7e73ef65fc --- /dev/null +++ b/framework/test/Volo.Abp.Features.Tests/Volo/Abp/Features/FeatureValueProviderManager_Tests.cs @@ -0,0 +1,54 @@ +using System; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Shouldly; +using Xunit; + +namespace Volo.Abp.Features; + +public class FeatureValueProviderManager_Tests : FeatureTestBase +{ + private readonly IFeatureValueProviderManager _featureValueProviderManager; + + public FeatureValueProviderManager_Tests() + { + _featureValueProviderManager = GetRequiredService(); + } + + protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) + { + options.Services.Configure(permissionOptions => + { + permissionOptions.ValueProviders.Add(); + }); + } + + [Fact] + public void Should_Throw_Exception_If_Duplicate_Provider_Name_Detected() + { + var exception = Assert.Throws(() => + { + var providers = _featureValueProviderManager.ValueProviders; + }); + + exception.Message.ShouldBe($"Duplicate feature value provider name detected: {TestDuplicateFeatureValueProvider.ProviderName}. Providers:{Environment.NewLine}{typeof(TestDuplicateFeatureValueProvider).FullName}{Environment.NewLine}{typeof(DefaultValueFeatureValueProvider).FullName}"); + } +} + +public class TestDuplicateFeatureValueProvider : FeatureValueProvider +{ + public const string ProviderName = "D"; + + public override string Name => ProviderName; + + public TestDuplicateFeatureValueProvider(IFeatureStore settingStore) + : base(settingStore) + { + + } + + public override Task GetOrNullAsync(FeatureDefinition setting) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Settings.Tests/Volo/Abp/Settings/SettingValueProviderManager_Tests.cs b/framework/test/Volo.Abp.Settings.Tests/Volo/Abp/Settings/SettingValueProviderManager_Tests.cs index 93bf26431a..f85e465d8e 100644 --- a/framework/test/Volo.Abp.Settings.Tests/Volo/Abp/Settings/SettingValueProviderManager_Tests.cs +++ b/framework/test/Volo.Abp.Settings.Tests/Volo/Abp/Settings/SettingValueProviderManager_Tests.cs @@ -1,9 +1,7 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; -using NSubstitute.Extensions; using Shouldly; using Volo.Abp.DependencyInjection; using Volo.Abp.Testing; @@ -25,7 +23,7 @@ public class SettingValueProviderManager_Tests: AbpIntegratedTest(settingOptions => { - settingOptions.ValueProviders.Add(); + settingOptions.ValueProviders.Add(); }); } @@ -37,18 +35,18 @@ public class SettingValueProviderManager_Tests: AbpIntegratedTest ProviderName; - public Test2SettingValueProvider() + public TestDuplicateSettingValueProvider() { } From 08adcc5c8c441e3896c9d04caacbf64e819b7920 Mon Sep 17 00:00:00 2001 From: Masum ULU <49063256+masumulu28@users.noreply.github.com> Date: Wed, 24 Jan 2024 08:58:40 +0300 Subject: [PATCH 106/154] Update HTTP-Error-Handling.md --- docs/en/UI/Angular/HTTP-Error-Handling.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/docs/en/UI/Angular/HTTP-Error-Handling.md b/docs/en/UI/Angular/HTTP-Error-Handling.md index 1b4de9c38a..e657f5c773 100644 --- a/docs/en/UI/Angular/HTTP-Error-Handling.md +++ b/docs/en/UI/Angular/HTTP-Error-Handling.md @@ -138,12 +138,11 @@ import { CUSTOM_HTTP_ERROR_HANDLER_PRIORITY } from "@abp/ng.theme.shared"; import { ToasterService } from "@abp/ng.theme.shared"; @Injectable({ providedIn: "root" }) -export class MyCustomErrorHandlerService - implements CustomHttpErrorHandlerService +export class MyCustomErrorHandlerService implements CustomHttpErrorHandlerService { // You can write any number here, ex: 9999 readonly priority = CUSTOM_HTTP_ERROR_HANDLER_PRIORITY.veryHigh; - private toaster = inject(ToasterService); + protected readonly toaster = inject(ToasterService); private error: HttpErrorResponse | undefined = undefined; // What kind of error should be handled by this service? You can decide it in this method. If error is suitable to your case then return true; otherwise return false. @@ -175,7 +174,11 @@ import { MyCustomErrorHandlerService } from './custom-error-handler.service'; // ... providers: [ // ... - { provide: CUSTOM_ERROR_HANDLERS, useExisting: MyCustomErrorHandlerService, multi: true } + { + provide: CUSTOM_ERROR_HANDLERS, + useExisting: MyCustomErrorHandlerService, + multi: true, + } ] }) export class AppModule {} From 9851f671b29da7fdbb7548e20f603c93a33a061b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sinan=20=C3=96zt=C3=BCrk?= Date: Wed, 24 Jan 2024 10:13:19 +0300 Subject: [PATCH 107/154] update document according to reviever comments --- docs/en/UI/Angular/HTTP-Error-Handling.md | 31 ++++++++++++----------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/docs/en/UI/Angular/HTTP-Error-Handling.md b/docs/en/UI/Angular/HTTP-Error-Handling.md index e657f5c773..d2e873aa63 100644 --- a/docs/en/UI/Angular/HTTP-Error-Handling.md +++ b/docs/en/UI/Angular/HTTP-Error-Handling.md @@ -4,7 +4,7 @@ When the `RestService` is used, all HTTP errors are reported to the [`HttpErrorR ## Custom HTTP Error Handler -### (Deprecated!) Function Method; +### Function Method `Deprecated` A custom HTTP error handler can be registered to an injection token named `HTTP_ERROR_HANDLER`. If a custom handler function is registered, the `ErrorHandler` executes that function. @@ -95,17 +95,15 @@ export function handleHttpErrors( } ``` -### Service Method; +### Service Method With Services you can provide **more than one handler**. -A custom HTTP error handler service can be registered to an injection token named **`CUSTOM_ERROR_HANDLERS`**. +A custom HTTP error handler service can be registered to an injection token named **`CUSTOM_ERROR_HANDLERS`**. ABP has some default [error handlers](https://github.com/abpframework/abp/blob/dev/npm/ng-packs/packages/theme-shared/src/lib/providers/error-handlers.provider.ts). -ABP has some default error handlers, you can see them [here](https://github.com/abpframework/abp/blob/dev/npm/ng-packs/packages/theme-shared/src/lib/providers/error-handlers.provider.ts). +### How To Add New Handler Service -### How To Add New Handler Service? - -- ABP error handler services are implements the interface of **CustomHttpErrorHandlerService**. +ABP error handler services are implements the interface of **CustomHttpErrorHandlerService**. **Interface of `CUSTOM_ERROR_HANDLERS`** @@ -117,9 +115,9 @@ interface CustomHttpErrorHandlerService { } ``` -- **`priority`** ABP sorts the services according to the number of the priority variable. Higher priority will be checked first. You can think this as a z-index property in CSS. -- **`canHandle(error: unknown): boolean :`** Check if the service can handle the error. Returns boolean. -- **`execute(): void :`** If the service can handle the error, then run the execute method. +- **`priority`** ABP sorts the services according to the number of the priority variable. Higher priority will be checked first. +- **`canHandle`** Check if the service can handle the error. Returns boolean. +- **`execute`** If the service can handle the error, then run the execute method. **In Summary** @@ -138,7 +136,8 @@ import { CUSTOM_HTTP_ERROR_HANDLER_PRIORITY } from "@abp/ng.theme.shared"; import { ToasterService } from "@abp/ng.theme.shared"; @Injectable({ providedIn: "root" }) -export class MyCustomErrorHandlerService implements CustomHttpErrorHandlerService +export class MyCustomErrorHandlerService + implements CustomHttpErrorHandlerService { // You can write any number here, ex: 9999 readonly priority = CUSTOM_HTTP_ERROR_HANDLER_PRIORITY.veryHigh; @@ -192,7 +191,9 @@ In the example above: ![custom-error-handler-toaster-message](images/custom-error-handler-toaster-message.jpg) -**Note 1:** If your service cannot handle the error. Then ABP will check the next Error Service. -**Note 2:** If none of the service handle the error. Then basic confirmation message about the error will be shown to the user. -**Note 3:** You can provide more than one service, with CUSTOM_ERROR_HANDLER injection token. -**Note 4:** If you want your custom service to be evaluated (checked) earlier, set the priority variable high. +### Notes + +- If your service cannot handle the error. Then ABP will check the next Error Service. +- If none of the service handle the error. Then basic confirmation message about the error will be shown to the user. +- You can provide more than one service, with CUSTOM_ERROR_HANDLER injection token. +- If you want your custom service to be evaluated (checked) earlier, set the priority variable high. From 20b7151d447e69aaa5944bddbc0842c5207fbd52 Mon Sep 17 00:00:00 2001 From: Masum ULU <49063256+masumulu28@users.noreply.github.com> Date: Wed, 24 Jan 2024 10:45:37 +0300 Subject: [PATCH 108/154] Minor changes applied --- docs/en/UI/Angular/HTTP-Error-Handling.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/en/UI/Angular/HTTP-Error-Handling.md b/docs/en/UI/Angular/HTTP-Error-Handling.md index d2e873aa63..606211bfeb 100644 --- a/docs/en/UI/Angular/HTTP-Error-Handling.md +++ b/docs/en/UI/Angular/HTTP-Error-Handling.md @@ -97,9 +97,7 @@ export function handleHttpErrors( ### Service Method -With Services you can provide **more than one handler**. - -A custom HTTP error handler service can be registered to an injection token named **`CUSTOM_ERROR_HANDLERS`**. ABP has some default [error handlers](https://github.com/abpframework/abp/blob/dev/npm/ng-packs/packages/theme-shared/src/lib/providers/error-handlers.provider.ts). +You can provide **more than one handler** with services, a custom HTTP error handler service can be registered with injection token named **`CUSTOM_ERROR_HANDLERS`**. ABP has some default [error handlers](https://github.com/abpframework/abp/blob/dev/npm/ng-packs/packages/theme-shared/src/lib/providers/error-handlers.provider.ts). ### How To Add New Handler Service From c43adeadfc148952cb08a609daeb2510a2c6b3c5 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Wed, 24 Jan 2024 15:46:10 +0800 Subject: [PATCH 109/154] Update Devart.Data.Oracle.EFCore to 10.3.10.8 --- Directory.Packages.props | 2 +- docs/en/Migration-Guides/Abp-8_0.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 4b265264c4..6a76d2d8c7 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -26,7 +26,7 @@ - + diff --git a/docs/en/Migration-Guides/Abp-8_0.md b/docs/en/Migration-Guides/Abp-8_0.md index 8214dfef1a..09e44b7ec8 100644 --- a/docs/en/Migration-Guides/Abp-8_0.md +++ b/docs/en/Migration-Guides/Abp-8_0.md @@ -181,7 +181,7 @@ You can see the following list of NuGet libraries that have been upgraded with . | Dapper | 2.0.123 | 2.1.21 | | Dapr.AspNetCore | 1.9.0 | 1.12.0 | | Dapr.Client | 1.9.0 | 1.12.0 | -| Devart.Data.Oracle.EFCore | 10.1.134.7 | 10.1.151.7 | +| Devart.Data.Oracle.EFCore | 10.1.134.7 | 10.3.10.8 | | DistributedLock.Core | 1.0.4 | 1.0.5 | | DistributedLock.Redis | 1.0.1 | 1.0.2 | | EphemeralMongo.Core | 1.1.0 | 1.1.3 | From da59ccbeebc8022c2334283de59272fe4dbfb9df Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Wed, 24 Jan 2024 15:53:20 +0800 Subject: [PATCH 110/154] Update Volo.Abp.EntityFrameworkCore.Oracle.Devart.csproj --- .../Volo.Abp.EntityFrameworkCore.Oracle.Devart.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo.Abp.EntityFrameworkCore.Oracle.Devart.csproj b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo.Abp.EntityFrameworkCore.Oracle.Devart.csproj index 70d234cd20..bb46006ac9 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo.Abp.EntityFrameworkCore.Oracle.Devart.csproj +++ b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo.Abp.EntityFrameworkCore.Oracle.Devart.csproj @@ -21,7 +21,6 @@ - From 46f3338e8fac2a4a1e3f933065fbad748e4ec738 Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Wed, 24 Jan 2024 10:55:11 +0300 Subject: [PATCH 111/154] Use Outline button variation for blazor alert --- .../src/Volo.Abp.BlazoriseUI/Components/UiMessageAlert.razor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/UiMessageAlert.razor b/framework/src/Volo.Abp.BlazoriseUI/Components/UiMessageAlert.razor index 82fc576b7e..9951e616e2 100644 --- a/framework/src/Volo.Abp.BlazoriseUI/Components/UiMessageAlert.razor +++ b/framework/src/Volo.Abp.BlazoriseUI/Components/UiMessageAlert.razor @@ -22,7 +22,7 @@ @if ( IsConfirmation ) { - + @@ -119,7 +119,7 @@ - + From 44d51d06bd7642594828f6c7bd6f898816d48231 Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Wed, 24 Jan 2024 15:19:55 +0300 Subject: [PATCH 117/154] Update FeatureManagementModal buttons --- .../Components/FeatureManagementModal.razor | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Blazor/Components/FeatureManagementModal.razor b/modules/feature-management/src/Volo.Abp.FeatureManagement.Blazor/Components/FeatureManagementModal.razor index 719cea562a..6b5a16fbb0 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Blazor/Components/FeatureManagementModal.razor +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Blazor/Components/FeatureManagementModal.razor @@ -95,8 +95,8 @@ - - + + } From 46fcdb21e5f32d1680abee23c0307d93d96e5e5e Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Wed, 24 Jan 2024 15:28:03 +0300 Subject: [PATCH 118/154] Use outline variation of buttons for Identity module on blazor --- .../Pages/Identity/RoleManagement.razor | 4 ++-- .../Pages/Identity/UserManagement.razor | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/RoleManagement.razor b/modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/RoleManagement.razor index b5b8b15d47..d65325abae 100644 --- a/modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/RoleManagement.razor +++ b/modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/RoleManagement.razor @@ -63,7 +63,7 @@ - + @@ -101,7 +101,7 @@ - + diff --git a/modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/UserManagement.razor b/modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/UserManagement.razor index 57ab80dc5e..349da3d9da 100644 --- a/modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/UserManagement.razor +++ b/modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/UserManagement.razor @@ -154,7 +154,7 @@ - + @@ -275,7 +275,7 @@ - + From 4384eb683e18690ea23ab888bff5f2df4efbb424 Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Wed, 24 Jan 2024 16:52:09 +0300 Subject: [PATCH 119/154] Update PermissionManagementModal.razor --- .../Components/PermissionManagementModal.razor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Components/PermissionManagementModal.razor b/modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Components/PermissionManagementModal.razor index 8c1f5871db..88d023a906 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Components/PermissionManagementModal.razor +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Components/PermissionManagementModal.razor @@ -81,7 +81,7 @@ } - + From 208a99b0f70be87a9e62cd73fc060e555f37ba35 Mon Sep 17 00:00:00 2001 From: honurbu Date: Wed, 24 Jan 2024 17:31:19 +0300 Subject: [PATCH 120/154] DoesTheSubscriptionRenewAutomaticallyExplanationAutoRenewal added en.json --- .../AbpIoLocalization/Commercial/Localization/Resources/en.json | 1 + 1 file changed, 1 insertion(+) diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json index e5d8c15ac2..00bc5df8ac 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json @@ -908,6 +908,7 @@ "NoLabels": "No labels", "DoesTheSubscriptionRenewAutomatically": "Does the subscription renew automatically?", "DoesTheSubscriptionRenewAutomaticallyExplanation": "The ABP Commercial does not have an auto-renewal billing model. Therefore your subscription will not be automatically renewed at the end of your license period. If you want to continue to have the benefits of ABP Commercial, you need to manually renew it at the organization management page. If you have multiple organizations, click the \"Manage\" button at your expiring organization and then click the \"Extend Now\" button to renew your license. You may also want to take a look at the What Happens When My License Ends? section.", + "DoesTheSubscriptionRenewAutomaticallyExplanationAutoRenewal": "ABP Commercial allows you to auto-renew your license. This is an optional service. You can toggle this feature when you purchase a new license or later enable it from your organization management page. Auto-renewal toggle is in the 'Payments Method' section of the organization management page. If you want to turn off auto-renewal, visit organization management page, go to the 'Payments Method' section and uncheck the 'Automatic Renewal' checkbox. When you turn off the auto-renewal feature, you must renew your license yourself.", "ExtraQuestionCreditsFaqTitle": "Can I purchase extra support question credits?", "ExtraQuestionCreditsFaqExplanation": "Yes, you can. To buy extra question credits, send an e-mail to info@abp.io with your organization's name. Here's the price list for the extra question credits:
  • 50 questions pack $999
  • 25 questions pack $625
  • 15 questions pack $450
", "AlreadyBetaTester": "You have already joined the beta tester program.", From 4df046dae234e6c6a64f2b22824567a8f6fcc3eb Mon Sep 17 00:00:00 2001 From: denizdemirkan Date: Wed, 24 Jan 2024 19:29:10 +0300 Subject: [PATCH 121/154] MarkdownSupported Localization for Community --- .../AbpIoLocalization/Community/Localization/Resources/ar.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/cs.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/de.json | 3 ++- .../Community/Localization/Resources/en-GB.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/en.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/es.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/fi.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/fr.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/hi.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/hr.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/hu.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/is.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/it.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/nl.json | 3 ++- .../Community/Localization/Resources/pl-PL.json | 3 ++- .../Community/Localization/Resources/pt-BR.json | 3 ++- .../Community/Localization/Resources/ro-RO.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/ru.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/sk.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/sl.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/tr.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/vi.json | 3 ++- .../Community/Localization/Resources/zh-Hans.json | 3 ++- .../Community/Localization/Resources/zh-Hant.json | 3 ++- 24 files changed, 48 insertions(+), 24 deletions(-) diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ar.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ar.json index 963546d9a3..df39dea75d 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ar.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ar.json @@ -255,6 +255,7 @@ "LatestArticles": "أحدث المقالات", "RaffleHeader": "مرحبًا عضو مجتمع برنامج الجسر الأكاديمي!", "RafflesInfo": "
هذه هي صفحة السحب المخصصة لإظهار تقديرنا لك لكونك عضوًا نشطًا في المجتمع. نحن نقوم بإجراء محادثات مجتمعية لبرنامج ABP ، ومؤتمر ABP .NET ، ونحضر أو نرعى الأحداث المتعلقة بـ .NET والتي نقدم فيها بعض الهدايا.

يمكنك متابعة هذه الصفحة لرؤية السحوبات القادمة أو حضورها أو الاطلاع على السحوبات السابقة التي قمنا بسحبها بما في ذلك الفائزين.

شكرا لكونك عضوا نشطا! نراكم في السحوبات القادمة.", - "RafflesInfoTitle": "سحوبات مجتمع ABP" + "RafflesInfoTitle": "سحوبات مجتمع ABP", + "MarkdownSupported": "Markdown أيد." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/cs.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/cs.json index 418cf5aef1..4c6a229861 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/cs.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/cs.json @@ -255,6 +255,7 @@ "LatestArticles": "poslední články", "RaffleHeader": "Dobrý den, člen komunity ABP!", "RafflesInfo": "
Toto je stránka s losováním věnovaná tomu, abychom vám ukázali naše uznání za to, že jste aktivním členem komunity. Pořádáme ABP Community Talks , ABP .NET Conference , účastníme se nebo sponzorujeme akce související s .NET, ve kterých rozdáváme nějaké dárky.

Na této stránce můžete sledovat nadcházející tomboly, zúčastnit se jich nebo si prohlédnout předchozí tomboly, které losujeme, včetně výherců.

Děkujeme, že jste aktivním členem! Uvidíme se v nadcházejícím slosování.", - "RafflesInfoTitle": "Komunitní tomboly ABP" + "RafflesInfoTitle": "Komunitní tomboly ABP", + "MarkdownSupported": "Markdown podporováno." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/de.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/de.json index 021c19b3ff..146985eb49 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/de.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/de.json @@ -255,6 +255,7 @@ "LatestArticles": "Neueste Artikel", "RaffleHeader": "Hallo ABP-Community-Mitglied!", "RafflesInfo": "
Auf dieser Verlosungsseite möchten wir Ihnen unsere Wertschätzung dafür zeigen, dass Sie ein aktives Community-Mitglied sind. Wir veranstalten ABP Community Talks und ABP .NET Conferences , nehmen an .NET-bezogenen Veranstaltungen teil oder sponsern diese, bei denen wir einige Geschenke verschenken.

Sie können dieser Seite folgen, um die bevorstehenden Verlosungen zu sehen, daran teilzunehmen oder frühere Verlosungen, die wir verlosen, einschließlich der Gewinner, anzusehen.

Vielen Dank, dass Sie ein aktives Mitglied sind! Wir sehen uns bei den kommenden Gewinnspielen.", - "RafflesInfoTitle": "ABP-Community- Verlosungen" + "RafflesInfoTitle": "ABP-Community- Verlosungen", + "MarkdownSupported": "Markdown unterstützt." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en-GB.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en-GB.json index 0283b963bc..fc21345c05 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en-GB.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en-GB.json @@ -103,6 +103,7 @@ "Language": "Language", "CreatePostLanguageInfo": "Language of the post", "SeeMore": "See More", - "MemberNotPublishedPostYet": "This member hasn't published any posts yet." + "MemberNotPublishedPostYet": "This member hasn't published any posts yet.", + "MarkdownSupported": "Markdown supported." } } diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json index fa10d9c408..4bcd1bd525 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json @@ -256,6 +256,7 @@ "RaffleHeader": "Hello ABP Community Member!", "RafflesInfo": "
This is the raffle page dedicated to show our appreciation towards you for being an active Community Member. We do ABP Community Talks ,ABP .NET Conference, attend or sponsor to the .NET-related events in which we give away some gifts.

You can follow this page to see the upcoming raffles, attend them, or see previous raffles we draw including the winners.

Thank you for being an active member! See you in the upcoming raffles.", "RafflesInfoTitle": "ABP Community Raffles", - "ToLuckyWinner": "to 1 lucky winner" + "ToLuckyWinner": "to 1 lucky winner", + "MarkdownSupported": "Markdown supported." } } diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/es.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/es.json index c4e178bbd9..f24cb1d511 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/es.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/es.json @@ -255,6 +255,7 @@ "LatestArticles": "últimos artículos", "RaffleHeader": "¡Hola miembro de la comunidad ABP!", "RafflesInfo": "
Esta es la página del sorteo dedicada a mostrarle nuestro agradecimiento por ser un miembro activo de la comunidad. Realizamos charlas comunitarias de ABP , conferencias ABP .NET , asistimos o patrocinamos eventos relacionados con .NET en los que regalamos algunos obsequios.

Puedes seguir esta página para ver los próximos sorteos, asistir a ellos o ver sorteos anteriores que sorteamos incluyendo a los ganadores.

¡Gracias por ser un miembro activo! Nos vemos en los próximos sorteos.", - "RafflesInfoTitle": "Rifas de la Comunidad ABP" + "RafflesInfoTitle": "Rifas de la Comunidad ABP", + "MarkdownSupported": "Markdown soportado." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fi.json index ac509875d6..a42a7d693f 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fi.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fi.json @@ -255,6 +255,7 @@ "LatestArticles": "Viimeisimmät artikkelit", "RaffleHeader": "Hei ABP-yhteisön jäsen!", "RafflesInfo": "
Tämä on arvontasivu, joka on omistettu osoittamaan kiitollisuuttamme sinua kohtaan, että olet aktiivinen yhteisön jäsen. Teemme ABP Community Talksia , ABP .NET -konferenssia , osallistumme tai sponsoroimme .NET-tapahtumia, joissa annamme lahjoja.

Voit seurata tätä sivua nähdäksesi tulevat arvonnat, osallistua niihin tai nähdäksesi aiemmat arvonnamme, mukaan lukien voittajat.

Kiitos aktiivisesta jäsenyydestäsi! Nähdään tulevissa arvonnassa.", - "RafflesInfoTitle": "ABP-yhteisön arpajaiset" + "RafflesInfoTitle": "ABP-yhteisön arpajaiset", + "MarkdownSupported": "Markdown tuettu." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fr.json index c98a48d93e..2ed85aaa95 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fr.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fr.json @@ -255,6 +255,7 @@ "LatestArticles": "Derniers articles", "RaffleHeader": "Bonjour membre de la communauté ABP !", "RafflesInfo": "
Ceci est la page de tirage au sort dédiée à vous montrer notre gratitude pour votre participation active à la communauté. Nous organisons des discussions communautaires ABP , des conférences ABP .NET , assistons ou sponsorisons des événements liés à .NET au cours desquels nous offrons des cadeaux.

Vous pouvez suivre cette page pour voir les tirages au sort à venir, y assister ou voir les tirages au sort précédents que nous tirons, y compris les gagnants.

Merci d'être un membre actif ! Rendez-vous lors des prochains tirages au sort.", - "RafflesInfoTitle": "Tirages au sort communautaires ABP" + "RafflesInfoTitle": "Tirages au sort communautaires ABP", + "MarkdownSupported": "Markdown prise en charge." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hi.json index f3d300e8a2..6a969b99f3 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hi.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hi.json @@ -255,6 +255,7 @@ "LatestArticles": "नवीनतम लेख", "RaffleHeader": "नमस्ते एबीपी समुदाय सदस्य!", "RafflesInfo": "
यह रैफ़ल पेज है जो एक सक्रिय समुदाय सदस्य होने के लिए आपके प्रति हमारी सराहना दिखाने के लिए समर्पित है। हम एबीपी सामुदायिक वार्ता , एबीपी .NET सम्मेलन करते हैं, .NET से संबंधित कार्यक्रमों में भाग लेते हैं या प्रायोजित करते हैं जिसमें हम कुछ उपहार देते हैं।

आप आगामी रैफ़ल देखने, उनमें भाग लेने, या विजेताओं सहित हमारे द्वारा निकाले गए पिछले रैफ़ल देखने के लिए इस पृष्ठ का अनुसरण कर सकते हैं।

सक्रिय सदस्य बनने के लिए धन्यवाद! आगामी रैफ़ल में मिलते हैं।", - "RafflesInfoTitle": "एबीपी कम्युनिटी रैफल्स" + "RafflesInfoTitle": "एबीपी कम्युनिटी रैफल्स", + "MarkdownSupported": "Markdown का समर्थन किया।" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hr.json index 5b3546a78b..4e213a9c66 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hr.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hr.json @@ -255,6 +255,7 @@ "LatestArticles": "Najnoviji članci", "RaffleHeader": "Pozdrav članu ABP zajednice!", "RafflesInfo": "
Ovo je stranica za nagradnu igru namijenjena da vam pokažemo našu zahvalnost što ste aktivni član zajednice. Vodimo razgovore o ABP zajednici , ABP .NET konferenciji , prisustvujemo ili sponzoriramo događaje vezane uz .NET na kojima dijelimo neke darove.

Možete pratiti ovu stranicu kako biste vidjeli nadolazeće nagradne igre, prisustvovali im ili vidjeli prethodne nagradne igre koje izvlačimo uključujući dobitnike.

Hvala vam što ste aktivan član! Vidimo se u nadolazećim nagradnim igrama.", - "RafflesInfoTitle": "Izvlačenje nagradne igre zajednice ABP" + "RafflesInfoTitle": "Izvlačenje nagradne igre zajednice ABP", + "MarkdownSupported": "Markdown podržan." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hu.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hu.json index 1f74f9e7a9..f489cdc571 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hu.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hu.json @@ -255,6 +255,7 @@ "LatestArticles": "Legfrissebb cikkek", "RaffleHeader": "Kedves ABP közösségi tag!", "RafflesInfo": "
Ez az a sorsolási oldal, amelynek célja, hogy kifejezzük hálánkat feléd, amiért aktív közösségi tag vagy. Az ABP Community Talks-okat , az ABP .NET konferenciákat szervezzük, részt veszünk vagy szponzorálunk olyan .NET-hez kapcsolódó eseményeket, amelyeken ajándékokat adunk.

Ezt az oldalt követheti, hogy megtekinthesse a közelgő sorsolásokat, részt vegyen azokon, vagy megtekinthesse korábbi sorsolásainkat, beleértve a nyerteseket is.

Köszönjük, hogy aktív tag vagy! Találkozunk a sorsoláson.", - "RafflesInfoTitle": "ABP közösségi tombola" + "RafflesInfoTitle": "ABP közösségi tombola", + "MarkdownSupported": "Markdown támogatott." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/is.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/is.json index a991c387d4..32284f5f37 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/is.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/is.json @@ -255,6 +255,7 @@ "LatestArticles": "Nýjustu greinar", "RaffleHeader": "Halló ABP samfélagsmeðlimur!", "RafflesInfo": "
Þetta er happdrættisíðan sem er tileinkuð þér að þakka þér fyrir að vera virkur samfélagsmeðlimur. Við gerum ABP Community Talks , ABP .NET ráðstefnu , sækjum eða styrkjum .NET tengda viðburði þar sem við gefum nokkrar gjafir.

Þú getur fylgst með þessari síðu til að sjá komandi happdrætti, mæta á þær eða sjá fyrri happdrætti sem við drögum út, þar á meðal vinningshafa.

Þakka þér fyrir að vera virkur meðlimur! Sjáumst í komandi happdrætti.", - "RafflesInfoTitle": "ABP samfélagshappdrætti" + "RafflesInfoTitle": "ABP samfélagshappdrætti", + "MarkdownSupported": "Markdown stutt." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/it.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/it.json index 901c356c9a..301c1e84e7 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/it.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/it.json @@ -255,6 +255,7 @@ "LatestArticles": "Articoli Recenti", "RaffleHeader": "Ciao membro della comunità ABP!", "RafflesInfo": "
Questa è la pagina della lotteria dedicata a mostrare il nostro apprezzamento nei tuoi confronti per essere un membro attivo della comunità. Organizziamo ABP Community Talks , ABP .NET Conference , partecipiamo o sponsorizziamo eventi relativi a .NET in cui regaliamo alcuni regali.

Puoi seguire questa pagina per vedere le prossime lotterie, parteciparvi o vedere le lotterie precedenti che estraiamo, compresi i vincitori.

Grazie per essere un membro attivo! Ci vediamo alle prossime lotterie.", - "RafflesInfoTitle": "Lotterie comunitarie ABP" + "RafflesInfoTitle": "Lotterie comunitarie ABP", + "MarkdownSupported": "Markdown supportato." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/nl.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/nl.json index 4ee8e44a09..8beba46650 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/nl.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/nl.json @@ -255,6 +255,7 @@ "LatestArticles": "Laatste artikels", "RaffleHeader": "Hallo ABP Community-lid!", "RafflesInfo": "
Dit is de loterijpagina die bedoeld is om onze waardering voor u te tonen omdat u een actief lid van de community bent. We houden ABP Community Talks , ABP .NET Conference , wonen of sponsoren de .NET-gerelateerde evenementen bij waarin we een aantal geschenken weggeven.

U kunt deze pagina volgen om de komende loterijen te zien, deze bij te wonen of eerdere loterijen te zien die we trekken, inclusief de winnaars.

Bedankt dat u een actief lid bent! Tot ziens bij de komende loterijen.", - "RafflesInfoTitle": "ABP- gemeenschaploterijen" + "RafflesInfoTitle": "ABP- gemeenschaploterijen", + "MarkdownSupported": "Markdown ondersteund." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/pl-PL.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/pl-PL.json index 2df6780f03..e47be75ccc 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/pl-PL.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/pl-PL.json @@ -255,6 +255,7 @@ "LatestArticles": "ostatnie artykuły", "RaffleHeader": "Witaj, członku społeczności ABP!", "RafflesInfo": "
To jest strona loterii, której celem jest wyrażenie naszego uznania dla Ciebie za bycie aktywnym członkiem społeczności. Prowadzimy rozmowy społecznościowe ABP , konferencje ABP .NET , uczestniczymy lub sponsorujemy wydarzenia związane z .NET, podczas których rozdajemy prezenty.

Możesz śledzić tę stronę, aby zobaczyć nadchodzące loterie, wziąć w nich udział lub zobaczyć poprzednie loterie, które losowaliśmy, w tym zwycięzców.

Dziękujemy za bycie aktywnym członkiem! Do zobaczenia w nadchodzących loteriach.", - "RafflesInfoTitle": "Loterie społecznościowe ABP" + "RafflesInfoTitle": "Loterie społecznościowe ABP", + "MarkdownSupported": "Markdown utrzymany." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/pt-BR.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/pt-BR.json index 9f2ce433d9..d987c03211 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/pt-BR.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/pt-BR.json @@ -255,6 +255,7 @@ "LatestArticles": "Artigos Mais Recentes", "RaffleHeader": "Olá, membro da comunidade ABP!", "RafflesInfo": "
Esta é a página do sorteio dedicada a mostrar nosso agradecimento por você ser um membro ativo da comunidade. Fazemos ABP Community Talks , ABP .NET Conference , participamos ou patrocinamos eventos relacionados ao .NET nos quais distribuímos alguns presentes.

Você pode seguir esta página para ver os próximos sorteios, participar deles ou ver os sorteios anteriores que sorteamos, incluindo os vencedores.

Obrigado por ser um membro ativo! Nos vemos nos próximos sorteios.", - "RafflesInfoTitle": "Sorteios da Comunidade ABP" + "RafflesInfoTitle": "Sorteios da Comunidade ABP", + "MarkdownSupported": "Markdown suportado." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ro-RO.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ro-RO.json index c2862d1fd7..06ecc4dea8 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ro-RO.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ro-RO.json @@ -255,6 +255,7 @@ "LatestArticles": "ultimele articole", "RaffleHeader": "Bună ziua, membru al comunității ABP!", "RafflesInfo": "
Aceasta este pagina de tombolă dedicată pentru a arăta aprecierea noastră față de dvs. pentru că sunteți un membru activ al comunității. Facem ABP Community Talks , ABP .NET Conference , participăm sau sponsorizăm evenimentele legate de .NET în care oferim câteva cadouri.

Puteți urmări această pagină pentru a vedea tombolele viitoare, a participa la ele sau pentru a vedea tombolele anterioare pe care le extragem, inclusiv câștigătorii.

Vă mulțumim că sunteți un membru activ! Ne vedem la tombolele viitoare.", - "RafflesInfoTitle": "Tombole comunitare ABP" + "RafflesInfoTitle": "Tombole comunitare ABP", + "MarkdownSupported": "Markdown sprijinit." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ru.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ru.json index 27f2b1203a..07d6a87fe9 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ru.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ru.json @@ -258,6 +258,7 @@ "LatestArticles": "Последние статьи", "RaffleHeader": "Привет, участник сообщества ABP!", "RafflesInfo": "
Эта страница розыгрыша посвящена тому, чтобы выразить нашу признательность вам за то, что вы являетесь активным членом сообщества. Обсуждения сообщества ABP ,Конференция ABP .NET, посещать или спонсировать мероприятия, связанные с .NET, на которых мы раздаем подарки.

Вы можете подписаться на эту страницу, чтобы увидеть предстоящие розыгрыши, посетить их или просмотреть предыдущие розыгрыши, которые мы проводим, включая победителей.

Спасибо за активное участие! ", - "RafflesInfoTitle": "Сообщество АБП Розыгрыши" + "RafflesInfoTitle": "Сообщество АБП Розыгрыши", + "MarkdownSupported": "Markdown поддерживается." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sk.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sk.json index 6ab3c9d074..fa9826b421 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sk.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sk.json @@ -255,6 +255,7 @@ "LatestArticles": "Najnovšie články", "RaffleHeader": "Dobrý deň, člen komunity ABP!", "RafflesInfo": "
Toto je stránka žrebovania venovaná na vyjadrenie nášho uznania vám za to, že ste aktívnym členom komunity. Robíme ABP Community Talks , ABP .NET konferenciu , zúčastňujeme sa alebo sponzorujeme podujatia súvisiace s .NET, na ktorých rozdávame nejaké darčeky.

Na tejto stránke si môžete pozrieť pripravované tomboly, zúčastniť sa ich alebo si pozrieť predchádzajúce žrebovanie, ktoré vyžrebujeme vrátane výhercov.

Ďakujeme, že ste aktívnym členom! Vidíme sa v najbližšom žrebovaní.", - "RafflesInfoTitle": "Komunitné tomboly ABP" + "RafflesInfoTitle": "Komunitné tomboly ABP", + "MarkdownSupported": "Markdown podporované." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sl.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sl.json index 23763c6f78..81e103cd17 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sl.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sl.json @@ -255,6 +255,7 @@ "LatestArticles": "Najnovejši članki", "RaffleHeader": "Pozdravljeni član skupnosti ABP!", "RafflesInfo": "
To je stran za nagradno igro, namenjena izkazovanju naše hvaležnosti do vas, ker ste aktivni član skupnosti. Izvajamo ABP Community Talks , ABP .NET Conference , se udeležujemo ali sponzoriramo dogodke, povezane z .NET, na katerih podarimo nekaj daril.

To stran lahko spremljate in si ogledate prihajajoče nagradne igre, se jih udeležite ali si ogledate prejšnje nagradne igre, ki smo jih izžrebali, vključno z zmagovalci.

Hvala, ker ste aktivni član! Se vidimo na prihajajočih nagradnih igrah.", - "RafflesInfoTitle": "Žrebanje skupnosti ABP" + "RafflesInfoTitle": "Žrebanje skupnosti ABP", + "MarkdownSupported": "Markdown podprt." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/tr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/tr.json index 2d52d01ed2..d184bb63d1 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/tr.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/tr.json @@ -189,6 +189,7 @@ "Layout_MetaDescription": "ABP Topluluğu, insanların ABP çerçevesi hakkında paylaşımlarda bulunabileceği ve projeleri takip edebileceği bir ortamdır.", "Index_Page_CommunityIntroduction": "Burası ABP Çerçevesi, .NET ve yazılım geliştirme için bir merkezdir. Makaleleri okuyabilir, eğitim videolarını izleyebilir, ABP'nin gelişim süreci ve ABP ile ilgili etkinlikler hakkında bilgi alabilir, diğer geliştiricilere yardımcı olabilir ve uzmanlığınızı ABP topluluğu ile paylaşabilirsiniz.", "IConsentToMedium": "Bu yazının https://medium.com/volosoft adresinde yayınlanmasına izin veriyorum.", - "DiscordPageTitle": "ABP Discord Topluluğu" + "DiscordPageTitle": "ABP Discord Topluluğu", + "MarkdownSupported": "Markdown destekleniyor." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/vi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/vi.json index a36ec9b0e8..d7febbb014 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/vi.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/vi.json @@ -255,6 +255,7 @@ "LatestArticles": "Bài viết mới nhất", "RaffleHeader": "Xin chào Thành viên Cộng đồng ABP!", "RafflesInfo": "
Đây là trang xổ số dành riêng để thể hiện sự đánh giá cao của chúng tôi đối với bạn vì đã trở thành Thành viên cộng đồng tích cực. Chúng tôi tổ chức các buổi nói chuyện cộng đồng ABP , Hội nghị ABP .NET , tham dự hoặc tài trợ cho các sự kiện liên quan đến .NET mà trong đó chúng tôi tặng một số quà tặng.

Bạn có thể theo dõi trang này để xem các cuộc xổ số sắp tới, tham dự hoặc xem các cuộc xổ số trước đây mà chúng tôi rút ra bao gồm cả những người chiến thắng.

Cảm ơn bạn đã là thành viên tích cực! Hẹn gặp lại các bạn trong đợt xổ số sắp tới.", - "RafflesInfoTitle": "Xổ số cộng đồng ABP" + "RafflesInfoTitle": "Xổ số cộng đồng ABP", + "MarkdownSupported": "Markdown được hỗ trợ." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hans.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hans.json index e899a94872..c0aaf2678b 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hans.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hans.json @@ -255,6 +255,7 @@ "LatestArticles": "最新文章", "RaffleHeader": "你好,ABP 社区成员!", "RafflesInfo": "
这是一个抽奖页面,旨在感谢您成为活跃的社区成员。我们举办 ABP 社区讲座 、ABP .NET 会议,参加或赞助与 .NET 相关的活动,并在活动中赠送一些礼品。

您可以关注此页面,查看即将举行的抽奖活动、参加这些活动或查看我们以前举行的抽奖活动(包括获奖者)。

感谢您成为我们的活跃成员!在即将举行的抽奖活动中再见。", - "RafflesInfoTitle": "ABP 社区来抽奖来抽奖Markdown 支持的。" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hant.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hant.json index ebec42dd8a..7f8e58f7df 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hant.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hant.json @@ -255,6 +255,7 @@ "LatestArticles": "最新的文章", "RaffleHeader": "ABP 社群成員您好!", "RafflesInfo": "
這是抽獎頁面,旨在表達我們對您作為活躍社區成員的感謝。我們舉辦ABP 社群講座、ABP .NET 會議、參加或贊助 .NET 相關活動,並在活動中贈送一些禮物。

您可以關注此頁面查看即將舉行的抽獎活動、參加抽獎活動或查看我們之前抽獎的抽獎活動(包括獲獎者)。

感謝您成為活躍會員!在即將到來的抽獎活動中再見。", - "RafflesInfoTitle": "ABP 社區萊佛士" + "RafflesInfoTitle": "ABP 社區萊佛士", + "MarkdownSupported": "Markdown 支持的。" } } \ No newline at end of file From 368eb9c565543934ab4d23b706b59a1f7e8556c1 Mon Sep 17 00:00:00 2001 From: maliming Date: Thu, 25 Jan 2024 13:53:30 +0800 Subject: [PATCH 122/154] Migration notes for NormalizedName property of Tenant. Resolve #18857 --- docs/en/Migration-Guides/Abp-8_1.md | 86 +++++++++++++++++++++++++++++ docs/en/Multi-Tenancy.md | 2 +- 2 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 docs/en/Migration-Guides/Abp-8_1.md diff --git a/docs/en/Migration-Guides/Abp-8_1.md b/docs/en/Migration-Guides/Abp-8_1.md new file mode 100644 index 0000000000..d5ec87a3ca --- /dev/null +++ b/docs/en/Migration-Guides/Abp-8_1.md @@ -0,0 +1,86 @@ +# ABP Version 8.1 Migration Guide + +This document is a guide for upgrading ABP v8.0 solutions to ABP v8.1. There are some changes in this version that may affect your applications, please read it carefully and apply the necessary changes to your application. + +## Added `NormalizedName` property to `Tenant` + +The `Tenant` entity has a new property called `NormalizedName`. It is used to find/cache a tenant by its name in a case-insensitive way. +This property is automatically set when a tenant is created or updated. It gets the normalized name of the tenant name by `UpperInvariantTenantNormalizer(ITenantNormalizer)` service. You can implement this service to change the normalization logic. + +### `ITenantStore` + +The `ITenantStore` will use the `NormalizedName` parameter to get tenants, Please use the `ITenantNormalizer` to normalize the tenant name before calling the `ITenantStore` methods. + +### Update `NormalizedName` in `appsettings.json` + +If your tenants defined in the `appsettings.json` file, you should add the `NormalizedName` property to your tenants. + +````json +"Tenants": [ + { + "Id": "446a5211-3d72-4339-9adc-845151f8ada0", + "Name": "tenant1", + "NormalizedName": "TENANT1" // <-- Add this property + }, + { + "Id": "25388015-ef1c-4355-9c18-f6b6ddbaf89d", + "Name": "tenant2", + "NormalizedName": "TENANT2", // <-- Add this property + "ConnectionStrings": { + "Default": "...tenant2's db connection string here..." + } + } + ] +```` + +### Update `NormalizedName` in the database + +Please add a sql script to your migration to set the `NormalizedName` property of the existing tenants. You can use the following script: + +> This script is for the SQL Server database. You can change it for your database. + +> The table name `SaasTenants` is used for ABP commercial Saas module. `AbpTenants` is for the ABP open-source Tenant Management module. + +```sql +UPDATE SaasTenants SET NormalizedName = UPPER(Name) WHERE NormalizedName IS NULL OR NormalizedName = '' +``` + +```csharp +/// +public partial class Add_NormalizedName : Migration +{ + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "NormalizedName", + table: "SaasTenants", + type: "citext", + maxLength: 64, + nullable: false, + defaultValue: ""); + + migrationBuilder.Sql("UPDATE SaasTenants SET NormalizedName = UPPER(Name) WHERE NormalizedName IS NULL OR NormalizedName = ''"); + + migrationBuilder.CreateIndex( + name: "IX_SaasTenants_NormalizedName", + table: "SaasTenants", + column: "NormalizedName"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_SaasTenants_NormalizedName", + table: "SaasTenants"); + + migrationBuilder.DropColumn( + name: "NormalizedName", + table: "SaasTenants"); + } +} +``` + +See https://learn.microsoft.com/en-us/ef/core/managing-schemas/migrations/managing?tabs=dotnet-core-cli#adding-raw-sql to learn how to add raw SQL to migrations. + diff --git a/docs/en/Multi-Tenancy.md b/docs/en/Multi-Tenancy.md index 392bea6809..698879bdf1 100644 --- a/docs/en/Multi-Tenancy.md +++ b/docs/en/Multi-Tenancy.md @@ -394,7 +394,7 @@ app.UseMultiTenancy(); `ITenantStore` is used to get the tenant configuration from a data source. -> Tenant names are not case-sensitive. `ITenantStore` will use the `NormalizedName` parameter to get tenants, You need to use `ITenantNormalizer to normalize tenant names. +> Tenant names are not case-sensitive. `ITenantStore` will use the `NormalizedName` parameter to get tenants, You need to use `ITenantNormalizer`` to normalize tenant names. #### Tenant Management Module From 1fe4a25b9cf73921b84305f8d258126f9db09436 Mon Sep 17 00:00:00 2001 From: maliming Date: Thu, 25 Jan 2024 13:55:42 +0800 Subject: [PATCH 123/154] Update Multi-Tenancy.md --- docs/en/Multi-Tenancy.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/Multi-Tenancy.md b/docs/en/Multi-Tenancy.md index 698879bdf1..922976767d 100644 --- a/docs/en/Multi-Tenancy.md +++ b/docs/en/Multi-Tenancy.md @@ -394,7 +394,7 @@ app.UseMultiTenancy(); `ITenantStore` is used to get the tenant configuration from a data source. -> Tenant names are not case-sensitive. `ITenantStore` will use the `NormalizedName` parameter to get tenants, You need to use `ITenantNormalizer`` to normalize tenant names. +> Tenant names are not case-sensitive. `ITenantStore` will use the `NormalizedName` parameter to get tenants, You need to use `ITenantNormalizer` to normalize tenant names. #### Tenant Management Module From 1bffcc7220b99eb9346fc4f88ca70722168e970d Mon Sep 17 00:00:00 2001 From: maliming Date: Thu, 25 Jan 2024 14:05:36 +0800 Subject: [PATCH 124/154] Update Abp-8_1.md --- docs/en/Migration-Guides/Abp-8_1.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/en/Migration-Guides/Abp-8_1.md b/docs/en/Migration-Guides/Abp-8_1.md index d5ec87a3ca..6f4c316d3f 100644 --- a/docs/en/Migration-Guides/Abp-8_1.md +++ b/docs/en/Migration-Guides/Abp-8_1.md @@ -55,8 +55,7 @@ public partial class Add_NormalizedName : Migration migrationBuilder.AddColumn( name: "NormalizedName", table: "SaasTenants", - type: "citext", - maxLength: 64, + type: "nvarchar(64)", nullable: false, defaultValue: ""); From 9438b57bbe4a3fca3cf2b995307459b2fe6591f9 Mon Sep 17 00:00:00 2001 From: maliming Date: Thu, 25 Jan 2024 14:17:32 +0800 Subject: [PATCH 125/154] Add index for `NormalizedName` peroperty. --- .../AbpTenantManagementDbContextModelCreatingExtensions.cs | 1 + ...nitial.Designer.cs => 20240125061235_Initial.Designer.cs} | 4 +++- .../{20240110051639_Initial.cs => 20240125061235_Initial.cs} | 5 +++++ .../Migrations/MyProjectNameDbContextModelSnapshot.cs | 2 ++ ...nitial.Designer.cs => 20240125061501_Initial.Designer.cs} | 4 +++- .../Server/Migrations/20240125061501_Initial.cs} | 5 +++++ .../Server/Migrations/MyProjectNameDbContextModelSnapshot.cs | 2 ++ ...nitial.Designer.cs => 20240125061101_Initial.Designer.cs} | 4 +++- .../{20240110051553_Initial.cs => 20240125061101_Initial.cs} | 5 +++++ .../Migrations/MyProjectNameDbContextModelSnapshot.cs | 2 ++ ...nitial.Designer.cs => 20240125061143_Initial.Designer.cs} | 4 +++- .../{20240110051615_Initial.cs => 20240125061143_Initial.cs} | 5 +++++ .../Migrations/MyProjectNameDbContextModelSnapshot.cs | 2 ++ ...nitial.Designer.cs => 20240125061248_Initial.Designer.cs} | 4 +++- .../{20240110051649_Initial.cs => 20240125061248_Initial.cs} | 5 +++++ .../Migrations/MyProjectNameDbContextModelSnapshot.cs | 2 ++ ...nitial.Designer.cs => 20240125061344_Initial.Designer.cs} | 4 +++- .../Migrations/20240125061344_Initial.cs} | 5 +++++ .../Migrations/AuthServerDbContextModelSnapshot.cs | 2 ++ ...nitial.Designer.cs => 20240125061321_Initial.Designer.cs} | 4 +++- .../{20240110051713_Initial.cs => 20240125061321_Initial.cs} | 5 +++++ .../Migrations/UnifiedDbContextModelSnapshot.cs | 2 ++ ...nitial.Designer.cs => 20240125061400_Initial.Designer.cs} | 2 +- .../{20240110051748_Initial.cs => 20240125061400_Initial.cs} | 0 ...nitial.Designer.cs => 20240125061424_Initial.Designer.cs} | 4 +++- .../{20240110051810_Initial.cs => 20240125061424_Initial.cs} | 5 +++++ .../Migrations/UnifiedDbContextModelSnapshot.cs | 2 ++ 27 files changed, 82 insertions(+), 9 deletions(-) rename templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/{20240110051639_Initial.Designer.cs => 20240125061235_Initial.Designer.cs} (99%) rename templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/{20240110051639_Initial.cs => 20240125061235_Initial.cs} (99%) rename templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/{20240110051838_Initial.Designer.cs => 20240125061501_Initial.Designer.cs} (99%) rename templates/{module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20240110051734_Initial.cs => app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20240125061501_Initial.cs} (99%) rename templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/{20240110051553_Initial.Designer.cs => 20240125061101_Initial.Designer.cs} (99%) rename templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/{20240110051553_Initial.cs => 20240125061101_Initial.cs} (99%) rename templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/{20240110051615_Initial.Designer.cs => 20240125061143_Initial.Designer.cs} (99%) rename templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/{20240110051615_Initial.cs => 20240125061143_Initial.cs} (99%) rename templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/{20240110051649_Initial.Designer.cs => 20240125061248_Initial.Designer.cs} (99%) rename templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/{20240110051649_Initial.cs => 20240125061248_Initial.cs} (99%) rename templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/{20240110051734_Initial.Designer.cs => 20240125061344_Initial.Designer.cs} (99%) rename templates/{app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20240110051838_Initial.cs => module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20240125061344_Initial.cs} (99%) rename templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/{20240110051713_Initial.Designer.cs => 20240125061321_Initial.Designer.cs} (99%) rename templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/{20240110051713_Initial.cs => 20240125061321_Initial.cs} (99%) rename templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/{20240110051748_Initial.Designer.cs => 20240125061400_Initial.Designer.cs} (96%) rename templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/{20240110051748_Initial.cs => 20240125061400_Initial.cs} (100%) rename templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/{20240110051810_Initial.Designer.cs => 20240125061424_Initial.Designer.cs} (99%) rename templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/{20240110051810_Initial.cs => 20240125061424_Initial.cs} (99%) diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/AbpTenantManagementDbContextModelCreatingExtensions.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/AbpTenantManagementDbContextModelCreatingExtensions.cs index bb189e72a1..a91cf066e5 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/AbpTenantManagementDbContextModelCreatingExtensions.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/AbpTenantManagementDbContextModelCreatingExtensions.cs @@ -28,6 +28,7 @@ public static class AbpTenantManagementDbContextModelCreatingExtensions b.HasMany(u => u.ConnectionStrings).WithOne().HasForeignKey(uc => uc.TenantId).IsRequired(); b.HasIndex(u => u.Name); + b.HasIndex(u => u.NormalizedName); b.ApplyObjectExtensionMappings(); }); diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20240110051639_Initial.Designer.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20240125061235_Initial.Designer.cs similarity index 99% rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20240110051639_Initial.Designer.cs rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20240125061235_Initial.Designer.cs index 720730ac29..2f3a437364 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20240110051639_Initial.Designer.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20240125061235_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Blazor.Server.Migrations { [DbContext(typeof(MyProjectNameDbContext))] - [Migration("20240110051639_Initial")] + [Migration("20240125061235_Initial")] partial class Initial { /// @@ -1696,6 +1696,8 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Migrations b.HasIndex("Name"); + b.HasIndex("NormalizedName"); + b.ToTable("AbpTenants", (string)null); }); diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20240110051639_Initial.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20240125061235_Initial.cs similarity index 99% rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20240110051639_Initial.cs rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20240125061235_Initial.cs index f55e1bd71a..dd96c605e7 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20240110051639_Initial.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20240125061235_Initial.cs @@ -914,6 +914,11 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Migrations table: "AbpTenants", column: "Name"); + migrationBuilder.CreateIndex( + name: "IX_AbpTenants_NormalizedName", + table: "AbpTenants", + column: "NormalizedName"); + migrationBuilder.CreateIndex( name: "IX_AbpUserClaims_UserId", table: "AbpUserClaims", diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/MyProjectNameDbContextModelSnapshot.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/MyProjectNameDbContextModelSnapshot.cs index 94403eda52..652e7b674d 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/MyProjectNameDbContextModelSnapshot.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/MyProjectNameDbContextModelSnapshot.cs @@ -1693,6 +1693,8 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Migrations b.HasIndex("Name"); + b.HasIndex("NormalizedName"); + b.ToTable("AbpTenants", (string)null); }); diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20240110051838_Initial.Designer.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20240125061501_Initial.Designer.cs similarity index 99% rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20240110051838_Initial.Designer.cs rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20240125061501_Initial.Designer.cs index d8f8a2f32c..f25d60e99b 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20240110051838_Initial.Designer.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20240125061501_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Migrations { [DbContext(typeof(MyProjectNameDbContext))] - [Migration("20240110051838_Initial")] + [Migration("20240125061501_Initial")] partial class Initial { /// @@ -1696,6 +1696,8 @@ namespace MyCompanyName.MyProjectName.Migrations b.HasIndex("Name"); + b.HasIndex("NormalizedName"); + b.ToTable("AbpTenants", (string)null); }); diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20240110051734_Initial.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20240125061501_Initial.cs similarity index 99% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20240110051734_Initial.cs rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20240125061501_Initial.cs index 42da66e3e2..b0cb9b0e6f 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20240110051734_Initial.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20240125061501_Initial.cs @@ -914,6 +914,11 @@ namespace MyCompanyName.MyProjectName.Migrations table: "AbpTenants", column: "Name"); + migrationBuilder.CreateIndex( + name: "IX_AbpTenants_NormalizedName", + table: "AbpTenants", + column: "NormalizedName"); + migrationBuilder.CreateIndex( name: "IX_AbpUserClaims_UserId", table: "AbpUserClaims", diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/MyProjectNameDbContextModelSnapshot.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/MyProjectNameDbContextModelSnapshot.cs index 2085b9d8cd..72f44ed239 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/MyProjectNameDbContextModelSnapshot.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/MyProjectNameDbContextModelSnapshot.cs @@ -1693,6 +1693,8 @@ namespace MyCompanyName.MyProjectName.Migrations b.HasIndex("Name"); + b.HasIndex("NormalizedName"); + b.ToTable("AbpTenants", (string)null); }); diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20240110051553_Initial.Designer.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20240125061101_Initial.Designer.cs similarity index 99% rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20240110051553_Initial.Designer.cs rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20240125061101_Initial.Designer.cs index a17b97362f..364eaa6b57 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20240110051553_Initial.Designer.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20240125061101_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Host.Migrations { [DbContext(typeof(MyProjectNameDbContext))] - [Migration("20240110051553_Initial")] + [Migration("20240125061101_Initial")] partial class Initial { /// @@ -1696,6 +1696,8 @@ namespace MyCompanyName.MyProjectName.Host.Migrations b.HasIndex("Name"); + b.HasIndex("NormalizedName"); + b.ToTable("AbpTenants", (string)null); }); diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20240110051553_Initial.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20240125061101_Initial.cs similarity index 99% rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20240110051553_Initial.cs rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20240125061101_Initial.cs index 0b4123ab8d..bfb34fcaad 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20240110051553_Initial.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20240125061101_Initial.cs @@ -914,6 +914,11 @@ namespace MyCompanyName.MyProjectName.Host.Migrations table: "AbpTenants", column: "Name"); + migrationBuilder.CreateIndex( + name: "IX_AbpTenants_NormalizedName", + table: "AbpTenants", + column: "NormalizedName"); + migrationBuilder.CreateIndex( name: "IX_AbpUserClaims_UserId", table: "AbpUserClaims", diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/MyProjectNameDbContextModelSnapshot.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/MyProjectNameDbContextModelSnapshot.cs index 6035862d19..f2b46a651f 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/MyProjectNameDbContextModelSnapshot.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/MyProjectNameDbContextModelSnapshot.cs @@ -1693,6 +1693,8 @@ namespace MyCompanyName.MyProjectName.Host.Migrations b.HasIndex("Name"); + b.HasIndex("NormalizedName"); + b.ToTable("AbpTenants", (string)null); }); diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20240110051615_Initial.Designer.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20240125061143_Initial.Designer.cs similarity index 99% rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20240110051615_Initial.Designer.cs rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20240125061143_Initial.Designer.cs index e2a3ff5a34..54929eb8e9 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20240110051615_Initial.Designer.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20240125061143_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Mvc.Migrations { [DbContext(typeof(MyProjectNameDbContext))] - [Migration("20240110051615_Initial")] + [Migration("20240125061143_Initial")] partial class Initial { /// @@ -1696,6 +1696,8 @@ namespace MyCompanyName.MyProjectName.Mvc.Migrations b.HasIndex("Name"); + b.HasIndex("NormalizedName"); + b.ToTable("AbpTenants", (string)null); }); diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20240110051615_Initial.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20240125061143_Initial.cs similarity index 99% rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20240110051615_Initial.cs rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20240125061143_Initial.cs index 6fd77905c4..44eddb6abb 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20240110051615_Initial.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20240125061143_Initial.cs @@ -914,6 +914,11 @@ namespace MyCompanyName.MyProjectName.Mvc.Migrations table: "AbpTenants", column: "Name"); + migrationBuilder.CreateIndex( + name: "IX_AbpTenants_NormalizedName", + table: "AbpTenants", + column: "NormalizedName"); + migrationBuilder.CreateIndex( name: "IX_AbpUserClaims_UserId", table: "AbpUserClaims", diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/MyProjectNameDbContextModelSnapshot.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/MyProjectNameDbContextModelSnapshot.cs index 7f594fe2e5..8041069541 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/MyProjectNameDbContextModelSnapshot.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/MyProjectNameDbContextModelSnapshot.cs @@ -1693,6 +1693,8 @@ namespace MyCompanyName.MyProjectName.Mvc.Migrations b.HasIndex("Name"); + b.HasIndex("NormalizedName"); + b.ToTable("AbpTenants", (string)null); }); diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20240110051649_Initial.Designer.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20240125061248_Initial.Designer.cs similarity index 99% rename from templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20240110051649_Initial.Designer.cs rename to templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20240125061248_Initial.Designer.cs index 5749fe8a39..e211d7e755 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20240110051649_Initial.Designer.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20240125061248_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Migrations { [DbContext(typeof(MyProjectNameDbContext))] - [Migration("20240110051649_Initial")] + [Migration("20240125061248_Initial")] partial class Initial { /// @@ -1748,6 +1748,8 @@ namespace MyCompanyName.MyProjectName.Migrations b.HasIndex("Name"); + b.HasIndex("NormalizedName"); + b.ToTable("AbpTenants", (string)null); }); diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20240110051649_Initial.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20240125061248_Initial.cs similarity index 99% rename from templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20240110051649_Initial.cs rename to templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20240125061248_Initial.cs index 2fe3338034..9fc3a5a0b9 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20240110051649_Initial.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20240125061248_Initial.cs @@ -940,6 +940,11 @@ namespace MyCompanyName.MyProjectName.Migrations table: "AbpTenants", column: "Name"); + migrationBuilder.CreateIndex( + name: "IX_AbpTenants_NormalizedName", + table: "AbpTenants", + column: "NormalizedName"); + migrationBuilder.CreateIndex( name: "IX_AbpUserClaims_UserId", table: "AbpUserClaims", diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/MyProjectNameDbContextModelSnapshot.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/MyProjectNameDbContextModelSnapshot.cs index 1b7c95358e..877bff36e8 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/MyProjectNameDbContextModelSnapshot.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/MyProjectNameDbContextModelSnapshot.cs @@ -1745,6 +1745,8 @@ namespace MyCompanyName.MyProjectName.Migrations b.HasIndex("Name"); + b.HasIndex("NormalizedName"); + b.ToTable("AbpTenants", (string)null); }); diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20240110051734_Initial.Designer.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20240125061344_Initial.Designer.cs similarity index 99% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20240110051734_Initial.Designer.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20240125061344_Initial.Designer.cs index d732cf68bb..b6dd932e2f 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20240110051734_Initial.Designer.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20240125061344_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Migrations { [DbContext(typeof(AuthServerDbContext))] - [Migration("20240110051734_Initial")] + [Migration("20240125061344_Initial")] partial class Initial { /// @@ -1696,6 +1696,8 @@ namespace MyCompanyName.MyProjectName.Migrations b.HasIndex("Name"); + b.HasIndex("NormalizedName"); + b.ToTable("AbpTenants", (string)null); }); diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20240110051838_Initial.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20240125061344_Initial.cs similarity index 99% rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20240110051838_Initial.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20240125061344_Initial.cs index 42da66e3e2..b0cb9b0e6f 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20240110051838_Initial.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20240125061344_Initial.cs @@ -914,6 +914,11 @@ namespace MyCompanyName.MyProjectName.Migrations table: "AbpTenants", column: "Name"); + migrationBuilder.CreateIndex( + name: "IX_AbpTenants_NormalizedName", + table: "AbpTenants", + column: "NormalizedName"); + migrationBuilder.CreateIndex( name: "IX_AbpUserClaims_UserId", table: "AbpUserClaims", diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/AuthServerDbContextModelSnapshot.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/AuthServerDbContextModelSnapshot.cs index 95ab069a86..c3fb7f9ff0 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/AuthServerDbContextModelSnapshot.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/AuthServerDbContextModelSnapshot.cs @@ -1693,6 +1693,8 @@ namespace MyCompanyName.MyProjectName.Migrations b.HasIndex("Name"); + b.HasIndex("NormalizedName"); + b.ToTable("AbpTenants", (string)null); }); diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20240110051713_Initial.Designer.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20240125061321_Initial.Designer.cs similarity index 99% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20240110051713_Initial.Designer.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20240125061321_Initial.Designer.cs index fa01be30fc..3c17670e22 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20240110051713_Initial.Designer.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20240125061321_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Blazor.Server.Host.Migrations { [DbContext(typeof(UnifiedDbContext))] - [Migration("20240110051713_Initial")] + [Migration("20240125061321_Initial")] partial class Initial { /// @@ -1337,6 +1337,8 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Host.Migrations b.HasIndex("Name"); + b.HasIndex("NormalizedName"); + b.ToTable("AbpTenants", (string)null); }); diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20240110051713_Initial.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20240125061321_Initial.cs similarity index 99% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20240110051713_Initial.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20240125061321_Initial.cs index a27989973a..1a8774f577 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20240110051713_Initial.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20240125061321_Initial.cs @@ -778,6 +778,11 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Host.Migrations table: "AbpTenants", column: "Name"); + migrationBuilder.CreateIndex( + name: "IX_AbpTenants_NormalizedName", + table: "AbpTenants", + column: "NormalizedName"); + migrationBuilder.CreateIndex( name: "IX_AbpUserClaims_UserId", table: "AbpUserClaims", diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/UnifiedDbContextModelSnapshot.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/UnifiedDbContextModelSnapshot.cs index 9835c59cd3..4acfb0c562 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/UnifiedDbContextModelSnapshot.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/UnifiedDbContextModelSnapshot.cs @@ -1334,6 +1334,8 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Host.Migrations b.HasIndex("Name"); + b.HasIndex("NormalizedName"); + b.ToTable("AbpTenants", (string)null); }); diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/20240110051748_Initial.Designer.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/20240125061400_Initial.Designer.cs similarity index 96% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/20240110051748_Initial.Designer.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/20240125061400_Initial.Designer.cs index 2eb38813a6..c58552ea60 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/20240110051748_Initial.Designer.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/20240125061400_Initial.Designer.cs @@ -12,7 +12,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Migrations { [DbContext(typeof(MyProjectNameHttpApiHostMigrationsDbContext))] - [Migration("20240110051748_Initial")] + [Migration("20240125061400_Initial")] partial class Initial { /// diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/20240110051748_Initial.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/20240125061400_Initial.cs similarity index 100% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/20240110051748_Initial.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/20240125061400_Initial.cs diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20240110051810_Initial.Designer.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20240125061424_Initial.Designer.cs similarity index 99% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20240110051810_Initial.Designer.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20240125061424_Initial.Designer.cs index f7363bd08d..04cad1c308 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20240110051810_Initial.Designer.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20240125061424_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Migrations { [DbContext(typeof(UnifiedDbContext))] - [Migration("20240110051810_Initial")] + [Migration("20240125061424_Initial")] partial class Initial { /// @@ -1337,6 +1337,8 @@ namespace MyCompanyName.MyProjectName.Migrations b.HasIndex("Name"); + b.HasIndex("NormalizedName"); + b.ToTable("AbpTenants", (string)null); }); diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20240110051810_Initial.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20240125061424_Initial.cs similarity index 99% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20240110051810_Initial.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20240125061424_Initial.cs index 014376034b..469e6eac08 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20240110051810_Initial.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20240125061424_Initial.cs @@ -778,6 +778,11 @@ namespace MyCompanyName.MyProjectName.Migrations table: "AbpTenants", column: "Name"); + migrationBuilder.CreateIndex( + name: "IX_AbpTenants_NormalizedName", + table: "AbpTenants", + column: "NormalizedName"); + migrationBuilder.CreateIndex( name: "IX_AbpUserClaims_UserId", table: "AbpUserClaims", diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/UnifiedDbContextModelSnapshot.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/UnifiedDbContextModelSnapshot.cs index 7a50a01df4..b6fd7b9e97 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/UnifiedDbContextModelSnapshot.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/UnifiedDbContextModelSnapshot.cs @@ -1334,6 +1334,8 @@ namespace MyCompanyName.MyProjectName.Migrations b.HasIndex("Name"); + b.HasIndex("NormalizedName"); + b.ToTable("AbpTenants", (string)null); }); From 5f5085a48554953df5befa0ddfb59f0e45f962ef Mon Sep 17 00:00:00 2001 From: maliming Date: Thu, 25 Jan 2024 14:34:55 +0800 Subject: [PATCH 126/154] Remove `Nito.AsyncEx.Coordination` package from `Volo.Abp.Core`. --- framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj b/framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj index 042cbd270c..8804c8868f 100644 --- a/framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj +++ b/framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj @@ -31,7 +31,6 @@ - From 771e93ecfc65edd7d48a7b9809a1cf82c448b102 Mon Sep 17 00:00:00 2001 From: maliming Date: Thu, 25 Jan 2024 14:35:20 +0800 Subject: [PATCH 127/154] Update Directory.Packages.props --- Directory.Packages.props | 1 - 1 file changed, 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index b9c94c0106..f5cf8871de 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -107,7 +107,6 @@ - From bf3b665de17487a5ccb262d743aa9afcc70b53bb Mon Sep 17 00:00:00 2001 From: Salih Date: Thu, 25 Jan 2024 09:48:27 +0300 Subject: [PATCH 128/154] Update en.json --- .../AbpIoLocalization/Admin/Localization/Resources/en.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json index aa16e3931c..ee660f72e4 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json @@ -592,6 +592,8 @@ "OrganizationId": "Organization Id", "RemoveAllWinnersConfirmationMessage": "Are you sure you want to remove all winners?", "AutoRenewals": "Auto Renewals", - "OrganizationHasCreditCard": "Organization has credit card. Please remove credit card first!" + "OrganizationHasCreditCard": "Organization has credit card. Please remove credit card first!", + "DisplayName:DontSendEmailForLicenseExpire": "Don't Send Email For License Expire", + "DontSendEmailForLicenseExpire": "Don't Send Email For License Expire" } } From 46afb5e3f9f96356457ee1b7e2c1dc5aafc32cee Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Thu, 25 Jan 2024 10:30:01 +0300 Subject: [PATCH 129/154] Update EmailSettingGroupViewComponent.razor --- .../EmailSettingGroup/EmailSettingGroupViewComponent.razor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Blazor/Pages/SettingManagement/EmailSettingGroup/EmailSettingGroupViewComponent.razor b/modules/setting-management/src/Volo.Abp.SettingManagement.Blazor/Pages/SettingManagement/EmailSettingGroup/EmailSettingGroupViewComponent.razor index e80115cfde..177f1d75fa 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Blazor/Pages/SettingManagement/EmailSettingGroup/EmailSettingGroupViewComponent.razor +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Blazor/Pages/SettingManagement/EmailSettingGroup/EmailSettingGroupViewComponent.razor @@ -95,7 +95,7 @@ @if (HasSendTestEmailPermission) { - + } From 5d8d15917a94c3eb8a868f4d5dd1d1cf59dcd421 Mon Sep 17 00:00:00 2001 From: Salih Date: Thu, 25 Jan 2024 11:17:17 +0300 Subject: [PATCH 130/154] Update en.json --- .../AbpIoLocalization/Commercial/Localization/Resources/en.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json index e5d8c15ac2..dcf3423484 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json @@ -1129,7 +1129,7 @@ "NameOnCard": "Name on Card", "BillingDetails": "Billing Details", "ThereIsNoDeveloper": "There is no developer.", - "CardDetails": "Card Details", + "CardDetails": "Debit/Credit Card Details", "NoActiveLicence": "You are not eligible for this action! You have no active license." } } From aa832dbfaadc218dc98ea6f997060c22a9f9b1e0 Mon Sep 17 00:00:00 2001 From: Engincan VESKE Date: Thu, 25 Jan 2024 13:39:30 +0300 Subject: [PATCH 131/154] Update Post.md --- .../2024-01-04-CLI-Online-Translate/Post.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/en/Community-Articles/2024-01-04-CLI-Online-Translate/Post.md b/docs/en/Community-Articles/2024-01-04-CLI-Online-Translate/Post.md index abddfd43fd..285d7d5dc9 100644 --- a/docs/en/Community-Articles/2024-01-04-CLI-Online-Translate/Post.md +++ b/docs/en/Community-Articles/2024-01-04-CLI-Online-Translate/Post.md @@ -1,12 +1,12 @@ # Use Deepl to translate localization files -Translating localized text during the development ABP modules is a boring work. For this reason we have added the `translate` command to the CLI tool to translate the localization files, but it still requires manual translate texts by the developer. +Translating localized text during the development of ABP modules is a boring job. For this reason, we have added the `translate` command to the CLI tool to translate the localization files, but it still requires manual translation of texts by the developer. -Now, We introduce a new way to translate the target language, which is to use the [Deepl](https://www.deepl.com/translator) translation service to translate the target language. +Now, we introduce a new way to translate the target language, which is to use the [Deepl](https://www.deepl.com/translator) translation service to translate the target language. -You can use the `translate --online` command to in your module directory to translate the target language. +You can use the `translate --online` command in your module directory to translate the target language. -For example, You have added all `en` localization texts to your module, and you want to translate them to `zh-Hans`, you can run the following command: +For example, if you have added all `en` localization texts to your module, and you want to translate them to `zh-Hans`, you can run the following command: ``` abp translate -r en -c zh-Hans --online --deepl-auth-key your_auth_key From 2282441869e7b821dce4684f377ee1822eedac22 Mon Sep 17 00:00:00 2001 From: Salih Date: Thu, 25 Jan 2024 15:42:50 +0300 Subject: [PATCH 132/154] Fix: Selects on docs shrinks to unusable sizes on mobile --- .../Pages/Documents/Project/Index.cshtml | 55 ++++++++++++------- 1 file changed, 36 insertions(+), 19 deletions(-) diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml index 85d402c11d..d285ae5338 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml @@ -332,28 +332,45 @@ - @foreach (var parameter in Model.DocumentPreferences.Parameters) - { -
-
- @(parameter.DisplayName) - + @foreach (var value in parameter.Values.OrderBy(p => p.Value)) { - + @if (value.Key == (Model.UserPreferences.ContainsKey(parameter.Name) ? Model.UserPreferences[parameter.Name] : null)) + { + + } + else + { + + } } - } - + +
-
+ } }
From 6784765b793ffef95b808c8abc5e3243481f97e3 Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Thu, 25 Jan 2024 15:47:25 +0300 Subject: [PATCH 133/154] Update FeatureManagementModal.cshtml --- .../Pages/FeatureManagement/FeatureManagementModal.cshtml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Pages/FeatureManagement/FeatureManagementModal.cshtml b/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Pages/FeatureManagement/FeatureManagementModal.cshtml index ca38284046..a3a00a89c1 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Pages/FeatureManagement/FeatureManagementModal.cshtml +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Pages/FeatureManagement/FeatureManagementModal.cshtml @@ -123,8 +123,8 @@ - @L["ResetToDefault"] - @L["Cancel"] + @L["Cancel"] + @L["ResetToDefault"] @L["Save"] } From 66cf8377cfe50b86d0789fa1f9cf3f729ee7cc9d Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Thu, 25 Jan 2024 15:50:43 +0300 Subject: [PATCH 134/154] Update Create.cshtml --- .../Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/Create.cshtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/Create.cshtml b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/Create.cshtml index 190df58ecb..5c855e9ffe 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/Create.cshtml +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/Create.cshtml @@ -132,7 +132,7 @@ - + @if ((await AuthorizationService.AuthorizeAsync(CmsKitAdminPermissions.BlogPosts.Publish)).Succeeded) { From 893b038efc72edb3fb0b7ae351d3180bb0c311da Mon Sep 17 00:00:00 2001 From: Salih Date: Thu, 25 Jan 2024 15:57:53 +0300 Subject: [PATCH 135/154] Update Index.cshtml --- .../src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml index d285ae5338..83f4c7a775 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml @@ -337,12 +337,13 @@ var count = Model.DocumentPreferences.Parameters.Count; var rowCount = count / maxCellCount + (count % maxCellCount > 0 ? 1 : 0); var cellSize = 12 / (count > maxCellCount ? maxCellCount : count); + var latestCellSize = 12 / count - (rowCount - 1) * maxCellCount; string BuildParameterDivClass(int index) { var row = index / maxCellCount; var isLastRow = row == rowCount - 1; - var currentCellSize = isLastRow ? 12 / (count % maxCellCount) : cellSize; + var currentCellSize = isLastRow ? latestCellSize : cellSize; return $"col-12 col-lg-{currentCellSize} mb-lg-{(isLastRow ? "0" : "2")} {(index == count - 1 ? "" : "mb-2")}"; } From 50e952bd6263b1bd95de377be4a3c291b6e20dce Mon Sep 17 00:00:00 2001 From: Salih Date: Thu, 25 Jan 2024 16:19:12 +0300 Subject: [PATCH 136/154] Add new localizations --- .../AbpIoLocalization/Www/Localization/Resources/en.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json index d1bc23b308..ec2d301a29 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json @@ -353,6 +353,8 @@ "BuildSolutionsWithAbp": "Build maintainable .NET solutions by following software development best practices using ABP.", "BuyOnAmazon": "Buy on Amazon", "BuyOnPackt": "Buy on Packt", + "BuyOnDangDang": "Buy on DangDang", + "BuyOnJD": "Buy on JD", "Discounted": "Discounted", "MasteringAbpFramework_Book_KeyFeatures": "Key Features", "MasteringAbpFramework_Book_Key_Features_Description_1": "Build robust, maintainable, modular, and scalable software solutions using ABP Framework.", From 0fe8b8ab6f29561319979723ca60b2e574bacec5 Mon Sep 17 00:00:00 2001 From: Salih Date: Thu, 25 Jan 2024 16:42:24 +0300 Subject: [PATCH 137/154] Update zh-Hant.json --- .../AbpIoLocalization/Www/Localization/Resources/zh-Hant.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hant.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hant.json index 81664b5f8d..dc396ce8b9 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hant.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hant.json @@ -353,6 +353,8 @@ "BuildSolutionsWithAbp": "使用 ABP 遵循軟體開發最佳實務來建立可維護的 .NET 解決方案。", "BuyOnAmazon": "在亞馬遜上購買", "BuyOnPackt": "在 Packt 上購買", + "BuyOnDangDang": "在當當上購買", + "BuyOnJD": "在京東上購買", "Discounted": "折扣", "MasteringAbpFramework_Book_KeyFeatures": "主要特徵", "MasteringAbpFramework_Book_Key_Features_Description_1": "使用 ABP 框架建構健壯、可維護、模組化和可擴展的軟體解決方案。", From 8f6f075944a6f177c1632683ecbe18c49e65cb50 Mon Sep 17 00:00:00 2001 From: Salih Date: Thu, 25 Jan 2024 16:42:26 +0300 Subject: [PATCH 138/154] Update zh-Hans.json --- .../AbpIoLocalization/Www/Localization/Resources/zh-Hans.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hans.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hans.json index 9fb6a08b32..88d56a6303 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hans.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hans.json @@ -353,6 +353,8 @@ "BuildSolutionsWithAbp": "使用 ABP,遵循软件开发最佳实践,构建可维护的 .NET 解决方案。", "BuyOnAmazon": "在亚马逊上购买", "BuyOnPackt": "在 Packt 购买", + "BuyOnDangDang": "在当当网购买", + "BuyOnJD": "在京东上购买", "Discounted": "折扣", "MasteringAbpFramework_Book_KeyFeatures": "主要功能", "MasteringAbpFramework_Book_Key_Features_Description_1": "使用 ABP 框架构建稳健、可维护、模块化和可扩展的软件解决方案。", From 446de0b438eff6b465b678369824b24208f37b83 Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Thu, 25 Jan 2024 16:49:39 +0300 Subject: [PATCH 139/154] Reorder buttons in email setting group component --- .../Components/EmailSettingGroup/Default.cshtml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Components/EmailSettingGroup/Default.cshtml b/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Components/EmailSettingGroup/Default.cshtml index 61d4dbe996..ee8db3e38f 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Components/EmailSettingGroup/Default.cshtml +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Components/EmailSettingGroup/Default.cshtml @@ -26,15 +26,15 @@
- - @L["Save"] - @if (await PermissionChecker.IsGrantedAsync(SettingManagementPermissions.EmailingTest)) { @L["SendTestEmail"] } + + @L["Save"] +
From 707b99f35a0d905b5d77037d8fea9f8fe1e9a7f5 Mon Sep 17 00:00:00 2001 From: Enis Necipoglu Date: Thu, 25 Jan 2024 16:52:02 +0300 Subject: [PATCH 140/154] Refactor email setting group view component --- .../EmailSettingGroup/EmailSettingGroupViewComponent.razor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Blazor/Pages/SettingManagement/EmailSettingGroup/EmailSettingGroupViewComponent.razor b/modules/setting-management/src/Volo.Abp.SettingManagement.Blazor/Pages/SettingManagement/EmailSettingGroup/EmailSettingGroupViewComponent.razor index 177f1d75fa..19f95ca52a 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Blazor/Pages/SettingManagement/EmailSettingGroup/EmailSettingGroupViewComponent.razor +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Blazor/Pages/SettingManagement/EmailSettingGroup/EmailSettingGroupViewComponent.razor @@ -92,11 +92,11 @@ - @if (HasSendTestEmailPermission) { } + From d3058a9a3ecd2d22717dfcb257416b9b76e7ac04 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Fri, 26 Jan 2024 10:01:29 +0800 Subject: [PATCH 141/154] Throw exception if provder was not found --- .../Volo/Abp/FeatureManagement/FeatureManager.cs | 2 +- .../Abp/FeatureManagement/FeatureManager_Tests.cs | 11 +++++++++++ .../PermissionManager_Tests.cs | 15 +++++++++++++++ .../Volo/Abp/SettingManagement/SettingManager.cs | 2 +- .../SettingManager_Basic_Tests.cs | 7 ++++--- 5 files changed, 32 insertions(+), 5 deletions(-) diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureManager.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureManager.cs index 1a5356a1be..9805f03752 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureManager.cs +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureManager.cs @@ -144,7 +144,7 @@ public class FeatureManager : IFeatureManager, ISingletonDependency if (!providers.Any()) { - return; + throw new AbpException($"Unknown feature value provider: {providerName}"); } if (providers.Count > 1 && !forceToSet && value != null) diff --git a/modules/feature-management/test/Volo.Abp.FeatureManagement.Domain.Tests/Volo/Abp/FeatureManagement/FeatureManager_Tests.cs b/modules/feature-management/test/Volo.Abp.FeatureManagement.Domain.Tests/Volo/Abp/FeatureManagement/FeatureManager_Tests.cs index 831d021e38..fd4ea324ea 100644 --- a/modules/feature-management/test/Volo.Abp.FeatureManagement.Domain.Tests/Volo/Abp/FeatureManagement/FeatureManager_Tests.cs +++ b/modules/feature-management/test/Volo.Abp.FeatureManagement.Domain.Tests/Volo/Abp/FeatureManagement/FeatureManager_Tests.cs @@ -209,4 +209,15 @@ public class FeatureManager_Tests : FeatureManagementDomainTestBase (await _featureManager.GetOrNullAsync(TestFeatureDefinitionProvider.BackupCount, TenantFeatureValueProvider.ProviderName, TestEditionIds.TenantId.ToString())).ShouldBe("0"); } + + [Fact] + public async Task Set_Should_Throw_Exception_If_Provider_Not_Found() + { + var exception = await Assert.ThrowsAsync(async () => + { + await _featureManager.SetAsync(TestFeatureDefinitionProvider.EmailSupport, "true", "UndefinedProvider", "Test"); + }); + + exception.Message.ShouldBe("Unknown feature value provider: UndefinedProvider"); + } } diff --git a/modules/permission-management/test/Volo.Abp.PermissionManagement.Domain.Tests/Volo/Abp/PermissionManagement/PermissionManager_Tests.cs b/modules/permission-management/test/Volo.Abp.PermissionManagement.Domain.Tests/Volo/Abp/PermissionManagement/PermissionManager_Tests.cs index 1f771bdb3b..3f2e9c7565 100644 --- a/modules/permission-management/test/Volo.Abp.PermissionManagement.Domain.Tests/Volo/Abp/PermissionManagement/PermissionManager_Tests.cs +++ b/modules/permission-management/test/Volo.Abp.PermissionManagement.Domain.Tests/Volo/Abp/PermissionManagement/PermissionManager_Tests.cs @@ -134,6 +134,21 @@ public class PermissionManager_Tests : PermissionTestBase "Test", true); } + + [Fact] + public async Task Set_Should_Throw_Exception_If_Provider_Not_Found() + { + var exception = await Assert.ThrowsAsync(async () => + { + await _permissionManager.SetAsync( + "MyPermission1", + "UndefinedProvider", + "Test", + true); + }); + + exception.Message.ShouldBe("Unknown permission management provider: UndefinedProvider"); + } [Fact] public async Task UpdateProviderKey() diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/SettingManager.cs b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/SettingManager.cs index 68d66ee4b0..ddf451154d 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/SettingManager.cs +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/SettingManager.cs @@ -125,7 +125,7 @@ public class SettingManager : ISettingManager, ISingletonDependency if (!providers.Any()) { - throw new AbpException($"Could not find a setting provider named '{providerName}'."); + throw new AbpException($"Unknown setting value provider: {providerName}"); } if (setting.IsEncrypted) diff --git a/modules/setting-management/test/Volo.Abp.SettingManagement.Tests/Volo/Abp/SettingManagement/SettingManager_Basic_Tests.cs b/modules/setting-management/test/Volo.Abp.SettingManagement.Tests/Volo/Abp/SettingManagement/SettingManager_Basic_Tests.cs index 00dc337c0f..ca9db64c70 100644 --- a/modules/setting-management/test/Volo.Abp.SettingManagement.Tests/Volo/Abp/SettingManagement/SettingManager_Basic_Tests.cs +++ b/modules/setting-management/test/Volo.Abp.SettingManagement.Tests/Volo/Abp/SettingManagement/SettingManager_Basic_Tests.cs @@ -1,3 +1,4 @@ +using System; using System.Threading.Tasks; using Shouldly; using Volo.Abp.Settings; @@ -65,13 +66,13 @@ public class SettingManager_Basic_Tests : SettingsTestBase } [Fact] - public async Task Should_Throw_Exception_If_Provider_Not_Found() + public async Task Set_Should_Throw_Exception_If_Provider_Not_Found() { var exception = await Assert.ThrowsAsync(async () => { - await _settingManager.SetAsync("MySetting1", "43", "UndefinedProvider", "UndefinedProviderKey"); + await _settingManager.SetAsync("MySetting1", "43", "UndefinedProvider", "Test"); }); - exception.Message.ShouldBe("Could not find a setting provider named 'UndefinedProvider'."); + exception.Message.ShouldBe("Unknown setting value provider: UndefinedProvider"); } } \ No newline at end of file From 88e6fc7aa81b615c5c6d68194ca3024b4a518745 Mon Sep 17 00:00:00 2001 From: denizdemirkan Date: Fri, 26 Jan 2024 13:21:03 +0300 Subject: [PATCH 142/154] Preview word added --- .../AbpIoLocalization/Community/Localization/Resources/ar.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/cs.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/de.json | 3 ++- .../Community/Localization/Resources/en-GB.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/en.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/es.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/fi.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/fr.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/hi.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/hr.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/hu.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/is.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/it.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/nl.json | 3 ++- .../Community/Localization/Resources/pl-PL.json | 3 ++- .../Community/Localization/Resources/pt-BR.json | 3 ++- .../Community/Localization/Resources/ro-RO.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/ru.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/sk.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/sl.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/tr.json | 3 ++- .../AbpIoLocalization/Community/Localization/Resources/vi.json | 3 ++- .../Community/Localization/Resources/zh-Hans.json | 3 ++- .../Community/Localization/Resources/zh-Hant.json | 3 ++- 24 files changed, 48 insertions(+), 24 deletions(-) diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ar.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ar.json index df39dea75d..7151345ea9 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ar.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ar.json @@ -256,6 +256,7 @@ "RaffleHeader": "مرحبًا عضو مجتمع برنامج الجسر الأكاديمي!", "RafflesInfo": "
هذه هي صفحة السحب المخصصة لإظهار تقديرنا لك لكونك عضوًا نشطًا في المجتمع. نحن نقوم بإجراء محادثات مجتمعية لبرنامج ABP ، ومؤتمر ABP .NET ، ونحضر أو نرعى الأحداث المتعلقة بـ .NET والتي نقدم فيها بعض الهدايا.

يمكنك متابعة هذه الصفحة لرؤية السحوبات القادمة أو حضورها أو الاطلاع على السحوبات السابقة التي قمنا بسحبها بما في ذلك الفائزين.

شكرا لكونك عضوا نشطا! نراكم في السحوبات القادمة.", "RafflesInfoTitle": "سحوبات مجتمع ABP", - "MarkdownSupported": "Markdown أيد." + "MarkdownSupported": "Markdown أيد.", + "Preview": "معاينة" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/cs.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/cs.json index 4c6a229861..252b0dcb2b 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/cs.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/cs.json @@ -256,6 +256,7 @@ "RaffleHeader": "Dobrý den, člen komunity ABP!", "RafflesInfo": "
Toto je stránka s losováním věnovaná tomu, abychom vám ukázali naše uznání za to, že jste aktivním členem komunity. Pořádáme ABP Community Talks , ABP .NET Conference , účastníme se nebo sponzorujeme akce související s .NET, ve kterých rozdáváme nějaké dárky.

Na této stránce můžete sledovat nadcházející tomboly, zúčastnit se jich nebo si prohlédnout předchozí tomboly, které losujeme, včetně výherců.

Děkujeme, že jste aktivním členem! Uvidíme se v nadcházejícím slosování.", "RafflesInfoTitle": "Komunitní tomboly ABP", - "MarkdownSupported": "Markdown podporováno." + "MarkdownSupported": "Markdown podporováno.", + "Preview": "Náhled" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/de.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/de.json index 146985eb49..4326ff88ef 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/de.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/de.json @@ -256,6 +256,7 @@ "RaffleHeader": "Hallo ABP-Community-Mitglied!", "RafflesInfo": "
Auf dieser Verlosungsseite möchten wir Ihnen unsere Wertschätzung dafür zeigen, dass Sie ein aktives Community-Mitglied sind. Wir veranstalten ABP Community Talks und ABP .NET Conferences , nehmen an .NET-bezogenen Veranstaltungen teil oder sponsern diese, bei denen wir einige Geschenke verschenken.

Sie können dieser Seite folgen, um die bevorstehenden Verlosungen zu sehen, daran teilzunehmen oder frühere Verlosungen, die wir verlosen, einschließlich der Gewinner, anzusehen.

Vielen Dank, dass Sie ein aktives Mitglied sind! Wir sehen uns bei den kommenden Gewinnspielen.", "RafflesInfoTitle": "ABP-Community- Verlosungen", - "MarkdownSupported": "Markdown unterstützt." + "MarkdownSupported": "Markdown unterstützt.", + "Preview": "Vorschau" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en-GB.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en-GB.json index fc21345c05..347b18ce4b 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en-GB.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en-GB.json @@ -104,6 +104,7 @@ "CreatePostLanguageInfo": "Language of the post", "SeeMore": "See More", "MemberNotPublishedPostYet": "This member hasn't published any posts yet.", - "MarkdownSupported": "Markdown supported." + "MarkdownSupported": "Markdown supported.", + "Preview": "Preview" } } diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json index 4bcd1bd525..b22fc19de8 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json @@ -257,6 +257,7 @@ "RafflesInfo": "
This is the raffle page dedicated to show our appreciation towards you for being an active Community Member. We do ABP Community Talks ,ABP .NET Conference, attend or sponsor to the .NET-related events in which we give away some gifts.

You can follow this page to see the upcoming raffles, attend them, or see previous raffles we draw including the winners.

Thank you for being an active member! See you in the upcoming raffles.", "RafflesInfoTitle": "ABP Community Raffles", "ToLuckyWinner": "to 1 lucky winner", - "MarkdownSupported": "Markdown supported." + "MarkdownSupported": "Markdown supported.", + "Preview": "Preview" } } diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/es.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/es.json index f24cb1d511..c53b45ab81 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/es.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/es.json @@ -256,6 +256,7 @@ "RaffleHeader": "¡Hola miembro de la comunidad ABP!", "RafflesInfo": "
Esta es la página del sorteo dedicada a mostrarle nuestro agradecimiento por ser un miembro activo de la comunidad. Realizamos charlas comunitarias de ABP , conferencias ABP .NET , asistimos o patrocinamos eventos relacionados con .NET en los que regalamos algunos obsequios.

Puedes seguir esta página para ver los próximos sorteos, asistir a ellos o ver sorteos anteriores que sorteamos incluyendo a los ganadores.

¡Gracias por ser un miembro activo! Nos vemos en los próximos sorteos.", "RafflesInfoTitle": "Rifas de la Comunidad ABP", - "MarkdownSupported": "Markdown soportado." + "MarkdownSupported": "Markdown soportado.", + "Preview": "Avance" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fi.json index a42a7d693f..abd8cdd21f 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fi.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fi.json @@ -256,6 +256,7 @@ "RaffleHeader": "Hei ABP-yhteisön jäsen!", "RafflesInfo": "
Tämä on arvontasivu, joka on omistettu osoittamaan kiitollisuuttamme sinua kohtaan, että olet aktiivinen yhteisön jäsen. Teemme ABP Community Talksia , ABP .NET -konferenssia , osallistumme tai sponsoroimme .NET-tapahtumia, joissa annamme lahjoja.

Voit seurata tätä sivua nähdäksesi tulevat arvonnat, osallistua niihin tai nähdäksesi aiemmat arvonnamme, mukaan lukien voittajat.

Kiitos aktiivisesta jäsenyydestäsi! Nähdään tulevissa arvonnassa.", "RafflesInfoTitle": "ABP-yhteisön arpajaiset", - "MarkdownSupported": "Markdown tuettu." + "MarkdownSupported": "Markdown tuettu.", + "Preview": "Esikatselu" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fr.json index 2ed85aaa95..1f259aac6d 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fr.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fr.json @@ -256,6 +256,7 @@ "RaffleHeader": "Bonjour membre de la communauté ABP !", "RafflesInfo": "
Ceci est la page de tirage au sort dédiée à vous montrer notre gratitude pour votre participation active à la communauté. Nous organisons des discussions communautaires ABP , des conférences ABP .NET , assistons ou sponsorisons des événements liés à .NET au cours desquels nous offrons des cadeaux.

Vous pouvez suivre cette page pour voir les tirages au sort à venir, y assister ou voir les tirages au sort précédents que nous tirons, y compris les gagnants.

Merci d'être un membre actif ! Rendez-vous lors des prochains tirages au sort.", "RafflesInfoTitle": "Tirages au sort communautaires ABP", - "MarkdownSupported": "Markdown prise en charge." + "MarkdownSupported": "Markdown prise en charge.", + "Preview": "Aperçu" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hi.json index 6a969b99f3..b868260ae6 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hi.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hi.json @@ -256,6 +256,7 @@ "RaffleHeader": "नमस्ते एबीपी समुदाय सदस्य!", "RafflesInfo": "
यह रैफ़ल पेज है जो एक सक्रिय समुदाय सदस्य होने के लिए आपके प्रति हमारी सराहना दिखाने के लिए समर्पित है। हम एबीपी सामुदायिक वार्ता , एबीपी .NET सम्मेलन करते हैं, .NET से संबंधित कार्यक्रमों में भाग लेते हैं या प्रायोजित करते हैं जिसमें हम कुछ उपहार देते हैं।

आप आगामी रैफ़ल देखने, उनमें भाग लेने, या विजेताओं सहित हमारे द्वारा निकाले गए पिछले रैफ़ल देखने के लिए इस पृष्ठ का अनुसरण कर सकते हैं।

सक्रिय सदस्य बनने के लिए धन्यवाद! आगामी रैफ़ल में मिलते हैं।", "RafflesInfoTitle": "एबीपी कम्युनिटी रैफल्स", - "MarkdownSupported": "Markdown का समर्थन किया।" + "MarkdownSupported": "Markdown का समर्थन किया।", + "Preview": "पूर्व दर्शन" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hr.json index 4e213a9c66..eb3b66d9c8 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hr.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hr.json @@ -256,6 +256,7 @@ "RaffleHeader": "Pozdrav članu ABP zajednice!", "RafflesInfo": "
Ovo je stranica za nagradnu igru namijenjena da vam pokažemo našu zahvalnost što ste aktivni član zajednice. Vodimo razgovore o ABP zajednici , ABP .NET konferenciji , prisustvujemo ili sponzoriramo događaje vezane uz .NET na kojima dijelimo neke darove.

Možete pratiti ovu stranicu kako biste vidjeli nadolazeće nagradne igre, prisustvovali im ili vidjeli prethodne nagradne igre koje izvlačimo uključujući dobitnike.

Hvala vam što ste aktivan član! Vidimo se u nadolazećim nagradnim igrama.", "RafflesInfoTitle": "Izvlačenje nagradne igre zajednice ABP", - "MarkdownSupported": "Markdown podržan." + "MarkdownSupported": "Markdown podržan.", + "Preview": "Pregled" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hu.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hu.json index f489cdc571..08917573ff 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hu.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hu.json @@ -256,6 +256,7 @@ "RaffleHeader": "Kedves ABP közösségi tag!", "RafflesInfo": "
Ez az a sorsolási oldal, amelynek célja, hogy kifejezzük hálánkat feléd, amiért aktív közösségi tag vagy. Az ABP Community Talks-okat , az ABP .NET konferenciákat szervezzük, részt veszünk vagy szponzorálunk olyan .NET-hez kapcsolódó eseményeket, amelyeken ajándékokat adunk.

Ezt az oldalt követheti, hogy megtekinthesse a közelgő sorsolásokat, részt vegyen azokon, vagy megtekinthesse korábbi sorsolásainkat, beleértve a nyerteseket is.

Köszönjük, hogy aktív tag vagy! Találkozunk a sorsoláson.", "RafflesInfoTitle": "ABP közösségi tombola", - "MarkdownSupported": "Markdown támogatott." + "MarkdownSupported": "Markdown támogatott.", + "Preview": "Előnézet" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/is.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/is.json index 32284f5f37..0d8eb6cb48 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/is.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/is.json @@ -256,6 +256,7 @@ "RaffleHeader": "Halló ABP samfélagsmeðlimur!", "RafflesInfo": "
Þetta er happdrættisíðan sem er tileinkuð þér að þakka þér fyrir að vera virkur samfélagsmeðlimur. Við gerum ABP Community Talks , ABP .NET ráðstefnu , sækjum eða styrkjum .NET tengda viðburði þar sem við gefum nokkrar gjafir.

Þú getur fylgst með þessari síðu til að sjá komandi happdrætti, mæta á þær eða sjá fyrri happdrætti sem við drögum út, þar á meðal vinningshafa.

Þakka þér fyrir að vera virkur meðlimur! Sjáumst í komandi happdrætti.", "RafflesInfoTitle": "ABP samfélagshappdrætti", - "MarkdownSupported": "Markdown stutt." + "MarkdownSupported": "Markdown stutt.", + "Preview": "Forskoðun" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/it.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/it.json index 301c1e84e7..a301a7f482 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/it.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/it.json @@ -256,6 +256,7 @@ "RaffleHeader": "Ciao membro della comunità ABP!", "RafflesInfo": "
Questa è la pagina della lotteria dedicata a mostrare il nostro apprezzamento nei tuoi confronti per essere un membro attivo della comunità. Organizziamo ABP Community Talks , ABP .NET Conference , partecipiamo o sponsorizziamo eventi relativi a .NET in cui regaliamo alcuni regali.

Puoi seguire questa pagina per vedere le prossime lotterie, parteciparvi o vedere le lotterie precedenti che estraiamo, compresi i vincitori.

Grazie per essere un membro attivo! Ci vediamo alle prossime lotterie.", "RafflesInfoTitle": "Lotterie comunitarie ABP", - "MarkdownSupported": "Markdown supportato." + "MarkdownSupported": "Markdown supportato.", + "Preview": "Anteprima" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/nl.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/nl.json index 8beba46650..45b3024c96 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/nl.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/nl.json @@ -256,6 +256,7 @@ "RaffleHeader": "Hallo ABP Community-lid!", "RafflesInfo": "
Dit is de loterijpagina die bedoeld is om onze waardering voor u te tonen omdat u een actief lid van de community bent. We houden ABP Community Talks , ABP .NET Conference , wonen of sponsoren de .NET-gerelateerde evenementen bij waarin we een aantal geschenken weggeven.

U kunt deze pagina volgen om de komende loterijen te zien, deze bij te wonen of eerdere loterijen te zien die we trekken, inclusief de winnaars.

Bedankt dat u een actief lid bent! Tot ziens bij de komende loterijen.", "RafflesInfoTitle": "ABP- gemeenschaploterijen", - "MarkdownSupported": "Markdown ondersteund." + "MarkdownSupported": "Markdown ondersteund.", + "Preview": "Voorbeeld" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/pl-PL.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/pl-PL.json index e47be75ccc..124f910ac0 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/pl-PL.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/pl-PL.json @@ -256,6 +256,7 @@ "RaffleHeader": "Witaj, członku społeczności ABP!", "RafflesInfo": "
To jest strona loterii, której celem jest wyrażenie naszego uznania dla Ciebie za bycie aktywnym członkiem społeczności. Prowadzimy rozmowy społecznościowe ABP , konferencje ABP .NET , uczestniczymy lub sponsorujemy wydarzenia związane z .NET, podczas których rozdajemy prezenty.

Możesz śledzić tę stronę, aby zobaczyć nadchodzące loterie, wziąć w nich udział lub zobaczyć poprzednie loterie, które losowaliśmy, w tym zwycięzców.

Dziękujemy za bycie aktywnym członkiem! Do zobaczenia w nadchodzących loteriach.", "RafflesInfoTitle": "Loterie społecznościowe ABP", - "MarkdownSupported": "Markdown utrzymany." + "MarkdownSupported": "Markdown utrzymany.", + "Preview": "Zapowiedź" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/pt-BR.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/pt-BR.json index d987c03211..419ef77140 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/pt-BR.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/pt-BR.json @@ -256,6 +256,7 @@ "RaffleHeader": "Olá, membro da comunidade ABP!", "RafflesInfo": "
Esta é a página do sorteio dedicada a mostrar nosso agradecimento por você ser um membro ativo da comunidade. Fazemos ABP Community Talks , ABP .NET Conference , participamos ou patrocinamos eventos relacionados ao .NET nos quais distribuímos alguns presentes.

Você pode seguir esta página para ver os próximos sorteios, participar deles ou ver os sorteios anteriores que sorteamos, incluindo os vencedores.

Obrigado por ser um membro ativo! Nos vemos nos próximos sorteios.", "RafflesInfoTitle": "Sorteios da Comunidade ABP", - "MarkdownSupported": "Markdown suportado." + "MarkdownSupported": "Markdown suportado.", + "Preview": "Visualização" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ro-RO.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ro-RO.json index 06ecc4dea8..47e513f125 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ro-RO.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ro-RO.json @@ -256,6 +256,7 @@ "RaffleHeader": "Bună ziua, membru al comunității ABP!", "RafflesInfo": "
Aceasta este pagina de tombolă dedicată pentru a arăta aprecierea noastră față de dvs. pentru că sunteți un membru activ al comunității. Facem ABP Community Talks , ABP .NET Conference , participăm sau sponsorizăm evenimentele legate de .NET în care oferim câteva cadouri.

Puteți urmări această pagină pentru a vedea tombolele viitoare, a participa la ele sau pentru a vedea tombolele anterioare pe care le extragem, inclusiv câștigătorii.

Vă mulțumim că sunteți un membru activ! Ne vedem la tombolele viitoare.", "RafflesInfoTitle": "Tombole comunitare ABP", - "MarkdownSupported": "Markdown sprijinit." + "MarkdownSupported": "Markdown sprijinit.", + "Preview": "previzualizare" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ru.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ru.json index 07d6a87fe9..b91893ce94 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ru.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ru.json @@ -259,6 +259,7 @@ "RaffleHeader": "Привет, участник сообщества ABP!", "RafflesInfo": "
Эта страница розыгрыша посвящена тому, чтобы выразить нашу признательность вам за то, что вы являетесь активным членом сообщества. Обсуждения сообщества ABP ,Конференция ABP .NET, посещать или спонсировать мероприятия, связанные с .NET, на которых мы раздаем подарки.

Вы можете подписаться на эту страницу, чтобы увидеть предстоящие розыгрыши, посетить их или просмотреть предыдущие розыгрыши, которые мы проводим, включая победителей.

Спасибо за активное участие! ", "RafflesInfoTitle": "Сообщество АБП Розыгрыши", - "MarkdownSupported": "Markdown поддерживается." + "MarkdownSupported": "Markdown поддерживается.", + "Preview": "Предварительный просмотр" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sk.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sk.json index fa9826b421..25a73a6bd7 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sk.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sk.json @@ -256,6 +256,7 @@ "RaffleHeader": "Dobrý deň, člen komunity ABP!", "RafflesInfo": "
Toto je stránka žrebovania venovaná na vyjadrenie nášho uznania vám za to, že ste aktívnym členom komunity. Robíme ABP Community Talks , ABP .NET konferenciu , zúčastňujeme sa alebo sponzorujeme podujatia súvisiace s .NET, na ktorých rozdávame nejaké darčeky.

Na tejto stránke si môžete pozrieť pripravované tomboly, zúčastniť sa ich alebo si pozrieť predchádzajúce žrebovanie, ktoré vyžrebujeme vrátane výhercov.

Ďakujeme, že ste aktívnym členom! Vidíme sa v najbližšom žrebovaní.", "RafflesInfoTitle": "Komunitné tomboly ABP", - "MarkdownSupported": "Markdown podporované." + "MarkdownSupported": "Markdown podporované.", + "Preview": "Náhľad" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sl.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sl.json index 81e103cd17..b6192142c6 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sl.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sl.json @@ -256,6 +256,7 @@ "RaffleHeader": "Pozdravljeni član skupnosti ABP!", "RafflesInfo": "
To je stran za nagradno igro, namenjena izkazovanju naše hvaležnosti do vas, ker ste aktivni član skupnosti. Izvajamo ABP Community Talks , ABP .NET Conference , se udeležujemo ali sponzoriramo dogodke, povezane z .NET, na katerih podarimo nekaj daril.

To stran lahko spremljate in si ogledate prihajajoče nagradne igre, se jih udeležite ali si ogledate prejšnje nagradne igre, ki smo jih izžrebali, vključno z zmagovalci.

Hvala, ker ste aktivni član! Se vidimo na prihajajočih nagradnih igrah.", "RafflesInfoTitle": "Žrebanje skupnosti ABP", - "MarkdownSupported": "Markdown podprt." + "MarkdownSupported": "Markdown podprt.", + "Preview": "Predogled" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/tr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/tr.json index d184bb63d1..88c88208e8 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/tr.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/tr.json @@ -190,6 +190,7 @@ "Index_Page_CommunityIntroduction": "Burası ABP Çerçevesi, .NET ve yazılım geliştirme için bir merkezdir. Makaleleri okuyabilir, eğitim videolarını izleyebilir, ABP'nin gelişim süreci ve ABP ile ilgili etkinlikler hakkında bilgi alabilir, diğer geliştiricilere yardımcı olabilir ve uzmanlığınızı ABP topluluğu ile paylaşabilirsiniz.", "IConsentToMedium": "Bu yazının https://medium.com/volosoft adresinde yayınlanmasına izin veriyorum.", "DiscordPageTitle": "ABP Discord Topluluğu", - "MarkdownSupported": "Markdown destekleniyor." + "MarkdownSupported": "Markdown destekleniyor.", + "Preview": "Ön izleme" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/vi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/vi.json index d7febbb014..e195a80fa5 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/vi.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/vi.json @@ -256,6 +256,7 @@ "RaffleHeader": "Xin chào Thành viên Cộng đồng ABP!", "RafflesInfo": "
Đây là trang xổ số dành riêng để thể hiện sự đánh giá cao của chúng tôi đối với bạn vì đã trở thành Thành viên cộng đồng tích cực. Chúng tôi tổ chức các buổi nói chuyện cộng đồng ABP , Hội nghị ABP .NET , tham dự hoặc tài trợ cho các sự kiện liên quan đến .NET mà trong đó chúng tôi tặng một số quà tặng.

Bạn có thể theo dõi trang này để xem các cuộc xổ số sắp tới, tham dự hoặc xem các cuộc xổ số trước đây mà chúng tôi rút ra bao gồm cả những người chiến thắng.

Cảm ơn bạn đã là thành viên tích cực! Hẹn gặp lại các bạn trong đợt xổ số sắp tới.", "RafflesInfoTitle": "Xổ số cộng đồng ABP", - "MarkdownSupported": "Markdown được hỗ trợ." + "MarkdownSupported": "Markdown được hỗ trợ.", + "Preview": "Xem trước" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hans.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hans.json index c0aaf2678b..fd1130b894 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hans.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hans.json @@ -256,6 +256,7 @@ "RaffleHeader": "你好,ABP 社区成员!", "RafflesInfo": "
这是一个抽奖页面,旨在感谢您成为活跃的社区成员。我们举办 ABP 社区讲座 、ABP .NET 会议,参加或赞助与 .NET 相关的活动,并在活动中赠送一些礼品。

您可以关注此页面,查看即将举行的抽奖活动、参加这些活动或查看我们以前举行的抽奖活动(包括获奖者)。

感谢您成为我们的活跃成员!在即将举行的抽奖活动中再见。", "RafflesInfoTitle": "ABP 社区来抽奖Markdown 支持的。" + "MarkdownSupported": "Markdown 支持的。", + "Preview": "预览" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hant.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hant.json index 7f8e58f7df..e5725ce996 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hant.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hant.json @@ -256,6 +256,7 @@ "RaffleHeader": "ABP 社群成員您好!", "RafflesInfo": "
這是抽獎頁面,旨在表達我們對您作為活躍社區成員的感謝。我們舉辦ABP 社群講座、ABP .NET 會議、參加或贊助 .NET 相關活動,並在活動中贈送一些禮物。

您可以關注此頁面查看即將舉行的抽獎活動、參加抽獎活動或查看我們之前抽獎的抽獎活動(包括獲獎者)。

感謝您成為活躍會員!在即將到來的抽獎活動中再見。", "RafflesInfoTitle": "ABP 社區萊佛士", - "MarkdownSupported": "Markdown 支持的。" + "MarkdownSupported": "Markdown 支持的。", + "Preview": "预览" } } \ No newline at end of file From ed266b79bf9317bb6e7527256e811a9a17fcc65e Mon Sep 17 00:00:00 2001 From: Salih Date: Fri, 26 Jan 2024 18:33:33 +0300 Subject: [PATCH 143/154] Fix: tooltip seems broken --- modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.js b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.js index f23100d34a..fef573f413 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.js +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.js @@ -283,7 +283,7 @@ initDocumentNodeBreadcrumb(); Element.prototype.querySelector = function (selector) { - var result = $(decodeURI(selector)); + var result = $(this).find(decodeURI(selector)); if(result.length > 0){ return result[0]; } From dc803c72fb3c256844b09d44c7fba046d597c5b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sinan=20=C3=96zt=C3=BCrk?= Date: Fri, 26 Jan 2024 18:44:20 +0300 Subject: [PATCH 144/154] datatable filtering issue --- npm/ng-packs/packages/core/src/lib/services/list.service.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/npm/ng-packs/packages/core/src/lib/services/list.service.ts b/npm/ng-packs/packages/core/src/lib/services/list.service.ts index 76dac87b5a..48996bade1 100644 --- a/npm/ng-packs/packages/core/src/lib/services/list.service.ts +++ b/npm/ng-packs/packages/core/src/lib/services/list.service.ts @@ -52,7 +52,7 @@ export class ListService implements return this._page; } - private _totalCount = 0 + private _totalCount = 0; set totalCount(value: number) { if (value === this._totalCount) return; @@ -150,7 +150,7 @@ export class ListService implements this._query$.next({ filter: this._filter || undefined, maxResultCount: this._maxResultCount, - skipCount: this._page * this._maxResultCount, + skipCount: this._filter ? 0 : this._page * this._maxResultCount, sorting: this._sortOrder ? `${this._sortKey} ${this._sortOrder}` : undefined, } as any as QueryParamsType); } From 8d9e3e09f8046ab71114103a67e7d9669e4bc717 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Mon, 29 Jan 2024 09:37:42 +0800 Subject: [PATCH 145/154] Improve --- .../PermissionValueProviderManager.cs | 17 ++++++++--------- .../Abp/Features/FeatureValueProviderManager.cs | 17 ++++++++--------- .../Abp/Settings/SettingValueProviderManager.cs | 17 ++++++++--------- 3 files changed, 24 insertions(+), 27 deletions(-) diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionValueProviderManager.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionValueProviderManager.cs index 09b2da2acb..aebd14f36e 100644 --- a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionValueProviderManager.cs +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionValueProviderManager.cs @@ -9,29 +9,28 @@ namespace Volo.Abp.Authorization.Permissions; public class PermissionValueProviderManager : IPermissionValueProviderManager, ISingletonDependency { - public IReadOnlyList ValueProviders => GetProviders(); + public IReadOnlyList ValueProviders => _lazyProviders.Value; private readonly Lazy> _lazyProviders; protected AbpPermissionOptions Options { get; } + protected IServiceProvider ServiceProvider { get; } public PermissionValueProviderManager( IServiceProvider serviceProvider, IOptions options) { Options = options.Value; + ServiceProvider = serviceProvider; - _lazyProviders = new Lazy>( - () => Options - .ValueProviders - .Select(c => serviceProvider.GetRequiredService(c) as IPermissionValueProvider) - .ToList()!, - true - ); + _lazyProviders = new Lazy>(GetProviders, true); } protected virtual List GetProviders() { - var providers = _lazyProviders.Value; + var providers = Options + .ValueProviders + .Select(type => (ServiceProvider.GetRequiredService(type) as IPermissionValueProvider)!) + .ToList(); var multipleProviders = providers.GroupBy(p => p.Name).FirstOrDefault(x => x.Count() > 1); if(multipleProviders != null) diff --git a/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureValueProviderManager.cs b/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureValueProviderManager.cs index 98d73dd4e4..c793ee8ce5 100644 --- a/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureValueProviderManager.cs +++ b/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureValueProviderManager.cs @@ -9,29 +9,28 @@ namespace Volo.Abp.Features; public class FeatureValueProviderManager : IFeatureValueProviderManager, ISingletonDependency { - public IReadOnlyList ValueProviders => GetProviders(); + public IReadOnlyList ValueProviders => _lazyProviders.Value; private readonly Lazy> _lazyProviders; protected AbpFeatureOptions Options { get; } + protected IServiceProvider ServiceProvider { get; } public FeatureValueProviderManager( IServiceProvider serviceProvider, IOptions options) { Options = options.Value; + ServiceProvider = serviceProvider; - _lazyProviders = new Lazy>( - () => Options - .ValueProviders - .Select(c => serviceProvider.GetRequiredService(c) as IFeatureValueProvider) - .ToList()!, - true - ); + _lazyProviders = new Lazy>(GetProviders, true); } protected virtual List GetProviders() { - var providers = _lazyProviders.Value; + var providers = Options + .ValueProviders + .Select(type => (ServiceProvider.GetRequiredService(type) as IFeatureValueProvider)!) + .ToList(); var multipleProviders = providers.GroupBy(p => p.Name).FirstOrDefault(x => x.Count() > 1); if(multipleProviders != null) diff --git a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingValueProviderManager.cs b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingValueProviderManager.cs index c13f884e98..116fae5643 100644 --- a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingValueProviderManager.cs +++ b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingValueProviderManager.cs @@ -9,9 +9,10 @@ namespace Volo.Abp.Settings; public class SettingValueProviderManager : ISettingValueProviderManager, ISingletonDependency { - public List Providers => GetProviders(); + public List Providers => _lazyProviders.Value; protected AbpSettingOptions Options { get; } + protected IServiceProvider ServiceProvider { get; } private readonly Lazy> _lazyProviders; public SettingValueProviderManager( @@ -20,19 +21,17 @@ public class SettingValueProviderManager : ISettingValueProviderManager, ISingle { Options = options.Value; + ServiceProvider = serviceProvider; - _lazyProviders = new Lazy>( - () => Options - .ValueProviders - .Select(type => serviceProvider.GetRequiredService(type) as ISettingValueProvider) - .ToList()!, - true - ); + _lazyProviders = new Lazy>(GetProviders, true); } protected virtual List GetProviders() { - var providers = _lazyProviders.Value; + var providers = Options + .ValueProviders + .Select(type => (ServiceProvider.GetRequiredService(type) as ISettingValueProvider)!) + .ToList(); var multipleProviders = providers.GroupBy(p => p.Name).FirstOrDefault(x => x.Count() > 1); if(multipleProviders != null) From e5dd6d54ed8ee6676af12dea0b640445a14cda8d Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Mon, 29 Jan 2024 09:55:27 +0800 Subject: [PATCH 146/154] Make sure getAbpApplicationConfiguration is called --- .../wwwroot/swagger/ui/abp.swagger.js | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/framework/src/Volo.Abp.Swashbuckle/wwwroot/swagger/ui/abp.swagger.js b/framework/src/Volo.Abp.Swashbuckle/wwwroot/swagger/ui/abp.swagger.js index 23e9420145..07deea114b 100644 --- a/framework/src/Volo.Abp.Swashbuckle/wwwroot/swagger/ui/abp.swagger.js +++ b/framework/src/Volo.Abp.Swashbuckle/wwwroot/swagger/ui/abp.swagger.js @@ -14,8 +14,6 @@ var abp = abp || {}; var requestInterceptor = configObject.requestInterceptor; var responseInterceptor = configObject.responseInterceptor; - - getAbpApplicationConfiguration(); configObject.requestInterceptor = async function (request) { @@ -29,17 +27,19 @@ var abp = abp || {}; }); firstRequest = false; } + // Intercept .well-known request when the discoveryEndpoint is provided if (!firstRequest && oidcDiscoveryEndpoint.length !== 0 && request.url.includes(".well-known/openid-configuration")) { + if (oidcDiscoveryEndpoint.endsWith(".well-known/openid-configuration")) { - request.url = replaceTenantPlaceHolder(oidcDiscoveryEndpoint); + request.url = await replaceTenantPlaceHolder(oidcDiscoveryEndpoint); console.log(request.url); return; } if (!oidcDiscoveryEndpoint.endsWith("/")) { oidcDiscoveryEndpoint += "/" } - request.url = replaceTenantPlaceHolder(oidcDiscoveryEndpoint) + ".well-known/openid-configuration"; + request.url = await replaceTenantPlaceHolder(oidcDiscoveryEndpoint) + ".well-known/openid-configuration"; console.log(request.url); } @@ -84,7 +84,11 @@ var abp = abp || {}; return response; }; - function replaceTenantPlaceHolder(url) { + async function replaceTenantPlaceHolder(url) { + + if(!abp.currentTenant){ + await getAbpApplicationConfiguration(); + } url.replace(tenantPlaceHolders[0], abp.currentTenant.id); url.replace(tenantPlaceHolders[1], abp.currentTenant.name); @@ -99,7 +103,7 @@ var abp = abp || {}; } function getAbpApplicationConfiguration() { - fetch(`${abp.appPath}api/abp/application-configuration`).then(response => response.json()).then(data => { + return fetch(`${abp.appPath}api/abp/application-configuration`).then(response => response.json()).then(data => { abp.currentTenant = data.currentTenant; }); } From cd8d078cdfdec8d00261071f86dce7fde59efba9 Mon Sep 17 00:00:00 2001 From: honurbu Date: Mon, 29 Jan 2024 16:45:17 +0300 Subject: [PATCH 147/154] Broken links fixed --- docs/en/API/API-Versioning.md | 2 +- .../en/Getting-Started-Create-Solution-Single-Layer.md | 2 +- docs/en/Getting-Started-Create-Solution.md | 2 +- docs/en/MongoDB.md | 2 +- docs/en/Themes/LeptonXLite/AspNetCore.md | 2 +- docs/en/UI/Angular/Page-Component.md | 2 +- docs/en/UI/Angular/Service-Proxies.md | 4 ++-- docs/en/UI/Angular/Theming.md | 2 +- docs/en/UI/AspNetCore/Customization-User-Interface.md | 2 +- docs/en/UI/AspNetCore/Modals.md | 4 ++-- docs/en/UI/AspNetCore/Overall.md | 2 +- docs/en/UI/AspNetCore/Tag-Helpers/Form-elements.md | 10 +++++----- docs/en/UI/Blazor/Overall.md | 2 +- docs/en/UI/Blazor/Theming.md | 2 +- docs/pt-BR/MongoDB.md | 2 +- docs/zh-Hans/Getting-Started-Create-Solution.md | 2 +- docs/zh-Hans/MongoDB.md | 2 +- docs/zh-Hans/UI/Angular/Service-Proxies.md | 4 ++-- .../zh-Hans/UI/AspNetCore/Tag-Helpers/Form-elements.md | 8 ++++---- 19 files changed, 29 insertions(+), 29 deletions(-) diff --git a/docs/en/API/API-Versioning.md b/docs/en/API/API-Versioning.md index 68343417de..d0f94f2259 100644 --- a/docs/en/API/API-Versioning.md +++ b/docs/en/API/API-Versioning.md @@ -1,6 +1,6 @@ # API Versioning System -ABP Framework integrates the [ASPNET-API-Versioning](https://github.com/dotnet/aspnet-api-versioning/wiki) feature and adapts to C# and JavaScript Static Client Proxies and [Auto API Controller](API/Auto-API-Controllers.md). +ABP Framework integrates the [ASPNET-API-Versioning](https://github.com/dotnet/aspnet-api-versioning/wiki) feature and adapts to C# and JavaScript Static Client Proxies and [Auto API Controller](../API/Auto-API-Controllers.md). ## Enable API Versioning diff --git a/docs/en/Getting-Started-Create-Solution-Single-Layer.md b/docs/en/Getting-Started-Create-Solution-Single-Layer.md index d6ed14600d..8c4a6d0d88 100644 --- a/docs/en/Getting-Started-Create-Solution-Single-Layer.md +++ b/docs/en/Getting-Started-Create-Solution-Single-Layer.md @@ -34,7 +34,7 @@ The solution structure is based on the [Single-Layer Startup Template](Startup-T ## MongoDB Transactions -The [startup template](Startup-templates/Index.md) **disables** transactions in the `.MongoDB` project by default. If your MongoDB server supports transactions, you can enable it in the *YourProjectModule* class's `ConfigureMongoDB` method: +The [startup template](Startup-Templates/Index.md) **disables** transactions in the `.MongoDB` project by default. If your MongoDB server supports transactions, you can enable it in the *YourProjectModule* class's `ConfigureMongoDB` method: ```csharp Configure(options => diff --git a/docs/en/Getting-Started-Create-Solution.md b/docs/en/Getting-Started-Create-Solution.md index 650d3163a0..45689b45fc 100644 --- a/docs/en/Getting-Started-Create-Solution.md +++ b/docs/en/Getting-Started-Create-Solution.md @@ -55,7 +55,7 @@ The solution has a layered structure (based on the [Domain Driven Design](Domain ## MongoDB Transactions -The [startup template](Startup-templates/Index.md) **disables** transactions in the `.MongoDB` project by default. If your MongoDB server supports transactions, you can enable it in the *YourProjectMongoDbModule* class's `ConfigureServices` method: +The [startup template](Startup-Templates/Index.md) **disables** transactions in the `.MongoDB` project by default. If your MongoDB server supports transactions, you can enable it in the *YourProjectMongoDbModule* class's `ConfigureServices` method: ```csharp Configure(options => diff --git a/docs/en/MongoDB.md b/docs/en/MongoDB.md index 372ad74ae6..0faa6a7d26 100644 --- a/docs/en/MongoDB.md +++ b/docs/en/MongoDB.md @@ -281,7 +281,7 @@ public class BookService ### Transactions -MongoDB supports multi-document transactions starting from the version 4.0 and the ABP Framework supports it. However, the [startup template](Startup-templates/Index.md) **disables** transactions by default. If your MongoDB **server** supports transactions, you can enable the it in the *YourProjectMongoDbModule* class: +MongoDB supports multi-document transactions starting from the version 4.0 and the ABP Framework supports it. However, the [startup template](Startup-Templates/Index.md) **disables** transactions by default. If your MongoDB **server** supports transactions, you can enable the it in the *YourProjectMongoDbModule* class: ```csharp Configure(options => diff --git a/docs/en/Themes/LeptonXLite/AspNetCore.md b/docs/en/Themes/LeptonXLite/AspNetCore.md index 1c6baeddf9..8bdf85704f 100644 --- a/docs/en/Themes/LeptonXLite/AspNetCore.md +++ b/docs/en/Themes/LeptonXLite/AspNetCore.md @@ -94,7 +94,7 @@ public class MyProjectNameMainToolbarContributor : IToolbarContributor ABP **helps** you make **highly customizable UI**. You can easily **customize** your themes to fit your needs. **The Virtual File System** makes it possible to **manage files** that **do not physically** exist on the **file system** (disk). It's mainly used to embed **(js, css, image..)** files into assemblies and **use them like** physical files at runtime. An application (or another module) can **override** a **virtual file of a module** just like placing a file with the **same name** and **extension** into the **same folder** of the **virtual file**. -LeptonX Lite is built on the [Abp Framework](https://abp.io/), so you can **easily** customize your Asp.Net Core MVC user interface by following [Abp Mvc UI Customization](https://docs.abp.io/en/abp/latest/UI/AspNetCore/Customization-xUser-Interface). +LeptonX Lite is built on the [Abp Framework](https://abp.io/), so you can **easily** customize your Asp.Net Core MVC user interface by following [Abp Mvc UI Customization](https://docs.abp.io/en/abp/latest/UI/AspNetCore/Customization-User-Interface). ## Branding Component diff --git a/docs/en/UI/Angular/Page-Component.md b/docs/en/UI/Angular/Page-Component.md index 912b516baf..81a2a2c5db 100644 --- a/docs/en/UI/Angular/Page-Component.md +++ b/docs/en/UI/Angular/Page-Component.md @@ -209,4 +209,4 @@ export class DashboardModule {} ## See Also -- [Page Toolbar Extensions for Angular UI](./Page-Page-Toolbar-Extensions.md) +- [Page Toolbar Extensions for Angular UI](./Page-Toolbar-Extensions.md) \ No newline at end of file diff --git a/docs/en/UI/Angular/Service-Proxies.md b/docs/en/UI/Angular/Service-Proxies.md index 43b8dc8b0f..f6a34b76b8 100644 --- a/docs/en/UI/Angular/Service-Proxies.md +++ b/docs/en/UI/Angular/Service-Proxies.md @@ -85,9 +85,9 @@ export const environment: Config.Environment = { ### Services -The `generate-proxy` command generates one service per back-end controller and a method (property with a function value actually) for each action in the controller. These methods call backend APIs via [RestService](./Http-Requests#restservice). +The `generate-proxy` command generates one service per back-end controller and a method (property with a function value actually) for each action in the controller. These methods call backend APIs via [RestService](./HTTP-Requests#restservice). -A variable named `apiName` (available as of v2.4) is defined in each service. `apiName` matches the module's `RemoteServiceName`. This variable passes to the `RestService` as a parameter at each request. If there is no microservice API defined in the environment, `RestService` uses the default. See [getting a specific API endpoint from application config](./Http-Requests#how-to-get-a-specific-api-endpoint-from-application-config) +A variable named `apiName` (available as of v2.4) is defined in each service. `apiName` matches the module's `RemoteServiceName`. This variable passes to the `RestService` as a parameter at each request. If there is no microservice API defined in the environment, `RestService` uses the default. See [getting a specific API endpoint from application config](./HTTP-Requests#how-to-get-a-specific-api-endpoint-from-application-config) The `providedIn` property of the services is defined as `'root'`. Therefore there is no need to provide them in a module. You can use them directly by injecting them into the constructor as shown below: diff --git a/docs/en/UI/Angular/Theming.md b/docs/en/UI/Angular/Theming.md index 435acc6930..a9d29bea02 100644 --- a/docs/en/UI/Angular/Theming.md +++ b/docs/en/UI/Angular/Theming.md @@ -20,7 +20,7 @@ Currently, three themes are **officially provided**: * The [Basic Theme](Basic-Theme.md) is the minimalist theme with the plain Bootstrap style. It is **open source and free**. * The [Lepton Theme](https://commercial.abp.io/themes) is a **commercial** theme developed by the core ABP team and is a part of the [ABP Commercial](https://commercial.abp.io/) license. -* The [LeptonX Theme](https://x.leptontheme.com/) is a theme that has both [commercial](https://docs.abp.io/en/commercial/latest/themes/lepton-x/commercial/angular) and [lite](../../Themes/LeptonXLite/Angular.md) choices. +* The [LeptonX Theme](https://x.leptontheme.com/) is a theme that has both [commercial](https://docs.abp.io/en/commercial/latest/themes/lepton-x/angular) and [lite](../../Themes/LeptonXLite/Angular.md) choices. ## Overall diff --git a/docs/en/UI/AspNetCore/Customization-User-Interface.md b/docs/en/UI/AspNetCore/Customization-User-Interface.md index 8b5a065e86..991f1247b8 100644 --- a/docs/en/UI/AspNetCore/Customization-User-Interface.md +++ b/docs/en/UI/AspNetCore/Customization-User-Interface.md @@ -63,7 +63,7 @@ The account module defines a `Login.cshtml` file under the `Pages/Account` folde You typically want to copy the original `.cshtml` file of the module, then make the necessary changes. You can find the original file [here](https://github.com/abpframework/abp/blob/dev/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml). Do not copy the `Login.cshtml.cs` file which is the code behind file for the razor page and we don't want to override it yet (see the next section). -> Don't forget to add [_ViewImports.cshtml](https://learn.microsoft.com/en-us/aspnet/core/mvc/views/layout?view=aspnetcore-7.0#importing-shared-directives) if the page you want to override contains [ABP Tag Helpers](../Tag-Helpers/Index.md). +> Don't forget to add [_ViewImports.cshtml](https://learn.microsoft.com/en-us/aspnet/core/mvc/views/layout?view=aspnetcore-7.0#importing-shared-directives) if the page you want to override contains [ABP Tag Helpers](../AspNetCore/Tag-Helpers/Index.md). ````csharp @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers diff --git a/docs/en/UI/AspNetCore/Modals.md b/docs/en/UI/AspNetCore/Modals.md index b0a0ba922e..95eaf2e404 100644 --- a/docs/en/UI/AspNetCore/Modals.md +++ b/docs/en/UI/AspNetCore/Modals.md @@ -186,7 +186,7 @@ For this example, creating a new Razor Page, named `ProductCreateModal.cshtml`, ```` * The `abp-modal` has been wrapped by the `form`. This is needed to place the `Save` and the `Cancel` buttons into the form. In this way, the `Save` button acts as the `submit` button for the `form`. -* Used the [abp-input tag helpers](Tag-Helpers/Form-Elements.md) to simplify to create the form elements. Otherwise, you need to write more HTML. +* Used the [abp-input tag helpers](Tag-Helpers/Form-elements.md) to simplify to create the form elements. Otherwise, you need to write more HTML. **ProductCreateModal.cshtml.cs Content:** @@ -247,7 +247,7 @@ namespace MyProject.Web.Pages.Products } ```` -* `abp-input` Tag Helper can understand the data annotation attributes and uses them to shape and validate the form elements. See the [abp-input tag helpers](Tag-Helpers/Form-Elements.md) document to learn more. +* `abp-input` Tag Helper can understand the data annotation attributes and uses them to shape and validate the form elements. See the [abp-input tag helpers](Tag-Helpers/Form-elements.md) document to learn more. #### Defining the Modal Manager diff --git a/docs/en/UI/AspNetCore/Overall.md b/docs/en/UI/AspNetCore/Overall.md index bc24c56fb8..0c7e05c105 100644 --- a/docs/en/UI/AspNetCore/Overall.md +++ b/docs/en/UI/AspNetCore/Overall.md @@ -36,7 +36,7 @@ Currently, three themes are **officially provided**: * The [Basic Theme](Basic-Theme.md) is the minimalist theme with the plain Bootstrap style. It is **open source and free**. * The [Lepton Theme](https://commercial.abp.io/themes) is a **commercial** theme developed by the core ABP team and is a part of the [ABP Commercial](https://commercial.abp.io/) license. -* The [LeptonX Theme](https://x.leptontheme.com/) is a theme that has both [commercial](https://docs.abp.io/en/commercial/latest/themes/lepton-x/commercial/mvc) and [lite](../../Themes/LeptonXLite/AspNetCore.md) choices. +* The [LeptonX Theme](https://x.leptontheme.com/) is a theme that has both [commercial](https://docs.abp.io/en/commercial/latest/themes/lepton-x/mvc) and [lite](../../Themes/LeptonXLite/AspNetCore.md) choices. There are also some community-driven themes for the ABP Framework (you can search on the web). diff --git a/docs/en/UI/AspNetCore/Tag-Helpers/Form-elements.md b/docs/en/UI/AspNetCore/Tag-Helpers/Form-elements.md index b8a55c2ad3..281010b39f 100644 --- a/docs/en/UI/AspNetCore/Tag-Helpers/Form-elements.md +++ b/docs/en/UI/AspNetCore/Tag-Helpers/Form-elements.md @@ -58,7 +58,7 @@ Model: ### Attributes -You can set some of the attributes on your c# property, or directly on HTML tag. If you are going to use this property in a [abp-dynamic-form](Dynamic-forms.md), then you can only set these properties via property attributes. +You can set some of the attributes on your c# property, or directly on HTML tag. If you are going to use this property in a [abp-dynamic-form](Dynamic-Forms.md), then you can only set these properties via property attributes. #### Property Attributes @@ -103,7 +103,7 @@ You can set the label of the input in several ways: `abp-select` tag creates a Bootstrap form select for a given c# property. It uses [ASP.NET Core Select Tag Helper](https://docs.microsoft.com/tr-tr/aspnet/core/mvc/views/working-with-forms?view=aspnetcore-3.1#the-select-tag-helper) in background, so every data annotation attribute of `select` tag helper of ASP.NET Core is also valid for `abp-select`. -`abp-select` tag needs a list of `Microsoft.AspNetCore.Mvc.Rendering.SelectListItem ` to work. It can be provided by `asp-items` attriube on the tag or `[SelectItems()]` attribute on c# property. (if you are using [abp-dynamic-form](Dynamic-forms.md), c# attribute is the only way.) +`abp-select` tag needs a list of `Microsoft.AspNetCore.Mvc.Rendering.SelectListItem ` to work. It can be provided by `asp-items` attriube on the tag or `[SelectItems()]` attribute on c# property. (if you are using [abp-dynamic-form](Dynamic-Forms.md), c# attribute is the only way.) `abp-select` supports multiple selection. @@ -171,7 +171,7 @@ Model: ### Attributes -You can set some of the attributes on your c# property, or directly on HTML tag. If you are going to use this property in a [abp-dynamic-form](Dynamic-forms.md), then you can only set these properties via property attributes. +You can set some of the attributes on your c# property, or directly on HTML tag. If you are going to use this property in a [abp-dynamic-form](Dynamic-Forms.md), then you can only set these properties via property attributes. #### Property Attributes @@ -252,7 +252,7 @@ Model: ### Attributes -You can set some of the attributes on your c# property, or directly on HTML tag. If you are going to use this property in a [abp-dynamic-form](Dynamic-forms.md), then you can only set these properties via property attributes. +You can set some of the attributes on your c# property, or directly on HTML tag. If you are going to use this property in a [abp-dynamic-form](Dynamic-Forms.md), then you can only set these properties via property attributes. #### Property Attributes @@ -325,7 +325,7 @@ Model: ### Attributes -You can set some of the attributes on your c# property, or directly on HTML tag. If you are going to use this property in a [abp-dynamic-form](Dynamic-forms.md), then you can only set these properties via property attributes. +You can set some of the attributes on your c# property, or directly on HTML tag. If you are going to use this property in a [abp-dynamic-form](Dynamic-Forms.md), then you can only set these properties via property attributes. #### Property Attributes diff --git a/docs/en/UI/Blazor/Overall.md b/docs/en/UI/Blazor/Overall.md index f38c0c257b..ac032e3b23 100644 --- a/docs/en/UI/Blazor/Overall.md +++ b/docs/en/UI/Blazor/Overall.md @@ -79,7 +79,7 @@ Currently, three themes are **officially provided**: * The [Basic Theme](Basic-Theme.md) is the minimalist theme with the plain Bootstrap style. It is **open source and free**. * The [Lepton Theme](https://commercial.abp.io/themes) is a **commercial** theme developed by the core ABP team and is a part of the [ABP Commercial](https://commercial.abp.io/) license. -* The [LeptonX Theme](https://x.leptontheme.com/) is a theme that has both [commercial](https://docs.abp.io/en/commercial/latest/themes/lepton-x/commercial/blazor) and [lite](../../Themes/LeptonXLite/Blazor.md) choices. +* The [LeptonX Theme](https://x.leptontheme.com/) is a theme that has both [commercial](https://docs.abp.io/en/commercial/latest/themes/lepton-x/blazor) and [lite](../../Themes/LeptonXLite/Blazor.md) choices. ### Base Libraries diff --git a/docs/en/UI/Blazor/Theming.md b/docs/en/UI/Blazor/Theming.md index 2496df9b20..50bb0d454e 100644 --- a/docs/en/UI/Blazor/Theming.md +++ b/docs/en/UI/Blazor/Theming.md @@ -27,7 +27,7 @@ Currently, three themes are **officially provided**: * The [Basic Theme](Basic-Theme.md) is the minimalist theme with the plain Bootstrap style. It is **open source and free**. * The [Lepton Theme](https://commercial.abp.io/themes) is a **commercial** theme developed by the core ABP team and is a part of the [ABP Commercial](https://commercial.abp.io/) license. -* The [LeptonX Theme](https://x.leptontheme.com/) is a theme that has a [commercial](https://docs.abp.io/en/commercial/latest/themes/lepton-x/commercial/blazor) and a [lite](../../Themes/LeptonXLite/Blazor.md) version. +* The [LeptonX Theme](https://x.leptontheme.com/) is a theme that has a [commercial](https://docs.abp.io/en/commercial/latest/themes/lepton-x/blazor) and a [lite](../../Themes/LeptonXLite/Blazor.md) version. ## Overall diff --git a/docs/pt-BR/MongoDB.md b/docs/pt-BR/MongoDB.md index bc4a7882a7..c7ad2ef1c3 100644 --- a/docs/pt-BR/MongoDB.md +++ b/docs/pt-BR/MongoDB.md @@ -279,7 +279,7 @@ public class BookService ### Transactions -O MongoDB oferece suporte multi-document transactions a partir da versão 4.0 e o ABP Framework oferece suporte para isso. No entanto, o [startup template](Startup-templates/Index.md) **desativa** transactions por padrão. Se o seu **servidor** MongoDB suportar transactions, você pode habilitar esse recurso na classe *YourProjectMongoDbModule*: +O MongoDB oferece suporte multi-document transactions a partir da versão 4.0 e o ABP Framework oferece suporte para isso. No entanto, o [startup template](Startup-Templates/Index.md) **desativa** transactions por padrão. Se o seu **servidor** MongoDB suportar transactions, você pode habilitar esse recurso na classe *YourProjectMongoDbModule*: ```csharp Configure(options => diff --git a/docs/zh-Hans/Getting-Started-Create-Solution.md b/docs/zh-Hans/Getting-Started-Create-Solution.md index 55906add7e..5b83f594e9 100644 --- a/docs/zh-Hans/Getting-Started-Create-Solution.md +++ b/docs/zh-Hans/Getting-Started-Create-Solution.md @@ -55,7 +55,7 @@ abp new Acme.BookStore{{if UI == "NG"}} -u angular{{else if UI == "Blazor"}} -u #### MongoDB 事务 -[启动模板](Startup-templates/Index.md) 默认在`.MongoDB`项目中**禁用**事务. 如果你的MongoDB服务器支持事务, 你可以在*YourProjectMongoDbModule*类中的`ConfigureServices`方法开启它: +[启动模板](Startup-Templates/Index.md) 默认在`.MongoDB`项目中**禁用**事务. 如果你的MongoDB服务器支持事务, 你可以在*YourProjectMongoDbModule*类中的`ConfigureServices`方法开启它: ```csharp Configure(options => diff --git a/docs/zh-Hans/MongoDB.md b/docs/zh-Hans/MongoDB.md index 87c99d3207..540793dd1f 100644 --- a/docs/zh-Hans/MongoDB.md +++ b/docs/zh-Hans/MongoDB.md @@ -238,7 +238,7 @@ public class BookService MongoDB在4.0版本开始支持事务, ABP在3.2版本加入了对MongoDb事务的支持. 如果你升级到3.2版本,需要将[MongoDbSchemaMigrator](https://github.com/abpframework/abp/blob/dev/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.MongoDB/MongoDb/MongoDbMyProjectNameDbSchemaMigrator.cs)添加到你的 `.MongoDB` 项目中. -[启动模板](Startup-templates/Index.md)默认在 `.MongoDB` 项目中**禁用**了工作单元事务. 如果你的MongoDB服务器支持事务,你可以手动启用工作单元的事务: +[启动模板](Startup-Templates/Index.md)默认在 `.MongoDB` 项目中**禁用**了工作单元事务. 如果你的MongoDB服务器支持事务,你可以手动启用工作单元的事务: ```csharp Configure(options => diff --git a/docs/zh-Hans/UI/Angular/Service-Proxies.md b/docs/zh-Hans/UI/Angular/Service-Proxies.md index cc07a24175..17b04823f3 100644 --- a/docs/zh-Hans/UI/Angular/Service-Proxies.md +++ b/docs/zh-Hans/UI/Angular/Service-Proxies.md @@ -26,7 +26,7 @@ abp generate-proxy -t ng ### Services -每个生成的服务都与后端控制器匹配. 服务方法通过[RestService](./Http-Requests#restservice)调用后端API. +每个生成的服务都与后端控制器匹配. 服务方法通过[RestService](./HTTP-Requests#restservice)调用后端API. 在每个服务中都定义了一个名为 `apiName` 的变量(自v2.4起可用). `apiName` 与模块的 `RemoteServiceName` 匹配. 在每次请求时该变量将作为参数传递给 `RestService`. 如果环境中未定义微服务API, `RestService` 使用默认值. 请参阅[从应用程序配置中获取特定的API端点](./Http-Requests#how-to-get-a-specific-api-endpoint-from-application-config) @@ -65,4 +65,4 @@ const instance = new IdentityRoleCreateDto({name: 'Role 1', isDefault: false, is ## 下一步是什么? -* [HTTP请求](./Http-Requests) \ No newline at end of file +* [HTTP请求](./HTTP-Requests) diff --git a/docs/zh-Hans/UI/AspNetCore/Tag-Helpers/Form-elements.md b/docs/zh-Hans/UI/AspNetCore/Tag-Helpers/Form-elements.md index a5629fb16a..57e66cc888 100644 --- a/docs/zh-Hans/UI/AspNetCore/Tag-Helpers/Form-elements.md +++ b/docs/zh-Hans/UI/AspNetCore/Tag-Helpers/Form-elements.md @@ -59,7 +59,7 @@ Model: ### 特性(Attributes) -你可以在你的c#属性上设置一些特性,或者直接在html标签上设置。如果您要在[abp-dynamic-form](Dynamic-forms.md)中使用此属性,则只能通过属性特性设置这些属性。 +你可以在你的c#属性上设置一些特性,或者直接在html标签上设置。如果您要在[abp-dynamic-form](Dynamic-Forms.md)中使用此属性,则只能通过属性特性设置这些属性。 #### 属性特性(Property Attributes) @@ -104,7 +104,7 @@ Model: `abp-select` 标签为给定的 C# 属性创建了一个 Bootstrap 表单选择器。它在后台使用 [Asp.Net Core 选择标签助手](https://docs.microsoft.com/tr-tr/aspnet/core/mvc/views/working-with-forms?view=aspnetcore-3.1#the-select-tag-helper),因此 `Asp.Net Core` 的 `select` 标签助手的每个数据注释属性也适用于 `abp-select`。 -`abp-select` 标签需要一个 `Microsoft.AspNetCore.Mvc.Rendering.SelectListItem` 的列表来工作。它可以通过标签上的 `asp-items` 属性或 C# 属性上的 `[SelectItems()]` 属性来提供(如果您使用的是 [abp-dynamic-form](Dynamic-forms.md),则只能使用 C# 属性的方式。) +`abp-select` 标签需要一个 `Microsoft.AspNetCore.Mvc.Rendering.SelectListItem` 的列表来工作。它可以通过标签上的 `asp-items` 属性或 C# 属性上的 `[SelectItems()]` 属性来提供(如果您使用的是 [abp-dynamic-form](Dynamic-Forms.md),则只能使用 C# 属性的方式。) `abp-select` 支持多重选择。 @@ -172,7 +172,7 @@ Model: ### 属性 -您可以在 C# 属性上或直接在 HTML 标签上设置一些属性。如果您将在 [abp-dynamic-form](Dynamic-forms.md) 中使用此属性,则只能通过属性属性设置这些属性。 +您可以在 C# 属性上或直接在 HTML 标签上设置一些属性。如果您将在 [abp-dynamic-form](Dynamic-Forms.md) 中使用此属性,则只能通过属性属性设置这些属性。 #### 属性特性(Property Attributes) @@ -255,7 +255,7 @@ Model: ### 特性(attributes) -您可以在C#属性或直接在HTML标签上设置一些属性。如果您将在[abp-dynamic-form](Dynamic-forms.md)中使用此属性,则只能通过属性属性设置这些属性。 +您可以在C#属性或直接在HTML标签上设置一些属性。如果您将在[abp-dynamic-form](Dynamic-Forms.md)中使用此属性,则只能通过属性属性设置这些属性。 #### 属性特性(Property Attributes) From 054757cca4d40539d0d27f8f746fdc074ef67033 Mon Sep 17 00:00:00 2001 From: masumulu28 Date: Mon, 29 Jan 2024 17:01:18 +0300 Subject: [PATCH 148/154] update schema for secondary-endpoint library in module template --- .../angular/projects/my-project-name/config/ng-package.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/templates/module/angular/projects/my-project-name/config/ng-package.json b/templates/module/angular/projects/my-project-name/config/ng-package.json index 37a8a9e06c..e09fb3fd03 100644 --- a/templates/module/angular/projects/my-project-name/config/ng-package.json +++ b/templates/module/angular/projects/my-project-name/config/ng-package.json @@ -1,6 +1,5 @@ { - "$schema": "../../../node_modules/ng-packagr/ng-package.schema.json", - "dest": "../../dist/my-project-name/config", + "$schema": "../../../node_modules/ng-packagr/ng-entrypoint.schema.json", "lib": { "entryFile": "src/public-api.ts" } From 36bb84cdc12a412e622b43ede3a67ff3144188b3 Mon Sep 17 00:00:00 2001 From: selman koc <64414348+skoc10@users.noreply.github.com> Date: Tue, 30 Jan 2024 10:54:12 +0300 Subject: [PATCH 149/154] Update auto-pr.yml --- .github/workflows/auto-pr.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/auto-pr.yml b/.github/workflows/auto-pr.yml index 5587120951..6ca52cfd0a 100644 --- a/.github/workflows/auto-pr.yml +++ b/.github/workflows/auto-pr.yml @@ -1,4 +1,4 @@ -name: Merge branch dev with rel-8.0 +name: Merge branch prerel-8.1 with rel-8.0 on: push: branches: @@ -7,7 +7,7 @@ permissions: contents: read jobs: - merge-dev-with-rel-8-0: + merge-prerel-8-1-with-rel-8-0: permissions: contents: write # for peter-evans/create-pull-request to create branch pull-requests: write # for peter-evans/create-pull-request to create a PR @@ -15,7 +15,7 @@ jobs: steps: - uses: actions/checkout@v2 with: - ref: dev + ref: prerel-8.1 - name: Reset promotion branch run: | git fetch origin rel-8.0:rel-8.0 @@ -24,8 +24,8 @@ jobs: uses: peter-evans/create-pull-request@v3 with: branch: auto-merge/rel-8-0/${{github.run_number}} - title: Merge branch dev with rel-8.0 - body: This PR generated automatically to merge dev with rel-8.0. Please review the changed files before merging to prevent any errors that may occur. + title: Merge branch prerel-8.1 with rel-8.0 + body: This PR generated automatically to merge prerel-8.1 with rel-8.0. Please review the changed files before merging to prevent any errors that may occur. reviewers: maliming token: ${{ github.token }} - name: Merge Pull Request From f0194a58575f1bb33f0610aaa252c136739a591e Mon Sep 17 00:00:00 2001 From: selman koc <64414348+skoc10@users.noreply.github.com> Date: Tue, 30 Jan 2024 10:59:38 +0300 Subject: [PATCH 150/154] Update auto-pr.yml --- .github/workflows/auto-pr.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/auto-pr.yml b/.github/workflows/auto-pr.yml index 5587120951..e9fe77a661 100644 --- a/.github/workflows/auto-pr.yml +++ b/.github/workflows/auto-pr.yml @@ -1,13 +1,13 @@ -name: Merge branch dev with rel-8.0 +name: Merge branch dev with prerel-8.1 on: push: branches: - - rel-8.0 + - prerel-8.1 permissions: contents: read jobs: - merge-dev-with-rel-8-0: + merge-dev-with-prerel-8-1: permissions: contents: write # for peter-evans/create-pull-request to create branch pull-requests: write # for peter-evans/create-pull-request to create a PR @@ -18,14 +18,14 @@ jobs: ref: dev - name: Reset promotion branch run: | - git fetch origin rel-8.0:rel-8.0 - git reset --hard rel-8.0 + git fetch origin prerel-8.1:prerel-8.1 + git reset --hard prerel-8.1 - name: Create Pull Request uses: peter-evans/create-pull-request@v3 with: - branch: auto-merge/rel-8-0/${{github.run_number}} - title: Merge branch dev with rel-8.0 - body: This PR generated automatically to merge dev with rel-8.0. Please review the changed files before merging to prevent any errors that may occur. + branch: auto-merge/prerel-8-1/${{github.run_number}} + title: Merge branch dev with prerel-8.1 + body: This PR generated automatically to merge dev with prerel-8.1. Please review the changed files before merging to prevent any errors that may occur. reviewers: maliming token: ${{ github.token }} - name: Merge Pull Request From 183d66d84264961a92477e4be5760fe0b5306ee8 Mon Sep 17 00:00:00 2001 From: selman koc <64414348+skoc10@users.noreply.github.com> Date: Tue, 30 Jan 2024 11:13:05 +0300 Subject: [PATCH 151/154] Update auto-pr.yml --- .github/workflows/auto-pr.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/auto-pr.yml b/.github/workflows/auto-pr.yml index e9fe77a661..164d23fdb5 100644 --- a/.github/workflows/auto-pr.yml +++ b/.github/workflows/auto-pr.yml @@ -32,5 +32,5 @@ jobs: env: GH_TOKEN: ${{ secrets.BOT_SECRET }} run: | - gh pr review auto-merge/rel-8-0/${{github.run_number}} --approve - gh pr merge auto-merge/rel-8-0/${{github.run_number}} --merge --auto --delete-branch + gh pr review auto-merge/prerel-8-1/${{github.run_number}} --approve + gh pr merge auto-merge/prerel-8-1/${{github.run_number}} --merge --auto --delete-branch From 60f5de39e947569c8d6b6bc483990b2bbc1b72d6 Mon Sep 17 00:00:00 2001 From: honurbu Date: Tue, 30 Jan 2024 12:07:35 +0300 Subject: [PATCH 152/154] Update CLI links --- docs/en/UI/AspNetCore/Static-JavaScript-Proxies.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/UI/AspNetCore/Static-JavaScript-Proxies.md b/docs/en/UI/AspNetCore/Static-JavaScript-Proxies.md index 20b87aa89b..fffc53cf83 100644 --- a/docs/en/UI/AspNetCore/Static-JavaScript-Proxies.md +++ b/docs/en/UI/AspNetCore/Static-JavaScript-Proxies.md @@ -49,7 +49,7 @@ Open a command-line terminal in the root folder of your web project (`.csproj`) abp generate-proxy -t js -u https://localhost:53929/ ```` -> If you haven't installed yet, you should install the [ABP CLI](../CLI.md). Change the example URL to your application's root URL. +> If you haven't installed yet, you should install the [ABP CLI](../../CLI.md). Change the example URL to your application's root URL. This command should generate the following files under the `ClientProxies` folder: From c4e466136f44cfa746ca0a1aef8b996bbea5e280 Mon Sep 17 00:00:00 2001 From: selman koc <64414348+skoc10@users.noreply.github.com> Date: Tue, 30 Jan 2024 17:28:02 +0300 Subject: [PATCH 153/154] Update version for preview nightly build --- common.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common.props b/common.props index d976cecd0d..de934818f0 100644 --- a/common.props +++ b/common.props @@ -1,7 +1,7 @@ latest - 8.1.0 + 8.2.0 $(NoWarn);CS1591;CS0436 https://abp.io/assets/abp_nupkg.png https://abp.io/ From 88f0eed3587dcb19338f790abe90960391f14be2 Mon Sep 17 00:00:00 2001 From: Miguel <10773024+miguelaristy@users.noreply.github.com> Date: Tue, 30 Jan 2024 16:57:21 -0500 Subject: [PATCH 154/154] fix(PermissionManagement): update localization Update localization "es.json" --- .../Volo/Abp/PermissionManagement/Localization/Domain/es.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/es.json b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/es.json index 7f95016b41..60aad5eee2 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/es.json +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/es.json @@ -4,8 +4,8 @@ "Permissions": "Permisos", "OnlyProviderPermissons": "Sólo este proveedor", "All": "Todos", - "SelectAllInAllTabs": "Condeder todos los permisos", + "SelectAllInAllTabs": "Conceder todos los permisos", "SelectAllInThisTab": "Seleccionar todo", "SaveWithoutAnyPermissionsWarningMessage": "¿Estás seguro de que quieres guardar sin ningún permiso?" } -} \ No newline at end of file +}