Merge pull request #13885 from abpframework/enisn/6.0-temp

Merge `rel-6.0` into `dev`
pull/13888/head
malik masis 3 years ago committed by GitHub
commit a33848adb5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -36,7 +36,6 @@ using Volo.Abp.Threading;
using Volo.Abp.VirtualFileSystem;
using Volo.CmsKit.Admin.Web;
using Volo.CmsKit.Comments;
using Volo.CmsKit.Contents;
using Volo.CmsKit.EntityFrameworkCore;
using Volo.CmsKit.MediaDescriptors;
using Volo.CmsKit.MultiTenancy;
@ -45,6 +44,7 @@ using Volo.CmsKit.Ratings;
using Volo.CmsKit.Reactions;
using Volo.CmsKit.Tags;
using Volo.CmsKit.Web;
using Volo.CmsKit.Web.Contents;
namespace Volo.CmsKit;

@ -1,9 +0,0 @@
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
namespace Volo.CmsKit.Admin.Contents;
public interface IContentAdminAppService : IApplicationService
{
Task<ListResultDto<ContentWidgetDto>> GetWidgetsAsync();
}

@ -13,4 +13,8 @@
<ProjectReference Include="..\Volo.CmsKit.Common.Application\Volo.CmsKit.Common.Application.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Volo\CmsKit\Admin\Contents\" />
</ItemGroup>
</Project>

@ -1,32 +0,0 @@
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using Volo.Abp.Application.Dtos;
using Volo.CmsKit.Contents;
namespace Volo.CmsKit.Admin.Contents;
public class ContentAdminAppService : CmsKitAdminAppServiceBase, IContentAdminAppService
{
private readonly CmsKitContentWidgetOptions _options;
public ContentAdminAppService(IOptions<CmsKitContentWidgetOptions> options)
{
_options = options.Value;
}
public virtual Task<ListResultDto<ContentWidgetDto>> GetWidgetsAsync()
{
return Task.FromResult(new ListResultDto<ContentWidgetDto>()
{
Items = _options.WidgetConfigs
.Select(n =>
new ContentWidgetDto
{
Key = n.Key,
Details = new WidgetDetailDto() { EditorComponentName = n.Value.EditorComponentName, Name = n.Value.Name },
}).ToList()
});
}
}

@ -1,22 +0,0 @@
// This file is automatically generated by ABP framework to use MVC Controllers from CSharp
using System;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Http.Client;
using Volo.Abp.Http.Modeling;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Http.Client.ClientProxying;
using Volo.CmsKit.Admin.Contents;
// ReSharper disable once CheckNamespace
namespace Volo.CmsKit.Admin.Contents.ClientProxies;
[Dependency(ReplaceServices = true)]
[ExposeServices(typeof(IContentAdminAppService), typeof(ContentAdminClientProxy))]
public partial class ContentAdminClientProxy : ClientProxyBase<IContentAdminAppService>, IContentAdminAppService
{
public virtual async Task<ListResultDto<ContentWidgetDto>> GetWidgetsAsync()
{
return await RequestAsync<ListResultDto<ContentWidgetDto>>(nameof(GetWidgetsAsync));
}
}

@ -1,7 +0,0 @@
// This file is part of ContentAdminClientProxy, you can customize it here
// ReSharper disable once CheckNamespace
namespace Volo.CmsKit.Admin.Contents.ClientProxies;
public partial class ContentAdminClientProxy
{
}

