Browse Source

Merge pull request #7963 from abpframework/cms-kit/blog-post-cover-image

Cms Kit - Convert BlogPost CoverImage to Media
pull/7995/head
İlkay İlknur 6 years ago
committed by GitHub
parent
commit
d536db8d6a
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 1951
      modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20210305122554_BlogPost_CoverImage.Designer.cs
  2. 56
      modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20210305122554_BlogPost_CoverImage.cs
  3. 75
      modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/UnifiedDbContextModelSnapshot.cs
  4. 4
      modules/cms-kit/host/Volo.CmsKit.Web.Unified/Volo.CmsKit.Web.Unified.csproj
  5. 7
      modules/cms-kit/host/Volo.CmsKit.Web.Unified/wwwroot/libs/tui-editor/tui-editor-jquery-patch.js
  6. 2
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/BlogPostDto.cs
  7. 2
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/CreateBlogPostDto.cs
  8. 3
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/IBlogPostAdminAppService.cs
  9. 2
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/UpdateBlogPostDto.cs
  10. 33
      modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Blogs/BlogPostAdminAppService.cs
  11. 44
      modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Blogs/BlogPostAdminController.cs
  12. 3
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/Create.cshtml.cs
  13. 2
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/Update.cshtml
  14. 3
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/Update.cshtml.cs
  15. 37
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/create.js
  16. 46
      modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/update.js
  17. 12
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/BlogPost.cs
  18. 9
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/BlogPostCoverImageContainer.cs
  19. 4
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/BlogPostManager.cs
  20. 4
      modules/cms-kit/src/Volo.CmsKit.Public.Application.Contracts/Volo/CmsKit/Public/Blogs/BlogPostPublicDto.cs
  21. 2
      modules/cms-kit/src/Volo.CmsKit.Public.Application.Contracts/Volo/CmsKit/Public/Blogs/IBlogPostPublicAppService.cs
  22. 13
      modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Blogs/BlogPostPublicAppService.cs
  23. 12
      modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/Blogs/BlogPostPublicController.cs
  24. 10
      modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Blogs/BlogPost/Default.cshtml
  25. 15
      modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/Index.cshtml
  26. 23
      modules/cms-kit/test/Volo.CmsKit.Application.Tests/Blogs/BlogPostAdminAppService_Tests.cs

1951
modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20210305122554_BlogPost_CoverImage.Designer.cs

File diff suppressed because it is too large

56
modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20210305122554_BlogPost_CoverImage.cs

@ -0,0 +1,56 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
namespace Volo.CmsKit.Migrations
{
public partial class BlogPost_CoverImage : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "CmsContents");
migrationBuilder.AddColumn<Guid>(
name: "CoverImageMediaId",
table: "CmsBlogPosts",
type: "uniqueidentifier",
nullable: true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "CoverImageMediaId",
table: "CmsBlogPosts");
migrationBuilder.CreateTable(
name: "CmsContents",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: true),
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true),
EntityId = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
EntityType = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true),
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false),
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
Value = table.Column<string>(type: "nvarchar(max)", maxLength: 2147483647, nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_CmsContents", x => x.Id);
});
migrationBuilder.CreateIndex(
name: "IX_CmsContents_TenantId_EntityType_EntityId",
table: "CmsContents",
columns: new[] { "TenantId", "EntityType", "EntityId" });
}
}
}

75
modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/UnifiedDbContextModelSnapshot.cs

