@oneuptime/common 7.0.3480 → 7.0.3517

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 (209) hide show
  1. package/Models/DatabaseModels/{AlertLog.ts → AlertFeed.ts} +157 -33
  2. package/Models/DatabaseModels/Incident.ts +6 -1
  3. package/Models/DatabaseModels/{IncidentLog.ts → IncidentFeed.ts} +169 -37
  4. package/Models/DatabaseModels/Index.ts +6 -6
  5. package/Models/DatabaseModels/{ScheduledMaintenanceLog.ts → ScheduledMaintenanceFeed.ts} +155 -31
  6. package/Server/Infrastructure/Postgres/SchemaMigrations/1736703138918-MigrationName.ts +29 -0
  7. package/Server/Infrastructure/Postgres/SchemaMigrations/1736780194077-MigrationName.ts +137 -0
  8. package/Server/Infrastructure/Postgres/SchemaMigrations/1736780194078-MigrationName.ts +16 -0
  9. package/Server/Infrastructure/Postgres/SchemaMigrations/1736787495707-MigrationName.ts +29 -0
  10. package/Server/Infrastructure/Postgres/SchemaMigrations/1736787985322-MigrationName.ts +83 -0
  11. package/Server/Infrastructure/Postgres/SchemaMigrations/1736788706141-MigrationName.ts +39 -0
  12. package/Server/Infrastructure/Postgres/SchemaMigrations/1736856662868-MigrationName.ts +27 -0
  13. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +14 -0
  14. package/Server/Services/AlertFeedService.ts +81 -0
  15. package/Server/Services/IncidentFeedService.ts +89 -0
  16. package/Server/Services/IncidentInternalNoteService.ts +28 -0
  17. package/Server/Services/IncidentOwnerTeamService.ts +112 -0
  18. package/Server/Services/IncidentOwnerUserService.ts +114 -0
  19. package/Server/Services/IncidentPublicNoteService.ts +26 -0
  20. package/Server/Services/IncidentService.ts +121 -0
  21. package/Server/Services/IncidentStateTimelineService.ts +43 -19
  22. package/Server/Services/Index.ts +6 -6
  23. package/Server/Services/OnCallDutyPolicyExecutionLogService.ts +116 -1
  24. package/Server/Services/OnCallDutyPolicyExecutionLogTimelineService.ts +169 -0
  25. package/Server/Services/ScheduledMaintenanceFeedService.ts +83 -0
  26. package/Server/Services/UserOnCallLogService.ts +2 -2
  27. package/Tests/Types/Database/ColumnLength.test.ts +1 -1
  28. package/Types/Database/ColumnLength.ts +1 -1
  29. package/Types/Database/LimitMax.ts +1 -1
  30. package/Types/Icon/IconProp.ts +1 -0
  31. package/Types/Permission.ts +32 -32
  32. package/UI/Components/CategoryCheckbox/Index.tsx +1 -1
  33. package/UI/Components/CustomFields/CustomFieldsDetail.tsx +3 -3
  34. package/UI/Components/ErrorMessage/ErrorMessage.tsx +2 -2
  35. package/UI/Components/Feed/Feed.tsx +31 -0
  36. package/UI/Components/Feed/FeedItem.tsx +176 -0
  37. package/UI/Components/Filters/FilterViewer.tsx +1 -1
  38. package/UI/Components/Filters/FiltersForm.tsx +1 -1
  39. package/UI/Components/FormModal/BasicFormModal.tsx +1 -1
  40. package/UI/Components/Forms/BasicForm.tsx +1 -1
  41. package/UI/Components/Icon/Icon.tsx +16 -0
  42. package/UI/Components/InfoCard/InfoCard.tsx +1 -3
  43. package/UI/Components/List/List.tsx +2 -2
  44. package/UI/Components/LogsViewer/LogsViewer.tsx +1 -1
  45. package/UI/Components/ModelDetail/ModelDetail.tsx +1 -1
  46. package/UI/Components/ModelList/ModelList.tsx +2 -2
  47. package/UI/Components/ModelProgress/ModelProgress.tsx +1 -1
  48. package/UI/Components/ModelTable/BaseModelTable.tsx +3 -3
  49. package/UI/Components/MonitorGraphs/Uptime.tsx +1 -1
  50. package/UI/Components/OrderedStatesList/OrderedStatesList.tsx +5 -2
  51. package/UI/Components/Page/Page.tsx +1 -1
  52. package/UI/Components/ProgressButtons/ProgressButtonItem.tsx +107 -0
  53. package/UI/Components/ProgressButtons/ProgressButtons.tsx +88 -0
  54. package/UI/Components/QR/QR.tsx +1 -1
  55. package/UI/Components/Table/Table.tsx +2 -2
  56. package/UI/Components/Workflow/ArgumentsForm.tsx +1 -1
  57. package/UI/Components/Workflow/ComponentArgumentsViewer.tsx +1 -1
  58. package/UI/Components/Workflow/ComponentPortViewer.tsx +1 -1
  59. package/UI/Components/Workflow/ComponentReturnValueViewer.tsx +1 -1
  60. package/UI/Components/Workflow/ComponentValuePickerModal.tsx +3 -3
  61. package/UI/Components/Workflow/ComponentsModal.tsx +1 -1
  62. package/UI/Components/Workflow/DocumentationViewer.tsx +1 -1
  63. package/UI/Components/Workflow/RunForm.tsx +1 -1
  64. package/UI/Components/Workflow/RunModal.tsx +1 -1
  65. package/UI/Utils/User.ts +1 -1
  66. package/UI/index.d.ts +4 -0
  67. package/build/dist/Models/DatabaseModels/{AlertLog.js → AlertFeed.js} +184 -57
  68. package/build/dist/Models/DatabaseModels/AlertFeed.js.map +1 -0
  69. package/build/dist/Models/DatabaseModels/Incident.js +6 -1
  70. package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
  71. package/build/dist/Models/DatabaseModels/{IncidentLog.js → IncidentFeed.js} +192 -57
  72. package/build/dist/Models/DatabaseModels/IncidentFeed.js.map +1 -0
  73. package/build/dist/Models/DatabaseModels/Index.js +6 -6
  74. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  75. package/build/dist/Models/DatabaseModels/{ScheduledMaintenanceLog.js → ScheduledMaintenanceFeed.js} +182 -55
  76. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceFeed.js.map +1 -0
  77. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1736703138918-MigrationName.js +16 -0
  78. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1736703138918-MigrationName.js.map +1 -0
  79. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1736780194077-MigrationName.js +54 -0
  80. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1736780194077-MigrationName.js.map +1 -0
  81. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1736780194078-MigrationName.js +15 -0
  82. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1736780194078-MigrationName.js.map +1 -0
  83. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1736787495707-MigrationName.js +16 -0
  84. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1736787495707-MigrationName.js.map +1 -0
  85. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1736787985322-MigrationName.js +34 -0
  86. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1736787985322-MigrationName.js.map +1 -0
  87. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1736788706141-MigrationName.js +22 -0
  88. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1736788706141-MigrationName.js.map +1 -0
  89. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1736856662868-MigrationName.js +16 -0
  90. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1736856662868-MigrationName.js.map +1 -0
  91. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +14 -0
  92. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  93. package/build/dist/Server/Services/AlertFeedService.js +54 -0
  94. package/build/dist/Server/Services/AlertFeedService.js.map +1 -0
  95. package/build/dist/Server/Services/IncidentFeedService.js +60 -0
  96. package/build/dist/Server/Services/IncidentFeedService.js.map +1 -0
  97. package/build/dist/Server/Services/IncidentInternalNoteService.js +19 -0
  98. package/build/dist/Server/Services/IncidentInternalNoteService.js.map +1 -1
  99. package/build/dist/Server/Services/IncidentOwnerTeamService.js +86 -0
  100. package/build/dist/Server/Services/IncidentOwnerTeamService.js.map +1 -1
  101. package/build/dist/Server/Services/IncidentOwnerUserService.js +89 -0
  102. package/build/dist/Server/Services/IncidentOwnerUserService.js.map +1 -1
  103. package/build/dist/Server/Services/IncidentPublicNoteService.js +19 -0
  104. package/build/dist/Server/Services/IncidentPublicNoteService.js.map +1 -1
  105. package/build/dist/Server/Services/IncidentService.js +108 -4
  106. package/build/dist/Server/Services/IncidentService.js.map +1 -1
  107. package/build/dist/Server/Services/IncidentStateTimelineService.js +37 -15
  108. package/build/dist/Server/Services/IncidentStateTimelineService.js.map +1 -1
  109. package/build/dist/Server/Services/Index.js +6 -6
  110. package/build/dist/Server/Services/Index.js.map +1 -1
  111. package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogService.js +93 -0
  112. package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogService.js.map +1 -1
  113. package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogTimelineService.js +129 -0
  114. package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogTimelineService.js.map +1 -1
  115. package/build/dist/Server/Services/ScheduledMaintenanceFeedService.js +57 -0
  116. package/build/dist/Server/Services/ScheduledMaintenanceFeedService.js.map +1 -0
  117. package/build/dist/Server/Services/UserOnCallLogService.js +2 -2
  118. package/build/dist/Server/Services/UserOnCallLogService.js.map +1 -1
  119. package/build/dist/Tests/Types/Database/ColumnLength.test.js +1 -1
  120. package/build/dist/Tests/Types/Database/ColumnLength.test.js.map +1 -1
  121. package/build/dist/Types/Database/ColumnLength.js +1 -1
  122. package/build/dist/Types/Database/ColumnLength.js.map +1 -1
  123. package/build/dist/Types/Database/LimitMax.js +1 -1
  124. package/build/dist/Types/Database/LimitMax.js.map +1 -1
  125. package/build/dist/Types/Icon/IconProp.js +1 -0
  126. package/build/dist/Types/Icon/IconProp.js.map +1 -1
  127. package/build/dist/Types/Permission.js +32 -32
  128. package/build/dist/Types/Permission.js.map +1 -1
  129. package/build/dist/UI/Components/CategoryCheckbox/Index.js +1 -1
  130. package/build/dist/UI/Components/CategoryCheckbox/Index.js.map +1 -1
  131. package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js +3 -3
  132. package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js.map +1 -1
  133. package/build/dist/UI/Components/ErrorMessage/ErrorMessage.js +1 -1
  134. package/build/dist/UI/Components/ErrorMessage/ErrorMessage.js.map +1 -1
  135. package/build/dist/UI/Components/Feed/Feed.js +14 -0
  136. package/build/dist/UI/Components/Feed/Feed.js.map +1 -0
  137. package/build/dist/UI/Components/Feed/FeedItem.js +67 -0
  138. package/build/dist/UI/Components/Feed/FeedItem.js.map +1 -0
  139. package/build/dist/UI/Components/Filters/FilterViewer.js +1 -1
  140. package/build/dist/UI/Components/Filters/FilterViewer.js.map +1 -1
  141. package/build/dist/UI/Components/Filters/FiltersForm.js +1 -1
  142. package/build/dist/UI/Components/Filters/FiltersForm.js.map +1 -1
  143. package/build/dist/UI/Components/FormModal/BasicFormModal.js +1 -1
  144. package/build/dist/UI/Components/FormModal/BasicFormModal.js.map +1 -1
  145. package/build/dist/UI/Components/Forms/BasicForm.js +1 -1
  146. package/build/dist/UI/Components/Forms/BasicForm.js.map +1 -1
  147. package/build/dist/UI/Components/Icon/Icon.js +6 -0
  148. package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
  149. package/build/dist/UI/Components/InfoCard/InfoCard.js +1 -1
  150. package/build/dist/UI/Components/InfoCard/InfoCard.js.map +1 -1
  151. package/build/dist/UI/Components/List/List.js +2 -2
  152. package/build/dist/UI/Components/List/List.js.map +1 -1
  153. package/build/dist/UI/Components/LogsViewer/LogsViewer.js +1 -1
  154. package/build/dist/UI/Components/LogsViewer/LogsViewer.js.map +1 -1
  155. package/build/dist/UI/Components/ModelDetail/ModelDetail.js +1 -1
  156. package/build/dist/UI/Components/ModelDetail/ModelDetail.js.map +1 -1
  157. package/build/dist/UI/Components/ModelList/ModelList.js +2 -2
  158. package/build/dist/UI/Components/ModelList/ModelList.js.map +1 -1
  159. package/build/dist/UI/Components/ModelProgress/ModelProgress.js +1 -1
  160. package/build/dist/UI/Components/ModelProgress/ModelProgress.js.map +1 -1
  161. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +3 -3
  162. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  163. package/build/dist/UI/Components/MonitorGraphs/Uptime.js +1 -1
  164. package/build/dist/UI/Components/MonitorGraphs/Uptime.js.map +1 -1
  165. package/build/dist/UI/Components/OrderedStatesList/OrderedStatesList.js +2 -2
  166. package/build/dist/UI/Components/OrderedStatesList/OrderedStatesList.js.map +1 -1
  167. package/build/dist/UI/Components/Page/Page.js +1 -1
  168. package/build/dist/UI/Components/Page/Page.js.map +1 -1
  169. package/build/dist/UI/Components/ProgressButtons/ProgressButtonItem.js +26 -0
  170. package/build/dist/UI/Components/ProgressButtons/ProgressButtonItem.js.map +1 -0
  171. package/build/dist/UI/Components/ProgressButtons/ProgressButtons.js +36 -0
  172. package/build/dist/UI/Components/ProgressButtons/ProgressButtons.js.map +1 -0
  173. package/build/dist/UI/Components/QR/QR.js +1 -1
  174. package/build/dist/UI/Components/QR/QR.js.map +1 -1
  175. package/build/dist/UI/Components/Table/Table.js +2 -2
  176. package/build/dist/UI/Components/Table/Table.js.map +1 -1
  177. package/build/dist/UI/Components/Workflow/ArgumentsForm.js +1 -1
  178. package/build/dist/UI/Components/Workflow/ArgumentsForm.js.map +1 -1
  179. package/build/dist/UI/Components/Workflow/ComponentArgumentsViewer.js +1 -1
  180. package/build/dist/UI/Components/Workflow/ComponentArgumentsViewer.js.map +1 -1
  181. package/build/dist/UI/Components/Workflow/ComponentPortViewer.js +1 -1
  182. package/build/dist/UI/Components/Workflow/ComponentPortViewer.js.map +1 -1
  183. package/build/dist/UI/Components/Workflow/ComponentReturnValueViewer.js +1 -1
  184. package/build/dist/UI/Components/Workflow/ComponentReturnValueViewer.js.map +1 -1
  185. package/build/dist/UI/Components/Workflow/ComponentValuePickerModal.js +3 -3
  186. package/build/dist/UI/Components/Workflow/ComponentValuePickerModal.js.map +1 -1
  187. package/build/dist/UI/Components/Workflow/ComponentsModal.js +1 -1
  188. package/build/dist/UI/Components/Workflow/ComponentsModal.js.map +1 -1
  189. package/build/dist/UI/Components/Workflow/DocumentationViewer.js +1 -1
  190. package/build/dist/UI/Components/Workflow/DocumentationViewer.js.map +1 -1
  191. package/build/dist/UI/Components/Workflow/RunForm.js +1 -1
  192. package/build/dist/UI/Components/Workflow/RunForm.js.map +1 -1
  193. package/build/dist/UI/Components/Workflow/RunModal.js +1 -1
  194. package/build/dist/UI/Components/Workflow/RunModal.js.map +1 -1
  195. package/build/dist/UI/Utils/User.js +1 -1
  196. package/build/dist/UI/Utils/User.js.map +1 -1
  197. package/package.json +2 -2
  198. package/Server/Services/AlertLogService.ts +0 -10
  199. package/Server/Services/IncidentLogService.ts +0 -10
  200. package/Server/Services/ScheduledMaintenanceLogService.ts +0 -10
  201. package/build/dist/Models/DatabaseModels/AlertLog.js.map +0 -1
  202. package/build/dist/Models/DatabaseModels/IncidentLog.js.map +0 -1
  203. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceLog.js.map +0 -1
  204. package/build/dist/Server/Services/AlertLogService.js +0 -9
  205. package/build/dist/Server/Services/AlertLogService.js.map +0 -1
  206. package/build/dist/Server/Services/IncidentLogService.js +0 -9
  207. package/build/dist/Server/Services/IncidentLogService.js.map +0 -1
  208. package/build/dist/Server/Services/ScheduledMaintenanceLogService.js +0 -9
  209. package/build/dist/Server/Services/ScheduledMaintenanceLogService.js.map +0 -1
