diff --git a/docs/en/Apps/VoloDocs.md b/docs/en/Apps/VoloDocs.md index 25fb0482c7..936f7f10d4 100644 --- a/docs/en/Apps/VoloDocs.md +++ b/docs/en/Apps/VoloDocs.md @@ -9,7 +9,7 @@ VoloDocs is a cross-platform web application that allows you to easily create be - Serves documents from your GitHub repository. - Supports Markdown / HTML document formatting. - Supports versioning (integrated to GitHub releases). -- Support multiple projects. +- Supports multiple projects. - Allows users to edit a document on GitHub. - Cross-platform; deployable to Windows / Linux / macOS. @@ -23,7 +23,7 @@ https://github.com/abpframework/abp/tree/master/modules/docs You can download the VoloDocs release from the following link: -http://apps.abp.io/VoloDocs/VoloDocs.zip +http://apps.abp.io/VoloDocs/VoloDocs.zip *(will be ready soon...)* ## Folder Structure diff --git a/docs/en/AspNetCore/Auto-API-Controllers.md b/docs/en/AspNetCore/Auto-API-Controllers.md index 48567b6919..db7fb63642 100644 --- a/docs/en/AspNetCore/Auto-API-Controllers.md +++ b/docs/en/AspNetCore/Auto-API-Controllers.md @@ -80,7 +80,7 @@ Then the route for getting a book will be '**/api/volosoft/book-store/book/{id}* * Removing '**Async**' postfix. If the method name is 'GetPhonesAsync' then it becomes 'GetPhones'. * Removing **HTTP method prefix**. 'GetList', 'GetAll', 'Get', 'Put', 'Update', 'Delete', 'Remove', 'Create', 'Add', 'Insert', 'Post' and 'Patch' prefixes are removed based on the selected HTTP method. So, 'GetPhones' becomes 'Phones' since 'Get' prefix is a duplicate for a GET request. * Converting the result to **camelCase**. - * If the resulting action name is **empty** then it's not added to the route. If it's not empty, it's added to the route (like '/phones'). For 'GetAllAsync' method name it will be empty, for 'GetPhonesAsync' method name is will be 'phones'. + * If the resulting action name is **empty** then it's not added to the route. If it's not empty, it's added to the route (like '/phones'). For 'GetAllAsync' method name it will be empty, for 'GetPhonesAsync' method name it will be 'phones'. * Normalization can be customized by setting the `UrlActionNameNormalizer` option. It's an action delegate that is called for every method. * If there is another parameter with 'Id' postfix, then it's also added to the route as the final route segment (like '/phoneId'). @@ -135,4 +135,4 @@ public class PersonAppService : ApplicationService } ```` -Disabled `IsMetadataEnabled` which hides this service from API explorer and it will not be discoverable. However, it still can be usable for the clients know the exact API path/route. \ No newline at end of file +Disabled `IsMetadataEnabled` which hides this service from API explorer and it will not be discoverable. However, it still can be usable for the clients know the exact API path/route. diff --git a/docs/en/AspNetCore/Bundling-Minification.md b/docs/en/AspNetCore/Bundling-Minification.md index 7170690ef3..220562935d 100644 --- a/docs/en/AspNetCore/Bundling-Minification.md +++ b/docs/en/AspNetCore/Bundling-Minification.md @@ -194,7 +194,7 @@ services.Configure(options => options .ScriptBundles .Configure("MyGlobalBundle", bundle => { - bundle.AddContributors(typeof(MyExtensionStyleBundleContributor)); + bundle.AddContributors(typeof(MyExtensionGlobalStyleContributor)); }); }); ```` @@ -279,9 +279,9 @@ public class MyExtensionStyleBundleContributor : BundleContributor Using the built-in contributors for standard packages; -* Prevents you typing **invalid the resource paths**. +* Prevents you typing **the invalid resource paths**. * Prevents changing your contributor if the resource **path changes** (the dependant contributor will handle it). -* Prevents multiple modules adding the **duplicate the files**. +* Prevents multiple modules adding the **duplicate files**. * Manages **dependencies recursively** (adds dependencies of dependencies, if necessary). #### Volo.Abp.AspNetCore.Mvc.UI.Packages Package diff --git a/docs/zh-Hans/AspNetCore/Bundling-Minification.md b/docs/zh-Hans/AspNetCore/Bundling-Minification.md index 7454bd3c17..b7c8c0a1b1 100644 --- a/docs/zh-Hans/AspNetCore/Bundling-Minification.md +++ b/docs/zh-Hans/AspNetCore/Bundling-Minification.md @@ -196,7 +196,7 @@ services.Configure(options => options .ScriptBundles .Configure("MyGlobalBundle", bundle => { - bundle.AddContributors(typeof(MyExtensionStyleBundleContributor)); + bundle.AddContributors(typeof(MyExtensionGlobalStyleContributor)); }); }); ```` @@ -214,7 +214,7 @@ services.Configure(options => `abp-style`和`abp-script`标签可以使用`type`属性(而不是`src`属性), 如本示例所示. 添加bundle贡献者时, 其依赖关系也会自动添加到bundle中. -#### Contributor Dependencies +#### 贡献者依赖关系 bundle贡献者可以与其他贡献者具有一个或多个依赖关系. 例如: @@ -227,9 +227,39 @@ public class MyExtensionStyleBundleContributor : BundleContributor } ```` -添加bundle贡献者时,其依赖关系将 **自动并递归** 添加. **依赖顺序** 通过阻止 **重复** 添加的依赖关系. 即使它们处于分离的束中,也会阻止重复. ABP在页面中组织所有bundle并消除重复. +添加bundle贡献者时,其依赖关系将 **自动并递归** 添加. **依赖顺序** 通过阻止 **重复** 添加的依赖关系. 即使它们处于分离的bundle中,也会阻止重复. ABP在页面中组织所有bundle并消除重复. -创建贡献者和定义依赖关系是一种跨不同模块组织包创建的方法. +创建贡献者和定义依赖关系是一种跨不同模块组织bundle创建的方法. + + +#### 贡献者扩展 + +在某些高级应用场景中, 当用到一个bundle贡献者时,你可能想做一些额外的配置. 贡献者扩展可以和被扩展的贡献者无缝衔接. + +下面的示例为 prism.js 脚本库添加一些样式: + +````csharp +public class MyPrismjsStyleExtension : BundleContributor +{ + public override void ConfigureBundle(BundleConfigurationContext context) + { + context.Files.AddIfNotContains("/libs/prismjs/plugins/toolbar/prism-toolbar.css"); + } +} +```` + +然后你可以配置 `BundleContributorOptions` 去扩展已存在的 `PrismjsStyleBundleContributor`. + +````csharp +Configure(options => +{ + options + .Extensions() + .Add(); +}); +```` + +任何时候当 `PrismjsStyleBundleContributor` 被添加到bundle中时, `MyPrismjsStyleExtension` 也会被自动添加. #### 访问 IServiceProvider @@ -239,7 +269,7 @@ public class MyExtensionStyleBundleContributor : BundleContributor 将特定的NPM包资源(js,css文件)添加到包中对于该包非常简单. 例如, 你总是为bootstrap NPM包添加`bootstrap.css`文件. -所有[标准NPM包](Client-Side-Package-Management.md)都有内置的贡献者. 例如,如果你的贡献者依赖于引导程序,你可以声明它,而不是自己添加bootstrap.css. +所有[标准NPM包](Client-Side-Package-Management.md)都有内置的贡献者. 例如,如果你的贡献者依赖于bootstrap,你可以声明它,而不是自己添加bootstrap.css. ````C# [DependsOn(typeof(BootstrapStyleContributor))] //Define the bootstrap style dependency @@ -261,7 +291,7 @@ public class MyExtensionStyleBundleContributor : BundleContributor > 默认情况下已在启动模板安装此软件包. 大多数情况下,你不需要手动安装它. 标准包贡献者在`Volo.Abp.AspNetCore.Mvc.UI.Packages` NuGet包中定义. -安装到你的项目中: +将它安装到你的项目中: ```` install-package Volo.Abp.AspNetCore.Mvc.UI.Packages @@ -283,9 +313,9 @@ namespace MyCompany.MyProject } ```` -#### Bundle Inheritance +#### Bundle 继承 -在某些特定情况下, 可能需要从其他bundle创建一个 **新** bundle **继承**, 从bundle继承(递归)继承该bundle的所有文件/贡献者. 然后派生的bundle可以添加或修改文件/贡献者**而无需修改**原始包. +在某些特定情况下, 可能需要从其他bundle创建一个 **新** bundle **继承**, 从bundle继承(递归)会继承该bundle的所有文件/贡献者. 然后派生的bundle可以添加或修改文件/贡献者**而无需修改**原始bundle. 例如: ````c# diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelperService.cs index 5a095d561c..cd3294d66f 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelperService.cs @@ -124,8 +124,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form return GetLabelAsHtmlUsingTagHelper(context, output) + GetRequiredSymbol(context, output); } - - + protected virtual string GetRequiredSymbol(TagHelperContext context, TagHelperOutput output) { if (!TagHelper.DisplayRequiredSymbol) diff --git a/modules/docs/README.md b/modules/docs/README.md index 993e009110..ee4e33a785 100644 --- a/modules/docs/README.md +++ b/modules/docs/README.md @@ -1,4 +1,4 @@ -# docs module +# Docs Module This module is used to create technical documentation web sites. [abp.io](https://abp.io) web site uses this module for its documentation. ### Screenshot @@ -7,7 +7,7 @@ This module is used to create technical documentation web sites. [abp.io](https: ### Main Features -* Can read documents from a Github repository. +* Retrieves documents from a Github repository. * Supports Markdown document formatting. * Supports versioning (integrated to Github releases). -* Support multiple projects. \ No newline at end of file +* Supports multiple projects. diff --git a/modules/docs/app/VoloDocs.Web/Assets/Images/Logo.png b/modules/docs/app/VoloDocs.Web/Assets/Images/Logo.png deleted file mode 100644 index d22a97e34b..0000000000 Binary files a/modules/docs/app/VoloDocs.Web/Assets/Images/Logo.png and /dev/null differ diff --git a/modules/docs/app/VoloDocs.Web/VoloDocs.Web.csproj b/modules/docs/app/VoloDocs.Web/VoloDocs.Web.csproj index 1b85705ea6..c405b583a8 100644 --- a/modules/docs/app/VoloDocs.Web/VoloDocs.Web.csproj +++ b/modules/docs/app/VoloDocs.Web/VoloDocs.Web.csproj @@ -36,10 +36,13 @@ - + + + + PreserveNewest diff --git a/modules/docs/app/VoloDocs.Web/appsettings.json b/modules/docs/app/VoloDocs.Web/appsettings.json index e328aa93f4..e893a26c7c 100644 --- a/modules/docs/app/VoloDocs.Web/appsettings.json +++ b/modules/docs/app/VoloDocs.Web/appsettings.json @@ -1,5 +1,5 @@ { "ConnectionString": "Server=localhost;Database=VoloDocs;Trusted_Connection=True;MultipleActiveResultSets=true", "Title": "Volo Documents", - "LogoUrl": "/Assets/Images/Logo.png" + "LogoUrl": "/assets/images/Logo.png" } \ No newline at end of file diff --git a/modules/docs/app/VoloDocs.Web/wwwroot/assets/images/Logo.png b/modules/docs/app/VoloDocs.Web/wwwroot/assets/images/Logo.png new file mode 100644 index 0000000000..30a85a0ca0 Binary files /dev/null and b/modules/docs/app/VoloDocs.Web/wwwroot/assets/images/Logo.png differ diff --git a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Roles/Index.cshtml b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Roles/Index.cshtml index 1979c87bb2..d2758f05d4 100644 --- a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Roles/Index.cshtml +++ b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Roles/Index.cshtml @@ -12,6 +12,11 @@ PageLayout.Content.BreadCrumb.Add(L["Menu:IdentityManagement"].Value); PageLayout.Content.MenuItemName = IdentityMenuNames.Roles; } +@section styles { + + + +} @section scripts { diff --git a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/Index.cshtml b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/Index.cshtml index bcef02cc72..23f7747ac8 100644 --- a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/Index.cshtml +++ b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/Index.cshtml @@ -15,6 +15,11 @@ PageLayout.Content.BreadCrumb.Add(L["Menu:IdentityManagement"].Value); PageLayout.Content.MenuItemName = IdentityMenuNames.Users; } +@section styles { + + + +} @section scripts { diff --git a/modules/identityserver/test/Volo.Abp.IdentityServer.EntityFrameworkCore.Tests/Volo/Abp/IdentityServer/Clients/ClientStore_Tests.cs b/modules/identityserver/test/Volo.Abp.IdentityServer.Domain.Tests/Volo/Abp/IdentityServer/Clients/ClientStore_Tests.cs similarity index 100% rename from modules/identityserver/test/Volo.Abp.IdentityServer.EntityFrameworkCore.Tests/Volo/Abp/IdentityServer/Clients/ClientStore_Tests.cs rename to modules/identityserver/test/Volo.Abp.IdentityServer.Domain.Tests/Volo/Abp/IdentityServer/Clients/ClientStore_Tests.cs diff --git a/modules/identityserver/test/Volo.Abp.IdentityServer.EntityFrameworkCore.Tests/Volo/Abp/IdentityServer/Clients/IdentityResourceStore_Tests.cs b/modules/identityserver/test/Volo.Abp.IdentityServer.Domain.Tests/Volo/Abp/IdentityServer/Clients/IdentityResourceStore_Tests.cs similarity index 100% rename from modules/identityserver/test/Volo.Abp.IdentityServer.EntityFrameworkCore.Tests/Volo/Abp/IdentityServer/Clients/IdentityResourceStore_Tests.cs rename to modules/identityserver/test/Volo.Abp.IdentityServer.Domain.Tests/Volo/Abp/IdentityServer/Clients/IdentityResourceStore_Tests.cs diff --git a/modules/identityserver/test/Volo.Abp.IdentityServer.EntityFrameworkCore.Tests/Volo/Abp/IdentityServer/Clients/PersistentGrant_Tests.cs b/modules/identityserver/test/Volo.Abp.IdentityServer.Domain.Tests/Volo/Abp/IdentityServer/Clients/PersistentGrant_Tests.cs similarity index 100% rename from modules/identityserver/test/Volo.Abp.IdentityServer.EntityFrameworkCore.Tests/Volo/Abp/IdentityServer/Clients/PersistentGrant_Tests.cs rename to modules/identityserver/test/Volo.Abp.IdentityServer.Domain.Tests/Volo/Abp/IdentityServer/Clients/PersistentGrant_Tests.cs diff --git a/modules/identityserver/test/Volo.Abp.IdentityServer.EntityFrameworkCore.Tests/Volo/Abp/IdentityServer/PersistentGrantRepository_Tests.cs b/modules/identityserver/test/Volo.Abp.IdentityServer.EntityFrameworkCore.Tests/Volo/Abp/IdentityServer/PersistentGrantRepository_Tests.cs new file mode 100644 index 0000000000..79bab1d23a --- /dev/null +++ b/modules/identityserver/test/Volo.Abp.IdentityServer.EntityFrameworkCore.Tests/Volo/Abp/IdentityServer/PersistentGrantRepository_Tests.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Volo.Abp.IdentityServer +{ + public class PersistentGrantRepository_Tests : PersistentGrantRepository_Tests + { + + } +} diff --git a/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/PersistentGrantRepository_Tests.cs b/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/PersistentGrantRepository_Tests.cs new file mode 100644 index 0000000000..fd2763dc6c --- /dev/null +++ b/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/PersistentGrantRepository_Tests.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Volo.Abp.IdentityServer +{ + public class PersistentGrantRepository_Tests : PersistentGrantRepository_Tests + { + + } +} diff --git a/modules/identityserver/test/Volo.Abp.IdentityServer.TestBase/Volo/Abp/IdentityServer/AbpIdentityServerTestDataBuilder.cs b/modules/identityserver/test/Volo.Abp.IdentityServer.TestBase/Volo/Abp/IdentityServer/AbpIdentityServerTestDataBuilder.cs index 0c18e85350..016820af49 100644 --- a/modules/identityserver/test/Volo.Abp.IdentityServer.TestBase/Volo/Abp/IdentityServer/AbpIdentityServerTestDataBuilder.cs +++ b/modules/identityserver/test/Volo.Abp.IdentityServer.TestBase/Volo/Abp/IdentityServer/AbpIdentityServerTestDataBuilder.cs @@ -1,6 +1,8 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using Volo.Abp.DependencyInjection; using Volo.Abp.Guids; +using Volo.Abp.Identity; using Volo.Abp.IdentityServer.ApiResources; using Volo.Abp.IdentityServer.Clients; using Volo.Abp.IdentityServer.Grants; @@ -14,7 +16,8 @@ namespace Volo.Abp.IdentityServer private readonly IApiResourceRepository _apiResourceRepository; private readonly IClientRepository _clientRepository; private readonly IIdentityResourceRepository _identityResourceRepository; - //private readonly IPersistentGrantRepository _persistentGrantRepository; + private readonly IIdentityClaimTypeRepository _identityClaimTypeRepository; + private readonly IPersistentGrantRepository _persistentGrantRepository; private readonly AbpIdentityServerTestData _testData; public AbpIdentityServerTestDataBuilder( @@ -22,15 +25,17 @@ namespace Volo.Abp.IdentityServer IApiResourceRepository apiResourceRepository, IClientRepository clientRepository, IIdentityResourceRepository identityResourceRepository, - AbpIdentityServerTestData testData - /*IPersistentGrantRepository persistentGrantRepository*/) + IIdentityClaimTypeRepository identityClaimTypeRepository, + AbpIdentityServerTestData testData, + IPersistentGrantRepository persistentGrantRepository) { _testData = testData; _guidGenerator = guidGenerator; _apiResourceRepository = apiResourceRepository; _clientRepository = clientRepository; _identityResourceRepository = identityResourceRepository; - //_persistentGrantRepository = persistentGrantRepository; + _identityClaimTypeRepository = identityClaimTypeRepository; + _persistentGrantRepository = persistentGrantRepository; } public void Build() @@ -39,13 +44,30 @@ namespace Volo.Abp.IdentityServer AddIdentityResources(); AddApiResources(); AddClients(); + AddClaimTypes(); } private void AddPersistedGrants() { - //_persistentGrantRepository.Insert(new PersistedGrant(_guidGenerator.Create())); - //_persistentGrantRepository.Insert(new PersistedGrant(_guidGenerator.Create())); - //_persistentGrantRepository.Insert(new PersistedGrant(_guidGenerator.Create())); + _persistentGrantRepository.Insert(new PersistedGrant(_guidGenerator.Create()) + { + + Key = "PersistedGrantKey1", + SubjectId = "PersistedGrantSubjectId1", + ClientId = "PersistedGrantClientId1", + Type = "PersistedGrantType1" + }); + _persistentGrantRepository.Insert(new PersistedGrant(_guidGenerator.Create()) + { + Key = "PersistedGrantKey2", + SubjectId = "PersistedGrantSubjectId2" + }); + + _persistentGrantRepository.Insert(new PersistedGrant(_guidGenerator.Create()) + { + Key = "PersistedGrantKey3", + SubjectId = "PersistedGrantSubjectId3" + }); } private void AddIdentityResources() @@ -105,5 +127,12 @@ namespace Volo.Abp.IdentityServer _clientRepository.Insert(new Client(_guidGenerator.Create(), "ClientId2")); _clientRepository.Insert(new Client(_guidGenerator.Create(), "ClientId3")); } + + private void AddClaimTypes() + { + var ageClaim = new IdentityClaimType(Guid.NewGuid(), "Age", false, false, null, null, null, + IdentityClaimValueType.Int); + _identityClaimTypeRepository.Insert(ageClaim); + } } } diff --git a/modules/identityserver/test/Volo.Abp.IdentityServer.TestBase/Volo/Abp/IdentityServer/PersistentGrantRepository_Tests.cs b/modules/identityserver/test/Volo.Abp.IdentityServer.TestBase/Volo/Abp/IdentityServer/PersistentGrantRepository_Tests.cs new file mode 100644 index 0000000000..20f6674515 --- /dev/null +++ b/modules/identityserver/test/Volo.Abp.IdentityServer.TestBase/Volo/Abp/IdentityServer/PersistentGrantRepository_Tests.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Shouldly; +using Volo.Abp.IdentityServer.Grants; +using Volo.Abp.Modularity; +using Xunit; + +namespace Volo.Abp.IdentityServer +{ + public abstract class PersistentGrantRepository_Tests : AbpIdentityServerTestBase + where TStartupModule : IAbpModule + { + private readonly IPersistentGrantRepository _persistentGrantRepository; + + protected PersistentGrantRepository_Tests() + { + _persistentGrantRepository = GetRequiredService(); + } + + [Fact] + public async Task FindByKeyAsync() + { + (await _persistentGrantRepository.FindByKeyAsync("PersistedGrantKey1")).ShouldNotBeNull(); + } + + [Fact] + public async Task GetListBySubjectIdAsync() + { + var persistedGrants = await _persistentGrantRepository.GetListBySubjectIdAsync("PersistedGrantSubjectId1"); + persistedGrants.ShouldNotBeEmpty(); + persistedGrants.ShouldContain(x => x.Key == "PersistedGrantKey1"); + } + + [Fact] + public async Task DeleteBySubjectIdAndClientId() + { + await _persistentGrantRepository.DeleteAsync("PersistedGrantSubjectId1", "PersistedGrantClientId1"); + + var persistedGrants = await _persistentGrantRepository.GetListAsync(); + persistedGrants.ShouldNotBeEmpty(); + persistedGrants.ShouldNotContain(x => + x.Key == "PersistedGrantKey1" && x.SubjectId == "PersistedGrantSubjectId1" && + x.ClientId == "PersistedGrantClientId1"); + } + + [Fact] + public async Task DeleteBySubjectIdAndClientIdAndType() + { + await _persistentGrantRepository.DeleteAsync("PersistedGrantSubjectId1", "PersistedGrantClientId1", + "PersistedGrantClientId1"); + + var persistedGrants = await _persistentGrantRepository.GetListAsync(); + persistedGrants.ShouldNotBeEmpty(); + persistedGrants.ShouldNotContain(x => + x.Key == "PersistedGrantKey1" && x.SubjectId == "PersistedGrantSubjectId1" && + x.ClientId == "PersistedGrantClientId1" && x.Type == "PersistedGrantClientId1"); + + } + } +} diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/AbpPermissionManagementWebAutoMapperProfile.cs b/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/AbpPermissionManagementWebAutoMapperProfile.cs index 631779b8ae..e707ba0676 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/AbpPermissionManagementWebAutoMapperProfile.cs +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/AbpPermissionManagementWebAutoMapperProfile.cs @@ -1,4 +1,5 @@ using AutoMapper; +using Volo.Abp.AutoMapper; using Volo.Abp.PermissionManagement.Web.Pages.AbpPermissionManagement; namespace Volo.Abp.PermissionManagement.Web @@ -7,7 +8,7 @@ namespace Volo.Abp.PermissionManagement.Web { public AbpPermissionManagementWebAutoMapperProfile() { - CreateMap(); + CreateMap().Ignore(p=>p.IsAllPermissionsGranted); CreateMap() .ForMember(p => p.Depth, opts => opts.Ignore()); diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Localization/Resources/AbpPermissionManagement/en.json b/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Localization/Resources/AbpPermissionManagement/en.json index bb6999c100..ba775f3ab0 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Localization/Resources/AbpPermissionManagement/en.json +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Localization/Resources/AbpPermissionManagement/en.json @@ -3,6 +3,8 @@ "texts": { "Permissions": "Permissions", "OnlyProviderPermissons": "Only this provider", - "All": "All" + "All": "All", + "SelectAllInAllTabs": "Grant all permissions", + "SelectAllInThisTab": "Select all" } } \ No newline at end of file diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Localization/Resources/AbpPermissionManagement/tr.json b/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Localization/Resources/AbpPermissionManagement/tr.json index 8da6bccd95..7f278ce6c1 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Localization/Resources/AbpPermissionManagement/tr.json +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Localization/Resources/AbpPermissionManagement/tr.json @@ -3,6 +3,8 @@ "texts": { "Permissions": "İzinler", "OnlyProviderPermissons": "Sadece bu sağlayıcı", - "All": "Hepsi" + "All": "Hepsi", + "SelectAllInAllTabs": "Tüm izinleri ver", + "SelectAllInThisTab": "Hepsini seç" } } \ No newline at end of file diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/PermissionManagementModal.cshtml b/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/PermissionManagementModal.cshtml index b78bb499d3..dd2c73eb23 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/PermissionManagementModal.cshtml +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/PermissionManagementModal.cshtml @@ -9,44 +9,27 @@ Layout = null; } -@*TO DO : Following styles and scripts will move*@ - -
- - + +
+ + @for (var i = 0; i < Model.Groups.Count; i++) {

@Model.Groups[i].DisplayName

-
+
+ +
@for (var j = 0; j < Model.Groups[i].Permissions.Count; j++) { - + group-style="margin-left: @(Model.Groups[i].Permissions[j].Depth * 20)px"/> + }
diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/PermissionManagementModal.cshtml.cs b/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/PermissionManagementModal.cshtml.cs index 0702c1e766..3bc688a6f1 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/PermissionManagementModal.cshtml.cs +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/PermissionManagementModal.cshtml.cs @@ -25,6 +25,10 @@ namespace Volo.Abp.PermissionManagement.Web.Pages.AbpPermissionManagement public string EntityDisplayName { get; set; } + public bool SelectAllInThisTab { get; set; } + + public bool SelectAllInAllTabs { get; set; } + private readonly IPermissionAppService _permissionAppService; public PermissionManagementModal(IPermissionAppService permissionAppService) @@ -49,6 +53,13 @@ namespace Volo.Abp.PermissionManagement.Web.Pages.AbpPermissionManagement { new FlatTreeDepthFinder().SetDepths(group.Permissions); } + + foreach (var group in Groups) + { + group.IsAllPermissionsGranted = group.Permissions.All(p => p.IsGranted); + } + + SelectAllInAllTabs = Groups.All(g => g.IsAllPermissionsGranted); } public async Task OnPostAsync() @@ -80,6 +91,8 @@ namespace Volo.Abp.PermissionManagement.Web.Pages.AbpPermissionManagement { public string Name { get; set; } + public bool IsAllPermissionsGranted { get; set; } + public string DisplayName { get; set; } public List Permissions { get; set; } diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/permission-management-modal.css b/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/permission-management-modal.css new file mode 100644 index 0000000000..d1f8731614 --- /dev/null +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/permission-management-modal.css @@ -0,0 +1,12 @@ +.custom-scroll-container > .col-4 { + overflow: hidden; + overflow-y: auto; + max-height: 499px; + display: block; + position: relative; + z-index: 123; +} + +.custom-scroll-content { + max-height: 440px; +} diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/permission-management-modal.js b/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/permission-management-modal.js index f32b00720e..2972ccfffb 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/permission-management-modal.js +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/permission-management-modal.js @@ -12,7 +12,7 @@ $tab.find('.custom-checkbox') .filter('[data-permission-name="' + parentName + '"]') .find('input[type="checkbox"]') - .each(function() { + .each(function () { var $parent = $(this); $parent.prop('checked', true); checkParents($tab, $parent); @@ -35,20 +35,170 @@ }); } - this.initDom = function($el) { + function handleUncheck($tab) { + var $checkBox = $tab.find('input[name="SelectAllInThisTab"]'); + + if ($checkBox.is(':checked')) { + if ($tab.find('input[type="checkbox"]').not('[name="SelectAllInThisTab"]').length > 1) { + $($checkBox).prop('indeterminate', true); + } + else { + $checkBox.prop('checked', false); + } + } + else if ($checkBox.is(':indeterminate')) { + var allUnchecked = true; + + $tab.find('input[type="checkbox"]').not('[name="SelectAllInThisTab"]').each(function () { + if ($(this).is(':checked') === true) { + allUnchecked = false; + } + }); + + if (allUnchecked) { + $($checkBox).prop('indeterminate', false); + $checkBox.prop('checked', false); + } + } + } + + function handleCheck($tab) { + var $checkBox = $tab.find('input[name="SelectAllInThisTab"]'); + + var allChecked = true; + + $tab.find('input[type="checkbox"]').not('[name="SelectAllInThisTab"]').each(function () { + if ($(this).is(':checked') === false) { + allChecked = false; + } + }); + + if (allChecked) { + $($checkBox).prop('indeterminate', false); + $checkBox.prop('checked', true); + } + else { + $($checkBox).prop('indeterminate', true); + } + } + + function initSelectAllInThisTab() { + var tabs = $('.tab-pane'); + for (var i = 0; i < tabs.length; i++) { + var $tab = $(tabs[i]); + var $checkBox = $tab.find('input[name="SelectAllInThisTab"]'); + + var allChecked = true; + var allUnChecked = true; + + $tab.find('input[type="checkbox"]').not('[name="SelectAllInThisTab"]').each(function () { + if ($(this).is(':checked') === true) { + allUnChecked = false; + } else { + allChecked = false; + } + }); + + if (allChecked) { + $($checkBox).prop('checked', true); + } + else if (allUnChecked) { + $($checkBox).prop('checked', false); + } + else { + $($checkBox).prop('indeterminate', true); + } + } + } + + function setSelectAllInAllTabs() { + var $checkBox = $('#SelectAllInAllTabs'); + + var anyIndeterminate = false; + var allChecked = true; + var allUnChecked = true; + + $('input[name="SelectAllInThisTab"]').each(function () { + if ($(this).is(':checked') === true) { + allUnChecked = false; + } else { + allChecked = false; + } + + if ($(this).is(':indeterminate') === true) { + anyIndeterminate = true; + } + }); + + if (anyIndeterminate) { + $($checkBox).prop('indeterminate', true); + return; + } else { + $($checkBox).prop('indeterminate', false); + } + + if (allChecked) { + $($checkBox).prop('checked', true); + } + else if (allUnChecked) { + $($checkBox).prop('checked', false); + } + else { + $($checkBox).prop('indeterminate', true); + } + } + + this.initDom = function ($el) { $el.find('.tab-pane').each(function () { var $tab = $(this); - $tab.find('input[type="checkbox"]').each(function () { + $tab.find('input[type="checkbox"]').not('[name="SelectAllInThisTab"]').each(function () { var $checkBox = $(this); $checkBox.change(function () { if ($checkBox.is(':checked')) { checkParents($tab, $checkBox); + handleCheck($tab); } else { uncheckChildren($tab, $checkBox); + handleUncheck($tab); } + setSelectAllInAllTabs(); }); }); }); + + $('input[name="SelectAllInThisTab"]').change(function () { + var $checkBox = $(this); + var $tab = $('#' + $checkBox.attr('data-tab-id')); + if ($checkBox.is(':checked')) { + $tab.find('input[type="checkbox"]').prop('checked', true); + } else { + $tab.find('input[type="checkbox"]').prop('checked', false); + } + $($checkBox).prop('indeterminate', false); + setSelectAllInAllTabs(); + }); + + $('input[name="SelectAllInAllTabs"]').change(function () { + var $checkBox = $(this); + if ($checkBox.is(':checked')) { + $('.tab-pane input[type="checkbox"]').prop('checked', true); + } else { + $('.tab-pane input[type="checkbox"]').prop('checked', false); + } + $($checkBox).prop('indeterminate', false); + }); + + $(function () { + $(".custom-scroll-content").mCustomScrollbar({ + theme: "minimal-dark" + }); + $(".custom-scroll-container > .col-4").mCustomScrollbar({ + theme: "minimal-dark" + }); + }); + + initSelectAllInThisTab(); + setSelectAllInAllTabs(); }; }; })(jQuery); \ No newline at end of file