From 3831d13e4dd642eacd6a897e4bb09ac0e66fc138 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Mon, 28 Sep 2020 14:08:04 +0800 Subject: [PATCH 001/566] Change tenant in all derived class of IDataSeedContributor --- .../CmsKitDataSeedContributor.cs | 25 ++++++++++++------- .../IdentityServerDataSeedContributor.cs | 15 ++++++++--- .../IdentityServerDataSeedContributor.cs | 15 ++++++++--- 3 files changed, 38 insertions(+), 17 deletions(-) diff --git a/modules/cms-kit/test/Volo.CmsKit.TestBase/CmsKitDataSeedContributor.cs b/modules/cms-kit/test/Volo.CmsKit.TestBase/CmsKitDataSeedContributor.cs index f91e79fb84..e2231570b9 100644 --- a/modules/cms-kit/test/Volo.CmsKit.TestBase/CmsKitDataSeedContributor.cs +++ b/modules/cms-kit/test/Volo.CmsKit.TestBase/CmsKitDataSeedContributor.cs @@ -2,6 +2,7 @@ using Volo.Abp.Data; using Volo.Abp.DependencyInjection; using Volo.Abp.Guids; +using Volo.Abp.MultiTenancy; using Volo.Abp.Users; using Volo.CmsKit.Comments; using Volo.CmsKit.Ratings; @@ -18,6 +19,7 @@ namespace Volo.CmsKit private readonly ICommentRepository _commentRepository; private readonly ReactionManager _reactionManager; private readonly IRatingRepository _ratingRepository; + private readonly ICurrentTenant _currentTenant; public CmsKitDataSeedContributor( IGuidGenerator guidGenerator, @@ -25,7 +27,8 @@ namespace Volo.CmsKit CmsKitTestData cmsKitTestData, ICommentRepository commentRepository, ReactionManager reactionManager, - IRatingRepository ratingRepository) + IRatingRepository ratingRepository, + ICurrentTenant currentTenant) { _guidGenerator = guidGenerator; _cmsUserRepository = cmsUserRepository; @@ -33,17 +36,21 @@ namespace Volo.CmsKit _commentRepository = commentRepository; _reactionManager = reactionManager; _ratingRepository = ratingRepository; + _currentTenant = currentTenant; } public async Task SeedAsync(DataSeedContext context) { - await SeedUsersAsync(); + using (_currentTenant.Change(context.TenantId)) + { + await SeedUsersAsync(); - await SeedCommentsAsync(); + await SeedCommentsAsync(); - await SeedReactionsAsync(); + await SeedReactionsAsync(); - await SeedRatingsAsync(); + await SeedRatingsAsync(); + } } private async Task SeedUsersAsync() @@ -148,21 +155,21 @@ namespace Volo.CmsKit 4, _cmsKitTestData.User1Id )); - + await _ratingRepository.InsertAsync(new Rating(_guidGenerator.Create(), _cmsKitTestData.EntityType1, _cmsKitTestData.EntityId1, 5, _cmsKitTestData.User1Id )); - + await _ratingRepository.InsertAsync(new Rating(_guidGenerator.Create(), _cmsKitTestData.EntityType2, _cmsKitTestData.EntityId2, 5, _cmsKitTestData.User2Id )); - + await _ratingRepository.InsertAsync(new Rating(_guidGenerator.Create(), _cmsKitTestData.EntityType2, _cmsKitTestData.EntityId2, @@ -171,4 +178,4 @@ namespace Volo.CmsKit )); } } -} \ No newline at end of file +} diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain/IdentityServer/IdentityServerDataSeedContributor.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain/IdentityServer/IdentityServerDataSeedContributor.cs index dcd105a4e9..fb87b48303 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain/IdentityServer/IdentityServerDataSeedContributor.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain/IdentityServer/IdentityServerDataSeedContributor.cs @@ -10,6 +10,7 @@ using Volo.Abp.Guids; using Volo.Abp.IdentityServer.ApiResources; using Volo.Abp.IdentityServer.Clients; using Volo.Abp.IdentityServer.IdentityResources; +using Volo.Abp.MultiTenancy; using Volo.Abp.PermissionManagement; using Volo.Abp.Uow; using ApiResource = Volo.Abp.IdentityServer.ApiResources.ApiResource; @@ -25,6 +26,7 @@ namespace MyCompanyName.MyProjectName.IdentityServer private readonly IGuidGenerator _guidGenerator; private readonly IPermissionDataSeeder _permissionDataSeeder; private readonly IConfiguration _configuration; + private readonly ICurrentTenant _currentTenant; public IdentityServerDataSeedContributor( IClientRepository clientRepository, @@ -32,7 +34,8 @@ namespace MyCompanyName.MyProjectName.IdentityServer IIdentityResourceDataSeeder identityResourceDataSeeder, IGuidGenerator guidGenerator, IPermissionDataSeeder permissionDataSeeder, - IConfiguration configuration) + IConfiguration configuration, + ICurrentTenant currentTenant) { _clientRepository = clientRepository; _apiResourceRepository = apiResourceRepository; @@ -40,14 +43,18 @@ namespace MyCompanyName.MyProjectName.IdentityServer _guidGenerator = guidGenerator; _permissionDataSeeder = permissionDataSeeder; _configuration = configuration; + _currentTenant = currentTenant; } [UnitOfWork] public virtual async Task SeedAsync(DataSeedContext context) { - await _identityResourceDataSeeder.CreateStandardResourcesAsync(); - await CreateApiResourcesAsync(); - await CreateClientsAsync(); + using (_currentTenant.Change(context.TenantId)) + { + await _identityResourceDataSeeder.CreateStandardResourcesAsync(); + await CreateApiResourcesAsync(); + await CreateClientsAsync(); + } } private async Task CreateApiResourcesAsync() diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/IdentityServer/IdentityServerDataSeedContributor.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/IdentityServer/IdentityServerDataSeedContributor.cs index 593169ae48..bff1f28f30 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/IdentityServer/IdentityServerDataSeedContributor.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/IdentityServer/IdentityServerDataSeedContributor.cs @@ -9,6 +9,7 @@ using Volo.Abp.Guids; using Volo.Abp.IdentityServer.ApiResources; using Volo.Abp.IdentityServer.Clients; using Volo.Abp.IdentityServer.IdentityResources; +using Volo.Abp.MultiTenancy; using Volo.Abp.PermissionManagement; using Volo.Abp.Uow; @@ -22,6 +23,7 @@ namespace MyCompanyName.MyProjectName.IdentityServer private readonly IGuidGenerator _guidGenerator; private readonly IPermissionDataSeeder _permissionDataSeeder; private readonly IConfiguration _configuration; + private readonly ICurrentTenant _currentTenant; public IdentityServerDataSeedContributor( IClientRepository clientRepository, @@ -29,7 +31,8 @@ namespace MyCompanyName.MyProjectName.IdentityServer IIdentityResourceDataSeeder identityResourceDataSeeder, IGuidGenerator guidGenerator, IPermissionDataSeeder permissionDataSeeder, - IConfiguration configuration) + IConfiguration configuration, + ICurrentTenant currentTenant) { _clientRepository = clientRepository; _apiResourceRepository = apiResourceRepository; @@ -37,14 +40,18 @@ namespace MyCompanyName.MyProjectName.IdentityServer _guidGenerator = guidGenerator; _permissionDataSeeder = permissionDataSeeder; _configuration = configuration; + _currentTenant = currentTenant; } [UnitOfWork] public virtual async Task SeedAsync(DataSeedContext context) { - await _identityResourceDataSeeder.CreateStandardResourcesAsync(); - await CreateApiResourcesAsync(); - await CreateClientsAsync(); + using (_currentTenant.Change(context.TenantId)) + { + await _identityResourceDataSeeder.CreateStandardResourcesAsync(); + await CreateApiResourcesAsync(); + await CreateClientsAsync(); + } } private async Task CreateApiResourcesAsync() From f044d94a193ffb47fd159d6591a74d84fae7fc92 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Mon, 28 Sep 2020 14:28:16 +0800 Subject: [PATCH 002/566] Improved --- .../test/Volo.CmsKit.TestBase/CmsKitDataSeedContributor.cs | 2 +- .../IdentityServer/IdentityServerDataSeedContributor.cs | 2 +- .../IdentityServer/IdentityServerDataSeedContributor.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/cms-kit/test/Volo.CmsKit.TestBase/CmsKitDataSeedContributor.cs b/modules/cms-kit/test/Volo.CmsKit.TestBase/CmsKitDataSeedContributor.cs index e2231570b9..2237ecc064 100644 --- a/modules/cms-kit/test/Volo.CmsKit.TestBase/CmsKitDataSeedContributor.cs +++ b/modules/cms-kit/test/Volo.CmsKit.TestBase/CmsKitDataSeedContributor.cs @@ -41,7 +41,7 @@ namespace Volo.CmsKit public async Task SeedAsync(DataSeedContext context) { - using (_currentTenant.Change(context.TenantId)) + using (_currentTenant.Change(context?.TenantId)) { await SeedUsersAsync(); diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain/IdentityServer/IdentityServerDataSeedContributor.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain/IdentityServer/IdentityServerDataSeedContributor.cs index fb87b48303..e447c3c505 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain/IdentityServer/IdentityServerDataSeedContributor.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain/IdentityServer/IdentityServerDataSeedContributor.cs @@ -49,7 +49,7 @@ namespace MyCompanyName.MyProjectName.IdentityServer [UnitOfWork] public virtual async Task SeedAsync(DataSeedContext context) { - using (_currentTenant.Change(context.TenantId)) + using (_currentTenant.Change(context?.TenantId)) { await _identityResourceDataSeeder.CreateStandardResourcesAsync(); await CreateApiResourcesAsync(); diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/IdentityServer/IdentityServerDataSeedContributor.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/IdentityServer/IdentityServerDataSeedContributor.cs index bff1f28f30..c74db4036e 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/IdentityServer/IdentityServerDataSeedContributor.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/IdentityServer/IdentityServerDataSeedContributor.cs @@ -46,7 +46,7 @@ namespace MyCompanyName.MyProjectName.IdentityServer [UnitOfWork] public virtual async Task SeedAsync(DataSeedContext context) { - using (_currentTenant.Change(context.TenantId)) + using (_currentTenant.Change(context?.TenantId)) { await _identityResourceDataSeeder.CreateStandardResourcesAsync(); await CreateApiResourcesAsync(); From 235109e4711f1b5b7a4b0a6a239251c4c80234fd Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Mon, 28 Sep 2020 15:39:34 +0800 Subject: [PATCH 003/566] Update data-seeding document --- docs/en/Data-Seeding.md | 32 +++++++++++-------- docs/zh-Hans/Data-Seeding.md | 32 +++++++++++-------- .../MyProjectNameDataSeedContributor.cs | 14 +++++--- 3 files changed, 48 insertions(+), 30 deletions(-) diff --git a/docs/en/Data-Seeding.md b/docs/en/Data-Seeding.md index 8827fe96c0..f3e9414f0f 100644 --- a/docs/en/Data-Seeding.md +++ b/docs/en/Data-Seeding.md @@ -38,31 +38,37 @@ namespace Acme.BookStore { private readonly IRepository _bookRepository; private readonly IGuidGenerator _guidGenerator; + private readonly ICurrentTenant _currentTenant; public BookStoreDataSeedContributor( IRepository bookRepository, - IGuidGenerator guidGenerator) + IGuidGenerator guidGenerator, + ICurrentTenant currentTenant) { _bookRepository = bookRepository; _guidGenerator = guidGenerator; + _currentTenant = currentTenant; } public async Task SeedAsync(DataSeedContext context) { - if (await _bookRepository.GetCountAsync() > 0) + using (_currentTenant.Change(context?.TenantId)) { - return; + if (await _bookRepository.GetCountAsync() > 0) + { + return; + } + + var book = new Book( + id: _guidGenerator.Create(), + name: "The Hitchhiker's Guide to the Galaxy", + type: BookType.ScienceFiction, + publishDate: new DateTime(1979, 10, 12), + price: 42 + ); + + await _bookRepository.InsertAsync(book); } - - var book = new Book( - id: _guidGenerator.Create(), - name: "The Hitchhiker's Guide to the Galaxy", - type: BookType.ScienceFiction, - publishDate: new DateTime(1979, 10, 12), - price: 42 - ); - - await _bookRepository.InsertAsync(book); } } } diff --git a/docs/zh-Hans/Data-Seeding.md b/docs/zh-Hans/Data-Seeding.md index 68f6fc1e73..97e7c7915c 100644 --- a/docs/zh-Hans/Data-Seeding.md +++ b/docs/zh-Hans/Data-Seeding.md @@ -38,31 +38,37 @@ namespace Acme.BookStore { private readonly IRepository _bookRepository; private readonly IGuidGenerator _guidGenerator; + private readonly ICurrentTenant _currentTenant; public BookStoreDataSeedContributor( IRepository bookRepository, - IGuidGenerator guidGenerator) + IGuidGenerator guidGenerator, + ICurrentTenant currentTenant) { _bookRepository = bookRepository; _guidGenerator = guidGenerator; + _currentTenant = currentTenant; } public async Task SeedAsync(DataSeedContext context) { - if (await _bookRepository.GetCountAsync() > 0) + using (_currentTenant.Change(context?.TenantId)) { - return; + if (await _bookRepository.GetCountAsync() > 0) + { + return; + } + + var book = new Book( + id: _guidGenerator.Create(), + name: "The Hitchhiker's Guide to the Galaxy", + type: BookType.ScienceFiction, + publishDate: new DateTime(1979, 10, 12), + price: 42 + ); + + await _bookRepository.InsertAsync(book); } - - var book = new Book( - id: _guidGenerator.Create(), - name: "The Hitchhiker's Guide to the Galaxy", - type: BookType.ScienceFiction, - publishDate: new DateTime(1979, 10, 12), - price: 42 - ); - - await _bookRepository.InsertAsync(book); } } } diff --git a/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.TestBase/MyProjectNameDataSeedContributor.cs b/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.TestBase/MyProjectNameDataSeedContributor.cs index 871c3274b8..fa7a35ec92 100644 --- a/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.TestBase/MyProjectNameDataSeedContributor.cs +++ b/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.TestBase/MyProjectNameDataSeedContributor.cs @@ -2,26 +2,32 @@ using Volo.Abp.Data; using Volo.Abp.DependencyInjection; using Volo.Abp.Guids; +using Volo.Abp.MultiTenancy; namespace MyCompanyName.MyProjectName { public class MyProjectNameDataSeedContributor : IDataSeedContributor, ITransientDependency { private readonly IGuidGenerator _guidGenerator; + private readonly ICurrentTenant _currentTenant; public MyProjectNameDataSeedContributor( - IGuidGenerator guidGenerator) + IGuidGenerator guidGenerator, ICurrentTenant currentTenant) { _guidGenerator = guidGenerator; + _currentTenant = currentTenant; } - + public Task SeedAsync(DataSeedContext context) { /* Instead of returning the Task.CompletedTask, you can insert your test data * at this point! */ - return Task.CompletedTask; + using (_currentTenant.Change(context?.TenantId)) + { + return Task.CompletedTask; + } } } -} \ No newline at end of file +} From eec13fa333d6cfb71abd0aac7b8cfcf833b70e88 Mon Sep 17 00:00:00 2001 From: Mladen Macanovic Date: Mon, 12 Oct 2020 10:57:09 +0200 Subject: [PATCH 004/566] New extension method to reset an object properties --- .../System/AbpObjectExtensions.cs | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/framework/src/Volo.Abp.Core/System/AbpObjectExtensions.cs b/framework/src/Volo.Abp.Core/System/AbpObjectExtensions.cs index 958398e0c5..9542383983 100644 --- a/framework/src/Volo.Abp.Core/System/AbpObjectExtensions.cs +++ b/framework/src/Volo.Abp.Core/System/AbpObjectExtensions.cs @@ -2,6 +2,7 @@ using System.ComponentModel; using System.Globalization; using System.Linq; +using System.Reflection; namespace System { @@ -105,5 +106,36 @@ namespace System return obj; } + + /// + /// Resets all fields of a given object to their default values. + /// + /// Type of the object + /// An object + /// Alternative custom method to reset the values. + /// Returns the original object. + public static T ResetState(this T obj, Action customReset = null) + { + if (customReset != null) + { + customReset(obj); + } + else + { + var properties = typeof(T).GetProperties(); + + foreach (var property in properties) + { + if (!property.CanWrite) + { + continue; + } + + property.SetValue(obj, null); + } + } + + return obj; + } } } From ed9f3f5c0a0d15f328d01dc05d63103bf455948d Mon Sep 17 00:00:00 2001 From: Mladen Macanovic Date: Mon, 12 Oct 2020 11:28:04 +0200 Subject: [PATCH 005/566] Reset model state when AbpCrudPageBase is opened --- framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs b/framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs index 8723209c53..44fc2403f0 100644 --- a/framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs +++ b/framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs @@ -318,7 +318,8 @@ namespace Volo.Abp.BlazoriseUI { await CheckCreatePolicyAsync(); - NewEntity = new TCreateViewModel(); + NewEntity.ResetState(); + CreateModal.Show(); } From 56fce17d70733f23510b0435b2780272b5ab5141 Mon Sep 17 00:00:00 2001 From: Mladen Macanovic Date: Mon, 12 Oct 2020 11:28:10 +0200 Subject: [PATCH 006/566] Blazorise client side validation for RoleManagementBase --- .../Pages/Identity/RoleManagement.razor | 28 +++++++++++-------- .../Pages/Identity/RoleManagement.razor.cs | 15 ++++++++++ 2 files changed, 32 insertions(+), 11 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 781756dd71..a45aafbe59 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 @@ -78,26 +78,32 @@ { - + @L["NewRole"] - + + + + @L["DisplayName:RoleName"] + + + + + + + - @L["DisplayName:RoleName"] - - - - @L["DisplayName:IsDefault"] - @L["DisplayName:IsPublic"] + @L["DisplayName:IsDefault"] + @L["DisplayName:IsPublic"] - + - + @@ -107,7 +113,7 @@ { - + @L["Edit"] diff --git a/modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/RoleManagement.razor.cs b/modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/RoleManagement.razor.cs index bccf3ddbd8..591707355b 100644 --- a/modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/RoleManagement.razor.cs +++ b/modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/RoleManagement.razor.cs @@ -1,5 +1,6 @@ using System; using System.Threading.Tasks; +using Blazorise; using Microsoft.AspNetCore.Authorization; using Volo.Abp.Application.Dtos; using Volo.Abp.BlazoriseUI; @@ -17,6 +18,8 @@ namespace Volo.Abp.Identity.Blazor.Pages.Identity protected bool ShouldShowEntityActions { get; set; } + protected Validations ValidationsRef { get; set; } + public RoleManagementBase() { ObjectMapperContext = typeof(AbpIdentityBlazorModule); @@ -38,5 +41,17 @@ namespace Volo.Abp.Identity.Blazor.Pages.Identity HasDeletePermission || HasManagePermissionsPermission; } + + protected virtual Task OnCreateEntityClicked() + { + if ( ValidationsRef.ValidateAll() ) + { + CreateModal.Hide(); + + return CreateEntityAsync(); + } + + return Task.CompletedTask; + } } } From 1a44a268f8787649ae32561ad83b2238468f8aaa Mon Sep 17 00:00:00 2001 From: Mladen Macanovic Date: Wed, 14 Oct 2020 12:11:39 +0200 Subject: [PATCH 007/566] Role and User client side Blazorise validations --- .../Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs | 2 +- .../System/AbpObjectExtensions.cs | 28 ++- .../Pages/Identity/RoleManagement.razor | 49 ++-- .../Pages/Identity/RoleManagement.razor.cs | 38 ++- .../Pages/Identity/UserManagement.razor | 219 ++++++++++++------ .../Pages/Identity/UserManagement.razor.cs | 47 +++- 6 files changed, 267 insertions(+), 116 deletions(-) diff --git a/framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs b/framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs index 44fc2403f0..7616447552 100644 --- a/framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs +++ b/framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs @@ -335,7 +335,7 @@ namespace Volo.Abp.BlazoriseUI var entityDto = await AppService.GetAsync(id); EditingEntityId = id; - EditingEntity = MapToEditingEntity(entityDto); + EditingEntity.ApplyState(MapToEditingEntity(entityDto)); EditModal.Show(); } diff --git a/framework/src/Volo.Abp.Core/System/AbpObjectExtensions.cs b/framework/src/Volo.Abp.Core/System/AbpObjectExtensions.cs index 9542383983..a173c2a95d 100644 --- a/framework/src/Volo.Abp.Core/System/AbpObjectExtensions.cs +++ b/framework/src/Volo.Abp.Core/System/AbpObjectExtensions.cs @@ -110,7 +110,7 @@ namespace System /// /// Resets all fields of a given object to their default values. /// - /// Type of the object + /// Type of the object. /// An object /// Alternative custom method to reset the values. /// Returns the original object. @@ -137,5 +137,31 @@ namespace System return obj; } + + /// + /// Applies all fields of a given object from it's counterpart. + /// + /// Type of the object. + /// An object. + /// An object from which we copy the values. + /// Returns the original object. + public static T ApplyState(this T obj, T other) + { + // This code is not production ready and it should be removed once + // the proper validation in Blazorise is done! + var properties = typeof(T).GetProperties(); + + foreach (var property in properties) + { + if (!property.CanWrite) + { + continue; + } + + property.SetValue(obj, typeof(T).GetProperty(property.Name).GetValue(other)); + } + + return obj; + } } } 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 a45aafbe59..033a5293d8 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 @@ -1,5 +1,5 @@ @page "/identity/roles" -@attribute [Authorize(IdentityPermissions.Roles.Default)] +@attribute [Authorize( IdentityPermissions.Roles.Default )] @using Volo.Abp.Identity @using Microsoft.AspNetCore.Authorization @using Microsoft.Extensions.Localization @@ -7,14 +7,13 @@ @using Volo.Abp.PermissionManagement.Blazor.Components @inherits RoleManagementBase @inject IStringLocalizer L - @* ************************* PAGE HEADER ************************* *@

@L["Roles"]