@@ -0,0 +1,27 @@
1
+ import { MigrationInterface, QueryRunner } from "typeorm";
2
+
3
+ export class MigrationName1736856662868 implements MigrationInterface {
4
+ public name = "MigrationName1736856662868";
5
+
6
+ public async up(queryRunner: QueryRunner): Promise<void> {
7
+ await queryRunner.query(
8
+ `ALTER TABLE "IncidentFeed" ADD "postedAt" TIMESTAMP WITH TIME ZONE`,
9
+ );
10
+ await queryRunner.query(
11
+ `ALTER TABLE "AlertFeed" ADD "postedAt" TIMESTAMP WITH TIME ZONE`,
12
+ );
13
+ await queryRunner.query(
14
+ `ALTER TABLE "ScheduledMaintenanceFeed" ADD "postedAt" TIMESTAMP WITH TIME ZONE`,
15
+ );
16
+ }
17
+
18
+ public async down(queryRunner: QueryRunner): Promise<void> {
19
+ await queryRunner.query(
20
+ `ALTER TABLE "ScheduledMaintenanceFeed" DROP COLUMN "postedAt"`,
21
+ );
22
+ await queryRunner.query(`ALTER TABLE "AlertFeed" DROP COLUMN "postedAt"`);
23
+ await queryRunner.query(
24
+ `ALTER TABLE "IncidentFeed" DROP COLUMN "postedAt"`,
25
+ );
26
+ }
27
+ }
@@ -88,6 +88,13 @@ import { MigrationName1736364478985 } from "./1736364478985-MigrationName";
88
88
  import { MigrationName1736364957990 } from "./1736364957990-MigrationName";