@ -1273,6 +1273,9 @@ namespace Volo.CmsKit.Migrations
.HasMaxLength(2147483647)
.HasColumnType("nvarchar(max)");
b.Property<Guid?>("CoverImageMediaId")
.HasColumnType("uniqueidentifier");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2")
.HasColumnName("CreationTime");
@ -1379,78 +1382,6 @@ namespace Volo.CmsKit.Migrations
b.ToTable("CmsComments");
});
modelBuilder.Entity("Volo.CmsKit.Contents.Content", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("uniqueidentifier")
.HasColumnName("CreatorId");
b.Property<Guid?>("DeleterId")
.HasColumnType("uniqueidentifier")
.HasColumnName("DeleterId");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2")
.HasColumnName("DeletionTime");
b.Property<string>("EntityId")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("EntityType")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("ExtraProperties")
.HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnType("bit")
.HasDefaultValue(false)
.HasColumnName("IsDeleted");
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("datetime2")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnType("uniqueidentifier")
.HasColumnName("LastModifierId");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.Property<string>("Value")
.IsRequired()
.HasMaxLength(2147483647)
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.HasIndex("TenantId", "EntityType", "EntityId");
b.ToTable("CmsContents");
});
modelBuilder.Entity("Volo.CmsKit.MediaDescriptors.MediaDescriptor", b =>
{
b.Property<Guid>("Id")

4
modules/cms-kit/host/Volo.CmsKit.Web.Unified/Volo.CmsKit.Web.Unified.csproj

@ -62,8 +62,4 @@
</None>
</ItemGroup>
<ItemGroup>
<Folder Include="Migrations" />
</ItemGroup>
</Project>

7
modules/cms-kit/host/Volo.CmsKit.Web.Unified/wwwroot/libs/tui-editor/tui-editor-jquery-patch.js

@ -0,0 +1,7 @@
/*
https://jquery.com/upgrade-guide/3.5/#jquery-htmlprefilter-changes
*/
var rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi;
jQuery.htmlPrefilter = function (html) {
return html.replace(rxhtmlTag, "<$1></$2>");
};

2
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/BlogPostDto.cs

@ -15,5 +15,7 @@ namespace Volo.CmsKit.Admin.Blogs
public string ShortDescription { get; set; }
public string Content { get; set; }
public Guid? CoverImageMediaId { get; set; }
}
}

2
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/CreateBlogPostDto.cs

@ -24,5 +24,7 @@ namespace Volo.CmsKit.Admin.Blogs
[DynamicMaxLength(typeof(BlogPostConsts), nameof(BlogPostConsts.MaxContentLength))]
public string Content { get; set; }
public Guid? CoverImageMediaId { get; set; }
}
}

3
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/IBlogPostAdminAppService.cs

@ -14,8 +14,5 @@ namespace Volo.CmsKit.Admin.Blogs
CreateBlogPostDto,
UpdateBlogPostDto>
{
Task SetCoverImageAsync(Guid id, RemoteStreamContent streamContent);
Task<RemoteStreamContent> GetCoverImageAsync(Guid id);
}
}

2
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/UpdateBlogPostDto.cs

@ -21,5 +21,7 @@ namespace Volo.CmsKit.Admin.Blogs
[DynamicMaxLength(typeof(BlogPostConsts), nameof(BlogPostConsts.MaxContentLength))]
public string Content { get; set; }
public Guid? CoverImageMediaId { get; set; }
}
}

33
modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Blogs/BlogPostAdminAppService.cs

@ -18,27 +18,23 @@ namespace Volo.CmsKit.Admin.Blogs
{
[RequiresGlobalFeature(typeof(BlogsFeature))]
[Authorize(CmsKitAdminPermissions.BlogPosts.Default)]
public class BlogPostAdminAppService: CmsKitAppServiceBase, IBlogPostAdminAppService
public class BlogPostAdminAppService : CmsKitAppServiceBase, IBlogPostAdminAppService
{
protected BlogPostManager BlogPostManager { get; }
protected IBlogPostRepository BlogPostRepository { get; }
protected IBlogRepository BlogRepository { get; }
protected IBlobContainer<BlogPostCoverImageContainer> BlobContainer { get; }
protected ICmsUserLookupService UserLookupService { get; }
public BlogPostAdminAppService(
BlogPostManager blogPostManager,
IBlogPostRepository blogPostRepository,
IBlogRepository blogRepository,
IBlobContainer<BlogPostCoverImageContainer> blobContainer,
ICmsUserLookupService userLookupService)
{
BlogPostManager = blogPostManager;
BlogPostRepository = blogPostRepository;
BlogRepository = blogRepository;
BlobContainer = blobContainer;
UserLookupService = userLookupService;
}
[Authorize(CmsKitAdminPermissions.BlogPosts.Create)]
@ -54,7 +50,8 @@ namespace Volo.CmsKit.Admin.Blogs
input.Title,
input.Slug,
input.ShortDescription,
input.Content);
input.Content,
input.CoverImageMediaId);
await BlogPostRepository.InsertAsync(blogPost);
@ -69,7 +66,8 @@ namespace Volo.CmsKit.Admin.Blogs
blogPost.SetTitle(input.Title);
blogPost.SetShortDescription(input.ShortDescription);
blogPost.SetContent(input.Content);
blogPost.CoverImageMediaId = input.CoverImageMediaId;
if (blogPost.Slug != input.Slug)
{
await BlogPostManager.SetSlugUrlAsync(blogPost, input.Slug);
@ -77,26 +75,7 @@ namespace Volo.CmsKit.Admin.Blogs
await BlogPostRepository.UpdateAsync(blogPost);
return ObjectMapper.Map<BlogPost,BlogPostDto>(blogPost);
}
[Authorize(CmsKitAdminPermissions.BlogPosts.Update)]
public virtual async Task SetCoverImageAsync(Guid id, RemoteStreamContent streamContent)
{
await BlogPostRepository.GetAsync(id);
using (var stream = streamContent.GetStream())
{
await BlobContainer.SaveAsync(id.ToString(), stream, overrideExisting: true);
}
}
[Authorize(CmsKitAdminPermissions.BlogPosts.Default)]
public virtual async Task<RemoteStreamContent> GetCoverImageAsync(Guid id)
{
var stream = await BlobContainer.GetAsync(id.ToString());
return new RemoteStreamContent(stream);
return ObjectMapper.Map<BlogPost, BlogPostDto>(blogPost);
}
[Authorize(CmsKitAdminPermissions.BlogPosts.Default)]

