@oneuptime/common 7.0.4039 → 7.0.4064

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 (92) hide show
  1. package/Models/DatabaseModels/Index.ts +9 -1
  2. package/Models/DatabaseModels/OnCallDutyPolicy.ts +20 -0
  3. package/Models/DatabaseModels/OnCallDutyPolicyFeed.ts +527 -0
  4. package/Models/DatabaseModels/OnCallDutyPolicyOwnerTeam.ts +426 -0
  5. package/Models/DatabaseModels/OnCallDutyPolicyOwnerUser.ts +425 -0
  6. package/Server/API/SlackAPI.ts +14 -0
  7. package/Server/Infrastructure/Postgres/SchemaMigrations/1744804990712-MigrationName.ts +17 -0
  8. package/Server/Infrastructure/Postgres/SchemaMigrations/1744809770336-MigrationName.ts +173 -0
  9. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +4 -0
  10. package/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.ts +71 -2
  11. package/Server/Services/OnCallDutyPolicyEscalationRuleService.ts +14 -0
  12. package/Server/Services/OnCallDutyPolicyEscalationRuleTeamService.ts +69 -2
  13. package/Server/Services/OnCallDutyPolicyEscalationRuleUserService.ts +77 -2
  14. package/Server/Services/OnCallDutyPolicyExecutionLogService.ts +1 -1
  15. package/Server/Services/OnCallDutyPolicyExecutionLogTimelineService.ts +1 -1
  16. package/Server/Services/OnCallDutyPolicyFeedService.ts +156 -0
  17. package/Server/Services/OnCallDutyPolicyOwnerTeamService.ts +181 -0
  18. package/Server/Services/OnCallDutyPolicyOwnerUserService.ts +174 -0
  19. package/Server/Services/OnCallDutyPolicyScheduleService.ts +101 -9
  20. package/Server/Services/OnCallDutyPolicyService.ts +219 -1
  21. package/Server/Services/OnCallDutyPolicyUserOverrideService.ts +184 -1
  22. package/Server/Services/WorkspaceNotificationRuleService.ts +93 -0
  23. package/Server/Utils/StartServer.ts +5 -2
  24. package/Server/Utils/Workspace/Slack/Actions/ActionTypes.ts +3 -0
  25. package/Server/Utils/Workspace/Slack/Actions/OnCallDutyPolicy.ts +48 -0
  26. package/Server/Utils/Workspace/Slack/Messages/OnCallDutyPolicy.ts +62 -0
  27. package/Server/Utils/Workspace/WorkspaceMessages/OnCallDutyPolicy.ts +75 -0
  28. package/Types/Permission.ts +112 -7
  29. package/Types/Workspace/NotificationRules/EventType.ts +1 -0
  30. package/Types/Workspace/NotificationRules/NotificationRuleCondition.ts +5 -0
  31. package/UI/webpack-middleware.js +65 -0
  32. package/build/dist/Models/DatabaseModels/Index.js +8 -0
  33. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  34. package/build/dist/Models/DatabaseModels/OnCallDutyPolicy.js +20 -0
  35. package/build/dist/Models/DatabaseModels/OnCallDutyPolicy.js.map +1 -1
  36. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyFeed.js +549 -0
  37. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyFeed.js.map +1 -0
  38. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyOwnerTeam.js +442 -0
  39. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyOwnerTeam.js.map +1 -0
  40. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyOwnerUser.js +441 -0
  41. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyOwnerUser.js.map +1 -0
  42. package/build/dist/Server/API/SlackAPI.js +11 -0
  43. package/build/dist/Server/API/SlackAPI.js.map +1 -1
  44. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1744804990712-MigrationName.js +12 -0
  45. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1744804990712-MigrationName.js.map +1 -0
  46. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1744809770336-MigrationName.js +66 -0
  47. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1744809770336-MigrationName.js.map +1 -0
  48. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +4 -0
  49. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  50. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js +52 -3
  51. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js.map +1 -1
  52. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleService.js +12 -0
  53. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleService.js.map +1 -1
  54. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleTeamService.js +52 -3
  55. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleTeamService.js.map +1 -1
  56. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleUserService.js +63 -3
  57. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleUserService.js.map +1 -1
  58. package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogService.js +1 -1
  59. package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogService.js.map +1 -1
  60. package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogTimelineService.js +1 -1
  61. package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogTimelineService.js.map +1 -1
  62. package/build/dist/Server/Services/OnCallDutyPolicyFeedService.js +119 -0
  63. package/build/dist/Server/Services/OnCallDutyPolicyFeedService.js.map +1 -0
  64. package/build/dist/Server/Services/OnCallDutyPolicyOwnerTeamService.js +161 -0
  65. package/build/dist/Server/Services/OnCallDutyPolicyOwnerTeamService.js.map +1 -0
  66. package/build/dist/Server/Services/OnCallDutyPolicyOwnerUserService.js +154 -0
  67. package/build/dist/Server/Services/OnCallDutyPolicyOwnerUserService.js.map +1 -0
  68. package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js +87 -20
  69. package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js.map +1 -1
  70. package/build/dist/Server/Services/OnCallDutyPolicyService.js +174 -2
  71. package/build/dist/Server/Services/OnCallDutyPolicyService.js.map +1 -1
  72. package/build/dist/Server/Services/OnCallDutyPolicyUserOverrideService.js +122 -0
  73. package/build/dist/Server/Services/OnCallDutyPolicyUserOverrideService.js.map +1 -1
  74. package/build/dist/Server/Services/WorkspaceNotificationRuleService.js +71 -0
  75. package/build/dist/Server/Services/WorkspaceNotificationRuleService.js.map +1 -1
  76. package/build/dist/Server/Utils/StartServer.js +5 -2
  77. package/build/dist/Server/Utils/StartServer.js.map +1 -1
  78. package/build/dist/Server/Utils/Workspace/Slack/Actions/ActionTypes.js +2 -0
  79. package/build/dist/Server/Utils/Workspace/Slack/Actions/ActionTypes.js.map +1 -1
  80. package/build/dist/Server/Utils/Workspace/Slack/Actions/OnCallDutyPolicy.js +50 -0
  81. package/build/dist/Server/Utils/Workspace/Slack/Actions/OnCallDutyPolicy.js.map +1 -0
  82. package/build/dist/Server/Utils/Workspace/Slack/Messages/OnCallDutyPolicy.js +52 -0
  83. package/build/dist/Server/Utils/Workspace/Slack/Messages/OnCallDutyPolicy.js.map +1 -0
  84. package/build/dist/Server/Utils/Workspace/WorkspaceMessages/OnCallDutyPolicy.js +69 -0
  85. package/build/dist/Server/Utils/Workspace/WorkspaceMessages/OnCallDutyPolicy.js.map +1 -0
  86. package/build/dist/Types/Permission.js +95 -7
  87. package/build/dist/Types/Permission.js.map +1 -1
  88. package/build/dist/Types/Workspace/NotificationRules/EventType.js +1 -0
  89. package/build/dist/Types/Workspace/NotificationRules/EventType.js.map +1 -1
  90. package/build/dist/Types/Workspace/NotificationRules/NotificationRuleCondition.js +4 -0
  91. package/build/dist/Types/Workspace/NotificationRules/NotificationRuleCondition.js.map +1 -1
  92. package/package.json +2 -2
@@ -0,0 +1,181 @@
1
+ import ObjectID from "../../Types/ObjectID";
2
+ import { OnCreate, OnDelete } from "../Types/Database/Hooks";
3
+ import DatabaseService from "./DatabaseService";
4
+ import Model from "Common/Models/DatabaseModels/OnCallDutyPolicyOwnerTeam";
5
+ import OnCallDutyPolicyFeedService from "./OnCallDutyPolicyFeedService";
6
+ import { OnCallDutyPolicyFeedEventType } from "../../Models/DatabaseModels/OnCallDutyPolicyFeed";
7
+ import { Gray500, Red500 } from "../../Types/BrandColors";
8
+ import TeamService from "./TeamService";
9
+ import Team from "../../Models/DatabaseModels/Team";
10
+ import DeleteBy from "../Types/Database/DeleteBy";
11
+ import OnCallDutyPolicyService from "./OnCallDutyPolicyService";
12
+ import WorkspaceNotificationRuleService from "./WorkspaceNotificationRuleService";
13
+ import NotificationRuleEventType from "../../Types/Workspace/NotificationRules/EventType";
14
+ import WorkspaceNotificationRule from "../../Models/DatabaseModels/WorkspaceNotificationRule";
15
+ import logger from "../Utils/Logger";
16
+ import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
17
+
18
+ export class Service extends DatabaseService<Model> {
19
+ public constructor() {
20
+ super(Model);
21
+ }
22
+
23
+ @CaptureSpan()
24
+ protected override async onBeforeDelete(
25
+ deleteBy: DeleteBy<Model>,
26
+ ): Promise<OnDelete<Model>> {
27
+ const itemsToDelete: Model[] = await this.findBy({
28
+ query: deleteBy.query,
29
+ limit: deleteBy.limit,
30
+ skip: deleteBy.skip,
31
+ props: {
32
+ isRoot: true,
33
+ },
34
+ select: {
35
+ onCallDutyPolicyId: true,
36
+ projectId: true,
37
+ teamId: true,
38
+ },
39
+ });
40
+
41
+ return {
42
+ carryForward: {
43
+ itemsToDelete: itemsToDelete,
44
+ },
45
+ deleteBy: deleteBy,
46
+ };
47
+ }
48
+
49
+ @CaptureSpan()
50
+ protected override async onDeleteSuccess(
51
+ onDelete: OnDelete<Model>,
52
+ _itemIdsBeforeDelete: Array<ObjectID>,
53
+ ): Promise<OnDelete<Model>> {
54
+ const deleteByUserId: ObjectID | undefined =
55
+ onDelete.deleteBy.deletedByUser?.id || onDelete.deleteBy.props.userId;
56
+
57
+ const itemsToDelete: Model[] = onDelete.carryForward.itemsToDelete;
58
+
59
+ for (const item of itemsToDelete) {
60
+ const onCallDutyPolicyId: ObjectID | undefined = item.onCallDutyPolicyId;
61
+ const projectId: ObjectID | undefined = item.projectId;
62
+ const teamId: ObjectID | undefined = item.teamId;
63
+
64
+ if (onCallDutyPolicyId && teamId && projectId) {
65
+ const team: Team | null = await TeamService.findOneById({
66
+ id: teamId,
67
+ select: {
68
+ name: true,
69
+ },
70
+ props: {
71
+ isRoot: true,
72
+ },
73
+ });
74
+
75
+ const onCallDutyPolicyName: string | null =
76
+ await OnCallDutyPolicyService.getOnCallDutyPolicyName({
77
+ onCallDutyPolicyId: onCallDutyPolicyId,
78
+ });
79
+
80
+ if (team && team.name) {
81
+ await OnCallDutyPolicyFeedService.createOnCallDutyPolicyFeedItem({
82
+ onCallDutyPolicyId: onCallDutyPolicyId,
83
+ projectId: projectId,
84
+ onCallDutyPolicyFeedEventType:
85
+ OnCallDutyPolicyFeedEventType.OwnerTeamRemoved,
86
+ displayColor: Red500,
87
+ feedInfoInMarkdown: `👨🏻‍👩🏻‍👦🏻 Removed team **${team.name}** from the [On-Call Policy ${onCallDutyPolicyName}](${(await OnCallDutyPolicyService.getOnCallDutyPolicyLinkInDashboard(projectId!, onCallDutyPolicyId!)).toString()}) as the owner.`,
88
+ userId: deleteByUserId || undefined,
89
+ workspaceNotification: {
90
+ sendWorkspaceNotification: true,
91
+ notifyUserId: deleteByUserId || undefined,
92
+ },
93
+ });
94
+ }
95
+ }
96
+ }
97
+
98
+ return onDelete;
99
+ }
100
+
101
+ @CaptureSpan()
102
+ public override async onCreateSuccess(
103
+ onCreate: OnCreate<Model>,
104
+ createdItem: Model,
105
+ ): Promise<Model> {
106
+ // add onCallDutyPolicy feed.
107
+
108
+ const onCallDutyPolicyId: ObjectID | undefined =
109
+ createdItem.onCallDutyPolicyId;
110
+ const projectId: ObjectID | undefined = createdItem.projectId;
111
+ const teamId: ObjectID | undefined = createdItem.teamId;
112
+ const createdByUserId: ObjectID | undefined =
113
+ createdItem.createdByUserId || onCreate.createBy.props.userId;
114
+
115
+ if (onCallDutyPolicyId && teamId && projectId) {
116
+ const team: Team | null = await TeamService.findOneById({
117
+ id: teamId,
118
+ select: {
119
+ name: true,
120
+ },
121
+ props: {
122
+ isRoot: true,
123
+ },
124
+ });
125
+
126
+ if (team && team.name) {
127
+ const onCallDutyPolicyName: string | null =
128
+ await OnCallDutyPolicyService.getOnCallDutyPolicyName({
129
+ onCallDutyPolicyId: onCallDutyPolicyId,
130
+ });
131
+
132
+ await OnCallDutyPolicyFeedService.createOnCallDutyPolicyFeedItem({
133
+ onCallDutyPolicyId: onCallDutyPolicyId,
134
+ projectId: projectId,
135
+ onCallDutyPolicyFeedEventType:
136
+ OnCallDutyPolicyFeedEventType.OwnerTeamAdded,
137
+ displayColor: Gray500,
138
+ feedInfoInMarkdown: `👨🏻‍👩🏻‍👦🏻 Added team **${team.name}** to the [On-Call Policy ${onCallDutyPolicyName}](${(await OnCallDutyPolicyService.getOnCallDutyPolicyLinkInDashboard(projectId!, onCallDutyPolicyId!)).toString()}) as the owner.`,
139
+ userId: createdByUserId || undefined,
140
+ workspaceNotification: {
141
+ sendWorkspaceNotification: true,
142
+ notifyUserId: createdByUserId || undefined,
143
+ },
144
+ });
145
+ }
146
+ }
147
+
148
+ // get notification rule where inviteOwners is true.
149
+ const notificationRules: Array<WorkspaceNotificationRule> =
150
+ await WorkspaceNotificationRuleService.getNotificationRulesWhereInviteOwnersIsTrue(
151
+ {
152
+ projectId: projectId!,
153
+ notificationFor: {
154
+ onCallDutyPolicyId: onCallDutyPolicyId,
155
+ },
156
+ notificationRuleEventType: NotificationRuleEventType.OnCallDutyPolicy,
157
+ },
158
+ );
159
+
160
+ logger.debug(`Notification Rules for OnCallDutyPolicy Owner Teams`);
161
+ logger.debug(notificationRules);
162
+
163
+ WorkspaceNotificationRuleService.inviteTeamsBasedOnRulesAndWorkspaceChannels(
164
+ {
165
+ notificationRules: notificationRules,
166
+ projectId: projectId!,
167
+ workspaceChannels:
168
+ await OnCallDutyPolicyService.getWorkspaceChannelForOnCallDutyPolicy({
169
+ onCallDutyPolicyId: onCallDutyPolicyId!,
170
+ }),
171
+ teamIds: [teamId!],
172
+ },
173
+ ).catch((error: Error) => {
174
+ logger.error(error);
175
+ });
176
+
177
+ return createdItem;
178
+ }
179
+ }
180
+
181
+ export default new Service();
@@ -0,0 +1,174 @@
1
+ import ObjectID from "../../Types/ObjectID";
2
+ import DatabaseService from "./DatabaseService";
3
+ import Model from "Common/Models/DatabaseModels/OnCallDutyPolicyOwnerUser";
4
+ import OnCallDutyPolicyFeedService from "./OnCallDutyPolicyFeedService";
5
+ import { OnCallDutyPolicyFeedEventType } from "../../Models/DatabaseModels/OnCallDutyPolicyFeed";
6
+ import { Gray500, Red500 } from "../../Types/BrandColors";
7
+ import User from "../../Models/DatabaseModels/User";
8
+ import UserService from "./UserService";
9
+ import { OnCreate, OnDelete } from "../Types/Database/Hooks";
10
+ import DeleteBy from "../Types/Database/DeleteBy";
11
+ import OnCallDutyPolicyService from "./OnCallDutyPolicyService";
12
+ import WorkspaceNotificationRuleService from "./WorkspaceNotificationRuleService";
13
+ import NotificationRuleEventType from "../../Types/Workspace/NotificationRules/EventType";
14
+ import WorkspaceNotificationRule from "../../Models/DatabaseModels/WorkspaceNotificationRule";
15
+ import logger from "../Utils/Logger";
16
+ import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
17
+
18
+ export class Service extends DatabaseService<Model> {
19
+ public constructor() {
20
+ super(Model);
21
+ }
22
+
23
+ @CaptureSpan()
24
+ protected override async onBeforeDelete(
25
+ deleteBy: DeleteBy<Model>,
26
+ ): Promise<OnDelete<Model>> {
27
+ const itemsToDelete: Model[] = await this.findBy({
28
+ query: deleteBy.query,
29
+ limit: deleteBy.limit,
30
+ skip: deleteBy.skip,
31
+ props: {
32
+ isRoot: true,
33
+ },
34
+ select: {
35
+ onCallDutyPolicyId: true,
36
+ projectId: true,
37
+ userId: true,
38
+ },
39
+ });
40
+
41
+ return {
42
+ carryForward: {
43
+ itemsToDelete: itemsToDelete,
44
+ },
45
+ deleteBy: deleteBy,
46
+ };
47
+ }
48
+
49
+ @CaptureSpan()
50
+ protected override async onDeleteSuccess(
51
+ onDelete: OnDelete<Model>,
52
+ _itemIdsBeforeDelete: Array<ObjectID>,
53
+ ): Promise<OnDelete<Model>> {
54
+ const deleteByUserId: ObjectID | undefined =
55
+ onDelete.deleteBy.deletedByUser?.id || onDelete.deleteBy.props.userId;
56
+
57
+ const itemsToDelete: Model[] = onDelete.carryForward.itemsToDelete;
58
+
59
+ for (const item of itemsToDelete) {
60
+ const onCallDutyPolicyId: ObjectID | undefined = item.onCallDutyPolicyId;
61
+ const projectId: ObjectID | undefined = item.projectId;
62
+ const userId: ObjectID | undefined = item.userId;
63
+
64
+ if (onCallDutyPolicyId && userId && projectId) {
65
+ const user: User | null = await UserService.findOneById({
66
+ id: userId,
67
+ select: {
68
+ name: true,
69
+ email: true,
70
+ },
71
+ props: {
72
+ isRoot: true,
73
+ },
74
+ });
75
+
76
+ const onCallDutyPolicyName: string | null =
77
+ await OnCallDutyPolicyService.getOnCallDutyPolicyName({
78
+ onCallDutyPolicyId: onCallDutyPolicyId,
79
+ });
80
+
81
+ if (user && user.name) {
82
+ await OnCallDutyPolicyFeedService.createOnCallDutyPolicyFeedItem({
83
+ onCallDutyPolicyId: onCallDutyPolicyId,
84
+ projectId: projectId,
85
+ onCallDutyPolicyFeedEventType:
86
+ OnCallDutyPolicyFeedEventType.OwnerUserRemoved,
87
+ displayColor: Red500,
88
+ feedInfoInMarkdown: `👨🏻‍💻 Removed **${user.name.toString()}** (${user.email?.toString()}) from the [On-Call Policy ${onCallDutyPolicyName}](${(await OnCallDutyPolicyService.getOnCallDutyPolicyLinkInDashboard(projectId!, onCallDutyPolicyId!)).toString()}) as the owner.`,
89
+ userId: deleteByUserId || undefined,
90
+ workspaceNotification: {
91
+ sendWorkspaceNotification: true,
92
+ notifyUserId: userId || undefined,
93
+ },
94
+ });
95
+ }
96
+ }
97
+ }
98
+
99
+ return onDelete;
100
+ }
101
+
102
+ @CaptureSpan()
103
+ public override async onCreateSuccess(
104
+ onCreate: OnCreate<Model>,
105
+ createdItem: Model,
106
+ ): Promise<Model> {
107
+ // add onCallDutyPolicy feed.
108
+
109
+ const onCallDutyPolicyId: ObjectID | undefined =
110
+ createdItem.onCallDutyPolicyId;
111
+ const projectId: ObjectID | undefined = createdItem.projectId;
112
+ const userId: ObjectID | undefined = createdItem.userId;
113
+ const createdByUserId: ObjectID | undefined =
114
+ createdItem.createdByUserId || onCreate.createBy.props.userId;
115
+
116
+ if (onCallDutyPolicyId && userId && projectId) {
117
+ const onCallDutyPolicyName: string | null =
118
+ await OnCallDutyPolicyService.getOnCallDutyPolicyName({
119
+ onCallDutyPolicyId: onCallDutyPolicyId,
120
+ });
121
+
122
+ if (userId) {
123
+ await OnCallDutyPolicyFeedService.createOnCallDutyPolicyFeedItem({
124
+ onCallDutyPolicyId: onCallDutyPolicyId,
125
+ projectId: projectId,
126
+ onCallDutyPolicyFeedEventType:
127
+ OnCallDutyPolicyFeedEventType.OwnerUserAdded,
128
+ displayColor: Gray500,
129
+ feedInfoInMarkdown: `👨🏻‍💻 Added **${await UserService.getUserMarkdownString(
130
+ {
131
+ userId: userId,
132
+ projectId: projectId,
133
+ },
134
+ )}** to the [On-Call Policy ${onCallDutyPolicyName}](${(await OnCallDutyPolicyService.getOnCallDutyPolicyLinkInDashboard(projectId!, onCallDutyPolicyId!)).toString()}) as the owner.`,
135
+ userId: createdByUserId || undefined,
136
+ workspaceNotification: {
137
+ sendWorkspaceNotification: true,
138
+ notifyUserId: userId || undefined,
139
+ },
140
+ });
141
+ }
142
+ }
143
+
144
+ // get notification rule where inviteOwners is true.
145
+ const notificationRules: Array<WorkspaceNotificationRule> =
146
+ await WorkspaceNotificationRuleService.getNotificationRulesWhereInviteOwnersIsTrue(
147
+ {
148
+ projectId: projectId!,
149
+ notificationFor: {
150
+ onCallDutyPolicyId: onCallDutyPolicyId,
151
+ },
152
+ notificationRuleEventType: NotificationRuleEventType.OnCallDutyPolicy,
153
+ },
154
+ );
155
+
156
+ WorkspaceNotificationRuleService.inviteUsersBasedOnRulesAndWorkspaceChannels(
157
+ {
158
+ notificationRules: notificationRules,
159
+ projectId: projectId!,
160
+ workspaceChannels:
161
+ await OnCallDutyPolicyService.getWorkspaceChannelForOnCallDutyPolicy({
162
+ onCallDutyPolicyId: onCallDutyPolicyId!,
163
+ }),
164
+ userIds: [userId!],
165
+ },
166
+ ).catch((error: Error) => {
167
+ logger.error(error);
168
+ });
169
+
170
+ return createdItem;
171
+ }
172
+ }
173
+
174
+ export default new Service();
@@ -28,6 +28,9 @@ import NotificationSettingEventType from "../../Types/NotificationSetting/Notifi
28
28
  import BadDataException from "../../Types/Exception/BadDataException";
