diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/IBlogAdminAppService.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/IBlogAdminAppService.cs index dfc488b0a3..4072c9f847 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/IBlogAdminAppService.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/IBlogAdminAppService.cs @@ -3,7 +3,7 @@ using Volo.Abp.Application.Services; namespace Volo.CmsKit.Admin.Blogs { - public interface IBlogAdminAppService : ICrudAppService + public interface IBlogAdminAppService : ICrudAppService { } } diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/IBlogPostAdminAppService.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/IBlogPostAdminAppService.cs index 195778d92b..866c536b85 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/IBlogPostAdminAppService.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/IBlogPostAdminAppService.cs @@ -2,6 +2,7 @@ using System.Threading.Tasks; using Volo.Abp.Application.Dtos; using Volo.Abp.Application.Services; +using Volo.Abp.Content; namespace Volo.CmsKit.Admin.Blogs { @@ -13,5 +14,9 @@ namespace Volo.CmsKit.Admin.Blogs CreateUpdateBlogPostDto> { Task GetByUrlSlugAsync(string urlSlug); + + Task SetCoverImageAsync(Guid id, RemoteStreamContent streamContent); + + Task GetCoverImageAsync(Guid id); } } diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Blogs/BlogPostAdminAppService.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Blogs/BlogPostAdminAppService.cs index 17cfd74763..2677b6c5ac 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Blogs/BlogPostAdminAppService.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Blogs/BlogPostAdminAppService.cs @@ -6,6 +6,8 @@ using System.Text; using System.Threading.Tasks; using Volo.Abp.Application.Dtos; using Volo.Abp.Application.Services; +using Volo.Abp.BlobStoring; +using Volo.Abp.Content; using Volo.Abp.Domain.Repositories; using Volo.CmsKit.Blogs; using Volo.CmsKit.Permissions; @@ -22,16 +24,17 @@ namespace Volo.CmsKit.Admin.Blogs CreateUpdateBlogPostDto> , IBlogPostAdminAppService { - protected readonly IBlogPostManager _blogPostManager; - protected readonly IBlogPostRepository _blogPostRepository; + protected readonly IBlogPostManager BlogPostManager; + protected readonly IBlogPostRepository BlogPostRepository; + protected readonly IBlobContainer BlobContainer; protected BlogPostAdminAppService( IRepository repository, IBlogPostManager blogPostManager, IBlogPostRepository blogPostRepository) : base(repository) { - _blogPostManager = blogPostManager; - _blogPostRepository = blogPostRepository; + BlogPostManager = blogPostManager; + BlogPostRepository = blogPostRepository; GetListPolicyName = CmsKitAdminPermissions.BlogPosts.Default; @@ -41,9 +44,9 @@ namespace Volo.CmsKit.Admin.Blogs DeletePolicyName = CmsKitAdminPermissions.BlogPosts.Delete; } - public async Task GetByUrlSlugAsync(string urlSlug) + public virtual async Task GetByUrlSlugAsync(string urlSlug) { - var blogPost = await _blogPostRepository.GetByUrlSlugAsync(urlSlug); + var blogPost = await BlogPostRepository.GetByUrlSlugAsync(urlSlug); return MapToGetOutputDto(blogPost); } @@ -51,7 +54,7 @@ namespace Volo.CmsKit.Admin.Blogs [Authorize(CmsKitAdminPermissions.BlogPosts.Create)] public override async Task CreateAsync(CreateUpdateBlogPostDto input) { - var entity = await _blogPostManager + var entity = await BlogPostManager .CreateAsync( new BlogPost( input.BlogId, @@ -65,7 +68,7 @@ namespace Volo.CmsKit.Admin.Blogs [Authorize(CmsKitAdminPermissions.BlogPosts.Update)] public override async Task UpdateAsync(Guid id, CreateUpdateBlogPostDto input) { - var entity = await _blogPostRepository.GetAsync(id); + var entity = await BlogPostRepository.GetAsync(id); entity.SetTitle(input.Title); entity.SetUrlSlug(input.UrlSlug); @@ -74,5 +77,22 @@ namespace Volo.CmsKit.Admin.Blogs return MapToGetOutputDto(entity); } + + public virtual async Task SetCoverImageAsync(Guid id, RemoteStreamContent streamContent) + { + await Repository.GetAsync(id); + + using (var stream = streamContent.GetStream()) + { + await BlobContainer.SaveAsync(id.ToString(), stream, overrideExisting: true); + } + } + + public virtual async Task GetCoverImageAsync(Guid id) + { + var stream = await BlobContainer.GetAsync(id.ToString()); + + return new RemoteStreamContent(stream); + } } } diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Blogs/BlogPostAdminController.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Blogs/BlogPostAdminController.cs new file mode 100644 index 0000000000..554200b492 --- /dev/null +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Blogs/BlogPostAdminController.cs @@ -0,0 +1,92 @@ +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; + +namespace Volo.CmsKit.Admin.Blogs +{ + [RequiresGlobalFeature(typeof(BlogsFeature))] + [RemoteService(Name = CmsKitCommonRemoteServiceConsts.RemoteServiceName)] + [Area("cms-kit")] + [Authorize(CmsKitAdminPermissions.BlogPosts.Default)] + [Route("api/cms-kit-admin/blogs/blog-posts")] + public class BlogPostAdminController : CmsKitAdminController, IBlogPostAdminAppService + { + protected readonly IBlogPostAdminAppService BlogPostAdminAppService; + + public BlogPostAdminController(IBlogPostAdminAppService blogPostAdminAppService) + { + BlogPostAdminAppService = blogPostAdminAppService; + } + + public virtual Task CreateAsync(CreateUpdateBlogPostDto input) + { + return BlogPostAdminAppService.CreateAsync(input); + } + + public virtual Task DeleteAsync(Guid id) + { + return BlogPostAdminAppService.DeleteAsync(id); + } + + public virtual Task GetAsync(Guid id) + { + return BlogPostAdminAppService.GetAsync(id); + } + + public virtual Task GetByUrlSlugAsync(string urlSlug) + { + return BlogPostAdminAppService.GetByUrlSlugAsync(urlSlug); + } + + public virtual Task 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); + } + + public virtual Task> GetListAsync(PagedAndSortedResultRequestDto input) + { + return BlogPostAdminAppService.GetListAsync(input); + } + + public virtual Task SetCoverImageAsync(Guid id, RemoteStreamContent streamContent) + { + return BlogPostAdminAppService.SetCoverImageAsync(id, streamContent); + } + + public virtual async Task UploadCoverImageAsync(Guid id, IFormFile file) + { + if (file == null) + { + return BadRequest(); + } + + using (var stream = file.OpenReadStream()) + { + await BlogPostAdminAppService.SetCoverImageAsync(id, new RemoteStreamContent(stream)); + } + + return StatusCode(201); + } + + public virtual Task UpdateAsync(Guid id, CreateUpdateBlogPostDto input) + { + return BlogPostAdminAppService.UpdateAsync(id, input); + } + } +} diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo.CmsKit.Domain.csproj b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo.CmsKit.Domain.csproj index ee064cbedc..0fc25899e9 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo.CmsKit.Domain.csproj +++ b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo.CmsKit.Domain.csproj @@ -12,6 +12,7 @@ + diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/BlogPost.cs b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/BlogPost.cs index de05a27167..73fda09418 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/BlogPost.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/BlogPost.cs @@ -19,8 +19,6 @@ namespace Volo.CmsKit.Blogs public string UrlSlug { get; protected set; } - public string CoverImageUrl { get; set; } - public Guid? TenantId { get; } protected BlogPost() @@ -31,14 +29,12 @@ namespace Volo.CmsKit.Blogs Guid blogId, [NotNull] string title, [NotNull] string urlSlug, - [CanBeNull] string shortDescription = null, - [CanBeNull] string coverImageUrl = null) + [CanBeNull] string shortDescription = null) { BlogId = blogId; SetTitle(title); SetUrlSlug(urlSlug); ShortDescription = shortDescription; - CoverImageUrl = coverImageUrl; } public void SetTitle(string title) diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/BlogPostCoverImageContainer.cs b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/BlogPostCoverImageContainer.cs new file mode 100644 index 0000000000..824db4fe3a --- /dev/null +++ b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/BlogPostCoverImageContainer.cs @@ -0,0 +1,9 @@ +using Volo.Abp.BlobStoring; + +namespace Volo.CmsKit.Blogs +{ + [BlobContainerName("blog-post-cover-images")] + public class BlogPostCoverImageContainer + { + } +} diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/CmsKitBlogOptions.cs b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/CmsKitBlogOptions.cs new file mode 100644 index 0000000000..bc3dd30435 --- /dev/null +++ b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/CmsKitBlogOptions.cs @@ -0,0 +1,31 @@ +using System; + +namespace Volo.CmsKit.Blogs +{ + public class CmsKitBlogOptions + { + private string routePrefix = "blog"; + + /// + /// Gets or sets route prefix. Default value is 'blog'. + /// + /// + /// This parameter will be used while presenting blogposts. + /// + public string RoutePrefix + { + get => GetFormattedRoutePrefix(); + set => routePrefix = value; + } + + private string GetFormattedRoutePrefix() + { + if (string.IsNullOrWhiteSpace(routePrefix)) + { + return "/"; + } + + return routePrefix.EnsureEndsWith('/').EnsureStartsWith('/'); + } + } +} diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/CmsKitDomainModule.cs b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/CmsKitDomainModule.cs index b1937dd6e0..c16734c377 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/CmsKitDomainModule.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/CmsKitDomainModule.cs @@ -1,4 +1,5 @@ -using Volo.Abp.Domain; +using Volo.Abp.BlobStoring; +using Volo.Abp.Domain; using Volo.Abp.Modularity; using Volo.Abp.Users; using Volo.CmsKit.Reactions; @@ -8,7 +9,8 @@ namespace Volo.CmsKit [DependsOn( typeof(CmsKitDomainSharedModule), typeof(AbpUsersDomainModule), - typeof(AbpDddDomainModule) + typeof(AbpDddDomainModule), + typeof(AbpBlobStoringModule) )] public class CmsKitDomainModule : AbpModule {