Browse Source

Merge pull request #7103 from abpframework/cms-kit/tag-definitions

CmsKit - Tag Definitions
pull/7363/head
İlkay İlknur 6 years ago
committed by GitHub
parent
commit
a216872779
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 16
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Tags/EntityTagCreateDto.cs
  2. 17
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Tags/EntityTagRemoveDto.cs
  3. 11
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Tags/IEntityTagAdminAppService.cs
  4. 3
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Tags/ITagAdminAppService.cs
  5. 18
      modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Tags/TagDefinitionDto.cs
  6. 4
      modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/CmsKitAdminApplicationAutoMapperProfile.cs
  7. 1
      modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Pages/PageAdminAppService.cs
  8. 52
      modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Tags/EntityTagAdminAppService.cs
  9. 19
      modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Tags/TagAdminAppService.cs
  10. 6
      modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Tags/TagAdminController.cs
  11. 10
      modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/CmsKitErrorCodes.cs
  12. 1
      modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/en.json
  13. 1
      modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/tr.json
  14. 22
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/CmsKitDomainModule.cs
  15. 8
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/CmsKitOptions.cs
  16. 32
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/PolicySpecifiedDefinition.cs
  17. 11
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/CmsKitTagOptions.cs
  18. 40
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/DefaultTagDefinitionStore.cs
  19. 26
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/EntityNotTaggableException.cs
  20. 3
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/EntityTag.cs
  21. 52
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/EntityTagManager.cs
  22. 24
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/IEntityTagManager.cs
  23. 12
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/IEntityTagRepository.cs
  24. 15
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/ITagDefinitionStore.cs
  25. 3
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/ITagManager.cs
  26. 2
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/TagAlreadyExistException.cs
  27. 20
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/TagEntityTypeDefinitionDictionary.cs
  28. 31
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/TagEntityTypeDefiniton1.cs
  29. 19
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/TagManager.cs
  30. 19
      modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Tags/EfCoreEntityTagRepository.cs
  31. 19
      modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Tags/MongoEntityTagRepository.cs
  32. 4
      modules/cms-kit/test/Volo.CmsKit.Application.Tests/Tags/TagAdminAppService_Tests.cs
  33. 1
      modules/cms-kit/test/Volo.CmsKit.Domain.Tests/CmsKitDomainTestModule.cs
  34. 60
      modules/cms-kit/test/Volo.CmsKit.Domain.Tests/Tags/EntityTagManager_Tests.cs
  35. 30
      modules/cms-kit/test/Volo.CmsKit.Domain.Tests/Tags/TagManager_Tests.cs
  36. 59
      modules/cms-kit/test/Volo.CmsKit.TestBase/CmsKitDataSeedContributor.cs
  37. 11
      modules/cms-kit/test/Volo.CmsKit.TestBase/CmsKitTestData.cs

16
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Tags/EntityTagCreateDto.cs

@ -0,0 +1,16 @@
using System.ComponentModel.DataAnnotations;
namespace Volo.CmsKit.Admin.Tags
{
public class EntityTagCreateDto
{
[Required]
public string TagName { get; set; }
[Required]
public string EntityType { get; set; }
[Required]
public string EntityId { get; set; }
}
}

17
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Tags/EntityTagRemoveDto.cs

@ -0,0 +1,17 @@
using System;
using System.ComponentModel.DataAnnotations;
namespace Volo.CmsKit.Admin.Tags
{
public class EntityTagRemoveDto
{
[Required]
public Guid TagId { get; set; }
[Required]
public string EntityType { get; set; }
[Required]
public string EntityId { get; set; }
}
}

11
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Tags/IEntityTagAdminAppService.cs

@ -0,0 +1,11 @@
using System.Threading.Tasks;
namespace Volo.CmsKit.Admin.Tags
{
public interface IEntityTagAdminAppService
{
Task AddTagToEntityAsync(EntityTagCreateDto input);
Task RemoveTagFromEntityAsync(EntityTagRemoveDto input);
}
}

3
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Tags/ITagAdminAppService.cs

@ -1,4 +1,6 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
using Volo.CmsKit.Tags;
@ -6,5 +8,6 @@ namespace Volo.CmsKit.Admin.Tags
{
public interface ITagAdminAppService : ICrudAppService<TagDto, Guid, TagGetListInput, TagCreateDto, TagUpdateDto>
{
Task<List<TagDefinitionDto>> GetTagDefinitionsAsync();
}
}

18
modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Tags/TagDefinitionDto.cs

@ -0,0 +1,18 @@
namespace Volo.CmsKit.Admin.Tags
{
public class TagDefinitionDto
{
public TagDefinitionDto()
{
}
public TagDefinitionDto(string entityType, string displayName)
{
EntityType = entityType;
DisplayName = displayName;
}
public string EntityType { get; set; }
public string DisplayName { get; set; }
}
}

