Browse Source

Merge branch 'dev' into studio-dev

pull/10363/head
Yunus Emre Kalkan 5 years ago
parent
commit
99447abca4
  1. 22
      docs/en/Background-Jobs-Hangfire.md
  2. 5
      docs/en/Tutorials/Part-1.md
  3. 5
      docs/en/Tutorials/Part-10.md
  4. 7
      docs/en/Tutorials/Part-2.md
  5. 5
      docs/en/Tutorials/Part-3.md
  6. 5
      docs/en/Tutorials/Part-4.md
  7. 7
      docs/en/Tutorials/Part-5.md
  8. 7
      docs/en/Tutorials/Part-6.md
  9. 5
      docs/en/Tutorials/Part-7.md
  10. 5
      docs/en/Tutorials/Part-8.md
  11. 5
      docs/en/Tutorials/Part-9.md
  12. 6
      docs/zh-Hans/Text-Templating.md
  13. 2
      framework/src/Volo.Abp.EntityFrameworkCore.Oracle/Volo.Abp.EntityFrameworkCore.Oracle.csproj
  14. 3
      framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/AbpHttpClientModule.cs
  15. 2
      framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ApiVersionInfo.cs
  16. 269
      framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyBase.cs
  17. 6
      framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyRequestContext.cs
  18. 13
      framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyRequestPayloadBuilder.cs
  19. 17
      framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyUrlBuilder.cs
  20. 63
      framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs
  21. 19
      framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptorClientProxy.cs
  22. 267
      framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/Proxying/HttpProxyExecuter.cs
  23. 12
      framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/Proxying/IHttpProxyExecuter.cs
  24. 1
      modules/account/src/Volo.Abp.Account.Web/Pages/Account/Components/ProfileManagementGroup/Password/AccountProfilePasswordManagementGroupViewComponent.cs
  25. 1
      modules/account/src/Volo.Abp.Account.Web/Pages/Account/Components/ProfileManagementGroup/PersonalInfo/AccountProfilePersonalInfoManagementGroupViewComponent.cs
  26. 5
      modules/blogging/app/Volo.BloggingTestApp/BloggingTestAppModule.cs
  27. 12
      modules/blogging/app/Volo.BloggingTestApp/Volo.BloggingTestApp.csproj
  28. 1
      modules/cms-kit/host/Volo.CmsKit.IdentityServer/CmsKitIdentityServerModule.cs
  29. 1
      modules/cms-kit/host/Volo.CmsKit.IdentityServer/Volo.CmsKit.IdentityServer.csproj
  30. 3123
      modules/cms-kit/host/Volo.CmsKit.IdentityServer/wwwroot/libs/sweetalert2/sweetalert2.all.js
  31. 2
      modules/cms-kit/host/Volo.CmsKit.IdentityServer/wwwroot/libs/sweetalert2/sweetalert2.all.min.js
  32. 1319
      modules/cms-kit/host/Volo.CmsKit.IdentityServer/wwwroot/libs/sweetalert2/sweetalert2.css
  33. 3121
      modules/cms-kit/host/Volo.CmsKit.IdentityServer/wwwroot/libs/sweetalert2/sweetalert2.js
  34. 1
      modules/cms-kit/host/Volo.CmsKit.IdentityServer/wwwroot/libs/sweetalert2/sweetalert2.min.css
  35. 1
      modules/cms-kit/host/Volo.CmsKit.IdentityServer/wwwroot/libs/sweetalert2/sweetalert2.min.js
  36. 3123
      modules/cms-kit/host/Volo.CmsKit.Web.Host/wwwroot/libs/sweetalert2/sweetalert2.all.js
  37. 2
      modules/cms-kit/host/Volo.CmsKit.Web.Host/wwwroot/libs/sweetalert2/sweetalert2.all.min.js
  38. 1319
      modules/cms-kit/host/Volo.CmsKit.Web.Host/wwwroot/libs/sweetalert2/sweetalert2.css
  39. 3121
      modules/cms-kit/host/Volo.CmsKit.Web.Host/wwwroot/libs/sweetalert2/sweetalert2.js
  40. 1
      modules/cms-kit/host/Volo.CmsKit.Web.Host/wwwroot/libs/sweetalert2/sweetalert2.min.css
  41. 1
      modules/cms-kit/host/Volo.CmsKit.Web.Host/wwwroot/libs/sweetalert2/sweetalert2.min.js
  42. 11
      modules/cms-kit/host/Volo.CmsKit.Web.Unified/CmsKitWebUnifiedModule.cs
  43. 6
      modules/cms-kit/host/Volo.CmsKit.Web.Unified/Volo.CmsKit.Web.Unified.csproj
  44. 3123
      modules/cms-kit/host/Volo.CmsKit.Web.Unified/wwwroot/libs/sweetalert2/sweetalert2.all.js
  45. 2
      modules/cms-kit/host/Volo.CmsKit.Web.Unified/wwwroot/libs/sweetalert2/sweetalert2.all.min.js
  46. 1319
      modules/cms-kit/host/Volo.CmsKit.Web.Unified/wwwroot/libs/sweetalert2/sweetalert2.css
  47. 3121
      modules/cms-kit/host/Volo.CmsKit.Web.Unified/wwwroot/libs/sweetalert2/sweetalert2.js
  48. 1
      modules/cms-kit/host/Volo.CmsKit.Web.Unified/wwwroot/libs/sweetalert2/sweetalert2.min.css
  49. 1
      modules/cms-kit/host/Volo.CmsKit.Web.Unified/wwwroot/libs/sweetalert2/sweetalert2.min.js
  50. 3
      modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Menus/MenuItemAdminAppService.cs
  51. 12
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Menus/MenuItem.cs
  52. 5
      modules/docs/app/VoloDocs.Web/VoloDocs.Web.csproj
  53. 10
      modules/docs/app/VoloDocs.Web/VoloDocsWebModule.cs
  54. 3123
      modules/docs/app/VoloDocs.Web/wwwroot/libs/sweetalert2/sweetalert2.all.js
  55. 2
      modules/docs/app/VoloDocs.Web/wwwroot/libs/sweetalert2/sweetalert2.all.min.js
  56. 1319
      modules/docs/app/VoloDocs.Web/wwwroot/libs/sweetalert2/sweetalert2.css
  57. 3121
      modules/docs/app/VoloDocs.Web/wwwroot/libs/sweetalert2/sweetalert2.js
  58. 1
      modules/docs/app/VoloDocs.Web/wwwroot/libs/sweetalert2/sweetalert2.min.css
  59. 1
      modules/docs/app/VoloDocs.Web/wwwroot/libs/sweetalert2/sweetalert2.min.js
  60. 4
      modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/ProfileAppService.cs
  61. 2
      modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/PermissionManagementModal.cshtml
  62. 5
      modules/setting-management/app/Volo.Abp.SettingManagement.DemoApp/DemoAppModule.cs
  63. 4
      modules/setting-management/app/Volo.Abp.SettingManagement.DemoApp/Volo.Abp.SettingManagement.DemoApp.csproj
  64. 3123
      modules/setting-management/app/Volo.Abp.SettingManagement.DemoApp/wwwroot/libs/sweetalert2/sweetalert2.all.js
  65. 2
      modules/setting-management/app/Volo.Abp.SettingManagement.DemoApp/wwwroot/libs/sweetalert2/sweetalert2.all.min.js
  66. 1319
      modules/setting-management/app/Volo.Abp.SettingManagement.DemoApp/wwwroot/libs/sweetalert2/sweetalert2.css
  67. 3121
      modules/setting-management/app/Volo.Abp.SettingManagement.DemoApp/wwwroot/libs/sweetalert2/sweetalert2.js
  68. 1
      modules/setting-management/app/Volo.Abp.SettingManagement.DemoApp/wwwroot/libs/sweetalert2/sweetalert2.min.css
  69. 1
      modules/setting-management/app/Volo.Abp.SettingManagement.DemoApp/wwwroot/libs/sweetalert2/sweetalert2.min.js
  70. 3
      modules/setting-management/src/Volo.Abp.SettingManagement.Application/Volo/Abp/SettingManagement/EmailSettingsAppService.cs
  71. 15
      modules/setting-management/src/Volo.Abp.SettingManagement.Web/Settings/EmailingPageContributor.cs
  72. 3123
      modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/wwwroot/libs/sweetalert2/sweetalert2.all.js
  73. 2
      modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/wwwroot/libs/sweetalert2/sweetalert2.all.min.js
  74. 1319
      modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/wwwroot/libs/sweetalert2/sweetalert2.css
  75. 3121
      modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/wwwroot/libs/sweetalert2/sweetalert2.js
  76. 1
      modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/wwwroot/libs/sweetalert2/sweetalert2.min.css
  77. 1
      modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/wwwroot/libs/sweetalert2/sweetalert2.min.js
  78. 4
      npm/ng-packs/package.json
  79. 8
      npm/ng-packs/packages/account-core/src/lib/tenant-box.service.ts
  80. 5
      npm/ng-packs/packages/core/src/lib/core.module.ts
  81. 1
      npm/ng-packs/packages/core/src/lib/directives/index.ts
  82. 20
      npm/ng-packs/packages/core/src/lib/directives/permission.directive.ts
  83. 66
      npm/ng-packs/packages/core/src/lib/directives/visibility.directive.ts
  84. 117
      npm/ng-packs/packages/core/src/lib/models/application-configuration.ts
  85. 1
      npm/ng-packs/packages/core/src/lib/models/index.ts
  86. 15
      npm/ng-packs/packages/core/src/lib/models/session.ts
  87. 24
      npm/ng-packs/packages/core/src/lib/services/application-configuration.service.ts
  88. 7
      npm/ng-packs/packages/core/src/lib/services/auth.service.ts
  89. 14
      npm/ng-packs/packages/core/src/lib/services/config-state.service.ts
  90. 1
      npm/ng-packs/packages/core/src/lib/services/index.ts
  91. 38
      npm/ng-packs/packages/core/src/lib/services/multi-tenancy.service.ts
  92. 27
      npm/ng-packs/packages/core/src/lib/tests/application-configuration.service.spec.ts
  93. 12
      npm/ng-packs/packages/core/src/lib/tests/config-state.service.spec.ts
  94. 29
      npm/ng-packs/packages/core/src/lib/tests/localization.service.spec.ts
  95. 2
      npm/ng-packs/packages/core/src/lib/tests/permission.directive.spec.ts
  96. 126
      npm/ng-packs/packages/core/src/lib/tests/visibility.directive.spec.ts
  97. 1
      npm/ng-packs/packages/core/src/lib/utils/date-utils.ts
  98. 1
      npm/ng-packs/packages/core/src/lib/utils/index.ts
  99. 31
      npm/ng-packs/packages/core/src/lib/utils/rxjs-utils.ts
  100. 2
      npm/ng-packs/packages/feature-management/src/lib/components/feature-management/feature-management.component.html

22
docs/en/Background-Jobs-Hangfire.md

@ -88,17 +88,21 @@ To make it secure by default, only local requests are allowed, however you can c
You can integrate the Hangfire dashboard to [ABP authorization system](Authorization.md) using the **AbpHangfireAuthorizationFilter**
class. This class is defined in the `Volo.Abp.Hangfire` package. The following example, checks if the current user is logged in to the application:
app.UseHangfireDashboard("/hangfire", new DashboardOptions
{
AsyncAuthorization = new[] { new AbpHangfireAuthorizationFilter() }
});
```csharp
app.UseHangfireDashboard("/hangfire", new DashboardOptions
{
AsyncAuthorization = new[] { new AbpHangfireAuthorizationFilter() }
});
```
If you want to require an additional permission, you can pass it into the constructor as below:
app.UseHangfireDashboard("/hangfire", new DashboardOptions
{
AsyncAuthorization = new[] { new AbpHangfireAuthorizationFilter("MyHangFireDashboardPermissionName") }
});
```csharp
app.UseHangfireDashboard("/hangfire", new DashboardOptions
{
AsyncAuthorization = new[] { new AbpHangfireAuthorizationFilter("MyHangFireDashboardPermissionName") }
});
```
**Important**: `UseHangfireDashboard` should be called after the authentication middleware in your `Startup` class (probably at the last line). Otherwise,
**Important**: `UseHangfireDashboard` should be called after the authentication and authorization middlewares in your `Startup` class (probably at the last line). Otherwise,
authorization will always fail!

5
docs/en/Tutorials/Part-1.md