89
89
  import { MigrationName1736365532085 } from "./1736365532085-MigrationName";
90
90
  import { MigrationName1736675947746 } from "./1736675947746-MigrationName";
91
+ import { MigrationName1736703138918 } from "./1736703138918-MigrationName";
92
+ import { MigrationName1736780194077 } from "./1736780194077-MigrationName";
93
+ import { MigrationName1736780194078 } from "./1736780194078-MigrationName";
94
+ import { MigrationName1736787495707 } from "./1736787495707-MigrationName";
95
+ import { MigrationName1736787985322 } from "./1736787985322-MigrationName";
96
+ import { MigrationName1736788706141 } from "./1736788706141-MigrationName";
97
+ import { MigrationName1736856662868 } from "./1736856662868-MigrationName";
91
98
 
92
99
  export default [
93
100
  InitialMigration,
@@ -180,4 +187,11 @@ export default [
180
187
  MigrationName1736364957990,
181
188
  MigrationName1736365532085,
182
189
  MigrationName1736675947746,
190
+ MigrationName1736703138918,
191
+ MigrationName1736780194077,
192
+ MigrationName1736780194078,
193
+ MigrationName1736787495707,
194
+ MigrationName1736787985322,
195
+ MigrationName1736788706141,
196
+ MigrationName1736856662868,
183
197
  ];
@@ -0,0 +1,81 @@
1
+ import { Blue500 } from "../../Types/BrandColors";
2
+ import Color from "../../Types/Color";
3
+ import OneUptimeDate from "../../Types/Date";
4
+ import BadDataException from "../../Types/Exception/BadDataException";
5
+ import ObjectID from "../../Types/ObjectID";
6
+ import { IsBillingEnabled } from "../EnvironmentConfig";
7
+ import DatabaseService from "./DatabaseService";
8
+ import Model, {
9
+ AlertFeedEventType,
10
+ } from "Common/Models/DatabaseModels/AlertFeed";
11
+
12
+ export class Service extends DatabaseService<Model> {
13
+ public constructor() {
14
+ super(Model);
15
+
16
+ if (IsBillingEnabled) {
17
+ this.hardDeleteItemsOlderThanInDays("createdAt", 120);
18
+ }
19
+ }
20
+
21
+ public async createAlertFeed(data: {
22
+ alertId: ObjectID;
23
+ feedInfoInMarkdown: string;
24
+ alertFeedEventType: AlertFeedEventType;
25
+ projectId: ObjectID;
26
+ moreInformationInMarkdown?: string | undefined;
27
+ displayColor?: Color | undefined;
28
+ userId?: ObjectID | undefined;
29
+ postedAt?: Date | undefined;
30
+ }): Promise<Model> {
31
+ if (!data.alertId) {
32
+ throw new BadDataException("Alert ID is required");
33
+ }
34
+
35
+ if (!data.feedInfoInMarkdown) {
36
+ throw new BadDataException("Log in markdown is required");
37
+ }
38
+
39
+ if (!data.alertFeedEventType) {
40
+ throw new BadDataException("Alert log event is required");
41
+ }
42
+
43
+ if (!data.projectId) {
44
+ throw new BadDataException("Project ID is required");
45
+ }
46
+
47
+ const alertFeed: Model = new Model();
48
+
49
+ if (!data.displayColor) {
50
+ data.displayColor = Blue500;
51
+ }
52
+
53
+ if (data.userId) {
54
+ alertFeed.userId = data.userId;
55
+ }
56
+
57
+ alertFeed.displayColor = data.displayColor;
58
+
59
+ alertFeed.alertId = data.alertId;
60
+ alertFeed.feedInfoInMarkdown = data.feedInfoInMarkdown;
61
+ alertFeed.alertFeedEventType = data.alertFeedEventType;
62
+ alertFeed.projectId = data.projectId;
63
+
64
+ if (!data.postedAt) {
65
+ alertFeed.postedAt = OneUptimeDate.getCurrentDate();
66
+ }
67
+
68
+ if (data.moreInformationInMarkdown) {
69
+ alertFeed.moreInformationInMarkdown = data.moreInformationInMarkdown;
70
+ }
71
+
72
+ return await this.create({
73
+ data: alertFeed,
74
+ props: {
75
+ isRoot: true,
76
+ },
77
+ });
78
+ }
79
+ }
80
+
81
+ export default new Service();
@@ -0,0 +1,89 @@
1
+ import { Blue500 } from "../../Types/BrandColors";
2
+ import Color from "../../Types/Color";
3
+ import OneUptimeDate from "../../Types/Date";
4
+ import BadDataException from "../../Types/Exception/BadDataException";
5
+ import ObjectID from "../../Types/ObjectID";
6
+ import { IsBillingEnabled } from "../EnvironmentConfig";
7
+ import logger from "../Utils/Logger";
8
+ import DatabaseService from "./DatabaseService";
9
+ import IncidentFeed, {
10
+ IncidentFeedEventType,
11
+ } from "Common/Models/DatabaseModels/IncidentFeed";
12
+
13
+ export class Service extends DatabaseService<IncidentFeed> {
14
+ public constructor() {
15
+ super(IncidentFeed);
16
+
17
+ if (IsBillingEnabled) {
18
+ this.hardDeleteItemsOlderThanInDays("createdAt", 120);
19
+ }
20
+ }
21
+
22
+ public async createIncidentFeed(data: {
23
+ incidentId: ObjectID;
24
+ feedInfoInMarkdown: string;
25
+ incidentFeedEventType: IncidentFeedEventType;
26
+ projectId: ObjectID;
27
+ moreInformationInMarkdown?: string | undefined;
28
+ displayColor?: Color | undefined;
29
+ userId?: ObjectID | undefined;
30
+ postedAt?: Date | undefined;
31
+ }): Promise<IncidentFeed> {
32
+ logger.debug("IncidentFeedService.createIncidentFeed");
33
+ logger.debug(data);
34
+
35
+ const incidentFeed: IncidentFeed = new IncidentFeed();
36
+
37
+ if (!data.incidentId) {
38
+ throw new BadDataException("Incident ID is required");
39
+ }
40
+
41
+ if (!data.feedInfoInMarkdown) {
42
+ throw new BadDataException("Log in markdown is required");
43
+ }
44
+
45
+ if (!data.incidentFeedEventType) {
46
+ throw new BadDataException("Incident log event is required");
47
+ }
48
+
49
+ if (!data.projectId) {
50
+ throw new BadDataException("Project ID is required");
51
+ }
52
+
53
+ if (!data.displayColor) {
54
+ data.displayColor = Blue500;
55
+ }
56
+
57
+ incidentFeed.displayColor = data.displayColor;
58
+ incidentFeed.incidentId = data.incidentId;
59
+ incidentFeed.feedInfoInMarkdown = data.feedInfoInMarkdown;
60
+ incidentFeed.incidentFeedEventType = data.incidentFeedEventType;
61
+ incidentFeed.projectId = data.projectId;
62
+
63
+ if (!data.postedAt) {
64
+ incidentFeed.postedAt = OneUptimeDate.getCurrentDate();
65
+ }
66
+
67
+ if (data.userId) {
68
+ incidentFeed.userId = data.userId;
69
+ }
70
+
71
+ if (data.moreInformationInMarkdown) {
72
+ incidentFeed.moreInformationInMarkdown = data.moreInformationInMarkdown;
73
+ }
74
+
75
+ const createdIncidentFeed: IncidentFeed = await this.create({
76
+ data: incidentFeed,
77
+ props: {
78
+ isRoot: true,
79
+ },
80
+ });
81
+
82
+ logger.debug("Incident Feed created");
83
+ logger.debug(createdIncidentFeed);
84
+
85
+ return createdIncidentFeed;
86
+ }
87
+ }
88
+
89
+ export default new Service();
@@ -1,10 +1,38 @@
1
+ import ObjectID from "../../Types/ObjectID";
1
2
  import DatabaseService from "./DatabaseService";
2
3
  import Model from "Common/Models/DatabaseModels/IncidentInternalNote";
4
+ import { OnCreate } from "../Types/Database/Hooks";
5
+ import IncidentFeedService from "./IncidentFeedService";
6
+ import { IncidentFeedEventType } from "../../Models/DatabaseModels/IncidentFeed";
7
+ import { Blue500 } from "../../Types/BrandColors";
3
8
 
4
9
  export class Service extends DatabaseService<Model> {
5
10
  public constructor() {
6
11
  super(Model);
7
12
  }
13
+
14
+ public override async onCreateSuccess(
15
+ _onCreate: OnCreate<Model>,
16
+ createdItem: Model,
17
+ ): Promise<Model> {
18
+ const userId: ObjectID | null | undefined =
19
+ createdItem.createdByUserId || createdItem.createdByUser?.id;
20
+
21
+ await IncidentFeedService.createIncidentFeed({
22
+ incidentId: createdItem.incidentId!,
23
+ projectId: createdItem.projectId!,
24
+ incidentFeedEventType: IncidentFeedEventType.PrivateNote,
25
+ displayColor: Blue500,
26
+ userId: userId || undefined,
27
+
28
+ feedInfoInMarkdown: `**Posted Internal / Private Note**
29
+
30
+ ${createdItem.note}
31
+ `,
32
+ });
33
+
34
+ return createdItem;
35
+ }
8
36
  }
9
37
 
10
38
  export default new Service();
@@ -1,10 +1,122 @@
1
+ import ObjectID from "../../Types/ObjectID";
2
+ import { OnCreate, OnDelete } from "../Types/Database/Hooks";
1
3
  import DatabaseService from "./DatabaseService";
2
4
  import Model from "Common/Models/DatabaseModels/IncidentOwnerTeam";
5
+ import IncidentFeedService from "./IncidentFeedService";
6
+ import { IncidentFeedEventType } from "../../Models/DatabaseModels/IncidentFeed";
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";
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
+ incidentId: 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 incidentId: ObjectID | undefined = item.incidentId;
53
+ const projectId: ObjectID | undefined = item.projectId;
54
+ const teamId: ObjectID | undefined = item.teamId;
55
+
56
+ if (incidentId && teamId && projectId) {
57
+ const team: Team | null = await TeamService.findOneById({
58
+ id: teamId,
59
+ select: {
60
+ name: true,
61
+ },
62
+ props: {
63
+ isRoot: true,
64
+ },
65
+ });
66
+
67
+ if (team && team.name) {
68
+ await IncidentFeedService.createIncidentFeed({
69
+ incidentId: incidentId,
70
+ projectId: projectId,
71
+ incidentFeedEventType: IncidentFeedEventType.OwnerTeamRemoved,
72
+ displayColor: Red500,
73
+ feedInfoInMarkdown: `**Team ${team.name}** was removed from the incident as the owner.`,
74
+ userId: deleteByUserId || undefined,
75
+ });
76
+ }
77
+ }
78
+ }
79
+
80
+ return onDelete;
81
+ }
82
+
83
+ public override async onCreateSuccess(
84
+ onCreate: OnCreate<Model>,
85
+ createdItem: Model,
86
+ ): Promise<Model> {
87
+ // add incident feed.
88
+
89
+ const incidentId: ObjectID | undefined = createdItem.incidentId;
90
+ const projectId: ObjectID | undefined = createdItem.projectId;
91
+ const teamId: ObjectID | undefined = createdItem.teamId;
92
+ const createdByUserId: ObjectID | undefined =
93
+ createdItem.createdByUserId || onCreate.createBy.props.userId;
94
+
95
+ if (incidentId && teamId && projectId) {
96
+ const team: Team | null = await TeamService.findOneById({
97
+ id: teamId,
98
+ select: {
99
+ name: true,
100
+ },
101
+ props: {
102
+ isRoot: true,
103
+ },
104
+ });
105
+
106
+ if (team && team.name) {
107
+ await IncidentFeedService.createIncidentFeed({
108
+ incidentId: incidentId,
109
+ projectId: projectId,
110
+ incidentFeedEventType: IncidentFeedEventType.OwnerTeamAdded,
111
+ displayColor: Gray500,
112
+ feedInfoInMarkdown: `**Team ${team.name}** was added to the incident as the owner.`,
113
+ userId: createdByUserId || undefined,
114
+ });
115
+ }
116
+ }
117
+
118
+ return createdItem;
119
+ }
8
120
  }