4
modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/CmsKitAdminApplicationAutoMapperProfile.cs

@ -1,8 +1,10 @@
using AutoMapper;
using Volo.CmsKit.Admin.Contents;
using Volo.CmsKit.Admin.Pages;
using Volo.CmsKit.Admin.Tags;
using Volo.CmsKit.Contents;
using Volo.CmsKit.Pages;
using Volo.CmsKit.Tags;
namespace Volo.CmsKit.Admin
{
@ -16,6 +18,8 @@ namespace Volo.CmsKit.Admin
CreateMap<Content, ContentGetListDto>(MemberList.Destination);
CreateMap<ContentCreateDto, Content>(MemberList.Source);
CreateMap<ContentUpdateDto, Content>(MemberList.Source);
CreateMap<TagEntityTypeDefiniton, TagDefinitionDto>(MemberList.Destination);
}
}
}

1
modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Pages/PageAdminAppService.cs

@ -24,7 +24,6 @@ namespace Volo.CmsKit.Admin.Pages
public virtual async Task<PageDto> GetAsync(Guid id)
{
var page = await PageRepository.GetAsync(id);
return ObjectMapper.Map<Page, PageDto>(page);
}

52
modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Tags/EntityTagAdminAppService.cs

@ -0,0 +1,52 @@
using System;
using System.Threading.Tasks;
using Volo.CmsKit.Admin.Tags;
using Volo.CmsKit.Tags;
namespace Volo.CmsKit.Admin.Application.Volo.CmsKit.Admin.Tags
{
public class EntityTagAdminAppService : CmsKitAdminAppServiceBase, IEntityTagAdminAppService
{
protected ITagDefinitionStore _tagDefinitionStore;
protected IEntityTagManager _entityTagManager;
protected ITagManager _tagManager;
public EntityTagAdminAppService(
ITagDefinitionStore tagDefinitionStore,
IEntityTagManager entityTagManager,
ITagManager tagManager)
{
_tagDefinitionStore = tagDefinitionStore;
_entityTagManager = entityTagManager;
_tagManager = tagManager;
}
public async Task AddTagToEntityAsync(EntityTagCreateDto input)
{
var definition = await _tagDefinitionStore.GetTagEntityTypeDefinitionsAsync(input.EntityType);
await CheckPolicyAsync(definition.CreatePolicy);
var tag = await _tagManager.GetOrAddAsync(input.EntityType, input.TagName, CurrentTenant?.Id);
await _entityTagManager.AddTagToEntityAsync(
tag.Id,
input.EntityType,
input.EntityId,
CurrentTenant?.Id);
}
public async Task RemoveTagFromEntityAsync(EntityTagRemoveDto input)
{
var definition = await _tagDefinitionStore.GetTagEntityTypeDefinitionsAsync(input.EntityType);
await CheckPolicyAsync(definition.DeletePolicy);
await _entityTagManager.RemoveTagFromEntityAsync(
input.TagId,
input.EntityType,
input.EntityId,
CurrentTenant?.Id);
}
}
}

19
modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Tags/TagAdminAppService.cs

@ -1,12 +1,11 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Localization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;
using Volo.CmsKit.Admin.Tags;
using Volo.CmsKit.Permissions;
using Volo.CmsKit.Tags;
@ -25,11 +24,15 @@ namespace Volo.CmsKit.Admin.Tags
{
protected ITagManager TagManager { get; }
protected IStringLocalizerFactory StringLocalizerFactory { get; }
public TagAdminAppService(
IRepository<Tag, Guid> repository,
ITagManager tagManager) : base(repository)
ITagManager tagManager,
IStringLocalizerFactory stringLocalizerFactory) : base(repository)
{
TagManager = tagManager;
StringLocalizerFactory = stringLocalizerFactory;
GetListPolicyName = CmsKitAdminPermissions.Tags.Default;
GetPolicyName = CmsKitAdminPermissions.Tags.Default;
@ -68,5 +71,15 @@ namespace Volo.CmsKit.Admin.Tags
x.Name.ToLower().Contains(input.Filter) ||
x.EntityType.ToLower().Contains(input.Filter));
}
public async Task<List<TagDefinitionDto>> GetTagDefinitionsAsync()
{
var definitions = await TagManager.GetTagDefinitionsAsync();
return definitions
.Select(s =>
new TagDefinitionDto(s.EntityType, s.DisplayName.Localize(StringLocalizerFactory)))
.ToList();
}
}
}

6
modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Tags/TagAdminController.cs