@ -1191,35 +1191,6 @@
}
}
},
"Volo.CmsKit.Admin.Contents.ContentAdminController": {
"controllerName": "ContentAdmin",
"controllerGroupName": "ContentAdmin",
"isRemoteService": true,
"apiVersion": null,
"type": "Volo.CmsKit.Admin.Contents.ContentAdminController",
"interfaces": [
{
"type": "Volo.CmsKit.Admin.Contents.IContentAdminAppService"
}
],
"actions": {
"GetWidgetsAsync": {
"uniqueName": "GetWidgetsAsync",
"name": "GetWidgetsAsync",
"httpMethod": "GET",
"url": "api/cms-kit-admin/contents",
"supportedVersions": [],
"parametersOnMethod": [],
"parameters": [],
"returnValue": {
"type": "Volo.Abp.Application.Dtos.ListResultDto<Volo.CmsKit.Admin.Contents.ContentWidgetDto>",
"typeSimple": "Volo.Abp.Application.Dtos.ListResultDto<Volo.CmsKit.Admin.Contents.ContentWidgetDto>"
},
"allowAnonymous": null,
"implementFrom": "Volo.CmsKit.Admin.Contents.IContentAdminAppService"
}
}
},
"Volo.CmsKit.Admin.Comments.CommentAdminController": {
"controllerName": "CommentAdmin",
"controllerGroupName": "CommentAdmin",

@ -1,25 +0,0 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
namespace Volo.CmsKit.Admin.Contents;
[RemoteService(Name = CmsKitAdminRemoteServiceConsts.RemoteServiceName)]
[Area(CmsKitAdminRemoteServiceConsts.ModuleName)]
[Route("api/cms-kit-admin/contents")]
public class ContentAdminController : CmsKitAdminController, IContentAdminAppService
{
protected IContentAdminAppService ContentAdminAppService { get; }
public ContentAdminController(IContentAdminAppService contentAdminAppService)
{
ContentAdminAppService = contentAdminAppService;
}
[HttpGet]
public virtual Task<ListResultDto<ContentWidgetDto>> GetWidgetsAsync()
{
return ContentAdminAppService.GetWidgetsAsync();
}
}

@ -3,38 +3,48 @@ using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.Extensions.Options;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form;
using Volo.Abp.AspNetCore.Mvc.UI.RazorPages;
using Volo.CmsKit.Admin.Contents;
using Volo.CmsKit.Contents;
using Volo.CmsKit.Web.Contents;
namespace Volo.CmsKit.Admin.Web.Pages.CmsKit.Contents;
public class AddWidgetModal : AbpPageModel
{
protected IContentAdminAppService ContentAdminAppService { get; }
[BindProperty]
public ContentViewModel ViewModel { get; set; }
public List<SelectListItem> Widgets { get; set; } = new();
public AddWidgetModal(IContentAdminAppService contentAdminAppService)
private readonly CmsKitContentWidgetOptions _options;
public AddWidgetModal(IOptions<CmsKitContentWidgetOptions> options)
{
ContentAdminAppService = contentAdminAppService;
_options = options.Value;
}
public async Task OnGetAsync()
{
var widgets = await ContentAdminAppService.GetWidgetsAsync();
var widgets = _options.WidgetConfigs
.Select(n =>
new ContentWidgetDto
{
Key = n.Key,
Details = new WidgetDetailDto() { EditorComponentName = n.Value.EditorComponentName, Name = n.Value.Name },
}).ToList();
ViewModel = new ContentViewModel()
{
Details = widgets.Items.Select(p => p.Details).ToList()
Details = widgets.Select(p => p.Details).ToList()
};
Widgets = new List<SelectListItem>() { new(string.Empty, string.Empty) };
Widgets.AddRange(widgets
.Items
.Select(w => new SelectListItem(w.Key, w.Details.Name))
.ToList());
}

@ -247,21 +247,6 @@
})();
// controller volo.cmsKit.admin.contents.contentAdmin
(function(){
abp.utils.createNamespace(window, 'volo.cmsKit.admin.contents.contentAdmin');
volo.cmsKit.admin.contents.contentAdmin.getWidgets = function(ajaxParams) {
return abp.ajax($.extend(true, {
url: abp.appPath + 'api/cms-kit-admin/contents',
type: 'GET'
}, ajaxParams));
};
})();
// controller volo.cmsKit.admin.comments.commentAdmin
(function(){

@ -1,12 +1,11 @@
using System;
using System.Collections.Generic;
using Volo.Abp.Application.Dtos;
using Volo.CmsKit.Users;
namespace Volo.CmsKit.Contents;
[Serializable]
public class BlogPostCommonDto : AuditedEntityDto<Guid>, IContent
public class BlogPostCommonDto : AuditedEntityDto<Guid>
{
public Guid BlogId { get; set; }
@ -16,8 +15,6 @@ public class BlogPostCommonDto : AuditedEntityDto<Guid>, IContent
public string ShortDescription { get; set; }
public List<ContentFragment> ContentFragments { get; set; }
public string Content { get; set; }
public Guid? CoverImageMediaId { get; set; }

@ -1,10 +0,0 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
namespace Volo.CmsKit.Contents;
public interface IContentAppService : IApplicationService
{
Task<List<ContentFragment>> ParseAsync(string content);
}

@ -5,7 +5,7 @@ using Volo.Abp.Application.Dtos;
namespace Volo.CmsKit.Contents;
[Serializable]
public class PageDto : EntityDto<Guid>, IContent
public class PageDto : EntityDto<Guid>
{
public string Title { get; set; }
@ -13,8 +13,6 @@ public class PageDto : EntityDto<Guid>, IContent
public string Content { get; set; }
public List<ContentFragment> ContentFragments { get; set; }
public string Script { get; set; }
public string Style { get; set; }

@ -1,22 +0,0 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.GlobalFeatures;
using Volo.CmsKit.GlobalFeatures;
namespace Volo.CmsKit.Contents;
[RequiresGlobalFeature(typeof(PagesFeature))]
public class ContentAppService : CmsKitAppServiceBase, IContentAppService
{
protected ContentParser ContentParser { get; }
public ContentAppService(ContentParser contentParser)
{
ContentParser = contentParser;
}
public async Task<List<ContentFragment>> ParseAsync(string content)
{
return await ContentParser.ParseAsync(content);
}
}

@ -6,21 +6,22 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc;
using Volo.CmsKit.Contents;
using Volo.CmsKit.Web.Contents;
namespace Volo.CmsKit.Web.Pages.CmsKit.Components.ContentPreview;
public class ContentPreviewViewComponent : AbpViewComponent
{
protected IContentAppService ContentAppService { get; }
protected ContentParser ContentParser { get; }
public ContentPreviewViewComponent(IContentAppService contentAppService)
public ContentPreviewViewComponent(ContentParser contentParser)
{
ContentAppService = contentAppService;
ContentParser = contentParser;
}
public virtual async Task<IViewComponentResult> InvokeAsync(string content)
{
var fragments = await ContentAppService.ParseAsync(content);
var fragments = await ContentParser.ParseAsync(content);
return View("~/Pages/CmsKit/Components/ContentPreview/Default.cshtml", new DefaultContentDto
{

@ -1,6 +1,6 @@
using System.Collections.Generic;
namespace Volo.CmsKit.Contents;
namespace Volo.CmsKit.Web.Contents;
public class CmsKitContentWidgetOptions
{

@ -5,9 +5,10 @@ using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
using Volo.CmsKit.Contents;
using static Volo.CmsKit.Contents.ContentConsts;
namespace Volo.CmsKit.Contents;
namespace Volo.CmsKit.Web.Contents;
public class ContentParser : ITransientDependency
{

@ -6,6 +6,7 @@ using Volo.Abp.Application.Dtos;
using Volo.Abp.Features;
using Volo.Abp.GlobalFeatures;
using Volo.CmsKit.Blogs;
using Volo.CmsKit.Contents;
using Volo.CmsKit.Features;
using Volo.CmsKit.GlobalFeatures;
@ -20,16 +21,13 @@ public class BlogPostPublicAppService : CmsKitPublicAppServiceBase, IBlogPostPub
protected IBlogRepository BlogRepository { get; }
protected IBlogPostRepository BlogPostRepository { get; }
protected ContentParser ContentParser { get; }
public BlogPostPublicAppService(
IBlogRepository blogRepository,
IBlogPostRepository blogPostRepository,
ContentParser contentParser)
IBlogPostRepository blogPostRepository)
{
BlogRepository = blogRepository;
BlogPostRepository = blogPostRepository;
ContentParser = contentParser;
}
public virtual async Task<BlogPostCommonDto> GetAsync(
@ -39,10 +37,7 @@ public class BlogPostPublicAppService : CmsKitPublicAppServiceBase, IBlogPostPub
var blogPost = await BlogPostRepository.GetBySlugAsync(blog.Id, blogPostSlug);
var blogPostDto = ObjectMapper.Map<BlogPost, BlogPostCommonDto>(blogPost);
blogPostDto.ContentFragments = await ContentParser.ParseAsync(blogPost.Content);
return blogPostDto;
return ObjectMapper.Map<BlogPost, BlogPostCommonDto>(blogPost);
}
public virtual async Task<PagedResultDto<BlogPostCommonDto>> GetListAsync([NotNull] string blogSlug, BlogPostGetListInput input)

@ -13,12 +13,10 @@ namespace Volo.CmsKit.Public.Pages;
public class PagePublicAppService : CmsKitPublicAppServiceBase, IPagePublicAppService
{
protected IPageRepository PageRepository { get; }
protected ContentParser ContentParser { get; }
public PagePublicAppService(IPageRepository pageRepository, ContentParser contentParser)
public PagePublicAppService(IPageRepository pageRepository)
{
PageRepository = pageRepository;
ContentParser = contentParser;
}
public virtual async Task<PageDto> FindBySlugAsync(string slug)
@ -30,8 +28,6 @@ public class PagePublicAppService : CmsKitPublicAppServiceBase, IPagePublicAppSe
return null;
}
var pageDto = ObjectMapper.Map<Page, PageDto>(page);
pageDto.ContentFragments = await ContentParser.ParseAsync(page.Content);
return pageDto;
return ObjectMapper.Map<Page, PageDto>(page);
}
}

@ -30,11 +30,9 @@ public class PublicApplicationAutoMapperProfile : Profile
CreateMap<Rating, RatingDto>();
CreateMap<Page, PageDto>()
.Ignore(x => x.ContentFragments);
CreateMap<BlogPost, BlogPostCommonDto>()
.Ignore(x => x.ContentFragments);
CreateMap<Page, PageDto>();
CreateMap<BlogPost, BlogPostCommonDto>();
CreateMap<MenuItem, MenuItemDto>();

@ -9,9 +9,9 @@
@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
@using Volo.CmsKit.Web.Renderers
@using Volo.Abp.AspNetCore.Mvc.UI.Packages.HighlightJs
@using Volo.CmsKit.Contents
@using Volo.CmsKit.Web.Renderers
@inherits CmsKitPublicPageBase
@ -21,7 +21,7 @@
@{
string dummyImageSource = "https://dummyimage.com/1280x720/a3a3a3/fff.png?text=" + Model.BlogPost.Title;
string dummyImageSource = "https://dummyimage.com/1280x720/a3a3a3/fff.png?text=" + Model.ViewModel.Title;
var isScrollIndexEnabled = GlobalFeatureManager.Instance.IsEnabled<BlogPostScrollIndexFeature>() && Model.BlogPostScrollIndexFeature?.IsEnabled == true;
}
@ -32,14 +32,13 @@
<abp-style src="/Pages/Public/CmsKit/Blogs/bootstrap-toc.css" />
</abp-abp-style-bundle>
}
<abp-abp-style-bundle>
<abp-style src="/Pages/Public/CmsKit/Blogs/blogPost.css" />
<abp-style type="typeof(HighlightJsStyleContributor)" />
</abp-abp-style-bundle>
}
@section scripts{
@section scripts{
@if (isScrollIndexEnabled)
{
<abp-script-bundle>
@ -55,41 +54,51 @@
}
<div class="row">
<div @Html.Raw(isScrollIndexEnabled ? "class=\"col-md-10 col-sm-12\"" : "class=\"col-md-12\"")>
<abp-card class="mb-4">
<img src="/api/cms-kit/media/@Model.BlogPost.CoverImageMediaId" class="card-img-top" onerror="this.src='@dummyImageSource'" />
<abp-card-body>
<abp-row>
<div class="col-lg-8 col-md-10 mx-auto pb-4">
<h1 class="mt-lg-4 mt-md-3">@Model.BlogPost.Title</h1>
<p class="mb-lg-5 mb-md-3">
<a href="/blogs/@Model.BlogSlug?authorId=@Model.BlogPost.Author.Id">
<span class="font-weight-bold">@@@Model.BlogPost.Author?.UserName</span>
</a>
<small style="opacity:.65;">@Model.BlogPost.CreationTime</small>
</p>
@await Component.InvokeAsync("ContentFragment", new { contentDto = Model.BlogPost })
<p class="mb-3">
@if (Model.BlogPost.LastModificationTime != null)
<div class="row">
<div @Html.Raw(isScrollIndexEnabled ? "class=\"col-md-10 col-sm-12\"" : "class=\"col-md-12\"")>
<abp-card class="mb-4">
<img src="/api/cms-kit/media/@Model.ViewModel.CoverImageMediaId" class="card-img-top" onerror="this.src='@dummyImageSource'" />
<abp-card-body>
<abp-row>
<div class="col-lg-8 col-md-10 mx-auto pb-4">
<h1 class="mt-lg-4 mt-md-3">@Model.ViewModel.Title</h1>
<p class="mb-lg-5 mb-md-3">
<a href="/blogs/@Model.BlogSlug?authorId=@Model.ViewModel.Author.Id">
<span class="font-weight-bold">@@@Model.ViewModel.Author?.UserName</span>
</a>
<small style="opacity:.65;">@Model.ViewModel.CreationTime</small>
</p>
@foreach (var contentFragment in Model.ViewModel.ContentFragments)
{
<small style="opacity:.65;">@L["LastModification"].Value : @Model.BlogPost.LastModificationTime</small>
if (contentFragment.Type == ContentConsts.Markdown)
{
@Html.Raw(await MarkdownRenderer.RenderAsync(contentFragment.GetProperty<string>("Content"), allowHtmlTags: true, preventXSS: true))
}
else if (contentFragment.Type == ContentConsts.Widget)
{
@await Component.InvokeAsync(contentFragment.GetProperty<string>("Type"), contentFragment.ExtraProperties.ConvertToDynamicObject())
}
}
</p>
<hr />
<p class="mb-3">
@if (Model.ViewModel.LastModificationTime != null)
{
<small style="opacity:.65;">@L["LastModification"].Value : @Model.ViewModel.LastModificationTime</small>
}
</p>
<hr />
@if (GlobalFeatureManager.Instance.IsEnabled<TagsFeature>())
{
if (Model.TagsFeature?.IsEnabled == true)
@if (GlobalFeatureManager.Instance.IsEnabled<TagsFeature>())
{
@await Component.InvokeAsync(typeof(TagViewComponent), new
if (Model.TagsFeature?.IsEnabled == true)
{
entityType = Volo.CmsKit.Blogs.BlogPostConsts.EntityType,
entityId = Model.BlogPost.Id.ToString(),
urlFormat = $"/blogs/{Model.BlogSlug}?tagId={{TagId}}"
})
@await Component.InvokeAsync(typeof(TagViewComponent), new
{
entityType = Volo.CmsKit.Blogs.BlogPostConsts.EntityType,
entityId = Model.ViewModel.Id.ToString(),
urlFormat = $"/blogs/{Model.BlogSlug}?tagId={{TagId}}"
})
}
}
}
</div>
</abp-row>
@ -100,10 +109,10 @@
if (Model.ReactionsFeature?.IsEnabled == true)
{
@await Component.InvokeAsync(typeof(ReactionSelectionViewComponent), new
{
entityType = Volo.CmsKit.Blogs.BlogPostConsts.EntityType,
entityId = Model.BlogPost.Id.ToString()
})
{
entityType = Volo.CmsKit.Blogs.BlogPostConsts.EntityType,
entityId = Model.ViewModel.Id.ToString()
})
}
}
</abp-column>
@ -113,10 +122,10 @@
if (Model.RatingsFeature?.IsEnabled == true)
{
@await Component.InvokeAsync(typeof(RatingViewComponent), new
{
entityType = Volo.CmsKit.Blogs.BlogPostConsts.EntityType,
entityId = Model.BlogPost.Id.ToString()
})
{
entityType = Volo.CmsKit.Blogs.BlogPostConsts.EntityType,
entityId = Model.ViewModel.Id.ToString()
})
}
}
</abp-column>
@ -124,7 +133,6 @@
</abp-card-body>
</abp-card>
</div>
@if (isScrollIndexEnabled)
{
<div class="col-md-2 d-sm-none d-md-block">
@ -132,7 +140,7 @@
<h5>@L["InThisDocument"]</h5>
<nav id="blog-post-sticky-index" class="navbar index-scroll pt-0">
</nav>
<div class="row">
<div class="col p-0 py-3">
<a href="#" class="scroll-top-btn">
@ -153,7 +161,7 @@
@await Component.InvokeAsync(typeof(DefaultBlogPostCommentViewComponent), new
{
entityType = Volo.CmsKit.Blogs.BlogPostConsts.EntityType,
entityId = Model.BlogPost.Id.ToString()
entityId = Model.ViewModel.Id.ToString()
})
}
}

@ -1,10 +1,12 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.GlobalFeatures;
using Volo.Abp.ObjectMapping;
using Volo.CmsKit.Blogs;
using Volo.CmsKit.Contents;
using Volo.CmsKit.GlobalFeatures;
using Volo.CmsKit.Public.Blogs;
using Volo.CmsKit.Web.Contents;
namespace Volo.CmsKit.Public.Web.Pages.Public.CmsKit.Blogs;
@ -16,7 +18,7 @@ public class BlogPostModel : CmsKitPublicPageModelBase
[BindProperty(SupportsGet = true)]
public string BlogPostSlug { get; set; }
public BlogPostCommonDto BlogPost { get; private set; }
public BlogPostViewModel ViewModel { get; private set; }
public BlogFeatureDto CommentsFeature { get; private set; }
@ -25,48 +27,61 @@ public class BlogPostModel : CmsKitPublicPageModelBase
public BlogFeatureDto RatingsFeature { get; private set; }
public BlogFeatureDto TagsFeature { get; private set; }
public BlogFeatureDto BlogPostScrollIndexFeature { get; private set; }
protected IBlogPostPublicAppService BlogPostPublicAppService { get; }
protected IBlogFeatureAppService BlogFeatureAppService { get; }
protected ContentParser ContentParser { get; }
public BlogPostModel(
IBlogPostPublicAppService blogPostPublicAppService,
IBlogFeatureAppService blogFeaturePublicAppService)
IBlogFeatureAppService blogFeaturePublicAppService,
ContentParser contentParser)
{
BlogPostPublicAppService = blogPostPublicAppService;
BlogFeatureAppService = blogFeaturePublicAppService;
ContentParser = contentParser;
}
public virtual async Task OnGetAsync()
public virtual async Task<IActionResult> OnGetAsync()
{
BlogPost = await BlogPostPublicAppService.GetAsync(BlogSlug, BlogPostSlug);
var blogPostPublicDto = await BlogPostPublicAppService.GetAsync(BlogSlug, BlogPostSlug);
ViewModel = ObjectMapper.Map<BlogPostCommonDto, BlogPostViewModel>(blogPostPublicDto);
if (ViewModel == null)
{
return NotFound();
}
ViewModel.ContentFragments = await ContentParser.ParseAsync(blogPostPublicDto.Content);
if (GlobalFeatureManager.Instance.IsEnabled<CommentsFeature>())
{
CommentsFeature = await BlogFeatureAppService.GetOrDefaultAsync(BlogPost.BlogId, GlobalFeatures.CommentsFeature.Name);
CommentsFeature = await BlogFeatureAppService.GetOrDefaultAsync(ViewModel.BlogId, GlobalFeatures.CommentsFeature.Name);
}
if (GlobalFeatureManager.Instance.IsEnabled<ReactionsFeature>())
{
ReactionsFeature = await BlogFeatureAppService.GetOrDefaultAsync(BlogPost.BlogId, GlobalFeatures.ReactionsFeature.Name);
ReactionsFeature = await BlogFeatureAppService.GetOrDefaultAsync(ViewModel.BlogId, GlobalFeatures.ReactionsFeature.Name);
}
if (GlobalFeatureManager.Instance.IsEnabled<RatingsFeature>())
{
RatingsFeature = await BlogFeatureAppService.GetOrDefaultAsync(BlogPost.BlogId, GlobalFeatures.RatingsFeature.Name);
RatingsFeature = await BlogFeatureAppService.GetOrDefaultAsync(ViewModel.BlogId, GlobalFeatures.RatingsFeature.Name);
}
if (GlobalFeatureManager.Instance.IsEnabled<TagsFeature>())
{
TagsFeature = await BlogFeatureAppService.GetOrDefaultAsync(BlogPost.BlogId, GlobalFeatures.TagsFeature.Name);
TagsFeature = await BlogFeatureAppService.GetOrDefaultAsync(ViewModel.BlogId, GlobalFeatures.TagsFeature.Name);
}
if (GlobalFeatureManager.Instance.IsEnabled<BlogPostScrollIndexFeature>())
{
BlogPostScrollIndexFeature = await BlogFeatureAppService.GetOrDefaultAsync(BlogPost.BlogId, GlobalFeatures.BlogPostScrollIndexFeature.Name);
BlogPostScrollIndexFeature = await BlogFeatureAppService.GetOrDefaultAsync(ViewModel.BlogId, GlobalFeatures.BlogPostScrollIndexFeature.Name);
}
return Page();
}
}

