From 7375e6e5284706038550116bafa1c63be1d5636e Mon Sep 17 00:00:00 2001 From: Simon Larsen Date: Fri, 19 May 2023 14:08:57 +0100 Subject: [PATCH] add annnouncement email --- CommonUI/src/Components/Detail/Detail.tsx | 2 +- ... => StatusPageOwnerAnnouncementPosted.hbs} | 0 Workers/Index.ts | 1 + .../IncidentOwners/SendNotePostedEmail.ts | 2 +- .../SendNotePostedEmail.ts | 2 +- .../SendAnnouncementCreatedEmail.ts | 107 ++++++++++++++++++ 6 files changed, 111 insertions(+), 3 deletions(-) rename Mail/Templates/{StatusPageOwnerAnnouncementCreated.hbs => StatusPageOwnerAnnouncementPosted.hbs} (100%) create mode 100644 Workers/Jobs/StatusPageOwners/SendAnnouncementCreatedEmail.ts diff --git a/CommonUI/src/Components/Detail/Detail.tsx b/CommonUI/src/Components/Detail/Detail.tsx index 509f7aa757d..22136c9184c 100644 --- a/CommonUI/src/Components/Detail/Detail.tsx +++ b/CommonUI/src/Components/Detail/Detail.tsx @@ -78,7 +78,7 @@ const Detail: Function = (props: ComponentProps): ReactElement => { let data: string | ReactElement = ''; if (_.get(props.item, fieldKey)) { - data = _.get(props.item, fieldKey, '') as any || ''; + data = (_.get(props.item, fieldKey, '') as any) || ''; } if (field.fieldType === FieldType.Date) { diff --git a/Mail/Templates/StatusPageOwnerAnnouncementCreated.hbs b/Mail/Templates/StatusPageOwnerAnnouncementPosted.hbs similarity index 100% rename from Mail/Templates/StatusPageOwnerAnnouncementCreated.hbs rename to Mail/Templates/StatusPageOwnerAnnouncementPosted.hbs diff --git a/Workers/Index.ts b/Workers/Index.ts index 90e0696addf..748a1ab700f 100644 --- a/Workers/Index.ts +++ b/Workers/Index.ts @@ -57,6 +57,7 @@ import './Jobs/ScheduledMaintenanceOwners/SendNotePostedEmail'; // Status Page Owners import './Jobs/StatusPageOwners/SendCreatedResourceEmail'; import './Jobs/StatusPageOwners/SendOwnerAddedEmail'; +import './Jobs/StatusPageOwners/SendAnnouncementCreatedEmail'; const APP_NAME: string = 'workers'; diff --git a/Workers/Jobs/IncidentOwners/SendNotePostedEmail.ts b/Workers/Jobs/IncidentOwners/SendNotePostedEmail.ts index 3b08fefebe5..ba2984a403e 100644 --- a/Workers/Jobs/IncidentOwners/SendNotePostedEmail.ts +++ b/Workers/Jobs/IncidentOwners/SendNotePostedEmail.ts @@ -76,7 +76,7 @@ RunCron( } for (const note of privateNotes) { - await IncidentPublicNoteService.updateOneById({ + await IncidentInternalNoteService.updateOneById({ id: note.id!, data: { isOwnerNotified: true, diff --git a/Workers/Jobs/ScheduledMaintenanceOwners/SendNotePostedEmail.ts b/Workers/Jobs/ScheduledMaintenanceOwners/SendNotePostedEmail.ts index 0d9fd1c57c7..611ebfe9df0 100644 --- a/Workers/Jobs/ScheduledMaintenanceOwners/SendNotePostedEmail.ts +++ b/Workers/Jobs/ScheduledMaintenanceOwners/SendNotePostedEmail.ts @@ -76,7 +76,7 @@ RunCron( } for (const note of privateNotes) { - await ScheduledMaintenancePublicNoteService.updateOneById({ + await ScheduledMaintenanceInternalNoteService.updateOneById({ id: note.id!, data: { isOwnerNotified: true, diff --git a/Workers/Jobs/StatusPageOwners/SendAnnouncementCreatedEmail.ts b/Workers/Jobs/StatusPageOwners/SendAnnouncementCreatedEmail.ts new file mode 100644 index 00000000000..24e5f9433dd --- /dev/null +++ b/Workers/Jobs/StatusPageOwners/SendAnnouncementCreatedEmail.ts @@ -0,0 +1,107 @@ +import { EVERY_MINUTE } from 'Common/Utils/CronTime'; +import LIMIT_MAX from 'Common/Types/Database/LimitMax'; +import RunCron from '../../Utils/Cron'; +import MailService from 'CommonServer/Services/MailService'; +import EmailTemplateType from 'Common/Types/Email/EmailTemplateType'; +import logger from 'CommonServer/Utils/Logger'; +import Dictionary from 'Common/Types/Dictionary'; +import StatusPage from 'Model/Models/StatusPage'; +import StatusPageService from 'CommonServer/Services/StatusPageService'; +import User from 'Model/Models/User'; +import ProjectService from 'CommonServer/Services/ProjectService'; +import Markdown from 'CommonServer/Types/Markdown'; +import StatusPageAnnouncement from 'Model/Models/StatusPageAnnouncement'; +import StatusPageAnnouncementService from 'CommonServer/Services/StatusPageAnnouncementService'; + +RunCron( + 'StatusPageOwner:SendAnnouncementCreatedEmail', + { schedule: EVERY_MINUTE, runOnStartup: false }, + async () => { + const announcements: Array = + await StatusPageAnnouncementService.findBy({ + query: { + isOwnerNotified: false, + }, + props: { + isRoot: true, + }, + limit: LIMIT_MAX, + skip: 0, + select: { + _id: true, + title: true, + description: true, + statusPages: true, + }, + populate: { + statusPages: { + _id: true, + name: true, + }, + }, + }); + + for (const announcement of announcements) { + await StatusPageAnnouncementService.updateOneById({ + id: announcement.id!, + data: { + isOwnerNotified: true, + }, + props: { + isRoot: true, + }, + }); + + const statusPages: Array = + announcement.statusPages || []; + + for (const statusPage of statusPages) { + // now find owners. + + let doesResourceHasOwners: boolean = true; + + let owners: Array = await StatusPageService.findOwners( + statusPage.id! + ); + + if (owners.length === 0) { + doesResourceHasOwners = false; + + // find project owners. + owners = await ProjectService.getOwners( + statusPage.projectId! + ); + } + + if (owners.length === 0) { + continue; + } + + const vars: Dictionary = { + statusPageName: statusPage.name!, + announcementTitle: announcement.title!, + announcementDescription: Markdown.convertToHTML( + announcement.description! + ), + }; + + if (doesResourceHasOwners === true) { + vars['isOwner'] = 'true'; + } + + for (const user of owners) { + MailService.sendMail({ + toEmail: user.email!, + templateType: + EmailTemplateType.StatusPageOwnerAnnouncementPosted, + vars: vars, + subject: + 'New announcement posted - ' + announcement.title!, + }).catch((err: Error) => { + logger.error(err); + }); + } + } + } + } +);