Browse Source

Blogging module improvements

pull/441/head
Yunus Emre Kalkan 8 years ago
parent
commit
f7c53184db
  1. 2
      modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/BloggingTestAppDbContextModelSnapshot.cs
  2. 10707
      modules/blogging/app/Volo.BloggingTestApp/Logs/logs.txt
  3. 15
      modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/BloggingPermissionDefinitionProvider.cs
  4. 32
      modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/BloggingPermissions.cs
  5. 2
      modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Blogs/IBlogAppService.cs
  6. 3
      modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Comments/Dtos/CommentDto.cs
  7. 5
      modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Comments/Dtos/CommentWithRepliesDto.cs
  8. 1
      modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Comments/ICommentAppService.cs
  9. 4
      modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Posts/IPostAppService.cs
  10. 1
      modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Posts/PostWithDetailsDto.cs
  11. 3
      modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Posts/UpdatePostDto.cs
  12. 3
      modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Tagging/ITagAppService.cs
  13. 5
      modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Comments/CommentAppService.cs
  14. 24
      modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Posts/PostAppService.cs
  15. 43
      modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Tagging/TagAppService.cs
  16. 6
      modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Comments/CommentConsts.cs
  17. 6
      modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Tagging/TagConsts.cs
  18. 4
      modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Comments/Comment.cs
  19. 1
      modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Comments/ICommentRepository.cs
  20. 6
      modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/IPostTagRepository.cs
  21. 1
      modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/PostTag.cs
  22. 2
      modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Tagging/ITagRepository.cs
  23. 19
      modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Tagging/Tag.cs
  24. 1
      modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Comments/EfCoreCommentRepository.cs
  25. 2
      modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Posts/EfCorePostRepository.cs
  26. 5
      modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Posts/EfCorePostTagRepository.cs
  27. 6
      modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Tagging/EfCoreTagRepository.cs
  28. 6
      modules/blogging/src/Volo.Blogging.Web/AbpBloggingWebAutoMapperProfile.cs
  29. 2
      modules/blogging/src/Volo.Blogging.Web/BloggingWebModule.cs
  30. 3
      modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/en.json
  31. 3
      modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/tr.json
  32. 39
      modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Detail.cshtml
  33. 23
      modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Index.cshtml
  34. 2
      modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Index.cshtml.cs
  35. 93
      modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Tags/Posts.cshtml
  36. 34
      modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Tags/Posts.cshtml.cs
  37. 2
      modules/blogging/test/Volo.Blogging.Application.Tests/Volo/Blogging/CommentAppService_Tests.cs

2
modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/BloggingTestAppDbContextModelSnapshot.cs

@ -3,8 +3,6 @@ using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Volo.BloggingTestApp.EntityFrameworkCore;
namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations
{

10707
modules/blogging/app/Volo.BloggingTestApp/Logs/logs.txt

File diff suppressed because it is too large

15
modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/BloggingPermissionDefinitionProvider.cs

@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Localization;
using Volo.Blogging.Localization;
@ -22,6 +19,16 @@ namespace Volo.Blogging
posts.AddChild(BloggingPermissions.Posts.Update, L("Permission:Edit"));
posts.AddChild(BloggingPermissions.Posts.Delete, L("Permission:Delete"));
posts.AddChild(BloggingPermissions.Posts.Create, L("Permission:Create"));
var tags = bloggingGroup.AddPermission(BloggingPermissions.Tags.Default, L("Permission:Tag"));
tags.AddChild(BloggingPermissions.Tags.Update, L("Permission:Edit"));
tags.AddChild(BloggingPermissions.Tags.Delete, L("Permission:Delete"));
tags.AddChild(BloggingPermissions.Tags.Create, L("Permission:Create"));
var comments = bloggingGroup.AddPermission(BloggingPermissions.Comments.Default, L("Permission:Comments"));
comments.AddChild(BloggingPermissions.Comments.Update, L("Permission:Edit"));
comments.AddChild(BloggingPermissions.Comments.Delete, L("Permission:Delete"));
comments.AddChild(BloggingPermissions.Comments.Create, L("Permission:Create"));
}
private static LocalizableString L(string name)