@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using AutoMapper;
using Volo.Abp.Application.Dtos;
using Volo.CmsKit.Contents;
using Volo.CmsKit.Users;
namespace Volo.CmsKit.Public.Web.Pages.Public.CmsKit.Blogs;
[AutoMap(typeof(BlogPostCommonDto), ReverseMap = true)]
public class BlogPostViewModel : AuditedEntityDto<Guid>
{
public Guid BlogId { get; set; }
public string Title { get; set; }
public string Slug { get; set; }
public string ShortDescription { get; set; }
public string Content { get; set; }
public List<ContentFragment> ContentFragments { get; set; }
public Guid? CoverImageMediaId { get; set; }
public CmsUserDto Author { get; set; }
}

@ -5,27 +5,39 @@
@using Volo.Abp.Data
@using Volo.Abp.AspNetCore.Mvc.UI.Packages.HighlightJs;
@using Volo.Abp.AspNetCore.Mvc.UI.Widgets;
@using Volo.CmsKit.Web.Renderers
@model Volo.CmsKit.Public.Web.Pages.Public.CmsKit.Pages.IndexModel
@inject IMarkdownToHtmlRenderer MarkdownRenderer
@section styles{
<abp-style src="/Pages/Public/CmsKit/Pages/index.css" />
<style>
@Html.Raw(Model.PageDto.Style)
@Html.Raw(Model.ViewModel.Style)
</style>
}
@section scripts{
<script>
@Html.Raw(Model.PageDto.Script)
@Html.Raw(Model.ViewModel.Script)
</script>
}
<abp-card>
<abp-card-body>
@await Component.InvokeAsync("ContentFragment", new { contentDto = Model.PageDto })
@foreach (ContentFragment contentFragment in Model.ViewModel.ContentFragments)
{
if (contentFragment.Type == ContentConsts.Markdown)
{
@Html.Raw(await MarkdownRenderer.RenderAsync(contentFragment.GetProperty<string>("Content"), allowHtmlTags: true, preventXSS: true))
}
else if (contentFragment.Type == ContentConsts.Widget)
{
@await Component.InvokeAsync(contentFragment.GetProperty<string>("Type"), contentFragment.ExtraProperties.ConvertToDynamicObject())
}
}
</abp-card-body>
</abp-card>