44
modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Blogs/BlogPostAdminController.cs

@ -1,14 +1,9 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
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.Permissions;
@ -52,50 +47,13 @@ namespace Volo.CmsKit.Admin.Blogs
return BlogPostAdminAppService.GetAsync(id);
}
[HttpGet]
[Route("{id}/cover-image")]
[Authorize(CmsKitAdminPermissions.BlogPosts.Default)]
public virtual 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 BlogPostAdminAppService.GetCoverImageAsync(id);
}
[HttpGet]
[Authorize(CmsKitAdminPermissions.BlogPosts.Default)]
public virtual Task<PagedResultDto<BlogPostDto>> GetListAsync(PagedAndSortedResultRequestDto input)
{
return BlogPostAdminAppService.GetListAsync(input);
}
[NonAction]
public virtual Task SetCoverImageAsync(Guid id, RemoteStreamContent streamContent)
{
return BlogPostAdminAppService.SetCoverImageAsync(id, streamContent);
}
[HttpPost]
[Route("{id}/cover-image")]
[Authorize(CmsKitAdminPermissions.BlogPosts.Update)]
public virtual async Task<IActionResult> UploadCoverImageAsync(Guid id, IFormFile file)
{
if (file == null)
{
return BadRequest();
}
using (var stream = file.OpenReadStream())
{
await BlogPostAdminAppService.SetCoverImageAsync(id, new RemoteStreamContent(stream));
}
return CreatedAtAction(nameof(GetCoverImageAsync), new { id });
}
[HttpPut]
[Route("{id}")]
[Authorize(CmsKitAdminPermissions.BlogPosts.Update)]

3
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/Create.cshtml.cs

@ -62,6 +62,9 @@ namespace Volo.CmsKit.Admin.Web.Pages.CmsKit.BlogPosts
[HiddenInput]
[DynamicMaxLength(typeof(BlogPostConsts), nameof(BlogPostConsts.MaxContentLength))]
public string Content { get; set; }
[HiddenInput]
public Guid? CoverImageMediaId { get; set; }
}
}
}

2
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/Update.cshtml

@ -45,7 +45,7 @@
<abp-card-body>
<div class="form-group">
<img height="120" src="/api/cms-kit-admin/blogs/blog-posts/@Model.Id/cover-image" />
<img height="120" src="/api/cms-kit/media/@Model.ViewModel.CoverImageMediaId" />
<label>@L["CoverImage"]</label>
<input type="file" id="BlogPostCoverImage" class="form-control" />
</div>

3
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/Update.cshtml.cs

@ -76,6 +76,9 @@ namespace Volo.CmsKit.Admin.Web.Pages.CmsKit.BlogPosts
[HiddenInput]
[DynamicMaxLength(typeof(BlogPostConsts), nameof(BlogPostConsts.MaxContentLength))]
public string Content { get; set; }
[HiddenInput]
public Guid? CoverImageMediaId { get; set; }
}
}
}

37
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/create.js

