diff --git a/models/chunter/src/notifications.ts b/models/chunter/src/notifications.ts
index 2c4cd4bd05..cefebd1c50 100644
--- a/models/chunter/src/notifications.ts
+++ b/models/chunter/src/notifications.ts
@@ -129,8 +129,8 @@ export function defineNotifications (builder: Builder): void {
defaultEnabled: false,
group: chunter.ids.ChunterNotificationGroup,
templates: {
- textTemplate: '{body}',
- htmlTemplate: '
{body}
',
+ textTemplate: '{sender} replied to {doc}:\n\n{message}',
+ htmlTemplate: '{sender} replied to {doc}:
{message}
{link}
',
subjectTemplate: '{title}'
}
},
diff --git a/models/notification/src/index.ts b/models/notification/src/index.ts
index 04a2b8233c..aff1814fc6 100644
--- a/models/notification/src/index.ts
+++ b/models/notification/src/index.ts
@@ -556,8 +556,8 @@ export function createModel (builder: Builder): void {
group: notification.ids.NotificationGroup,
defaultEnabled: true,
templates: {
- textTemplate: '{sender} mentioned you in {doc} {message}',
- htmlTemplate: '{sender} mentioned you in {doc}
{message}',
+ textTemplate: '{sender} mentioned you in {doc}: {message}',
+ htmlTemplate: '{sender} mentioned you in {doc}:
{message}
{link}
',
subjectTemplate: 'You were mentioned in {doc}'
}
},
diff --git a/models/server-chunter/src/index.ts b/models/server-chunter/src/index.ts
index 9302dfbf15..b74fa8fa47 100644
--- a/models/server-chunter/src/index.ts
+++ b/models/server-chunter/src/index.ts
@@ -37,6 +37,10 @@ export function createModel (builder: Builder): void {
presenter: serverChunter.function.ChatMessageTextPresenter
})
+ builder.mixin(chunter.class.ChatMessage, core.class.Class, serverNotification.mixin.HTMLPresenter, {
+ presenter: serverChunter.function.ChatMessageTextPresenter
+ })
+
builder.mixin, ObjectDDParticipant>(
chunter.class.ChatMessage,
core.class.Class,
diff --git a/plugins/notification-assets/lang/en.json b/plugins/notification-assets/lang/en.json
index 8f906a9060..741a4a0a22 100644
--- a/plugins/notification-assets/lang/en.json
+++ b/plugins/notification-assets/lang/en.json
@@ -56,6 +56,7 @@
"CommonNotificationCollectionRemoved": "{senderName} removed {collection}",
"Sound": "Sound",
"SoundNotificationsDescription": "Receive sound notifications for events.",
- "NoAccessToObject": "You no longer have access to this object"
+ "NoAccessToObject": "You no longer have access to this object",
+ "ViewIn": "View in {app}"
}
}
diff --git a/plugins/notification-assets/lang/es.json b/plugins/notification-assets/lang/es.json
index eda8de8712..96f4c4c0eb 100644
--- a/plugins/notification-assets/lang/es.json
+++ b/plugins/notification-assets/lang/es.json
@@ -55,6 +55,7 @@
"SoundNotificationsDescription": "Reciba notificaciones de sonido para eventos.",
"CommonNotificationCollectionAdded": "{senderName} añadió {collection}",
"CommonNotificationCollectionRemoved": "{senderName} eliminó {collection}",
- "NoAccessToObject": "Ya no tienes acceso a este objeto"
+ "NoAccessToObject": "Ya no tienes acceso a este objeto",
+ "ViewIn": "Ver en {app}"
}
}
\ No newline at end of file
diff --git a/plugins/notification-assets/lang/fr.json b/plugins/notification-assets/lang/fr.json
index 97cc8e7587..27afae2d5d 100644
--- a/plugins/notification-assets/lang/fr.json
+++ b/plugins/notification-assets/lang/fr.json
@@ -56,6 +56,7 @@
"SoundNotificationsDescription": "Recevez des notifications sonores pour les événements.",
"CommonNotificationCollectionAdded": "{senderName} a ajouté {collection}",
"CommonNotificationCollectionRemoved": "{senderName} a supprimé {collection}",
- "NoAccessToObject": "Vous n'avez plus accès à cet objet"
+ "NoAccessToObject": "Vous n'avez plus accès à cet objet",
+ "ViewIn": "Voir dans {app}"
}
}
\ No newline at end of file
diff --git a/plugins/notification-assets/lang/pt.json b/plugins/notification-assets/lang/pt.json
index 6eda5c6b4b..a9e6901bdd 100644
--- a/plugins/notification-assets/lang/pt.json
+++ b/plugins/notification-assets/lang/pt.json
@@ -55,6 +55,7 @@
"SoundNotificationsDescription": "Receba notificações sonoras para eventos.",
"CommonNotificationCollectionAdded": "{senderName} adicionou {collection}",
"CommonNotificationCollectionRemoved": "{senderName} removeu {collection}",
- "NoAccessToObject": "Você não tem mais acesso a este objeto"
+ "NoAccessToObject": "Você não tem mais acesso a este objeto",
+ "ViewIn": "Ver em {app}"
}
}
\ No newline at end of file
diff --git a/plugins/notification-assets/lang/ru.json b/plugins/notification-assets/lang/ru.json
index ddcd2db164..ada9f03cc5 100644
--- a/plugins/notification-assets/lang/ru.json
+++ b/plugins/notification-assets/lang/ru.json
@@ -56,6 +56,7 @@
"SoundNotificationsDescription": "Получайте звуковые уведомления о событиях.",
"CommonNotificationCollectionAdded": "{senderName} добавил {collection}",
"CommonNotificationCollectionRemoved": "{senderName} удалил {collection}",
- "NoAccessToObject": "У вас больше нет доступа к этому объекту"
+ "NoAccessToObject": "У вас больше нет доступа к этому объекту",
+ "ViewIn": "Посмотреть в {app}"
}
}
diff --git a/plugins/notification-assets/lang/zh.json b/plugins/notification-assets/lang/zh.json
index 43f9d51d1f..dd06de99ee 100644
--- a/plugins/notification-assets/lang/zh.json
+++ b/plugins/notification-assets/lang/zh.json
@@ -56,6 +56,7 @@
"SoundNotificationsDescription": "接收事件的声音通知。",
"CommonNotificationCollectionAdded": "{senderName} 添加了 {collection}",
"CommonNotificationCollectionRemoved": "{senderName} 移除了 {collection}",
- "NoAccessToObject": "您不再可以访问此对象"
+ "NoAccessToObject": "您不再可以访问此对象",
+ "ViewIn": "在 {app} 中查看"
}
}
diff --git a/plugins/notification-resources/src/components/inbox/Inbox.svelte b/plugins/notification-resources/src/components/inbox/Inbox.svelte
index ca8e3624d4..0ddef087c6 100644
--- a/plugins/notification-resources/src/components/inbox/Inbox.svelte
+++ b/plugins/notification-resources/src/components/inbox/Inbox.svelte
@@ -15,7 +15,7 @@
,
diff --git a/server-plugins/chunter-resources/src/index.ts b/server-plugins/chunter-resources/src/index.ts
index 0b1186a6d5..1c1a6f8777 100644
--- a/server-plugins/chunter-resources/src/index.ts
+++ b/server-plugins/chunter-resources/src/index.ts
@@ -53,7 +53,7 @@ import {
getDocCollaborators,
getMixinTx
} from '@hcengineering/server-notification-resources'
-import { markupToText, stripTags } from '@hcengineering/text'
+import { markupToHTML, markupToText, stripTags } from '@hcengineering/text'
import { workbenchId } from '@hcengineering/workbench'
import { NOTIFICATION_BODY_SIZE } from '@hcengineering/server-notification'
@@ -91,6 +91,10 @@ export async function ChatMessageTextPresenter (doc: ChatMessage): Promise {
+ return markupToHTML(doc.message)
+}
+
/**
* @public
*/
@@ -580,6 +584,7 @@ export default async () => ({
ChannelTextPresenter: channelTextPresenter,
ChunterNotificationContentProvider: getChunterNotificationContent,
ChatMessageTextPresenter,
+ ChatMessageHtmlPresenter,
JoinChannelTypeMatch
}
})
diff --git a/server-plugins/chunter/src/index.ts b/server-plugins/chunter/src/index.ts
index d32a731e4f..dc92deda3d 100644
--- a/server-plugins/chunter/src/index.ts
+++ b/server-plugins/chunter/src/index.ts
@@ -40,6 +40,7 @@ export default plugin(serverChunterId, {
ChannelTextPresenter: '' as Resource,
ChunterNotificationContentProvider: '' as Resource,
ChatMessageTextPresenter: '' as Resource,
+ ChatMessageHtmlPresenter: '' as Resource,
JoinChannelTypeMatch: '' as TypeMatchFunc
}
})
diff --git a/server-plugins/gmail-resources/package.json b/server-plugins/gmail-resources/package.json
index f885922d2b..888a13c03c 100644
--- a/server-plugins/gmail-resources/package.json
+++ b/server-plugins/gmail-resources/package.json
@@ -37,13 +37,15 @@
"@types/jest": "^29.5.5"
},
"dependencies": {
+ "@hcengineering/activity": "^0.6.0",
+ "@hcengineering/contact": "^0.6.24",
"@hcengineering/core": "^0.6.32",
+ "@hcengineering/gmail": "^0.6.22",
+ "@hcengineering/notification": "^0.6.23",
"@hcengineering/platform": "^0.6.11",
"@hcengineering/server-core": "^0.6.1",
"@hcengineering/server-notification": "^0.6.1",
"@hcengineering/server-notification-resources": "^0.6.0",
- "@hcengineering/notification": "^0.6.23",
- "@hcengineering/contact": "^0.6.24",
- "@hcengineering/gmail": "^0.6.22"
+ "@hcengineering/text": "^0.6.5"
}
}
diff --git a/server-plugins/gmail-resources/src/index.ts b/server-plugins/gmail-resources/src/index.ts
index 732bfdb325..516e0c3d55 100644
--- a/server-plugins/gmail-resources/src/index.ts
+++ b/server-plugins/gmail-resources/src/index.ts
@@ -39,6 +39,7 @@ import serverNotification, {
} from '@hcengineering/server-notification'
import { getContentByTemplate } from '@hcengineering/server-notification-resources'
import { getMetadata } from '@hcengineering/platform'
+import { ActivityMessage } from '@hcengineering/activity'
/**
* @public
@@ -134,7 +135,8 @@ async function notifyByEmail (
doc: Doc | undefined,
sender: SenderInfo,
receiver: ReceiverInfo,
- data: InboxNotification
+ data: InboxNotification,
+ message?: ActivityMessage
): Promise {
const account = receiver.account
@@ -145,8 +147,7 @@ async function notifyByEmail (
const senderPerson = sender.person
const senderName = senderPerson !== undefined ? formatName(senderPerson.name, control.branding?.lastNameFirst) : ''
- const content = await getContentByTemplate(doc, senderName, type, control, '', data)
-
+ const content = await getContentByTemplate(doc, senderName, type, control, '', data, message)
if (content !== undefined) {
await sendEmailNotification(control.ctx, content.text, content.html, content.subject, account.email)
}
@@ -158,7 +159,8 @@ const SendEmailNotifications: NotificationProviderFunc = async (
object: Doc,
data: InboxNotification,
receiver: ReceiverInfo,
- sender: SenderInfo
+ sender: SenderInfo,
+ message?: ActivityMessage
): Promise => {
if (types.length === 0) {
return []
@@ -169,7 +171,7 @@ const SendEmailNotifications: NotificationProviderFunc = async (
}
for (const type of types) {
- await notifyByEmail(control, type._id, object, sender, receiver, data)
+ await notifyByEmail(control, type._id, object, sender, receiver, data, message)
}
return []
diff --git a/server-plugins/notification-resources/src/index.ts b/server-plugins/notification-resources/src/index.ts
index b48118131d..b51314d057 100644
--- a/server-plugins/notification-resources/src/index.ts
+++ b/server-plugins/notification-resources/src/index.ts
@@ -80,7 +80,7 @@ import serverNotification, {
SenderInfo
} from '@hcengineering/server-notification'
import serverView from '@hcengineering/server-view'
-import { stripTags } from '@hcengineering/text'
+import { markupToText, stripTags } from '@hcengineering/text'
import { encodeObjectURI } from '@hcengineering/view'
import { workbenchId } from '@hcengineering/workbench'
import webpush, { WebPushError } from 'web-push'
@@ -91,6 +91,7 @@ import {
createPushCollaboratorsTx,
getHTMLPresenter,
getNotificationContent,
+ getNotificationLink,
getTextPresenter,
getUsersInfo,
isAllowed,
@@ -98,6 +99,7 @@ import {
isShouldNotifyTx,
isUserEmployeeInFieldValue,
isUserInFieldValue,
+ messageToMarkup,
replaceAll,
toReceiverInfo,
updateNotifyContextsSpace
@@ -212,7 +214,8 @@ export async function getContentByTemplate (
type: Ref,
control: TriggerControl,
data: string,
- notificationData?: InboxNotification
+ notificationData?: InboxNotification,
+ message?: ActivityMessage
): Promise {
if (doc === undefined) return
const notificationType = control.modelDb.getObject(type)
@@ -220,11 +223,24 @@ export async function getContentByTemplate (
const textPart = await getTextPart(doc, control)
if (textPart === undefined) return
- const params =
+ const params: Record =
notificationData !== undefined
? await getTranslatedNotificationContent(notificationData, notificationData._class, control)
: {}
+ if (message !== undefined) {
+ const markup = await messageToMarkup(control, message)
+ params.message = markup !== undefined ? markupToText(markup) : params.message ?? ''
+ } else if (params.message === undefined) {
+ params.message = params.body ?? ''
+ }
+
+ const link = await getNotificationLink(control, doc, message?._id)
+ const app = control.branding?.title ?? 'Huly'
+ const linkText = await translate(notification.string.ViewIn, { app })
+
+ params.link = `${linkText}`
+
const text = fillTemplate(notificationType.templates.textTemplate, sender, textPart, data, params)
const htmlPart = await getHtmlPart(doc, control)
const html = fillTemplate(notificationType.templates.htmlTemplate, sender, htmlPart ?? textPart, data, params)
@@ -838,16 +854,24 @@ export async function createCollabDocInfo (
return res
}
- const notifyContexts = await control.findAllCtx(ctx, notification.class.DocNotifyContext, { objectId: object._id })
-
- await updateContextsTimestamp(notifyContexts, originTx.modifiedOn, control, originTx.modifiedBy)
- await removeContexts(notifyContexts, unsubscribe, control)
-
const docMessages = activityMessages.filter((message) => message.attachedTo === object._id)
+
if (docMessages.length === 0) {
+ if (unsubscribe.length > 0) {
+ const notifyContexts = await control.findAllCtx(ctx, notification.class.DocNotifyContext, {
+ objectId: object._id,
+ user: { $in: unsubscribe }
+ })
+ await removeContexts(notifyContexts, unsubscribe, control)
+ }
+
return res
}
+ const notifyContexts = await control.findAllCtx(ctx, notification.class.DocNotifyContext, { objectId: object._id })
+ await removeContexts(notifyContexts, unsubscribe, control)
+ await updateContextsTimestamp(notifyContexts, originTx.modifiedOn, control, originTx.modifiedBy)
+
const targets = new Set(collaborators)
// user is not collaborator of himself, but we should notify user of changes related to users account (mentions, comments etc)
diff --git a/server-plugins/notification-resources/src/utils.ts b/server-plugins/notification-resources/src/utils.ts
index 1fb631288e..aefe9df66f 100644
--- a/server-plugins/notification-resources/src/utils.ts
+++ b/server-plugins/notification-resources/src/utils.ts
@@ -55,10 +55,11 @@ import serverNotification, {
SenderInfo,
TextPresenter
} from '@hcengineering/server-notification'
-import { ActivityMessage, DocUpdateMessage } from '@hcengineering/activity'
+import activity, { ActivityMessage, DocUpdateMessage } from '@hcengineering/activity'
import serverView from '@hcengineering/server-view'
import { workbenchId } from '@hcengineering/workbench'
import { encodeObjectURI } from '@hcengineering/view'
+import chunter, { ChatMessage } from '@hcengineering/chunter'
import { NotifyResult } from './types'
@@ -568,11 +569,45 @@ export async function getNotificationLink (
id = await encodeFn(doc, control)
}
+ let thread: string | undefined
+
+ if (control.hierarchy.isDerived(doc._class, activity.class.ActivityMessage)) {
+ const id = (doc as ActivityMessage)._id
+
+ if (message === undefined) {
+ message = id
+ } else {
+ thread = id
+ }
+ }
+
const front = control.branding?.front ?? getMetadata(serverCore.metadata.FrontUrl) ?? ''
- const path = [workbenchId, 'platform', notificationId, encodeObjectURI(id, doc._class)]
+ const path = [workbenchId, control.workspace.workspaceUrl, notificationId, encodeObjectURI(id, doc._class), thread]
+ .filter((x): x is string => x !== undefined)
.map((p) => encodeURIComponent(p))
.join('/')
+
const link = concatLink(front, path)
return message !== undefined ? `${link}?message=${message}` : link
}
+
+export async function messageToMarkup (control: TriggerControl, message: ActivityMessage): Promise {
+ const { hierarchy } = control
+ if (hierarchy.isDerived(message._class, chunter.class.ChatMessage)) {
+ const chatMessage = message as ChatMessage
+ return chatMessage.message
+ } else {
+ const resource = getTextPresenter(message._class, control.hierarchy)
+
+ if (resource !== undefined) {
+ const fn = await getResource(resource.presenter)
+ const textData = await fn(message, control)
+ if (textData !== undefined && textData !== '') {
+ return textData
+ }
+ }
+ }
+
+ return undefined
+}