@oneuptime/common 9.5.2 → 9.5.3
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.
- package/Models/DatabaseModels/Alert.ts +1 -0
- package/Models/DatabaseModels/AlertEpisode.ts +1 -0
- package/Models/DatabaseModels/AlertEpisodeStateTimeline.ts +1 -0
- package/Models/DatabaseModels/AlertStateTimeline.ts +1 -0
- package/Models/DatabaseModels/Incident.ts +1 -0
- package/Models/DatabaseModels/IncidentEpisode.ts +156 -0
- package/Models/DatabaseModels/IncidentEpisodeFeed.ts +2 -0
- package/Models/DatabaseModels/IncidentEpisodePublicNote.ts +611 -0
- package/Models/DatabaseModels/IncidentEpisodeStateTimeline.ts +84 -0
- package/Models/DatabaseModels/IncidentGroupingRule.ts +36 -0
- package/Models/DatabaseModels/IncidentStateTimeline.ts +1 -0
- package/Models/DatabaseModels/Index.ts +2 -0
- package/Models/DatabaseModels/MonitorStatusTimeline.ts +1 -0
- package/Models/DatabaseModels/Project.ts +2 -1
- package/Models/DatabaseModels/ProjectCallSMSConfig.ts +1 -0
- package/Models/DatabaseModels/ScheduledMaintenance.ts +1 -0
- package/Models/DatabaseModels/ScheduledMaintenanceTemplate.ts +1 -0
- package/Models/DatabaseModels/StatusPage.ts +120 -0
- package/Server/API/IncidentEpisodePublicNoteAPI.ts +98 -0
- package/Server/API/StatusPageAPI.ts +1092 -45
- package/Server/Infrastructure/Postgres/SchemaMigrations/1770232207959-MigrationName.ts +181 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1770237245069-MigrationName.ts +35 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +4 -0
- package/Server/Services/IncidentEpisodePublicNoteService.ts +254 -0
- package/Server/Services/IncidentEpisodeService.ts +26 -0
- package/Server/Services/Index.ts +2 -0
- package/Server/Utils/Monitor/MonitorIncident.ts +6 -0
- package/Types/Email/EmailTemplateType.ts +4 -0
- package/Types/Icon/IconProp.ts +172 -0
- package/Types/Monitor/CriteriaIncident.ts +2 -0
- package/Types/Permission.ts +40 -0
- package/Types/StatusPage/StatusPageSubscriberNotificationEventType.ts +5 -0
- package/UI/Components/Icon/Icon.tsx +1333 -1
- package/build/dist/Models/DatabaseModels/Alert.js +1 -0
- package/build/dist/Models/DatabaseModels/Alert.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertEpisode.js +1 -0
- package/build/dist/Models/DatabaseModels/AlertEpisode.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertEpisodeStateTimeline.js +1 -0
- package/build/dist/Models/DatabaseModels/AlertEpisodeStateTimeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertStateTimeline.js +1 -0
- package/build/dist/Models/DatabaseModels/AlertStateTimeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Incident.js +1 -0
- package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentEpisode.js +161 -0
- package/build/dist/Models/DatabaseModels/IncidentEpisode.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentEpisodeFeed.js +2 -0
- package/build/dist/Models/DatabaseModels/IncidentEpisodeFeed.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentEpisodePublicNote.js +626 -0
- package/build/dist/Models/DatabaseModels/IncidentEpisodePublicNote.js.map +1 -0
- package/build/dist/Models/DatabaseModels/IncidentEpisodeStateTimeline.js +86 -0
- package/build/dist/Models/DatabaseModels/IncidentEpisodeStateTimeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentGroupingRule.js +37 -0
- package/build/dist/Models/DatabaseModels/IncidentGroupingRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentStateTimeline.js +1 -0
- package/build/dist/Models/DatabaseModels/IncidentStateTimeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Index.js +2 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/MonitorStatusTimeline.js +1 -0
- package/build/dist/Models/DatabaseModels/MonitorStatusTimeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Project.js +2 -1
- package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ProjectCallSMSConfig.js +1 -0
- package/build/dist/Models/DatabaseModels/ProjectCallSMSConfig.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js +1 -0
- package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceTemplate.js +1 -0
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceTemplate.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPage.js +126 -0
- package/build/dist/Models/DatabaseModels/StatusPage.js.map +1 -1
- package/build/dist/Server/API/IncidentEpisodePublicNoteAPI.js +68 -0
- package/build/dist/Server/API/IncidentEpisodePublicNoteAPI.js.map +1 -0
- package/build/dist/Server/API/StatusPageAPI.js +874 -47
- package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1770232207959-MigrationName.js +68 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1770232207959-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1770237245069-MigrationName.js +18 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1770237245069-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +4 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodePublicNoteService.js +223 -0
- package/build/dist/Server/Services/IncidentEpisodePublicNoteService.js.map +1 -0
- package/build/dist/Server/Services/IncidentEpisodeService.js +22 -0
- package/build/dist/Server/Services/IncidentEpisodeService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +2 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js +5 -0
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
- package/build/dist/Types/Email/EmailTemplateType.js +3 -0
- package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
- package/build/dist/Types/Icon/IconProp.js +172 -0
- package/build/dist/Types/Icon/IconProp.js.map +1 -1
- package/build/dist/Types/Monitor/CriteriaIncident.js +1 -0
- package/build/dist/Types/Monitor/CriteriaIncident.js.map +1 -1
- package/build/dist/Types/Permission.js +34 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/StatusPage/StatusPageSubscriberNotificationEventType.js +4 -0
- package/build/dist/Types/StatusPage/StatusPageSubscriberNotificationEventType.js.map +1 -1
- package/build/dist/UI/Components/Icon/Icon.js +502 -1
- package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { MigrationInterface, QueryRunner } from "typeorm";
|
|
2
|
+
|
|
3
|
+
export class MigrationName1770232207959 implements MigrationInterface {
|
|
4
|
+
public name = "MigrationName1770232207959";
|
|
5
|
+
|
|
6
|
+
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
7
|
+
await queryRunner.query(
|
|
8
|
+
`CREATE TABLE "IncidentEpisodePublicNote" ("_id" uuid NOT NULL DEFAULT uuid_generate_v4(), "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "deletedAt" TIMESTAMP WITH TIME ZONE, "version" integer NOT NULL, "projectId" uuid NOT NULL, "incidentEpisodeId" uuid NOT NULL, "createdByUserId" uuid, "deletedByUserId" uuid, "note" text NOT NULL, "subscriberNotificationStatusOnNoteCreated" character varying NOT NULL DEFAULT 'Pending', "subscriberNotificationStatusMessage" text, "shouldStatusPageSubscribersBeNotifiedOnNoteCreated" boolean NOT NULL DEFAULT true, "isOwnerNotified" boolean NOT NULL DEFAULT false, "postedAt" TIMESTAMP WITH TIME ZONE, "postedFromSlackMessageId" character varying, CONSTRAINT "PK_7ac3241d9cf7bdf5ecac42c9c98" PRIMARY KEY ("_id"))`,
|
|
9
|
+
);
|
|
10
|
+
await queryRunner.query(
|
|
11
|
+
`CREATE INDEX "IDX_46268b7b996f3b8129136d12d2" ON "IncidentEpisodePublicNote" ("projectId") `,
|
|
12
|
+
);
|
|
13
|
+
await queryRunner.query(
|
|
14
|
+
`CREATE INDEX "IDX_885de505291c2f6f4f86b988ca" ON "IncidentEpisodePublicNote" ("incidentEpisodeId") `,
|
|
15
|
+
);
|
|
16
|
+
await queryRunner.query(
|
|
17
|
+
`CREATE INDEX "IDX_2e0c6dd840bbc05b9a5117f882" ON "IncidentEpisodePublicNote" ("isOwnerNotified") `,
|
|
18
|
+
);
|
|
19
|
+
await queryRunner.query(
|
|
20
|
+
`CREATE INDEX "IDX_784fb865a857417194a37034ed" ON "IncidentEpisodePublicNote" ("postedFromSlackMessageId") `,
|
|
21
|
+
);
|
|
22
|
+
await queryRunner.query(
|
|
23
|
+
`CREATE TABLE "IncidentEpisodePublicNoteFile" ("incidentEpisodePublicNoteId" uuid NOT NULL, "fileId" uuid NOT NULL, CONSTRAINT "PK_546f0c2cf908ebf301fb164a1ed" PRIMARY KEY ("incidentEpisodePublicNoteId", "fileId"))`,
|
|
24
|
+
);
|
|
25
|
+
await queryRunner.query(
|
|
26
|
+
`CREATE INDEX "IDX_8e439d24c574141d9a66d74fa5" ON "IncidentEpisodePublicNoteFile" ("incidentEpisodePublicNoteId") `,
|
|
27
|
+
);
|
|
28
|
+
await queryRunner.query(
|
|
29
|
+
`CREATE INDEX "IDX_0dfcd7747b6e55239df9bbaac5" ON "IncidentEpisodePublicNoteFile" ("fileId") `,
|
|
30
|
+
);
|
|
31
|
+
await queryRunner.query(
|
|
32
|
+
`ALTER TABLE "IncidentGroupingRule" ADD "showEpisodeOnStatusPage" boolean NOT NULL DEFAULT false`,
|
|
33
|
+
);
|
|
34
|
+
await queryRunner.query(
|
|
35
|
+
`ALTER TABLE "IncidentEpisode" ADD "isVisibleOnStatusPage" boolean NOT NULL DEFAULT false`,
|
|
36
|
+
);
|
|
37
|
+
await queryRunner.query(
|
|
38
|
+
`ALTER TABLE "IncidentEpisode" ADD "declaredAt" TIMESTAMP WITH TIME ZONE`,
|
|
39
|
+
);
|
|
40
|
+
await queryRunner.query(
|
|
41
|
+
`ALTER TABLE "IncidentEpisode" ADD "shouldStatusPageSubscribersBeNotifiedOnEpisodeCreated" boolean NOT NULL DEFAULT true`,
|
|
42
|
+
);
|
|
43
|
+
await queryRunner.query(
|
|
44
|
+
`ALTER TABLE "IncidentEpisode" ADD "subscriberNotificationStatusOnEpisodeCreated" character varying NOT NULL DEFAULT 'Pending'`,
|
|
45
|
+
);
|
|
46
|
+
await queryRunner.query(
|
|
47
|
+
`ALTER TABLE "IncidentEpisode" ADD "subscriberNotificationStatusMessage" text`,
|
|
48
|
+
);
|
|
49
|
+
await queryRunner.query(
|
|
50
|
+
`ALTER TABLE "StatusPage" ADD "showEpisodesOnStatusPage" boolean NOT NULL DEFAULT true`,
|
|
51
|
+
);
|
|
52
|
+
await queryRunner.query(
|
|
53
|
+
`ALTER TABLE "IncidentEpisodeStateTimeline" ADD "shouldStatusPageSubscribersBeNotified" boolean NOT NULL DEFAULT true`,
|
|
54
|
+
);
|
|
55
|
+
await queryRunner.query(
|
|
56
|
+
`ALTER TABLE "IncidentEpisodeStateTimeline" ADD "subscriberNotificationStatus" character varying NOT NULL DEFAULT 'Pending'`,
|
|
57
|
+
);
|
|
58
|
+
await queryRunner.query(
|
|
59
|
+
`ALTER TABLE "IncidentEpisodeStateTimeline" ADD "subscriberNotificationStatusMessage" text`,
|
|
60
|
+
);
|
|
61
|
+
await queryRunner.query(
|
|
62
|
+
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type":"Recurring","value":{"intervalType":"Day","intervalCount":{"_type":"PositiveNumber","value":1}}}'`,
|
|
63
|
+
);
|
|
64
|
+
await queryRunner.query(
|
|
65
|
+
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type":"RestrictionTimes","value":{"restictionType":"None","dayRestrictionTimes":null,"weeklyRestrictionTimes":[]}}'`,
|
|
66
|
+
);
|
|
67
|
+
await queryRunner.query(
|
|
68
|
+
`CREATE INDEX "IDX_9d7bfebab97dc56583df143ae8" ON "IncidentGroupingRule" ("showEpisodeOnStatusPage") `,
|
|
69
|
+
);
|
|
70
|
+
await queryRunner.query(
|
|
71
|
+
`CREATE INDEX "IDX_298e3524e859ddb920c05e1072" ON "IncidentEpisode" ("isVisibleOnStatusPage") `,
|
|
72
|
+
);
|
|
73
|
+
await queryRunner.query(
|
|
74
|
+
`CREATE INDEX "IDX_30d4a06d51be505b6233185906" ON "IncidentEpisode" ("declaredAt") `,
|
|
75
|
+
);
|
|
76
|
+
await queryRunner.query(
|
|
77
|
+
`ALTER TABLE "IncidentEpisodePublicNote" ADD CONSTRAINT "FK_46268b7b996f3b8129136d12d21" FOREIGN KEY ("projectId") REFERENCES "Project"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
|
78
|
+
);
|
|
79
|
+
await queryRunner.query(
|
|
80
|
+
`ALTER TABLE "IncidentEpisodePublicNote" ADD CONSTRAINT "FK_885de505291c2f6f4f86b988ca6" FOREIGN KEY ("incidentEpisodeId") REFERENCES "IncidentEpisode"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
|
81
|
+
);
|
|
82
|
+
await queryRunner.query(
|
|
83
|
+
`ALTER TABLE "IncidentEpisodePublicNote" ADD CONSTRAINT "FK_7711bde5254d7c1021bbbb0f944" FOREIGN KEY ("createdByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
|
84
|
+
);
|
|
85
|
+
await queryRunner.query(
|
|
86
|
+
`ALTER TABLE "IncidentEpisodePublicNote" ADD CONSTRAINT "FK_96d88a43c5479b67ddd7c70df16" FOREIGN KEY ("deletedByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
|
87
|
+
);
|
|
88
|
+
await queryRunner.query(
|
|
89
|
+
`ALTER TABLE "IncidentEpisodePublicNoteFile" ADD CONSTRAINT "FK_8e439d24c574141d9a66d74fa5c" FOREIGN KEY ("incidentEpisodePublicNoteId") REFERENCES "IncidentEpisodePublicNote"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
|
|
90
|
+
);
|
|
91
|
+
await queryRunner.query(
|
|
92
|
+
`ALTER TABLE "IncidentEpisodePublicNoteFile" ADD CONSTRAINT "FK_0dfcd7747b6e55239df9bbaac59" FOREIGN KEY ("fileId") REFERENCES "File"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
97
|
+
await queryRunner.query(
|
|
98
|
+
`ALTER TABLE "IncidentEpisodePublicNoteFile" DROP CONSTRAINT "FK_0dfcd7747b6e55239df9bbaac59"`,
|
|
99
|
+
);
|
|
100
|
+
await queryRunner.query(
|
|
101
|
+
`ALTER TABLE "IncidentEpisodePublicNoteFile" DROP CONSTRAINT "FK_8e439d24c574141d9a66d74fa5c"`,
|
|
102
|
+
);
|
|
103
|
+
await queryRunner.query(
|
|
104
|
+
`ALTER TABLE "IncidentEpisodePublicNote" DROP CONSTRAINT "FK_96d88a43c5479b67ddd7c70df16"`,
|
|
105
|
+
);
|
|
106
|
+
await queryRunner.query(
|
|
107
|
+
`ALTER TABLE "IncidentEpisodePublicNote" DROP CONSTRAINT "FK_7711bde5254d7c1021bbbb0f944"`,
|
|
108
|
+
);
|
|
109
|
+
await queryRunner.query(
|
|
110
|
+
`ALTER TABLE "IncidentEpisodePublicNote" DROP CONSTRAINT "FK_885de505291c2f6f4f86b988ca6"`,
|
|
111
|
+
);
|
|
112
|
+
await queryRunner.query(
|
|
113
|
+
`ALTER TABLE "IncidentEpisodePublicNote" DROP CONSTRAINT "FK_46268b7b996f3b8129136d12d21"`,
|
|
114
|
+
);
|
|
115
|
+
await queryRunner.query(
|
|
116
|
+
`DROP INDEX "public"."IDX_30d4a06d51be505b6233185906"`,
|
|
117
|
+
);
|
|
118
|
+
await queryRunner.query(
|
|
119
|
+
`DROP INDEX "public"."IDX_298e3524e859ddb920c05e1072"`,
|
|
120
|
+
);
|
|
121
|
+
await queryRunner.query(
|
|
122
|
+
`DROP INDEX "public"."IDX_9d7bfebab97dc56583df143ae8"`,
|
|
123
|
+
);
|
|
124
|
+
await queryRunner.query(
|
|
125
|
+
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type": "RestrictionTimes", "value": {"restictionType": "None", "dayRestrictionTimes": null, "weeklyRestrictionTimes": []}}'`,
|
|
126
|
+
);
|
|
127
|
+
await queryRunner.query(
|
|
128
|
+
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type": "Recurring", "value": {"intervalType": "Day", "intervalCount": {"_type": "PositiveNumber", "value": 1}}}'`,
|
|
129
|
+
);
|
|
130
|
+
await queryRunner.query(
|
|
131
|
+
`ALTER TABLE "IncidentEpisodeStateTimeline" DROP COLUMN "subscriberNotificationStatusMessage"`,
|
|
132
|
+
);
|
|
133
|
+
await queryRunner.query(
|
|
134
|
+
`ALTER TABLE "IncidentEpisodeStateTimeline" DROP COLUMN "subscriberNotificationStatus"`,
|
|
135
|
+
);
|
|
136
|
+
await queryRunner.query(
|
|
137
|
+
`ALTER TABLE "IncidentEpisodeStateTimeline" DROP COLUMN "shouldStatusPageSubscribersBeNotified"`,
|
|
138
|
+
);
|
|
139
|
+
await queryRunner.query(
|
|
140
|
+
`ALTER TABLE "StatusPage" DROP COLUMN "showEpisodesOnStatusPage"`,
|
|
141
|
+
);
|
|
142
|
+
await queryRunner.query(
|
|
143
|
+
`ALTER TABLE "IncidentEpisode" DROP COLUMN "subscriberNotificationStatusMessage"`,
|
|
144
|
+
);
|
|
145
|
+
await queryRunner.query(
|
|
146
|
+
`ALTER TABLE "IncidentEpisode" DROP COLUMN "subscriberNotificationStatusOnEpisodeCreated"`,
|
|
147
|
+
);
|
|
148
|
+
await queryRunner.query(
|
|
149
|
+
`ALTER TABLE "IncidentEpisode" DROP COLUMN "shouldStatusPageSubscribersBeNotifiedOnEpisodeCreated"`,
|
|
150
|
+
);
|
|
151
|
+
await queryRunner.query(
|
|
152
|
+
`ALTER TABLE "IncidentEpisode" DROP COLUMN "declaredAt"`,
|
|
153
|
+
);
|
|
154
|
+
await queryRunner.query(
|
|
155
|
+
`ALTER TABLE "IncidentEpisode" DROP COLUMN "isVisibleOnStatusPage"`,
|
|
156
|
+
);
|
|
157
|
+
await queryRunner.query(
|
|
158
|
+
`ALTER TABLE "IncidentGroupingRule" DROP COLUMN "showEpisodeOnStatusPage"`,
|
|
159
|
+
);
|
|
160
|
+
await queryRunner.query(
|
|
161
|
+
`DROP INDEX "public"."IDX_0dfcd7747b6e55239df9bbaac5"`,
|
|
162
|
+
);
|
|
163
|
+
await queryRunner.query(
|
|
164
|
+
`DROP INDEX "public"."IDX_8e439d24c574141d9a66d74fa5"`,
|
|
165
|
+
);
|
|
166
|
+
await queryRunner.query(`DROP TABLE "IncidentEpisodePublicNoteFile"`);
|
|
167
|
+
await queryRunner.query(
|
|
168
|
+
`DROP INDEX "public"."IDX_784fb865a857417194a37034ed"`,
|
|
169
|
+
);
|
|
170
|
+
await queryRunner.query(
|
|
171
|
+
`DROP INDEX "public"."IDX_2e0c6dd840bbc05b9a5117f882"`,
|
|
172
|
+
);
|
|
173
|
+
await queryRunner.query(
|
|
174
|
+
`DROP INDEX "public"."IDX_885de505291c2f6f4f86b988ca"`,
|
|
175
|
+
);
|
|
176
|
+
await queryRunner.query(
|
|
177
|
+
`DROP INDEX "public"."IDX_46268b7b996f3b8129136d12d2"`,
|
|
178
|
+
);
|
|
179
|
+
await queryRunner.query(`DROP TABLE "IncidentEpisodePublicNote"`);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { MigrationInterface, QueryRunner } from "typeorm";
|
|
2
|
+
|
|
3
|
+
export class MigrationName1770237245069 implements MigrationInterface {
|
|
4
|
+
public name = "MigrationName1770237245069";
|
|
5
|
+
|
|
6
|
+
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
7
|
+
await queryRunner.query(
|
|
8
|
+
`ALTER TABLE "StatusPage" ADD "showEpisodeHistoryInDays" integer NOT NULL DEFAULT '14'`,
|
|
9
|
+
);
|
|
10
|
+
await queryRunner.query(
|
|
11
|
+
`ALTER TABLE "StatusPage" ADD "showEpisodeLabelsOnStatusPage" boolean NOT NULL DEFAULT false`,
|
|
12
|
+
);
|
|
13
|
+
await queryRunner.query(
|
|
14
|
+
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type":"Recurring","value":{"intervalType":"Day","intervalCount":{"_type":"PositiveNumber","value":1}}}'`,
|
|
15
|
+
);
|
|
16
|
+
await queryRunner.query(
|
|
17
|
+
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type":"RestrictionTimes","value":{"restictionType":"None","dayRestrictionTimes":null,"weeklyRestrictionTimes":[]}}'`,
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
22
|
+
await queryRunner.query(
|
|
23
|
+
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type": "RestrictionTimes", "value": {"restictionType": "None", "dayRestrictionTimes": null, "weeklyRestrictionTimes": []}}'`,
|
|
24
|
+
);
|
|
25
|
+
await queryRunner.query(
|
|
26
|
+
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type": "Recurring", "value": {"intervalType": "Day", "intervalCount": {"_type": "PositiveNumber", "value": 1}}}'`,
|
|
27
|
+
);
|
|
28
|
+
await queryRunner.query(
|
|
29
|
+
`ALTER TABLE "StatusPage" DROP COLUMN "showEpisodeLabelsOnStatusPage"`,
|
|
30
|
+
);
|
|
31
|
+
await queryRunner.query(
|
|
32
|
+
`ALTER TABLE "StatusPage" DROP COLUMN "showEpisodeHistoryInDays"`,
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -249,6 +249,8 @@ import { MigrationName1769774527481 } from "./1769774527481-MigrationName";
|
|
|
249
249
|
import { MigrationName1769780297584 } from "./1769780297584-MigrationName";
|
|
250
250
|
import { MigrationName1769802715014 } from "./1769802715014-MigrationName";
|
|
251
251
|
import { MigrationName1770054293299 } from "./1770054293299-MigrationName";
|
|
252
|
+
import { MigrationName1770232207959 } from "./1770232207959-MigrationName";
|
|
253
|
+
import { MigrationName1770237245069 } from "./1770237245069-MigrationName";
|
|
252
254
|
|
|
253
255
|
export default [
|
|
254
256
|
InitialMigration,
|
|
@@ -502,4 +504,6 @@ export default [
|
|
|
502
504
|
MigrationName1769780297584,
|
|
503
505
|
MigrationName1769802715014,
|
|
504
506
|
MigrationName1770054293299,
|
|
507
|
+
MigrationName1770232207959,
|
|
508
|
+
MigrationName1770237245069,
|
|
505
509
|
];
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
import CreateBy from "../Types/Database/CreateBy";
|
|
2
|
+
import { OnCreate, OnUpdate } from "../Types/Database/Hooks";
|
|
3
|
+
import DatabaseService from "./DatabaseService";
|
|
4
|
+
import OneUptimeDate from "../../Types/Date";
|
|
5
|
+
import Model from "../../Models/DatabaseModels/IncidentEpisodePublicNote";
|
|
6
|
+
import IncidentEpisodeFeedService from "./IncidentEpisodeFeedService";
|
|
7
|
+
import { IncidentEpisodeFeedEventType } from "../../Models/DatabaseModels/IncidentEpisodeFeed";
|
|
8
|
+
import { Blue500, Indigo500 } from "../../Types/BrandColors";
|
|
9
|
+
import ObjectID from "../../Types/ObjectID";
|
|
10
|
+
import { LIMIT_PER_PROJECT } from "../../Types/Database/LimitMax";
|
|
11
|
+
import IncidentEpisodeService from "./IncidentEpisodeService";
|
|
12
|
+
import IncidentEpisode from "../../Models/DatabaseModels/IncidentEpisode";
|
|
13
|
+
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
|
|
14
|
+
import StatusPageSubscriberNotificationStatus from "../../Types/StatusPage/StatusPageSubscriberNotificationStatus";
|
|
15
|
+
import File from "../../Models/DatabaseModels/File";
|
|
16
|
+
import FileAttachmentMarkdownUtil from "../Utils/FileAttachmentMarkdownUtil";
|
|
17
|
+
|
|
18
|
+
export class Service extends DatabaseService<Model> {
|
|
19
|
+
public constructor() {
|
|
20
|
+
super(Model);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@CaptureSpan()
|
|
24
|
+
public async addNote(data: {
|
|
25
|
+
userId: ObjectID;
|
|
26
|
+
incidentEpisodeId: ObjectID;
|
|
27
|
+
projectId: ObjectID;
|
|
28
|
+
note: string;
|
|
29
|
+
attachmentFileIds?: Array<ObjectID>;
|
|
30
|
+
postedFromSlackMessageId?: string;
|
|
31
|
+
}): Promise<Model> {
|
|
32
|
+
const publicNote: Model = new Model();
|
|
33
|
+
publicNote.createdByUserId = data.userId;
|
|
34
|
+
publicNote.incidentEpisodeId = data.incidentEpisodeId;
|
|
35
|
+
publicNote.projectId = data.projectId;
|
|
36
|
+
publicNote.note = data.note;
|
|
37
|
+
publicNote.postedAt = OneUptimeDate.getCurrentDate();
|
|
38
|
+
|
|
39
|
+
if (data.postedFromSlackMessageId) {
|
|
40
|
+
publicNote.postedFromSlackMessageId = data.postedFromSlackMessageId;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (data.attachmentFileIds && data.attachmentFileIds.length > 0) {
|
|
44
|
+
publicNote.attachments = data.attachmentFileIds.map(
|
|
45
|
+
(fileId: ObjectID) => {
|
|
46
|
+
const file: File = new File();
|
|
47
|
+
file.id = fileId;
|
|
48
|
+
return file;
|
|
49
|
+
},
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return this.create({
|
|
54
|
+
data: publicNote,
|
|
55
|
+
props: {
|
|
56
|
+
isRoot: true,
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
@CaptureSpan()
|
|
62
|
+
public async hasNoteFromSlackMessage(data: {
|
|
63
|
+
incidentEpisodeId: ObjectID;
|
|
64
|
+
postedFromSlackMessageId: string;
|
|
65
|
+
}): Promise<boolean> {
|
|
66
|
+
const existingNote: Model | null = await this.findOneBy({
|
|
67
|
+
query: {
|
|
68
|
+
incidentEpisodeId: data.incidentEpisodeId,
|
|
69
|
+
postedFromSlackMessageId: data.postedFromSlackMessageId,
|
|
70
|
+
},
|
|
71
|
+
select: {
|
|
72
|
+
_id: true,
|
|
73
|
+
},
|
|
74
|
+
props: {
|
|
75
|
+
isRoot: true,
|
|
76
|
+
},
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
return existingNote !== null;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
@CaptureSpan()
|
|
83
|
+
protected override async onBeforeCreate(
|
|
84
|
+
createBy: CreateBy<Model>,
|
|
85
|
+
): Promise<OnCreate<Model>> {
|
|
86
|
+
if (!createBy.data.postedAt) {
|
|
87
|
+
createBy.data.postedAt = OneUptimeDate.getCurrentDate();
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Set notification status based on shouldStatusPageSubscribersBeNotifiedOnNoteCreated
|
|
91
|
+
if (
|
|
92
|
+
createBy.data.shouldStatusPageSubscribersBeNotifiedOnNoteCreated === false
|
|
93
|
+
) {
|
|
94
|
+
createBy.data.subscriberNotificationStatusOnNoteCreated =
|
|
95
|
+
StatusPageSubscriberNotificationStatus.Skipped;
|
|
96
|
+
createBy.data.subscriberNotificationStatusMessage =
|
|
97
|
+
"Notifications skipped as subscribers are not to be notified for this episode note.";
|
|
98
|
+
} else if (
|
|
99
|
+
createBy.data.shouldStatusPageSubscribersBeNotifiedOnNoteCreated === true
|
|
100
|
+
) {
|
|
101
|
+
createBy.data.subscriberNotificationStatusOnNoteCreated =
|
|
102
|
+
StatusPageSubscriberNotificationStatus.Pending;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return {
|
|
106
|
+
createBy: createBy,
|
|
107
|
+
carryForward: null,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
@CaptureSpan()
|
|
112
|
+
public override async onCreateSuccess(
|
|
113
|
+
_onCreate: OnCreate<Model>,
|
|
114
|
+
createdItem: Model,
|
|
115
|
+
): Promise<Model> {
|
|
116
|
+
const userId: ObjectID | null | undefined =
|
|
117
|
+
createdItem.createdByUserId || createdItem.createdByUser?.id;
|
|
118
|
+
|
|
119
|
+
const incidentEpisodeId: ObjectID = createdItem.incidentEpisodeId!;
|
|
120
|
+
const projectId: ObjectID = createdItem.projectId!;
|
|
121
|
+
const episodeNumber: number | null =
|
|
122
|
+
await IncidentEpisodeService.getEpisodeNumber({
|
|
123
|
+
episodeId: incidentEpisodeId,
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
const attachmentsMarkdown: string = await this.getAttachmentsMarkdown(
|
|
127
|
+
createdItem.id!,
|
|
128
|
+
"/incident-episode-public-note/attachment",
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
await IncidentEpisodeFeedService.createIncidentEpisodeFeedItem({
|
|
132
|
+
incidentEpisodeId: createdItem.incidentEpisodeId!,
|
|
133
|
+
projectId: createdItem.projectId!,
|
|
134
|
+
incidentEpisodeFeedEventType: IncidentEpisodeFeedEventType.PublicNote,
|
|
135
|
+
displayColor: Indigo500,
|
|
136
|
+
userId: userId || undefined,
|
|
137
|
+
feedInfoInMarkdown: `📄 posted **public note** for this [Episode ${episodeNumber}](${(await IncidentEpisodeService.getEpisodeLinkInDashboard(projectId!, incidentEpisodeId!)).toString()}) on status page:
|
|
138
|
+
|
|
139
|
+
${(createdItem.note || "") + attachmentsMarkdown}
|
|
140
|
+
`,
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
return createdItem;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
@CaptureSpan()
|
|
147
|
+
public override async onUpdateSuccess(
|
|
148
|
+
onUpdate: OnUpdate<Model>,
|
|
149
|
+
_updatedItemIds: Array<ObjectID>,
|
|
150
|
+
): Promise<OnUpdate<Model>> {
|
|
151
|
+
if (onUpdate.updateBy.data.note) {
|
|
152
|
+
const updatedItems: Array<Model> = await this.findBy({
|
|
153
|
+
query: onUpdate.updateBy.query,
|
|
154
|
+
limit: LIMIT_PER_PROJECT,
|
|
155
|
+
skip: 0,
|
|
156
|
+
props: {
|
|
157
|
+
isRoot: true,
|
|
158
|
+
},
|
|
159
|
+
select: {
|
|
160
|
+
incidentEpisodeId: true,
|
|
161
|
+
projectId: true,
|
|
162
|
+
incidentEpisode: {
|
|
163
|
+
_id: true,
|
|
164
|
+
episodeNumber: true,
|
|
165
|
+
projectId: true,
|
|
166
|
+
},
|
|
167
|
+
note: true,
|
|
168
|
+
createdByUserId: true,
|
|
169
|
+
createdByUser: {
|
|
170
|
+
_id: true,
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
const userId: ObjectID | null | undefined =
|
|
176
|
+
onUpdate.updateBy.props.userId;
|
|
177
|
+
|
|
178
|
+
for (const updatedItem of updatedItems) {
|
|
179
|
+
const episode: IncidentEpisode = updatedItem.incidentEpisode!;
|
|
180
|
+
|
|
181
|
+
const attachmentsMarkdown: string = await this.getAttachmentsMarkdown(
|
|
182
|
+
updatedItem.id!,
|
|
183
|
+
"/incident-episode-public-note/attachment",
|
|
184
|
+
);
|
|
185
|
+
|
|
186
|
+
await IncidentEpisodeFeedService.createIncidentEpisodeFeedItem({
|
|
187
|
+
incidentEpisodeId: updatedItem.incidentEpisodeId!,
|
|
188
|
+
projectId: updatedItem.projectId!,
|
|
189
|
+
incidentEpisodeFeedEventType: IncidentEpisodeFeedEventType.PublicNote,
|
|
190
|
+
displayColor: Blue500,
|
|
191
|
+
userId: userId || undefined,
|
|
192
|
+
feedInfoInMarkdown: `📄 updated **Public Note** for this [Episode ${episode.episodeNumber}](${(await IncidentEpisodeService.getEpisodeLinkInDashboard(episode.projectId!, episode.id!)).toString()})
|
|
193
|
+
|
|
194
|
+
${(updatedItem.note || "") + attachmentsMarkdown}
|
|
195
|
+
`,
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return onUpdate;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
private async getAttachmentsMarkdown(
|
|
203
|
+
modelId: ObjectID,
|
|
204
|
+
attachmentApiPath: string,
|
|
205
|
+
): Promise<string> {
|
|
206
|
+
if (!modelId) {
|
|
207
|
+
return "";
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const noteWithAttachments: Model | null = await this.findOneById({
|
|
211
|
+
id: modelId,
|
|
212
|
+
select: {
|
|
213
|
+
attachments: {
|
|
214
|
+
_id: true,
|
|
215
|
+
},
|
|
216
|
+
},
|
|
217
|
+
props: {
|
|
218
|
+
isRoot: true,
|
|
219
|
+
},
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
if (!noteWithAttachments || !noteWithAttachments.attachments) {
|
|
223
|
+
return "";
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
const attachmentIds: Array<ObjectID> = noteWithAttachments.attachments
|
|
227
|
+
.map((file: File) => {
|
|
228
|
+
if (file.id) {
|
|
229
|
+
return file.id;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
if (file._id) {
|
|
233
|
+
return new ObjectID(file._id);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
return null;
|
|
237
|
+
})
|
|
238
|
+
.filter((id: ObjectID | null): id is ObjectID => {
|
|
239
|
+
return Boolean(id);
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
if (!attachmentIds.length) {
|
|
243
|
+
return "";
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
return await FileAttachmentMarkdownUtil.buildAttachmentMarkdown({
|
|
247
|
+
modelId,
|
|
248
|
+
attachmentIds,
|
|
249
|
+
attachmentApiPath,
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
export default new Service();
|
|
@@ -38,6 +38,8 @@ import Semaphore, { SemaphoreMutex } from "../Infrastructure/Semaphore";
|
|
|
38
38
|
import OnCallDutyPolicyService from "./OnCallDutyPolicyService";
|
|
39
39
|
import OnCallDutyPolicy from "../../Models/DatabaseModels/OnCallDutyPolicy";
|
|
40
40
|
import UserNotificationEventType from "../../Types/UserNotification/UserNotificationEventType";
|
|
41
|
+
import IncidentGroupingRuleService from "./IncidentGroupingRuleService";
|
|
42
|
+
import IncidentGroupingRule from "../../Models/DatabaseModels/IncidentGroupingRule";
|
|
41
43
|
|
|
42
44
|
export class Service extends DatabaseService<Model> {
|
|
43
45
|
public constructor() {
|
|
@@ -135,6 +137,30 @@ export class Service extends DatabaseService<Model> {
|
|
|
135
137
|
createBy.data.lastIncidentAddedAt = OneUptimeDate.getCurrentDate();
|
|
136
138
|
}
|
|
137
139
|
|
|
140
|
+
// Set declaredAt if not provided
|
|
141
|
+
if (!createBy.data.declaredAt) {
|
|
142
|
+
createBy.data.declaredAt = OneUptimeDate.getCurrentDate();
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Copy showEpisodeOnStatusPage from grouping rule if available
|
|
146
|
+
if (createBy.data.incidentGroupingRuleId) {
|
|
147
|
+
const groupingRule: IncidentGroupingRule | null =
|
|
148
|
+
await IncidentGroupingRuleService.findOneById({
|
|
149
|
+
id: createBy.data.incidentGroupingRuleId,
|
|
150
|
+
select: {
|
|
151
|
+
showEpisodeOnStatusPage: true,
|
|
152
|
+
},
|
|
153
|
+
props: {
|
|
154
|
+
isRoot: true,
|
|
155
|
+
},
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
if (groupingRule) {
|
|
159
|
+
createBy.data.isVisibleOnStatusPage =
|
|
160
|
+
groupingRule.showEpisodeOnStatusPage ?? true;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
138
164
|
return { createBy, carryForward: { mutex } };
|
|
139
165
|
} catch (error) {
|
|
140
166
|
// Release the mutex if it was acquired and an error occurred
|
package/Server/Services/Index.ts
CHANGED
|
@@ -181,6 +181,7 @@ import IncidentEpisodeRoleMemberService from "./IncidentEpisodeRoleMemberService
|
|
|
181
181
|
import IncidentEpisodeOwnerTeamService from "./IncidentEpisodeOwnerTeamService";
|
|
182
182
|
import IncidentEpisodeOwnerUserService from "./IncidentEpisodeOwnerUserService";
|
|
183
183
|
import IncidentEpisodeStateTimelineService from "./IncidentEpisodeStateTimelineService";
|
|
184
|
+
import IncidentEpisodePublicNoteService from "./IncidentEpisodePublicNoteService";
|
|
184
185
|
import AlertGroupingRuleService from "./AlertGroupingRuleService";
|
|
185
186
|
import IncidentSlaRuleService from "./IncidentSlaRuleService";
|
|
186
187
|
import IncidentSlaService from "./IncidentSlaService";
|
|
@@ -400,6 +401,7 @@ const services: Array<BaseService> = [
|
|
|
400
401
|
IncidentEpisodeOwnerTeamService,
|
|
401
402
|
IncidentEpisodeOwnerUserService,
|
|
402
403
|
IncidentEpisodeStateTimelineService,
|
|
404
|
+
IncidentEpisodePublicNoteService,
|
|
403
405
|
AlertGroupingRuleService,
|
|
404
406
|
IncidentSlaRuleService,
|
|
405
407
|
IncidentSlaService,
|
|
@@ -242,6 +242,12 @@ export default class MonitorIncident {
|
|
|
242
242
|
|
|
243
243
|
incident.isCreatedAutomatically = true;
|
|
244
244
|
|
|
245
|
+
// Set status page visibility (defaults to true if not specified)
|
|
246
|
+
if (criteriaIncident.showIncidentOnStatusPage !== undefined) {
|
|
247
|
+
incident.isVisibleOnStatusPage =
|
|
248
|
+
criteriaIncident.showIncidentOnStatusPage;
|
|
249
|
+
}
|
|
250
|
+
|
|
245
251
|
if (input.props.telemetryQuery) {
|
|
246
252
|
incident.telemetryQuery = input.props.telemetryQuery;
|
|
247
253
|
}
|
|
@@ -53,6 +53,10 @@ enum EmailTemplateType {
|
|
|
53
53
|
IncidentEpisodeOwnerNotePosted = "IncidentEpisodeOwnerNotePosted.hbs",
|
|
54
54
|
IncidentEpisodeOwnerResourceCreated = "IncidentEpisodeOwnerResourceCreated.hbs",
|
|
55
55
|
|
|
56
|
+
SubscriberEpisodeCreated = "SubscriberEpisodeCreated.hbs",
|
|
57
|
+
SubscriberEpisodeStateChanged = "SubscriberEpisodeStateChanged.hbs",
|
|
58
|
+
SubscriberEpisodeNoteCreated = "SubscriberEpisodeNoteCreated.hbs",
|
|
59
|
+
|
|
56
60
|
ScheduledMaintenanceOwnerNotePosted = "ScheduledMaintenanceOwnerNotePosted.hbs",
|
|
57
61
|
ScheduledMaintenanceOwnerAdded = "ScheduledMaintenanceOwnerAdded.hbs",
|
|
58
62
|
ScheduledMaintenanceOwnerStateChanged = "ScheduledMaintenanceOwnerStateChanged.hbs",
|