feat(server): send comment notifications
This commit is contained in:
parent
559aa849c8
commit
c582ed6f35
@ -6,6 +6,7 @@ import {
|
||||
createReplyMutation,
|
||||
deleteCommentMutation,
|
||||
deleteReplyMutation,
|
||||
DocMode,
|
||||
listCommentChangesQuery,
|
||||
listCommentsQuery,
|
||||
resolveCommentMutation,
|
||||
@ -64,6 +65,8 @@ e2e('should create comment work', async t => {
|
||||
input: {
|
||||
workspaceId: workspace.id,
|
||||
docId,
|
||||
docMode: DocMode.page,
|
||||
docTitle: 'test',
|
||||
content: {
|
||||
type: 'paragraph',
|
||||
content: [{ type: 'text', text: 'test' }],
|
||||
@ -82,6 +85,8 @@ e2e('should create comment work', async t => {
|
||||
input: {
|
||||
workspaceId: workspace.id,
|
||||
docId,
|
||||
docMode: DocMode.page,
|
||||
docTitle: 'test',
|
||||
content: {
|
||||
type: 'paragraph',
|
||||
content: [{ type: 'text', text: 'test' }],
|
||||
@ -94,6 +99,52 @@ e2e('should create comment work', async t => {
|
||||
t.is(result2.createComment.replies.length, 0);
|
||||
});
|
||||
|
||||
e2e('should create comment with mentions work', async t => {
|
||||
const docId = randomUUID();
|
||||
await app.create(Mockers.DocUser, {
|
||||
workspaceId: teamWorkspace.id,
|
||||
docId,
|
||||
userId: member.id,
|
||||
type: DocRole.Owner,
|
||||
});
|
||||
|
||||
await app.login(member);
|
||||
|
||||
const count = app.queue.count('notification.sendComment');
|
||||
const result = await app.gql({
|
||||
query: createCommentMutation,
|
||||
variables: {
|
||||
input: {
|
||||
workspaceId: teamWorkspace.id,
|
||||
docId,
|
||||
docMode: DocMode.page,
|
||||
docTitle: 'test',
|
||||
content: {
|
||||
type: 'paragraph',
|
||||
content: [{ type: 'text', text: 'test' }],
|
||||
},
|
||||
mentions: [
|
||||
// send
|
||||
owner.id,
|
||||
// ignore doc owner himself
|
||||
member.id,
|
||||
// ignore not workspace member
|
||||
other.id,
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
t.truthy(result.createComment.id);
|
||||
t.false(result.createComment.resolved);
|
||||
t.is(result.createComment.replies.length, 0);
|
||||
// only send one notification to owner
|
||||
t.is(app.queue.count('notification.sendComment'), count + 1);
|
||||
const notification = app.queue.last('notification.sendComment');
|
||||
t.is(notification.name, 'notification.sendComment');
|
||||
t.is(notification.payload.userId, owner.id);
|
||||
});
|
||||
|
||||
e2e('should create comment work when user is Commenter', async t => {
|
||||
const docId = randomUUID();
|
||||
await app.create(Mockers.DocUser, {
|
||||
@ -110,6 +161,8 @@ e2e('should create comment work when user is Commenter', async t => {
|
||||
input: {
|
||||
workspaceId: teamWorkspace.id,
|
||||
docId,
|
||||
docMode: DocMode.page,
|
||||
docTitle: 'test',
|
||||
content: {
|
||||
type: 'paragraph',
|
||||
content: [{ type: 'text', text: 'test' }],
|
||||
@ -134,6 +187,8 @@ e2e('should create comment failed when user is not member', async t => {
|
||||
input: {
|
||||
workspaceId: workspace.id,
|
||||
docId,
|
||||
docMode: DocMode.page,
|
||||
docTitle: 'test',
|
||||
content: {
|
||||
type: 'paragraph',
|
||||
content: [{ type: 'text', text: 'test' }],
|
||||
@ -166,6 +221,8 @@ e2e('should create comment failed when user is Reader', async t => {
|
||||
input: {
|
||||
workspaceId: teamWorkspace.id,
|
||||
docId,
|
||||
docMode: DocMode.page,
|
||||
docTitle: 'test',
|
||||
content: {
|
||||
type: 'paragraph',
|
||||
content: [{ type: 'text', text: 'test' }],
|
||||
@ -190,6 +247,8 @@ e2e('should update comment work', async t => {
|
||||
input: {
|
||||
workspaceId: workspace.id,
|
||||
docId,
|
||||
docMode: DocMode.page,
|
||||
docTitle: 'test',
|
||||
content: {
|
||||
type: 'paragraph',
|
||||
content: [{ type: 'text', text: 'test' }],
|
||||
@ -225,6 +284,8 @@ e2e('should update comment failed by another user', async t => {
|
||||
input: {
|
||||
workspaceId: workspace.id,
|
||||
docId,
|
||||
docMode: DocMode.page,
|
||||
docTitle: 'test',
|
||||
content: {
|
||||
type: 'paragraph',
|
||||
content: [{ type: 'text', text: 'test' }],
|
||||
@ -286,6 +347,8 @@ e2e('should resolve comment work', async t => {
|
||||
input: {
|
||||
workspaceId: workspace.id,
|
||||
docId,
|
||||
docMode: DocMode.page,
|
||||
docTitle: 'test',
|
||||
content: {
|
||||
type: 'paragraph',
|
||||
content: [{ type: 'text', text: 'test' }],
|
||||
@ -350,6 +413,8 @@ e2e('should resolve comment work by doc Commenter himself', async t => {
|
||||
input: {
|
||||
workspaceId: teamWorkspace.id,
|
||||
docId,
|
||||
docMode: DocMode.page,
|
||||
docTitle: 'test',
|
||||
content: {
|
||||
type: 'paragraph',
|
||||
content: [{ type: 'text', text: 'test' }],
|
||||
@ -387,6 +452,8 @@ e2e('should resolve comment failed by doc Reader user', async t => {
|
||||
input: {
|
||||
workspaceId: teamWorkspace.id,
|
||||
docId,
|
||||
docMode: DocMode.page,
|
||||
docTitle: 'test',
|
||||
content: {
|
||||
type: 'paragraph',
|
||||
content: [{ type: 'text', text: 'test' }],
|
||||
@ -441,6 +508,8 @@ e2e('should delete comment work', async t => {
|
||||
input: {
|
||||
workspaceId: workspace.id,
|
||||
docId,
|
||||
docMode: DocMode.page,
|
||||
docTitle: 'test',
|
||||
content: {
|
||||
type: 'paragraph',
|
||||
content: [{ type: 'text', text: 'test' }],
|
||||
@ -473,6 +542,8 @@ e2e('should create reply work', async t => {
|
||||
input: {
|
||||
workspaceId: workspace.id,
|
||||
docId,
|
||||
docMode: DocMode.page,
|
||||
docTitle: 'test',
|
||||
content: {
|
||||
type: 'paragraph',
|
||||
content: [{ type: 'text', text: 'test' }],
|
||||
@ -486,6 +557,8 @@ e2e('should create reply work', async t => {
|
||||
variables: {
|
||||
input: {
|
||||
commentId: createResult.createComment.id,
|
||||
docMode: DocMode.page,
|
||||
docTitle: 'test',
|
||||
content: {
|
||||
type: 'paragraph',
|
||||
content: [{ type: 'text', text: 'test' }],
|
||||
@ -498,6 +571,122 @@ e2e('should create reply work', async t => {
|
||||
t.is(result.createReply.commentId, createResult.createComment.id);
|
||||
});
|
||||
|
||||
e2e('should create reply with mentions work', async t => {
|
||||
const docId = randomUUID();
|
||||
await app.create(Mockers.DocUser, {
|
||||
workspaceId: teamWorkspace.id,
|
||||
docId,
|
||||
userId: member.id,
|
||||
type: DocRole.Owner,
|
||||
});
|
||||
|
||||
await app.login(member);
|
||||
const createResult = await app.gql({
|
||||
query: createCommentMutation,
|
||||
variables: {
|
||||
input: {
|
||||
workspaceId: teamWorkspace.id,
|
||||
docId,
|
||||
docMode: DocMode.page,
|
||||
docTitle: 'test',
|
||||
content: {
|
||||
type: 'paragraph',
|
||||
content: [{ type: 'text', text: 'test' }],
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const count = app.queue.count('notification.sendComment');
|
||||
const result = await app.gql({
|
||||
query: createReplyMutation,
|
||||
variables: {
|
||||
input: {
|
||||
commentId: createResult.createComment.id,
|
||||
docMode: DocMode.page,
|
||||
docTitle: 'test',
|
||||
content: {
|
||||
type: 'paragraph',
|
||||
content: [{ type: 'text', text: 'test' }],
|
||||
},
|
||||
mentions: [
|
||||
// send
|
||||
owner.id,
|
||||
// ignore doc owner himself
|
||||
member.id,
|
||||
// ignore not workspace member
|
||||
other.id,
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
t.truthy(result.createReply.id);
|
||||
t.is(result.createReply.commentId, createResult.createComment.id);
|
||||
// only send one notification to owner
|
||||
t.is(app.queue.count('notification.sendComment'), count + 1);
|
||||
const notification = app.queue.last('notification.sendComment');
|
||||
t.is(notification.name, 'notification.sendComment');
|
||||
t.is(notification.payload.userId, owner.id);
|
||||
t.is(notification.payload.body.replyId, result.createReply.id);
|
||||
t.is(notification.payload.isMention, true);
|
||||
});
|
||||
|
||||
e2e(
|
||||
'should create reply and send comment notification to doc owner',
|
||||
async t => {
|
||||
const docId = randomUUID();
|
||||
await app.create(Mockers.DocUser, {
|
||||
workspaceId: teamWorkspace.id,
|
||||
docId,
|
||||
userId: member.id,
|
||||
type: DocRole.Owner,
|
||||
});
|
||||
|
||||
await app.login(owner);
|
||||
const createResult = await app.gql({
|
||||
query: createCommentMutation,
|
||||
variables: {
|
||||
input: {
|
||||
workspaceId: teamWorkspace.id,
|
||||
docId,
|
||||
docMode: DocMode.page,
|
||||
docTitle: 'test',
|
||||
content: {
|
||||
type: 'paragraph',
|
||||
content: [{ type: 'text', text: 'test' }],
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const count = app.queue.count('notification.sendComment');
|
||||
const result = await app.gql({
|
||||
query: createReplyMutation,
|
||||
variables: {
|
||||
input: {
|
||||
commentId: createResult.createComment.id,
|
||||
docMode: DocMode.page,
|
||||
docTitle: 'test',
|
||||
content: {
|
||||
type: 'paragraph',
|
||||
content: [{ type: 'text', text: 'test' }],
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
t.truthy(result.createReply.id);
|
||||
t.is(result.createReply.commentId, createResult.createComment.id);
|
||||
t.is(app.queue.count('notification.sendComment'), count + 1);
|
||||
const notification = app.queue.last('notification.sendComment');
|
||||
t.is(notification.name, 'notification.sendComment');
|
||||
t.is(notification.payload.userId, member.id);
|
||||
t.is(notification.payload.body.replyId, result.createReply.id);
|
||||
t.is(notification.payload.isMention, undefined);
|
||||
}
|
||||
);
|
||||
|
||||
e2e('should create reply work when user is Commenter', async t => {
|
||||
const docId = randomUUID();
|
||||
await app.create(Mockers.DocUser, {
|
||||
@ -514,6 +703,8 @@ e2e('should create reply work when user is Commenter', async t => {
|
||||
input: {
|
||||
workspaceId: teamWorkspace.id,
|
||||
docId,
|
||||
docMode: DocMode.page,
|
||||
docTitle: 'test',
|
||||
content: {
|
||||
type: 'paragraph',
|
||||
content: [{ type: 'text', text: 'test' }],
|
||||
@ -527,6 +718,8 @@ e2e('should create reply work when user is Commenter', async t => {
|
||||
variables: {
|
||||
input: {
|
||||
commentId: createResult.createComment.id,
|
||||
docMode: DocMode.page,
|
||||
docTitle: 'test',
|
||||
content: {
|
||||
type: 'paragraph',
|
||||
content: [{ type: 'text', text: 'test' }],
|
||||
@ -547,6 +740,8 @@ e2e('should create reply failed when comment not found', async t => {
|
||||
variables: {
|
||||
input: {
|
||||
commentId: 'not-found',
|
||||
docMode: DocMode.page,
|
||||
docTitle: 'test',
|
||||
content: {
|
||||
type: 'paragraph',
|
||||
content: [{ type: 'text', text: 'test' }],
|
||||
@ -570,6 +765,8 @@ e2e('should create reply failed when user is not member', async t => {
|
||||
input: {
|
||||
workspaceId: workspace.id,
|
||||
docId,
|
||||
docMode: DocMode.page,
|
||||
docTitle: 'test',
|
||||
content: {
|
||||
type: 'paragraph',
|
||||
content: [{ type: 'text', text: 'test' }],
|
||||
@ -585,6 +782,8 @@ e2e('should create reply failed when user is not member', async t => {
|
||||
variables: {
|
||||
input: {
|
||||
commentId: createResult.createComment.id,
|
||||
docMode: DocMode.page,
|
||||
docTitle: 'test',
|
||||
content: {
|
||||
type: 'paragraph',
|
||||
content: [{ type: 'text', text: 'test' }],
|
||||
@ -616,6 +815,8 @@ e2e('should create reply failed when user is Reader', async t => {
|
||||
input: {
|
||||
workspaceId: teamWorkspace.id,
|
||||
docId,
|
||||
docMode: DocMode.page,
|
||||
docTitle: 'test',
|
||||
content: {
|
||||
type: 'paragraph',
|
||||
content: [{ type: 'text', text: 'test' }],
|
||||
@ -631,6 +832,8 @@ e2e('should create reply failed when user is Reader', async t => {
|
||||
variables: {
|
||||
input: {
|
||||
commentId: createResult.createComment.id,
|
||||
docMode: DocMode.page,
|
||||
docTitle: 'test',
|
||||
content: {
|
||||
type: 'paragraph',
|
||||
content: [{ type: 'text', text: 'test' }],
|
||||
@ -655,6 +858,8 @@ e2e('should update reply work when user is reply owner', async t => {
|
||||
input: {
|
||||
workspaceId: workspace.id,
|
||||
docId,
|
||||
docMode: DocMode.page,
|
||||
docTitle: 'test',
|
||||
content: {
|
||||
type: 'paragraph',
|
||||
content: [{ type: 'text', text: 'test' }],
|
||||
@ -668,6 +873,8 @@ e2e('should update reply work when user is reply owner', async t => {
|
||||
variables: {
|
||||
input: {
|
||||
commentId: createResult.createComment.id,
|
||||
docMode: DocMode.page,
|
||||
docTitle: 'test',
|
||||
content: {
|
||||
type: 'paragraph',
|
||||
content: [{ type: 'text', text: 'test' }],
|
||||
@ -702,6 +909,8 @@ e2e('should update reply failed when user is not reply owner', async t => {
|
||||
input: {
|
||||
workspaceId: workspace.id,
|
||||
docId,
|
||||
docMode: DocMode.page,
|
||||
docTitle: 'test',
|
||||
content: {
|
||||
type: 'paragraph',
|
||||
content: [{ type: 'text', text: 'test' }],
|
||||
@ -715,6 +924,8 @@ e2e('should update reply failed when user is not reply owner', async t => {
|
||||
variables: {
|
||||
input: {
|
||||
commentId: createResult.createComment.id,
|
||||
docMode: DocMode.page,
|
||||
docTitle: 'test',
|
||||
content: {
|
||||
type: 'paragraph',
|
||||
content: [{ type: 'text', text: 'test' }],
|
||||
@ -775,6 +986,8 @@ e2e('should delete reply work when user is reply owner', async t => {
|
||||
input: {
|
||||
workspaceId: workspace.id,
|
||||
docId,
|
||||
docMode: DocMode.page,
|
||||
docTitle: 'test',
|
||||
content: {
|
||||
type: 'paragraph',
|
||||
content: [{ type: 'text', text: 'test' }],
|
||||
@ -788,6 +1001,8 @@ e2e('should delete reply work when user is reply owner', async t => {
|
||||
variables: {
|
||||
input: {
|
||||
commentId: createResult.createComment.id,
|
||||
docMode: DocMode.page,
|
||||
docTitle: 'test',
|
||||
content: {
|
||||
type: 'paragraph',
|
||||
content: [{ type: 'text', text: 'test' }],
|
||||
@ -822,6 +1037,8 @@ e2e('should delete reply work when user is doc Editor', async t => {
|
||||
input: {
|
||||
workspaceId: teamWorkspace.id,
|
||||
docId,
|
||||
docMode: DocMode.page,
|
||||
docTitle: 'test',
|
||||
content: {
|
||||
type: 'paragraph',
|
||||
content: [{ type: 'text', text: 'test' }],
|
||||
@ -835,6 +1052,8 @@ e2e('should delete reply work when user is doc Editor', async t => {
|
||||
variables: {
|
||||
input: {
|
||||
commentId: createResult.createComment.id,
|
||||
docMode: DocMode.page,
|
||||
docTitle: 'test',
|
||||
content: {
|
||||
type: 'paragraph',
|
||||
content: [{ type: 'text', text: 'test' }],
|
||||
@ -870,6 +1089,8 @@ e2e('should delete reply work when user is doc Manager', async t => {
|
||||
input: {
|
||||
workspaceId: teamWorkspace.id,
|
||||
docId,
|
||||
docMode: DocMode.page,
|
||||
docTitle: 'test',
|
||||
content: {
|
||||
type: 'paragraph',
|
||||
content: [{ type: 'text', text: 'test' }],
|
||||
@ -883,6 +1104,8 @@ e2e('should delete reply work when user is doc Manager', async t => {
|
||||
variables: {
|
||||
input: {
|
||||
commentId: createResult.createComment.id,
|
||||
docMode: DocMode.page,
|
||||
docTitle: 'test',
|
||||
content: {
|
||||
type: 'paragraph',
|
||||
content: [{ type: 'text', text: 'test' }],
|
||||
@ -933,6 +1156,8 @@ e2e('should list comments and changes work', async t => {
|
||||
input: {
|
||||
workspaceId: workspace.id,
|
||||
docId,
|
||||
docMode: DocMode.page,
|
||||
docTitle: 'test',
|
||||
content: {
|
||||
type: 'paragraph',
|
||||
content: [{ type: 'text', text: 'test 1' }],
|
||||
@ -949,6 +1174,8 @@ e2e('should list comments and changes work', async t => {
|
||||
input: {
|
||||
workspaceId: workspace.id,
|
||||
docId,
|
||||
docMode: DocMode.page,
|
||||
docTitle: 'test',
|
||||
content: {
|
||||
type: 'paragraph',
|
||||
content: [{ type: 'text', text: 'test 2' }],
|
||||
@ -963,6 +1190,8 @@ e2e('should list comments and changes work', async t => {
|
||||
input: {
|
||||
workspaceId: workspace.id,
|
||||
docId,
|
||||
docMode: DocMode.page,
|
||||
docTitle: 'test',
|
||||
content: {
|
||||
type: 'paragraph',
|
||||
content: [{ type: 'text', text: 'test 3' }],
|
||||
@ -976,6 +1205,8 @@ e2e('should list comments and changes work', async t => {
|
||||
variables: {
|
||||
input: {
|
||||
commentId: createResult.createComment.id,
|
||||
docMode: DocMode.page,
|
||||
docTitle: 'test',
|
||||
content: {
|
||||
type: 'paragraph',
|
||||
content: [{ type: 'text', text: 'test 1 reply 1' }],
|
||||
@ -991,6 +1222,8 @@ e2e('should list comments and changes work', async t => {
|
||||
variables: {
|
||||
input: {
|
||||
commentId: createResult.createComment.id,
|
||||
docMode: DocMode.page,
|
||||
docTitle: 'test',
|
||||
content: {
|
||||
type: 'paragraph',
|
||||
content: [{ type: 'text', text: 'test 1 reply 2' }],
|
||||
@ -1062,6 +1295,8 @@ e2e('should list comments and changes work', async t => {
|
||||
variables: {
|
||||
input: {
|
||||
commentId: createResult.createComment.id,
|
||||
docMode: DocMode.page,
|
||||
docTitle: 'test',
|
||||
content: {
|
||||
type: 'paragraph',
|
||||
content: [{ type: 'text', text: 'test 1 reply 3' }],
|
||||
|
@ -13,6 +13,7 @@ import {
|
||||
CommentAttachmentQuotaExceeded,
|
||||
CommentNotFound,
|
||||
type FileUpload,
|
||||
JobQueue,
|
||||
readableToBuffer,
|
||||
ReplyNotFound,
|
||||
} from '../../base';
|
||||
@ -21,6 +22,7 @@ import {
|
||||
paginateWithCustomCursor,
|
||||
PaginationInput,
|
||||
} from '../../base/graphql';
|
||||
import { Comment, DocMode, Models, Reply } from '../../models';
|
||||
import { CurrentUser } from '../auth/session';
|
||||
import { AccessController, DocAction } from '../permission';
|
||||
import { CommentAttachmentStorage } from '../storage';
|
||||
@ -50,7 +52,9 @@ export class CommentResolver {
|
||||
constructor(
|
||||
private readonly service: CommentService,
|
||||
private readonly ac: AccessController,
|
||||
private readonly commentAttachmentStorage: CommentAttachmentStorage
|
||||
private readonly commentAttachmentStorage: CommentAttachmentStorage,
|
||||
private readonly queue: JobQueue,
|
||||
private readonly models: Models
|
||||
) {}
|
||||
|
||||
@Mutation(() => CommentObjectType)
|
||||
@ -64,6 +68,15 @@ export class CommentResolver {
|
||||
...input,
|
||||
userId: me.id,
|
||||
});
|
||||
|
||||
await this.sendCommentNotification(
|
||||
me,
|
||||
comment,
|
||||
input.docTitle,
|
||||
input.docMode,
|
||||
input.mentions
|
||||
);
|
||||
|
||||
return {
|
||||
...comment,
|
||||
user: {
|
||||
@ -142,6 +155,16 @@ export class CommentResolver {
|
||||
...input,
|
||||
userId: me.id,
|
||||
});
|
||||
|
||||
await this.sendCommentNotification(
|
||||
me,
|
||||
comment,
|
||||
input.docTitle,
|
||||
input.docMode,
|
||||
input.mentions,
|
||||
reply
|
||||
);
|
||||
|
||||
return {
|
||||
...reply,
|
||||
user: {
|
||||
@ -338,6 +361,74 @@ export class CommentResolver {
|
||||
return this.commentAttachmentStorage.getUrl(workspaceId, docId, key);
|
||||
}
|
||||
|
||||
private async sendCommentNotification(
|
||||
sender: UserType,
|
||||
comment: Comment,
|
||||
docTitle: string,
|
||||
docMode: DocMode,
|
||||
mentions?: string[],
|
||||
reply?: Reply
|
||||
) {
|
||||
// send comment notification to doc owners
|
||||
const owner = await this.models.docUser.getOwner(
|
||||
comment.workspaceId,
|
||||
comment.docId
|
||||
);
|
||||
if (owner && owner.userId !== sender.id) {
|
||||
await this.queue.add('notification.sendComment', {
|
||||
userId: owner.userId,
|
||||
body: {
|
||||
workspaceId: comment.workspaceId,
|
||||
createdByUserId: sender.id,
|
||||
commentId: comment.id,
|
||||
replyId: reply?.id,
|
||||
doc: {
|
||||
id: comment.docId,
|
||||
title: docTitle,
|
||||
mode: docMode,
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// send comment mention notification to mentioned users
|
||||
if (mentions) {
|
||||
for (const mentionUserId of mentions) {
|
||||
// skip if the mention user is the doc owner
|
||||
if (mentionUserId === owner?.userId || mentionUserId === sender.id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// check if the mention user has Doc.Comments.Read permission
|
||||
const hasPermission = await this.ac
|
||||
.user(mentionUserId)
|
||||
.workspace(comment.workspaceId)
|
||||
.doc(comment.docId)
|
||||
.can('Doc.Comments.Read');
|
||||
|
||||
if (!hasPermission) {
|
||||
continue;
|
||||
}
|
||||
|
||||
await this.queue.add('notification.sendComment', {
|
||||
isMention: true,
|
||||
userId: mentionUserId,
|
||||
body: {
|
||||
workspaceId: comment.workspaceId,
|
||||
createdByUserId: sender.id,
|
||||
commentId: comment.id,
|
||||
replyId: reply?.id,
|
||||
doc: {
|
||||
id: comment.docId,
|
||||
title: docTitle,
|
||||
mode: docMode,
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async assertPermission(
|
||||
me: UserType,
|
||||
item: {
|
||||
|
@ -17,6 +17,7 @@ import {
|
||||
CommentResolve,
|
||||
CommentUpdate,
|
||||
DeletedChangeItem,
|
||||
DocMode,
|
||||
Reply,
|
||||
ReplyCreate,
|
||||
ReplyUpdate,
|
||||
@ -150,8 +151,21 @@ export class CommentCreateInput implements Partial<CommentCreate> {
|
||||
@Field(() => ID)
|
||||
docId!: string;
|
||||
|
||||
@Field(() => String)
|
||||
docTitle!: string;
|
||||
|
||||
@Field(() => DocMode)
|
||||
docMode!: DocMode;
|
||||
|
||||
@Field(() => GraphQLJSONObject)
|
||||
content!: object;
|
||||
|
||||
@Field(() => [String], {
|
||||
nullable: true,
|
||||
description:
|
||||
'The mention user ids, if not provided, the comment will not be mentioned',
|
||||
})
|
||||
mentions?: string[];
|
||||
}
|
||||
|
||||
@InputType()
|
||||
@ -181,6 +195,19 @@ export class ReplyCreateInput implements Partial<ReplyCreate> {
|
||||
|
||||
@Field(() => GraphQLJSONObject)
|
||||
content!: object;
|
||||
|
||||
@Field(() => String)
|
||||
docTitle!: string;
|
||||
|
||||
@Field(() => DocMode)
|
||||
docMode!: DocMode;
|
||||
|
||||
@Field(() => [String], {
|
||||
nullable: true,
|
||||
description:
|
||||
'The mention user ids, if not provided, the comment reply will not be mentioned',
|
||||
})
|
||||
mentions?: string[];
|
||||
}
|
||||
|
||||
@InputType()
|
||||
|
@ -125,6 +125,13 @@ type CommentChangeObjectTypeEdge {
|
||||
input CommentCreateInput {
|
||||
content: JSONObject!
|
||||
docId: ID!
|
||||
docMode: DocMode!
|
||||
docTitle: String!
|
||||
|
||||
"""
|
||||
The mention user ids, if not provided, the comment will not be mentioned
|
||||
"""
|
||||
mentions: [String!]
|
||||
workspaceId: ID!
|
||||
}
|
||||
|
||||
@ -1583,6 +1590,13 @@ input RemoveContextFileInput {
|
||||
input ReplyCreateInput {
|
||||
commentId: ID!
|
||||
content: JSONObject!
|
||||
docMode: DocMode!
|
||||
docTitle: String!
|
||||
|
||||
"""
|
||||
The mention user ids, if not provided, the comment reply will not be mentioned
|
||||
"""
|
||||
mentions: [String!]
|
||||
}
|
||||
|
||||
type ReplyObjectType {
|
||||
|
@ -165,6 +165,10 @@ export interface CommentChangeObjectTypeEdge {
|
||||
export interface CommentCreateInput {
|
||||
content: Scalars['JSONObject']['input'];
|
||||
docId: Scalars['ID']['input'];
|
||||
docMode: DocMode;
|
||||
docTitle: Scalars['String']['input'];
|
||||
/** The mention user ids, if not provided, the comment will not be mentioned */
|
||||
mentions?: InputMaybe<Array<Scalars['String']['input']>>;
|
||||
workspaceId: Scalars['ID']['input'];
|
||||
}
|
||||
|
||||
@ -2172,6 +2176,10 @@ export interface RemoveContextFileInput {
|
||||
export interface ReplyCreateInput {
|
||||
commentId: Scalars['ID']['input'];
|
||||
content: Scalars['JSONObject']['input'];
|
||||
docMode: DocMode;
|
||||
docTitle: Scalars['String']['input'];
|
||||
/** The mention user ids, if not provided, the comment reply will not be mentioned */
|
||||
mentions?: InputMaybe<Array<Scalars['String']['input']>>;
|
||||
}
|
||||
|
||||
export interface ReplyObjectType {
|
||||
|
Loading…
x
Reference in New Issue
Block a user