Browse Source

Merge branch 'dev' into cli-ConnectionStringProvider

pull/7340/head
Alper Ebicoglu 6 years ago
committed by GitHub
parent
commit
8048e7e7ee
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      common.props
  2. 103
      docs/en/Community-Articles/2021-01-20-How-to-Integrate-the-MatBlazor-Blazor-Component/POST.md
  3. BIN
      docs/en/Community-Articles/2021-01-20-How-to-Integrate-the-MatBlazor-Blazor-Component/example-result.png
  4. BIN
      docs/en/Community-Articles/2021-01-20-How-to-Integrate-the-MatBlazor-Blazor-Component/initial-project.png
  5. BIN
      docs/en/Community-Articles/2021-01-20-How-to-Integrate-the-MatBlazor-Blazor-Component/table-app-contract.png
  6. BIN
      docs/en/Community-Articles/2021-01-20-How-to-Integrate-the-MatBlazor-Blazor-Component/table-application.png
  7. BIN
      docs/en/Community-Articles/2021-01-20-How-to-Integrate-the-MatBlazor-Blazor-Component/table-web.png
  8. 4
      docs/en/UI/Angular/Testing.md
  9. 26
      framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs
  10. 5
      framework/src/Volo.Abp.Validation/Volo/Abp/Validation/ValidationHelper.cs
  11. 6
      framework/test/Volo.Abp.Validation.Tests/Volo/Abp/Validation/ApplicationService_Validation_Tests.cs
  12. 2
      modules/account/src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml
  13. 9
      modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/IAuditLogRepository.cs
  14. 26
      modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/EfCoreAuditLogRepository.cs
  15. 54
      modules/audit-logging/src/Volo.Abp.AuditLogging.MongoDB/Volo/Abp/AuditLogging/MongoDB/MongoAuditLogRepository.cs
  16. 5
      modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo/Abp/BackgroundJobs/IBackgroundJobRepository.cs
  17. 7
      modules/background-jobs/src/Volo.Abp.BackgroundJobs.EntityFrameworkCore/Volo/Abp/BackgroundJobs/EntityFrameworkCore/EfCoreBackgroundJobRepository.cs
  18. 11
      modules/background-jobs/src/Volo.Abp.BackgroundJobs.MongoDB/Volo/Abp/BackgroundJobs/MongoDB/MongoBackgroundJobRepository.cs
  19. 3
      modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Blogs/IBlogRepository.cs
  20. 11
      modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Comments/ICommentRepository.cs
  21. 9
      modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/IPostRepository.cs
  22. 8
      modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Tagging/ITagRepository.cs
  23. 5
      modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Blogs/EfCoreBlogRepository.cs
  24. 17
      modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Comments/EfCoreCommentRepository.cs
  25. 19
      modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Posts/EfCorePostRepository.cs
  26. 16
      modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Tagging/EfCoreTagRepository.cs
  27. 5
      modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Blogs/MongoBlogRepository.cs
  28. 25
      modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Comments/MongoCommentRepository.cs
  29. 23
      modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Posts/MongoPostRepository.cs
  30. 18
      modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Tagging/MongoTagRepository.cs
  31. 4
      modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Users/MongoBlogUserRepository.cs
  32. 12
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Contents/ContentGetListDto.cs
  33. 1
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Contents/IContentAdminAppService.cs
  34. 16
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Tags/EntityTagCreateDto.cs
  35. 17
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Tags/EntityTagRemoveDto.cs
  36. 11
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Tags/IEntityTagAdminAppService.cs
  37. 3
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Tags/ITagAdminAppService.cs
  38. 18
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Tags/TagDefinitionDto.cs
  39. 5
      modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/CmsKitAdminApplicationAutoMapperProfile.cs
  40. 3
      modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Contents/ContentAdminAppService.cs
  41. 1
      modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Pages/PageAdminAppService.cs
  42. 52
      modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Tags/EntityTagAdminAppService.cs
  43. 19
      modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Tags/TagAdminAppService.cs
  44. 2
      modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Contents/ContentAdminController.cs
  45. 6
      modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Tags/TagAdminController.cs
  46. 10
      modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/CmsKitErrorCodes.cs
  47. 1
      modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/en.json
  48. 1
      modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/tr.json
  49. 22
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/CmsKitDomainModule.cs
  50. 8
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/CmsKitOptions.cs
  51. 32
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/PolicySpecifiedDefinition.cs
  52. 11
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/CmsKitTagOptions.cs
  53. 40
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/DefaultTagDefinitionStore.cs
  54. 26
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/EntityNotTaggableException.cs
  55. 3
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/EntityTag.cs
  56. 52
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/EntityTagManager.cs
  57. 24
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/IEntityTagManager.cs
  58. 12
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/IEntityTagRepository.cs
  59. 15
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/ITagDefinitionStore.cs
  60. 3
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/ITagManager.cs
  61. 2
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/TagAlreadyExistException.cs
  62. 20
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/TagEntityTypeDefinitionDictionary.cs
  63. 31
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/TagEntityTypeDefiniton1.cs
  64. 19
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/TagManager.cs
  65. 19
      modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Tags/EfCoreEntityTagRepository.cs
  66. 2
      modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Contents/MongoContentRepository.cs
  67. 2
      modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Pages/MongoPageRepository.cs
  68. 19
      modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Tags/MongoEntityTagRepository.cs
  69. 2
      modules/cms-kit/src/Volo.CmsKit.Public.Application.Contracts/Volo/CmsKit/Public/Pages/IPageAppService.cs
  70. 9
      modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Pages/PageAppService.cs
  71. 6
      modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/Pages/PagesPublicController.cs
  72. 5
      modules/cms-kit/src/Volo.CmsKit.Public.Web/CmsKitPublicWebModule.cs
  73. 2
      modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Pages/Index.cshtml
  74. 11
      modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Pages/Index.cshtml.cs
  75. 32
      modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Contents/ContentViewComponent.cs
  76. 2
      modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Contents/Default.cshtml
  77. 12
      modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Pages/Default.cshtml
  78. 3
      modules/cms-kit/test/Volo.CmsKit.Application.Tests/Contents/ContentAdminAppService_Tests.cs
  79. 11
      modules/cms-kit/test/Volo.CmsKit.Application.Tests/Pages/PagePublicAppService_Tests.cs
  80. 4
      modules/cms-kit/test/Volo.CmsKit.Application.Tests/Tags/TagAdminAppService_Tests.cs
  81. 1
      modules/cms-kit/test/Volo.CmsKit.Domain.Tests/CmsKitDomainTestModule.cs
  82. 60
      modules/cms-kit/test/Volo.CmsKit.Domain.Tests/Tags/EntityTagManager_Tests.cs
  83. 30
      modules/cms-kit/test/Volo.CmsKit.Domain.Tests/Tags/TagManager_Tests.cs
  84. 59
      modules/cms-kit/test/Volo.CmsKit.TestBase/CmsKitDataSeedContributor.cs
  85. 11
      modules/cms-kit/test/Volo.CmsKit.TestBase/CmsKitTestData.cs
  86. 9
      modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/IProjectRepository.cs
  87. 13
      modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/Projects/EfCoreProjectRepository.cs
  88. 15
      modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/Projects/MongoProjectRepository.cs
  89. 18
      modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/IFeatureValueRepository.cs
  90. 26
      modules/feature-management/src/Volo.Abp.FeatureManagement.EntityFrameworkCore/Volo/Abp/FeatureManagement/EntityFrameworkCore/EfCoreFeatureValueRepository.cs
  91. 30
      modules/feature-management/src/Volo.Abp.FeatureManagement.MongoDB/Volo/Abp/FeatureManagement/MongoDB/MongoFeatureValueRepository.cs
  92. 11
      modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentitySecurityLogRepository.cs
  93. 9
      modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoPersistedGrantRepository.cs
  94. 18
      modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/ISettingRepository.cs
  95. 29
      modules/setting-management/src/Volo.Abp.SettingManagement.EntityFrameworkCore/Volo/Abp/SettingManagement/EntityFrameworkCore/EfCoreSettingRepository.cs
  96. 36
      modules/setting-management/src/Volo.Abp.SettingManagement.MongoDB/Volo/Abp/SettingManagement/MongoDB/MongoSettingRepository.cs
  97. 75
      npm/ng-packs/packages/core/src/lib/tests/tree-utils.spec.ts
  98. 19
      npm/ng-packs/packages/core/src/lib/utils/tree-utils.ts

2
common.props

@ -1,7 +1,7 @@
<Project>
<PropertyGroup>
<LangVersion>latest</LangVersion>
<Version>4.3.0</Version>
<Version>4.3.0</Version>
<NoWarn>$(NoWarn);CS1591;CS0436</NoWarn>
<PackageIconUrl>https://abp.io/assets/abp_nupkg.png</PackageIconUrl>
<PackageProjectUrl>https://abp.io/</PackageProjectUrl>

103
docs/en/Community-Articles/2021-01-20-How-to-Integrate-the-MatBlazor-Blazor-Component/POST.md

@ -0,0 +1,103 @@
## Using MatBlazor UI Components With the ABP Framework
Hi, in this step by step article, I will show you how to integrate [MatBlazor](https://www.matblazor.com/), a blazor UI components into ABP Framework-based applications.
![example-result](example-result.png)
*(A screenshot from the example application developed in this article)*
## Create the Project
> First thing is to create the project. ABP Framework offers startup templates to get into business faster.
In this article, I will create a new startup template with EF Core as a database provider and Blazor for UI framework. But if you already have a project with Blazor UI, you don't need to create a new startup template, you can directly implement the following steps to your existing project.
> If you already have a project with the Blazor UI, you can skip this section.
* Before starting the development, we will create a new solution named `MatBlazorSample` (or whatever you want). We will create a new startup template with EF Core as a database provider and Blazor for UI framework by using [ABP CLI](https://docs.abp.io/en/abp/latest/CLI):
````bash
abp new MatBlazorSample -u blazor
````
This will create new project inside of `aspnet-core`, so:
````bash
cd aspnet-core
````
and
````bash
dotnet restore
````
* Our project boilerplate will be ready after the download is finished. Then, we can open the solution in the Visual Studio (or any other IDE) and run the `MatBlazorSample.DbMigrator` to create the database and seed initial data (which creates the admin user, admin role, permissions etc.)
![initial-project](initial-project.png)
* After database and initial data created,
* Run the `MatBlazorSample.HttpApi.Host` to see our server side working and
* Run the `MatBlazorSample.Blazor` to see our UI working properly.
> _Default login credentials for admin: username is **admin** and password is **1q2w3E\***_
## Install MatBlazor
You can follow [this documentation](https://www.matblazor.com/) to install MatBlazor packages into your computer.
### Adding MatBlazor NuGet Packages
```bash
Install-Package MatBlazor
```
### Register MatBlazor Resources
1. Add the following line to the HEAD section of the `wwwroot/index.html` file within the `MatBlazorSample.Blazor` project:
```Razor
<head>
<!--...-->
<script src="_content/MatBlazor/dist/matBlazor.js"></script>
<link href="_content/MatBlazor/dist/matBlazor.css" rel="stylesheet" />
</head>
```
2. In the `MatBlazorSampleBlazorModule` class, call the `AddMatBlazor()` method from your project's `ConfigureServices()` method:
```csharp
public override void ConfigureServices(ServiceConfigurationContext context)
{
var environment = context.Services.GetSingletonInstance<IWebAssemblyHostEnvironment>();
var builder = context.Services.GetSingletonInstance<WebAssemblyHostBuilder>();
// ...
builder.Services.AddMatBlazor();
}
```
3. Register the **MatBlazorSample.Blazor** namespace in the `_Imports.razor` file:
```Razor
@using MatBlazor
```
## The Sample Application
We have created a sample application with [Table](https://www.matblazor.com/Table) example.
### The Source Code
You can download the source code from [here](https://github.com/abpframework/abp-samples/tree/master/MatBlazorSample).
The related files for this example are marked in the following screenshots.
![table-app-contract](table-app-contract.png)
![table-application](table-application.png)
![table-web](table-web.png)
## Conclusion
In this article, I've explained how to use [MatBlazor](https://www.matblazor.com/) components in your application. ABP Framework is designed so that it can work with any UI library/framework.

BIN
docs/en/Community-Articles/2021-01-20-How-to-Integrate-the-MatBlazor-Blazor-Component/example-result.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

BIN
docs/en/Community-Articles/2021-01-20-How-to-Integrate-the-MatBlazor-Blazor-Component/initial-project.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
docs/en/Community-Articles/2021-01-20-How-to-Integrate-the-MatBlazor-Blazor-Component/table-app-contract.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

BIN
docs/en/Community-Articles/2021-01-20-How-to-Integrate-the-MatBlazor-Blazor-Component/table-application.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

BIN
docs/en/Community-Articles/2021-01-20-How-to-Integrate-the-MatBlazor-Blazor-Component/table-web.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

4
docs/en/UI/Angular/Testing.md

@ -374,3 +374,7 @@ Finally, don't forget to run your CI tests with the following command:
```sh
npm test -- --prod
```
## See Also
* [ABP Community Video - Unit Testing with the Angular UI](https://community.abp.io/articles/unit-testing-with-the-angular-ui-p4l550q3)

26
framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs

@ -269,7 +269,7 @@ namespace Volo.Abp.BlazoriseUI
await GetEntitiesAsync();
StateHasChanged();
await InvokeAsync(StateHasChanged);
}
protected virtual async Task OnDataGridReadAsync(DataGridReadDataEventArgs<TListViewModel> e)
@ -282,7 +282,7 @@ namespace Volo.Abp.BlazoriseUI
await GetEntitiesAsync();
StateHasChanged();
await InvokeAsync(StateHasChanged);
}
protected virtual async Task OpenCreateModalAsync()
@ -295,7 +295,7 @@ namespace Volo.Abp.BlazoriseUI
// Mapper will not notify Blazor that binded values are changed
// so we need to notify it manually by calling StateHasChanged
await InvokeAsync(() => StateHasChanged());
await InvokeAsync(StateHasChanged);
CreateModal.Show();
}
@ -317,7 +317,7 @@ namespace Volo.Abp.BlazoriseUI
EditingEntityId = entity.Id;
EditingEntity = MapToEditingEntity(entityDto);
await InvokeAsync(() => StateHasChanged());
await InvokeAsync(StateHasChanged);
EditModal.Show();
}
@ -362,11 +362,8 @@ namespace Volo.Abp.BlazoriseUI
await CheckCreatePolicyAsync();
var createInput = MapToCreateInput(NewEntity);
await AppService.CreateAsync(createInput);
await GetEntitiesAsync();
await OnCreatedEntityAsync();
CreateModal.Hide();
}
}
@ -375,9 +372,11 @@ namespace Volo.Abp.BlazoriseUI
return Task.CompletedTask;
}
protected virtual Task OnCreatedEntityAsync()
protected virtual async Task OnCreatedEntityAsync()
{
return Task.CompletedTask;
await GetEntitiesAsync();
CreateModal.Hide();
}
protected virtual async Task UpdateEntityAsync()
@ -389,11 +388,8 @@ namespace Volo.Abp.BlazoriseUI
await CheckUpdatePolicyAsync();
var updateInput = MapToUpdateInput(EditingEntity);
await AppService.UpdateAsync(EditingEntityId, updateInput);
await GetEntitiesAsync();
await OnUpdatedEntityAsync();
EditModal.Hide();
}
}
@ -402,9 +398,11 @@ namespace Volo.Abp.BlazoriseUI
return Task.CompletedTask;
}
protected virtual Task OnUpdatedEntityAsync()
protected virtual async Task OnUpdatedEntityAsync()
{
return Task.CompletedTask;
await GetEntitiesAsync();
EditModal.Hide();
}
protected virtual async Task DeleteEntityAsync(TListViewModel entity)

