notify user that is mentioned in document
pull/139/head
fantasticit 2022-07-29 22:54:50 +08:00
parent 52e8f637c9
commit 837643b641
6 changed files with 83 additions and 5 deletions

View File

@ -1,4 +1,5 @@
import type { IPagination, IUser } from '@think/domains';
import { IAuth, IUser, OrganizationApiDefinition } from '@think/domains';
import Router from 'next/router';
import { HttpClient } from './http-client';
@ -9,3 +10,14 @@ export const register = (data: Partial<IUser>): Promise<IUser> => {
export const getUsers = (): Promise<IUser[]> => {
return HttpClient.get('/user');
};
export const getMentionUser = (): Promise<{ data: Array<{ auth: IAuth; user: IUser }>; total: number }> => {
const { organizationId } = Router.query;
return HttpClient.request({
method: OrganizationApiDefinition.getMembers.method,
url: OrganizationApiDefinition.getMembers.client(organizationId as string),
params: {
pageSize: 10000,
},
});
};

View File

@ -1,14 +1,14 @@
import BulitInMention from '@tiptap/extension-mention';
import { ReactRenderer } from '@tiptap/react';
import { getUsers } from 'services/user';
import { getMentionUser } from 'services/user';
import tippy from 'tippy.js';
import { MentionList } from 'tiptap/core/wrappers/mention-list';
import { getDatasetAttribute } from 'tiptap/prose-utils';
const suggestion = {
items: async ({ query }) => {
const res = await getUsers();
const data = res.map((item) => item.name);
const res = await getMentionUser();
const data = (res.data || []).map((item) => item.user.name);
return data.filter((item) => item.toLowerCase().startsWith(query.toLowerCase()));
},

View File

@ -46,6 +46,7 @@ export const CollaborationEditor = forwardRef((props: ICollaborationEditorProps,
targetId: documentId,
userId: user && user.id,
docType: type,
editable,
},
maxAttempts: 1,
onAwarenessUpdate: throttle(({ states }) => {
@ -67,7 +68,7 @@ export const CollaborationEditor = forwardRef((props: ICollaborationEditorProps,
setStatus(status);
},
} as any);
}, [documentId, user, type, onAwarenessUpdate, toggleLoading]);
}, [documentId, user, type, editable, onAwarenessUpdate, toggleLoading]);
useImperativeHandle(
ref,

View File

@ -10,6 +10,25 @@ import { DocumentStatus, IUser } from '@think/domains';
import * as lodash from 'lodash';
import * as Y from 'yjs';
export const findMentions = (content) => {
const queue = [content];
const res = [];
while (queue.length) {
const node = queue.shift();
if (node.type === 'mention') {
res.push(node.attrs.id);
}
if (node.content && node.content.length) {
queue.push(...node.content);
}
}
return res;
};
@Injectable()
export class CollaborationService {
server: typeof Server;
@ -244,6 +263,7 @@ export class CollaborationService {
const targetId = requestParameters.get('targetId');
const docType = requestParameters.get('docType');
const userId = requestParameters.get('userId');
const editable = requestParameters.get('editable');
if (docType === 'document') {
const data = await this.documentService.findById(targetId);
@ -252,6 +272,14 @@ export class CollaborationService {
title: '未命名文档',
});
}
if (editable) {
const content = data.content;
const json = JSON.parse(content).default;
const mentionUsers = findMentions(json);
this.documentService.notifyMentionUsers(targetId, mentionUsers);
}
return;
}

View File

@ -727,4 +727,33 @@ export class DocumentService {
return data;
}
/**
* @
* @param documentId
* @param mentionUsers
* @returns
*/
public async notifyMentionUsers(documentId, mentionUsers) {
const doc = await this.documentRepo.findOne(documentId);
if (!doc) return;
await Promise.all(
mentionUsers
.map(async (userName) => {
const user = await this.userService.findOne({ name: userName });
if (!user) return null;
return await this.messageService.notify(user.id, {
title: `文档「${doc.title}」提及了您`,
message: `文档「${doc.title}」提及了您,快去看看吧!`,
url: buildMessageURL('toDocument')({
organizationId: doc.organizationId,
wikiId: doc.wikiId,
documentId: doc.id,
}),
});
})
.filter(Boolean)
);
}
}

View File

@ -19,6 +19,14 @@ export class MessageService {
*/
async notify(userId: IUser['id'], msg) {
const data = { userId, ...msg };
const mayBeNotified = await this.messageRepo.findOne(data);
if (mayBeNotified) {
if (!mayBeNotified.read) {
return;
}
}
const res = await this.messageRepo.create(data);
const ret = await this.messageRepo.save(res);
return ret;