@ -1,6 +1,7 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
@ -60,5 +61,10 @@ namespace Volo.CmsKit.Admin.Tags
{
return TagAdminAppService.UpdateAsync(id, input);
}
public Task<List<TagDefinitionDto>> GetTagDefinitionsAsync()
{
return TagAdminAppService.GetTagDefinitionsAsync();
}
}
}

10
modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/CmsKitErrorCodes.cs

@ -2,10 +2,14 @@
{
public static class CmsKitErrorCodes
{
public const string TagAlreadyExist = "CmsKit:0001";
public static class Tags
{
public const string TagAlreadyExist = "CmsKit:Tag:0001";
public const string EntityNotTaggable = "CmsKit:Tag:0002";
}
public const string ContentAlreadyExist = "CmsKit:0002";
public static class Pages
{
public const string UrlAlreadyExist = "CmsKit:Page:0001";

1
modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/en.json

@ -2,6 +2,7 @@
"culture": "en",
"texts": {
"CmsKit:0002": "Content already exists!",
"CmsKit:0003": "The entity {0} is not taggable.",
"CommentAuthorizationExceptionMessage": "Those comments are not allowed for public display.",
"Comments": "Comments",
"Delete": "Delete",

1
modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/tr.json

@ -2,6 +2,7 @@
"culture": "tr",
"texts": {
"CmsKit:0002": "İçerik zaten mevcut!",
"CmsKit:0003": "{0} ögesi etiketlenebilir değil.",
"CommentAuthorizationExceptionMessage": "Bu yorumları görebilmek için yetki gerekir.",
"Comments": "Yorumlar",
"Delete": "Sil",

22
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/CmsKitDomainModule.cs

@ -1,7 +1,14 @@
using Volo.Abp.Domain;
using Microsoft.Extensions.Options;
using Volo.Abp.Domain;
using Volo.Abp.GlobalFeatures;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.Users;
using Volo.CmsKit.GlobalFeatures;
using Volo.CmsKit.Localization;
using Volo.CmsKit.Pages;
using Volo.CmsKit.Reactions;
using Volo.CmsKit.Tags;
namespace Volo.CmsKit
{
@ -28,7 +35,18 @@ namespace Volo.CmsKit
options.Reactions.AddOrReplace(StandardReactions.HeartBroken);
options.Reactions.AddOrReplace(StandardReactions.Rocket);
options.Reactions.AddOrReplace(StandardReactions.Pray);
});
if (GlobalFeatureManager.Instance.IsEnabled<TagsFeature>())
{
// TODO: Configure TagEntityTypes here...
}
}
private static LocalizableString L(string name)
{
return LocalizableString.Create<CmsKitResource>(name);
}
}
}
}

8
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/CmsKitOptions.cs

@ -1,16 +1,12 @@
using JetBrains.Annotations;
using Volo.CmsKit.Reactions;
using Volo.CmsKit.Tags;
namespace Volo.CmsKit
{
public class CmsKitOptions
{
[NotNull]
public ReactionDefinitionDictionary Reactions { get; }
public CmsKitOptions()
{
Reactions = new ReactionDefinitionDictionary();
}
public ReactionDefinitionDictionary Reactions { get; } = new ReactionDefinitionDictionary();
}
}

32
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/PolicySpecifiedDefinition.cs

@ -0,0 +1,32 @@
using JetBrains.Annotations;
using Volo.Abp;
using Volo.Abp.Localization;
namespace Volo.CmsKit.Domain.Volo.CmsKit
{
public abstract class PolicySpecifiedDefinition
{
protected PolicySpecifiedDefinition()
{
}
public PolicySpecifiedDefinition(
[CanBeNull] string createPolicy = null,
[CanBeNull] string updatePolicy = null,
[CanBeNull] string deletePolicy = null)
{
CreatePolicy = createPolicy;
DeletePolicy = deletePolicy;
UpdatePolicy = updatePolicy;
}
[CanBeNull]
public virtual string CreatePolicy { get; set; }
[CanBeNull]
public virtual string UpdatePolicy { get; set; }
[CanBeNull]
public virtual string DeletePolicy { get; set; }
}
}

11
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/CmsKitTagOptions.cs

@ -0,0 +1,11 @@
using JetBrains.Annotations;
using Volo.CmsKit.Tags;
namespace Volo.CmsKit.Tags
{
public class CmsKitTagOptions
{
[NotNull]
public TagEntityTypeDefinitionDictionary EntityTypes { get; } = new TagEntityTypeDefinitionDictionary();
}
}

40
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/DefaultTagDefinitionStore.cs

