@oneuptime/common 9.1.2 → 9.2.0

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 (37) hide show
  1. package/Models/DatabaseModels/Incident.ts +112 -0
  2. package/Server/API/IncidentAPI.ts +106 -0
  3. package/Server/API/MicrosoftTeamsAPI.ts +42 -1
  4. package/Server/API/StatusPageAPI.ts +134 -0
  5. package/Server/Infrastructure/Postgres/SchemaMigrations/1764762146063-MigrationName.ts +45 -0
  6. package/Server/Infrastructure/Postgres/SchemaMigrations/1764767371788-MigrationName.ts +23 -0
  7. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +4 -0
  8. package/Server/Utils/Workspace/MicrosoftTeams/Actions/ActionTypes.ts +2 -2
  9. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +18 -16
  10. package/Types/Icon/IconProp.ts +1 -0
  11. package/UI/Components/EventItem/EventItem.tsx +32 -14
  12. package/UI/Components/Icon/Icon.tsx +8 -0
  13. package/build/dist/Models/DatabaseModels/Incident.js +115 -0
  14. package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
  15. package/build/dist/Server/API/IncidentAPI.js +76 -0
  16. package/build/dist/Server/API/IncidentAPI.js.map +1 -0
  17. package/build/dist/Server/API/MicrosoftTeamsAPI.js +35 -1
  18. package/build/dist/Server/API/MicrosoftTeamsAPI.js.map +1 -1
  19. package/build/dist/Server/API/StatusPageAPI.js +154 -45
  20. package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
  21. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1764762146063-MigrationName.js +22 -0
  22. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1764762146063-MigrationName.js.map +1 -0
  23. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1764767371788-MigrationName.js +14 -0
  24. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1764767371788-MigrationName.js.map +1 -0
  25. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +4 -0
  26. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  27. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/ActionTypes.js +2 -2
  28. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/ActionTypes.js.map +1 -1
  29. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +14 -12
  30. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
  31. package/build/dist/Types/Icon/IconProp.js +1 -0
  32. package/build/dist/Types/Icon/IconProp.js.map +1 -1
  33. package/build/dist/UI/Components/EventItem/EventItem.js +10 -6
  34. package/build/dist/UI/Components/EventItem/EventItem.js.map +1 -1
  35. package/build/dist/UI/Components/Icon/Icon.js +3 -0
  36. package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
  37. package/package.json +1 -1
@@ -7,6 +7,7 @@ import OnCallDutyPolicy from "./OnCallDutyPolicy";
7
7
  import Probe from "./Probe";
8
8
  import Project from "./Project";
9
9
  import User from "./User";
10
+ import File from "./File";
10
11
  import BaseModel from "./DatabaseBaseModel/DatabaseBaseModel";
11
12
  import Route from "../../Types/API/Route";
12
13
  import ColumnAccessControl from "../../Types/Database/AccessControl/ColumnAccessControl";
@@ -996,6 +997,117 @@ export default class Incident extends BaseModel {
996
997
  })
997
998
  public postmortemNote?: string = undefined;
998
999
 