5
framework/src/Volo.Abp.Validation/Volo/Abp/Validation/ValidationHelper.cs

@ -4,7 +4,9 @@ namespace Volo.Abp.Validation
{
public class ValidationHelper
{
private const string EmailRegEx = @"[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?";
// Taken from W3C as an alternative to the RFC5322 specification: https://html.spec.whatwg.org/#valid-e-mail-address
// The RFC5322 regex can be found here: https://emailregex.com/
public static string EmailRegEx { get; set; } = @"^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$";
public static bool IsValidEmailAddress(string email)
{
@ -13,7 +15,6 @@ namespace Volo.Abp.Validation
return false;
}
/*RFC 2822 (simplified)*/
return Regex.IsMatch(email, EmailRegEx, RegexOptions.Compiled | RegexOptions.IgnoreCase);
}
}

6
framework/test/Volo.Abp.Validation.Tests/Volo/Abp/Validation/ApplicationService_Validation_Tests.cs

@ -180,15 +180,19 @@ namespace Volo.Abp.Validation
{
//Valid
ValidationHelper.IsValidEmailAddress("john.doe@domain.com").ShouldBe(true);
ValidationHelper.IsValidEmailAddress("john-doe1@domain.co").ShouldBe(true);
ValidationHelper.IsValidEmailAddress("ip@1.2.3.123").ShouldBe(true);
ValidationHelper.IsValidEmailAddress("pharaoh@egyptian.museum").ShouldBe(true);
ValidationHelper.IsValidEmailAddress("john.doe+regexbuddy@gmail.com").ShouldBe(true);
ValidationHelper.IsValidEmailAddress("Mike.O'Dell@ireland.com").ShouldBe(true);
ValidationHelper.IsValidEmailAddress("admin@localhost").ShouldBe(true);
ValidationHelper.IsValidEmailAddress("j@h.c").ShouldBe(true);
//Invalid
ValidationHelper.IsValidEmailAddress("1024x768@60Hz").ShouldBe(false);
ValidationHelper.IsValidEmailAddress("not.a.valid.email").ShouldBe(false);
ValidationHelper.IsValidEmailAddress("john@aol...com").ShouldBe(false);
ValidationHelper.IsValidEmailAddress("john@aol@domain.com").ShouldBe(false);
ValidationHelper.IsValidEmailAddress("jack@domain.").ShouldBe(false);
}
[DependsOn(typeof(AbpAutofacModule))]

2
modules/account/src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml

@ -56,7 +56,7 @@
<input asp-for="ReturnUrlHash"/>
@foreach (var provider in Model.VisibleExternalProviders)
{
<button type="submit" class="btn btn-primary m-1" name="provider" value="@provider.AuthenticationScheme" title="@L["GivenTenantIsNotAvailable", provider.DisplayName]">@provider.DisplayName</button>
<button type="submit" class="btn btn-primary m-1" name="provider" value="@provider.AuthenticationScheme" title="@L["LogInUsingYourProviderAccount", provider.DisplayName]">@provider.DisplayName</button>
}
</form>
</div>

9
modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/IAuditLogRepository.cs

@ -44,9 +44,10 @@ namespace Volo.Abp.AuditLogging
Task<Dictionary<DateTime, double>> GetAverageExecutionDurationPerDayAsync(
DateTime startDate,
DateTime endDate);
DateTime endDate,
CancellationToken cancellationToken = default);
Task<EntityChange> GetEntityChange(Guid entityChangeId);
Task<EntityChange> GetEntityChange(Guid entityChangeId, CancellationToken cancellationToken = default);
Task<List<EntityChange>> GetEntityChangeListAsync(
string sorting = null,
@ -70,8 +71,8 @@ namespace Volo.Abp.AuditLogging
string entityTypeFullName = null,
CancellationToken cancellationToken = default);
Task<EntityChangeWithUsername> GetEntityChangeWithUsernameAsync(Guid entityChangeId);
Task<EntityChangeWithUsername> GetEntityChangeWithUsernameAsync(Guid entityChangeId, CancellationToken cancellationToken = default);
Task<List<EntityChangeWithUsername>> GetEntityChangesWithUsernameAsync(string entityId, string entityTypeFullName);
Task<List<EntityChangeWithUsername>> GetEntityChangesWithUsernameAsync(string entityId, string entityTypeFullName, CancellationToken cancellationToken = default);
}
}

26
modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/EfCoreAuditLogRepository.cs

@ -125,14 +125,17 @@ namespace Volo.Abp.AuditLogging.EntityFrameworkCore
.WhereIf(minExecutionDuration != null && minExecutionDuration.Value > 0, auditLog => auditLog.ExecutionDuration >= minExecutionDuration);
}
public virtual async Task<Dictionary<DateTime, double>> GetAverageExecutionDurationPerDayAsync(DateTime startDate, DateTime endDate)
public virtual async Task<Dictionary<DateTime, double>> GetAverageExecutionDurationPerDayAsync(
DateTime startDate,
DateTime endDate,
CancellationToken cancellationToken = default)
{
var result = await (await GetDbSetAsync()).AsNoTracking()
.Where(a => a.ExecutionTime < endDate.AddDays(1) && a.ExecutionTime > startDate)
.OrderBy(t => t.ExecutionTime)
.GroupBy(t => new { t.ExecutionTime.Date })
.Select(g => new { Day = g.Min(t => t.ExecutionTime), avgExecutionTime = g.Average(t => t.ExecutionDuration) })
.ToListAsync();
.ToListAsync(GetCancellationToken(cancellationToken));
return result.ToDictionary(element => element.Day.ClearTime(), element => element.avgExecutionTime);
}
@ -148,14 +151,16 @@ namespace Volo.Abp.AuditLogging.EntityFrameworkCore
return (await GetQueryableAsync()).IncludeDetails();
}
public virtual async Task<EntityChange> GetEntityChange(Guid entityChangeId)
public virtual async Task<EntityChange> GetEntityChange(
Guid entityChangeId,
CancellationToken cancellationToken = default)
{
var entityChange = await (await GetDbContextAsync()).Set<EntityChange>()
.AsNoTracking()
.IncludeDetails()
.Where(x => x.Id == entityChangeId)
.OrderBy(x => x.Id)
.FirstOrDefaultAsync();
.FirstOrDefaultAsync(GetCancellationToken(cancellationToken));
if (entityChange == null)
{
@ -201,10 +206,12 @@ namespace Volo.Abp.AuditLogging.EntityFrameworkCore
return totalCount;
}
public virtual async Task<EntityChangeWithUsername> GetEntityChangeWithUsernameAsync(Guid entityChangeId)
public virtual async Task<EntityChangeWithUsername> GetEntityChangeWithUsernameAsync(
Guid entityChangeId,
CancellationToken cancellationToken = default)
{
var auditLog = await (await GetDbSetAsync()).AsNoTracking().IncludeDetails()
.Where(x => x.EntityChanges.Any(y => y.Id == entityChangeId)).FirstAsync();
.Where(x => x.EntityChanges.Any(y => y.Id == entityChangeId)).FirstAsync(GetCancellationToken(cancellationToken));
return new EntityChangeWithUsername()
{
@ -213,7 +220,10 @@ namespace Volo.Abp.AuditLogging.EntityFrameworkCore
};
}
public virtual async Task<List<EntityChangeWithUsername>> GetEntityChangesWithUsernameAsync(string entityId, string entityTypeFullName)
public virtual async Task<List<EntityChangeWithUsername>> GetEntityChangesWithUsernameAsync(
string entityId,
string entityTypeFullName,
CancellationToken cancellationToken = default)
{
var dbContext = await GetDbContextAsync();
@ -225,7 +235,7 @@ namespace Volo.Abp.AuditLogging.EntityFrameworkCore
return await (from e in query
join auditLog in dbContext.AuditLogs on e.AuditLogId equals auditLog.Id
select new EntityChangeWithUsername {EntityChange = e, UserName = auditLog.UserName})
.OrderByDescending(x => x.EntityChange.ChangeTime).ToListAsync();
.OrderByDescending(x => x.EntityChange.ChangeTime).ToListAsync(GetCancellationToken(cancellationToken));
}
protected virtual async Task<IQueryable<EntityChange>> GetEntityChangeListQueryAsync(

54
modules/audit-logging/src/Volo.Abp.AuditLogging.MongoDB/Volo/Abp/AuditLogging/MongoDB/MongoAuditLogRepository.cs

@ -52,7 +52,8 @@ namespace Volo.Abp.AuditLogging.MongoDB
minDuration,
hasException,
httpStatusCode,
includeDetails
includeDetails,
cancellationToken
);
return await query.OrderBy(sorting ?? "executionTime desc").As<IMongoQueryable<AuditLog>>()
@ -85,7 +86,8 @@ namespace Volo.Abp.AuditLogging.MongoDB
maxDuration,
minDuration,
hasException,
httpStatusCode
httpStatusCode,
cancellationToken: cancellationToken
);
var count = await query.As<IMongoQueryable<AuditLog>>()
@ -106,9 +108,10 @@ namespace Volo.Abp.AuditLogging.MongoDB
int? minDuration = null,
bool? hasException = null,
HttpStatusCode? httpStatusCode = null,
bool includeDetails = false)
bool includeDetails = false,
CancellationToken cancellationToken = default)
{
return (await GetMongoQueryableAsync())
return (await GetMongoQueryableAsync(cancellationToken))
.WhereIf(startTime.HasValue, auditLog => auditLog.ExecutionTime >= startTime)
.WhereIf(endTime.HasValue, auditLog => auditLog.ExecutionTime <= endTime)
.WhereIf(hasException.HasValue && hasException.Value, auditLog => auditLog.Exceptions != null && auditLog.Exceptions != "")
@ -124,9 +127,12 @@ namespace Volo.Abp.AuditLogging.MongoDB
}
public virtual async Task<Dictionary<DateTime, double>> GetAverageExecutionDurationPerDayAsync(DateTime startDate, DateTime endDate)
public virtual async Task<Dictionary<DateTime, double>> GetAverageExecutionDurationPerDayAsync(
DateTime startDate,
DateTime endDate,
CancellationToken cancellationToken = default)
{
var result = await (await GetMongoQueryableAsync())
var result = await (await GetMongoQueryableAsync(cancellationToken))
.Where(a => a.ExecutionTime < endDate.AddDays(1) && a.ExecutionTime > startDate)
.OrderBy(t => t.ExecutionTime)
.GroupBy(t => new
@ -136,17 +142,19 @@ namespace Volo.Abp.AuditLogging.MongoDB
t.ExecutionTime.Day
})
.Select(g => new { Day = g.Min(t => t.ExecutionTime), avgExecutionTime = g.Average(t => t.ExecutionDuration) })
.ToListAsync();
.ToListAsync(GetCancellationToken(cancellationToken));
return result.ToDictionary(element => element.Day.ClearTime(), element => element.avgExecutionTime);
}
public virtual async Task<EntityChange> GetEntityChange(Guid entityChangeId)
public virtual async Task<EntityChange> GetEntityChange(
Guid entityChangeId,
CancellationToken cancellationToken = default)
{
var entityChange = (await (await GetMongoQueryableAsync())
var entityChange = (await (await GetMongoQueryableAsync(cancellationToken))
.Where(x => x.EntityChanges.Any(y => y.Id == entityChangeId))
.OrderBy(x => x.Id)
.FirstAsync()).EntityChanges.FirstOrDefault(x => x.Id == entityChangeId);
.FirstAsync(GetCancellationToken(cancellationToken))).EntityChanges.FirstOrDefault(x => x.Id == entityChangeId);
if (entityChange == null)
{
@ -169,7 +177,7 @@ namespace Volo.Abp.AuditLogging.MongoDB
bool includeDetails = false,
CancellationToken cancellationToken = default)
{
var query = await GetEntityChangeListQueryAsync(auditLogId, startTime, endTime, changeType, entityId, entityTypeFullName);
var query = await GetEntityChangeListQueryAsync(auditLogId, startTime, endTime, changeType, entityId, entityTypeFullName, cancellationToken);
return await query
.OrderBy(sorting ?? "changeTime desc")
@ -187,18 +195,20 @@ namespace Volo.Abp.AuditLogging.MongoDB
string entityTypeFullName = null,
CancellationToken cancellationToken = default)
{
var query = await GetEntityChangeListQueryAsync(auditLogId, startTime, endTime, changeType, entityId, entityTypeFullName);
var query = await GetEntityChangeListQueryAsync(auditLogId, startTime, endTime, changeType, entityId, entityTypeFullName, cancellationToken);
var count = await query.As<IMongoQueryable<EntityChange>>().LongCountAsync(GetCancellationToken(cancellationToken));
return count;
}
public virtual async Task<EntityChangeWithUsername> GetEntityChangeWithUsernameAsync(Guid entityChangeId)
public virtual async Task<EntityChangeWithUsername> GetEntityChangeWithUsernameAsync(
Guid entityChangeId,
CancellationToken cancellationToken = default)
{
var auditLog = (await (await GetMongoQueryableAsync())
var auditLog = await (await GetMongoQueryableAsync(cancellationToken))
.Where(x => x.EntityChanges.Any(y => y.Id == entityChangeId))
.FirstAsync());
.FirstAsync(GetCancellationToken(cancellationToken));
return new EntityChangeWithUsername()
{
@ -207,13 +217,16 @@ namespace Volo.Abp.AuditLogging.MongoDB
};
}
public virtual async Task<List<EntityChangeWithUsername>> GetEntityChangesWithUsernameAsync(string entityId, string entityTypeFullName)
public virtual async Task<List<EntityChangeWithUsername>> GetEntityChangesWithUsernameAsync(
string entityId,
string entityTypeFullName,
CancellationToken cancellationToken = default)
{
var auditLogs = await (await GetMongoQueryableAsync())
var auditLogs = await (await GetMongoQueryableAsync(cancellationToken))
.Where(x => x.EntityChanges.Any(y => y.EntityId == entityId && y.EntityTypeFullName == entityTypeFullName))
.As<IMongoQueryable<AuditLog>>()
.OrderByDescending(x => x.ExecutionTime)
.ToListAsync();
.ToListAsync(GetCancellationToken(cancellationToken));
var entityChanges = auditLogs.SelectMany(x => x.EntityChanges).ToList();
@ -229,9 +242,10 @@ namespace Volo.Abp.AuditLogging.MongoDB
DateTime? endTime = null,
EntityChangeType? changeType = null,
string entityId = null,
string entityTypeFullName = null)
string entityTypeFullName = null,
CancellationToken cancellationToken = default)
{
return (await GetMongoQueryableAsync())
return (await GetMongoQueryableAsync(cancellationToken))
.SelectMany(x => x.EntityChanges)
.WhereIf(auditLogId.HasValue, e => e.Id == auditLogId)
.WhereIf(startTime.HasValue, e => e.ChangeTime >= startTime)

5
modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo/Abp/BackgroundJobs/IBackgroundJobRepository.cs

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
@ -7,6 +8,6 @@ namespace Volo.Abp.BackgroundJobs
{
public interface IBackgroundJobRepository : IBasicRepository<BackgroundJobRecord, Guid>
{
Task<List<BackgroundJobRecord>> GetWaitingListAsync(int maxResultCount);
Task<List<BackgroundJobRecord>> GetWaitingListAsync(int maxResultCount, CancellationToken cancellationToken = default);
}
}
}

