@oneuptime/common 7.0.3717 → 7.0.3786

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (203) hide show
  1. package/Models/DatabaseModels/Alert.ts +3 -2
  2. package/Models/DatabaseModels/Incident.ts +3 -2
  3. package/Models/DatabaseModels/Index.ts +3 -0
  4. package/Models/DatabaseModels/ProjectUser.ts +335 -0
  5. package/Models/DatabaseModels/ScheduledMaintenance.ts +3 -2
  6. package/Server/API/SlackAPI.ts +65 -97
  7. package/Server/API/UserOnCallLogTimelineAPI.ts +2 -9
  8. package/Server/Infrastructure/Postgres/SchemaMigrations/1740597525803-MigrationName.ts +17 -0
  9. package/Server/Infrastructure/Postgres/SchemaMigrations/1740598793630-MigrationName.ts +17 -0
  10. package/Server/Infrastructure/Postgres/SchemaMigrations/1741031019972-MigrationName.ts +17 -0
  11. package/Server/Infrastructure/Postgres/SchemaMigrations/1741209339971-MigrationName.ts +101 -0
  12. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +8 -0
  13. package/Server/Middleware/SlackAuthorization.ts +11 -2
  14. package/Server/Services/AlertFeedService.ts +2 -2
  15. package/Server/Services/AlertInternalNoteService.ts +2 -2
  16. package/Server/Services/AlertOwnerTeamService.ts +4 -4
  17. package/Server/Services/AlertOwnerUserService.ts +3 -3
  18. package/Server/Services/AlertService.ts +62 -20
  19. package/Server/Services/AlertStateTimelineService.ts +8 -18
  20. package/Server/Services/IncidentFeedService.ts +101 -2
  21. package/Server/Services/IncidentInternalNoteService.ts +47 -4
  22. package/Server/Services/IncidentOwnerTeamService.ts +57 -4
  23. package/Server/Services/IncidentOwnerUserService.ts +59 -15
  24. package/Server/Services/IncidentPublicNoteService.ts +41 -4
  25. package/Server/Services/IncidentService.ts +279 -193
  26. package/Server/Services/IncidentStateService.ts +25 -0
  27. package/Server/Services/IncidentStateTimelineService.ts +37 -19
  28. package/Server/Services/MonitorStatusTimelineService.ts +7 -17
  29. package/Server/Services/OnCallDutyPolicyEscalationRuleService.ts +2 -0
  30. package/Server/Services/OnCallDutyPolicyExecutionLogService.ts +74 -7
  31. package/Server/Services/OnCallDutyPolicyExecutionLogTimelineService.ts +63 -4
  32. package/Server/Services/OnCallDutyPolicyService.ts +13 -0
  33. package/Server/Services/ProjectUserService.ts +130 -0
  34. package/Server/Services/ScheduledMaintenanceFeedService.ts +2 -2
  35. package/Server/Services/ScheduledMaintenanceInternalNoteService.ts +12 -10
  36. package/Server/Services/ScheduledMaintenanceOwnerTeamService.ts +22 -18
  37. package/Server/Services/ScheduledMaintenanceOwnerUserService.ts +28 -30
  38. package/Server/Services/ScheduledMaintenancePublicNoteService.ts +12 -10
  39. package/Server/Services/ScheduledMaintenanceService.ts +16 -10
  40. package/Server/Services/ScheduledMaintenanceStateTimelineService.ts +1 -1
  41. package/Server/Services/StatusPageSubscriberService.ts +3 -0
  42. package/Server/Services/TeamMemberService.ts +20 -0
  43. package/Server/Services/UserNotificationRuleService.ts +74 -0
  44. package/Server/Services/UserOnCallLogService.ts +1 -1
  45. package/Server/Services/UserService.ts +35 -0
  46. package/Server/Services/WorkspaceNotificationRuleService.ts +508 -149
  47. package/Server/Services/WorkspaceUserAuthTokenService.ts +23 -0
  48. package/Server/Utils/Express.ts +1 -1
  49. package/Server/Utils/StartServer.ts +6 -1
  50. package/Server/Utils/Workspace/MicrosoftTeams/Messages/Incident.ts +195 -0
  51. package/Server/Utils/Workspace/Slack/Actions/ActionTypes.ts +20 -0
  52. package/Server/Utils/Workspace/Slack/Actions/Auth.ts +266 -0
  53. package/Server/Utils/Workspace/Slack/Actions/Incident.ts +1117 -0
  54. package/Server/Utils/Workspace/Slack/Messages/Incident.ts +116 -0
  55. package/Server/Utils/Workspace/Slack/Slack.ts +555 -18
  56. package/Server/Utils/Workspace/Slack/app-manifest.json +18 -10
  57. package/Server/Utils/Workspace/Workspace.ts +194 -1
  58. package/Server/Utils/Workspace/WorkspaceBase.ts +145 -19
  59. package/Server/Utils/Workspace/WorkspaceMessages/Incident.ts +68 -0
  60. package/Types/Icon/IconProp.ts +1 -0
  61. package/Types/Workspace/NotificationRules/NotificationRuleCondition.ts +2 -1
  62. package/Types/Workspace/NotificationRules/NotificationRuleUtil.ts +251 -121
  63. package/Types/Workspace/NotificationRules/NotificationRuleWorkspaceChannel.ts +6 -0
  64. package/Types/Workspace/WorkspaceMessagePayload.ts +71 -2
  65. package/UI/Components/ComingSoon/ComingSoon.tsx +13 -3
  66. package/UI/Components/Forms/Fields/FormField.tsx +2 -2
  67. package/UI/Components/Icon/Icon.tsx +39 -2
  68. package/UI/Components/ModelTable/BaseModelTable.tsx +16 -0
  69. package/UI/Components/Radio/Radio.tsx +11 -2
  70. package/UI/Components/Table/TableCard.tsx +2 -2
  71. package/build/dist/Models/DatabaseModels/Alert.js.map +1 -1
  72. package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
  73. package/build/dist/Models/DatabaseModels/Index.js +2 -0
  74. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  75. package/build/dist/Models/DatabaseModels/ProjectUser.js +340 -0
  76. package/build/dist/Models/DatabaseModels/ProjectUser.js.map +1 -0
  77. package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js.map +1 -1
  78. package/build/dist/Server/API/SlackAPI.js +39 -79
  79. package/build/dist/Server/API/SlackAPI.js.map +1 -1
  80. package/build/dist/Server/API/UserOnCallLogTimelineAPI.js.map +1 -1
  81. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1740597525803-MigrationName.js +12 -0
  82. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1740597525803-MigrationName.js.map +1 -0
  83. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1740598793630-MigrationName.js +12 -0
  84. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1740598793630-MigrationName.js.map +1 -0
  85. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1741031019972-MigrationName.js +12 -0
  86. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1741031019972-MigrationName.js.map +1 -0
  87. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1741209339971-MigrationName.js +42 -0
  88. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1741209339971-MigrationName.js.map +1 -0
  89. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +8 -0
  90. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  91. package/build/dist/Server/Middleware/SlackAuthorization.js +8 -2
  92. package/build/dist/Server/Middleware/SlackAuthorization.js.map +1 -1
  93. package/build/dist/Server/Services/AlertFeedService.js +2 -2
  94. package/build/dist/Server/Services/AlertFeedService.js.map +1 -1
  95. package/build/dist/Server/Services/AlertInternalNoteService.js +2 -2
  96. package/build/dist/Server/Services/AlertInternalNoteService.js.map +1 -1
  97. package/build/dist/Server/Services/AlertOwnerTeamService.js +4 -4
  98. package/build/dist/Server/Services/AlertOwnerTeamService.js.map +1 -1
  99. package/build/dist/Server/Services/AlertOwnerUserService.js +3 -3
  100. package/build/dist/Server/Services/AlertOwnerUserService.js.map +1 -1
  101. package/build/dist/Server/Services/AlertService.js +44 -19
  102. package/build/dist/Server/Services/AlertService.js.map +1 -1
  103. package/build/dist/Server/Services/AlertStateTimelineService.js +6 -16
  104. package/build/dist/Server/Services/AlertStateTimelineService.js.map +1 -1
  105. package/build/dist/Server/Services/IncidentFeedService.js +62 -2
  106. package/build/dist/Server/Services/IncidentFeedService.js.map +1 -1
  107. package/build/dist/Server/Services/IncidentInternalNoteService.js +35 -4
  108. package/build/dist/Server/Services/IncidentInternalNoteService.js.map +1 -1
  109. package/build/dist/Server/Services/IncidentOwnerTeamService.js +42 -4
  110. package/build/dist/Server/Services/IncidentOwnerTeamService.js.map +1 -1
  111. package/build/dist/Server/Services/IncidentOwnerUserService.js +43 -15
  112. package/build/dist/Server/Services/IncidentOwnerUserService.js.map +1 -1
  113. package/build/dist/Server/Services/IncidentPublicNoteService.js +32 -4
  114. package/build/dist/Server/Services/IncidentPublicNoteService.js.map +1 -1
  115. package/build/dist/Server/Services/IncidentService.js +221 -170
  116. package/build/dist/Server/Services/IncidentService.js.map +1 -1
  117. package/build/dist/Server/Services/IncidentStateService.js +14 -0
  118. package/build/dist/Server/Services/IncidentStateService.js.map +1 -1
  119. package/build/dist/Server/Services/IncidentStateTimelineService.js +31 -17
  120. package/build/dist/Server/Services/IncidentStateTimelineService.js.map +1 -1
  121. package/build/dist/Server/Services/MonitorStatusTimelineService.js +5 -15
  122. package/build/dist/Server/Services/MonitorStatusTimelineService.js.map +1 -1
  123. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleService.js +1 -0
  124. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleService.js.map +1 -1
  125. package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogService.js +62 -7
  126. package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogService.js.map +1 -1
  127. package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogTimelineService.js +51 -5
  128. package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogTimelineService.js.map +1 -1
  129. package/build/dist/Server/Services/OnCallDutyPolicyService.js +6 -0
  130. package/build/dist/Server/Services/OnCallDutyPolicyService.js.map +1 -1
  131. package/build/dist/Server/Services/ProjectUserService.js +106 -0
  132. package/build/dist/Server/Services/ProjectUserService.js.map +1 -0
  133. package/build/dist/Server/Services/ScheduledMaintenanceFeedService.js +2 -2
  134. package/build/dist/Server/Services/ScheduledMaintenanceFeedService.js.map +1 -1
  135. package/build/dist/Server/Services/ScheduledMaintenanceInternalNoteService.js +2 -2
  136. package/build/dist/Server/Services/ScheduledMaintenanceInternalNoteService.js.map +1 -1
  137. package/build/dist/Server/Services/ScheduledMaintenanceOwnerTeamService.js +4 -4
  138. package/build/dist/Server/Services/ScheduledMaintenanceOwnerTeamService.js.map +1 -1
  139. package/build/dist/Server/Services/ScheduledMaintenanceOwnerUserService.js +8 -16
  140. package/build/dist/Server/Services/ScheduledMaintenanceOwnerUserService.js.map +1 -1
  141. package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js +2 -2
  142. package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js.map +1 -1
  143. package/build/dist/Server/Services/ScheduledMaintenanceService.js +5 -2
  144. package/build/dist/Server/Services/ScheduledMaintenanceService.js.map +1 -1
  145. package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js +1 -1
  146. package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js.map +1 -1
  147. package/build/dist/Server/Services/StatusPageSubscriberService.js +3 -0
  148. package/build/dist/Server/Services/StatusPageSubscriberService.js.map +1 -1
  149. package/build/dist/Server/Services/TeamMemberService.js +17 -0
  150. package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
  151. package/build/dist/Server/Services/UserNotificationRuleService.js +52 -0
  152. package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
  153. package/build/dist/Server/Services/UserOnCallLogService.js +1 -1
  154. package/build/dist/Server/Services/UserOnCallLogService.js.map +1 -1
  155. package/build/dist/Server/Services/UserService.js +23 -0
  156. package/build/dist/Server/Services/UserService.js.map +1 -1
  157. package/build/dist/Server/Services/WorkspaceNotificationRuleService.js +306 -84
  158. package/build/dist/Server/Services/WorkspaceNotificationRuleService.js.map +1 -1
  159. package/build/dist/Server/Services/WorkspaceUserAuthTokenService.js +18 -0
  160. package/build/dist/Server/Services/WorkspaceUserAuthTokenService.js.map +1 -1
  161. package/build/dist/Server/Utils/StartServer.js +4 -0
  162. package/build/dist/Server/Utils/StartServer.js.map +1 -1
  163. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Messages/Incident.js +148 -0
  164. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Messages/Incident.js.map +1 -0
  165. package/build/dist/Server/Utils/Workspace/Slack/Actions/ActionTypes.js +19 -0
  166. package/build/dist/Server/Utils/Workspace/Slack/Actions/ActionTypes.js.map +1 -0
  167. package/build/dist/Server/Utils/Workspace/Slack/Actions/Auth.js +167 -0
  168. package/build/dist/Server/Utils/Workspace/Slack/Actions/Auth.js.map +1 -0
  169. package/build/dist/Server/Utils/Workspace/Slack/Actions/Incident.js +727 -0
  170. package/build/dist/Server/Utils/Workspace/Slack/Actions/Incident.js.map +1 -0
  171. package/build/dist/Server/Utils/Workspace/Slack/Messages/Incident.js +82 -0
  172. package/build/dist/Server/Utils/Workspace/Slack/Messages/Incident.js.map +1 -0
  173. package/build/dist/Server/Utils/Workspace/Slack/Slack.js +397 -14
  174. package/build/dist/Server/Utils/Workspace/Slack/Slack.js.map +1 -1
  175. package/build/dist/Server/Utils/Workspace/Slack/app-manifest.json +18 -10
  176. package/build/dist/Server/Utils/Workspace/Workspace.js +126 -0
  177. package/build/dist/Server/Utils/Workspace/Workspace.js.map +1 -1
  178. package/build/dist/Server/Utils/Workspace/WorkspaceBase.js +69 -11
  179. package/build/dist/Server/Utils/Workspace/WorkspaceBase.js.map +1 -1
  180. package/build/dist/Server/Utils/Workspace/WorkspaceMessages/Incident.js +47 -0
  181. package/build/dist/Server/Utils/Workspace/WorkspaceMessages/Incident.js.map +1 -0
  182. package/build/dist/Types/Icon/IconProp.js +1 -0
  183. package/build/dist/Types/Icon/IconProp.js.map +1 -1
  184. package/build/dist/Types/Workspace/NotificationRules/NotificationRuleCondition.js +2 -1
  185. package/build/dist/Types/Workspace/NotificationRules/NotificationRuleCondition.js.map +1 -1
  186. package/build/dist/Types/Workspace/NotificationRules/NotificationRuleUtil.js +214 -120
  187. package/build/dist/Types/Workspace/NotificationRules/NotificationRuleUtil.js.map +1 -1
  188. package/build/dist/Types/Workspace/NotificationRules/NotificationRuleWorkspaceChannel.js +2 -0
  189. package/build/dist/Types/Workspace/NotificationRules/NotificationRuleWorkspaceChannel.js.map +1 -0
  190. package/build/dist/UI/Components/ComingSoon/ComingSoon.js +3 -2
  191. package/build/dist/UI/Components/ComingSoon/ComingSoon.js.map +1 -1
  192. package/build/dist/UI/Components/Forms/Fields/FormField.js +2 -2
  193. package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
  194. package/build/dist/UI/Components/Icon/Icon.js +19 -2
  195. package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
  196. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +11 -0
  197. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  198. package/build/dist/UI/Components/Radio/Radio.js +5 -2
  199. package/build/dist/UI/Components/Radio/Radio.js.map +1 -1
  200. package/build/dist/UI/Components/Table/TableCard.js +2 -2
  201. package/build/dist/UI/Components/Table/TableCard.js.map +1 -1
  202. package/package.json +3 -2
  203. package/Server/Utils/Workspace/Slack/app-manifest.example.json +0 -198