9
121
 
10
122
  export default new Service();
@@ -1,10 +1,124 @@
1
+ import ObjectID from "../../Types/ObjectID";
1
2
  import DatabaseService from "./DatabaseService";
2
3
  import Model from "Common/Models/DatabaseModels/IncidentOwnerUser";
4
+ import IncidentFeedService from "./IncidentFeedService";
5
+ import { IncidentFeedEventType } from "../../Models/DatabaseModels/IncidentFeed";
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";
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
+ incidentId: true,
29
+ projectId: true,
30
+ userId: 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 incidentId: ObjectID | undefined = item.incidentId;
53
+ const projectId: ObjectID | undefined = item.projectId;
54
+ const userId: ObjectID | undefined = item.userId;
55
+
56
+ if (incidentId && userId && projectId) {
57
+ const user: User | null = await UserService.findOneById({
58
+ id: userId,
59
+ select: {
60
+ name: true,
61
+ email: true,
62
+ },
63
+ props: {
64
+ isRoot: true,
65
+ },
66
+ });
67
+
68
+ if (user && user.name) {
69
+ await IncidentFeedService.createIncidentFeed({
70
+ incidentId: incidentId,
71
+ projectId: projectId,
72
+ incidentFeedEventType: IncidentFeedEventType.OwnerUserRemoved,
73
+ displayColor: Red500,
74
+ feedInfoInMarkdown: `**${user.name.toString()}** (${user.email?.toString()}) was removed from the incident as the owner.`,
75
+ userId: deleteByUserId || undefined,
76
+ });
77
+ }
78
+ }
79
+ }
80
+
81
+ return onDelete;
82
+ }
83
+
84
+ public override async onCreateSuccess(
85
+ onCreate: OnCreate<Model>,
86
+ createdItem: Model,
87
+ ): Promise<Model> {
88
+ // add incident feed.
89
+
90
+ const incidentId: ObjectID | undefined = createdItem.incidentId;
91
+ const projectId: ObjectID | undefined = createdItem.projectId;
92
+ const userId: ObjectID | undefined = createdItem.userId;
93
+ const createdByUserId: ObjectID | undefined =
94
+ createdItem.createdByUserId || onCreate.createBy.props.userId;
95
+
96
+ if (incidentId && userId && projectId) {
97
+ const user: User | null = await UserService.findOneById({
98
+ id: userId,
99
+ select: {
100
+ name: true,
101
+ email: true,
102
+ },
103
+ props: {
104
+ isRoot: true,
105
+ },
106
+ });
107
+
108
+ if (user && user.name) {
109
+ await IncidentFeedService.createIncidentFeed({
110
+ incidentId: incidentId,
111
+ projectId: projectId,
112
+ incidentFeedEventType: IncidentFeedEventType.OwnerUserAdded,
113
+ displayColor: Gray500,
114
+ feedInfoInMarkdown: `**${user.name.toString()}** (${user.email?.toString()}) was added to the incident as the owner.`,
115
+ userId: createdByUserId || undefined,
116
+ });
117
+ }
118
+ }
119
+
120
+ return createdItem;
121
+ }
8
122
  }