@ -2,6 +2,7 @@
using Microsoft.AspNetCore.Mvc;
using Volo.CmsKit.Contents;
using Volo.CmsKit.Public.Pages;
using Volo.CmsKit.Web.Contents;
using Volo.CmsKit.Web.Pages;
namespace Volo.CmsKit.Public.Web.Pages.Public.CmsKit.Pages;
@ -13,21 +14,26 @@ public class IndexModel : CommonPageModel
protected IPagePublicAppService PagePublicAppService { get; }
public PageDto PageDto { get; private set; }
protected ContentParser ContentParser { get; }
public IndexModel(IPagePublicAppService pagePublicAppService)
public PageViewModel ViewModel { get; private set; }
public IndexModel(IPagePublicAppService pagePublicAppService, ContentParser contentParser)
{
PagePublicAppService = pagePublicAppService;
ContentParser = contentParser;
}
public async Task<IActionResult> OnGetAsync()
public virtual async Task<IActionResult> OnGetAsync()
{
PageDto = await PagePublicAppService.FindBySlugAsync(Slug);
if (PageDto == null)
var pageDto = await PagePublicAppService.FindBySlugAsync(Slug);
ViewModel = ObjectMapper.Map<PageDto, PageViewModel>(pageDto);
if (ViewModel == null)
{
return NotFound();
}
ViewModel.ContentFragments = await ContentParser.ParseAsync(pageDto.Content);
return Page();
}