@@ -17,7 +17,6 @@ import Incident from "Common/Models/DatabaseModels/Incident";
17
17
  import IncidentPublicNote from "Common/Models/DatabaseModels/IncidentPublicNote";
18
18
  import IncidentState from "Common/Models/DatabaseModels/IncidentState";
19
19
  import IncidentStateTimeline from "Common/Models/DatabaseModels/IncidentStateTimeline";
20
- import User from "Common/Models/DatabaseModels/User";
21
20
  import { IsBillingEnabled } from "../EnvironmentConfig";
22
21
  import logger from "../Utils/Logger";
23
22
  import IncidentFeedService from "./IncidentFeedService";
@@ -82,22 +81,13 @@ export class Service extends DatabaseService<IncidentStateTimeline> {
82
81
  userId = createBy.data.createdByUser.id;
83
82
  }
84
83
 
85
- const user: User | null = await UserService.findOneBy({
86
- query: {
87
- _id: userId?.toString() as string,
88
- },
89
- select: {
90
- _id: true,
91
- name: true,
92
- email: true,
93
- },
94
- props: {
95
- isRoot: true,
96
- },
97
- });
98
-
99
- if (user) {
100
- createBy.data.rootCause = `Incident state created by ${user.name} (${user.email})`;
84
+ if (userId) {
85
+ createBy.data.rootCause = `Incident state created by ${await UserService.getUserMarkdownString(
86
+ {
87
+ userId: userId!,
88
+ projectId: createBy.data.projectId || createBy.props.tenantId!,
89
+ },
90
+ )}`;
101
91
  }
102
92
  }