9
123
 
10
124
  export default new Service();
@@ -3,6 +3,10 @@ import { OnCreate } from "../Types/Database/Hooks";
3
3
  import DatabaseService from "./DatabaseService";
4
4
  import OneUptimeDate from "../../Types/Date";
5
5
  import Model from "Common/Models/DatabaseModels/IncidentPublicNote";
6
+ import IncidentFeedService from "./IncidentFeedService";
7
+ import { IncidentFeedEventType } from "../../Models/DatabaseModels/IncidentFeed";
8
+ import { Indigo500 } from "../../Types/BrandColors";
9
+ import ObjectID from "../../Types/ObjectID";
6
10
 
7
11
  export class Service extends DatabaseService<Model> {
8
12
  public constructor() {
@@ -21,6 +25,28 @@ export class Service extends DatabaseService<Model> {
21
25
  carryForward: null,
22
26
  };
23
27
  }
28
+
29
+ public override async onCreateSuccess(
30
+ _onCreate: OnCreate<Model>,
31
+ createdItem: Model,
32
+ ): Promise<Model> {
33
+ const userId: ObjectID | null | undefined =
34
+ createdItem.createdByUserId || createdItem.createdByUser?.id;
35
+
36
+ await IncidentFeedService.createIncidentFeed({
37
+ incidentId: createdItem.incidentId!,
38
+ projectId: createdItem.projectId!,
39
+ incidentFeedEventType: IncidentFeedEventType.PublicNote,
40
+ displayColor: Indigo500,
41
+ userId: userId || undefined,
42
+ feedInfoInMarkdown: `**Posted public note for this incident on status page**
43
+
44
+ ${createdItem.note}
45
+ `,
46
+ });
47
+
48
+ return createdItem;
49
+ }
24
50
  }