7
modules/background-jobs/src/Volo.Abp.BackgroundJobs.EntityFrameworkCore/Volo/Abp/BackgroundJobs/EntityFrameworkCore/EfCoreBackgroundJobRepository.cs

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
@ -21,9 +22,11 @@ namespace Volo.Abp.BackgroundJobs.EntityFrameworkCore
Clock = clock;
}
public virtual async Task<List<BackgroundJobRecord>> GetWaitingListAsync(int maxResultCount)
public virtual async Task<List<BackgroundJobRecord>> GetWaitingListAsync(
int maxResultCount,
CancellationToken cancellationToken = default)
{
return await (await GetWaitingListQueryAsync(maxResultCount)).ToListAsync();
return await (await GetWaitingListQueryAsync(maxResultCount)).ToListAsync(GetCancellationToken(cancellationToken));
}
protected virtual async Task<IQueryable<BackgroundJobRecord>> GetWaitingListQueryAsync(int maxResultCount)

11
modules/background-jobs/src/Volo.Abp.BackgroundJobs.MongoDB/Volo/Abp/BackgroundJobs/MongoDB/MongoBackgroundJobRepository.cs

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using MongoDB.Driver;
using MongoDB.Driver.Linq;
@ -21,15 +22,17 @@ namespace Volo.Abp.BackgroundJobs.MongoDB
Clock = clock;
}
public virtual async Task<List<BackgroundJobRecord>> GetWaitingListAsync(int maxResultCount)
public virtual async Task<List<BackgroundJobRecord>> GetWaitingListAsync(
int maxResultCount,
CancellationToken cancellationToken = default)
{
return await (await GetWaitingListQuery(maxResultCount)).ToListAsync();
return await (await GetWaitingListQuery(maxResultCount)).ToListAsync(GetCancellationToken(cancellationToken));
}
protected virtual async Task<IMongoQueryable<BackgroundJobRecord>> GetWaitingListQuery(int maxResultCount)
protected virtual async Task<IMongoQueryable<BackgroundJobRecord>> GetWaitingListQuery(int maxResultCount, CancellationToken cancellationToken = default)
{
var now = Clock.Now;
return (await GetMongoQueryableAsync())
return (await GetMongoQueryableAsync(cancellationToken))
.Where(t => !t.IsAbandoned && t.NextTryTime <= now)
.OrderByDescending(t => t.Priority)
.ThenBy(t => t.TryCount)

3
modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Blogs/IBlogRepository.cs

@ -1,4 +1,5 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
@ -6,6 +7,6 @@ namespace Volo.Blogging.Blogs
{
public interface IBlogRepository : IBasicRepository<Blog, Guid>
{
Task<Blog> FindByShortNameAsync(string shortName);
Task<Blog> FindByShortNameAsync(string shortName, CancellationToken cancellationToken = default);
}
}

11
modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Comments/ICommentRepository.cs

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
@ -7,14 +8,12 @@ namespace Volo.Blogging.Comments
{
public interface ICommentRepository : IBasicRepository<Comment, Guid>
{
Task<List<Comment>> GetListOfPostAsync(
Guid postId
);
Task<List<Comment>> GetListOfPostAsync(Guid postId, CancellationToken cancellationToken = default);
Task<int> GetCommentCountOfPostAsync(Guid postId);
Task<int> GetCommentCountOfPostAsync(Guid postId, CancellationToken cancellationToken = default);
Task<List<Comment>> GetRepliesOfComment(Guid id);
Task<List<Comment>> GetRepliesOfComment(Guid id, CancellationToken cancellationToken = default);
Task DeleteOfPost(Guid id);
Task DeleteOfPost(Guid id, CancellationToken cancellationToken = default);
}
}

9
modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/IPostRepository.cs

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
@ -7,12 +8,12 @@ namespace Volo.Blogging.Posts
{
public interface IPostRepository : IBasicRepository<Post, Guid>
{
Task<List<Post>> GetPostsByBlogId(Guid id);
Task<List<Post>> GetPostsByBlogId(Guid id, CancellationToken cancellationToken = default);
Task<bool> IsPostUrlInUseAsync(Guid blogId, string url, Guid? excludingPostId = null);
Task<bool> IsPostUrlInUseAsync(Guid blogId, string url, Guid? excludingPostId = null, CancellationToken cancellationToken = default);
Task<Post> GetPostByUrl(Guid blogId, string url);
Task<Post> GetPostByUrl(Guid blogId, string url, CancellationToken cancellationToken = default);
Task<List<Post>> GetOrderedList(Guid blogId,bool descending = false);
Task<List<Post>> GetOrderedList(Guid blogId,bool descending = false, CancellationToken cancellationToken = default);
}
}

8
modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Tagging/ITagRepository.cs

@ -8,13 +8,13 @@ namespace Volo.Blogging.Tagging
{
public interface ITagRepository : IBasicRepository<Tag, Guid>
{
Task<List<Tag>> GetListAsync(Guid blogId);
Task<List<Tag>> GetListAsync(Guid blogId, CancellationToken cancellationToken = default);
Task<Tag> GetByNameAsync(Guid blogId, string name);
Task<Tag> GetByNameAsync(Guid blogId, string name, CancellationToken cancellationToken = default);
Task<Tag> FindByNameAsync(Guid blogId, string name);
Task<Tag> FindByNameAsync(Guid blogId, string name, CancellationToken cancellationToken = default);
Task<List<Tag>> GetListAsync(IEnumerable<Guid> ids);
Task<List<Tag>> GetListAsync(IEnumerable<Guid> ids, CancellationToken cancellationToken = default);
Task DecreaseUsageCountOfTagsAsync(List<Guid> id, CancellationToken cancellationToken = default);
}

5
modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Blogs/EfCoreBlogRepository.cs

@ -1,4 +1,5 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
@ -15,9 +16,9 @@ namespace Volo.Blogging.Blogs
}
public async Task<Blog> FindByShortNameAsync(string shortName)
public async Task<Blog> FindByShortNameAsync(string shortName, CancellationToken cancellationToken = default)
{
return await (await GetDbSetAsync()).FirstOrDefaultAsync(p => p.ShortName == shortName);
return await (await GetDbSetAsync()).FirstOrDefaultAsync(p => p.ShortName == shortName, GetCancellationToken(cancellationToken));
}
}
}

17
modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Comments/EfCoreCommentRepository.cs

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
@ -16,29 +17,29 @@ namespace Volo.Blogging.Comments
{
}
public async Task<List<Comment>> GetListOfPostAsync(Guid postId)
public async Task<List<Comment>> GetListOfPostAsync(Guid postId, CancellationToken cancellationToken = default)
{
return await (await GetDbSetAsync())
.Where(a => a.PostId == postId)
.OrderBy(a => a.CreationTime)
.ToListAsync();
.ToListAsync(GetCancellationToken(cancellationToken));
}
public async Task<int> GetCommentCountOfPostAsync(Guid postId)
public async Task<int> GetCommentCountOfPostAsync(Guid postId, CancellationToken cancellationToken = default)
{
return await (await GetDbSetAsync())
.CountAsync(a => a.PostId == postId);
.CountAsync(a => a.PostId == postId, GetCancellationToken(cancellationToken));
}
public async Task<List<Comment>> GetRepliesOfComment(Guid id)
public async Task<List<Comment>> GetRepliesOfComment(Guid id, CancellationToken cancellationToken = default)
{
return await (await GetDbSetAsync())
.Where(a => a.RepliedCommentId == id).ToListAsync();
.Where(a => a.RepliedCommentId == id).ToListAsync(GetCancellationToken(cancellationToken));
}
public async Task DeleteOfPost(Guid id)
public async Task DeleteOfPost(Guid id, CancellationToken cancellationToken = default)
{
var recordsToDelete = (await GetDbSetAsync()).Where(pt => pt.PostId == id);
var recordsToDelete = await (await GetDbSetAsync()).Where(pt => pt.PostId == id).ToListAsync(GetCancellationToken(cancellationToken));
(await GetDbSetAsync()).RemoveRange(recordsToDelete);
}
}

19
modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Posts/EfCorePostRepository.cs

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Domain.Entities;
@ -18,12 +19,12 @@ namespace Volo.Blogging.Posts
}
public async Task<List<Post>> GetPostsByBlogId(Guid id)
public async Task<List<Post>> GetPostsByBlogId(Guid id, CancellationToken cancellationToken = default)
{
return await (await GetDbSetAsync()).Where(p => p.BlogId == id).OrderByDescending(p=>p.CreationTime).ToListAsync();
return await (await GetDbSetAsync()).Where(p => p.BlogId == id).OrderByDescending(p=>p.CreationTime).ToListAsync(GetCancellationToken(cancellationToken));
}
public async Task<bool> IsPostUrlInUseAsync(Guid blogId, string url, Guid? excludingPostId = null)
public async Task<bool> IsPostUrlInUseAsync(Guid blogId, string url, Guid? excludingPostId = null, CancellationToken cancellationToken = default)
{
var query = (await GetDbSetAsync()).Where(p => blogId == p.BlogId && p.Url == url);
@ -32,12 +33,12 @@ namespace Volo.Blogging.Posts
query = query.Where(p => excludingPostId != p.Id);
}
return await query.AnyAsync();
return await query.AnyAsync(GetCancellationToken(cancellationToken));
}
public async Task<Post> GetPostByUrl(Guid blogId, string url)
public async Task<Post> GetPostByUrl(Guid blogId, string url, CancellationToken cancellationToken = default)
{
var post = await (await GetDbSetAsync()).FirstOrDefaultAsync(p => p.BlogId == blogId && p.Url == url);
var post = await (await GetDbSetAsync()).FirstOrDefaultAsync(p => p.BlogId == blogId && p.Url == url, GetCancellationToken(cancellationToken));
if (post == null)
{
@ -47,15 +48,15 @@ namespace Volo.Blogging.Posts
return post;
}
public async Task<List<Post>> GetOrderedList(Guid blogId,bool descending = false)
public async Task<List<Post>> GetOrderedList(Guid blogId,bool descending = false, CancellationToken cancellationToken = default)
{
if (!descending)
{
return await (await GetDbSetAsync()).Where(x=>x.BlogId==blogId).OrderByDescending(x => x.CreationTime).ToListAsync();
return await (await GetDbSetAsync()).Where(x=>x.BlogId==blogId).OrderByDescending(x => x.CreationTime).ToListAsync(GetCancellationToken(cancellationToken));
}
else
{
return await (await GetDbSetAsync()).Where(x => x.BlogId == blogId).OrderBy(x => x.CreationTime).ToListAsync();
return await (await GetDbSetAsync()).Where(x => x.BlogId == blogId).OrderBy(x => x.CreationTime).ToListAsync(GetCancellationToken(cancellationToken));
}
}

16
modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Tagging/EfCoreTagRepository.cs

@ -17,24 +17,24 @@ namespace Volo.Blogging.Tagging
{
}
public async Task<List<Tag>> GetListAsync(Guid blogId)
public async Task<List<Tag>> GetListAsync(Guid blogId, CancellationToken cancellationToken = default)
{
return await (await GetDbSetAsync()).Where(t=>t.BlogId == blogId).ToListAsync();
return await (await GetDbSetAsync()).Where(t=>t.BlogId == blogId).ToListAsync(GetCancellationToken(cancellationToken));
}
public async Task<Tag> GetByNameAsync(Guid blogId, string name)
public async Task<Tag> GetByNameAsync(Guid blogId, string name, CancellationToken cancellationToken = default)
{
return await (await GetDbSetAsync()).FirstAsync(t=> t.BlogId == blogId && t.Name == name);
return await (await GetDbSetAsync()).FirstAsync(t=> t.BlogId == blogId && t.Name == name, GetCancellationToken(cancellationToken));
}
public async Task<Tag> FindByNameAsync(Guid blogId, string name)
public async Task<Tag> FindByNameAsync(Guid blogId, string name, CancellationToken cancellationToken = default)
{
return await (await GetDbSetAsync()).FirstOrDefaultAsync(t => t.BlogId == blogId && t.Name == name);
return await (await GetDbSetAsync()).FirstOrDefaultAsync(t => t.BlogId == blogId && t.Name == name, GetCancellationToken(cancellationToken));
}
public async Task<List<Tag>> GetListAsync(IEnumerable<Guid> ids)
public async Task<List<Tag>> GetListAsync(IEnumerable<Guid> ids, CancellationToken cancellationToken = default)
{
return await (await GetDbSetAsync()).Where(t => ids.Contains(t.Id)).ToListAsync();
return await (await GetDbSetAsync()).Where(t => ids.Contains(t.Id)).ToListAsync(GetCancellationToken(cancellationToken));
}
public async Task DecreaseUsageCountOfTagsAsync(List<Guid> ids, CancellationToken cancellationToken = default)

5
modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Blogs/MongoBlogRepository.cs

@ -1,4 +1,5 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using MongoDB.Driver.Linq;
using Volo.Abp.Domain.Repositories.MongoDB;
@ -13,9 +14,9 @@ namespace Volo.Blogging.Blogs
{
}
public async Task<Blog> FindByShortNameAsync(string shortName)
public async Task<Blog> FindByShortNameAsync(string shortName, CancellationToken cancellationToken = default)
{
return await (await GetMongoQueryableAsync()).FirstOrDefaultAsync(p => p.ShortName == shortName);
return await (await GetMongoQueryableAsync(cancellationToken)).FirstOrDefaultAsync(p => p.ShortName == shortName, GetCancellationToken(cancellationToken));
}
}
}