@ -6,6 +6,7 @@
var $formCreate = $('#form-blog-post-create');
var $title = $('#ViewModel_Title');
var $shortDescription = $('#ViewModel_ShortDescription');
var $coverImage = $('#ViewModel_CoverImageMediaId');
var $url = $('#ViewModel_Slug');
var $buttonSubmit = $('#button-blog-post-create');
var $pageContentInput = $('#ViewModel_Content');
@ -13,7 +14,6 @@
var $fileInput = $('#BlogPostCoverImage');
var $tagsWrapper = $('#blog-post-tags-wrapper');
var UPPY_UPLOAD_ENDPOINT = "/api/cms-kit-admin/blogs/blog-posts/{0}/cover-image";
var UPPY_FILE_ID = "uppy-upload-file";
var isTagsEnabled = true;
@ -37,15 +37,13 @@
if ($formCreate.valid()) {
abp.ui.setBusy();
$formCreate.ajaxSubmit({
success: function (result) {
if (isTagsEnabled) {
submitEntityTags(result.id);
}
else {
submitCoverImage(result.id);
finishSaving();
}
},
error: function (result) {
@ -54,22 +52,25 @@
}
});
}
else {
abp.ui.clearBusy();
}
});
$buttonSubmit.click(function (e) {
e.preventDefault();
$formCreate.submit();
submitCoverImage();
});
function submitEntityTags(blogPostId) {
var tags = $tagsInput.val().split(',').map(x => x.trim()).filter(x => x);
if(tags.length === 0){
submitCoverImage(blogPostId);
if (tags.length === 0) {
finishSaving();
return;
}
volo.cmsKit.admin.tags.entityTagAdmin
.setEntityTags({
entityType: 'BlogPost',
@ -77,7 +78,7 @@
tags: tags
})
.then(function (result) {
submitCoverImage(blogPostId);
finishSaving(result);
});
}
@ -88,9 +89,11 @@
return headers;
}
function submitCoverImage(blogPostId) {
function submitCoverImage() {
abp.ui.setBusy();
var UPPY_OPTIONS = {
endpoint: UPPY_UPLOAD_ENDPOINT.replace("{0}", blogPostId),
endpoint: fileUploadUri,
formData: true,
fieldName: "file",
method: "post",
@ -116,12 +119,14 @@
if (result.failed.length > 0) {
abp.message.error(l("UploadFailedMessage"));
} else {
finishSaving();
$coverImage.val(result.successful[0].response.body.id);
$formCreate.submit();
}
});
}
else {
finishSaving();
$formCreate.submit();
}
}
@ -201,7 +206,7 @@
}
});
});
// -----------------------------------
var fileUploadUri = "/api/cms-kit-admin/media/blogpost";
var fileUriPrefix = "/api/cms-kit/media/";

46
modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/update.js

@ -4,21 +4,19 @@
var $selectBlog = $('#BlogSelectionSelect');
var $formUpdate = $('#form-blog-post-update');
var $title = $('#ViewModel_Title');
var $titleClone = $('#title-clone');
var $coverImage = $('#ViewModel_CoverImageMediaId');
var $slug = $('#ViewModel_Slug');
var $buttonSubmit = $('#button-blog-post-update');
var $blogPostIdInput = $('#Id');
var $tagsInput = $('.tag-editor-form input[name=tags]');
var $fileInput = $('#BlogPostCoverImage');
var UPPY_UPLOAD_ENDPOINT = "/api/cms-kit-admin/blogs/blog-posts/{0}/cover-image";
var UPPY_FILE_ID = "uppy-upload-file";
var isTagsEnabled = true;
$formUpdate.data('validator').settings.ignore = ":hidden, [contenteditable='true']:not([name]), .tui-popup-wrapper";
function initSelectBlog() {
$selectBlog.data('autocompleteApiUrl', '/api/cms-kit-admin/blogs/blogs');
$selectBlog.data('autocompleteDisplayProperty', 'name');
@ -44,30 +42,34 @@
submitEntityTags($blogPostIdInput.val());
}
else {
submitCoverImage($blogPostIdInput.val());
finishSaving(result);
}
},
error: function (result) {
abp.ui.clearBusy(); abp.notify.error(result.responseJSON.error.message);
abp.ui.clearBusy();
abp.notify.error(result.responseJSON.error.message);
}
});
}
else {
abp.ui.clearBusy();
}
});
$buttonSubmit.click(function (e) {
e.preventDefault();
$formUpdate.submit();
submitCoverImage();
});
function submitEntityTags(blogPostId) {
function submitEntityTags(blogPostId) {
var tags = $tagsInput.val().split(',').map(x => x.trim()).filter(x => x);
if(tags.length === 0){
submitCoverImage(blogPostId);
if (tags.length === 0) {
finishSaving();
return;
}
volo.cmsKit.admin.tags.entityTagAdmin
.setEntityTags({
entityType: 'BlogPost',
@ -75,7 +77,7 @@
tags: tags
})
.then(function (result) {
submitCoverImage(blogPostId);
finishSaving(result);
});
}
@ -86,9 +88,11 @@
return headers;
}
function submitCoverImage(blogPostId) {
function submitCoverImage() {
abp.ui.setBusy();
var UPPY_OPTIONS = {
endpoint: UPPY_UPLOAD_ENDPOINT.replace("{0}", blogPostId),
endpoint: fileUploadUri,
formData: true,
fieldName: "file",
method: "post",
@ -114,12 +118,14 @@
if (result.failed.length > 0) {
abp.message.error(l("UploadFailedMessage"));
} else {
finishSaving();
$coverImage.val(result.successful[0].response.body.id);
$formUpdate.submit();
}
});
}
else {
finishSaving();
$formUpdate.submit();
}
}
@ -129,10 +135,6 @@
location.href = "../../BlogPosts";
}
$titleClone.on('change paste keyup', function () {
$title.val($titleClone.val());
});
$slug.on('change', function () {
reflectUrlChanges();
});