@ -0,0 +1,40 @@
using JetBrains.Annotations;
using Microsoft.Extensions.Options;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.DependencyInjection;
namespace Volo.CmsKit.Tags
{
public class DefaultTagDefinitionStore : ITagDefinitionStore, ITransientDependency
{
private readonly CmsKitTagOptions options;
public DefaultTagDefinitionStore(IOptions<CmsKitTagOptions> options)
{
this.options = options.Value;
}
public virtual Task<TagEntityTypeDefiniton> GetTagEntityTypeDefinitionsAsync([NotNull] string entityType)
{
Check.NotNullOrWhiteSpace(entityType, nameof(entityType));
var result = options.EntityTypes.GetOrDefault(entityType) ?? throw new EntityNotTaggableException(entityType);
return Task.FromResult(result);
}
public virtual Task<List<TagEntityTypeDefiniton>> GetTagDefinitionsAsync()
{
return Task.FromResult(options.EntityTypes.Values.ToList());
}
public virtual Task<bool> IsDefinedAsync([NotNull] string entityType)
{
Check.NotNullOrWhiteSpace(entityType, nameof(entityType));
return Task.FromResult(options.EntityTypes.ContainsKey(entityType));
}
}
}

26
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/EntityNotTaggableException.cs

@ -0,0 +1,26 @@
using Microsoft.Extensions.Logging;
using System;
using Volo.Abp;
namespace Volo.CmsKit.Tags
{
[Serializable]
public class EntityNotTaggableException : BusinessException
{
public EntityNotTaggableException(
string code = null,
string message = null,
string details = null,
Exception innerException = null,
LogLevel logLevel = LogLevel.Warning)
: base(code, message, details, innerException, logLevel)
{
}
public EntityNotTaggableException(string entityType)
{
Code = CmsKitErrorCodes.Tags.EntityNotTaggable;
WithData(nameof(Tag.EntityType), entityType);
}
}
}

3
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/EntityTag.cs

@ -16,7 +16,7 @@ namespace Volo.CmsKit.Tags
{
}
public EntityTag(Guid tagId, string entityId, Guid? tenantId = null)
internal EntityTag(Guid tagId, string entityId, Guid? tenantId = null)
{
TagId = tagId;
EntityId = entityId;
@ -27,6 +27,5 @@ namespace Volo.CmsKit.Tags
{
return new object[] { TagId, EntityId };
}
}
}

52
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/EntityTagManager.cs

@ -0,0 +1,52 @@
using JetBrains.Annotations;
using System;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Services;
using Volo.CmsKit.Tags;
namespace Volo.CmsKit.Tags
{
public class EntityTagManager : DomainService, IEntityTagManager
{
protected readonly IEntityTagRepository _entityTagRepository;
protected readonly ITagDefinitionStore _tagDefinitionStore;
public EntityTagManager(
IEntityTagRepository entityTagRepository,
ITagDefinitionStore tagDefinitionStore)
{
_entityTagRepository = entityTagRepository;
_tagDefinitionStore = tagDefinitionStore;
}
public async Task<EntityTag> AddTagToEntityAsync(
[NotNull] Guid tagId,
[NotNull] string entityType,
[NotNull] string entityId,
[CanBeNull] Guid? tenantId = null,
CancellationToken cancellationToken = default)
{
if (!await _tagDefinitionStore.IsDefinedAsync(entityType))
{
throw new EntityNotTaggableException(entityType);
}
var entityTag = new EntityTag(tagId, entityId, tenantId);
return await _entityTagRepository.InsertAsync(entityTag, cancellationToken: cancellationToken);
}
public async Task RemoveTagFromEntityAsync(
[NotNull] Guid tagId,
[NotNull] string entityType,
[NotNull] string entityId,
[CanBeNull] Guid? tenantId = null,
CancellationToken cancellationToken = default)
{
var entityTag = await _entityTagRepository.FindAsync(tagId, entityId, tenantId, cancellationToken);
await _entityTagRepository.DeleteAsync(entityTag);
}
}
}

24
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/IEntityTagManager.cs

@ -0,0 +1,24 @@
using JetBrains.Annotations;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Volo.CmsKit.Tags
{
public interface IEntityTagManager
{
Task<EntityTag> AddTagToEntityAsync(
[NotNull] Guid tagId,
[NotNull] string entityType,
[NotNull] string entityId,
[CanBeNull] Guid? tenantId = null,
CancellationToken cancellationToken = default);
Task RemoveTagFromEntityAsync(
[NotNull] Guid tagId,
[NotNull] string entityType,
[NotNull] string entityId,
[CanBeNull] Guid? tenantId = null,
CancellationToken cancellationToken = default);
}
}

12
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/IEntityTagRepository.cs

@ -1,9 +1,17 @@
using Volo.Abp.Domain.Repositories;
using JetBrains.Annotations;
using System;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
namespace Volo.CmsKit.Tags
{
public interface IEntityTagRepository : IBasicRepository<EntityTag>
{
Task<EntityTag> FindAsync(
[NotNull] Guid tagId,
[NotNull] string entityId,
[CanBeNull] Guid? tenantId,
CancellationToken cancellationToken = default);
}
}