25
modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Comments/MongoCommentRepository.cs

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using MongoDB.Driver;
using MongoDB.Driver.Linq;
@ -15,33 +16,33 @@ namespace Volo.Blogging.Comments
{
}
public async Task<List<Comment>> GetListOfPostAsync(Guid postId)
public async Task<List<Comment>> GetListOfPostAsync(Guid postId, CancellationToken cancellationToken = default)
{
return await (await GetMongoQueryableAsync())
return await (await GetMongoQueryableAsync(cancellationToken))
.Where(a => a.PostId == postId)
.OrderBy(a => a.CreationTime)
.ToListAsync();
.ToListAsync(GetCancellationToken(cancellationToken));
}
public async Task<int> GetCommentCountOfPostAsync(Guid postId)
public async Task<int> GetCommentCountOfPostAsync(Guid postId, CancellationToken cancellationToken = default)
{
return await (await GetMongoQueryableAsync())
.CountAsync(a => a.PostId == postId);
return await (await GetMongoQueryableAsync(cancellationToken))
.CountAsync(a => a.PostId == postId, GetCancellationToken(cancellationToken));
}
public async Task<List<Comment>> GetRepliesOfComment(Guid id)
public async Task<List<Comment>> GetRepliesOfComment(Guid id, CancellationToken cancellationToken = default)
{
return await (await GetMongoQueryableAsync())
.Where(a => a.RepliedCommentId == id).ToListAsync();
return await (await GetMongoQueryableAsync(cancellationToken))
.Where(a => a.RepliedCommentId == id).ToListAsync(GetCancellationToken(cancellationToken));
}
public async Task DeleteOfPost(Guid id)
public async Task DeleteOfPost(Guid id, CancellationToken cancellationToken = default)
{
var recordsToDelete = (await GetMongoQueryableAsync()).Where(pt => pt.PostId == id);
var recordsToDelete = (await GetMongoQueryableAsync(cancellationToken)).Where(pt => pt.PostId == id);
foreach (var record in recordsToDelete)
{
await DeleteAsync(record);
await DeleteAsync(record, cancellationToken: GetCancellationToken(cancellationToken));
}
}
}

23
modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Posts/MongoPostRepository.cs

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using MongoDB.Driver;
using MongoDB.Driver.Linq;
@ -16,27 +17,27 @@ namespace Volo.Blogging.Posts
{
}
public async Task<List<Post>> GetPostsByBlogId(Guid id)
public async Task<List<Post>> GetPostsByBlogId(Guid id, CancellationToken cancellationToken = default)
{
return await (await GetMongoQueryableAsync()).Where(p => p.BlogId == id).OrderByDescending(p => p.CreationTime).ToListAsync();
return await (await GetMongoQueryableAsync(cancellationToken)).Where(p => p.BlogId == id).OrderByDescending(p => p.CreationTime).ToListAsync(GetCancellationToken(cancellationToken));
}
public async Task<bool> IsPostUrlInUseAsync(Guid blogId, string url, Guid? excludingPostId = null)
public async Task<bool> IsPostUrlInUseAsync(Guid blogId, string url, Guid? excludingPostId = null, CancellationToken cancellationToken = default)
{
var query = (await GetMongoQueryableAsync()).Where(p => blogId == p.BlogId && p.Url == url);
var query = (await GetMongoQueryableAsync(cancellationToken)).Where(p => blogId == p.BlogId && p.Url == url);
if (excludingPostId != null)
{
query = query.Where(p => excludingPostId != p.Id);
}
return await query.AnyAsync();
return await query.AnyAsync(GetCancellationToken(cancellationToken));
}
public async Task<Post> GetPostByUrl(Guid blogId, string url)
public async Task<Post> GetPostByUrl(Guid blogId, string url, CancellationToken cancellationToken = default)
{
var post = await (await GetMongoQueryableAsync()).FirstOrDefaultAsync(p => p.BlogId == blogId && p.Url == url);
var post = await (await GetMongoQueryableAsync(cancellationToken)).FirstOrDefaultAsync(p => p.BlogId == blogId && p.Url == url, GetCancellationToken(cancellationToken));
if (post == null)
{
@ -46,16 +47,16 @@ namespace Volo.Blogging.Posts
return post;
}
public async Task<List<Post>> GetOrderedList(Guid blogId, bool @descending = false)
public async Task<List<Post>> GetOrderedList(Guid blogId, bool @descending = false, CancellationToken cancellationToken = default)
{
var query = (await GetMongoQueryableAsync()).Where(x => x.BlogId == blogId);
var query = (await GetMongoQueryableAsync(cancellationToken)).Where(x => x.BlogId == blogId);
if (!descending)
{
return await query.OrderBy(x => x.CreationTime).ToListAsync();
return await query.OrderBy(x => x.CreationTime).ToListAsync(GetCancellationToken(cancellationToken));
}
return await query.OrderByDescending(x => x.CreationTime).ToListAsync();
return await query.OrderByDescending(x => x.CreationTime).ToListAsync(GetCancellationToken(cancellationToken));
}
}
}

18
modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Tagging/MongoTagRepository.cs

@ -18,29 +18,29 @@ namespace Volo.Blogging.Tagging
{
}
public async Task<List<Tag>> GetListAsync(Guid blogId)
public async Task<List<Tag>> GetListAsync(Guid blogId, CancellationToken cancellationToken = default)
{
return await (await GetMongoQueryableAsync()).Where(t => t.BlogId == blogId).ToListAsync();
return await (await GetMongoQueryableAsync(cancellationToken)).Where(t => t.BlogId == blogId).ToListAsync(GetCancellationToken(cancellationToken));
}
public async Task<Tag> GetByNameAsync(Guid blogId, string name)
public async Task<Tag> GetByNameAsync(Guid blogId, string name, CancellationToken cancellationToken = default)
{
return await (await GetMongoQueryableAsync()).Where(t => t.BlogId == blogId && t.Name == name).FirstAsync();
return await (await GetMongoQueryableAsync(cancellationToken)).Where(t => t.BlogId == blogId && t.Name == name).FirstAsync(GetCancellationToken(cancellationToken));
}
public async Task<Tag> FindByNameAsync(Guid blogId, string name)
public async Task<Tag> FindByNameAsync(Guid blogId, string name, CancellationToken cancellationToken = default)
{
return await (await GetMongoQueryableAsync()).Where(t => t.BlogId == blogId && t.Name == name).FirstOrDefaultAsync();
return await (await GetMongoQueryableAsync(cancellationToken)).Where(t => t.BlogId == blogId && t.Name == name).FirstOrDefaultAsync(GetCancellationToken(cancellationToken));
}
public async Task<List<Tag>> GetListAsync(IEnumerable<Guid> ids)
public async Task<List<Tag>> GetListAsync(IEnumerable<Guid> ids, CancellationToken cancellationToken = default)
{
return await (await GetMongoQueryableAsync()).Where(t => ids.Contains(t.Id)).ToListAsync();
return await (await GetMongoQueryableAsync(cancellationToken)).Where(t => ids.Contains(t.Id)).ToListAsync(GetCancellationToken(cancellationToken));
}
public async Task DecreaseUsageCountOfTagsAsync(List<Guid> ids, CancellationToken cancellationToken = default)
{
var tags = await (await GetMongoQueryableAsync())
var tags = await (await GetMongoQueryableAsync(cancellationToken))
.Where(t => ids.Contains(t.Id))
.ToListAsync(GetCancellationToken(cancellationToken));

4
modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Users/MongoBlogUserRepository.cs

@ -15,7 +15,7 @@ namespace Volo.Blogging.Users
{
}
public async Task<List<BlogUser>> GetUsersAsync(int maxCount, string filter, CancellationToken cancellationToken)
public async Task<List<BlogUser>> GetUsersAsync(int maxCount, string filter, CancellationToken cancellationToken = default)
{
var query = await GetMongoQueryableAsync(cancellationToken);
@ -24,7 +24,7 @@ namespace Volo.Blogging.Users
query = query.Where(x => x.UserName.Contains(filter));
}
return await query.Take(maxCount).ToListAsync(cancellationToken);
return await query.Take(maxCount).ToListAsync(GetCancellationToken(cancellationToken));
}
}
}

12
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Contents/ContentGetListDto.cs

@ -0,0 +1,12 @@
using System;
using Volo.Abp.Application.Dtos;
namespace Volo.CmsKit.Admin.Contents
{
public class ContentGetListDto : EntityDto<Guid>
{
public string EntityType { get; set; }
public string EntityId { get; set; }
}
}

1
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Contents/IContentAdminAppService.cs

@ -7,6 +7,7 @@ namespace Volo.CmsKit.Admin.Contents
public interface IContentAdminAppService
: ICrudAppService<
ContentDto,
ContentGetListDto,
Guid,
ContentGetListInput,
ContentCreateDto,

16
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Tags/EntityTagCreateDto.cs

@ -0,0 +1,16 @@
using System.ComponentModel.DataAnnotations;
namespace Volo.CmsKit.Admin.Tags
{
public class EntityTagCreateDto
{
[Required]
public string TagName { get; set; }
[Required]
public string EntityType { get; set; }
[Required]
public string EntityId { get; set; }
}
}

17
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Tags/EntityTagRemoveDto.cs

@ -0,0 +1,17 @@
using System;
using System.ComponentModel.DataAnnotations;
namespace Volo.CmsKit.Admin.Tags
{
public class EntityTagRemoveDto
{
[Required]
public Guid TagId { get; set; }
[Required]
public string EntityType { get; set; }
[Required]
public string EntityId { get; set; }
}
}

11
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Tags/IEntityTagAdminAppService.cs

@ -0,0 +1,11 @@
using System.Threading.Tasks;
namespace Volo.CmsKit.Admin.Tags
{
public interface IEntityTagAdminAppService
{
Task AddTagToEntityAsync(EntityTagCreateDto input);
Task RemoveTagFromEntityAsync(EntityTagRemoveDto input);
}
}

3
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Tags/ITagAdminAppService.cs

@ -1,4 +1,6 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
using Volo.CmsKit.Tags;
@ -6,5 +8,6 @@ namespace Volo.CmsKit.Admin.Tags
{
public interface ITagAdminAppService : ICrudAppService<TagDto, Guid, TagGetListInput, TagCreateDto, TagUpdateDto>
{
Task<List<TagDefinitionDto>> GetTagDefinitionsAsync();
}
}

18
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Tags/TagDefinitionDto.cs

@ -0,0 +1,18 @@
namespace Volo.CmsKit.Admin.Tags
{
public class TagDefinitionDto
{
public TagDefinitionDto()
{
}
public TagDefinitionDto(string entityType, string displayName)
{
EntityType = entityType;
DisplayName = displayName;
}
public string EntityType { get; set; }
public string DisplayName { get; set; }
}
}

5
modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/CmsKitAdminApplicationAutoMapperProfile.cs

@ -1,8 +1,10 @@
using AutoMapper;
using Volo.CmsKit.Admin.Contents;
using Volo.CmsKit.Admin.Pages;
using Volo.CmsKit.Admin.Tags;
using Volo.CmsKit.Contents;
using Volo.CmsKit.Pages;
using Volo.CmsKit.Tags;
namespace Volo.CmsKit.Admin
{
@ -13,8 +15,11 @@ namespace Volo.CmsKit.Admin
CreateMap<Page, PageDto>();
CreateMap<Content, ContentDto>(MemberList.Destination);
CreateMap<Content, ContentGetListDto>(MemberList.Destination);
CreateMap<ContentCreateDto, Content>(MemberList.Source);
CreateMap<ContentUpdateDto, Content>(MemberList.Source);
CreateMap<TagEntityTypeDefiniton, TagDefinitionDto>(MemberList.Destination);
}
}
}

3
modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Contents/ContentAdminAppService.cs

@ -14,6 +14,7 @@ namespace Volo.CmsKit.Admin.Contents
CrudAppService<
Content,
ContentDto,
ContentGetListDto,
Guid,
ContentGetListInput,
ContentCreateDto,
@ -51,7 +52,7 @@ namespace Volo.CmsKit.Admin.Contents
await ContentManager.InsertAsync(entity);
return MapToGetListOutputDto(entity);
return MapToGetOutputDto(entity);
}
}
}

1
modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Pages/PageAdminAppService.cs

@ -24,7 +24,6 @@ namespace Volo.CmsKit.Admin.Pages
public virtual async Task<PageDto> GetAsync(Guid id)
{
var page = await PageRepository.GetAsync(id);
return ObjectMapper.Map<Page, PageDto>(page);
}

52
modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Tags/EntityTagAdminAppService.cs

@ -0,0 +1,52 @@
using System;
using System.Threading.Tasks;
using Volo.CmsKit.Admin.Tags;
using Volo.CmsKit.Tags;
namespace Volo.CmsKit.Admin.Application.Volo.CmsKit.Admin.Tags
{
public class EntityTagAdminAppService : CmsKitAdminAppServiceBase, IEntityTagAdminAppService
{
protected ITagDefinitionStore _tagDefinitionStore;
protected IEntityTagManager _entityTagManager;
protected ITagManager _tagManager;
public EntityTagAdminAppService(
ITagDefinitionStore tagDefinitionStore,
IEntityTagManager entityTagManager,
ITagManager tagManager)
{
_tagDefinitionStore = tagDefinitionStore;
_entityTagManager = entityTagManager;
_tagManager = tagManager;
}
public async Task AddTagToEntityAsync(EntityTagCreateDto input)
{
var definition = await _tagDefinitionStore.GetTagEntityTypeDefinitionsAsync(input.EntityType);
await CheckPolicyAsync(definition.CreatePolicy);
var tag = await _tagManager.GetOrAddAsync(input.EntityType, input.TagName, CurrentTenant?.Id);
await _entityTagManager.AddTagToEntityAsync(
tag.Id,
input.EntityType,
input.EntityId,
CurrentTenant?.Id);
}
public async Task RemoveTagFromEntityAsync(EntityTagRemoveDto input)
{
var definition = await _tagDefinitionStore.GetTagEntityTypeDefinitionsAsync(input.EntityType);
await CheckPolicyAsync(definition.DeletePolicy);
await _entityTagManager.RemoveTagFromEntityAsync(
input.TagId,
input.EntityType,
input.EntityId,
CurrentTenant?.Id);
}
}
}

19
modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Tags/TagAdminAppService.cs

