diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Tags/EntityTagAdminAppService.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Tags/EntityTagAdminAppService.cs index 3725923138..c08ae435f7 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Tags/EntityTagAdminAppService.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Tags/EntityTagAdminAppService.cs @@ -61,20 +61,7 @@ namespace Volo.CmsKit.Admin.Tags await CheckPolicyAsync(definition.UpdatePolicy); - var existingTags = - await TagRepository.GetAllRelatedTagsAsync(input.EntityType, input.EntityId); - - var deletedTags = existingTags.Where(x => !input.Tags.Contains(x.Name)).ToList(); - var addedTags = input.Tags.Where(x => !existingTags.Any(a => a.Name == x)); - - await EntityTagRepository.DeleteManyAsync(deletedTags.Select(s => s.Id).ToArray()); - - foreach (var addedTag in addedTags) - { - var tag = await TagManager.GetOrAddAsync(input.EntityType, addedTag); - - await EntityTagManager.AddTagToEntityAsync(tag.Id, input.EntityType, input.EntityId, CurrentTenant?.Id); - } + await this.EntityTagManager.SetEntityTagsAsync(input.EntityType, input.EntityId, input.Tags); } } } \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/EntityTagManager.cs b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/EntityTagManager.cs index fbb9ab2e93..97a2e7cd74 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/EntityTagManager.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/EntityTagManager.cs @@ -1,5 +1,7 @@ using JetBrains.Annotations; using System; +using System.Collections.Generic; +using System.Linq; using System.Threading; using System.Threading.Tasks; using Volo.Abp.Domain.Services; @@ -9,14 +11,20 @@ namespace Volo.CmsKit.Tags public class EntityTagManager : DomainService { protected IEntityTagRepository EntityTagRepository { get; } + protected ITagRepository TagRepository { get; } protected ITagDefinitionStore TagDefinitionStore { get; } + protected TagManager TagManager { get; } public EntityTagManager( IEntityTagRepository entityTagRepository, - ITagDefinitionStore tagDefinitionStore) + ITagRepository tagRepository, + ITagDefinitionStore tagDefinitionStore, + TagManager tagManager) { EntityTagRepository = entityTagRepository; + TagRepository = tagRepository; TagDefinitionStore = tagDefinitionStore; + TagManager = tagManager; } public virtual async Task AddTagToEntityAsync( @@ -45,5 +53,23 @@ namespace Volo.CmsKit.Tags var entityTag = await EntityTagRepository.FindAsync(tagId, entityId, tenantId, cancellationToken); await EntityTagRepository.DeleteAsync(entityTag, cancellationToken: cancellationToken); } + + public async Task SetEntityTagsAsync(string entityType, string entityId, List tags) + { + var existingTags = + await TagRepository.GetAllRelatedTagsAsync(entityType, entityId); + + var deletedTags = existingTags.Where(x => !tags.Contains(x.Name)).ToList(); + var addedTags = tags.Where(x => !existingTags.Any(a => a.Name == x)); + + await EntityTagRepository.DeleteManyAsync(deletedTags.Select(s => s.Id).ToArray()); + + foreach (var addedTag in addedTags) + { + var tag = await TagManager.GetOrAddAsync(entityType, addedTag); + + await AddTagToEntityAsync(tag.Id, entityType, entityId, CurrentTenant?.Id); + } + } } } \ No newline at end of file diff --git a/modules/cms-kit/test/Volo.CmsKit.Domain.Tests/Tags/EntityTagManager_Tests.cs b/modules/cms-kit/test/Volo.CmsKit.Domain.Tests/Tags/EntityTagManager_Tests.cs index b3e5e49fd1..a39e6a1095 100644 --- a/modules/cms-kit/test/Volo.CmsKit.Domain.Tests/Tags/EntityTagManager_Tests.cs +++ b/modules/cms-kit/test/Volo.CmsKit.Domain.Tests/Tags/EntityTagManager_Tests.cs @@ -1,4 +1,5 @@ using Shouldly; +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Volo.Abp.Guids; @@ -56,5 +57,54 @@ namespace Volo.CmsKit.Tags tags.ShouldNotContain(x => x.Id == tagToDelete.Id); } + + [Fact] + public async Task SetEntityTagsAsync_ShouldWorkProperly_WithNonExistingTags() + { + var newTags = new List { "non-existing-awesome-tag-a", "non-existing-awesome-tag-b" }; + + await _entityTagManager.SetEntityTagsAsync(_cmsKitTestData.EntityType1, _cmsKitTestData.EntityId1, newTags); + + var tags = await _tagRepository.GetAllRelatedTagsAsync(_cmsKitTestData.EntityType1, _cmsKitTestData.EntityId1); + + tags.ShouldNotBeNull(); + tags.ShouldNotBeEmpty(); + tags.ForEach(tag => newTags.Contains(tag.Name)); + } + + [Fact] + public async Task SetEntityTagsAsync_ShouldWorkProperly_WithExistingTag() + { + var entityTags = new List + { + _cmsKitTestData.TagName_1 + }; + + await _entityTagManager.SetEntityTagsAsync(_cmsKitTestData.EntityType1, _cmsKitTestData.EntityId1, entityTags); + + var tags = await _tagRepository.GetAllRelatedTagsAsync(_cmsKitTestData.EntityType1, _cmsKitTestData.EntityId1); + + tags.ShouldNotBeNull(); + tags.ShouldNotBeEmpty(); + tags.ForEach(tag => entityTags.Contains(tag.Name)); + } + + [Fact] + public async Task SetEntityTagsAsync_ShouldWorkProperly_WithExistingAndNonExistingTag() + { + var entityTags = new List + { + "New Awesome Tag", + _cmsKitTestData.TagName_1 + }; + + await _entityTagManager.SetEntityTagsAsync(_cmsKitTestData.EntityType1, _cmsKitTestData.EntityId1, entityTags); + + var tags = await _tagRepository.GetAllRelatedTagsAsync(_cmsKitTestData.EntityType1, _cmsKitTestData.EntityId1); + + tags.ShouldNotBeNull(); + tags.ShouldNotBeEmpty(); + tags.ForEach(tag => entityTags.Contains(tag.Name)); + } } }