15
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/ITagDefinitionStore.cs

@ -0,0 +1,15 @@
using JetBrains.Annotations;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Volo.CmsKit.Tags
{
public interface ITagDefinitionStore
{
Task<List<TagEntityTypeDefiniton>> GetTagDefinitionsAsync();
Task<TagEntityTypeDefiniton> GetTagEntityTypeDefinitionsAsync([NotNull] string entityType);
Task<bool> IsDefinedAsync([NotNull] string entityType);
}
}

3
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/ITagManager.cs

@ -1,5 +1,6 @@
using JetBrains.Annotations;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Services;
@ -26,5 +27,7 @@ namespace Volo.CmsKit.Tags
[NotNull] string name,
Guid? tenantId = null,
CancellationToken cancellationToken = default);
Task<List<TagEntityTypeDefiniton>> GetTagDefinitionsAsync(CancellationToken cancellationToken = default);
}
}

2
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/TagAlreadyExistException.cs

@ -9,7 +9,7 @@ namespace Volo.CmsKit.Tags
{
public TagAlreadyExistException([NotNull] string entityType, [NotNull] string name)
{
Code = CmsKitErrorCodes.TagAlreadyExist;
Code = CmsKitErrorCodes.Tags.TagAlreadyExist;
WithData(nameof(Tag.EntityType), entityType);
WithData(nameof(Tag.Name), name);
}

20
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/TagEntityTypeDefinitionDictionary.cs

@ -0,0 +1,20 @@
using JetBrains.Annotations;
using System.Collections.Generic;
using Volo.Abp.Localization;
namespace Volo.CmsKit.Tags
{
public class TagEntityTypeDefinitionDictionary : Dictionary<string, TagEntityTypeDefiniton>
{
public void AddOrReplace(
[NotNull] string entityType,
[CanBeNull] ILocalizableString displayName = null,
[CanBeNull] string createPolicy = null,
[CanBeNull] string updatePolicy = null,
[CanBeNull] string deletePolicy = null
)
{
this[entityType] = new TagEntityTypeDefiniton(entityType, displayName, createPolicy, updatePolicy, deletePolicy);
}
}
}

31
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/TagEntityTypeDefiniton1.cs

@ -0,0 +1,31 @@
using JetBrains.Annotations;
using Volo.Abp;
using Volo.Abp.Localization;
using Volo.CmsKit.Domain.Volo.CmsKit;
namespace Volo.CmsKit.Tags
{
public class TagEntityTypeDefiniton : PolicySpecifiedDefinition
{
public string EntityType { get; }
[CanBeNull]
public virtual ILocalizableString DisplayName { get; }
public TagEntityTypeDefiniton()
{
}
public TagEntityTypeDefiniton(
[NotNull] string entityType,
[CanBeNull] ILocalizableString displayName = null,
[CanBeNull] string createPolicy = null,
[CanBeNull] string updatePolicy = null,
[CanBeNull] string deletePolicy = null) : base(createPolicy, updatePolicy, deletePolicy)
{
EntityType = Check.NotNullOrWhiteSpace(entityType, nameof(entityType));
DisplayName = displayName;
}
}
}

19
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/TagManager.cs

@ -1,5 +1,8 @@
using JetBrains.Annotations;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp;
@ -10,10 +13,14 @@ namespace Volo.CmsKit.Tags
public class TagManager : DomainService, ITagManager
{
private readonly ITagRepository _tagRepository;
private readonly ITagDefinitionStore _tagDefinitionStore;
public TagManager(ITagRepository tagRepository)
public TagManager(
ITagRepository tagRepository,
ITagDefinitionStore tagDefinitionStore)
{
_tagRepository = tagRepository;
_tagDefinitionStore = tagDefinitionStore;
}
public async Task<Tag> GetOrAddAsync(
@ -44,6 +51,11 @@ namespace Volo.CmsKit.Tags
throw new TagAlreadyExistException(entityType, name);
}
if (!await _tagDefinitionStore.IsDefinedAsync(entityType))
{
throw new EntityNotTaggableException(entityType);
}
return await _tagRepository.InsertAsync(
new Tag(
id,
@ -70,5 +82,10 @@ namespace Volo.CmsKit.Tags
return await _tagRepository.UpdateAsync(entity, cancellationToken: cancellationToken);
}
public Task<List<TagEntityTypeDefiniton>> GetTagDefinitionsAsync(CancellationToken cancellationToken = default)
{
return _tagDefinitionStore.GetTagDefinitionsAsync();
}
}
}

19
modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Tags/EfCoreEntityTagRepository.cs

@ -1,4 +1,8 @@
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using JetBrains.Annotations;
using System;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
using Volo.CmsKit.EntityFrameworkCore;
@ -9,5 +13,18 @@ namespace Volo.CmsKit.Tags
public EfCoreEntityTagRepository(IDbContextProvider<ICmsKitDbContext> dbContextProvider) : base(dbContextProvider)
{
}
public Task<EntityTag> FindAsync(
[NotNull] Guid tagId,
[NotNull] string entityId,
[CanBeNull] Guid? tenantId,
CancellationToken cancellationToken = default)
{
return base.FindAsync(x =>
x.TagId == tagId &&
x.EntityId == entityId &&
x.TenantId == tenantId,
cancellationToken: cancellationToken);
}
}
}