- @if (HasCreatePermission) + @if ( HasCreatePermission ) { @@ -31,7 +30,7 @@ ShowPager="true" PageSize="PageSize"> - @if (ShouldShowEntityActions) + @if ( ShouldShowEntityActions ) { @@ -40,15 +39,15 @@ @L["Actions"] - @if (HasUpdatePermission) + @if ( HasUpdatePermission ) { @L["Edit"] } - @if (HasManagePermissionsPermission) + @if ( HasManagePermissionsPermission ) { @L["Permissions"] } - @if (HasDeletePermission) + @if ( HasDeletePermission ) { @L["Delete"] } @@ -60,11 +59,11 @@ @(context.As().Name) - @if (context.As().IsDefault) + @if ( context.As().IsDefault ) { @L["DisplayName:IsDefault"] } - @if (context.As().IsPublic) + @if ( context.As().IsPublic ) { @L["DisplayName:IsPublic"] } @@ -74,7 +73,7 @@ @* ************************* CREATE MODAL ************************* *@ -@if (HasCreatePermission) +@if ( HasCreatePermission ) { @@ -84,7 +83,7 @@
- + @L["DisplayName:RoleName"] @@ -103,13 +102,13 @@ - +
} @* ************************* EDIT MODAL ************************* *@ -@if (HasUpdatePermission) +@if ( HasUpdatePermission ) { @@ -119,17 +118,23 @@ - + + + + @L["DisplayName:RoleName"] + + + + + + + - @L["DisplayName:RoleName"] - - - - @L["DisplayName:IsDefault"] - @L["DisplayName:IsPublic"] + @L["DisplayName:IsDefault"] + @L["DisplayName:IsPublic"] - + @@ -139,4 +144,4 @@ } - + diff --git a/modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/RoleManagement.razor.cs b/modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/RoleManagement.razor.cs index 591707355b..1645f1f2a3 100644 --- a/modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/RoleManagement.razor.cs +++ b/modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/RoleManagement.razor.cs @@ -8,7 +8,7 @@ using Volo.Abp.PermissionManagement.Blazor.Components; namespace Volo.Abp.Identity.Blazor.Pages.Identity { - public abstract class RoleManagementBase : AbpCrudPageBase + public abstract class RoleManagementBase : AbpCrudPageBase { protected const string PermissionProviderName = "R"; @@ -18,7 +18,9 @@ namespace Volo.Abp.Identity.Blazor.Pages.Identity protected bool ShouldShowEntityActions { get; set; } - protected Validations ValidationsRef { get; set; } + protected Validations CreateValidationsRef { get; set; } + + protected Validations EditValidationsRef { get; set; } public RoleManagementBase() { @@ -42,13 +44,39 @@ namespace Volo.Abp.Identity.Blazor.Pages.Identity HasManagePermissionsPermission; } - protected virtual Task OnCreateEntityClicked() + protected override Task OpenCreateModalAsync() + { + CreateValidationsRef.ClearAll(); + + return base.OpenCreateModalAsync(); + } + + protected override Task OpenEditModalAsync(Guid id) + { + EditValidationsRef.ClearAll(); + + return base.OpenEditModalAsync(id); + } + + protected override Task CreateEntityAsync() { - if ( ValidationsRef.ValidateAll() ) + if (CreateValidationsRef.ValidateAll()) { CreateModal.Hide(); - return CreateEntityAsync(); + return base.CreateEntityAsync(); + } + + return Task.CompletedTask; + } + + protected override Task UpdateEntityAsync() + { + if (EditValidationsRef.ValidateAll()) + { + EditModal.Hide(); + + return base.UpdateEntityAsync(); } return Task.CompletedTask; 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 bfbd2150c6..e3a24323e8 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 @@ -1,19 +1,18 @@ @page "/identity/users" -@attribute [Authorize(IdentityPermissions.Users.Default)] +@attribute [Authorize( IdentityPermissions.Users.Default )] @using Microsoft.AspNetCore.Authorization @using Microsoft.Extensions.Localization @using Volo.Abp.Identity.Localization @using Volo.Abp.PermissionManagement.Blazor.Components @inherits UserManagementBase @inject IStringLocalizer L - @* ************************* PAGE HEADER ************************* *@

@L["Users"]

- @if (HasCreatePermission) + @if ( HasCreatePermission ) { @@ -30,7 +29,7 @@ ShowPager="true" PageSize="PageSize"> - @if (ShouldShowEntityActions) + @if ( ShouldShowEntityActions ) { @@ -39,17 +38,17 @@ @L["Actions"] - @if (HasUpdatePermission) + @if ( HasUpdatePermission ) { @L["Edit"] } - @if (HasManagePermissionsPermission) + @if ( HasManagePermissionsPermission ) { @L["Permissions"] } - @if (HasDeletePermission) + @if ( HasDeletePermission ) { - + @L["Delete"] } @@ -76,17 +75,17 @@ @* ************************* CREATE MODAL ************************* *@ -@if (HasCreatePermission) +@if ( HasCreatePermission ) { - + @L["NewUser"] - + - + @L["UserInformations"] @@ -94,71 +93,107 @@ + + + @L["DisplayName:UserName"] + + + + + + + + + + @L["DisplayName:Name"] + + + + + + + + + + @L["DisplayName:Surname"] + + + + + + + + + + @L["DisplayName:Password"] + + + + + + + + + + @L["DisplayName:Email"] + + + + + + + + + + @L["DisplayName:PhoneNumber"] + + + + + + + - @L["DisplayName:UserName"] - - - - @L["DisplayName:Name"] - - - - @L["DisplayName:Surname"] - - - - @L["DisplayName:Password"] - - - - @L["DisplayName:Email"] - - - - @L["DisplayName:PhoneNumber"] - - - - @L["DisplayName:LockoutEnabled"] + @L["DisplayName:LockoutEnabled"] - @if (NewUserRoles != null) + @if ( NewUserRoles != null ) { - @foreach (var role in NewUserRoles) + @foreach ( var role in NewUserRoles ) { - - @role.Name + + @role.Name } } - + - + } @* ************************* EDIT MODAL ************************* *@ -@if (HasUpdatePermission) +@if ( HasUpdatePermission ) { - + @L["Edit"] - + - - + + @@ -168,55 +203,89 @@ - @L["DisplayName:UserName"] - - - - @L["DisplayName:Name"] - + + @L["DisplayName:UserName"] + + + + + + + + + @L["DisplayName:Name"] + + + + + + + @L["DisplayName:Surname"] - - - - @L["DisplayName:Password"] - - - - @L["DisplayName:Email"] - - - - @L["DisplayName:PhoneNumber"] - + + + + + + + + @L["DisplayName:Password"] + + + + + + + + + + @L["DisplayName:Email"] + + + + + + + + + + @L["DisplayName:PhoneNumber"] + + + + + + + - @L["DisplayName:LockoutEnabled"] + @L["DisplayName:LockoutEnabled"] - @if (EditUserRoles != null) + @if ( EditUserRoles != null ) { - @foreach (var role in EditUserRoles) + @foreach ( var role in EditUserRoles ) { - - @role.Name + + @role.Name } } - + - + } - \ No newline at end of file + \ No newline at end of file diff --git a/modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/UserManagement.razor.cs b/modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/UserManagement.razor.cs index a488cbd358..dc51f59dc1 100644 --- a/modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/UserManagement.razor.cs +++ b/modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/UserManagement.razor.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Blazorise; using Microsoft.AspNetCore.Authorization; using Volo.Abp.BlazoriseUI; using Volo.Abp.PermissionManagement.Blazor.Components; @@ -29,6 +30,10 @@ namespace Volo.Abp.Identity.Blazor.Pages.Identity protected string EditModalSelectedTab = DefaultSelectedTab; + protected Validations CreateValidationsRef { get; set; } + + protected Validations EditValidationsRef { get; set; } + public UserManagementBase() { ObjectMapperContext = typeof(AbpIdentityBlazorModule); @@ -60,44 +65,62 @@ namespace Volo.Abp.Identity.Blazor.Pages.Identity protected override Task OpenCreateModalAsync() { + CreateValidationsRef.ClearAll(); + CreateModalSelectedTab = DefaultSelectedTab; NewUserRoles = Roles.Select(x => new AssignedRoleViewModel - { - Name = x.Name, - IsAssigned = x.IsDefault - }).ToArray(); + { + Name = x.Name, + IsAssigned = x.IsDefault + }).ToArray(); return base.OpenCreateModalAsync(); } protected override Task CreateEntityAsync() { - NewEntity.RoleNames = NewUserRoles.Where(x => x.IsAssigned).Select(x => x.Name).ToArray(); + if (CreateValidationsRef.ValidateAll()) + { + CreateModal.Hide(); + + NewEntity.RoleNames = NewUserRoles.Where(x => x.IsAssigned).Select(x => x.Name).ToArray(); - return base.CreateEntityAsync(); + return base.CreateEntityAsync(); + } + + return Task.CompletedTask; } protected override async Task OpenEditModalAsync(Guid id) { + EditValidationsRef.ClearAll(); + EditModalSelectedTab = DefaultSelectedTab; var userRoleNames = (await AppService.GetRolesAsync(id)).Items.Select(r => r.Name).ToList(); EditUserRoles = Roles.Select(x => new AssignedRoleViewModel - { - Name = x.Name, - IsAssigned = userRoleNames.Contains(x.Name) - }).ToArray(); + { + Name = x.Name, + IsAssigned = userRoleNames.Contains(x.Name) + }).ToArray(); await base.OpenEditModalAsync(id); } protected override Task UpdateEntityAsync() { - EditingEntity.RoleNames = EditUserRoles.Where(x => x.IsAssigned).Select(x => x.Name).ToArray(); + if (EditValidationsRef.ValidateAll()) + { + EditModal.Hide(); + + EditingEntity.RoleNames = EditUserRoles.Where(x => x.IsAssigned).Select(x => x.Name).ToArray(); + + return base.UpdateEntityAsync(); + } - return base.UpdateEntityAsync(); + return Task.CompletedTask; } } From fe72aba723211071f90c17a27369da0e4d6f1822 Mon Sep 17 00:00:00 2001 From: Kishore Sahasranaman Date: Fri, 16 Oct 2020 15:59:38 +0530 Subject: [PATCH 008/566] Added Service Proxy Generation To generate proxies for updated C# classes. --- docs/en/Tutorials/Part-10.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/docs/en/Tutorials/Part-10.md b/docs/en/Tutorials/Part-10.md index 2e0b1c4939..70afab36b1 100644 --- a/docs/en/Tutorials/Part-10.md +++ b/docs/en/Tutorials/Part-10.md @@ -911,6 +911,17 @@ You can run the application and try to create a new book or update an existing b {{else if UI=="NG"}} +### Service Proxy Generation + +[ABP CLI](../CLI.md) provides `generate-proxy` command that generates client proxies for your HTTP APIs to make easy to consume your HTTP APIs from the client side. Before running `generate-proxy` command, your host must be up and running. + +Run the following command in the `angular` folder: + +```bash +abp generate-proxy +``` +This command will update the service proxy files under the `/src/app/proxy/` folder. + ### The Book List Book list page change is trivial. Open the `/src/app/book/book.component.html` and add the following column definition between the `Name` and `Type` columns: @@ -1164,4 +1175,4 @@ Add the following `Field` definition into the `ModalBody` of the *Edit* modal, a That's all. We are reusing the `authorList` defined for the *Create* modal. -{{end}} \ No newline at end of file +{{end}} From d3c4029e0f83f079e1ccc61467440df13fe95933 Mon Sep 17 00:00:00 2001 From: PMExtra Date: Tue, 20 Oct 2020 15:35:21 +0800 Subject: [PATCH 009/566] checkPassword -> check-password. --- .../Areas/Account/Controllers/AccountController.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/modules/account/src/Volo.Abp.Account.Web/Areas/Account/Controllers/AccountController.cs b/modules/account/src/Volo.Abp.Account.Web/Areas/Account/Controllers/AccountController.cs index 575853f410..5e3ffad3fc 100644 --- a/modules/account/src/Volo.Abp.Account.Web/Areas/Account/Controllers/AccountController.cs +++ b/modules/account/src/Volo.Abp.Account.Web/Areas/Account/Controllers/AccountController.cs @@ -83,6 +83,14 @@ namespace Volo.Abp.Account.Web.Areas.Account.Controllers [HttpPost] [Route("checkPassword")] + [ApiExplorerSettings(IgnoreApi = true)] + public virtual Task CheckPasswordCompatible(UserLoginInfo login) + { + return CheckPassword(login); + } + + [HttpPost] + [Route("check-password")] public virtual async Task CheckPassword(UserLoginInfo login) { ValidateLoginInfo(login); From f4e568befe16efbf99123e558d24e0c11638a0e8 Mon Sep 17 00:00:00 2001 From: Mladen Macanovic Date: Wed, 21 Oct 2020 12:11:11 +0200 Subject: [PATCH 010/566] WIP message arguments localization --- ...dentityBlazorMessageLocalizerExtensions.cs | 15 ++++++ .../Pages/Identity/RoleManagement.razor | 5 +- .../Identity/AbpIdentityDomainSharedModule.cs | 5 +- .../Identity/AbpIdentityMessageLocalizer.cs | 46 +++++++++++++++++++ 4 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 modules/identity/src/Volo.Abp.Identity.Blazor/AbpIdentityBlazorMessageLocalizerExtensions.cs create mode 100644 modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/AbpIdentityMessageLocalizer.cs diff --git a/modules/identity/src/Volo.Abp.Identity.Blazor/AbpIdentityBlazorMessageLocalizerExtensions.cs b/modules/identity/src/Volo.Abp.Identity.Blazor/AbpIdentityBlazorMessageLocalizerExtensions.cs new file mode 100644 index 0000000000..480b17ac14 --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.Blazor/AbpIdentityBlazorMessageLocalizerExtensions.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using System.Linq; +using Blazorise; + +namespace Volo.Abp.Identity.Blazor +{ + public static class AbpIdentityBlazorMessageLocalizerExtensions + { + public static IEnumerable Localize(this AbpIdentityMessageLocalizer abpIdentityMessageLocalizer, + ValidationMessageLocalizerEventArgs eventArgs) + { + return abpIdentityMessageLocalizer.Localize(eventArgs.Messages?.Select(m => (m.Message, m.MessageArguments)))?.ToArray(); + } + } +} 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 033a5293d8..e850e5c87a 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 @@ -7,6 +7,7 @@ @using Volo.Abp.PermissionManagement.Blazor.Components @inherits RoleManagementBase @inject IStringLocalizer L +@inject AbpIdentityMessageLocalizer ML @* ************************* PAGE HEADER ************************* *@ @@ -84,7 +85,7 @@ - + @L["DisplayName:RoleName"] @@ -120,7 +121,7 @@ - + @L["DisplayName:RoleName"] diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/AbpIdentityDomainSharedModule.cs b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/AbpIdentityDomainSharedModule.cs index e14ce5e3f4..5a63d52b24 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/AbpIdentityDomainSharedModule.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/AbpIdentityDomainSharedModule.cs @@ -1,4 +1,5 @@ -using Volo.Abp.Features; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Features; using Volo.Abp.Identity.Localization; using Volo.Abp.Localization; using Volo.Abp.Localization.ExceptionHandling; @@ -37,6 +38,8 @@ namespace Volo.Abp.Identity { options.MapCodeNamespace("Volo.Abp.Identity", typeof(IdentityResource)); }); + + context.Services.AddSingleton(typeof(AbpIdentityMessageLocalizer<>), typeof(AbpIdentityMessageLocalizer<>)); } } } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/AbpIdentityMessageLocalizer.cs b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/AbpIdentityMessageLocalizer.cs new file mode 100644 index 0000000000..ff2c50ee83 --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/AbpIdentityMessageLocalizer.cs @@ -0,0 +1,46 @@ +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using Microsoft.Extensions.Localization; + +namespace Volo.Abp.Identity +{ + public class AbpIdentityMessageLocalizer + { + private readonly IStringLocalizer stringLocalizer; + + public AbpIdentityMessageLocalizer(IStringLocalizer stringLocalizer) + { + this.stringLocalizer = stringLocalizer; + } + + public virtual string Localize(string format, params string[] arguments) + { + try + { + return arguments?.Length > 0 + ? string.Format(stringLocalizer[format], LocalizeArguments(arguments)?.ToArray()) + : stringLocalizer[format]; + } + catch + { + return stringLocalizer[format]; + } + } + + public virtual IEnumerable Localize(IEnumerable<(string format, string[] arguments)> messages) + { + return messages?.Select(m => Localize(m.format, m.arguments)); + } + + protected virtual IEnumerable LocalizeArguments(IEnumerable arguments) + { + foreach (var argument in arguments) + { + yield return stringLocalizer[$"DisplayName:{argument}"] + ?? stringLocalizer[argument] + ?? argument; + } + } + } +} From b3ba2e3186e078607ff0f6489022eb20c45cfaa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0lkay=20=C4=B0lknur?= Date: Wed, 21 Oct 2020 17:33:54 +0300 Subject: [PATCH 011/566] entity actions component implementation. --- .../Components/EntityAction.razor | 21 ++++++++++ .../Components/EntityAction.razor.cs | 33 ++++++++++++++++ .../Components/EntityActions.razor | 30 ++++++++++++++ .../Components/EntityActions.razor.cs | 39 +++++++++++++++++++ 4 files changed, 123 insertions(+) create mode 100644 framework/src/Volo.Abp.BlazoriseUI/Components/EntityAction.razor create mode 100644 framework/src/Volo.Abp.BlazoriseUI/Components/EntityAction.razor.cs create mode 100644 framework/src/Volo.Abp.BlazoriseUI/Components/EntityActions.razor create mode 100644 framework/src/Volo.Abp.BlazoriseUI/Components/EntityActions.razor.cs diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/EntityAction.razor b/framework/src/Volo.Abp.BlazoriseUI/Components/EntityAction.razor new file mode 100644 index 0000000000..c36620f195 --- /dev/null +++ b/framework/src/Volo.Abp.BlazoriseUI/Components/EntityAction.razor @@ -0,0 +1,21 @@ +@typeparam TItem +@using Blazorise + +@if (ParentActions.Type == ActionType.Dropdown) +{ + if (IsVisible && Primary == false) + { + @Text + } +} +else +{ + if (IsVisible) + { + + @Text + + } +} diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/EntityAction.razor.cs b/framework/src/Volo.Abp.BlazoriseUI/Components/EntityAction.razor.cs new file mode 100644 index 0000000000..8dc4dcb5a0 --- /dev/null +++ b/framework/src/Volo.Abp.BlazoriseUI/Components/EntityAction.razor.cs @@ -0,0 +1,33 @@ +using System.Threading.Tasks; +using Microsoft.AspNetCore.Components; + +namespace Volo.Abp.BlazoriseUI.Components +{ + public partial class EntityAction : ComponentBase + { + [Parameter] + public bool IsVisible { get; set; } + [Parameter] + public string Text { get; set; } + + [Parameter] + public bool Primary { get; set; } + + [Parameter] + public EventCallback Clicked { get; set; } + + [CascadingParameter] + public EntityActions ParentActions { get; set; } + + protected override void OnInitialized() + { + base.OnInitialized(); + ParentActions.AddAction(this); + } + + protected virtual async Task ActionClickedAsync() + { + await Clicked.InvokeAsync(ParentActions.Entity); + } + } +} diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/EntityActions.razor b/framework/src/Volo.Abp.BlazoriseUI/Components/EntityActions.razor new file mode 100644 index 0000000000..b5afcdbadf --- /dev/null +++ b/framework/src/Volo.Abp.BlazoriseUI/Components/EntityActions.razor @@ -0,0 +1,30 @@ +@typeparam TItem + + @if (Type == ActionType.Dropdown) + { + + @if (HasPrimaryAction) + { + + @PrimaryAction.Text + + + } + else + { + + @ToggleText + + } + + @ChildContent + + + } + else + { + @ChildContent + } + \ No newline at end of file diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/EntityActions.razor.cs b/framework/src/Volo.Abp.BlazoriseUI/Components/EntityActions.razor.cs new file mode 100644 index 0000000000..d24c7125a7 --- /dev/null +++ b/framework/src/Volo.Abp.BlazoriseUI/Components/EntityActions.razor.cs @@ -0,0 +1,39 @@ +using System.Collections.Generic; +using System.Linq; +using Blazorise; +using Microsoft.AspNetCore.Components; + +namespace Volo.Abp.BlazoriseUI.Components +{ + public partial class EntityActions : ComponentBase + { + protected List> Actions = new List>(); + protected bool HasPrimaryAction => Actions.Any(t => t.Primary); + protected EntityAction PrimaryAction => Actions.FirstOrDefault(t => t.Primary); + protected internal ActionType Type => Actions.Count(t => t.IsVisible) > 1 ? ActionType.Dropdown : ActionType.Button; + + [Parameter] + public Color ToggleColor { get; set; } + + [Parameter] + public string ToggleText { get; set; } + + [Parameter] + public TItem Entity { get; set; } + + [Parameter] + public RenderFragment ChildContent { get; set; } + + internal void AddAction(EntityAction action) + { + Actions.Add(action); + StateHasChanged(); + } + } + + public enum ActionType + { + Dropdown, + Button + } +} From eb2be1d672335f188ffac94f2a715c2588cddc49 Mon Sep 17 00:00:00 2001 From: Mladen Macanovic Date: Thu, 22 Oct 2020 11:25:57 +0200 Subject: [PATCH 012/566] Optimized usage of Localize method --- .../Pages/Identity/RoleManagement.razor | 4 +- .../Pages/Identity/UserManagement.razor | 47 ++++++++++--------- 2 files changed, 27 insertions(+), 24 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 e850e5c87a..daba629c3e 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 @@ -85,7 +85,7 @@ - + @L["DisplayName:RoleName"] @@ -121,7 +121,7 @@ - + @L["DisplayName:RoleName"] 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 e3a24323e8..f0fe98c61c 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 @@ -6,6 +6,7 @@ @using Volo.Abp.PermissionManagement.Blazor.Components @inherits UserManagementBase @inject IStringLocalizer L +@inject AbpIdentityMessageLocalizer ML @* ************************* PAGE HEADER ************************* *@ @@ -79,7 +80,7 @@ { - + @L["NewUser"] @@ -93,7 +94,7 @@ - + @L["DisplayName:UserName"] @@ -103,7 +104,7 @@ - + @L["DisplayName:Name"] @@ -113,7 +114,7 @@ - + @L["DisplayName:Surname"] @@ -133,7 +134,7 @@ - + @L["DisplayName:Email"] @@ -143,7 +144,7 @@ - + @L["DisplayName:PhoneNumber"] @@ -186,7 +187,7 @@ { - + @L["Edit"] @@ -202,17 +203,17 @@ - - + + @L["DisplayName:UserName"] - - - + + + @L["DisplayName:Name"] @@ -222,14 +223,16 @@ - - @L["DisplayName:Surname"] - - - - - - + + + @L["DisplayName:Surname"] + + + + + + + @L["DisplayName:Password"] @@ -240,7 +243,7 @@ - + @L["DisplayName:Email"] @@ -250,7 +253,7 @@ - + @L["DisplayName:PhoneNumber"] From f24a7d18e18a35cc7ccf1a7e7ebae4d6b0700c5f Mon Sep 17 00:00:00 2001 From: Mladen Macanovic Date: Thu, 22 Oct 2020 11:26:33 +0200 Subject: [PATCH 013/566] Fixed blazor app element for .Net 5 --- .../MyProjectNameBlazorModule.cs | 2 +- .../src/MyCompanyName.MyProjectName.Blazor/wwwroot/index.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyProjectNameBlazorModule.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyProjectNameBlazorModule.cs index 7554ae8aca..279fe57114 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyProjectNameBlazorModule.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyProjectNameBlazorModule.cs @@ -77,7 +77,7 @@ namespace MyCompanyName.MyProjectName.Blazor private static void ConfigureUI(WebAssemblyHostBuilder builder) { - builder.RootComponents.Add("app"); + builder.RootComponents.Add("#app"); } private static void ConfigureHttpClient(ServiceConfigurationContext context, IWebAssemblyHostEnvironment environment) diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/wwwroot/index.html b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/wwwroot/index.html index 4566bec3c1..576e00f716 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/wwwroot/index.html +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/wwwroot/index.html @@ -17,7 +17,7 @@ - Loading... +
Loading...
From 38495de1812f66d0151d12f20e97e51961a5ddca Mon Sep 17 00:00:00 2001 From: Mladen Macanovic Date: Thu, 22 Oct 2020 11:27:55 +0200 Subject: [PATCH 014/566] Added editorconfig for identity/module solution --- modules/identity/.editorconfig | 131 +++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 modules/identity/.editorconfig diff --git a/modules/identity/.editorconfig b/modules/identity/.editorconfig new file mode 100644 index 0000000000..9f20b90112 --- /dev/null +++ b/modules/identity/.editorconfig @@ -0,0 +1,131 @@ +# Rules in this file were initially inferred by Visual Studio IntelliCode from the D:\Projects\Volosoft\abp\framework codebase based on best match to current usage at 2.10.2020. +# You can modify the rules from these initially generated values to suit your own policies +# You can learn more about editorconfig here: https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-code-style-settings-reference +[*.cs] + + +#Core editorconfig formatting - indentation + +#use soft tabs (spaces) for indentation +indent_style = space + +#Formatting - indentation options + +#indent switch case contents. +csharp_indent_case_contents = true +#indent switch labels +csharp_indent_switch_labels = true + +#Formatting - new line options + +#place catch statements on a new line +csharp_new_line_before_catch = true +#place else statements on a new line +csharp_new_line_before_else = true +#require members of object intializers to be on separate lines +csharp_new_line_before_members_in_object_initializers = true +#require braces to be on a new line for accessors, methods, lambdas, object_collection_array_initializers, control_blocks, types, and properties (also known as "Allman" style) +csharp_new_line_before_open_brace = accessors, methods, lambdas, object_collection_array_initializers, control_blocks, types, properties + +#Formatting - organize using options + +#sort System.* using directives alphabetically, and place them before other usings +dotnet_sort_system_directives_first = true + +#Formatting - spacing options + +csharp_space_after_cast = false +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_after_comma = true +csharp_space_after_dot = false +csharp_space_after_keywords_in_control_flow_statements = true +csharp_space_after_semicolon_in_for_statement = true +csharp_space_around_binary_operators = before_and_after +csharp_space_around_declaration_statements = false +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_before_comma = false +csharp_space_before_dot = false +csharp_space_before_open_square_brackets = false +csharp_space_before_semicolon_in_for_statement = false +csharp_space_between_empty_square_brackets = false +csharp_space_between_method_call_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_call_parameter_list_parentheses = false +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +csharp_space_between_method_declaration_name_and_open_parenthesis = false +csharp_space_between_method_declaration_parameter_list_parentheses = false +csharp_space_between_parentheses = false +csharp_space_between_square_brackets = false + +#Formatting - wrapping options + +#leave code block on single line +csharp_preserve_single_line_blocks = true + +#Style - Code block preferences + +#prefer curly braces even for one line of code +csharp_prefer_braces = true:suggestion + +#Style - expression bodied member options + +#prefer block bodies for constructors +csharp_style_expression_bodied_constructors = false:suggestion +#prefer block bodies for methods +csharp_style_expression_bodied_methods = false:suggestion +#prefer expression-bodied members for properties +csharp_style_expression_bodied_properties = true:suggestion + +#Style - expression level options + +#prefer out variables to be declared inline in the argument list of a method call when possible +csharp_style_inlined_variable_declaration = true:suggestion +#prefer the language keyword for member access expressions, instead of the type name, for types that have a keyword to represent them +dotnet_style_predefined_type_for_member_access = true:suggestion + +#Style - Expression-level preferences + +#prefer default over default(T) +csharp_prefer_simple_default_expression = true:suggestion +#prefer objects to be initialized using object initializers when possible +dotnet_style_object_initializer = true:suggestion +#prefer inferred tuple element names +dotnet_style_prefer_inferred_tuple_names = true:suggestion + +#Style - implicit and explicit types + +#prefer var over explicit type in all cases, unless overridden by another code style rule +csharp_style_var_elsewhere = true:suggestion +#prefer var is used to declare variables with built-in system types such as int +csharp_style_var_for_built_in_types = true:suggestion +#prefer var when the type is already mentioned on the right-hand side of a declaration expression +csharp_style_var_when_type_is_apparent = true:suggestion + +#Style - language keyword and framework type options + +#prefer the language keyword for local variables, method parameters, and class members, instead of the type name, for types that have a keyword to represent them +dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion + +#Style - modifier options + +#prefer accessibility modifiers to be declared except for public interface members. This will currently not differ from always and will act as future proofing for if C# adds default interface methods. +dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion + +#Style - Modifier preferences + +#when this rule is set to a list of modifiers, prefer the specified ordering. +csharp_preferred_modifier_order = public,protected,private,virtual,async,static,override,readonly,abstract:suggestion + +#Style - Pattern matching + +#prefer pattern matching instead of is expression with type casts +csharp_style_pattern_matching_over_as_with_null_check = true:suggestion + +#Style - qualification options + +#prefer fields not to be prefaced with this. or Me. in Visual Basic +dotnet_style_qualification_for_field = false:suggestion +#prefer methods not to be prefaced with this. or Me. in Visual Basic +dotnet_style_qualification_for_method = false:suggestion +#prefer properties not to be prefaced with this. or Me. in Visual Basic +dotnet_style_qualification_for_property = false:suggestion From d6fce9d9d65e474d0412174cabd113667f5fbdb4 Mon Sep 17 00:00:00 2001 From: Mladen Macanovic Date: Thu, 22 Oct 2020 11:36:53 +0200 Subject: [PATCH 015/566] Update Blazorise 0.9.2-preview12 --- .../src/Volo.Abp.BlazoriseUI/Volo.Abp.BlazoriseUI.csproj | 4 ++-- .../MyCompanyName.MyProjectName.Blazor.csproj | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/framework/src/Volo.Abp.BlazoriseUI/Volo.Abp.BlazoriseUI.csproj b/framework/src/Volo.Abp.BlazoriseUI/Volo.Abp.BlazoriseUI.csproj index e696a2f915..2e67a2b182 100644 --- a/framework/src/Volo.Abp.BlazoriseUI/Volo.Abp.BlazoriseUI.csproj +++ b/framework/src/Volo.Abp.BlazoriseUI/Volo.Abp.BlazoriseUI.csproj @@ -12,8 +12,8 @@ - - + + diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyCompanyName.MyProjectName.Blazor.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyCompanyName.MyProjectName.Blazor.csproj index d1bec5d5d3..31f9899115 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyCompanyName.MyProjectName.Blazor.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyCompanyName.MyProjectName.Blazor.csproj @@ -6,8 +6,8 @@ - - + + From 1d84ce4f8af7b13c9bf80005bbacf3a1adb94de4 Mon Sep 17 00:00:00 2001 From: Mladen Macanovic Date: Thu, 22 Oct 2020 11:43:21 +0200 Subject: [PATCH 016/566] Fix Password localization --- .../Pages/Identity/UserManagement.razor | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 f0fe98c61c..03a8b68fa7 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 @@ -124,7 +124,7 @@
- + @L["DisplayName:Password"] @@ -233,7 +233,7 @@ - + @L["DisplayName:Password"] From 167aae0ec520d2e1bae76fd025f4476ab9e8415e Mon Sep 17 00:00:00 2001 From: Mladen Macanovic Date: Fri, 23 Oct 2020 10:05:34 +0200 Subject: [PATCH 017/566] Fixed formating --- .../Pages/Identity/RoleManagement.razor | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 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 daba629c3e..4246d2dd76 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 @@ -11,10 +11,10 @@ @* ************************* PAGE HEADER ************************* *@ -

@L["Roles"]

+ @L["Roles"]
- @if ( HasCreatePermission ) + @if (HasCreatePermission) { @@ -31,7 +31,7 @@ ShowPager="true" PageSize="PageSize"> - @if ( ShouldShowEntityActions ) + @if (ShouldShowEntityActions) { @@ -40,15 +40,15 @@ @L["Actions"] - @if ( HasUpdatePermission ) + @if (HasUpdatePermission) { @L["Edit"] } - @if ( HasManagePermissionsPermission ) + @if (HasManagePermissionsPermission) { @L["Permissions"] } - @if ( HasDeletePermission ) + @if (HasDeletePermission) { @L["Delete"] } @@ -60,11 +60,11 @@ @(context.As().Name) - @if ( context.As().IsDefault ) + @if (context.As().IsDefault) { @L["DisplayName:IsDefault"] } - @if ( context.As().IsPublic ) + @if (context.As().IsPublic) { @L["DisplayName:IsPublic"] } @@ -74,7 +74,7 @@ @* ************************* CREATE MODAL ************************* *@ -@if ( HasCreatePermission ) +@if (HasCreatePermission) { @@ -109,7 +109,7 @@ } @* ************************* EDIT MODAL ************************* *@ -@if ( HasUpdatePermission ) +@if (HasUpdatePermission) { From 157d7b1d6e732bd4f6beb2b8ba2485c3e85b7f37 Mon Sep 17 00:00:00 2001 From: Mladen Macanovic Date: Fri, 23 Oct 2020 11:06:07 +0200 Subject: [PATCH 018/566] Use ObjectMapper for NewEntity and EditingEntity --- .../src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs b/framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs index 7616447552..c6491f1ec1 100644 --- a/framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs +++ b/framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs @@ -318,7 +318,11 @@ namespace Volo.Abp.BlazoriseUI { await CheckCreatePolicyAsync(); - NewEntity.ResetState(); + ObjectMapper.Map(new TCreateViewModel(), NewEntity); + + // Mapper will not notify Blazor that binded values are changed + // so we need to notify it manually by calling StateHasChanged + await InvokeAsync(() => StateHasChanged()); CreateModal.Show(); } @@ -334,8 +338,12 @@ namespace Volo.Abp.BlazoriseUI await CheckUpdatePolicyAsync(); var entityDto = await AppService.GetAsync(id); + EditingEntityId = id; - EditingEntity.ApplyState(MapToEditingEntity(entityDto)); + ObjectMapper.Map(entityDto, EditingEntity); + + await InvokeAsync(() => StateHasChanged()); + EditModal.Show(); } @@ -379,8 +387,6 @@ namespace Volo.Abp.BlazoriseUI CreateModal.Hide(); } - - protected virtual async Task UpdateEntityAsync() { await CheckUpdatePolicyAsync(); From b5986115a2ac737ce7bcc90ef9839d5585a639d2 Mon Sep 17 00:00:00 2001 From: Mladen Macanovic Date: Fri, 23 Oct 2020 11:13:20 +0200 Subject: [PATCH 019/566] Remove explicit Auto validation mode --- .../Pages/Identity/RoleManagement.razor | 22 +++++++++---------- .../Pages/Identity/UserManagement.razor | 4 ++-- 2 files changed, 13 insertions(+), 13 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 4246d2dd76..ef59e969fd 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 @@ -14,7 +14,7 @@ @L["Roles"] - @if (HasCreatePermission) + @if ( HasCreatePermission ) { @@ -31,7 +31,7 @@ ShowPager="true" PageSize="PageSize"> - @if (ShouldShowEntityActions) + @if ( ShouldShowEntityActions ) { @@ -40,15 +40,15 @@ @L["Actions"] - @if (HasUpdatePermission) + @if ( HasUpdatePermission ) { @L["Edit"] } - @if (HasManagePermissionsPermission) + @if ( HasManagePermissionsPermission ) { @L["Permissions"] } - @if (HasDeletePermission) + @if ( HasDeletePermission ) { @L["Delete"] } @@ -60,11 +60,11 @@ @(context.As().Name) - @if (context.As().IsDefault) + @if ( context.As().IsDefault ) { @L["DisplayName:IsDefault"] } - @if (context.As().IsPublic) + @if ( context.As().IsPublic ) { @L["DisplayName:IsPublic"] } @@ -74,7 +74,7 @@ @* ************************* CREATE MODAL ************************* *@ -@if (HasCreatePermission) +@if ( HasCreatePermission ) { @@ -84,7 +84,7 @@ - + @L["DisplayName:RoleName"] @@ -109,7 +109,7 @@ } @* ************************* EDIT MODAL ************************* *@ -@if (HasUpdatePermission) +@if ( HasUpdatePermission ) { @@ -119,7 +119,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 03a8b68fa7..0ed1fd3d5a 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 @@ -86,7 +86,7 @@ - + @L["UserInformations"] @@ -193,7 +193,7 @@ - + From e6b9253614c883ae19be2039804d5622e372214b Mon Sep 17 00:00:00 2001 From: Mladen Macanovic Date: Fri, 23 Oct 2020 11:25:09 +0200 Subject: [PATCH 020/566] Removed AbpIdentityMessageLocalizer --- ...dentityBlazorMessageLocalizerExtensions.cs | 35 ++++++++++++-- .../Pages/Identity/RoleManagement.razor | 5 +- .../Pages/Identity/UserManagement.razor | 25 +++++----- .../Identity/AbpIdentityDomainSharedModule.cs | 2 - .../Identity/AbpIdentityMessageLocalizer.cs | 46 ------------------- 5 files changed, 46 insertions(+), 67 deletions(-) delete mode 100644 modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/AbpIdentityMessageLocalizer.cs diff --git a/modules/identity/src/Volo.Abp.Identity.Blazor/AbpIdentityBlazorMessageLocalizerExtensions.cs b/modules/identity/src/Volo.Abp.Identity.Blazor/AbpIdentityBlazorMessageLocalizerExtensions.cs index 480b17ac14..bb5214ac63 100644 --- a/modules/identity/src/Volo.Abp.Identity.Blazor/AbpIdentityBlazorMessageLocalizerExtensions.cs +++ b/modules/identity/src/Volo.Abp.Identity.Blazor/AbpIdentityBlazorMessageLocalizerExtensions.cs @@ -1,15 +1,44 @@ using System.Collections.Generic; using System.Linq; using Blazorise; +using Microsoft.Extensions.Localization; namespace Volo.Abp.Identity.Blazor { public static class AbpIdentityBlazorMessageLocalizerExtensions { - public static IEnumerable Localize(this AbpIdentityMessageLocalizer abpIdentityMessageLocalizer, - ValidationMessageLocalizerEventArgs eventArgs) + public static IEnumerable Localize(this IStringLocalizer stringLocalizer, ValidationMessageLocalizerEventArgs eventArgs) { - return abpIdentityMessageLocalizer.Localize(eventArgs.Messages?.Select(m => (m.Message, m.MessageArguments)))?.ToArray(); + return LocalizeMessages(stringLocalizer, eventArgs.Messages?.Select(m => (m.Message, m.MessageArguments)))?.ToArray(); + } + + private static IEnumerable LocalizeMessages(IStringLocalizer stringLocalizer, IEnumerable<(string format, string[] arguments)> messages) + { + return messages?.Select(m => LocalizeMessage(stringLocalizer, m.format, m.arguments)); + } + + private static string LocalizeMessage(IStringLocalizer stringLocalizer, string format, params string[] arguments) + { + try + { + return arguments?.Length > 0 + ? string.Format(stringLocalizer[format], LocalizeMessageArguments(stringLocalizer, arguments)?.ToArray()) + : stringLocalizer[format]; + } + catch + { + return stringLocalizer[format]; + } + } + + private static IEnumerable LocalizeMessageArguments(IStringLocalizer stringLocalizer, IEnumerable arguments) + { + foreach (var argument in arguments) + { + yield return stringLocalizer[$"DisplayName:{argument}"] + ?? stringLocalizer[argument] + ?? argument; + } } } } 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 ef59e969fd..ac40aca83d 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 @@ -7,7 +7,6 @@ @using Volo.Abp.PermissionManagement.Blazor.Components @inherits RoleManagementBase @inject IStringLocalizer L -@inject AbpIdentityMessageLocalizer ML @* ************************* PAGE HEADER ************************* *@ @@ -85,7 +84,7 @@ - + @L["DisplayName:RoleName"] @@ -121,7 +120,7 @@ - + @L["DisplayName:RoleName"] 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 0ed1fd3d5a..6f33181f8a 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 @@ -6,7 +6,6 @@ @using Volo.Abp.PermissionManagement.Blazor.Components @inherits UserManagementBase @inject IStringLocalizer L -@inject AbpIdentityMessageLocalizer ML @* ************************* PAGE HEADER ************************* *@ @@ -94,7 +93,7 @@ - + @L["DisplayName:UserName"] @@ -104,7 +103,7 @@ - + @L["DisplayName:Name"] @@ -114,7 +113,7 @@ - + @L["DisplayName:Surname"] @@ -124,7 +123,7 @@ - + @L["DisplayName:Password"] @@ -134,7 +133,7 @@ - + @L["DisplayName:Email"] @@ -144,7 +143,7 @@ - + @L["DisplayName:PhoneNumber"] @@ -203,7 +202,7 @@ - + @L["DisplayName:UserName"] @@ -213,7 +212,7 @@ - + @L["DisplayName:Name"] @@ -223,7 +222,7 @@ - + @L["DisplayName:Surname"] @@ -233,7 +232,7 @@ - + @L["DisplayName:Password"] @@ -243,7 +242,7 @@ - + @L["DisplayName:Email"] @@ -253,7 +252,7 @@ - + @L["DisplayName:PhoneNumber"] diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/AbpIdentityDomainSharedModule.cs b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/AbpIdentityDomainSharedModule.cs index 5a63d52b24..80d039b7d7 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/AbpIdentityDomainSharedModule.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/AbpIdentityDomainSharedModule.cs @@ -38,8 +38,6 @@ namespace Volo.Abp.Identity { options.MapCodeNamespace("Volo.Abp.Identity", typeof(IdentityResource)); }); - - context.Services.AddSingleton(typeof(AbpIdentityMessageLocalizer<>), typeof(AbpIdentityMessageLocalizer<>)); } } } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/AbpIdentityMessageLocalizer.cs b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/AbpIdentityMessageLocalizer.cs deleted file mode 100644 index ff2c50ee83..0000000000 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/AbpIdentityMessageLocalizer.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using Microsoft.Extensions.Localization; - -namespace Volo.Abp.Identity -{ - public class AbpIdentityMessageLocalizer - { - private readonly IStringLocalizer stringLocalizer; - - public AbpIdentityMessageLocalizer(IStringLocalizer stringLocalizer) - { - this.stringLocalizer = stringLocalizer; - } - - public virtual string Localize(string format, params string[] arguments) - { - try - { - return arguments?.Length > 0 - ? string.Format(stringLocalizer[format], LocalizeArguments(arguments)?.ToArray()) - : stringLocalizer[format]; - } - catch - { - return stringLocalizer[format]; - } - } - - public virtual IEnumerable Localize(IEnumerable<(string format, string[] arguments)> messages) - { - return messages?.Select(m => Localize(m.format, m.arguments)); - } - - protected virtual IEnumerable LocalizeArguments(IEnumerable arguments) - { - foreach (var argument in arguments) - { - yield return stringLocalizer[$"DisplayName:{argument}"] - ?? stringLocalizer[argument] - ?? argument; - } - } - } -} From f7a3955e368b80dd4397849a30a251d490afaa18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0lkay=20=C4=B0lknur?= Date: Fri, 23 Oct 2020 15:13:01 +0300 Subject: [PATCH 021/566] Introduce DataGridActionsColumn and add policy check, default value setting --- .../Components/DataGridEntityActionsColumn.cs | 23 ++++++++ .../Components/EntityAction.razor | 5 +- .../Components/EntityAction.razor.cs | 57 +++++++++++++++---- .../Components/EntityActions.razor | 7 +-- .../Components/EntityActions.razor.cs | 30 +++++++--- 5 files changed, 98 insertions(+), 24 deletions(-) create mode 100644 framework/src/Volo.Abp.BlazoriseUI/Components/DataGridEntityActionsColumn.cs diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/DataGridEntityActionsColumn.cs b/framework/src/Volo.Abp.BlazoriseUI/Components/DataGridEntityActionsColumn.cs new file mode 100644 index 0000000000..316c01370b --- /dev/null +++ b/framework/src/Volo.Abp.BlazoriseUI/Components/DataGridEntityActionsColumn.cs @@ -0,0 +1,23 @@ +using System.Linq; +using Blazorise.DataGrid; +using Localization.Resources.AbpUi; +using Microsoft.AspNetCore.Components; +using Microsoft.Extensions.Localization; + +namespace Volo.Abp.BlazoriseUI.Components +{ + public class DataGridEntityActionsColumn : DataGridColumn + { + [Inject] + public IStringLocalizer UiLocalizer { get; set; } + + protected override void OnInitialized() + { + base.OnInitialized(); + Caption = UiLocalizer["Actions"]; + Width = "150px"; + Sortable = false; + Field = typeof(TItem).GetProperties().First().Name; + } + } +} diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/EntityAction.razor b/framework/src/Volo.Abp.BlazoriseUI/Components/EntityAction.razor index c36620f195..4988af6725 100644 --- a/framework/src/Volo.Abp.BlazoriseUI/Components/EntityAction.razor +++ b/framework/src/Volo.Abp.BlazoriseUI/Components/EntityAction.razor @@ -1,5 +1,4 @@ -@typeparam TItem -@using Blazorise +@using Blazorise @if (ParentActions.Type == ActionType.Dropdown) { @@ -13,7 +12,7 @@ else if (IsVisible) { @Text diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/EntityAction.razor.cs b/framework/src/Volo.Abp.BlazoriseUI/Components/EntityAction.razor.cs index 8dc4dcb5a0..872a735f83 100644 --- a/framework/src/Volo.Abp.BlazoriseUI/Components/EntityAction.razor.cs +++ b/framework/src/Volo.Abp.BlazoriseUI/Components/EntityAction.razor.cs @@ -1,12 +1,16 @@ -using System.Threading.Tasks; +using System; +using System.Threading.Tasks; +using Blazorise; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Components; +using Volo.Abp.AspNetCore.Components.WebAssembly; namespace Volo.Abp.BlazoriseUI.Components { - public partial class EntityAction : ComponentBase + public partial class EntityAction : ComponentBase { - [Parameter] - public bool IsVisible { get; set; } + internal bool IsVisible; + [Parameter] public string Text { get; set; } @@ -14,20 +18,53 @@ namespace Volo.Abp.BlazoriseUI.Components public bool Primary { get; set; } [Parameter] - public EventCallback Clicked { get; set; } + public EventCallback Clicked { get; set; } + + [Parameter] + public string Policy { get; set; } + + [Parameter] + public Color Color { get; set; } + + [Parameter] + public string ConfirmationMessage { get; set; } [CascadingParameter] - public EntityActions ParentActions { get; set; } + public EntityActions ParentActions { get; set; } - protected override void OnInitialized() + [Inject] + protected IAuthorizationService AuthorizationService { get; set; } + + [Inject] + protected IUiMessageService UiMessageService { get; set; } + + protected async override Task OnInitializedAsync() { - base.OnInitialized(); + await base.OnInitializedAsync(); + await SetDefaultValuesAsync(); ParentActions.AddAction(this); + IsVisible = await AuthorizationService.IsGrantedAsync(Policy); + } + + protected internal virtual async Task ActionClickedAsync() + { + if (!ConfirmationMessage.IsNullOrEmpty()) + { + if (await UiMessageService.ConfirmAsync(ConfirmationMessage)) + { + await Clicked.InvokeAsync(); + } + } + else + { + await Clicked.InvokeAsync(); + } } - protected virtual async Task ActionClickedAsync() + protected virtual ValueTask SetDefaultValuesAsync() { - await Clicked.InvokeAsync(ParentActions.Entity); + Color = Color.Primary; + return ValueTask.CompletedTask; } } } diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/EntityActions.razor b/framework/src/Volo.Abp.BlazoriseUI/Components/EntityActions.razor index b5afcdbadf..16e4889490 100644 --- a/framework/src/Volo.Abp.BlazoriseUI/Components/EntityActions.razor +++ b/framework/src/Volo.Abp.BlazoriseUI/Components/EntityActions.razor @@ -1,13 +1,12 @@ -@typeparam TItem - + @if (Type == ActionType.Dropdown) { @if (HasPrimaryAction) { + Color="@PrimaryAction.Color" + Clicked="async ()=> await PrimaryAction.ActionClickedAsync()"> @PrimaryAction.Text diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/EntityActions.razor.cs b/framework/src/Volo.Abp.BlazoriseUI/Components/EntityActions.razor.cs index d24c7125a7..9024bf0d4b 100644 --- a/framework/src/Volo.Abp.BlazoriseUI/Components/EntityActions.razor.cs +++ b/framework/src/Volo.Abp.BlazoriseUI/Components/EntityActions.razor.cs @@ -1,15 +1,18 @@ using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; using Blazorise; +using Localization.Resources.AbpUi; using Microsoft.AspNetCore.Components; +using Microsoft.Extensions.Localization; namespace Volo.Abp.BlazoriseUI.Components { - public partial class EntityActions : ComponentBase + public partial class EntityActions : ComponentBase { - protected List> Actions = new List>(); + protected readonly List Actions = new List(); protected bool HasPrimaryAction => Actions.Any(t => t.Primary); - protected EntityAction PrimaryAction => Actions.FirstOrDefault(t => t.Primary); + protected EntityAction PrimaryAction => Actions.FirstOrDefault(t => t.Primary); protected internal ActionType Type => Actions.Count(t => t.IsVisible) > 1 ? ActionType.Dropdown : ActionType.Button; [Parameter] @@ -18,17 +21,30 @@ namespace Volo.Abp.BlazoriseUI.Components [Parameter] public string ToggleText { get; set; } - [Parameter] - public TItem Entity { get; set; } - [Parameter] public RenderFragment ChildContent { get; set; } - internal void AddAction(EntityAction action) + [Inject] + public IStringLocalizer UiLocalizer { get; set; } + + internal void AddAction(EntityAction action) { Actions.Add(action); StateHasChanged(); } + + protected override async Task OnInitializedAsync() + { + await base.OnInitializedAsync(); + await SetDefaultValuesAsync(); + } + + protected virtual ValueTask SetDefaultValuesAsync() + { + ToggleColor = Color.Primary; + ToggleText = UiLocalizer["Actions"]; + return ValueTask.CompletedTask; + } } public enum ActionType From a2643f3f2834444ae515cb43023e6009fcc120db Mon Sep 17 00:00:00 2001 From: Ilkay Ilknur Date: Sun, 25 Oct 2020 23:50:43 +0300 Subject: [PATCH 022/566] add datagridentityactionscolumn reference to the entityactions component and code refactorings. --- .../Components/DataGridEntityActionsColumn.cs | 11 ++++++-- .../Components/EntityAction.razor | 3 +- .../Components/EntityAction.razor.cs | 6 ++-- .../Components/EntityActions.razor | 3 +- .../Components/EntityActions.razor.cs | 28 +++++++++---------- 5 files changed, 30 insertions(+), 21 deletions(-) diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/DataGridEntityActionsColumn.cs b/framework/src/Volo.Abp.BlazoriseUI/Components/DataGridEntityActionsColumn.cs index 316c01370b..f41ec63e2c 100644 --- a/framework/src/Volo.Abp.BlazoriseUI/Components/DataGridEntityActionsColumn.cs +++ b/framework/src/Volo.Abp.BlazoriseUI/Components/DataGridEntityActionsColumn.cs @@ -1,4 +1,5 @@ using System.Linq; +using System.Threading.Tasks; using Blazorise.DataGrid; using Localization.Resources.AbpUi; using Microsoft.AspNetCore.Components; @@ -11,13 +12,19 @@ namespace Volo.Abp.BlazoriseUI.Components [Inject] public IStringLocalizer UiLocalizer { get; set; } - protected override void OnInitialized() + protected override async Task OnInitializedAsync() + { + await base.OnInitializedAsync(); + await SetDefaultValuesAsync(); + } + + protected virtual ValueTask SetDefaultValuesAsync() { - base.OnInitialized(); Caption = UiLocalizer["Actions"]; Width = "150px"; Sortable = false; Field = typeof(TItem).GetProperties().First().Name; + return ValueTask.CompletedTask; } } } diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/EntityAction.razor b/framework/src/Volo.Abp.BlazoriseUI/Components/EntityAction.razor index 4988af6725..99e0383fdc 100644 --- a/framework/src/Volo.Abp.BlazoriseUI/Components/EntityAction.razor +++ b/framework/src/Volo.Abp.BlazoriseUI/Components/EntityAction.razor @@ -1,4 +1,5 @@ -@using Blazorise +@typeparam TItem +@using Blazorise @if (ParentActions.Type == ActionType.Dropdown) { diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/EntityAction.razor.cs b/framework/src/Volo.Abp.BlazoriseUI/Components/EntityAction.razor.cs index 872a735f83..60b2495938 100644 --- a/framework/src/Volo.Abp.BlazoriseUI/Components/EntityAction.razor.cs +++ b/framework/src/Volo.Abp.BlazoriseUI/Components/EntityAction.razor.cs @@ -7,7 +7,7 @@ using Volo.Abp.AspNetCore.Components.WebAssembly; namespace Volo.Abp.BlazoriseUI.Components { - public partial class EntityAction : ComponentBase + public partial class EntityAction : ComponentBase { internal bool IsVisible; @@ -30,7 +30,7 @@ namespace Volo.Abp.BlazoriseUI.Components public string ConfirmationMessage { get; set; } [CascadingParameter] - public EntityActions ParentActions { get; set; } + public EntityActions ParentActions { get; set; } [Inject] protected IAuthorizationService AuthorizationService { get; set; } @@ -42,8 +42,8 @@ namespace Volo.Abp.BlazoriseUI.Components { await base.OnInitializedAsync(); await SetDefaultValuesAsync(); - ParentActions.AddAction(this); IsVisible = await AuthorizationService.IsGrantedAsync(Policy); + ParentActions.AddAction(this); } protected internal virtual async Task ActionClickedAsync() diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/EntityActions.razor b/framework/src/Volo.Abp.BlazoriseUI/Components/EntityActions.razor index 16e4889490..d445d102d3 100644 --- a/framework/src/Volo.Abp.BlazoriseUI/Components/EntityActions.razor +++ b/framework/src/Volo.Abp.BlazoriseUI/Components/EntityActions.razor @@ -1,4 +1,5 @@ - +@typeparam TItem + @if (Type == ActionType.Dropdown) { diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/EntityActions.razor.cs b/framework/src/Volo.Abp.BlazoriseUI/Components/EntityActions.razor.cs index 9024bf0d4b..ef3d9a8a9e 100644 --- a/framework/src/Volo.Abp.BlazoriseUI/Components/EntityActions.razor.cs +++ b/framework/src/Volo.Abp.BlazoriseUI/Components/EntityActions.razor.cs @@ -8,15 +8,15 @@ using Microsoft.Extensions.Localization; namespace Volo.Abp.BlazoriseUI.Components { - public partial class EntityActions : ComponentBase + public partial class EntityActions : ComponentBase { - protected readonly List Actions = new List(); + protected readonly List> Actions = new List>(); protected bool HasPrimaryAction => Actions.Any(t => t.Primary); - protected EntityAction PrimaryAction => Actions.FirstOrDefault(t => t.Primary); + protected EntityAction PrimaryAction => Actions.FirstOrDefault(t => t.Primary); protected internal ActionType Type => Actions.Count(t => t.IsVisible) > 1 ? ActionType.Dropdown : ActionType.Button; [Parameter] - public Color ToggleColor { get; set; } + public Color ToggleColor { get; set; } = Color.Primary; [Parameter] public string ToggleText { get; set; } @@ -24,26 +24,26 @@ namespace Volo.Abp.BlazoriseUI.Components [Parameter] public RenderFragment ChildContent { get; set; } + [Parameter] + public DataGridEntityActionsColumn EntityActionsColumn { get; set; } + [Inject] public IStringLocalizer UiLocalizer { get; set; } - internal void AddAction(EntityAction action) + internal void AddAction(EntityAction action) { Actions.Add(action); + if (EntityActionsColumn != null) + { + EntityActionsColumn.Displayable = Actions.Any(t => t.IsVisible); + } StateHasChanged(); } - protected override async Task OnInitializedAsync() - { - await base.OnInitializedAsync(); - await SetDefaultValuesAsync(); - } - - protected virtual ValueTask SetDefaultValuesAsync() + protected override void OnInitialized() { - ToggleColor = Color.Primary; + base.OnInitialized(); ToggleText = UiLocalizer["Actions"]; - return ValueTask.CompletedTask; } } From b2d05a53bc1a9bbb5b6e196312f0fe4051633f80 Mon Sep 17 00:00:00 2001 From: Ilkay Ilknur Date: Mon, 26 Oct 2020 11:50:43 +0300 Subject: [PATCH 023/566] policy name changed. --- .../Volo.Abp.BlazoriseUI/Components/EntityAction.razor.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/EntityAction.razor.cs b/framework/src/Volo.Abp.BlazoriseUI/Components/EntityAction.razor.cs index 60b2495938..7d2a96dcf1 100644 --- a/framework/src/Volo.Abp.BlazoriseUI/Components/EntityAction.razor.cs +++ b/framework/src/Volo.Abp.BlazoriseUI/Components/EntityAction.razor.cs @@ -21,12 +21,12 @@ namespace Volo.Abp.BlazoriseUI.Components public EventCallback Clicked { get; set; } [Parameter] - public string Policy { get; set; } + public string RequiredPolicy { get; set; } [Parameter] public Color Color { get; set; } - - [Parameter] + + [Parameter] public string ConfirmationMessage { get; set; } [CascadingParameter] @@ -42,7 +42,7 @@ namespace Volo.Abp.BlazoriseUI.Components { await base.OnInitializedAsync(); await SetDefaultValuesAsync(); - IsVisible = await AuthorizationService.IsGrantedAsync(Policy); + IsVisible = await AuthorizationService.IsGrantedAsync(RequiredPolicy); ParentActions.AddAction(this); } From a36ccf1e822727c7cf7af0e8c4f3147c99f7a648 Mon Sep 17 00:00:00 2001 From: Ilkay Ilknur Date: Mon, 26 Oct 2020 13:55:16 +0300 Subject: [PATCH 024/566] move confirmation check to the actions component. --- framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs | 6 ------ .../Volo.Abp.BlazoriseUI/Components/EntityAction.razor.cs | 8 +++++--- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs b/framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs index 76f7caf377..4df70152fa 100644 --- a/framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs +++ b/framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs @@ -169,7 +169,6 @@ namespace Volo.Abp.BlazoriseUI where TUpdateViewModel : class, new() { [Inject] protected TAppService AppService { get; set; } - [Inject] protected IUiMessageService UiMessageService { get; set; } [Inject] protected IStringLocalizer UiLocalizer { get; set; } [Inject] protected IAuthorizationService AuthorizationService { get; set; } @@ -392,11 +391,6 @@ namespace Volo.Abp.BlazoriseUI { await CheckDeletePolicyAsync(); - if (!await UiMessageService.ConfirmAsync(GetDeleteConfirmationMessage(entity))) - { - return; - } - await AppService.DeleteAsync(entity.Id); await GetEntitiesAsync(); } diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/EntityAction.razor.cs b/framework/src/Volo.Abp.BlazoriseUI/Components/EntityAction.razor.cs index 7d2a96dcf1..6e98865297 100644 --- a/framework/src/Volo.Abp.BlazoriseUI/Components/EntityAction.razor.cs +++ b/framework/src/Volo.Abp.BlazoriseUI/Components/EntityAction.razor.cs @@ -1,8 +1,10 @@ using System; using System.Threading.Tasks; using Blazorise; +using Localization.Resources.AbpUi; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Components; +using Microsoft.Extensions.Localization; using Volo.Abp.AspNetCore.Components.WebAssembly; namespace Volo.Abp.BlazoriseUI.Components @@ -27,7 +29,7 @@ namespace Volo.Abp.BlazoriseUI.Components public Color Color { get; set; } [Parameter] - public string ConfirmationMessage { get; set; } + public Func ConfirmationMessage { get; set; } [CascadingParameter] public EntityActions ParentActions { get; set; } @@ -48,9 +50,9 @@ namespace Volo.Abp.BlazoriseUI.Components protected internal virtual async Task ActionClickedAsync() { - if (!ConfirmationMessage.IsNullOrEmpty()) + if (ConfirmationMessage != null) { - if (await UiMessageService.ConfirmAsync(ConfirmationMessage)) + if (await UiMessageService.ConfirmAsync(ConfirmationMessage())) { await Clicked.InvokeAsync(); } From 3666579a2970a14089b23a5b14d17990d138b340 Mon Sep 17 00:00:00 2001 From: Ilkay Ilknur Date: Mon, 26 Oct 2020 14:14:40 +0300 Subject: [PATCH 025/566] move action type enum to a new file. --- .../src/Volo.Abp.BlazoriseUI/Components/ActionType.cs | 8 ++++++++ .../Components/EntityActions.razor.cs | 6 ------ 2 files changed, 8 insertions(+), 6 deletions(-) create mode 100644 framework/src/Volo.Abp.BlazoriseUI/Components/ActionType.cs diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/ActionType.cs b/framework/src/Volo.Abp.BlazoriseUI/Components/ActionType.cs new file mode 100644 index 0000000000..8f6afd69c9 --- /dev/null +++ b/framework/src/Volo.Abp.BlazoriseUI/Components/ActionType.cs @@ -0,0 +1,8 @@ +namespace Volo.Abp.BlazoriseUI.Components +{ + public enum ActionType + { + Dropdown, + Button + } +} diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/EntityActions.razor.cs b/framework/src/Volo.Abp.BlazoriseUI/Components/EntityActions.razor.cs index ef3d9a8a9e..0d058904c4 100644 --- a/framework/src/Volo.Abp.BlazoriseUI/Components/EntityActions.razor.cs +++ b/framework/src/Volo.Abp.BlazoriseUI/Components/EntityActions.razor.cs @@ -46,10 +46,4 @@ namespace Volo.Abp.BlazoriseUI.Components ToggleText = UiLocalizer["Actions"]; } } - - public enum ActionType - { - Dropdown, - Button - } } From 7b06cfb5a2bc85f770cb1c708179ea0e9da7c61d Mon Sep 17 00:00:00 2001 From: maliming Date: Tue, 27 Oct 2020 11:44:39 +0800 Subject: [PATCH 026/566] Move to System.Text.Json Resolve #1198 --- framework/Volo.Abp.sln | 7 ++ .../Volo.Abp.AspNetCore.Mvc.csproj | 1 - .../AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs | 8 +- .../Mvc/Json/AbpJsonOptionsSetup.cs | 25 ++++++ .../Mvc/Json/AbpMvcJsonContractResolver.cs | 46 ---------- .../Abp/Auditing/AuditingContractResolver.cs | 39 -------- .../AuditingRuntimeIgnoreConverter.cs | 45 ++++++++++ .../Abp/Auditing/JsonNetAuditSerializer.cs | 29 ++---- .../Volo/Abp/Domain/Entities/EntityHelper.cs | 39 +++++++- .../Domain/Entities/EntityJsonConverter.cs | 29 ++++++ .../ValueConverters/AbpJsonValueConverter.cs | 12 +-- .../ExtraPropertiesValueConverter.cs | 15 ++-- .../DynamicProxying/ApiDescriptionFinder.cs | 15 ++-- .../Modeling/ActionApiDescriptionModel.cs | 4 +- .../ApplicationApiDescriptionModel.cs | 6 +- .../Modeling/ControllerApiDescriptionModel.cs | 4 +- .../ControllerInterfaceApiDescriptionModel.cs | 6 +- .../MethodParameterApiDescriptionModel.cs | 2 +- .../Modeling/ModuleApiDescriptionModel.cs | 14 +-- .../Modeling/ParameterApiDescriptionModel.cs | 2 +- .../ReturnValueApiDescriptionModel.cs | 2 +- .../Http/Modeling/TypeApiDescriptionModel.cs | 2 +- .../Volo.Abp.Json.Newtonsoft/FodyWeavers.xml | 3 + .../Volo.Abp.Json.Newtonsoft/FodyWeavers.xsd | 30 +++++++ .../Volo.Abp.Json.Newtonsoft.csproj | 25 ++++++ .../Volo/Abp/Json/AbpJsonModule.cs | 21 +++++ .../Newtonsoft/AbpJsonIsoDateTimeConverter.cs | 0 .../AbpNewtonsoftJsonSerializerOptions.cs | 0 .../Newtonsoft/NewtonsoftJsonSerializer.cs | 1 + .../src/Volo.Abp.Json/Volo.Abp.Json.csproj | 4 - .../Volo/Abp/Json/AbpJsonModule.cs | 10 +-- .../Volo/Abp/Json/AbpJsonOptions.cs | 2 +- .../Abp/Json/Microsoft/AbpJsonSerializer.cs | 49 ++++++++++ .../Microsoft/AbpJsonSerializerOptions.cs | 18 ++++ .../AbpJsonSerializerOptionsSetup.cs | 23 +++++ .../JsonConverters/AbpDateTimeConverter.cs | 38 ++++++++ .../AbpNullableDateTimeConverter.cs | 50 +++++++++++ .../ObjectToInferredTypesConverter.cs | 54 +++++++++++ .../Volo.Abp.Localization.csproj | 4 - .../Json/JsonLocalizationDictionaryBuilder.cs | 19 ++-- .../Localization/Json/JsonLocalizationFile.cs | 4 +- .../MemoryDb/Utf8JsonMemoryDbSerializer.cs | 41 ++------- .../Utf8JsonMemoryDbSerializerOptions.cs | 14 +++ .../OAuth/Claims/MultipleClaimAction_Tests.cs | 1 - .../Abp/AspNetCore/AbpAspNetCoreTestBase.cs | 14 +-- .../Abp/MemoryDb/AbpMemoryDbTestModule.cs | 11 ++- .../Repository_Basic_Tests_With_Int_Pk.cs | 1 + .../Volo.Docs.Domain.Shared.csproj | 4 + ...ureManagementApplicationContractsModule.cs | 11 ++- .../LocalizableStringInfoJsonConverter.cs | 24 +++++ .../SelectionStringValueItemJsonConverter.cs | 36 ++++++++ ...ctionStringValueItemSourceJsonConverter.cs | 36 ++++++++ .../StringValueTypeJsonConverter.cs | 47 ++++++++++ .../ValueValidatorJsonConverter.cs | 68 ++++++++++++++ .../StringValueTypeJsonConverter.cs | 90 ------------------- .../StringValueJsonConverter_Tests.cs | 6 +- nupkg/common.ps1 | 1 + 57 files changed, 783 insertions(+), 329 deletions(-) create mode 100644 framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpJsonOptionsSetup.cs delete mode 100644 framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpMvcJsonContractResolver.cs delete mode 100644 framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingContractResolver.cs create mode 100644 framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingRuntimeIgnoreConverter.cs create mode 100644 framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/EntityJsonConverter.cs create mode 100644 framework/src/Volo.Abp.Json.Newtonsoft/FodyWeavers.xml create mode 100644 framework/src/Volo.Abp.Json.Newtonsoft/FodyWeavers.xsd create mode 100644 framework/src/Volo.Abp.Json.Newtonsoft/Volo.Abp.Json.Newtonsoft.csproj create mode 100644 framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/AbpJsonModule.cs rename framework/src/{Volo.Abp.Json => Volo.Abp.Json.Newtonsoft}/Volo/Abp/Json/Newtonsoft/AbpJsonIsoDateTimeConverter.cs (100%) rename framework/src/{Volo.Abp.Json => Volo.Abp.Json.Newtonsoft}/Volo/Abp/Json/Newtonsoft/AbpNewtonsoftJsonSerializerOptions.cs (100%) rename framework/src/{Volo.Abp.Json => Volo.Abp.Json.Newtonsoft}/Volo/Abp/Json/Newtonsoft/NewtonsoftJsonSerializer.cs (98%) create mode 100644 framework/src/Volo.Abp.Json/Volo/Abp/Json/Microsoft/AbpJsonSerializer.cs create mode 100644 framework/src/Volo.Abp.Json/Volo/Abp/Json/Microsoft/AbpJsonSerializerOptions.cs create mode 100644 framework/src/Volo.Abp.Json/Volo/Abp/Json/Microsoft/AbpJsonSerializerOptionsSetup.cs create mode 100644 framework/src/Volo.Abp.Json/Volo/Abp/Json/Microsoft/JsonConverters/AbpDateTimeConverter.cs create mode 100644 framework/src/Volo.Abp.Json/Volo/Abp/Json/Microsoft/JsonConverters/AbpNullableDateTimeConverter.cs create mode 100644 framework/src/Volo.Abp.Json/Volo/Abp/Json/Microsoft/JsonConverters/ObjectToInferredTypesConverter.cs create mode 100644 framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/Utf8JsonMemoryDbSerializerOptions.cs create mode 100644 modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/LocalizableStringInfoJsonConverter.cs create mode 100644 modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/SelectionStringValueItemJsonConverter.cs create mode 100644 modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/SelectionStringValueItemSourceJsonConverter.cs create mode 100644 modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/StringValueTypeJsonConverter.cs create mode 100644 modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/ValueValidatorJsonConverter.cs delete mode 100644 modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/StringValueTypeJsonConverter.cs diff --git a/framework/Volo.Abp.sln b/framework/Volo.Abp.sln index 65cac6e7cd..fb59c91051 100644 --- a/framework/Volo.Abp.sln +++ b/framework/Volo.Abp.sln @@ -355,6 +355,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.AspNetCore.Compone EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Swashbuckle", "src\Volo.Abp.Swashbuckle\Volo.Abp.Swashbuckle.csproj", "{DD9519E0-5A68-48DC-A051-7BF2AC922F3E}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Json.Newtonsoft", "src\Volo.Abp.Json.Newtonsoft\Volo.Abp.Json.Newtonsoft.csproj", "{B5DEA857-1A22-4479-8441-E871D1BCBAB2}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -1057,6 +1059,10 @@ Global {DD9519E0-5A68-48DC-A051-7BF2AC922F3E}.Debug|Any CPU.Build.0 = Debug|Any CPU {DD9519E0-5A68-48DC-A051-7BF2AC922F3E}.Release|Any CPU.ActiveCfg = Release|Any CPU {DD9519E0-5A68-48DC-A051-7BF2AC922F3E}.Release|Any CPU.Build.0 = Release|Any CPU + {B5DEA857-1A22-4479-8441-E871D1BCBAB2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B5DEA857-1A22-4479-8441-E871D1BCBAB2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B5DEA857-1A22-4479-8441-E871D1BCBAB2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B5DEA857-1A22-4479-8441-E871D1BCBAB2}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1236,6 +1242,7 @@ Global {B9D1ADCB-D552-4626-A1F1-78FF72C1E822} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {89840441-5A3A-4FD7-9CB4-E5B52FAEF72A} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {DD9519E0-5A68-48DC-A051-7BF2AC922F3E} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} + {B5DEA857-1A22-4479-8441-E871D1BCBAB2} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj index 3e691f57f3..fff97c83c3 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj @@ -29,7 +29,6 @@ - diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs index 3097a3c725..f35721c3c0 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs @@ -35,6 +35,7 @@ using Volo.Abp.Http; using Volo.Abp.DynamicProxy; using Volo.Abp.GlobalFeatures; using Volo.Abp.Http.Modeling; +using Volo.Abp.Json.Microsoft; using Volo.Abp.Localization; using Volo.Abp.Modularity; using Volo.Abp.UI; @@ -114,11 +115,6 @@ namespace Volo.Abp.AspNetCore.Mvc ); var mvcBuilder = context.Services.AddMvc() - .AddNewtonsoftJson(options => - { - options.SerializerSettings.ContractResolver = - new AbpMvcJsonContractResolver(context.Services); - }) .AddRazorRuntimeCompilation() .AddDataAnnotationsLocalization(options => { @@ -139,6 +135,8 @@ namespace Volo.Abp.AspNetCore.Mvc }) .AddViewLocalization(); //TODO: How to configure from the application? Also, consider to move to a UI module since APIs does not care about it. + context.Services.TryAddEnumerable(ServiceDescriptor.Transient, AbpJsonOptionsSetup>()); + Configure(options => { options.FileProviders.Add( diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpJsonOptionsSetup.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpJsonOptionsSetup.cs new file mode 100644 index 0000000000..f9d58a3918 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpJsonOptionsSetup.cs @@ -0,0 +1,25 @@ +using System; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Volo.Abp.Json.Microsoft; +using Volo.Abp.Json.Microsoft.JsonConverters; + +namespace Volo.Abp.AspNetCore.Mvc.Json +{ + public class AbpJsonOptionsSetup : IConfigureOptions + { + protected IServiceProvider ServiceProvider { get; } + + public AbpJsonOptionsSetup(IServiceProvider serviceProvider) + { + ServiceProvider = serviceProvider; + } + + public void Configure(JsonOptions options) + { + options.JsonSerializerOptions.Converters.Add(ServiceProvider.GetRequiredService()); + options.JsonSerializerOptions.Converters.Add(ServiceProvider.GetRequiredService()); + } + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpMvcJsonContractResolver.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpMvcJsonContractResolver.cs deleted file mode 100644 index 695212f563..0000000000 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpMvcJsonContractResolver.cs +++ /dev/null @@ -1,46 +0,0 @@ -using Microsoft.Extensions.DependencyInjection; -using Newtonsoft.Json; -using Newtonsoft.Json.Serialization; -using System; -using System.Reflection; -using Volo.Abp.Json.Newtonsoft; -using Volo.Abp.Reflection; -using Volo.Abp.Timing; - -namespace Volo.Abp.AspNetCore.Mvc.Json -{ - public class AbpMvcJsonContractResolver : DefaultContractResolver - { - private readonly Lazy _dateTimeConverter; - - public AbpMvcJsonContractResolver(IServiceCollection services) - { - _dateTimeConverter = services.GetServiceLazy(); - - NamingStrategy = new CamelCaseNamingStrategy(); - } - - protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) - { - JsonProperty property = base.CreateProperty(member, memberSerialization); - - ModifyProperty(member, property); - - return property; - } - - protected virtual void ModifyProperty(MemberInfo member, JsonProperty property) - { - if (property.PropertyType != typeof(DateTime) && property.PropertyType != typeof(DateTime?)) - { - return; - } - - if (ReflectionHelper.GetSingleAttributeOfMemberOrDeclaringTypeOrDefault(member) == null) - { - property.Converter = _dateTimeConverter.Value; - } - - } - } -} diff --git a/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingContractResolver.cs b/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingContractResolver.cs deleted file mode 100644 index e6d03bf707..0000000000 --- a/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingContractResolver.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Reflection; -using Newtonsoft.Json; -using Newtonsoft.Json.Serialization; - -namespace Volo.Abp.Auditing -{ - public class AuditingContractResolver : CamelCasePropertyNamesContractResolver - { - private readonly List _ignoredTypes; - - public AuditingContractResolver(List ignoredTypes) - { - _ignoredTypes = ignoredTypes; - } - - protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) - { - var property = base.CreateProperty(member, memberSerialization); - - if (member.IsDefined(typeof(DisableAuditingAttribute)) || member.IsDefined(typeof(JsonIgnoreAttribute))) - { - property.ShouldSerialize = instance => false; - } - - foreach (var ignoredType in _ignoredTypes) - { - if (ignoredType.GetTypeInfo().IsAssignableFrom(property.PropertyType)) - { - property.ShouldSerialize = instance => false; - break; - } - } - - return property; - } - } -} diff --git a/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingRuntimeIgnoreConverter.cs b/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingRuntimeIgnoreConverter.cs new file mode 100644 index 0000000000..240b2581ab --- /dev/null +++ b/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingRuntimeIgnoreConverter.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Volo.Abp.Auditing +{ + public class AuditingRuntimeIgnoreConverter : JsonConverter> + { + private readonly List _ignoredTypes; + + public AuditingRuntimeIgnoreConverter(List ignoredTypes) + { + _ignoredTypes = ignoredTypes; + } + + public override Dictionary Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + throw new JsonException(); + } + + public override void Write(Utf8JsonWriter writer, Dictionary value, JsonSerializerOptions options) + { + var newDictionary = new Dictionary(); + foreach (var item in value.Where(x => x.Value != null)) + { + if (item.GetType().IsDefined(typeof(DisableAuditingAttribute), true) || + item.GetType().IsDefined(typeof(JsonIgnoreAttribute), true)) + { + continue; + } + + if (_ignoredTypes.Any(x => x.IsInstanceOfType(item.Value))) + { + continue; + } + + newDictionary[item.Key] = item.Value; + } + + JsonSerializer.Serialize(writer, newDictionary); + } + } +} diff --git a/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/JsonNetAuditSerializer.cs b/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/JsonNetAuditSerializer.cs index b86df6b6c8..d11886e5a7 100644 --- a/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/JsonNetAuditSerializer.cs +++ b/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/JsonNetAuditSerializer.cs @@ -1,5 +1,5 @@ +using System.Text.Json; using Microsoft.Extensions.Options; -using Newtonsoft.Json; using Volo.Abp.DependencyInjection; namespace Volo.Abp.Auditing @@ -16,29 +16,14 @@ namespace Volo.Abp.Auditing public string Serialize(object obj) { - return JsonConvert.SerializeObject(obj, GetSharedJsonSerializerSettings()); + return JsonSerializer.Serialize(obj, GetJsonSerializerOptions()); } - private static readonly object SyncObj = new object(); - private static JsonSerializerSettings _sharedJsonSerializerSettings; - - private JsonSerializerSettings GetSharedJsonSerializerSettings() + private JsonSerializerOptions GetJsonSerializerOptions() { - if (_sharedJsonSerializerSettings == null) - { - lock (SyncObj) - { - if (_sharedJsonSerializerSettings == null) - { - _sharedJsonSerializerSettings = new JsonSerializerSettings - { - ContractResolver = new AuditingContractResolver(Options.IgnoredTypes) - }; - } - } - } - - return _sharedJsonSerializerSettings; + var options = new JsonSerializerOptions(); + options.Converters.Add(new AuditingRuntimeIgnoreConverter(Options.IgnoredTypes)); + return options; } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/EntityHelper.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/EntityHelper.cs index 65f2992257..b778ec2b67 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/EntityHelper.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/EntityHelper.cs @@ -77,7 +77,7 @@ namespace Volo.Abp.Domain.Entities { var entity1Key = entity1Keys[i]; var entity2Key = entity2Keys[i]; - + if (entity1Key == null) { if (entity2Key == null) @@ -89,13 +89,13 @@ namespace Volo.Abp.Domain.Entities //entity2Key is not null! return false; } - + if (entity2Key == null) { //entity1Key was not null! return false; } - + if (TypeHelper.IsDefaultValue(entity1Key) && TypeHelper.IsDefaultValue(entity2Key)) { return false; @@ -266,5 +266,36 @@ namespace Volo.Abp.Domain.Entities property?.SetValue(entity, idFactory()); } + + public static void TrySetId( + object entity, + TKey id, + bool checkForDisableIdGenerationAttribute = false) + { + var property = CachedIdProperties.GetOrAdd( + $"{entity.GetType().FullName}-{checkForDisableIdGenerationAttribute}", () => + { + var idProperty = entity + .GetType() + .GetProperties() + .FirstOrDefault(x => x.Name == nameof(IEntity.Id) && + x.GetSetMethod(true) != null); + + if (idProperty == null) + { + return null; + } + + if (checkForDisableIdGenerationAttribute && + idProperty.IsDefined(typeof(DisableIdGenerationAttribute), true)) + { + return null; + } + + return idProperty; + }); + + property?.SetValue(entity, id); + } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/EntityJsonConverter.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/EntityJsonConverter.cs new file mode 100644 index 0000000000..d472fd36d0 --- /dev/null +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/EntityJsonConverter.cs @@ -0,0 +1,29 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Volo.Abp.Domain.Entities +{ + public class EntityJsonConverter : JsonConverter + { + public override TEntity Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var jsonDocument = JsonDocument.ParseValue(ref reader); + var entity = (TEntity)JsonSerializer.Deserialize(jsonDocument.RootElement.GetRawText(), typeToConvert); + var idJsonElement = jsonDocument.RootElement.GetProperty(nameof(IEntity.Id)); + + var id = JsonSerializer.Deserialize(idJsonElement.GetRawText()); + if (id != null) + { + EntityHelper.TrySetId(entity, id); + } + + return entity; + } + + public override void Write(Utf8JsonWriter writer, TEntity value, JsonSerializerOptions options) + { + JsonSerializer.Serialize(writer, value); + } + } +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ValueConverters/AbpJsonValueConverter.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ValueConverters/AbpJsonValueConverter.cs index 6ecf19fa98..4955a703b3 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ValueConverters/AbpJsonValueConverter.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ValueConverters/AbpJsonValueConverter.cs @@ -1,6 +1,6 @@ -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Newtonsoft.Json; -using Volo.Abp.Data; +using System.Text.Json; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Volo.Abp.Json.Microsoft.JsonConverters; namespace Volo.Abp.EntityFrameworkCore.ValueConverters { @@ -16,12 +16,14 @@ namespace Volo.Abp.EntityFrameworkCore.ValueConverters private static string SerializeObject(TPropertyType d) { - return JsonConvert.SerializeObject(d, Formatting.None); + return JsonSerializer.Serialize(d); } private static TPropertyType DeserializeObject(string s) { - return JsonConvert.DeserializeObject(s); + var deserializeOptions = new JsonSerializerOptions(); + deserializeOptions.Converters.Add(new ObjectToInferredTypesConverter()); + return JsonSerializer.Deserialize(s, deserializeOptions); } } } diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ValueConverters/ExtraPropertiesValueConverter.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ValueConverters/ExtraPropertiesValueConverter.cs index 2fa00e3caf..b94a433367 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ValueConverters/ExtraPropertiesValueConverter.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ValueConverters/ExtraPropertiesValueConverter.cs @@ -1,8 +1,8 @@ using System; using System.Collections.Generic; -using System.ComponentModel; +using System.Text.Json; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Newtonsoft.Json; +using Volo.Abp.Json.Microsoft.JsonConverters; using Volo.Abp.ObjectExtending; namespace Volo.Abp.EntityFrameworkCore.ValueConverters @@ -36,13 +36,14 @@ namespace Volo.Abp.EntityFrameworkCore.ValueConverters } } - return JsonConvert.SerializeObject(copyDictionary, Formatting.None); + return JsonSerializer.Serialize(copyDictionary); } private static Dictionary DeserializeObject(string extraPropertiesAsJson, Type entityType) { - var dictionary = JsonConvert.DeserializeObject>(extraPropertiesAsJson); - + var deserializeOptions = new JsonSerializerOptions(); + deserializeOptions.Converters.Add(new ObjectToInferredTypesConverter()); + var dictionary = JsonSerializer.Deserialize>(extraPropertiesAsJson, deserializeOptions) ?? new Dictionary(); if (entityType != null) { var objectExtension = ObjectExtensionManager.Instance.GetOrNull(entityType); @@ -59,7 +60,7 @@ namespace Volo.Abp.EntityFrameworkCore.ValueConverters } private static object GetNormalizedValue( - Dictionary dictionary, + Dictionary dictionary, ObjectExtensionPropertyInfo property) { var value = dictionary.GetOrDefault(property.Name); @@ -84,4 +85,4 @@ namespace Volo.Abp.EntityFrameworkCore.ValueConverters } } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/ApiDescriptionFinder.cs b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/ApiDescriptionFinder.cs index a9b51eca6a..9142118b97 100644 --- a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/ApiDescriptionFinder.cs +++ b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/ApiDescriptionFinder.cs @@ -2,9 +2,8 @@ using System.Linq; using System.Net.Http; using System.Reflection; +using System.Text.Json; using System.Threading.Tasks; -using Newtonsoft.Json; -using Newtonsoft.Json.Serialization; using Volo.Abp.DependencyInjection; using Volo.Abp.Http.Modeling; using Volo.Abp.Threading; @@ -17,11 +16,6 @@ namespace Volo.Abp.Http.Client.DynamicProxying protected IApiDescriptionCache Cache { get; } - private static readonly JsonSerializerSettings SharedJsonSerializerSettings = new JsonSerializerSettings - { - ContractResolver = new CamelCasePropertyNamesContractResolver() - }; - public ApiDescriptionFinder(IApiDescriptionCache cache) { Cache = cache; @@ -91,9 +85,10 @@ namespace Volo.Abp.Http.Client.DynamicProxying var content = await response.Content.ReadAsStringAsync(); - var result = JsonConvert.DeserializeObject( - content, - typeof(ApplicationApiDescriptionModel), SharedJsonSerializerSettings); + var result = JsonSerializer.Deserialize(content, new JsonSerializerOptions + { + PropertyNamingPolicy = JsonNamingPolicy.CamelCase + }); return (ApplicationApiDescriptionModel)result; } diff --git a/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ActionApiDescriptionModel.cs b/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ActionApiDescriptionModel.cs index 7e9d375d06..fffd9d14d5 100644 --- a/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ActionApiDescriptionModel.cs +++ b/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ActionApiDescriptionModel.cs @@ -26,7 +26,7 @@ namespace Volo.Abp.Http.Modeling public ReturnValueApiDescriptionModel ReturnValue { get; set; } - private ActionApiDescriptionModel() + public ActionApiDescriptionModel() { } @@ -71,4 +71,4 @@ namespace Volo.Abp.Http.Modeling return $"[ActionApiDescriptionModel {Name}]"; } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ApplicationApiDescriptionModel.cs b/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ApplicationApiDescriptionModel.cs index cc09b7a153..77fb28eed5 100644 --- a/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ApplicationApiDescriptionModel.cs +++ b/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ApplicationApiDescriptionModel.cs @@ -12,9 +12,9 @@ namespace Volo.Abp.Http.Modeling public IDictionary Types { get; set; } - private ApplicationApiDescriptionModel() + public ApplicationApiDescriptionModel() { - + } public static ApplicationApiDescriptionModel Create() @@ -56,4 +56,4 @@ namespace Volo.Abp.Http.Modeling return subModel; } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ControllerApiDescriptionModel.cs b/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ControllerApiDescriptionModel.cs index db5a5eb37a..3c4b1ee538 100644 --- a/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ControllerApiDescriptionModel.cs +++ b/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ControllerApiDescriptionModel.cs @@ -16,7 +16,7 @@ namespace Volo.Abp.Http.Modeling public Dictionary Actions { get; set; } - private ControllerApiDescriptionModel() + public ControllerApiDescriptionModel() { } @@ -79,4 +79,4 @@ namespace Volo.Abp.Http.Modeling return $"[ControllerApiDescriptionModel {ControllerName}]"; } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ControllerInterfaceApiDescriptionModel.cs b/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ControllerInterfaceApiDescriptionModel.cs index 04b5ea1bc9..3515ee3129 100644 --- a/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ControllerInterfaceApiDescriptionModel.cs +++ b/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ControllerInterfaceApiDescriptionModel.cs @@ -7,9 +7,9 @@ namespace Volo.Abp.Http.Modeling { public string Type { get; set; } - private ControllerInterfaceApiDescriptionModel() + public ControllerInterfaceApiDescriptionModel() { - + } public static ControllerInterfaceApiDescriptionModel Create(Type type) @@ -20,4 +20,4 @@ namespace Volo.Abp.Http.Modeling }; } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/MethodParameterApiDescriptionModel.cs b/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/MethodParameterApiDescriptionModel.cs index b4e272c2f3..49e51fed17 100644 --- a/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/MethodParameterApiDescriptionModel.cs +++ b/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/MethodParameterApiDescriptionModel.cs @@ -19,7 +19,7 @@ namespace Volo.Abp.Http.Modeling public object DefaultValue { get; set; } - private MethodParameterApiDescriptionModel() + public MethodParameterApiDescriptionModel() { } diff --git a/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ModuleApiDescriptionModel.cs b/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ModuleApiDescriptionModel.cs index b879b90135..5c7c53745c 100644 --- a/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ModuleApiDescriptionModel.cs +++ b/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ModuleApiDescriptionModel.cs @@ -11,22 +11,22 @@ namespace Volo.Abp.Http.Modeling /// /// "app". /// - public const string DefaultRootPath = "app"; + public const string DefaultRootPath = "app"; /// /// "Default". /// - public const string DefaultRemoteServiceName = "Default"; - + public const string DefaultRemoteServiceName = "Default"; + public string RootPath { get; set; } public string RemoteServiceName { get; set; } public IDictionary Controllers { get; set; } - private ModuleApiDescriptionModel() + public ModuleApiDescriptionModel() { - + } public static ModuleApiDescriptionModel Create(string rootPath, string remoteServiceName) @@ -53,7 +53,7 @@ namespace Volo.Abp.Http.Modeling { return Controllers.GetOrAdd(uniqueName, () => ControllerApiDescriptionModel.Create(name, type, ignoredInterfaces)); } - + public ModuleApiDescriptionModel CreateSubModel(string[] controllers, string[] actions) { var subModel = Create(RootPath, RemoteServiceName); @@ -69,4 +69,4 @@ namespace Volo.Abp.Http.Modeling return subModel; } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ParameterApiDescriptionModel.cs b/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ParameterApiDescriptionModel.cs index 675ba8bf54..8bdead565e 100644 --- a/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ParameterApiDescriptionModel.cs +++ b/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ParameterApiDescriptionModel.cs @@ -24,7 +24,7 @@ namespace Volo.Abp.Http.Modeling public string DescriptorName { get; set; } - private ParameterApiDescriptionModel() + public ParameterApiDescriptionModel() { } diff --git a/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ReturnValueApiDescriptionModel.cs b/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ReturnValueApiDescriptionModel.cs index 83fa4bb6be..291abf09ae 100644 --- a/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ReturnValueApiDescriptionModel.cs +++ b/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ReturnValueApiDescriptionModel.cs @@ -11,7 +11,7 @@ namespace Volo.Abp.Http.Modeling public string TypeSimple { get; set; } - private ReturnValueApiDescriptionModel() + public ReturnValueApiDescriptionModel() { } diff --git a/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/TypeApiDescriptionModel.cs b/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/TypeApiDescriptionModel.cs index 4b0b0b870c..6114ed2ee6 100644 --- a/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/TypeApiDescriptionModel.cs +++ b/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/TypeApiDescriptionModel.cs @@ -19,7 +19,7 @@ namespace Volo.Abp.Http.Modeling public PropertyApiDescriptionModel[] Properties { get; set; } - private TypeApiDescriptionModel() + public TypeApiDescriptionModel() { } diff --git a/framework/src/Volo.Abp.Json.Newtonsoft/FodyWeavers.xml b/framework/src/Volo.Abp.Json.Newtonsoft/FodyWeavers.xml new file mode 100644 index 0000000000..bc5a74a236 --- /dev/null +++ b/framework/src/Volo.Abp.Json.Newtonsoft/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + diff --git a/framework/src/Volo.Abp.Json.Newtonsoft/FodyWeavers.xsd b/framework/src/Volo.Abp.Json.Newtonsoft/FodyWeavers.xsd new file mode 100644 index 0000000000..3f3946e282 --- /dev/null +++ b/framework/src/Volo.Abp.Json.Newtonsoft/FodyWeavers.xsd @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/framework/src/Volo.Abp.Json.Newtonsoft/Volo.Abp.Json.Newtonsoft.csproj b/framework/src/Volo.Abp.Json.Newtonsoft/Volo.Abp.Json.Newtonsoft.csproj new file mode 100644 index 0000000000..dd6cdc06ae --- /dev/null +++ b/framework/src/Volo.Abp.Json.Newtonsoft/Volo.Abp.Json.Newtonsoft.csproj @@ -0,0 +1,25 @@ + + + + + + + netstandard2.0 + Volo.Abp.Json.Newtonsoft + Volo.Abp.Json.Newtonsoft + $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; + false + false + false + + + + + + + + + + + + diff --git a/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/AbpJsonModule.cs b/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/AbpJsonModule.cs new file mode 100644 index 0000000000..a502239e19 --- /dev/null +++ b/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/AbpJsonModule.cs @@ -0,0 +1,21 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.Options; +using Volo.Abp.Json.Microsoft; +using Volo.Abp.Json.Newtonsoft; +using Volo.Abp.Modularity; + +namespace Volo.Abp.Json +{ + [DependsOn(typeof(AbpJsonModule))] + public class AbpJsonNewtonsoftModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.Converters.Add(); + }); + } + } +} diff --git a/framework/src/Volo.Abp.Json/Volo/Abp/Json/Newtonsoft/AbpJsonIsoDateTimeConverter.cs b/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpJsonIsoDateTimeConverter.cs similarity index 100% rename from framework/src/Volo.Abp.Json/Volo/Abp/Json/Newtonsoft/AbpJsonIsoDateTimeConverter.cs rename to framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpJsonIsoDateTimeConverter.cs diff --git a/framework/src/Volo.Abp.Json/Volo/Abp/Json/Newtonsoft/AbpNewtonsoftJsonSerializerOptions.cs b/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpNewtonsoftJsonSerializerOptions.cs similarity index 100% rename from framework/src/Volo.Abp.Json/Volo/Abp/Json/Newtonsoft/AbpNewtonsoftJsonSerializerOptions.cs rename to framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpNewtonsoftJsonSerializerOptions.cs diff --git a/framework/src/Volo.Abp.Json/Volo/Abp/Json/Newtonsoft/NewtonsoftJsonSerializer.cs b/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/NewtonsoftJsonSerializer.cs similarity index 98% rename from framework/src/Volo.Abp.Json/Volo/Abp/Json/Newtonsoft/NewtonsoftJsonSerializer.cs rename to framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/NewtonsoftJsonSerializer.cs index 20e49ac817..e241484719 100644 --- a/framework/src/Volo.Abp.Json/Volo/Abp/Json/Newtonsoft/NewtonsoftJsonSerializer.cs +++ b/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/NewtonsoftJsonSerializer.cs @@ -9,6 +9,7 @@ using Volo.Abp.DependencyInjection; namespace Volo.Abp.Json.Newtonsoft { + [Dependency(ReplaceServices = true)] public class NewtonsoftJsonSerializer : IJsonSerializer, ITransientDependency { private static readonly CamelCaseExceptDictionaryKeysResolver SharedCamelCaseExceptDictionaryKeysResolver = diff --git a/framework/src/Volo.Abp.Json/Volo.Abp.Json.csproj b/framework/src/Volo.Abp.Json/Volo.Abp.Json.csproj index 4e891a687d..ddf8cfba65 100644 --- a/framework/src/Volo.Abp.Json/Volo.Abp.Json.csproj +++ b/framework/src/Volo.Abp.Json/Volo.Abp.Json.csproj @@ -14,10 +14,6 @@ - - - - diff --git a/framework/src/Volo.Abp.Json/Volo/Abp/Json/AbpJsonModule.cs b/framework/src/Volo.Abp.Json/Volo/Abp/Json/AbpJsonModule.cs index c3ea13da43..2899a8ed6b 100644 --- a/framework/src/Volo.Abp.Json/Volo/Abp/Json/AbpJsonModule.cs +++ b/framework/src/Volo.Abp.Json/Volo/Abp/Json/AbpJsonModule.cs @@ -1,4 +1,7 @@ -using Volo.Abp.Json.Newtonsoft; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.Options; +using Volo.Abp.Json.Microsoft; using Volo.Abp.Modularity; using Volo.Abp.Timing; @@ -9,10 +12,7 @@ namespace Volo.Abp.Json { public override void ConfigureServices(ServiceConfigurationContext context) { - Configure(options => - { - options.Converters.Add(); - }); + context.Services.TryAddEnumerable(ServiceDescriptor.Transient, AbpJsonSerializerOptionsSetup>()); } } } diff --git a/framework/src/Volo.Abp.Json/Volo/Abp/Json/AbpJsonOptions.cs b/framework/src/Volo.Abp.Json/Volo/Abp/Json/AbpJsonOptions.cs index 9449aa338d..239d7864cd 100644 --- a/framework/src/Volo.Abp.Json/Volo/Abp/Json/AbpJsonOptions.cs +++ b/framework/src/Volo.Abp.Json/Volo/Abp/Json/AbpJsonOptions.cs @@ -7,4 +7,4 @@ /// public string DefaultDateTimeFormat { get; set; } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.Json/Volo/Abp/Json/Microsoft/AbpJsonSerializer.cs b/framework/src/Volo.Abp.Json/Volo/Abp/Json/Microsoft/AbpJsonSerializer.cs new file mode 100644 index 0000000000..55adc67ad4 --- /dev/null +++ b/framework/src/Volo.Abp.Json/Volo/Abp/Json/Microsoft/AbpJsonSerializer.cs @@ -0,0 +1,49 @@ +using System; +using System.Text.Json; +using Microsoft.Extensions.Options; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Json.Microsoft +{ + public class AbpJsonSerializer : IJsonSerializer, ITransientDependency + { + protected AbpJsonSerializerOptions Options { get; } + + public AbpJsonSerializer(IOptions options) + { + Options = options.Value; + } + + public string Serialize(object obj, bool camelCase = true, bool indented = false) + { + return JsonSerializer.Serialize(obj, CreateJsonSerializerOptions(camelCase, indented)); + } + + public T Deserialize(string jsonString, bool camelCase = true) + { + return JsonSerializer.Deserialize(jsonString, CreateJsonSerializerOptions(camelCase)); + } + + public object Deserialize(Type type, string jsonString, bool camelCase = true) + { + return JsonSerializer.Deserialize(jsonString, type, CreateJsonSerializerOptions(camelCase)); + } + + protected virtual JsonSerializerOptions CreateJsonSerializerOptions(bool camelCase = true, bool indented = false) + { + var settings = new JsonSerializerOptions(Options.JsonSerializerOptions); + + if (camelCase) + { + settings.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; + } + + if (indented) + { + settings.WriteIndented = true; + } + + return settings; + } + } +} diff --git a/framework/src/Volo.Abp.Json/Volo/Abp/Json/Microsoft/AbpJsonSerializerOptions.cs b/framework/src/Volo.Abp.Json/Volo/Abp/Json/Microsoft/AbpJsonSerializerOptions.cs new file mode 100644 index 0000000000..bbf92c77f4 --- /dev/null +++ b/framework/src/Volo.Abp.Json/Volo/Abp/Json/Microsoft/AbpJsonSerializerOptions.cs @@ -0,0 +1,18 @@ +using System.Text.Json; + +namespace Volo.Abp.Json.Microsoft +{ + public class AbpJsonSerializerOptions + { + public JsonSerializerOptions JsonSerializerOptions { get; } + + public AbpJsonSerializerOptions() + { + //TODO:Defaults? + //https://github.com/dotnet/aspnetcore/blob/master/src/Mvc/Mvc.Core/src/JsonOptions.cs#L18 + //https://github.com/dotnet/runtime/blob/master/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerDefaults.cs + + JsonSerializerOptions = new JsonSerializerOptions(JsonSerializerDefaults.Web); + } + } +} diff --git a/framework/src/Volo.Abp.Json/Volo/Abp/Json/Microsoft/AbpJsonSerializerOptionsSetup.cs b/framework/src/Volo.Abp.Json/Volo/Abp/Json/Microsoft/AbpJsonSerializerOptionsSetup.cs new file mode 100644 index 0000000000..b06e884d4c --- /dev/null +++ b/framework/src/Volo.Abp.Json/Volo/Abp/Json/Microsoft/AbpJsonSerializerOptionsSetup.cs @@ -0,0 +1,23 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Volo.Abp.Json.Microsoft.JsonConverters; + +namespace Volo.Abp.Json.Microsoft +{ + public class AbpJsonSerializerOptionsSetup : IConfigureOptions + { + protected IServiceProvider ServiceProvider { get; } + + public AbpJsonSerializerOptionsSetup(IServiceProvider serviceProvider) + { + ServiceProvider = serviceProvider; + } + + public void Configure(AbpJsonSerializerOptions options) + { + options.JsonSerializerOptions.Converters.Add(ServiceProvider.GetRequiredService()); + options.JsonSerializerOptions.Converters.Add(ServiceProvider.GetRequiredService()); + } + } +} diff --git a/framework/src/Volo.Abp.Json/Volo/Abp/Json/Microsoft/JsonConverters/AbpDateTimeConverter.cs b/framework/src/Volo.Abp.Json/Volo/Abp/Json/Microsoft/JsonConverters/AbpDateTimeConverter.cs new file mode 100644 index 0000000000..e563ee8aac --- /dev/null +++ b/framework/src/Volo.Abp.Json/Volo/Abp/Json/Microsoft/JsonConverters/AbpDateTimeConverter.cs @@ -0,0 +1,38 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; +using Microsoft.Extensions.Options; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Timing; + +namespace Volo.Abp.Json.Microsoft.JsonConverters +{ + public class AbpDateTimeConverter : JsonConverter, ITransientDependency + { + private readonly IClock _clock; + private readonly AbpJsonOptions _options; + + public AbpDateTimeConverter(IClock clock, IOptions abpJsonOptions) + { + _clock = clock; + _options = abpJsonOptions.Value; + } + + public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return _clock.Normalize(reader.GetDateTime()); + } + + public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options) + { + if (_options.DefaultDateTimeFormat.IsNullOrWhiteSpace()) + { + writer.WriteStringValue(_clock.Normalize(value)); + } + else + { + writer.WriteStringValue(_clock.Normalize(value).ToString(_options.DefaultDateTimeFormat)); + } + } + } +} diff --git a/framework/src/Volo.Abp.Json/Volo/Abp/Json/Microsoft/JsonConverters/AbpNullableDateTimeConverter.cs b/framework/src/Volo.Abp.Json/Volo/Abp/Json/Microsoft/JsonConverters/AbpNullableDateTimeConverter.cs new file mode 100644 index 0000000000..a072d1426c --- /dev/null +++ b/framework/src/Volo.Abp.Json/Volo/Abp/Json/Microsoft/JsonConverters/AbpNullableDateTimeConverter.cs @@ -0,0 +1,50 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; +using Microsoft.Extensions.Options; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Timing; + +namespace Volo.Abp.Json.Microsoft.JsonConverters +{ + public class AbpNullableDateTimeConverter : JsonConverter, ITransientDependency + { + private readonly IClock _clock; + private readonly AbpJsonOptions _options; + + public AbpNullableDateTimeConverter(IClock clock, IOptions abpJsonOptions) + { + _clock = clock; + _options = abpJsonOptions.Value; + } + + public override DateTime? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TryGetDateTime(out var dateTime)) + { + return _clock.Normalize(dateTime); + } + + return null; + } + + public override void Write(Utf8JsonWriter writer, DateTime? value, JsonSerializerOptions options) + { + if (value == null) + { + writer.WriteNullValue(); + } + else + { + if (_options.DefaultDateTimeFormat.IsNullOrWhiteSpace()) + { + writer.WriteStringValue(_clock.Normalize(value.Value)); + } + else + { + writer.WriteStringValue(_clock.Normalize(value.Value).ToString(_options.DefaultDateTimeFormat)); + } + } + } + } +} diff --git a/framework/src/Volo.Abp.Json/Volo/Abp/Json/Microsoft/JsonConverters/ObjectToInferredTypesConverter.cs b/framework/src/Volo.Abp.Json/Volo/Abp/Json/Microsoft/JsonConverters/ObjectToInferredTypesConverter.cs new file mode 100644 index 0000000000..af29e55a3a --- /dev/null +++ b/framework/src/Volo.Abp.Json/Volo/Abp/Json/Microsoft/JsonConverters/ObjectToInferredTypesConverter.cs @@ -0,0 +1,54 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Volo.Abp.Json.Microsoft.JsonConverters +{ + public class ObjectToInferredTypesConverter : JsonConverter + { + public override object Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TokenType == JsonTokenType.True) + { + return true; + } + + if (reader.TokenType == JsonTokenType.False) + { + return false; + } + + if (reader.TokenType == JsonTokenType.Number) + { + if (reader.TryGetInt64(out var l)) + { + return l; + } + + return reader.GetDouble(); + } + + if (reader.TokenType == JsonTokenType.String) + { + if (reader.TryGetDateTime(out var datetime)) + { + return datetime; + } + + return reader.GetString(); + } + + // Use JsonElement as fallback. + // Newtonsoft uses JArray or JObject. + using (var document = JsonDocument.ParseValue(ref reader)) + { + return document.RootElement.Clone(); + } + } + + public override void Write(Utf8JsonWriter writer, object objectToWrite, JsonSerializerOptions options) + { + throw new InvalidOperationException("Should not get here."); + } + } +} diff --git a/framework/src/Volo.Abp.Localization/Volo.Abp.Localization.csproj b/framework/src/Volo.Abp.Localization/Volo.Abp.Localization.csproj index df04ab95df..64352257f3 100644 --- a/framework/src/Volo.Abp.Localization/Volo.Abp.Localization.csproj +++ b/framework/src/Volo.Abp.Localization/Volo.Abp.Localization.csproj @@ -19,10 +19,6 @@ - - - - diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Json/JsonLocalizationDictionaryBuilder.cs b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Json/JsonLocalizationDictionaryBuilder.cs index 9b1f1617f6..c13fb643bd 100644 --- a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Json/JsonLocalizationDictionaryBuilder.cs +++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Json/JsonLocalizationDictionaryBuilder.cs @@ -1,19 +1,13 @@ using System; using System.Collections.Generic; using System.IO; +using System.Text.Json; using Microsoft.Extensions.Localization; -using Newtonsoft.Json; -using Newtonsoft.Json.Serialization; namespace Volo.Abp.Localization.Json { public static class JsonLocalizationDictionaryBuilder { - private static readonly JsonSerializerSettings SharedJsonSerializerSettings = new JsonSerializerSettings - { - ContractResolver = new CamelCasePropertyNamesContractResolver() - }; - /// /// Builds an from given file. /// @@ -39,8 +33,13 @@ namespace Volo.Abp.Localization.Json JsonLocalizationFile jsonFile; try { - jsonFile = JsonConvert.DeserializeObject( - jsonString, SharedJsonSerializerSettings); + var options = new JsonSerializerOptions + { + PropertyNameCaseInsensitive = true, + DictionaryKeyPolicy = JsonNamingPolicy.CamelCase + }; + + jsonFile = JsonSerializer.Deserialize(jsonString, options); } catch (JsonException ex) { @@ -80,4 +79,4 @@ namespace Volo.Abp.Localization.Json return new StaticLocalizationDictionary(cultureCode, dictionary); } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Json/JsonLocalizationFile.cs b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Json/JsonLocalizationFile.cs index c2dc911532..2af738221a 100644 --- a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Json/JsonLocalizationFile.cs +++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Json/JsonLocalizationFile.cs @@ -9,11 +9,11 @@ namespace Volo.Abp.Localization.Json /// public string Culture { get; set; } - public Dictionary Texts { get; } + public Dictionary Texts { get; set; } public JsonLocalizationFile() { Texts = new Dictionary(); } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/Utf8JsonMemoryDbSerializer.cs b/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/Utf8JsonMemoryDbSerializer.cs index e68b4b6f37..e0040a678d 100644 --- a/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/Utf8JsonMemoryDbSerializer.cs +++ b/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/Utf8JsonMemoryDbSerializer.cs @@ -1,52 +1,27 @@ using System; -using System.Reflection; -using System.Text; -using Newtonsoft.Json; -using Newtonsoft.Json.Serialization; +using System.Text.Json; +using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; -using Volo.Abp.Json; namespace Volo.Abp.Domain.Repositories.MemoryDb { public class Utf8JsonMemoryDbSerializer : IMemoryDbSerializer, ITransientDependency { - private static readonly JsonSerializerSettings MemoryDbSerializerSettings; + protected Utf8JsonMemoryDbSerializerOptions Options { get; } - static Utf8JsonMemoryDbSerializer() + public Utf8JsonMemoryDbSerializer(IOptions options) { - MemoryDbSerializerSettings = new JsonSerializerSettings - { - ContractResolver = new ResolverWithPrivateSetters(), - ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor - }; + Options = options.Value; } byte[] IMemoryDbSerializer.Serialize(object obj) { - var jsonString = JsonConvert.SerializeObject(obj, MemoryDbSerializerSettings); - return Encoding.UTF8.GetBytes(jsonString); + return JsonSerializer.SerializeToUtf8Bytes(obj, Options.JsonSerializerOptions); } public object Deserialize(byte[] value, Type type) { - var jsonString = Encoding.UTF8.GetString(value); - return JsonConvert.DeserializeObject(jsonString, type, MemoryDbSerializerSettings); - } - - public class ResolverWithPrivateSetters : DefaultContractResolver - { - protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) - { - var prop = base.CreateProperty(member, memberSerialization); - if (prop.Writable) - { - return prop; - } - - prop.Writable = member.As()?.GetSetMethod(true) != null; - - return prop; - } + return JsonSerializer.Deserialize(value, type, Options.JsonSerializerOptions); } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/Utf8JsonMemoryDbSerializerOptions.cs b/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/Utf8JsonMemoryDbSerializerOptions.cs new file mode 100644 index 0000000000..a31e9d5eff --- /dev/null +++ b/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/Utf8JsonMemoryDbSerializerOptions.cs @@ -0,0 +1,14 @@ +using System.Text.Json; + +namespace Volo.Abp.Domain.Repositories.MemoryDb +{ + public class Utf8JsonMemoryDbSerializerOptions + { + public JsonSerializerOptions JsonSerializerOptions { get; } + + public Utf8JsonMemoryDbSerializerOptions() + { + JsonSerializerOptions = new JsonSerializerOptions(); + } + } +} diff --git a/framework/test/Volo.Abp.AspNetCore.Authentication.OAuth.Tests/Volo/Abp/AspNetCore/Authentication/OAuth/Claims/MultipleClaimAction_Tests.cs b/framework/test/Volo.Abp.AspNetCore.Authentication.OAuth.Tests/Volo/Abp/AspNetCore/Authentication/OAuth/Claims/MultipleClaimAction_Tests.cs index bf869fc809..dd53e82167 100644 --- a/framework/test/Volo.Abp.AspNetCore.Authentication.OAuth.Tests/Volo/Abp/AspNetCore/Authentication/OAuth/Claims/MultipleClaimAction_Tests.cs +++ b/framework/test/Volo.Abp.AspNetCore.Authentication.OAuth.Tests/Volo/Abp/AspNetCore/Authentication/OAuth/Claims/MultipleClaimAction_Tests.cs @@ -1,7 +1,6 @@ using System.Linq; using System.Security.Claims; using System.Text.Json; -using Newtonsoft.Json.Linq; using Shouldly; using Volo.Abp.Security.Claims; using Xunit; diff --git a/framework/test/Volo.Abp.AspNetCore.Tests/Volo/Abp/AspNetCore/AbpAspNetCoreTestBase.cs b/framework/test/Volo.Abp.AspNetCore.Tests/Volo/Abp/AspNetCore/AbpAspNetCoreTestBase.cs index dd5edff807..3c5571f115 100644 --- a/framework/test/Volo.Abp.AspNetCore.Tests/Volo/Abp/AspNetCore/AbpAspNetCoreTestBase.cs +++ b/framework/test/Volo.Abp.AspNetCore.Tests/Volo/Abp/AspNetCore/AbpAspNetCoreTestBase.cs @@ -1,10 +1,8 @@ using System.Globalization; using System.Net; using System.Net.Http; -using System.Net.Http.Headers; +using System.Text.Json; using System.Threading.Tasks; -using Newtonsoft.Json; -using Newtonsoft.Json.Serialization; using Shouldly; using Volo.Abp.AspNetCore.TestBase; @@ -18,16 +16,10 @@ namespace Volo.Abp.AspNetCore public abstract class AbpAspNetCoreTestBase : AbpAspNetCoreIntegratedTestBase where TStartup : class { - private static readonly JsonSerializerSettings SharedJsonSerializerSettings = - new JsonSerializerSettings - { - ContractResolver = new CamelCasePropertyNamesContractResolver() - }; - protected virtual async Task GetResponseAsObjectAsync(string url, HttpStatusCode expectedStatusCode = HttpStatusCode.OK) { var strResponse = await GetResponseAsStringAsync(url, expectedStatusCode); - return JsonConvert.DeserializeObject(strResponse, SharedJsonSerializerSettings); + return JsonSerializer.Deserialize(strResponse, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); } protected virtual async Task GetResponseAsStringAsync(string url, HttpStatusCode expectedStatusCode = HttpStatusCode.OK) @@ -49,4 +41,4 @@ namespace Volo.Abp.AspNetCore } } } -} \ No newline at end of file +} diff --git a/framework/test/Volo.Abp.MemoryDb.Tests/Volo/Abp/MemoryDb/AbpMemoryDbTestModule.cs b/framework/test/Volo.Abp.MemoryDb.Tests/Volo/Abp/MemoryDb/AbpMemoryDbTestModule.cs index 7e5d9fcb6b..05839d5c8e 100644 --- a/framework/test/Volo.Abp.MemoryDb.Tests/Volo/Abp/MemoryDb/AbpMemoryDbTestModule.cs +++ b/framework/test/Volo.Abp.MemoryDb.Tests/Volo/Abp/MemoryDb/AbpMemoryDbTestModule.cs @@ -4,14 +4,16 @@ using Volo.Abp.Modularity; using Volo.Abp.TestApp.MemoryDb; using Volo.Abp.Data; using Volo.Abp.Autofac; +using Volo.Abp.Domain.Entities; +using Volo.Abp.Domain.Repositories.MemoryDb; using Volo.Abp.TestApp; using Volo.Abp.TestApp.Domain; namespace Volo.Abp.MemoryDb { [DependsOn( - typeof(TestAppModule), - typeof(AbpMemoryDbModule), + typeof(TestAppModule), + typeof(AbpMemoryDbModule), typeof(AbpAutofacModule))] public class AbpMemoryDbTestModule : AbpModule { @@ -29,6 +31,11 @@ namespace Volo.Abp.MemoryDb options.AddDefaultRepositories(); options.AddRepository(); }); + + Configure(options => + { + options.JsonSerializerOptions.Converters.Add(new EntityJsonConverter()); + }); } } } diff --git a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/Repository_Basic_Tests_With_Int_Pk.cs b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/Repository_Basic_Tests_With_Int_Pk.cs index f873fe4265..821a80492b 100644 --- a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/Repository_Basic_Tests_With_Int_Pk.cs +++ b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/Repository_Basic_Tests_With_Int_Pk.cs @@ -1,4 +1,5 @@ using System.Linq; +using System.Text.Json; using System.Threading.Tasks; using Shouldly; using Volo.Abp.Domain.Repositories; diff --git a/modules/docs/src/Volo.Docs.Domain.Shared/Volo.Docs.Domain.Shared.csproj b/modules/docs/src/Volo.Docs.Domain.Shared/Volo.Docs.Domain.Shared.csproj index 99066c0b9b..d655e05df0 100644 --- a/modules/docs/src/Volo.Docs.Domain.Shared/Volo.Docs.Domain.Shared.csproj +++ b/modules/docs/src/Volo.Docs.Domain.Shared/Volo.Docs.Domain.Shared.csproj @@ -13,5 +13,9 @@ + + + + diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/AbpFeatureManagementApplicationContractsModule.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/AbpFeatureManagementApplicationContractsModule.cs index 37b49f2d8a..add06e1e14 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/AbpFeatureManagementApplicationContractsModule.cs +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/AbpFeatureManagementApplicationContractsModule.cs @@ -1,5 +1,7 @@ using Volo.Abp.Application; -using Volo.Abp.Json.Newtonsoft; +using Volo.Abp.FeatureManagement.JsonConverters; +using Volo.Abp.Json; +using Volo.Abp.Json.Microsoft; using Volo.Abp.Modularity; using Volo.Abp.VirtualFileSystem; @@ -7,7 +9,8 @@ namespace Volo.Abp.FeatureManagement { [DependsOn( typeof(AbpFeatureManagementDomainSharedModule), - typeof(AbpDddApplicationModule) + typeof(AbpDddApplicationModule), + typeof(AbpJsonModule) )] public class AbpFeatureManagementApplicationContractsModule : AbpModule { @@ -18,9 +21,9 @@ namespace Volo.Abp.FeatureManagement options.FileSets.AddEmbedded(); }); - Configure(options => + Configure(options => { - options.Converters.Add(); + options.JsonSerializerOptions.Converters.Add(new StringValueTypeJsonConverter()); }); } } diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/LocalizableStringInfoJsonConverter.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/LocalizableStringInfoJsonConverter.cs new file mode 100644 index 0000000000..e9f5cf599c --- /dev/null +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/LocalizableStringInfoJsonConverter.cs @@ -0,0 +1,24 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; +using Volo.Abp.Validation.StringValues; + +namespace Volo.Abp.FeatureManagement.JsonConverters +{ + public class LocalizableStringInfoJsonConverter : JsonConverter + { + public override LocalizableStringInfo Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var rootElement = JsonDocument.ParseValue(ref reader).RootElement; + return new LocalizableStringInfo( + rootElement.GetProperty("ResourceName").GetString(), + rootElement.GetProperty("Name").GetString() + ); + } + + public override void Write(Utf8JsonWriter writer, LocalizableStringInfo value, JsonSerializerOptions options) + { + JsonSerializer.Serialize(writer, value); + } + } +} diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/SelectionStringValueItemJsonConverter.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/SelectionStringValueItemJsonConverter.cs new file mode 100644 index 0000000000..59b2f77c6b --- /dev/null +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/SelectionStringValueItemJsonConverter.cs @@ -0,0 +1,36 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; +using Volo.Abp.Validation.StringValues; + +namespace Volo.Abp.FeatureManagement.JsonConverters +{ + public class SelectionStringValueItemJsonConverter : JsonConverter + { + public override ISelectionStringValueItem Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var rootElement = JsonDocument.ParseValue(ref reader).RootElement; + + var jsonSerializerOptions = new JsonSerializerOptions(); + jsonSerializerOptions.Converters.Add(new LocalizableStringInfoJsonConverter()); + + return new LocalizableSelectionStringValueItem + { + Value = rootElement.GetProperty("Value").GetString(), + DisplayText = JsonSerializer.Deserialize(rootElement.GetProperty("DisplayText").GetRawText(), jsonSerializerOptions) + }; + } + + public override void Write(Utf8JsonWriter writer, ISelectionStringValueItem value, JsonSerializerOptions options) + { + if (value.GetType() == typeof(LocalizableStringInfo)) + { + JsonSerializer.Serialize(writer, (LocalizableSelectionStringValueItem)value); + } + else + { + throw new JsonException("Unknown ISelectionStringValueItem type!"); + } + } + } +} diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/SelectionStringValueItemSourceJsonConverter.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/SelectionStringValueItemSourceJsonConverter.cs new file mode 100644 index 0000000000..b523dba20b --- /dev/null +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/SelectionStringValueItemSourceJsonConverter.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Text.Json; +using System.Text.Json.Serialization; +using Volo.Abp.Validation.StringValues; + +namespace Volo.Abp.FeatureManagement.JsonConverters +{ + public class SelectionStringValueItemSourceJsonConverter : JsonConverter + { + public override ISelectionStringValueItemSource Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var rootElement = JsonDocument.ParseValue(ref reader).RootElement; + var jsonSerializerOptions = new JsonSerializerOptions(); + jsonSerializerOptions.Converters.Add(new SelectionStringValueItemJsonConverter()); + + var selectionStringValueItem = + JsonSerializer.Deserialize>(rootElement.GetProperty("Items").GetRawText(), jsonSerializerOptions) ?? + new List(); + + return new StaticSelectionStringValueItemSource(selectionStringValueItem.ToArray()); + } + + public override void Write(Utf8JsonWriter writer, ISelectionStringValueItemSource value, JsonSerializerOptions options) + { + if (value.GetType() == typeof(StaticSelectionStringValueItemSource)) + { + JsonSerializer.Serialize(writer, (StaticSelectionStringValueItemSource)value); + } + else + { + throw new JsonException("Unknown ISelectionStringValueItemSource type!"); + } + } + } +} diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/StringValueTypeJsonConverter.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/StringValueTypeJsonConverter.cs new file mode 100644 index 0000000000..5cdaf352bb --- /dev/null +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/StringValueTypeJsonConverter.cs @@ -0,0 +1,47 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; +using Volo.Abp.Validation.StringValues; + +namespace Volo.Abp.FeatureManagement.JsonConverters +{ + public class StringValueTypeJsonConverter : JsonConverter + { + public override IStringValueType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var rootElement = JsonDocument.ParseValue(ref reader).RootElement; + var jsonSerializerOptions = new JsonSerializerOptions(); + jsonSerializerOptions.Converters.Add(new ValueValidatorJsonConverter()); + jsonSerializerOptions.Converters.Add(new SelectionStringValueItemSourceJsonConverter()); + + var name = rootElement.GetProperty("Name").GetString(); + return name switch + { + "SelectionStringValueType" => JsonSerializer.Deserialize(rootElement.GetRawText(), jsonSerializerOptions), + "FreeTextStringValueType" => JsonSerializer.Deserialize(rootElement.GetRawText(), jsonSerializerOptions), + "ToggleStringValueType" => JsonSerializer.Deserialize(rootElement.GetRawText(), jsonSerializerOptions), + _ => throw new ArgumentException($"{nameof(IStringValueType)} named {name} was not found!") + }; + } + + public override void Write(Utf8JsonWriter writer, IStringValueType value, JsonSerializerOptions options) + { + if (value.GetType() == typeof(FreeTextStringValueType)) + { + JsonSerializer.Serialize(writer, (FreeTextStringValueType)value); + } + else if (value.GetType() == typeof(SelectionStringValueType)) + { + JsonSerializer.Serialize(writer, (SelectionStringValueType)value); + } + else if (value.GetType() == typeof(ToggleStringValueType)) + { + JsonSerializer.Serialize(writer, (ToggleStringValueType)value); + } + else + { + throw new JsonException("Unknown IStringValueType type!"); + } + } + } +} diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/ValueValidatorJsonConverter.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/ValueValidatorJsonConverter.cs new file mode 100644 index 0000000000..cefa97a6aa --- /dev/null +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/ValueValidatorJsonConverter.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.Json; +using System.Text.Json.Serialization; +using Volo.Abp.Json.Microsoft.JsonConverters; +using Volo.Abp.Validation.StringValues; + +namespace Volo.Abp.FeatureManagement.JsonConverters +{ + public class ValueValidatorJsonConverter : JsonConverter + { + public override IValueValidator Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var rootElement = JsonDocument.ParseValue(ref reader).RootElement; + var valueValidator = CreateValueValidatorByName(rootElement.GetProperty("Name").GetString()); + + var deserializeOptions = new JsonSerializerOptions(); + deserializeOptions.Converters.Add(new ObjectToInferredTypesConverter()); + var properties = JsonSerializer.Deserialize>(rootElement.GetProperty("Properties").GetRawText(), deserializeOptions); + if (properties != null && properties.Any()) + { + foreach (var property in properties) + { + valueValidator.Properties[property.Key] = property.Value; + } + } + + return valueValidator; + } + + public override void Write(Utf8JsonWriter writer, IValueValidator value, JsonSerializerOptions options) + { + if (value.GetType() == typeof(AlwaysValidValueValidator)) + { + JsonSerializer.Serialize(writer, (AlwaysValidValueValidator)value); + } + else if (value.GetType() == typeof(BooleanValueValidator)) + { + JsonSerializer.Serialize(writer, (BooleanValueValidator)value); + } + else if (value.GetType() == typeof(NumericValueValidator)) + { + JsonSerializer.Serialize(writer, (NumericValueValidator)value); + } + else if (value.GetType() == typeof(StringValueValidator)) + { + JsonSerializer.Serialize(writer, (StringValueValidator)value); + } + else + { + throw new JsonException("Unknown IValueValidator type!"); + } + } + + protected virtual IValueValidator CreateValueValidatorByName(string name) + { + return name switch + { + "NULL" => new AlwaysValidValueValidator(), + "BOOLEAN" => new BooleanValueValidator(), + "NUMERIC" => new NumericValueValidator(), + "STRING" => new StringValueValidator(), + _ => throw new ArgumentException($"{nameof(IValueValidator)} named {name} was not found!") + }; + } + } +} diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/StringValueTypeJsonConverter.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/StringValueTypeJsonConverter.cs deleted file mode 100644 index 0ee276cce1..0000000000 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/StringValueTypeJsonConverter.cs +++ /dev/null @@ -1,90 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using Volo.Abp.DependencyInjection; -using Volo.Abp.Validation.StringValues; - -namespace Volo.Abp.FeatureManagement -{ - public class StringValueTypeJsonConverter : JsonConverter, ITransientDependency - { - public override bool CanWrite => false; - - public override bool CanConvert(Type objectType) - { - return objectType == typeof(IStringValueType); - } - - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - throw new NotImplementedException("This method should not be called to write (since CanWrite is false)."); - } - - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) - { - if (reader.TokenType != JsonToken.StartObject) - { - return null; - } - - var jsonObject = JObject.Load(reader); - - var stringValue = CreateStringValueTypeByName(jsonObject, jsonObject["name"].ToString()); - foreach (var o in serializer.Deserialize>( - new JsonTextReader(new StringReader(jsonObject["properties"].ToString())))) - { - stringValue[o.Key] = o.Value; - } - - stringValue.Validator = CreateValueValidatorByName(jsonObject["validator"], jsonObject["validator"]["name"].ToString()); - foreach (var o in serializer.Deserialize>( - new JsonTextReader(new StringReader(jsonObject["validator"]["properties"].ToString())))) - { - stringValue.Validator[o.Key] = o.Value; - } - - return stringValue; - } - - protected virtual IStringValueType CreateStringValueTypeByName(JObject jObject, string name) - { - if (name == "SelectionStringValueType") - { - var selectionStringValueType = new SelectionStringValueType(); - if (jObject["itemSource"].HasValues) - { - selectionStringValueType.ItemSource = new StaticSelectionStringValueItemSource(jObject["itemSource"]["items"] - .Select(item => new LocalizableSelectionStringValueItem() - { - Value = item["value"].ToString(), - DisplayText = new LocalizableStringInfo(item["displayText"]["resourceName"].ToString(), item["displayText"]["name"].ToString()) - }).ToArray()); - } - - return selectionStringValueType; - } - - return name switch - { - "FreeTextStringValueType" => new FreeTextStringValueType(), - "ToggleStringValueType" => new ToggleStringValueType(), - _ => throw new ArgumentException($"{nameof(IStringValueType)} named {name} was not found!") - }; - } - - protected virtual IValueValidator CreateValueValidatorByName(JToken jObject, string name) - { - return name switch - { - "NULL" => new AlwaysValidValueValidator(), - "BOOLEAN" => new BooleanValueValidator(), - "NUMERIC" => new NumericValueValidator(), - "STRING" => new StringValueValidator(), - _ => throw new ArgumentException($"{nameof(IValueValidator)} named {name} was not found!") - }; - } - } -} diff --git a/modules/feature-management/test/Volo.Abp.FeatureManagement.Application.Tests/Volo/Abp/FeatureManagement/StringValueJsonConverter_Tests.cs b/modules/feature-management/test/Volo.Abp.FeatureManagement.Application.Tests/Volo/Abp/FeatureManagement/StringValueJsonConverter_Tests.cs index 1b7553b773..4e5d4b20a3 100644 --- a/modules/feature-management/test/Volo.Abp.FeatureManagement.Application.Tests/Volo/Abp/FeatureManagement/StringValueJsonConverter_Tests.cs +++ b/modules/feature-management/test/Volo.Abp.FeatureManagement.Application.Tests/Volo/Abp/FeatureManagement/StringValueJsonConverter_Tests.cs @@ -1,6 +1,6 @@ using System; using System.Collections.Generic; -using Newtonsoft.Json; +using System.Text.Json; using Shouldly; using Volo.Abp.Json; using Volo.Abp.Validation.StringValues; @@ -66,9 +66,11 @@ namespace Volo.Abp.FeatureManagement } }; - var serialized = _jsonSerializer.Serialize(featureListDto, indented: true); + var serialized = _jsonSerializer.Serialize(featureListDto); + var featureListDto2 = _jsonSerializer.Deserialize(serialized); + featureListDto2.ShouldNotBeNull(); featureListDto2.Groups[0].Features[0].ValueType.ShouldBeOfType(); featureListDto2.Groups[0].Features[0].ValueType.Validator.ShouldBeOfType(); diff --git a/nupkg/common.ps1 b/nupkg/common.ps1 index 29cb13d9f3..3df9140805 100644 --- a/nupkg/common.ps1 +++ b/nupkg/common.ps1 @@ -109,6 +109,7 @@ $projects = ( "framework/src/Volo.Abp.Http", "framework/src/Volo.Abp.IdentityModel", "framework/src/Volo.Abp.Json", + "framework/src/Volo.Abp.Json.Newtonsoft", "framework/src/Volo.Abp.Ldap", "framework/src/Volo.Abp.Localization.Abstractions", "framework/src/Volo.Abp.MailKit", From 0bde769e116d578e0499770f81a038446f8a61ff Mon Sep 17 00:00:00 2001 From: maliming Date: Tue, 27 Oct 2020 14:48:54 +0800 Subject: [PATCH 027/566] Revert to use Newtonsoft for IAuditSerializer. Add JsonNetAuditSerializer_Test. --- .../Volo.Abp.Auditing.csproj | 4 ++ .../Abp/Auditing/AuditingContractResolver.cs | 43 ++++++++++++ .../AuditingRuntimeIgnoreConverter.cs | 45 ------------- .../Abp/Auditing/JsonNetAuditSerializer.cs | 27 ++++++-- .../Auditing/JsonNetAuditSerializer_Test.cs | 67 +++++++++++++++++++ 5 files changed, 135 insertions(+), 51 deletions(-) create mode 100644 framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingContractResolver.cs delete mode 100644 framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingRuntimeIgnoreConverter.cs create mode 100644 framework/test/Volo.Abp.Auditing.Tests/Volo/Abp/Auditing/JsonNetAuditSerializer_Test.cs diff --git a/framework/src/Volo.Abp.Auditing/Volo.Abp.Auditing.csproj b/framework/src/Volo.Abp.Auditing/Volo.Abp.Auditing.csproj index 4ac2420c8f..b3548a949b 100644 --- a/framework/src/Volo.Abp.Auditing/Volo.Abp.Auditing.csproj +++ b/framework/src/Volo.Abp.Auditing/Volo.Abp.Auditing.csproj @@ -22,5 +22,9 @@ + + + + diff --git a/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingContractResolver.cs b/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingContractResolver.cs new file mode 100644 index 0000000000..a88de55aea --- /dev/null +++ b/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingContractResolver.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using Newtonsoft.Json; +using Newtonsoft.Json.Serialization; + +namespace Volo.Abp.Auditing +{ + public class AuditingContractResolver : CamelCasePropertyNamesContractResolver + { + private readonly List _ignoredTypes; + + public AuditingContractResolver(List ignoredTypes) + { + _ignoredTypes = ignoredTypes; + } + + protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) + { + var property = base.CreateProperty(member, memberSerialization); + + if (_ignoredTypes.Any(ignoredType => ignoredType.GetTypeInfo().IsAssignableFrom(property.PropertyType))) + { + property.ShouldSerialize = instance => false; + return property; + } + + if (member.DeclaringType != null && (member.DeclaringType.IsDefined(typeof(DisableAuditingAttribute)) || member.DeclaringType.IsDefined(typeof(JsonIgnoreAttribute)))) + { + property.ShouldSerialize = instance => false; + return property; + } + + if (member.IsDefined(typeof(DisableAuditingAttribute)) || member.IsDefined(typeof(JsonIgnoreAttribute))) + { + property.ShouldSerialize = instance => false; + } + + return property; + } + } +} diff --git a/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingRuntimeIgnoreConverter.cs b/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingRuntimeIgnoreConverter.cs deleted file mode 100644 index 240b2581ab..0000000000 --- a/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingRuntimeIgnoreConverter.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace Volo.Abp.Auditing -{ - public class AuditingRuntimeIgnoreConverter : JsonConverter> - { - private readonly List _ignoredTypes; - - public AuditingRuntimeIgnoreConverter(List ignoredTypes) - { - _ignoredTypes = ignoredTypes; - } - - public override Dictionary Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - throw new JsonException(); - } - - public override void Write(Utf8JsonWriter writer, Dictionary value, JsonSerializerOptions options) - { - var newDictionary = new Dictionary(); - foreach (var item in value.Where(x => x.Value != null)) - { - if (item.GetType().IsDefined(typeof(DisableAuditingAttribute), true) || - item.GetType().IsDefined(typeof(JsonIgnoreAttribute), true)) - { - continue; - } - - if (_ignoredTypes.Any(x => x.IsInstanceOfType(item.Value))) - { - continue; - } - - newDictionary[item.Key] = item.Value; - } - - JsonSerializer.Serialize(writer, newDictionary); - } - } -} diff --git a/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/JsonNetAuditSerializer.cs b/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/JsonNetAuditSerializer.cs index d11886e5a7..b1ce95675b 100644 --- a/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/JsonNetAuditSerializer.cs +++ b/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/JsonNetAuditSerializer.cs @@ -1,5 +1,5 @@ -using System.Text.Json; using Microsoft.Extensions.Options; +using Newtonsoft.Json; using Volo.Abp.DependencyInjection; namespace Volo.Abp.Auditing @@ -16,14 +16,29 @@ namespace Volo.Abp.Auditing public string Serialize(object obj) { - return JsonSerializer.Serialize(obj, GetJsonSerializerOptions()); + return JsonConvert.SerializeObject(obj, GetSharedJsonSerializerSettings()); } - private JsonSerializerOptions GetJsonSerializerOptions() + private static readonly object SyncObj = new object(); + private static JsonSerializerSettings _sharedJsonSerializerSettings; + + private JsonSerializerSettings GetSharedJsonSerializerSettings() { - var options = new JsonSerializerOptions(); - options.Converters.Add(new AuditingRuntimeIgnoreConverter(Options.IgnoredTypes)); - return options; + if (_sharedJsonSerializerSettings == null) + { + lock (SyncObj) + { + if (_sharedJsonSerializerSettings == null) + { + _sharedJsonSerializerSettings = new JsonSerializerSettings + { + ContractResolver = new AuditingContractResolver(Options.IgnoredTypes) + }; + } + } + } + + return _sharedJsonSerializerSettings; } } } diff --git a/framework/test/Volo.Abp.Auditing.Tests/Volo/Abp/Auditing/JsonNetAuditSerializer_Test.cs b/framework/test/Volo.Abp.Auditing.Tests/Volo/Abp/Auditing/JsonNetAuditSerializer_Test.cs new file mode 100644 index 0000000000..da98f49bd6 --- /dev/null +++ b/framework/test/Volo.Abp.Auditing.Tests/Volo/Abp/Auditing/JsonNetAuditSerializer_Test.cs @@ -0,0 +1,67 @@ +using System; +using System.Collections.Generic; +using Microsoft.Extensions.DependencyInjection; +using Shouldly; +using Xunit; + +namespace Volo.Abp.Auditing +{ + public class JsonNetAuditSerializer_Test : AbpAuditingTestBase + { + private readonly JsonNetAuditSerializer _jsonNetAuditSerializer; + + public JsonNetAuditSerializer_Test() + { + _jsonNetAuditSerializer = GetRequiredService(); + } + + protected override void AfterAddApplication(IServiceCollection services) + { + services.Configure(options => + { + options.IgnoredTypes.Add(typeof(DateTime)); + }); + + base.AfterAddApplication(services); + } + + [Fact] + public void Serialize_Test() + { + var arguments = new Dictionary + { + {"input", new InputDto {PersonData = "IdCard:123123"}}, + {"input2", new Input2Dto {UserName = "admin", Password = "1q2w3E*", Birthday = DateTime.Now}} + }; + + var str = _jsonNetAuditSerializer.Serialize(arguments); + + str.ShouldNotContain("IdCard"); + str.ShouldNotContain("1q2w3E*"); + str.ShouldNotContain("Birthday"); + + str.ShouldContain("UserName"); + str.ShouldContain("admin"); + } + + + [DisableAuditing] + class InputDto + { + public string PersonData { get; set; } + } + + class Input2Dto + { + public string UserName { get; set; } + + [DisableAuditing] + public string Password { get; set; } + + [Newtonsoft.Json.JsonIgnore] + public string PrivateEmail { get; set; } + + public DateTime Birthday { get; set; } + } + } +} From 0778e380be9488bec56607776889e57498b29da7 Mon Sep 17 00:00:00 2001 From: maliming Date: Tue, 27 Oct 2020 15:24:23 +0800 Subject: [PATCH 028/566] Rename namespaces. --- .../Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs | 2 +- .../Volo/Abp/AspNetCore/Mvc/Json/AbpJsonOptionsSetup.cs | 4 ++-- .../ValueConverters/AbpJsonValueConverter.cs | 2 +- .../ValueConverters/ExtraPropertiesValueConverter.cs | 2 +- .../Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/AbpJsonModule.cs | 2 +- framework/src/Volo.Abp.Json/Volo/Abp/Json/AbpJsonModule.cs | 1 - .../Volo/Abp/Json/{Microsoft => }/AbpJsonSerializer.cs | 2 +- .../Abp/Json/{Microsoft => }/AbpJsonSerializerOptions.cs | 2 +- .../Json/{Microsoft => }/AbpJsonSerializerOptionsSetup.cs | 5 +++-- .../{Microsoft => }/JsonConverters/AbpDateTimeConverter.cs | 2 +- .../JsonConverters/AbpNullableDateTimeConverter.cs | 2 +- .../JsonConverters/ObjectToInferredTypesConverter.cs | 2 +- .../Volo/Abp/MemoryDb/AbpMemoryDbTestModule.cs | 1 + .../Volo/Abp/MemoryDb/JsonConverters}/EntityJsonConverter.cs | 3 ++- .../AbpFeatureManagementApplicationContractsModule.cs | 2 +- .../JsonConverters/ValueValidatorJsonConverter.cs | 2 +- 16 files changed, 19 insertions(+), 17 deletions(-) rename framework/src/Volo.Abp.Json/Volo/Abp/Json/{Microsoft => }/AbpJsonSerializer.cs (97%) rename framework/src/Volo.Abp.Json/Volo/Abp/Json/{Microsoft => }/AbpJsonSerializerOptions.cs (94%) rename framework/src/Volo.Abp.Json/Volo/Abp/Json/{Microsoft => }/AbpJsonSerializerOptionsSetup.cs (90%) rename framework/src/Volo.Abp.Json/Volo/Abp/Json/{Microsoft => }/JsonConverters/AbpDateTimeConverter.cs (96%) rename framework/src/Volo.Abp.Json/Volo/Abp/Json/{Microsoft => }/JsonConverters/AbpNullableDateTimeConverter.cs (96%) rename framework/src/Volo.Abp.Json/Volo/Abp/Json/{Microsoft => }/JsonConverters/ObjectToInferredTypesConverter.cs (96%) rename framework/{src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities => test/Volo.Abp.MemoryDb.Tests/Volo/Abp/MemoryDb/JsonConverters}/EntityJsonConverter.cs (92%) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs index f35721c3c0..0897c69ed3 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs @@ -35,7 +35,7 @@ using Volo.Abp.Http; using Volo.Abp.DynamicProxy; using Volo.Abp.GlobalFeatures; using Volo.Abp.Http.Modeling; -using Volo.Abp.Json.Microsoft; +using Volo.Abp.Json; using Volo.Abp.Localization; using Volo.Abp.Modularity; using Volo.Abp.UI; diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpJsonOptionsSetup.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpJsonOptionsSetup.cs index f9d58a3918..821b2c9218 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpJsonOptionsSetup.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpJsonOptionsSetup.cs @@ -2,8 +2,8 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; -using Volo.Abp.Json.Microsoft; -using Volo.Abp.Json.Microsoft.JsonConverters; +using Volo.Abp.Json.JsonConverters; +using Volo.Abp.Json; namespace Volo.Abp.AspNetCore.Mvc.Json { diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ValueConverters/AbpJsonValueConverter.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ValueConverters/AbpJsonValueConverter.cs index 4955a703b3..afce924d59 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ValueConverters/AbpJsonValueConverter.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ValueConverters/AbpJsonValueConverter.cs @@ -1,6 +1,6 @@ using System.Text.Json; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Volo.Abp.Json.Microsoft.JsonConverters; +using Volo.Abp.Json.JsonConverters; namespace Volo.Abp.EntityFrameworkCore.ValueConverters { diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ValueConverters/ExtraPropertiesValueConverter.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ValueConverters/ExtraPropertiesValueConverter.cs index b94a433367..00ce8459a6 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ValueConverters/ExtraPropertiesValueConverter.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ValueConverters/ExtraPropertiesValueConverter.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Text.Json; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Volo.Abp.Json.Microsoft.JsonConverters; +using Volo.Abp.Json.JsonConverters; using Volo.Abp.ObjectExtending; namespace Volo.Abp.EntityFrameworkCore.ValueConverters diff --git a/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/AbpJsonModule.cs b/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/AbpJsonModule.cs index a502239e19..b040f1afbb 100644 --- a/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/AbpJsonModule.cs +++ b/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/AbpJsonModule.cs @@ -1,7 +1,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Options; -using Volo.Abp.Json.Microsoft; +using Volo.Abp.Json; using Volo.Abp.Json.Newtonsoft; using Volo.Abp.Modularity; diff --git a/framework/src/Volo.Abp.Json/Volo/Abp/Json/AbpJsonModule.cs b/framework/src/Volo.Abp.Json/Volo/Abp/Json/AbpJsonModule.cs index 2899a8ed6b..c5376d0f05 100644 --- a/framework/src/Volo.Abp.Json/Volo/Abp/Json/AbpJsonModule.cs +++ b/framework/src/Volo.Abp.Json/Volo/Abp/Json/AbpJsonModule.cs @@ -1,7 +1,6 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Options; -using Volo.Abp.Json.Microsoft; using Volo.Abp.Modularity; using Volo.Abp.Timing; diff --git a/framework/src/Volo.Abp.Json/Volo/Abp/Json/Microsoft/AbpJsonSerializer.cs b/framework/src/Volo.Abp.Json/Volo/Abp/Json/AbpJsonSerializer.cs similarity index 97% rename from framework/src/Volo.Abp.Json/Volo/Abp/Json/Microsoft/AbpJsonSerializer.cs rename to framework/src/Volo.Abp.Json/Volo/Abp/Json/AbpJsonSerializer.cs index 55adc67ad4..250111fee2 100644 --- a/framework/src/Volo.Abp.Json/Volo/Abp/Json/Microsoft/AbpJsonSerializer.cs +++ b/framework/src/Volo.Abp.Json/Volo/Abp/Json/AbpJsonSerializer.cs @@ -3,7 +3,7 @@ using System.Text.Json; using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; -namespace Volo.Abp.Json.Microsoft +namespace Volo.Abp.Json { public class AbpJsonSerializer : IJsonSerializer, ITransientDependency { diff --git a/framework/src/Volo.Abp.Json/Volo/Abp/Json/Microsoft/AbpJsonSerializerOptions.cs b/framework/src/Volo.Abp.Json/Volo/Abp/Json/AbpJsonSerializerOptions.cs similarity index 94% rename from framework/src/Volo.Abp.Json/Volo/Abp/Json/Microsoft/AbpJsonSerializerOptions.cs rename to framework/src/Volo.Abp.Json/Volo/Abp/Json/AbpJsonSerializerOptions.cs index bbf92c77f4..c1289ce159 100644 --- a/framework/src/Volo.Abp.Json/Volo/Abp/Json/Microsoft/AbpJsonSerializerOptions.cs +++ b/framework/src/Volo.Abp.Json/Volo/Abp/Json/AbpJsonSerializerOptions.cs @@ -1,6 +1,6 @@ using System.Text.Json; -namespace Volo.Abp.Json.Microsoft +namespace Volo.Abp.Json { public class AbpJsonSerializerOptions { diff --git a/framework/src/Volo.Abp.Json/Volo/Abp/Json/Microsoft/AbpJsonSerializerOptionsSetup.cs b/framework/src/Volo.Abp.Json/Volo/Abp/Json/AbpJsonSerializerOptionsSetup.cs similarity index 90% rename from framework/src/Volo.Abp.Json/Volo/Abp/Json/Microsoft/AbpJsonSerializerOptionsSetup.cs rename to framework/src/Volo.Abp.Json/Volo/Abp/Json/AbpJsonSerializerOptionsSetup.cs index b06e884d4c..c4b9981199 100644 --- a/framework/src/Volo.Abp.Json/Volo/Abp/Json/Microsoft/AbpJsonSerializerOptionsSetup.cs +++ b/framework/src/Volo.Abp.Json/Volo/Abp/Json/AbpJsonSerializerOptionsSetup.cs @@ -1,9 +1,10 @@ using System; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; -using Volo.Abp.Json.Microsoft.JsonConverters; +using Volo.Abp.Json.JsonConverters; +using Volo.Abp.Json; -namespace Volo.Abp.Json.Microsoft +namespace Volo.Abp.Json { public class AbpJsonSerializerOptionsSetup : IConfigureOptions { diff --git a/framework/src/Volo.Abp.Json/Volo/Abp/Json/Microsoft/JsonConverters/AbpDateTimeConverter.cs b/framework/src/Volo.Abp.Json/Volo/Abp/Json/JsonConverters/AbpDateTimeConverter.cs similarity index 96% rename from framework/src/Volo.Abp.Json/Volo/Abp/Json/Microsoft/JsonConverters/AbpDateTimeConverter.cs rename to framework/src/Volo.Abp.Json/Volo/Abp/Json/JsonConverters/AbpDateTimeConverter.cs index e563ee8aac..7523f1e4d9 100644 --- a/framework/src/Volo.Abp.Json/Volo/Abp/Json/Microsoft/JsonConverters/AbpDateTimeConverter.cs +++ b/framework/src/Volo.Abp.Json/Volo/Abp/Json/JsonConverters/AbpDateTimeConverter.cs @@ -5,7 +5,7 @@ using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; using Volo.Abp.Timing; -namespace Volo.Abp.Json.Microsoft.JsonConverters +namespace Volo.Abp.Json.JsonConverters { public class AbpDateTimeConverter : JsonConverter, ITransientDependency { diff --git a/framework/src/Volo.Abp.Json/Volo/Abp/Json/Microsoft/JsonConverters/AbpNullableDateTimeConverter.cs b/framework/src/Volo.Abp.Json/Volo/Abp/Json/JsonConverters/AbpNullableDateTimeConverter.cs similarity index 96% rename from framework/src/Volo.Abp.Json/Volo/Abp/Json/Microsoft/JsonConverters/AbpNullableDateTimeConverter.cs rename to framework/src/Volo.Abp.Json/Volo/Abp/Json/JsonConverters/AbpNullableDateTimeConverter.cs index a072d1426c..0e1e20bedc 100644 --- a/framework/src/Volo.Abp.Json/Volo/Abp/Json/Microsoft/JsonConverters/AbpNullableDateTimeConverter.cs +++ b/framework/src/Volo.Abp.Json/Volo/Abp/Json/JsonConverters/AbpNullableDateTimeConverter.cs @@ -5,7 +5,7 @@ using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; using Volo.Abp.Timing; -namespace Volo.Abp.Json.Microsoft.JsonConverters +namespace Volo.Abp.Json.JsonConverters { public class AbpNullableDateTimeConverter : JsonConverter, ITransientDependency { diff --git a/framework/src/Volo.Abp.Json/Volo/Abp/Json/Microsoft/JsonConverters/ObjectToInferredTypesConverter.cs b/framework/src/Volo.Abp.Json/Volo/Abp/Json/JsonConverters/ObjectToInferredTypesConverter.cs similarity index 96% rename from framework/src/Volo.Abp.Json/Volo/Abp/Json/Microsoft/JsonConverters/ObjectToInferredTypesConverter.cs rename to framework/src/Volo.Abp.Json/Volo/Abp/Json/JsonConverters/ObjectToInferredTypesConverter.cs index af29e55a3a..4a3cd5e8df 100644 --- a/framework/src/Volo.Abp.Json/Volo/Abp/Json/Microsoft/JsonConverters/ObjectToInferredTypesConverter.cs +++ b/framework/src/Volo.Abp.Json/Volo/Abp/Json/JsonConverters/ObjectToInferredTypesConverter.cs @@ -2,7 +2,7 @@ using System.Text.Json; using System.Text.Json.Serialization; -namespace Volo.Abp.Json.Microsoft.JsonConverters +namespace Volo.Abp.Json.JsonConverters { public class ObjectToInferredTypesConverter : JsonConverter { diff --git a/framework/test/Volo.Abp.MemoryDb.Tests/Volo/Abp/MemoryDb/AbpMemoryDbTestModule.cs b/framework/test/Volo.Abp.MemoryDb.Tests/Volo/Abp/MemoryDb/AbpMemoryDbTestModule.cs index 05839d5c8e..6f5d7a3718 100644 --- a/framework/test/Volo.Abp.MemoryDb.Tests/Volo/Abp/MemoryDb/AbpMemoryDbTestModule.cs +++ b/framework/test/Volo.Abp.MemoryDb.Tests/Volo/Abp/MemoryDb/AbpMemoryDbTestModule.cs @@ -6,6 +6,7 @@ using Volo.Abp.Data; using Volo.Abp.Autofac; using Volo.Abp.Domain.Entities; using Volo.Abp.Domain.Repositories.MemoryDb; +using Volo.Abp.MemoryDb.JsonConverters; using Volo.Abp.TestApp; using Volo.Abp.TestApp.Domain; diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/EntityJsonConverter.cs b/framework/test/Volo.Abp.MemoryDb.Tests/Volo/Abp/MemoryDb/JsonConverters/EntityJsonConverter.cs similarity index 92% rename from framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/EntityJsonConverter.cs rename to framework/test/Volo.Abp.MemoryDb.Tests/Volo/Abp/MemoryDb/JsonConverters/EntityJsonConverter.cs index d472fd36d0..9a41fd4045 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/EntityJsonConverter.cs +++ b/framework/test/Volo.Abp.MemoryDb.Tests/Volo/Abp/MemoryDb/JsonConverters/EntityJsonConverter.cs @@ -1,8 +1,9 @@ using System; using System.Text.Json; using System.Text.Json.Serialization; +using Volo.Abp.Domain.Entities; -namespace Volo.Abp.Domain.Entities +namespace Volo.Abp.MemoryDb.JsonConverters { public class EntityJsonConverter : JsonConverter { diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/AbpFeatureManagementApplicationContractsModule.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/AbpFeatureManagementApplicationContractsModule.cs index add06e1e14..3c9303f968 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/AbpFeatureManagementApplicationContractsModule.cs +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/AbpFeatureManagementApplicationContractsModule.cs @@ -1,7 +1,7 @@ using Volo.Abp.Application; using Volo.Abp.FeatureManagement.JsonConverters; using Volo.Abp.Json; -using Volo.Abp.Json.Microsoft; +using Volo.Abp.Json; using Volo.Abp.Modularity; using Volo.Abp.VirtualFileSystem; diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/ValueValidatorJsonConverter.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/ValueValidatorJsonConverter.cs index cefa97a6aa..b525651d73 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/ValueValidatorJsonConverter.cs +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/ValueValidatorJsonConverter.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Text.Json; using System.Text.Json.Serialization; -using Volo.Abp.Json.Microsoft.JsonConverters; +using Volo.Abp.Json.JsonConverters; using Volo.Abp.Validation.StringValues; namespace Volo.Abp.FeatureManagement.JsonConverters From 55b2b3289c89f691db1c79d9d032e6b05be11b91 Mon Sep 17 00:00:00 2001 From: muhammedaltug Date: Tue, 27 Oct 2020 12:07:40 +0300 Subject: [PATCH 029/566] feat: add permission service - replace config state's getGrantedPolicy selector with permission service methods - config state's getGrantedPolicy selector deprecated - add injector to AbstractNavTreeService constructor - tests fix - parameter names change --- docs/en/UI/Angular/Permission-Management.md | 12 ++-- .../config/src/providers/route.provider.ts | 37 ++++++------ .../dev-app/src/app/route.provider.ts | 4 +- .../apps/dev-app/src/app/route.provider.ts | 4 +- .../config/src/providers/route.provider.ts | 4 +- .../packages/core/src/lib/directives/index.ts | 4 +- .../lib/directives/permission.directive.ts | 10 ++-- .../core/src/lib/guards/permission.guard.ts | 13 +++-- .../src/lib/services/config-state.service.ts | 1 + .../packages/core/src/lib/services/index.ts | 1 + .../src/lib/services/permission.service.ts | 58 +++++++++++++++++++ .../core/src/lib/services/routes.service.ts | 18 +++--- .../core/src/lib/states/config.state.ts | 3 + .../tests/dynamic-layout.component.spec.ts | 16 ++--- .../lib/tests/permission.directive.spec.ts | 14 +++-- .../src/lib/tests/permission.guard.spec.ts | 16 ++--- .../core/src/lib/tests/routes.service.spec.ts | 10 +--- .../core/src/lib/tests/utils/common.utils.ts | 28 +++++++++ .../core/src/lib/tests/utils/index.ts | 1 + .../utils/permission-service.spec.utils.ts | 7 +++ .../tests/utils/routes-service.spec.utils.ts | 12 ++++ .../core/src/lib/utils/route-utils.ts | 6 +- .../config/src/providers/route.provider.ts | 4 +- .../config/src/providers/route.provider.ts | 12 ++-- .../setting-management.component.ts | 4 +- .../components/routes/routes.component.html | 2 +- .../lib/components/routes/routes.component.ts | 4 +- .../src/lib/directives/loading.directive.ts | 4 +- .../src/lib/providers/route.provider.ts | 4 +- .../app/angular/src/app/route.provider.ts | 4 +- .../dev-app/src/app/route.provider.ts | 4 +- .../config/src/providers/route.provider.ts | 5 +- 32 files changed, 223 insertions(+), 103 deletions(-) create mode 100644 npm/ng-packs/packages/core/src/lib/services/permission.service.ts create mode 100644 npm/ng-packs/packages/core/src/lib/tests/utils/common.utils.ts create mode 100644 npm/ng-packs/packages/core/src/lib/tests/utils/index.ts create mode 100644 npm/ng-packs/packages/core/src/lib/tests/utils/permission-service.spec.utils.ts create mode 100644 npm/ng-packs/packages/core/src/lib/tests/utils/routes-service.spec.utils.ts diff --git a/docs/en/UI/Angular/Permission-Management.md b/docs/en/UI/Angular/Permission-Management.md index b9c4649c03..a6d7d13c14 100644 --- a/docs/en/UI/Angular/Permission-Management.md +++ b/docs/en/UI/Angular/Permission-Management.md @@ -2,18 +2,20 @@ A permission is a simple policy that is granted or prohibited for a particular user, role or client. You can read more about [authorization in ABP](../../Authorization.md) document. -You can get permission of authenticated user using `getGrantedPolicy` selector of `ConfigState`. +You can get permission of authenticated user using `getGrantedPolicy` or `getGrantedPolicy$` method of `PermissionService`. + +> ConfigState's getGrantedPolicy selector and ConfigStateService's getGrantedPolicy method deprecated. Use permission service's `getGrantedPolicy$` or `getGrantedPolicy`methods instead You can get permission as boolean value: ```js -import { ConfigStateService } from '@abp/ng.core'; +import { PermissionService } from '@abp/ng.core'; export class YourComponent { - constructor(private config: ConfigStateService) {} + constructor(private permissionService: PermissionService) {} ngOnInit(): void { - const canCreate = this.config.getGrantedPolicy('AbpIdentity.Roles.Create'); + const canCreate = this.permissionService.getGrantedPolicy('AbpIdentity.Roles.Create'); } } ``` @@ -59,4 +61,4 @@ Granted Policies are stored in the `auth` property of `ConfigState`. ## What's Next? -* [Multi Tenancy](./Multi-Tenancy.md) \ No newline at end of file +* [Multi Tenancy](./Multi-Tenancy.md) diff --git a/modules/cms-kit/angular/projects/cms-kit/config/src/providers/route.provider.ts b/modules/cms-kit/angular/projects/cms-kit/config/src/providers/route.provider.ts index 2fa8ce1bb8..a6cf4cefd8 100644 --- a/modules/cms-kit/angular/projects/cms-kit/config/src/providers/route.provider.ts +++ b/modules/cms-kit/angular/projects/cms-kit/config/src/providers/route.provider.ts @@ -1,27 +1,26 @@ import { eLayoutType, RoutesService } from '@abp/ng.core'; -import { eThemeSharedRouteNames } from '@abp/ng.theme.shared'; import { APP_INITIALIZER } from '@angular/core'; import { eCmsKitRouteNames } from '../enums/route-names'; export const MY_PROJECT_NAME_ROUTE_PROVIDERS = [ - { - provide: APP_INITIALIZER, - useFactory: configureRoutes, - deps: [RoutesService], - multi: true, - }, + { + provide: APP_INITIALIZER, + useFactory: configureRoutes, + deps: [RoutesService], + multi: true, + }, ]; -export function configureRoutes(routes: RoutesService) { - return () => { - routes.add([ - { - path: '/cms-kit', - name: eCmsKitRouteNames.CmsKit, - iconClass: 'fas fa-book', - layout: eLayoutType.application, - order: 3, - }, - ]); - }; +export function configureRoutes(routesService: RoutesService) { + return () => { + routesService.add([ + { + path: '/cms-kit', + name: eCmsKitRouteNames.CmsKit, + iconClass: 'fas fa-book', + layout: eLayoutType.application, + order: 3, + }, + ]); + }; } diff --git a/modules/cms-kit/angular/projects/dev-app/src/app/route.provider.ts b/modules/cms-kit/angular/projects/dev-app/src/app/route.provider.ts index a412259466..1c7138236f 100644 --- a/modules/cms-kit/angular/projects/dev-app/src/app/route.provider.ts +++ b/modules/cms-kit/angular/projects/dev-app/src/app/route.provider.ts @@ -10,9 +10,9 @@ export const APP_ROUTE_PROVIDER = [ }, ]; -function configureRoutes(routes: RoutesService) { +function configureRoutes(routesService: RoutesService) { return () => { - routes.add([ + routesService.add([ { path: '/', name: 'Home', diff --git a/npm/ng-packs/apps/dev-app/src/app/route.provider.ts b/npm/ng-packs/apps/dev-app/src/app/route.provider.ts index 5a14ad7ba0..73865dfd0a 100644 --- a/npm/ng-packs/apps/dev-app/src/app/route.provider.ts +++ b/npm/ng-packs/apps/dev-app/src/app/route.provider.ts @@ -5,9 +5,9 @@ export const APP_ROUTE_PROVIDER = [ { provide: APP_INITIALIZER, useFactory: configureRoutes, deps: [RoutesService], multi: true }, ]; -function configureRoutes(routes: RoutesService) { +function configureRoutes(routesService: RoutesService) { return () => { - routes.add([ + routesService.add([ { path: '/', name: '::Menu:Home', diff --git a/npm/ng-packs/packages/account/config/src/providers/route.provider.ts b/npm/ng-packs/packages/account/config/src/providers/route.provider.ts index 2deb086b10..2094c4dca3 100644 --- a/npm/ng-packs/packages/account/config/src/providers/route.provider.ts +++ b/npm/ng-packs/packages/account/config/src/providers/route.provider.ts @@ -6,9 +6,9 @@ export const ACCOUNT_ROUTE_PROVIDERS = [ { provide: APP_INITIALIZER, useFactory: configureRoutes, deps: [RoutesService], multi: true }, ]; -export function configureRoutes(routes: RoutesService) { +export function configureRoutes(routesService: RoutesService) { return () => { - routes.add([ + routesService.add([ { path: '/account', name: eAccountRouteNames.Account, diff --git a/npm/ng-packs/packages/core/src/lib/directives/index.ts b/npm/ng-packs/packages/core/src/lib/directives/index.ts index 73b572f61d..a297faa14b 100644 --- a/npm/ng-packs/packages/core/src/lib/directives/index.ts +++ b/npm/ng-packs/packages/core/src/lib/directives/index.ts @@ -1,10 +1,10 @@ export * from './autofocus.directive'; +export * from './debounce.directive'; export * from './ellipsis.directive'; export * from './for.directive'; export * from './form-submit.directive'; export * from './init.directive'; export * from './permission.directive'; export * from './replaceable-template.directive'; -export * from './visibility.directive'; -export * from './debounce.directive'; export * from './stop-propagation.directive'; +export * from './visibility.directive'; diff --git a/npm/ng-packs/packages/core/src/lib/directives/permission.directive.ts b/npm/ng-packs/packages/core/src/lib/directives/permission.directive.ts index fda8b7d315..c24cd9b2d1 100644 --- a/npm/ng-packs/packages/core/src/lib/directives/permission.directive.ts +++ b/npm/ng-packs/packages/core/src/lib/directives/permission.directive.ts @@ -11,9 +11,8 @@ import { TemplateRef, ViewContainerRef, } from '@angular/core'; -import { Store } from '@ngxs/store'; import { Subscription } from 'rxjs'; -import { ConfigState } from '../states'; +import { PermissionService } from '../services/permission.service'; @Directive({ selector: '[abpPermission]', @@ -26,18 +25,17 @@ export class PermissionDirective implements OnInit, OnDestroy, OnChanges { constructor( private elRef: ElementRef, private renderer: Renderer2, - private store: Store, @Optional() private templateRef: TemplateRef, private vcRef: ViewContainerRef, + private permissionService: PermissionService, ) {} private check() { if (this.subscription) { this.subscription.unsubscribe(); } - - this.subscription = this.store - .select(ConfigState.getGrantedPolicy(this.condition)) + this.subscription = this.permissionService + .getGrantedPolicy$(this.condition) .subscribe(isGranted => { if (this.templateRef && isGranted) { this.vcRef.clear(); diff --git a/npm/ng-packs/packages/core/src/lib/guards/permission.guard.ts b/npm/ng-packs/packages/core/src/lib/guards/permission.guard.ts index 5c94873ee2..17da350056 100644 --- a/npm/ng-packs/packages/core/src/lib/guards/permission.guard.ts +++ b/npm/ng-packs/packages/core/src/lib/guards/permission.guard.ts @@ -5,26 +5,31 @@ import { Observable, of } from 'rxjs'; import { tap } from 'rxjs/operators'; import { RestOccurError } from '../actions/rest.actions'; import { RoutesService } from '../services/routes.service'; -import { ConfigState } from '../states/config.state'; import { findRoute, getRoutePath } from '../utils/route-utils'; +import { PermissionService } from '../services'; @Injectable({ providedIn: 'root', }) export class PermissionGuard implements CanActivate { - constructor(private router: Router, private routes: RoutesService, private store: Store) {} + constructor( + private router: Router, + private routesService: RoutesService, + private store: Store, + private permissionService: PermissionService, + ) {} canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable { let { requiredPolicy } = route.data || {}; if (!requiredPolicy) { - const routeFound = findRoute(this.routes, getRoutePath(this.router, state.url)); + const routeFound = findRoute(this.routesService, getRoutePath(this.router, state.url)); requiredPolicy = routeFound?.requiredPolicy; } if (!requiredPolicy) return of(true); - return this.store.select(ConfigState.getGrantedPolicy(requiredPolicy)).pipe( + return this.permissionService.getGrantedPolicy$(requiredPolicy).pipe( tap(access => { if (!access) { this.store.dispatch(new RestOccurError({ status: 403 })); diff --git a/npm/ng-packs/packages/core/src/lib/services/config-state.service.ts b/npm/ng-packs/packages/core/src/lib/services/config-state.service.ts index ee3f49e17a..e7bbc8599d 100644 --- a/npm/ng-packs/packages/core/src/lib/services/config-state.service.ts +++ b/npm/ng-packs/packages/core/src/lib/services/config-state.service.ts @@ -45,6 +45,7 @@ export class ConfigStateService { return this.store.selectSnapshot(ConfigState.getSettings(...args)); } + /** @deprecated Use PermissionService's getGrantedPolicySnapshot method */ getGrantedPolicy(...args: Parameters) { return this.store.selectSnapshot(ConfigState.getGrantedPolicy(...args)); } diff --git a/npm/ng-packs/packages/core/src/lib/services/index.ts b/npm/ng-packs/packages/core/src/lib/services/index.ts index d3d13de20b..670a2fe5f1 100644 --- a/npm/ng-packs/packages/core/src/lib/services/index.ts +++ b/npm/ng-packs/packages/core/src/lib/services/index.ts @@ -7,6 +7,7 @@ export * from './lazy-load.service'; export * from './list.service'; export * from './localization.service'; export * from './multi-tenancy.service'; +export * from './permission.service'; export * from './profile-state.service'; export * from './profile.service'; export * from './replaceable-components.service'; diff --git a/npm/ng-packs/packages/core/src/lib/services/permission.service.ts b/npm/ng-packs/packages/core/src/lib/services/permission.service.ts new file mode 100644 index 0000000000..92045b00ce --- /dev/null +++ b/npm/ng-packs/packages/core/src/lib/services/permission.service.ts @@ -0,0 +1,58 @@ +import { ConfigState } from '../states'; +import { Store } from '@ngxs/store'; +import { map } from 'rxjs/operators'; +import { ApplicationConfiguration } from '../models'; +import snq from 'snq'; + +export class PermissionService { + constructor(private store: Store) {} + + getGrantedPolicy$(key: string) { + return this.getStream().pipe(map(policies => this.isPolicyGranted(key, policies))); + } + + getGrantedPolicy(key: string) { + const policies = this.getSnapshot(); + return this.isPolicyGranted(key, policies); + } + + private isPolicyGranted(key: string, policies: ApplicationConfiguration.Policy) { + if (!key) return true; + + const orRegexp = /\|\|/g; + const andRegexp = /&&/g; + + // TODO: Allow combination of ANDs & ORs + if (orRegexp.test(key)) { + const keys = key.split('||').filter(Boolean); + + if (keys.length < 2) return false; + + return keys.some(k => this.getPolicy(k.trim(), policies)); + } else if (andRegexp.test(key)) { + const keys = key.split('&&').filter(Boolean); + + if (keys.length < 2) return false; + + return keys.every(k => this.getPolicy(k.trim(), policies)); + } + + return this.getPolicy(key, policies); + } + + private getStream() { + return this.store.select(ConfigState).pipe(map(this.mapToPolicies)); + } + + private getSnapshot() { + return this.mapToPolicies(this.store.selectSnapshot(ConfigState)); + } + + private mapToPolicies(applicationConfiguration: ApplicationConfiguration.Response) { + return snq(() => applicationConfiguration.auth.grantedPolicies); + } + + private getPolicy(policy: string, policies: ApplicationConfiguration.Policy) { + return snq(() => policies[policy], false); + } +} diff --git a/npm/ng-packs/packages/core/src/lib/services/routes.service.ts b/npm/ng-packs/packages/core/src/lib/services/routes.service.ts index c19628760c..3ce32401d2 100644 --- a/npm/ng-packs/packages/core/src/lib/services/routes.service.ts +++ b/npm/ng-packs/packages/core/src/lib/services/routes.service.ts @@ -1,11 +1,11 @@ -import { Injectable, OnDestroy } from '@angular/core'; -import { Actions, ofActionSuccessful, Store } from '@ngxs/store'; +import { Injectable, Injector, OnDestroy } from '@angular/core'; +import { Actions, ofActionSuccessful } from '@ngxs/store'; import { BehaviorSubject, Observable, Subscription } from 'rxjs'; import { GetAppConfiguration } from '../actions/config.actions'; import { ABP } from '../models/common'; -import { ConfigState } from '../states/config.state'; import { pushValueTo } from '../utils/array-utils'; import { BaseTreeNode, createTreeFromList, TreeNode } from '../utils/tree-utils'; +import { PermissionService } from './permission.service'; export abstract class AbstractTreeService { abstract id: string; @@ -134,9 +134,12 @@ export abstract class AbstractTreeService { } @Injectable() -export abstract class AbstractNavTreeService extends AbstractTreeService +export abstract class AbstractNavTreeService + extends AbstractTreeService implements OnDestroy { + protected actions: Actions; private subscription: Subscription; + private permissionService: PermissionService; readonly id = 'name'; readonly parentId = 'parentName'; readonly hide = (item: T) => item.invisible || !this.isGranted(item); @@ -147,16 +150,17 @@ export abstract class AbstractNavTreeService extends Abstract return a.order - b.order; }; - constructor(protected actions: Actions, protected store: Store) { + constructor(protected injector: Injector) { super(); - + this.actions = injector.get(Actions); this.subscription = this.actions .pipe(ofActionSuccessful(GetAppConfiguration)) .subscribe(() => this.refresh()); + this.permissionService = injector.get(PermissionService); } protected isGranted({ requiredPolicy }: T): boolean { - return this.store.selectSnapshot(ConfigState.getGrantedPolicy(requiredPolicy)); + return this.permissionService.getGrantedPolicy(requiredPolicy); } hasChildren(identifier: string): boolean { diff --git a/npm/ng-packs/packages/core/src/lib/states/config.state.ts b/npm/ng-packs/packages/core/src/lib/states/config.state.ts index 2953c5212f..a721299411 100644 --- a/npm/ng-packs/packages/core/src/lib/states/config.state.ts +++ b/npm/ng-packs/packages/core/src/lib/states/config.state.ts @@ -104,6 +104,9 @@ export class ConfigState { return selector; } + /** + * @deprecated use PermissionService's getGrantedPolicyStream or getGrantedPolicy methods. + */ static getGrantedPolicy(key: string) { const selector = createSelector([ConfigState], (state: Config.State): boolean => { if (!key) return true; diff --git a/npm/ng-packs/packages/core/src/lib/tests/dynamic-layout.component.spec.ts b/npm/ng-packs/packages/core/src/lib/tests/dynamic-layout.component.spec.ts index 43ad6f87b1..f4f46ee83a 100644 --- a/npm/ng-packs/packages/core/src/lib/tests/dynamic-layout.component.spec.ts +++ b/npm/ng-packs/packages/core/src/lib/tests/dynamic-layout.component.spec.ts @@ -1,18 +1,19 @@ import { HttpClient } from '@angular/common/http'; -import { Component, NgModule } from '@angular/core'; +import { Component, Injector, NgModule, ɵangular_packages_core_core_d } from '@angular/core'; import { ActivatedRoute, RouterModule } from '@angular/router'; import { createRoutingFactory, SpectatorRouting } from '@ngneat/spectator/jest'; -import { Actions, NgxsModule, Store } from '@ngxs/store'; +import { NgxsModule, Store } from '@ngxs/store'; import { NEVER } from 'rxjs'; import { DynamicLayoutComponent, RouterOutletComponent } from '../components'; import { eLayoutType } from '../enums/common'; import { ABP } from '../models'; import { ApplicationConfigurationService, - RoutesService, + PermissionService, ReplaceableComponentsService, + RoutesService, } from '../services'; -import { ReplaceableComponentsState } from '../states'; +import { mockRoutesService } from './utils'; @Component({ selector: 'abp-layout-application', @@ -91,12 +92,7 @@ describe('DynamicLayoutComponent', () => { providers: [ { provide: RoutesService, - useFactory: () => - new RoutesService(NEVER, ({ - selectSnapshot() { - return true; - }, - } as unknown) as Store), + useFactory: () => mockRoutesService(), }, ReplaceableComponentsService, ], diff --git a/npm/ng-packs/packages/core/src/lib/tests/permission.directive.spec.ts b/npm/ng-packs/packages/core/src/lib/tests/permission.directive.spec.ts index 4c6356634b..067a620606 100644 --- a/npm/ng-packs/packages/core/src/lib/tests/permission.directive.spec.ts +++ b/npm/ng-packs/packages/core/src/lib/tests/permission.directive.spec.ts @@ -1,16 +1,20 @@ import { PermissionDirective } from '../directives/permission.directive'; -import { SpectatorDirective, createDirectiveFactory, SpyObject } from '@ngneat/spectator/jest'; +import { createDirectiveFactory, SpectatorDirective } from '@ngneat/spectator/jest'; import { Store } from '@ngxs/store'; -import { of, Subject } from 'rxjs'; +import { Subject } from 'rxjs'; +import { PermissionService } from '../services'; +import { mockStore } from './utils/common.utils'; describe('PermissionDirective', () => { let spectator: SpectatorDirective; let directive: PermissionDirective; - const grantedPolicy$ = new Subject(); - + const grantedPolicy$ = new Subject(); const createDirective = createDirectiveFactory({ directive: PermissionDirective, - providers: [{ provide: Store, useValue: { select: () => grantedPolicy$ } }], + providers: [ + { provide: Store, useValue: mockStore }, + { provide: PermissionService, useValue: { getGrantedPolicy$: () => grantedPolicy$ } }, + ], }); describe('with condition', () => { diff --git a/npm/ng-packs/packages/core/src/lib/tests/permission.guard.spec.ts b/npm/ng-packs/packages/core/src/lib/tests/permission.guard.spec.ts index cd9108ec87..c69dcf4346 100644 --- a/npm/ng-packs/packages/core/src/lib/tests/permission.guard.spec.ts +++ b/npm/ng-packs/packages/core/src/lib/tests/permission.guard.spec.ts @@ -7,19 +7,21 @@ import { of } from 'rxjs'; import { RestOccurError } from '../actions'; import { PermissionGuard } from '../guards/permission.guard'; import { RoutesService } from '../services/routes.service'; +import { PermissionService } from '../services'; describe('PermissionGuard', () => { let spectator: SpectatorService; let guard: PermissionGuard; let routes: SpyObject; let store: SpyObject; + let permissionService: SpyObject; @Component({ template: '' }) class DummyComponent {} const createService = createServiceFactory({ service: PermissionGuard, - mocks: [Store], + mocks: [PermissionService, Store], declarations: [DummyComponent], imports: [ RouterModule.forRoot([ @@ -53,10 +55,11 @@ describe('PermissionGuard', () => { guard = spectator.service; routes = spectator.inject(RoutesService); store = spectator.inject(Store); + permissionService = spectator.inject(PermissionService); }); it('should return true when the grantedPolicy is true', done => { - store.select.andReturn(of(true)); + permissionService.getGrantedPolicy$.andReturn(of(true)); const spy = jest.spyOn(store, 'dispatch'); guard.canActivate({ data: { requiredPolicy: 'test' } } as any, null).subscribe(res => { expect(res).toBe(true); @@ -66,7 +69,7 @@ describe('PermissionGuard', () => { }); it('should return false and dispatch RestOccurError when the grantedPolicy is false', done => { - store.select.andReturn(of(false)); + permissionService.getGrantedPolicy$.andReturn(of(false)); const spy = jest.spyOn(store, 'dispatch'); guard.canActivate({ data: { requiredPolicy: 'test' } } as any, null).subscribe(res => { expect(res).toBe(false); @@ -84,10 +87,9 @@ describe('PermissionGuard', () => { requiredPolicy: 'TestPolicy', }, ]); - store.select.andReturn(of(false)); - const spy = jest.spyOn(store, 'select'); - guard.canActivate({ data: {} } as any, { url: 'test' } as any).subscribe(() => { - expect(spy.mock.calls[0][0]({ auth: { grantedPolicies: { TestPolicy: true } } })).toBe(true); + permissionService.getGrantedPolicy$.mockImplementation(policy => of(policy === 'TestPolicy')); + guard.canActivate({ data: {} } as any, { url: 'test' } as any).subscribe(result => { + expect(result).toBe(true); done(); }); }); diff --git a/npm/ng-packs/packages/core/src/lib/tests/routes.service.spec.ts b/npm/ng-packs/packages/core/src/lib/tests/routes.service.spec.ts index 6b7ae3f50a..35d56dbf81 100644 --- a/npm/ng-packs/packages/core/src/lib/tests/routes.service.spec.ts +++ b/npm/ng-packs/packages/core/src/lib/tests/routes.service.spec.ts @@ -3,6 +3,8 @@ import { Subject } from 'rxjs'; import { take } from 'rxjs/operators'; import { GetAppConfiguration } from '../actions'; import { RoutesService } from '../services'; +import { mockRoutesService } from './utils'; +import { mockActions } from './utils/common.utils'; describe('Routes Service', () => { let service: RoutesService; @@ -14,15 +16,9 @@ describe('Routes Service', () => { { path: '/foo/x', name: 'x', parentName: 'foo', order: 1 }, ]; - const mockActions = new Subject(); - const mockStore = ({ - selectSnapshot() { - return true; - }, - } as unknown) as Store; beforeEach(() => { - service = new RoutesService(mockActions, mockStore); + service = mockRoutesService(); }); describe('#add', () => { diff --git a/npm/ng-packs/packages/core/src/lib/tests/utils/common.utils.ts b/npm/ng-packs/packages/core/src/lib/tests/utils/common.utils.ts new file mode 100644 index 0000000000..ba05659736 --- /dev/null +++ b/npm/ng-packs/packages/core/src/lib/tests/utils/common.utils.ts @@ -0,0 +1,28 @@ +import { Observable, of, Subject } from 'rxjs'; +import { Store } from '@ngxs/store'; +import { AbstractType, InjectFlags, InjectionToken, Injector, Type } from '@angular/core'; + +export const mockActions = new Subject(); +export const mockStore = ({ + selectSnapshot() { + return true; + }, + select(): Observable { + return of(null); + }, +} as unknown) as Store; + +export class DummyInjector extends Injector { + constructor(public payload: { [key: string]: any }) { + super(); + } + get( + token: Type | InjectionToken | AbstractType, + notFoundValue?: T, + flags?: InjectFlags, + ): T; + get(token: any, notFoundValue?: any): any; + get(token, notFoundValue?, flags?: InjectFlags): any { + return this.payload[token.name || token]; + } +} diff --git a/npm/ng-packs/packages/core/src/lib/tests/utils/index.ts b/npm/ng-packs/packages/core/src/lib/tests/utils/index.ts new file mode 100644 index 0000000000..75de71af2f --- /dev/null +++ b/npm/ng-packs/packages/core/src/lib/tests/utils/index.ts @@ -0,0 +1 @@ +export * from './routes-service.spec.utils'; diff --git a/npm/ng-packs/packages/core/src/lib/tests/utils/permission-service.spec.utils.ts b/npm/ng-packs/packages/core/src/lib/tests/utils/permission-service.spec.utils.ts new file mode 100644 index 0000000000..ef1a264c2b --- /dev/null +++ b/npm/ng-packs/packages/core/src/lib/tests/utils/permission-service.spec.utils.ts @@ -0,0 +1,7 @@ +import { PermissionService } from '../../services'; +import { Subject } from 'rxjs'; + +export const mockPermissionService = (args = {} as Partial) => { + const permissionService = { getGrantedPolicy$: new Subject(), getGrantedPolicy: arg => true }; + return Object.assign({}, permissionService, args); +}; diff --git a/npm/ng-packs/packages/core/src/lib/tests/utils/routes-service.spec.utils.ts b/npm/ng-packs/packages/core/src/lib/tests/utils/routes-service.spec.utils.ts new file mode 100644 index 0000000000..303bfbba18 --- /dev/null +++ b/npm/ng-packs/packages/core/src/lib/tests/utils/routes-service.spec.utils.ts @@ -0,0 +1,12 @@ +import { RoutesService } from '../../services'; +import { mockPermissionService } from './permission-service.spec.utils'; +import { DummyInjector, mockActions } from './common.utils'; + +export const mockRoutesService = (injectorPayload = {} as { [key: string]: any }) => { + const injector = new DummyInjector({ + PermissionService: mockPermissionService(), + Actions: mockActions, + ...injectorPayload, + }); + return new RoutesService(injector); +}; diff --git a/npm/ng-packs/packages/core/src/lib/utils/route-utils.ts b/npm/ng-packs/packages/core/src/lib/utils/route-utils.ts index 8c9553fac2..07fad6a1fe 100644 --- a/npm/ng-packs/packages/core/src/lib/utils/route-utils.ts +++ b/npm/ng-packs/packages/core/src/lib/utils/route-utils.ts @@ -5,12 +5,12 @@ import { RoutesService } from '../services/routes.service'; import { noop } from './common-utils'; import { TreeNode } from './tree-utils'; -export function findRoute(routes: RoutesService, path: string): TreeNode { - const node = routes.find(route => route.path === path); +export function findRoute(routesService: RoutesService, path: string): TreeNode { + const node = routesService.find(route => route.path === path); return node || path === '/' ? node - : findRoute(routes, path.split('/').slice(0, -1).join('/') || '/'); + : findRoute(routesService, path.split('/').slice(0, -1).join('/') || '/'); } export function getRoutePath(router: Router, url = router.url) { diff --git a/npm/ng-packs/packages/identity/config/src/providers/route.provider.ts b/npm/ng-packs/packages/identity/config/src/providers/route.provider.ts index 1ab2cbb3ee..f5c2bc2327 100644 --- a/npm/ng-packs/packages/identity/config/src/providers/route.provider.ts +++ b/npm/ng-packs/packages/identity/config/src/providers/route.provider.ts @@ -8,9 +8,9 @@ export const IDENTITY_ROUTE_PROVIDERS = [ { provide: APP_INITIALIZER, useFactory: configureRoutes, deps: [RoutesService], multi: true }, ]; -export function configureRoutes(routes: RoutesService) { +export function configureRoutes(routesService: RoutesService) { return () => { - routes.add([ + routesService.add([ { path: '/identity', name: eIdentityRouteNames.IdentityManagement, diff --git a/npm/ng-packs/packages/setting-management/config/src/providers/route.provider.ts b/npm/ng-packs/packages/setting-management/config/src/providers/route.provider.ts index 28c0fb7388..9d272b8be0 100644 --- a/npm/ng-packs/packages/setting-management/config/src/providers/route.provider.ts +++ b/npm/ng-packs/packages/setting-management/config/src/providers/route.provider.ts @@ -14,9 +14,9 @@ export const SETTING_MANAGEMENT_ROUTE_PROVIDERS = [ }, ]; -export function configureRoutes(routes: RoutesService) { +export function configureRoutes(routesService: RoutesService) { return () => { - routes.add([ + routesService.add([ { name: eSettingManagementRouteNames.Settings, path: '/setting-management', @@ -29,13 +29,15 @@ export function configureRoutes(routes: RoutesService) { }; } -export function hideRoutes(routes: RoutesService, tabs: SettingTabsService) { +export function hideRoutes(routesService: RoutesService, settingTabsService: SettingTabsService) { return () => { - tabs.visible$ + settingTabsService.visible$ .pipe( debounceTime(0), map(nodes => !nodes.length), ) - .subscribe(invisible => routes.patch(eSettingManagementRouteNames.Settings, { invisible })); + .subscribe(invisible => + routesService.patch(eSettingManagementRouteNames.Settings, { invisible }), + ); }; } diff --git a/npm/ng-packs/packages/setting-management/src/lib/components/setting-management.component.ts b/npm/ng-packs/packages/setting-management/src/lib/components/setting-management.component.ts index 5b65c1f76d..e8e94293e9 100644 --- a/npm/ng-packs/packages/setting-management/src/lib/components/setting-management.component.ts +++ b/npm/ng-packs/packages/setting-management/src/lib/components/setting-management.component.ts @@ -24,7 +24,7 @@ export class SettingManagementComponent implements OnDestroy, OnInit { trackByFn: TrackByFunction = (_, item) => item.name; - constructor(private store: Store, private settingTabs: SettingTabsService) {} + constructor(private store: Store, private settingTabsService: SettingTabsService) {} ngOnDestroy() { this.subscription.unsubscribe(); @@ -32,7 +32,7 @@ export class SettingManagementComponent implements OnDestroy, OnInit { ngOnInit() { this.subscription.add( - this.settingTabs.visible$.subscribe(settings => { + this.settingTabsService.visible$.subscribe(settings => { this.settings = settings; if (!this.selected) this.selected = this.settings[0]; diff --git a/npm/ng-packs/packages/theme-basic/src/lib/components/routes/routes.component.html b/npm/ng-packs/packages/theme-basic/src/lib/components/routes/routes.component.html index 4e6395da05..cf27990b4e 100644 --- a/npm/ng-packs/packages/theme-basic/src/lib/components/routes/routes.component.html +++ b/npm/ng-packs/packages/theme-basic/src/lib/components/routes/routes.component.html @@ -1,6 +1,6 @@