12
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/BlogPost.cs

@ -12,17 +12,19 @@ namespace Volo.CmsKit.Blogs
{
public virtual Guid BlogId { get; protected set; }
[NotNull]
[NotNull]
public virtual string Title { get; protected set; }
[NotNull]
[NotNull]
public virtual string Slug { get; protected set; }
[NotNull]
[NotNull]
public virtual string ShortDescription { get; protected set; }
public virtual string Content { get; protected set; }
public Guid? CoverImageMediaId { get; set; }
public virtual Guid? TenantId { get; protected set; }
public Guid AuthorId { get; set; }
@ -41,6 +43,7 @@ namespace Volo.CmsKit.Blogs
[NotNull] string slug,
[CanBeNull] string shortDescription = null,
[CanBeNull] string content = null,
[CanBeNull] Guid? coverImageMediaId = null,
[CanBeNull] Guid? tenantId = null) : base(id)
{
TenantId = tenantId;
@ -50,6 +53,7 @@ namespace Volo.CmsKit.Blogs
SetSlug(slug);
SetShortDescription(shortDescription);
SetContent(content);
CoverImageMediaId = coverImageMediaId;
}
public virtual void SetTitle(string title)

9
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/BlogPostCoverImageContainer.cs

@ -1,9 +0,0 @@
using Volo.Abp.BlobStoring;
namespace Volo.CmsKit.Blogs
{
[BlobContainerName("blog-post-cover-images")]
public class BlogPostCoverImageContainer
{
}
}

4
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/BlogPostManager.cs

@ -27,7 +27,8 @@ namespace Volo.CmsKit.Blogs
[NotNull] string title,
[NotNull] string slug,
[CanBeNull] string shortDescription = null,
[CanBeNull] string content = null)
[CanBeNull] string content = null,
[CanBeNull] Guid? coverImageMediaId = null)
{
Check.NotNull(author, nameof(author));
Check.NotNull(blog, nameof(blog));
@ -44,6 +45,7 @@ namespace Volo.CmsKit.Blogs
slug,
shortDescription,
content,
coverImageMediaId,
CurrentTenant.Id
);

4
modules/cms-kit/src/Volo.CmsKit.Public.Application.Contracts/Volo/CmsKit/Public/Blogs/BlogPostPublicDto.cs

@ -16,7 +16,9 @@ namespace Volo.CmsKit.Public.Blogs
public string ShortDescription { get; set; }
public string Content { get; set; }
public Guid? CoverImageMediaId { get; set; }
public CmsUserDto Author { get; set; }
}
}

2
modules/cms-kit/src/Volo.CmsKit.Public.Application.Contracts/Volo/CmsKit/Public/Blogs/IBlogPostPublicAppService.cs

@ -12,7 +12,5 @@ namespace Volo.CmsKit.Public.Blogs
Task<PagedResultDto<BlogPostPublicDto>> GetListAsync([NotNull] string blogSlug, PagedAndSortedResultRequestDto input);
Task<BlogPostPublicDto> GetAsync([NotNull] string blogSlug, [NotNull] string blogPostSlug);
Task<RemoteStreamContent> GetCoverImageAsync(Guid id);
}
}

13
modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Blogs/BlogPostPublicAppService.cs