@ -34,6 +34,11 @@ This tutorial has multiple versions based on your **UI** and **Database** prefer
* [Blazor UI with EF Core](https://github.com/abpframework/abp-samples/tree/master/BookStore-Blazor-EfCore)
* [Angular UI with MongoDB](https://github.com/abpframework/abp-samples/tree/master/BookStore-Angular-MongoDb)
> If you encounter the "filename too long" or "unzip error" on Windows, it's probably related to the Windows maximum file path limitation. Windows has a maximum file path limitation of 250 characters. To solve this, [enable the long path option in Windows 10](https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=cmd#enable-long-paths-in-windows-10-version-1607-and-later).
> If you face long path errors related to Git, try the following command to enable long paths in Windows. See https://github.com/msysgit/msysgit/wiki/Git-cannot-create-a-file-or-directory-with-a-long-path
> `git config --system core.longpaths true`
{{if UI == "MVC" && DB == "EF"}}
### Video Tutorial

5
docs/en/Tutorials/Part-10.md

@ -34,6 +34,11 @@ This tutorial has multiple versions based on your **UI** and **Database** prefer
* [Blazor UI with EF Core](https://github.com/abpframework/abp-samples/tree/master/BookStore-Blazor-EfCore)
* [Angular UI with MongoDB](https://github.com/abpframework/abp-samples/tree/master/BookStore-Angular-MongoDb)
> If you encounter the "filename too long" or "unzip error" on Windows, it's probably related to the Windows maximum file path limitation. Windows has a maximum file path limitation of 250 characters. To solve this, [enable the long path option in Windows 10](https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=cmd#enable-long-paths-in-windows-10-version-1607-and-later).
> If you face long path errors related to Git, try the following command to enable long paths in Windows. See https://github.com/msysgit/msysgit/wiki/Git-cannot-create-a-file-or-directory-with-a-long-path
> `git config --system core.longpaths true`
## Introduction
We have created `Book` and `Author` functionalities for the book store application. However, currently there is no relation between these entities.

7
docs/en/Tutorials/Part-2.md

@ -34,6 +34,11 @@ This tutorial has multiple versions based on your **UI** and **Database** prefer
* [Blazor UI with EF Core](https://github.com/abpframework/abp-samples/tree/master/BookStore-Blazor-EfCore)
* [Angular UI with MongoDB](https://github.com/abpframework/abp-samples/tree/master/BookStore-Angular-MongoDb)
> If you encounter the "filename too long" or "unzip error" on Windows, it's probably related to the Windows maximum file path limitation. Windows has a maximum file path limitation of 250 characters. To solve this, [enable the long path option in Windows 10](https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=cmd#enable-long-paths-in-windows-10-version-1607-and-later).
> If you face long path errors related to Git, try the following command to enable long paths in Windows. See https://github.com/msysgit/msysgit/wiki/Git-cannot-create-a-file-or-directory-with-a-long-path
> `git config --system core.longpaths true`
{{if UI == "MVC" && DB == "EF"}}
### Video Tutorial
@ -85,6 +90,8 @@ acme.bookStore.books.book.create({
});
````
> If you downloaded the source code of the tutorial and following the steps from the sample, you should also pass the `authorId` parameter to the create method for **creating a new book**.
You should see a message in the console something like that:
````text

5
docs/en/Tutorials/Part-3.md

@ -34,6 +34,11 @@ This tutorial has multiple versions based on your **UI** and **Database** prefer
* [Blazor UI with EF Core](https://github.com/abpframework/abp-samples/tree/master/BookStore-Blazor-EfCore)
* [Angular UI with MongoDB](https://github.com/abpframework/abp-samples/tree/master/BookStore-Angular-MongoDb)
> If you encounter the "filename too long" or "unzip error" on Windows, it's probably related to the Windows maximum file path limitation. Windows has a maximum file path limitation of 250 characters. To solve this, [enable the long path option in Windows 10](https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=cmd#enable-long-paths-in-windows-10-version-1607-and-later).
> If you face long path errors related to Git, try the following command to enable long paths in Windows. See https://github.com/msysgit/msysgit/wiki/Git-cannot-create-a-file-or-directory-with-a-long-path
> `git config --system core.longpaths true`
{{if UI == "MVC" && DB == "EF"}}
### Video Tutorial

5
docs/en/Tutorials/Part-4.md

@ -34,6 +34,11 @@ This tutorial has multiple versions based on your **UI** and **Database** prefer
* [Blazor UI with EF Core](https://github.com/abpframework/abp-samples/tree/master/BookStore-Blazor-EfCore)
* [Angular UI with MongoDB](https://github.com/abpframework/abp-samples/tree/master/BookStore-Angular-MongoDb)
> If you encounter the "filename too long" or "unzip error" on Windows, it's probably related to the Windows maximum file path limitation. Windows has a maximum file path limitation of 250 characters. To solve this, [enable the long path option in Windows 10](https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=cmd#enable-long-paths-in-windows-10-version-1607-and-later).
> If you face long path errors related to Git, try the following command to enable long paths in Windows. See https://github.com/msysgit/msysgit/wiki/Git-cannot-create-a-file-or-directory-with-a-long-path
> `git config --system core.longpaths true`
{{if UI == "MVC" && DB == "EF"}}
### Video Tutorial

7
docs/en/Tutorials/Part-5.md

@ -34,6 +34,11 @@ This tutorial has multiple versions based on your **UI** and **Database** prefer
* [Blazor UI with EF Core](https://github.com/abpframework/abp-samples/tree/master/BookStore-Blazor-EfCore)
* [Angular UI with MongoDB](https://github.com/abpframework/abp-samples/tree/master/BookStore-Angular-MongoDb)
> If you encounter the "filename too long" or "unzip error" on Windows, it's probably related to the Windows maximum file path limitation. Windows has a maximum file path limitation of 250 characters. To solve this, [enable the long path option in Windows 10](https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=cmd#enable-long-paths-in-windows-10-version-1607-and-later).
> If you face long path errors related to Git, try the following command to enable long paths in Windows. See https://github.com/msysgit/msysgit/wiki/Git-cannot-create-a-file-or-directory-with-a-long-path
> `git config --system core.longpaths true`
{{if UI == "MVC" && DB == "EF"}}
### Video Tutorial
@ -627,4 +632,4 @@ private async Task ConfigureMainMenuAsync(MenuConfigurationContext context)
## The Next Part
See the [next part](Part-6.md) of this tutorial.
See the [next part](Part-6.md) of this tutorial.

7
docs/en/Tutorials/Part-6.md

@ -34,6 +34,11 @@ This tutorial has multiple versions based on your **UI** and **Database** prefer
* [Blazor UI with EF Core](https://github.com/abpframework/abp-samples/tree/master/BookStore-Blazor-EfCore)
* [Angular UI with MongoDB](https://github.com/abpframework/abp-samples/tree/master/BookStore-Angular-MongoDb)
> If you encounter the "filename too long" or "unzip error" on Windows, it's probably related to the Windows maximum file path limitation. Windows has a maximum file path limitation of 250 characters. To solve this, [enable the long path option in Windows 10](https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=cmd#enable-long-paths-in-windows-10-version-1607-and-later).
> If you face long path errors related to Git, try the following command to enable long paths in Windows. See https://github.com/msysgit/msysgit/wiki/Git-cannot-create-a-file-or-directory-with-a-long-path
> `git config --system core.longpaths true`
## Introduction
In the previous parts, we've used the ABP infrastructure to easily build some services;
@ -270,4 +275,4 @@ This part covered the domain layer of the authors functionality of the book stor
## The Next Part
See the [next part](Part-7.md) of this tutorial.
See the [next part](Part-7.md) of this tutorial.

5
docs/en/Tutorials/Part-7.md

@ -34,6 +34,11 @@ This tutorial has multiple versions based on your **UI** and **Database** prefer
* [Blazor UI with EF Core](https://github.com/abpframework/abp-samples/tree/master/BookStore-Blazor-EfCore)
* [Angular UI with MongoDB](https://github.com/abpframework/abp-samples/tree/master/BookStore-Angular-MongoDb)
> If you encounter the "filename too long" or "unzip error" on Windows, it's probably related to the Windows maximum file path limitation. Windows has a maximum file path limitation of 250 characters. To solve this, [enable the long path option in Windows 10](https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=cmd#enable-long-paths-in-windows-10-version-1607-and-later).
> If you face long path errors related to Git, try the following command to enable long paths in Windows. See https://github.com/msysgit/msysgit/wiki/Git-cannot-create-a-file-or-directory-with-a-long-path
> `git config --system core.longpaths true`
## Introduction
This part explains how to configure the database integration for the `Author` entity introduced in the previous part.

5
docs/en/Tutorials/Part-8.md

@ -34,6 +34,11 @@ This tutorial has multiple versions based on your **UI** and **Database** prefer
* [Blazor UI with EF Core](https://github.com/abpframework/abp-samples/tree/master/BookStore-Blazor-EfCore)
* [Angular UI with MongoDB](https://github.com/abpframework/abp-samples/tree/master/BookStore-Angular-MongoDb)
> If you encounter the "filename too long" or "unzip error" on Windows, it's probably related to the Windows maximum file path limitation. Windows has a maximum file path limitation of 250 characters. To solve this, [enable the long path option in Windows 10](https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=cmd#enable-long-paths-in-windows-10-version-1607-and-later).
> If you face long path errors related to Git, try the following command to enable long paths in Windows. See https://github.com/msysgit/msysgit/wiki/Git-cannot-create-a-file-or-directory-with-a-long-path
> `git config --system core.longpaths true`
## Introduction
This part explains to create an application layer for the `Author` entity created before.

5
docs/en/Tutorials/Part-9.md

@ -34,6 +34,11 @@ This tutorial has multiple versions based on your **UI** and **Database** prefer
* [Blazor UI with EF Core](https://github.com/abpframework/abp-samples/tree/master/BookStore-Blazor-EfCore)
* [Angular UI with MongoDB](https://github.com/abpframework/abp-samples/tree/master/BookStore-Angular-MongoDb)
> If you encounter the "filename too long" or "unzip error" on Windows, it's probably related to the Windows maximum file path limitation. Windows has a maximum file path limitation of 250 characters. To solve this, [enable the long path option in Windows 10](https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=cmd#enable-long-paths-in-windows-10-version-1607-and-later).
> If you face long path errors related to Git, try the following command to enable long paths in Windows. See https://github.com/msysgit/msysgit/wiki/Git-cannot-create-a-file-or-directory-with-a-long-path
> `git config --system core.longpaths true`
## Introduction
This part explains how to create a CRUD page for the `Author` entity introduced in the previous parts.

6
docs/zh-Hans/Text-Templating.md

@ -187,9 +187,9 @@ var result = await _templateRenderer.RenderAsync(
示例中我们并没有创建模型类,但是创建了一个匿名对象模型.
### 大驼峰 与 小驼峰
### PascalCase 与 snake_case
PascalCase 属性名(如 `UserName`) 在模板中用做小驼峰(如 `userName`).
PascalCase 属性名(如 `UserName`) 在模板中使用蛇形命名(如 `user_name`).
## 本地化
@ -454,4 +454,4 @@ public class MyTemplateContentProvider
* 本文开发和引用的[应用程序示例源码](https://github.com/abpframework/abp-samples/tree/master/TextTemplateDemo).
* [本地化系统](Localization.md).
* [虚拟文件系统](Virtual-File-System.md).
* [虚拟文件系统](Virtual-File-System.md).

2
framework/src/Volo.Abp.EntityFrameworkCore.Oracle/Volo.Abp.EntityFrameworkCore.Oracle.csproj

@ -18,7 +18,7 @@
<ProjectReference Include="..\Volo.Abp.EntityFrameworkCore\Volo.Abp.EntityFrameworkCore.csproj" />
</ItemGroup>
<ItemGroup>
<ItemGroup>
<PackageReference Include="Oracle.EntityFrameworkCore" Version="5.21.1" />
</ItemGroup>

3
framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/AbpHttpClientModule.cs

@ -5,6 +5,7 @@ using Volo.Abp.MultiTenancy;
using Volo.Abp.Threading;
using Volo.Abp.Validation;
using Volo.Abp.ExceptionHandling;
using Volo.Abp.Http.Client.DynamicProxying;
namespace Volo.Abp.Http.Client
{
@ -22,6 +23,8 @@ namespace Volo.Abp.Http.Client
{
var configuration = context.Services.GetConfiguration();
Configure<AbpRemoteServiceOptions>(configuration);
context.Services.AddTransient(typeof(DynamicHttpProxyInterceptorClientProxy<>));
}
}
}

2
framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/Proxying/ApiVersionInfo.cs → framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ApiVersionInfo.cs

@ -1,6 +1,6 @@
using System;
namespace Volo.Abp.Http.Client.Proxying
namespace Volo.Abp.Http.Client.ClientProxying
{
public class ApiVersionInfo //TODO: Rename to not conflict with api versioning apis
{

269
framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyBase.cs

@ -1,9 +1,23 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.Primitives;
using Volo.Abp.Content;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Http.Client.Authentication;
using Volo.Abp.Http.Client.Proxying;
using Volo.Abp.Http.Modeling;
using Volo.Abp.Http.ProxyScripting.Generators;
using Volo.Abp.Json;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Threading;
using Volo.Abp.Tracing;
namespace Volo.Abp.Http.Client.ClientProxying
{
@ -11,42 +25,265 @@ namespace Volo.Abp.Http.Client.ClientProxying
{
public IAbpLazyServiceProvider LazyServiceProvider { get; set; }
protected IHttpProxyExecuter HttpProxyExecuter => LazyServiceProvider.LazyGetRequiredService<IHttpProxyExecuter>();
protected IClientProxyApiDescriptionFinder ClientProxyApiDescriptionFinder => LazyServiceProvider.LazyGetRequiredService<IClientProxyApiDescriptionFinder>();
protected ICancellationTokenProvider CancellationTokenProvider => LazyServiceProvider.LazyGetRequiredService<ICancellationTokenProvider>();
protected ICorrelationIdProvider CorrelationIdProvider => LazyServiceProvider.LazyGetRequiredService<ICorrelationIdProvider>();
protected ICurrentTenant CurrentTenant => LazyServiceProvider.LazyGetRequiredService<ICurrentTenant>();
protected IOptions<AbpCorrelationIdOptions> AbpCorrelationIdOptions => LazyServiceProvider.LazyGetRequiredService<IOptions<AbpCorrelationIdOptions>>();
protected IProxyHttpClientFactory HttpClientFactory => LazyServiceProvider.LazyGetRequiredService<IProxyHttpClientFactory>();
protected IRemoteServiceConfigurationProvider RemoteServiceConfigurationProvider => LazyServiceProvider.LazyGetRequiredService<IRemoteServiceConfigurationProvider>();
protected IOptions<AbpHttpClientOptions> ClientOptions => LazyServiceProvider.LazyGetRequiredService<IOptions<AbpHttpClientOptions>>();
protected IJsonSerializer JsonSerializer => LazyServiceProvider.LazyGetRequiredService<IJsonSerializer>();
protected IRemoteServiceHttpClientAuthenticator ClientAuthenticator => LazyServiceProvider.LazyGetRequiredService<IRemoteServiceHttpClientAuthenticator>();
protected ClientProxyRequestPayloadBuilder ClientProxyRequestPayloadBuilder => LazyServiceProvider.LazyGetRequiredService<ClientProxyRequestPayloadBuilder>();
protected ClientProxyUrlBuilder ClientProxyUrlBuilder => LazyServiceProvider.LazyGetRequiredService<ClientProxyUrlBuilder>();
protected virtual async Task RequestAsync(string methodName, params object[] arguments)
{
await HttpProxyExecuter.MakeRequestAsync(BuildHttpProxyExecuterContext(methodName, arguments));
await RequestAsync(BuildHttpProxyClientProxyContext(methodName, arguments));
}
protected virtual async Task<T> RequestAsync<T>(string methodName, params object[] arguments)
{
return await HttpProxyExecuter.MakeRequestAndGetResultAsync<T>(BuildHttpProxyExecuterContext(methodName, arguments));
return await RequestAsync<T>(BuildHttpProxyClientProxyContext(methodName, arguments));
}
protected virtual HttpProxyExecuterContext BuildHttpProxyExecuterContext(string methodName, params object[] arguments)
protected virtual ClientProxyRequestContext BuildHttpProxyClientProxyContext(string methodName, params object[] arguments)
{
var actionKey = GetActionKey(methodName, arguments);
var action = ClientProxyApiDescriptionFinder.FindAction(actionKey);
return new HttpProxyExecuterContext(action, BuildArguments(action, arguments), typeof(TService));
var methodUniqueName = $"{typeof(TService).FullName}.{methodName}.{string.Join("-", arguments.Select(x => x.GetType().FullName))}";
var action = ClientProxyApiDescriptionFinder.FindAction(methodUniqueName);
if (action == null)
{
throw new AbpException($"The API description of the {typeof(TService).FullName}.{methodName} method was not found!");
}
return new ClientProxyRequestContext(
action,
action.Parameters
.GroupBy(x => x.NameOnMethod)
.Select((x, i) => new KeyValuePair<string, object>(x.Key, arguments[i]))
.ToDictionary(x => x.Key, x => x.Value),
typeof(TService));
}
protected virtual Dictionary<string, object> BuildArguments(ActionApiDescriptionModel action, object[] arguments)
protected virtual async Task<T> RequestAsync<T>(ClientProxyRequestContext requestContext)
{
var parameters = action.Parameters.GroupBy(x => x.NameOnMethod).Select(x => x.Key).ToList();
var dict = new Dictionary<string, object>();
var responseContent = await RequestAsync(requestContext);
if (typeof(T) == typeof(IRemoteStreamContent) ||
typeof(T) == typeof(RemoteStreamContent))
{
/* returning a class that holds a reference to response
* content just to be sure that GC does not dispose of
* it before we finish doing our work with the stream */
return (T)(object)new RemoteStreamContent(
await responseContent.ReadAsStreamAsync(),
responseContent.Headers?.ContentDisposition?.FileNameStar ??
RemoveQuotes(responseContent.Headers?.ContentDisposition?.FileName).ToString(),
responseContent.Headers?.ContentType?.ToString(),
responseContent.Headers?.ContentLength);
}
var stringContent = await responseContent.ReadAsStringAsync();
if (typeof(T) == typeof(string))
{
return (T)(object)stringContent;
}
if (stringContent.IsNullOrWhiteSpace())
{
return default;
}
return JsonSerializer.Deserialize<T>(stringContent);
}
protected virtual async Task<HttpContent> RequestAsync(ClientProxyRequestContext requestContext)
{
var clientConfig = ClientOptions.Value.HttpClientProxies.GetOrDefault(requestContext.ServiceType) ?? throw new AbpException($"Could not get HttpClientProxyConfig for {requestContext.ServiceType.FullName}.");
var remoteServiceConfig = await RemoteServiceConfigurationProvider.GetConfigurationOrDefaultAsync(clientConfig.RemoteServiceName);
var client = HttpClientFactory.Create(clientConfig.RemoteServiceName);
var apiVersion = await GetApiVersionInfoAsync(requestContext);
var url = remoteServiceConfig.BaseUrl.EnsureEndsWith('/') + await GetUrlWithParametersAsync(requestContext, apiVersion);
var requestMessage = new HttpRequestMessage(requestContext.Action.GetHttpMethod(), url)
{
Content = ClientProxyRequestPayloadBuilder.BuildContent(requestContext.Action, requestContext.Arguments, JsonSerializer, apiVersion)
};
AddHeaders(requestContext.Arguments, requestContext.Action, requestMessage, apiVersion);
if (requestContext.Action.AllowAnonymous != true)
{
await ClientAuthenticator.Authenticate(
new RemoteServiceHttpClientAuthenticateContext(
client,
requestMessage,
remoteServiceConfig,
clientConfig.RemoteServiceName
)
);
}
var response = await client.SendAsync(
requestMessage,
HttpCompletionOption.ResponseHeadersRead /*this will buffer only the headers, the content will be used as a stream*/,
GetCancellationToken(requestContext.Arguments)
);
for (var i = 0; i < parameters.Count; i++)
if (!response.IsSuccessStatusCode)
{
dict[parameters[i]] = arguments[i];
await ThrowExceptionForResponseAsync(response);
}
return dict;
return response.Content;
}
protected virtual async Task<ApiVersionInfo> GetApiVersionInfoAsync(ClientProxyRequestContext requestContext)
{
var apiVersion = await FindBestApiVersionAsync(requestContext);
//TODO: Make names configurable?
var versionParam = requestContext.Action.Parameters.FirstOrDefault(p => p.Name == "apiVersion" && p.BindingSourceId == ParameterBindingSources.Path) ??
requestContext.Action.Parameters.FirstOrDefault(p => p.Name == "api-version" && p.BindingSourceId == ParameterBindingSources.Query);
return new ApiVersionInfo(versionParam?.BindingSourceId, apiVersion);
}
protected virtual Task<string> GetUrlWithParametersAsync(ClientProxyRequestContext requestContext, ApiVersionInfo apiVersion)
{
return Task.FromResult(ClientProxyUrlBuilder.GenerateUrlWithParameters(requestContext.Action, requestContext.Arguments, apiVersion));
}
private static string GetActionKey(string methodName, params object[] arguments)
protected virtual Task<HttpContent> GetHttpContentAsync(ClientProxyRequestContext requestContext, ApiVersionInfo apiVersion)
{
return $"{typeof(TService).FullName}.{methodName}.{string.Join("-", arguments.Select(x => x.GetType().FullName))}";
return Task.FromResult(ClientProxyRequestPayloadBuilder.BuildContent(requestContext.Action, requestContext.Arguments, JsonSerializer, apiVersion));
}
protected virtual async Task<string> FindBestApiVersionAsync(ClientProxyRequestContext requestContext)
{
var configuredVersion = await GetConfiguredApiVersionAsync(requestContext);
if (requestContext.Action.SupportedVersions.IsNullOrEmpty())
{
return configuredVersion ?? "1.0";
}
if (requestContext.Action.SupportedVersions.Contains(configuredVersion))
{
return configuredVersion;
}
return requestContext.Action.SupportedVersions.Last(); //TODO: Ensure to get the latest version!
}
protected virtual async Task<string> GetConfiguredApiVersionAsync(ClientProxyRequestContext requestContext)
{
var clientConfig = ClientOptions.Value.HttpClientProxies.GetOrDefault(requestContext.ServiceType)
?? throw new AbpException($"Could not get DynamicHttpClientProxyConfig for {requestContext.ServiceType.FullName}.");
return (await RemoteServiceConfigurationProvider
.GetConfigurationOrDefaultOrNullAsync(clientConfig.RemoteServiceName))?.Version;
}
protected virtual async Task ThrowExceptionForResponseAsync(HttpResponseMessage response)
{
if (response.Headers.Contains(AbpHttpConsts.AbpErrorFormat))
{
var errorResponse = JsonSerializer.Deserialize<RemoteServiceErrorResponse>(
await response.Content.ReadAsStringAsync()
);
throw new AbpRemoteCallException(errorResponse.Error)
{
HttpStatusCode = (int) response.StatusCode
};
}
throw new AbpRemoteCallException(
new RemoteServiceErrorInfo
{
Message = response.ReasonPhrase,
Code = response.StatusCode.ToString()
}
)
{
HttpStatusCode = (int) response.StatusCode
};
}
protected virtual void AddHeaders(
IReadOnlyDictionary<string, object> argumentsDictionary,
ActionApiDescriptionModel action,
HttpRequestMessage requestMessage,
ApiVersionInfo apiVersion)
{
//API Version
if (!apiVersion.Version.IsNullOrEmpty())
{
//TODO: What about other media types?
requestMessage.Headers.Add("accept", $"{MimeTypes.Text.Plain}; v={apiVersion.Version}");
requestMessage.Headers.Add("accept", $"{MimeTypes.Application.Json}; v={apiVersion.Version}");
requestMessage.Headers.Add("api-version", apiVersion.Version);
}
//Header parameters
var headers = action.Parameters.Where(p => p.BindingSourceId == ParameterBindingSources.Header).ToArray();
foreach (var headerParameter in headers)
{
var value = HttpActionParameterHelper.FindParameterValue(argumentsDictionary, headerParameter);
if (value != null)
{
requestMessage.Headers.Add(headerParameter.Name, value.ToString());
}
}
//CorrelationId
requestMessage.Headers.Add(AbpCorrelationIdOptions.Value.HttpHeaderName, CorrelationIdProvider.Get());
//TenantId
if (CurrentTenant.Id.HasValue)
{
//TODO: Use AbpAspNetCoreMultiTenancyOptions to get the key
requestMessage.Headers.Add(TenantResolverConsts.DefaultTenantKey, CurrentTenant.Id.Value.ToString());
}
//Culture
//TODO: Is that the way we want? Couldn't send the culture (not ui culture)
var currentCulture = CultureInfo.CurrentUICulture.Name ?? CultureInfo.CurrentCulture.Name;
if (!currentCulture.IsNullOrEmpty())
{
requestMessage.Headers.AcceptLanguage.Add(new StringWithQualityHeaderValue(currentCulture));
}
//X-Requested-With
requestMessage.Headers.Add("X-Requested-With", "XMLHttpRequest");
}
protected virtual StringSegment RemoveQuotes(StringSegment input)
{
if (!StringSegment.IsNullOrEmpty(input) && input.Length >= 2 && input[0] == '"' && input[input.Length - 1] == '"')
{
input = input.Subsegment(1, input.Length - 2);
}
return input;
}
protected virtual CancellationToken GetCancellationToken(IReadOnlyDictionary<string, object> arguments)
{
var cancellationTokenArg = arguments.LastOrDefault();
if (cancellationTokenArg.Value is CancellationToken cancellationToken)
{
if (cancellationToken != default)
{
return cancellationToken;
}
}
return CancellationTokenProvider.Token;
}
}
}

6
framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/Proxying/HttpProxyExecuterContext.cs → framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyRequestContext.cs

@ -3,9 +3,9 @@ using System.Collections.Generic;
using JetBrains.Annotations;
using Volo.Abp.Http.Modeling;
namespace Volo.Abp.Http.Client.Proxying
namespace Volo.Abp.Http.Client.ClientProxying
{
public class HttpProxyExecuterContext
public class ClientProxyRequestContext
{
[NotNull]
public ActionApiDescriptionModel Action { get; }
@ -16,7 +16,7 @@ namespace Volo.Abp.Http.Client.Proxying
[NotNull]
public Type ServiceType { get; }
public HttpProxyExecuterContext(
public ClientProxyRequestContext(
[NotNull] ActionApiDescriptionModel action,
[NotNull] IReadOnlyDictionary<string, object> arguments,
[NotNull] Type serviceType)

13
framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/Proxying/RequestPayloadBuilder.cs → framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyRequestPayloadBuilder.cs

@ -6,17 +6,18 @@ using System.Net.Http.Headers;
using System.Text;
using JetBrains.Annotations;
using Volo.Abp.Content;
using Volo.Abp.Http.Client.DynamicProxying;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Http.Client.Proxying;
using Volo.Abp.Http.Modeling;
using Volo.Abp.Http.ProxyScripting.Generators;
using Volo.Abp.Json;
namespace Volo.Abp.Http.Client.Proxying
namespace Volo.Abp.Http.Client.ClientProxying
{
public static class RequestPayloadBuilder
public class ClientProxyRequestPayloadBuilder : ITransientDependency
{
[CanBeNull]
public static HttpContent BuildContent(ActionApiDescriptionModel action, IReadOnlyDictionary<string, object> methodArguments, IJsonSerializer jsonSerializer, ApiVersionInfo apiVersion)
public virtual HttpContent BuildContent(ActionApiDescriptionModel action, IReadOnlyDictionary<string, object> methodArguments, IJsonSerializer jsonSerializer, ApiVersionInfo apiVersion)
{
var body = GenerateBody(action, methodArguments, jsonSerializer);
if (body != null)
@ -29,7 +30,7 @@ namespace Volo.Abp.Http.Client.Proxying
return body;
}
private static HttpContent GenerateBody(ActionApiDescriptionModel action, IReadOnlyDictionary<string, object> methodArguments, IJsonSerializer jsonSerializer)
protected virtual HttpContent GenerateBody(ActionApiDescriptionModel action, IReadOnlyDictionary<string, object> methodArguments, IJsonSerializer jsonSerializer)
{
var parameters = action
.Parameters
@ -57,7 +58,7 @@ namespace Volo.Abp.Http.Client.Proxying
return new StringContent(jsonSerializer.Serialize(value), Encoding.UTF8, MimeTypes.Application.Json);
}
private static HttpContent GenerateFormPostData(ActionApiDescriptionModel action, IReadOnlyDictionary<string, object> methodArguments)
protected virtual HttpContent GenerateFormPostData(ActionApiDescriptionModel action, IReadOnlyDictionary<string, object> methodArguments)
{
var parameters = action
.Parameters

17
framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/Proxying/UrlBuilder.cs → framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyUrlBuilder.cs

@ -5,16 +5,17 @@ using System.Globalization;
using System.Linq;
using System.Text;
using JetBrains.Annotations;
using Volo.Abp.Http.Client.DynamicProxying;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Http.Client.Proxying;
using Volo.Abp.Http.Modeling;
using Volo.Abp.Http.ProxyScripting.Generators;
using Volo.Abp.Localization;
namespace Volo.Abp.Http.Client.Proxying
namespace Volo.Abp.Http.Client.ClientProxying
{
internal static class UrlBuilder
public class ClientProxyUrlBuilder : ITransientDependency
{
public static string GenerateUrlWithParameters(ActionApiDescriptionModel action, IReadOnlyDictionary<string, object> methodArguments, ApiVersionInfo apiVersion)
public string GenerateUrlWithParameters(ActionApiDescriptionModel action, IReadOnlyDictionary<string, object> methodArguments, ApiVersionInfo apiVersion)
{
// The ASP.NET Core route value provider and query string value provider:
// Treat values as invariant culture.
@ -30,7 +31,7 @@ namespace Volo.Abp.Http.Client.Proxying
}
}
private static void ReplacePathVariables(StringBuilder urlBuilder, IList<ParameterApiDescriptionModel> actionParameters, IReadOnlyDictionary<string, object> methodArguments, ApiVersionInfo apiVersion)
protected virtual void ReplacePathVariables(StringBuilder urlBuilder, IList<ParameterApiDescriptionModel> actionParameters, IReadOnlyDictionary<string, object> methodArguments, ApiVersionInfo apiVersion)
{
var pathParameters = actionParameters
.Where(p => p.BindingSourceId == ParameterBindingSources.Path)
@ -72,7 +73,7 @@ namespace Volo.Abp.Http.Client.Proxying
}
}
private static void AddQueryStringParameters(StringBuilder urlBuilder, IList<ParameterApiDescriptionModel> actionParameters, IReadOnlyDictionary<string, object> methodArguments, ApiVersionInfo apiVersion)
protected virtual void AddQueryStringParameters(StringBuilder urlBuilder, IList<ParameterApiDescriptionModel> actionParameters, IReadOnlyDictionary<string, object> methodArguments, ApiVersionInfo apiVersion)
{
var queryStringParameters = actionParameters
.Where(p => p.BindingSourceId.IsIn(ParameterBindingSources.ModelBinding, ParameterBindingSources.Query))
@ -100,7 +101,7 @@ namespace Volo.Abp.Http.Client.Proxying
}
}
private static bool AddQueryStringParameter(
protected virtual bool AddQueryStringParameter(
StringBuilder urlBuilder,
bool isFirstParam,
string name,
@ -133,7 +134,7 @@ namespace Volo.Abp.Http.Client.Proxying
return true;
}
private static string ConvertValueToString([CanBeNull] object value)
protected virtual string ConvertValueToString([CanBeNull] object value)
{
if (value is DateTime dateTimeValue)
{

63
framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs

@ -8,6 +8,7 @@ using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
using Volo.Abp.DynamicProxy;
using Volo.Abp.Http.Client.ClientProxying;
using Volo.Abp.Http.Client.Proxying;
using Volo.Abp.Http.Modeling;
@ -15,32 +16,32 @@ namespace Volo.Abp.Http.Client.DynamicProxying
{
public class DynamicHttpProxyInterceptor<TService> : AbpInterceptor, ITransientDependency
{
// ReSharper disable once StaticMemberInGenericType
protected static MethodInfo MakeRequestAndGetResultAsyncMethod { get; }
protected static MethodInfo CallRequestAsyncMethod { get; }
static DynamicHttpProxyInterceptor()
{
CallRequestAsyncMethod = typeof(DynamicHttpProxyInterceptor<TService>)
.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance)
.First(m => m.Name == nameof(CallRequestAsync) && m.IsGenericMethodDefinition);
}
public ILogger<DynamicHttpProxyInterceptor<TService>> Logger { get; set; }
protected DynamicHttpProxyInterceptorClientProxy<TService> InterceptorClientProxy { get; }
protected AbpHttpClientOptions ClientOptions { get; }
protected IHttpProxyExecuter HttpProxyExecuter { get; }
protected IProxyHttpClientFactory HttpClientFactory { get; }
protected IRemoteServiceConfigurationProvider RemoteServiceConfigurationProvider { get; }
protected IApiDescriptionFinder ApiDescriptionFinder { get; }
public ILogger<DynamicHttpProxyInterceptor<TService>> Logger { get; set; }
static DynamicHttpProxyInterceptor()
{
MakeRequestAndGetResultAsyncMethod = typeof(HttpProxyExecuter)
.GetMethods(BindingFlags.Public | BindingFlags.Instance)
.First(m => m.Name == nameof(IHttpProxyExecuter.MakeRequestAndGetResultAsync) && m.IsGenericMethodDefinition);
}
public DynamicHttpProxyInterceptor(
IHttpProxyExecuter httpProxyExecuter,
DynamicHttpProxyInterceptorClientProxy<TService> interceptorClientProxy,
IOptions<AbpHttpClientOptions> clientOptions,
IProxyHttpClientFactory httpClientFactory,
IRemoteServiceConfigurationProvider remoteServiceConfigurationProvider,
IApiDescriptionFinder apiDescriptionFinder)
{
HttpProxyExecuter = httpProxyExecuter;
InterceptorClientProxy = interceptorClientProxy;
HttpClientFactory = httpClientFactory;
RemoteServiceConfigurationProvider = remoteServiceConfigurationProvider;
ApiDescriptionFinder = apiDescriptionFinder;
@ -49,34 +50,32 @@ namespace Volo.Abp.Http.Client.DynamicProxying
Logger = NullLogger<DynamicHttpProxyInterceptor<TService>>.Instance;
}
public override async Task InterceptAsync(IAbpMethodInvocation invocation)
{
var context = new HttpProxyExecuterContext(
var context = new ClientProxyRequestContext(
await GetActionApiDescriptionModel(invocation),
invocation.ArgumentsDictionary,
typeof(TService));
if (invocation.Method.ReturnType.GenericTypeArguments.IsNullOrEmpty())
{
await HttpProxyExecuter.MakeRequestAsync(context);
await InterceptorClientProxy.CallRequestAsync(context);
}
else
{
var result = (Task)MakeRequestAndGetResultAsyncMethod
.MakeGenericMethod(invocation.Method.ReturnType.GenericTypeArguments[0])
.Invoke(HttpProxyExecuter, new object[] { context });
var returnType = invocation.Method.ReturnType.GenericTypeArguments[0];
var result = (Task)CallRequestAsyncMethod
.MakeGenericMethod(returnType)
.Invoke(this, new object[] { context });
invocation.ReturnValue = await GetResultAsync(
result,
invocation.Method.ReturnType.GetGenericArguments()[0]
);
invocation.ReturnValue = await GetResultAsync(result, returnType);
}
}
private async Task<ActionApiDescriptionModel> GetActionApiDescriptionModel(IAbpMethodInvocation invocation)
protected virtual async Task<ActionApiDescriptionModel> GetActionApiDescriptionModel(IAbpMethodInvocation invocation)
{
var clientConfig = ClientOptions.HttpClientProxies.GetOrDefault(typeof(TService)) ?? throw new AbpException($"Could not get DynamicHttpClientProxyConfig for {typeof(TService).FullName}.");
var clientConfig = ClientOptions.HttpClientProxies.GetOrDefault(typeof(TService)) ??
throw new AbpException($"Could not get DynamicHttpClientProxyConfig for {typeof(TService).FullName}.");
var remoteServiceConfig = await RemoteServiceConfigurationProvider.GetConfigurationOrDefaultAsync(clientConfig.RemoteServiceName);
var client = HttpClientFactory.Create(clientConfig.RemoteServiceName);
@ -88,13 +87,19 @@ namespace Volo.Abp.Http.Client.DynamicProxying
);
}
private async Task<object> GetResultAsync(Task task, Type resultType)
protected virtual async Task<T> CallRequestAsync<T>(ClientProxyRequestContext context)
{
return await InterceptorClientProxy.CallRequestAsync<T>(context);
}
protected virtual async Task<object> GetResultAsync(Task task, Type resultType)
{
await task;
return typeof(Task<>)
var resultProperty = typeof(Task<>)
.MakeGenericType(resultType)
.GetProperty(nameof(Task<object>.Result), BindingFlags.Instance | BindingFlags.Public)
.GetValue(task);
.GetProperty(nameof(Task<object>.Result), BindingFlags.Instance | BindingFlags.Public);
Check.NotNull(resultProperty, nameof(resultProperty));
return resultProperty.GetValue(task);
}
}
}

19
framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptorClientProxy.cs

@ -0,0 +1,19 @@
using System.Net.Http;
using System.Threading.Tasks;
using Volo.Abp.Http.Client.ClientProxying;
namespace Volo.Abp.Http.Client.DynamicProxying
{
public class DynamicHttpProxyInterceptorClientProxy<TService> : ClientProxyBase<TService>
{
public virtual async Task<T> CallRequestAsync<T>(ClientProxyRequestContext requestContext)
{
return await base.RequestAsync<T>(requestContext);
}
public virtual async Task<HttpContent> CallRequestAsync(ClientProxyRequestContext requestContext)
{
return await base.RequestAsync(requestContext);
}
}
}

267
framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/Proxying/HttpProxyExecuter.cs

@ -1,267 +0,0 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.Primitives;
using Volo.Abp.Content;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Http.Client.Authentication;
using Volo.Abp.Http.Modeling;
using Volo.Abp.Http.ProxyScripting.Generators;
using Volo.Abp.Json;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Threading;
using Volo.Abp.Tracing;
namespace Volo.Abp.Http.Client.Proxying
{
public class HttpProxyExecuter : IHttpProxyExecuter, ITransientDependency
{
protected ICancellationTokenProvider CancellationTokenProvider { get; }
protected ICorrelationIdProvider CorrelationIdProvider { get; }
protected ICurrentTenant CurrentTenant { get; }
protected AbpCorrelationIdOptions AbpCorrelationIdOptions { get; }
protected IProxyHttpClientFactory HttpClientFactory { get; }
protected IRemoteServiceConfigurationProvider RemoteServiceConfigurationProvider { get; }
protected AbpHttpClientOptions ClientOptions { get; }
protected IJsonSerializer JsonSerializer { get; }
protected IRemoteServiceHttpClientAuthenticator ClientAuthenticator { get; }
public HttpProxyExecuter(
ICancellationTokenProvider cancellationTokenProvider,
ICorrelationIdProvider correlationIdProvider,
ICurrentTenant currentTenant,
IOptions<AbpCorrelationIdOptions> abpCorrelationIdOptions,
IProxyHttpClientFactory httpClientFactory,
IRemoteServiceConfigurationProvider remoteServiceConfigurationProvider,
IOptions<AbpHttpClientOptions> clientOptions,
IRemoteServiceHttpClientAuthenticator clientAuthenticator,
IJsonSerializer jsonSerializer)
{
CancellationTokenProvider = cancellationTokenProvider;
CorrelationIdProvider = correlationIdProvider;
CurrentTenant = currentTenant;
AbpCorrelationIdOptions = abpCorrelationIdOptions.Value;
HttpClientFactory = httpClientFactory;
RemoteServiceConfigurationProvider = remoteServiceConfigurationProvider;
ClientOptions = clientOptions.Value;
ClientAuthenticator = clientAuthenticator;
JsonSerializer = jsonSerializer;
}
public virtual async Task<T> MakeRequestAndGetResultAsync<T>(HttpProxyExecuterContext context)
{
var responseContent = await MakeRequestAsync(context);
if (typeof(T) == typeof(IRemoteStreamContent) ||
typeof(T) == typeof(RemoteStreamContent))
{
/* returning a class that holds a reference to response
* content just to be sure that GC does not dispose of
* it before we finish doing our work with the stream */
return (T) (object) new RemoteStreamContent(
await responseContent.ReadAsStreamAsync(),
responseContent.Headers?.ContentDisposition?.FileNameStar ?? RemoveQuotes(responseContent.Headers?.ContentDisposition?.FileName).ToString(),
responseContent.Headers?.ContentType?.ToString(),
responseContent.Headers?.ContentLength);
}
var stringContent = await responseContent.ReadAsStringAsync();
if (typeof(T) == typeof(string))
{
return (T)(object)stringContent;
}
if (stringContent.IsNullOrWhiteSpace())
{
return default;
}
return JsonSerializer.Deserialize<T>(stringContent);
}
public virtual async Task<HttpContent> MakeRequestAsync(HttpProxyExecuterContext context)
{
var clientConfig = ClientOptions.HttpClientProxies.GetOrDefault(context.ServiceType) ?? throw new AbpException($"Could not get HttpClientProxyConfig for {context.ServiceType.FullName}.");
var remoteServiceConfig = await RemoteServiceConfigurationProvider.GetConfigurationOrDefaultAsync(clientConfig.RemoteServiceName);
var client = HttpClientFactory.Create(clientConfig.RemoteServiceName);
var apiVersion = await GetApiVersionInfoAsync(context);
var url = remoteServiceConfig.BaseUrl.EnsureEndsWith('/') + UrlBuilder.GenerateUrlWithParameters(context.Action, context.Arguments, apiVersion);
var requestMessage = new HttpRequestMessage(context.Action.GetHttpMethod(), url)
{
Content = RequestPayloadBuilder.BuildContent(context.Action, context.Arguments, JsonSerializer, apiVersion)
};
AddHeaders(context.Arguments, context.Action, requestMessage, apiVersion);
if (context.Action.AllowAnonymous != true)
{
await ClientAuthenticator.Authenticate(
new RemoteServiceHttpClientAuthenticateContext(
client,
requestMessage,
remoteServiceConfig,
clientConfig.RemoteServiceName
)
);
}
var response = await client.SendAsync(
requestMessage,
HttpCompletionOption.ResponseHeadersRead /*this will buffer only the headers, the content will be used as a stream*/,
GetCancellationToken(context.Arguments)
);
if (!response.IsSuccessStatusCode)
{
await ThrowExceptionForResponseAsync(response);
}
return response.Content;
}
private async Task<ApiVersionInfo> GetApiVersionInfoAsync(HttpProxyExecuterContext context)
{
var apiVersion = await FindBestApiVersionAsync(context);
//TODO: Make names configurable?
var versionParam = context.Action.Parameters.FirstOrDefault(p => p.Name == "apiVersion" && p.BindingSourceId == ParameterBindingSources.Path) ??
context.Action.Parameters.FirstOrDefault(p => p.Name == "api-version" && p.BindingSourceId == ParameterBindingSources.Query);
return new ApiVersionInfo(versionParam?.BindingSourceId, apiVersion);
}
private async Task<string> FindBestApiVersionAsync(HttpProxyExecuterContext context)
{
var configuredVersion = await GetConfiguredApiVersionAsync(context);
if (context.Action.SupportedVersions.IsNullOrEmpty())
{
return configuredVersion ?? "1.0";
}
if (context.Action.SupportedVersions.Contains(configuredVersion))
{
return configuredVersion;
}
return context.Action.SupportedVersions.Last(); //TODO: Ensure to get the latest version!
}
private async Task<string> GetConfiguredApiVersionAsync(HttpProxyExecuterContext context)
{
var clientConfig = ClientOptions.HttpClientProxies.GetOrDefault(context.ServiceType)
?? throw new AbpException($"Could not get DynamicHttpClientProxyConfig for {context.ServiceType.FullName}.");
return (await RemoteServiceConfigurationProvider
.GetConfigurationOrDefaultOrNullAsync(clientConfig.RemoteServiceName))?.Version;
}
private async Task ThrowExceptionForResponseAsync(HttpResponseMessage response)
{
if (response.Headers.Contains(AbpHttpConsts.AbpErrorFormat))
{
var errorResponse = JsonSerializer.Deserialize<RemoteServiceErrorResponse>(
await response.Content.ReadAsStringAsync()
);
throw new AbpRemoteCallException(errorResponse.Error)
{
HttpStatusCode = (int) response.StatusCode
};
}
throw new AbpRemoteCallException(
new RemoteServiceErrorInfo
{
Message = response.ReasonPhrase,
Code = response.StatusCode.ToString()
}
)
{
HttpStatusCode = (int) response.StatusCode
};
}
protected virtual void AddHeaders(
IReadOnlyDictionary<string, object> argumentsDictionary,
ActionApiDescriptionModel action,
HttpRequestMessage requestMessage,
ApiVersionInfo apiVersion)
{
//API Version
if (!apiVersion.Version.IsNullOrEmpty())
{
//TODO: What about other media types?
requestMessage.Headers.Add("accept", $"{MimeTypes.Text.Plain}; v={apiVersion.Version}");
requestMessage.Headers.Add("accept", $"{MimeTypes.Application.Json}; v={apiVersion.Version}");
requestMessage.Headers.Add("api-version", apiVersion.Version);
}
//Header parameters
var headers = action.Parameters.Where(p => p.BindingSourceId == ParameterBindingSources.Header).ToArray();
foreach (var headerParameter in headers)
{
var value = HttpActionParameterHelper.FindParameterValue(argumentsDictionary, headerParameter);
if (value != null)
{
requestMessage.Headers.Add(headerParameter.Name, value.ToString());
}
}
//CorrelationId
requestMessage.Headers.Add(AbpCorrelationIdOptions.HttpHeaderName, CorrelationIdProvider.Get());
//TenantId
if (CurrentTenant.Id.HasValue)
{
//TODO: Use AbpAspNetCoreMultiTenancyOptions to get the key
requestMessage.Headers.Add(TenantResolverConsts.DefaultTenantKey, CurrentTenant.Id.Value.ToString());
}
//Culture
//TODO: Is that the way we want? Couldn't send the culture (not ui culture)
var currentCulture = CultureInfo.CurrentUICulture.Name ?? CultureInfo.CurrentCulture.Name;
if (!currentCulture.IsNullOrEmpty())
{
requestMessage.Headers.AcceptLanguage.Add(new StringWithQualityHeaderValue(currentCulture));
}
//X-Requested-With
requestMessage.Headers.Add("X-Requested-With", "XMLHttpRequest");
}
protected virtual StringSegment RemoveQuotes(StringSegment input)
{
if (!StringSegment.IsNullOrEmpty(input) && input.Length >= 2 && input[0] == '"' && input[input.Length - 1] == '"')
{
input = input.Subsegment(1, input.Length - 2);
}
return input;
}
protected virtual CancellationToken GetCancellationToken(IReadOnlyDictionary<string, object> arguments)
{
var cancellationTokenArg = arguments.LastOrDefault();
if (cancellationTokenArg.Value is CancellationToken cancellationToken)
{
if (cancellationToken != default)
{
return cancellationToken;
}
}
return CancellationTokenProvider.Token;
}
}
}

12
framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/Proxying/IHttpProxyExecuter.cs

@ -1,12 +0,0 @@
using System.Net.Http;
using System.Threading.Tasks;
namespace Volo.Abp.Http.Client.Proxying
{
public interface IHttpProxyExecuter
{
Task<HttpContent> MakeRequestAsync(HttpProxyExecuterContext context);
Task<T> MakeRequestAndGetResultAsync<T>(HttpProxyExecuterContext context);
}
}

1
modules/account/src/Volo.Abp.Account.Web/Pages/Account/Components/ProfileManagementGroup/Password/AccountProfilePasswordManagementGroupViewComponent.cs

@ -2,6 +2,7 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.Widgets;
using Volo.Abp.Auditing;
using Volo.Abp.Identity;
using Volo.Abp.Validation;

1
modules/account/src/Volo.Abp.Account.Web/Pages/Account/Components/ProfileManagementGroup/PersonalInfo/AccountProfilePersonalInfoManagementGroupViewComponent.cs

@ -2,6 +2,7 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.Widgets;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Identity;
using Volo.Abp.Validation;

5
modules/blogging/app/Volo.BloggingTestApp/BloggingTestAppModule.cs

@ -31,6 +31,7 @@ using Volo.Abp.Identity;
using Volo.Abp.Identity.Web;
using Volo.Abp.Modularity;
using Volo.Abp.PermissionManagement;
using Volo.Abp.PermissionManagement.HttpApi;
using Volo.Abp.PermissionManagement.Identity;
using Volo.Abp.Threading;
using Volo.Abp.UI;
@ -44,8 +45,8 @@ namespace Volo.BloggingTestApp
{
[DependsOn(
typeof(BloggingWebModule),
typeof(BloggingHttpApiModule),
typeof(BloggingApplicationModule),
typeof(BloggingHttpApiModule),
typeof(BloggingAdminWebModule),
typeof(BloggingAdminHttpApiModule),
typeof(BloggingAdminApplicationModule),
@ -55,12 +56,14 @@ namespace Volo.BloggingTestApp
typeof(BloggingTestAppEntityFrameworkCoreModule),
#endif
typeof(AbpAccountWebModule),
typeof(AbpAccountHttpApiModule),
typeof(AbpAccountApplicationModule),
typeof(AbpIdentityWebModule),
typeof(AbpIdentityHttpApiModule),
typeof(AbpIdentityApplicationModule),
typeof(AbpPermissionManagementDomainIdentityModule),
typeof(AbpPermissionManagementApplicationModule),
typeof(AbpPermissionManagementHttpApiModule),
typeof(BlobStoringDatabaseDomainModule),
typeof(AbpAutofacModule),
typeof(AbpAspNetCoreMvcUiBasicThemeModule)

12
modules/blogging/app/Volo.BloggingTestApp/Volo.BloggingTestApp.csproj

@ -15,19 +15,19 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Serilog.AspNetCore" Version="3.4.0" />
<PackageReference Include="Serilog.Sinks.File" Version="4.1.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.6.3" />
<PackageReference Include="Serilog.AspNetCore" Version="4.1.0" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Volo.Blogging.Admin.HttpApi\Volo.Blogging.Admin.HttpApi.csproj" />
<ProjectReference Include="..\..\src\Volo.Blogging.HttpApi\Volo.Blogging.HttpApi.csproj" />
<ProjectReference Include="..\Volo.BloggingTestApp.EntityFrameworkCore\Volo.BloggingTestApp.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\..\src\Volo.Blogging.Application\Volo.Blogging.Application.csproj" />
<ProjectReference Include="..\..\src\Volo.Blogging.Web\Volo.Blogging.Web.csproj" />
<ProjectReference Include="..\..\src\Volo.Blogging.HttpApi\Volo.Blogging.HttpApi.csproj" />
<ProjectReference Include="..\..\src\Volo.Blogging.Admin.Application\Volo.Blogging.Admin.Application.csproj" />
<ProjectReference Include="..\..\src\Volo.Blogging.Admin.Web\Volo.Blogging.Admin.Web.csproj" />
<ProjectReference Include="..\..\src\Volo.Blogging.Admin.HttpApi\Volo.Blogging.Admin.HttpApi.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.Autofac\Volo.Abp.Autofac.csproj" />
<ProjectReference Include="..\..\..\..\modules\basic-theme\src\Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic\Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.csproj" />
<ProjectReference Include="..\..\..\..\modules\identity\src\Volo.Abp.Identity.Application\Volo.Abp.Identity.Application.csproj" />
@ -35,7 +35,9 @@
<ProjectReference Include="..\..\..\..\modules\identity\src\Volo.Abp.Identity.HttpApi\Volo.Abp.Identity.HttpApi.csproj" />
<ProjectReference Include="..\..\..\..\modules\identity\src\Volo.Abp.PermissionManagement.Domain.Identity\Volo.Abp.PermissionManagement.Domain.Identity.csproj" />
<ProjectReference Include="..\..\..\..\modules\permission-management\src\Volo.Abp.PermissionManagement.Application\Volo.Abp.PermissionManagement.Application.csproj" />
<ProjectReference Include="..\..\..\..\modules\permission-management\src\Volo.Abp.PermissionManagement.HttpApi\Volo.Abp.PermissionManagement.HttpApi.csproj" />
<ProjectReference Include="..\..\..\..\modules\account\src\Volo.Abp.Account.Web\Volo.Abp.Account.Web.csproj" />
<ProjectReference Include="..\..\..\..\modules\account\src\Volo.Abp.Account.HttpApi\Volo.Abp.Account.HttpApi.csproj" />
<ProjectReference Include="..\..\..\..\modules\account\src\Volo.Abp.Account.Application\Volo.Abp.Account.Application.csproj" />
<ProjectReference Include="..\..\..\..\modules\blob-storing-database\src\Volo.Abp.BlobStoring.Database.Domain\Volo.Abp.BlobStoring.Database.Domain.csproj" />
</ItemGroup>

1
modules/cms-kit/host/Volo.CmsKit.IdentityServer/CmsKitIdentityServerModule.cs

@ -49,6 +49,7 @@ namespace Volo.CmsKit
[DependsOn(
typeof(AbpAccountWebIdentityServerModule),
typeof(AbpAccountApplicationModule),
typeof(AbpAccountHttpApiModule),
typeof(AbpAspNetCoreMvcUiMultiTenancyModule),
typeof(AbpAspNetCoreMvcModule),
typeof(AbpAspNetCoreMvcUiBasicThemeModule),

1
modules/cms-kit/host/Volo.CmsKit.IdentityServer/Volo.CmsKit.IdentityServer.csproj

@ -23,6 +23,7 @@
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AspNetCore.Serilog\Volo.Abp.AspNetCore.Serilog.csproj" />
<ProjectReference Include="..\..\..\..\modules\account\src\Volo.Abp.Account.Web.IdentityServer\Volo.Abp.Account.Web.IdentityServer.csproj" />
<ProjectReference Include="..\..\..\..\modules\account\src\Volo.Abp.Account.Application\Volo.Abp.Account.Application.csproj" />
<ProjectReference Include="..\..\..\..\modules\account\src\Volo.Abp.Account.HttpApi\Volo.Abp.Account.HttpApi.csproj" />
<ProjectReference Include="..\..\..\..\modules\setting-management\src\Volo.Abp.SettingManagement.EntityFrameworkCore\Volo.Abp.SettingManagement.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\..\..\..\modules\audit-logging\src\Volo.Abp.AuditLogging.EntityFrameworkCore\Volo.Abp.AuditLogging.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\..\..\..\modules\identityserver\src\Volo.Abp.IdentityServer.EntityFrameworkCore\Volo.Abp.IdentityServer.EntityFrameworkCore.csproj" />

3123
modules/cms-kit/host/Volo.CmsKit.IdentityServer/wwwroot/libs/sweetalert2/sweetalert2.all.js

File diff suppressed because one or more lines are too long

2
modules/cms-kit/host/Volo.CmsKit.IdentityServer/wwwroot/libs/sweetalert2/sweetalert2.all.min.js

File diff suppressed because one or more lines are too long

1319
modules/cms-kit/host/Volo.CmsKit.IdentityServer/wwwroot/libs/sweetalert2/sweetalert2.css

File diff suppressed because it is too large

3121
modules/cms-kit/host/Volo.CmsKit.IdentityServer/wwwroot/libs/sweetalert2/sweetalert2.js

File diff suppressed because it is too large

1
modules/cms-kit/host/Volo.CmsKit.IdentityServer/wwwroot/libs/sweetalert2/sweetalert2.min.css

File diff suppressed because one or more lines are too long

1
modules/cms-kit/host/Volo.CmsKit.IdentityServer/wwwroot/libs/sweetalert2/sweetalert2.min.js

File diff suppressed because one or more lines are too long

3123
modules/cms-kit/host/Volo.CmsKit.Web.Host/wwwroot/libs/sweetalert2/sweetalert2.all.js

File diff suppressed because one or more lines are too long

2
modules/cms-kit/host/Volo.CmsKit.Web.Host/wwwroot/libs/sweetalert2/sweetalert2.all.min.js

File diff suppressed because one or more lines are too long

1319
modules/cms-kit/host/Volo.CmsKit.Web.Host/wwwroot/libs/sweetalert2/sweetalert2.css

File diff suppressed because it is too large

3121
modules/cms-kit/host/Volo.CmsKit.Web.Host/wwwroot/libs/sweetalert2/sweetalert2.js

File diff suppressed because it is too large

1
modules/cms-kit/host/Volo.CmsKit.Web.Host/wwwroot/libs/sweetalert2/sweetalert2.min.css

File diff suppressed because one or more lines are too long

1
modules/cms-kit/host/Volo.CmsKit.Web.Host/wwwroot/libs/sweetalert2/sweetalert2.min.js

File diff suppressed because one or more lines are too long

11
modules/cms-kit/host/Volo.CmsKit.Web.Unified/CmsKitWebUnifiedModule.cs

@ -40,6 +40,7 @@ using Volo.Abp.VirtualFileSystem;
using Volo.CmsKit.Admin.Web;
using Volo.CmsKit.Public.Web;
using System;
using Volo.Abp.PermissionManagement.HttpApi;
using Volo.CmsKit.Tags;
using Volo.CmsKit.Comments;
using Volo.CmsKit.MediaDescriptors;
@ -51,24 +52,30 @@ namespace Volo.CmsKit
[DependsOn(
typeof(CmsKitWebModule),
typeof(CmsKitApplicationModule),
typeof(CmsKitHttpApiModule),
typeof(CmsKitEntityFrameworkCoreModule),
typeof(AbpAuditLoggingEntityFrameworkCoreModule),
typeof(AbpAutofacModule),
typeof(AbpAccountWebModule),
typeof(AbpAccountApplicationModule),
typeof(AbpAccountHttpApiModule),
typeof(AbpEntityFrameworkCoreSqlServerModule),
typeof(AbpSettingManagementEntityFrameworkCoreModule),
typeof(AbpPermissionManagementEntityFrameworkCoreModule),
typeof(AbpPermissionManagementApplicationModule),
typeof(AbpPermissionManagementHttpApiModule),
typeof(AbpIdentityWebModule),
typeof(AbpIdentityApplicationModule),
typeof(AbpIdentityHttpApiModule),
typeof(AbpIdentityEntityFrameworkCoreModule),
typeof(AbpPermissionManagementDomainIdentityModule),
typeof(AbpFeatureManagementApplicationModule),
typeof(AbpFeatureManagementHttpApiModule),
typeof(AbpFeatureManagementEntityFrameworkCoreModule),
typeof(AbpFeatureManagementWebModule),
typeof(AbpTenantManagementWebModule),
typeof(AbpTenantManagementApplicationModule),
typeof(AbpTenantManagementHttpApiModule),
typeof(AbpTenantManagementEntityFrameworkCoreModule),
typeof(AbpAspNetCoreMvcUiBasicThemeModule),
typeof(AbpAspNetCoreSerilogModule),
@ -161,11 +168,11 @@ namespace Volo.CmsKit
{
options.EntityTypes.Add(new MediaDescriptorDefinition("quote"));
});
Configure<CmsKitReactionOptions>(options =>
{
options.EntityTypes.Add(
new ReactionEntityTypeDefinition("quote",
new ReactionEntityTypeDefinition("quote",
reactions: new[]
{
new ReactionDefinition(StandardReactions.ThumbsUp),

6
modules/cms-kit/host/Volo.CmsKit.Web.Unified/Volo.CmsKit.Web.Unified.csproj

@ -19,17 +19,22 @@
<ProjectReference Include="..\..\..\..\modules\audit-logging\src\Volo.Abp.AuditLogging.EntityFrameworkCore\Volo.Abp.AuditLogging.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\..\..\..\modules\account\src\Volo.Abp.Account.Web\Volo.Abp.Account.Web.csproj" />
<ProjectReference Include="..\..\..\..\modules\account\src\Volo.Abp.Account.Application\Volo.Abp.Account.Application.csproj" />
<ProjectReference Include="..\..\..\..\modules\account\src\Volo.Abp.Account.HttpApi\Volo.Abp.Account.HttpApi.csproj" />
<ProjectReference Include="..\..\..\..\modules\setting-management\src\Volo.Abp.SettingManagement.EntityFrameworkCore\Volo.Abp.SettingManagement.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\..\..\..\modules\permission-management\src\Volo.Abp.PermissionManagement.Application\Volo.Abp.PermissionManagement.Application.csproj" />
<ProjectReference Include="..\..\..\..\modules\permission-management\src\Volo.Abp.PermissionManagement.HttpApi\Volo.Abp.PermissionManagement.HttpApi.csproj" />
<ProjectReference Include="..\..\..\..\modules\permission-management\src\Volo.Abp.PermissionManagement.EntityFrameworkCore\Volo.Abp.PermissionManagement.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\..\..\..\modules\identity\src\Volo.Abp.Identity.Application\Volo.Abp.Identity.Application.csproj" />
<ProjectReference Include="..\..\..\..\modules\identity\src\Volo.Abp.Identity.HttpApi\Volo.Abp.Identity.HttpApi.csproj" />
<ProjectReference Include="..\..\..\..\modules\identity\src\Volo.Abp.Identity.Web\Volo.Abp.Identity.Web.csproj" />
<ProjectReference Include="..\..\..\..\modules\identity\src\Volo.Abp.Identity.EntityFrameworkCore\Volo.Abp.Identity.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\..\..\..\modules\identity\src\Volo.Abp.PermissionManagement.Domain.Identity\Volo.Abp.PermissionManagement.Domain.Identity.csproj" />
<ProjectReference Include="..\..\..\..\modules\feature-management\src\Volo.Abp.FeatureManagement.EntityFrameworkCore\Volo.Abp.FeatureManagement.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\..\..\..\modules\feature-management\src\Volo.Abp.FeatureManagement.Application\Volo.Abp.FeatureManagement.Application.csproj" />
<ProjectReference Include="..\..\..\..\modules\feature-management\src\Volo.Abp.FeatureManagement.HttpApi\Volo.Abp.FeatureManagement.HttpApi.csproj" />
<ProjectReference Include="..\..\..\..\modules\feature-management\src\Volo.Abp.FeatureManagement.Web\Volo.Abp.FeatureManagement.Web.csproj" />
<ProjectReference Include="..\..\..\..\modules\tenant-management\src\Volo.Abp.TenantManagement.Application\Volo.Abp.TenantManagement.Application.csproj" />
<ProjectReference Include="..\..\..\..\modules\tenant-management\src\Volo.Abp.TenantManagement.HttpApi\Volo.Abp.TenantManagement.HttpApi.csproj" />
<ProjectReference Include="..\..\..\..\modules\tenant-management\src\Volo.Abp.TenantManagement.Web\Volo.Abp.TenantManagement.Web.csproj" />
<ProjectReference Include="..\..\..\..\modules\tenant-management\src\Volo.Abp.TenantManagement.EntityFrameworkCore\Volo.Abp.TenantManagement.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\..\..\..\modules\blob-storing-database\src\Volo.Abp.BlobStoring.Database.EntityFrameworkCore\Volo.Abp.BlobStoring.Database.EntityFrameworkCore.csproj" />
@ -37,6 +42,7 @@
<ItemGroup>
<ProjectReference Include="..\..\src\Volo.CmsKit.Application\Volo.CmsKit.Application.csproj" />
<ProjectReference Include="..\..\src\Volo.CmsKit.HttpApi\Volo.CmsKit.HttpApi.csproj" />
<ProjectReference Include="..\..\src\Volo.CmsKit.EntityFrameworkCore\Volo.CmsKit.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\..\src\Volo.CmsKit.Application\Volo.CmsKit.Application.csproj" />
<ProjectReference Include="..\..\src\Volo.CmsKit.Web\Volo.CmsKit.Web.csproj" />

3123
modules/cms-kit/host/Volo.CmsKit.Web.Unified/wwwroot/libs/sweetalert2/sweetalert2.all.js

File diff suppressed because one or more lines are too long

2
modules/cms-kit/host/Volo.CmsKit.Web.Unified/wwwroot/libs/sweetalert2/sweetalert2.all.min.js

File diff suppressed because one or more lines are too long

1319
modules/cms-kit/host/Volo.CmsKit.Web.Unified/wwwroot/libs/sweetalert2/sweetalert2.css

File diff suppressed because it is too large

3121
modules/cms-kit/host/Volo.CmsKit.Web.Unified/wwwroot/libs/sweetalert2/sweetalert2.js

File diff suppressed because it is too large

1
modules/cms-kit/host/Volo.CmsKit.Web.Unified/wwwroot/libs/sweetalert2/sweetalert2.min.css

File diff suppressed because one or more lines are too long

1
modules/cms-kit/host/Volo.CmsKit.Web.Unified/wwwroot/libs/sweetalert2/sweetalert2.min.js

File diff suppressed because one or more lines are too long

3
modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Menus/MenuItemAdminAppService.cs

@ -60,7 +60,8 @@ namespace Volo.CmsKit.Admin.Menus
input.Order,
input.Target,
input.ElementId,
input.CssClass
input.CssClass,
CurrentTenant.Id
);
await MenuItemRepository.InsertAsync(menuItem);

12
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Menus/MenuItem.cs

@ -23,7 +23,7 @@ namespace Volo.CmsKit.Menus
public string DisplayName { get; protected set; }
public bool IsActive { get; set; }
[NotNull]
public string Url { get; protected set; }
@ -39,7 +39,7 @@ namespace Volo.CmsKit.Menus
public Guid? PageId { get; protected set; }
public Guid? TenantId { get; protected set; }
public Guid? TenantId { get; protected set; }
public MenuItem(Guid id,
[NotNull] string displayName,
@ -50,8 +50,9 @@ namespace Volo.CmsKit.Menus
int order = 0,
[CanBeNull] string target = null,
[CanBeNull] string elementId = null,
[CanBeNull] string cssClass = null)
:base(id)
[CanBeNull] string cssClass = null,
[CanBeNull] Guid? tenantId = null)
: base(id)
{
SetDisplayName(displayName);
IsActive = isActive;
@ -62,6 +63,7 @@ namespace Volo.CmsKit.Menus
Target = target;
ElementId = elementId;
CssClass = cssClass;
TenantId = tenantId;
}
public void SetDisplayName([NotNull] string displayName)
@ -69,7 +71,7 @@ namespace Volo.CmsKit.Menus
DisplayName = Check.NotNullOrEmpty(displayName, nameof(displayName), MenuItemConsts.MaxDisplayNameLength);
}
public void SetUrl([NotNull]string url)
public void SetUrl([NotNull] string url)
{
Url = Check.NotNullOrEmpty(url, nameof(url), MenuItemConsts.MaxUrlLength);
}

5
modules/docs/app/VoloDocs.Web/VoloDocs.Web.csproj

@ -24,18 +24,23 @@
<ItemGroup>
<ProjectReference Include="..\..\src\Volo.Docs.Application\Volo.Docs.Application.csproj" />
<ProjectReference Include="..\..\src\Volo.Docs.HttpApi\Volo.Docs.HttpApi.csproj" />
<ProjectReference Include="..\..\src\Volo.Docs.Admin.Application\Volo.Docs.Admin.Application.csproj" />
<ProjectReference Include="..\..\src\Volo.Docs.Admin.HttpApi\Volo.Docs.Admin.HttpApi.csproj" />
<ProjectReference Include="..\..\src\Volo.Docs.Web\Volo.Docs.Web.csproj" />
<ProjectReference Include="..\..\src\Volo.Docs.Admin.Web\Volo.Docs.Admin.Web.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.Autofac\Volo.Abp.Autofac.csproj" />
<ProjectReference Include="..\..\..\..\modules\basic-theme\src\Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic\Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.csproj" />
<ProjectReference Include="..\VoloDocs.EntityFrameworkCore\VoloDocs.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\..\..\..\modules\identity\src\Volo.Abp.Identity.Application\Volo.Abp.Identity.Application.csproj" />
<ProjectReference Include="..\..\..\..\modules\identity\src\Volo.Abp.Identity.HttpApi\Volo.Abp.Identity.HttpApi.csproj" />
<ProjectReference Include="..\..\..\..\modules\identity\src\Volo.Abp.Identity.Web\Volo.Abp.Identity.Web.csproj" />
<ProjectReference Include="..\..\..\..\modules\identity\src\Volo.Abp.PermissionManagement.Domain.Identity\Volo.Abp.PermissionManagement.Domain.Identity.csproj" />
<ProjectReference Include="..\..\..\..\modules\permission-management\src\Volo.Abp.PermissionManagement.Application\Volo.Abp.PermissionManagement.Application.csproj" />
<ProjectReference Include="..\..\..\..\modules\permission-management\src\Volo.Abp.PermissionManagement.HttpApi\Volo.Abp.PermissionManagement.HttpApi.csproj" />
<ProjectReference Include="..\..\..\..\modules\account\src\Volo.Abp.Account.Web\Volo.Abp.Account.Web.csproj" />
<ProjectReference Include="..\..\..\..\modules\account\src\Volo.Abp.Account.Application\Volo.Abp.Account.Application.csproj" />
<ProjectReference Include="..\..\..\..\modules\account\src\Volo.Abp.Account.HttpApi\Volo.Abp.Account.HttpApi.csproj" />
</ItemGroup>
<ItemGroup>

10
modules/docs/app/VoloDocs.Web/VoloDocsWebModule.cs

@ -32,6 +32,7 @@ using Localization.Resources.AbpUi;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Hosting;
using Volo.Abp.Account;
using Volo.Abp.PermissionManagement.HttpApi;
using Volo.Abp.Validation.Localization;
using Volo.Docs.Documents.FullSearch.Elastic;
@ -41,15 +42,20 @@ namespace VoloDocs.Web
typeof(DocsWebModule),
typeof(DocsAdminWebModule),
typeof(DocsApplicationModule),
typeof(DocsHttpApiModule),
typeof(DocsAdminApplicationModule),
typeof(DocsAdminHttpApiModule),
typeof(VoloDocsEntityFrameworkCoreModule),
typeof(AbpAutofacModule),
typeof(AbpAccountWebModule),
typeof(AbpAccountApplicationModule),
typeof(AbpAccountHttpApiModule),
typeof(AbpIdentityWebModule),
typeof(AbpIdentityApplicationModule),
typeof(AbpIdentityHttpApiModule),
typeof(AbpPermissionManagementDomainIdentityModule),
typeof(AbpPermissionManagementApplicationModule),
typeof(AbpPermissionManagementHttpApiModule),
typeof(AbpAspNetCoreMvcUiBasicThemeModule)
)]
public class VoloDocsWebModule : AbpModule
@ -113,7 +119,7 @@ namespace VoloDocs.Web
options.DocInclusionPredicate((docName, description) => true);
options.CustomSchemaIds(type => type.FullName);
});
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<VoloDocsWebModule>("VoloDocs.Web");
@ -170,7 +176,7 @@ namespace VoloDocs.Web
});
app.UseStatusCodePagesWithReExecute("/error/{0}");
//app.UseMiddleware<GlobalExceptionHandlerMiddleware>();
app.UseConfiguredEndpoints();

3123
modules/docs/app/VoloDocs.Web/wwwroot/libs/sweetalert2/sweetalert2.all.js

File diff suppressed because one or more lines are too long

2
modules/docs/app/VoloDocs.Web/wwwroot/libs/sweetalert2/sweetalert2.all.min.js

File diff suppressed because one or more lines are too long

1319
modules/docs/app/VoloDocs.Web/wwwroot/libs/sweetalert2/sweetalert2.css

File diff suppressed because it is too large

3121
modules/docs/app/VoloDocs.Web/wwwroot/libs/sweetalert2/sweetalert2.js

File diff suppressed because it is too large

1
modules/docs/app/VoloDocs.Web/wwwroot/libs/sweetalert2/sweetalert2.min.css

File diff suppressed because one or more lines are too long

1
modules/docs/app/VoloDocs.Web/wwwroot/libs/sweetalert2/sweetalert2.min.js

File diff suppressed because one or more lines are too long

4
modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/ProfileAppService.cs

@ -39,6 +39,8 @@ namespace Volo.Abp.Identity
var user = await UserManager.GetByIdAsync(CurrentUser.GetId());
user.SetConcurrencyStampIfNotNull(input.ConcurrencyStamp);
if (!string.Equals(user.UserName, input.UserName, StringComparison.InvariantCultureIgnoreCase))
{
if (await SettingProvider.IsTrueAsync(IdentitySettingNames.User.IsUserNameUpdateEnabled))
@ -63,8 +65,6 @@ namespace Volo.Abp.Identity
user.Name = input.Name;
user.Surname = input.Surname;
user.SetConcurrencyStampIfNotNull(input.ConcurrencyStamp);
input.MapExtraPropertiesTo(user);
(await UserManager.UpdateAsync(user)).CheckErrors();

2
modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/PermissionManagementModal.cshtml

@ -24,7 +24,7 @@
<abp-tab title="@group.DisplayName" name="v-pills-tab-@group.GetNormalizedGroupName()">
<h4>@group.DisplayName</h4>
<hr class="mt-2 mb-3"/>
<div class="custom-scroll-content">
<div class="w-100" style="max-height: 640px;overflow-y: auto">
<div class="pl-1 pt-1">
<abp-input asp-for="@group.IsAllPermissionsGranted"
check-box-hidden-input-render-mode="None"

5
modules/setting-management/app/Volo.Abp.SettingManagement.DemoApp/DemoAppModule.cs

@ -21,6 +21,7 @@ using Volo.Abp.Modularity;
using Volo.Abp.MultiTenancy;
using Volo.Abp.PermissionManagement;
using Volo.Abp.PermissionManagement.EntityFrameworkCore;
using Volo.Abp.PermissionManagement.HttpApi;
using Volo.Abp.PermissionManagement.Identity;
using Volo.Abp.SettingManagement.EntityFrameworkCore;
using Volo.Abp.SettingManagement.Web;
@ -32,15 +33,19 @@ namespace Volo.Abp.SettingManagement.DemoApp
[DependsOn(
typeof(AbpSettingManagementWebModule),
typeof(AbpSettingManagementApplicationModule),
typeof(AbpSettingManagementHttpApiModule),
typeof(AbpAutofacModule),
typeof(AbpAccountWebModule),
typeof(AbpAccountApplicationModule),
typeof(AbpAccountHttpApiModule),
typeof(AbpEntityFrameworkCoreSqlServerModule),
typeof(AbpSettingManagementEntityFrameworkCoreModule),
typeof(AbpPermissionManagementEntityFrameworkCoreModule),
typeof(AbpPermissionManagementApplicationModule),
typeof(AbpPermissionManagementHttpApiModule),
typeof(AbpIdentityWebModule),
typeof(AbpIdentityApplicationModule),
typeof(AbpIdentityHttpApiModule),
typeof(AbpIdentityEntityFrameworkCoreModule),
typeof(AbpPermissionManagementDomainIdentityModule),
typeof(AbpAspNetCoreMvcUiBasicThemeModule)

4
modules/setting-management/app/Volo.Abp.SettingManagement.DemoApp/Volo.Abp.SettingManagement.DemoApp.csproj

@ -17,19 +17,23 @@
<ItemGroup>
<ProjectReference Include="..\..\src\Volo.Abp.SettingManagement.Application\Volo.Abp.SettingManagement.Application.csproj" />
<ProjectReference Include="..\..\src\Volo.Abp.SettingManagement.HttpApi\Volo.Abp.SettingManagement.HttpApi.csproj" />
<ProjectReference Include="..\..\src\Volo.Abp.SettingManagement.Web\Volo.Abp.SettingManagement.Web.csproj" />
<ProjectReference Include="..\..\src\Volo.Abp.SettingManagement.EntityFrameworkCore\Volo.Abp.SettingManagement.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.Autofac\Volo.Abp.Autofac.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.EntityFrameworkCore.SqlServer\Volo.Abp.EntityFrameworkCore.SqlServer.csproj" />
<ProjectReference Include="..\..\..\..\modules\permission-management\src\Volo.Abp.PermissionManagement.Application\Volo.Abp.PermissionManagement.Application.csproj" />
<ProjectReference Include="..\..\..\..\modules\permission-management\src\Volo.Abp.PermissionManagement.HttpApi\Volo.Abp.PermissionManagement.HttpApi.csproj" />
<ProjectReference Include="..\..\..\..\modules\permission-management\src\Volo.Abp.PermissionManagement.EntityFrameworkCore\Volo.Abp.PermissionManagement.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\..\..\..\modules\identity\src\Volo.Abp.Identity.EntityFrameworkCore\Volo.Abp.Identity.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\..\..\..\modules\identity\src\Volo.Abp.PermissionManagement.Domain.Identity\Volo.Abp.PermissionManagement.Domain.Identity.csproj" />
<ProjectReference Include="..\..\..\..\modules\basic-theme\src\Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic\Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.csproj" />
<ProjectReference Include="..\..\..\..\modules\account\src\Volo.Abp.Account.Web\Volo.Abp.Account.Web.csproj" />
<ProjectReference Include="..\..\..\..\modules\account\src\Volo.Abp.Account.Application\Volo.Abp.Account.Application.csproj" />
<ProjectReference Include="..\..\..\..\modules\account\src\Volo.Abp.Account.HttpApi\Volo.Abp.Account.HttpApi.csproj" />
<ProjectReference Include="..\..\..\..\modules\identity\src\Volo.Abp.Identity.Application\Volo.Abp.Identity.Application.csproj" />
<ProjectReference Include="..\..\..\..\modules\identity\src\Volo.Abp.Identity.HttpApi\Volo.Abp.Identity.HttpApi.csproj" />
<ProjectReference Include="..\..\..\..\modules\identity\src\Volo.Abp.Identity.Web\Volo.Abp.Identity.Web.csproj" />
</ItemGroup>

3123
modules/setting-management/app/Volo.Abp.SettingManagement.DemoApp/wwwroot/libs/sweetalert2/sweetalert2.all.js

File diff suppressed because one or more lines are too long

2
modules/setting-management/app/Volo.Abp.SettingManagement.DemoApp/wwwroot/libs/sweetalert2/sweetalert2.all.min.js

File diff suppressed because one or more lines are too long

1319
modules/setting-management/app/Volo.Abp.SettingManagement.DemoApp/wwwroot/libs/sweetalert2/sweetalert2.css

File diff suppressed because it is too large

3121
modules/setting-management/app/Volo.Abp.SettingManagement.DemoApp/wwwroot/libs/sweetalert2/sweetalert2.js

File diff suppressed because it is too large

1
modules/setting-management/app/Volo.Abp.SettingManagement.DemoApp/wwwroot/libs/sweetalert2/sweetalert2.min.css

File diff suppressed because one or more lines are too long

1
modules/setting-management/app/Volo.Abp.SettingManagement.DemoApp/wwwroot/libs/sweetalert2/sweetalert2.min.js

File diff suppressed because one or more lines are too long

3
modules/setting-management/src/Volo.Abp.SettingManagement.Application/Volo/Abp/SettingManagement/EmailSettingsAppService.cs

@ -59,8 +59,9 @@ namespace Volo.Abp.SettingManagement
await SettingManager.SetForTenantOrGlobalAsync(CurrentTenant.Id, EmailSettingNames.DefaultFromDisplayName, input.DefaultFromDisplayName);
}
private async Task CheckFeatureAsync()
protected virtual async Task CheckFeatureAsync()
{
await FeatureChecker.CheckEnabledAsync(SettingManagementFeatures.Enable);
if (CurrentTenant.IsAvailable)
{
await FeatureChecker.CheckEnabledAsync(SettingManagementFeatures.AllowTenantsToChangeEmailSettings);

15
modules/setting-management/src/Volo.Abp.SettingManagement.Web/Settings/EmailingPageContributor.cs

@ -48,17 +48,18 @@ namespace Volo.Abp.SettingManagement.Web.Settings
private async Task<bool> CheckFeatureAsync(SettingPageCreationContext context)
{
var currentTenant = context.ServiceProvider.GetRequiredService<ICurrentTenant>();
if (!currentTenant.IsAvailable)
var featureCheck = context.ServiceProvider.GetRequiredService<IFeatureChecker>();
if (!await featureCheck.IsEnabledAsync(SettingManagementFeatures.Enable))
{
return true;
return false;
}
var featureCheck = context.ServiceProvider.GetRequiredService<IFeatureChecker>();
return await featureCheck.IsEnabledAsync(SettingManagementFeatures.AllowTenantsToChangeEmailSettings);
if (context.ServiceProvider.GetRequiredService<ICurrentTenant>().IsAvailable)
{
return await featureCheck.IsEnabledAsync(SettingManagementFeatures.AllowTenantsToChangeEmailSettings);
}
return true;
}
}
}

3123
modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/wwwroot/libs/sweetalert2/sweetalert2.all.js

File diff suppressed because one or more lines are too long

2
modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/wwwroot/libs/sweetalert2/sweetalert2.all.min.js

File diff suppressed because one or more lines are too long

1319
modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/wwwroot/libs/sweetalert2/sweetalert2.css

File diff suppressed because it is too large

3121
modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/wwwroot/libs/sweetalert2/sweetalert2.js

File diff suppressed because it is too large

1
modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/wwwroot/libs/sweetalert2/sweetalert2.min.css

File diff suppressed because one or more lines are too long

1
modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/wwwroot/libs/sweetalert2/sweetalert2.min.js

File diff suppressed because one or more lines are too long

4
npm/ng-packs/package.json

@ -48,7 +48,7 @@
"@abp/ng.tenant-management": "~4.4.2",
"@abp/ng.theme.basic": "~4.4.2",
"@abp/ng.theme.shared": "~4.4.2",
"@abp/utils": "^4.4.2",
"@abp/utils": "~4.4.2",
"@angular-devkit/build-angular": "~12.2.0",
"@angular-devkit/build-ng-packagr": "^0.1002.0",
"@angular-devkit/schematics-cli": "~12.2.0",
@ -115,4 +115,4 @@
"typescript": "~4.3.5",
"zone.js": "~0.11.4"
}
}
}

8
npm/ng-packs/packages/account-core/src/lib/tenant-box.service.ts

@ -1,12 +1,11 @@
import { Injectable } from '@angular/core';
import { ToasterService } from '@abp/ng.theme.shared';
import {
AbpApplicationConfigurationService,
AbpTenantService,
ConfigStateService,
CurrentTenantDto,
SessionStateService,
} from '@abp/ng.core';
import { ToasterService } from '@abp/ng.theme.shared';
import { Injectable } from '@angular/core';
import { finalize } from 'rxjs/operators';
@Injectable()
@ -24,7 +23,6 @@ export class TenantBoxService {
private tenantService: AbpTenantService,
private sessionState: SessionStateService,
private configState: ConfigStateService,
private appConfigService: AbpApplicationConfigurationService,
) {}
onSwitch() {
@ -57,7 +55,7 @@ export class TenantBoxService {
private setTenant(tenant: CurrentTenantDto) {
this.sessionState.setTenant(tenant);
this.appConfigService.get().subscribe(res => this.configState.setState(res));
this.configState.refreshAppState();
}
private showError() {

5
npm/ng-packs/packages/core/src/lib/core.module.ts

@ -16,7 +16,6 @@ import { InitDirective } from './directives/init.directive';
import { PermissionDirective } from './directives/permission.directive';
import { ReplaceableTemplateDirective } from './directives/replaceable-template.directive';
import { StopPropagationDirective } from './directives/stop-propagation.directive';
import { VisibilityDirective } from './directives/visibility.directive';
import { OAuthConfigurationHandler } from './handlers/oauth-configuration.handler';
import { RoutesHandler } from './handlers/routes.handler';
import { ApiInterceptor } from './interceptors/api.interceptor';
@ -24,6 +23,7 @@ import { LocalizationModule } from './localization.module';
import { ABP } from './models/common';
import { LocalizationPipe } from './pipes/localization.pipe';
import { SortPipe } from './pipes/sort.pipe';
import { CookieLanguageProvider } from './providers/cookie-language.provider';
import { LocaleProvider } from './providers/locale.provider';
import { LocalizationService } from './services/localization.service';
import { oAuthStorage } from './strategies/auth-flow.strategy';
@ -32,7 +32,6 @@ import { TENANT_KEY } from './tokens/tenant-key.token';
import { noop } from './utils/common-utils';
import './utils/date-extensions';
import { getInitialData, localeInitializer } from './utils/initial-utils';
import { CookieLanguageProvider } from './providers/cookie-language.provider';
export function storageFactory(): OAuthStorage {
return oAuthStorage;
@ -65,7 +64,6 @@ export function storageFactory(): OAuthStorage {
RouterOutletComponent,
SortPipe,
StopPropagationDirective,
VisibilityDirective,
],
imports: [
OAuthModule,
@ -90,7 +88,6 @@ export function storageFactory(): OAuthStorage {
RouterOutletComponent,
SortPipe,
StopPropagationDirective,
VisibilityDirective,
],
providers: [LocalizationPipe],
entryComponents: [

1
npm/ng-packs/packages/core/src/lib/directives/index.ts

@ -6,4 +6,3 @@ export * from './init.directive';
export * from './permission.directive';
export * from './replaceable-template.directive';
export * from './stop-propagation.directive';
export * from './visibility.directive';

20
npm/ng-packs/packages/core/src/lib/directives/permission.directive.ts

@ -40,28 +40,12 @@ export class PermissionDirective implements OnDestroy, OnChanges {
.getGrantedPolicy$(this.condition)
.pipe(distinctUntilChanged())
.subscribe(isGranted => {
if (this.templateRef) this.initStructural(isGranted);
else this.initAttribute(isGranted);
this.vcRef.clear();
if (isGranted) this.vcRef.createEmbeddedView(this.templateRef);
this.cdRef.detectChanges();
});
}
private initStructural(isGranted: boolean) {
this.vcRef.clear();
if (isGranted) this.vcRef.createEmbeddedView(this.templateRef);
}
/**
* @deprecated Will be deleted in v5.0
*/
private initAttribute(isGranted: boolean) {
if (!isGranted) {
this.renderer.removeChild(this.elRef.nativeElement.parentElement, this.elRef.nativeElement);
}
}
ngOnDestroy(): void {
if (this.subscription) this.subscription.unsubscribe();
}

66
npm/ng-packs/packages/core/src/lib/directives/visibility.directive.ts

@ -1,66 +0,0 @@
import { AfterViewInit, Directive, ElementRef, Input, Optional, Renderer2 } from '@angular/core';
import { Subject } from 'rxjs';
/**
*
* @deprecated To be deleted in v5.0
*/
@Directive({
selector: '[abpVisibility]',
})
export class VisibilityDirective implements AfterViewInit {
@Input('abpVisibility')
focusedElement: HTMLElement;
completed$ = new Subject<boolean>();
constructor(@Optional() private elRef: ElementRef, private renderer: Renderer2) {}
ngAfterViewInit() {
if (!this.focusedElement && this.elRef) {
this.focusedElement = this.elRef.nativeElement;
}
const observer = new MutationObserver(mutations => {
mutations.forEach(mutation => {
if (!mutation.target) return;
const htmlNodes =
Array.from(mutation.target.childNodes || []).filter(
node => node instanceof HTMLElement,
) || [];
if (!htmlNodes.length) {
this.removeFromDOM();
}
});
});
observer.observe(this.focusedElement, {
childList: true,
});
setTimeout(() => {
const htmlNodes =
Array.from(this.focusedElement.childNodes || []).filter(
node => node instanceof HTMLElement,
) || [];
if (!htmlNodes.length) this.removeFromDOM();
}, 0);
this.completed$.subscribe(() => observer.disconnect());
}
disconnect() {
this.completed$.next();
this.completed$.complete();
}
removeFromDOM() {
if (!this.elRef.nativeElement) return;
this.renderer.removeChild(this.elRef.nativeElement.parentElement, this.elRef.nativeElement);
this.disconnect();
}
}

117
npm/ng-packs/packages/core/src/lib/models/application-configuration.ts

@ -1,117 +0,0 @@
import { ABP } from './common';
export namespace ApplicationConfiguration {
/**
* @deprecated Use the ApplicationConfigurationDto interface instead. To be deleted in v5.0.
*/
export interface Response {
localization: Localization;
auth: Auth;
setting: Value;
currentUser: CurrentUser;
currentTenant: CurrentTenant;
features: Value;
}
/**
* @deprecated Use the ApplicationLocalizationConfigurationDto interface instead. To be deleted in v5.0.
*/
export interface Localization {
currentCulture: CurrentCulture;
defaultResourceName: string;
languages: Language[];
values: LocalizationValue;
}
/**
* @deprecated Use the Record<string, Record<string, string>> type instead. To be deleted in v5.0.
*/
export interface LocalizationValue {
[key: string]: { [key: string]: string };
}
/**
* @deprecated Use the LanguageInfo interface instead. To be deleted in v5.0.
*/
export interface Language {
cultureName: string;
uiCultureName: string;
displayName: string;
flagIcon: string;
}
/**
* @deprecated Use the CurrentCultureDto interface instead. To be deleted in v5.0.
*/
export interface CurrentCulture {
cultureName: string;
dateTimeFormat: DateTimeFormat;
displayName: string;
englishName: string;
isRightToLeft: boolean;
name: string;
nativeName: string;
threeLetterIsoLanguageName: string;
twoLetterIsoLanguageName: string;
}
/**
* @deprecated Use the DateTimeFormatDto interface instead. To be deleted in v5.0.
*/
export interface DateTimeFormat {
calendarAlgorithmType: string;
dateSeparator: string;
fullDateTimePattern: string;
longTimePattern: string;
shortDatePattern: string;
shortTimePattern: string;
}
/**
* @deprecated Use the ApplicationAuthConfigurationDto interface instead. To be deleted in v5.0.
*/
export interface Auth {
policies: Policy;
grantedPolicies: Policy;
}
/**
* @deprecated Use the Record<string, boolean> type instead. To be deleted in v5.0.
*/
export interface Policy {
[key: string]: boolean;
}
/**
* @deprecated To be deleted in v5.0.
*/
export interface Value {
values: ABP.Dictionary<string>;
}
/**
* @deprecated Use the CurrentUserDto interface instead. To be deleted in v5.0.
*/
export interface CurrentUser {
email: string;
emailVerified: false;
id: string;
isAuthenticated: boolean;
roles: string[];
tenantId: string;
userName: string;
name: string;
phoneNumber: string;
phoneNumberVerified: boolean;
surName: string;
}
/**
* @deprecated Use the CurrentTenantDto interface instead. To be deleted in v5.0.
*/
export interface CurrentTenant {
id: string;
name: string;
isAvailable?: boolean;
}
}

1
npm/ng-packs/packages/core/src/lib/models/index.ts

@ -1,4 +1,3 @@
export * from './application-configuration';
export * from './auth';
export * from './common';
export * from './dtos';

15
npm/ng-packs/packages/core/src/lib/models/session.ts

@ -4,20 +4,5 @@ export namespace Session {
export interface State {
language: string;
tenant: CurrentTenantDto;
/**
*
* @deprecated To be deleted in v5.0
*/
sessionDetail: SessionDetail;
}
/**
*
* @deprecated To be deleted in v5.0
*/
export interface SessionDetail {
openedTabCount: number;
lastExitTime: number;
remember: boolean;
}
}

24
npm/ng-packs/packages/core/src/lib/services/application-configuration.service.ts

@ -1,24 +0,0 @@
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { Rest } from '../models/rest';
import { ApplicationConfigurationDto } from '../proxy/volo/abp/asp-net-core/mvc/application-configurations/models';
import { RestService } from './rest.service';
/**
* @deprecated Use AbpApplicationConfigurationService instead. To be deleted in v5.0.
*/
@Injectable({
providedIn: 'root',
})
export class ApplicationConfigurationService {
constructor(private rest: RestService) {}
getConfiguration(): Observable<ApplicationConfigurationDto> {
const request: Rest.Request<null> = {
method: 'GET',
url: '/api/abp/application-configuration',
};
return this.rest.request<null, ApplicationConfigurationDto>(request, {});
}
}

7
npm/ng-packs/packages/core/src/lib/services/auth.service.ts

@ -42,13 +42,6 @@ export class AuthService {
return this.strategy.logout(queryParams);
}
/**
* @deprecated Use navigateToLogin method instead. To be deleted in v5.0
*/
initLogin() {
this.strategy.navigateToLogin();
}
navigateToLogin(queryParams?: Params) {
this.strategy.navigateToLogin(queryParams);
}

14
npm/ng-packs/packages/core/src/lib/services/config-state.service.ts

@ -1,9 +1,9 @@
import { Injectable } from '@angular/core';
import { Observable, Subject } from 'rxjs';
import { map, take, switchMap } from 'rxjs/operators';
import { map, switchMap, take } from 'rxjs/operators';
import { AbpApplicationConfigurationService } from '../proxy/volo/abp/asp-net-core/mvc/application-configurations/abp-application-configuration.service';
import { ApplicationConfigurationDto } from '../proxy/volo/abp/asp-net-core/mvc/application-configurations/models';
import { InternalStore } from '../utils/internal-store-utils';
import { AbpApplicationConfigurationService } from '../proxy/volo/abp/asp-net-core/mvc/application-configurations/abp-application-configuration.service';
@Injectable({
providedIn: 'root',
@ -24,15 +24,7 @@ export class ConfigStateService {
private initUpdateStream() {
this.updateSubject
.pipe(switchMap(() => this.abpConfigService.get()))
.subscribe(res => this.setState(res));
}
/**
* @deprecated do not use this method directly, instead call refreshAppState
* This method will be private in v5.0
*/
setState(state: ApplicationConfigurationDto) {
this.store.set(state);
.subscribe(res => this.store.set(res));
}
refreshAppState() {

1
npm/ng-packs/packages/core/src/lib/services/index.ts

@ -1,4 +1,3 @@
export * from './application-configuration.service';
export * from './auth.service';
export * from './config-state.service';
export * from './content-projection.service';

38
npm/ng-packs/packages/core/src/lib/services/multi-tenancy.service.ts

@ -1,16 +1,14 @@
import { Injectable, Inject } from '@angular/core';
import { switchMap, map } from 'rxjs/operators';
import { Observable } from 'rxjs';
import { ABP } from '../models/common';
import { Inject, Injectable } from '@angular/core';
import { map, switchMap } from 'rxjs/operators';
import { AbpTenantService } from '../proxy/pages/abp/multi-tenancy';
import {
FindTenantResultDto,
CurrentTenantDto,
FindTenantResultDto,
} from '../proxy/volo/abp/asp-net-core/mvc/multi-tenancy/models';
import { RestService } from './rest.service';
import { AbpTenantService } from '../proxy/pages/abp/multi-tenancy';
import { TENANT_KEY } from '../tokens/tenant-key.token';
import { ConfigStateService } from './config-state.service';
import { RestService } from './rest.service';
import { SessionStateService } from './session-state.service';
import { TENANT_KEY } from '../tokens/tenant-key.token';
@Injectable({ providedIn: 'root' })
export class MultiTenancyService {
@ -33,30 +31,6 @@ export class MultiTenancyService {
@Inject(TENANT_KEY) public tenantKey: string,
) {}
/**
* @deprecated Use AbpTenantService.findTenantByName method instead. To be deleted in v5.0.
*/
findTenantByName(name: string, headers: ABP.Dictionary<string>): Observable<FindTenantResultDto> {
return this.restService.request(
{
url: `/api/abp/multi-tenancy/tenants/by-name/${name}`,
method: 'GET',
headers,
},
{ apiName: this.apiName },
);
}
/**
* @deprecated Use AbpTenantService.findTenantById method instead. To be deleted in v5.0.
*/
findTenantById(id: string, headers: ABP.Dictionary<string>): Observable<FindTenantResultDto> {
return this.restService.request(
{ url: `/api/abp/multi-tenancy/tenants/by-id/${id}`, method: 'GET', headers },
{ apiName: this.apiName },
);
}
setTenantByName(tenantName: string) {
return this.tenantService
.findTenantByName(tenantName, { [this.tenantKey]: '' })

27
npm/ng-packs/packages/core/src/lib/tests/application-configuration.service.spec.ts

@ -1,27 +0,0 @@
import { createServiceFactory, SpectatorService } from '@ngneat/spectator/jest';
import { of } from 'rxjs';
import { ApplicationConfigurationService, RestService } from '../services';
describe('ApplicationConfigurationService', () => {
let spectator: SpectatorService<ApplicationConfigurationService>;
const createService = createServiceFactory({
service: ApplicationConfigurationService,
mocks: [RestService],
});
beforeEach(() => (spectator = createService()));
it('should send a GET to application-configuration API', () => {
const rest = spectator.inject(RestService);
const requestSpy = jest.spyOn(rest, 'request');
requestSpy.mockReturnValue(of(null));
spectator.service.getConfiguration().subscribe();
expect(requestSpy).toHaveBeenCalledWith(
{ method: 'GET', url: '/api/abp/application-configuration' },
{},
);
});
});

12
npm/ng-packs/packages/core/src/lib/tests/config-state.service.spec.ts

@ -1,5 +1,7 @@
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { createServiceFactory, SpectatorService } from '@ngneat/spectator/jest';
import { of } from 'rxjs';
import { AbpApplicationConfigurationService } from '../proxy/volo/abp/asp-net-core/mvc/application-configurations/abp-application-configuration.service';
import {
ApplicationConfigurationDto,
CurrentUserDto,
@ -107,14 +109,20 @@ describe('ConfigStateService', () => {
const createService = createServiceFactory({
service: ConfigStateService,
imports: [HttpClientTestingModule],
providers: [{ provide: CORE_OPTIONS, useValue: { skipGetAppConfiguration: true } }],
providers: [
{ provide: CORE_OPTIONS, useValue: { skipGetAppConfiguration: true } },
{
provide: AbpApplicationConfigurationService,
useValue: { get: () => of(CONFIG_STATE_DATA) },
},
],
});
beforeEach(() => {
spectator = createService();
configState = spectator.service;
configState.setState(CONFIG_STATE_DATA);
configState.refreshAppState();
});
describe('#getAll', () => {

29
npm/ng-packs/packages/core/src/lib/tests/localization.service.spec.ts

@ -1,13 +1,15 @@
import { Injector } from '@angular/core';
import { Router } from '@angular/router';
import { createServiceFactory, SpectatorService, SpyObject } from '@ngneat/spectator/jest';
import { of } from 'rxjs';
import { BehaviorSubject } from 'rxjs';
import { AbpApplicationConfigurationService } from '../proxy/volo/abp/asp-net-core/mvc/application-configurations/abp-application-configuration.service';
import { ConfigStateService, SessionStateService } from '../services';
import { LocalizationService } from '../services/localization.service';
import { CORE_OPTIONS } from '../tokens/options.token';
import { CONFIG_STATE_DATA } from './config-state.service.spec';
const appConfigData$ = new BehaviorSubject(CONFIG_STATE_DATA);
describe('LocalizationService', () => {
let spectator: SpectatorService<LocalizationService>;
let sessionState: SpyObject<SessionStateService>;
@ -25,7 +27,7 @@ describe('LocalizationService', () => {
},
{
provide: AbpApplicationConfigurationService,
useValue: { get: () => of(CONFIG_STATE_DATA) },
useValue: { get: () => appConfigData$ },
},
],
});
@ -36,8 +38,9 @@ describe('LocalizationService', () => {
configState = spectator.inject(ConfigStateService);
service = spectator.service;
configState.setState(CONFIG_STATE_DATA);
configState.refreshAppState();
sessionState.setLanguage('tr');
appConfigData$.next(CONFIG_STATE_DATA);
});
describe('#currentLang', () => {
@ -108,12 +111,13 @@ describe('LocalizationService', () => {
`(
'should return observable $expected when resource name is $resource and key is $key',
async ({ resource, key, defaultValue, expected }) => {
configState.setState({
appConfigData$.next({
localization: {
values: { foo: { bar: 'baz' }, x: { y: 'z' } },
defaultResourceName: 'x',
},
});
} as any);
configState.refreshAppState();
service.localize(resource, key, defaultValue).subscribe(result => {
expect(result).toBe(expected);
@ -149,12 +153,13 @@ describe('LocalizationService', () => {
`(
'should return $expected when resource name is $resource and key is $key',
({ resource, key, defaultValue, expected }) => {
configState.setState({
appConfigData$.next({
localization: {
values: { foo: { bar: 'baz' }, x: { y: 'z' } },
defaultResourceName: 'x',
},
});
} as any);
configState.refreshAppState();
const result = service.localizeSync(resource, key, defaultValue);
@ -195,12 +200,13 @@ describe('LocalizationService', () => {
`(
'should return observable $expected when resource names are $resources and keys are $keys',
async ({ resources, keys, defaultValue, expected }) => {
configState.setState({
appConfigData$.next({
localization: {
values: { foo: { bar: 'baz' }, x: { y: 'z' } },
defaultResourceName: 'x',
},
});
} as any);
configState.refreshAppState();
service.localizeWithFallback(resources, keys, defaultValue).subscribe(result => {
expect(result).toBe(expected);
@ -241,12 +247,13 @@ describe('LocalizationService', () => {
`(
'should return $expected when resource names are $resources and keys are $keys',
({ resources, keys, defaultValue, expected }) => {
configState.setState({
appConfigData$.next({
localization: {
values: { foo: { bar: 'baz' }, x: { y: 'z' } },
defaultResourceName: 'x',
},
});
} as any);
configState.refreshAppState();
const result = service.localizeWithFallbackSync(resources, keys, defaultValue);

2
npm/ng-packs/packages/core/src/lib/tests/permission.directive.spec.ts

@ -17,7 +17,7 @@ describe('PermissionDirective', () => {
describe('with condition', () => {
beforeEach(() => {
spectator = createDirective(
`<div id="test-element" [abpPermission]="'test'">Testing Permission Directive</div>`,
`<div id="test-element" *abpPermission="'test'">Testing Permission Directive</div>`,
);
directive = spectator.directive;
});

126
npm/ng-packs/packages/core/src/lib/tests/visibility.directive.spec.ts

@ -1,126 +0,0 @@
import { SpectatorDirective, createDirectiveFactory } from '@ngneat/spectator/jest';
import { VisibilityDirective } from '../directives/visibility.directive';
describe('VisibilityDirective', () => {
let spectator: SpectatorDirective<VisibilityDirective>;
let directive: VisibilityDirective;
const createDirective = createDirectiveFactory({
directive: VisibilityDirective,
});
describe('without content', () => {
beforeEach(() => {
spectator = createDirective('<div [abpVisibility]></div>');
directive = spectator.directive;
});
it('should be created', () => {
expect(directive).toBeTruthy();
});
xit('should be removed', done => {
setTimeout(() => {
expect(spectator.query('div')).toBeFalsy();
done();
}, 0);
});
});
describe('without mutation observer and with content', () => {
beforeEach(() => {
spectator = createDirective('<div [abpVisibility]><p id="content">Content</p></div>');
directive = spectator.directive;
});
it('should not removed', done => {
setTimeout(() => {
expect(spectator.query('div')).toBeTruthy();
done();
}, 0);
});
});
describe('without mutation observer and with focused element', () => {
beforeEach(() => {
spectator = createDirective(
'<div id="main" [abpVisibility]="container"></div><div #container><p id="content">Content</p></div>',
);
directive = spectator.directive;
});
it('should not removed', done => {
setTimeout(() => {
expect(spectator.query('#main')).toBeTruthy();
done();
}, 0);
});
});
describe('without content and with focused element', () => {
beforeEach(() => {
spectator = createDirective(
'<div id="main" [abpVisibility]="container"></div><div #container></div>',
);
directive = spectator.directive;
});
xit('should be removed', done => {
setTimeout(() => {
expect(spectator.query('#main')).toBeFalsy();
done();
}, 0);
});
});
describe('with mutation observer and with content', () => {
beforeEach(() => {
spectator = createDirective('<div [abpVisibility]><div id="content">Content</div></div>');
directive = spectator.directive;
});
xit('should remove the main div element when content removed', done => {
spectator.query('#content').remove();
setTimeout(() => {
expect(spectator.query('div')).toBeFalsy();
done();
}, 0);
});
it('should not remove the main div element', done => {
spectator.query('div').appendChild(document.createElement('div'));
setTimeout(() => {
expect(spectator.query('div')).toBeTruthy();
done();
}, 100);
});
});
describe('with mutation observer and with focused element', () => {
beforeEach(() => {
spectator = createDirective(
'<div id="main" [abpVisibility]="container"></div><div #container><p id="content">Content</p></div>',
);
directive = spectator.directive;
});
xit('should remove the main div element when content removed', done => {
spectator.query('#content').remove();
setTimeout(() => {
expect(spectator.query('#main')).toBeFalsy();
done();
}, 0);
});
it('should not remove the main div element', done => {
spectator.query('#content').appendChild(document.createElement('div'));
setTimeout(() => {
expect(spectator.query('#main')).toBeTruthy();
done();
}, 100);
});
});
});

1
npm/ng-packs/packages/core/src/lib/utils/date-utils.ts

@ -1,4 +1,3 @@
import { ApplicationConfiguration } from '../models/application-configuration';
import { DateTimeFormatDto } from '../proxy/volo/abp/asp-net-core/mvc/application-configurations/models';
import { ConfigStateService } from '../services';

1
npm/ng-packs/packages/core/src/lib/utils/index.ts

@ -16,6 +16,5 @@ export * from './multi-tenancy-utils';
export * from './number-utils';
export * from './object-utils';
export * from './route-utils';
export * from './rxjs-utils';
export * from './string-utils';
export * from './tree-utils';

31
npm/ng-packs/packages/core/src/lib/utils/rxjs-utils.ts

@ -1,31 +0,0 @@
import { Observable, Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
function isFunction(value) {
return typeof value === 'function';
}
/**
* @deprecated no longer working, please use SubscriptionService (https://docs.abp.io/en/abp/latest/UI/Angular/Subscription-Service) instead.
*/
export const takeUntilDestroy =
(componentInstance, destroyMethodName = 'ngOnDestroy') =>
<T>(source: Observable<T>) => {
const originalDestroy = componentInstance[destroyMethodName];
if (isFunction(originalDestroy) === false) {
throw new Error(
`${componentInstance.constructor.name} is using untilDestroyed but doesn't implement ${destroyMethodName}`,
);
}
if (!componentInstance['__takeUntilDestroy']) {
componentInstance['__takeUntilDestroy'] = new Subject();
componentInstance[destroyMethodName] = function () {
// eslint-disable-next-line prefer-rest-params
isFunction(originalDestroy) && originalDestroy.apply(this, arguments);
componentInstance['__takeUntilDestroy'].next(true);
componentInstance['__takeUntilDestroy'].complete();
};
}
return source.pipe(takeUntil<T>(componentInstance['__takeUntilDestroy']));
};

2
npm/ng-packs/packages/feature-management/src/lib/components/feature-management/feature-management.component.html

@ -1,4 +1,4 @@
<abp-modal *ngIf="visible" size="lg" [(visible)]="visible" [busy]="modalBusy">
<abp-modal *ngIf="visible" [(visible)]="visible" [busy]="modalBusy" [options]="{ size: 'lg' }">
<ng-template #abpHeader>
<h3>{{ 'AbpFeatureManagement::Features' | abpLocalization }}</h3>
</ng-template>

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save