mirror of
https://github.com/hcengineering/platform.git
synced 2025-04-13 19:58:09 +00:00
Fix multiple mention notifications on edit doc (#5460)
Signed-off-by: Kristina Fefelova <kristin.fefelova@gmail.com>
This commit is contained in:
parent
e1c9523d4d
commit
109985333f
@ -259,6 +259,12 @@ export class TReplyProvider extends TDoc implements ReplyProvider {
|
||||
function!: Resource<(message: ActivityMessage) => Promise<void>>
|
||||
}
|
||||
|
||||
@Model(activity.class.UserMentionInfo, core.class.AttachedDoc, DOMAIN_ACTIVITY)
|
||||
export class TUserMentionInfo extends TAttachedDoc {
|
||||
user!: Ref<Person>
|
||||
content!: string
|
||||
}
|
||||
|
||||
export function createModel (builder: Builder): void {
|
||||
builder.createModel(
|
||||
TTxViewlet,
|
||||
@ -276,7 +282,8 @@ export function createModel (builder: Builder): void {
|
||||
TIgnoreActivity,
|
||||
TActivityReference,
|
||||
TActivityMessagePreview,
|
||||
TReplyProvider
|
||||
TReplyProvider,
|
||||
TUserMentionInfo
|
||||
)
|
||||
|
||||
builder.mixin(activity.class.DocUpdateMessage, core.class.Class, view.mixin.ObjectPresenter, {
|
||||
|
@ -302,6 +302,11 @@ export interface ReplyProvider extends Doc {
|
||||
function: Resource<(message: ActivityMessage) => Promise<void>>
|
||||
}
|
||||
|
||||
export interface UserMentionInfo extends AttachedDoc {
|
||||
user: Ref<Person>
|
||||
content: string
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
@ -328,7 +333,8 @@ export default plugin(activityId, {
|
||||
Reaction: '' as Ref<Class<Reaction>>,
|
||||
SavedMessage: '' as Ref<Class<SavedMessage>>,
|
||||
ActivityReference: '' as Ref<Class<ActivityReference>>,
|
||||
ReplyProvider: '' as Ref<Class<ReplyProvider>>
|
||||
ReplyProvider: '' as Ref<Class<ReplyProvider>>,
|
||||
UserMentionInfo: '' as Ref<Class<UserMentionInfo>>
|
||||
},
|
||||
icon: {
|
||||
Activity: '' as Asset,
|
||||
|
@ -36,17 +36,35 @@ import core, {
|
||||
Type
|
||||
} from '@hcengineering/core'
|
||||
import notification, { MentionInboxNotification } from '@hcengineering/notification'
|
||||
import { extractReferences, markupToPmNode, pmNodeToMarkup, yDocContentToNodes } from '@hcengineering/text'
|
||||
import {
|
||||
extractReferences,
|
||||
markupToPmNode,
|
||||
pmNodeToMarkup,
|
||||
yDocContentToNodes,
|
||||
areEqualJson
|
||||
} from '@hcengineering/text'
|
||||
import { StorageAdapter, TriggerControl } from '@hcengineering/server-core'
|
||||
import activity, { ActivityMessage, ActivityReference } from '@hcengineering/activity'
|
||||
import activity, { ActivityMessage, ActivityReference, UserMentionInfo } from '@hcengineering/activity'
|
||||
import contact, { Person, PersonAccount } from '@hcengineering/contact'
|
||||
import {
|
||||
getPushCollaboratorTx,
|
||||
getCommonNotificationTxes,
|
||||
getPushCollaboratorTx,
|
||||
isMessageAlreadyNotified,
|
||||
shouldNotifyCommon
|
||||
} from '@hcengineering/server-notification-resources'
|
||||
|
||||
async function getPersonAccount (person: Ref<Person>, control: TriggerControl): Promise<PersonAccount | undefined> {
|
||||
return (
|
||||
await control.modelDb.findAll(
|
||||
contact.class.PersonAccount,
|
||||
{
|
||||
person
|
||||
},
|
||||
{ limit: 1 }
|
||||
)
|
||||
)[0]
|
||||
}
|
||||
|
||||
export function isDocMentioned (doc: Ref<Doc>, content: string | Buffer): boolean {
|
||||
const references = []
|
||||
|
||||
@ -76,15 +94,8 @@ export async function getPersonNotificationTxes (
|
||||
space: Ref<Space>,
|
||||
originTx: TxCUD<Doc>
|
||||
): Promise<Tx[]> {
|
||||
const receiver = (
|
||||
await control.modelDb.findAll(
|
||||
contact.class.PersonAccount,
|
||||
{
|
||||
person: reference.attachedTo as Ref<Person>
|
||||
},
|
||||
{ limit: 1 }
|
||||
)
|
||||
)[0]
|
||||
const receiverPerson = reference.attachedTo as Ref<Person>
|
||||
const receiver = await getPersonAccount(receiverPerson, control)
|
||||
|
||||
if (receiver === undefined) {
|
||||
return []
|
||||
@ -111,6 +122,31 @@ export async function getPersonNotificationTxes (
|
||||
return res
|
||||
}
|
||||
|
||||
const info = (
|
||||
await control.findAll<UserMentionInfo>(activity.class.UserMentionInfo, {
|
||||
user: receiverPerson,
|
||||
attachedTo: reference.attachedDocId
|
||||
})
|
||||
)[0]
|
||||
|
||||
if (info === undefined) {
|
||||
res.push(
|
||||
control.txFactory.createTxCreateDoc(activity.class.UserMentionInfo, space, {
|
||||
attachedTo: reference.attachedDocId ?? reference.srcDocId,
|
||||
attachedToClass: reference.attachedDocClass ?? reference.srcDocClass,
|
||||
user: receiverPerson,
|
||||
content: reference.message,
|
||||
collection: 'mentions'
|
||||
})
|
||||
)
|
||||
} else {
|
||||
res.push(
|
||||
control.txFactory.createTxUpdateDoc(info._class, info.space, info._id, {
|
||||
content: reference.message
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
const data: Partial<Data<MentionInboxNotification>> = {
|
||||
header: activity.string.MentionedYouIn,
|
||||
messageHtml: reference.message,
|
||||
@ -274,7 +310,7 @@ async function getCreateReferencesTxes (
|
||||
? (srcDocId as Ref<Space>)
|
||||
: srcDocSpace
|
||||
|
||||
return await getReferencesTxes(control, txFactory, refs, refSpace, [], originTx)
|
||||
return await getReferencesTxes(control, txFactory, refs, refSpace, [], [], originTx)
|
||||
}
|
||||
|
||||
async function getUpdateReferencesTxes (
|
||||
@ -330,12 +366,15 @@ async function getUpdateReferencesTxes (
|
||||
attachedDocId,
|
||||
collection: 'references'
|
||||
})
|
||||
const userMentions = await control.findAll(activity.class.UserMentionInfo, {
|
||||
attachedTo: attachedDocId
|
||||
})
|
||||
|
||||
const refSpace: Ref<Space> = control.hierarchy.isDerived(srcDocClass, core.class.Space)
|
||||
? (srcDocId as Ref<Space>)
|
||||
: srcDocSpace
|
||||
|
||||
return await getReferencesTxes(control, txFactory, references, refSpace, current, originTx)
|
||||
return await getReferencesTxes(control, txFactory, references, refSpace, current, userMentions, originTx)
|
||||
}
|
||||
|
||||
return []
|
||||
@ -402,6 +441,7 @@ async function getReferencesTxes (
|
||||
references: Data<ActivityReference>[],
|
||||
space: Ref<Space>,
|
||||
current: ActivityReference[],
|
||||
mentions: UserMentionInfo[],
|
||||
originTx: TxCUD<Doc>
|
||||
): Promise<Tx[]> {
|
||||
const txes: Tx[] = []
|
||||
@ -428,6 +468,24 @@ async function getReferencesTxes (
|
||||
}
|
||||
}
|
||||
|
||||
for (const mention of mentions) {
|
||||
const refIndex = references.findIndex(
|
||||
(r) => mention.user === r.attachedTo && mention.attachedTo === r.attachedDocId
|
||||
)
|
||||
|
||||
const ref = references[refIndex]
|
||||
|
||||
if (refIndex !== -1) {
|
||||
const alreadyProcessed = areEqualJson(JSON.parse(mention.content), JSON.parse(ref.message))
|
||||
|
||||
if (alreadyProcessed) {
|
||||
references.splice(refIndex, 1)
|
||||
}
|
||||
} else {
|
||||
txes.push(txFactory.createTxRemoveDoc(mention._class, mention.space, mention._id))
|
||||
}
|
||||
}
|
||||
|
||||
// Add missing references
|
||||
for (const ref of references) {
|
||||
txes.push(...(await createReferenceTxes(control, txFactory, ref, space, originTx)))
|
||||
@ -447,11 +505,28 @@ async function getRemoveActivityReferenceTxes (
|
||||
collection: 'references'
|
||||
})
|
||||
|
||||
const mentions = await control.findAll(activity.class.UserMentionInfo, {
|
||||
attachedTo: removedDocId
|
||||
})
|
||||
|
||||
for (const ref of refs) {
|
||||
const removeTx = txFactory.createTxRemoveDoc(ref._class, ref.space, ref._id)
|
||||
txes.push(txFactory.createTxCollectionCUD(ref.attachedToClass, ref.attachedTo, ref.space, ref.collection, removeTx))
|
||||
}
|
||||
|
||||
for (const mention of mentions) {
|
||||
const removeTx = txFactory.createTxRemoveDoc(mention._class, mention.space, mention._id)
|
||||
txes.push(
|
||||
txFactory.createTxCollectionCUD(
|
||||
mention.attachedToClass,
|
||||
mention.attachedTo,
|
||||
mention.space,
|
||||
mention.collection,
|
||||
removeTx
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
return txes
|
||||
}
|
||||
|
||||
@ -559,7 +634,7 @@ async function ActivityReferenceRemove (tx: Tx, control: TriggerControl): Promis
|
||||
let hasMarkdown = false
|
||||
|
||||
for (const attr of attributes.values()) {
|
||||
if (isMarkupType(attr.type._class)) {
|
||||
if (isMarkupType(attr.type._class) || isCollaborativeType(attr.type._class)) {
|
||||
hasMarkdown = true
|
||||
break
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user