mirror of
https://github.com/hcengineering/platform.git
synced 2025-04-21 07:46:24 +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>>
|
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 {
|
export function createModel (builder: Builder): void {
|
||||||
builder.createModel(
|
builder.createModel(
|
||||||
TTxViewlet,
|
TTxViewlet,
|
||||||
@ -276,7 +282,8 @@ export function createModel (builder: Builder): void {
|
|||||||
TIgnoreActivity,
|
TIgnoreActivity,
|
||||||
TActivityReference,
|
TActivityReference,
|
||||||
TActivityMessagePreview,
|
TActivityMessagePreview,
|
||||||
TReplyProvider
|
TReplyProvider,
|
||||||
|
TUserMentionInfo
|
||||||
)
|
)
|
||||||
|
|
||||||
builder.mixin(activity.class.DocUpdateMessage, core.class.Class, view.mixin.ObjectPresenter, {
|
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>>
|
function: Resource<(message: ActivityMessage) => Promise<void>>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface UserMentionInfo extends AttachedDoc {
|
||||||
|
user: Ref<Person>
|
||||||
|
content: string
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
@ -328,7 +333,8 @@ export default plugin(activityId, {
|
|||||||
Reaction: '' as Ref<Class<Reaction>>,
|
Reaction: '' as Ref<Class<Reaction>>,
|
||||||
SavedMessage: '' as Ref<Class<SavedMessage>>,
|
SavedMessage: '' as Ref<Class<SavedMessage>>,
|
||||||
ActivityReference: '' as Ref<Class<ActivityReference>>,
|
ActivityReference: '' as Ref<Class<ActivityReference>>,
|
||||||
ReplyProvider: '' as Ref<Class<ReplyProvider>>
|
ReplyProvider: '' as Ref<Class<ReplyProvider>>,
|
||||||
|
UserMentionInfo: '' as Ref<Class<UserMentionInfo>>
|
||||||
},
|
},
|
||||||
icon: {
|
icon: {
|
||||||
Activity: '' as Asset,
|
Activity: '' as Asset,
|
||||||
|
@ -36,17 +36,35 @@ import core, {
|
|||||||
Type
|
Type
|
||||||
} from '@hcengineering/core'
|
} from '@hcengineering/core'
|
||||||
import notification, { MentionInboxNotification } from '@hcengineering/notification'
|
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 { 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 contact, { Person, PersonAccount } from '@hcengineering/contact'
|
||||||
import {
|
import {
|
||||||
getPushCollaboratorTx,
|
|
||||||
getCommonNotificationTxes,
|
getCommonNotificationTxes,
|
||||||
|
getPushCollaboratorTx,
|
||||||
isMessageAlreadyNotified,
|
isMessageAlreadyNotified,
|
||||||
shouldNotifyCommon
|
shouldNotifyCommon
|
||||||
} from '@hcengineering/server-notification-resources'
|
} 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 {
|
export function isDocMentioned (doc: Ref<Doc>, content: string | Buffer): boolean {
|
||||||
const references = []
|
const references = []
|
||||||
|
|
||||||
@ -76,15 +94,8 @@ export async function getPersonNotificationTxes (
|
|||||||
space: Ref<Space>,
|
space: Ref<Space>,
|
||||||
originTx: TxCUD<Doc>
|
originTx: TxCUD<Doc>
|
||||||
): Promise<Tx[]> {
|
): Promise<Tx[]> {
|
||||||
const receiver = (
|
const receiverPerson = reference.attachedTo as Ref<Person>
|
||||||
await control.modelDb.findAll(
|
const receiver = await getPersonAccount(receiverPerson, control)
|
||||||
contact.class.PersonAccount,
|
|
||||||
{
|
|
||||||
person: reference.attachedTo as Ref<Person>
|
|
||||||
},
|
|
||||||
{ limit: 1 }
|
|
||||||
)
|
|
||||||
)[0]
|
|
||||||
|
|
||||||
if (receiver === undefined) {
|
if (receiver === undefined) {
|
||||||
return []
|
return []
|
||||||
@ -111,6 +122,31 @@ export async function getPersonNotificationTxes (
|
|||||||
return res
|
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>> = {
|
const data: Partial<Data<MentionInboxNotification>> = {
|
||||||
header: activity.string.MentionedYouIn,
|
header: activity.string.MentionedYouIn,
|
||||||
messageHtml: reference.message,
|
messageHtml: reference.message,
|
||||||
@ -274,7 +310,7 @@ async function getCreateReferencesTxes (
|
|||||||
? (srcDocId as Ref<Space>)
|
? (srcDocId as Ref<Space>)
|
||||||
: srcDocSpace
|
: srcDocSpace
|
||||||
|
|
||||||
return await getReferencesTxes(control, txFactory, refs, refSpace, [], originTx)
|
return await getReferencesTxes(control, txFactory, refs, refSpace, [], [], originTx)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getUpdateReferencesTxes (
|
async function getUpdateReferencesTxes (
|
||||||
@ -330,12 +366,15 @@ async function getUpdateReferencesTxes (
|
|||||||
attachedDocId,
|
attachedDocId,
|
||||||
collection: 'references'
|
collection: 'references'
|
||||||
})
|
})
|
||||||
|
const userMentions = await control.findAll(activity.class.UserMentionInfo, {
|
||||||
|
attachedTo: attachedDocId
|
||||||
|
})
|
||||||
|
|
||||||
const refSpace: Ref<Space> = control.hierarchy.isDerived(srcDocClass, core.class.Space)
|
const refSpace: Ref<Space> = control.hierarchy.isDerived(srcDocClass, core.class.Space)
|
||||||
? (srcDocId as Ref<Space>)
|
? (srcDocId as Ref<Space>)
|
||||||
: srcDocSpace
|
: srcDocSpace
|
||||||
|
|
||||||
return await getReferencesTxes(control, txFactory, references, refSpace, current, originTx)
|
return await getReferencesTxes(control, txFactory, references, refSpace, current, userMentions, originTx)
|
||||||
}
|
}
|
||||||
|
|
||||||
return []
|
return []
|
||||||
@ -402,6 +441,7 @@ async function getReferencesTxes (
|
|||||||
references: Data<ActivityReference>[],
|
references: Data<ActivityReference>[],
|
||||||
space: Ref<Space>,
|
space: Ref<Space>,
|
||||||
current: ActivityReference[],
|
current: ActivityReference[],
|
||||||
|
mentions: UserMentionInfo[],
|
||||||
originTx: TxCUD<Doc>
|
originTx: TxCUD<Doc>
|
||||||
): Promise<Tx[]> {
|
): Promise<Tx[]> {
|
||||||
const txes: 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
|
// Add missing references
|
||||||
for (const ref of references) {
|
for (const ref of references) {
|
||||||
txes.push(...(await createReferenceTxes(control, txFactory, ref, space, originTx)))
|
txes.push(...(await createReferenceTxes(control, txFactory, ref, space, originTx)))
|
||||||
@ -447,11 +505,28 @@ async function getRemoveActivityReferenceTxes (
|
|||||||
collection: 'references'
|
collection: 'references'
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const mentions = await control.findAll(activity.class.UserMentionInfo, {
|
||||||
|
attachedTo: removedDocId
|
||||||
|
})
|
||||||
|
|
||||||
for (const ref of refs) {
|
for (const ref of refs) {
|
||||||
const removeTx = txFactory.createTxRemoveDoc(ref._class, ref.space, ref._id)
|
const removeTx = txFactory.createTxRemoveDoc(ref._class, ref.space, ref._id)
|
||||||
txes.push(txFactory.createTxCollectionCUD(ref.attachedToClass, ref.attachedTo, ref.space, ref.collection, removeTx))
|
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
|
return txes
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -559,7 +634,7 @@ async function ActivityReferenceRemove (tx: Tx, control: TriggerControl): Promis
|
|||||||
let hasMarkdown = false
|
let hasMarkdown = false
|
||||||
|
|
||||||
for (const attr of attributes.values()) {
|
for (const attr of attributes.values()) {
|
||||||
if (isMarkupType(attr.type._class)) {
|
if (isMarkupType(attr.type._class) || isCollaborativeType(attr.type._class)) {
|
||||||
hasMarkdown = true
|
hasMarkdown = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user