1000
+ @ColumnAccessControl({
1001
+ create: [
1002
+ Permission.ProjectOwner,
1003
+ Permission.ProjectAdmin,
1004
+ Permission.ProjectMember,
1005
+ Permission.CreateProjectIncident,
1006
+ ],
1007
+ read: [
1008
+ Permission.ProjectOwner,
1009
+ Permission.ProjectAdmin,
1010
+ Permission.ProjectMember,
1011
+ Permission.ReadProjectIncident,
1012
+ ],
1013
+ update: [
1014
+ Permission.ProjectOwner,
1015
+ Permission.ProjectAdmin,
1016
+ Permission.ProjectMember,
1017
+ Permission.EditProjectIncident,
1018
+ ],
1019
+ })
1020
+ @TableColumn({
1021
+ type: TableColumnType.Boolean,
1022
+ title: "Show postmortem on status page?",
1023
+ description:
1024
+ "Should the postmortem note and attachments be visible on the status page once published?",
1025
+ defaultValue: false,
1026
+ isDefaultValueColumn: true,
1027
+ })
1028
+ @Column({
1029
+ type: ColumnType.Boolean,
1030
+ default: false,
1031
+ })
1032
+ public showPostmortemOnStatusPage?: boolean = undefined;
1033
+
1034
+ @ColumnAccessControl({
1035
+ create: [
1036
+ Permission.ProjectOwner,
1037
+ Permission.ProjectAdmin,
1038
+ Permission.ProjectMember,
1039
+ Permission.CreateProjectIncident,
1040
+ ],
1041
+ read: [
1042
+ Permission.ProjectOwner,
1043
+ Permission.ProjectAdmin,
1044
+ Permission.ProjectMember,
1045
+ Permission.ReadProjectIncident,
1046
+ ],
1047
+ update: [
1048
+ Permission.ProjectOwner,
1049
+ Permission.ProjectAdmin,
1050
+ Permission.ProjectMember,
1051
+ Permission.EditProjectIncident,
1052
+ ],
1053
+ })
1054
+ @TableColumn({
1055
+ type: TableColumnType.Date,
1056
+ title: "Postmortem Posted At",
1057
+ description:
1058
+ "Timestamp that will be shown alongside the published postmortem on the status page.",
1059
+ required: false,
1060
+ })
1061
+ @Column({
1062
+ type: ColumnType.Date,
1063
+ nullable: true,
1064
+ })
1065
+ public postmortemPostedAt?: Date = undefined;
1066
+
1067
+ @ColumnAccessControl({
1068
+ create: [
1069
+ Permission.ProjectOwner,
1070
+ Permission.ProjectAdmin,
1071
+ Permission.ProjectMember,
1072
+ Permission.CreateProjectIncident,
1073
+ ],
1074
+ read: [
1075
+ Permission.ProjectOwner,
1076
+ Permission.ProjectAdmin,
1077
+ Permission.ProjectMember,
1078
+ Permission.ReadProjectIncident,
1079
+ ],
1080
+ update: [
1081
+ Permission.ProjectOwner,
1082
+ Permission.ProjectAdmin,
1083
+ Permission.ProjectMember,
1084
+ Permission.EditProjectIncident,
1085
+ ],
1086
+ })
1087
+ @TableColumn({
1088
+ type: TableColumnType.EntityArray,
1089
+ modelType: File,
1090
+ title: "Postmortem Attachments",
1091
+ description:
1092
+ "Files that accompany the postmortem note and can be shared publicly when enabled.",
1093
+ required: false,
1094
+ })
1095
+ @ManyToMany(() => {
1096
+ return File;
1097
+ })
1098
+ @JoinTable({
1099
+ name: "IncidentPostmortemAttachmentFile",
1100
+ joinColumn: {
1101
+ name: "incidentId",
1102
+ referencedColumnName: "_id",
1103
+ },
1104
+ inverseJoinColumn: {
1105
+ name: "fileId",
1106
+ referencedColumnName: "_id",
1107
+ },
1108
+ })
1109
+ public postmortemAttachments?: Array<File> = undefined;
1110
+
999
1111
  @ColumnAccessControl({
1000
1112
  create: [],
1001
1113
  read: [
@@ -0,0 +1,106 @@
1
+ import Incident from "../../Models/DatabaseModels/Incident";
2
+ import File from "../../Models/DatabaseModels/File";
3
+ import NotFoundException from "../../Types/Exception/NotFoundException";
4
+ import ObjectID from "../../Types/ObjectID";
5
+ import IncidentService, {
6
+ Service as IncidentServiceType,
7
+ } from "../Services/IncidentService";
8
+ import UserMiddleware from "../Middleware/UserAuthorization";
9
+ import Response from "../Utils/Response";
10
+ import BaseAPI from "./BaseAPI";
11
+ import {
12
+ ExpressRequest,
13
+ ExpressResponse,
14
+ NextFunction,
15
+ } from "../Utils/Express";
16
+ import CommonAPI from "./CommonAPI";
17
+ import DatabaseCommonInteractionProps from "../../Types/BaseDatabase/DatabaseCommonInteractionProps";
18
+
19
+ export default class IncidentAPI extends BaseAPI<
20
+ Incident,
21
+ IncidentServiceType
22
+ > {
23
+ public constructor() {
24
+ super(Incident, IncidentService);
25
+
26
+ this.router.get(
27
+ `${new this.entityType()
28
+ .getCrudApiPath()
29
+ ?.toString()}/postmortem/attachment/:projectId/:incidentId/:fileId`,
30
+ UserMiddleware.getUserMiddleware,
31
+ async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
32
+ try {
33
+ await this.getPostmortemAttachment(req, res);
34
+ } catch (err) {
35
+ next(err);
36
+ }
37
+ },
38
+ );
39
+ }
40
+
41
+ private async getPostmortemAttachment(
42
+ req: ExpressRequest,
43
+ res: ExpressResponse,
44
+ ): Promise<void> {
45
+ const projectIdParam: string | undefined = req.params["projectId"];
46
+ const incidentIdParam: string | undefined = req.params["incidentId"];
47
+ const fileIdParam: string | undefined = req.params["fileId"];
48
+
49
+ if (!projectIdParam || !incidentIdParam || !fileIdParam) {
50
+ throw new NotFoundException("Attachment not found");
51
+ }
52
+
53
+ let incidentId: ObjectID;
54
+ let fileId: ObjectID;
55
+ let projectId: ObjectID;
56
+
57
+ try {
58
+ incidentId = new ObjectID(incidentIdParam);
59
+ fileId = new ObjectID(fileIdParam);
60
+ projectId = new ObjectID(projectIdParam);
61
+ } catch {
62
+ throw new NotFoundException("Attachment not found");
63
+ }
64
+
65
+ const props: DatabaseCommonInteractionProps =
66
+ await CommonAPI.getDatabaseCommonInteractionProps(req);
67
+
68
+ const incident: Incident | null = await this.service.findOneBy({
69
+ query: {
70
+ _id: incidentId,
71
+ projectId,
72
+ },
73
+ select: {
74
+ postmortemAttachments: {
75
+ _id: true,
76
+ file: true,
77
+ fileType: true,
78
+ name: true,
79
+ },
80
+ },
81
+ props,
82
+ });
83
+
84
+ if (!incident) {
85
+ throw new NotFoundException("Attachment not found");
86
+ }
87
+
88
+ const attachment: File | undefined = incident.postmortemAttachments?.find(
89
+ (file: File) => {
90
+ const attachmentId: string | null = file._id
91
+ ? file._id.toString()
92
+ : file.id
93
+ ? file.id.toString()
94
+ : null;
95
+ return attachmentId === fileId.toString();
96
+ },
97
+ );
98
+
99
+ if (!attachment || !attachment.file) {
100
+ throw new NotFoundException("Attachment not found");
101
+ }
102
+
103
+ Response.setNoCacheHeaders(res);
104
+ return Response.sendFileResponse(req, res, attachment);
105
+ }
106
+ }
@@ -101,7 +101,48 @@ export default class MicrosoftTeamsAPI {
101
101
  supportsCalling: false,
102
102
  supportsVideo: false,
103
103
  // Provide basic command lists to improve client compatibility (esp. mobile)
104
- commandLists: [],
104
+ commandLists: [
105
+ {
106
+ scopes: ["team", "groupChat", "personal"],
107
+ commands: [
108
+ {
109
+ title: "help",
110
+ description:
111
+ "Show instructions for interacting with the OneUptime bot.",
112
+ },
113
+ {
114
+ title: "create incident",
115
+ description:
116
+ "Launch the adaptive card to declare a new incident in OneUptime.",
117
+ },
118
+ {
119
+ title: "create maintenance",
120
+ description:
121
+ "Open the workflow to schedule maintenance directly from Teams.",
122
+ },
123
+ {
124
+ title: "show active incidents",
125
+ description:
126
+ "List all ongoing incidents with severity and state context.",
127
+ },
128
+ {
129
+ title: "show scheduled maintenance",
130
+ description:
131
+ "Display upcoming scheduled maintenance events for the workspace.",
132
+ },
133
+ {
134
+ title: "show ongoing maintenance",
135
+ description:
136
+ "Surface maintenance windows that are currently in progress.",
137
+ },
138
+ {
139
+ title: "show active alerts",
140
+ description:
141
+ "Provide a summary of alerts that still require attention.",
142
+ },
143
+ ],
144
+ },
145
+ ],
105
146
  },
106
147
  ],
107
148
  permissions: ["identity", "messageTeamMembers"],
@@ -408,6 +408,20 @@ export default class StatusPageAPI extends BaseAPI<
408
408
  },
