mirror of https://github.com/abpframework/abp.git
committed by
GitHub
45 changed files with 1470 additions and 55 deletions
@ -1,43 +0,0 @@ |
|||||
using System; |
|
||||
using Microsoft.EntityFrameworkCore.Migrations; |
|
||||
|
|
||||
namespace Volo.CmsKit.Migrations |
|
||||
{ |
|
||||
public partial class Added_Reactions : Migration |
|
||||
{ |
|
||||
protected override void Up(MigrationBuilder migrationBuilder) |
|
||||
{ |
|
||||
migrationBuilder.CreateTable( |
|
||||
name: "CmsUserReactions", |
|
||||
columns: table => new |
|
||||
{ |
|
||||
Id = table.Column<Guid>(nullable: false), |
|
||||
EntityType = table.Column<string>(maxLength: 64, nullable: false), |
|
||||
EntityId = table.Column<string>(maxLength: 64, nullable: false), |
|
||||
ReactionName = table.Column<string>(maxLength: 32, nullable: false), |
|
||||
CreatorId = table.Column<Guid>(nullable: false), |
|
||||
CreationTime = table.Column<DateTime>(nullable: false) |
|
||||
}, |
|
||||
constraints: table => |
|
||||
{ |
|
||||
table.PrimaryKey("PK_CmsUserReactions", x => x.Id); |
|
||||
}); |
|
||||
|
|
||||
migrationBuilder.CreateIndex( |
|
||||
name: "IX_CmsUserReactions_EntityType_EntityId", |
|
||||
table: "CmsUserReactions", |
|
||||
columns: new[] { "EntityType", "EntityId" }); |
|
||||
|
|
||||
migrationBuilder.CreateIndex( |
|
||||
name: "IX_CmsUserReactions_CreatorId_EntityType_EntityId_ReactionName", |
|
||||
table: "CmsUserReactions", |
|
||||
columns: new[] { "CreatorId", "EntityType", "EntityId", "ReactionName" }); |
|
||||
} |
|
||||
|
|
||||
protected override void Down(MigrationBuilder migrationBuilder) |
|
||||
{ |
|
||||
migrationBuilder.DropTable( |
|
||||
name: "CmsUserReactions"); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,36 @@ |
|||||
|
@page |
||||
|
@using Localization.Resources.AbpUi |
||||
|
@using Microsoft.Extensions.Localization |
||||
|
@using Volo.CmsKit.Pages |
||||
|
@using Volo.CmsKit.Web.Pages.CmsKit.Shared.Components.Commenting |
||||
|
@model PublicModel |
||||
|
@inject IStringLocalizer<AbpUiResource> Localizer |
||||
|
<h1>CMS Kit DEMO - Public</h1> |
||||
|
|
||||
|
<abp-card class="mb-3"> |
||||
|
<abp-card-body> |
||||
|
<abp-blockquote> |
||||
|
<p> |
||||
|
Any fool can write code that a computer can understand. Good programmers write code that humans can understand. |
||||
|
</p> |
||||
|
<footer> |
||||
|
Martin Fowler |
||||
|
</footer> |
||||
|
</abp-blockquote> |
||||
|
</abp-card-body> |
||||
|
@await Component.InvokeAsync(typeof(CommentingViewComponent), new { entityType = "publicQuote", entityId = "1", loginUrl="Account/Login?ReturnUrl=%2Fpublic" }) |
||||
|
</abp-card> |
||||
|
|
||||
|
<abp-card class="mb-3"> |
||||
|
<abp-card-body> |
||||
|
<abp-blockquote> |
||||
|
<p> |
||||
|
Writing code is very simple, but writing simple code is the hardest thing there is! |
||||
|
</p> |
||||
|
<footer> |
||||
|
Halil ibrahim Kalkan <small>(inspired from Johan Cruyff)</small> |
||||
|
</footer> |
||||
|
</abp-blockquote> |
||||
|
</abp-card-body> |
||||
|
@await Component.InvokeAsync(typeof(CommentingViewComponent), new { entityType = "publicQuote", entityId = "2", loginUrl="Account/Login?ReturnUrl=%2Fpublic" }) |
||||
|
</abp-card> |
||||
@ -0,0 +1,11 @@ |
|||||
|
using Microsoft.AspNetCore.Mvc.RazorPages; |
||||
|
|
||||
|
namespace Volo.CmsKit.Pages |
||||
|
{ |
||||
|
public class PublicModel : PageModel |
||||
|
{ |
||||
|
public void OnGet() |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
namespace Volo.CmsKit.Comments |
||||
|
{ |
||||
|
public static class CommentConsts |
||||
|
{ |
||||
|
public static int EntityTypeLength { get; set; } = 64; |
||||
|
|
||||
|
public static int EntityIdLength { get; set; } = 64; |
||||
|
|
||||
|
public static int MaxTextLength { get; set; } = 512; |
||||
|
} |
||||
|
} |
||||
@ -1,6 +1,18 @@ |
|||||
{ |
{ |
||||
"culture": "en", |
"culture": "en", |
||||
"texts": { |
"texts": { |
||||
"PickYourReaction": "Pick your reaction" |
"PickYourReaction": "Pick your reaction", |
||||
|
"YourComment": "Your comment", |
||||
|
"YourReply": "Your reply", |
||||
|
"Comments": "Comments", |
||||
|
"Send": "Send", |
||||
|
"Delete": "Delete", |
||||
|
"Reply": "Reply", |
||||
|
"Update": "Update", |
||||
|
"Edit": "Edit", |
||||
|
"LoginToAddComment": "Login to add comment", |
||||
|
"LoginToReply": "Login to reply", |
||||
|
"MessageDeletionConfirmationMessage": "This comment will be deleted completely.", |
||||
|
"CommentAuthorizationExceptionMessage": "Those comments are not allowed for public display." |
||||
} |
} |
||||
} |
} |
||||
|
|||||
@ -0,0 +1,50 @@ |
|||||
|
using System; |
||||
|
using JetBrains.Annotations; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.Auditing; |
||||
|
using Volo.Abp.Domain.Entities; |
||||
|
|
||||
|
namespace Volo.CmsKit.Comments |
||||
|
{ |
||||
|
public class Comment: Entity<Guid>, IAggregateRoot<Guid>, IHasCreationTime, IMustHaveCreator |
||||
|
{ |
||||
|
public virtual string EntityType { get; protected set; } |
||||
|
|
||||
|
public virtual string EntityId { get; protected set; } |
||||
|
|
||||
|
public virtual string Text { get; protected set; } |
||||
|
|
||||
|
public virtual Guid? RepliedCommentId { get; protected set; } |
||||
|
|
||||
|
public virtual Guid CreatorId { get; set; } |
||||
|
|
||||
|
public virtual DateTime CreationTime { get; set; } |
||||
|
|
||||
|
protected Comment() |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
public Comment( |
||||
|
Guid id, |
||||
|
[NotNull] string entityType, |
||||
|
[NotNull] string entityId, |
||||
|
[NotNull] string text, |
||||
|
Guid? repliedCommentId, |
||||
|
Guid creatorId) |
||||
|
: base(id) |
||||
|
{ |
||||
|
EntityType = Check.NotNullOrWhiteSpace(entityType, nameof(entityType), CommentConsts.EntityTypeLength); |
||||
|
EntityId = Check.NotNullOrWhiteSpace(entityId, nameof(entityId), CommentConsts.EntityIdLength); |
||||
|
RepliedCommentId = repliedCommentId; |
||||
|
CreatorId = creatorId; |
||||
|
|
||||
|
SetText(text); |
||||
|
} |
||||
|
|
||||
|
public virtual void SetText(string text) |
||||
|
{ |
||||
|
Text = Check.NotNullOrWhiteSpace(text, nameof(text), CommentConsts.MaxTextLength); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
using Volo.CmsKit.Users; |
||||
|
|
||||
|
namespace Volo.CmsKit.Comments |
||||
|
{ |
||||
|
public class CommentWithAuthor |
||||
|
{ |
||||
|
public Comment Comment { get; set; } |
||||
|
|
||||
|
public CmsUser Author { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,15 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
using JetBrains.Annotations; |
||||
|
using Volo.Abp.Domain.Repositories; |
||||
|
|
||||
|
namespace Volo.CmsKit.Comments |
||||
|
{ |
||||
|
public interface ICommentRepository : IBasicRepository<Comment, Guid> |
||||
|
{ |
||||
|
Task<List<CommentWithAuthor>> GetListWithAuthorsAsync( |
||||
|
[NotNull] string entityType, |
||||
|
[NotNull] string entityId); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,82 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp.Domain.Entities; |
||||
|
using Volo.Abp.Users; |
||||
|
|
||||
|
namespace Volo.CmsKit.Users |
||||
|
{ |
||||
|
public class CmsUser : AggregateRoot<Guid>, IUser, IUpdateUserData |
||||
|
{ |
||||
|
public virtual Guid? TenantId { get; protected set; } |
||||
|
|
||||
|
public virtual string UserName { get; protected set; } |
||||
|
|
||||
|
public virtual string Email { get; protected set; } |
||||
|
|
||||
|
public virtual string Name { get; set; } |
||||
|
|
||||
|
public virtual string Surname { get; set; } |
||||
|
|
||||
|
public virtual bool EmailConfirmed { get; protected set; } |
||||
|
|
||||
|
public virtual string PhoneNumber { get; protected set; } |
||||
|
|
||||
|
public virtual bool PhoneNumberConfirmed { get; protected set; } |
||||
|
|
||||
|
protected CmsUser() |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
public CmsUser(IUserData user) |
||||
|
: base(user.Id) |
||||
|
{ |
||||
|
TenantId = user.TenantId; |
||||
|
UpdateInternal(user); |
||||
|
} |
||||
|
|
||||
|
public virtual bool Update(IUserData user) |
||||
|
{ |
||||
|
if (Id != user.Id) |
||||
|
{ |
||||
|
throw new ArgumentException($"Given User's Id '{user.Id}' does not match to this User's Id '{Id}'"); |
||||
|
} |
||||
|
|
||||
|
if (TenantId != user.TenantId) |
||||
|
{ |
||||
|
throw new ArgumentException($"Given User's TenantId '{user.TenantId}' does not match to this User's TenantId '{TenantId}'"); |
||||
|
} |
||||
|
|
||||
|
if (Equals(user)) |
||||
|
{ |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
UpdateInternal(user); |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
protected virtual bool Equals(IUserData user) |
||||
|
{ |
||||
|
return Id == user.Id && |
||||
|
TenantId == user.TenantId && |
||||
|
UserName == user.UserName && |
||||
|
Name == user.Name && |
||||
|
Surname == user.Surname && |
||||
|
Email == user.Email && |
||||
|
EmailConfirmed == user.EmailConfirmed && |
||||
|
PhoneNumber == user.PhoneNumber && |
||||
|
PhoneNumberConfirmed == user.PhoneNumberConfirmed; |
||||
|
} |
||||
|
|
||||
|
protected virtual void UpdateInternal(IUserData user) |
||||
|
{ |
||||
|
Email = user.Email; |
||||
|
Name = user.Name; |
||||
|
Surname = user.Surname; |
||||
|
EmailConfirmed = user.EmailConfirmed; |
||||
|
PhoneNumber = user.PhoneNumber; |
||||
|
PhoneNumberConfirmed = user.PhoneNumberConfirmed; |
||||
|
UserName = user.UserName; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,24 @@ |
|||||
|
using Volo.Abp.Uow; |
||||
|
using Volo.Abp.Users; |
||||
|
|
||||
|
namespace Volo.CmsKit.Users |
||||
|
{ |
||||
|
public class CmsUserLookupService: UserLookupService<CmsUser, ICmsUserRepository>, ICmsUserLookupService |
||||
|
{ |
||||
|
public CmsUserLookupService( |
||||
|
ICmsUserRepository userRepository, |
||||
|
IUnitOfWorkManager unitOfWorkManager) |
||||
|
: base( |
||||
|
userRepository, |
||||
|
unitOfWorkManager) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
protected override CmsUser CreateUser(IUserData externalUser) |
||||
|
{ |
||||
|
return new CmsUser(externalUser); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,43 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.Domain.Entities.Events.Distributed; |
||||
|
using Volo.Abp.EventBus.Distributed; |
||||
|
using Volo.Abp.Users; |
||||
|
|
||||
|
namespace Volo.CmsKit.Users |
||||
|
{ |
||||
|
public class CmsUserSynchronizer : |
||||
|
IDistributedEventHandler<EntityUpdatedEto<UserEto>>, |
||||
|
ITransientDependency |
||||
|
{ |
||||
|
protected ICmsUserRepository UserRepository { get; } |
||||
|
|
||||
|
protected ICmsUserLookupService UserLookupService { get; } |
||||
|
|
||||
|
public CmsUserSynchronizer( |
||||
|
ICmsUserRepository userRepository, |
||||
|
ICmsUserLookupService userLookupService) |
||||
|
{ |
||||
|
UserRepository = userRepository; |
||||
|
UserLookupService = userLookupService; |
||||
|
} |
||||
|
|
||||
|
public virtual async Task HandleEventAsync(EntityUpdatedEto<UserEto> eventData) |
||||
|
{ |
||||
|
var user = await UserRepository.FindAsync(eventData.Entity.Id); |
||||
|
if (user == null) |
||||
|
{ |
||||
|
user = await UserLookupService.FindByIdAsync(eventData.Entity.Id); |
||||
|
if (user == null) |
||||
|
{ |
||||
|
return; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (user.Update(eventData.Entity)) |
||||
|
{ |
||||
|
await UserRepository.UpdateAsync(user); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
using Volo.Abp.Users; |
||||
|
|
||||
|
namespace Volo.CmsKit.Users |
||||
|
{ |
||||
|
public interface ICmsUserLookupService : IUserLookupService<CmsUser> |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
using Volo.Abp.Users; |
||||
|
|
||||
|
namespace Volo.CmsKit.Users |
||||
|
{ |
||||
|
public interface ICmsUserRepository: IUserRepository<CmsUser> |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,57 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Threading; |
||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.EntityFrameworkCore; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.Domain.Repositories.EntityFrameworkCore; |
||||
|
using Volo.Abp.EntityFrameworkCore; |
||||
|
using Volo.CmsKit.EntityFrameworkCore; |
||||
|
|
||||
|
namespace Volo.CmsKit.Comments |
||||
|
{ |
||||
|
public class EfCoreCommentRepository : EfCoreRepository<ICmsKitDbContext, Comment, Guid>, |
||||
|
ICommentRepository |
||||
|
{ |
||||
|
public EfCoreCommentRepository(IDbContextProvider<ICmsKitDbContext> dbContextProvider) |
||||
|
: base(dbContextProvider) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
public async Task<List<CommentWithAuthor>> GetListWithAuthorsAsync( |
||||
|
string entityType, |
||||
|
string entityId) |
||||
|
{ |
||||
|
Check.NotNullOrWhiteSpace(entityType, nameof(entityType)); |
||||
|
Check.NotNullOrWhiteSpace(entityId, nameof(entityId)); |
||||
|
|
||||
|
var query = from comment in DbSet |
||||
|
join user in DbContext.CmsUsers on comment.CreatorId equals user.Id |
||||
|
where entityType == comment.EntityType && entityId == comment.EntityId |
||||
|
orderby comment.CreationTime |
||||
|
select new CommentWithAuthor |
||||
|
{ |
||||
|
Comment = comment, |
||||
|
Author = user |
||||
|
}; |
||||
|
|
||||
|
return await query.ToListAsync(); |
||||
|
} |
||||
|
|
||||
|
public override async Task DeleteAsync(Guid id, bool autoSave = false, CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
var replies = await DbSet |
||||
|
.Where(x => x.RepliedCommentId == id) |
||||
|
.ToListAsync(GetCancellationToken(cancellationToken)); |
||||
|
|
||||
|
foreach (var reply in replies) |
||||
|
{ |
||||
|
//TODO: Discuss if it is better to mark it as deleted and show in the ui as "This is deleted" instead of deleting it and replies completely
|
||||
|
await base.DeleteAsync(reply.Id, autoSave, GetCancellationToken(cancellationToken)); |
||||
|
} |
||||
|
|
||||
|
await base.DeleteAsync(id, autoSave, GetCancellationToken(cancellationToken)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,14 @@ |
|||||
|
using Volo.Abp.EntityFrameworkCore; |
||||
|
using Volo.Abp.Users.EntityFrameworkCore; |
||||
|
using Volo.CmsKit.EntityFrameworkCore; |
||||
|
|
||||
|
namespace Volo.CmsKit.Users |
||||
|
{ |
||||
|
public class EfCoreCmsUserRepository: EfCoreUserRepositoryBase<ICmsKitDbContext, CmsUser>, ICmsUserRepository |
||||
|
{ |
||||
|
public EfCoreCmsUserRepository(IDbContextProvider<ICmsKitDbContext> dbContextProvider) |
||||
|
: base(dbContextProvider) |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,17 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace Volo.CmsKit.Comments |
||||
|
{ |
||||
|
public class CmsUserDto |
||||
|
{ |
||||
|
public Guid Id { get; set; } |
||||
|
|
||||
|
public string UserName { get; set; } |
||||
|
|
||||
|
public string Email { get; set; } |
||||
|
|
||||
|
public string Name { get; set; } |
||||
|
|
||||
|
public string Surname { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,23 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace Volo.CmsKit.Comments |
||||
|
{ |
||||
|
public class CommentDto |
||||
|
{ |
||||
|
public Guid Id { get; set; } |
||||
|
|
||||
|
public string EntityType { get; set; } |
||||
|
|
||||
|
public string EntityId { get; set; } |
||||
|
|
||||
|
public string Text { get; set; } |
||||
|
|
||||
|
public Guid? RepliedCommentId { get; set; } |
||||
|
|
||||
|
public Guid CreatorId { get; set; } |
||||
|
|
||||
|
public DateTime CreationTime { get; set; } |
||||
|
|
||||
|
public CmsUserDto Author { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,24 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace Volo.CmsKit.Comments |
||||
|
{ |
||||
|
public class CommentWithDetailsDto |
||||
|
{ |
||||
|
public Guid Id { get; set; } |
||||
|
|
||||
|
public string EntityType { get; set; } |
||||
|
|
||||
|
public string EntityId { get; set; } |
||||
|
|
||||
|
public string Text { get; set; } |
||||
|
|
||||
|
public Guid CreatorId { get; set; } |
||||
|
|
||||
|
public DateTime CreationTime { get; set; } |
||||
|
|
||||
|
public List<CommentDto> Replies { get; set; } |
||||
|
|
||||
|
public CmsUserDto Author { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,23 @@ |
|||||
|
using System; |
||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
using Volo.Abp.Validation; |
||||
|
|
||||
|
namespace Volo.CmsKit.Comments |
||||
|
{ |
||||
|
public class CreateCommentInput |
||||
|
{ |
||||
|
[Required] |
||||
|
[DynamicStringLength(typeof(CommentConsts), nameof(CommentConsts.EntityTypeLength))] |
||||
|
public string EntityType { get; set; } |
||||
|
|
||||
|
[Required] |
||||
|
[DynamicStringLength(typeof(CommentConsts), nameof(CommentConsts.EntityIdLength))] |
||||
|
public string EntityId { get; set; } |
||||
|
|
||||
|
[Required] |
||||
|
[DynamicStringLength(typeof(CommentConsts), nameof(CommentConsts.MaxTextLength))] |
||||
|
public string Text { get; set; } |
||||
|
|
||||
|
public Guid? RepliedCommentId { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,20 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
using JetBrains.Annotations; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
using Volo.Abp.Application.Services; |
||||
|
|
||||
|
namespace Volo.CmsKit.Comments |
||||
|
{ |
||||
|
public interface ICommentPublicAppService : IApplicationService |
||||
|
{ |
||||
|
Task<ListResultDto<CommentWithDetailsDto>> GetAllForEntityAsync(string entityType, string entityId); |
||||
|
|
||||
|
Task<CommentDto> CreateAsync(CreateCommentInput input); |
||||
|
|
||||
|
Task<CommentDto> UpdateAsync(Guid id, UpdateCommentInput input); |
||||
|
|
||||
|
Task DeleteAsync(Guid id); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,13 @@ |
|||||
|
using System; |
||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
using Volo.Abp.Validation; |
||||
|
|
||||
|
namespace Volo.CmsKit.Comments |
||||
|
{ |
||||
|
public class UpdateCommentInput |
||||
|
{ |
||||
|
[Required] |
||||
|
[DynamicStringLength(typeof(CommentConsts), nameof(CommentConsts.MaxTextLength))] |
||||
|
public string Text { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,142 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.AspNetCore.Authorization; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
using Volo.Abp.Application.Services; |
||||
|
using Volo.Abp.Authorization; |
||||
|
using Volo.CmsKit.Users; |
||||
|
|
||||
|
namespace Volo.CmsKit.Comments |
||||
|
{ |
||||
|
public class CommentPublicAppService : ApplicationService, ICommentPublicAppService |
||||
|
{ |
||||
|
protected CmsKitOptions CmsKitOptions { get; } |
||||
|
protected ICommentRepository CommentRepository { get; } |
||||
|
protected ICmsUserLookupService CmsUserLookupService { get; } |
||||
|
|
||||
|
public CommentPublicAppService( |
||||
|
ICommentRepository commentRepository, |
||||
|
ICmsUserLookupService cmsUserLookupService, |
||||
|
IOptions<CmsKitOptions> cmsKitOptions) |
||||
|
{ |
||||
|
CmsKitOptions = cmsKitOptions.Value; |
||||
|
CommentRepository = commentRepository; |
||||
|
CmsUserLookupService = cmsUserLookupService; |
||||
|
} |
||||
|
|
||||
|
public async Task<ListResultDto<CommentWithDetailsDto>> GetAllForEntityAsync(string entityType, string entityId) |
||||
|
{ |
||||
|
CheckAuthorizationAsync(entityType); |
||||
|
|
||||
|
var commentsWithAuthor = await CommentRepository.GetListWithAuthorsAsync(entityType, entityId); |
||||
|
|
||||
|
return new ListResultDto<CommentWithDetailsDto>( |
||||
|
ConvertCommentsToNestedStructure(commentsWithAuthor) |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
[Authorize] |
||||
|
public async Task<CommentDto> CreateAsync(CreateCommentInput input) |
||||
|
{ |
||||
|
var user = await CmsUserLookupService.FindByIdAsync(CurrentUser.Id.Value); |
||||
|
|
||||
|
if (user == null) |
||||
|
{ |
||||
|
throw new BusinessException(message: "User Not found!"); |
||||
|
} |
||||
|
|
||||
|
var comment = await CommentRepository.InsertAsync(new Comment( |
||||
|
GuidGenerator.Create(), |
||||
|
input.EntityType, |
||||
|
input.EntityId, |
||||
|
input.Text, |
||||
|
input.RepliedCommentId, |
||||
|
CurrentUser.Id.Value |
||||
|
)); |
||||
|
|
||||
|
return ObjectMapper.Map<Comment, CommentDto>(comment); |
||||
|
} |
||||
|
|
||||
|
[Authorize] |
||||
|
public async Task<CommentDto> UpdateAsync(Guid id, UpdateCommentInput input) |
||||
|
{ |
||||
|
var comment = await CommentRepository.GetAsync(id); |
||||
|
|
||||
|
if (comment.CreatorId != CurrentUser.Id) |
||||
|
{ |
||||
|
throw new BusinessException(); |
||||
|
} |
||||
|
|
||||
|
comment.SetText(input.Text); |
||||
|
|
||||
|
var updatedComment = await CommentRepository.UpdateAsync(comment); |
||||
|
|
||||
|
return ObjectMapper.Map<Comment, CommentDto>(updatedComment); |
||||
|
} |
||||
|
|
||||
|
[Authorize] |
||||
|
public async Task DeleteAsync(Guid id) |
||||
|
{ |
||||
|
var comment = await CommentRepository.GetAsync(id); |
||||
|
|
||||
|
if (comment.CreatorId != CurrentUser.Id) |
||||
|
{ |
||||
|
throw new BusinessException(); |
||||
|
} |
||||
|
|
||||
|
await CommentRepository.DeleteAsync(id); |
||||
|
} |
||||
|
|
||||
|
private List<CommentWithDetailsDto> ConvertCommentsToNestedStructure(List<CommentWithAuthor> comments) |
||||
|
{ |
||||
|
var parentComments = comments |
||||
|
.Where(c=> c.Comment.RepliedCommentId == null) |
||||
|
.Select(c=> ObjectMapper.Map<Comment, CommentWithDetailsDto>(c.Comment)) |
||||
|
.ToList(); |
||||
|
|
||||
|
foreach (var parentComment in parentComments) |
||||
|
{ |
||||
|
parentComment.Author = GetAuthorAsDtoFromCommentList(comments, parentComment.Id); |
||||
|
|
||||
|
parentComment.Replies = comments |
||||
|
.Where(c => c.Comment.RepliedCommentId == parentComment.Id) |
||||
|
.Select(c => ObjectMapper.Map<Comment, CommentDto>(c.Comment)) |
||||
|
.ToList(); |
||||
|
|
||||
|
foreach (var reply in parentComment.Replies) |
||||
|
{ |
||||
|
reply.Author = GetAuthorAsDtoFromCommentList(comments, reply.Id); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return parentComments; |
||||
|
} |
||||
|
|
||||
|
private async Task CheckAuthorizationAsync(string entityType) |
||||
|
{ |
||||
|
if (await IsPublicEntity(entityType)) |
||||
|
{ |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (!CurrentUser.IsAuthenticated) |
||||
|
{ |
||||
|
throw new AbpAuthorizationException(L["CommentAuthorizationExceptionMessage"]); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private async Task<bool> IsPublicEntity(string entityType) |
||||
|
{ |
||||
|
return CmsKitOptions.PublicCommentEntities.Contains(entityType); |
||||
|
} |
||||
|
|
||||
|
private CmsUserDto GetAuthorAsDtoFromCommentList(List<CommentWithAuthor> comments, Guid commentId) |
||||
|
{ |
||||
|
return ObjectMapper.Map<CmsUser, CmsUserDto>(comments.Single(c => c.Comment.Id == commentId).Author); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,49 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
|
||||
|
namespace Volo.CmsKit.Comments |
||||
|
{ |
||||
|
[RemoteService(Name = CmsKitPublicRemoteServiceConsts.RemoteServiceName)] |
||||
|
[Area("cms-kit")] |
||||
|
[Route("api/cms-kit-public/comments")] |
||||
|
public class CommentPublicController : CmsKitPublicControllerBase, ICommentPublicAppService |
||||
|
{ |
||||
|
public ICommentPublicAppService CommentPublicAppService { get; } |
||||
|
|
||||
|
public CommentPublicController(ICommentPublicAppService commentPublicAppService) |
||||
|
{ |
||||
|
CommentPublicAppService = commentPublicAppService; |
||||
|
} |
||||
|
|
||||
|
[HttpGet] |
||||
|
[Route("{entityType}/{entityId}")] |
||||
|
public Task<ListResultDto<CommentWithDetailsDto>> GetAllForEntityAsync(string entityType, string entityId) |
||||
|
{ |
||||
|
return CommentPublicAppService.GetAllForEntityAsync(entityType, entityId); |
||||
|
} |
||||
|
|
||||
|
[HttpPost] |
||||
|
public Task<CommentDto> CreateAsync(CreateCommentInput input) |
||||
|
{ |
||||
|
return CommentPublicAppService.CreateAsync(input); |
||||
|
} |
||||
|
|
||||
|
[HttpPost] |
||||
|
[Route("{id}")] |
||||
|
public Task<CommentDto> UpdateAsync(Guid id, UpdateCommentInput input) |
||||
|
{ |
||||
|
return CommentPublicAppService.UpdateAsync(id, input); |
||||
|
} |
||||
|
|
||||
|
[HttpDelete] |
||||
|
[Route("update")] |
||||
|
public Task DeleteAsync(Guid id) |
||||
|
{ |
||||
|
return CommentPublicAppService.DeleteAsync(id); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,15 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
using Volo.Abp.AspNetCore.Mvc.UI.Bundling; |
||||
|
using Volo.Abp.AspNetCore.Mvc.UI.Packages.Bootstrap; |
||||
|
using Volo.Abp.Modularity; |
||||
|
|
||||
|
namespace Volo.CmsKit.Web.Pages.CmsKit.Shared.Components.Commenting |
||||
|
{ |
||||
|
public class CommentingScriptBundleContributor : BundleContributor |
||||
|
{ |
||||
|
public override void ConfigureBundle(BundleConfigurationContext context) |
||||
|
{ |
||||
|
context.Files.AddIfNotContains("/Pages/CmsKit/Shared/Components/Commenting/default.js"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,13 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
using Volo.Abp.AspNetCore.Mvc.UI.Bundling; |
||||
|
|
||||
|
namespace Volo.CmsKit.Web.Pages.CmsKit.Shared.Components.Commenting |
||||
|
{ |
||||
|
public class CommentingStyleBundleContributor : BundleContributor |
||||
|
{ |
||||
|
public override void ConfigureBundle(BundleConfigurationContext context) |
||||
|
{ |
||||
|
context.Files.AddIfNotContains("/Pages/CmsKit/Shared/Components/Commenting/default.css"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,53 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Volo.Abp.AspNetCore.Mvc; |
||||
|
using Volo.Abp.AspNetCore.Mvc.UI.Widgets; |
||||
|
using Volo.CmsKit.Comments; |
||||
|
|
||||
|
namespace Volo.CmsKit.Web.Pages.CmsKit.Shared.Components.Commenting |
||||
|
{ |
||||
|
[ViewComponent(Name = "CmsCommenting")] |
||||
|
[Widget( |
||||
|
ScriptTypes = new[] {typeof(CommentingScriptBundleContributor)}, |
||||
|
StyleTypes = new[] {typeof(CommentingStyleBundleContributor)}, |
||||
|
RefreshUrl = "/CmsKitPublicWidgets/Commenting" |
||||
|
)] |
||||
|
public class CommentingViewComponent : AbpViewComponent |
||||
|
{ |
||||
|
public ICommentPublicAppService CommentPublicAppService { get; } |
||||
|
|
||||
|
public CommentingViewComponent( |
||||
|
ICommentPublicAppService commentPublicAppService) |
||||
|
{ |
||||
|
CommentPublicAppService = commentPublicAppService; |
||||
|
} |
||||
|
|
||||
|
public virtual async Task<IViewComponentResult> InvokeAsync(string entityType, string entityId, string loginUrl = null) |
||||
|
{ |
||||
|
var result = await CommentPublicAppService.GetAllForEntityAsync(entityType, entityId); |
||||
|
|
||||
|
var viewModel = new CommentingViewModel |
||||
|
{ |
||||
|
EntityId = entityId, |
||||
|
EntityType = entityType, |
||||
|
LoginUrl = loginUrl, |
||||
|
Comments = result.Items.ToList() |
||||
|
}; |
||||
|
|
||||
|
return View("~/Pages/CmsKit/Shared/Components/Commenting/Default.cshtml", viewModel); |
||||
|
} |
||||
|
|
||||
|
public class CommentingViewModel |
||||
|
{ |
||||
|
public string EntityType { get; set; } |
||||
|
|
||||
|
public string EntityId { get; set; } |
||||
|
|
||||
|
public string LoginUrl { get; set; } |
||||
|
|
||||
|
public List<CommentWithDetailsDto> Comments { get; set; } |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,145 @@ |
|||||
|
@using Microsoft.AspNetCore.Html |
||||
|
@using Microsoft.AspNetCore.Mvc.Localization |
||||
|
@using Volo.Abp.Users |
||||
|
@using Volo.CmsKit.Comments |
||||
|
@using Volo.CmsKit.Localization |
||||
|
@inject ICurrentUser CurrentUser |
||||
|
@inject IHtmlLocalizer<CmsKitResource> L |
||||
|
@model Volo.CmsKit.Web.Pages.CmsKit.Shared.Components.Commenting.CommentingViewComponent.CommentingViewModel |
||||
|
|
||||
|
@{ |
||||
|
Func<dynamic, IHtmlContent> GetCommentTitle(CmsUserDto author, DateTime creationTime) => |
||||
|
@<span> |
||||
|
@((string.IsNullOrWhiteSpace(author.Name) |
||||
|
? author.UserName |
||||
|
: author.Name + " " + author.Surname).Trim()) |
||||
|
<small>@creationTime.ToString()</small> |
||||
|
</span>; |
||||
|
} |
||||
|
@{ |
||||
|
Func<dynamic, IHtmlContent> GetCommentArea(Guid? repliedCommentId, bool cancelButton = false) => |
||||
|
@<div class="cms-comment-form-area" data-reply-id="@(repliedCommentId?.ToString() ?? "")" |
||||
|
style="@(string.IsNullOrEmpty(repliedCommentId?.ToString() ?? "") ? "" : "display:none")"> |
||||
|
<form class="cms-comment-form"> |
||||
|
<input hidden value="@(repliedCommentId?.ToString() ?? "")" name="repliedCommentId"/> |
||||
|
<div class="form-group"> |
||||
|
<label> @(string.IsNullOrEmpty(repliedCommentId?.ToString() ?? "") ? L["YourComment"] : L["YourReply"]) </label> |
||||
|
<textarea class="form-control" name="commentText" rows="3"></textarea> |
||||
|
</div> |
||||
|
@if (cancelButton) |
||||
|
{ |
||||
|
<abp-button type="button" button-type="Secondary" class="reply-cancel-button" data-reply-id="@(repliedCommentId?.ToString() ?? "")"> @L["Cancel"] </abp-button> |
||||
|
} |
||||
|
<abp-button type="submit" button-type="Primary"> @L["Send"] </abp-button> |
||||
|
</form> |
||||
|
</div>; |
||||
|
} |
||||
|
@{ |
||||
|
Func<dynamic, IHtmlContent> GetCommentContentArea(Guid id, Guid authorId, bool isReply, string text) => |
||||
|
@<div> |
||||
|
<div class="cms-comment-content-area" data-id="@id.ToString()"> |
||||
|
<p> |
||||
|
@text |
||||
|
</p> |
||||
|
</div> |
||||
|
|
||||
|
@if (!isReply) |
||||
|
{ |
||||
|
@if (CurrentUser.IsAuthenticated) |
||||
|
{ |
||||
|
<a href="#" class="comment-reply-link" data-reply-id="@id.ToString()"> |
||||
|
<i class="fa fa-reply"></i> @L["Reply"] |
||||
|
</a> |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
<a href="@Model.LoginUrl"> @L["LoginToReply"]</a> |
||||
|
} |
||||
|
} |
||||
|
@if (authorId == CurrentUser.Id) |
||||
|
{ |
||||
|
@if (!isReply) |
||||
|
{ |
||||
|
<span> | </span> |
||||
|
} |
||||
|
|
||||
|
<a href="#" class="comment-delete-link" data-id="@id.ToString()"> |
||||
|
<i class="fa fa-trash"></i> @L["Delete"] |
||||
|
</a> |
||||
|
|
||||
|
<span> | </span> |
||||
|
|
||||
|
<a href="#" class="comment-edit-link" data-id="@id.ToString()"> |
||||
|
<i class="fa fa-pencil"></i> @L["Edit"] |
||||
|
</a> |
||||
|
} |
||||
|
<div class="cms-comment-edit-area" data-id="@id.ToString()" style="display:none"> |
||||
|
<form class="cms-comment-update-form"> |
||||
|
<input hidden value="@id.ToString()" name="id"/> |
||||
|
<div class="form-group"> |
||||
|
<textarea class="form-control" name="commentText" rows="3">@text</textarea> |
||||
|
</div> |
||||
|
<abp-button type="button" button-type="Secondary" class="comment-edit-cancel-button" data-id="@id.ToString()"> @L["Cancel"] </abp-button> |
||||
|
<abp-button type="submit" button-type="Primary"> @L["Update"] </abp-button> |
||||
|
</form> |
||||
|
</div> |
||||
|
</div>; |
||||
|
} |
||||
|
|
||||
|
<div class="cms-comment-area" data-entity-type="@Model.EntityType" data-entity-id="@Model.EntityId"> |
||||
|
|
||||
|
<div class="pl-5 pt-3"> |
||||
|
<h4> |
||||
|
<i class="fa fa-comment-o"></i> |
||||
|
@L["Comments"] |
||||
|
</h4> |
||||
|
@foreach (var comment in Model.Comments) |
||||
|
{ |
||||
|
<div class="comment pt-2 mt-1 mb-1"> |
||||
|
<div class="border-bottom"> |
||||
|
<h5> |
||||
|
@GetCommentTitle(comment.Author, comment.CreationTime).Invoke(null) |
||||
|
</h5> |
||||
|
|
||||
|
@GetCommentContentArea(comment.Id, comment.Author.Id, false, comment.Text).Invoke(null) |
||||
|
|
||||
|
@if (CurrentUser.IsAuthenticated) |
||||
|
{ |
||||
|
@GetCommentArea(comment.Id, true).Invoke(null) |
||||
|
} |
||||
|
|
||||
|
@if (comment.Replies.Any()) |
||||
|
{ |
||||
|
<div class="pl-5"> |
||||
|
@foreach (var reply in comment.Replies) |
||||
|
{ |
||||
|
<div class="comment pt-3"> |
||||
|
<div class="border-bottom"> |
||||
|
|
||||
|
<h6> |
||||
|
@GetCommentTitle(reply.Author, reply.CreationTime).Invoke(null) |
||||
|
</h6> |
||||
|
|
||||
|
@GetCommentContentArea(reply.Id, reply.Author.Id, true, reply.Text).Invoke(null) |
||||
|
</div> |
||||
|
</div> |
||||
|
} |
||||
|
</div> |
||||
|
} |
||||
|
</div> |
||||
|
</div> |
||||
|
} |
||||
|
<div class="p-3 pl-5"> |
||||
|
@if (CurrentUser.IsAuthenticated) |
||||
|
{ |
||||
|
@GetCommentArea(null).Invoke(null) |
||||
|
} |
||||
|
else if (!string.IsNullOrWhiteSpace(Model.LoginUrl)) |
||||
|
{ |
||||
|
<div class="float-right mb-2"> |
||||
|
<a href="@Model.LoginUrl" class="btn btn-primary"> @L["LoginToAddComment"]</a> |
||||
|
</div> |
||||
|
} |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
@ -0,0 +1 @@ |
|||||
|
|
||||
@ -0,0 +1,162 @@ |
|||||
|
(function ($) { |
||||
|
|
||||
|
var l = abp.localization.getResource('CmsKit'); |
||||
|
|
||||
|
$(document).ready(function () { |
||||
|
|
||||
|
abp.widgets.CmsCommenting = function ($widget) { |
||||
|
var widgetManager = $widget.data('abp-widget-manager'); |
||||
|
var $commentArea = $widget.find('.cms-comment-area'); |
||||
|
|
||||
|
function getFilters() { |
||||
|
return { |
||||
|
entityType: $commentArea.attr('data-entity-type'), |
||||
|
entityId: $commentArea.attr('data-entity-id') |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
function registerEditLinks($container) { |
||||
|
$container.find('.comment-edit-link').each(function () { |
||||
|
var $link = $(this); |
||||
|
$link.on('click', function (e) { |
||||
|
e.preventDefault(); |
||||
|
|
||||
|
var commentId = $link.data('id'); |
||||
|
|
||||
|
var $relatedCommentContentArea = $container.find('.cms-comment-content-area[data-id='+ commentId +']'); |
||||
|
var $relatedCommentEditFormArea = $container.find('.cms-comment-edit-area[data-id='+ commentId +']'); |
||||
|
|
||||
|
$relatedCommentContentArea.hide(); |
||||
|
$relatedCommentEditFormArea.show(); |
||||
|
$link.removeAttr('href'); |
||||
|
}); |
||||
|
}); |
||||
|
$container.find('.comment-edit-cancel-button').each(function () { |
||||
|
var $button = $(this); |
||||
|
$button.on('click', function (e) { |
||||
|
e.preventDefault(); |
||||
|
|
||||
|
var commentId = $button.data('id'); |
||||
|
|
||||
|
var $relatedCommentContentArea = $container.find('.cms-comment-content-area[data-id='+ commentId +']'); |
||||
|
var $relatedCommentEditFormArea = $container.find('.cms-comment-edit-area[data-id='+ commentId +']'); |
||||
|
var $link = $container.find('.comment-edit-link[data-id='+ commentId +']'); |
||||
|
|
||||
|
$relatedCommentContentArea.show(); |
||||
|
$relatedCommentEditFormArea.hide(); |
||||
|
$link.attr('href','#'); |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function registerReplyLinks($container) { |
||||
|
$container.find('.comment-reply-link').each(function () { |
||||
|
var $link = $(this); |
||||
|
$link.on('click', function (e) { |
||||
|
e.preventDefault(); |
||||
|
|
||||
|
var replyCommentId = $link.data('reply-id'); |
||||
|
|
||||
|
var $relatedCommentArea = $container.find('.cms-comment-form-area[data-reply-id='+ replyCommentId +']'); |
||||
|
|
||||
|
$relatedCommentArea.show(); |
||||
|
$link.removeAttr('href'); |
||||
|
}); |
||||
|
}); |
||||
|
$container.find('.reply-cancel-button').each(function () { |
||||
|
var $button = $(this); |
||||
|
$button.on('click', function (e) { |
||||
|
e.preventDefault(); |
||||
|
|
||||
|
var replyCommentId = $button.data('reply-id'); |
||||
|
|
||||
|
var $relatedCommentArea = $container.find('.cms-comment-form-area[data-reply-id='+ replyCommentId +']'); |
||||
|
var $replyLink = $container.find('.comment-reply-link[data-reply-id='+ replyCommentId +']'); |
||||
|
|
||||
|
$relatedCommentArea.hide(); |
||||
|
$replyLink.attr('href','#'); |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function registerDeleteLinks($container) { |
||||
|
$container.find('.comment-delete-link').each(function () { |
||||
|
var $link = $(this); |
||||
|
$link.on('click', '', function (e) { |
||||
|
e.preventDefault(); |
||||
|
|
||||
|
abp.message.confirm(l("MessageDeletionConfirmationMessage"), function (ok) { |
||||
|
if (ok){ |
||||
|
volo.cmsKit.comments.commentPublic.delete($link.data('id') |
||||
|
).then(function () { |
||||
|
widgetManager.refresh($widget); |
||||
|
}); |
||||
|
} |
||||
|
}); |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function registerUpdateOfNewComment($container) { |
||||
|
$container.find('.cms-comment-update-form').each(function () { |
||||
|
var $form = $(this); |
||||
|
$form.submit(function (e) { |
||||
|
e.preventDefault(); |
||||
|
var formAsObject = $form.serializeFormToObject(); |
||||
|
volo.cmsKit.comments.commentPublic.update( |
||||
|
formAsObject.id, |
||||
|
{ |
||||
|
text: formAsObject.commentText |
||||
|
} |
||||
|
).then(function () { |
||||
|
widgetManager.refresh($widget); |
||||
|
}); |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function registerSubmissionOfNewComment($container) { |
||||
|
$container.find('.cms-comment-form').each(function () { |
||||
|
var $form = $(this); |
||||
|
$form.submit(function (e) { |
||||
|
e.preventDefault(); |
||||
|
var formAsObject = $form.serializeFormToObject(); |
||||
|
console.log(formAsObject); |
||||
|
volo.cmsKit.comments.commentPublic.create( |
||||
|
$.extend(getFilters(), { |
||||
|
repliedCommentId: formAsObject.repliedCommentId, |
||||
|
text: formAsObject.commentText |
||||
|
}) |
||||
|
).then(function () { |
||||
|
widgetManager.refresh($widget); |
||||
|
}); |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function init() { |
||||
|
registerReplyLinks($widget); |
||||
|
registerEditLinks($widget); |
||||
|
registerDeleteLinks($widget); |
||||
|
|
||||
|
registerUpdateOfNewComment($widget); |
||||
|
registerSubmissionOfNewComment($widget); |
||||
|
} |
||||
|
|
||||
|
return { |
||||
|
init: init, |
||||
|
getFilters: getFilters |
||||
|
}; |
||||
|
}; |
||||
|
|
||||
|
$('.abp-widget-wrapper[data-widget-name="CmsCommenting"]') |
||||
|
.each(function () { |
||||
|
var widgetManager = new abp.WidgetManager({ |
||||
|
wrapper: $(this), |
||||
|
}); |
||||
|
|
||||
|
widgetManager.init(); |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
})(jQuery); |
||||
Loading…
Reference in new issue