@ -15,16 +15,12 @@ namespace Volo.CmsKit.Public.Blogs
protected IBlogPostRepository BlogPostRepository { get; }
protected IBlobContainer<BlogPostCoverImageContainer> BlobContainer { get; }
public BlogPostPublicAppService(
IBlogRepository blogRepository,
IBlogPostRepository blogPostRepository,
IBlobContainer<BlogPostCoverImageContainer> blobContainer)
IBlogPostRepository blogPostRepository)
{
BlogRepository = blogRepository;
BlogPostRepository = blogPostRepository;
BlobContainer = blobContainer;
}
public virtual async Task<BlogPostPublicDto> GetAsync([NotNull] string blogSlug, [NotNull] string blogPostSlug)
@ -46,12 +42,5 @@ namespace Volo.CmsKit.Public.Blogs
await BlogPostRepository.GetCountAsync(blog.Id),
ObjectMapper.Map<List<BlogPost>, List<BlogPostPublicDto>>(blogPosts));
}
public virtual async Task<RemoteStreamContent> GetCoverImageAsync(Guid id)
{
var stream = await BlobContainer.GetAsync(id.ToString());
return new RemoteStreamContent(stream);
}
}
}

12
modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/Blogs/BlogPostPublicController.cs

@ -29,18 +29,6 @@ namespace Volo.CmsKit.Public.Blogs
return BlogPostPublicAppService.GetAsync(blogSlug, blogPostSlug);
}
[HttpGet]
[Route("{id}/cover-image")]
public virtual 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]
[Route("{blogSlug}")]
public virtual Task<PagedResultDto<BlogPostPublicDto>> GetListAsync(string blogSlug, PagedAndSortedResultRequestDto input)

10
modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Blogs/BlogPost/Default.cshtml

@ -4,14 +4,16 @@
@inject IStringLocalizer<CmsKitResource> L
<h1>@Model.Title</h1>
@{
const string dummyImageSource = "https://dummyimage.com/300x200/a3a3a3/fff.png";
}
<abp-card>
<abp-card-header>
<img src="/api/cms-kit/media/@Model.CoverImageMediaId" class="card-img-top" onerror="this.src='@dummyImageSource'" />
<abp-card-body>
<abp-card-title>@Model.Title</abp-card-title>
<abp-card-subtitle>@Model.Author?.UserName</abp-card-subtitle>
</abp-card-header>
<abp-card-body>
@Html.Raw(Model.Content)
</abp-card-body>
<abp-card-footer>

15
modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/Index.cshtml

@ -1,12 +1,16 @@
@page
@using Volo.CmsKit.Public.Web.Pages
@using Volo.CmsKit.Public.Web.Pages.Public.CmsKit.Blogs
@using Volo.CmsKit.Public.Web.Pages.Public.CmsKit.Blogs
@inherits CmsKitPublicPageBase
@model IndexModel
@{
const string dummyImageSource = "https://dummyimage.com/300x200/a3a3a3/fff.png";
}
<abp-row id="blogs-container">
@foreach (var blog in Model.Blogs.Items)
{
@ -21,7 +25,14 @@
</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" style="max-width:200px;max-height:200px;" onerror="this.src='https://dummyimage.com/300x200/a3a3a3/fff.png'" />
@if (blog.CoverImageMediaId != null)
{
<img src="/api/cms-kit/media/@blog.CoverImageMediaId" class="card-img-top" style="max-width:200px;max-height:200px;" onerror="this.src='@dummyImageSource'" />
}
else
{
<img src="@dummyImageSource" class="card-img-top" style="max-width:200px;max-height:200px;" />
}
<abp-card-text>
@blog.ShortDescription
</abp-card-text>

23
modules/cms-kit/test/Volo.CmsKit.Application.Tests/Blogs/BlogPostAdminAppService_Tests.cs

@ -156,28 +156,5 @@ namespace Volo.CmsKit.Blogs
exception.EntityType.ShouldBe(typeof(BlogPost));
exception.Id.ShouldBe(cmsKitTestData.Page_2_Id);
}
[Fact]
public async Task SetCoverImage_ShouldNotThrowException_WithCorrectData()
{
using (var imageStream = GetSampleImageStream())
{
await WithUnitOfWorkAsync(async () =>
{
await blogPostAdminAppService.SetCoverImageAsync(
cmsKitTestData.BlogPost_2_Id,
new RemoteStreamContent(imageStream));
});
}
}
private Stream GetSampleImageStream()
{
var assembly = GetType().Assembly;
var resourceName = "Volo.CmsKit.Data.BlogPostSample.png";
return assembly.GetManifestResourceStream(resourceName);
}
// SetCoverImage
}
}

Loading…
Cancel
Save