Browse Source

Merge branch 'dev' into feature/blog-feature

pull/7745/head^2
Ilkay Ilknur 5 years ago
parent
commit
49941dd90b
  1. 7
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LoginDisplay.razor
  2. 43
      framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/RabbitMqMessageConsumer.cs
  3. 2
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/IBlogAdminAppService.cs
  4. 15
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Comments/CmsUserDto.cs
  5. 21
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Comments/CommentDto.cs
  6. 22
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Comments/CommentGetListInput.cs
  7. 25
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Comments/CommentWithAuthorDto.cs
  8. 16
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Comments/ICommentAdminAppService.cs
  9. 7
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Permissions/CmsKitAdminPermissionDefinitionProvider.cs
  10. 6
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Permissions/CmsKitAdminPermissions.cs
  11. 10
      modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/CmsKitAdminApplicationAutoMapperProfile.cs
  12. 77
      modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Comments/CommentAdminAppService.cs
  13. 2
      modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Blogs/BlogAdminController.cs
  14. 48
      modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Comments/CommentAdminController.cs
  15. 2
      modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/en.json
  16. 12
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/Blog.cs
  17. 19
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/BlogPost.cs
  18. 31
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/BlogPostManager.cs
  19. 7
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/BlogPostSlugAlreadyExistException.cs
  20. 4
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/IBlogPostManager.cs
  21. 2
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/IBlogPostRepository.cs
  22. 5
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/IBlogRepository.cs
  23. 27
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Comments/ICommentRepository.cs
  24. 9
      modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Blogs/EfCoreBlogRepository.cs
  25. 119
      modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Comments/EfCoreCommentRepository.cs
  26. 10
      modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Blogs/MongoBlogRepository.cs
  27. 133
      modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Comments/MongoCommentRepository.cs
  28. 7
      modules/cms-kit/src/Volo.CmsKit.Public.Application.Contracts/Volo/CmsKit/Public/Blogs/IBlogPostPublicAppService.cs
  29. 9
      modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Blogs/BlogPostPublicAppService.cs
  30. 10
      modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/Blogs/BlogPostPublicController.cs
  31. 51
      modules/cms-kit/test/Volo.CmsKit.Application.Tests/Comments/CommentAdminAppService_Tests.cs
  32. 27
      modules/cms-kit/test/Volo.CmsKit.TestBase/Comments/CommentRepository_Tests.cs
  33. 7
      npm/ng-packs/packages/core/src/lib/tests/ng-model.component.spec.ts

7
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LoginDisplay.razor

@ -1,11 +1,14 @@
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@using Microsoft.Extensions.Localization
@using Volo.Abp.Users
@using Volo.Abp.MultiTenancy
@using global::Localization.Resources.AbpUi
@inject ICurrentUser CurrentUser
@inject ICurrentTenant CurrentTenant
@inject IJSRuntime JsRuntime
@inject NavigationManager Navigation
@inject SignOutSessionStateManager SignOutManager
@inject IStringLocalizer<AbpUiResource> UiLocalizer
<AuthorizeView>
<Authorized>
<Dropdown>
@ -28,12 +31,12 @@
}
}
<DropdownDivider />
<DropdownItem Clicked="BeginSignOut">Logout</DropdownItem>
<DropdownItem Clicked="BeginSignOut">@UiLocalizer["Logout"]</DropdownItem>
</DropdownMenu>
</Dropdown>
</Authorized>
<NotAuthorized>
<a class="nav-link" href="authentication/login">Log in</a>
<a class="nav-link" href="authentication/login">@UiLocalizer["Login"]</a>
</NotAuthorized>
</AuthorizeView>
@code{

43
framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/RabbitMqMessageConsumer.cs

@ -90,29 +90,30 @@ namespace Volo.Abp.RabbitMQ
lock (ChannelSendSyncLock)
{
QueueBindCommands.TryPeek(out var command);
switch (command.Type)
if (QueueBindCommands.TryPeek(out var command))
{
case QueueBindType.Bind:
Channel.QueueBind(
queue: Queue.QueueName,
exchange: Exchange.ExchangeName,
routingKey: command.RoutingKey
);
break;
case QueueBindType.Unbind:
Channel.QueueUnbind(
queue: Queue.QueueName,
exchange: Exchange.ExchangeName,
routingKey: command.RoutingKey
);
break;
default:
throw new AbpException($"Unknown {nameof(QueueBindType)}: {command.Type}");
switch (command.Type)
{
case QueueBindType.Bind:
Channel.QueueBind(
queue: Queue.QueueName,
exchange: Exchange.ExchangeName,
routingKey: command.RoutingKey
);
break;
case QueueBindType.Unbind:
Channel.QueueUnbind(
queue: Queue.QueueName,
exchange: Exchange.ExchangeName,
routingKey: command.RoutingKey
);
break;
default:
throw new AbpException($"Unknown {nameof(QueueBindType)}: {command.Type}");
}
QueueBindCommands.TryDequeue(out command);
}
QueueBindCommands.TryDequeue(out command);
}
}
}

2
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/IBlogAdminAppService.cs

@ -1,6 +1,4 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
namespace Volo.CmsKit.Admin.Blogs

15
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Comments/CmsUserDto.cs