25
51
 
26
52
  export default new Service();
@@ -47,6 +47,9 @@ import logger from "../Utils/Logger";
47
47
  import Semaphore, {
48
48
  SemaphoreMutex,
49
49
  } from "Common/Server/Infrastructure/Semaphore";
50
+ import IncidentFeedService from "./IncidentFeedService";
51
+ import { IncidentFeedEventType } from "../../Models/DatabaseModels/IncidentFeed";
52
+ import { Gray500, Red500 } from "../../Types/BrandColors";
50
53
 
51
54
  export class Service extends DatabaseService<Model> {
52
55
  public constructor() {
@@ -326,6 +329,28 @@ export class Service extends DatabaseService<Model> {
326
329
  }
327
330
  }
328
331
 
332
+ const createdByUserId: ObjectID | undefined | null =
333
+ createdItem.createdByUserId || createdItem.createdByUser?.id;
334
+
335
+ await IncidentFeedService.createIncidentFeed({
336
+ incidentId: createdItem.id!,
337
+ projectId: createdItem.projectId!,
338
+ incidentFeedEventType: IncidentFeedEventType.IncidentCreated,
339
+ displayColor: Red500,
340
+ feedInfoInMarkdown: `**Incident #${createdItem.incidentNumber?.toString()} Created**:
341
+
342
+ **Incident Title**:
343
+
344
+ ${createdItem.title || "No title provided."}
345
+
346
+ **Description**:
347
+
348
+ ${createdItem.description || "No description provided."}
349
+
350
+ `,
351
+ userId: createdByUserId || undefined,
352
+ });
353
+
329
354
  if (!createdItem.currentIncidentStateId) {
330
355
  throw new BadDataException("currentIncidentStateId is required");
331
356
  }
@@ -366,6 +391,26 @@ export class Service extends DatabaseService<Model> {
366
391
  },
367
392
  });