@ -1,12 +1,11 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Localization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;
using Volo.CmsKit.Admin.Tags;
using Volo.CmsKit.Permissions;
using Volo.CmsKit.Tags;
@ -25,11 +24,15 @@ namespace Volo.CmsKit.Admin.Tags
{
protected ITagManager TagManager { get; }
protected IStringLocalizerFactory StringLocalizerFactory { get; }
public TagAdminAppService(
IRepository<Tag, Guid> repository,
ITagManager tagManager) : base(repository)
ITagManager tagManager,
IStringLocalizerFactory stringLocalizerFactory) : base(repository)
{
TagManager = tagManager;
StringLocalizerFactory = stringLocalizerFactory;
GetListPolicyName = CmsKitAdminPermissions.Tags.Default;
GetPolicyName = CmsKitAdminPermissions.Tags.Default;
@ -68,5 +71,15 @@ namespace Volo.CmsKit.Admin.Tags
x.Name.ToLower().Contains(input.Filter) ||
x.EntityType.ToLower().Contains(input.Filter));
}
public async Task<List<TagDefinitionDto>> GetTagDefinitionsAsync()
{
var definitions = await TagManager.GetTagDefinitionsAsync();
return definitions
.Select(s =>
new TagDefinitionDto(s.EntityType, s.DisplayName.Localize(StringLocalizerFactory)))
.ToList();
}
}
}

2
modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Contents/ContentAdminController.cs

@ -48,7 +48,7 @@ namespace Volo.CmsKit.Admin.Contents
[HttpGet]
[Authorize(CmsKitAdminPermissions.Contents.Default)]
public Task<PagedResultDto<ContentDto>> GetListAsync(ContentGetListInput input)
public Task<PagedResultDto<ContentGetListDto>> GetListAsync(ContentGetListInput input)
{
return ContentAdminAppService.GetListAsync(input);
}

6
modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Tags/TagAdminController.cs

@ -1,6 +1,7 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
@ -60,5 +61,10 @@ namespace Volo.CmsKit.Admin.Tags
{
return TagAdminAppService.UpdateAsync(id, input);
}
public Task<List<TagDefinitionDto>> GetTagDefinitionsAsync()
{
return TagAdminAppService.GetTagDefinitionsAsync();
}
}
}

10
modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/CmsKitErrorCodes.cs

@ -2,10 +2,14 @@
{
public static class CmsKitErrorCodes
{
public const string TagAlreadyExist = "CmsKit:0001";
public static class Tags
{
public const string TagAlreadyExist = "CmsKit:Tag:0001";
public const string EntityNotTaggable = "CmsKit:Tag:0002";
}
public const string ContentAlreadyExist = "CmsKit:0002";
public static class Pages
{
public const string UrlAlreadyExist = "CmsKit:Page:0001";

1
modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/en.json

@ -2,6 +2,7 @@
"culture": "en",
"texts": {
"CmsKit:0002": "Content already exists!",
"CmsKit:0003": "The entity {0} is not taggable.",
"CommentAuthorizationExceptionMessage": "Those comments are not allowed for public display.",
"Comments": "Comments",
"Delete": "Delete",

1
modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/tr.json

@ -2,6 +2,7 @@
"culture": "tr",
"texts": {
"CmsKit:0002": "İçerik zaten mevcut!",
"CmsKit:0003": "{0} ögesi etiketlenebilir değil.",
"CommentAuthorizationExceptionMessage": "Bu yorumları görebilmek için yetki gerekir.",
"Comments": "Yorumlar",
"Delete": "Sil",

22
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/CmsKitDomainModule.cs

@ -1,7 +1,14 @@
using Volo.Abp.Domain;
using Microsoft.Extensions.Options;
using Volo.Abp.Domain;
using Volo.Abp.GlobalFeatures;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.Users;
using Volo.CmsKit.GlobalFeatures;
using Volo.CmsKit.Localization;
using Volo.CmsKit.Pages;
using Volo.CmsKit.Reactions;
using Volo.CmsKit.Tags;
namespace Volo.CmsKit
{
@ -28,7 +35,18 @@ namespace Volo.CmsKit
options.Reactions.AddOrReplace(StandardReactions.HeartBroken);
options.Reactions.AddOrReplace(StandardReactions.Rocket);
options.Reactions.AddOrReplace(StandardReactions.Pray);
});
if (GlobalFeatureManager.Instance.IsEnabled<TagsFeature>())
{
// TODO: Configure TagEntityTypes here...
}
}
private static LocalizableString L(string name)
{
return LocalizableString.Create<CmsKitResource>(name);
}
}
}
}

8
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/CmsKitOptions.cs

@ -1,16 +1,12 @@
using JetBrains.Annotations;
using Volo.CmsKit.Reactions;
using Volo.CmsKit.Tags;
namespace Volo.CmsKit
{
public class CmsKitOptions
{
[NotNull]
public ReactionDefinitionDictionary Reactions { get; }
public CmsKitOptions()
{
Reactions = new ReactionDefinitionDictionary();
}
public ReactionDefinitionDictionary Reactions { get; } = new ReactionDefinitionDictionary();
}
}

32
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/PolicySpecifiedDefinition.cs

@ -0,0 +1,32 @@
using JetBrains.Annotations;
using Volo.Abp;
using Volo.Abp.Localization;
namespace Volo.CmsKit.Domain.Volo.CmsKit
{
public abstract class PolicySpecifiedDefinition
{
protected PolicySpecifiedDefinition()
{
}
public PolicySpecifiedDefinition(
[CanBeNull] string createPolicy = null,
[CanBeNull] string updatePolicy = null,
[CanBeNull] string deletePolicy = null)
{
CreatePolicy = createPolicy;
DeletePolicy = deletePolicy;
UpdatePolicy = updatePolicy;
}
[CanBeNull]
public virtual string CreatePolicy { get; set; }
[CanBeNull]
public virtual string UpdatePolicy { get; set; }
[CanBeNull]
public virtual string DeletePolicy { get; set; }
}
}

11
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/CmsKitTagOptions.cs

@ -0,0 +1,11 @@
using JetBrains.Annotations;
using Volo.CmsKit.Tags;
namespace Volo.CmsKit.Tags
{
public class CmsKitTagOptions
{
[NotNull]
public TagEntityTypeDefinitionDictionary EntityTypes { get; } = new TagEntityTypeDefinitionDictionary();
}
}

40
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/DefaultTagDefinitionStore.cs

@ -0,0 +1,40 @@
using JetBrains.Annotations;
using Microsoft.Extensions.Options;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.DependencyInjection;
namespace Volo.CmsKit.Tags
{
public class DefaultTagDefinitionStore : ITagDefinitionStore, ITransientDependency
{
private readonly CmsKitTagOptions options;
public DefaultTagDefinitionStore(IOptions<CmsKitTagOptions> options)
{
this.options = options.Value;
}
public virtual Task<TagEntityTypeDefiniton> GetTagEntityTypeDefinitionsAsync([NotNull] string entityType)
{
Check.NotNullOrWhiteSpace(entityType, nameof(entityType));
var result = options.EntityTypes.GetOrDefault(entityType) ?? throw new EntityNotTaggableException(entityType);
return Task.FromResult(result);
}
public virtual Task<List<TagEntityTypeDefiniton>> GetTagDefinitionsAsync()
{
return Task.FromResult(options.EntityTypes.Values.ToList());
}
public virtual Task<bool> IsDefinedAsync([NotNull] string entityType)
{
Check.NotNullOrWhiteSpace(entityType, nameof(entityType));
return Task.FromResult(options.EntityTypes.ContainsKey(entityType));
}
}
}

26
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/EntityNotTaggableException.cs

@ -0,0 +1,26 @@
using Microsoft.Extensions.Logging;
using System;
using Volo.Abp;
namespace Volo.CmsKit.Tags
{
[Serializable]
public class EntityNotTaggableException : BusinessException
{
public EntityNotTaggableException(
string code = null,
string message = null,
string details = null,
Exception innerException = null,
LogLevel logLevel = LogLevel.Warning)
: base(code, message, details, innerException, logLevel)
{
}
public EntityNotTaggableException(string entityType)
{
Code = CmsKitErrorCodes.Tags.EntityNotTaggable;
WithData(nameof(Tag.EntityType), entityType);
}
}
}

3
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/EntityTag.cs

@ -16,7 +16,7 @@ namespace Volo.CmsKit.Tags
{
}
public EntityTag(Guid tagId, string entityId, Guid? tenantId = null)
internal EntityTag(Guid tagId, string entityId, Guid? tenantId = null)
{
TagId = tagId;
EntityId = entityId;
@ -27,6 +27,5 @@ namespace Volo.CmsKit.Tags
{
return new object[] { TagId, EntityId };
}
}
}

52
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/EntityTagManager.cs

@ -0,0 +1,52 @@
using JetBrains.Annotations;
using System;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Services;
using Volo.CmsKit.Tags;
namespace Volo.CmsKit.Tags
{
public class EntityTagManager : DomainService, IEntityTagManager
{
protected readonly IEntityTagRepository _entityTagRepository;
protected readonly ITagDefinitionStore _tagDefinitionStore;
public EntityTagManager(
IEntityTagRepository entityTagRepository,
ITagDefinitionStore tagDefinitionStore)
{
_entityTagRepository = entityTagRepository;
_tagDefinitionStore = tagDefinitionStore;
}
public async Task<EntityTag> AddTagToEntityAsync(
[NotNull] Guid tagId,
[NotNull] string entityType,
[NotNull] string entityId,
[CanBeNull] Guid? tenantId = null,
CancellationToken cancellationToken = default)
{
if (!await _tagDefinitionStore.IsDefinedAsync(entityType))
{
throw new EntityNotTaggableException(entityType);
}
var entityTag = new EntityTag(tagId, entityId, tenantId);
return await _entityTagRepository.InsertAsync(entityTag, cancellationToken: cancellationToken);
}
public async Task RemoveTagFromEntityAsync(
[NotNull] Guid tagId,
[NotNull] string entityType,
[NotNull] string entityId,
[CanBeNull] Guid? tenantId = null,
CancellationToken cancellationToken = default)
{
var entityTag = await _entityTagRepository.FindAsync(tagId, entityId, tenantId, cancellationToken);
await _entityTagRepository.DeleteAsync(entityTag);
}
}
}

24
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/IEntityTagManager.cs

@ -0,0 +1,24 @@
using JetBrains.Annotations;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Volo.CmsKit.Tags
{
public interface IEntityTagManager
{
Task<EntityTag> AddTagToEntityAsync(
[NotNull] Guid tagId,
[NotNull] string entityType,
[NotNull] string entityId,
[CanBeNull] Guid? tenantId = null,
CancellationToken cancellationToken = default);
Task RemoveTagFromEntityAsync(
[NotNull] Guid tagId,
[NotNull] string entityType,
[NotNull] string entityId,
[CanBeNull] Guid? tenantId = null,
CancellationToken cancellationToken = default);
}
}

12
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/IEntityTagRepository.cs

@ -1,9 +1,17 @@
using Volo.Abp.Domain.Repositories;
using JetBrains.Annotations;
using System;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
namespace Volo.CmsKit.Tags
{
public interface IEntityTagRepository : IBasicRepository<EntityTag>
{
Task<EntityTag> FindAsync(
[NotNull] Guid tagId,
[NotNull] string entityId,
[CanBeNull] Guid? tenantId,
CancellationToken cancellationToken = default);
}
}

15
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/ITagDefinitionStore.cs

@ -0,0 +1,15 @@
using JetBrains.Annotations;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Volo.CmsKit.Tags
{
public interface ITagDefinitionStore
{
Task<List<TagEntityTypeDefiniton>> GetTagDefinitionsAsync();
Task<TagEntityTypeDefiniton> GetTagEntityTypeDefinitionsAsync([NotNull] string entityType);
Task<bool> IsDefinedAsync([NotNull] string entityType);
}
}

3
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/ITagManager.cs

@ -1,5 +1,6 @@
using JetBrains.Annotations;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Services;
@ -26,5 +27,7 @@ namespace Volo.CmsKit.Tags
[NotNull] string name,
Guid? tenantId = null,
CancellationToken cancellationToken = default);
Task<List<TagEntityTypeDefiniton>> GetTagDefinitionsAsync(CancellationToken cancellationToken = default);
}
}

2
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/TagAlreadyExistException.cs

@ -9,7 +9,7 @@ namespace Volo.CmsKit.Tags
{
public TagAlreadyExistException([NotNull] string entityType, [NotNull] string name)
{
Code = CmsKitErrorCodes.TagAlreadyExist;
Code = CmsKitErrorCodes.Tags.TagAlreadyExist;
WithData(nameof(Tag.EntityType), entityType);
WithData(nameof(Tag.Name), name);
}

20
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/TagEntityTypeDefinitionDictionary.cs

@ -0,0 +1,20 @@
using JetBrains.Annotations;
using System.Collections.Generic;
using Volo.Abp.Localization;
namespace Volo.CmsKit.Tags
{
public class TagEntityTypeDefinitionDictionary : Dictionary<string, TagEntityTypeDefiniton>
{
public void AddOrReplace(
[NotNull] string entityType,
[CanBeNull] ILocalizableString displayName = null,
[CanBeNull] string createPolicy = null,
[CanBeNull] string updatePolicy = null,
[CanBeNull] string deletePolicy = null
)
{
this[entityType] = new TagEntityTypeDefiniton(entityType, displayName, createPolicy, updatePolicy, deletePolicy);
}
}
}

31
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/TagEntityTypeDefiniton1.cs

@ -0,0 +1,31 @@
using JetBrains.Annotations;
using Volo.Abp;
using Volo.Abp.Localization;
using Volo.CmsKit.Domain.Volo.CmsKit;
namespace Volo.CmsKit.Tags
{
public class TagEntityTypeDefiniton : PolicySpecifiedDefinition
{
public string EntityType { get; }
[CanBeNull]
public virtual ILocalizableString DisplayName { get; }
public TagEntityTypeDefiniton()
{
}
public TagEntityTypeDefiniton(
[NotNull] string entityType,
[CanBeNull] ILocalizableString displayName = null,
[CanBeNull] string createPolicy = null,
[CanBeNull] string updatePolicy = null,
[CanBeNull] string deletePolicy = null) : base(createPolicy, updatePolicy, deletePolicy)
{
EntityType = Check.NotNullOrWhiteSpace(entityType, nameof(entityType));
DisplayName = displayName;
}
}
}

19
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/TagManager.cs

@ -1,5 +1,8 @@
using JetBrains.Annotations;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp;
@ -10,10 +13,14 @@ namespace Volo.CmsKit.Tags
public class TagManager : DomainService, ITagManager
{
private readonly ITagRepository _tagRepository;
private readonly ITagDefinitionStore _tagDefinitionStore;
public TagManager(ITagRepository tagRepository)
public TagManager(
ITagRepository tagRepository,
ITagDefinitionStore tagDefinitionStore)
{
_tagRepository = tagRepository;
_tagDefinitionStore = tagDefinitionStore;
}
public async Task<Tag> GetOrAddAsync(
@ -44,6 +51,11 @@ namespace Volo.CmsKit.Tags
throw new TagAlreadyExistException(entityType, name);
}
if (!await _tagDefinitionStore.IsDefinedAsync(entityType))
{
throw new EntityNotTaggableException(entityType);
}
return await _tagRepository.InsertAsync(
new Tag(
id,
@ -70,5 +82,10 @@ namespace Volo.CmsKit.Tags
return await _tagRepository.UpdateAsync(entity, cancellationToken: cancellationToken);
}
public Task<List<TagEntityTypeDefiniton>> GetTagDefinitionsAsync(CancellationToken cancellationToken = default)
{
return _tagDefinitionStore.GetTagDefinitionsAsync();
}
}
}

19
modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Tags/EfCoreEntityTagRepository.cs

@ -1,4 +1,8 @@
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using JetBrains.Annotations;
using System;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
using Volo.CmsKit.EntityFrameworkCore;
@ -9,5 +13,18 @@ namespace Volo.CmsKit.Tags
public EfCoreEntityTagRepository(IDbContextProvider<ICmsKitDbContext> dbContextProvider) : base(dbContextProvider)
{
}
public Task<EntityTag> FindAsync(
[NotNull] Guid tagId,
[NotNull] string entityId,
[CanBeNull] Guid? tenantId,
CancellationToken cancellationToken = default)
{
return base.FindAsync(x =>
x.TagId == tagId &&
x.EntityId == entityId &&
x.TenantId == tenantId,
cancellationToken: cancellationToken);
}
}
}

