mirror of https://github.com/abpframework/abp.git
80 changed files with 2380 additions and 11783 deletions
@ -1,6 +1,6 @@ |
|||
{ |
|||
"sdk": { |
|||
"version": "5.0.100", |
|||
"version": "5.0.201", |
|||
"rollForward": "latestFeature" |
|||
} |
|||
} |
|||
|
|||
@ -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,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; |
|||
} |
|||
} |
|||
@ -1,12 +0,0 @@ |
|||
using JetBrains.Annotations; |
|||
using Volo.CmsKit.Reactions; |
|||
using Volo.CmsKit.Tags; |
|||
|
|||
namespace Volo.CmsKit |
|||
{ |
|||
public class CmsKitOptions |
|||
{ |
|||
[NotNull] |
|||
public ReactionDefinitionDictionary Reactions { get; } = new ReactionDefinitionDictionary(); |
|||
} |
|||
} |
|||
@ -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); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
using JetBrains.Annotations; |
|||
using System.Collections.Generic; |
|||
|
|||
namespace Volo.CmsKit.Reactions |
|||
{ |
|||
public class CmsKitReactionOptions |
|||
{ |
|||
[NotNull] |
|||
public List<ReactionEntityTypeDefinition> EntityTypes { get; } = new (); |
|||
} |
|||
} |
|||
@ -1,28 +1,59 @@ |
|||
using System.Collections.Generic; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using JetBrains.Annotations; |
|||
using Microsoft.Extensions.Options; |
|||
using Volo.Abp; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace Volo.CmsKit.Reactions |
|||
{ |
|||
public class DefaultReactionDefinitionStore : IReactionDefinitionStore, ITransientDependency |
|||
{ |
|||
protected CmsKitOptions Options { get; } |
|||
protected CmsKitReactionOptions Options { get; } |
|||
|
|||
public DefaultReactionDefinitionStore(IOptions<CmsKitOptions> options) |
|||
public DefaultReactionDefinitionStore(IOptions<CmsKitReactionOptions> options) |
|||
{ |
|||
Options = options.Value; |
|||
} |
|||
|
|||
public virtual Task<List<ReactionDefinition>> GetReactionsAsync(string entityType = null) |
|||
public virtual async Task<List<ReactionDefinition>> GetReactionsAsync([NotNull] string entityType) |
|||
{ |
|||
return Task.FromResult(Options.Reactions.Values.ToList()); |
|||
Check.NotNullOrEmpty(entityType, nameof(entityType)); |
|||
|
|||
var definition = await GetAsync(entityType); |
|||
|
|||
return definition.Reactions; |
|||
} |
|||
|
|||
public virtual async Task<ReactionDefinition> GetReactionOrNullAsync([NotNull] string reactionName, [NotNull] string entityType) |
|||
{ |
|||
Check.NotNullOrEmpty(entityType, nameof(entityType)); |
|||
Check.NotNullOrEmpty(reactionName, nameof(reactionName)); |
|||
|
|||
var definition = await GetAsync(entityType); |
|||
|
|||
return definition.Reactions.SingleOrDefault(x => x.Name == reactionName); |
|||
} |
|||
|
|||
public virtual Task<ReactionDefinition> GetReactionOrNullAsync(string reactionName, string entityType = null) |
|||
public virtual Task<bool> IsDefinedAsync([NotNull] string entityType) |
|||
{ |
|||
return Task.FromResult(Options.Reactions.GetOrDefault(reactionName)); |
|||
Check.NotNullOrWhiteSpace(entityType, nameof(entityType)); |
|||
|
|||
var isDefined = Options.EntityTypes.Any(x => x.EntityType.Equals(entityType, StringComparison.InvariantCultureIgnoreCase)); |
|||
|
|||
return Task.FromResult(isDefined); |
|||
} |
|||
|
|||
public virtual Task<ReactionEntityTypeDefinition> GetAsync([NotNull] string entityType) |
|||
{ |
|||
Check.NotNullOrWhiteSpace(entityType, nameof(entityType)); |
|||
|
|||
var definition = Options.EntityTypes.SingleOrDefault(x => x.EntityType.Equals(entityType, StringComparison.InvariantCultureIgnoreCase)) ?? |
|||
throw new EntityCantHaveReactionException(entityType); |
|||
|
|||
return Task.FromResult(definition); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,23 @@ |
|||
|
|||
using JetBrains.Annotations; |
|||
using System.Runtime.Serialization; |
|||
using Volo.Abp; |
|||
|
|||
namespace Volo.CmsKit.Reactions |
|||
{ |
|||
public class EntityCantHaveReactionException : BusinessException |
|||
{ |
|||
public EntityCantHaveReactionException(SerializationInfo serializationInfo, StreamingContext context) : base(serializationInfo, context) |
|||
{ |
|||
} |
|||
|
|||
public EntityCantHaveReactionException([NotNull] string entityType) |
|||
{ |
|||
EntityType = Check.NotNullOrEmpty(entityType, nameof(entityType)); |
|||
Code = CmsKitErrorCodes.Reactions.EntityCantHaveReaction; |
|||
WithData(nameof(EntityType), EntityType); |
|||
} |
|||
|
|||
public string EntityType { get; } |
|||
} |
|||
} |
|||
@ -1,14 +0,0 @@ |
|||
using System.Collections.Generic; |
|||
using JetBrains.Annotations; |
|||
using Volo.Abp.Localization; |
|||
|
|||
namespace Volo.CmsKit.Reactions |
|||
{ |
|||
public class ReactionDefinitionDictionary : Dictionary<string, ReactionDefinition> |
|||
{ |
|||
public void AddOrReplace([NotNull] string name, ILocalizableString displayName = null) |
|||
{ |
|||
this[name] = new ReactionDefinition(name, displayName); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
using JetBrains.Annotations; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp; |
|||
|
|||
namespace Volo.CmsKit.Reactions |
|||
{ |
|||
public class ReactionEntityTypeDefinition : PolicySpecifiedDefinition |
|||
{ |
|||
[NotNull] |
|||
public List<ReactionDefinition> Reactions { get; } = new(); |
|||
|
|||
public ReactionEntityTypeDefinition( |
|||
[NotNull] string entityType, |
|||
[NotNull] IEnumerable<ReactionDefinition> reactions, |
|||
IEnumerable<string> createPolicies = null, |
|||
IEnumerable<string> updatePolicies = null, |
|||
IEnumerable<string> deletePolicies = null) : base(entityType, createPolicies, updatePolicies, deletePolicies) |
|||
{ |
|||
Reactions = Check.NotNull(reactions, nameof(reactions)).ToList(); |
|||
} |
|||
} |
|||
} |
|||
@ -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()); |
|||
} |
|||
@ -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(); |
|||
} |
|||
} |
|||
} |
|||
@ -1,4 +1,4 @@ |
|||
export function getPathName(url: string): string { |
|||
const { pathname } = new URL(url); |
|||
const { pathname } = new URL(url, window.location.origin); |
|||
return pathname; |
|||
} |
|||
|
|||
File diff suppressed because it is too large
@ -0,0 +1,9 @@ |
|||
export const shouldQuoteProp = (key: string) => { |
|||
try { |
|||
new Function('return {}.' + key); |
|||
} catch (_) { |
|||
return true; |
|||
} |
|||
|
|||
return false; |
|||
}; |
|||
Loading…
Reference in new issue