@ -1,9 +1,12 @@
using System;
using System.Collections.Generic;
using AutoMapper;
using Volo.CmsKit.Contents;
using Volo.CmsKit.Public.Pages;
namespace Volo.CmsKit.Public.Web.Pages.Public.CmsKit.Pages;
[AutoMap(typeof(PageDto), ReverseMap = true)]
public class PageViewModel
{
public Guid Id { get; set; }
@ -11,4 +14,8 @@ public class PageViewModel
public string Title { get; set; }
public List<ContentFragment> ContentFragments { get; set; }
public string Script { get; set; }
public string Style { get; set; }
}

@ -1,27 +0,0 @@
using System.Linq;
using System.Threading.Tasks;
using Shouldly;
using Volo.CmsKit.Admin.Contents;
using Xunit;
namespace Volo.CmsKit.Contents;
public class ContentAdminAppService_Tests : CmsKitApplicationTestBase
{
private readonly IContentAdminAppService _contentAdminAppService;
public ContentAdminAppService_Tests()
{
_contentAdminAppService = GetRequiredService<IContentAdminAppService>();
}
[Fact]
public async Task ShouldGet_PagedListAsync()
{
var widgets = await _contentAdminAppService.GetWidgetsAsync();
widgets.Items.Count.ShouldBe(0);
widgets.Items.Any().ShouldBeFalse();
}
}

