UBER-845: Add NotificationPresenter to send rich text notifications (#3729)

Signed-off-by: Maxim Karmatskikh <mkarmatskih@gmail.com>
This commit is contained in:
Maksim Karmatskikh
2023-09-28 12:08:00 +07:00
committed by GitHub
parent a3fd97e3b4
commit 1ca9de297a
21 changed files with 368 additions and 47 deletions
+86 -2
View File
@@ -14,6 +14,7 @@
//
import core, {
Account,
AttachedDoc,
concatLink,
Doc,
@@ -29,11 +30,16 @@ import core, {
TxUpdateDoc,
WithLookup
} from '@hcengineering/core'
import { getMetadata } from '@hcengineering/platform'
import { getMetadata, IntlString } from '@hcengineering/platform'
import { Person, PersonAccount } from '@hcengineering/contact'
import serverCore, { TriggerControl } from '@hcengineering/server-core'
import tracker, { Component, Issue, IssueParentInfo, TimeSpendReport, trackerId } from '@hcengineering/tracker'
import { NotificationContent } from '@hcengineering/notification'
import { workbenchId } from '@hcengineering/workbench'
import chunter, { Comment } from '@hcengineering/chunter'
import { stripTags } from '@hcengineering/text'
async function updateSubIssues (
updateTx: TxUpdateDoc<Issue>,
control: TriggerControl,
@@ -69,6 +75,83 @@ export async function issueTextPresenter (doc: Doc, control: TriggerControl): Pr
return issueName
}
function isSamePerson (control: TriggerControl, assignee: Ref<Person>, target: Ref<Account>): boolean {
const targetAccount = control.modelDb.getObject(target) as PersonAccount
return assignee === targetAccount?.person
}
const NOTIFICATION_BODY_SIZE = 50
/**
* @public
*/
export async function getIssueNotificationContent (
doc: Doc,
tx: TxCUD<Doc>,
target: Ref<Account>,
control: TriggerControl
): Promise<NotificationContent> {
const issue = doc as Issue
const issueShortName = await issueTextPresenter(doc, control)
const issueTitle = `${issueShortName}: ${issue.title}`
const title = tracker.string.IssueNotificationTitle
let body = tracker.string.IssueNotificationBody
const intlParams: Record<string, string | number> = {
issueTitle
}
const intlParamsNotLocalized: Record<string, IntlString> = {}
if (tx._class === core.class.TxCollectionCUD) {
const ptx = tx as TxCollectionCUD<Doc, AttachedDoc>
if (ptx.tx._class === core.class.TxCreateDoc) {
if (ptx.tx.objectClass === chunter.class.Comment) {
const createTx = ptx.tx as TxCreateDoc<Comment>
const message = createTx.attributes.message
const plainTextMessage = stripTags(message, NOTIFICATION_BODY_SIZE)
intlParams.message = plainTextMessage
}
} else if (ptx.tx._class === core.class.TxUpdateDoc) {
const updateTx = ptx.tx as TxUpdateDoc<Issue>
if (
updateTx.operations.assignee !== null &&
updateTx.operations.assignee !== undefined &&
isSamePerson(control, updateTx.operations.assignee, target)
) {
body = tracker.string.IssueAssigneedToYou
} else {
const attributes = control.hierarchy.getAllAttributes(doc._class)
for (const attrName in updateTx.operations) {
if (!Object.prototype.hasOwnProperty.call(updateTx.operations, attrName)) {
continue
}
const attr = attributes.get(attrName)
if (attr !== null && attr !== undefined) {
intlParamsNotLocalized.property = attr.label
if (attr.type._class === core.class.TypeString) {
body = tracker.string.IssueNotificationChangedProperty
intlParams.newValue = (issue as any)[attr.name]?.toString()
} else {
body = tracker.string.IssueNotificationChanged
}
}
break
}
}
}
}
return {
title,
body,
intlParams,
intlParamsNotLocalized
}
}
/**
* @public
*/
@@ -157,7 +240,8 @@ export async function OnIssueUpdate (tx: Tx, control: TriggerControl): Promise<T
export default async () => ({
function: {
IssueHTMLPresenter: issueHTMLPresenter,
IssueTextPresenter: issueTextPresenter
IssueTextPresenter: issueTextPresenter,
IssueNotificationContentProvider: getIssueNotificationContent
},
trigger: {
OnIssueUpdate,