2
modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Contents/MongoContentRepository.cs

@ -54,7 +54,7 @@ namespace Volo.CmsKit.MongoDB.Contents
public async Task<bool> ExistsAsync([NotNull] string entityType, [NotNull] string entityId, Guid? tenantId = null, CancellationToken cancellationToken = default)
{
return await (await GetMongoQueryableAsync()).AnyAsync(x =>
return await (await GetMongoQueryableAsync(cancellationToken)).AnyAsync(x =>
x.EntityType == entityType &&
x.EntityId == entityId &&
x.TenantId == tenantId,

2
modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Pages/MongoPageRepository.cs

@ -63,7 +63,7 @@ namespace Volo.CmsKit.MongoDB.Pages
public virtual async Task<bool> ExistsAsync(string url, CancellationToken cancellationToken = default)
{
return await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))).AnyAsync(x => x.Url == url, GetCancellationToken(cancellationToken));
return await (await GetMongoQueryableAsync(cancellationToken)).AnyAsync(x => x.Url == url, GetCancellationToken(cancellationToken));
}
}
}

19
modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Tags/MongoEntityTagRepository.cs

@ -1,4 +1,8 @@
using Volo.Abp.Domain.Repositories.MongoDB;
using JetBrains.Annotations;
using System;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories.MongoDB;
using Volo.Abp.MongoDB;
using Volo.CmsKit.Tags;
@ -9,5 +13,18 @@ namespace Volo.CmsKit.MongoDB.Tags
public MongoEntityTagRepository(IMongoDbContextProvider<ICmsKitMongoDbContext> dbContextProvider) : base(dbContextProvider)
{
}
public Task<EntityTag> FindAsync(
[NotNull] Guid tagId,
[NotNull] string entityId,
[CanBeNull] Guid? tenantId,
CancellationToken cancellationToken = default)
{
return base.FindAsync(x =>
x.TagId == tagId &&
x.EntityId == entityId &&
x.TenantId == tenantId,
cancellationToken: cancellationToken);
}
}
}

2
modules/cms-kit/src/Volo.CmsKit.Public.Application.Contracts/Volo/CmsKit/Public/Pages/IPageAppService.cs

@ -5,6 +5,6 @@ namespace Volo.CmsKit.Public.Pages
{
public interface IPageAppService
{
Task<PageDto> GetByUrlAsync([NotNull] string url);
Task<PageDto> FindByUrlAsync([NotNull] string url);
}
}

9
modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Pages/PageAppService.cs

@ -12,9 +12,14 @@ namespace Volo.CmsKit.Public.Pages
PageRepository = pageRepository;
}
public virtual async Task<PageDto> GetByUrlAsync(string url)
public virtual async Task<PageDto> FindByUrlAsync(string url)
{
var page = await PageRepository.GetByUrlAsync(url);
var page = await PageRepository.FindByUrlAsync(url);
if (page == null)
{
return null;
}
return ObjectMapper.Map<Page, PageDto>(page);
}

6
modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/Pages/PagesPublicController.cs

@ -7,7 +7,7 @@ namespace Volo.CmsKit.Public.Pages
[RemoteService(Name = CmsKitPublicRemoteServiceConsts.RemoteServiceName)]
[Area("cms-kit")]
[Route("api/cms-kit-public/comments")]
public class PagesPublicController
public class PagesPublicController : IPageAppService
{
protected readonly IPageAppService PageAppService;
@ -18,9 +18,9 @@ namespace Volo.CmsKit.Public.Pages
[HttpGet]
[Route("url/{url}")]
public Task<PageDto> GetByUrlAsync(string url)
public Task<PageDto> FindByUrlAsync(string url)
{
return PageAppService.GetByUrlAsync(url);
return PageAppService.FindByUrlAsync(url);
}
}
}

5
modules/cms-kit/src/Volo.CmsKit.Public.Web/CmsKitPublicWebModule.cs

@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.Linq;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.AspNetCore.Mvc.Localization;
using Volo.Abp.AutoMapper;
@ -56,7 +57,7 @@ namespace Volo.CmsKit.Public.Web
Configure<RazorPagesOptions>(options =>
{
//...
options.Conventions.AddPageRoute("/CmsKit/Pages/Index", "/{*pageUrl}");
});
}
}

2
modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Pages/Index.cshtml

@ -1,4 +1,4 @@
@page "{pageUrl}"
@page "{*pageUrl}"
@using Microsoft.AspNetCore.Mvc.Localization
@using Volo.CmsKit.Localization
@using Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.Pages

11
modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Pages/Index.cshtml.cs

@ -19,9 +19,16 @@ namespace Volo.CmsKit.Public.Web.Pages.CmsKit.Pages
PageAppService = pageAppService;
}
public async Task OnGetAsync()
public async Task<IActionResult> OnGetAsync()
{
Page = await PageAppService.GetByUrlAsync(PageUrl);
Page = await PageAppService.FindByUrlAsync(PageUrl);
if (Page == null)
{
return NotFound();
}
return Page();
}
}
}

32
modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Contents/ContentViewComponent.cs

@ -2,6 +2,7 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.Domain.Entities;
using Volo.CmsKit.Public.Contents;
using Volo.CmsKit.Web.Contents;
@ -25,18 +26,26 @@ namespace Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.Contents
string entityType,
string entityId)
{
var content = await contentAppService.GetAsync(new GetContentInput
var content = string.Empty;
try
{
EntityId = entityId,
EntityType = entityType
});
var contentDto = await contentAppService.GetAsync(new GetContentInput
{
EntityId = entityId,
EntityType = entityType
});
content = contentDto.Value;
}
catch (EntityNotFoundException e)
{
// ContentDto can be null, we will render empty content.
}
var viewModel = new ContentViewModel
{
EntityId = entityId,
EntityType = entityType,
ContentId = content.Id,
Rendered = await contentRenderer.RenderAsync(content.Value)
Value = await contentRenderer.RenderAsync(content)
};
return View("~/Pages/CmsKit/Shared/Components/Contents/Default.cshtml", viewModel);
@ -44,12 +53,7 @@ namespace Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.Contents
public class ContentViewModel
{
public Guid ContentId { get; set; }
public string EntityType { get; set; }
public string EntityId { get; set; }
public string Rendered { get; set; }
public string Value { get; set; }
}
}
}

2
modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Contents/Default.cshtml

@ -1,3 +1,3 @@
@model Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.Contents.ContentViewComponent.ContentViewModel
@Html.Raw(Model.Rendered)
@Html.Raw(Model.Value)

12
modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Pages/Default.cshtml

@ -1,16 +1,16 @@
@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bootstrap
@using Microsoft.AspNetCore.Mvc.RazorPages
@using Volo.Abp.AspNetCore.Mvc.UI.Layout
@using Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.Contents
@model Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.Pages.PageViewModel
@inject IPageLayout PageLayout
@{
PageLayout.Content.Title = Model.Title;
}
<abp-card>
<abp-card-header>
<h3>
@Model.Title
</h3>
</abp-card-header>
<abp-card-body>
@await Component.InvokeAsync(typeof(ContentViewComponent),
new

3
modules/cms-kit/test/Volo.CmsKit.Application.Tests/Contents/ContentAdminAppService_Tests.cs

@ -38,6 +38,7 @@ namespace Volo.CmsKit.Contents
result.ShouldNotBeNull();
result.Items.ShouldNotBeEmpty();
result.Items.Count.ShouldBe(4);
result.Items.All(x => x.ShouldBeOfType<ContentGetListDto>() != null);
}
[Fact]
@ -46,6 +47,8 @@ namespace Volo.CmsKit.Contents
var result = await _service.GetAsync(_data.Content_1_Id);
result.ShouldNotBeNull();
result.ShouldBeOfType<Admin.Contents.ContentDto>();
result.ShouldNotBeNull(result.Value);
}
[Fact]

11
modules/cms-kit/test/Volo.CmsKit.Application.Tests/Pages/PagePublicAppService_Tests.cs

@ -18,15 +18,20 @@ namespace Volo.CmsKit.Pages
}
[Fact]
public async Task ShouldGetByUrlAsync()
public async Task ShouldFindByUrlAsync()
{
await Should.NotThrowAsync(async () => await _pageAppService.GetByUrlAsync(_data.Page_1_Url));
var page = await _pageAppService.FindByUrlAsync(_data.Page_1_Url);
page.ShouldNotBeNull();
page.Title.ShouldBe(_data.Page_1_Title);
}
[Fact]
public async Task ShouldNotGetByUrlAsync()
{
await Should.ThrowAsync<Exception>(async () => await _pageAppService.GetByUrlAsync("not-exist-url"));
var page = await _pageAppService.FindByUrlAsync("not-exist-url");
page.ShouldBeNull();
}
}
}

4
modules/cms-kit/test/Volo.CmsKit.Application.Tests/Tags/TagAdminAppService_Tests.cs

@ -32,8 +32,8 @@ namespace Volo.CmsKit.Tags
{
var list = await _tagAdminAppService.CreateAsync(new TagCreateDto
{
EntityType = "any_new_type",
Name = "1",
EntityType = _cmsKitTestData.EntityType1,
Name = "My First Tag",
});
list.Id.ShouldNotBe(Guid.Empty);

1
modules/cms-kit/test/Volo.CmsKit.Domain.Tests/CmsKitDomainTestModule.cs

@ -12,6 +12,5 @@ namespace Volo.CmsKit
)]
public class CmsKitDomainTestModule : AbpModule
{
}
}

60
modules/cms-kit/test/Volo.CmsKit.Domain.Tests/Tags/EntityTagManager_Tests.cs

@ -0,0 +1,60 @@
using Shouldly;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Guids;
using Xunit;
namespace Volo.CmsKit.Tags
{
public class EntityTagManager_Tests : CmsKitDomainTestBase
{
private readonly CmsKitTestData _cmsKitTestData;
private readonly IEntityTagManager _entityTagManager;
private readonly ITagRepository _tagRepository;
private readonly IGuidGenerator _guidGenerator;
public EntityTagManager_Tests()
{
_cmsKitTestData = GetRequiredService<CmsKitTestData>();
_entityTagManager = GetRequiredService<IEntityTagManager>();
_tagRepository = GetRequiredService<ITagRepository>();
_guidGenerator = GetRequiredService<IGuidGenerator>();
}
[Fact]
public async Task AddTagToEntityAsync_ShouldAdd_WhenEverythingCorrect()
{
var tag = await _tagRepository.InsertAsync(new Tag(_guidGenerator.Create(), _cmsKitTestData.EntityType1, "My Test Tag #1"));
var entityTag = await _entityTagManager.AddTagToEntityAsync(tag.Id, _cmsKitTestData.EntityType1, _cmsKitTestData.EntityId1);
entityTag.ShouldNotBeNull();
}
[Fact]
public async Task AddTagToEntity_ShouldThrowNotTaggable_WithNotConfiguredEntityType()
{
var entityType = "Not.Configured.EntityType";
var exception = Should.Throw<EntityNotTaggableException>(async () =>
await _entityTagManager.AddTagToEntityAsync(_cmsKitTestData.TagId_1, entityType, _cmsKitTestData.EntityId1)
);
exception.ShouldNotBeNull();
exception.Data[nameof(Tag.EntityType)].ShouldBe(entityType);
}
[Fact]
public async Task RemoveTagFromEntityAsync_ShouldRemove_WhenEverythingCorrect()
{
var tagToDelete = (await _tagRepository.GetAllRelatedTagsAsync(_cmsKitTestData.EntityType1, _cmsKitTestData.EntityId1))
.First();
await _entityTagManager.RemoveTagFromEntityAsync(tagToDelete.Id, tagToDelete.EntityType, _cmsKitTestData.EntityId1);
var tags = await _tagRepository.GetAllRelatedTagsAsync(_cmsKitTestData.EntityType1, _cmsKitTestData.EntityId1);
tags.ShouldNotContain(x => x.Id == tagToDelete.Id);
}
}
}

30
modules/cms-kit/test/Volo.CmsKit.Domain.Tests/Tags/TagManager_Tests.cs

@ -22,7 +22,7 @@ namespace Volo.CmsKit.Tags
[Fact]
public async Task ShouldAddWhenGettingAsync()
{
var newTagEntityType = "testEntity";
var newTagEntityType = _cmsKitTestData.EntityType1;
var newTagName = "test_tag_2123";
var doesExist = await _tagRepository.AnyAsync(newTagEntityType, newTagName);
@ -53,16 +53,28 @@ namespace Volo.CmsKit.Tags
}
[Fact]
public async Task ShouldInsert()
public async Task ShouldInsertAsync()
{
var tag = await _tagManager.InsertAsync(Guid.NewGuid(), "test", "test");
var tagName = "Freshly Created New Tag";
var tag = await _tagManager.InsertAsync(Guid.NewGuid(), _cmsKitTestData.EntityType1, tagName);
tag.ShouldNotBeNull();
var doesExist = await _tagRepository.AnyAsync("test", "test");
var doesExist = await _tagRepository.AnyAsync(_cmsKitTestData.EntityType1, tagName);
doesExist.ShouldBeTrue();
}
[Fact]
public async Task ShouldntInsertWithUnconfiguredEntityTypeAsync()
{
var notConfiguredEntityType = "My.Namespace.SomeEntity";
var exception = await Should.ThrowAsync<EntityNotTaggableException>(async () =>
await _tagManager.InsertAsync(Guid.NewGuid(), notConfiguredEntityType, "test"));
exception.ShouldNotBeNull();
exception.Data[nameof(Tag.EntityType)].ShouldBe(notConfiguredEntityType);
}
[Fact]
public async Task ShouldNotInsert()
@ -100,5 +112,15 @@ namespace Volo.CmsKit.Tags
Should.Throw<Exception>(async () => await _tagManager.UpdateAsync(tag.Id, newName));
}
[Fact]
public async Task ShouldGetTagDefinitionsProperly_WithoutParameter()
{
var definitions = await _tagManager.GetTagDefinitionsAsync();
definitions.ShouldNotBeNull();
definitions.Count.ShouldBeGreaterThan(1);
definitions.ShouldContain(x => x.EntityType == _cmsKitTestData.TagDefinition_1_EntityType);
}
}
}