409
409
  );
410
410
 
411
+ this.router.get(
412
+ `${new this.entityType()
413
+ .getCrudApiPath()
414
+ ?.toString()}/incident/postmortem/attachment/:statusPageId/:incidentId/:fileId`,
415
+ UserMiddleware.getUserMiddleware,
416
+ async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
417
+ try {
418
+ await this.getIncidentPostmortemAttachment(req, res);
419
+ } catch (err) {
420
+ next(err);
421
+ }
422
+ },
423
+ );
424
+
411
425
  this.router.get(
412
426
  `${new this.entityType()
413
427
  .getCrudApiPath()
@@ -1422,9 +1436,17 @@ export default class StatusPageAPI extends BaseAPI<
1422
1436
  let select: Select<Incident> = {
1423
1437
  createdAt: true,
1424
1438
  declaredAt: true,
1439
+ updatedAt: true,
1425
1440
  title: true,
1426
1441
  description: true,
1427
1442
  _id: true,
1443
+ postmortemNote: true,
1444
+ postmortemPostedAt: true,
1445
+ showPostmortemOnStatusPage: true,
1446
+ postmortemAttachments: {
1447
+ _id: true,
1448
+ name: true,
1449
+ },
1428
1450
  incidentSeverity: {
1429
1451
  name: true,
1430
1452
  color: true,
@@ -3306,9 +3328,17 @@ export default class StatusPageAPI extends BaseAPI<
3306
3328
  let selectIncidents: Select<Incident> = {
3307
3329
  createdAt: true,
3308
3330
  declaredAt: true,
3331
+ updatedAt: true,
3309
3332
  title: true,
3310
3333
  description: true,
3311
3334
  _id: true,
3335
+ postmortemNote: true,
3336
+ postmortemPostedAt: true,
3337
+ showPostmortemOnStatusPage: true,
3338
+ postmortemAttachments: {
3339
+ _id: true,
3340
+ name: true,
3341
+ },
3312
3342
  incidentSeverity: {
3313
3343
  name: true,
3314
3344
  color: true,
@@ -3969,6 +3999,110 @@ export default class StatusPageAPI extends BaseAPI<
3969
3999
  return Response.sendFileResponse(req, res, attachment);
3970
4000
  }
3971
4001
 
4002
+ private async getIncidentPostmortemAttachment(
4003
+ req: ExpressRequest,
4004
+ res: ExpressResponse,
4005
+ ): Promise<void> {
4006
+ const statusPageIdParam: string | undefined = req.params["statusPageId"];
4007
+ const incidentIdParam: string | undefined = req.params["incidentId"];
4008
+ const fileIdParam: string | undefined = req.params["fileId"];
4009
+
4010
+ if (!statusPageIdParam || !incidentIdParam || !fileIdParam) {
4011
+ throw new NotFoundException("Attachment not found");
4012
+ }
4013
+
4014
+ let statusPageId: ObjectID;
4015
+ let incidentId: ObjectID;
4016
+ let fileId: ObjectID;
4017
+
4018
+ try {
4019
+ statusPageId = new ObjectID(statusPageIdParam);
4020
+ incidentId = new ObjectID(incidentIdParam);
4021
+ fileId = new ObjectID(fileIdParam);
4022
+ } catch {
4023
+ throw new NotFoundException("Attachment not found");
4024
+ }
4025
+
4026
+ await this.checkHasReadAccess({
4027
+ statusPageId,
4028
+ req,
4029
+ });
4030
+
4031
+ const statusPage: StatusPage | null = await StatusPageService.findOneBy({
4032
+ query: {
4033
+ _id: statusPageId.toString(),
4034
+ },
4035
+ select: {
4036
+ _id: true,
4037
+ projectId: true,
4038
+ showIncidentsOnStatusPage: true,
4039
+ },
4040
+ props: {
4041
+ isRoot: true,
4042
+ },
4043
+ });
4044
+
4045
+ if (
4046
+ !statusPage ||
4047
+ !statusPage.projectId ||
4048
+ !statusPage.showIncidentsOnStatusPage
4049
+ ) {
4050
+ throw new NotFoundException("Attachment not found");
4051
+ }
4052
+
4053
+ const { monitorsOnStatusPage } =
4054
+ await StatusPageService.getMonitorIdsOnStatusPage({
4055
+ statusPageId,
4056
+ });
4057
+
4058
+ if (!monitorsOnStatusPage || monitorsOnStatusPage.length === 0) {
4059
+ throw new NotFoundException("Attachment not found");
4060
+ }
4061
+
4062
+ const incident: Incident | null = await IncidentService.findOneBy({
4063
+ query: {
4064
+ _id: incidentId.toString(),
4065
+ projectId: statusPage.projectId!,
4066
+ isVisibleOnStatusPage: true,
4067
+ showPostmortemOnStatusPage: true,
4068
+ monitors: monitorsOnStatusPage as any,
4069
+ },
4070
+ select: {
4071
+ postmortemAttachments: {
4072
+ _id: true,
4073
+ file: true,
4074
+ fileType: true,
4075
+ name: true,
4076
+ },
4077
+ },
4078
+ props: {
4079
+ isRoot: true,
4080
+ },
4081
+ });
4082
+
4083
+ if (!incident) {
4084
+ throw new NotFoundException("Attachment not found");
4085
+ }
4086
+
4087
+ const attachment: File | undefined = incident.postmortemAttachments?.find(
4088
+ (file: File) => {
4089
+ const attachmentId: string | null = file._id
4090
+ ? file._id.toString()
4091
+ : file.id
4092
+ ? file.id.toString()
4093
+ : null;
4094
+ return attachmentId === fileId.toString();
4095
+ },
4096
+ );
4097
+
4098
+ if (!attachment || !attachment.file) {
4099
+ throw new NotFoundException("Attachment not found");
4100
+ }
4101
+
4102
+ Response.setNoCacheHeaders(res);
4103
+ return Response.sendFileResponse(req, res, attachment);
4104
+ }
4105
+
3972
4106
  private async getIncidentPublicNoteAttachment(
3973
4107
  req: ExpressRequest,
3974
4108
  res: ExpressResponse,
@@ -0,0 +1,45 @@
1
+ import { MigrationInterface, QueryRunner } from "typeorm";
2
+
3
+ export class MigrationName1764762146063 implements MigrationInterface {
4
+ public name = "MigrationName1764762146063";
5
+
6
+ public async up(queryRunner: QueryRunner): Promise<void> {
7
+ await queryRunner.query(
8
+ `CREATE TABLE "IncidentPostmortemAttachmentFile" ("incidentId" uuid NOT NULL, "fileId" uuid NOT NULL, CONSTRAINT "PK_40b17c7d5bcfbde48d7ebab4130" PRIMARY KEY ("incidentId", "fileId"))`,
9
+ );
10
+ await queryRunner.query(
11
+ `CREATE INDEX "IDX_62b9c09c42e05df3f134aa14a4" ON "IncidentPostmortemAttachmentFile" ("incidentId") `,
12
+ );
13
+ await queryRunner.query(
14
+ `CREATE INDEX "IDX_7e09116a3b9672622bba9f8b2e" ON "IncidentPostmortemAttachmentFile" ("fileId") `,
15
+ );
16
+ await queryRunner.query(
17
+ `ALTER TABLE "Incident" ADD "showPostmortemOnStatusPage" boolean NOT NULL DEFAULT false`,
18
+ );
19
+ await queryRunner.query(
20
+ `ALTER TABLE "IncidentPostmortemAttachmentFile" ADD CONSTRAINT "FK_62b9c09c42e05df3f134aa14a46" FOREIGN KEY ("incidentId") REFERENCES "Incident"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
21
+ );
22
+ await queryRunner.query(
23
+ `ALTER TABLE "IncidentPostmortemAttachmentFile" ADD CONSTRAINT "FK_7e09116a3b9672622bba9f8b2e3" FOREIGN KEY ("fileId") REFERENCES "File"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
24
+ );
25
+ }
26
+
27
+ public async down(queryRunner: QueryRunner): Promise<void> {
28
+ await queryRunner.query(
29
+ `ALTER TABLE "IncidentPostmortemAttachmentFile" DROP CONSTRAINT "FK_7e09116a3b9672622bba9f8b2e3"`,
30
+ );
31
+ await queryRunner.query(
32
+ `ALTER TABLE "IncidentPostmortemAttachmentFile" DROP CONSTRAINT "FK_62b9c09c42e05df3f134aa14a46"`,
33
+ );
34
+ await queryRunner.query(
35
+ `ALTER TABLE "Incident" DROP COLUMN "showPostmortemOnStatusPage"`,
36
+ );
37
+ await queryRunner.query(
38
+ `DROP INDEX "public"."IDX_7e09116a3b9672622bba9f8b2e"`,
39
+ );
40
+ await queryRunner.query(
41
+ `DROP INDEX "public"."IDX_62b9c09c42e05df3f134aa14a4"`,
42
+ );
43
+ await queryRunner.query(`DROP TABLE "IncidentPostmortemAttachmentFile"`);
44
+ }
45
+ }
@@ -0,0 +1,23 @@
1
+ import { MigrationInterface, QueryRunner } from "typeorm";
2
+
3
+ export class MigrationName1764767371788 implements MigrationInterface {
4
+ public name = "MigrationName1764767371788";
5
+
6
+ public async up(queryRunner: QueryRunner): Promise<void> {
7
+ await queryRunner.query(
8
+ `ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type":"Recurring","value":{"intervalType":"Day","intervalCount":{"_type":"PositiveNumber","value":1}}}'`,
9
+ );
10
+ await queryRunner.query(
11
+ `ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type":"RestrictionTimes","value":{"restictionType":"None","dayRestrictionTimes":null,"weeklyRestrictionTimes":[]}}'`,
12
+ );
13
+ }
14
+
15
+ public async down(queryRunner: QueryRunner): Promise<void> {
16
+ await queryRunner.query(
17
+ `ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type": "RestrictionTimes", "value": {"restictionType": "None", "dayRestrictionTimes": null, "weeklyRestrictionTimes": []}}'`,
18
+ );
19
+ await queryRunner.query(
20
+ `ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type": "Recurring", "value": {"intervalType": "Day", "intervalCount": {"_type": "PositiveNumber", "value": 1}}}'`,
21
+ );
22
+ }
23
+ }
@@ -187,6 +187,8 @@ import { MigrationName1763477560906 } from "./1763477560906-MigrationName";
187
187
  import { MigrationName1763480947474 } from "./1763480947474-MigrationName";