19
modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Tags/MongoEntityTagRepository.cs

@ -1,4 +1,8 @@
using Volo.Abp.Domain.Repositories.MongoDB;
using JetBrains.Annotations;
using System;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories.MongoDB;
using Volo.Abp.MongoDB;
using Volo.CmsKit.Tags;
@ -9,5 +13,18 @@ namespace Volo.CmsKit.MongoDB.Tags
public MongoEntityTagRepository(IMongoDbContextProvider<ICmsKitMongoDbContext> dbContextProvider) : base(dbContextProvider)
{
}
public Task<EntityTag> FindAsync(
[NotNull] Guid tagId,
[NotNull] string entityId,
[CanBeNull] Guid? tenantId,
CancellationToken cancellationToken = default)
{
return base.FindAsync(x =>
x.TagId == tagId &&
x.EntityId == entityId &&
x.TenantId == tenantId,
cancellationToken: cancellationToken);
}
}
}

4
modules/cms-kit/test/Volo.CmsKit.Application.Tests/Tags/TagAdminAppService_Tests.cs

@ -32,8 +32,8 @@ namespace Volo.CmsKit.Tags
{
var list = await _tagAdminAppService.CreateAsync(new TagCreateDto
{
EntityType = "any_new_type",
Name = "1",
EntityType = _cmsKitTestData.EntityType1,
Name = "My First Tag",
});
list.Id.ShouldNotBe(Guid.Empty);

1
modules/cms-kit/test/Volo.CmsKit.Domain.Tests/CmsKitDomainTestModule.cs

@ -12,6 +12,5 @@ namespace Volo.CmsKit
)]
public class CmsKitDomainTestModule : AbpModule
{
}
}

60
modules/cms-kit/test/Volo.CmsKit.Domain.Tests/Tags/EntityTagManager_Tests.cs

@ -0,0 +1,60 @@
using Shouldly;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Guids;
using Xunit;
namespace Volo.CmsKit.Tags
{
public class EntityTagManager_Tests : CmsKitDomainTestBase
{
private readonly CmsKitTestData _cmsKitTestData;
private readonly IEntityTagManager _entityTagManager;
private readonly ITagRepository _tagRepository;
private readonly IGuidGenerator _guidGenerator;
public EntityTagManager_Tests()
{
_cmsKitTestData = GetRequiredService<CmsKitTestData>();
_entityTagManager = GetRequiredService<IEntityTagManager>();
_tagRepository = GetRequiredService<ITagRepository>();
_guidGenerator = GetRequiredService<IGuidGenerator>();
}
[Fact]
public async Task AddTagToEntityAsync_ShouldAdd_WhenEverythingCorrect()
{
var tag = await _tagRepository.InsertAsync(new Tag(_guidGenerator.Create(), _cmsKitTestData.EntityType1, "My Test Tag #1"));
var entityTag = await _entityTagManager.AddTagToEntityAsync(tag.Id, _cmsKitTestData.EntityType1, _cmsKitTestData.EntityId1);
entityTag.ShouldNotBeNull();
}
[Fact]
public async Task AddTagToEntity_ShouldThrowNotTaggable_WithNotConfiguredEntityType()
{
var entityType = "Not.Configured.EntityType";
var exception = Should.Throw<EntityNotTaggableException>(async () =>
await _entityTagManager.AddTagToEntityAsync(_cmsKitTestData.TagId_1, entityType, _cmsKitTestData.EntityId1)
);
exception.ShouldNotBeNull();
exception.Data[nameof(Tag.EntityType)].ShouldBe(entityType);
}
[Fact]
public async Task RemoveTagFromEntityAsync_ShouldRemove_WhenEverythingCorrect()
{
var tagToDelete = (await _tagRepository.GetAllRelatedTagsAsync(_cmsKitTestData.EntityType1, _cmsKitTestData.EntityId1))
.First();
await _entityTagManager.RemoveTagFromEntityAsync(tagToDelete.Id, tagToDelete.EntityType, _cmsKitTestData.EntityId1);
var tags = await _tagRepository.GetAllRelatedTagsAsync(_cmsKitTestData.EntityType1, _cmsKitTestData.EntityId1);
tags.ShouldNotContain(x => x.Id == tagToDelete.Id);
}
}
}

