mirror of https://github.com/abpframework/abp.git
56 changed files with 1166 additions and 51 deletions
@ -0,0 +1,15 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace Volo.CmsKit.Admin.Tags |
||||
|
{ |
||||
|
public class EntityTagSetDto |
||||
|
{ |
||||
|
public string EntityId { get; set; } |
||||
|
public string EntityType { get; set; } |
||||
|
public List<string> Tags { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,42 @@ |
|||||
|
using Microsoft.AspNetCore.Authorization; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.GlobalFeatures; |
||||
|
using Volo.CmsKit.GlobalFeatures; |
||||
|
using Volo.CmsKit.Permissions; |
||||
|
|
||||
|
namespace Volo.CmsKit.Admin.Tags |
||||
|
{ |
||||
|
[RequiresGlobalFeature(typeof(TagsFeature))] |
||||
|
[RemoteService(Name = CmsKitCommonRemoteServiceConsts.RemoteServiceName)] |
||||
|
[Area("cms-kit")] |
||||
|
[Route("api/cms-kit-admin/entity-tags")] |
||||
|
public class EntityTagAdminController : CmsKitAdminController, IEntityTagAdminAppService |
||||
|
{ |
||||
|
protected IEntityTagAdminAppService EntityTagAdminAppService { get; } |
||||
|
|
||||
|
public EntityTagAdminController(IEntityTagAdminAppService entityTagAdminAppService) |
||||
|
{ |
||||
|
EntityTagAdminAppService = entityTagAdminAppService; |
||||
|
} |
||||
|
|
||||
|
[HttpPost] |
||||
|
public Task AddTagToEntityAsync(EntityTagCreateDto input) |
||||
|
{ |
||||
|
return EntityTagAdminAppService.AddTagToEntityAsync(input); |
||||
|
} |
||||
|
|
||||
|
[HttpDelete] |
||||
|
public Task RemoveTagFromEntityAsync(EntityTagRemoveDto input) |
||||
|
{ |
||||
|
return EntityTagAdminAppService.RemoveTagFromEntityAsync(input); |
||||
|
} |
||||
|
|
||||
|
[HttpPut] |
||||
|
public Task SetEntityTagsAsync(EntityTagSetDto input) |
||||
|
{ |
||||
|
return EntityTagAdminAppService.SetEntityTagsAsync(input); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,20 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
|
||||
|
namespace Volo.CmsKit.Users |
||||
|
{ |
||||
|
public class CmsUserDto : EntityDto<Guid> |
||||
|
{ |
||||
|
public virtual Guid? TenantId { get; protected set; } |
||||
|
|
||||
|
public virtual string UserName { get; protected set; } |
||||
|
|
||||
|
public virtual string Name { get; set; } |
||||
|
|
||||
|
public virtual string Surname { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,17 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
using Volo.CmsKit.Users; |
||||
|
|
||||
|
namespace Volo.CmsKit.Public.Blogs |
||||
|
{ |
||||
|
public class BlogPostPublicDto : AuditedEntityWithUserDto<Guid, CmsUserDto> |
||||
|
{ |
||||
|
public Guid BlogId { get; set; } |
||||
|
|
||||
|
public string Title { get; set; } |
||||
|
|
||||
|
public string UrlSlug { get; set; } |
||||
|
|
||||
|
public string ShortDescription { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,17 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
using Volo.Abp.Content; |
||||
|
|
||||
|
namespace Volo.CmsKit.Public.Blogs |
||||
|
{ |
||||
|
public interface IBlogPostPublicAppService |
||||
|
{ |
||||
|
Task<PagedResultDto<BlogPostPublicDto>> GetListAsync(string blogUrlSlug, PagedAndSortedResultRequestDto input); |
||||
|
|
||||
|
Task<BlogPostPublicDto> GetAsync(string blogUrlSlug, string blogPostUrlSlug); |
||||
|
|
||||
|
Task<RemoteStreamContent> GetCoverImageAsync(Guid id); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,54 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
using Volo.Abp.BlobStoring; |
||||
|
using Volo.Abp.Content; |
||||
|
using Volo.CmsKit.Blogs; |
||||
|
|
||||
|
namespace Volo.CmsKit.Public.Blogs |
||||
|
{ |
||||
|
public class BlogPostPublicAppService : CmsKitPublicAppServiceBase, IBlogPostPublicAppService |
||||
|
{ |
||||
|
protected IBlogRepository BlogRepository { get; } |
||||
|
|
||||
|
protected IBlobContainer<BlogPostCoverImageContainer> BlobContainer { get; } |
||||
|
|
||||
|
protected IBlogPostRepository BlogPostRepository { get; } |
||||
|
|
||||
|
public BlogPostPublicAppService( |
||||
|
IBlogRepository blogRepository, |
||||
|
IBlogPostRepository blogPostRepository) |
||||
|
{ |
||||
|
BlogRepository = blogRepository; |
||||
|
BlogPostRepository = blogPostRepository; |
||||
|
} |
||||
|
|
||||
|
public async Task<BlogPostPublicDto> GetAsync(string blogUrlSlug, string blogPostUrlSlug) |
||||
|
{ |
||||
|
var blog = await BlogRepository.GetByUrlSlugAsync(blogUrlSlug); |
||||
|
|
||||
|
var blogPost = await BlogPostRepository.GetByUrlSlugAsync(blog.Id, blogPostUrlSlug); |
||||
|
|
||||
|
return ObjectMapper.Map<BlogPost, BlogPostPublicDto>(blogPost); |
||||
|
} |
||||
|
|
||||
|
public async Task<PagedResultDto<BlogPostPublicDto>> GetListAsync(string blogUrlSlug, PagedAndSortedResultRequestDto input) |
||||
|
{ |
||||
|
var blog = await BlogRepository.GetByUrlSlugAsync(blogUrlSlug); |
||||
|
|
||||
|
var blogPosts = await BlogPostRepository.GetPagedListAsync(blog.Id, input.SkipCount, input.MaxResultCount, input.Sorting); |
||||
|
|
||||
|
return new PagedResultDto<BlogPostPublicDto>( |
||||
|
await BlogPostRepository.GetCountAsync(blog.Id), |
||||
|
ObjectMapper.Map<List<BlogPost>, List<BlogPostPublicDto>>(blogPosts)); |
||||
|
} |
||||
|
|
||||
|
public async Task<RemoteStreamContent> GetCoverImageAsync(Guid id) |
||||
|
{ |
||||
|
var stream = await BlobContainer.GetAsync(id.ToString()); |
||||
|
|
||||
|
return new RemoteStreamContent(stream); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,53 @@ |
|||||
|
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 |
||||
|
{ |
||||
|
[RequiresGlobalFeature(typeof(BlogsFeature))] |
||||
|
[RemoteService(Name = CmsKitPublicRemoteServiceConsts.RemoteServiceName)] |
||||
|
[Area("cms-kit")] |
||||
|
[Route("api/cms-kit-public/blog-posts")] |
||||
|
public class BlogPostPublicController : CmsKitPublicControllerBase, IBlogPostPublicAppService |
||||
|
{ |
||||
|
protected IBlogPostPublicAppService BlogPostPublicAppService { get; } |
||||
|
|
||||
|
public BlogPostPublicController(IBlogPostPublicAppService blogPostPublicAppService) |
||||
|
{ |
||||
|
BlogPostPublicAppService = blogPostPublicAppService; |
||||
|
} |
||||
|
|
||||
|
[HttpGet] |
||||
|
public Task<BlogPostPublicDto> GetAsync(string blogUrlSlug, string blogPostUrlSlug) |
||||
|
{ |
||||
|
return BlogPostPublicAppService.GetAsync(blogUrlSlug, blogPostUrlSlug); |
||||
|
} |
||||
|
|
||||
|
[HttpGet] |
||||
|
[Route("{id}/cover-image")] |
||||
|
public Task<RemoteStreamContent> GetCoverImageAsync(Guid id) |
||||
|
{ |
||||
|
Response.Headers.Add("Content-Disposition", $"inline;filename=\"{id}\""); |
||||
|
Response.Headers.Add("Accept-Ranges", "bytes"); |
||||
|
Response.Headers.Add("Cache-Control", "max-age=120"); |
||||
|
Response.ContentType = "image"; |
||||
|
|
||||
|
return BlogPostPublicAppService.GetCoverImageAsync(id); |
||||
|
} |
||||
|
|
||||
|
[HttpGet] |
||||
|
public Task<PagedResultDto<BlogPostPublicDto>> GetListAsync(string blogUrlSlug, PagedAndSortedResultRequestDto input) |
||||
|
{ |
||||
|
return BlogPostPublicAppService.GetListAsync(blogUrlSlug, input); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,63 @@ |
|||||
|
@page "/blogs/{blogUrlSlug}/{blogPostUrlSlug}" |
||||
|
|
||||
|
@using Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.Blogs.BlogPost |
||||
|
@using Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.Blogs.BlogPostComment |
||||
|
@using Volo.CmsKit.Public.Web.Pages.CmsKit.Blogs |
||||
|
@using Volo.CmsKit.Public.Web.Pages |
||||
|
@using Volo.Abp.GlobalFeatures |
||||
|
@using Volo.CmsKit.GlobalFeatures |
||||
|
@using Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.ReactionSelection |
||||
|
@using Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.Rating |
||||
|
@using Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.Tags |
||||
|
|
||||
|
@inherits CmsKitPublicPageBase |
||||
|
|
||||
|
@model BlogPostModel |
||||
|
|
||||
|
@{ |
||||
|
PageLayout.Content.Title = Model.BlogPost.Title; |
||||
|
} |
||||
|
|
||||
|
@await Component.InvokeAsync(typeof(DefaultBlogPostViewComponent), new |
||||
|
{ |
||||
|
Model.BlogUrlSlug, |
||||
|
Model.BlogPostUrlSlug |
||||
|
}) |
||||
|
|
||||
|
@if (GlobalFeatureManager.Instance.IsEnabled<TagsFeature>()) |
||||
|
{ |
||||
|
@await Component.InvokeAsync(typeof(TagViewComponent), new |
||||
|
{ |
||||
|
entityType = Volo.CmsKit.Blogs.BlogPostConsts.EntityType, |
||||
|
entityId = Model.BlogPost.Id.ToString() |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
@if (GlobalFeatureManager.Instance.IsEnabled<ReactionsFeature>()) |
||||
|
{ |
||||
|
@await Component.InvokeAsync(typeof(ReactionSelectionViewComponent), new |
||||
|
{ |
||||
|
entityType = Volo.CmsKit.Blogs.BlogPostConsts.EntityType, |
||||
|
entityId = Model.BlogPost.Id.ToString() |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
@if (GlobalFeatureManager.Instance.IsEnabled<RatingsFeature>()) |
||||
|
{ |
||||
|
@await Component.InvokeAsync(typeof(RatingViewComponent), new |
||||
|
{ |
||||
|
entityType = Volo.CmsKit.Blogs.BlogPostConsts.EntityType, |
||||
|
entityId = Model.BlogPost.Id.ToString() |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
<hr /> |
||||
|
|
||||
|
@if (GlobalFeatureManager.Instance.IsEnabled<CommentsFeature>()) |
||||
|
{ |
||||
|
@await Component.InvokeAsync(typeof(DefaultBlogPostCommentViewComponent), new |
||||
|
{ |
||||
|
entityType = Volo.CmsKit.Blogs.BlogPostConsts.EntityType, |
||||
|
entityId = Model.BlogPost.Id.ToString() |
||||
|
}) |
||||
|
} |
||||
@ -0,0 +1,33 @@ |
|||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.CmsKit.Public.Blogs; |
||||
|
|
||||
|
namespace Volo.CmsKit.Public.Web.Pages.CmsKit.Blogs |
||||
|
{ |
||||
|
public class BlogPostModel : CmsKitPublicPageModelBase |
||||
|
{ |
||||
|
[BindProperty(SupportsGet = true)] |
||||
|
public string BlogUrlSlug { get; set; } |
||||
|
|
||||
|
[BindProperty(SupportsGet = true)] |
||||
|
public string BlogPostUrlSlug { get; set; } |
||||
|
|
||||
|
public BlogPostPublicDto BlogPost { get; private set; } |
||||
|
|
||||
|
protected IBlogPostPublicAppService BlogPostPublicAppService { get; } |
||||
|
|
||||
|
public BlogPostModel(IBlogPostPublicAppService blogPostPublicAppService) |
||||
|
{ |
||||
|
BlogPostPublicAppService = blogPostPublicAppService; |
||||
|
} |
||||
|
|
||||
|
public async Task OnGetAsync() |
||||
|
{ |
||||
|
BlogPost = await BlogPostPublicAppService.GetAsync(BlogUrlSlug, BlogPostUrlSlug); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,47 @@ |
|||||
|
@page "/blogs/{blogUrlSlug}" |
||||
|
|
||||
|
@using Volo.CmsKit.Public.Web.Pages |
||||
|
|
||||
|
@inherits CmsKitPublicPageBase |
||||
|
|
||||
|
@model Volo.CmsKit.Public.Web.Pages.CmsKit.Blogs.IndexModel |
||||
|
|
||||
|
<abp-row id="blogs-container"> |
||||
|
@foreach (var blog in Model.Blogs.Items) |
||||
|
{ |
||||
|
<abp-column size="_12" class="m-3"> |
||||
|
<abp-card> |
||||
|
<abp-card-header> |
||||
|
<abp-card-title> |
||||
|
@blog.Title |
||||
|
</abp-card-title> |
||||
|
<abp-card-subtitle> |
||||
|
@@@blog.Creator?.UserName |
||||
|
</abp-card-subtitle> |
||||
|
</abp-card-header> |
||||
|
<abp-card-body> |
||||
|
<img src="/api/cms-kit-public/blog-posts/@blog.Id/cover-image" class="card-img-top" onerror="this.src='https://dummyimage.com/300x200/a3a3a3/fff.png'"/> |
||||
|
<abp-card-text> |
||||
|
@blog.ShortDescription |
||||
|
</abp-card-text> |
||||
|
<abp-card-text> |
||||
|
<a href="/blogs/@Model.BlogUrlSlug/@blog.UrlSlug"> |
||||
|
<abp-button text="@L["Read"]" |
||||
|
button-type="Outline_Primary" /> |
||||
|
</a> |
||||
|
</abp-card-text> |
||||
|
</abp-card-body> |
||||
|
<abp-card-footer> |
||||
|
<abp-card-text> |
||||
|
@blog.CreationTime |
||||
|
</abp-card-text> |
||||
|
</abp-card-footer> |
||||
|
</abp-card> |
||||
|
</abp-column> |
||||
|
|
||||
|
} |
||||
|
</abp-row> |
||||
|
<abp-row> |
||||
|
<abp-paginator model="Model.PagerModel" /> |
||||
|
</abp-row> |
||||
|
|
||||
@ -0,0 +1,45 @@ |
|||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Pagination; |
||||
|
using Volo.CmsKit.Public.Blogs; |
||||
|
|
||||
|
namespace Volo.CmsKit.Public.Web.Pages.CmsKit.Blogs |
||||
|
{ |
||||
|
public class IndexModel : CmsKitPublicPageModelBase |
||||
|
{ |
||||
|
public const int PageSize = 12; |
||||
|
|
||||
|
[BindProperty(SupportsGet = true)] |
||||
|
public string BlogUrlSlug { get; set; } |
||||
|
|
||||
|
[BindProperty(SupportsGet = true)] |
||||
|
public int CurrentPage { get; set; } = 1; |
||||
|
|
||||
|
public PagedResultDto<BlogPostPublicDto> Blogs { get; private set; } |
||||
|
|
||||
|
public PagerModel PagerModel => new PagerModel(Blogs.TotalCount, Blogs.Items.Count, CurrentPage, PageSize, Request.Path.ToString()); |
||||
|
|
||||
|
protected IBlogPostPublicAppService BlogPostPublicAppService { get; } |
||||
|
|
||||
|
public IndexModel(IBlogPostPublicAppService blogPostPublicAppService) |
||||
|
{ |
||||
|
BlogPostPublicAppService = blogPostPublicAppService; |
||||
|
} |
||||
|
|
||||
|
public async Task OnGetAsync() |
||||
|
{ |
||||
|
Blogs = await BlogPostPublicAppService.GetListAsync( |
||||
|
BlogUrlSlug, |
||||
|
new PagedAndSortedResultRequestDto |
||||
|
{ |
||||
|
SkipCount = PageSize * (CurrentPage - 1), |
||||
|
MaxResultCount = PageSize |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,33 @@ |
|||||
|
@model Volo.CmsKit.Public.Blogs.BlogPostPublicDto |
||||
|
@using Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.Contents |
||||
|
@using Volo.Abp.AspNetCore.Mvc.UI.Layout |
||||
|
@using Volo.CmsKit.Localization |
||||
|
@using Microsoft.Extensions.Localization |
||||
|
|
||||
|
@inject IStringLocalizer<CmsKitResource> L |
||||
|
|
||||
|
|
||||
|
<abp-card> |
||||
|
<abp-card-header> |
||||
|
<abp-card-title>@Model.Title</abp-card-title> |
||||
|
<abp-card-subtitle>@@@Model.Creator?.UserName</abp-card-subtitle> |
||||
|
</abp-card-header> |
||||
|
|
||||
|
<abp-card-body> |
||||
|
<img src="/api/cms-kit-public/blog-posts/@Model.Id/cover-image" class="card-img-top" onerror="this.src='https://dummyimage.com/300x200/a3a3a3/fff.png'" /> |
||||
|
@await Component.InvokeAsync(typeof(ContentViewComponent), new |
||||
|
{ |
||||
|
entityType = Volo.CmsKit.Blogs.BlogPostConsts.EntityType, |
||||
|
entityId = Model.Id.ToString() |
||||
|
}) |
||||
|
</abp-card-body> |
||||
|
<abp-card-footer> |
||||
|
<abp-card-subtitle>@Model.CreationTime</abp-card-subtitle> |
||||
|
@if (Model.LastModificationTime != null) |
||||
|
{ |
||||
|
<abp-card-text><i>@L["LastModification"].Value : @Model.LastModificationTime</i></abp-card-text> |
||||
|
} |
||||
|
</abp-card-footer> |
||||
|
</abp-card> |
||||
|
|
||||
|
|
||||
@ -0,0 +1,29 @@ |
|||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.AspNetCore.Mvc; |
||||
|
using Volo.CmsKit.Public.Blogs; |
||||
|
|
||||
|
namespace Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.Blogs.BlogPost |
||||
|
{ |
||||
|
[ViewComponent(Name = "CmsDefaultBlogPost")] |
||||
|
public class DefaultBlogPostViewComponent : AbpViewComponent |
||||
|
{ |
||||
|
protected IBlogPostPublicAppService BlogPostPublicAppService { get; } |
||||
|
|
||||
|
public DefaultBlogPostViewComponent(IBlogPostPublicAppService blogPostPublicAppService) |
||||
|
{ |
||||
|
BlogPostPublicAppService = blogPostPublicAppService; |
||||
|
} |
||||
|
|
||||
|
public virtual async Task<IViewComponentResult> InvokeAsync(string blogUrlSlug, string blogPostUrlSlug) |
||||
|
{ |
||||
|
var blogPost = await BlogPostPublicAppService.GetAsync(blogUrlSlug, blogPostUrlSlug); |
||||
|
|
||||
|
return View("~/Pages/CmsKit/Shared/Components/Blogs/BlogPost/Default.cshtml", blogPost); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,22 @@ |
|||||
|
@using Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.Commenting |
||||
|
@using Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.Blogs.BlogPostComment |
||||
|
@using Volo.CmsKit.Localization |
||||
|
@using Microsoft.Extensions.Localization |
||||
|
|
||||
|
@inject IStringLocalizer<CmsKitResource> L |
||||
|
|
||||
|
@model DefaultBlogPostCommentViewComponent.DefaultBlogPostCommentViewModel |
||||
|
|
||||
|
|
||||
|
<abp-card> |
||||
|
<abp-card-header> |
||||
|
<abp-card-title>@L["Comments"]</abp-card-title> |
||||
|
</abp-card-header> |
||||
|
<abp-card-body> |
||||
|
@await Component.InvokeAsync(typeof(CommentingViewComponent), new |
||||
|
{ |
||||
|
entityType = Model.EntityType, |
||||
|
entityId = Model.EntityId |
||||
|
}) |
||||
|
</abp-card-body> |
||||
|
</abp-card> |
||||
@ -0,0 +1,39 @@ |
|||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.AspNetCore.Mvc; |
||||
|
using Volo.CmsKit.Public.Blogs; |
||||
|
|
||||
|
namespace Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.Blogs.BlogPostComment |
||||
|
{ |
||||
|
[ViewComponent(Name = "CmsDefaultBlogPostComment")] |
||||
|
public class DefaultBlogPostCommentViewComponent : AbpViewComponent |
||||
|
{ |
||||
|
protected IBlogPostPublicAppService BlogPostPublicAppService; |
||||
|
|
||||
|
public DefaultBlogPostCommentViewComponent(IBlogPostPublicAppService blogPostPublicAppService) |
||||
|
{ |
||||
|
BlogPostPublicAppService = blogPostPublicAppService; |
||||
|
} |
||||
|
|
||||
|
public virtual async Task<IViewComponentResult> InvokeAsync(string entityType, string entityId) |
||||
|
{ |
||||
|
return View( |
||||
|
"~/Pages/CmsKit/Shared/Components/Blogs/BlogPostComment/Default.cshtml", |
||||
|
new DefaultBlogPostCommentViewModel |
||||
|
{ |
||||
|
EntityType = entityType, |
||||
|
EntityId = entityId |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
public class DefaultBlogPostCommentViewModel |
||||
|
{ |
||||
|
public string EntityType { get; set; } |
||||
|
public string EntityId { get; set; } |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,26 @@ |
|||||
|
using Microsoft.AspNetCore.Mvc.Razor.Internal; |
||||
|
using Microsoft.Extensions.Localization; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.AspNetCore.Mvc.UI.Layout; |
||||
|
using Volo.CmsKit.Localization; |
||||
|
|
||||
|
namespace Volo.CmsKit.Public.Web.Pages |
||||
|
{ |
||||
|
public class CmsKitPublicPageBase : Microsoft.AspNetCore.Mvc.RazorPages.Page |
||||
|
{ |
||||
|
[RazorInject] |
||||
|
public IStringLocalizer<CmsKitResource> L { get; set; } |
||||
|
|
||||
|
[RazorInject] |
||||
|
public IPageLayout PageLayout { get; set; } |
||||
|
|
||||
|
public override Task ExecuteAsync() |
||||
|
{ |
||||
|
return Task.CompletedTask; // Will be overriden by razor pages. (.cshtml)
|
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,27 @@ |
|||||
|
{ |
||||
|
"iisSettings": { |
||||
|
"windowsAuthentication": false, |
||||
|
"anonymousAuthentication": true, |
||||
|
"iisExpress": { |
||||
|
"applicationUrl": "http://localhost:60873/", |
||||
|
"sslPort": 44300 |
||||
|
} |
||||
|
}, |
||||
|
"profiles": { |
||||
|
"IIS Express": { |
||||
|
"commandName": "IISExpress", |
||||
|
"launchBrowser": true, |
||||
|
"environmentVariables": { |
||||
|
"ASPNETCORE_ENVIRONMENT": "Development" |
||||
|
} |
||||
|
}, |
||||
|
"Volo.CmsKit.Public.Web": { |
||||
|
"commandName": "Project", |
||||
|
"launchBrowser": true, |
||||
|
"environmentVariables": { |
||||
|
"ASPNETCORE_ENVIRONMENT": "Development" |
||||
|
}, |
||||
|
"applicationUrl": "https://localhost:5001;http://localhost:5000" |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,14 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.CmsKit.Blogs; |
||||
|
using Volo.CmsKit.Pages; |
||||
|
|
||||
|
namespace Volo.CmsKit.EntityFrameworkCore.Blogs |
||||
|
{ |
||||
|
public class BlogPostRepository_Test : BlogPostRepository_Test<CmsKitEntityFrameworkCoreTestModule> |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,14 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.CmsKit.Blogs; |
||||
|
|
||||
|
namespace Volo.CmsKit.EntityFrameworkCore.Blogs |
||||
|
{ |
||||
|
public class BlogRepository_Test : BlogRepository_Test<CmsKitEntityFrameworkCoreTestModule> |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,14 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.CmsKit.Tags; |
||||
|
|
||||
|
namespace Volo.CmsKit.EntityFrameworkCore.Tags |
||||
|
{ |
||||
|
public class EntityTagRepository_Test : EntityTagRepository_Test<CmsKitEntityFrameworkCoreTestModule> |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.CmsKit.Blogs; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Volo.CmsKit.MongoDB.Blogs |
||||
|
{ |
||||
|
[Collection(MongoTestCollection.Name)] |
||||
|
public class BlogPostRepository_Test : BlogPostRepository_Test<CmsKitMongoDbTestModule> |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.CmsKit.Blogs; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Volo.CmsKit.MongoDB.Blogs |
||||
|
{ |
||||
|
[Collection(MongoTestCollection.Name)] |
||||
|
public class BlogRepository_Test : BlogRepository_Test<CmsKitMongoDbTestModule> |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.CmsKit.Tags; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Volo.CmsKit.MongoDB.Tags |
||||
|
{ |
||||
|
[Collection(MongoTestCollection.Name)] |
||||
|
public class EntityTagRepository_Test : EntityTagRepository_Test<CmsKitMongoDbTestModule> |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,125 @@ |
|||||
|
using Shouldly; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Domain.Entities; |
||||
|
using Volo.Abp.Modularity; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Volo.CmsKit.Blogs |
||||
|
{ |
||||
|
public abstract class BlogPostRepository_Test<TStartupModule> : CmsKitTestBase<TStartupModule> |
||||
|
where TStartupModule : IAbpModule |
||||
|
{ |
||||
|
private readonly CmsKitTestData testData; |
||||
|
private readonly IBlogPostRepository blogPostRepository; |
||||
|
|
||||
|
public BlogPostRepository_Test() |
||||
|
{ |
||||
|
testData = GetRequiredService<CmsKitTestData>(); |
||||
|
blogPostRepository = GetRequiredService<IBlogPostRepository>(); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task SlugExistsAsync_ShouldReturnTrue_WithExistingUrlSlug() |
||||
|
{ |
||||
|
var result = await blogPostRepository.SlugExistsAsync(testData.Blog_Id, testData.BlogPost_1_UrlSlug); |
||||
|
|
||||
|
result.ShouldBeTrue(); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task SlugExistsAsync_ShouldReturnFalse_WithNonExistingUrlSlug() |
||||
|
{ |
||||
|
var nonExistingSlug = "any-other-url-slug"; |
||||
|
|
||||
|
var result = await blogPostRepository.SlugExistsAsync(testData.Blog_Id, nonExistingSlug); |
||||
|
|
||||
|
result.ShouldBeFalse(); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task SlugExistsAsync_ShouldReturnFalse_WithNonExistingBlogId() |
||||
|
{ |
||||
|
var nonExistingBlogId = Guid.NewGuid(); |
||||
|
|
||||
|
var result = await blogPostRepository.SlugExistsAsync(nonExistingBlogId, testData.BlogPost_1_UrlSlug); |
||||
|
|
||||
|
result.ShouldBeFalse(); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task GetByUrlSlugAsync_ShouldWorkProperly_WithCorrectParameters() |
||||
|
{ |
||||
|
var blogPost = await blogPostRepository.GetByUrlSlugAsync(testData.Blog_Id, testData.BlogPost_1_UrlSlug); |
||||
|
|
||||
|
blogPost.ShouldNotBeNull(); |
||||
|
blogPost.Id.ShouldBe(testData.BlogPost_1_Id); |
||||
|
blogPost.UrlSlug.ShouldBe(testData.BlogPost_1_UrlSlug); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task GetByUrlSlugAsync_ShouldThrowException_WithNonExistingBlogPostUrlSlug() |
||||
|
{ |
||||
|
var nonExistingSlugUrl = "absolutely-non-existing-url"; |
||||
|
var exception = await Should.ThrowAsync<EntityNotFoundException>( |
||||
|
async () => await blogPostRepository.GetByUrlSlugAsync(testData.Blog_Id, nonExistingSlugUrl)); |
||||
|
|
||||
|
exception.ShouldNotBeNull(); |
||||
|
exception.EntityType.ShouldBe(typeof(BlogPost)); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task GetByUrlSlugAsync_ShouldThrowException_WithNonExistingBlogId() |
||||
|
{ |
||||
|
var nonExistingBlogId = Guid.NewGuid(); |
||||
|
var exception = await Should.ThrowAsync<EntityNotFoundException>( |
||||
|
async () => await blogPostRepository.GetByUrlSlugAsync(nonExistingBlogId, testData.BlogPost_1_UrlSlug)); |
||||
|
|
||||
|
exception.ShouldNotBeNull(); |
||||
|
exception.EntityType.ShouldBe(typeof(BlogPost)); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task GetPagedListAsync_ShouldWorkProperly_WithBlogId_WhileGetting10_WithoutSorting() |
||||
|
{ |
||||
|
var result = await blogPostRepository.GetPagedListAsync(testData.Blog_Id, 0, 10, default); |
||||
|
|
||||
|
result.ShouldNotBeNull(); |
||||
|
result.ShouldNotBeEmpty(); |
||||
|
result.Count.ShouldBe(2); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task GetPagedListAsync_ShouldWorkProperly_WithBlogId_WhileGetting1_WithoutSorting() |
||||
|
{ |
||||
|
var result = await blogPostRepository.GetPagedListAsync(testData.Blog_Id, default, 1, default); |
||||
|
|
||||
|
result.ShouldNotBeNull(); |
||||
|
result.ShouldNotBeEmpty(); |
||||
|
result.Count.ShouldBe(1); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task GetPagedListAsync_ShouldWorkProperly_WithBlogId_WhileGetting1InPage2_WithoutSorting() |
||||
|
{ |
||||
|
var result = await blogPostRepository.GetPagedListAsync(testData.Blog_Id, 1, 1, default); |
||||
|
|
||||
|
result.ShouldNotBeNull(); |
||||
|
result.ShouldNotBeEmpty(); |
||||
|
result.Count.ShouldBe(1); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task GetPagedListAsync_ShouldWorkProperly_WithBlogId_WhileGetting10_WithSortingByTitle() |
||||
|
{ |
||||
|
var result = await blogPostRepository.GetPagedListAsync(testData.Blog_Id, default, 10, nameof(BlogPost.Title)); |
||||
|
|
||||
|
result.ShouldNotBeNull(); |
||||
|
result.ShouldNotBeEmpty(); |
||||
|
result.Count.ShouldBe(2); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,65 @@ |
|||||
|
using Shouldly; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Domain.Entities; |
||||
|
using Volo.Abp.Modularity; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Volo.CmsKit.Blogs |
||||
|
{ |
||||
|
public abstract class BlogRepository_Test<TStartupModule> : CmsKitTestBase<TStartupModule> |
||||
|
where TStartupModule : IAbpModule |
||||
|
{ |
||||
|
private readonly CmsKitTestData testData; |
||||
|
private readonly IBlogRepository blogRepository; |
||||
|
|
||||
|
public BlogRepository_Test() |
||||
|
{ |
||||
|
this.testData = GetRequiredService<CmsKitTestData>(); |
||||
|
this.blogRepository = GetRequiredService<IBlogRepository>(); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task GetByUrlSlugAsync_ShouldWorkProperly_WithExistingSlug() |
||||
|
{ |
||||
|
var blog = await blogRepository.GetByUrlSlugAsync(testData.BlogUrlSlug); |
||||
|
|
||||
|
blog.ShouldNotBeNull(); |
||||
|
blog.UrlSlug.ShouldBe(testData.BlogUrlSlug); |
||||
|
blog.Id.ShouldBe(testData.Blog_Id); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task GetByUrlSlugAsync_ShouldThrowException_WithNonExistingSlug() |
||||
|
{ |
||||
|
var nonExistingSlug = "some-blog-slug-that-doesnt-exist"; |
||||
|
|
||||
|
var exception = await Should.ThrowAsync<EntityNotFoundException>( |
||||
|
async () => await blogRepository.GetByUrlSlugAsync(nonExistingSlug)); |
||||
|
|
||||
|
exception.ShouldNotBeNull(); |
||||
|
exception.EntityType.ShouldBe(typeof(Blog)); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task ExistsAsync_ShouldReturnTrue_WithExistingId() |
||||
|
{ |
||||
|
var result = await blogRepository.ExistsAsync(testData.Blog_Id); |
||||
|
|
||||
|
result.ShouldBeTrue(); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task ExistsAsync_ShouldReturnFalse_WithExistingId() |
||||
|
{ |
||||
|
var nonExistingId = Guid.NewGuid(); |
||||
|
|
||||
|
var result = await blogRepository.ExistsAsync(nonExistingId); |
||||
|
|
||||
|
result.ShouldBeFalse(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,38 @@ |
|||||
|
using Shouldly; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Modularity; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Volo.CmsKit.Tags |
||||
|
{ |
||||
|
public abstract class EntityTagRepository_Test<TStartupModule> : CmsKitTestBase<TStartupModule> |
||||
|
where TStartupModule : IAbpModule |
||||
|
{ |
||||
|
private CmsKitTestData _cmsKitTestData; |
||||
|
private IEntityTagRepository _entityTagRepository; |
||||
|
private ITagRepository _tagRepository; |
||||
|
|
||||
|
public EntityTagRepository_Test() |
||||
|
{ |
||||
|
_cmsKitTestData = GetRequiredService<CmsKitTestData>(); |
||||
|
_entityTagRepository = GetRequiredService<IEntityTagRepository>(); |
||||
|
_tagRepository = GetRequiredService<ITagRepository>(); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task DeleteManyAsync_ShouldWorkProperly_WithExistingIds() |
||||
|
{ |
||||
|
var relatedTags = await _tagRepository.GetAllRelatedTagsAsync(_cmsKitTestData.Content_1_EntityType, _cmsKitTestData.Content_1_EntityId); |
||||
|
|
||||
|
await _entityTagRepository.DeleteManyAsync(relatedTags.Select(s => s.Id).ToArray()); |
||||
|
|
||||
|
relatedTags = await _tagRepository.GetAllRelatedTagsAsync(_cmsKitTestData.Content_1_EntityType, _cmsKitTestData.Content_1_EntityId); |
||||
|
|
||||
|
relatedTags.ShouldBeEmpty(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue