Merge branch 'dev' into cms-kit/refactoring

pull/8012/head
Ilkay Ilknur 5 years ago
commit af9c7b0715

@ -207,7 +207,7 @@
"DeleteCoverImageConfirmationMessage": "Are you sure you want to delete the cover image for \"{0}\"?",
"DeleteCoverImageSuccessMessage": "Cover image successfully deleted",
"PaymentsOf": "Payments of",
"ShowPaymentsOfOrganization": "Show payments",
"ShowPaymentsOfOrganization": "Payments",
"Date": "Date",
"Products": "Products",
"TotalAmount": "Total amount",
@ -234,6 +234,19 @@
"Permission:CliAnalyticses": "Cli Analyticses",
"Permission:CliAnalytics": "Cli Analytics",
"Search": "Search",
"ClearFilter": "Clear filter"
"ClearFilter": "Clear filter",
"LicensePrivateKey": "License private key",
"LicensePublicKey": "License public key",
"ApiKey": "NuGet API key",
"ShowInvoiceRequestsOfOrganization": "Invoice requests",
"ShowQuestionsOfOrganization": "Questions",
"Question": "Question",
"Open": "Open",
"Questions": "Questions",
"InvoiceRequests": "Invoice Requests",
"Address": "Address",
"TaxNo": "Tax No",
"Permission:InvoiceRequest": "Invoice Request",
"Permission:Question": "Question"
}
}

@ -182,6 +182,20 @@
"Permission:CliAnalyticses": "Cli Analitikleri",
"Permission:CliAnalytics": "Cli Analitik",
"Search": "Ara",
"ClearFilter": "Filtreyi temizle"
"ShowPaymentsOfOrganization": "Ödemeler",
"ClearFilter": "Filtreyi temizle",
"LicensePrivateKey": "Lisans özel anahtar",
"LicensePublicKey": "Lisans genel key",
"ApiKey": "NuGet API anahatar",
"ShowInvoiceRequestsOfOrganization": "Fatura talepleri",
"ShowQuestionsOfOrganization": "Sorular",
"Question": "Soru",
"Open": "Aç",
"Questions": "Sorular",
"InvoiceRequests": "Fatura talepleri",
"Address": "Adres",
"TaxNo": "Vergi no",
"Permission:InvoiceRequest": "Fatura Talebi",
"Permission:Question": "Soru"
}
}

@ -217,6 +217,21 @@
"FailReason": "失败原因",
"ReIndexAllPosts": "重新索引所有帖子",
"ReIndexAllPostsConfirmationMessage": "你确定要重新索引所有的帖子吗",
"SuccessfullyReIndexAllPosts": "成功索引所有的帖子"
"SuccessfullyReIndexAllPosts": "成功索引所有的帖子",
"ClearFilter": "清除过滤",
"LicensePrivateKey": "许可私有密钥",
"LicensePublicKey": "许可公有密钥",
"ApiKey": "NuGet API密钥",
"ShowInvoiceRequestsOfOrganization": "发票请求",
"ShowQuestionsOfOrganization": "问题",
"Question": "问题",
"Open": "打开",
"Questions": "问题",
"InvoiceRequests": "发票请求",
"Address": "地址",
"TaxNo": "税号",
"Permission:InvoiceRequest": "发票请求",
"Permission:Question": "问题"
}
}

@ -0,0 +1,12 @@
using System;
using Volo.Abp.Application.Dtos;
namespace Volo.CmsKit.Admin.Blogs
{
public class BlogPostGetListInput : PagedAndSortedResultRequestDto
{
public string Filter { get; set; }
public Guid? BlogId { get; set; }
}
}

