mirror of
https://github.com/OneUptime/oneuptime.git
synced 2026-04-06 00:32:12 +02:00
Refactor and clean up code across multiple files
- Added missing commas in migration index. - Improved type annotations for dynamic imports in IncidentService and IncidentSlaRuleService. - Simplified logger debug messages in IncidentSlaService and IncidentSlaRuleService. - Cleaned up JSX formatting in IconPicker, NotificationBellDropdown, RoleLabel, and Header components. - Enhanced readability by restructuring long lines and removing unnecessary line breaks in various components. - Updated error handling in fetch functions within DashboardHeader to use concise catch blocks. - Refactored UserSettings and Incident routes for better readability. - Improved code consistency and formatting in CheckSlaBreaches job.
This commit is contained in:
@@ -520,7 +520,8 @@ export default class IncidentSla extends BaseModel {
|
||||
type: TableColumnType.Date,
|
||||
required: false,
|
||||
title: "Breach Notification Sent At",
|
||||
description: "The time when breach notification was sent to incident owners",
|
||||
description:
|
||||
"The time when breach notification was sent to incident owners",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Date,
|
||||
|
||||
@@ -44,10 +44,7 @@ import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
|
||||
Permission.ReadTeamMemberCustomField,
|
||||
Permission.ReadAllProjectResources,
|
||||
],
|
||||
delete: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
],
|
||||
delete: [Permission.ProjectOwner, Permission.ProjectAdmin],
|
||||
update: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
|
||||
@@ -44,8 +44,6 @@ export default class ProjectAPI extends BaseAPI<Project, ProjectServiceType> {
|
||||
|
||||
const projectId: ObjectID = new ObjectID(req.params["id"] as string);
|
||||
|
||||
|
||||
|
||||
const body: JSONObject = (req.body as JSONObject) || {};
|
||||
const data: JSONObject = (body["data"] as JSONObject) || {};
|
||||
const paymentProviderPlanId: string | undefined = data[
|
||||
@@ -56,7 +54,6 @@ export default class ProjectAPI extends BaseAPI<Project, ProjectServiceType> {
|
||||
throw new BadDataException("Plan ID is required to change plan");
|
||||
}
|
||||
|
||||
|
||||
// Check for payment methods early before making any Stripe API calls
|
||||
const project: Project | null = await ProjectService.findOneById({
|
||||
id: projectId,
|
||||
@@ -82,7 +79,9 @@ export default class ProjectAPI extends BaseAPI<Project, ProjectServiceType> {
|
||||
);
|
||||
|
||||
if (!hasPaymentMethods) {
|
||||
throw new BadDataException(Errors.BillingService.NO_PAYMENTS_METHODS);
|
||||
throw new BadDataException(
|
||||
Errors.BillingService.NO_PAYMENTS_METHODS,
|
||||
);
|
||||
}
|
||||
|
||||
const permissions: Array<UserPermission> =
|
||||
@@ -107,7 +106,6 @@ export default class ProjectAPI extends BaseAPI<Project, ProjectServiceType> {
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
await ProjectService.changePlan({
|
||||
projectId: projectId,
|
||||
paymentProviderPlanId: paymentProviderPlanId,
|
||||
|
||||
@@ -1,40 +1,91 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class MigrationName1769772215532 implements MigrationInterface {
|
||||
public name = 'MigrationName1769772215532'
|
||||
public name = "MigrationName1769772215532";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`CREATE TABLE "ProjectUserProfile" ("_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, "userId" uuid NOT NULL, "customFields" jsonb, "createdByUserId" uuid, "deletedByUserId" uuid, CONSTRAINT "PK_2fd2054e182a7603f7032745eb9" PRIMARY KEY ("_id"))`);
|
||||
await queryRunner.query(`CREATE INDEX "IDX_3ba2d6a8eaeb966afa8820dbf0" ON "ProjectUserProfile" ("projectId") `);
|
||||
await queryRunner.query(`CREATE INDEX "IDX_39df4735afea8ab70c00674575" ON "ProjectUserProfile" ("userId") `);
|
||||
await queryRunner.query(`CREATE TABLE "TeamMemberCustomField" ("_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, "name" character varying(100) NOT NULL, "description" character varying(500), "customFieldType" character varying(100), "createdByUserId" uuid, "deletedByUserId" uuid, CONSTRAINT "PK_c0a4e92fd1fb77fe4cbb2f85ad4" PRIMARY KEY ("_id"))`);
|
||||
await queryRunner.query(`CREATE INDEX "IDX_e11389841b4ca122ec4a36c472" ON "TeamMemberCustomField" ("projectId") `);
|
||||
await queryRunner.query(`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type":"Recurring","value":{"intervalType":"Day","intervalCount":{"_type":"PositiveNumber","value":1}}}'`);
|
||||
await queryRunner.query(`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type":"RestrictionTimes","value":{"restictionType":"None","dayRestrictionTimes":null,"weeklyRestrictionTimes":[]}}'`);
|
||||
await queryRunner.query(`ALTER TABLE "ProjectUserProfile" ADD CONSTRAINT "FK_3ba2d6a8eaeb966afa8820dbf0a" FOREIGN KEY ("projectId") REFERENCES "Project"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||
await queryRunner.query(`ALTER TABLE "ProjectUserProfile" ADD CONSTRAINT "FK_39df4735afea8ab70c006745752" FOREIGN KEY ("userId") REFERENCES "User"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||
await queryRunner.query(`ALTER TABLE "ProjectUserProfile" ADD CONSTRAINT "FK_b9db61caf3923a882e09943f367" FOREIGN KEY ("createdByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`);
|
||||
await queryRunner.query(`ALTER TABLE "ProjectUserProfile" ADD CONSTRAINT "FK_5fe8245962849bde50687e2c707" FOREIGN KEY ("deletedByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`);
|
||||
await queryRunner.query(`ALTER TABLE "TeamMemberCustomField" ADD CONSTRAINT "FK_e11389841b4ca122ec4a36c4720" FOREIGN KEY ("projectId") REFERENCES "Project"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||
await queryRunner.query(`ALTER TABLE "TeamMemberCustomField" ADD CONSTRAINT "FK_5ea46786eae26e125d07bbfddfa" FOREIGN KEY ("createdByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`);
|
||||
await queryRunner.query(`ALTER TABLE "TeamMemberCustomField" ADD CONSTRAINT "FK_35409d7ec1b559d4de58913e522" FOREIGN KEY ("deletedByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`ALTER TABLE "TeamMemberCustomField" DROP CONSTRAINT "FK_35409d7ec1b559d4de58913e522"`);
|
||||
await queryRunner.query(`ALTER TABLE "TeamMemberCustomField" DROP CONSTRAINT "FK_5ea46786eae26e125d07bbfddfa"`);
|
||||
await queryRunner.query(`ALTER TABLE "TeamMemberCustomField" DROP CONSTRAINT "FK_e11389841b4ca122ec4a36c4720"`);
|
||||
await queryRunner.query(`ALTER TABLE "ProjectUserProfile" DROP CONSTRAINT "FK_5fe8245962849bde50687e2c707"`);
|
||||
await queryRunner.query(`ALTER TABLE "ProjectUserProfile" DROP CONSTRAINT "FK_b9db61caf3923a882e09943f367"`);
|
||||
await queryRunner.query(`ALTER TABLE "ProjectUserProfile" DROP CONSTRAINT "FK_39df4735afea8ab70c006745752"`);
|
||||
await queryRunner.query(`ALTER TABLE "ProjectUserProfile" DROP CONSTRAINT "FK_3ba2d6a8eaeb966afa8820dbf0a"`);
|
||||
await queryRunner.query(`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type": "RestrictionTimes", "value": {"restictionType": "None", "dayRestrictionTimes": null, "weeklyRestrictionTimes": []}}'`);
|
||||
await queryRunner.query(`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type": "Recurring", "value": {"intervalType": "Day", "intervalCount": {"_type": "PositiveNumber", "value": 1}}}'`);
|
||||
await queryRunner.query(`DROP INDEX "public"."IDX_e11389841b4ca122ec4a36c472"`);
|
||||
await queryRunner.query(`DROP TABLE "TeamMemberCustomField"`);
|
||||
await queryRunner.query(`DROP INDEX "public"."IDX_39df4735afea8ab70c00674575"`);
|
||||
await queryRunner.query(`DROP INDEX "public"."IDX_3ba2d6a8eaeb966afa8820dbf0"`);
|
||||
await queryRunner.query(`DROP TABLE "ProjectUserProfile"`);
|
||||
}
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`CREATE TABLE "ProjectUserProfile" ("_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, "userId" uuid NOT NULL, "customFields" jsonb, "createdByUserId" uuid, "deletedByUserId" uuid, CONSTRAINT "PK_2fd2054e182a7603f7032745eb9" PRIMARY KEY ("_id"))`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_3ba2d6a8eaeb966afa8820dbf0" ON "ProjectUserProfile" ("projectId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_39df4735afea8ab70c00674575" ON "ProjectUserProfile" ("userId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE TABLE "TeamMemberCustomField" ("_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, "name" character varying(100) NOT NULL, "description" character varying(500), "customFieldType" character varying(100), "createdByUserId" uuid, "deletedByUserId" uuid, CONSTRAINT "PK_c0a4e92fd1fb77fe4cbb2f85ad4" PRIMARY KEY ("_id"))`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_e11389841b4ca122ec4a36c472" ON "TeamMemberCustomField" ("projectId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type":"Recurring","value":{"intervalType":"Day","intervalCount":{"_type":"PositiveNumber","value":1}}}'`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type":"RestrictionTimes","value":{"restictionType":"None","dayRestrictionTimes":null,"weeklyRestrictionTimes":[]}}'`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ProjectUserProfile" ADD CONSTRAINT "FK_3ba2d6a8eaeb966afa8820dbf0a" FOREIGN KEY ("projectId") REFERENCES "Project"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ProjectUserProfile" ADD CONSTRAINT "FK_39df4735afea8ab70c006745752" FOREIGN KEY ("userId") REFERENCES "User"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ProjectUserProfile" ADD CONSTRAINT "FK_b9db61caf3923a882e09943f367" FOREIGN KEY ("createdByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ProjectUserProfile" ADD CONSTRAINT "FK_5fe8245962849bde50687e2c707" FOREIGN KEY ("deletedByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "TeamMemberCustomField" ADD CONSTRAINT "FK_e11389841b4ca122ec4a36c4720" FOREIGN KEY ("projectId") REFERENCES "Project"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "TeamMemberCustomField" ADD CONSTRAINT "FK_5ea46786eae26e125d07bbfddfa" FOREIGN KEY ("createdByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "TeamMemberCustomField" ADD CONSTRAINT "FK_35409d7ec1b559d4de58913e522" FOREIGN KEY ("deletedByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "TeamMemberCustomField" DROP CONSTRAINT "FK_35409d7ec1b559d4de58913e522"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "TeamMemberCustomField" DROP CONSTRAINT "FK_5ea46786eae26e125d07bbfddfa"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "TeamMemberCustomField" DROP CONSTRAINT "FK_e11389841b4ca122ec4a36c4720"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ProjectUserProfile" DROP CONSTRAINT "FK_5fe8245962849bde50687e2c707"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ProjectUserProfile" DROP CONSTRAINT "FK_b9db61caf3923a882e09943f367"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ProjectUserProfile" DROP CONSTRAINT "FK_39df4735afea8ab70c006745752"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ProjectUserProfile" DROP CONSTRAINT "FK_3ba2d6a8eaeb966afa8820dbf0a"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type": "RestrictionTimes", "value": {"restictionType": "None", "dayRestrictionTimes": null, "weeklyRestrictionTimes": []}}'`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type": "Recurring", "value": {"intervalType": "Day", "intervalCount": {"_type": "PositiveNumber", "value": 1}}}'`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_e11389841b4ca122ec4a36c472"`,
|
||||
);
|
||||
await queryRunner.query(`DROP TABLE "TeamMemberCustomField"`);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_39df4735afea8ab70c00674575"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_3ba2d6a8eaeb966afa8820dbf0"`,
|
||||
);
|
||||
await queryRunner.query(`DROP TABLE "ProjectUserProfile"`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,29 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class MigrationName1769774527481 implements MigrationInterface {
|
||||
public name = 'MigrationName1769774527481'
|
||||
public name = "MigrationName1769774527481";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`ALTER TABLE "IncidentRole" ADD "roleIcon" character varying(100)`);
|
||||
await queryRunner.query(`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type":"Recurring","value":{"intervalType":"Day","intervalCount":{"_type":"PositiveNumber","value":1}}}'`);
|
||||
await queryRunner.query(`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type":"RestrictionTimes","value":{"restictionType":"None","dayRestrictionTimes":null,"weeklyRestrictionTimes":[]}}'`);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type": "RestrictionTimes", "value": {"restictionType": "None", "dayRestrictionTimes": null, "weeklyRestrictionTimes": []}}'`);
|
||||
await queryRunner.query(`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type": "Recurring", "value": {"intervalType": "Day", "intervalCount": {"_type": "PositiveNumber", "value": 1}}}'`);
|
||||
await queryRunner.query(`ALTER TABLE "IncidentRole" DROP COLUMN "roleIcon"`);
|
||||
}
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentRole" ADD "roleIcon" character varying(100)`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type":"Recurring","value":{"intervalType":"Day","intervalCount":{"_type":"PositiveNumber","value":1}}}'`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type":"RestrictionTimes","value":{"restictionType":"None","dayRestrictionTimes":null,"weeklyRestrictionTimes":[]}}'`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type": "RestrictionTimes", "value": {"restictionType": "None", "dayRestrictionTimes": null, "weeklyRestrictionTimes": []}}'`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type": "Recurring", "value": {"intervalType": "Day", "intervalCount": {"_type": "PositiveNumber", "value": 1}}}'`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentRole" DROP COLUMN "roleIcon"`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,94 +1,245 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class MigrationName1769780297584 implements MigrationInterface {
|
||||
public name = 'MigrationName1769780297584'
|
||||
public name = "MigrationName1769780297584";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`CREATE TABLE "IncidentSlaRule" ("_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, "name" character varying(100) NOT NULL, "description" character varying(500), "order" integer NOT NULL DEFAULT '1', "isEnabled" boolean NOT NULL DEFAULT true, "responseTimeInMinutes" integer, "resolutionTimeInMinutes" integer, "atRiskThresholdInPercentage" integer NOT NULL DEFAULT '80', "internalNoteReminderIntervalInMinutes" integer, "publicNoteReminderIntervalInMinutes" integer, "internalNoteReminderTemplate" text, "publicNoteReminderTemplate" text, "incidentTitlePattern" character varying(500), "incidentDescriptionPattern" character varying(500), "createdByUserId" uuid, "deletedByUserId" uuid, CONSTRAINT "PK_7df8338a70c16abb7151cc9773a" PRIMARY KEY ("_id"))`);
|
||||
await queryRunner.query(`CREATE INDEX "IDX_cd2943c22620ee3a9910e45663" ON "IncidentSlaRule" ("projectId") `);
|
||||
await queryRunner.query(`CREATE INDEX "IDX_98e3b3d2a1e67d5d87f6254aad" ON "IncidentSlaRule" ("name") `);
|
||||
await queryRunner.query(`CREATE INDEX "IDX_7d2380a578cc24568b6e0e9f6a" ON "IncidentSlaRule" ("order") `);
|
||||
await queryRunner.query(`CREATE INDEX "IDX_ec7114aadb854b2e6f09fa3d16" ON "IncidentSlaRule" ("isEnabled") `);
|
||||
await queryRunner.query(`CREATE TABLE "IncidentSla" ("_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, "incidentId" uuid NOT NULL, "incidentSlaRuleId" uuid NOT NULL, "responseDeadline" TIMESTAMP WITH TIME ZONE, "resolutionDeadline" TIMESTAMP WITH TIME ZONE, "status" character varying NOT NULL DEFAULT 'On Track', "respondedAt" TIMESTAMP WITH TIME ZONE, "resolvedAt" TIMESTAMP WITH TIME ZONE, "lastInternalNoteReminderSentAt" TIMESTAMP WITH TIME ZONE, "lastPublicNoteReminderSentAt" TIMESTAMP WITH TIME ZONE, "breachNotificationSentAt" TIMESTAMP WITH TIME ZONE, "slaStartedAt" TIMESTAMP WITH TIME ZONE NOT NULL, "createdByUserId" uuid, "deletedByUserId" uuid, CONSTRAINT "PK_1e0e4d23867592377d865cd7fb6" PRIMARY KEY ("_id"))`);
|
||||
await queryRunner.query(`CREATE INDEX "IDX_b20ae37629c143339b0f105d3f" ON "IncidentSla" ("projectId") `);
|
||||
await queryRunner.query(`CREATE INDEX "IDX_2716e3d68b8fed7a062cb41e04" ON "IncidentSla" ("incidentId") `);
|
||||
await queryRunner.query(`CREATE INDEX "IDX_cae25577f21f1c0c52c6d038ab" ON "IncidentSla" ("incidentSlaRuleId") `);
|
||||
await queryRunner.query(`CREATE INDEX "IDX_872fce6c27af1f0aa04cf5b0bc" ON "IncidentSla" ("status") `);
|
||||
await queryRunner.query(`CREATE INDEX "IDX_1e9dfd0511bc457251e0d27992" ON "IncidentSla" ("slaStartedAt") `);
|
||||
await queryRunner.query(`CREATE TABLE "IncidentSlaRuleMonitor" ("incidentSlaRuleId" uuid NOT NULL, "monitorId" uuid NOT NULL, CONSTRAINT "PK_5ca43621c3484d364bba1db0fdb" PRIMARY KEY ("incidentSlaRuleId", "monitorId"))`);
|
||||
await queryRunner.query(`CREATE INDEX "IDX_330c3f5655149584f1918bf125" ON "IncidentSlaRuleMonitor" ("incidentSlaRuleId") `);
|
||||
await queryRunner.query(`CREATE INDEX "IDX_3deaa8530c9d6065da31f65116" ON "IncidentSlaRuleMonitor" ("monitorId") `);
|
||||
await queryRunner.query(`CREATE TABLE "IncidentSlaRuleIncidentSeverity" ("incidentSlaRuleId" uuid NOT NULL, "incidentSeverityId" uuid NOT NULL, CONSTRAINT "PK_2a68293adc48c01c8ef849ffefd" PRIMARY KEY ("incidentSlaRuleId", "incidentSeverityId"))`);
|
||||
await queryRunner.query(`CREATE INDEX "IDX_9d7443c084cbde74e8ab77d6df" ON "IncidentSlaRuleIncidentSeverity" ("incidentSlaRuleId") `);
|
||||
await queryRunner.query(`CREATE INDEX "IDX_1dbba01db81040f8139bf5c4aa" ON "IncidentSlaRuleIncidentSeverity" ("incidentSeverityId") `);
|
||||
await queryRunner.query(`CREATE TABLE "IncidentSlaRuleIncidentLabel" ("incidentSlaRuleId" uuid NOT NULL, "labelId" uuid NOT NULL, CONSTRAINT "PK_c3a28da9a45df8251bb25d5e8d6" PRIMARY KEY ("incidentSlaRuleId", "labelId"))`);
|
||||
await queryRunner.query(`CREATE INDEX "IDX_a63cac299eedb0d44c1e937fc2" ON "IncidentSlaRuleIncidentLabel" ("incidentSlaRuleId") `);
|
||||
await queryRunner.query(`CREATE INDEX "IDX_df0e2d83d9dcbc528b830645de" ON "IncidentSlaRuleIncidentLabel" ("labelId") `);
|
||||
await queryRunner.query(`CREATE TABLE "IncidentSlaRuleMonitorLabel" ("incidentSlaRuleId" uuid NOT NULL, "labelId" uuid NOT NULL, CONSTRAINT "PK_e20fa59ad1d35c2f3a9c45f0832" PRIMARY KEY ("incidentSlaRuleId", "labelId"))`);
|
||||
await queryRunner.query(`CREATE INDEX "IDX_c94cf6138ec340ae7c1976dbea" ON "IncidentSlaRuleMonitorLabel" ("incidentSlaRuleId") `);
|
||||
await queryRunner.query(`CREATE INDEX "IDX_93e6f28f50bf56aadcc907f440" ON "IncidentSlaRuleMonitorLabel" ("labelId") `);
|
||||
await queryRunner.query(`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type":"Recurring","value":{"intervalType":"Day","intervalCount":{"_type":"PositiveNumber","value":1}}}'`);
|
||||
await queryRunner.query(`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type":"RestrictionTimes","value":{"restictionType":"None","dayRestrictionTimes":null,"weeklyRestrictionTimes":[]}}'`);
|
||||
await queryRunner.query(`ALTER TABLE "IncidentSlaRule" ADD CONSTRAINT "FK_cd2943c22620ee3a9910e456637" FOREIGN KEY ("projectId") REFERENCES "Project"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||
await queryRunner.query(`ALTER TABLE "IncidentSlaRule" ADD CONSTRAINT "FK_26e788cca21b14940116395350f" FOREIGN KEY ("createdByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`);
|
||||
await queryRunner.query(`ALTER TABLE "IncidentSlaRule" ADD CONSTRAINT "FK_eb48fce1657c9a1e9245611857f" FOREIGN KEY ("deletedByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`);
|
||||
await queryRunner.query(`ALTER TABLE "IncidentSla" ADD CONSTRAINT "FK_b20ae37629c143339b0f105d3f8" FOREIGN KEY ("projectId") REFERENCES "Project"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||
await queryRunner.query(`ALTER TABLE "IncidentSla" ADD CONSTRAINT "FK_2716e3d68b8fed7a062cb41e04f" FOREIGN KEY ("incidentId") REFERENCES "Incident"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||
await queryRunner.query(`ALTER TABLE "IncidentSla" ADD CONSTRAINT "FK_cae25577f21f1c0c52c6d038ab4" FOREIGN KEY ("incidentSlaRuleId") REFERENCES "IncidentSlaRule"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||
await queryRunner.query(`ALTER TABLE "IncidentSla" ADD CONSTRAINT "FK_9771f22534ed092c59f55198c5a" FOREIGN KEY ("createdByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`);
|
||||
await queryRunner.query(`ALTER TABLE "IncidentSla" ADD CONSTRAINT "FK_c1cadef60fde93931b5131fbbba" FOREIGN KEY ("deletedByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`);
|
||||
await queryRunner.query(`ALTER TABLE "IncidentSlaRuleMonitor" ADD CONSTRAINT "FK_330c3f5655149584f1918bf1258" FOREIGN KEY ("incidentSlaRuleId") REFERENCES "IncidentSlaRule"("_id") ON DELETE CASCADE ON UPDATE CASCADE`);
|
||||
await queryRunner.query(`ALTER TABLE "IncidentSlaRuleMonitor" ADD CONSTRAINT "FK_3deaa8530c9d6065da31f65116c" FOREIGN KEY ("monitorId") REFERENCES "Monitor"("_id") ON DELETE CASCADE ON UPDATE CASCADE`);
|
||||
await queryRunner.query(`ALTER TABLE "IncidentSlaRuleIncidentSeverity" ADD CONSTRAINT "FK_9d7443c084cbde74e8ab77d6dfc" FOREIGN KEY ("incidentSlaRuleId") REFERENCES "IncidentSlaRule"("_id") ON DELETE CASCADE ON UPDATE CASCADE`);
|
||||
await queryRunner.query(`ALTER TABLE "IncidentSlaRuleIncidentSeverity" ADD CONSTRAINT "FK_1dbba01db81040f8139bf5c4aae" FOREIGN KEY ("incidentSeverityId") REFERENCES "IncidentSeverity"("_id") ON DELETE CASCADE ON UPDATE CASCADE`);
|
||||
await queryRunner.query(`ALTER TABLE "IncidentSlaRuleIncidentLabel" ADD CONSTRAINT "FK_a63cac299eedb0d44c1e937fc24" FOREIGN KEY ("incidentSlaRuleId") REFERENCES "IncidentSlaRule"("_id") ON DELETE CASCADE ON UPDATE CASCADE`);
|
||||
await queryRunner.query(`ALTER TABLE "IncidentSlaRuleIncidentLabel" ADD CONSTRAINT "FK_df0e2d83d9dcbc528b830645ded" FOREIGN KEY ("labelId") REFERENCES "Label"("_id") ON DELETE CASCADE ON UPDATE CASCADE`);
|
||||
await queryRunner.query(`ALTER TABLE "IncidentSlaRuleMonitorLabel" ADD CONSTRAINT "FK_c94cf6138ec340ae7c1976dbea2" FOREIGN KEY ("incidentSlaRuleId") REFERENCES "IncidentSlaRule"("_id") ON DELETE CASCADE ON UPDATE CASCADE`);
|
||||
await queryRunner.query(`ALTER TABLE "IncidentSlaRuleMonitorLabel" ADD CONSTRAINT "FK_93e6f28f50bf56aadcc907f4403" FOREIGN KEY ("labelId") REFERENCES "Label"("_id") ON DELETE CASCADE ON UPDATE CASCADE`);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`ALTER TABLE "IncidentSlaRuleMonitorLabel" DROP CONSTRAINT "FK_93e6f28f50bf56aadcc907f4403"`);
|
||||
await queryRunner.query(`ALTER TABLE "IncidentSlaRuleMonitorLabel" DROP CONSTRAINT "FK_c94cf6138ec340ae7c1976dbea2"`);
|
||||
await queryRunner.query(`ALTER TABLE "IncidentSlaRuleIncidentLabel" DROP CONSTRAINT "FK_df0e2d83d9dcbc528b830645ded"`);
|
||||
await queryRunner.query(`ALTER TABLE "IncidentSlaRuleIncidentLabel" DROP CONSTRAINT "FK_a63cac299eedb0d44c1e937fc24"`);
|
||||
await queryRunner.query(`ALTER TABLE "IncidentSlaRuleIncidentSeverity" DROP CONSTRAINT "FK_1dbba01db81040f8139bf5c4aae"`);
|
||||
await queryRunner.query(`ALTER TABLE "IncidentSlaRuleIncidentSeverity" DROP CONSTRAINT "FK_9d7443c084cbde74e8ab77d6dfc"`);
|
||||
await queryRunner.query(`ALTER TABLE "IncidentSlaRuleMonitor" DROP CONSTRAINT "FK_3deaa8530c9d6065da31f65116c"`);
|
||||
await queryRunner.query(`ALTER TABLE "IncidentSlaRuleMonitor" DROP CONSTRAINT "FK_330c3f5655149584f1918bf1258"`);
|
||||
await queryRunner.query(`ALTER TABLE "IncidentSla" DROP CONSTRAINT "FK_c1cadef60fde93931b5131fbbba"`);
|
||||
await queryRunner.query(`ALTER TABLE "IncidentSla" DROP CONSTRAINT "FK_9771f22534ed092c59f55198c5a"`);
|
||||
await queryRunner.query(`ALTER TABLE "IncidentSla" DROP CONSTRAINT "FK_cae25577f21f1c0c52c6d038ab4"`);
|
||||
await queryRunner.query(`ALTER TABLE "IncidentSla" DROP CONSTRAINT "FK_2716e3d68b8fed7a062cb41e04f"`);
|
||||
await queryRunner.query(`ALTER TABLE "IncidentSla" DROP CONSTRAINT "FK_b20ae37629c143339b0f105d3f8"`);
|
||||
await queryRunner.query(`ALTER TABLE "IncidentSlaRule" DROP CONSTRAINT "FK_eb48fce1657c9a1e9245611857f"`);
|
||||
await queryRunner.query(`ALTER TABLE "IncidentSlaRule" DROP CONSTRAINT "FK_26e788cca21b14940116395350f"`);
|
||||
await queryRunner.query(`ALTER TABLE "IncidentSlaRule" DROP CONSTRAINT "FK_cd2943c22620ee3a9910e456637"`);
|
||||
await queryRunner.query(`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type": "RestrictionTimes", "value": {"restictionType": "None", "dayRestrictionTimes": null, "weeklyRestrictionTimes": []}}'`);
|
||||
await queryRunner.query(`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type": "Recurring", "value": {"intervalType": "Day", "intervalCount": {"_type": "PositiveNumber", "value": 1}}}'`);
|
||||
await queryRunner.query(`DROP INDEX "public"."IDX_93e6f28f50bf56aadcc907f440"`);
|
||||
await queryRunner.query(`DROP INDEX "public"."IDX_c94cf6138ec340ae7c1976dbea"`);
|
||||
await queryRunner.query(`DROP TABLE "IncidentSlaRuleMonitorLabel"`);
|
||||
await queryRunner.query(`DROP INDEX "public"."IDX_df0e2d83d9dcbc528b830645de"`);
|
||||
await queryRunner.query(`DROP INDEX "public"."IDX_a63cac299eedb0d44c1e937fc2"`);
|
||||
await queryRunner.query(`DROP TABLE "IncidentSlaRuleIncidentLabel"`);
|
||||
await queryRunner.query(`DROP INDEX "public"."IDX_1dbba01db81040f8139bf5c4aa"`);
|
||||
await queryRunner.query(`DROP INDEX "public"."IDX_9d7443c084cbde74e8ab77d6df"`);
|
||||
await queryRunner.query(`DROP TABLE "IncidentSlaRuleIncidentSeverity"`);
|
||||
await queryRunner.query(`DROP INDEX "public"."IDX_3deaa8530c9d6065da31f65116"`);
|
||||
await queryRunner.query(`DROP INDEX "public"."IDX_330c3f5655149584f1918bf125"`);
|
||||
await queryRunner.query(`DROP TABLE "IncidentSlaRuleMonitor"`);
|
||||
await queryRunner.query(`DROP INDEX "public"."IDX_1e9dfd0511bc457251e0d27992"`);
|
||||
await queryRunner.query(`DROP INDEX "public"."IDX_872fce6c27af1f0aa04cf5b0bc"`);
|
||||
await queryRunner.query(`DROP INDEX "public"."IDX_cae25577f21f1c0c52c6d038ab"`);
|
||||
await queryRunner.query(`DROP INDEX "public"."IDX_2716e3d68b8fed7a062cb41e04"`);
|
||||
await queryRunner.query(`DROP INDEX "public"."IDX_b20ae37629c143339b0f105d3f"`);
|
||||
await queryRunner.query(`DROP TABLE "IncidentSla"`);
|
||||
await queryRunner.query(`DROP INDEX "public"."IDX_ec7114aadb854b2e6f09fa3d16"`);
|
||||
await queryRunner.query(`DROP INDEX "public"."IDX_7d2380a578cc24568b6e0e9f6a"`);
|
||||
await queryRunner.query(`DROP INDEX "public"."IDX_98e3b3d2a1e67d5d87f6254aad"`);
|
||||
await queryRunner.query(`DROP INDEX "public"."IDX_cd2943c22620ee3a9910e45663"`);
|
||||
await queryRunner.query(`DROP TABLE "IncidentSlaRule"`);
|
||||
}
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`CREATE TABLE "IncidentSlaRule" ("_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, "name" character varying(100) NOT NULL, "description" character varying(500), "order" integer NOT NULL DEFAULT '1', "isEnabled" boolean NOT NULL DEFAULT true, "responseTimeInMinutes" integer, "resolutionTimeInMinutes" integer, "atRiskThresholdInPercentage" integer NOT NULL DEFAULT '80', "internalNoteReminderIntervalInMinutes" integer, "publicNoteReminderIntervalInMinutes" integer, "internalNoteReminderTemplate" text, "publicNoteReminderTemplate" text, "incidentTitlePattern" character varying(500), "incidentDescriptionPattern" character varying(500), "createdByUserId" uuid, "deletedByUserId" uuid, CONSTRAINT "PK_7df8338a70c16abb7151cc9773a" PRIMARY KEY ("_id"))`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_cd2943c22620ee3a9910e45663" ON "IncidentSlaRule" ("projectId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_98e3b3d2a1e67d5d87f6254aad" ON "IncidentSlaRule" ("name") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_7d2380a578cc24568b6e0e9f6a" ON "IncidentSlaRule" ("order") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_ec7114aadb854b2e6f09fa3d16" ON "IncidentSlaRule" ("isEnabled") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE TABLE "IncidentSla" ("_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, "incidentId" uuid NOT NULL, "incidentSlaRuleId" uuid NOT NULL, "responseDeadline" TIMESTAMP WITH TIME ZONE, "resolutionDeadline" TIMESTAMP WITH TIME ZONE, "status" character varying NOT NULL DEFAULT 'On Track', "respondedAt" TIMESTAMP WITH TIME ZONE, "resolvedAt" TIMESTAMP WITH TIME ZONE, "lastInternalNoteReminderSentAt" TIMESTAMP WITH TIME ZONE, "lastPublicNoteReminderSentAt" TIMESTAMP WITH TIME ZONE, "breachNotificationSentAt" TIMESTAMP WITH TIME ZONE, "slaStartedAt" TIMESTAMP WITH TIME ZONE NOT NULL, "createdByUserId" uuid, "deletedByUserId" uuid, CONSTRAINT "PK_1e0e4d23867592377d865cd7fb6" PRIMARY KEY ("_id"))`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_b20ae37629c143339b0f105d3f" ON "IncidentSla" ("projectId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_2716e3d68b8fed7a062cb41e04" ON "IncidentSla" ("incidentId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_cae25577f21f1c0c52c6d038ab" ON "IncidentSla" ("incidentSlaRuleId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_872fce6c27af1f0aa04cf5b0bc" ON "IncidentSla" ("status") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_1e9dfd0511bc457251e0d27992" ON "IncidentSla" ("slaStartedAt") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE TABLE "IncidentSlaRuleMonitor" ("incidentSlaRuleId" uuid NOT NULL, "monitorId" uuid NOT NULL, CONSTRAINT "PK_5ca43621c3484d364bba1db0fdb" PRIMARY KEY ("incidentSlaRuleId", "monitorId"))`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_330c3f5655149584f1918bf125" ON "IncidentSlaRuleMonitor" ("incidentSlaRuleId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_3deaa8530c9d6065da31f65116" ON "IncidentSlaRuleMonitor" ("monitorId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE TABLE "IncidentSlaRuleIncidentSeverity" ("incidentSlaRuleId" uuid NOT NULL, "incidentSeverityId" uuid NOT NULL, CONSTRAINT "PK_2a68293adc48c01c8ef849ffefd" PRIMARY KEY ("incidentSlaRuleId", "incidentSeverityId"))`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_9d7443c084cbde74e8ab77d6df" ON "IncidentSlaRuleIncidentSeverity" ("incidentSlaRuleId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_1dbba01db81040f8139bf5c4aa" ON "IncidentSlaRuleIncidentSeverity" ("incidentSeverityId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE TABLE "IncidentSlaRuleIncidentLabel" ("incidentSlaRuleId" uuid NOT NULL, "labelId" uuid NOT NULL, CONSTRAINT "PK_c3a28da9a45df8251bb25d5e8d6" PRIMARY KEY ("incidentSlaRuleId", "labelId"))`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_a63cac299eedb0d44c1e937fc2" ON "IncidentSlaRuleIncidentLabel" ("incidentSlaRuleId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_df0e2d83d9dcbc528b830645de" ON "IncidentSlaRuleIncidentLabel" ("labelId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE TABLE "IncidentSlaRuleMonitorLabel" ("incidentSlaRuleId" uuid NOT NULL, "labelId" uuid NOT NULL, CONSTRAINT "PK_e20fa59ad1d35c2f3a9c45f0832" PRIMARY KEY ("incidentSlaRuleId", "labelId"))`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_c94cf6138ec340ae7c1976dbea" ON "IncidentSlaRuleMonitorLabel" ("incidentSlaRuleId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_93e6f28f50bf56aadcc907f440" ON "IncidentSlaRuleMonitorLabel" ("labelId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type":"Recurring","value":{"intervalType":"Day","intervalCount":{"_type":"PositiveNumber","value":1}}}'`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type":"RestrictionTimes","value":{"restictionType":"None","dayRestrictionTimes":null,"weeklyRestrictionTimes":[]}}'`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentSlaRule" ADD CONSTRAINT "FK_cd2943c22620ee3a9910e456637" FOREIGN KEY ("projectId") REFERENCES "Project"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentSlaRule" ADD CONSTRAINT "FK_26e788cca21b14940116395350f" FOREIGN KEY ("createdByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentSlaRule" ADD CONSTRAINT "FK_eb48fce1657c9a1e9245611857f" FOREIGN KEY ("deletedByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentSla" ADD CONSTRAINT "FK_b20ae37629c143339b0f105d3f8" FOREIGN KEY ("projectId") REFERENCES "Project"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentSla" ADD CONSTRAINT "FK_2716e3d68b8fed7a062cb41e04f" FOREIGN KEY ("incidentId") REFERENCES "Incident"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentSla" ADD CONSTRAINT "FK_cae25577f21f1c0c52c6d038ab4" FOREIGN KEY ("incidentSlaRuleId") REFERENCES "IncidentSlaRule"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentSla" ADD CONSTRAINT "FK_9771f22534ed092c59f55198c5a" FOREIGN KEY ("createdByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentSla" ADD CONSTRAINT "FK_c1cadef60fde93931b5131fbbba" FOREIGN KEY ("deletedByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentSlaRuleMonitor" ADD CONSTRAINT "FK_330c3f5655149584f1918bf1258" FOREIGN KEY ("incidentSlaRuleId") REFERENCES "IncidentSlaRule"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentSlaRuleMonitor" ADD CONSTRAINT "FK_3deaa8530c9d6065da31f65116c" FOREIGN KEY ("monitorId") REFERENCES "Monitor"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentSlaRuleIncidentSeverity" ADD CONSTRAINT "FK_9d7443c084cbde74e8ab77d6dfc" FOREIGN KEY ("incidentSlaRuleId") REFERENCES "IncidentSlaRule"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentSlaRuleIncidentSeverity" ADD CONSTRAINT "FK_1dbba01db81040f8139bf5c4aae" FOREIGN KEY ("incidentSeverityId") REFERENCES "IncidentSeverity"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentSlaRuleIncidentLabel" ADD CONSTRAINT "FK_a63cac299eedb0d44c1e937fc24" FOREIGN KEY ("incidentSlaRuleId") REFERENCES "IncidentSlaRule"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentSlaRuleIncidentLabel" ADD CONSTRAINT "FK_df0e2d83d9dcbc528b830645ded" FOREIGN KEY ("labelId") REFERENCES "Label"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentSlaRuleMonitorLabel" ADD CONSTRAINT "FK_c94cf6138ec340ae7c1976dbea2" FOREIGN KEY ("incidentSlaRuleId") REFERENCES "IncidentSlaRule"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentSlaRuleMonitorLabel" ADD CONSTRAINT "FK_93e6f28f50bf56aadcc907f4403" FOREIGN KEY ("labelId") REFERENCES "Label"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentSlaRuleMonitorLabel" DROP CONSTRAINT "FK_93e6f28f50bf56aadcc907f4403"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentSlaRuleMonitorLabel" DROP CONSTRAINT "FK_c94cf6138ec340ae7c1976dbea2"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentSlaRuleIncidentLabel" DROP CONSTRAINT "FK_df0e2d83d9dcbc528b830645ded"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentSlaRuleIncidentLabel" DROP CONSTRAINT "FK_a63cac299eedb0d44c1e937fc24"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentSlaRuleIncidentSeverity" DROP CONSTRAINT "FK_1dbba01db81040f8139bf5c4aae"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentSlaRuleIncidentSeverity" DROP CONSTRAINT "FK_9d7443c084cbde74e8ab77d6dfc"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentSlaRuleMonitor" DROP CONSTRAINT "FK_3deaa8530c9d6065da31f65116c"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentSlaRuleMonitor" DROP CONSTRAINT "FK_330c3f5655149584f1918bf1258"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentSla" DROP CONSTRAINT "FK_c1cadef60fde93931b5131fbbba"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentSla" DROP CONSTRAINT "FK_9771f22534ed092c59f55198c5a"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentSla" DROP CONSTRAINT "FK_cae25577f21f1c0c52c6d038ab4"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentSla" DROP CONSTRAINT "FK_2716e3d68b8fed7a062cb41e04f"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentSla" DROP CONSTRAINT "FK_b20ae37629c143339b0f105d3f8"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentSlaRule" DROP CONSTRAINT "FK_eb48fce1657c9a1e9245611857f"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentSlaRule" DROP CONSTRAINT "FK_26e788cca21b14940116395350f"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentSlaRule" DROP CONSTRAINT "FK_cd2943c22620ee3a9910e456637"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type": "RestrictionTimes", "value": {"restictionType": "None", "dayRestrictionTimes": null, "weeklyRestrictionTimes": []}}'`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type": "Recurring", "value": {"intervalType": "Day", "intervalCount": {"_type": "PositiveNumber", "value": 1}}}'`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_93e6f28f50bf56aadcc907f440"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_c94cf6138ec340ae7c1976dbea"`,
|
||||
);
|
||||
await queryRunner.query(`DROP TABLE "IncidentSlaRuleMonitorLabel"`);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_df0e2d83d9dcbc528b830645de"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_a63cac299eedb0d44c1e937fc2"`,
|
||||
);
|
||||
await queryRunner.query(`DROP TABLE "IncidentSlaRuleIncidentLabel"`);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_1dbba01db81040f8139bf5c4aa"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_9d7443c084cbde74e8ab77d6df"`,
|
||||
);
|
||||
await queryRunner.query(`DROP TABLE "IncidentSlaRuleIncidentSeverity"`);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_3deaa8530c9d6065da31f65116"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_330c3f5655149584f1918bf125"`,
|
||||
);
|
||||
await queryRunner.query(`DROP TABLE "IncidentSlaRuleMonitor"`);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_1e9dfd0511bc457251e0d27992"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_872fce6c27af1f0aa04cf5b0bc"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_cae25577f21f1c0c52c6d038ab"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_2716e3d68b8fed7a062cb41e04"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_b20ae37629c143339b0f105d3f"`,
|
||||
);
|
||||
await queryRunner.query(`DROP TABLE "IncidentSla"`);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_ec7114aadb854b2e6f09fa3d16"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_7d2380a578cc24568b6e0e9f6a"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_98e3b3d2a1e67d5d87f6254aad"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_cd2943c22620ee3a9910e45663"`,
|
||||
);
|
||||
await queryRunner.query(`DROP TABLE "IncidentSlaRule"`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -497,5 +497,5 @@ export default [
|
||||
MigrationName1769723982900,
|
||||
MigrationName1769772215532,
|
||||
MigrationName1769774527481,
|
||||
MigrationName1769780297584
|
||||
MigrationName1769780297584,
|
||||
];
|
||||
|
||||
@@ -855,8 +855,13 @@ export class Service extends DatabaseService<Model> {
|
||||
.then(async () => {
|
||||
// Create SLA record for incident if a matching rule exists
|
||||
try {
|
||||
if (createdItem.projectId && createdItem.id && createdItem.declaredAt) {
|
||||
const IncidentSlaService = (await import("./IncidentSlaService")).default;
|
||||
if (
|
||||
createdItem.projectId &&
|
||||
createdItem.id &&
|
||||
createdItem.declaredAt
|
||||
) {
|
||||
const IncidentSlaService: typeof import("./IncidentSlaService").default =
|
||||
(await import("./IncidentSlaService")).default;
|
||||
await IncidentSlaService.createSlaForIncident({
|
||||
incidentId: createdItem.id,
|
||||
projectId: createdItem.projectId,
|
||||
@@ -1532,7 +1537,8 @@ ${incidentSeverity.name}
|
||||
|
||||
// Recalculate SLA deadlines when severity changes
|
||||
try {
|
||||
const IncidentSlaService = (await import("./IncidentSlaService")).default;
|
||||
const IncidentSlaService: typeof import("./IncidentSlaService").default =
|
||||
(await import("./IncidentSlaService")).default;
|
||||
await IncidentSlaService.recalculateDeadlines({
|
||||
incidentId: incidentId,
|
||||
});
|
||||
|
||||
@@ -65,7 +65,9 @@ export class Service extends DatabaseService<Model> {
|
||||
let incident: Incident | null = data.incident || null;
|
||||
|
||||
if (!incident) {
|
||||
const IncidentService = (await import("./IncidentService")).default;
|
||||
const IncidentService: typeof import("./IncidentService").default = (
|
||||
await import("./IncidentService")
|
||||
).default;
|
||||
|
||||
incident = await IncidentService.findOneById({
|
||||
id: data.incidentId,
|
||||
@@ -138,9 +140,7 @@ export class Service extends DatabaseService<Model> {
|
||||
});
|
||||
|
||||
if (rules.length === 0) {
|
||||
logger.debug(
|
||||
`No enabled SLA rules found for project ${data.projectId}`,
|
||||
);
|
||||
logger.debug(`No enabled SLA rules found for project ${data.projectId}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -156,9 +156,7 @@ export class Service extends DatabaseService<Model> {
|
||||
}
|
||||
}
|
||||
|
||||
logger.debug(
|
||||
`Incident ${data.incidentId} did not match any SLA rules`,
|
||||
);
|
||||
logger.debug(`Incident ${data.incidentId} did not match any SLA rules`);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -177,11 +175,9 @@ export class Service extends DatabaseService<Model> {
|
||||
return false;
|
||||
}
|
||||
|
||||
const ruleMonitorIds: Array<string> = rule.monitors.map(
|
||||
(m: Monitor) => {
|
||||
return m.id?.toString() || "";
|
||||
},
|
||||
);
|
||||
const ruleMonitorIds: Array<string> = rule.monitors.map((m: Monitor) => {
|
||||
return m.id?.toString() || "";
|
||||
});
|
||||
|
||||
const incidentMonitorIds: Array<string> = incident.monitors.map(
|
||||
(m: Monitor) => {
|
||||
@@ -238,11 +234,9 @@ export class Service extends DatabaseService<Model> {
|
||||
},
|
||||
);
|
||||
|
||||
const hasMatchingLabel: boolean = ruleLabelIds.some(
|
||||
(labelId: string) => {
|
||||
return incidentLabelIds.includes(labelId);
|
||||
},
|
||||
);
|
||||
const hasMatchingLabel: boolean = ruleLabelIds.some((labelId: string) => {
|
||||
return incidentLabelIds.includes(labelId);
|
||||
});
|
||||
|
||||
if (!hasMatchingLabel) {
|
||||
return false;
|
||||
|
||||
@@ -104,7 +104,9 @@ export class Service extends DatabaseService<Model> {
|
||||
|
||||
return createdSla;
|
||||
} catch (error) {
|
||||
logger.error(`Error creating SLA record for incident ${data.incidentId}: ${error}`);
|
||||
logger.error(
|
||||
`Error creating SLA record for incident ${data.incidentId}: ${error}`,
|
||||
);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -150,9 +152,7 @@ export class Service extends DatabaseService<Model> {
|
||||
},
|
||||
});
|
||||
|
||||
logger.info(
|
||||
`Marked SLA ${sla.id} as responded at ${data.respondedAt}`,
|
||||
);
|
||||
logger.info(`Marked SLA ${sla.id} as responded at ${data.respondedAt}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -238,12 +238,12 @@ export class Service extends DatabaseService<Model> {
|
||||
public async recalculateDeadlines(data: {
|
||||
incidentId: ObjectID;
|
||||
}): Promise<void> {
|
||||
logger.debug(
|
||||
`Recalculating deadlines for incident ${data.incidentId}`,
|
||||
);
|
||||
logger.debug(`Recalculating deadlines for incident ${data.incidentId}`);
|
||||
|
||||
// Get the incident to find the new severity and project
|
||||
const IncidentService = (await import("./IncidentService")).default;
|
||||
const IncidentService: typeof import("./IncidentService").default = (
|
||||
await import("./IncidentService")
|
||||
).default;
|
||||
|
||||
const incident: Incident | null = await IncidentService.findOneById({
|
||||
id: data.incidentId,
|
||||
@@ -355,10 +355,12 @@ export class Service extends DatabaseService<Model> {
|
||||
public async getIncidentsNeedingInternalNoteReminder(): Promise<
|
||||
Array<Model>
|
||||
> {
|
||||
// Find SLAs where:
|
||||
// - Not resolved
|
||||
// - Has internal note reminder interval configured
|
||||
// - Last reminder was sent more than interval ago OR never sent
|
||||
/*
|
||||
* Find SLAs where:
|
||||
* - Not resolved
|
||||
* - Has internal note reminder interval configured
|
||||
* - Last reminder was sent more than interval ago OR never sent
|
||||
*/
|
||||
const now: Date = OneUptimeDate.getCurrentDate();
|
||||
|
||||
const slaRecords: Array<Model> = await this.findBy({
|
||||
@@ -405,10 +407,11 @@ export class Service extends DatabaseService<Model> {
|
||||
return timeSinceStart >= interval;
|
||||
}
|
||||
|
||||
const timeSinceLastReminder: number = OneUptimeDate.getDifferenceInMinutes(
|
||||
now,
|
||||
sla.lastInternalNoteReminderSentAt,
|
||||
);
|
||||
const timeSinceLastReminder: number =
|
||||
OneUptimeDate.getDifferenceInMinutes(
|
||||
now,
|
||||
sla.lastInternalNoteReminderSentAt,
|
||||
);
|
||||
|
||||
return timeSinceLastReminder >= interval;
|
||||
});
|
||||
@@ -464,10 +467,11 @@ export class Service extends DatabaseService<Model> {
|
||||
return timeSinceStart >= interval;
|
||||
}
|
||||
|
||||
const timeSinceLastReminder: number = OneUptimeDate.getDifferenceInMinutes(
|
||||
now,
|
||||
sla.lastPublicNoteReminderSentAt,
|
||||
);
|
||||
const timeSinceLastReminder: number =
|
||||
OneUptimeDate.getDifferenceInMinutes(
|
||||
now,
|
||||
sla.lastPublicNoteReminderSentAt,
|
||||
);
|
||||
|
||||
return timeSinceLastReminder >= interval;
|
||||
});
|
||||
|
||||
@@ -697,12 +697,15 @@ ${createdItem.rootCause}`,
|
||||
previousStateWasResolved: boolean;
|
||||
}): Promise<void> {
|
||||
try {
|
||||
const IncidentSlaService = (await import("./IncidentSlaService")).default;
|
||||
const IncidentSlaService: typeof import("./IncidentSlaService").default =
|
||||
(await import("./IncidentSlaService")).default;
|
||||
|
||||
// Check if incident is being reopened (previous state was resolved, current state is not resolved)
|
||||
if (data.previousStateWasResolved && !data.isResolvedState) {
|
||||
// Incident is being reopened - create a new SLA record
|
||||
const IncidentService = (await import("./IncidentService")).default;
|
||||
const IncidentService: typeof import("./IncidentService").default = (
|
||||
await import("./IncidentService")
|
||||
).default;
|
||||
|
||||
const incident: Incident | null = await IncidentService.findOneById({
|
||||
id: data.incidentId,
|
||||
|
||||
@@ -70,10 +70,7 @@ const IconPicker: FunctionComponent<ComponentProps> = (
|
||||
className="flex items-center justify-center h-5 w-5 cursor-pointer"
|
||||
>
|
||||
{selectedIcon ? (
|
||||
<Icon
|
||||
icon={selectedIcon}
|
||||
className="h-5 w-5 text-gray-600"
|
||||
/>
|
||||
<Icon icon={selectedIcon} className="h-5 w-5 text-gray-600" />
|
||||
) : (
|
||||
<div className="h-5 w-5 border border-dashed border-gray-300 rounded"></div>
|
||||
)}
|
||||
@@ -150,10 +147,7 @@ const IconPicker: FunctionComponent<ComponentProps> = (
|
||||
}`}
|
||||
title={icon}
|
||||
>
|
||||
<Icon
|
||||
icon={icon}
|
||||
className="h-5 w-5 text-gray-600"
|
||||
/>
|
||||
<Icon icon={icon} className="h-5 w-5 text-gray-600" />
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
|
||||
@@ -49,7 +49,10 @@ const NotificationBellDropdown: (props: ComponentProps) => ReactElement = (
|
||||
)}
|
||||
|
||||
{errorItems.length > 0 && (
|
||||
<NotificationBellSection title="Critical" alertType={HeaderAlertType.ERROR}>
|
||||
<NotificationBellSection
|
||||
title="Critical"
|
||||
alertType={HeaderAlertType.ERROR}
|
||||
>
|
||||
{errorItems.map((item: NotificationItem) => {
|
||||
return (
|
||||
<NotificationBellItem
|
||||
@@ -65,7 +68,10 @@ const NotificationBellDropdown: (props: ComponentProps) => ReactElement = (
|
||||
)}
|
||||
|
||||
{successItems.length > 0 && (
|
||||
<NotificationBellSection title="On-Call" alertType={HeaderAlertType.SUCCESS}>
|
||||
<NotificationBellSection
|
||||
title="On-Call"
|
||||
alertType={HeaderAlertType.SUCCESS}
|
||||
>
|
||||
{successItems.map((item: NotificationItem) => {
|
||||
return (
|
||||
<NotificationBellItem
|
||||
@@ -81,7 +87,10 @@ const NotificationBellDropdown: (props: ComponentProps) => ReactElement = (
|
||||
)}
|
||||
|
||||
{infoItems.length > 0 && (
|
||||
<NotificationBellSection title="Information" alertType={HeaderAlertType.INFO}>
|
||||
<NotificationBellSection
|
||||
title="Information"
|
||||
alertType={HeaderAlertType.INFO}
|
||||
>
|
||||
{infoItems.map((item: NotificationItem) => {
|
||||
return (
|
||||
<NotificationBellItem
|
||||
|
||||
@@ -45,11 +45,7 @@ const RoleLabel: FunctionComponent<ComponentProps> = (
|
||||
backgroundColor: resolvedColor.toString(),
|
||||
}}
|
||||
>
|
||||
<Icon
|
||||
icon={resolvedIcon}
|
||||
className="h-4 w-4"
|
||||
color={iconColor}
|
||||
/>
|
||||
<Icon icon={resolvedIcon} className="h-4 w-4" color={iconColor} />
|
||||
</div>
|
||||
) : (
|
||||
<div
|
||||
|
||||
@@ -71,61 +71,64 @@ const DashboardHeader: FunctionComponent<ComponentProps> = (
|
||||
const [showCurrentOnCallPolicyModal, setShowCurrentOnCallPolicyModal] =
|
||||
useState<boolean>(false);
|
||||
|
||||
const fetchIncidentsCount: PromiseVoidFunction = useCallback(async (): Promise<void> => {
|
||||
try {
|
||||
const count: number = await ModelAPI.count<Incident>({
|
||||
modelType: Incident,
|
||||
query: {
|
||||
currentIncidentState: {
|
||||
order: 1,
|
||||
const fetchIncidentsCount: PromiseVoidFunction =
|
||||
useCallback(async (): Promise<void> => {
|
||||
try {
|
||||
const count: number = await ModelAPI.count<Incident>({
|
||||
modelType: Incident,
|
||||
query: {
|
||||
currentIncidentState: {
|
||||
order: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
requestOptions: {
|
||||
isMultiTenantRequest: true,
|
||||
},
|
||||
});
|
||||
setIncidentsCount(count);
|
||||
} catch (err) {
|
||||
setIncidentsCount(0);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const fetchAlertsCount: PromiseVoidFunction = useCallback(async (): Promise<void> => {
|
||||
try {
|
||||
const count: number = await ModelAPI.count<Alert>({
|
||||
modelType: Alert,
|
||||
query: {
|
||||
currentAlertState: {
|
||||
order: 1,
|
||||
requestOptions: {
|
||||
isMultiTenantRequest: true,
|
||||
},
|
||||
},
|
||||
requestOptions: {
|
||||
isMultiTenantRequest: true,
|
||||
},
|
||||
});
|
||||
setAlertsCount(count);
|
||||
} catch (err) {
|
||||
setAlertsCount(0);
|
||||
}
|
||||
}, []);
|
||||
});
|
||||
setIncidentsCount(count);
|
||||
} catch {
|
||||
setIncidentsCount(0);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const fetchInvitationsCount: PromiseVoidFunction = useCallback(async (): Promise<void> => {
|
||||
try {
|
||||
const count: number = await ModelAPI.count<TeamMember>({
|
||||
modelType: TeamMember,
|
||||
query: {
|
||||
userId: User.getUserId(),
|
||||
hasAcceptedInvitation: false,
|
||||
},
|
||||
requestOptions: {
|
||||
isMultiTenantRequest: true,
|
||||
},
|
||||
});
|
||||
setInvitationsCount(count);
|
||||
} catch (err) {
|
||||
setInvitationsCount(0);
|
||||
}
|
||||
}, []);
|
||||
const fetchAlertsCount: PromiseVoidFunction =
|
||||
useCallback(async (): Promise<void> => {
|
||||
try {
|
||||
const count: number = await ModelAPI.count<Alert>({
|
||||
modelType: Alert,
|
||||
query: {
|
||||
currentAlertState: {
|
||||
order: 1,
|
||||
},
|
||||
},
|
||||
requestOptions: {
|
||||
isMultiTenantRequest: true,
|
||||
},
|
||||
});
|
||||
setAlertsCount(count);
|
||||
} catch {
|
||||
setAlertsCount(0);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const fetchInvitationsCount: PromiseVoidFunction =
|
||||
useCallback(async (): Promise<void> => {
|
||||
try {
|
||||
const count: number = await ModelAPI.count<TeamMember>({
|
||||
modelType: TeamMember,
|
||||
query: {
|
||||
userId: User.getUserId(),
|
||||
hasAcceptedInvitation: false,
|
||||
},
|
||||
requestOptions: {
|
||||
isMultiTenantRequest: true,
|
||||
},
|
||||
});
|
||||
setInvitationsCount(count);
|
||||
} catch {
|
||||
setInvitationsCount(0);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const refreshIncidentCount: VoidFunction = () => {
|
||||
fetchIncidentsCount().catch(() => {
|
||||
@@ -436,77 +439,81 @@ const DashboardHeader: FunctionComponent<ComponentProps> = (
|
||||
)
|
||||
: 0;
|
||||
|
||||
const buildNotificationItems: () => Array<NotificationItem> = (): Array<NotificationItem> => {
|
||||
const items: Array<NotificationItem> = [];
|
||||
const buildNotificationItems: () => Array<NotificationItem> =
|
||||
(): Array<NotificationItem> => {
|
||||
const items: Array<NotificationItem> = [];
|
||||
|
||||
// Incidents - ERROR type
|
||||
items.push({
|
||||
id: "incidents",
|
||||
icon: IconProp.Alert,
|
||||
title: `${incidentsCount} Active ${incidentsCount === 1 ? "Incident" : "Incidents"}`,
|
||||
count: incidentsCount,
|
||||
alertType: HeaderAlertType.ERROR,
|
||||
tooltip: "View all active incidents",
|
||||
});
|
||||
|
||||
// Alerts - ERROR type
|
||||
items.push({
|
||||
id: "alerts",
|
||||
icon: IconProp.ExclaimationCircle,
|
||||
title: `${alertsCount} Active ${alertsCount === 1 ? "Alert" : "Alerts"}`,
|
||||
count: alertsCount,
|
||||
alertType: HeaderAlertType.ERROR,
|
||||
tooltip: "View all active alerts",
|
||||
});
|
||||
|
||||
// On-Call Policies - SUCCESS type
|
||||
if (props.selectedProject && currentOnCallPolicies.length > 0) {
|
||||
// Incidents - ERROR type
|
||||
items.push({
|
||||
id: "oncall",
|
||||
icon: IconProp.Call,
|
||||
title: `On duty for ${currentOnCallPolicies.length} ${currentOnCallPolicies.length === 1 ? "policy" : "policies"}`,
|
||||
count: currentOnCallPolicies.length,
|
||||
alertType: HeaderAlertType.SUCCESS,
|
||||
tooltip: "On-call policies you are currently on duty for",
|
||||
id: "incidents",
|
||||
icon: IconProp.Alert,
|
||||
title: `${incidentsCount} Active ${incidentsCount === 1 ? "Incident" : "Incidents"}`,
|
||||
count: incidentsCount,
|
||||
alertType: HeaderAlertType.ERROR,
|
||||
tooltip: "View all active incidents",
|
||||
});
|
||||
}
|
||||
|
||||
// Invitations - INFO type
|
||||
items.push({
|
||||
id: "invitations",
|
||||
icon: IconProp.Folder,
|
||||
title: `${invitationsCount} Pending ${invitationsCount === 1 ? "Invitation" : "Invitations"}`,
|
||||
count: invitationsCount,
|
||||
alertType: HeaderAlertType.INFO,
|
||||
tooltip: "Looks like you have pending project invitations. Please click here to review and accept them.",
|
||||
});
|
||||
|
||||
// Trial Days - INFO type (only if showTrialButton is true)
|
||||
if (showTrialButton && trialDaysRemaining > 0) {
|
||||
// Alerts - ERROR type
|
||||
items.push({
|
||||
id: "trial",
|
||||
icon: IconProp.Clock,
|
||||
title: `Trial ends in ${trialDaysRemaining} ${trialDaysRemaining === 1 ? "day" : "days"}`,
|
||||
count: trialDaysRemaining,
|
||||
id: "alerts",
|
||||
icon: IconProp.ExclaimationCircle,
|
||||
title: `${alertsCount} Active ${alertsCount === 1 ? "Alert" : "Alerts"}`,
|
||||
count: alertsCount,
|
||||
alertType: HeaderAlertType.ERROR,
|
||||
tooltip: "View all active alerts",
|
||||
});
|
||||
|
||||
// On-Call Policies - SUCCESS type
|
||||
if (props.selectedProject && currentOnCallPolicies.length > 0) {
|
||||
items.push({
|
||||
id: "oncall",
|
||||
icon: IconProp.Call,
|
||||
title: `On duty for ${currentOnCallPolicies.length} ${currentOnCallPolicies.length === 1 ? "policy" : "policies"}`,
|
||||
count: currentOnCallPolicies.length,
|
||||
alertType: HeaderAlertType.SUCCESS,
|
||||
tooltip: "On-call policies you are currently on duty for",
|
||||
});
|
||||
}
|
||||
|
||||
// Invitations - INFO type
|
||||
items.push({
|
||||
id: "invitations",
|
||||
icon: IconProp.Folder,
|
||||
title: `${invitationsCount} Pending ${invitationsCount === 1 ? "Invitation" : "Invitations"}`,
|
||||
count: invitationsCount,
|
||||
alertType: HeaderAlertType.INFO,
|
||||
tooltip: "Your trial ends soon. Add card details to continue using the service.",
|
||||
tooltip:
|
||||
"Looks like you have pending project invitations. Please click here to review and accept them.",
|
||||
});
|
||||
}
|
||||
|
||||
// Add Card Details - INFO type (only if showAddCardButton is true)
|
||||
if (showAddCardButton) {
|
||||
items.push({
|
||||
id: "addcard",
|
||||
icon: IconProp.Billing,
|
||||
title: "Add Card Details",
|
||||
count: 1,
|
||||
alertType: HeaderAlertType.INFO,
|
||||
tooltip: "Add your payment card details to continue using the service.",
|
||||
});
|
||||
}
|
||||
// Trial Days - INFO type (only if showTrialButton is true)
|
||||
if (showTrialButton && trialDaysRemaining > 0) {
|
||||
items.push({
|
||||
id: "trial",
|
||||
icon: IconProp.Clock,
|
||||
title: `Trial ends in ${trialDaysRemaining} ${trialDaysRemaining === 1 ? "day" : "days"}`,
|
||||
count: trialDaysRemaining,
|
||||
alertType: HeaderAlertType.INFO,
|
||||
tooltip:
|
||||
"Your trial ends soon. Add card details to continue using the service.",
|
||||
});
|
||||
}
|
||||
|
||||
return items;
|
||||
};
|
||||
// Add Card Details - INFO type (only if showAddCardButton is true)
|
||||
if (showAddCardButton) {
|
||||
items.push({
|
||||
id: "addcard",
|
||||
icon: IconProp.Billing,
|
||||
title: "Add Card Details",
|
||||
count: 1,
|
||||
alertType: HeaderAlertType.INFO,
|
||||
tooltip:
|
||||
"Add your payment card details to continue using the service.",
|
||||
});
|
||||
}
|
||||
|
||||
return items;
|
||||
};
|
||||
|
||||
const handleNotificationItemClick: (item: NotificationItem) => void = (
|
||||
item: NotificationItem,
|
||||
|
||||
@@ -13,10 +13,14 @@ import SortOrder from "Common/Types/BaseDatabase/SortOrder";
|
||||
import ProjectUtil from "Common/UI/Utils/Project";
|
||||
import OneUptimeDate from "Common/Types/Date";
|
||||
|
||||
const IncidentViewSla: FunctionComponent<PageComponentProps> = (): ReactElement => {
|
||||
const IncidentViewSla: FunctionComponent<
|
||||
PageComponentProps
|
||||
> = (): ReactElement => {
|
||||
const modelId: ObjectID = Navigation.getLastParamAsObjectID(1);
|
||||
|
||||
const getStatusColor = (status: IncidentSlaStatus | undefined): Color => {
|
||||
const getStatusColor: (status: IncidentSlaStatus | undefined) => Color = (
|
||||
status: IncidentSlaStatus | undefined,
|
||||
): Color => {
|
||||
switch (status) {
|
||||
case IncidentSlaStatus.OnTrack:
|
||||
return Green;
|
||||
@@ -32,7 +36,9 @@ const IncidentViewSla: FunctionComponent<PageComponentProps> = (): ReactElement
|
||||
}
|
||||
};
|
||||
|
||||
const formatTimeRemaining = (deadline: Date | undefined): string => {
|
||||
const formatTimeRemaining: (deadline: Date | undefined) => string = (
|
||||
deadline: Date | undefined,
|
||||
): string => {
|
||||
if (!deadline) {
|
||||
return "N/A";
|
||||
}
|
||||
@@ -107,7 +113,8 @@ const IncidentViewSla: FunctionComponent<PageComponentProps> = (): ReactElement
|
||||
type: FieldType.Text,
|
||||
getElement: (item: IncidentSla): ReactElement => {
|
||||
const ruleName: string =
|
||||
(item.incidentSlaRule as { name?: string })?.name || "Unknown Rule";
|
||||
(item.incidentSlaRule as { name?: string })?.name ||
|
||||
"Unknown Rule";
|
||||
return <span>{ruleName}</span>;
|
||||
},
|
||||
},
|
||||
@@ -138,7 +145,7 @@ const IncidentViewSla: FunctionComponent<PageComponentProps> = (): ReactElement
|
||||
return <span className="text-gray-400">Not configured</span>;
|
||||
}
|
||||
|
||||
const isResponded: boolean = !!item.respondedAt;
|
||||
const isResponded: boolean = Boolean(item.respondedAt);
|
||||
const deadline: Date = item.responseDeadline;
|
||||
const formattedDeadline: string =
|
||||
OneUptimeDate.getDateAsLocalFormattedString(deadline);
|
||||
@@ -152,9 +159,7 @@ const IncidentViewSla: FunctionComponent<PageComponentProps> = (): ReactElement
|
||||
return (
|
||||
<div>
|
||||
<span
|
||||
className={
|
||||
wasOnTime ? "text-green-600" : "text-red-600"
|
||||
}
|
||||
className={wasOnTime ? "text-green-600" : "text-red-600"}
|
||||
>
|
||||
{wasOnTime ? "Met" : "Missed"}
|
||||
</span>
|
||||
@@ -190,7 +195,7 @@ const IncidentViewSla: FunctionComponent<PageComponentProps> = (): ReactElement
|
||||
return <span className="text-gray-400">Not configured</span>;
|
||||
}
|
||||
|
||||
const isResolved: boolean = !!item.resolvedAt;
|
||||
const isResolved: boolean = Boolean(item.resolvedAt);
|
||||
const deadline: Date = item.resolutionDeadline;
|
||||
const formattedDeadline: string =
|
||||
OneUptimeDate.getDateAsLocalFormattedString(deadline);
|
||||
@@ -204,9 +209,7 @@ const IncidentViewSla: FunctionComponent<PageComponentProps> = (): ReactElement
|
||||
return (
|
||||
<div>
|
||||
<span
|
||||
className={
|
||||
wasOnTime ? "text-green-600" : "text-red-600"
|
||||
}
|
||||
className={wasOnTime ? "text-green-600" : "text-red-600"}
|
||||
>
|
||||
{wasOnTime ? "Met" : "Missed"}
|
||||
</span>
|
||||
|
||||
@@ -74,142 +74,146 @@ const Teams: FunctionComponent<PageComponentProps> = (
|
||||
)}
|
||||
|
||||
<ModelTable<TeamMember>
|
||||
modelType={TeamMember}
|
||||
id="teams-table"
|
||||
name="Settings > Users"
|
||||
userPreferencesKey="users-table"
|
||||
isDeleteable={!isPushGroupsManaged}
|
||||
bulkActions={
|
||||
!isPushGroupsManaged
|
||||
? {
|
||||
buttons: [ModalTableBulkDefaultActions.Delete],
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
isEditable={false}
|
||||
isCreateable={false}
|
||||
onFilterApplied={(isApplied: boolean) => {
|
||||
setIsFilterApplied(isApplied);
|
||||
}}
|
||||
isViewable={true}
|
||||
onBeforeDelete={async (item: TeamMember): Promise<TeamMember> => {
|
||||
if (isPushGroupsManaged) {
|
||||
throw new BadDataException(
|
||||
"Cannot remove team members while SCIM Push Groups is enabled for this project. Disable Push Groups to manage members from OneUptime.",
|
||||
);
|
||||
}
|
||||
return item;
|
||||
}}
|
||||
cardProps={{
|
||||
title: "Users",
|
||||
description:
|
||||
"Here is a list of all the team members in this project.",
|
||||
buttons: [
|
||||
{
|
||||
title: "Invite User",
|
||||
buttonStyle: ButtonStyleType.NORMAL,
|
||||
icon: IconProp.Add,
|
||||
onClick: () => {
|
||||
if (isPushGroupsManaged) {
|
||||
setShowScimErrorModal(true);
|
||||
} else {
|
||||
setShowInviteUserModal(true);
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
}}
|
||||
noItemsMessage={
|
||||
isFilterApplied
|
||||
? "No users found"
|
||||
: "Please wait, we are refreshing the list of users for this project. Please try again in sometime."
|
||||
}
|
||||
query={{
|
||||
projectId: ProjectUtil.getCurrentProjectId()!,
|
||||
}}
|
||||
showRefreshButton={true}
|
||||
onViewPage={(item: TeamMember) => {
|
||||
const viewPageRoute: string =
|
||||
RouteUtil.populateRouteParams(props.pageRoute).toString() +
|
||||
"/" +
|
||||
item.user?.id?.toString();
|
||||
// add user id to the route
|
||||
return Promise.resolve(new Route(viewPageRoute));
|
||||
}}
|
||||
filters={[
|
||||
{
|
||||
field: {
|
||||
team: {
|
||||
name: true,
|
||||
},
|
||||
},
|
||||
title: "Team",
|
||||
type: FieldType.Entity,
|
||||
filterEntityType: Team,
|
||||
filterQuery: {
|
||||
projectId: ProjectUtil.getCurrentProjectId()!,
|
||||
},
|
||||
filterDropdownField: {
|
||||
label: "name",
|
||||
value: "_id",
|
||||
},
|
||||
},
|
||||
{
|
||||
field: {
|
||||
hasAcceptedInvitation: true,
|
||||
},
|
||||
title: "Status",
|
||||
type: FieldType.Boolean,
|
||||
},
|
||||
]}
|
||||
columns={[
|
||||
{
|
||||
field: {
|
||||
user: {
|
||||
name: true,
|
||||
email: true,
|
||||
profilePictureId: true,
|
||||
},
|
||||
},
|
||||
title: "User",
|
||||
type: FieldType.Element,
|
||||
getElement: (item: TeamMember) => {
|
||||
if (!item.user) {
|
||||
return <p>User not found</p>;
|
||||
}
|
||||
return <UserElement user={item.user!} />;
|
||||
},
|
||||
},
|
||||
{
|
||||
field: {
|
||||
team: {
|
||||
name: true,
|
||||
_id: true,
|
||||
},
|
||||
},
|
||||
title: "Team",
|
||||
type: FieldType.Element,
|
||||
getElement: (item: TeamMember) => {
|
||||
if (!item.team) {
|
||||
return <p>No team assigned</p>;
|
||||
}
|
||||
return <TeamElement team={item.team!} />;
|
||||
},
|
||||
},
|
||||
{
|
||||
field: {
|
||||
hasAcceptedInvitation: true,
|
||||
},
|
||||
title: "Status",
|
||||
type: FieldType.Element,
|
||||
getElement: (item: TeamMember) => {
|
||||
if (item.hasAcceptedInvitation) {
|
||||
return <Pill text="Member" color={Green} />;
|
||||
}
|
||||
return <Pill text="Invitation Sent" color={Yellow} />;
|
||||
},
|
||||
},
|
||||
]}
|
||||
modelType={TeamMember}
|
||||
id="teams-table"
|
||||
name="Settings > Users"
|
||||
userPreferencesKey="users-table"
|
||||
isDeleteable={!isPushGroupsManaged}
|
||||
bulkActions={
|
||||
!isPushGroupsManaged
|
||||
? {
|
||||
buttons: [ModalTableBulkDefaultActions.Delete],
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
isEditable={false}
|
||||
isCreateable={false}
|
||||
onFilterApplied={(isApplied: boolean) => {
|
||||
setIsFilterApplied(isApplied);
|
||||
}}
|
||||
isViewable={true}
|
||||
onBeforeDelete={async (
|
||||
item: TeamMember,
|
||||
): Promise<TeamMember> => {
|
||||
if (isPushGroupsManaged) {
|
||||
throw new BadDataException(
|
||||
"Cannot remove team members while SCIM Push Groups is enabled for this project. Disable Push Groups to manage members from OneUptime.",
|
||||
);
|
||||
}
|
||||
return item;
|
||||
}}
|
||||
cardProps={{
|
||||
title: "Users",
|
||||
description:
|
||||
"Here is a list of all the team members in this project.",
|
||||
buttons: [
|
||||
{
|
||||
title: "Invite User",
|
||||
buttonStyle: ButtonStyleType.NORMAL,
|
||||
icon: IconProp.Add,
|
||||
onClick: () => {
|
||||
if (isPushGroupsManaged) {
|
||||
setShowScimErrorModal(true);
|
||||
} else {
|
||||
setShowInviteUserModal(true);
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
}}
|
||||
noItemsMessage={
|
||||
isFilterApplied
|
||||
? "No users found"
|
||||
: "Please wait, we are refreshing the list of users for this project. Please try again in sometime."
|
||||
}
|
||||
query={{
|
||||
projectId: ProjectUtil.getCurrentProjectId()!,
|
||||
}}
|
||||
showRefreshButton={true}
|
||||
onViewPage={(item: TeamMember) => {
|
||||
const viewPageRoute: string =
|
||||
RouteUtil.populateRouteParams(
|
||||
props.pageRoute,
|
||||
).toString() +
|
||||
"/" +
|
||||
item.user?.id?.toString();
|
||||
// add user id to the route
|
||||
return Promise.resolve(new Route(viewPageRoute));
|
||||
}}
|
||||
filters={[
|
||||
{
|
||||
field: {
|
||||
team: {
|
||||
name: true,
|
||||
},
|
||||
},
|
||||
title: "Team",
|
||||
type: FieldType.Entity,
|
||||
filterEntityType: Team,
|
||||
filterQuery: {
|
||||
projectId: ProjectUtil.getCurrentProjectId()!,
|
||||
},
|
||||
filterDropdownField: {
|
||||
label: "name",
|
||||
value: "_id",
|
||||
},
|
||||
},
|
||||
{
|
||||
field: {
|
||||
hasAcceptedInvitation: true,
|
||||
},
|
||||
title: "Status",
|
||||
type: FieldType.Boolean,
|
||||
},
|
||||
]}
|
||||
columns={[
|
||||
{
|
||||
field: {
|
||||
user: {
|
||||
name: true,
|
||||
email: true,
|
||||
profilePictureId: true,
|
||||
},
|
||||
},
|
||||
title: "User",
|
||||
type: FieldType.Element,
|
||||
getElement: (item: TeamMember) => {
|
||||
if (!item.user) {
|
||||
return <p>User not found</p>;
|
||||
}
|
||||
return <UserElement user={item.user!} />;
|
||||
},
|
||||
},
|
||||
{
|
||||
field: {
|
||||
team: {
|
||||
name: true,
|
||||
_id: true,
|
||||
},
|
||||
},
|
||||
title: "Team",
|
||||
type: FieldType.Element,
|
||||
getElement: (item: TeamMember) => {
|
||||
if (!item.team) {
|
||||
return <p>No team assigned</p>;
|
||||
}
|
||||
return <TeamElement team={item.team!} />;
|
||||
},
|
||||
},
|
||||
{
|
||||
field: {
|
||||
hasAcceptedInvitation: true,
|
||||
},
|
||||
title: "Status",
|
||||
type: FieldType.Element,
|
||||
getElement: (item: TeamMember) => {
|
||||
if (item.hasAcceptedInvitation) {
|
||||
return <Pill text="Member" color={Green} />;
|
||||
}
|
||||
return <Pill text="Invitation Sent" color={Yellow} />;
|
||||
},
|
||||
},
|
||||
]}
|
||||
/>
|
||||
{showInviteUserModal && !isPushGroupsManaged && (
|
||||
<ModelFormModal<TeamMember>
|
||||
|
||||
@@ -81,7 +81,10 @@ const UserSettingsCustomFields: FunctionComponent<
|
||||
newProfile.userId = userId;
|
||||
|
||||
const response: HTTPResponse<
|
||||
JSONObject | JSONArray | ProjectUserProfile | Array<ProjectUserProfile>
|
||||
| JSONObject
|
||||
| JSONArray
|
||||
| ProjectUserProfile
|
||||
| Array<ProjectUserProfile>
|
||||
> = await ModelAPI.create<ProjectUserProfile>({
|
||||
model: newProfile,
|
||||
modelType: ProjectUserProfile,
|
||||
|
||||
@@ -566,9 +566,7 @@ const IncidentsRoutes: FunctionComponent<ComponentProps> = (
|
||||
/>
|
||||
|
||||
<PageRoute
|
||||
path={
|
||||
IncidentsRoutePath[PageMap.INCIDENTS_SETTINGS_SLA_RULES] || ""
|
||||
}
|
||||
path={IncidentsRoutePath[PageMap.INCIDENTS_SETTINGS_SLA_RULES] || ""}
|
||||
element={
|
||||
<Suspense fallback={Loader}>
|
||||
<IncidentSettingsSlaRules
|
||||
|
||||
@@ -94,12 +94,16 @@ const UserSettingsRoutes: FunctionComponent<ComponentProps> = (
|
||||
}
|
||||
/>
|
||||
<PageRoute
|
||||
path={UserSettingsRoutePath[PageMap.USER_SETTINGS_CUSTOM_FIELDS] || ""}
|
||||
path={
|
||||
UserSettingsRoutePath[PageMap.USER_SETTINGS_CUSTOM_FIELDS] || ""
|
||||
}
|
||||
element={
|
||||
<Suspense fallback={Loader}>
|
||||
<UserSettingsCustomFields
|
||||
{...props}
|
||||
pageRoute={RouteMap[PageMap.USER_SETTINGS_CUSTOM_FIELDS] as Route}
|
||||
pageRoute={
|
||||
RouteMap[PageMap.USER_SETTINGS_CUSTOM_FIELDS] as Route
|
||||
}
|
||||
/>
|
||||
</Suspense>
|
||||
}
|
||||
|
||||
@@ -63,10 +63,11 @@ RunCron(
|
||||
breachType = "response";
|
||||
} else if (sla.status === IncidentSlaStatus.OnTrack) {
|
||||
// Check if at risk for response
|
||||
const totalResponseTime: number = OneUptimeDate.getDifferenceInMinutes(
|
||||
sla.responseDeadline,
|
||||
sla.slaStartedAt,
|
||||
);
|
||||
const totalResponseTime: number =
|
||||
OneUptimeDate.getDifferenceInMinutes(
|
||||
sla.responseDeadline,
|
||||
sla.slaStartedAt,
|
||||
);
|
||||
const elapsedTime: number = OneUptimeDate.getDifferenceInMinutes(
|
||||
now,
|
||||
sla.slaStartedAt,
|
||||
|
||||
Reference in New Issue
Block a user