30
modules/cms-kit/test/Volo.CmsKit.Domain.Tests/Tags/TagManager_Tests.cs

@ -22,7 +22,7 @@ namespace Volo.CmsKit.Tags
[Fact]
public async Task ShouldAddWhenGettingAsync()
{
var newTagEntityType = "testEntity";
var newTagEntityType = _cmsKitTestData.EntityType1;
var newTagName = "test_tag_2123";
var doesExist = await _tagRepository.AnyAsync(newTagEntityType, newTagName);
@ -53,16 +53,28 @@ namespace Volo.CmsKit.Tags
}
[Fact]
public async Task ShouldInsert()
public async Task ShouldInsertAsync()
{
var tag = await _tagManager.InsertAsync(Guid.NewGuid(), "test", "test");
var tagName = "Freshly Created New Tag";
var tag = await _tagManager.InsertAsync(Guid.NewGuid(), _cmsKitTestData.EntityType1, tagName);
tag.ShouldNotBeNull();
var doesExist = await _tagRepository.AnyAsync("test", "test");
var doesExist = await _tagRepository.AnyAsync(_cmsKitTestData.EntityType1, tagName);
doesExist.ShouldBeTrue();
}
[Fact]
public async Task ShouldntInsertWithUnconfiguredEntityTypeAsync()
{
var notConfiguredEntityType = "My.Namespace.SomeEntity";
var exception = await Should.ThrowAsync<EntityNotTaggableException>(async () =>
await _tagManager.InsertAsync(Guid.NewGuid(), notConfiguredEntityType, "test"));
exception.ShouldNotBeNull();
exception.Data[nameof(Tag.EntityType)].ShouldBe(notConfiguredEntityType);
}
[Fact]
public async Task ShouldNotInsert()
@ -100,5 +112,15 @@ namespace Volo.CmsKit.Tags
Should.Throw<Exception>(async () => await _tagManager.UpdateAsync(tag.Id, newName));
}
[Fact]
public async Task ShouldGetTagDefinitionsProperly_WithoutParameter()
{
var definitions = await _tagManager.GetTagDefinitionsAsync();
definitions.ShouldNotBeNull();
definitions.Count.ShouldBeGreaterThan(1);
definitions.ShouldContain(x => x.EntityType == _cmsKitTestData.TagDefinition_1_EntityType);
}
}
}

59
modules/cms-kit/test/Volo.CmsKit.TestBase/CmsKitDataSeedContributor.cs