@ -0,0 +1,15 @@
using System;
namespace Volo.CmsKit.Admin.Comments
{
public class CmsUserDto
{
public Guid Id { get; set; }
public string UserName { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
}
}

21
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Comments/CommentDto.cs

@ -0,0 +1,21 @@
using System;
namespace Volo.CmsKit.Admin.Comments
{
public class CommentDto
{
public Guid Id { get; set; }
public string EntityType { get; set; }
public string EntityId { get; set; }
public string Text { get; set; }
public Guid? RepliedCommentId { get; set; }
public Guid CreatorId { get; set; }
public DateTime CreationTime { get; set; }
}
}

22
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Comments/CommentGetListInput.cs

@ -0,0 +1,22 @@
using System;
using Volo.Abp.Application.Dtos;
namespace Volo.CmsKit.Admin.Comments
{
public class CommentGetListInput : PagedAndSortedResultRequestDto
{
public string EntityType { get; set; }
public string EntityId { get; set; }
public string Text { get; set; }
public Guid? RepliedCommentId { get; set; }
public string Author { get; set; }
public DateTime? CreationStartDate { get; set; }
public DateTime? CreationEndDate { get; set; }
}
}

25
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Comments/CommentWithAuthorDto.cs

@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using Volo.CmsKit.Users;
namespace Volo.CmsKit.Admin.Comments
{
public class CommentWithAuthorDto
{
public Guid Id { get; set; }
public string EntityType { get; set; }
public string EntityId { get; set; }
public string Text { get; set; }
public Guid? RepliedCommentId { get; set; }
public Guid CreatorId { get; set; }
public DateTime CreationTime { get; set; }
public CmsUserDto Author { get; set; }
}
}

16
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Comments/ICommentAdminAppService.cs

@ -0,0 +1,16 @@
using System;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
namespace Volo.CmsKit.Admin.Comments
{
public interface ICommentAdminAppService : IApplicationService
{
Task<PagedResultDto<CommentWithAuthorDto>> GetListAsync(CommentGetListInput input);
Task<CommentWithAuthorDto> GetAsync(Guid id);
Task DeleteAsync(Guid id);
}
}

7
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Permissions/CmsKitAdminPermissionDefinitionProvider.cs

@ -13,6 +13,12 @@ namespace Volo.CmsKit.Permissions
{
var cmsGroup = context.GetGroupOrNull(CmsKitAdminPermissions.GroupName) ?? context.AddGroup(CmsKitAdminPermissions.GroupName, L("Permission:CmsKit"));
if (GlobalFeatureManager.Instance.IsEnabled<CommentsFeature>())
{
var contentGroup = cmsGroup.AddPermission(CmsKitAdminPermissions.Comments.Default, L("Permission:Comments"));
contentGroup.AddChild(CmsKitAdminPermissions.Comments.Delete, L("Permission:Comments.Delete"));
}
if (GlobalFeatureManager.Instance.IsEnabled<ContentsFeature>())
{
var contentGroup = cmsGroup.AddPermission(CmsKitAdminPermissions.Contents.Default, L("Permission:Contents"));
@ -20,6 +26,7 @@ namespace Volo.CmsKit.Permissions
contentGroup.AddChild(CmsKitAdminPermissions.Contents.Update, L("Permission:Contents.Update"));
contentGroup.AddChild(CmsKitAdminPermissions.Contents.Delete, L("Permission:Contents.Delete"));
}
if (GlobalFeatureManager.Instance.IsEnabled<TagsFeature>())
{
var tagGroup = cmsGroup.AddPermission(CmsKitAdminPermissions.Tags.Default, L("Permission:TagManagement"));

6
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Permissions/CmsKitAdminPermissions.cs

@ -6,6 +6,12 @@ namespace Volo.CmsKit.Permissions
{
public const string GroupName = "CmsKit";
public static class Comments
{
public const string Default = GroupName + ".Comments";
public const string Delete = Default + ".Delete";
}
public static class Tags
{
public const string Default = GroupName + ".Tags";

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

@ -1,14 +1,18 @@
using AutoMapper;
using Volo.Abp.AutoMapper;
using Volo.CmsKit.Admin.Blogs;
using Volo.CmsKit.Admin.Comments;
using Volo.CmsKit.Admin.Contents;
using Volo.CmsKit.Admin.MediaDescriptors;
using Volo.CmsKit.Admin.Pages;
using Volo.CmsKit.Blogs;
using Volo.CmsKit.Admin.Tags;
using Volo.CmsKit.Comments;
using Volo.CmsKit.Contents;
using Volo.CmsKit.MediaDescriptors;
using Volo.CmsKit.Pages;
using Volo.CmsKit.Tags;
using Volo.CmsKit.Users;
namespace Volo.CmsKit.Admin
{
@ -16,6 +20,12 @@ namespace Volo.CmsKit.Admin
{
public CmsKitAdminApplicationAutoMapperProfile()
{
CreateMap<CmsUser, Comments.CmsUserDto>();
CreateMap<Comment, CommentDto>();
CreateMap<Comment, CommentWithAuthorDto>()
.Ignore(x=> x.Author);
CreateMap<Page, PageDto>();
CreateMap<Content, ContentDto>(MemberList.Destination);

77
modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Comments/CommentAdminAppService.cs

@ -0,0 +1,77 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Volo.Abp.Application.Dtos;
using Volo.Abp.GlobalFeatures;
using Volo.CmsKit.Comments;
using Volo.CmsKit.GlobalFeatures;
using Volo.CmsKit.Permissions;
using Volo.CmsKit.Users;
namespace Volo.CmsKit.Admin.Comments
{
[RequiresGlobalFeature(typeof(CommentsFeature))]
[Authorize(CmsKitAdminPermissions.Comments.Default)]
public class CommentAdminAppService : CmsKitAdminAppServiceBase, ICommentAdminAppService
{
protected ICommentRepository CommentRepository { get; }
public CommentAdminAppService(ICommentRepository commentRepository)
{
CommentRepository = commentRepository;
}
public virtual async Task<PagedResultDto<CommentWithAuthorDto>> GetListAsync(CommentGetListInput input)
{
var totalCount = await CommentRepository.GetCountAsync(
input.Text,
input.EntityType,
input.EntityId,
input.RepliedCommentId,
input.Author,
input.CreationStartDate,
input.CreationEndDate);
var comments = await CommentRepository.GetListAsync(
input.Text,
input.EntityType,
input.EntityId,
input.RepliedCommentId,
input.Author,
input.CreationStartDate,
input.CreationEndDate,
input.Sorting,
input.MaxResultCount,
input.SkipCount
);
var dtos = comments.Select(queryResultItem =>
{
var dto = ObjectMapper.Map<Comment, CommentWithAuthorDto>(queryResultItem.Comment);
dto.Author = ObjectMapper.Map<CmsUser, CmsUserDto>(queryResultItem.Author);
return dto;
}).ToList();
return new PagedResultDto<CommentWithAuthorDto>(totalCount, dtos);
}
public virtual async Task<CommentWithAuthorDto> GetAsync(Guid id)
{
var comment = await CommentRepository.GetWithAuthorAsync(id);
var dto = ObjectMapper.Map<Comment, CommentWithAuthorDto>(comment.Comment);
dto.Author = ObjectMapper.Map<CmsUser, CmsUserDto>(comment.Author);
return dto;
}
[Authorize(CmsKitAdminPermissions.Comments.Delete)]
public virtual async Task DeleteAsync(Guid id)
{
var comment = await CommentRepository.GetAsync(id);
await CommentRepository.DeleteWithRepliesAsync(comment);
}
}
}

2
modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Blogs/BlogAdminController.cs

@ -17,7 +17,7 @@ namespace Volo.CmsKit.Admin.Blogs
[RemoteService(Name = CmsKitCommonRemoteServiceConsts.RemoteServiceName)]
[Area("cms-kit")]
[Authorize(CmsKitAdminPermissions.Blogs.Default)]
[Route("api/cms-kit-admin/blogs/blogs")]
[Route("api/cms-kit-admin/blogs")]
public class BlogAdminController : CmsKitAdminController, IBlogAdminAppService
{
protected IBlogAdminAppService BlogAdminAppService { get; }

48
modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Comments/CommentAdminController.cs

@ -0,0 +1,48 @@
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.GlobalFeatures;
using Volo.CmsKit.GlobalFeatures;
using Volo.CmsKit.Permissions;
namespace Volo.CmsKit.Admin.Comments
{
[Authorize(CmsKitAdminPermissions.Comments.Default)]
[RequiresGlobalFeature(typeof(CommentsFeature))]
[RemoteService(Name = CmsKitCommonRemoteServiceConsts.RemoteServiceName)]
[Area("cms-kit")]
[Route("api/cms-kit-admin/comments")]
public class CommentAdminController : CmsKitAdminController, ICommentAdminAppService
{
protected ICommentAdminAppService CommentAdminAppService { get; }
public CommentAdminController(ICommentAdminAppService commentAdminAppService)
{
CommentAdminAppService = commentAdminAppService;
}
[HttpGet]
public virtual Task<PagedResultDto<CommentWithAuthorDto>> GetListAsync(CommentGetListInput input)
{
return CommentAdminAppService.GetListAsync(input);
}
[HttpGet]
[Route("{id}")]
public virtual Task<CommentWithAuthorDto> GetAsync(Guid id)
{
return CommentAdminAppService.GetAsync(id);
}
[HttpDelete]
[Route("{id}")]
[Authorize(CmsKitAdminPermissions.Comments.Delete)]
public virtual Task DeleteAsync(Guid id)
{
return CommentAdminAppService.DeleteAsync(id);
}
}
}

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

@ -19,6 +19,8 @@
"MessageDeletionConfirmationMessage": "This comment will be deleted completely.",
"Permission:BlogManagement.Features": "Features",
"Permission:CmsKit": "CmsKit",
"Permission:Comments": "Comment Management",
"Permission:Comments.Delete": "Delete",
"Permission:Contents": "Content Management",
"Permission:Contents.Create": "Create Content",
"Permission:Contents.Delete": "Delete Content",

12
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/Blog.cs

@ -20,18 +20,20 @@ namespace Volo.CmsKit.Blogs
TenantId = tenantId;
}
public string Name { get; protected set; }
[NotNull]
public virtual string Name { get; protected set; }
public string Slug { get; protected set; }
[NotNull]
public virtual string Slug { get; protected set; }
public Guid? TenantId { get; protected set; }
public virtual Guid? TenantId { get; protected set; }
public void SetName(string name)
public virtual void SetName(string name)
{
Name = Check.NotNullOrWhiteSpace(name, nameof(name), maxLength: BlogConsts.MaxNameLength);
}
public void SetSlug(string slug)
public virtual void SetSlug(string slug)
{
Check.NotNullOrWhiteSpace(slug, nameof(slug), maxLength: BlogConsts.MaxNameLength);

19
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/BlogPost.cs

@ -1,10 +1,8 @@
using JetBrains.Annotations;
using System;
using System.Text.RegularExpressions;
using Volo.Abp;
using Volo.Abp.Domain.Entities.Auditing;
using Volo.Abp.MultiTenancy;
using Volo.CmsKit.Blogs;
using Volo.CmsKit.Blogs.Extensions;
using Volo.CmsKit.Users;
@ -12,15 +10,18 @@ namespace Volo.CmsKit.Blogs
{
public class BlogPost : FullAuditedAggregateRootWithUser<Guid, CmsUser>, IMultiTenant
{
public Guid BlogId { get; protected set; }
public virtual Guid BlogId { get; protected set; }
public string Title { get; protected set; }
[NotNull]
public virtual string Title { get; protected set; }
public string Slug { get; protected set; }
[NotNull]
public virtual string Slug { get; protected set; }
public string ShortDescription { get; protected set; }
[NotNull]
public virtual string ShortDescription { get; protected set; }
public Guid? TenantId { get; protected set; }
public virtual Guid? TenantId { get; protected set; }
protected BlogPost()
{
@ -39,7 +40,7 @@ namespace Volo.CmsKit.Blogs
ShortDescription = shortDescription;
}
public void SetTitle(string title)
public virtual void SetTitle(string title)
{
Title = Check.NotNullOrWhiteSpace(title, nameof(title), BlogPostConsts.MaxTitleLength);
}
@ -51,7 +52,7 @@ namespace Volo.CmsKit.Blogs
Slug = slug.NormalizeSlug();
}
public void SetShortDescription(string shortDescription)
public virtual void SetShortDescription(string shortDescription)
{
ShortDescription = Check.Length(shortDescription, nameof(shortDescription), BlogPostConsts.MaxShortDescriptionLength);
}

31
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/BlogPostManager.cs

@ -1,8 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using JetBrains.Annotations;
using System;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Domain.Services;
@ -10,35 +9,37 @@ namespace Volo.CmsKit.Blogs
{
public class BlogPostManager : DomainService, IBlogPostManager
{
protected readonly IBlogPostRepository blogPostRepository;
protected readonly IBlogRepository blogRepository;
protected IBlogPostRepository BlogPostRepository { get; }
protected IBlogRepository BlogRepository { get; }
public BlogPostManager(
IBlogPostRepository blogPostRepository,
IBlogRepository blogRepository)
{
this.blogPostRepository = blogPostRepository;
this.blogRepository = blogRepository;
BlogPostRepository = blogPostRepository;
BlogRepository = blogRepository;
}
public async Task<BlogPost> CreateAsync(BlogPost blogPost)
public virtual async Task<BlogPost> CreateAsync(BlogPost blogPost)
{
await CheckBlogExistenceAsync(blogPost.BlogId);
await CheckSlugExistenceAsync(blogPost.BlogId, blogPost.Slug);
return await blogPostRepository.InsertAsync(blogPost);
return await BlogPostRepository.InsertAsync(blogPost);
}
public async Task UpdateAsync(BlogPost blogPost)
public virtual async Task UpdateAsync(BlogPost blogPost)
{
await CheckBlogExistenceAsync(blogPost.BlogId);
await blogPostRepository.UpdateAsync(blogPost);
await BlogPostRepository.UpdateAsync(blogPost);
}
public async Task SetSlugUrlAsync(BlogPost blogPost, string newSlug)
public virtual async Task SetSlugUrlAsync(BlogPost blogPost, [NotNull] string newSlug)
{
Check.NotNullOrWhiteSpace(newSlug, nameof(newSlug));
await CheckSlugExistenceAsync(blogPost.BlogId, newSlug);
blogPost.SetSlug(newSlug);
@ -46,7 +47,7 @@ namespace Volo.CmsKit.Blogs
private async Task CheckSlugExistenceAsync(Guid blogId, string slug)
{
if (await blogPostRepository.SlugExistsAsync(blogId, slug))
if (await BlogPostRepository.SlugExistsAsync(blogId, slug))
{
throw new BlogPostSlugAlreadyExistException(blogId, slug);
}
@ -54,7 +55,7 @@ namespace Volo.CmsKit.Blogs
private async Task CheckBlogExistenceAsync(Guid blogId)
{
if (!await blogRepository.ExistsAsync(blogId))
if (!await BlogRepository.ExistsAsync(blogId))
throw new EntityNotFoundException(typeof(Blog), blogId);
}
}

7
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/BlogPostSlugAlreadyExistException.cs

@ -1,4 +1,5 @@
using System;
using System.Runtime.Serialization;
using Volo.Abp;
namespace Volo.CmsKit.Blogs
@ -9,7 +10,7 @@ namespace Volo.CmsKit.Blogs
{
}
internal BlogPostSlugAlreadyExistException(System.Runtime.Serialization.SerializationInfo serializationInfo, System.Runtime.Serialization.StreamingContext context) : base(serializationInfo, context)
internal BlogPostSlugAlreadyExistException(SerializationInfo serializationInfo, System.Runtime.Serialization.StreamingContext context) : base(serializationInfo, context)
{
}
@ -24,8 +25,8 @@ namespace Volo.CmsKit.Blogs
WithData(nameof(BlogId), BlogId);
}
public string Slug { get; }
public virtual string Slug { get; }
public Guid BlogId { get; }
public virtual Guid BlogId { get; }
}
}

4
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/IBlogPostManager.cs

@ -1,4 +1,4 @@
using System;
using JetBrains.Annotations;
using System.Threading.Tasks;
namespace Volo.CmsKit.Blogs
@ -9,6 +9,6 @@ namespace Volo.CmsKit.Blogs
Task UpdateAsync(BlogPost blogPost);
Task SetSlugUrlAsync(BlogPost blogPost, string newSlug);
Task SetSlugUrlAsync(BlogPost blogPost, [NotNull] string newSlug);
}
}

2
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/IBlogPostRepository.cs

@ -1,7 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;

5
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/IBlogRepository.cs

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

27
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Comments/ICommentRepository.cs

@ -9,6 +9,33 @@ namespace Volo.CmsKit.Comments
{
public interface ICommentRepository : IBasicRepository<Comment, Guid>
{
Task<CommentWithAuthorQueryResultItem> GetWithAuthorAsync(Guid id, CancellationToken cancellationToken = default);
Task<List<CommentWithAuthorQueryResultItem>> GetListAsync(
string filter = null,
string entityType = null,
string entityId = null,
Guid? repliedCommentId = null,
string authorUsername = null,
DateTime? creationStartDate = null,
DateTime? creationEndDate = null,
string sorting = null,
int maxResultCount = int.MaxValue,
int skipCount = 0,
CancellationToken cancellationToken = default
);
Task<long> GetCountAsync(
string text = null,
string entityType = null,
string entityId = null,
Guid? repliedCommentId = null,
string authorUsername = null,
DateTime? creationStartDate = null,
DateTime? creationEndDate = null,
CancellationToken cancellationToken = default
);
Task<List<CommentWithAuthorQueryResultItem>> GetListWithAuthorsAsync(
[NotNull] string entityType,
[NotNull] string entityId,

9
modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Blogs/EfCoreBlogRepository.cs

@ -1,6 +1,7 @@
using Microsoft.EntityFrameworkCore;
using System;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
@ -14,14 +15,14 @@ namespace Volo.CmsKit.Blogs
{
}
public async Task<bool> ExistsAsync(Guid blogId)
public virtual async Task<bool> ExistsAsync(Guid blogId, CancellationToken cancellationToken = default)
{
return await (await GetQueryableAsync()).AnyAsync(x => x.Id == blogId);
return await (await GetQueryableAsync()).AnyAsync(x => x.Id == blogId, cancellationToken);
}
public Task<Blog> GetBySlugAsync(string slug)
public virtual Task<Blog> GetBySlugAsync(string slug, CancellationToken cancellationToken = default)
{
return GetAsync(x => x.Slug == slug);
return GetAsync(x => x.Slug == slug, cancellationToken: cancellationToken);
}
}
}

119
modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Comments/EfCoreCommentRepository.cs

@ -1,10 +1,12 @@
using System;
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;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
using Volo.CmsKit.EntityFrameworkCore;
@ -20,6 +22,89 @@ namespace Volo.CmsKit.Comments
{
}
public async Task<CommentWithAuthorQueryResultItem> GetWithAuthorAsync(Guid id,
CancellationToken cancellationToken = default)
{
var query = from comment in (await GetDbSetAsync())
join user in (await GetDbContextAsync()).Set<CmsUser>() on comment.CreatorId equals user.Id
where id == comment.Id
select new CommentWithAuthorQueryResultItem
{
Comment = comment,
Author = user
};
var commentWithAuthor = await query.FirstOrDefaultAsync(GetCancellationToken(cancellationToken));
if (commentWithAuthor == null)
{
throw new EntityNotFoundException(typeof(Comment), id);
}
return commentWithAuthor;
}
public async Task<List<CommentWithAuthorQueryResultItem>> GetListAsync(
string filter = null,
string entityType = null,
string entityId = null,
Guid? repliedCommentId = null,
string authorUsername = null,
DateTime? creationStartDate = null,
DateTime? creationEndDate = null,
string sorting = null,
int maxResultCount = int.MaxValue,
int skipCount = 0,
CancellationToken cancellationToken = default
)
{
var token = GetCancellationToken(cancellationToken);
var query = await GetListQueryAsync(
filter,
entityType,
entityId,
repliedCommentId,
authorUsername,
creationStartDate,
creationEndDate,
token);
if (sorting != null)
{
sorting = "comment." + sorting;
}
query = query.OrderBy(sorting ?? "comment.creationTime desc")
.PageBy(skipCount, maxResultCount);
return await query.ToListAsync(token);
}
public async Task<long> GetCountAsync(
string text = null,
string entityType = null,
string entityId = null,
Guid? repliedCommentId = null,
string authorUsername = null,
DateTime? creationStartDate = null,
DateTime? creationEndDate = null,
CancellationToken cancellationToken = default
)
{
var token = GetCancellationToken(cancellationToken);
var query = await GetListQueryAsync(
text,
entityType,
entityId,
repliedCommentId,
authorUsername,
creationStartDate,
creationEndDate,
token);
return await query.LongCountAsync(token);
}
public async Task<List<CommentWithAuthorQueryResultItem>> GetListWithAuthorsAsync(
string entityType,
string entityId,
@ -59,5 +144,37 @@ namespace Volo.CmsKit.Comments
await DeleteAsync(comment, cancellationToken: GetCancellationToken(cancellationToken));
}
protected virtual async Task<IQueryable<CommentWithAuthorQueryResultItem>> GetListQueryAsync(
string filter = null,
string entityType = null,
string entityId = null,
Guid? repliedCommentId = null,
string authorUsername = null,
DateTime? creationStartDate = null,
DateTime? creationEndDate = null,
CancellationToken cancellationToken = default
)
{
var commentDbSet = await GetDbSetAsync();
var cmsUserSet = (await GetDbContextAsync()).Set<CmsUser>();
var query = from comment in commentDbSet
join user in cmsUserSet
on comment.CreatorId equals user.Id
select new CommentWithAuthorQueryResultItem
{
Comment = comment,
Author = user
};
return query.WhereIf(!filter.IsNullOrWhiteSpace(), c => c.Comment.Text.Contains(filter))
.WhereIf(!entityType.IsNullOrWhiteSpace(), c => c.Comment.EntityType.Contains(entityType))
.WhereIf(!entityId.IsNullOrWhiteSpace(), c => c.Comment.EntityId.Contains(entityId))
.WhereIf(repliedCommentId.HasValue, c => c.Comment.RepliedCommentId == repliedCommentId)
.WhereIf(!authorUsername.IsNullOrWhiteSpace(),c=>c.Author.UserName.Contains(authorUsername))
.WhereIf(creationStartDate.HasValue, c => c.Comment.CreationTime >= creationStartDate)
.WhereIf(creationEndDate.HasValue, c => c.Comment.CreationTime <= creationEndDate);
}
}
}
}

10
modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Blogs/MongoBlogRepository.cs

@ -1,5 +1,6 @@
using MongoDB.Driver.Core.Operations;
using System;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories.MongoDB;
using Volo.Abp.MongoDB;
@ -13,16 +14,17 @@ namespace Volo.CmsKit.MongoDB.Blogs
{
}
public async Task<bool> ExistsAsync(Guid blogId)
public virtual async Task<bool> ExistsAsync(Guid blogId, CancellationToken cancellationToken = default)
{
return await AsyncExecuter.AnyAsync(
await GetQueryableAsync(),
x => x.Id == blogId);
x => x.Id == blogId,
cancellationToken);
}
public Task<Blog> GetBySlugAsync(string slug)
public virtual Task<Blog> GetBySlugAsync(string slug, CancellationToken cancellationToken = default)
{
return GetAsync(x => x.Slug == slug);
return GetAsync(x => x.Slug == slug, cancellationToken: cancellationToken);
}
}
}

133
modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Comments/MongoCommentRepository.cs

@ -1,14 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading;
using System.Threading.Tasks;
using MongoDB.Driver.Linq;
using MongoDB.Driver;
using MongoDB.Driver.Linq;
using Volo.Abp;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Domain.Repositories.MongoDB;
using Volo.Abp.MongoDB;
using Volo.CmsKit.Comments;
using Volo.CmsKit.Users;
namespace Volo.CmsKit.MongoDB.Comments
{
@ -18,6 +21,102 @@ namespace Volo.CmsKit.MongoDB.Comments
{
}
public async Task<CommentWithAuthorQueryResultItem> GetWithAuthorAsync(Guid id, CancellationToken cancellationToken = default)
{
var query = from comment in (await GetMongoQueryableAsync(cancellationToken))
join user in (await GetDbContextAsync(cancellationToken)).CmsUsers on comment.CreatorId equals user.Id
where id == comment.Id
select new CommentWithAuthorQueryResultItem
{
Comment = comment,
Author = user
};
var commentWithAuthor = await query.FirstOrDefaultAsync(GetCancellationToken(cancellationToken));
if (commentWithAuthor == null)
{
throw new EntityNotFoundException(typeof(Comment), id);
}
return commentWithAuthor;
}
public async Task<List<CommentWithAuthorQueryResultItem>> GetListAsync(
string filter = null,
string entityType = null,
string entityId = null,
Guid? repliedCommentId = null,
string authorUsername = null,
DateTime? creationStartDate = null,
DateTime? creationEndDate = null,
string sorting = null,
int maxResultCount = int.MaxValue,
int skipCount = 0,
CancellationToken cancellationToken = default
)
{
var token = GetCancellationToken(cancellationToken);
var query = await GetListQueryAsync(
filter,
entityType,
entityId,
repliedCommentId,
authorUsername,
creationStartDate,
creationEndDate,
token);
var comments = await query.OrderBy(sorting ?? "creationTime desc")
.As<IMongoQueryable<Comment>>()
.PageBy<Comment, IMongoQueryable<Comment>>(skipCount, maxResultCount)
.ToListAsync(token);
var commentIds = comments.Select(x => x.Id).ToList();
var authorsQuery = from comment in (await GetMongoQueryableAsync(token))
join user in (await GetDbContextAsync(token)).CmsUsers on comment.CreatorId equals user.Id
where commentIds.Contains(comment.Id)
orderby comment.CreationTime
select user;
var authors = await authorsQuery.ToListAsync(token);
return comments
.Select(
comment =>
new CommentWithAuthorQueryResultItem
{
Comment = comment,
Author = authors.FirstOrDefault(a => a.Id == comment.CreatorId)
}).ToList();
}
public async Task<long> GetCountAsync(
string text = null,
string entityType = null,
string entityId = null,
Guid? repliedCommentId = null,
string authorUsername = null,
DateTime? creationStartDate = null,
DateTime? creationEndDate = null,
CancellationToken cancellationToken = default
)
{
var query = await GetListQueryAsync(
text,
entityType,
entityId,
repliedCommentId,
authorUsername,
creationStartDate,
creationEndDate,
cancellationToken);
return await query.As<IMongoQueryable<Comment>>()
.LongCountAsync(GetCancellationToken(cancellationToken));
}
public async Task<List<CommentWithAuthorQueryResultItem>> GetListWithAuthorsAsync(
string entityType,
string entityId,
@ -70,5 +169,37 @@ namespace Volo.CmsKit.MongoDB.Comments
cancellationToken: GetCancellationToken(cancellationToken)
);
}
protected virtual async Task<IQueryable<Comment>> GetListQueryAsync(
string filter = null,
string entityType = null,
string entityId = null,
Guid? repliedCommentId = null,
string authorUsername = null,
DateTime? creationStartDate = null,
DateTime? creationEndDate = null,
CancellationToken cancellationToken = default
)
{
var queryable = await GetMongoQueryableAsync(cancellationToken);
if (!string.IsNullOrEmpty(authorUsername))
{
var authorQueryable = (await GetDbContextAsync(cancellationToken)).Collection<CmsUser>().AsQueryable();
var author = await authorQueryable.FirstOrDefaultAsync(x => x.UserName == authorUsername, cancellationToken: cancellationToken);
var authorId = author?.Id ?? Guid.Empty;
queryable = queryable.Where(x => x.CreatorId == authorId);
}
return queryable.WhereIf(!filter.IsNullOrWhiteSpace(), c => c.Text.Contains(filter))
.WhereIf(!entityType.IsNullOrWhiteSpace(), c => c.EntityType == entityType)
.WhereIf(!entityId.IsNullOrWhiteSpace(), c => c.EntityId == entityId)
.WhereIf(repliedCommentId.HasValue, c => c.RepliedCommentId == repliedCommentId)
.WhereIf(creationStartDate.HasValue, c => c.CreationTime >= creationStartDate)
.WhereIf(creationEndDate.HasValue, c => c.CreationTime <= creationEndDate);
}
}
}

7
modules/cms-kit/src/Volo.CmsKit.Public.Application.Contracts/Volo/CmsKit/Public/Blogs/IBlogPostPublicAppService.cs

@ -1,4 +1,5 @@
using System;
using JetBrains.Annotations;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
@ -8,9 +9,9 @@ namespace Volo.CmsKit.Public.Blogs
{
public interface IBlogPostPublicAppService
{
Task<PagedResultDto<BlogPostPublicDto>> GetListAsync(string blogSlug, PagedAndSortedResultRequestDto input);
Task<PagedResultDto<BlogPostPublicDto>> GetListAsync([NotNull] string blogSlug, PagedAndSortedResultRequestDto input);
Task<BlogPostPublicDto> GetAsync(string blogSlug, string blogPostSlug);
Task<BlogPostPublicDto> GetAsync([NotNull] string blogSlug, [NotNull] string blogPostSlug);
Task<RemoteStreamContent> GetCoverImageAsync(Guid id);
}

9
modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Blogs/BlogPostPublicAppService.cs

@ -1,4 +1,5 @@
using System;
using JetBrains.Annotations;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
@ -26,7 +27,7 @@ namespace Volo.CmsKit.Public.Blogs
BlobContainer = blobContainer;
}
public async Task<BlogPostPublicDto> GetAsync(string blogSlug, string blogPostSlug)
public virtual async Task<BlogPostPublicDto> GetAsync([NotNull] string blogSlug, [NotNull] string blogPostSlug)
{
var blog = await BlogRepository.GetBySlugAsync(blogSlug);
@ -35,7 +36,7 @@ namespace Volo.CmsKit.Public.Blogs
return ObjectMapper.Map<BlogPost, BlogPostPublicDto>(blogPost);
}
public async Task<PagedResultDto<BlogPostPublicDto>> GetListAsync(string blogSlug, PagedAndSortedResultRequestDto input)
public virtual async Task<PagedResultDto<BlogPostPublicDto>> GetListAsync([NotNull] string blogSlug, PagedAndSortedResultRequestDto input)
{
var blog = await BlogRepository.GetBySlugAsync(blogSlug);
@ -46,7 +47,7 @@ namespace Volo.CmsKit.Public.Blogs
ObjectMapper.Map<List<BlogPost>, List<BlogPostPublicDto>>(blogPosts));
}
public async Task<RemoteStreamContent> GetCoverImageAsync(Guid id)
public virtual async Task<RemoteStreamContent> GetCoverImageAsync(Guid id)
{
var stream = await BlobContainer.GetAsync(id.ToString());

10
modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/Blogs/BlogPostPublicController.cs

@ -1,15 +1,11 @@
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Content;
using Volo.Abp.GlobalFeatures;
using Volo.CmsKit.GlobalFeatures;
using Volo.CmsKit.Public.Blogs;
namespace Volo.CmsKit.Public.Blogs
{
@ -28,14 +24,14 @@ namespace Volo.CmsKit.Public.Blogs
[HttpGet]
[Route("{blogSlug}/{blogPostSlug}")]
public Task<BlogPostPublicDto> GetAsync(string blogSlug, string blogPostSlug)
public virtual Task<BlogPostPublicDto> GetAsync(string blogSlug, string blogPostSlug)
{
return BlogPostPublicAppService.GetAsync(blogSlug, blogPostSlug);
}
[HttpGet]
[Route("{id}/cover-image")]
public Task<RemoteStreamContent> GetCoverImageAsync(Guid id)
public virtual Task<RemoteStreamContent> GetCoverImageAsync(Guid id)
{
Response.Headers.Add("Content-Disposition", $"inline;filename=\"{id}\"");
Response.Headers.Add("Accept-Ranges", "bytes");
@ -47,7 +43,7 @@ namespace Volo.CmsKit.Public.Blogs
[HttpGet]
[Route("{blogSlug}")]
public Task<PagedResultDto<BlogPostPublicDto>> GetListAsync(string blogSlug, PagedAndSortedResultRequestDto input)
public virtual Task<PagedResultDto<BlogPostPublicDto>> GetListAsync(string blogSlug, PagedAndSortedResultRequestDto input)
{
return BlogPostPublicAppService.GetListAsync(blogSlug, input);
}

51
modules/cms-kit/test/Volo.CmsKit.Application.Tests/Comments/CommentAdminAppService_Tests.cs

@ -0,0 +1,51 @@
using System.Linq;
using System.Threading.Tasks;
using Shouldly;
using Volo.Abp.Domain.Entities;
using Volo.CmsKit.Admin.Comments;
using Xunit;
namespace Volo.CmsKit.Comments
{
public class CommentAdminAppService_Tests : CmsKitApplicationTestBase
{
private readonly ICommentAdminAppService _commentAdminAppService;
private readonly CmsKitTestData _cmsKitTestData;
public CommentAdminAppService_Tests()
{
_commentAdminAppService = GetRequiredService<ICommentAdminAppService>();
_cmsKitTestData = GetRequiredService<CmsKitTestData>();
}
[Fact]
public async Task ShouldGet_PagedListAsync()
{
var comments = await _commentAdminAppService.GetListAsync(new CommentGetListInput
{
MaxResultCount = 3
});
comments.TotalCount.ShouldBe(6);
comments.Items.Count.ShouldBe(3);
comments.Items.Any(x => x.Author != null).ShouldBeTrue();
}
[Fact]
public async Task ShouldGet_CommentWithAuthorAsync()
{
var comment = await _commentAdminAppService.GetAsync(_cmsKitTestData.CommentWithChildId);
comment.ShouldNotBeNull();
comment.Author.ShouldNotBeNull();
}
[Fact]
public async Task ShouldDelete_WithRepliesAsync()
{
await _commentAdminAppService.DeleteAsync(_cmsKitTestData.CommentWithChildId);
await Should.ThrowAsync<EntityNotFoundException>(async () => await _commentAdminAppService.GetAsync(_cmsKitTestData.CommentWithChildId));
}
}
}

27
modules/cms-kit/test/Volo.CmsKit.TestBase/Comments/CommentRepository_Tests.cs

@ -18,6 +18,31 @@ namespace Volo.CmsKit.Comments
_commentRepository = GetRequiredService<ICommentRepository>();
}
[Fact]
public async Task GetList_ShouldWork()
{
var comments = await _commentRepository.GetListAsync();
comments.ShouldNotBeNull();
comments.Count.ShouldBe(6);
var headCommentId = comments.First(x => x.Comment.RepliedCommentId != null).Comment.RepliedCommentId;
var replies = await _commentRepository.GetListAsync(repliedCommentId: headCommentId);
replies.ShouldNotBeNull();
replies.Count.ShouldBeLessThan(6);
replies.Count.ShouldBeGreaterThanOrEqualTo(1);
}
[Fact]
public async Task GetCount_ShouldWork()
{
var commentsCount = await _commentRepository.GetCountAsync();
commentsCount.ShouldBe(6);
}
[Fact]
public async Task GetListWithAuthorsAsync()
{
@ -38,7 +63,7 @@ namespace Volo.CmsKit.Comments
var list = await _commentRepository.GetListAsync();
list.Any(x=>
x.Id == _cmsKitTestData.CommentWithChildId || x.RepliedCommentId == _cmsKitTestData.CommentWithChildId)
x.Comment.Id == _cmsKitTestData.CommentWithChildId || x.Comment.RepliedCommentId == _cmsKitTestData.CommentWithChildId)
.ShouldBeFalse();
}
}

7
npm/ng-packs/packages/core/src/lib/tests/ng-model.component.spec.ts

@ -1,8 +1,8 @@
import { Component, forwardRef, Input, OnInit } from '@angular/core';
import { Component, Input, OnInit } from '@angular/core';
import { FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
import { createHostFactory, SpectatorHost } from '@ngneat/spectator/jest';
import { AbstractNgModelComponent } from '../abstracts';
import { timer } from 'rxjs';
import { AbstractNgModelComponent } from '../abstracts';
@Component({
selector: 'abp-test',
@ -10,8 +10,7 @@ import { timer } from 'rxjs';
providers: [
{
provide: NG_VALUE_ACCESSOR,
// tslint:disable-next-line: no-forward-ref
useExisting: forwardRef(() => TestComponent),
useExisting: TestComponent,
multi: true,
},
],

Loading…
Cancel
Save