@oneuptime/common 7.0.3517 → 7.0.3538

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 (115) hide show
  1. package/Models/DatabaseModels/AlertFeed.ts +12 -4
  2. package/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.ts +2 -0
  3. package/Models/DatabaseModels/OnCallDutyPolicyExecutionLogTimeline.ts +59 -2
  4. package/Models/DatabaseModels/ScheduledMaintenanceFeed.ts +15 -7
  5. package/Models/DatabaseModels/UserNotificationRule.ts +50 -0
  6. package/Models/DatabaseModels/UserOnCallLog.ts +48 -1
  7. package/Models/DatabaseModels/UserOnCallLogTimeline.ts +49 -2
  8. package/Server/API/BillingInvoiceAPI.ts +2 -32
  9. package/Server/API/UserOnCallLogTimelineAPI.ts +32 -8
  10. package/Server/Infrastructure/Postgres/SchemaMigrations/1737141420441-MigrationName.ts +131 -0
  11. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +2 -0
  12. package/Server/Services/AlertFeedService.ts +44 -37
  13. package/Server/Services/AlertInternalNoteService.ts +73 -0
  14. package/Server/Services/AlertOwnerTeamService.ts +112 -0
  15. package/Server/Services/AlertOwnerUserService.ts +114 -0
  16. package/Server/Services/AlertService.ts +121 -0
  17. package/Server/Services/AlertStateTimelineService.ts +52 -0
  18. package/Server/Services/BillingInvoiceService.ts +170 -0
  19. package/Server/Services/IncidentFeedService.ts +59 -54
  20. package/Server/Services/IncidentInternalNoteService.ts +46 -1
  21. package/Server/Services/IncidentPublicNoteService.ts +47 -2
  22. package/Server/Services/OnCallDutyPolicyEscalationRuleService.ts +32 -14
  23. package/Server/Services/OnCallDutyPolicyExecutionLogService.ts +86 -27
  24. package/Server/Services/OnCallDutyPolicyExecutionLogTimelineService.ts +30 -12
  25. package/Server/Services/ScheduledMaintenanceFeedService.ts +51 -40
  26. package/Server/Services/ScheduledMaintenanceInternalNoteService.ts +75 -0
  27. package/Server/Services/ScheduledMaintenanceOwnerTeamService.ts +116 -0
  28. package/Server/Services/ScheduledMaintenanceOwnerUserService.ts +118 -0
  29. package/Server/Services/ScheduledMaintenancePublicNoteService.ts +74 -1
  30. package/Server/Services/ScheduledMaintenanceService.ts +68 -0
  31. package/Server/Services/ScheduledMaintenanceStateTimelineService.ts +30 -0
  32. package/Server/Services/UserNotificationRuleService.ts +450 -67
  33. package/Server/Services/UserOnCallLogService.ts +61 -18
  34. package/Server/Services/UserOnCallLogTimelineService.ts +25 -11
  35. package/Server/Utils/Logger.ts +14 -0
  36. package/Types/Email/EmailTemplateType.ts +1 -0
  37. package/Types/NotificationRule/NotificationRuleType.ts +1 -1
  38. package/UI/Utils/Project.ts +25 -0
  39. package/build/dist/Models/DatabaseModels/AlertFeed.js +12 -4
  40. package/build/dist/Models/DatabaseModels/AlertFeed.js.map +1 -1
  41. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.js +2 -0
  42. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.js.map +1 -1
  43. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLogTimeline.js +60 -2
  44. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLogTimeline.js.map +1 -1
  45. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceFeed.js +15 -7
  46. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceFeed.js.map +1 -1
  47. package/build/dist/Models/DatabaseModels/UserNotificationRule.js +49 -0
  48. package/build/dist/Models/DatabaseModels/UserNotificationRule.js.map +1 -1
  49. package/build/dist/Models/DatabaseModels/UserOnCallLog.js +48 -1
  50. package/build/dist/Models/DatabaseModels/UserOnCallLog.js.map +1 -1
  51. package/build/dist/Models/DatabaseModels/UserOnCallLogTimeline.js +50 -2
  52. package/build/dist/Models/DatabaseModels/UserOnCallLogTimeline.js.map +1 -1
  53. package/build/dist/Server/API/BillingInvoiceAPI.js +2 -19
  54. package/build/dist/Server/API/BillingInvoiceAPI.js.map +1 -1
  55. package/build/dist/Server/API/UserOnCallLogTimelineAPI.js +10 -2
  56. package/build/dist/Server/API/UserOnCallLogTimelineAPI.js.map +1 -1
  57. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1737141420441-MigrationName.js +50 -0
  58. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1737141420441-MigrationName.js.map +1 -0
  59. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +2 -0
  60. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  61. package/build/dist/Server/Services/AlertFeedService.js +43 -35
  62. package/build/dist/Server/Services/AlertFeedService.js.map +1 -1
  63. package/build/dist/Server/Services/AlertInternalNoteService.js +56 -0
  64. package/build/dist/Server/Services/AlertInternalNoteService.js.map +1 -1
  65. package/build/dist/Server/Services/AlertOwnerTeamService.js +86 -0
  66. package/build/dist/Server/Services/AlertOwnerTeamService.js.map +1 -1
  67. package/build/dist/Server/Services/AlertOwnerUserService.js +89 -0
  68. package/build/dist/Server/Services/AlertOwnerUserService.js.map +1 -1
  69. package/build/dist/Server/Services/AlertService.js +107 -3
  70. package/build/dist/Server/Services/AlertService.js.map +1 -1
  71. package/build/dist/Server/Services/AlertStateTimelineService.js +44 -1
  72. package/build/dist/Server/Services/AlertStateTimelineService.js.map +1 -1
  73. package/build/dist/Server/Services/BillingInvoiceService.js +123 -0
  74. package/build/dist/Server/Services/BillingInvoiceService.js.map +1 -1
  75. package/build/dist/Server/Services/IncidentFeedService.js +45 -39
  76. package/build/dist/Server/Services/IncidentFeedService.js.map +1 -1
  77. package/build/dist/Server/Services/IncidentInternalNoteService.js +37 -0
  78. package/build/dist/Server/Services/IncidentInternalNoteService.js.map +1 -1
  79. package/build/dist/Server/Services/IncidentPublicNoteService.js +38 -1
  80. package/build/dist/Server/Services/IncidentPublicNoteService.js.map +1 -1
  81. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleService.js +18 -8
  82. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleService.js.map +1 -1
  83. package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogService.js +70 -24
  84. package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogService.js.map +1 -1
  85. package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogTimelineService.js +26 -11
  86. package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogTimelineService.js.map +1 -1
  87. package/build/dist/Server/Services/ScheduledMaintenanceFeedService.js +45 -37
  88. package/build/dist/Server/Services/ScheduledMaintenanceFeedService.js.map +1 -1
  89. package/build/dist/Server/Services/ScheduledMaintenanceInternalNoteService.js +56 -0
  90. package/build/dist/Server/Services/ScheduledMaintenanceInternalNoteService.js.map +1 -1
  91. package/build/dist/Server/Services/ScheduledMaintenanceOwnerTeamService.js +86 -0
  92. package/build/dist/Server/Services/ScheduledMaintenanceOwnerTeamService.js.map +1 -1
  93. package/build/dist/Server/Services/ScheduledMaintenanceOwnerUserService.js +89 -0
  94. package/build/dist/Server/Services/ScheduledMaintenanceOwnerUserService.js.map +1 -1
  95. package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js +56 -0
  96. package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js.map +1 -1
  97. package/build/dist/Server/Services/ScheduledMaintenanceService.js +57 -0
  98. package/build/dist/Server/Services/ScheduledMaintenanceService.js.map +1 -1
  99. package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js +24 -0
  100. package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js.map +1 -1
  101. package/build/dist/Server/Services/UserNotificationRuleService.js +334 -67
  102. package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
  103. package/build/dist/Server/Services/UserOnCallLogService.js +66 -27
  104. package/build/dist/Server/Services/UserOnCallLogService.js.map +1 -1
  105. package/build/dist/Server/Services/UserOnCallLogTimelineService.js +16 -5
  106. package/build/dist/Server/Services/UserOnCallLogTimelineService.js.map +1 -1
  107. package/build/dist/Server/Utils/Logger.js +11 -0
  108. package/build/dist/Server/Utils/Logger.js.map +1 -1
  109. package/build/dist/Types/Email/EmailTemplateType.js +1 -0
  110. package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
  111. package/build/dist/Types/NotificationRule/NotificationRuleType.js +1 -1
  112. package/build/dist/Types/NotificationRule/NotificationRuleType.js.map +1 -1
  113. package/build/dist/UI/Utils/Project.js +11 -0
  114. package/build/dist/UI/Utils/Project.js.map +1 -1
  115. package/package.json +2 -2