59
modules/cms-kit/test/Volo.CmsKit.TestBase/CmsKitDataSeedContributor.cs

@ -1,4 +1,5 @@
using System;
using Microsoft.Extensions.Options;
using System;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Data;
@ -26,9 +27,12 @@ namespace Volo.CmsKit
private readonly IRatingRepository _ratingRepository;
private readonly ICurrentTenant _currentTenant;
private readonly IContentRepository _contentRepository;
private readonly IEntityTagRepository _entityTagRepository;
private readonly IEntityTagManager _entityTagManager;
private readonly ITagManager _tagManager;
private readonly IPageRepository _pageRepository;
private readonly IOptions<CmsKitOptions> _options;
private readonly IOptions<CmsKitTagOptions> _tagOptions;
public CmsKitDataSeedContributor(
IGuidGenerator guidGenerator,
ICmsUserRepository cmsUserRepository,
@ -36,11 +40,13 @@ namespace Volo.CmsKit
ICommentRepository commentRepository,
ReactionManager reactionManager,
IRatingRepository ratingRepository,
ICurrentTenant currentTenant,
ICurrentTenant currentTenant,
IContentRepository contentRepository,
ITagManager tagManager,
IEntityTagRepository entityTagRepository,
IPageRepository pageRepository)
ITagManager tagManager,
IEntityTagManager entityTagManager,
IPageRepository pageRepository,
IOptions<CmsKitOptions> options,
IOptions<CmsKitTagOptions> tagOptions)
{
_guidGenerator = guidGenerator;
_cmsUserRepository = cmsUserRepository;
@ -51,14 +57,18 @@ namespace Volo.CmsKit
_currentTenant = currentTenant;
_contentRepository = contentRepository;
_tagManager = tagManager;
_entityTagRepository = entityTagRepository;
_entityTagManager = entityTagManager;
_pageRepository = pageRepository;
_options = options;
_tagOptions = tagOptions;
}
public async Task SeedAsync(DataSeedContext context)
{
using (_currentTenant.Change(context?.TenantId))
{
await ConfigureCmsKitOptionsAsync();
await SeedUsersAsync();
await SeedCommentsAsync();
@ -75,6 +85,17 @@ namespace Volo.CmsKit
}
}
private Task ConfigureCmsKitOptionsAsync()
{
_tagOptions.Value.EntityTypes.AddOrReplace(_cmsKitTestData.EntityType1);
_tagOptions.Value.EntityTypes.AddOrReplace(_cmsKitTestData.EntityType2);
_tagOptions.Value.EntityTypes.AddOrReplace(_cmsKitTestData.Content_1_EntityType);
_tagOptions.Value.EntityTypes.AddOrReplace(_cmsKitTestData.Content_2_EntityType);
_tagOptions.Value.EntityTypes.AddOrReplace(_cmsKitTestData.TagDefinition_1_EntityType);
return Task.CompletedTask;
}
private async Task SeedUsersAsync()
{
await _cmsUserRepository.InsertAsync(new CmsUser(new UserData(_cmsKitTestData.User1Id, "user1",
@ -208,14 +229,14 @@ namespace Volo.CmsKit
_cmsKitTestData.Content_1_EntityId,
_cmsKitTestData.Content_1
);
var content2 = new Content(
_cmsKitTestData.Content_2_Id,
_cmsKitTestData.Content_2_EntityType,
_cmsKitTestData.Content_2_EntityId,
_cmsKitTestData.Content_2
);
var content3 = new Content(
Guid.NewGuid(),
"deleted_entity_type",
@ -233,18 +254,26 @@ namespace Volo.CmsKit
private async Task SeedTagsAsync()
{
var created1 = await _tagManager.InsertAsync(_cmsKitTestData.TagId_1, _cmsKitTestData.EntityType1, _cmsKitTestData.TagName_1);
await _entityTagManager.AddTagToEntityAsync(created1.Id, created1.EntityType, _cmsKitTestData.EntityId1);
var created2 = await _tagManager.InsertAsync(_cmsKitTestData.TagId_2, _cmsKitTestData.EntityType2, _cmsKitTestData.TagName_2);
await _entityTagManager.AddTagToEntityAsync(created2.Id, created2.EntityType, _cmsKitTestData.EntityId2);
foreach (var tag in _cmsKitTestData.Content_1_Tags)
{
var tagEntity = await _tagManager.InsertAsync(_guidGenerator.Create(), _cmsKitTestData.Content_1_EntityType, tag);
await _entityTagRepository.InsertAsync(new EntityTag(tagEntity.Id, _cmsKitTestData.Content_1_EntityId));
await _entityTagManager.AddTagToEntityAsync(tagEntity.Id, _cmsKitTestData.Content_1_EntityType, _cmsKitTestData.Content_1_EntityId);
}
foreach (var tag in _cmsKitTestData.Content_2_Tags)
{
var tagEntity = await _tagManager.InsertAsync(_guidGenerator.Create(), _cmsKitTestData.Content_2_EntityType, tag);
await _entityTagRepository.InsertAsync(new EntityTag(tagEntity.Id, _cmsKitTestData.Content_2_EntityId));
await _entityTagManager.AddTagToEntityAsync(tagEntity.Id, _cmsKitTestData.Content_2_EntityType, _cmsKitTestData.Content_2_EntityId);
}
}
@ -252,10 +281,10 @@ namespace Volo.CmsKit
{
var page1 = new Page(_cmsKitTestData.Page_1_Id, _cmsKitTestData.Page_1_Title, _cmsKitTestData.Page_1_Url, _cmsKitTestData.Page_1_Description);
var page1Content = new Content(_guidGenerator.Create(), nameof(Page), page1.Id.ToString(), _cmsKitTestData.Page_1_Content);
await _pageRepository.InsertAsync(page1);
await _contentRepository.InsertAsync(page1Content);
var page2 = new Page(_cmsKitTestData.Page_2_Id, _cmsKitTestData.Page_2_Title, _cmsKitTestData.Page_2_Url, _cmsKitTestData.Page_2_Description);
var page2Content = new Content(_guidGenerator.Create(), nameof(Page), page2.Id.ToString(), _cmsKitTestData.Page_2_Content);

11
modules/cms-kit/test/Volo.CmsKit.TestBase/CmsKitTestData.cs

@ -12,6 +12,7 @@ namespace Volo.CmsKit
public Guid CommentWithChildId { get; } = Guid.NewGuid();
public string EntityType1 { get; } = "EntityName1";
public string EntityType2 { get; } = "EntityName2";
@ -59,5 +60,15 @@ namespace Volo.CmsKit
public Guid Page_2_Id { get; } = Guid.NewGuid();
public string Page_2_Content => Content_2;
public string TagDefinition_1_EntityType => "My.Namespace.CustomType";
public Guid TagId_1 { get; } = Guid.NewGuid();
public string TagName_1 => "Awesome";
public Guid TagId_2 { get; } = Guid.NewGuid();
public string TagName_2 => "News";
}
}

9
modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/IProjectRepository.cs

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
@ -7,10 +8,10 @@ namespace Volo.Docs.Projects
{
public interface IProjectRepository : IBasicRepository<Project, Guid>
{
Task<List<Project>> GetListAsync(string sorting, int maxResultCount, int skipCount);
Task<List<Project>> GetListAsync(string sorting, int maxResultCount, int skipCount, CancellationToken cancellationToken = default);
Task<Project> GetByShortNameAsync(string shortName);
Task<Project> GetByShortNameAsync(string shortName, CancellationToken cancellationToken = default);
Task<bool> ShortNameExistsAsync(string shortName);
Task<bool> ShortNameExistsAsync(string shortName, CancellationToken cancellationToken = default);
}
}
}

13
modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/Projects/EfCoreProjectRepository.cs

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Domain.Entities;
@ -18,20 +19,20 @@ namespace Volo.Docs.Projects
{
}
public async Task<List<Project>> GetListAsync(string sorting, int maxResultCount, int skipCount)
public async Task<List<Project>> GetListAsync(string sorting, int maxResultCount, int skipCount, CancellationToken cancellationToken = default)
{
var projects = await (await GetDbSetAsync()).OrderBy(sorting ?? "Id desc")
.PageBy(skipCount, maxResultCount)
.ToListAsync();
.ToListAsync(GetCancellationToken(cancellationToken));
return projects;
}
public async Task<Project> GetByShortNameAsync(string shortName)
public async Task<Project> GetByShortNameAsync(string shortName, CancellationToken cancellationToken = default)
{
var normalizeShortName = NormalizeShortName(shortName);
var project = await (await GetDbSetAsync()).FirstOrDefaultAsync(p => p.ShortName == normalizeShortName);
var project = await (await GetDbSetAsync()).FirstOrDefaultAsync(p => p.ShortName == normalizeShortName, GetCancellationToken(cancellationToken));
if (project == null)
{
@ -41,11 +42,11 @@ namespace Volo.Docs.Projects
return project;
}
public async Task<bool> ShortNameExistsAsync(string shortName)
public async Task<bool> ShortNameExistsAsync(string shortName, CancellationToken cancellationToken = default)
{
var normalizeShortName = NormalizeShortName(shortName);
return await (await GetDbSetAsync()).AnyAsync(x => x.ShortName == normalizeShortName);
return await (await GetDbSetAsync()).AnyAsync(x => x.ShortName == normalizeShortName, GetCancellationToken(cancellationToken));
}
private string NormalizeShortName(string shortName)

15
modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/Projects/MongoProjectRepository.cs

@ -9,6 +9,7 @@ using Volo.Abp.MongoDB;
using Volo.Docs.MongoDB;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading;
namespace Volo.Docs.Projects
{
@ -19,20 +20,20 @@ namespace Volo.Docs.Projects
{
}
public async Task<List<Project>> GetListAsync(string sorting, int maxResultCount, int skipCount)
public async Task<List<Project>> GetListAsync(string sorting, int maxResultCount, int skipCount, CancellationToken cancellationToken = default)
{
var projects = await (await GetMongoQueryableAsync()).OrderBy(sorting ?? "Id desc").As<IMongoQueryable<Project>>()
var projects = await (await GetMongoQueryableAsync(cancellationToken)).OrderBy(sorting ?? "Id desc").As<IMongoQueryable<Project>>()
.PageBy<Project, IMongoQueryable<Project>>(skipCount, maxResultCount)
.ToListAsync();
.ToListAsync(GetCancellationToken(cancellationToken));
return projects;
}
public async Task<Project> GetByShortNameAsync(string shortName)
public async Task<Project> GetByShortNameAsync(string shortName, CancellationToken cancellationToken = default)
{
var normalizeShortName = NormalizeShortName(shortName);
var project = await (await GetMongoQueryableAsync()).FirstOrDefaultAsync(p => p.ShortName == normalizeShortName);
var project = await (await GetMongoQueryableAsync(cancellationToken)).FirstOrDefaultAsync(p => p.ShortName == normalizeShortName, GetCancellationToken(cancellationToken));
if (project == null)
{
@ -42,11 +43,11 @@ namespace Volo.Docs.Projects
return project;
}
public async Task<bool> ShortNameExistsAsync(string shortName)
public async Task<bool> ShortNameExistsAsync(string shortName, CancellationToken cancellationToken = default)
{
var normalizeShortName = NormalizeShortName(shortName);
return await (await GetMongoQueryableAsync()).AnyAsync(x => x.ShortName == normalizeShortName);
return await (await GetMongoQueryableAsync(cancellationToken)).AnyAsync(x => x.ShortName == normalizeShortName, GetCancellationToken(cancellationToken));
}
private string NormalizeShortName(string shortName)

18
modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/IFeatureValueRepository.cs

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
@ -7,10 +8,21 @@ namespace Volo.Abp.FeatureManagement
{
public interface IFeatureValueRepository : IBasicRepository<FeatureValue, Guid>
{
Task<FeatureValue> FindAsync(string name, string providerName, string providerKey);
Task<FeatureValue> FindAsync(
string name,
string providerName,
string providerKey,
CancellationToken cancellationToken = default);
Task<List<FeatureValue>> FindAllAsync(string name, string providerName, string providerKey);
Task<List<FeatureValue>> FindAllAsync(
string name,
string providerName,
string providerKey,
CancellationToken cancellationToken = default);
Task<List<FeatureValue>> GetListAsync(string providerName, string providerKey);
Task<List<FeatureValue>> GetListAsync(
string providerName,
string providerKey,
CancellationToken cancellationToken = default);
}
}

26
modules/feature-management/src/Volo.Abp.FeatureManagement.EntityFrameworkCore/Volo/Abp/FeatureManagement/EntityFrameworkCore/EfCoreFeatureValueRepository.cs

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
@ -15,29 +16,38 @@ namespace Volo.Abp.FeatureManagement.EntityFrameworkCore
{
}
public virtual async Task<FeatureValue> FindAsync(string name, string providerName, string providerKey)
public virtual async Task<FeatureValue> FindAsync(
string name,
string providerName,
string providerKey,
CancellationToken cancellationToken = default)
{
return await (await GetDbSetAsync())
.OrderBy(x => x.Id)
.FirstOrDefaultAsync(
s => s.Name == name && s.ProviderName == providerName && s.ProviderKey == providerKey
);
.FirstOrDefaultAsync(s => s.Name == name && s.ProviderName == providerName && s.ProviderKey == providerKey, GetCancellationToken(cancellationToken));
}
public async Task<List<FeatureValue>> FindAllAsync(string name, string providerName, string providerKey)
public async Task<List<FeatureValue>> FindAllAsync(
string name,
string providerName,
string providerKey,
CancellationToken cancellationToken = default)
{
return await (await GetDbSetAsync())
.Where(
s => s.Name == name && s.ProviderName == providerName && s.ProviderKey == providerKey
).ToListAsync();
).ToListAsync(GetCancellationToken(cancellationToken));
}
public virtual async Task<List<FeatureValue>> GetListAsync(string providerName, string providerKey)
public virtual async Task<List<FeatureValue>> GetListAsync(
string providerName,
string providerKey,
CancellationToken cancellationToken = default)
{
return await (await GetDbSetAsync())
.Where(
s => s.ProviderName == providerName && s.ProviderKey == providerKey
).ToListAsync();
).ToListAsync(GetCancellationToken(cancellationToken));
}
}
}

30
modules/feature-management/src/Volo.Abp.FeatureManagement.MongoDB/Volo/Abp/FeatureManagement/MongoDB/MongoFeatureValueRepository.cs

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using MongoDB.Driver;
using MongoDB.Driver.Linq;
@ -16,24 +17,35 @@ namespace Volo.Abp.FeatureManagement.MongoDB
}
public virtual async Task<FeatureValue> FindAsync(string name, string providerName, string providerKey)
public virtual async Task<FeatureValue> FindAsync(
string name,
string providerName,
string providerKey,
CancellationToken cancellationToken = default)
{
return await (await GetMongoQueryableAsync())
return await (await GetMongoQueryableAsync(cancellationToken))
.OrderBy(x => x.Id)
.FirstOrDefaultAsync(s => s.Name == name && s.ProviderName == providerName && s.ProviderKey == providerKey);
.FirstOrDefaultAsync(s => s.Name == name && s.ProviderName == providerName && s.ProviderKey == providerKey, GetCancellationToken(cancellationToken));
}
public async Task<List<FeatureValue>> FindAllAsync(string name, string providerName, string providerKey)
public async Task<List<FeatureValue>> FindAllAsync(
string name,
string providerName,
string providerKey,
CancellationToken cancellationToken = default)
{
return await (await GetMongoQueryableAsync())
.Where(s => s.Name == name && s.ProviderName == providerName && s.ProviderKey == providerKey).ToListAsync();
return await (await GetMongoQueryableAsync(cancellationToken))
.Where(s => s.Name == name && s.ProviderName == providerName && s.ProviderKey == providerKey).ToListAsync(GetCancellationToken(cancellationToken));
}
public virtual async Task<List<FeatureValue>> GetListAsync(string providerName, string providerKey)
public virtual async Task<List<FeatureValue>> GetListAsync(
string providerName,
string providerKey,
CancellationToken cancellationToken = default)
{
return await (await GetMongoQueryableAsync())
return await (await GetMongoQueryableAsync(cancellationToken))
.Where(s => s.ProviderName == providerName && s.ProviderKey == providerKey)
.ToListAsync();
.ToListAsync(GetCancellationToken(cancellationToken));
}
}
}

