diff --git a/README.md b/README.md index 5f8e037177..e71c85a2c3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # ABP -[![Build Status](https://travis-ci.org/volosoft/abp.svg?branch=master)](https://travis-ci.org/volosoft/abp) +[![Build Status](http://vjenkins.dynu.net:5480/job/abp/badge/icon)](http://vjenkins.dynu.net:5480/blue/organizations/jenkins/abp/activity) This project is the next generation of the [ASP.NET Boilerplate](https://aspnetboilerplate.com/) web application framework. diff --git a/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AutoMapperExpressionExtensions.cs b/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AutoMapperExpressionExtensions.cs index e41e949bae..d8cc559d0f 100644 --- a/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AutoMapperExpressionExtensions.cs +++ b/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AutoMapperExpressionExtensions.cs @@ -6,9 +6,9 @@ namespace Volo.Abp.AutoMapper { public static class AutoMapperExpressionExtensions { - public static void Ignore(this IMappingExpression mappingExpression, Expression> destinationMember) + public static IMappingExpression Ignore(this IMappingExpression mappingExpression, Expression> destinationMember) { - mappingExpression.ForMember(destinationMember, opts => opts.Ignore()); + return mappingExpression.ForMember(destinationMember, opts => opts.Ignore()); } } } diff --git a/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Comments/Dtos/CommentDto.cs b/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Comments/Dtos/CommentWithDetailsDto.cs similarity index 58% rename from modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Comments/Dtos/CommentDto.cs rename to modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Comments/Dtos/CommentWithDetailsDto.cs index f43b7f552b..7c39dc5142 100644 --- a/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Comments/Dtos/CommentDto.cs +++ b/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Comments/Dtos/CommentWithDetailsDto.cs @@ -1,12 +1,15 @@ using System; using Volo.Abp.Application.Dtos; +using Volo.Blogging.Posts; namespace Volo.Blogging.Comments.Dtos { - public class CommentDto : FullAuditedEntityDto + public class CommentWithDetailsDto : FullAuditedEntityDto { public Guid? RepliedCommentId { get; set; } public string Text { get; set; } + + public BlogUserDto Writer { get; set; } } } diff --git a/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Comments/Dtos/CommentWithRepliesDto.cs b/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Comments/Dtos/CommentWithRepliesDto.cs index 968e026fdf..1a136005be 100644 --- a/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Comments/Dtos/CommentWithRepliesDto.cs +++ b/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Comments/Dtos/CommentWithRepliesDto.cs @@ -4,8 +4,8 @@ namespace Volo.Blogging.Comments.Dtos { public class CommentWithRepliesDto { - public CommentDto Comment { get; set; } + public CommentWithDetailsDto Comment { get; set; } - public List Replies { get; set; } = new List(); + public List Replies { get; set; } = new List(); } } diff --git a/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Comments/ICommentAppService.cs b/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Comments/ICommentAppService.cs index 32b4f4cd18..d91b66ae80 100644 --- a/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Comments/ICommentAppService.cs +++ b/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Comments/ICommentAppService.cs @@ -10,9 +10,9 @@ namespace Volo.Blogging.Comments { Task> GetHierarchicalListOfPostAsync(GetCommentListOfPostAsync input); - Task CreateAsync(CreateCommentDto input); + Task CreateAsync(CreateCommentDto input); - Task UpdateAsync(Guid id, UpdateCommentDto input); + Task UpdateAsync(Guid id, UpdateCommentDto input); Task DeleteAsync(Guid id); } diff --git a/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/BloggingApplicationAutoMapperProfile.cs b/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/BloggingApplicationAutoMapperProfile.cs index d769e3e248..80ac9b8fb2 100644 --- a/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/BloggingApplicationAutoMapperProfile.cs +++ b/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/BloggingApplicationAutoMapperProfile.cs @@ -16,8 +16,8 @@ namespace Volo.Blogging { CreateMap(); CreateMap(); - CreateMap().Ignore(x=>x.CommentCount); - CreateMap(); + CreateMap().ForMember(x => x.Writer, opt => opt.Ignore()).Ignore(x=>x.CommentCount); + CreateMap().ForMember(x => x.Writer, opt => opt.Ignore()); CreateMap(); } } diff --git a/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Comments/CommentAppService.cs b/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Comments/CommentAppService.cs index 02dee1b1ca..4b675491b9 100644 --- a/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Comments/CommentAppService.cs +++ b/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Comments/CommentAppService.cs @@ -5,25 +5,54 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Volo.Abp.Application.Services; using Volo.Abp.Guids; +using Volo.Abp.Users; using Volo.Blogging.Comments.Dtos; +using Volo.Blogging.Posts; +using Volo.Blogging.Users; namespace Volo.Blogging.Comments { // [Authorize(BloggingPermissions.Comments.Default)] public class CommentAppService : ApplicationService, ICommentAppService { + protected IBlogUserLookupService UserLookupService; + private readonly ICommentRepository _commentRepository; private readonly IGuidGenerator _guidGenerator; - public CommentAppService(ICommentRepository commentRepository, IGuidGenerator guidGenerator) + public CommentAppService(ICommentRepository commentRepository, IGuidGenerator guidGenerator, IBlogUserLookupService userLookupService) { _commentRepository = commentRepository; _guidGenerator = guidGenerator; + UserLookupService = userLookupService; } public async Task> GetHierarchicalListOfPostAsync(GetCommentListOfPostAsync input) { var comments = await GetListOfPostAsync(input); + var userDictionary = new Dictionary(); + + foreach (var commentDto in comments) + { + if (commentDto.CreatorId.HasValue) + { + var creatorUser = await UserLookupService.FindByIdAsync(commentDto.CreatorId.Value); + + if (creatorUser != null && !userDictionary.ContainsKey(creatorUser.Id)) + { + userDictionary.Add(creatorUser.Id, ObjectMapper.Map(creatorUser)); + } + } + } + + foreach (var commentDto in comments) + { + if (commentDto.CreatorId.HasValue && userDictionary.ContainsKey((Guid)commentDto.CreatorId)) + { + commentDto.Writer = userDictionary[(Guid)commentDto.CreatorId]; + } + } + var hierarchicalComments = new List(); foreach (var commentDto in comments) @@ -45,25 +74,25 @@ namespace Volo.Blogging.Comments return hierarchicalComments; } - private async Task> GetListOfPostAsync(GetCommentListOfPostAsync input) + private async Task> GetListOfPostAsync(GetCommentListOfPostAsync input) { var comments = await _commentRepository.GetListOfPostAsync(input.PostId); - return new List( - ObjectMapper.Map, List>(comments)); + return new List( + ObjectMapper.Map, List>(comments)); } [Authorize(BloggingPermissions.Comments.Create)] - public async Task CreateAsync(CreateCommentDto input) + public async Task CreateAsync(CreateCommentDto input) { var comment = new Comment(_guidGenerator.Create(), input.PostId, input.RepliedCommentId, input.Text); comment = await _commentRepository.InsertAsync(comment); - return ObjectMapper.Map(comment); + return ObjectMapper.Map(comment); } - public async Task UpdateAsync(Guid id, UpdateCommentDto input) + public async Task UpdateAsync(Guid id, UpdateCommentDto input) { var comment = await _commentRepository.GetAsync(id); @@ -76,18 +105,18 @@ namespace Volo.Blogging.Comments } [Authorize(BloggingPermissions.Comments.Update)] - private async Task UpdateAsAdminAsync(Guid id, Comment comment, UpdateCommentDto input) + private async Task UpdateAsAdminAsync(Guid id, Comment comment, UpdateCommentDto input) { return await UpdateCommentAsync(id, comment, input); } - private async Task UpdateCommentAsync(Guid id, Comment comment, UpdateCommentDto input) + private async Task UpdateCommentAsync(Guid id, Comment comment, UpdateCommentDto input) { comment.SetText(input.Text); comment = await _commentRepository.UpdateAsync(comment); - return ObjectMapper.Map(comment); + return ObjectMapper.Map(comment); } public async Task DeleteAsync(Guid id) diff --git a/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Posts/PostAppService.cs b/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Posts/PostAppService.cs index 5a6e68d542..f8d3643508 100644 --- a/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Posts/PostAppService.cs +++ b/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Posts/PostAppService.cs @@ -40,32 +40,22 @@ namespace Volo.Blogging.Posts public async Task> GetListByBlogIdAndTagName(Guid id, string tagName) { var posts = _postRepository.GetPostsByBlogId(id); - var tag = tagName.IsNullOrWhiteSpace()? null: await _tagRepository.GetByNameAsync(tagName); - - var allPostDtos = new List( - ObjectMapper.Map, List>(posts)); - - var filteredPostDtos = new List(); - var userDictionary = new Dictionary(); + var postDtos = new List(ObjectMapper.Map, List>(posts)); - foreach (var postDto in allPostDtos) + if (tag != null) { - postDto.Tags = await GetTagsOfPost(postDto.Id); - - if (tag != null && postDto.Tags.All(t => t.Id != tag.Id)) - { - continue; - } - - filteredPostDtos.Add(postDto); + postDtos = await FilterPostsByTag(postDtos, tag); } - foreach (var postDto in filteredPostDtos) + foreach (var postDto in postDtos) { postDto.CommentCount = await _commentRepository.GetCommentCountOfPostAsync(postDto.Id); + } + foreach (var postDto in postDtos) + { if (postDto.CreatorId.HasValue) { var creatorUser = await UserLookupService.FindByIdAsync(postDto.CreatorId.Value); @@ -77,7 +67,7 @@ namespace Volo.Blogging.Posts } } - foreach (var postDto in filteredPostDtos) + foreach (var postDto in postDtos) { if (postDto.CreatorId.HasValue && userDictionary.ContainsKey((Guid) postDto.CreatorId)) { @@ -85,7 +75,24 @@ namespace Volo.Blogging.Posts } } - return new ListResultDto(allPostDtos); + return new ListResultDto(postDtos); + } + + private async Task> FilterPostsByTag(List allPostDtos, Tag tag) + { + var filteredPostDtos = new List(); + + foreach (var postDto in allPostDtos) + { + if (await _postTagRepository.FindByTagIdAndPostIdAsync(postDto.Id, tag.Id) == null) + { + continue; + } + + filteredPostDtos.Add(postDto); + } + + return filteredPostDtos; } public async Task GetForReadingAsync(GetPostInput input) @@ -98,6 +105,13 @@ namespace Volo.Blogging.Posts postDto.Tags = await GetTagsOfPost(postDto.Id); + if (postDto.CreatorId.HasValue) + { + var creatorUser = await UserLookupService.FindByIdAsync(postDto.CreatorId.Value); + + postDto.Writer = ObjectMapper.Map(creatorUser); + } + return postDto; } @@ -109,6 +123,13 @@ namespace Volo.Blogging.Posts postDto.Tags = await GetTagsOfPost(postDto.Id); + if (postDto.CreatorId.HasValue) + { + var creatorUser = await UserLookupService.FindByIdAsync(postDto.CreatorId.Value); + + postDto.Writer = ObjectMapper.Map(creatorUser); + } + return postDto; } diff --git a/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/IPostTagRepository.cs b/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/IPostTagRepository.cs index 7caa7ef917..f552424e93 100644 --- a/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/IPostTagRepository.cs +++ b/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/IPostTagRepository.cs @@ -7,5 +7,7 @@ namespace Volo.Blogging.Posts public interface IPostTagRepository : IBasicRepository { void DeleteOfPost(Guid id); + + Task FindByTagIdAndPostIdAsync(Guid postId, Guid tagId); } } diff --git a/modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Posts/EfCorePostTagRepository.cs b/modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Posts/EfCorePostTagRepository.cs index ff6c434d5a..e95fdeb6ca 100644 --- a/modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Posts/EfCorePostTagRepository.cs +++ b/modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Posts/EfCorePostTagRepository.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; using Volo.Abp.Domain.Repositories.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore; using Volo.Blogging.EntityFrameworkCore; @@ -18,5 +19,10 @@ namespace Volo.Blogging.Posts var recordsToDelete = DbSet.Where(pt=>pt.PostId == id); DbSet.RemoveRange(recordsToDelete); } + + public async Task FindByTagIdAndPostIdAsync(Guid postId, Guid tagId) + { + return await DbSet.FirstOrDefaultAsync(pt=> pt.PostId == postId && pt.TagId == tagId); + } } } diff --git a/modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Detail.cshtml b/modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Detail.cshtml index e7aa591fbc..71c3a6ffaf 100644 --- a/modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Detail.cshtml +++ b/modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Detail.cshtml @@ -19,16 +19,83 @@ } -
-
-
-
-
-