29
29
  import Timezone from "../../Types/Timezone";
30
30
  import logger from "../Utils/Logger";
31
+ import OnCallDutyPolicyFeedService from "./OnCallDutyPolicyFeedService";
32
+ import { OnCallDutyPolicyFeedEventType } from "../../Models/DatabaseModels/OnCallDutyPolicyFeed";
33
+ import { Green500 } from "../../Types/BrandColors";
31
34
 
32
35
  export class Service extends DatabaseService<OnCallDutyPolicySchedule> {
33
36
  private layerUtil = new LayerUtil();
@@ -177,7 +180,7 @@ export class Service extends DatabaseService<OnCallDutyPolicySchedule> {
177
180
  rosterStartsAt:
178
181
  OneUptimeDate.getDateAsFormattedHTMLInMultipleTimezones({
179
182
  date: previousInformation.rosterStartAt!,
180
- timezones: userTimezone ? [userTimezone] : [],
183
+ timezones: userTimezone ? [userTimezone] : [Timezone.GMT],
181
184
  }),
182
185
  rosterEndsAt:
183
186
  OneUptimeDate.getDateAsFormattedHTMLInMultipleTimezones({
@@ -186,10 +189,10 @@ export class Service extends DatabaseService<OnCallDutyPolicySchedule> {
186
189
  )
187
190
  ? OneUptimeDate.getCurrentDate()
188
191
  : previousInformation.rosterHandoffAt!,
189
- timezones: userTimezone ? [userTimezone] : [],
192
+ timezones: userTimezone ? [userTimezone] : [Timezone.GMT],
190
193
  }),
191
194
  onCallPolicyViewLink: (
192
- await OnCallDutyPolicyService.getOnCallPolicyLinkInDashboard(
195
+ await OnCallDutyPolicyService.getOnCallDutyPolicyLinkInDashboard(
193
196
  projectId,
194
197
  onCallPolicy.id!,
195
198
  )
@@ -224,6 +227,29 @@ export class Service extends DatabaseService<OnCallDutyPolicySchedule> {
224
227
  eventType:
225
228
  NotificationSettingEventType.SEND_WHEN_USER_IS_NO_LONGER_ACTIVE_ON_ON_CALL_ROSTER,
226
229
  });
230
+
231
+ const onCallDutyPolicyId: ObjectID =
232
+ escalationRule.onCallDutyPolicy!.id!;
233
+
234
+ // Send workspace notifiction as well.
235
+ await OnCallDutyPolicyFeedService.createOnCallDutyPolicyFeedItem({
236
+ onCallDutyPolicyId: onCallDutyPolicyId,
237
+ projectId: projectId!,
238
+ onCallDutyPolicyFeedEventType:
239
+ OnCallDutyPolicyFeedEventType.RosterHandoff,
240
+ displayColor: Green500,
241
+ feedInfoInMarkdown: `📵 **${await UserService.getUserMarkdownString(
242
+ {
243
+ userId: sendEmailToUserId,
244
+ projectId: projectId!,
245
+ },
246
+ )}** is no longer on call for [On-Call Policy ${escalationRule.onCallDutyPolicy?.name}](${(await OnCallDutyPolicyService.getOnCallDutyPolicyLinkInDashboard(projectId!, onCallDutyPolicyId!)).toString()}) escalation rule **${escalationRule.onCallDutyPolicyEscalationRule?.name}** with order **${escalationRule.onCallDutyPolicyEscalationRule?.order}** because your on-call roster on schedule **${onCallSchedule.name}** just ended.`,
247
+ userId: sendEmailToUserId || undefined,
248
+ workspaceNotification: {
249
+ sendWorkspaceNotification: true,
250
+ notifyUserId: undefined,
251
+ },
252
+ });
227
253
  }
228
254
 
229
255
  if (newInformation.currentUserIdOnRoster?.toString()) {
@@ -247,15 +273,15 @@ export class Service extends DatabaseService<OnCallDutyPolicySchedule> {
247
273
  rosterStartsAt:
248
274
  OneUptimeDate.getDateAsFormattedHTMLInMultipleTimezones({
249
275
  date: newInformation.rosterStartAt!,
250
- timezones: userTimezone ? [userTimezone] : [],
276
+ timezones: userTimezone ? [userTimezone] : [Timezone.GMT],
251
277
  }),
252
278
  rosterEndsAt:
253
279
  OneUptimeDate.getDateAsFormattedHTMLInMultipleTimezones({
254
280
  date: newInformation.rosterHandoffAt!,
255
- timezones: userTimezone ? [userTimezone] : [],
281
+ timezones: userTimezone ? [userTimezone] : [Timezone.GMT],
256
282
  }),
257
283
  onCallPolicyViewLink: (
258
- await OnCallDutyPolicyService.getOnCallPolicyLinkInDashboard(
284
+ await OnCallDutyPolicyService.getOnCallDutyPolicyLinkInDashboard(
259
285
  projectId,
260
286
  onCallPolicy.id!,
261
287
  )
@@ -289,6 +315,39 @@ export class Service extends DatabaseService<OnCallDutyPolicySchedule> {
289
315
  eventType:
290
316
  NotificationSettingEventType.SEND_WHEN_USER_IS_ON_CALL_ROSTER,
291
317
  });
318
+
319
+ const onCallDutyPolicyId: ObjectID =
320
+ escalationRule.onCallDutyPolicy!.id!;
321
+
322
+ // Send workspace notifiction as well.
323
+ await OnCallDutyPolicyFeedService.createOnCallDutyPolicyFeedItem({
324
+ onCallDutyPolicyId: onCallDutyPolicyId,
325
+ projectId: projectId!,
326
+ onCallDutyPolicyFeedEventType:
327
+ OnCallDutyPolicyFeedEventType.RosterHandoff,
328
+ displayColor: Green500,
329
+ feedInfoInMarkdown: `📞 **${await UserService.getUserMarkdownString(
330
+ {
331
+ userId: sendEmailToUserId,
332
+ projectId: projectId!,
333
+ },
334
+ )}** is currently on call for [On-Call Policy ${escalationRule.onCallDutyPolicy?.name}](${(await OnCallDutyPolicyService.getOnCallDutyPolicyLinkInDashboard(projectId!, onCallDutyPolicyId!)).toString()}) escalation rule **${escalationRule.onCallDutyPolicyEscalationRule?.name}** with order **${escalationRule.onCallDutyPolicyEscalationRule?.order}** because of schedule **${onCallSchedule.name}** and your on-call roster starts at **${OneUptimeDate.getDateAsFormattedStringInMultipleTimezones(
335
+ {
336
+ date: newInformation.rosterStartAt!,
337
+ timezones: userTimezone ? [userTimezone] : [Timezone.GMT],
338
+ },
339
+ )}** and ends at **${OneUptimeDate.getDateAsFormattedStringInMultipleTimezones(
340
+ {
341
+ date: newInformation.rosterHandoffAt!,
342
+ timezones: userTimezone ? [userTimezone] : [Timezone.GMT],
343
+ },
344
+ )}**.`,
345
+ userId: sendEmailToUserId || undefined,
346
+ workspaceNotification: {
347
+ sendWorkspaceNotification: true,
348
+ notifyUserId: undefined,
349
+ },
350
+ });
292
351
  }
293
352
  }
294
353
 
@@ -322,15 +381,15 @@ export class Service extends DatabaseService<OnCallDutyPolicySchedule> {
322
381
  rosterStartsAt:
323
382
  OneUptimeDate.getDateAsFormattedHTMLInMultipleTimezones({
324
383
  date: newInformation.nextRosterStartAt!,
325
- timezones: userTimezone ? [userTimezone] : [],
384
+ timezones: userTimezone ? [userTimezone] : [Timezone.GMT],
326
385
  }),
327
386
  rosterEndsAt:
328
387
  OneUptimeDate.getDateAsFormattedHTMLInMultipleTimezones({
329
388
  date: newInformation.nextHandOffTimeAt!,
330
- timezones: userTimezone ? [userTimezone] : [],
389
+ timezones: userTimezone ? [userTimezone] : [Timezone.GMT],
331
390
  }),
332
391
  onCallPolicyViewLink: (
333
- await OnCallDutyPolicyService.getOnCallPolicyLinkInDashboard(
392
+ await OnCallDutyPolicyService.getOnCallDutyPolicyLinkInDashboard(
334
393
  projectId,
335
394
  onCallPolicy.id!,
336
395
  )
@@ -364,6 +423,39 @@ export class Service extends DatabaseService<OnCallDutyPolicySchedule> {
364
423
  eventType:
365
424
  NotificationSettingEventType.SEND_WHEN_USER_IS_NEXT_ON_CALL_ROSTER,
366
425
  });
426
+
427
+ const onCallDutyPolicyId: ObjectID =
428
+ escalationRule.onCallDutyPolicy!.id!;
429
+
430
+ // Send workspace notifiction as well.
431
+ await OnCallDutyPolicyFeedService.createOnCallDutyPolicyFeedItem({
432
+ onCallDutyPolicyId: onCallDutyPolicyId,
433
+ projectId: projectId!,
434
+ onCallDutyPolicyFeedEventType:
435
+ OnCallDutyPolicyFeedEventType.RosterHandoff,
436
+ displayColor: Green500,
437
+ feedInfoInMarkdown: `➡️ **${await UserService.getUserMarkdownString(
438
+ {
439
+ userId: sendEmailToUserId,
440
+ projectId: projectId!,
441
+ },
442
+ )}** is next on call for [On-Call Policy ${escalationRule.onCallDutyPolicy?.name}](${(await OnCallDutyPolicyService.getOnCallDutyPolicyLinkInDashboard(projectId!, onCallDutyPolicyId!)).toString()}) escalation rule **${escalationRule.onCallDutyPolicyEscalationRule?.name}** with order **${escalationRule.onCallDutyPolicyEscalationRule?.order}**. The on-call roster on schedule **${onCallSchedule.name}** will start when the next handoff happens which is at **${OneUptimeDate.getDateAsFormattedStringInMultipleTimezones(
443
+ {
444
+ date: newInformation.nextRosterStartAt!,
445
+ timezones: userTimezone ? [userTimezone] : [Timezone.GMT],
446
+ },
447
+ )}** and will end at **${OneUptimeDate.getDateAsFormattedStringInMultipleTimezones(
448
+ {
449
+ date: newInformation.nextHandOffTimeAt!,
450
+ timezones: userTimezone ? [userTimezone] : [Timezone.GMT],
451
+ },
452
+ )}**.`,
453
+ userId: sendEmailToUserId || undefined,
454
+ workspaceNotification: {
455
+ sendWorkspaceNotification: true,
456
+ notifyUserId: undefined,
457
+ },
458
+ });
367
459
  }
368
460
  }
369
461
  }