188
188
  import { MigrationName1763643080445 } from "./1763643080445-MigrationName";
189
189
  import { MigrationName1764324618043 } from "./1764324618043-MigrationName";
190
+ import { MigrationName1764762146063 } from "./1764762146063-MigrationName";
191
+ import { MigrationName1764767371788 } from "./1764767371788-MigrationName";
190
192
 
191
193
  export default [
192
194
  InitialMigration,
@@ -378,4 +380,6 @@ export default [
378
380
  MigrationName1763480947474,
379
381
  MigrationName1763643080445,
380
382
  MigrationName1764324618043,
383
+ MigrationName1764762146063,
384
+ MigrationName1764767371788,
381
385
  ];
@@ -16,7 +16,7 @@ export enum MicrosoftTeamsIncidentActionType {
16
16
  SubmitExecuteIncidentOnCallPolicy = "SubmitExecuteIncidentOnCallPolicy",
17
17
  ViewChangeIncidentState = "ViewChangeIncidentState",
18
18
  SubmitChangeIncidentState = "SubmitChangeIncidentState",
19
- NewIncident = "/incident", // new incident slash command
19
+ NewIncident = "CreateIncident",
20
20
  SubmitNewIncident = "SubmitNewIncident",
21
21
  }
22
22
 
@@ -57,7 +57,7 @@ export enum MicrosoftTeamsScheduledMaintenanceActionType {
57
57
  SubmitScheduledMaintenanceNote = "SubmitScheduledMaintenanceNote",
58
58
  ViewChangeScheduledMaintenanceState = "ViewChangeScheduledMaintenanceState",
59
59
  SubmitChangeScheduledMaintenanceState = "SubmitChangeScheduledMaintenanceState",
60
- NewScheduledMaintenance = "/maintenance", // new scheduled maintenance slash command
60
+ NewScheduledMaintenance = "CreateMaintenance",
61
61
  SubmitNewScheduledMaintenance = "SubmitNewScheduledMaintenance",
62
62
  }
63
63
 
@@ -1798,14 +1798,19 @@ export default class MicrosoftTeamsUtil extends WorkspaceBase {
1798
1798
  let responseText: string = "";
1799
1799
 
1800
1800
  try {
1801
+ const isCreateIncidentCommand: boolean =
1802
+ cleanText === "create incident" ||
1803
+ cleanText.startsWith("create incident ");
1804
+
1805
+ const isCreateMaintenanceCommand: boolean =
1806
+ cleanText === "create maintenance" ||
1807
+ cleanText.startsWith("create maintenance ");
1808
+
1801
1809
  if (cleanText.includes("help") || cleanText === "") {
1802
1810
  responseText = this.getHelpMessage();
1803
- } else if (
1804
- cleanText === "/incident" ||
1805
- cleanText.startsWith("/incident ")
1806
- ) {
1807
- // Handle /incident slash command
1808
- logger.debug("Processing /incident command");
1811
+ } else if (isCreateIncidentCommand) {
1812
+ // Handle create incident command (legacy slash command supported)
1813
+ logger.debug("Processing create incident command");
1809
1814
  const card: JSONObject =
1810
1815
  await MicrosoftTeamsIncidentActions.buildNewIncidentCard(projectId);
1811
1816
  await data.turnContext.sendActivity({
@@ -1818,12 +1823,9 @@ export default class MicrosoftTeamsUtil extends WorkspaceBase {
1818
1823
  });
1819
1824
  logger.debug("New incident card sent successfully");
1820
1825
  return;
1821
- } else if (
1822
- cleanText === "/maintenance" ||
1823
- cleanText.startsWith("/maintenance ")
1824
- ) {
1825
- // Handle /maintenance slash command
1826
- logger.debug("Processing /maintenance command");
1826
+ } else if (isCreateMaintenanceCommand) {
1827
+ // Handle create maintenance command (legacy slash command supported)
1828
+ logger.debug("Processing create maintenance command");
1827
1829
  const card: JSONObject =
1828
1830
  await MicrosoftTeamsScheduledMaintenanceActions.buildNewScheduledMaintenanceCard(
1829
1831
  projectId,
@@ -1880,8 +1882,8 @@ export default class MicrosoftTeamsUtil extends WorkspaceBase {
1880
1882
 
1881
1883
  **Available Commands:**
1882
1884
  - **help** — Show this help message
1883
- - **/incident** — Create a new incident
1884
- - **/maintenance** — Create a new scheduled maintenance event
1885
+ - **create incident** — Create a new incident
1886
+ - **create maintenance** — Create a new scheduled maintenance event
1885
1887
  - **show active incidents** — Display all currently active incidents
1886
1888
  - **show scheduled maintenance** — Show upcoming scheduled maintenance events
1887
1889
  - **show ongoing maintenance** — Display currently ongoing maintenance events
@@ -2720,11 +2722,11 @@ All monitoring checks are passing normally.`;
2720
2722
  value: "Show quick help and useful links",
2721
2723
  },
2722
2724
  {
2723
- title: "/incident",
2725
+ title: "create incident",
2724
2726
  value: "Create a new incident without leaving Teams",
2725
2727
  },
2726
2728
  {
2727
- title: "/maintenance",
2729
+ title: "create maintenance",
2728
2730
  value: "Schedule or review maintenance windows",
2729
2731
  },
2730
2732
  {
@@ -2,6 +2,7 @@ enum IconProp {
2
2
  Equals = "Equals",
3
3
  Archive = "Archive",
4
4
  File = "File",
5
+ DocumentCheck = "DocumentCheck",
5
6
  Automation = "Automation",
6
7
  Workflow = "Workflow",
7
8
  TableCells = "TableCells",