@ -1,138 +0,0 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using Shouldly;
using Xunit;
namespace Volo.CmsKit.Contents;
public class ContentParser_Test : CmsKitDomainTestBase
{
private readonly CmsKitTestData testData;
private readonly IOptions<CmsKitContentWidgetOptions> _options;
private ContentParser contentParser;
public ContentParser_Test()
{
testData = GetRequiredService<CmsKitTestData>();
_options = GetRequiredService<IOptions<CmsKitContentWidgetOptions>>();
}
[Fact]
public async Task ParseAsync_ShouldWorkWithDifferentWidgetTypes()
{
_options.Value.AddWidget(testData.PollName, testData.WidgetName, string.Empty);
_options.Value.AddWidget("ImageGallery", "ImageGallery", string.Empty);
contentParser = new ContentParser(_options);
var content = @"**ABP Framework** is completely open source and developed in a community-driven manner.
[Widget Type=""Poll"" Code=""poll-name""]
Thanks _for_ *your * feedback.
[Widget GalleryName=""Xyz"" Type=""ImageGallery"" Source=""GoogleDrive""]";
var widgets = await contentParser.ParseAsync(content);
widgets.ShouldNotBeNull();
widgets.Count.ShouldBe(4);
widgets[1].ExtraProperties.Count.ShouldBe(2);
widgets[3].ExtraProperties.Count.ShouldBe(3);
}
[Fact]
public async Task ParseAsync_ShouldWorkWithoutConfigOptions()
{
var content = @"**ABP Framework** is completely open source and developed in a community-driven manner.
[Widget Type= ""Poll"" Code =""poll-name""]
Thanks _for_ *your * feedback.";
contentParser = new ContentParser(_options);
var widgets = await contentParser.ParseAsync(content);
widgets.ShouldNotBeNull();
widgets.Count.ShouldBe(1);//Ignored Widget
}
[Fact]
public async Task ParseAsync_ShouldWorkWithWrongConfigOptions()
{
_options.Value.AddWidget(testData.WidgetName, testData.PollName, string.Empty);
contentParser = new ContentParser(_options);
var content = @"**ABP Framework** is completely open source and developed in a community-driven manner.
[Widget Type= ""Poll"" Code =""poll-name""]
Thanks _for_ *your * feedback.";
var widgets = await contentParser.ParseAsync(content);
widgets.ShouldNotBeNull();
widgets.Count.ShouldBe(2);
}
[Fact]
public async Task ParseAsync_ShouldWorkWithWrongWidgetType()
{
_options.Value.AddWidget(testData.PollName, testData.WidgetName, string.Empty);
contentParser = new ContentParser(_options);
var content = @"**ABP Framework** is completely open source and developed in a community-driven manner.
[Widget Wrong Type= ""Poll"" Code =""poll-name""]
Thanks _for_ *your * feedback.";
var widgets = await contentParser.ParseAsync(content);
widgets.ShouldNotBeNull();
widgets.Count.ShouldBe(2);
}
[Fact]
public async Task ParseAsync_ShouldWorkWithWrongPollName()
{
_options.Value.AddWidget(testData.PollName, testData.WidgetName, string.Empty);
contentParser = new ContentParser(_options);
var content = @"**ABP Framework** is completely open source and developed in a community-driven manner.
[Widget Type= ""Poll"" PollWrongName =""poll-name""]
Thanks _for_ *your * feedback.";
var widgets = await contentParser.ParseAsync(content);
widgets.ShouldNotBeNull();
widgets.Count.ShouldBe(3);
}
[Theory]
[MemberData(nameof(ExampleData))]
public async Task ParseAsync_ShouldWorkProperlyWithCorrectInputs(string content, int expectedLine)
{
_options.Value.AddWidget(testData.PollName, testData.WidgetName, string.Empty);
contentParser = new ContentParser(_options);
var widgets = await contentParser.ParseAsync(content);
widgets.ShouldNotBeNull();
widgets.Count.ShouldBe(expectedLine);
}
public static IEnumerable<object[]> ExampleData =>
new List<object[]>
{
new object[] { @"**ABP Framework** is completely open source and developed in a community-driven manner.
[Widget Type=""Poll"" Code=""poll-name""]
Thanks _for_ *your * feedback.", 3},
new object[] { @"**ABP Framework** is completely open source and developed in a community-driven manner.
[Widget Type=""Poll"" Code=""poll-name""]
Thanks _for_ *your * feedback.
[Widget Type=""Poll"" Code=""poll-name1""]", 4 },
new object[] { @"**ABP Framework** is completely open source and developed in a community-driven manner.
Thanks _for_ *your * feedback.
[Widget Type=""Poll"" Code=""poll-name""]", 2 },
new object[] { @"[Widget Type=""Poll"" Code=""poll-name""] gg [Widget Type=""Poll"" Code=""poll-name1""]**ABP Framework** is completely open source and developed in a community-driven manner.
Thanks _for_ *your * feedback.
Thanks _for_ *your * feedback.", 4},
new object[] { @"Thanks _for_ *your * feedback.
Thanks _for_ *your * feedback.", 1}
};
}

@ -59,9 +59,9 @@ namespace Volo.Docs
var filterItems = await _documentAdminAppService.GetFilterItemsAsync();
filterItems.ShouldNotBeEmpty();
filterItems.ShouldContain(p => p.ProjectId == _testData.PorjectId);
filterItems.ShouldContain(p => p.Version == "2.0.0" && p.ProjectId == _testData.PorjectId);
filterItems.ShouldContain(p => p.LanguageCode == "en" && p.ProjectId == _testData.PorjectId);
filterItems.ShouldContain(p => p.ProjectId == _testData.ProjectId);
filterItems.ShouldContain(p => p.Version == "2.0.0" && p.ProjectId == _testData.ProjectId);
filterItems.ShouldContain(p => p.LanguageCode == "en" && p.ProjectId == _testData.ProjectId);
filterItems.ShouldContain(p => p.Format == "md");
}

Loading…
Cancel
Save