- @L["Volosoft"] - - @L["Blog"] - +
+
+
+
+
+

+ @L["Volosoft"] + + @L["Blog"] + +

+
+
+ +
+
+
+ + @L["Blog"] + + | + + + + | + + + + | + + + +
+
+
+
+
+
+
+
+
+
+
+

+ @foreach (var tag in Model.Post.Tags) + { + @tag.Name + } +

+

+ @Model.Post.Title

@@ -38,19 +105,19 @@ - Halil İbrahim Kalkan, @ConvertDatetimeToTimeAgo(Model.Post.CreationTime) + @(Model.Post.Writer == null ? "" : Model.Post.Writer.UserName), @ConvertDatetimeToTimeAgo(Model.Post.CreationTime) - | + | @Model.Post.ReadCount @L["Read"] - | + | @Model.CommentCount @L["Comment"] - @if (await Authorization.IsGrantedAsync(BloggingPermissions.Posts.Update) || (CurrentUser.Id == Model.Post.CreatorId)) + @if (await Authorization.IsGrantedAsync(BloggingPermissions.Posts.Update)) { | @@ -60,257 +127,196 @@
-
-
+

-
-
-
-
-
-
-
-

- @foreach (var tag in Model.Post.Tags) - { - @tag.Name - } -

-

- @Model.Post.Title -

-
-
- -
-
-
+
+
-
-
-
-

@Html.Raw(Model.FormattedContent)

- -
+
+
+
+
@L["TagsInThisArticle"]
+ @foreach (var tag in Model.Post.Tags) + { + @tag.Name + }
-
- -
-
-
-
@L["TagsInThisArticle"]
- @foreach (var tag in Model.Post.Tags) - { - @tag.Name - } +
+
+

@L["LeaveComment"]

-
-
-

@L["LeaveComment"]

-
-
-
-
- - -
- -
- - -
+
+
+
+ + +
+ +
+ +
-
+
+
+ + @foreach (var commentWithRepliesDto in Model.CommentsWithReplies) + { +
+ +
+
+ @(commentWithRepliesDto.Comment.Writer == null ? "" : commentWithRepliesDto.Comment.Writer.UserName) + @ConvertDatetimeToTimeAgo(commentWithRepliesDto.Comment.CreationTime) +
+

+ @commentWithRepliesDto.Comment.Text +

+
- @foreach (var commentWithRepliesDto in Model.CommentsWithReplies) - { -
- -
-
- Armağan Ünlü - @ConvertDatetimeToTimeAgo(commentWithRepliesDto.Comment.CreationTime) -
-

- @commentWithRepliesDto.Comment.Text -

-
+ + @L["Reply"] + + @if (await Authorization.IsGrantedAsync(BloggingPermissions.Comments.Delete)) + { + | + + @L["Delete"] + + } - - @L["Reply"] + @if (await Authorization.IsGrantedAsync(BloggingPermissions.Comments.Update) || (CurrentUser.Id == commentWithRepliesDto.Comment.CreatorId)) + { + | + + @L["Edit"] - @if (await Authorization.IsGrantedAsync(BloggingPermissions.Comments.Delete)) - { - | - - @L["Delete"] - - } + } +
+ +
+
+

+ @L["ReplyTo"] + @(commentWithRepliesDto.Comment.Writer == null ? "" : commentWithRepliesDto.Comment.Writer.UserName) +

+
+
+ + - @if (await Authorization.IsGrantedAsync(BloggingPermissions.Comments.Update) || (CurrentUser.Id == commentWithRepliesDto.Comment.CreatorId)) - { - | - - @L["Edit"] - - } +
+ +
+ + +
+
-
+ @if (await Authorization.IsGrantedAsync(BloggingPermissions.Comments.Update) || (CurrentUser.Id == commentWithRepliesDto.Comment.CreatorId)) + { +
-

@L["ReplyTo"] Armağan Ünlü

-
- - - + +
- +
- +
+ } - @if (await Authorization.IsGrantedAsync(BloggingPermissions.Comments.Update) || (CurrentUser.Id == commentWithRepliesDto.Comment.CreatorId)) - { -
-
-
-
- -
- -
- - -
-
-
- } + @foreach (var reply in commentWithRepliesDto.Replies) + { +
+ +
+
+ @(reply.Writer == null ? "" : reply.Writer.UserName) + @ConvertDatetimeToTimeAgo(reply.CreationTime) +
+

+ @reply.Text +

+
+ + @L["Reply"] + - @foreach (var reply in commentWithRepliesDto.Replies) - { -
- -
-
- Zlatan Ibrahimovic - @ConvertDatetimeToTimeAgo(reply.CreationTime) -
-

- @reply.Text -

-
- - @L["Reply"] + @if (await Authorization.IsGrantedAsync(BloggingPermissions.Comments.Delete) || (CurrentUser.Id == commentWithRepliesDto.Comment.CreatorId)) + { + | + + @L["Delete"] + } - @if (await Authorization.IsGrantedAsync(BloggingPermissions.Comments.Delete) || (CurrentUser.Id == commentWithRepliesDto.Comment.CreatorId)) - { - | - - @L["Delete"] - - } + @if (await Authorization.IsGrantedAsync(BloggingPermissions.Comments.Update) || (CurrentUser.Id == commentWithRepliesDto.Comment.CreatorId)) + { + | + + @L["Edit"] + + } +
- @if (await Authorization.IsGrantedAsync(BloggingPermissions.Comments.Update) || (CurrentUser.Id == commentWithRepliesDto.Comment.CreatorId)) - { - | - - @L["Edit"] - - } +
+
+

+ @L["ReplyTo"] + @(commentWithRepliesDto.Comment.Writer == null ? "" : commentWithRepliesDto.Comment.Writer.UserName) +

+
+
+ + +
+ +
+ + +
+
-
+ @if (await Authorization.IsGrantedAsync(BloggingPermissions.Comments.Update) || (CurrentUser.Id == commentWithRepliesDto.Comment.CreatorId)) + { +
-

@L["ReplyTo"] Armağan Ünlü

-
- - + +
- +
- - @if (await Authorization.IsGrantedAsync(BloggingPermissions.Comments.Update) || (CurrentUser.Id == commentWithRepliesDto.Comment.CreatorId)) - { -
-
-
-
- -
- -
- - -
-
-
- } -
+ }
- } -
+
+ }
- } -
+
+ }
+
diff --git a/modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Index.cshtml b/modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Index.cshtml index 6d134c874b..90e65f610f 100644 --- a/modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Index.cshtml +++ b/modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Index.cshtml @@ -93,7 +93,7 @@ - Armağan Ünlü, @ConvertDatetimeToTimeAgo(post.CreationTime) + @post.Writer.UserName, @ConvertDatetimeToTimeAgo(post.CreationTime) | @@ -135,7 +135,7 @@ @@ -192,7 +192,7 @@ - Armağan Ünlü, @ConvertDatetimeToTimeAgo(post.CreationTime) + @post.Writer.UserName, @ConvertDatetimeToTimeAgo(post.CreationTime) |