@ -1,8 +1,5 @@
using System;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Content;
namespace Volo.CmsKit.Admin.Blogs
{
@ -10,7 +7,7 @@ namespace Volo.CmsKit.Admin.Blogs
: ICrudAppService<
BlogPostDto,
Guid,
PagedAndSortedResultRequestDto,
BlogPostGetListInput,
CreateBlogPostDto,
UpdateBlogPostDto>
{

@ -1,7 +1,6 @@
using System;
using System.ComponentModel.DataAnnotations;
using Volo.Abp.Validation;
using Volo.CmsKit.Contents;
using Volo.CmsKit.Pages;
namespace Volo.CmsKit.Admin.Pages

@ -1,7 +1,6 @@
using System;
using System.ComponentModel.DataAnnotations;
using Volo.Abp.Validation;
using Volo.CmsKit.Contents;
using Volo.CmsKit.Pages;
namespace Volo.CmsKit.Admin.Pages

@ -16,13 +16,18 @@ namespace Volo.CmsKit.Admin.Blogs
{
protected IBlogRepository BlogRepository { get; }
protected BlogManager BlogManager { get; }
public BlogAdminAppService(IBlogRepository blogRepository, BlogManager blogManager)
protected BlogFeatureManager BlogFeatureManager{ get; }
public BlogAdminAppService(
IBlogRepository blogRepository,
BlogManager blogManager,
BlogFeatureManager blogFeatureManager = null)
{
BlogRepository = blogRepository;
BlogManager = blogManager;
BlogFeatureManager = blogFeatureManager;
}
public virtual async Task<BlogDto> GetAsync(Guid id)
{
var blog = await BlogRepository.GetAsync(id);
@ -48,7 +53,9 @@ namespace Volo.CmsKit.Admin.Blogs
{
var blog = await BlogManager.CreateAsync(input.Name, input.Slug);
await BlogRepository.InsertAsync(blog);
await BlogRepository.InsertAsync(blog, autoSave: true);
await BlogFeatureManager.SetDefaultsAsync(blog.Id);
return ObjectMapper.Map<Blog, BlogDto>(blog);
}

@ -1,12 +1,9 @@
using Microsoft.AspNetCore.Authorization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.EventBus.Distributed;
using Volo.Abp.GlobalFeatures;
using Volo.CmsKit.Admin.Blogs;
using Volo.CmsKit.Blogs;
using Volo.CmsKit.GlobalFeatures;
using Volo.CmsKit.Permissions;
@ -14,6 +11,7 @@ using Volo.CmsKit.Permissions;
namespace Volo.CmsKit.Admin.Blogs
{
[RequiresGlobalFeature(typeof(BlogsFeature))]
[Authorize(CmsKitAdminPermissions.Blogs.Features)]
public class BlogFeatureAdminAppService : CmsKitAdminAppServiceBase, IBlogFeatureAdminAppService
{
protected IBlogFeatureRepository BlogFeatureRepository { get; }
@ -32,15 +30,13 @@ namespace Volo.CmsKit.Admin.Blogs
EventBus = eventBus;
}
[Authorize(CmsKitAdminPermissions.Blogs.Features)]
public virtual async Task<List<BlogFeatureDto>> GetListAsync(Guid blogId)
{
var blogFeatures = await BlogFeatureManager.GetListAsync(blogId);
var blogFeatures = await BlogFeatureRepository.GetListAsync(blogId);
return ObjectMapper.Map<List<BlogFeature>, List<BlogFeatureDto>>(blogFeatures);
}
[Authorize(CmsKitAdminPermissions.Blogs.Features)]
public virtual Task SetAsync(Guid blogId, BlogFeatureInputDto dto)
{
return BlogFeatureManager.SetAsync(blogId, dto.FeatureName, dto.IsEnabled);

@ -3,10 +3,6 @@ using System;
using System.Collections.Generic;
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.Abp.GlobalFeatures;
using Volo.Abp.Users;
using Volo.CmsKit.Blogs;
@ -87,20 +83,15 @@ namespace Volo.CmsKit.Admin.Blogs
}
[Authorize(CmsKitAdminPermissions.BlogPosts.Default)]
public virtual async Task<PagedResultDto<BlogPostDto>> GetListAsync(PagedAndSortedResultRequestDto input)
public virtual async Task<PagedResultDto<BlogPostDto>> GetListAsync(BlogPostGetListInput input)
{
if (input.Sorting.IsNullOrEmpty())
{
input.Sorting = nameof(BlogPost.CreationTime) + " desc";
}
var blogPosts = await BlogPostRepository.GetPagedListAsync(input.SkipCount, input.MaxResultCount, input.Sorting, includeDetails: true);
var blogPosts = await BlogPostRepository.GetListAsync(input.Filter, input.BlogId, input.MaxResultCount, input.SkipCount, input.Sorting);
var count = await BlogPostRepository.GetCountAsync();
var count = await BlogPostRepository.GetCountAsync(input.Filter);
return new PagedResultDto<BlogPostDto>(
count,
ObjectMapper.Map<List<BlogPost>, List<BlogPostDto>>(blogPosts));
var dtoList = ObjectMapper.Map<List<BlogPost>, List<BlogPostDto>>(blogPosts);
return new PagedResultDto<BlogPostDto>(count, dtoList);
}
[Authorize(CmsKitAdminPermissions.BlogPosts.Delete)]

@ -33,6 +33,7 @@ namespace Volo.CmsKit.Admin.MediaDescriptors
{
var definition = await MediaDescriptorDefinitionStore.GetDefinitionAsync(inputStream.EntityType);
/* TODO: Shouldn't CreatePolicies be a dictionary and we check for inputStream.EntityType? */
await CheckAnyOfPoliciesAsync(definition.CreatePolicies);
using (var stream = inputStream.GetStream())
@ -52,6 +53,7 @@ namespace Volo.CmsKit.Admin.MediaDescriptors
var definition = await MediaDescriptorDefinitionStore.GetDefinitionAsync(mediaDescriptor.EntityType);
/* TODO: Shouldn't DeletePolicies be a dictionary and we check for inputStream.EntityType? */
await CheckAnyOfPoliciesAsync(definition.DeletePolicies);
await MediaContainer.DeleteAsync(id.ToString());

@ -16,10 +16,15 @@ namespace Volo.CmsKit.Admin.Pages
public class PageAdminAppService : CmsKitAdminAppServiceBase, IPageAdminAppService
{
protected IPageRepository PageRepository { get; }
public PageAdminAppService(IPageRepository pageRepository)
protected PageManager PageManager { get; }
public PageAdminAppService(
IPageRepository pageRepository,
PageManager pageManager)
{
PageRepository = pageRepository;
PageManager = pageManager;
}
public virtual async Task<PageDto> GetAsync(Guid id)
@ -48,9 +53,7 @@ namespace Volo.CmsKit.Admin.Pages
[Authorize(CmsKitAdminPermissions.Pages.Create)]
public virtual async Task<PageDto> CreateAsync(CreatePageInputDto input)
{
await CheckPageSlugAsync(input.Slug);
var page = new Page(GuidGenerator.Create(), input.Title, input.Slug, input.Content, CurrentTenant.Id);
var page = await PageManager.CreateAsync(input.Title, input.Slug, input.Content);
await PageRepository.InsertAsync(page);
@ -62,13 +65,9 @@ namespace Volo.CmsKit.Admin.Pages
{
var page = await PageRepository.GetAsync(id);
if (page.Slug != input.Slug)
{
await CheckPageSlugAsync(input.Slug);
}
await PageManager.SetSlugAsync(page, input.Slug);
page.SetTitle(input.Title);
page.SetSlug(input.Slug);
page.SetContent(input.Content);
await PageRepository.UpdateAsync(page);
@ -81,13 +80,5 @@ namespace Volo.CmsKit.Admin.Pages
{
await PageRepository.DeleteAsync(id);
}
protected virtual async Task CheckPageSlugAsync(string slug)
{
if (await PageRepository.ExistsAsync(slug))
{
throw new PageSlugAlreadyExistsException(slug);
}
}
}
}

@ -49,7 +49,7 @@ namespace Volo.CmsKit.Admin.Blogs
[HttpGet]
[Authorize(CmsKitAdminPermissions.BlogPosts.Default)]
public virtual Task<PagedResultDto<BlogPostDto>> GetListAsync(PagedAndSortedResultRequestDto input)
public virtual Task<PagedResultDto<BlogPostDto>> GetListAsync(BlogPostGetListInput input)
{
return BlogPostAdminAppService.GetListAsync(input);
}

@ -1,5 +1,6 @@
@page
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Pages.Shared.Components.AbpPageSearchBox
@using Volo.CmsKit.Admin.Web.Pages.CmsKit.BlogPosts
@using Volo.CmsKit.Admin.Web.Pages
@using Volo.CmsKit.Admin.Web.Menus
@ -27,7 +28,13 @@
<div id="CmsKitBlogPostsWrapper">
<abp-card>
<abp-card-body>
<abp-table striped-rows="true" id="BlogPostsTable" class="nowrap"></abp-table>
<abp-row>
<abp-column>
@await Component.InvokeAsync(typeof(AbpPageSearchBoxViewComponent))
</abp-column>
</abp-row>
</abp-card-body>
</abp-card>
<abp-table striped-rows="true" id="BlogPostsTable" class="nowrap"></abp-table>
</div>

@ -4,8 +4,12 @@ $(function () {
var blogsService = volo.cmsKit.admin.blogs.blogPostAdmin;
var $blogPostWrapper = $('#CmsKitBlogPostsWrapper');
var getFilter = function () {
return {
filter: $('#CmsKitBlogPostsWrapper input.page-search-filter-text').val()
};
};
var dataTable = $("#BlogPostsTable").DataTable(abp.libs.datatables.normalizeConfiguration({
processing: true,
serverSide: true,
@ -16,7 +20,7 @@ $(function () {
scrollX: true,
ordering: true,
order: [[1, "desc"]],
ajax: abp.libs.datatables.createAjax(blogsService.getList),
ajax: abp.libs.datatables.createAjax(blogsService.getList, getFilter),
columnDefs: [
{
title: l("Details"),
@ -61,6 +65,11 @@ $(function () {
]
}));
$('#CmsKitBlogPostsWrapper form.page-search-form').submit(function (e) {
e.preventDefault();
dataTable.ajax.reload();
});
$('#AbpContentToolbar button[name=CreateBlogPost]').on('click', function (e) {
e.preventDefault();
window.location.href = "BlogPosts/Create"

@ -1,7 +1,5 @@
using AutoMapper;
using Volo.CmsKit.Blogs;
using Volo.CmsKit.Contents;
using Volo.CmsKit.Pages;
using Volo.CmsKit.Tags;
using Volo.CmsKit.Users;

@ -8,8 +8,6 @@
public const string EntityNotTaggable = "CmsKit:Tag:0002";
}
public const string ContentAlreadyExist = "CmsKit:0002";
public static class Pages
{
public const string SlugAlreadyExist = "CmsKit:Page:0001";

@ -1,15 +0,0 @@
using System;
using Volo.CmsKit.Entities;
namespace Volo.CmsKit.Contents
{
public static class ContentConsts
{
public static int MaxEntityTypeLength { get; set; } = CmsEntityConsts.MaxEntityTypeLength;
public static int MaxEntityIdLength { get; set; } = CmsEntityConsts.MaxEntityIdLength;
// TODO: consider
public static int MaxValueLength { get; set; } = int.MaxValue;
}
}

@ -3,7 +3,6 @@ using System;
using Volo.Abp;
using Volo.Abp.Domain.Entities.Auditing;
using Volo.Abp.MultiTenancy;
using Volo.CmsKit.Blogs.Extensions;
namespace Volo.CmsKit.Blogs
{
@ -17,7 +16,12 @@ namespace Volo.CmsKit.Blogs
public virtual Guid? TenantId { get; protected set; }
protected internal Blog(Guid id, [NotNull] string name, [NotNull] string slug, [CanBeNull] Guid? tenantId = null) : base(id)
protected internal Blog(
Guid id,
[NotNull] string name,
[NotNull] string slug,
[CanBeNull] Guid? tenantId = null
) : base(id)
{
SetName(name);
SetSlug(slug);
@ -33,7 +37,7 @@ namespace Volo.CmsKit.Blogs
{
Check.NotNullOrWhiteSpace(slug, nameof(slug), BlogConsts.MaxNameLength);
Slug = slug.NormalizeSlug();
Slug = SlugNormalizer.Normalize(slug);
}
}
}

@ -5,13 +5,13 @@ using Volo.Abp.Domain.Entities.Auditing;
namespace Volo.CmsKit.Blogs
{
public class BlogFeature : FullAuditedAggregateRoot<Guid>, IEquatable<BlogFeature>
public class BlogFeature : FullAuditedAggregateRoot<Guid>
{
public Guid BlogId { get; protected set; }
public string FeatureName { get; protected set; }
public bool IsEnabled { get; set; } = true;
public bool IsEnabled { get; protected internal set; }
public BlogFeature(Guid blogId, [NotNull] string featureName, bool isEnabled = true)
{
@ -19,10 +19,5 @@ namespace Volo.CmsKit.Blogs
FeatureName = Check.NotNullOrWhiteSpace(featureName, nameof(featureName));
IsEnabled = isEnabled;
}
public bool Equals(BlogFeature other)
{
return BlogId == other?.BlogId && FeatureName == other?.FeatureName;
}
}
}

@ -1,10 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Domain.Services;
using Volo.Abp.EventBus.Distributed;
using Volo.Abp.EventBus.Local;
using Volo.Abp.Uow;
namespace Volo.CmsKit.Blogs
{
@ -22,17 +20,6 @@ namespace Volo.CmsKit.Blogs
DefaultBlogFeatureProvider = defaultBlogFeatureProvider;
}
public async Task<List<BlogFeature>> GetListAsync(Guid blogId)
{
var blogFeatures = await BlogFeatureRepository.GetListAsync(blogId);
var defaultFeatures = await DefaultBlogFeatureProvider.GetDefaultFeaturesAsync(blogId);
defaultFeatures.ForEach(x => blogFeatures.AddIfNotContains(x));
return blogFeatures;
}
public async Task SetAsync(Guid blogId, string featureName, bool isEnabled)
{
var blogFeature = await BlogFeatureRepository.FindAsync(blogId, featureName);
@ -47,5 +34,15 @@ namespace Volo.CmsKit.Blogs
await BlogFeatureRepository.UpdateAsync(blogFeature);
}
}
public async Task SetDefaultsAsync(Guid blogId)
{
var defaultFeatures = await DefaultBlogFeatureProvider.GetDefaultFeaturesAsync(blogId);
foreach (var feature in defaultFeatures)
{
await SetAsync(blogId, feature.FeatureName, isEnabled: true);
}
}
}
}

@ -3,7 +3,6 @@ using System;
using Volo.Abp;
using Volo.Abp.Domain.Entities.Auditing;
using Volo.Abp.MultiTenancy;
using Volo.CmsKit.Blogs.Extensions;
using Volo.CmsKit.Users;
namespace Volo.CmsKit.Blogs
@ -65,7 +64,7 @@ namespace Volo.CmsKit.Blogs
{
Check.NotNullOrWhiteSpace(slug, nameof(slug), BlogPostConsts.MaxSlugLength, BlogPostConsts.MinSlugLength);
Slug = slug.NormalizeSlug();
Slug = SlugNormalizer.Normalize(slug);
}
public virtual void SetShortDescription(string shortDescription)

@ -12,13 +12,17 @@ namespace Volo.CmsKit.Blogs
{
protected IBlogPostRepository BlogPostRepository { get; }
protected IBlogRepository BlogRepository { get; }
protected IDefaultBlogFeatureProvider BlogFeatureProvider { get; }
public BlogPostManager(
IBlogPostRepository blogPostRepository,
IBlogRepository blogRepository)
IBlogRepository blogRepository,
IDefaultBlogFeatureProvider blogFeatureProvider)
{
BlogPostRepository = blogPostRepository;
BlogRepository = blogRepository;
BlogFeatureProvider = blogFeatureProvider;
}
public virtual async Task<BlogPost> CreateAsync(
@ -35,8 +39,6 @@ namespace Volo.CmsKit.Blogs
Check.NotNullOrEmpty(title, nameof(title));
Check.NotNullOrEmpty(slug, nameof(slug));
await CheckBlogExistenceAsync(blog.Id);
var blogPost = new BlogPost(
GuidGenerator.Create(),
blog.Id,

@ -6,11 +6,8 @@ namespace Volo.CmsKit.Blogs
{
public class BlogPostSlugAlreadyExistException : BusinessException
{
internal BlogPostSlugAlreadyExistException(string code = null, string message = null, string details = null, Exception innerException = null, Microsoft.Extensions.Logging.LogLevel logLevel = Microsoft.Extensions.Logging.LogLevel.Warning) : base(code, message, details, innerException, logLevel)
{
}
internal BlogPostSlugAlreadyExistException(SerializationInfo serializationInfo, System.Runtime.Serialization.StreamingContext context) : base(serializationInfo, context)
public BlogPostSlugAlreadyExistException(SerializationInfo serializationInfo, StreamingContext context)
: base(serializationInfo, context)
{
}

@ -8,14 +8,13 @@ namespace Volo.CmsKit.Blogs
public class BlogSlugAlreadyExistException : BusinessException
{
public BlogSlugAlreadyExistException(string slug)
: base(code: CmsKitErrorCodes.Blogs.SlugAlreadyExists)
{
Code = CmsKitErrorCodes.Blogs.SlugAlreadyExists;
WithData(nameof(Blog.Slug), slug);
}
public BlogSlugAlreadyExistException(
SerializationInfo serializationInfo, StreamingContext context) : base(serializationInfo, context)
public BlogSlugAlreadyExistException(SerializationInfo serializationInfo, StreamingContext context)
: base(serializationInfo, context)
{
}
}

@ -8,12 +8,21 @@ namespace Volo.CmsKit.Blogs
{
public interface IBlogPostRepository : IBasicRepository<BlogPost, Guid>
{
Task<int> GetCountAsync(
string filter = null,
Guid? blogId = null,
CancellationToken cancellationToken = default);
Task<List<BlogPost>> GetListAsync(
string filter = null,
Guid? blogId = null,
int maxResultCount = int.MaxValue,
int skipCount = 0,
string sorting = null,
CancellationToken cancellationToken = default);
Task<bool> SlugExistsAsync(Guid blogId, string slug, CancellationToken cancellationToken = default);
Task<BlogPost> GetBySlugAsync(Guid blogId, string slug, CancellationToken cancellationToken = default);
Task<List<BlogPost>> GetPagedListAsync(Guid blogId, int skipCount, int maxResultCount, string sorting, bool includeDetails = false, CancellationToken cancellationToken = default);
Task<int> GetCountAsync(Guid blogId, CancellationToken cancellationToken = default);
}
}

@ -39,11 +39,6 @@ namespace Volo.CmsKit
options.Reactions.AddOrReplace(StandardReactions.Pray);
});
if (GlobalFeatureManager.Instance.IsEnabled<TagsFeature>())
{
// TODO: Configure TagEntityTypes here...
}
}
private static LocalizableString L(string name)

@ -29,17 +29,20 @@ namespace Volo.CmsKit.MediaDescriptors
{
Check.NotNullOrWhiteSpace(entityType, nameof(entityType));
var result = Options.EntityTypes.SingleOrDefault(x => x.EntityType.Equals(entityType, StringComparison.InvariantCultureIgnoreCase)) ??
throw new EntityCantHaveMediaException(entityType);
var definition = Options.EntityTypes.SingleOrDefault(
x => x.EntityType.Equals(entityType, StringComparison.InvariantCultureIgnoreCase)
) ?? throw new EntityCantHaveMediaException(entityType);
return Task.FromResult(result);
return Task.FromResult(definition);
}
public virtual Task<bool> IsDefinedAsync([NotNull] string entityType)
{
Check.NotNullOrEmpty(entityType, nameof(entityType));
var isDefined = Options.EntityTypes.Any(a => a.EntityType.Equals(entityType, StringComparison.InvariantCultureIgnoreCase));
var isDefined = Options.EntityTypes.Any(
a => a.EntityType.Equals(entityType, StringComparison.InvariantCultureIgnoreCase)
);
return Task.FromResult(isDefined);
}

@ -9,10 +9,10 @@ namespace Volo.CmsKit.MediaDescriptors
{
}
public EntityCantHaveMediaException(string entityType)
public EntityCantHaveMediaException(string entityType)
: base(code: CmsKitErrorCodes.MediaDescriptors.EntityTypeDoesntExist)
{
EntityType = entityType;
Code = CmsKitErrorCodes.MediaDescriptors.EntityTypeDoesntExist;
WithData(nameof(entityType), EntityType);
}

@ -20,7 +20,7 @@ namespace Volo.CmsKit.Pages
{
}
public Page(Guid id, [NotNull] string title, [NotNull] string slug, string content = null, Guid? tenantId = null) : base(id)
internal Page(Guid id, [NotNull] string title, [NotNull] string slug, string content = null, Guid? tenantId = null) : base(id)
{
TenantId = tenantId;
@ -34,7 +34,7 @@ namespace Volo.CmsKit.Pages
Title = Check.NotNullOrEmpty(title, nameof(title), PageConsts.MaxTitleLength);
}
public virtual void SetSlug(string slug)
internal virtual void SetSlug(string slug)
{
Slug = Check.NotNullOrEmpty(slug, nameof(slug), PageConsts.MaxSlugLength);
}

@ -0,0 +1,56 @@
using JetBrains.Annotations;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Domain.Services;
namespace Volo.CmsKit.Pages
{
public class PageManager : DomainService
{
protected IPageRepository PageRepository { get; }
public PageManager(IPageRepository pageRepository)
{
PageRepository = pageRepository;
}
public virtual async Task<Page> CreateAsync(
[NotNull] string title,
[NotNull] string slug,
[CanBeNull] string content = null)
{
Check.NotNullOrEmpty(title, nameof(title));
Check.NotNullOrEmpty(slug, nameof(slug));
await CheckPageSlugAsync(slug);
return new Page(
GuidGenerator.Create(),
title,
slug,
content,
CurrentTenant.Id);
}
public virtual async Task SetSlugAsync(Page page, string newSlug)
{
if (page.Slug != newSlug)
{
await CheckPageSlugAsync(newSlug);
page.SetSlug(newSlug);
}
}
protected virtual async Task CheckPageSlugAsync(string slug)
{
if (await PageRepository.ExistsAsync(slug))
{
throw new PageSlugAlreadyExistsException(slug);
}
}
}
}

@ -1,12 +1,12 @@
using Slugify;
using Unidecode.NET;
namespace Volo.CmsKit.Blogs.Extensions
namespace Volo.CmsKit
{
public static class SlugExtensions
public static class SlugNormalizer
{
static readonly SlugHelper SlugHelper = new ();
public static string NormalizeSlug(this string value)
public static string Normalize(string value)
{
return SlugHelper.GenerateSlug(value?.Unidecode());
}

@ -33,48 +33,58 @@ namespace Volo.CmsKit.Blogs
blogPost.Author = await (await GetDbContextAsync())
.Set<CmsUser>()
.FirstOrDefaultAsync(x =>x.Id == blogPost.AuthorId);
.FirstOrDefaultAsync(x =>x.Id == blogPost.AuthorId, GetCancellationToken(cancellationToken));
return blogPost;
}
public async Task<int> GetCountAsync(Guid blogId, CancellationToken cancellationToken = default)
public virtual async Task<int> GetCountAsync(
string filter = null,
Guid? blogId = null,
CancellationToken cancellationToken = default)
{
return await (await GetQueryableAsync()).CountAsync(
x => x.BlogId == blogId,
GetCancellationToken(cancellationToken));
var queryable = (await GetDbSetAsync())
.WhereIf(blogId.HasValue, x => x.BlogId == blogId)
.WhereIf(!string.IsNullOrEmpty(filter), x => x.Title.Contains(filter) || x.Slug.Contains(filter));
var count = await queryable.CountAsync(GetCancellationToken(cancellationToken));
return count;
}
public async Task<List<BlogPost>> GetPagedListAsync(Guid blogId, int skipCount, int maxResultCount,
string sorting, bool includeDetails = false, CancellationToken cancellationToken = default)
public virtual async Task<List<BlogPost>> GetListAsync(
string filter = null,
Guid? blogId = null,
int maxResultCount = int.MaxValue,
int skipCount = 0,
string sorting = null,
CancellationToken cancellationToken = default)
{
var dbContext = await GetDbContextAsync();
var blogPostsDbSet = dbContext.Set<BlogPost>();
var usersDbSet = dbContext.Set<CmsUser>();
var queryable = blogPostsDbSet
.Where(x => x.BlogId == blogId);
if (!sorting.IsNullOrWhiteSpace())
{
queryable = queryable.OrderBy(sorting);
}
.WhereIf(blogId.HasValue, x => x.BlogId == blogId)
.WhereIf(!string.IsNullOrWhiteSpace(filter), x => x.Title.Contains(filter) || x.Slug.Contains(filter));
queryable = queryable.OrderBy(sorting ?? $"{nameof(BlogPost.CreationTime)} desc");
var combinedResult = await queryable
.Join(
usersDbSet,
o => o.AuthorId,
i => i.Id,
(blogPost,user) => new { blogPost, user })
.Skip(skipCount)
.Take(maxResultCount)
.ToListAsync(GetCancellationToken(cancellationToken));
.Join(
usersDbSet,
o => o.AuthorId,
i => i.Id,
(blogPost,user) => new { blogPost, user })
.Skip(skipCount)
.Take(maxResultCount)
.ToListAsync(GetCancellationToken(cancellationToken));
return combinedResult.Select(s =>
{
s.blogPost.Author = s.user;
return s.blogPost;
}).ToList();
{
s.blogPost.Author = s.user;
return s.blogPost;
}).ToList();
}
public async Task<bool> SlugExistsAsync(Guid blogId, [NotNull] string slug,

@ -4,7 +4,6 @@ using Volo.Abp.Modularity;
using Volo.Abp.Users.EntityFrameworkCore;
using Volo.CmsKit.Blogs;
using Volo.CmsKit.Comments;
using Volo.CmsKit.Contents;
using Volo.CmsKit.MediaDescriptors;
using Volo.CmsKit.Pages;
using Volo.CmsKit.Ratings;

@ -27,41 +27,51 @@ namespace Volo.CmsKit.MongoDB.Blogs
{
Check.NotNullOrEmpty(slug, nameof(slug));
var token = GetCancellationToken(cancellationToken);
var blogPost = await GetAsync(x =>
x.BlogId == blogId &&
x.Slug.ToLower() == slug,
cancellationToken: GetCancellationToken(cancellationToken));
cancellationToken: token);
var dbContext = await GetDbContextAsync();
var dbContext = await GetDbContextAsync(token);
blogPost.Author = await dbContext.Collection<CmsUser>().AsQueryable().FirstOrDefaultAsync(x => x.Id == blogPost.AuthorId);
blogPost.Author = await dbContext.Collection<CmsUser>().AsQueryable().FirstOrDefaultAsync(x => x.Id == blogPost.AuthorId, token);
return blogPost;
}
public async Task<int> GetCountAsync(Guid blogId, CancellationToken cancellationToken = default)
public async Task<int> GetCountAsync(
string filter = null,
Guid? blogId = null,
CancellationToken cancellationToken = default)
{
return await AsyncExecuter.CountAsync(
await WithDetailsAsync(),
x => x.BlogId == blogId,
GetCancellationToken(cancellationToken));
var token = GetCancellationToken(cancellationToken);
return await (await GetMongoQueryableAsync(token))
.WhereIf<BlogPost, IMongoQueryable<BlogPost>>(!string.IsNullOrWhiteSpace(filter), x => x.Title.Contains(filter) || x.Slug.Contains(filter))
.WhereIf<BlogPost, IMongoQueryable<BlogPost>>(blogId.HasValue, x => x.BlogId == blogId)
.CountAsync(GetCancellationToken(cancellationToken));
}
public async Task<List<BlogPost>> GetPagedListAsync(Guid blogId, int skipCount, int maxResultCount,
string sorting, bool includeDetails = false, CancellationToken cancellationToken = default)
public async Task<List<BlogPost>> GetListAsync(
string filter = null,
Guid? blogId = null,
int maxResultCount = int.MaxValue,
int skipCount = 0,
string sorting = null,
CancellationToken cancellationToken = default)
{
var token = GetCancellationToken(cancellationToken);
var dbContext = await GetDbContextAsync(token);
var blogPostQueryable = dbContext.Collection<BlogPost>().AsQueryable();
var usersQueryable = dbContext.Collection<CmsUser>().AsQueryable();
IQueryable<BlogPost> queryable = blogPostQueryable
.Where(x => x.BlogId == blogId);
var queryable = blogPostQueryable
.WhereIf(blogId.HasValue, x => x.BlogId == blogId)
.WhereIf(!string.IsNullOrWhiteSpace(filter), x => x.Title.Contains(filter) || x.Slug.Contains(filter));
if (!sorting.IsNullOrWhiteSpace())
{
queryable = queryable.OrderBy(sorting);
}
queryable = queryable.OrderBy(sorting ?? $"{nameof(BlogPost.CreationTime)} desc");
var combinedQueryable = queryable
.Join(

@ -1,9 +1,8 @@
using MongoDB.Driver;
using Volo.Abp.Data;
using Volo.Abp.MongoDB;
using Volo.CmsKit.Comments;
using Volo.CmsKit.Contents;
using Volo.CmsKit.Blogs;
using Volo.CmsKit.Comments;
using Volo.CmsKit.MediaDescriptors;
using Volo.CmsKit.Pages;
using Volo.CmsKit.Ratings;

@ -1,9 +1,8 @@
using System;
using Volo.Abp;
using Volo.Abp.MongoDB;
using Volo.CmsKit.Comments;
using Volo.CmsKit.Contents;
using Volo.CmsKit.Blogs;
using Volo.CmsKit.Comments;
using Volo.CmsKit.MediaDescriptors;
using Volo.CmsKit.Pages;
using Volo.CmsKit.Ratings;

@ -1,9 +1,8 @@
using MongoDB.Driver;
using Volo.Abp.Data;
using Volo.Abp.MongoDB;
using Volo.CmsKit.Comments;
using Volo.CmsKit.Contents;
using Volo.CmsKit.Blogs;
using Volo.CmsKit.Comments;
using Volo.CmsKit.MediaDescriptors;
using Volo.CmsKit.Pages;
using Volo.CmsKit.Ratings;

@ -36,10 +36,10 @@ namespace Volo.CmsKit.Public.Blogs
{
var blog = await BlogRepository.GetBySlugAsync(blogSlug);
var blogPosts = await BlogPostRepository.GetPagedListAsync(blog.Id, input.SkipCount, input.MaxResultCount, input.Sorting);
var blogPosts = await BlogPostRepository.GetListAsync(null, blog.Id,input.MaxResultCount, input.SkipCount, input.Sorting);
return new PagedResultDto<BlogPostPublicDto>(
await BlogPostRepository.GetCountAsync(blog.Id),
await BlogPostRepository.GetCountAsync(blogId: blog.Id),
ObjectMapper.Map<List<BlogPost>, List<BlogPostPublicDto>>(blogPosts));
}
}

@ -7,6 +7,7 @@ using Microsoft.Extensions.Options;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Authorization;
using Volo.Abp.EventBus.Distributed;
using Volo.Abp.Uow;
using Volo.Abp.Users;
@ -85,7 +86,7 @@ namespace Volo.CmsKit.Public.Comments
if (comment.CreatorId != CurrentUser.GetId())
{
throw new BusinessException(); //TODO: AbpAuthorizationException!
throw new AbpAuthorizationException();
}
comment.SetText(input.Text);
@ -102,7 +103,7 @@ namespace Volo.CmsKit.Public.Comments
if (comment.CreatorId != CurrentUser.GetId())
{
throw new BusinessException(); //TODO: AbpAuthorizationException!
throw new AbpAuthorizationException();
}
await CommentRepository.DeleteWithRepliesAsync(comment);

@ -61,7 +61,7 @@ namespace Volo.CmsKit.Blogs
result.ShouldNotBeNull();
result.ShouldNotBeEmpty();
result.Count.ShouldBeGreaterThan(2); // 2 are seeded and there are built-in Features.
result.Count.ShouldBeGreaterThanOrEqualTo(2); // 2 are seeded and there are built-in Features.
}
}
}

@ -98,7 +98,7 @@ namespace Volo.CmsKit.Blogs
[Fact]
public async Task GetListAsync_ShouldWorkProperly_WithDefaultParameters()
{
var list = await blogPostAdminAppService.GetListAsync(new PagedAndSortedResultRequestDto());
var list = await blogPostAdminAppService.GetListAsync(new BlogPostGetListInput());
list.ShouldNotBeNull();
list.TotalCount.ShouldBe(2);

@ -1,10 +1,8 @@
using System;
using Shouldly;
using System;
using System.Linq;
using System.Threading.Tasks;
using Shouldly;
using Volo.Abp.Uow;
using Volo.CmsKit.Admin.Pages;
using Volo.CmsKit.Contents;
using Xunit;
namespace Volo.CmsKit.Pages

@ -1,12 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Shouldly;
using Xunit;
using Volo.CmsKit.Blogs.Extensions;
using Shouldly;
using Unidecode.NET;
namespace Volo.CmsKit.Blogs
{
@ -20,7 +13,7 @@ namespace Volo.CmsKit.Blogs
var expected = "my-awesome-name";
// Act
var actual = name.NormalizeSlug();
var actual = SlugNormalizer.Normalize(name);
// Assert
actual.ShouldBe(expected);
@ -33,7 +26,7 @@ namespace Volo.CmsKit.Blogs
var expected = "my-perfect-title-v.2";
// Act
var actual = name.NormalizeSlug();
var actual = SlugNormalizer.Normalize(name);
// Assert
actual.ShouldBe(expected);
@ -47,7 +40,7 @@ namespace Volo.CmsKit.Blogs
var expected = "are-you-gonna-die";
// Act
var actual = name.NormalizeSlug();
var actual = SlugNormalizer.Normalize(name);
// Assert
actual.ShouldBe(expected);
@ -61,7 +54,7 @@ namespace Volo.CmsKit.Blogs
var expected = "we-machines-challenge";
// Act
var actual = name.NormalizeSlug();
var actual = SlugNormalizer.Normalize(name);
// Assert
actual.ShouldBe(expected);
@ -75,7 +68,7 @@ namespace Volo.CmsKit.Blogs
var expected = "go-and-code-part-2";
// Act
var actual = name.NormalizeSlug();
var actual = SlugNormalizer.Normalize(name);
// Assert
actual.ShouldBe(expected);
@ -89,7 +82,7 @@ namespace Volo.CmsKit.Blogs
var expected = "moe-klassnoe-nazvanie";
// Act
var actual = name.NormalizeSlug();
var actual = SlugNormalizer.Normalize(name);
// Assert
actual.ShouldBe(expected);
@ -103,7 +96,7 @@ namespace Volo.CmsKit.Blogs
var expected = "ozel-turkce-karakterler-gusioc";
// Act
var actual = name.NormalizeSlug();
var actual = SlugNormalizer.Normalize(name);
// Assert
actual.ShouldBe(expected);
@ -117,7 +110,7 @@ namespace Volo.CmsKit.Blogs
var expected = "wo-de-zhen-bang-tou-xian";
// Act
var actual = name.NormalizeSlug();
var actual = SlugNormalizer.Normalize(name);
// Assert
actual.ShouldBe(expected);
@ -131,7 +124,7 @@ namespace Volo.CmsKit.Blogs
var expected = "lets-rock";
// Act
var actual = name.NormalizeSlug();
var actual = SlugNormalizer.Normalize(name);
// Assert
actual.ShouldBe(expected);

@ -0,0 +1,70 @@
using Shouldly;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Volo.CmsKit.Pages
{
public class PageManager_Test : CmsKitDomainTestBase
{
private readonly PageManager pageManager;
private readonly CmsKitTestData testData;
private readonly IPageRepository pageRepository;
public PageManager_Test()
{
pageManager = GetRequiredService<PageManager>();
testData = GetRequiredService<CmsKitTestData>();
pageRepository = GetRequiredService<IPageRepository>();
}
public async Task CreateAsync_ShouldWorkProperly_WithNonExistingSlug()
{
var title = "My awesome page";
var slug = "my-awesome-page";
var content = "<h1>My Awesome Page</h1><p>This is my awesome page content!</p>";
var page = await pageManager.CreateAsync(title, slug, content);
page.ShouldNotBeNull();
page.Title.ShouldBe(title);
page.Slug.ShouldBe(slug);
page.Content.ShouldBe(content);
}
public async Task CreateAsync_ShouldThrowException_WithExistingSlug()
{
var title = "My awesome page";
var slug = testData.Page_1_Slug;
var content = "<h1>My Awesome Page</h1><p>This is my awesome page content!</p>";
var exception = await Should.ThrowAsync<PageSlugAlreadyExistsException>(async () =>
await pageManager.CreateAsync(title, slug, content));
exception.ShouldNotBeNull();
}
public async Task SetSlugAsync_ShouldWorkProperly_WithNonExistingSlug()
{
var newSlug = "freshly-generated-new-slug";
var page = await pageRepository.GetAsync(testData.Page_1_Id);
await pageManager.SetSlugAsync(page, newSlug);
page.Slug.ShouldBe(newSlug);
}
public async Task SetSlugAsync_ShouldThrowException_WithExistingSlug()
{
var newSlug = testData.Page_2_Slug;
var page = await pageRepository.GetAsync(testData.Page_1_Id);
var exception = await Should.ThrowAsync<PageSlugAlreadyExistsException>(async () =>
await pageManager.SetSlugAsync(page, newSlug));
exception.ShouldNotBeNull();
}
}
}

@ -97,7 +97,7 @@ namespace Volo.CmsKit.Blogs
[Fact]
public async Task GetPagedListAsync_ShouldWorkProperly_WithBlogId_WhileGetting10_WithoutSorting()
{
var result = await blogPostRepository.GetPagedListAsync(testData.Blog_Id, 0, 10, default);
var result = await blogPostRepository.GetListAsync(null, testData.Blog_Id);
result.ShouldNotBeNull();
result.ShouldNotBeEmpty();
@ -107,7 +107,7 @@ namespace Volo.CmsKit.Blogs
[Fact]
public async Task GetPagedListAsync_ShouldHaveAuthor_WithBlogId_WhileGetting10_WithoutSorting()
{
var result = await blogPostRepository.GetPagedListAsync(testData.Blog_Id, 0, 10, default);
var result = await blogPostRepository.GetListAsync(null, testData.Blog_Id);
result.ShouldNotBeNull();
result.ShouldNotBeEmpty();
@ -119,7 +119,7 @@ namespace Volo.CmsKit.Blogs
[Fact]
public async Task GetPagedListAsync_ShouldWorkProperly_WithBlogId_WhileGetting1_WithoutSorting()
{
var result = await blogPostRepository.GetPagedListAsync(testData.Blog_Id, default, 1, default);
var result = await blogPostRepository.GetListAsync(blogId: testData.Blog_Id, maxResultCount: 1);
result.ShouldNotBeNull();
result.ShouldNotBeEmpty();
@ -129,7 +129,7 @@ namespace Volo.CmsKit.Blogs
[Fact]
public async Task GetPagedListAsync_ShouldWorkProperly_WithBlogId_WhileGetting1InPage2_WithoutSorting()
{
var result = await blogPostRepository.GetPagedListAsync(testData.Blog_Id, 1, 1, default);
var result = await blogPostRepository.GetListAsync(blogId: testData.Blog_Id, skipCount: 1, maxResultCount: 1);
result.ShouldNotBeNull();
result.ShouldNotBeEmpty();
@ -139,7 +139,7 @@ namespace Volo.CmsKit.Blogs
[Fact]
public async Task GetPagedListAsync_ShouldWorkProperly_WithBlogId_WhileGetting10_WithSortingByTitle()
{
var result = await blogPostRepository.GetPagedListAsync(testData.Blog_Id, default, 10, nameof(BlogPost.Title));
var result = await blogPostRepository.GetListAsync(blogId: testData.Blog_Id, sorting: $"{nameof(BlogPost.Title)} asc");
result.ShouldNotBeNull();
result.ShouldNotBeEmpty();

@ -8,6 +8,11 @@
$('li:not(.last-link) span.plus-icon i.fa-chevron-right').click(
function () {
var $element = $(this).parent();
var $filter = $('.docs-version #filter');
if ($filter && $filter.val() != ''){
return;
}
$element.parent().children('ul.tree').toggle(100);
$element.closest('li').toggleClass('selected-tree');

File diff suppressed because it is too large Load Diff

@ -16,6 +16,7 @@ export interface Type {
export interface PropertyDef {
name: string;
jsonName: string | null;
type: string;
typeSimple: string;
isRequired: boolean;
@ -61,6 +62,7 @@ export interface ParameterInSignature {
export interface ParameterInBody {
nameOnMethod: string;
name: string;
jsonName: string | null;
type: string;
typeSimple: string;
isOptional: boolean;

@ -41,20 +41,21 @@ export class Body {
url: string;
registerActionParameter = (param: ParameterInBody) => {
const { bindingSourceId, descriptorName, name, nameOnMethod } = param;
const { bindingSourceId, descriptorName, jsonName, name, nameOnMethod } = param;
const camelName = camel(name);
const value = descriptorName ? `${descriptorName}.${camelName}` : nameOnMethod;
const paramName = jsonName || camelName;
const value = descriptorName ? `${descriptorName}.${paramName}` : nameOnMethod;
switch (bindingSourceId) {
case eBindingSourceId.Model:
case eBindingSourceId.Query:
this.params.push(`${camelName}: ${value}`);
this.params.push(`${paramName}: ${value}`);
break;
case eBindingSourceId.Body:
this.body = value;
break;
case eBindingSourceId.Path:
const regex = new RegExp('{(' + camelName + '|' + name + ')}', 'g');
const regex = new RegExp('{(' + paramName + '|' + camelName + '|' + name + ')}', 'g');
this.url = this.url.replace(regex, '${' + value + '}');
break;
default:

@ -134,7 +134,7 @@ export function createImportRefToInterfaceReducerCreator(params: ModelGeneratorP
genericsCollector.reset();
typeDef.properties?.forEach(prop => {
const name = camel(prop.name);
const name = prop.jsonName || camel(prop.name);
const type = simplifyType(prop.typeSimple);
const refs = parseType(prop.type).reduce(
(acc: string[], r) => acc.concat(parseGenerics(r).toGenerics()),

Loading…
Cancel
Save