@@ -14,6 +14,9 @@ import OnCallDutyPolicy from "../../Models/DatabaseModels/OnCallDutyPolicy";
14
14
  import OnCallDutyPolicyService from "./OnCallDutyPolicyService";
15
15
  import ObjectID from "../../Types/ObjectID";
16
16
  import Color from "../../Types/Color";
17
+ import AlertFeedService from "./AlertFeedService";
18
+ import { AlertFeedEventType } from "../../Models/DatabaseModels/AlertFeed";
19
+ import BadDataException from "../../Types/Exception/BadDataException";
17
20
 
18
21
  export class Service extends DatabaseService<Model> {
19
22
  public constructor() {
@@ -39,7 +42,7 @@ export class Service extends DatabaseService<Model> {
39
42
  _onCreate: OnCreate<Model>,
40
43
  createdItem: Model,
41
44
  ): Promise<Model> {
42
- if (createdItem.triggeredByIncidentId) {
45
+ if (createdItem.triggeredByIncidentId || createdItem.triggeredByAlertId) {
43
46
  const onCallPolicy: OnCallDutyPolicy | null =
44
47
  await OnCallDutyPolicyService.findOneById({
45
48
  id: createdItem.onCallDutyPolicyId!,
@@ -54,13 +57,31 @@ export class Service extends DatabaseService<Model> {
54
57
  });
55
58
 
56
59
  if (onCallPolicy && onCallPolicy.id) {
57
- await IncidentFeedService.createIncidentFeed({
58
- incidentId: createdItem.triggeredByIncidentId,
59
- projectId: createdItem.projectId!,
60
- incidentFeedEventType: IncidentFeedEventType.OnCallPolicy,
61
- displayColor: Yellow500,
62
- feedInfoInMarkdown: `**On Call Policy Started Executing:** On Call Policy **${onCallPolicy.name}** started executing. Users on call on this policy will now be notified.`,
63
- });
60
+ 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.`;
61
+
62
+ if (
63
+ onCallPolicy &&
64
+ onCallPolicy.id &&
65
+ createdItem.triggeredByIncidentId
66
+ ) {
67
+ await IncidentFeedService.createIncidentFeed({
68
+ incidentId: createdItem.triggeredByIncidentId,
69
+ projectId: createdItem.projectId!,
70
+ incidentFeedEventType: IncidentFeedEventType.OnCallPolicy,
71
+ displayColor: Yellow500,
72
+ feedInfoInMarkdown: feedInfoInMarkdown,
73
+ });
74
+ }
75
+
76
+ if (onCallPolicy && onCallPolicy.id && createdItem.triggeredByAlertId) {
77
+ await AlertFeedService.createAlertFeed({
78
+ alertId: createdItem.triggeredByAlertId,
79
+ projectId: createdItem.projectId!,
80
+ alertFeedEventType: AlertFeedEventType.OnCallPolicy,
81
+ displayColor: Yellow500,
82
+ feedInfoInMarkdown: feedInfoInMarkdown,
83
+ });
84
+ }
64
85
  }
65
86
  }
66
87
 
@@ -92,12 +113,27 @@ export class Service extends DatabaseService<Model> {
92
113
  },
93
114
  });
94
115
 
116
+ let userNotificationEventType: UserNotificationEventType | null = null;
117
+
118
+ if (createdItem.triggeredByIncidentId) {
119
+ userNotificationEventType = UserNotificationEventType.IncidentCreated;
120
+ }
121
+
122
+ if (createdItem.triggeredByAlertId) {
123
+ userNotificationEventType = UserNotificationEventType.AlertCreated;
124
+ }
125
+
126
+ if (!userNotificationEventType) {
127
+ throw new BadDataException("Invalid userNotificationEventType");
128
+ }
129
+
95
130
  await OnCallDutyPolicyEscalationRuleService.startRuleExecution(
96
131
  executionRule.id!,
97
132
  {
98
133
  projectId: createdItem.projectId!,
99
134
  triggeredByIncidentId: createdItem.triggeredByIncidentId,
100
- userNotificationEventType: UserNotificationEventType.IncidentCreated,
135
+ triggeredByAlertId: createdItem.triggeredByAlertId,
136
+ userNotificationEventType: userNotificationEventType,
101
137
  onCallPolicyExecutionLogId: createdItem.id!,
102
138
  onCallPolicyId: createdItem.onCallDutyPolicyId!,
103
139
  },
@@ -107,7 +143,7 @@ export class Service extends DatabaseService<Model> {
107
143
  id: createdItem.id!,
108
144
  data: {
109
145
  status: OnCallDutyPolicyStatus.Executing,
110
- statusMessage: "First escalation rule executed....",
146
+ statusMessage: "First escalation rule executed...",
111
147
  },
112
148
  props: {
113
149
  isRoot: true,
@@ -165,6 +201,7 @@ export class Service extends DatabaseService<Model> {
165
201
  status: true,
166
202
  statusMessage: true,
167
203
  triggeredByIncidentId: true,
204
+ triggeredByAlertId: true,
168
205
  },
169
206
  props: {
170
207
  isRoot: true,
@@ -174,7 +211,8 @@ export class Service extends DatabaseService<Model> {
174
211
 
175
212
  if (
176
213
  onCalldutyPolicyExecutionLog &&
177
- onCalldutyPolicyExecutionLog.triggeredByIncidentId
214
+ (onCalldutyPolicyExecutionLog.triggeredByIncidentId ||
215
+ onCalldutyPolicyExecutionLog.triggeredByAlertId)
178
216
  ) {
179
217
  const onCallPolicy: OnCallDutyPolicy | null =
180
218
  await OnCallDutyPolicyService.findOneById({
@@ -190,22 +228,43 @@ export class Service extends DatabaseService<Model> {
190
228
  });
191
229
 
192
230
  if (onCallPolicy && onCallPolicy.id) {
193
- await IncidentFeedService.createIncidentFeed({
194
- incidentId: onCalldutyPolicyExecutionLog.triggeredByIncidentId,
195
- projectId: onCalldutyPolicyExecutionLog.projectId!,
196
- incidentFeedEventType: IncidentFeedEventType.OnCallPolicy,
197
- displayColor: onCalldutyPolicyExecutionLog.status
198
- ? this.getDisplayColorByStatus(
199
- onCalldutyPolicyExecutionLog.status,
200
- )
201
- : Blue500,
202
- moreInformationInMarkdown: `**Status:** ${onCalldutyPolicyExecutionLog.status}
203
-
204
- **Message:** ${onCalldutyPolicyExecutionLog.statusMessage}`,
205
- feedInfoInMarkdown: `**On Call Policy Status Updated:**
206
-
207
- On-call policy **${onCallPolicy.name}** status updated to **${onCalldutyPolicyExecutionLog.status}**`,
208
- });
231
+ const moreInformationInMarkdown: string = `**Status:** ${onCalldutyPolicyExecutionLog.status}
232
+
233
+ **Message:** ${onCalldutyPolicyExecutionLog.statusMessage}`;
234
+
235
+ const feedInfoInMarkdown: string = `**On Call Policy Status Updated:**
236
+
237
+ On-call policy **${onCallPolicy.name}** status updated to **${onCalldutyPolicyExecutionLog.status}**`;
238
+
239
+ if (onCalldutyPolicyExecutionLog.triggeredByIncidentId) {
240
+ await IncidentFeedService.createIncidentFeed({
241
+ incidentId: onCalldutyPolicyExecutionLog.triggeredByIncidentId,
242
+ projectId: onCalldutyPolicyExecutionLog.projectId!,
243
+ incidentFeedEventType: IncidentFeedEventType.OnCallPolicy,
244
+ displayColor: onCalldutyPolicyExecutionLog.status
245
+ ? this.getDisplayColorByStatus(
246
+ onCalldutyPolicyExecutionLog.status,
247
+ )
248
+ : Blue500,
249
+ moreInformationInMarkdown: moreInformationInMarkdown,
250
+ feedInfoInMarkdown: feedInfoInMarkdown,
251
+ });
252
+ }
253
+
254
+ if (onCalldutyPolicyExecutionLog.triggeredByAlertId) {
255
+ await AlertFeedService.createAlertFeed({
256
+ alertId: onCalldutyPolicyExecutionLog.triggeredByAlertId,
257
+ projectId: onCalldutyPolicyExecutionLog.projectId!,
258
+ alertFeedEventType: AlertFeedEventType.OnCallPolicy,
259
+ displayColor: onCalldutyPolicyExecutionLog.status
260
+ ? this.getDisplayColorByStatus(
261
+ onCalldutyPolicyExecutionLog.status,
262
+ )
263
+ : Blue500,
264
+ moreInformationInMarkdown: moreInformationInMarkdown,
265
+ feedInfoInMarkdown: feedInfoInMarkdown,
266
+ });
267
+ }
209
268
  }
210
269
  }
211
270
  }
@@ -9,6 +9,8 @@ import Color from "../../Types/Color";
9
9
  import ObjectID from "../../Types/ObjectID";
10
10
  import logger from "../Utils/Logger";
11
11
  import { LIMIT_PER_PROJECT } from "../../Types/Database/LimitMax";
12
+ import AlertFeedService from "./AlertFeedService";
13
+ import { AlertFeedEventType } from "../../Models/DatabaseModels/AlertFeed";
12
14
 
13
15
  export class Service extends DatabaseService<Model> {
14
16
  public constructor() {
@@ -36,7 +38,7 @@ export class Service extends DatabaseService<Model> {
36
38
  }
37
39
  }
38
40
 
39
- public async addToIncidentFeed(data: {
41
+ public async addToIncidentOrAlertFeed(data: {
40
42
  onCallDutyPolicyExecutionLogTimelineId: ObjectID;
41
43
  }): Promise<void> {
42
44
  logger.debug(
@@ -50,6 +52,7 @@ export class Service extends DatabaseService<Model> {
50
52
  _id: true,
51
53
  onCallDutyPolicyId: true,
52
54
  triggeredByIncidentId: true,
55
+ triggeredByAlertId: true,
53
56
  projectId: true,
54
57
  status: true,
55
58
  statusMessage: true,
@@ -89,7 +92,10 @@ export class Service extends DatabaseService<Model> {
89
92
  return;
90
93
  }
91
94
 
92
- if (!onCallDutyPolicyExecutionLogTimeline.triggeredByIncidentId) {
95
+ if (
96
+ !onCallDutyPolicyExecutionLogTimeline.triggeredByIncidentId &&
97
+ !onCallDutyPolicyExecutionLogTimeline.triggeredByAlertId
98
+ ) {
93
99
  return;
94
100
  }
95
101
 
@@ -120,14 +126,26 @@ The on-call policy **${onCallDutyPolicyExecutionLogTimeline.onCallDutyPolicy.nam
120
126
 
121
127
  logger.debug("Feed Info in Markdown: " + feedInfoInMarkdown);
122
128
 
123
- await IncidentFeedService.createIncidentFeed({
124
- incidentId:
125
- onCallDutyPolicyExecutionLogTimeline.triggeredByIncidentId,
126
- projectId: onCallDutyPolicyExecutionLogTimeline.projectId!,
127
- incidentFeedEventType: IncidentFeedEventType.OnCallPolicy,
128
- displayColor: displayColor,
129
- feedInfoInMarkdown: feedInfoInMarkdown,
130
- });
129
+ if (onCallDutyPolicyExecutionLogTimeline.triggeredByIncidentId) {
130
+ await IncidentFeedService.createIncidentFeed({
131
+ incidentId:
132
+ onCallDutyPolicyExecutionLogTimeline.triggeredByIncidentId,
133
+ projectId: onCallDutyPolicyExecutionLogTimeline.projectId!,
134
+ incidentFeedEventType: IncidentFeedEventType.OnCallPolicy,
135
+ displayColor: displayColor,
136
+ feedInfoInMarkdown: feedInfoInMarkdown,
137
+ });
138
+ }
139
+
140
+ if (onCallDutyPolicyExecutionLogTimeline.triggeredByAlertId) {
141
+ await AlertFeedService.createAlertFeed({
142
+ alertId: onCallDutyPolicyExecutionLogTimeline.triggeredByAlertId,
143
+ projectId: onCallDutyPolicyExecutionLogTimeline.projectId!,
144
+ alertFeedEventType: AlertFeedEventType.OnCallPolicy,
145
+ displayColor: displayColor,
146
+ feedInfoInMarkdown: feedInfoInMarkdown,
147
+ });
148
+ }
131
149
 
132
150
  logger.debug("Incident Feed created");
133
151
  }
@@ -141,7 +159,7 @@ The on-call policy **${onCallDutyPolicyExecutionLogTimeline.onCallDutyPolicy.nam
141
159
  logger.debug("OnCallDutyPolicyExecutionLogTimelineService.onCreateSuccess");
142
160
  logger.debug(createdItem);
143
161
 
144
- await this.addToIncidentFeed({
162
+ await this.addToIncidentOrAlertFeed({
145
163
  onCallDutyPolicyExecutionLogTimelineId: createdItem.id!,
146
164
  });
147
165
 
@@ -166,7 +184,7 @@ The on-call policy **${onCallDutyPolicyExecutionLogTimeline.onCallDutyPolicy.nam
166
184
  });
167
185
 
168
186
  for (const updatedItem of updatedItems) {
169
- await this.addToIncidentFeed({
187
+ await this.addToIncidentOrAlertFeed({
170
188
  onCallDutyPolicyExecutionLogTimelineId: updatedItem.id as ObjectID,
171
189
  });
172
190
  }
@@ -4,6 +4,7 @@ import OneUptimeDate from "../../Types/Date";
4
4
  import BadDataException from "../../Types/Exception/BadDataException";
5
5
  import ObjectID from "../../Types/ObjectID";
6
6
  import { IsBillingEnabled } from "../EnvironmentConfig";
7
+ import logger from "../Utils/Logger";
7
8
  import DatabaseService from "./DatabaseService";
8
9
  import Model, {
9
10
  ScheduledMaintenanceFeedEventType,
@@ -27,56 +28,66 @@ export class Service extends DatabaseService<Model> {
27
28
  displayColor?: Color | undefined;
28
29
  userId?: ObjectID | undefined;
29
30
  postedAt?: Date | undefined;
30
- }): Promise<Model> {
31
- if (!data.scheduledMaintenanceId) {
32
- throw new BadDataException("Scheduled Maintenance ID is required");
33
- }
31
+ }): Promise<void> {
32
+ try {
33
+ if (!data.scheduledMaintenanceId) {
34
+ throw new BadDataException("Scheduled Maintenance ID is required");
35
+ }
34
36
 
35
- if (!data.feedInfoInMarkdown) {
36
- throw new BadDataException("Log in markdown is required");
37
- }
37
+ if (!data.feedInfoInMarkdown) {
38
+ throw new BadDataException("Log in markdown is required");
39
+ }
38
40
 
39
- if (!data.scheduledMaintenanceFeedEventType) {
40
- throw new BadDataException("Scheduled Maintenance log event is required");
41
- }
41
+ if (!data.scheduledMaintenanceFeedEventType) {
42
+ throw new BadDataException(
43
+ "Scheduled Maintenance log event is required",
44
+ );
45
+ }
42
46
 
43
- if (!data.projectId) {
44
- throw new BadDataException("Project ID is required");
45
- }
47
+ if (!data.projectId) {
48
+ throw new BadDataException("Project ID is required");
49
+ }
46
50
 
47
- if (!data.displayColor) {
48
- data.displayColor = Blue500;
49
- }
51
+ if (!data.displayColor) {
52
+ data.displayColor = Blue500;
53
+ }
50
54
 
51
- const scheduledMaintenanceFeed: Model = new Model();
55
+ const scheduledMaintenanceFeed: Model = new Model();
52
56
 
53
- scheduledMaintenanceFeed.displayColor = data.displayColor;
54
- scheduledMaintenanceFeed.scheduledMaintenanceId =
55
- data.scheduledMaintenanceId;
56
- scheduledMaintenanceFeed.feedInfoInMarkdown = data.feedInfoInMarkdown;
57
- scheduledMaintenanceFeed.scheduledMaintenanceFeedEventType =
58
- data.scheduledMaintenanceFeedEventType;
59
- scheduledMaintenanceFeed.projectId = data.projectId;
57
+ scheduledMaintenanceFeed.displayColor = data.displayColor;
58
+ scheduledMaintenanceFeed.scheduledMaintenanceId =
59
+ data.scheduledMaintenanceId;
60
+ scheduledMaintenanceFeed.feedInfoInMarkdown = data.feedInfoInMarkdown;
61
+ scheduledMaintenanceFeed.scheduledMaintenanceFeedEventType =
62
+ data.scheduledMaintenanceFeedEventType;
63
+ scheduledMaintenanceFeed.projectId = data.projectId;
60
64
 
61
- if (data.userId) {
62
- scheduledMaintenanceFeed.userId = data.userId;
63
- }
65
+ if (data.userId) {
66
+ scheduledMaintenanceFeed.userId = data.userId;
67
+ }
64
68
 
65
- if (data.moreInformationInMarkdown) {
66
- scheduledMaintenanceFeed.moreInformationInMarkdown =
67
- data.moreInformationInMarkdown;
68
- }
69
+ if (data.moreInformationInMarkdown) {
70
+ scheduledMaintenanceFeed.moreInformationInMarkdown =
71
+ data.moreInformationInMarkdown;
72
+ }
69
73
 
70
- if (!data.postedAt) {
71
- scheduledMaintenanceFeed.postedAt = OneUptimeDate.getCurrentDate();
72
- }
74
+ if (!data.postedAt) {
75
+ scheduledMaintenanceFeed.postedAt = OneUptimeDate.getCurrentDate();
76
+ }
73
77
 
74
- return await this.create({
75
- data: scheduledMaintenanceFeed,
76
- props: {
77
- isRoot: true,
78
- },
79
- });
78
+ await this.create({
79
+ data: scheduledMaintenanceFeed,
80
+ props: {
81
+ isRoot: true,
82
+ },
83
+ });
84
+ } catch (error) {
85
+ logger.error(
86
+ "ScheduledMaintenanceFeedService.createScheduledMaintenanceFeed",
87
+ );
88
+ logger.error(error);
89
+ // we dont want to throw the error here, as this is not critical but we still log it.
90
+ }
80
91
  }
81
92
  }
82
93
 
@@ -1,10 +1,85 @@
1
+ import ObjectID from "../../Types/ObjectID";
2
+ import { OnCreate, OnUpdate } from "../Types/Database/Hooks";
1
3
  import DatabaseService from "./DatabaseService";
2
4
  import Model from "Common/Models/DatabaseModels/ScheduledMaintenanceInternalNote";
5
+ import ScheduledMaintenanceFeedService from "./ScheduledMaintenanceFeedService";
6
+ import { ScheduledMaintenanceFeedEventType } from "../../Models/DatabaseModels/ScheduledMaintenanceFeed";
7
+ import { Blue500 } from "../../Types/BrandColors";
8
+ import { LIMIT_PER_PROJECT } from "../../Types/Database/LimitMax";
3
9
 
4
10
  export class Service extends DatabaseService<Model> {
5
11
  public constructor() {
6
12
  super(Model);
7
13
  }
14
+
15
+ public override async onCreateSuccess(
16
+ _onCreate: OnCreate<Model>,
17
+ createdItem: Model,
18
+ ): Promise<Model> {
19
+ const userId: ObjectID | null | undefined =
20
+ createdItem.createdByUserId || createdItem.createdByUser?.id;
21
+
22
+ await ScheduledMaintenanceFeedService.createScheduledMaintenanceFeed({
23
+ scheduledMaintenanceId: createdItem.scheduledMaintenanceId!,
24
+ projectId: createdItem.projectId!,
25
+ scheduledMaintenanceFeedEventType:
26
+ ScheduledMaintenanceFeedEventType.PrivateNote,
27
+ displayColor: Blue500,
28
+ userId: userId || undefined,
29
+
30
+ feedInfoInMarkdown: `**Posted Internal / Private Note**
31
+
32
+ ${createdItem.note}
33
+ `,
34
+ });
35
+
36
+ return createdItem;
37
+ }
38
+
39
+ public override async onUpdateSuccess(
40
+ onUpdate: OnUpdate<Model>,
41
+ _updatedItemIds: Array<ObjectID>,
42
+ ): Promise<OnUpdate<Model>> {
43
+ if (onUpdate.updateBy.data.note) {
44
+ const updatedItems: Array<Model> = await this.findBy({
45
+ query: onUpdate.updateBy.query,
46
+ limit: LIMIT_PER_PROJECT,
47
+ skip: 0,
48
+ props: {
49
+ isRoot: true,
50
+ },
51
+ select: {
52
+ scheduledMaintenanceId: true,
53
+ projectId: true,
54
+ note: true,
55
+ createdByUserId: true,
56
+ createdByUser: {
57
+ _id: true,
58
+ },
59
+ },
60
+ });
61
+
62
+ const userId: ObjectID | null | undefined =
63
+ onUpdate.updateBy.props.userId;
64
+
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,
73
+
74
+ feedInfoInMarkdown: `**Updated Private Note**
75
+
76
+ ${updatedItem.note}
77
+ `,
78
+ });
79
+ }
80
+ }
81
+ return onUpdate;
82
+ }
8
83
  }
9
84
 
10
85
  export default new Service();
@@ -1,10 +1,126 @@
1
+ import Team from "../../Models/DatabaseModels/Team";
2
+ import ObjectID from "../../Types/ObjectID";
1
3
  import DatabaseService from "./DatabaseService";
2
4
  import Model from "Common/Models/DatabaseModels/ScheduledMaintenanceOwnerTeam";
5
+ import TeamService from "./TeamService";
6
+ import ScheduledMaintenanceFeedService from "./ScheduledMaintenanceFeedService";
7
+ import { ScheduledMaintenanceFeedEventType } from "../../Models/DatabaseModels/ScheduledMaintenanceFeed";
8
+ import { Gray500, Red500 } from "../../Types/BrandColors";
9
+ import { OnCreate, OnDelete } from "../Types/Database/Hooks";
10
+ import DeleteBy from "../Types/Database/DeleteBy";
3
11
 
4
12
  export class Service extends DatabaseService<Model> {
5
13
  public constructor() {
6
14
  super(Model);
7
15
  }
16
+
17
+ protected override async onBeforeDelete(
18
+ deleteBy: DeleteBy<Model>,
19
+ ): Promise<OnDelete<Model>> {
20
+ const itemsToDelete: Model[] = await this.findBy({
21
+ query: deleteBy.query,
22
+ limit: deleteBy.limit,
23
+ skip: deleteBy.skip,
24
+ props: {
25
+ isRoot: true,
26
+ },
27
+ select: {
28
+ scheduledMaintenanceId: true,
29
+ projectId: true,
30
+ teamId: true,
31
+ },
32
+ });
33
+
34
+ return {
35
+ carryForward: {
36
+ itemsToDelete: itemsToDelete,
37
+ },
38
+ deleteBy: deleteBy,
39
+ };
40
+ }
41
+
42
+ protected override async onDeleteSuccess(
43
+ onDelete: OnDelete<Model>,
44
+ _itemIdsBeforeDelete: Array<ObjectID>,
45
+ ): Promise<OnDelete<Model>> {
46
+ const deleteByUserId: ObjectID | undefined =
47
+ onDelete.deleteBy.deletedByUser?.id || onDelete.deleteBy.props.userId;
48
+
49
+ const itemsToDelete: Model[] = onDelete.carryForward.itemsToDelete;
50
+
51
+ for (const item of itemsToDelete) {
52
+ const scheduledMaintenanceId: ObjectID | undefined =
53
+ item.scheduledMaintenanceId;
54
+ const projectId: ObjectID | undefined = item.projectId;
55
+ const teamId: ObjectID | undefined = item.teamId;
56
+
57
+ if (scheduledMaintenanceId && teamId && projectId) {
58
+ const team: Team | null = await TeamService.findOneById({
59
+ id: teamId,
60
+ select: {
61
+ name: true,
62
+ },
63
+ props: {
64
+ isRoot: true,
65
+ },
66
+ });
67
+
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
+ });
78
+ }
79
+ }
80
+ }
81
+
82
+ return onDelete;
83
+ }
84
+
85
+ public override async onCreateSuccess(
86
+ onCreate: OnCreate<Model>,
87
+ createdItem: Model,
88
+ ): Promise<Model> {
89
+ // add scheduledMaintenance feed.
90
+
91
+ const scheduledMaintenanceId: ObjectID | undefined =
92
+ createdItem.scheduledMaintenanceId;
93
+ const projectId: ObjectID | undefined = createdItem.projectId;
94
+ const teamId: ObjectID | undefined = createdItem.teamId;
95
+ const createdByUserId: ObjectID | undefined =
96
+ createdItem.createdByUserId || onCreate.createBy.props.userId;
97
+
98
+ if (scheduledMaintenanceId && teamId && projectId) {
99
+ const team: Team | null = await TeamService.findOneById({
100
+ id: teamId,
101
+ select: {
102
+ name: true,
103
+ },
104
+ props: {
105
+ isRoot: true,
106
+ },
107
+ });
108
+
109
+ 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
+ });
119
+ }
120
+ }
121
+
122
+ return createdItem;
123
+ }
8
124
  }
9
125
 
10
126
  export default new Service();