103
93
 
@@ -195,16 +185,44 @@ export class Service extends DatabaseService<IncidentStateTimeline> {
195
185
  });
196
186
 
197
187
  const stateName: string = incidentState?.name || "";
188
+ let stateEmoji: string = "➡️";
189
+
190
+ // if resolved state then change emoji to ✅.
191
+
192
+ if (incidentState?.isResolvedState) {
193
+ stateEmoji = "✅";
194
+ } else if (incidentState?.isAcknowledgedState) {
195
+ // eyes emoji for acknowledged state.
196
+ stateEmoji = "👀";
197
+ } else if (incidentState?.isCreatedState) {
198
+ stateEmoji = "🔴";
199
+ }
198
200
 
199
- await IncidentFeedService.createIncidentFeed({
201
+ const incidentNumber: number | null =
202
+ await IncidentService.getIncidentNumber({
203
+ incidentId: createdItem.incidentId,
204
+ });
205
+
206
+ const projectId: ObjectID = createdItem.projectId!;
207
+ const incidentId: ObjectID = createdItem.incidentId!;
208
+
209
+ await IncidentFeedService.createIncidentFeedItem({
200
210
  incidentId: createdItem.incidentId!,
201
211
  projectId: createdItem.projectId!,
202
212
  incidentFeedEventType: IncidentFeedEventType.IncidentStateChanged,
203
213
  displayColor: incidentState?.color,
204
- feedInfoInMarkdown: "**Incident State** changed to **" + stateName + "**",
214
+ feedInfoInMarkdown:
215
+ stateEmoji +
216
+ ` Changed **[Incident ${incidentNumber}](${(await IncidentService.getIncidentLinkInDashboard(projectId!, incidentId!)).toString()}) State** to **` +
217
+ stateName +
218
+ "**",
205
219
  moreInformationInMarkdown: `**Cause:**
206
220
  ${createdItem.rootCause}`,
207
221
  userId: createdItem.createdByUserId || onCreate.createBy.props.userId,
222
+ workspaceNotification: {
223
+ sendWorkspaceNotification: true,
224
+ notifyUserId: createdItem.createdByUserId,
225
+ },
208
226
  });
209
227
 
210
228
  const isResolvedState: boolean = incidentState?.isResolvedState || false;
@@ -13,7 +13,6 @@ import BadDataException from "../../Types/Exception/BadDataException";
13
13
  import ObjectID from "../../Types/ObjectID";
14
14
  import PositiveNumber from "../../Types/PositiveNumber";
15
15
  import MonitorStatusTimeline from "Common/Models/DatabaseModels/MonitorStatusTimeline";
16
- import User from "Common/Models/DatabaseModels/User";
17
16
  import { IsBillingEnabled } from "../EnvironmentConfig";
18
17
 
19
18
  export class Service extends DatabaseService<MonitorStatusTimeline> {
@@ -62,22 +61,13 @@ export class Service extends DatabaseService<MonitorStatusTimeline> {
62
61
  userId = createBy.data.createdByUser.id;
63
62
  }
64
63
 
65
- const user: User | null = await UserService.findOneBy({
66
- query: {
67
- _id: userId?.toString() as string,
68
- },
69
- select: {
70
- _id: true,
71
- name: true,
72
- email: true,
73
- },
74
- props: {
75
- isRoot: true,
76
- },
77
- });
78
-
79
- if (user) {
80
- createBy.data.rootCause = `Monitor status created by ${user.name} (${user.email})`;
64
+ if (userId) {
65
+ createBy.data.rootCause = `Monitor status created by ${await UserService.getUserMarkdownString(
66
+ {
67
+ userId: userId!,
68
+ projectId: createBy.data.projectId || createBy.props.tenantId!,
69
+ },
70
+ )}`;
81
71
  }
82
72
  }
83
73
 
@@ -188,6 +188,8 @@ export class Service extends DatabaseService<Model> {
188
188
  teamId: ObjectID | null,
189
189
  scheduleId: ObjectID | null,
190
190
  ): Promise<void> => {
191
+ // This is where user is notified.
192
+
191
193
  logger.debug(
192
194
  `Starting notification rule execution for userId: ${userId.toString()}`,
193
195
  );
@@ -17,6 +17,8 @@ import Color from "../../Types/Color";
17
17
  import AlertFeedService from "./AlertFeedService";
18
18
  import { AlertFeedEventType } from "../../Models/DatabaseModels/AlertFeed";
19
19
  import BadDataException from "../../Types/Exception/BadDataException";
20
+ import IncidentService from "./IncidentService";
21
+ import AlertService from "./AlertService";
20
22
 
21
23
  export class Service extends DatabaseService<Model> {
22
24
  public constructor() {
@@ -65,24 +67,47 @@ export class Service extends DatabaseService<Model> {
65
67
  });
66
68
 
67
69
  if (onCallPolicy && onCallPolicy.id) {
68
- const feedInfoInMarkdown: string = `**On Call Policy Started Executing:** On Call Policy **${onCallPolicy.name}** started executing. Users on call on this policy will now be notified.`;
70
+ let incidentOrAlertLink: string = "";
71
+
72
+ if (createdItem.triggeredByIncidentId) {
73
+ const projectId: ObjectID | undefined = createdItem.projectId;
74
+ const incidentId: ObjectID | undefined =
75
+ createdItem.triggeredByIncidentId;
76
+ const incidentNumber: number | null =
77
+ await IncidentService.getIncidentNumber({
78
+ incidentId: incidentId,
79
+ });
80
+ incidentOrAlertLink = `[Incident ${incidentNumber}](${(await IncidentService.getIncidentLinkInDashboard(projectId!, incidentId!)).toString()})`;
81
+ }
82
+
83
+ if (createdItem.triggeredByAlertId) {
84
+ const alertNumber: number | null = await AlertService.getAlertNumber({
85
+ alertId: createdItem.triggeredByAlertId,
86
+ });
87
+ incidentOrAlertLink = `[Alert ${alertNumber}](${(await AlertService.getAlertLinkInDashboard(createdItem.projectId!, createdItem.triggeredByAlertId)).toString()})`;
88
+ }
89
+
90
+ const feedInfoInMarkdown: string = `**📞 On Call Policy Started Executing:** On Call Policy **${onCallPolicy.name}** started executing for ${incidentOrAlertLink}. Users on call on this policy will now be notified.`;
69
91
 
70
92
  if (
71
93
  onCallPolicy &&
72
94
  onCallPolicy.id &&
73
95
  createdItem.triggeredByIncidentId
74
96
  ) {
75
- await IncidentFeedService.createIncidentFeed({
97
+ await IncidentFeedService.createIncidentFeedItem({
76
98
  incidentId: createdItem.triggeredByIncidentId,
77
99
  projectId: createdItem.projectId!,
78
100
  incidentFeedEventType: IncidentFeedEventType.OnCallPolicy,
79
101
  displayColor: Yellow500,
80
102
  feedInfoInMarkdown: feedInfoInMarkdown,
103
+ workspaceNotification: {
104
+ sendWorkspaceNotification: true,
105
+ },
81
106
  });
82
107
  }
83
108
 
84
109
  if (onCallPolicy && onCallPolicy.id && createdItem.triggeredByAlertId) {
85
- await AlertFeedService.createAlertFeed({
110
+ await AlertFeedService.createAlertFeedItem({
86
111
  alertId: createdItem.triggeredByAlertId,
87
112
  projectId: createdItem.projectId!,
88
113
  alertFeedEventType: AlertFeedEventType.OnCallPolicy,
@@ -191,6 +216,23 @@ export class Service extends DatabaseService<Model> {
191
216
  }
192
217
  }
193
218
 
219
+ public getEmojiByStatus(status: OnCallDutyPolicyStatus | undefined): string {
220
+ switch (status) {
221
+ case OnCallDutyPolicyStatus.Scheduled:
222
+ return "📅";
223
+ case OnCallDutyPolicyStatus.Started:
224
+ return "🚀";
225
+ case OnCallDutyPolicyStatus.Executing:
226
+ return "▶️";
227
+ case OnCallDutyPolicyStatus.Completed:
228
+ return "🏁";
229
+ case OnCallDutyPolicyStatus.Error:
230
+ return "❌";
231
+ default:
232
+ return "📅";
233
+ }
234
+ }
235
+
194
236
  protected override async onUpdateSuccess(
195
237
  onUpdate: OnUpdate<Model>,
196
238
  _updatedItemIds: Array<ObjectID>,
@@ -240,12 +282,34 @@ export class Service extends DatabaseService<Model> {
240
282
 
241
283
  **Message:** ${onCalldutyPolicyExecutionLog.statusMessage}`;
242
284
 
243
- const feedInfoInMarkdown: string = `**On Call Policy Status Updated:**
285
+ let incidentOrAlertLink: string = "";
286
+
287
+ if (onCalldutyPolicyExecutionLog.triggeredByIncidentId) {
288
+ const projectId: ObjectID | undefined =
289
+ onCalldutyPolicyExecutionLog.projectId;
290
+ const incidentId: ObjectID | undefined =
291
+ onCalldutyPolicyExecutionLog.triggeredByIncidentId;
292
+ const incidentNumber: number | null =
293
+ await IncidentService.getIncidentNumber({
294
+ incidentId: incidentId,
295
+ });
296
+ incidentOrAlertLink = `[Incident ${incidentNumber}](${(await IncidentService.getIncidentLinkInDashboard(projectId!, incidentId!)).toString()})`;
297
+ }
298
+
299
+ if (onCalldutyPolicyExecutionLog.triggeredByAlertId) {
300
+ const alertNumber: number | null =
301
+ await AlertService.getAlertNumber({
302
+ alertId: onCalldutyPolicyExecutionLog.triggeredByAlertId,
303
+ });
304
+ incidentOrAlertLink = `[Alert ${alertNumber}](${(await AlertService.getAlertLinkInDashboard(onCalldutyPolicyExecutionLog.projectId!, onCalldutyPolicyExecutionLog.triggeredByAlertId)).toString()})`;
305
+ }
306
+
307
+ const feedInfoInMarkdown: string = `**${this.getEmojiByStatus(onCalldutyPolicyExecutionLog.status)} On Call Policy Status Updated for ${incidentOrAlertLink}:**
244
308
 
245
- On-call policy **${onCallPolicy.name}** status updated to **${onCalldutyPolicyExecutionLog.status}**`;
309
+ On-call policy **[${onCallPolicy.name?.toString()}](${(await OnCallDutyPolicyService.getOnCallPolicyLinkInDashboard(onCallPolicy.projectId!, onCallPolicy.id!)).toString()})** status updated to **${onCalldutyPolicyExecutionLog.status}**`;
246
310
 
247
311
  if (onCalldutyPolicyExecutionLog.triggeredByIncidentId) {
248
- await IncidentFeedService.createIncidentFeed({
312
+ await IncidentFeedService.createIncidentFeedItem({
249
313
  incidentId: onCalldutyPolicyExecutionLog.triggeredByIncidentId,
250
314
  projectId: onCalldutyPolicyExecutionLog.projectId!,
251
315
  incidentFeedEventType: IncidentFeedEventType.OnCallPolicy,
@@ -256,11 +320,14 @@ On-call policy **${onCallPolicy.name}** status updated to **${onCalldutyPolicyEx
256
320
  : Blue500,
257
321
  moreInformationInMarkdown: moreInformationInMarkdown,
258
322
  feedInfoInMarkdown: feedInfoInMarkdown,
323
+ workspaceNotification: {
324
+ sendWorkspaceNotification: true,
325
+ },
259
326
  });
260
327
  }
261
328
 
262
329
  if (onCalldutyPolicyExecutionLog.triggeredByAlertId) {
263
- await AlertFeedService.createAlertFeed({
330
+ await AlertFeedService.createAlertFeedItem({
264
331
  alertId: onCalldutyPolicyExecutionLog.triggeredByAlertId,
265
332
  projectId: onCalldutyPolicyExecutionLog.projectId!,
266
333
  alertFeedEventType: AlertFeedEventType.OnCallPolicy,
@@ -11,6 +11,10 @@ import logger from "../Utils/Logger";
11
11
  import { LIMIT_PER_PROJECT } from "../../Types/Database/LimitMax";
12
12
  import AlertFeedService from "./AlertFeedService";
13
13
  import { AlertFeedEventType } from "../../Models/DatabaseModels/AlertFeed";
14
+ import OnCallDutyPolicyService from "./OnCallDutyPolicyService";
15
+ import AlertService from "./AlertService";
16
+ import IncidentService from "./IncidentService";
17
+ import UserService from "./UserService";
14
18
 
15
19
  export class Service extends DatabaseService<Model> {
16
20
  public constructor() {
@@ -38,6 +42,27 @@ export class Service extends DatabaseService<Model> {
38
42
  }
39
43
  }
40
44
 
45
+ public getEmojiBasedOnStatus(
46
+ status: OnCallDutyExecutionLogTimelineStatus,
47
+ ): string {
48
+ switch (status) {
49
+ case OnCallDutyExecutionLogTimelineStatus.Started:
50
+ return "🚀";
51
+ case OnCallDutyExecutionLogTimelineStatus.Executing:
52
+ return "🔄";
53
+ case OnCallDutyExecutionLogTimelineStatus.Error:
54
+ return "❌";
55
+ case OnCallDutyExecutionLogTimelineStatus.NotificationSent:
56
+ return "📧";
57
+ case OnCallDutyExecutionLogTimelineStatus.Skipped:
58
+ return "🚫";
59
+ case OnCallDutyExecutionLogTimelineStatus.SuccessfullyAcknowledged:
60
+ return "✅";
61
+ default:
62
+ return "🚀";
63
+ }
64
+ }
65
+
41
66
  public async addToIncidentOrAlertFeed(data: {
42
67
  onCallDutyPolicyExecutionLogTimelineId: ObjectID;
43
68
  }): Promise<void> {
@@ -120,25 +145,59 @@ export class Service extends DatabaseService<Model> {
120
145
  ? this.getColorBasedOnStatus(status)
121
146
  : Blue500;
122
147
 
123
- const feedInfoInMarkdown: string = `**On-call alert ${status} to ${onCallDutyPolicyExecutionLogTimeline.alertSentToUser?.name?.toString().trim()}**
148
+ let incidentOrAlertLink: string = "";
124
149
 
125
- The on-call policy **${onCallDutyPolicyExecutionLogTimeline.onCallDutyPolicy.name}** has been triggered. The escalation rule **${onCallDutyPolicyExecutionLogTimeline.onCallDutyPolicyEscalationRule?.name}** ${onCallDutyPolicyExecutionLogTimeline.onCallDutySchedule?.name ? String(" and schedule **" + onCallDutyPolicyExecutionLogTimeline.onCallDutySchedule?.name + "**") : ""} were applied. The user **${onCallDutyPolicyExecutionLogTimeline.alertSentToUser?.name}** (${onCallDutyPolicyExecutionLogTimeline.alertSentToUser?.email}) was alerted. The status of this alert is **${status}** with the message: \`${onCallDutyPolicyExecutionLogTimeline.statusMessage}\`. ${onCallDutyPolicyExecutionLogTimeline.userBelongsToTeam?.name ? "The alert was sent because the user belogs to the team **" + onCallDutyPolicyExecutionLogTimeline.userBelongsToTeam?.name + "**" : ""} ${onCallDutyPolicyExecutionLogTimeline.isAcknowledged ? "The alert was acknowledged at **" + onCallDutyPolicyExecutionLogTimeline.acknowledgedAt + "**" : ""}`;
150
+ if (onCallDutyPolicyExecutionLogTimeline.triggeredByIncidentId) {
151
+ const projectId: ObjectID | undefined =
152
+ onCallDutyPolicyExecutionLogTimeline.projectId;
153
+ const incidentId: ObjectID | undefined =
154
+ onCallDutyPolicyExecutionLogTimeline.triggeredByIncidentId;
155
+ const incidentNumber: number | null =
156
+ await IncidentService.getIncidentNumber({
157
+ incidentId: incidentId,
158
+ });
159
+ incidentOrAlertLink = `[Incident ${incidentNumber}](${(await IncidentService.getIncidentLinkInDashboard(projectId!, incidentId!)).toString()})`;
160
+ }
161
+
162
+ if (onCallDutyPolicyExecutionLogTimeline.triggeredByAlertId) {
163
+ const alertNumber: number | null = await AlertService.getAlertNumber({
164
+ alertId: onCallDutyPolicyExecutionLogTimeline.triggeredByAlertId,
165
+ });
166
+ incidentOrAlertLink = `[Alert ${alertNumber}](${(await AlertService.getAlertLinkInDashboard(onCallDutyPolicyExecutionLogTimeline.projectId!, onCallDutyPolicyExecutionLogTimeline.triggeredByAlertId)).toString()})`;
167
+ }
168
+
169
+ const feedInfoInMarkdown: string = `**${this.getEmojiBasedOnStatus(status)} ${incidentOrAlertLink} On-Call Alert ${status} to ${await UserService.getUserMarkdownString(
170
+ {
171
+ userId: onCallDutyPolicyExecutionLogTimeline.alertSentToUserId!,
172
+ projectId: onCallDutyPolicyExecutionLogTimeline.projectId!,
173
+ },
174
+ )}**
175
+
176
+ The on-call policy **[${onCallDutyPolicyExecutionLogTimeline.onCallDutyPolicy.name}](${(await OnCallDutyPolicyService.getOnCallPolicyLinkInDashboard(onCallDutyPolicyExecutionLogTimeline.projectId!, onCallDutyPolicyExecutionLogTimeline.onCallDutyPolicy.id!)).toString()})** has been triggered. The escalation rule **${onCallDutyPolicyExecutionLogTimeline.onCallDutyPolicyEscalationRule?.name}** ${onCallDutyPolicyExecutionLogTimeline.onCallDutySchedule?.name ? String(" and schedule **" + onCallDutyPolicyExecutionLogTimeline.onCallDutySchedule?.name + "**") : ""} were applied. ${await UserService.getUserMarkdownString(
177
+ {
178
+ userId: onCallDutyPolicyExecutionLogTimeline.alertSentToUserId!,
179
+ projectId: onCallDutyPolicyExecutionLogTimeline.projectId!,
180
+ },
181
+ )} was alerted. The status of this alert is **${status}** with the message: \`${onCallDutyPolicyExecutionLogTimeline.statusMessage}\`. ${onCallDutyPolicyExecutionLogTimeline.userBelongsToTeam?.name ? "The alert was sent because the user belogs to the team **" + onCallDutyPolicyExecutionLogTimeline.userBelongsToTeam?.name + "**" : ""} ${onCallDutyPolicyExecutionLogTimeline.isAcknowledged ? "The alert was acknowledged at **" + onCallDutyPolicyExecutionLogTimeline.acknowledgedAt + "**" : ""}`;
126
182
 
127
183
  logger.debug("Feed Info in Markdown: " + feedInfoInMarkdown);
128
184
 
129
185
  if (onCallDutyPolicyExecutionLogTimeline.triggeredByIncidentId) {
130
- await IncidentFeedService.createIncidentFeed({
186
+ await IncidentFeedService.createIncidentFeedItem({
131
187
  incidentId:
132
188
  onCallDutyPolicyExecutionLogTimeline.triggeredByIncidentId,
133
189
  projectId: onCallDutyPolicyExecutionLogTimeline.projectId!,
134
190
  incidentFeedEventType: IncidentFeedEventType.OnCallPolicy,
135
191
  displayColor: displayColor,
136
192
  feedInfoInMarkdown: feedInfoInMarkdown,
193
+ workspaceNotification: {
194
+ sendWorkspaceNotification: true,
195
+ },
137
196
  });
138
197
  }
139
198
 
140
199
  if (onCallDutyPolicyExecutionLogTimeline.triggeredByAlertId) {
141
- await AlertFeedService.createAlertFeed({
200
+ await AlertFeedService.createAlertFeedItem({
142
201
  alertId: onCallDutyPolicyExecutionLogTimeline.triggeredByAlertId,
143
202
  projectId: onCallDutyPolicyExecutionLogTimeline.projectId!,
144
203
  alertFeedEventType: AlertFeedEventType.OnCallPolicy,
@@ -6,12 +6,25 @@ import OnCallDutyPolicyStatus from "../../Types/OnCallDutyPolicy/OnCallDutyPolic
6
6
  import UserNotificationEventType from "../../Types/UserNotification/UserNotificationEventType";
7
7
  import OnCallDutyPolicy from "Common/Models/DatabaseModels/OnCallDutyPolicy";
8
8
  import OnCallDutyPolicyExecutionLog from "Common/Models/DatabaseModels/OnCallDutyPolicyExecutionLog";
9
+ import DatabaseConfig from "../DatabaseConfig";
10
+ import URL from "../../Types/API/URL";
9
11
 
10
12
  export class Service extends DatabaseService<OnCallDutyPolicy> {
11
13
  public constructor() {
12
14
  super(OnCallDutyPolicy);
13
15
  }
14
16
 
17
+ public async getOnCallPolicyLinkInDashboard(
18
+ projectId: ObjectID,
19
+ onCallDutyPolicyId: ObjectID,
20
+ ): Promise<URL> {
21
+ const dashboardUrl: URL = await DatabaseConfig.getDashboardUrl();
22
+
23
+ return URL.fromString(dashboardUrl.toString()).addRoute(
24
+ `/${projectId.toString()}/on-call-duty/policies/${onCallDutyPolicyId.toString()}`,
25
+ );
26
+ }
27
+
15
28
  public async executePolicy(
16
29
  policyId: ObjectID,
17
30
  options: {
@@ -0,0 +1,130 @@
1
+ import TeamMember from "../../Models/DatabaseModels/TeamMember";
2
+ import LIMIT_MAX from "../../Types/Database/LimitMax";
3
+ import ObjectID from "../../Types/ObjectID";
4
+ import DatabaseService from "./DatabaseService";
5
+ import Model from "Common/Models/DatabaseModels/ProjectUser";
6
+ import TeamMemberService from "./TeamMemberService";
7
+
8
+ export class Service extends DatabaseService<Model> {
9
+ public constructor() {
10
+ super(Model);
11
+ }
12
+
13
+ public async refreshProjectUsersByProject(data: {
14
+ projectId: ObjectID;
15
+ }): Promise<void> {
16
+ // get all team members by user
17
+
18
+ // first delete all project users by project id.
19
+ await this.deleteBy({
20
+ query: {
21
+ projectId: data.projectId,
22
+ },
23
+ limit: LIMIT_MAX,
24
+ skip: 0,
25
+ props: {
26
+ isRoot: true,
27
+ },
28
+ });
29
+
30
+ // get all team members by project.
31
+ const teamMembers: Array<TeamMember> = await TeamMemberService.findBy({
32
+ query: {
33
+ projectId: data.projectId,
34
+ },
35
+ limit: LIMIT_MAX,
36
+ skip: 0,
37
+ props: {
38
+ isRoot: true,
39
+ },
40
+ select: {
41
+ userId: true,
42
+ teamId: true,
43
+ team: {
44
+ _id: true,
45
+ },
46
+ hasAcceptedInvitation: true,
47
+ },
48
+ });
49
+
50
+ // create project users by team members.
51
+
52
+ const projectUsersToCreate: Array<Model> = [];
53
+
54
+ for (const teamMember of teamMembers) {
55
+ // check if the user already exists in the project users.
56
+
57
+ // if yes then add the team to the project user acceptedTeams, if the invitation is accepted.
58
+
59
+ // if no then create a new project user.
60
+
61
+ // if the user is not accepted the invitation then add the team to invitedTeams of the project user.
62
+
63
+ // if the user is accepted the invitation then add the team to acceptedTeams of the project user.
64
+
65
+ let doesProjectUserExist: boolean = false;
66
+
67
+ for (const item of projectUsersToCreate) {
68
+ if (item.userId?.toString() === teamMember.userId?.toString()) {
69
+ doesProjectUserExist = true;
70
+ break;
71
+ }
72
+ }
73
+
74
+ if (doesProjectUserExist) {
75
+ // add the team to the project user acceptedTeams, if the invitation is accepted.
76
+ if (teamMember.hasAcceptedInvitation) {
77
+ for (const projectUser of projectUsersToCreate) {
78
+ if (
79
+ projectUser.userId?.toString() === teamMember.userId?.toString()
80
+ ) {
81
+ if (!projectUser.acceptedTeams) {
82
+ projectUser.acceptedTeams = [];
83
+ }
84
+
85
+ projectUser.acceptedTeams?.push(teamMember.team!);
86
+ }
87
+ }
88
+ } else {
89
+ for (const projectUser of projectUsersToCreate) {
90
+ if (
91
+ projectUser.userId?.toString() === teamMember.userId?.toString()
92
+ ) {
93
+ if (!projectUser.invitedTeams) {
94
+ projectUser.invitedTeams = [];
95
+ }
96
+
97
+ projectUser.invitedTeams?.push(teamMember.team!);
98
+ }
99
+ }
100
+ }
101
+ } else {
102
+ // create a new project user.
103
+ const projectUser: Model = new Model();
104
+ projectUser.userId = teamMember.userId!;
105
+ projectUser.projectId = data.projectId;
106
+
107
+ if (teamMember.hasAcceptedInvitation) {
108
+ projectUser.acceptedTeams = [teamMember.team!];
109
+ } else {
110
+ projectUser.invitedTeams = [teamMember.team!];
111
+ }
112
+
113
+ projectUsersToCreate.push(projectUser);
114
+ }
115
+ }
116
+
117
+ // now create the project users.
118
+
119
+ for (const projectUser of projectUsersToCreate) {
120
+ await this.create({
121
+ data: projectUser,
122
+ props: {
123
+ isRoot: true,
124
+ },
125
+ });
126
+ }
127
+ }
128
+ }
129
+
130
+ export default new Service();
@@ -19,7 +19,7 @@ export class Service extends DatabaseService<Model> {
19
19
  }
20
20
  }
21
21
 
22
- public async createScheduledMaintenanceFeed(data: {
22
+ public async createScheduledMaintenanceFeedItem(data: {
23
23
  scheduledMaintenanceId: ObjectID;
24
24
  feedInfoInMarkdown: string;
25
25
  scheduledMaintenanceFeedEventType: ScheduledMaintenanceFeedEventType;
@@ -83,7 +83,7 @@ export class Service extends DatabaseService<Model> {
83
83
  });
84
84
  } catch (error) {
85
85
  logger.error(
86
- "ScheduledMaintenanceFeedService.createScheduledMaintenanceFeed",
86
+ "ScheduledMaintenanceFeedService.createScheduledMaintenanceFeedItem",
87
87
  );
88
88
  logger.error(error);
89
89
  // we dont want to throw the error here, as this is not critical but we still log it.
@@ -19,7 +19,7 @@ export class Service extends DatabaseService<Model> {
19
19
  const userId: ObjectID | null | undefined =
20
20
  createdItem.createdByUserId || createdItem.createdByUser?.id;
21
21
 
22
- await ScheduledMaintenanceFeedService.createScheduledMaintenanceFeed({
22
+ await ScheduledMaintenanceFeedService.createScheduledMaintenanceFeedItem({
23
23
  scheduledMaintenanceId: createdItem.scheduledMaintenanceId!,
24
24
  projectId: createdItem.projectId!,
25
25
  scheduledMaintenanceFeedEventType:
@@ -63,19 +63,21 @@ ${createdItem.note}
63
63
  onUpdate.updateBy.props.userId;
64
64
 
65
65
  for (const updatedItem of updatedItems) {
66
- await ScheduledMaintenanceFeedService.createScheduledMaintenanceFeed({
67
- scheduledMaintenanceId: updatedItem.scheduledMaintenanceId!,
68
- projectId: updatedItem.projectId!,
69
- scheduledMaintenanceFeedEventType:
70
- ScheduledMaintenanceFeedEventType.PrivateNote,
71
- displayColor: Blue500,
72
- userId: userId || undefined,
66
+ await ScheduledMaintenanceFeedService.createScheduledMaintenanceFeedItem(
67
+ {
68
+ scheduledMaintenanceId: updatedItem.scheduledMaintenanceId!,
69
+ projectId: updatedItem.projectId!,
70
+ scheduledMaintenanceFeedEventType:
71
+ ScheduledMaintenanceFeedEventType.PrivateNote,
72
+ displayColor: Blue500,
73
+ userId: userId || undefined,
73
74
 
74
- feedInfoInMarkdown: `**Updated Private Note**
75
+ feedInfoInMarkdown: `**Updated Private Note**
75
76
 
76
77
  ${updatedItem.note}
77
78
  `,
78
- });
79
+ },
80
+ );
79
81
  }
80
82
  }
81
83
  return onUpdate;
@@ -66,15 +66,17 @@ export class Service extends DatabaseService<Model> {
66
66
  });
67
67
 
68
68
  if (team && team.name) {
69
- await ScheduledMaintenanceFeedService.createScheduledMaintenanceFeed({
70
- scheduledMaintenanceId: scheduledMaintenanceId,
71
- projectId: projectId,
72
- scheduledMaintenanceFeedEventType:
73
- ScheduledMaintenanceFeedEventType.OwnerTeamRemoved,
74
- displayColor: Red500,
75
- feedInfoInMarkdown: `**Team ${team.name}** was removed from the scheduled maintenance as the owner.`,
76
- userId: deleteByUserId || undefined,
77
- });
69
+ await ScheduledMaintenanceFeedService.createScheduledMaintenanceFeedItem(
70
+ {
71
+ scheduledMaintenanceId: scheduledMaintenanceId,
72
+ projectId: projectId,
73
+ scheduledMaintenanceFeedEventType:
74
+ ScheduledMaintenanceFeedEventType.OwnerTeamRemoved,
75
+ displayColor: Red500,
76
+ feedInfoInMarkdown: `Removed team **${team.name}** from the scheduled maintenance as the owner.`,
77
+ userId: deleteByUserId || undefined,
78
+ },
79
+ );
78
80
  }
79
81
  }
80
82
  }
@@ -107,15 +109,17 @@ export class Service extends DatabaseService<Model> {
107
109
  });
108
110
 
109
111
  if (team && team.name) {
110
- await ScheduledMaintenanceFeedService.createScheduledMaintenanceFeed({
111
- scheduledMaintenanceId: scheduledMaintenanceId,
112
- projectId: projectId,
113
- scheduledMaintenanceFeedEventType:
114
- ScheduledMaintenanceFeedEventType.OwnerTeamAdded,
115
- displayColor: Gray500,
116
- feedInfoInMarkdown: `**Team ${team.name}** was added to the scheduled maintenance as the owner.`,
117
- userId: createdByUserId || undefined,
118
- });
112
+ await ScheduledMaintenanceFeedService.createScheduledMaintenanceFeedItem(
113
+ {
114
+ scheduledMaintenanceId: scheduledMaintenanceId,
115
+ projectId: projectId,
116
+ scheduledMaintenanceFeedEventType:
117
+ ScheduledMaintenanceFeedEventType.OwnerTeamAdded,
118
+ displayColor: Gray500,
119
+ feedInfoInMarkdown: `Added team **${team.name}** to the scheduled maintenance as the owner.`,
120
+ userId: createdByUserId || undefined,
121
+ },
122
+ );
119
123
  }
120
124
  }
121
125