11
modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentitySecurityLogRepository.cs

@ -44,7 +44,8 @@ namespace Volo.Abp.Identity.MongoDB
userId,
userName,
clientId,
correlationId
correlationId,
cancellationToken
);
return await query.OrderBy(sorting ?? nameof(IdentitySecurityLog.CreationTime) + " desc")
@ -74,7 +75,8 @@ namespace Volo.Abp.Identity.MongoDB
userId,
userName,
clientId,
correlationId
correlationId,
cancellationToken
);
return await query.As<IMongoQueryable<IdentitySecurityLog>>()
@ -98,9 +100,10 @@ namespace Volo.Abp.Identity.MongoDB
Guid? userId = null,
string userName = null,
string clientId = null,
string correlationId = null)
string correlationId = null,
CancellationToken cancellationToken = default)
{
return (await GetMongoQueryableAsync())
return (await GetMongoQueryableAsync(cancellationToken))
.WhereIf(startTime.HasValue, securityLog => securityLog.CreationTime >= startTime.Value)
.WhereIf(endTime.HasValue, securityLog => securityLog.CreationTime < endTime.Value.AddDays(1).Date)
.WhereIf(!applicationName.IsNullOrWhiteSpace(),

9
modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoPersistedGrantRepository.cs

@ -21,7 +21,7 @@ namespace Volo.Abp.IdentityServer.MongoDB
public async Task<List<PersistedGrant>> GetListAsync(string subjectId, string sessionId, string clientId, string type, bool includeDetails = false,
CancellationToken cancellationToken = default)
{
return await (await FilterAsync(subjectId, sessionId, clientId, type))
return await (await FilterAsync(subjectId, sessionId, clientId, type, cancellationToken))
.ToListAsync(GetCancellationToken(cancellationToken));
}
@ -57,7 +57,7 @@ namespace Volo.Abp.IdentityServer.MongoDB
string type = null,
CancellationToken cancellationToken = default)
{
var persistedGrants = await (await FilterAsync(subjectId, sessionId, clientId, type))
var persistedGrants = await (await FilterAsync(subjectId, sessionId, clientId, type, cancellationToken))
.ToListAsync(GetCancellationToken(cancellationToken));
foreach (var persistedGrant in persistedGrants)
@ -86,9 +86,10 @@ namespace Volo.Abp.IdentityServer.MongoDB
string subjectId,
string sessionId,
string clientId,
string type)
string type,
CancellationToken cancellationToken = default)
{
return (await GetMongoQueryableAsync())
return (await GetMongoQueryableAsync(cancellationToken))
.WhereIf<PersistedGrant, IMongoQueryable<PersistedGrant>>(!subjectId.IsNullOrWhiteSpace(), x => x.SubjectId == subjectId)
.WhereIf<PersistedGrant, IMongoQueryable<PersistedGrant>>(!sessionId.IsNullOrWhiteSpace(), x => x.SessionId == sessionId)
.WhereIf<PersistedGrant, IMongoQueryable<PersistedGrant>>(!clientId.IsNullOrWhiteSpace(), x => x.ClientId == clientId)

18
modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/ISettingRepository.cs

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
@ -7,10 +8,21 @@ namespace Volo.Abp.SettingManagement
{
public interface ISettingRepository : IBasicRepository<Setting, Guid>
{
Task<Setting> FindAsync(string name, string providerName, string providerKey);
Task<Setting> FindAsync(
string name,
string providerName,
string providerKey,
CancellationToken cancellationToken = default);
Task<List<Setting>> GetListAsync(string providerName, string providerKey);
Task<List<Setting>> GetListAsync(
string providerName,
string providerKey,
CancellationToken cancellationToken = default);
Task<List<Setting>> GetListAsync(string[] names, string providerName, string providerKey);
Task<List<Setting>> GetListAsync(
string[] names,
string providerName,
string providerKey,
CancellationToken cancellationToken = default);
}
}

29
modules/setting-management/src/Volo.Abp.SettingManagement.EntityFrameworkCore/Volo/Abp/SettingManagement/EntityFrameworkCore/EfCoreSettingRepository.cs

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
@ -8,36 +9,48 @@ using Volo.Abp.EntityFrameworkCore;
namespace Volo.Abp.SettingManagement.EntityFrameworkCore
{
public class EfCoreSettingRepository : EfCoreRepository<ISettingManagementDbContext, Setting, Guid>, ISettingRepository
public class EfCoreSettingRepository : EfCoreRepository<ISettingManagementDbContext, Setting, Guid>,
ISettingRepository
{
public EfCoreSettingRepository(IDbContextProvider<ISettingManagementDbContext> dbContextProvider)
: base(dbContextProvider)
{
}
public virtual async Task<Setting> FindAsync(string name, string providerName, string providerKey)
public virtual async Task<Setting> FindAsync(
string name,
string providerName,
string providerKey,
CancellationToken cancellationToken = default)
{
return await (await GetDbSetAsync())
.OrderBy(x => x.Id)
.FirstOrDefaultAsync(
s => s.Name == name && s.ProviderName == providerName && s.ProviderKey == providerKey
);
s => s.Name == name && s.ProviderName == providerName && s.ProviderKey == providerKey,
GetCancellationToken(cancellationToken));
}
public virtual async Task<List<Setting>> GetListAsync(string providerName, string providerKey)
public virtual async Task<List<Setting>> GetListAsync(
string providerName,
string providerKey,
CancellationToken cancellationToken = default)
{
return await (await GetDbSetAsync())
.Where(
s => s.ProviderName == providerName && s.ProviderKey == providerKey
).ToListAsync();
).ToListAsync(GetCancellationToken(cancellationToken));
}
public virtual async Task<List<Setting>> GetListAsync(string[] names, string providerName, string providerKey)
public virtual async Task<List<Setting>> GetListAsync(
string[] names,
string providerName,
string providerKey,
CancellationToken cancellationToken = default)
{
return await (await GetDbSetAsync())
.Where(
s => names.Contains(s.Name) && s.ProviderName == providerName && s.ProviderKey == providerKey
).ToListAsync();
).ToListAsync(GetCancellationToken(cancellationToken));
}
}
}

36
modules/setting-management/src/Volo.Abp.SettingManagement.MongoDB/Volo/Abp/SettingManagement/MongoDB/MongoSettingRepository.cs

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MongoDB.Driver;
using MongoDB.Driver.Linq;
@ -9,33 +10,46 @@ using Volo.Abp.MongoDB;
namespace Volo.Abp.SettingManagement.MongoDB
{
public class MongoSettingRepository : MongoDbRepository<ISettingManagementMongoDbContext, Setting, Guid>, ISettingRepository
public class MongoSettingRepository : MongoDbRepository<ISettingManagementMongoDbContext, Setting, Guid>,
ISettingRepository
{
public MongoSettingRepository(IMongoDbContextProvider<ISettingManagementMongoDbContext> dbContextProvider)
: base(dbContextProvider)
{
}
public virtual async Task<Setting> FindAsync(string name, string providerName, string providerKey)
public virtual async Task<Setting> FindAsync(
string name,
string providerName,
string providerKey,
CancellationToken cancellationToken = default)
{
return await (await GetMongoQueryableAsync())
return await (await GetMongoQueryableAsync(cancellationToken))
.OrderBy(x => x.Id)
.FirstOrDefaultAsync(s => s.Name == name && s.ProviderName == providerName && s.ProviderKey == providerKey);
.FirstOrDefaultAsync(
s => s.Name == name && s.ProviderName == providerName && s.ProviderKey == providerKey,
GetCancellationToken(cancellationToken));
}
public virtual async Task<List<Setting>> GetListAsync(string providerName, string providerKey)
public virtual async Task<List<Setting>> GetListAsync(
string providerName,
string providerKey,
CancellationToken cancellationToken = default)
{
return await (await GetMongoQueryableAsync())
return await (await GetMongoQueryableAsync(cancellationToken))
.Where(s => s.ProviderName == providerName && s.ProviderKey == providerKey)
.ToListAsync();
.ToListAsync(GetCancellationToken(cancellationToken));
}
public virtual async Task<List<Setting>> GetListAsync(string[] names, string providerName, string providerKey)
public virtual async Task<List<Setting>> GetListAsync(
string[] names,
string providerName,
string providerKey,
CancellationToken cancellationToken = default)
{
return await (await GetMongoQueryableAsync())
return await (await GetMongoQueryableAsync(cancellationToken))
.Where(s => names.Contains(s.Name) && s.ProviderName == providerName && s.ProviderKey == providerKey)
.ToListAsync();
.ToListAsync(GetCancellationToken(cancellationToken));
}
}
}

75
npm/ng-packs/packages/core/src/lib/tests/tree-utils.spec.ts

@ -1,4 +1,9 @@
import { BaseTreeNode, createTreeFromList, TreeNode } from '../utils/tree-utils';
import {
BaseTreeNode,
createTreeFromList,
createTreeNodeFilterCreator,
TreeNode,
} from '../utils/tree-utils';
const LIST_1 = [
{ id: 1, pid: null },
@ -38,6 +43,42 @@ const TREE_3 = [
],
},
];
const SOURCE_TREE: TreeNode<SearchModel>[] = [
{
id: 1,
pid: null,
isLeaf: false,
name: 'foo',
children: [
{
id: 2,
pid: 1,
name: 'bar',
isLeaf: false,
children: [{ id: 3, pid: 2, name: 'qux', isLeaf: true, children: [] }],
},
{ id: 4, pid: 1, name: 'baz', isLeaf: true, children: [] },
{ id: 5, pid: 1, name: 'quux', isLeaf: true, children: [] },
],
},
];
const RESULT_TREE_1 = [
{ id: 3, pid: 2, name: 'qux', isLeaf: true, children: [] },
{ id: 5, pid: 1, name: 'quux', isLeaf: true, children: [] },
];
const RESULT_TREE_2 = [{ id: 5, pid: 1, name: 'quux', isLeaf: true, children: [] }];
const RESULT_TREE_3 = [
{
id: 2,
pid: 1,
name: 'bar',
isLeaf: false,
children: [{ id: 3, pid: 2, name: 'qux', isLeaf: true, children: [] }],
},
{ id: 4, pid: 1, name: 'baz', isLeaf: true, children: [] },
];
const RESULT_TREE_4 = [{ id: 4, pid: 1, name: 'baz', isLeaf: true, children: [] }];
describe('Tree Utils', () => {
describe('createTreeFromList', () => {
test.each`
@ -56,6 +97,23 @@ describe('Tree Utils', () => {
expect(removeParents(tree)).toEqual(expected);
});
});
describe('createTreeNodeFilterCreator', () => {
test.each`
search | expected
${'qu'} | ${RESULT_TREE_1}
${'quu'} | ${RESULT_TREE_2}
${'ba'} | ${RESULT_TREE_3}
${'baz'} | ${RESULT_TREE_4}
`(
'should return $expected when $search is searched',
({ search, expected }: TestCreateTreeNodeFilter) => {
const filter = createTreeNodeFilterCreator('name', String)(search);
expect(filter(SOURCE_TREE)).toEqual(expected);
},
);
});
});
function removeParents(tree: TreeNode<Model>[]) {
@ -72,6 +130,17 @@ interface TestCreateTreeFromList {
}
interface Model {
id: 1;
pid: null;
id: number;
pid?: number;
}
interface TestCreateTreeNodeFilter {
search: string;
expected: TreeNode<SearchModel>[];
}
interface SearchModel {
id: number;
pid?: number;
name: string;
}

19
npm/ng-packs/packages/core/src/lib/utils/tree-utils.ts

@ -54,6 +54,25 @@ export function createMapFromList<T extends object, R extends unknown>(
return map;
}
export function createTreeNodeFilterCreator<T extends object>(
key: keyof T,
mapperFn: (value: any) => string,
) {
return (search: string) => {
const regex = new RegExp('.*' + search + '.*', 'i');
return function collectNodes(nodes: TreeNode<T>[], matches = []) {
for (const node of nodes) {
if (regex.test(mapperFn(node[key]))) matches.push(node);
if (node.children.length) collectNodes(node.children, matches);
}
return matches;
};
};
}
export type TreeNode<T extends object> = {
[K in keyof T]: T[K];
} & {

Loading…
Cancel
Save