32
modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/BloggingPermissions.cs

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Volo.Blogging
namespace Volo.Blogging
{
public class BloggingPermissions
{
@ -24,6 +20,22 @@ namespace Volo.Blogging
public const string Create = Default + ".Create";
}
public static class Tags
{
public const string Default = GroupName + ".Tag";
public const string Delete = Default + ".Delete";
public const string Update = Default + ".Update";
public const string Create = Default + ".Create";
}
public static class Comments
{
public const string Default = GroupName + ".Comment";
public const string Delete = Default + ".Delete";
public const string Update = Default + ".Update";
public const string Create = Default + ".Create";
}
public static string[] GetAll()
{
return new[]
@ -36,7 +48,15 @@ namespace Volo.Blogging
Posts.Default,
Posts.Delete,
Posts.Update,
Posts.Create
Posts.Create,
Tags.Default,
Tags.Delete,
Tags.Update,
Tags.Create,
Comments.Default,
Comments.Delete,
Comments.Update,
Comments.Create
};
}
}

2
modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Blogs/IBlogAppService.cs

@ -1,6 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;

3
modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Comments/Dtos/CommentDto.cs

@ -1,8 +1,5 @@
using System;
using System.Collections.Generic;
using System.Text;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Domain.Entities.Auditing;
namespace Volo.Blogging.Comments.Dtos
{

5
modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Comments/Dtos/CommentWithRepliesDto.cs

@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
using Volo.Abp.Application.Dtos;
using System.Collections.Generic;
namespace Volo.Blogging.Comments.Dtos
{

1
modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Comments/ICommentAppService.cs

@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
using Volo.Blogging.Comments.Dtos;

4
modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Posts/IPostAppService.cs

@ -1,6 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
@ -11,6 +9,8 @@ namespace Volo.Blogging.Posts
{
Task<ListResultDto<PostWithDetailsDto>> GetListByBlogId(Guid id);
Task<ListResultDto<PostWithDetailsDto>> GetListByBlogIdAndTagName(Guid blogId, string tagName);
Task<PostWithDetailsDto> GetByUrlAsync(GetPostInput input);
Task<PostWithDetailsDto> GetAsync(Guid id);

1
modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Posts/PostWithDetailsDto.cs

@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Text;
using Volo.Abp.Application.Dtos;
using Volo.Blogging.Tagging.Dtos;

3
modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Posts/UpdatePostDto.cs

@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
using Volo.Abp.Application.Dtos;
namespace Volo.Blogging.Posts
{

3
modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Tagging/ITagAppService.cs

@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
using Volo.Blogging.Tagging.Dtos;
@ -19,7 +18,7 @@ namespace Volo.Blogging.Tagging
Task DeleteAsync(Guid id);
Task<List<PopularTagDto>> GetPopularTags(GetPopularTagsInput input);
Task<List<TagDto>> GetPopularTags(GetPopularTagsInput input);
}
}

5
modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Comments/CommentAppService.cs

@ -1,12 +1,14 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Volo.Abp.Application.Services;
using Volo.Abp.Guids;
using Volo.Blogging.Comments.Dtos;
namespace Volo.Blogging.Comments
{
[Authorize(BloggingPermissions.Comments.Default)]
public class CommentAppService : ApplicationService, ICommentAppService
{
private readonly ICommentRepository _commentRepository;
@ -48,6 +50,7 @@ namespace Volo.Blogging.Comments
ObjectMapper.Map<List<Comment>, List<CommentDto>>(comments));
}
[Authorize(BloggingPermissions.Comments.Create)]
public async Task<CommentDto> CreateAsync(CreateCommentDto input)
{
var comment = new Comment(_guidGenerator.Create(), input.PostId, input.RepliedCommentId,input.Text);
@ -57,6 +60,7 @@ namespace Volo.Blogging.Comments
return ObjectMapper.Map<Comment, CommentDto>(comment);
}
[Authorize(BloggingPermissions.Comments.Update)]
public async Task<CommentDto> UpdateAsync(Guid id, UpdateCommentDto input)
{
var comment = await _commentRepository.GetAsync(id);
@ -68,6 +72,7 @@ namespace Volo.Blogging.Comments
return ObjectMapper.Map<Comment, CommentDto>(comment);
}
[Authorize(BloggingPermissions.Comments.Delete)]
public async Task DeleteAsync(Guid id)
{
await _commentRepository.DeleteAsync(id);

24
modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Posts/PostAppService.cs

@ -5,10 +5,7 @@ using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using System.Collections.Generic;
using Microsoft.AspNetCore.Authorization;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Users;
using Volo.Blogging.Blogs;
using Volo.Blogging.Comments;
using Volo.Blogging.Tagging;
using Volo.Blogging.Tagging.Dtos;
@ -52,6 +49,15 @@ namespace Volo.Blogging.Posts
return new ListResultDto<PostWithDetailsDto>(postDtos);
}
public async Task<ListResultDto<PostWithDetailsDto>> GetListByBlogIdAndTagName(Guid blogId, string tagName)
{
var all = (await GetListByBlogId(blogId)).Items;
var tag = await _tagRepository.GetByNameAsync(tagName);
return new ListResultDto<PostWithDetailsDto>(all.Where(p=>p.Tags.Any(t=>t.Id == tag.Id)).ToList());
}
public async Task<PostWithDetailsDto> GetByUrlAsync(GetPostInput input)
{
var post = await _postRepository.GetPostByUrl(input.BlogId, input.Url);
@ -125,6 +131,11 @@ namespace Volo.Blogging.Posts
foreach (var oldTag in oldTags)
{
await _postTagRepository.DeleteAsync(oldTag);
var tag = await _tagRepository.GetAsync(oldTag.TagId);
tag.DecreaseUsageCount();
await _tagRepository.UpdateAsync(tag);
}
var tags = await _tagRepository.GetListAsync();
@ -135,7 +146,12 @@ namespace Volo.Blogging.Posts
if (tag == null)
{
tag = await _tagRepository.InsertAsync(new Tag(newTag));
tag = await _tagRepository.InsertAsync(new Tag(newTag, 1));
}
else
{
tag.IncreaseUsageCount();
tag = await _tagRepository.UpdateAsync(tag);
}
await _postTagRepository.InsertAsync(new PostTag(post.Id, tag.Id));

43
modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Tagging/TagAppService.cs

@ -2,12 +2,14 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Volo.Abp.Application.Services;
using Volo.Blogging.Posts;
using Volo.Blogging.Tagging.Dtos;
namespace Volo.Blogging.Tagging
{
[Authorize(BloggingPermissions.Tags.Default)]
public class TagAppService : ApplicationService, ITagAppService
{
private readonly ITagRepository _tagRepository;
@ -35,11 +37,13 @@ namespace Volo.Blogging.Tagging
ObjectMapper.Map<List<Tag>, List<TagDto>>(tags));
}
[Authorize(BloggingPermissions.Tags.Create)]
public async Task<TagDto> CreateAsync(CreateTagDto input)
{
var newTag = await _tagRepository.InsertAsync(
new Tag(
input.Name,
input.Name,
0,
input.Description
)
);
@ -47,6 +51,7 @@ namespace Volo.Blogging.Tagging
return ObjectMapper.Map<Tag, TagDto>(newTag);
}
[Authorize(BloggingPermissions.Tags.Update)]
public async Task<TagDto> UpdateAsync(Guid id, UpdateTagDto input)
{
var tag = await _tagRepository.GetAsync(id);
@ -59,39 +64,21 @@ namespace Volo.Blogging.Tagging
return ObjectMapper.Map<Tag, TagDto>(tag);
}
[Authorize(BloggingPermissions.Tags.Delete)]
public async Task DeleteAsync(Guid id)
{
await _tagRepository.DeleteAsync(id);
}
public async Task<List<PopularTagDto>> GetPopularTags(GetPopularTagsInput input)
public async Task<List<TagDto>> GetPopularTags(GetPopularTagsInput input)
{
var postTags = await _postTagRepository.GetListAsync();
var postTagsGrouped = postTags.GroupBy(x => x.PostId)
.OrderByDescending(g => g.Count())
.SelectMany(g => g).Select(t=>t.TagId).Distinct().ToList();
var popularTagDtos = new List<PopularTagDto>();
for (var i = 0; i < input.ResultCount && i < postTagsGrouped.Count; i++)
{
var tagId = postTagsGrouped[i];
var count = postTags.Count(t => t.TagId == tagId);
if (count < input.MinimumPostCount)
{
break;
}
var tag = await _tagRepository.GetAsync(tagId);
popularTagDtos.Add(new PopularTagDto
{
Tag = ObjectMapper.Map<Tag, TagDto>(tag),
Count = count
});
}
return popularTagDtos;
var postTags = (await _tagRepository.GetListAsync()).OrderByDescending(t=>t.UsageCount)
.WhereIf(input.MinimumPostCount != null, t=>t.UsageCount >= input.MinimumPostCount)
.Take(input.ResultCount).ToList();
return new List<TagDto>(
ObjectMapper.Map<List<Tag>, List<TagDto>>(postTags));
}
}
}

6
modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Comments/CommentConsts.cs

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Volo.Blogging.Comments
namespace Volo.Blogging.Comments
{
public class CommentConsts
{

6
modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Tagging/TagConsts.cs

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Volo.Blogging.Tagging
namespace Volo.Blogging.Tagging
{
public class TagConsts
{

4
modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Comments/Comment.cs

@ -1,11 +1,7 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using JetBrains.Annotations;
using Volo.Abp;
using Volo.Abp.Domain.Entities.Auditing;
using Volo.Abp.MultiTenancy;
namespace Volo.Blogging.Comments
{

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

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

6
modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/IPostTagRepository.cs

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
using Volo.Abp.Domain.Repositories;
using Volo.Blogging.Tagging;
using Volo.Abp.Domain.Repositories;
namespace Volo.Blogging.Posts
{

1
modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/PostTag.cs

@ -1,6 +1,5 @@
using System;
using Volo.Abp.Domain.Entities.Auditing;
using Volo.Abp.MultiTenancy;
namespace Volo.Blogging.Posts
{

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

@ -9,6 +9,8 @@ namespace Volo.Blogging.Tagging
{
Task<List<Tag>> GetListAsync();
Task<Tag> GetByNameAsync(string name);
Task<List<Tag>> GetListAsync(IEnumerable<Guid> ids);
}
}

19
modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Tagging/Tag.cs

@ -1,9 +1,7 @@
using System;
using JetBrains.Annotations;
using Volo.Abp;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Domain.Entities.Auditing;
using Volo.Abp.MultiTenancy;
namespace Volo.Blogging.Tagging
{
@ -20,10 +18,11 @@ namespace Volo.Blogging.Tagging
}
public Tag([NotNull] string name, string description = null)
public Tag([NotNull] string name, int usageCount = 0, string description = null)
{
Name = Check.NotNullOrWhiteSpace(name, nameof(name));
Description = description;
UsageCount = usageCount;
}
public virtual void SetName(string name)
@ -31,6 +30,20 @@ namespace Volo.Blogging.Tagging
Name = Check.NotNullOrWhiteSpace(name, nameof(name));
}
public virtual void IncreaseUsageCount(int number = 1)
{
UsageCount += number;
}
public virtual void DecreaseUsageCount(int number = 1)
{
if (UsageCount <= 0)
{
return;
}
UsageCount -= number;
}
public virtual void SetDescription(string description)
{
Description = description;

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

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

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

@ -1,13 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
using Volo.Blogging.Blogs;
using Volo.Blogging.EntityFrameworkCore;
namespace Volo.Blogging.Posts

5
modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Posts/EfCorePostTagRepository.cs

@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
using Volo.Blogging.EntityFrameworkCore;

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

@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
@ -22,6 +21,11 @@ namespace Volo.Blogging.Tagging
return await DbSet.ToListAsync();
}
public async Task<Tag> GetByNameAsync(string name)
{
return await DbSet.FirstOrDefaultAsync(t=>t.Name == name);
}
public async Task<List<Tag>> GetListAsync(IEnumerable<Guid> ids)
{
return await DbSet.Where(c => ids.Contains(c.Id)).ToListAsync();

6
modules/blogging/src/Volo.Blogging.Web/AbpBloggingWebAutoMapperProfile.cs

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AutoMapper;
using AutoMapper;
using Volo.Abp.AutoMapper;
using Volo.Blogging.Pages.Blog.Posts;
using Volo.Blogging.Posts;

2
modules/blogging/src/Volo.Blogging.Web/BloggingWebModule.cs

@ -1,6 +1,5 @@
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Localization;
using Volo.Abp.AspNetCore.Mvc.Localization;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap;
using Volo.Abp.AutoMapper;
@ -56,6 +55,7 @@ namespace Volo.Blogging
options.Conventions.AddPageRoute("/Blog/Posts/Detail", "blog/{blogShortName}/{postUrl}");
options.Conventions.AddPageRoute("/Blog/Posts/Edit", "blog/{blogShortName}/posts/edit/{postId}");
options.Conventions.AddPageRoute("/Blog/Posts/New", "blog/{blogShortName}/posts/new");
options.Conventions.AddPageRoute("/Blog/Tags/Posts", "blog/{blogShortName}/{tagName}/posts");
});
context.Services.AddAssemblyOf<BloggingWebModule>();

3
modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/en.json

@ -10,6 +10,7 @@
"Read": "Read",
"LastPosts": "Last Posts",
"Posts": "Posts",
"Comment": "Comment"
"Comment": "Comment",
"WhatIsNew": "What is new?"
}
}

3
modules/blogging/src/Volo.Blogging.Web/Localization/Resources/Blogging/Web/tr.json

@ -10,6 +10,7 @@
"Read": "Okunma",
"LastPosts": "Son Yazılar",
"Posts": "Yazılar",
"Comment": "Yorum"
"Comment": "Yorum",
"WhatIsNew": "Yeniler"
}
}

39
modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Detail.cshtml

@ -1,6 +1,9 @@
@page
@inherits Volo.Blogging.Pages.Blog.BloggingPage
@using Microsoft.AspNetCore.Authorization
@using Volo.Blogging
@using Volo.Blogging.Pages.Blog.Posts
@inject IAuthorizationService Authorization
@model DetailModel
@{
}
@ -21,17 +24,17 @@
<div class="col-md-12 mx-auto">
<section class="hero-section">
<div class="hero-articles">
<div class="img-container" style="min-height: 480px; background: url(https://cdn-images-1.medium.com/max/800/1*yFcPtGZXbm10e6v9WIXVOQ.png) center center no-repeat; background-size: cover; ">
<div class="img-container" style="min-height: 480px; background: url(https://placeimg.com/800/435/tech) center center no-repeat; background-size: cover; ">
</div>
<div class="hero-content">
<p class="tags">
<p class="tags">
<p class="tags">
@foreach (var tag in Model.Post.Tags)
{
<a href="#" class="tag">@tag.Name</a>
}
</p>
@foreach (var tag in Model.Post.Tags)
{
<a asp-page="/Blog/Tags/Posts" asp-route-blogShortName="@Model.BlogShortName" asp-route-tagName="@tag.Name" class="tag">@tag.Name</a>
}
</p>
</p>
<h1>
<a href="#">@Model.Post.Title</a>
@ -42,10 +45,10 @@
<div class="article-infos">
<div class="user-card">
<a href="#">
<img src="https://cdn-images-1.medium.com/fit/c/60/60/0*uarpjksge8Mloaa6.jpeg" class="article-avatar">
<img src="https://placeimg.com/60/60/people" class="article-avatar">
</a>
<a href="#">
<strong> @Model.Blog.Name</strong>, @Model.Post.CreationTime
<strong> Halil İbrahim Kalkan</strong>, @Model.Post.CreationTime.ToString("dd/MM/yyyy hh/mm")
</a>
<span class="seperator">|</span>
<a href="#">
@ -55,6 +58,15 @@
<a href="#">
<i class="fa fa-comment"></i> @Model.CommentCount @L["Comment"]
</a>
@if (await Authorization.IsGrantedAsync(BloggingPermissions.Posts.Update))
{
<span class="seperator">|</span>
<a asp-page="./Edit" asp-route-postId="@Model.Post.Id" asp-route-blogShortName="@Model.BlogShortName">
<i class="fa fa-pencil"></i> @L["Edit"]
</a>
}
</div>
</div>
</div>
@ -74,7 +86,7 @@
<div class="row">
<div class="col-md-8 mx-auto">
<section class="post-content">
<p>@Model.FormattedContent</p>
<p>@Html.Raw(Model.FormattedContent)</p>
</section>
</div>
@ -87,10 +99,9 @@
<h5>Tags in this article</h5>
@foreach (var tag in Model.Post.Tags)
{
<a href="#" class="tag">@tag.Name</a>
<a asp-page="/Blog/Tags/Posts" asp-route-blogShortName="@Model.BlogShortName" asp-route-tagName="@tag.Name" class="tag">@tag.Name</a>
}
</div>
<a asp-page="./Edit" asp-route-postId="@Model.Post.Id" asp-route-blogShortName="@Model.BlogShortName">@L["Edit"]</a>
<div class="comment-form mt-4">
<div class="clearfix bg-light p-4">
<h3 class="mt-0">@L["LeaveComment"]</h3>
@ -116,7 +127,7 @@
<div class="media-body">
<h5 class="comment-owner">
Armağan Ünlü
<span class="float-right">@commentWithRepliesDto.Comment.CreationTime</span>
<span class="float-right">@commentWithRepliesDto.Comment.CreationTime.ToString("dd/MM/yyyy hh/mm")</span>
</h5>
<p>
@commentWithRepliesDto.Comment.Text
@ -161,7 +172,7 @@
<div class="media-body">
<h5 class="comment-owner">
Zlatan Ibrahimovic
<span class="float-right">@reply.CreationTime</span>
<span class="float-right">@reply.CreationTime.ToString("dd/MM/yyyy hh/mm")</span>
</h5>
<p>
@reply.Text

23
modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Index.cshtml

@ -1,7 +1,10 @@
@page
@inherits Volo.Blogging.Pages.Blog.BloggingPage
@using System.Net
@using Microsoft.AspNetCore.Authorization
@using Volo.Blogging
@using Volo.Blogging.Pages.Blog.Posts
@using Volo.Blogging.Posts
@inject IAuthorizationService Authorization
@model Volo.Blogging.Pages.Blog.Posts.IndexModel
@{
@ -22,7 +25,7 @@
<abp-style src="/Pages/Blog/Posts/blogcss/owlcarousel/dist/assets/owl.theme.green.min.css" />
</abp-style-bundle>
}
<a asp-page="./New" asp-route-blogShortName="@Model.BlogShortName">Create New Post</a>
<div class="container hero-container pb-5 bg-white">
<div class="row">
@ -44,14 +47,14 @@
<p class="tags">
@foreach (var tag in post.Tags)
{
<a href="#" class="tag">@tag.Name</a>
<a asp-page="/Blog/Tags/Posts" asp-route-blogShortName="@Model.BlogShortName" asp-route-tagName="@tag.Name" class="tag">@tag.Name</a>
}
</p>
<h2>
<a asp-page="./Detail" asp-route-postUrl="@post.Url" asp-route-blogShortName="@Model.BlogShortName">@post.Title</a>
</h2>
<p class="article-sum">
@(post.Content == null ? "" : (post.Content.Length > 150 ? post.Content.Substring(0,150) : post.Content))
@(post.Content == null ? "" : (post.Content.Length > 150 ? post.Content.Substring(0, 150) : post.Content))
</p>
<a asp-page="./Detail" asp-route-postUrl="@post.Url" asp-route-blogShortName="@Model.BlogShortName" class="btn btn-primary btn-rounded">@L["ContinueReading"]</a>
@ -92,7 +95,13 @@
</div>
<div class="col-md-4">
<h2>What is new?</h2>
@if (await Authorization.IsGrantedAsync(BloggingPermissions.Posts.Create))
{
<a asp-page="./New" asp-route-blogShortName="@Model.BlogShortName">Create New Post</a>
}
<h2>@L["WhatIsNew"]</h2>
<div class="list-group">
@for (var index = 0; index < Model.Posts.Count && index < 3; index++)
@ -180,7 +189,7 @@
<p class="tags">
@foreach (var tag in post.Tags)
{
<a href="#" class="tag">@tag.Name</a>
<a asp-page="/Blog/Tags/Posts" asp-route-blogShortName="@Model.BlogShortName" asp-route-tagName="@tag.Name" class="tag">@tag.Name</a>
}
</p>
<h3>
@ -226,7 +235,7 @@
<div class="popular-tags">
@foreach (var popularTag in Model.PopularTags)
{
<a href="#">@popularTag.Tag.Name <span>(@popularTag.Count @L["Posts"])</span></a>
<a asp-page="/Blog/Tags/Posts" asp-route-blogShortName="@Model.BlogShortName" asp-route-tagName="@popularTag.Name">@popularTag.Name <span>(@popularTag.UsageCount @L["Posts"])</span></a>
}
</div>

2
modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Index.cshtml.cs

@ -20,7 +20,7 @@ namespace Volo.Blogging.Pages.Blog.Posts
public IReadOnlyList<PostWithDetailsDto> Posts { get; set; }
public IReadOnlyList<PopularTagDto> PopularTags { get; set; }
public IReadOnlyList<TagDto> PopularTags { get; set; }
public IndexModel(IPostAppService postAppService, IBlogAppService blogAppService, ITagAppService tagAppService)
{

93
modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Tags/Posts.cshtml

@ -0,0 +1,93 @@
@page
@inherits Volo.Blogging.Pages.Blog.BloggingPage
@using Volo.Blogging.Pages.Blog.Tags
@model PostsModel
@{
}
@section scripts {
<abp-script-bundle name="@typeof(PostsModel).FullName">
<abp-script src="/Pages/Blog/Posts/blogcss/blog.js" />
</abp-script-bundle>
}
@section styles {
<abp-style-bundle @*name="@typeof(DetailModel).FullName" *@>
<abp-style src="/Pages/Blog/Posts/blogcss/blog.css" />
</abp-style-bundle>
}
<div class="container last-post-section pb-5">
<div class="row">
<div class="col-md-8">
<div class="row">
<div class="col">
<div class="titline">
<h2>#@Model.TagName</h2>
</div>
</div>
</div>
@for (var index = 0; index < Model.Posts.Count; index++)
{
var post = Model.Posts[index];
var oddPost = index % 2 == 1;
<section class="box-articles">
<div class="row @(oddPost?"align-middle":"")">
<div class="col-md-4 order-md-@(oddPost?"last":"first")">
<div class="img-container">
<a asp-page="/Blog/Posts/Detail" asp-route-postUrl="@post.Url" asp-route-blogShortName="@Model.BlogShortName">
<img src="https://placeimg.com/480/270/tech" class="box-article-img">
</a>
<div class="user-link-icons">
<a class="add-bookmark" href="#">
<i class="fa fa-bookmark"></i>
</a>
<a class="share-article" href="#">
<i class="fa fa-share-alt"></i>
</a>
</div>
</div>
</div>
<div class="col-md-8 order-md-@(oddPost?"first":"last")">
<p class="tags">
@foreach (var tag in post.Tags)
{
<a asp-page="/Blog/Tags/Posts" asp-route-blogShortName="@Model.BlogShortName" asp-route-tagName="@tag.Name" class="tag">@tag.Name</a>
}
</p>
<h3>
<a asp-page="/Blog/Posts/Detail" asp-route-postUrl="@post.Url" asp-route-blogShortName="@Model.BlogShortName">@post.Title</a>
</h3>
<p>
@(post.Content == null ? "" : (post.Content.Length > 250 ? post.Content.Substring(0, 150) : post.Content))...
</p>
<div class="article-owner">
<div class="article-infos">
<div class="user-card">
<a href="#">
<img src="https://placeimg.com/120/120/pople" class="article-avatar">
</a>
<a href="#">
<strong>Armağan Ünlü</strong>, @((DateTime.Today - post.CreationTime).Days) @L["DaysAgo"]
</a>
<span class="seperator">|</span>
<a href="#">
<i class="fa fa-eye"></i> 156K
</a>
<span class="seperator">|</span>
<a href="#">
<i class="fa fa-comment"></i> @post.CommentCount
</a>
</div>
</div>
</div>
</div>
</div>
</section>
}
</div>
</div>
</div>

34
modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Tags/Posts.cshtml.cs

@ -0,0 +1,34 @@
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Volo.Blogging.Blogs;
using Volo.Blogging.Posts;
namespace Volo.Blogging.Pages.Blog.Tags
{
public class PostsModel : PageModel
{
private readonly IPostAppService _postAppService;
private readonly IBlogAppService _blogAppService;
[BindProperty(SupportsGet = true)]
public string BlogShortName { get; set; }
[BindProperty(SupportsGet = true)]
public string TagName { get; set; }
public IReadOnlyList<PostWithDetailsDto> Posts { get; set; }
public PostsModel(IPostAppService postAppService, IBlogAppService blogAppService)
{
_postAppService = postAppService;
_blogAppService = blogAppService;
}
public async void OnGetAsync()
{
var blog = await _blogAppService.GetByShortNameAsync(BlogShortName);
Posts = (await _postAppService.GetListByBlogIdAndTagName(blog.Id, TagName)).Items;
}
}
}

2
modules/blogging/test/Volo.Blogging.Application.Tests/Volo/Blogging/CommentAppService_Tests.cs

@ -1,6 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Shouldly;
using Volo.Blogging.Comments;

Loading…
Cancel
Save