Browse Source

CmsKit - RatingEntityType Implementation

pull/8026/head
enisn 6 years ago
parent
commit
803d08369c
  1. 5
      modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/CmsKitErrorCodes.cs
  2. 1
      modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/en.json
  3. 5
      modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/tr.json
  4. 23
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/CmsKitDomainModule.cs
  5. 11
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Comments/CommentEntityTypeDefinition.cs
  6. 11
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Ratings/CmsKitRatingOptions.cs
  7. 38
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Ratings/DefaultRatingEntityTypeDefinitionStore.cs
  8. 22
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Ratings/EntityCantHaveRatingException.cs
  9. 9
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Ratings/IRatingEntityTypeDefinitionStore.cs
  10. 2
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Ratings/Rating.cs
  11. 12
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Ratings/RatingEntityTypeDefinition.cs
  12. 52
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Ratings/RatingManager.cs
  13. 5
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/TagEntityTypeDefiniton.cs
  14. 28
      modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Ratings/RatingPublicAppService.cs
  15. 66
      modules/cms-kit/test/Volo.CmsKit.Domain.Tests/Ratings/RatingManager_Test.cs
  16. 8
      modules/cms-kit/test/Volo.CmsKit.TestBase/CmsKitDataSeedContributor.cs

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

