diff --git a/modules/cms-kit/host/Volo.CmsKit.Web.Unified/wwwroot/libs/malihu-custom-scrollbar-plugin/mCSB_buttons.png b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/wwwroot/libs/malihu-custom-scrollbar-plugin/mCSB_buttons.png index 74424318a4..985a9b8b5a 100644 Binary files a/modules/cms-kit/host/Volo.CmsKit.Web.Unified/wwwroot/libs/malihu-custom-scrollbar-plugin/mCSB_buttons.png and b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/wwwroot/libs/malihu-custom-scrollbar-plugin/mCSB_buttons.png differ diff --git a/modules/cms-kit/host/Volo.CmsKit.Web.Unified/wwwroot/libs/prismjs/LICENSE b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/wwwroot/libs/prismjs/LICENSE new file mode 100644 index 0000000000..528949f42d --- /dev/null +++ b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/wwwroot/libs/prismjs/LICENSE @@ -0,0 +1,21 @@ +MIT LICENSE + +Copyright (c) 2012 Lea Verou + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Comments/CommentApprovalDto.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Comments/CommentApprovalDto.cs new file mode 100644 index 0000000000..79c2813beb --- /dev/null +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Comments/CommentApprovalDto.cs @@ -0,0 +1,9 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Volo.CmsKit.Admin.Comments; +public class CommentApprovalDto +{ + public bool IsApproved { get; set; } +} diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Comments/CommentDto.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Comments/CommentDto.cs index aa64135270..4a51749fdb 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Comments/CommentDto.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Comments/CommentDto.cs @@ -19,4 +19,6 @@ public class CommentDto : ExtensibleObject public Guid CreatorId { get; set; } public DateTime CreationTime { get; set; } + public bool? IsApproved { get; set; } + } diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Comments/CommentGetListInput.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Comments/CommentGetListInput.cs index 399674e520..b6f1ae61a3 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Comments/CommentGetListInput.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Comments/CommentGetListInput.cs @@ -17,4 +17,6 @@ public class CommentGetListInput : PagedAndSortedResultRequestDto public DateTime? CreationStartDate { get; set; } public DateTime? CreationEndDate { get; set; } + public bool? IsApproved { get; set; } + } diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Comments/CommentWithAuthorDto.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Comments/CommentWithAuthorDto.cs index eeef248267..9e9f29453c 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Comments/CommentWithAuthorDto.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Comments/CommentWithAuthorDto.cs @@ -23,4 +23,6 @@ public class CommentWithAuthorDto : ExtensibleObject public CmsUserDto Author { get; set; } public string Url { get; set; } + public bool? IsApproved { get; set; } + } diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Comments/ICommentAdminAppService.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Comments/ICommentAdminAppService.cs index 5ea8d64d1d..9fed6e546a 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Comments/ICommentAdminAppService.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Comments/ICommentAdminAppService.cs @@ -12,4 +12,6 @@ public interface ICommentAdminAppService : IApplicationService Task GetAsync(Guid id); Task DeleteAsync(Guid id); + Task UpdateApprovalStatusAsync(Guid id, CommentApprovalDto commentApprovalDto); + } diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Comments/CommentAdminAppService.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Comments/CommentAdminAppService.cs index 973a74b58e..a5d41ccd68 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Comments/CommentAdminAppService.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Comments/CommentAdminAppService.cs @@ -74,4 +74,14 @@ public class CommentAdminAppService : CmsKitAdminAppServiceBase, ICommentAdminAp var comment = await CommentRepository.GetAsync(id); await CommentRepository.DeleteWithRepliesAsync(comment); } + + + + public async Task UpdateApprovalStatusAsync(Guid id, CommentApprovalDto commentApprovalDto) + { + var comment = await CommentRepository.GetAsync(id); + comment.IsApproved = commentApprovalDto.IsApproved; + + await CommentRepository.UpdateAsync(comment); + } } diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi.Client/ClientProxies/Volo/CmsKit/Admin/Comments/CommentAdminClientProxy.Generated.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi.Client/ClientProxies/Volo/CmsKit/Admin/Comments/CommentAdminClientProxy.Generated.cs index a92570cd0e..eb3fa6b5c3 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi.Client/ClientProxies/Volo/CmsKit/Admin/Comments/CommentAdminClientProxy.Generated.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi.Client/ClientProxies/Volo/CmsKit/Admin/Comments/CommentAdminClientProxy.Generated.cs @@ -40,4 +40,13 @@ public partial class CommentAdminClientProxy : ClientProxyBase, IHasCreationTime, IMustHaveCreator, public virtual string Url { get; set; } public virtual string IdempotencyToken { get; set; } + public virtual bool? IsApproved { get; set; } - protected Comment() + protected Comment() { } diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Comments/ICommentRepository.cs b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Comments/ICommentRepository.cs index b054f11037..3c12242d89 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Comments/ICommentRepository.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Comments/ICommentRepository.cs @@ -9,41 +9,45 @@ namespace Volo.CmsKit.Comments; public interface ICommentRepository : IBasicRepository { - Task GetWithAuthorAsync(Guid id, CancellationToken cancellationToken = default); - - Task> GetListAsync( - string filter = null, - string entityType = 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 GetCountAsync( - string text = null, - string entityType = null, - Guid? repliedCommentId = null, - string authorUsername = null, - DateTime? creationStartDate = null, - DateTime? creationEndDate = null, - CancellationToken cancellationToken = default - ); - - Task> GetListWithAuthorsAsync( - [NotNull] string entityType, - [NotNull] string entityId, - CancellationToken cancellationToken = default - ); - - Task DeleteWithRepliesAsync( - Comment comment, - CancellationToken cancellationToken = default - ); - - Task ExistsAsync(string idempotencyToken, CancellationToken cancellationToken = default); + Task GetWithAuthorAsync(Guid id, CancellationToken cancellationToken = default); + + Task> GetListAsync( + string filter = null, + string entityType = null, + Guid? repliedCommentId = null, + string authorUsername = null, + DateTime? creationStartDate = null, + DateTime? creationEndDate = null, + string sorting = null, + int maxResultCount = int.MaxValue, + int skipCount = 0, + bool? isApproved = null, + + CancellationToken cancellationToken = default + + ); + + Task GetCountAsync( + string text = null, + string entityType = null, + Guid? repliedCommentId = null, + string authorUsername = null, + DateTime? creationStartDate = null, + DateTime? creationEndDate = null, + bool? isApproved = null, + CancellationToken cancellationToken = default + ); + + Task> GetListWithAuthorsAsync( + [NotNull] string entityType, + [NotNull] string entityId, + CancellationToken cancellationToken = default + ); + + Task DeleteWithRepliesAsync( + Comment comment, + CancellationToken cancellationToken = default + ); + + Task ExistsAsync(string idempotencyToken, CancellationToken cancellationToken = default); } diff --git a/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Comments/EfCoreCommentRepository.cs b/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Comments/EfCoreCommentRepository.cs index 2f626a5cd7..92a179f01e 100644 --- a/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Comments/EfCoreCommentRepository.cs +++ b/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Comments/EfCoreCommentRepository.cs @@ -15,164 +15,173 @@ using Volo.CmsKit.Users; namespace Volo.CmsKit.Comments; public class EfCoreCommentRepository : EfCoreRepository, - ICommentRepository + ICommentRepository { - public EfCoreCommentRepository(IDbContextProvider dbContextProvider) - : base(dbContextProvider) - { - } - - public virtual async Task GetWithAuthorAsync(Guid id, - CancellationToken cancellationToken = default) - { - var query = from comment in (await GetDbSetAsync()) - join user in (await GetDbContextAsync()).Set() 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 virtual async Task> GetListAsync( - string filter = null, - string entityType = 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, - repliedCommentId, - authorUsername, - creationStartDate, - creationEndDate, - token); - - if (!sorting.IsNullOrEmpty()) - { - sorting = "comment." + sorting; - } - - query = query.OrderBy(sorting.IsNullOrEmpty() ? "comment.creationTime desc" : sorting) - .PageBy(skipCount, maxResultCount); - - return await query.ToListAsync(token); - } - - public virtual async Task GetCountAsync( - string text = null, - string entityType = 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, - repliedCommentId, - authorUsername, - creationStartDate, - creationEndDate, - token); - - return await query.LongCountAsync(token); - } - - public virtual async Task> GetListWithAuthorsAsync( - string entityType, - string entityId, - CancellationToken cancellationToken = default) - { - Check.NotNullOrWhiteSpace(entityType, nameof(entityType)); - Check.NotNullOrWhiteSpace(entityId, nameof(entityId)); - - var query = from comment in (await GetDbSetAsync()) - join user in (await GetDbContextAsync()).Set() on comment.CreatorId equals user.Id - where entityType == comment.EntityType && entityId == comment.EntityId - orderby comment.CreationTime - select new CommentWithAuthorQueryResultItem - { - Comment = comment, - Author = user - }; - - return await query.ToListAsync(GetCancellationToken(cancellationToken)); - } - - public virtual async Task DeleteWithRepliesAsync( - Comment comment, - CancellationToken cancellationToken = default) - { - var replies = await (await GetDbSetAsync()) - .Where(x => x.RepliedCommentId == comment.Id) - .ToListAsync(GetCancellationToken(cancellationToken)); - - foreach (var reply in replies) - { - await DeleteAsync( - reply, - cancellationToken: GetCancellationToken(cancellationToken) - ); - } - - await DeleteAsync(comment, cancellationToken: GetCancellationToken(cancellationToken)); - } - - public virtual async Task ExistsAsync(string idempotencyToken, CancellationToken cancellationToken = default) - { - return await (await GetDbSetAsync()).AnyAsync(x => x.IdempotencyToken == idempotencyToken, GetCancellationToken(cancellationToken)); - } - - protected virtual async Task> GetListQueryAsync( - string filter = null, - string entityType = 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(); - - 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(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); - } + public EfCoreCommentRepository(IDbContextProvider dbContextProvider) + : base(dbContextProvider) + { + } + + public virtual async Task GetWithAuthorAsync(Guid id, + CancellationToken cancellationToken = default) + { + var query = from comment in (await GetDbSetAsync()) + join user in (await GetDbContextAsync()).Set() 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 virtual async Task> GetListAsync( + string filter = null, + string entityType = null, + Guid? repliedCommentId = null, + string authorUsername = null, + DateTime? creationStartDate = null, + DateTime? creationEndDate = null, + string sorting = null, + int maxResultCount = int.MaxValue, + int skipCount = 0, + bool? isApproved = null, + CancellationToken cancellationToken = default + ) + { + var token = GetCancellationToken(cancellationToken); + var query = await GetListQueryAsync( + filter, + entityType, + repliedCommentId, + authorUsername, + creationStartDate, + creationEndDate, + isApproved, + token); + + if (!sorting.IsNullOrEmpty()) + { + sorting = "comment." + sorting; + } + + query = query.OrderBy(sorting.IsNullOrEmpty() ? "comment.creationTime desc" : sorting) + .PageBy(skipCount, maxResultCount); + + return await query.ToListAsync(token); + } + + public virtual async Task GetCountAsync( + string text = null, + string entityType = null, + Guid? repliedCommentId = null, + string authorUsername = null, + DateTime? creationStartDate = null, + DateTime? creationEndDate = null, + bool? isApproved = null, + CancellationToken cancellationToken = default + + ) + { + var token = GetCancellationToken(cancellationToken); + var query = await GetListQueryAsync( + text, + entityType, + repliedCommentId, + authorUsername, + creationStartDate, + creationEndDate, + isApproved, + token); + + return await query.LongCountAsync(token); + } + + public virtual async Task> GetListWithAuthorsAsync( + string entityType, + string entityId, + CancellationToken cancellationToken = default) + { + Check.NotNullOrWhiteSpace(entityType, nameof(entityType)); + Check.NotNullOrWhiteSpace(entityId, nameof(entityId)); + + var query = from comment in (await GetDbSetAsync()) + join user in (await GetDbContextAsync()).Set() on comment.CreatorId equals user.Id + where entityType == comment.EntityType && entityId == comment.EntityId + orderby comment.CreationTime + select new CommentWithAuthorQueryResultItem + { + Comment = comment, + Author = user + }; + + return await query.ToListAsync(GetCancellationToken(cancellationToken)); + } + + public virtual async Task DeleteWithRepliesAsync( + Comment comment, + CancellationToken cancellationToken = default) + { + var replies = await (await GetDbSetAsync()) + .Where(x => x.RepliedCommentId == comment.Id) + .ToListAsync(GetCancellationToken(cancellationToken)); + + foreach (var reply in replies) + { + await DeleteAsync( + reply, + cancellationToken: GetCancellationToken(cancellationToken) + ); + } + + await DeleteAsync(comment, cancellationToken: GetCancellationToken(cancellationToken)); + } + + public virtual async Task ExistsAsync(string idempotencyToken, CancellationToken cancellationToken = default) + { + return await (await GetDbSetAsync()).AnyAsync(x => x.IdempotencyToken == idempotencyToken, GetCancellationToken(cancellationToken)); + } + + protected virtual async Task> GetListQueryAsync( + string filter = null, + string entityType = null, + Guid? repliedCommentId = null, + string authorUsername = null, + DateTime? creationStartDate = null, + DateTime? creationEndDate = null, + bool? isApproved = null, + + CancellationToken cancellationToken = default + + ) + { + var commentDbSet = await GetDbSetAsync(); + var cmsUserSet = (await GetDbContextAsync()).Set(); + + 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(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) + .WhereIf(isApproved.HasValue, c => c.Comment.IsApproved == isApproved); + } } diff --git a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Comments/MongoCommentRepository.cs b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Comments/MongoCommentRepository.cs index 698c533b4e..de28984289 100644 --- a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Comments/MongoCommentRepository.cs +++ b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Comments/MongoCommentRepository.cs @@ -16,180 +16,186 @@ namespace Volo.CmsKit.MongoDB.Comments; public class MongoCommentRepository : MongoDbRepository, ICommentRepository { - public MongoCommentRepository(IMongoDbContextProvider dbContextProvider) : base(dbContextProvider) - { - } - - public virtual async Task GetWithAuthorAsync(Guid id, CancellationToken cancellationToken = default) - { - var comment = await GetAsync(id); - var author = await (await GetDbContextAsync()) - .CmsUsers - .AsQueryable() - .FirstOrDefaultAsync(x => x.Id == comment.CreatorId, GetCancellationToken(cancellationToken)); - - return new CommentWithAuthorQueryResultItem() - { - Comment = comment, - Author = author - }; - } - - public virtual async Task> GetListAsync( - string filter = null, - string entityType = 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, - repliedCommentId, - authorUsername, - creationStartDate, - creationEndDate, - token); - - var comments = await query.OrderBy(sorting.IsNullOrEmpty() ? "creationTime desc" : sorting) - .As>() - .PageBy>(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 ApplyDataFilters, CmsUser>(authorsQuery).ToListAsync(token); - - return comments - .Select( - comment => - new CommentWithAuthorQueryResultItem - { - Comment = comment, - Author = authors.FirstOrDefault(a => a.Id == comment.CreatorId) - }).ToList(); - } - - public virtual async Task GetCountAsync( - string text = null, - string entityType = null, - Guid? repliedCommentId = null, - string authorUsername = null, - DateTime? creationStartDate = null, - DateTime? creationEndDate = null, - CancellationToken cancellationToken = default - ) - { - var query = await GetListQueryAsync( - text, - entityType, - repliedCommentId, - authorUsername, - creationStartDate, - creationEndDate, - cancellationToken); - - return await query.As>() - .LongCountAsync(GetCancellationToken(cancellationToken)); - } - - public virtual async Task> GetListWithAuthorsAsync( - string entityType, - string entityId, - CancellationToken cancellationToken = default) - { - Check.NotNullOrWhiteSpace(entityType, nameof(entityType)); - Check.NotNullOrWhiteSpace(entityId, nameof(entityId)); - - var authorsQuery = from comment in (await GetMongoQueryableAsync(cancellationToken)) - join user in (await GetDbContextAsync(cancellationToken)).CmsUsers on comment.CreatorId equals user.Id - where entityType == comment.EntityType && entityId == comment.EntityId - orderby comment.CreationTime - select user; - - var authors = await ApplyDataFilters, CmsUser>(authorsQuery).ToListAsync(GetCancellationToken(cancellationToken)); - - var comments = await (await GetMongoQueryableAsync(cancellationToken)) - .Where(c => c.EntityId == entityId && c.EntityType == entityType) - .OrderBy(c => c.CreationTime) - .ToListAsync(GetCancellationToken(cancellationToken)); - - return comments - .Select( - comment => - new CommentWithAuthorQueryResultItem - { - Comment = comment, - Author = authors.FirstOrDefault(a => a.Id == comment.CreatorId) - }).ToList(); - } - - public virtual async Task DeleteWithRepliesAsync( - Comment comment, - CancellationToken cancellationToken = default) - { - var replies = await (await GetMongoQueryableAsync(cancellationToken)) - .Where(x => x.RepliedCommentId == comment.Id) - .ToListAsync(GetCancellationToken(cancellationToken)); - - await base.DeleteAsync( - comment, - cancellationToken: GetCancellationToken(cancellationToken) - ); - - foreach (var reply in replies) - { - await base.DeleteAsync( - reply, - cancellationToken: GetCancellationToken(cancellationToken) - ); - } - } - - public virtual async Task ExistsAsync(string idempotencyToken, CancellationToken cancellationToken = default) - { - return await (await GetMongoQueryableAsync(cancellationToken)) - .AnyAsync(x => x.IdempotencyToken == idempotencyToken, GetCancellationToken(cancellationToken)); - } - - protected virtual async Task> GetListQueryAsync( - string filter = null, - string entityType = 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 author = await (await GetMongoQueryableAsync(cancellationToken)).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(repliedCommentId.HasValue, c => c.RepliedCommentId == repliedCommentId) - .WhereIf(creationStartDate.HasValue, c => c.CreationTime >= creationStartDate) - .WhereIf(creationEndDate.HasValue, c => c.CreationTime <= creationEndDate); - } + public MongoCommentRepository(IMongoDbContextProvider dbContextProvider) : base(dbContextProvider) + { + } + + public virtual async Task GetWithAuthorAsync(Guid id, CancellationToken cancellationToken = default) + { + var comment = await GetAsync(id); + var author = await (await GetDbContextAsync()) + .CmsUsers + .AsQueryable() + .FirstOrDefaultAsync(x => x.Id == comment.CreatorId, GetCancellationToken(cancellationToken)); + + return new CommentWithAuthorQueryResultItem() + { + Comment = comment, + Author = author + }; + } + + public virtual async Task> GetListAsync( + string filter = null, + string entityType = null, + Guid? repliedCommentId = null, + string authorUsername = null, + DateTime? creationStartDate = null, + DateTime? creationEndDate = null, + string sorting = null, + int maxResultCount = int.MaxValue, + int skipCount = 0, + bool? isApproved = null, + CancellationToken cancellationToken = default + ) + { + var token = GetCancellationToken(cancellationToken); + var query = await GetListQueryAsync( + filter, + entityType, + repliedCommentId, + authorUsername, + creationStartDate, + creationEndDate, + isApproved, + token); + + var comments = await query.OrderBy(sorting.IsNullOrEmpty() ? "creationTime desc" : sorting) + .As>() + .PageBy>(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 ApplyDataFilters, CmsUser>(authorsQuery).ToListAsync(token); + + return comments + .Select( + comment => + new CommentWithAuthorQueryResultItem + { + Comment = comment, + Author = authors.FirstOrDefault(a => a.Id == comment.CreatorId) + }).ToList(); + } + + public virtual async Task GetCountAsync( + string text = null, + string entityType = null, + Guid? repliedCommentId = null, + string authorUsername = null, + DateTime? creationStartDate = null, + DateTime? creationEndDate = null, + bool? isApproved = null, + CancellationToken cancellationToken = default + ) + { + var query = await GetListQueryAsync( + text, + entityType, + repliedCommentId, + authorUsername, + creationStartDate, + creationEndDate, + isApproved, + cancellationToken); + + return await query.As>() + .LongCountAsync(GetCancellationToken(cancellationToken)); + } + + public virtual async Task> GetListWithAuthorsAsync( + string entityType, + string entityId, + CancellationToken cancellationToken = default) + { + Check.NotNullOrWhiteSpace(entityType, nameof(entityType)); + Check.NotNullOrWhiteSpace(entityId, nameof(entityId)); + + var authorsQuery = from comment in (await GetMongoQueryableAsync(cancellationToken)) + join user in (await GetDbContextAsync(cancellationToken)).CmsUsers on comment.CreatorId equals user.Id + where entityType == comment.EntityType && entityId == comment.EntityId + orderby comment.CreationTime + select user; + + var authors = await ApplyDataFilters, CmsUser>(authorsQuery).ToListAsync(GetCancellationToken(cancellationToken)); + + var comments = await (await GetMongoQueryableAsync(cancellationToken)) + .Where(c => c.EntityId == entityId && c.EntityType == entityType) + .OrderBy(c => c.CreationTime) + .ToListAsync(GetCancellationToken(cancellationToken)); + + return comments + .Select( + comment => + new CommentWithAuthorQueryResultItem + { + Comment = comment, + Author = authors.FirstOrDefault(a => a.Id == comment.CreatorId) + }).ToList(); + } + + public virtual async Task DeleteWithRepliesAsync( + Comment comment, + CancellationToken cancellationToken = default) + { + var replies = await (await GetMongoQueryableAsync(cancellationToken)) + .Where(x => x.RepliedCommentId == comment.Id) + .ToListAsync(GetCancellationToken(cancellationToken)); + + await base.DeleteAsync( + comment, + cancellationToken: GetCancellationToken(cancellationToken) + ); + + foreach (var reply in replies) + { + await base.DeleteAsync( + reply, + cancellationToken: GetCancellationToken(cancellationToken) + ); + } + } + + public virtual async Task ExistsAsync(string idempotencyToken, CancellationToken cancellationToken = default) + { + return await (await GetMongoQueryableAsync(cancellationToken)) + .AnyAsync(x => x.IdempotencyToken == idempotencyToken, GetCancellationToken(cancellationToken)); + } + + protected virtual async Task> GetListQueryAsync( + string filter = null, + string entityType = null, + Guid? repliedCommentId = null, + string authorUsername = null, + DateTime? creationStartDate = null, + DateTime? creationEndDate = null, + bool? isApproved = null, + CancellationToken cancellationToken = default + ) + { + var queryable = await GetMongoQueryableAsync(cancellationToken); + + if (!string.IsNullOrEmpty(authorUsername)) + { + var author = await (await GetMongoQueryableAsync(cancellationToken)).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(repliedCommentId.HasValue, c => c.RepliedCommentId == repliedCommentId) + .WhereIf(creationStartDate.HasValue, c => c.CreationTime >= creationStartDate) + .WhereIf(creationEndDate.HasValue, c => c.CreationTime <= creationEndDate) + .WhereIf(isApproved.HasValue, c => c.IsApproved == isApproved); + } }