@ -1,4 +1,5 @@
using System;
using Microsoft.Extensions.Options;
using System;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Data;
@ -26,9 +27,12 @@ namespace Volo.CmsKit
private readonly IRatingRepository _ratingRepository;
private readonly ICurrentTenant _currentTenant;
private readonly IContentRepository _contentRepository;
private readonly IEntityTagRepository _entityTagRepository;
private readonly IEntityTagManager _entityTagManager;
private readonly ITagManager _tagManager;
private readonly IPageRepository _pageRepository;
private readonly IOptions<CmsKitOptions> _options;
private readonly IOptions<CmsKitTagOptions> _tagOptions;
public CmsKitDataSeedContributor(
IGuidGenerator guidGenerator,
ICmsUserRepository cmsUserRepository,
@ -36,11 +40,13 @@ namespace Volo.CmsKit
ICommentRepository commentRepository,
ReactionManager reactionManager,
IRatingRepository ratingRepository,
ICurrentTenant currentTenant,
ICurrentTenant currentTenant,
IContentRepository contentRepository,
ITagManager tagManager,
IEntityTagRepository entityTagRepository,
IPageRepository pageRepository)
ITagManager tagManager,
IEntityTagManager entityTagManager,
IPageRepository pageRepository,
IOptions<CmsKitOptions> options,
IOptions<CmsKitTagOptions> tagOptions)
{
_guidGenerator = guidGenerator;
_cmsUserRepository = cmsUserRepository;
@ -51,14 +57,18 @@ namespace Volo.CmsKit
_currentTenant = currentTenant;
_contentRepository = contentRepository;
_tagManager = tagManager;
_entityTagRepository = entityTagRepository;
_entityTagManager = entityTagManager;
_pageRepository = pageRepository;
_options = options;
_tagOptions = tagOptions;
}
public async Task SeedAsync(DataSeedContext context)
{
using (_currentTenant.Change(context?.TenantId))
{
await ConfigureCmsKitOptionsAsync();
await SeedUsersAsync();
await SeedCommentsAsync();
@ -75,6 +85,17 @@ namespace Volo.CmsKit
}
}
private Task ConfigureCmsKitOptionsAsync()
{
_tagOptions.Value.EntityTypes.AddOrReplace(_cmsKitTestData.EntityType1);
_tagOptions.Value.EntityTypes.AddOrReplace(_cmsKitTestData.EntityType2);
_tagOptions.Value.EntityTypes.AddOrReplace(_cmsKitTestData.Content_1_EntityType);
_tagOptions.Value.EntityTypes.AddOrReplace(_cmsKitTestData.Content_2_EntityType);
_tagOptions.Value.EntityTypes.AddOrReplace(_cmsKitTestData.TagDefinition_1_EntityType);
return Task.CompletedTask;
}
private async Task SeedUsersAsync()
{
await _cmsUserRepository.InsertAsync(new CmsUser(new UserData(_cmsKitTestData.User1Id, "user1",
@ -208,14 +229,14 @@ namespace Volo.CmsKit
_cmsKitTestData.Content_1_EntityId,
_cmsKitTestData.Content_1
);
var content2 = new Content(
_cmsKitTestData.Content_2_Id,
_cmsKitTestData.Content_2_EntityType,
_cmsKitTestData.Content_2_EntityId,
_cmsKitTestData.Content_2
);
var content3 = new Content(
Guid.NewGuid(),
"deleted_entity_type",
@ -233,18 +254,26 @@ namespace Volo.CmsKit
private async Task SeedTagsAsync()
{
var created1 = await _tagManager.InsertAsync(_cmsKitTestData.TagId_1, _cmsKitTestData.EntityType1, _cmsKitTestData.TagName_1);
await _entityTagManager.AddTagToEntityAsync(created1.Id, created1.EntityType, _cmsKitTestData.EntityId1);
var created2 = await _tagManager.InsertAsync(_cmsKitTestData.TagId_2, _cmsKitTestData.EntityType2, _cmsKitTestData.TagName_2);
await _entityTagManager.AddTagToEntityAsync(created2.Id, created2.EntityType, _cmsKitTestData.EntityId2);
foreach (var tag in _cmsKitTestData.Content_1_Tags)
{
var tagEntity = await _tagManager.InsertAsync(_guidGenerator.Create(), _cmsKitTestData.Content_1_EntityType, tag);
await _entityTagRepository.InsertAsync(new EntityTag(tagEntity.Id, _cmsKitTestData.Content_1_EntityId));
await _entityTagManager.AddTagToEntityAsync(tagEntity.Id, _cmsKitTestData.Content_1_EntityType, _cmsKitTestData.Content_1_EntityId);
}
foreach (var tag in _cmsKitTestData.Content_2_Tags)
{
var tagEntity = await _tagManager.InsertAsync(_guidGenerator.Create(), _cmsKitTestData.Content_2_EntityType, tag);
await _entityTagRepository.InsertAsync(new EntityTag(tagEntity.Id, _cmsKitTestData.Content_2_EntityId));
await _entityTagManager.AddTagToEntityAsync(tagEntity.Id, _cmsKitTestData.Content_2_EntityType, _cmsKitTestData.Content_2_EntityId);
}
}
@ -252,10 +281,10 @@ namespace Volo.CmsKit
{
var page1 = new Page(_cmsKitTestData.Page_1_Id, _cmsKitTestData.Page_1_Title, _cmsKitTestData.Page_1_Url, _cmsKitTestData.Page_1_Description);
var page1Content = new Content(_guidGenerator.Create(), nameof(Page), page1.Id.ToString(), _cmsKitTestData.Page_1_Content);
await _pageRepository.InsertAsync(page1);
await _contentRepository.InsertAsync(page1Content);
var page2 = new Page(_cmsKitTestData.Page_2_Id, _cmsKitTestData.Page_2_Title, _cmsKitTestData.Page_2_Url, _cmsKitTestData.Page_2_Description);
var page2Content = new Content(_guidGenerator.Create(), nameof(Page), page2.Id.ToString(), _cmsKitTestData.Page_2_Content);

11
modules/cms-kit/test/Volo.CmsKit.TestBase/CmsKitTestData.cs

@ -12,6 +12,7 @@ namespace Volo.CmsKit
public Guid CommentWithChildId { get; } = Guid.NewGuid();
public string EntityType1 { get; } = "EntityName1";
public string EntityType2 { get; } = "EntityName2";
@ -59,5 +60,15 @@ namespace Volo.CmsKit
public Guid Page_2_Id { get; } = Guid.NewGuid();
public string Page_2_Content => Content_2;
public string TagDefinition_1_EntityType => "My.Namespace.CustomType";
public Guid TagId_1 { get; } = Guid.NewGuid();
public string TagName_1 => "Awesome";
public Guid TagId_2 { get; } = Guid.NewGuid();
public string TagName_2 => "News";
}
}

Loading…
Cancel
Save