368
393
 
394
+ await IncidentFeedService.createIncidentFeed({
395
+ incidentId: createdItem.id!,
396
+ projectId: createdItem.projectId!,
397
+ incidentFeedEventType: IncidentFeedEventType.RootCause,
398
+ displayColor: Red500,
399
+ feedInfoInMarkdown: `**Root Cause**
400
+
401
+ ${createdItem.rootCause || "No root cause provided."}`,
402
+ });
403
+
404
+ await IncidentFeedService.createIncidentFeed({
405
+ incidentId: createdItem.id!,
406
+ projectId: createdItem.projectId!,
407
+ incidentFeedEventType: IncidentFeedEventType.RemediationNotes,
408
+ displayColor: Red500,
409
+ feedInfoInMarkdown: `**Remediation Notes**
410
+
411
+ ${createdItem.remediationNotes || "No remediation notes provided."}`,
412
+ });
413
+
369
414
  // add owners.
370
415
 
371
416
  if (
@@ -597,6 +642,82 @@ export class Service extends DatabaseService<Model> {
597
642
  }
598
643
  }
599
644
 
645
+ if (updatedItemIds.length > 0) {
646
+ for (const incidentId of updatedItemIds) {
647
+ if (onUpdate.updateBy.data.title) {
648
+ // add incident feed.
649
+ const createdByUserId: ObjectID | undefined | null =
650
+ onUpdate.updateBy.props.userId;
651
+
652
+ await IncidentFeedService.createIncidentFeed({
653
+ incidentId: incidentId,
654
+ projectId: onUpdate.updateBy.props.tenantId as ObjectID,
655
+ incidentFeedEventType: IncidentFeedEventType.IncidentUpdated,
656
+ displayColor: Gray500,
657
+ feedInfoInMarkdown: `**Incident title was updated.** Here's the new title.
658
+
659
+ ${onUpdate.updateBy.data.title || "No title provided."}
660
+ `,
661
+ userId: createdByUserId || undefined,
662
+ });
663
+ }
664
+
665
+ if (onUpdate.updateBy.data.rootCause) {
666
+ // add incident feed.
667
+ const createdByUserId: ObjectID | undefined | null =
668
+ onUpdate.updateBy.props.userId;
669
+
670
+ await IncidentFeedService.createIncidentFeed({
671
+ incidentId: incidentId,
672
+ projectId: onUpdate.updateBy.props.tenantId as ObjectID,
673
+ incidentFeedEventType: IncidentFeedEventType.IncidentUpdated,
674
+ displayColor: Gray500,
675
+ feedInfoInMarkdown: `**Incident root cause was updated.** Here's the new root cause.
676
+
677
+ ${onUpdate.updateBy.data.rootCause || "No root cause provided."}
678
+ `,
679
+ userId: createdByUserId || undefined,
680
+ });
681
+ }
682
+
683
+ if (onUpdate.updateBy.data.description) {
684
+ // add incident feed.
685
+ const createdByUserId: ObjectID | undefined | null =
686
+ onUpdate.updateBy.props.userId;
687
+
688
+ await IncidentFeedService.createIncidentFeed({
689
+ incidentId: incidentId,
690
+ projectId: onUpdate.updateBy.props.tenantId as ObjectID,
691
+ incidentFeedEventType: IncidentFeedEventType.IncidentUpdated,
692
+ displayColor: Gray500,
693
+ feedInfoInMarkdown: `**Incident description was updated.** Here's the new description.
694
+
695
+ ${onUpdate.updateBy.data.description || "No description provided."}
696
+ `,
697
+ userId: createdByUserId || undefined,
698
+ });
699
+ }
700
+
701
+ if (onUpdate.updateBy.data.remediationNotes) {
702
+ // add incident feed.
703
+ const createdByUserId: ObjectID | undefined | null =
704
+ onUpdate.updateBy.props.userId;
705
+
706
+ await IncidentFeedService.createIncidentFeed({
707
+ incidentId: incidentId,
708
+ projectId: onUpdate.updateBy.props.tenantId as ObjectID,
709
+ incidentFeedEventType: IncidentFeedEventType.IncidentUpdated,
710
+ displayColor: Gray500,
711
+ feedInfoInMarkdown: `**Remediation notes were updated.** Here are the new notes.
712
+
713
+ ${onUpdate.updateBy.data.remediationNotes || "No remediation notes provided."}
714
+ `,
715
+ userId: createdByUserId || undefined,
716
+ });
717
+ }
718
+ }
719
+ }
720
+
600
721
  return onUpdate;
601
722
  }
602
723