From ab6fe37c3e1c3c18b19f1d200245860e3b7a154a Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Thu, 10 Apr 2025 18:38:51 +0200 Subject: [PATCH] refactor(backend): new chat message notification email (#8357) * new chat message notification email - new mail features name in subject and text * fix english version * typo * fix typos * adjust tests --- .../helpers/email/templateBuilder.spec.ts | 16 +++++++++---- .../helpers/email/templateBuilder.ts | 17 +++++++++---- .../helpers/email/templates/chatMessage.html | 8 +++---- .../middleware/helpers/isUserOnline.spec.ts | 24 +++++++++---------- .../src/middleware/helpers/isUserOnline.ts | 6 ++--- .../notifications/notificationsMiddleware.ts | 15 ++++++------ 6 files changed, 49 insertions(+), 37 deletions(-) diff --git a/backend/src/middleware/helpers/email/templateBuilder.spec.ts b/backend/src/middleware/helpers/email/templateBuilder.spec.ts index 48e8b4c99..9dbfca91f 100644 --- a/backend/src/middleware/helpers/email/templateBuilder.spec.ts +++ b/backend/src/middleware/helpers/email/templateBuilder.spec.ts @@ -39,7 +39,12 @@ const resetPasswordTemplateData = () => ({ const chatMessageTemplateData = { email: 'test@example.org', variables: { - name: 'Mr Example', + senderUser: { + name: 'Sender', + }, + recipientUser: { + name: 'Recipient', + }, }, } const wrongAccountTemplateData = () => ({ @@ -174,10 +179,10 @@ describe('templateBuilder', () => { describe('chatMessageTemplate', () => { describe('multi language', () => { it('e-mail is build with all data', () => { - const subject = 'Neue Chatnachricht | New chat message' + const subject = `Neue Chat-Nachricht | New chat message - ${chatMessageTemplateData.variables.senderUser.name}` const actionUrl = new URL('/chat', CONFIG.CLIENT_URI).toString() - const enContent = 'You have received a new chat message.' - const deContent = 'Du hast eine neue Chatnachricht erhalten.' + const enContent = `You have received a new chat message from ${chatMessageTemplateData.variables.senderUser.name}.` + const deContent = `Du hast eine neue Chat-Nachricht von ${chatMessageTemplateData.variables.senderUser.name} erhalten.` testEmailData(null, chatMessageTemplate, chatMessageTemplateData, [ ...textsStandard, { @@ -187,7 +192,8 @@ describe('templateBuilder', () => { }, englishHint, actionUrl, - chatMessageTemplateData.variables.name, + chatMessageTemplateData.variables.senderUser, + chatMessageTemplateData.variables.recipientUser, enContent, deContent, supportUrl, diff --git a/backend/src/middleware/helpers/email/templateBuilder.ts b/backend/src/middleware/helpers/email/templateBuilder.ts index c091bf1f8..bd44716fe 100644 --- a/backend/src/middleware/helpers/email/templateBuilder.ts +++ b/backend/src/middleware/helpers/email/templateBuilder.ts @@ -1,9 +1,9 @@ /* eslint-disable import/no-namespace */ import mustache from 'mustache' -import logosWebapp from '@config//logos' -import metadata from '@config//metadata' import CONFIG from '@config/index' +import logosWebapp from '@config/logos' +import metadata from '@config/metadata' import * as templates from './templates' import * as templatesDE from './templates/de' @@ -73,10 +73,17 @@ export const resetPasswordTemplate = ({ email, variables: { nonce, name } }) => } } -export const chatMessageTemplate = ({ email, variables: { name } }) => { - const subject = 'Neue Chatnachricht | New chat message' +export const chatMessageTemplate = ({ email, variables: { senderUser, recipientUser } }) => { + const subject = `Neue Chat-Nachricht | New chat message - ${senderUser.name}` const actionUrl = new URL('/chat', CONFIG.CLIENT_URI) - const renderParams = { ...defaultParams, englishHint, actionUrl, name, subject } + const renderParams = { + ...defaultParams, + subject, + englishHint, + actionUrl, + senderUser, + recipientUser, + } return { from, diff --git a/backend/src/middleware/helpers/email/templates/chatMessage.html b/backend/src/middleware/helpers/email/templates/chatMessage.html index 0b1bacb08..49fc69bf2 100644 --- a/backend/src/middleware/helpers/email/templates/chatMessage.html +++ b/backend/src/middleware/helpers/email/templates/chatMessage.html @@ -23,8 +23,8 @@ style="padding: 20px; padding-top: 0; font-family: Lato, sans-serif; font-size: 16px; line-height: 22px; color: #555555;">

- Hallo {{ name }}!

-

Du hast eine neue Chatnachricht erhalten.

+ Hallo {{ recipientUser.name }}! +

Du hast eine neue Chat-Nachricht von {{ senderUser.name }} erhalten.

@@ -78,8 +78,8 @@ style="padding: 20px; padding-top: 0; font-family: Lato, sans-serif; font-size: 16px; line-height: 22px; color: #555555;">

- Hello {{ name }}!

-

You have received a new chat message.

+ Hello {{ recipientUser.name }}! +

You have received a new chat message from {{ senderUser.name }}.

diff --git a/backend/src/middleware/helpers/isUserOnline.spec.ts b/backend/src/middleware/helpers/isUserOnline.spec.ts index bf2cb8d17..62ed17f79 100644 --- a/backend/src/middleware/helpers/isUserOnline.spec.ts +++ b/backend/src/middleware/helpers/isUserOnline.spec.ts @@ -5,35 +5,33 @@ let user describe('isUserOnline', () => { beforeEach(() => { user = { - properties: { - lastActiveAt: null, - awaySince: null, - lastOnlineStatus: null, - }, + lastActiveAt: null, + awaySince: null, + lastOnlineStatus: null, } }) describe('user has lastOnlineStatus `online`', () => { it('returns true if he was active within the last 90 seconds', () => { - user.properties.lastOnlineStatus = 'online' - user.properties.lastActiveAt = new Date() + user.lastOnlineStatus = 'online' + user.lastActiveAt = new Date() expect(isUserOnline(user)).toBe(true) }) it('returns false if he was not active within the last 90 seconds', () => { - user.properties.lastOnlineStatus = 'online' - user.properties.lastActiveAt = new Date().getTime() - 90001 + user.lastOnlineStatus = 'online' + user.lastActiveAt = new Date().getTime() - 90001 expect(isUserOnline(user)).toBe(false) }) }) describe('user has lastOnlineStatus `away`', () => { it('returns true if he went away less then 180 seconds ago', () => { - user.properties.lastOnlineStatus = 'away' - user.properties.awaySince = new Date() + user.lastOnlineStatus = 'away' + user.awaySince = new Date() expect(isUserOnline(user)).toBe(true) }) it('returns false if he went away more then 180 seconds ago', () => { - user.properties.lastOnlineStatus = 'away' - user.properties.awaySince = new Date().getTime() - 180001 + user.lastOnlineStatus = 'away' + user.awaySince = new Date().getTime() - 180001 expect(isUserOnline(user)).toBe(false) }) }) diff --git a/backend/src/middleware/helpers/isUserOnline.ts b/backend/src/middleware/helpers/isUserOnline.ts index 679953f81..23ddeb0dc 100644 --- a/backend/src/middleware/helpers/isUserOnline.ts +++ b/backend/src/middleware/helpers/isUserOnline.ts @@ -1,9 +1,9 @@ export const isUserOnline = (user) => { // Is Recipient considered online - const lastActive = new Date(user.properties.lastActiveAt).getTime() - const awaySince = new Date(user.properties.awaySince).getTime() + const lastActive = new Date(user.lastActiveAt).getTime() + const awaySince = new Date(user.awaySince).getTime() const now = new Date().getTime() - const status = user.properties.lastOnlineStatus + const status = user.lastOnlineStatus if ( // online & last active less than 1.5min -> online (status === 'online' && now - lastActive < 90000) || diff --git a/backend/src/middleware/notifications/notificationsMiddleware.ts b/backend/src/middleware/notifications/notificationsMiddleware.ts index faf4fd994..d24ddc8ef 100644 --- a/backend/src/middleware/notifications/notificationsMiddleware.ts +++ b/backend/src/middleware/notifications/notificationsMiddleware.ts @@ -355,12 +355,12 @@ const handleCreateMessage = async (resolve, root, args, context, resolveInfo) => const session = context.driver.session() const messageRecipient = session.readTransaction(async (transaction) => { const messageRecipientCypher = ` - MATCH (currentUser:User { id: $currentUserId })-[:CHATS_IN]->(room:Room { id: $roomId }) + MATCH (senderUser:User { id: $currentUserId })-[:CHATS_IN]->(room:Room { id: $roomId }) MATCH (room)<-[:CHATS_IN]-(recipientUser:User)-[:PRIMARY_EMAIL]->(emailAddress:EmailAddress) WHERE NOT recipientUser.id = $currentUserId - AND NOT (recipientUser)-[:BLOCKED]-(currentUser) + AND NOT (recipientUser)-[:BLOCKED]-(senderUser) AND NOT recipientUser.emailNotificationsChatMessage = false - RETURN recipientUser, emailAddress {.email} + RETURN senderUser {.*}, recipientUser {.*}, emailAddress {.email} ` const txResponse = await transaction.run(messageRecipientCypher, { currentUserId, @@ -368,18 +368,19 @@ const handleCreateMessage = async (resolve, root, args, context, resolveInfo) => }) return { - user: await txResponse.records.map((record) => record.get('recipientUser'))[0], + senderUser: await txResponse.records.map((record) => record.get('senderUser'))[0], + recipientUser: await txResponse.records.map((record) => record.get('recipientUser'))[0], email: await txResponse.records.map((record) => record.get('emailAddress'))[0]?.email, } }) try { // Execute Query - const { user, email } = await messageRecipient + const { senderUser, recipientUser, email } = await messageRecipient // Send EMail if we found a user(not blocked) and he is not considered online - if (user && !isUserOnline(user)) { - void sendMail(chatMessageTemplate({ email, variables: { name: user.properties.name } })) + if (recipientUser && !isUserOnline(recipientUser)) { + void sendMail(chatMessageTemplate({ email, variables: { senderUser, recipientUser } })) } // Return resolver result to client