@ -13,6 +13,11 @@
public const string SlugAlreadyExist = "CmsKit:Page:0001";
}
public static class Ratings
{
public const string EntityCantHaveRating = "CmsKit:Rating:0001";
}
public static class Reactions
{
public const string EntityCantHaveReaction = "CmsKit:Reaction:0001";

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

@ -21,6 +21,7 @@
"CmsKit:Media:0001": "'{Name}' is not a valid media name.",
"CmsKit:Media:0002": "The entity can't have media.",
"CmsKit:Page:0001": "The given url ({0}) already exists.",
"CmsKit:Rating:0001": "The entity {EntityType} can't be rated.",
"CmsKit:Reaction:0001": "The entity {EntityType} can't have reactions.",
"CmsKit:Tag:0002": "The entity is not taggable!",
"CommentAuthorizationExceptionMessage": "Those comments are not allowed for public display.",

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

@ -13,13 +13,14 @@
"CmsKit.Ratings": "Puanlama",
"CmsKit.Reactions": "Tepkiler",
"CmsKit.Tags": "Etiketler",
"CmsKit:Comments:0001": "{0} ögesi yorumlanabilir değil.",
"CmsKit:0002": "İçerik zaten mevcut!",
"CmsKit:0003": "{0} ögesi etiketlenebilir değil.",
"CmsKit:BlogPost:0001": "Aynı url etiketi zaten mevcut.",
"CmsKit:Comments:0001": "{0} ögesi yorumlanabilir değil.",
"CmsKit:Media:0002": "Bu öge için medya eklenemez.",
"CmsKit:Reaction:0001": "Bu ögeye tepki verilemez.",
"CmsKit:Page:0001": "Girilen url ({0}) kullanımdadır.",
"CmsKit:Rating:0001": "{EntityType}, puanlanabilir değil.",
"CmsKit:Reaction:0001": "Bu ögeye tepki verilemez.",
"CmsKit:Tag:0002": "Bu öge etiketlenebilir değil.",
"CommentAuthorizationExceptionMessage": "Bu yorumları görebilmek için yetki gerekir.",
"CommentDeletionConfirmationMessage": "Bu yorum ve buna yapılan tüm yorumlan silinecektir!",

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

@ -1,19 +1,15 @@
using Volo.Abp.BlobStoring;
using Microsoft.Extensions.Options;
using System.Collections.Generic;
using Volo.Abp;
using Volo.Abp.Domain;
using Volo.Abp.GlobalFeatures;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.Users;
using Volo.CmsKit.Blogs;
using Volo.CmsKit.Comments;
using Volo.CmsKit.GlobalFeatures;
using Volo.CmsKit.Localization;
using Volo.CmsKit.Pages;
using Volo.CmsKit.Ratings;
using Volo.CmsKit.Reactions;
using Volo.CmsKit.Tags;
using Volo.CmsKit.Blogs;
using Volo.CmsKit.Comments;
namespace Volo.CmsKit
{
@ -67,6 +63,19 @@ namespace Volo.CmsKit
});
}
if (GlobalFeatureManager.Instance.IsEnabled<RatingsFeature>())
{
Configure<CmsKitRatingOptions>(options =>
{
if (GlobalFeatureManager.Instance.IsEnabled<BlogsFeature>())
{
options.EntityTypes.Add(new RatingEntityTypeDefinition(BlogPostConsts.EntityType));
}
// TODO: Define entity types here which can be rated.
});
}
if (GlobalFeatureManager.Instance.IsEnabled<TagsFeature>())
{
// TODO: Configure TagEntityTypes here...

11
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Comments/CommentEntityTypeDefinition.cs

@ -4,18 +4,11 @@ using Volo.Abp;
namespace Volo.CmsKit.Comments
{
public class CommentEntityTypeDefinition : IEquatable<CommentEntityTypeDefinition>
public class CommentEntityTypeDefinition : EntityTypeDefinition
{
public CommentEntityTypeDefinition([NotNull] string entityType)
public CommentEntityTypeDefinition([NotNull] string entityType) : base(entityType)
{
EntityType = Check.NotNullOrEmpty(entityType, nameof(entityType));
}
public string EntityType { get; }
public bool Equals(CommentEntityTypeDefinition other)
{
return EntityType == other?.EntityType;
}
}
}

11
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Ratings/CmsKitRatingOptions.cs

@ -0,0 +1,11 @@
using JetBrains.Annotations;
using System.Collections.Generic;
namespace Volo.CmsKit.Ratings
{
public class CmsKitRatingOptions
{
[NotNull]
public List<RatingEntityTypeDefinition> EntityTypes { get; } = new ();
}
}

38
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Ratings/DefaultRatingEntityTypeDefinitionStore.cs

@ -0,0 +1,38 @@
using JetBrains.Annotations;
using Microsoft.Extensions.Options;
using System;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp;
namespace Volo.CmsKit.Ratings
{
public class DefaultRatingEntityTypeDefinitionStore : IRatingEntityTypeDefinitionStore
{
protected CmsKitRatingOptions Options { get; }
public DefaultRatingEntityTypeDefinitionStore(IOptions<CmsKitRatingOptions> options)
{
Options = options.Value;
}
public virtual Task<RatingEntityTypeDefinition> GetAsync([NotNull] string entityType)
{
Check.NotNullOrWhiteSpace(entityType, nameof(entityType));
var definition = Options.EntityTypes.SingleOrDefault(x => x.EntityType.Equals(entityType, StringComparison.InvariantCultureIgnoreCase)) ??
throw new EntityCantHaveRatingException(entityType);
return Task.FromResult(definition);
}
public virtual Task<bool> IsDefinedAsync([NotNull] string entityType)
{
Check.NotNullOrWhiteSpace(entityType, nameof(entityType));
var isDefined = Options.EntityTypes.Any(x => x.EntityType.Equals(entityType, StringComparison.InvariantCultureIgnoreCase));
return Task.FromResult(isDefined);
}
}
}

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

@ -0,0 +1,22 @@
using JetBrains.Annotations;
using System.Runtime.Serialization;
using Volo.Abp;
namespace Volo.CmsKit.Ratings
{
public class EntityCantHaveRatingException : BusinessException
{
public EntityCantHaveRatingException(SerializationInfo serializationInfo, StreamingContext context) : base(serializationInfo, context)
{
}
public EntityCantHaveRatingException([NotNull] string entityType)
{
Code = CmsKitErrorCodes.Ratings.EntityCantHaveRating;
EntityType = Check.NotNullOrEmpty(entityType, nameof(entityType));
WithData(nameof(EntityType), EntityType);
}
public string EntityType { get; }
}
}

9
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Ratings/IRatingEntityTypeDefinitionStore.cs

@ -0,0 +1,9 @@
using Volo.CmsKit.Ratings;
namespace Volo.CmsKit.Ratings
{
public interface IRatingEntityTypeDefinitionStore : IEntityTypeDefinitionStore<RatingEntityTypeDefinition>
{
}
}

2
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Ratings/Rating.cs

@ -25,7 +25,7 @@ namespace Volo.CmsKit.Ratings
}
public Rating(
internal Rating(
Guid id,
[NotNull] string entityType,
[NotNull] string entityId,

12
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Ratings/RatingEntityTypeDefinition.cs

@ -0,0 +1,12 @@
using JetBrains.Annotations;
namespace Volo.CmsKit.Ratings
{
public class RatingEntityTypeDefinition : EntityTypeDefinition
{
public RatingEntityTypeDefinition(
[NotNull] string entityType) : base(entityType)
{
}
}
}

52
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Ratings/RatingManager.cs

@ -0,0 +1,52 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Domain.Services;
using Volo.CmsKit.Users;
namespace Volo.CmsKit.Ratings
{
public class RatingManager : DomainService
{
protected IRatingRepository RatingRepository { get; }
protected IRatingEntityTypeDefinitionStore RatingDefinitionStore { get; }
public RatingManager(
IRatingRepository ratingRepository,
IRatingEntityTypeDefinitionStore ratingDefinitionStore)
{
RatingRepository = ratingRepository;
RatingDefinitionStore = ratingDefinitionStore;
}
public async Task<Rating> SetStarAsync(CmsUser user, string entityType, string entityId, short starCount)
{
var currentUserRating = await RatingRepository.GetCurrentUserRatingAsync(entityType, entityId, user.Id);
if (currentUserRating != null)
{
currentUserRating.SetStarCount(starCount);
return await RatingRepository.UpdateAsync(currentUserRating);
}
if (!await RatingDefinitionStore.IsDefinedAsync(entityType))
{
throw new EntityCantHaveRatingException(entityType);
}
return await RatingRepository.InsertAsync(
new Rating(
GuidGenerator.Create(),
entityType,
entityId,
starCount,
user.Id,
CurrentTenant.Id
)
);
}
}
}

5
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/TagEntityTypeDefiniton.cs

@ -11,10 +11,6 @@ namespace Volo.CmsKit.Tags
[CanBeNull]
public virtual ILocalizableString DisplayName { get; }
protected TagEntityTypeDefiniton()
{
}
public TagEntityTypeDefiniton(
[NotNull] string entityType,
[CanBeNull] ILocalizableString displayName = null,
@ -23,7 +19,6 @@ namespace Volo.CmsKit.Tags
IEnumerable<string> deletePolicies = null) : base(entityType, createPolicies, updatePolicies, deletePolicies)
{
DisplayName = displayName;
}
public bool Equals(TagEntityTypeDefiniton other)

28
modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Ratings/RatingPublicAppService.cs

@ -13,11 +13,16 @@ namespace Volo.CmsKit.Public.Ratings
{
protected IRatingRepository RatingRepository { get; }
public ICmsUserLookupService CmsUserLookupService { get; }
protected RatingManager RatingManager { get; }
public RatingPublicAppService(IRatingRepository ratingRepository, ICmsUserLookupService cmsUserLookupService)
public RatingPublicAppService(
IRatingRepository ratingRepository,
ICmsUserLookupService cmsUserLookupService,
RatingManager ratingManager)
{
RatingRepository = ratingRepository;
CmsUserLookupService = cmsUserLookupService;
RatingManager = ratingManager;
}
[Authorize]
@ -27,26 +32,7 @@ namespace Volo.CmsKit.Public.Ratings
var userId = CurrentUser.GetId();
var user = await CmsUserLookupService.GetByIdAsync(userId);
var currentUserRating = await RatingRepository.GetCurrentUserRatingAsync(entityType, entityId, userId);
if (currentUserRating != null)
{
currentUserRating.SetStarCount(input.StarCount);
var updatedRating = await RatingRepository.UpdateAsync(currentUserRating);
return ObjectMapper.Map<Rating, RatingDto>(updatedRating);
}
var rating = await RatingRepository.InsertAsync(
new Rating(
GuidGenerator.Create(),
entityType,
entityId,
input.StarCount,
user.Id,
CurrentTenant.Id
)
);
var rating = await RatingManager.SetStarAsync(user, entityType, entityId, input.StarCount);
return ObjectMapper.Map<Rating, RatingDto>(rating);
}

66
modules/cms-kit/test/Volo.CmsKit.Domain.Tests/Ratings/RatingManager_Test.cs

@ -0,0 +1,66 @@
using Shouldly;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.CmsKit.Blogs;
using Volo.CmsKit.Users;
using Xunit;
namespace Volo.CmsKit.Ratings
{
public class RatingManager_Test : CmsKitDomainTestBase
{
private readonly CmsKitTestData _cmsKitTestData;
private readonly RatingManager _ratingManager;
private readonly ICmsUserRepository _userRepository;
public RatingManager_Test()
{
_cmsKitTestData = GetRequiredService<CmsKitTestData>();
_ratingManager = GetRequiredService<RatingManager>();
_userRepository = GetRequiredService<ICmsUserRepository>();
}
[Fact]
public async Task SetStarAsync_ShouldCreate_WhenFirstCall()
{
var user = await _userRepository.GetAsync(_cmsKitTestData.User1Id);
short starCount = 4;
var rating = await _ratingManager.SetStarAsync(user, BlogPostConsts.EntityType, _cmsKitTestData.BlogPost_1_Id.ToString(), starCount);
rating.ShouldNotBeNull();
rating.Id.ShouldNotBe(Guid.Empty);
rating.StarCount.ShouldBe(starCount);
}
[Fact]
public async Task SetStarAsync_ShouldUpdate_WithExistingRating()
{
var user = await _userRepository.GetAsync(_cmsKitTestData.User1Id);
short starCount = 2;
var rating = await _ratingManager.SetStarAsync(user, _cmsKitTestData.EntityType1, _cmsKitTestData.EntityId1, starCount);
rating.ShouldNotBeNull();
rating.Id.ShouldNotBe(Guid.Empty);
rating.StarCount.ShouldBe(starCount);
}
[Fact]
public async Task SetStarAsync_ShouldThrowException_WithNotConfiguredentityType()
{
var user = await _userRepository.GetAsync(_cmsKitTestData.User1Id);
var notConfiguredEntityType = "AnyOtherEntityType";
short starCount = 3;
var exception = await Should.ThrowAsync<EntityCantHaveRatingException>(async () =>
await _ratingManager.SetStarAsync(user, notConfiguredEntityType, "1", starCount));
exception.ShouldNotBeNull();
exception.EntityType.ShouldBe(notConfiguredEntityType);
}
}
}

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

@ -46,6 +46,7 @@ namespace Volo.CmsKit
private readonly BlogManager _blogManager;
private readonly IOptions<CmsKitMediaOptions> _mediaOptions;
private readonly IOptions<CmsKitCommentOptions> _commentsOptions;
private readonly IOptions<CmsKitRatingOptions> _ratingOptions;
public CmsKitDataSeedContributor(
IGuidGenerator guidGenerator,
@ -70,7 +71,8 @@ namespace Volo.CmsKit
IBlobContainer<MediaContainer> mediaBlobContainer,
BlogManager blogManager,
IOptions<CmsKitMediaOptions> cmsMediaOptions,
IOptions<CmsKitCommentOptions> commentsOptions)
IOptions<CmsKitCommentOptions> commentsOptions,
IOptions<CmsKitRatingOptions> ratingOptions)
{
_guidGenerator = guidGenerator;
_cmsUserRepository = cmsUserRepository;
@ -95,6 +97,7 @@ namespace Volo.CmsKit
_blogManager = blogManager;
_mediaOptions = cmsMediaOptions;
_commentsOptions = commentsOptions;
this._ratingOptions = ratingOptions;
}
public async Task SeedAsync(DataSeedContext context)
@ -159,6 +162,9 @@ namespace Volo.CmsKit
_reactionOptions.Value.EntityTypes.Add(new ReactionEntityTypeDefinition(_cmsKitTestData.EntityType1, reactions));
_reactionOptions.Value.EntityTypes.Add(new ReactionEntityTypeDefinition(_cmsKitTestData.EntityType2, reactions));
_ratingOptions.Value.EntityTypes.Add(new RatingEntityTypeDefinition(_cmsKitTestData.EntityType1));
_ratingOptions.Value.EntityTypes.Add(new RatingEntityTypeDefinition(_cmsKitTestData.EntityType2));
return Task.CompletedTask;
}

Loading…
Cancel
Save