mirror of
https://github.com/OneUptime/oneuptime.git
synced 2026-04-06 00:32:12 +02:00
add scheduled maintenance
This commit is contained in:
@@ -17,12 +17,14 @@ import QueryHelper from '../Types/Database/QueryHelper';
|
||||
import ObjectID from 'Common/Types/ObjectID';
|
||||
import OneUptimeDate from 'Common/Types/Date';
|
||||
import MonitorStatus from 'Model/Models/MonitorStatus';
|
||||
import { Yellow, Green, Red, Moroon } from 'Common/Types/BrandColors';
|
||||
import { Yellow, Green, Red, Moroon, Black } from 'Common/Types/BrandColors';
|
||||
import MonitorStatusService from './MonitorStatusService';
|
||||
import IncidentState from 'Model/Models/IncidentState';
|
||||
import IncidentStateService from './IncidentStateService';
|
||||
import IncidentSeverity from 'Model/Models/IncidentSeverity';
|
||||
import IncidentSeverityService from './IncidentSeverityService';
|
||||
import ScheduledMaintenanceState from 'Model/Models/ScheduledMaintenanceState';
|
||||
import ScheduledMaintenanceStateService from './ScheduledMaintenanceStateService';
|
||||
|
||||
export class Service extends DatabaseService<Model> {
|
||||
public constructor(postgresDatabase?: PostgresDatabase) {
|
||||
@@ -79,6 +81,61 @@ export class Service extends DatabaseService<Model> {
|
||||
return Promise.resolve({ createBy: data, carryForward: null });
|
||||
}
|
||||
|
||||
|
||||
private async addDefaultScheduledMaintenanceState(createdItem: Model): Promise<Model> {
|
||||
let createdScheduledMaintenanceState: ScheduledMaintenanceState = new ScheduledMaintenanceState();
|
||||
createdScheduledMaintenanceState.name = 'Scheduled';
|
||||
createdScheduledMaintenanceState.description =
|
||||
'When an event is scheduled, it belongs to this state';
|
||||
createdScheduledMaintenanceState.color = Black;
|
||||
createdScheduledMaintenanceState.isScheduledState = true;
|
||||
createdScheduledMaintenanceState.projectId = createdItem.id!;
|
||||
createdScheduledMaintenanceState.order = 1;
|
||||
|
||||
createdScheduledMaintenanceState = await ScheduledMaintenanceStateService.create({
|
||||
data: createdScheduledMaintenanceState,
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
|
||||
let ongoingScheduledMaintenanceState: ScheduledMaintenanceState = new ScheduledMaintenanceState();
|
||||
ongoingScheduledMaintenanceState.name = 'Ongoing';
|
||||
ongoingScheduledMaintenanceState.description =
|
||||
'When an event is ongoing, it belongs to this state.';
|
||||
ongoingScheduledMaintenanceState.color = Yellow;
|
||||
ongoingScheduledMaintenanceState.isOngoingState = true;
|
||||
ongoingScheduledMaintenanceState.projectId = createdItem.id!;
|
||||
ongoingScheduledMaintenanceState.order = 2;
|
||||
|
||||
ongoingScheduledMaintenanceState = await ScheduledMaintenanceStateService.create({
|
||||
data: ongoingScheduledMaintenanceState,
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
|
||||
let completedScheduledMaintenanceState: ScheduledMaintenanceState = new ScheduledMaintenanceState();
|
||||
completedScheduledMaintenanceState.name = 'Completed';
|
||||
completedScheduledMaintenanceState.description =
|
||||
'When an event is completed, it belongs to this state.';
|
||||
completedScheduledMaintenanceState.color = Green;
|
||||
completedScheduledMaintenanceState.isResolvedState = true;
|
||||
completedScheduledMaintenanceState.projectId = createdItem.id!;
|
||||
completedScheduledMaintenanceState.order = 3;
|
||||
|
||||
completedScheduledMaintenanceState = await ScheduledMaintenanceStateService.create({
|
||||
data: completedScheduledMaintenanceState,
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
|
||||
return createdItem;
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected override async onCreateSuccess(
|
||||
_onCreate: OnCreate<Model>,
|
||||
createdItem: Model
|
||||
@@ -86,6 +143,7 @@ export class Service extends DatabaseService<Model> {
|
||||
createdItem = await this.addDefaultProjectTeams(createdItem);
|
||||
createdItem = await this.addDefaultMonitorStatus(createdItem);
|
||||
createdItem = await this.addDefaultIncidentState(createdItem);
|
||||
createdItem = await this.addDefaultScheduledMaintenanceState(createdItem);
|
||||
createdItem = await this.addDefaultIncidentSeverity(createdItem);
|
||||
|
||||
return createdItem;
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
import PostgresDatabase from '../Infrastructure/PostgresDatabase';
|
||||
import Model from 'Model/Models/ScheduledMaintenanceInternalNote';
|
||||
import DatabaseService from './DatabaseService';
|
||||
|
||||
export class Service extends DatabaseService<Model> {
|
||||
public constructor(postgresDatabase?: PostgresDatabase) {
|
||||
super(Model, postgresDatabase);
|
||||
}
|
||||
}
|
||||
|
||||
export default new Service();
|
||||
@@ -0,0 +1,11 @@
|
||||
import PostgresDatabase from '../Infrastructure/PostgresDatabase';
|
||||
import Model from 'Model/Models/ScheduledMaintenancePublicNote';
|
||||
import DatabaseService from './DatabaseService';
|
||||
|
||||
export class Service extends DatabaseService<Model> {
|
||||
public constructor(postgresDatabase?: PostgresDatabase) {
|
||||
super(Model, postgresDatabase);
|
||||
}
|
||||
}
|
||||
|
||||
export default new Service();
|
||||
109
CommonServer/Services/ScheduledMaintenanceService.ts
Normal file
109
CommonServer/Services/ScheduledMaintenanceService.ts
Normal file
@@ -0,0 +1,109 @@
|
||||
import PostgresDatabase from '../Infrastructure/PostgresDatabase';
|
||||
import Model from 'Model/Models/ScheduledMaintenance';
|
||||
import DatabaseService, { OnCreate } from './DatabaseService';
|
||||
import ObjectID from 'Common/Types/ObjectID';
|
||||
import Monitor from 'Model/Models/Monitor';
|
||||
import MonitorService from './MonitorService';
|
||||
import DatabaseCommonInteractionProps from 'Common/Types/Database/DatabaseCommonInteractionProps';
|
||||
import ScheduledMaintenanceStateTimeline from 'Model/Models/ScheduledMaintenanceStateTimeline';
|
||||
import ScheduledMaintenanceStateTimelineService from './ScheduledMaintenanceStateTimelineService';
|
||||
import CreateBy from '../Types/Database/CreateBy';
|
||||
import BadDataException from 'Common/Types/Exception/BadDataException';
|
||||
import ScheduledMaintenanceState from 'Model/Models/ScheduledMaintenanceState';
|
||||
import ScheduledMaintenanceStateService from './ScheduledMaintenanceStateService';
|
||||
|
||||
export class Service extends DatabaseService<Model> {
|
||||
public constructor(postgresDatabase?: PostgresDatabase) {
|
||||
super(Model, postgresDatabase);
|
||||
}
|
||||
|
||||
protected override async onBeforeCreate(
|
||||
createBy: CreateBy<Model>
|
||||
): Promise<OnCreate<Model>> {
|
||||
if (!createBy.props.tenantId) {
|
||||
throw new BadDataException('ProjectId required to create monitor.');
|
||||
}
|
||||
|
||||
const scheduledMaintenanceState: ScheduledMaintenanceState | null =
|
||||
await ScheduledMaintenanceStateService.findOneBy({
|
||||
query: {
|
||||
projectId: createBy.props.tenantId,
|
||||
isScheduledState: true,
|
||||
},
|
||||
select: {
|
||||
_id: true,
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!scheduledMaintenanceState || !scheduledMaintenanceState.id) {
|
||||
throw new BadDataException(
|
||||
'Created state not found for this project. Please add an operational status'
|
||||
);
|
||||
}
|
||||
|
||||
createBy.data.currentScheduledMaintenanceStateId = scheduledMaintenanceState.id;
|
||||
|
||||
return { createBy, carryForward: null };
|
||||
}
|
||||
|
||||
protected override async onCreateSuccess(
|
||||
onCreate: OnCreate<Model>,
|
||||
createdItem: Model
|
||||
): Promise<Model> {
|
||||
if (!createdItem.projectId) {
|
||||
throw new BadDataException('projectId is required');
|
||||
}
|
||||
|
||||
if (!createdItem.id) {
|
||||
throw new BadDataException('id is required');
|
||||
}
|
||||
|
||||
if (!createdItem.currentScheduledMaintenanceStateId) {
|
||||
throw new BadDataException('currentScheduledMaintenanceStateId is required');
|
||||
}
|
||||
|
||||
if (createdItem.changeMonitorStatusToId && createdItem.projectId) {
|
||||
// change status of all the monitors.
|
||||
await MonitorService.changeMonitorStatus(
|
||||
createdItem.projectId,
|
||||
createdItem.monitors?.map((monitor: Monitor) => {
|
||||
return new ObjectID(monitor._id || '');
|
||||
}) || [],
|
||||
createdItem.changeMonitorStatusToId,
|
||||
onCreate.createBy.props
|
||||
);
|
||||
}
|
||||
|
||||
await this.changeScheduledMaintenanceState(
|
||||
createdItem.projectId,
|
||||
createdItem.id,
|
||||
createdItem.currentScheduledMaintenanceStateId,
|
||||
onCreate.createBy.props
|
||||
);
|
||||
|
||||
return createdItem;
|
||||
}
|
||||
|
||||
public async changeScheduledMaintenanceState(
|
||||
projectId: ObjectID,
|
||||
scheduledMaintenanceId: ObjectID,
|
||||
scheduledMaintenanceStateId: ObjectID,
|
||||
props: DatabaseCommonInteractionProps
|
||||
): Promise<void> {
|
||||
const statusTimeline: ScheduledMaintenanceStateTimeline =
|
||||
new ScheduledMaintenanceStateTimeline();
|
||||
|
||||
statusTimeline.scheduledMaintenanceId = scheduledMaintenanceId;
|
||||
statusTimeline.scheduledMaintenanceStateId = scheduledMaintenanceStateId;
|
||||
statusTimeline.projectId = projectId;
|
||||
|
||||
await ScheduledMaintenanceStateTimelineService.create({
|
||||
data: statusTimeline,
|
||||
props: props,
|
||||
});
|
||||
}
|
||||
}
|
||||
export default new Service();
|
||||
162
CommonServer/Services/ScheduledMaintenanceStateService.ts
Normal file
162
CommonServer/Services/ScheduledMaintenanceStateService.ts
Normal file
@@ -0,0 +1,162 @@
|
||||
import PostgresDatabase from '../Infrastructure/PostgresDatabase';
|
||||
import Model from 'Model/Models/ScheduledMaintenanceState';
|
||||
import DatabaseService, {
|
||||
OnCreate,
|
||||
OnDelete,
|
||||
OnUpdate,
|
||||
} from './DatabaseService';
|
||||
import CreateBy from '../Types/Database/CreateBy';
|
||||
import LIMIT_MAX from 'Common/Types/Database/LimitMax';
|
||||
import ObjectID from 'Common/Types/ObjectID';
|
||||
import BadDataException from 'Common/Types/Exception/BadDataException';
|
||||
import QueryHelper from '../Types/Database/QueryHelper';
|
||||
import SortOrder from 'Common/Types/Database/SortOrder';
|
||||
import UpdateBy from '../Types/Database/UpdateBy';
|
||||
import DeleteBy from '../Types/Database/DeleteBy';
|
||||
|
||||
export class Service extends DatabaseService<Model> {
|
||||
public constructor(postgresDatabase?: PostgresDatabase) {
|
||||
super(Model, postgresDatabase);
|
||||
}
|
||||
|
||||
protected override async onBeforeCreate(
|
||||
createBy: CreateBy<Model>
|
||||
): Promise<OnCreate<Model>> {
|
||||
if (!createBy.data.order) {
|
||||
throw new BadDataException('Incient State order is required');
|
||||
}
|
||||
|
||||
if (!createBy.data.projectId) {
|
||||
throw new BadDataException('Incient State projectId is required');
|
||||
}
|
||||
|
||||
await this.rearrangeOrder(
|
||||
createBy.data.order,
|
||||
createBy.data.projectId,
|
||||
true
|
||||
);
|
||||
|
||||
return {
|
||||
createBy: createBy,
|
||||
carryForward: null,
|
||||
};
|
||||
}
|
||||
|
||||
protected override async onBeforeDelete(
|
||||
deleteBy: DeleteBy<Model>
|
||||
): Promise<OnDelete<Model>> {
|
||||
if (!deleteBy.query._id && !deleteBy.props.isRoot) {
|
||||
throw new BadDataException(
|
||||
'_id should be present when deleting scheduled maintenance states. Please try the delete with objectId'
|
||||
);
|
||||
}
|
||||
|
||||
let scheduledMaintenanceState: Model | null = null;
|
||||
|
||||
if (!deleteBy.props.isRoot) {
|
||||
scheduledMaintenanceState = await this.findOneBy({
|
||||
query: deleteBy.query,
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
select: {
|
||||
order: true,
|
||||
projectId: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
deleteBy,
|
||||
carryForward: scheduledMaintenanceState,
|
||||
};
|
||||
}
|
||||
|
||||
protected override async onDeleteSuccess(
|
||||
onDelete: OnDelete<Model>,
|
||||
_itemIdsBeforeDelete: ObjectID[]
|
||||
): Promise<OnDelete<Model>> {
|
||||
const deleteBy: DeleteBy<Model> = onDelete.deleteBy;
|
||||
const scheduledMaintenanceState: Model | null = onDelete.carryForward;
|
||||
|
||||
if (!deleteBy.props.isRoot && scheduledMaintenanceState) {
|
||||
if (
|
||||
scheduledMaintenanceState &&
|
||||
scheduledMaintenanceState.order &&
|
||||
scheduledMaintenanceState.projectId
|
||||
) {
|
||||
await this.rearrangeOrder(
|
||||
scheduledMaintenanceState.order,
|
||||
scheduledMaintenanceState.projectId,
|
||||
false
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
deleteBy: deleteBy,
|
||||
carryForward: null,
|
||||
};
|
||||
}
|
||||
|
||||
protected override async onBeforeUpdate(
|
||||
updateBy: UpdateBy<Model>
|
||||
): Promise<OnUpdate<Model>> {
|
||||
if (updateBy.data.order && !updateBy.props.isRoot) {
|
||||
throw new BadDataException(
|
||||
'Scheduled Maintenance State order should not be updated. Delete this scheduled maintenance state and create a new state with the right order.'
|
||||
);
|
||||
}
|
||||
|
||||
return { updateBy, carryForward: null };
|
||||
}
|
||||
|
||||
private async rearrangeOrder(
|
||||
currentOrder: number,
|
||||
projectId: ObjectID,
|
||||
increaseOrder: boolean = true
|
||||
): Promise<void> {
|
||||
// get scheduledMaintenance with this order.
|
||||
const scheduledMaintenanceStates: Array<Model> = await this.findBy({
|
||||
query: {
|
||||
order: QueryHelper.greaterThanEqualTo(currentOrder),
|
||||
projectId: projectId,
|
||||
},
|
||||
limit: LIMIT_MAX,
|
||||
skip: 0,
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
select: {
|
||||
_id: true,
|
||||
order: true,
|
||||
},
|
||||
sort: {
|
||||
order: SortOrder.Ascending,
|
||||
},
|
||||
});
|
||||
|
||||
let newOrder: number = currentOrder;
|
||||
|
||||
for (const scheduledMaintenanceState of scheduledMaintenanceStates) {
|
||||
if (increaseOrder) {
|
||||
newOrder = scheduledMaintenanceState.order! + 1;
|
||||
} else {
|
||||
newOrder = scheduledMaintenanceState.order! - 1;
|
||||
}
|
||||
|
||||
await this.updateBy({
|
||||
query: {
|
||||
_id: scheduledMaintenanceState._id!,
|
||||
},
|
||||
data: {
|
||||
order: newOrder,
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
export default new Service();
|
||||
@@ -0,0 +1,132 @@
|
||||
import PostgresDatabase from '../Infrastructure/PostgresDatabase';
|
||||
import ScheduledMaintenanceStateTimeline from 'Model/Models/ScheduledMaintenanceStateTimeline';
|
||||
import DatabaseService, { OnCreate, OnDelete } from './DatabaseService';
|
||||
import BadDataException from 'Common/Types/Exception/BadDataException';
|
||||
import ScheduledMaintenanceService from './ScheduledMaintenanceService';
|
||||
import DeleteBy from '../Types/Database/DeleteBy';
|
||||
import ObjectID from 'Common/Types/ObjectID';
|
||||
import PositiveNumber from 'Common/Types/PositiveNumber';
|
||||
import SortOrder from 'Common/Types/Database/SortOrder';
|
||||
|
||||
export class Service extends DatabaseService<ScheduledMaintenanceStateTimeline> {
|
||||
public constructor(postgresDatabase?: PostgresDatabase) {
|
||||
super(ScheduledMaintenanceStateTimeline, postgresDatabase);
|
||||
}
|
||||
|
||||
protected override async onCreateSuccess(
|
||||
onCreate: OnCreate<ScheduledMaintenanceStateTimeline>,
|
||||
createdItem: ScheduledMaintenanceStateTimeline
|
||||
): Promise<ScheduledMaintenanceStateTimeline> {
|
||||
if (!createdItem.scheduledMaintenanceId) {
|
||||
throw new BadDataException('scheduledMaintenanceId is null');
|
||||
}
|
||||
|
||||
if (!createdItem.scheduledMaintenanceStateId) {
|
||||
throw new BadDataException('scheduledMaintenanceStateId is null');
|
||||
}
|
||||
|
||||
await ScheduledMaintenanceService.updateBy({
|
||||
query: {
|
||||
_id: createdItem.scheduledMaintenanceId?.toString(),
|
||||
},
|
||||
data: {
|
||||
currentScheduledMaintenanceStateId: createdItem.scheduledMaintenanceStateId,
|
||||
},
|
||||
props: onCreate.createBy.props,
|
||||
});
|
||||
|
||||
return createdItem;
|
||||
}
|
||||
|
||||
protected override async onBeforeDelete(
|
||||
deleteBy: DeleteBy<ScheduledMaintenanceStateTimeline>
|
||||
): Promise<OnDelete<ScheduledMaintenanceStateTimeline>> {
|
||||
if (deleteBy.query._id) {
|
||||
const scheduledMaintenanceStateTimeline: ScheduledMaintenanceStateTimeline | null =
|
||||
await this.findOneById({
|
||||
id: new ObjectID(deleteBy.query._id as string),
|
||||
select: {
|
||||
scheduledMaintenanceId: true,
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
|
||||
const scheduledMaintenanceId: ObjectID | undefined =
|
||||
scheduledMaintenanceStateTimeline?.scheduledMaintenanceId;
|
||||
|
||||
if (scheduledMaintenanceId) {
|
||||
const scheduledMaintenanceStateTimeline: PositiveNumber =
|
||||
await this.countBy({
|
||||
query: {
|
||||
scheduledMaintenanceId: scheduledMaintenanceId,
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (scheduledMaintenanceStateTimeline.isOne()) {
|
||||
throw new BadDataException(
|
||||
'Cannot delete the only state timeline. Scheduled Maintenance should have atleast one state in its timeline.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return { deleteBy, carryForward: scheduledMaintenanceId };
|
||||
}
|
||||
|
||||
return { deleteBy, carryForward: null };
|
||||
}
|
||||
|
||||
protected override async onDeleteSuccess(
|
||||
onDelete: OnDelete<ScheduledMaintenanceStateTimeline>,
|
||||
_itemIdsBeforeDelete: ObjectID[]
|
||||
): Promise<OnDelete<ScheduledMaintenanceStateTimeline>> {
|
||||
if (onDelete.carryForward) {
|
||||
// this is scheduledMaintenanceId.
|
||||
const scheduledMaintenanceId: ObjectID = onDelete.carryForward as ObjectID;
|
||||
|
||||
// get last status of this monitor.
|
||||
const scheduledMaintenanceStateTimeline: ScheduledMaintenanceStateTimeline | null =
|
||||
await this.findOneBy({
|
||||
query: {
|
||||
scheduledMaintenanceId: scheduledMaintenanceId,
|
||||
},
|
||||
sort: {
|
||||
createdAt: SortOrder.Descending,
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
select: {
|
||||
_id: true,
|
||||
scheduledMaintenanceStateId: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (
|
||||
scheduledMaintenanceStateTimeline &&
|
||||
scheduledMaintenanceStateTimeline.scheduledMaintenanceStateId
|
||||
) {
|
||||
await ScheduledMaintenanceService.updateBy({
|
||||
query: {
|
||||
_id: scheduledMaintenanceId.toString(),
|
||||
},
|
||||
data: {
|
||||
currentScheduledMaintenanceStateId:
|
||||
scheduledMaintenanceStateTimeline.scheduledMaintenanceStateId,
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return onDelete;
|
||||
}
|
||||
}
|
||||
|
||||
export default new Service();
|
||||
217
CommonUI/package-lock.json
generated
217
CommonUI/package-lock.json
generated
@@ -9,7 +9,6 @@
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@ailibs/feather-react-ts": "^3.0.3",
|
||||
"@fortawesome/fontawesome-svg-core": "^6.1.1",
|
||||
"@fortawesome/free-regular-svg-icons": "^6.1.1",
|
||||
"@fortawesome/free-solid-svg-icons": "^6.1.1",
|
||||
@@ -39,6 +38,7 @@
|
||||
"react-dnd-html5-backend": "^16.0.1",
|
||||
"react-dom": "^18.1.0",
|
||||
"react-dropzone": "^14.2.2",
|
||||
"react-feather": "^2.0.10",
|
||||
"react-icons": "^4.4.0",
|
||||
"react-markdown": "^8.0.3",
|
||||
"react-modern-drawer": "^1.1.1",
|
||||
@@ -8450,16 +8450,6 @@
|
||||
"integrity": "sha512-+u76oB43nOHrF4DDWRLWDCtci7f3QJoEBigemIdIeTi1ODqjx6Tad9NCVnPRwewWlKkVab5PlK8DCtPTyX7S8g==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@ailibs/feather-react-ts": {
|
||||
"version": "3.0.3",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"html-react-parser": "^1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@ampproject/remapping": {
|
||||
"version": "2.2.0",
|
||||
"license": "Apache-2.0",
|
||||
@@ -11605,35 +11595,6 @@
|
||||
"csstype": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/dom-serializer": {
|
||||
"version": "1.4.1",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"domelementtype": "^2.0.1",
|
||||
"domhandler": "^4.2.0",
|
||||
"entities": "^2.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/dom-serializer/node_modules/entities": {
|
||||
"version": "2.2.0",
|
||||
"license": "BSD-2-Clause",
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/domelementtype": {
|
||||
"version": "2.3.0",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/fb55"
|
||||
}
|
||||
],
|
||||
"license": "BSD-2-Clause"
|
||||
},
|
||||
"node_modules/domexception": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz",
|
||||
@@ -11646,31 +11607,6 @@
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/domhandler": {
|
||||
"version": "4.3.1",
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"domelementtype": "^2.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/domhandler?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/domutils": {
|
||||
"version": "2.8.0",
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"dom-serializer": "^1.0.1",
|
||||
"domelementtype": "^2.2.0",
|
||||
"domhandler": "^4.2.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/domutils?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/electron-to-chromium": {
|
||||
"version": "1.4.170",
|
||||
"license": "ISC"
|
||||
@@ -11691,16 +11627,6 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/entities": {
|
||||
"version": "3.0.1",
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/error-ex": {
|
||||
"version": "1.3.2",
|
||||
"license": "MIT",
|
||||
@@ -12270,14 +12196,6 @@
|
||||
"react-is": "^16.7.0"
|
||||
}
|
||||
},
|
||||
"node_modules/html-dom-parser": {
|
||||
"version": "1.2.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"domhandler": "4.3.1",
|
||||
"htmlparser2": "7.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/html-encoding-sniffer": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz",
|
||||
@@ -12295,19 +12213,6 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/html-react-parser": {
|
||||
"version": "1.4.14",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"domhandler": "4.3.1",
|
||||
"html-dom-parser": "1.2.0",
|
||||
"react-property": "2.0.0",
|
||||
"style-to-js": "1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "0.14 || 15 || 16 || 17 || 18"
|
||||
}
|
||||
},
|
||||
"node_modules/html-void-elements": {
|
||||
"version": "2.0.1",
|
||||
"license": "MIT",
|
||||
@@ -12316,23 +12221,6 @@
|
||||
"url": "https://github.com/sponsors/wooorm"
|
||||
}
|
||||
},
|
||||
"node_modules/htmlparser2": {
|
||||
"version": "7.2.0",
|
||||
"funding": [
|
||||
"https://github.com/fb55/htmlparser2?sponsor=1",
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/fb55"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"domelementtype": "^2.0.1",
|
||||
"domhandler": "^4.2.2",
|
||||
"domutils": "^2.8.0",
|
||||
"entities": "^3.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/http-proxy-agent": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz",
|
||||
@@ -17944,6 +17832,17 @@
|
||||
"version": "2.0.4",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/react-feather": {
|
||||
"version": "2.0.10",
|
||||
"resolved": "https://registry.npmjs.org/react-feather/-/react-feather-2.0.10.tgz",
|
||||
"integrity": "sha512-BLhukwJ+Z92Nmdcs+EMw6dy1Z/VLiJTzEQACDUEnWMClhYnFykJCGWQx+NmwP/qQHGX/5CzQ+TGi8ofg2+HzVQ==",
|
||||
"dependencies": {
|
||||
"prop-types": "^15.7.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.8.6"
|
||||
}
|
||||
},
|
||||
"node_modules/react-icons": {
|
||||
"version": "4.4.0",
|
||||
"license": "MIT",
|
||||
@@ -18019,10 +17918,6 @@
|
||||
"version": "3.2.0",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/react-property": {
|
||||
"version": "2.0.0",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/react-redux": {
|
||||
"version": "7.2.8",
|
||||
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.8.tgz",
|
||||
@@ -18720,13 +18615,6 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/style-to-js": {
|
||||
"version": "1.1.1",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"style-to-object": "0.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/style-to-object": {
|
||||
"version": "0.3.0",
|
||||
"license": "MIT",
|
||||
@@ -19561,12 +19449,6 @@
|
||||
"integrity": "sha512-+u76oB43nOHrF4DDWRLWDCtci7f3QJoEBigemIdIeTi1ODqjx6Tad9NCVnPRwewWlKkVab5PlK8DCtPTyX7S8g==",
|
||||
"dev": true
|
||||
},
|
||||
"@ailibs/feather-react-ts": {
|
||||
"version": "3.0.3",
|
||||
"requires": {
|
||||
"html-react-parser": "^1.1.1"
|
||||
}
|
||||
},
|
||||
"@ampproject/remapping": {
|
||||
"version": "2.2.0",
|
||||
"requires": {
|
||||
@@ -24343,22 +24225,6 @@
|
||||
"csstype": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"dom-serializer": {
|
||||
"version": "1.4.1",
|
||||
"requires": {
|
||||
"domelementtype": "^2.0.1",
|
||||
"domhandler": "^4.2.0",
|
||||
"entities": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"entities": {
|
||||
"version": "2.2.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"domelementtype": {
|
||||
"version": "2.3.0"
|
||||
},
|
||||
"domexception": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz",
|
||||
@@ -24368,20 +24234,6 @@
|
||||
"webidl-conversions": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"domhandler": {
|
||||
"version": "4.3.1",
|
||||
"requires": {
|
||||
"domelementtype": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"domutils": {
|
||||
"version": "2.8.0",
|
||||
"requires": {
|
||||
"dom-serializer": "^1.0.1",
|
||||
"domelementtype": "^2.2.0",
|
||||
"domhandler": "^4.2.0"
|
||||
}
|
||||
},
|
||||
"electron-to-chromium": {
|
||||
"version": "1.4.170"
|
||||
},
|
||||
@@ -24393,9 +24245,6 @@
|
||||
"version": "8.0.0",
|
||||
"dev": true
|
||||
},
|
||||
"entities": {
|
||||
"version": "3.0.1"
|
||||
},
|
||||
"error-ex": {
|
||||
"version": "1.3.2",
|
||||
"requires": {
|
||||
@@ -24768,13 +24617,6 @@
|
||||
"react-is": "^16.7.0"
|
||||
}
|
||||
},
|
||||
"html-dom-parser": {
|
||||
"version": "1.2.0",
|
||||
"requires": {
|
||||
"domhandler": "4.3.1",
|
||||
"htmlparser2": "7.2.0"
|
||||
}
|
||||
},
|
||||
"html-encoding-sniffer": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz",
|
||||
@@ -24788,27 +24630,9 @@
|
||||
"version": "2.0.2",
|
||||
"dev": true
|
||||
},
|
||||
"html-react-parser": {
|
||||
"version": "1.4.14",
|
||||
"requires": {
|
||||
"domhandler": "4.3.1",
|
||||
"html-dom-parser": "1.2.0",
|
||||
"react-property": "2.0.0",
|
||||
"style-to-js": "1.1.1"
|
||||
}
|
||||
},
|
||||
"html-void-elements": {
|
||||
"version": "2.0.1"
|
||||
},
|
||||
"htmlparser2": {
|
||||
"version": "7.2.0",
|
||||
"requires": {
|
||||
"domelementtype": "^2.0.1",
|
||||
"domhandler": "^4.2.2",
|
||||
"domutils": "^2.8.0",
|
||||
"entities": "^3.0.1"
|
||||
}
|
||||
},
|
||||
"http-proxy-agent": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz",
|
||||
@@ -33626,6 +33450,14 @@
|
||||
"react-fast-compare": {
|
||||
"version": "2.0.4"
|
||||
},
|
||||
"react-feather": {
|
||||
"version": "2.0.10",
|
||||
"resolved": "https://registry.npmjs.org/react-feather/-/react-feather-2.0.10.tgz",
|
||||
"integrity": "sha512-BLhukwJ+Z92Nmdcs+EMw6dy1Z/VLiJTzEQACDUEnWMClhYnFykJCGWQx+NmwP/qQHGX/5CzQ+TGi8ofg2+HzVQ==",
|
||||
"requires": {
|
||||
"prop-types": "^15.7.2"
|
||||
}
|
||||
},
|
||||
"react-icons": {
|
||||
"version": "4.4.0",
|
||||
"requires": {}
|
||||
@@ -33677,9 +33509,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"react-property": {
|
||||
"version": "2.0.0"
|
||||
},
|
||||
"react-redux": {
|
||||
"version": "7.2.8",
|
||||
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.8.tgz",
|
||||
@@ -34136,12 +33965,6 @@
|
||||
"version": "3.1.1",
|
||||
"dev": true
|
||||
},
|
||||
"style-to-js": {
|
||||
"version": "1.1.1",
|
||||
"requires": {
|
||||
"style-to-object": "0.3.0"
|
||||
}
|
||||
},
|
||||
"style-to-object": {
|
||||
"version": "0.3.0",
|
||||
"requires": {
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@ailibs/feather-react-ts": "^3.0.3",
|
||||
"@fortawesome/fontawesome-svg-core": "^6.1.1",
|
||||
"@fortawesome/free-regular-svg-icons": "^6.1.1",
|
||||
"@fortawesome/free-solid-svg-icons": "^6.1.1",
|
||||
@@ -41,6 +40,7 @@
|
||||
"react-dnd-html5-backend": "^16.0.1",
|
||||
"react-dom": "^18.1.0",
|
||||
"react-dropzone": "^14.2.2",
|
||||
"react-feather": "^2.0.10",
|
||||
"react-icons": "^4.4.0",
|
||||
"react-markdown": "^8.0.3",
|
||||
"react-modern-drawer": "^1.1.1",
|
||||
|
||||
@@ -1,61 +1,61 @@
|
||||
import Color from 'Common/Types/Color';
|
||||
import React, { CSSProperties, FunctionComponent, ReactElement } from 'react';
|
||||
import {
|
||||
FiHome,
|
||||
FiGrid,
|
||||
FiActivity,
|
||||
FiAlertOctagon,
|
||||
FiPhoneCall,
|
||||
FiSettings,
|
||||
FiBell,
|
||||
FiCheckCircle,
|
||||
FiSearch,
|
||||
FiHelpCircle,
|
||||
FiDisc,
|
||||
FiPower,
|
||||
FiImage,
|
||||
FiGlobe,
|
||||
FiMoreVertical,
|
||||
FiCreditCard,
|
||||
FiUser,
|
||||
FiChevronDown,
|
||||
FiChevronRight,
|
||||
FiChevronLeft,
|
||||
FiChevronUp,
|
||||
FiCircle,
|
||||
FiSend,
|
||||
FiMail,
|
||||
FiBarChart2,
|
||||
FiSlack,
|
||||
FiClock,
|
||||
FiTerminal,
|
||||
FiAlertTriangle,
|
||||
FiCode,
|
||||
FiPieChart,
|
||||
FiUsers,
|
||||
FiRss,
|
||||
FiLock,
|
||||
FiKey,
|
||||
FiType,
|
||||
FiFolder,
|
||||
FiShare2,
|
||||
FiMessageSquare,
|
||||
FiInfo,
|
||||
FiCheck,
|
||||
FiTrash,
|
||||
FiX,
|
||||
FiPlus,
|
||||
FiTag,
|
||||
FiRefreshCcw,
|
||||
FiFilter,
|
||||
FiEdit2,
|
||||
FiEyeOff,
|
||||
FiFileText,
|
||||
FiList,
|
||||
FiLink2,
|
||||
FiExternalLink,
|
||||
FiLayers
|
||||
} from 'react-icons/fi';
|
||||
Home,
|
||||
Grid,
|
||||
Activity,
|
||||
AlertOctagon,
|
||||
PhoneCall,
|
||||
Settings,
|
||||
Bell,
|
||||
CheckCircle,
|
||||
Search,
|
||||
HelpCircle,
|
||||
Disc,
|
||||
Power,
|
||||
Image,
|
||||
Globe,
|
||||
MoreVertical,
|
||||
CreditCard,
|
||||
User,
|
||||
ChevronDown,
|
||||
ChevronRight,
|
||||
ChevronLeft,
|
||||
ChevronUp,
|
||||
Circle,
|
||||
Send,
|
||||
Mail,
|
||||
BarChart2,
|
||||
Slack,
|
||||
Clock,
|
||||
Terminal,
|
||||
AlertTriangle,
|
||||
Code,
|
||||
PieChart,
|
||||
Users,
|
||||
Rss,
|
||||
Lock,
|
||||
Key,
|
||||
Type,
|
||||
Folder,
|
||||
Share2,
|
||||
MessageSquare,
|
||||
Info,
|
||||
Check,
|
||||
Trash,
|
||||
X,
|
||||
Plus,
|
||||
Tag,
|
||||
RefreshCcw,
|
||||
Filter,
|
||||
Edit2,
|
||||
EyeOff,
|
||||
FileText,
|
||||
List,
|
||||
Link2,
|
||||
ExternalLink,
|
||||
Layers,
|
||||
} from 'react-feather';
|
||||
|
||||
export enum SizeProp {
|
||||
ExtraSmall = '8px',
|
||||
@@ -97,7 +97,7 @@ export enum IconProp {
|
||||
List,
|
||||
CheckCircle,
|
||||
Search,
|
||||
TextFile,
|
||||
Textle,
|
||||
Globe,
|
||||
Logout,
|
||||
Billing,
|
||||
@@ -135,7 +135,8 @@ export enum IconProp {
|
||||
SendMessage,
|
||||
ExternalLink,
|
||||
Link,
|
||||
Layers
|
||||
Layers,
|
||||
Clock
|
||||
}
|
||||
|
||||
export interface ComponentProps {
|
||||
@@ -168,175 +169,175 @@ const Icon: FunctionComponent<ComponentProps> = ({
|
||||
}}
|
||||
>
|
||||
{icon === IconProp.Home && (
|
||||
<FiHome
|
||||
<Home
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
/>
|
||||
)}
|
||||
{icon === IconProp.More && (
|
||||
<FiGrid
|
||||
<Grid
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
/>
|
||||
)}
|
||||
{icon === IconProp.Activity && (
|
||||
<FiActivity
|
||||
<Activity
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
/>
|
||||
)}
|
||||
{icon === IconProp.Alert && (
|
||||
<FiAlertOctagon
|
||||
<AlertOctagon
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
/>
|
||||
)}
|
||||
{icon === IconProp.Call && (
|
||||
<FiPhoneCall
|
||||
<PhoneCall
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
/>
|
||||
)}
|
||||
{icon === IconProp.Settings && (
|
||||
<FiSettings
|
||||
<Settings
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
/>
|
||||
)}
|
||||
{icon === IconProp.Notification && (
|
||||
<FiBell
|
||||
<Bell
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
/>
|
||||
)}
|
||||
{icon === IconProp.CheckCircle && (
|
||||
<FiCheckCircle
|
||||
<CheckCircle
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
/>
|
||||
)}
|
||||
{icon === IconProp.Search && (
|
||||
<FiSearch
|
||||
<Search
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
/>
|
||||
)}
|
||||
{icon === IconProp.Help && (
|
||||
<FiHelpCircle
|
||||
<HelpCircle
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
/>
|
||||
)}
|
||||
{icon === IconProp.Logout && (
|
||||
<FiPower
|
||||
<Power
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
/>
|
||||
)}
|
||||
{icon === IconProp.Billing && (
|
||||
<FiCreditCard
|
||||
<CreditCard
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
/>
|
||||
)}
|
||||
{icon === IconProp.User && (
|
||||
<FiUser
|
||||
<User
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
/>
|
||||
)}
|
||||
{icon === IconProp.ChevronDown && (
|
||||
<FiChevronDown
|
||||
<ChevronDown
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
/>
|
||||
)}
|
||||
{icon === IconProp.ChevronLeft && (
|
||||
<FiChevronLeft
|
||||
<ChevronLeft
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
/>
|
||||
)}
|
||||
{icon === IconProp.ChevronRight && (
|
||||
<FiChevronRight
|
||||
<ChevronRight
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
/>
|
||||
)}
|
||||
{icon === IconProp.ChevronUp && (
|
||||
<FiChevronUp
|
||||
<ChevronUp
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
/>
|
||||
)}
|
||||
{icon === IconProp.Email && (
|
||||
<FiMail
|
||||
<Mail
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
/>
|
||||
)}
|
||||
{icon === IconProp.Slack && (
|
||||
<FiSlack
|
||||
<Slack
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
/>
|
||||
)}
|
||||
{icon === IconProp.Time && (
|
||||
<FiClock
|
||||
<Clock
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
/>
|
||||
)}
|
||||
{icon === IconProp.Terminal && (
|
||||
<FiTerminal
|
||||
<Terminal
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
/>
|
||||
)}
|
||||
{icon === IconProp.Error && (
|
||||
<FiAlertTriangle
|
||||
<AlertTriangle
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
/>
|
||||
)}
|
||||
{icon === IconProp.Code && (
|
||||
<FiCode
|
||||
<Code
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
/>
|
||||
)}
|
||||
{icon === IconProp.Report && (
|
||||
<FiPieChart
|
||||
<PieChart
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
/>
|
||||
)}
|
||||
{icon === IconProp.Team && (
|
||||
<FiUsers
|
||||
<Users
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
@@ -344,7 +345,7 @@ const Icon: FunctionComponent<ComponentProps> = ({
|
||||
)}
|
||||
|
||||
{icon === IconProp.Lock && (
|
||||
<FiLock
|
||||
<Lock
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
@@ -352,7 +353,7 @@ const Icon: FunctionComponent<ComponentProps> = ({
|
||||
)}
|
||||
|
||||
{icon === IconProp.Key && (
|
||||
<FiKey
|
||||
<Key
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
@@ -360,7 +361,7 @@ const Icon: FunctionComponent<ComponentProps> = ({
|
||||
)}
|
||||
|
||||
{icon === IconProp.Folder && (
|
||||
<FiFolder
|
||||
<Folder
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
@@ -368,7 +369,7 @@ const Icon: FunctionComponent<ComponentProps> = ({
|
||||
)}
|
||||
|
||||
{icon === IconProp.Integrations && (
|
||||
<FiShare2
|
||||
<Share2
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
@@ -376,105 +377,105 @@ const Icon: FunctionComponent<ComponentProps> = ({
|
||||
)}
|
||||
|
||||
{icon === IconProp.SMS && (
|
||||
<FiMessageSquare
|
||||
<MessageSquare
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
/>
|
||||
)}
|
||||
{icon === IconProp.Info && (
|
||||
<FiInfo
|
||||
<Info
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
/>
|
||||
)}
|
||||
{icon === IconProp.Success && (
|
||||
<FiCheck
|
||||
<Check
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
/>
|
||||
)}
|
||||
{icon === IconProp.Trash && (
|
||||
<FiTrash
|
||||
<Trash
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
/>
|
||||
)}
|
||||
{icon === IconProp.Close && (
|
||||
<FiX
|
||||
<X
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
/>
|
||||
)}
|
||||
{icon === IconProp.Add && (
|
||||
<FiPlus
|
||||
<Plus
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
/>
|
||||
)}
|
||||
{icon === IconProp.Label && (
|
||||
<FiTag
|
||||
<Tag
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
/>
|
||||
)}
|
||||
{icon === IconProp.Refresh && (
|
||||
<FiRefreshCcw
|
||||
<RefreshCcw
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
/>
|
||||
)}
|
||||
{icon === IconProp.Filter && (
|
||||
<FiFilter
|
||||
<Filter
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
/>
|
||||
)}
|
||||
{icon === IconProp.Edit && (
|
||||
<FiEdit2
|
||||
<Edit2
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
/>
|
||||
)}
|
||||
{icon === IconProp.Hide && (
|
||||
<FiEyeOff
|
||||
<EyeOff
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
/>
|
||||
)}
|
||||
{icon === IconProp.Check && (
|
||||
<FiCheck
|
||||
<Check
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
/>
|
||||
)}
|
||||
{icon === IconProp.True && (
|
||||
<FiCheck
|
||||
<Check
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
/>
|
||||
)}
|
||||
{icon === IconProp.False && (
|
||||
<FiX
|
||||
<X
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
/>
|
||||
)}
|
||||
{icon === IconProp.List && (
|
||||
<FiList
|
||||
<List
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
@@ -482,7 +483,7 @@ const Icon: FunctionComponent<ComponentProps> = ({
|
||||
)}
|
||||
|
||||
{icon === IconProp.Public && (
|
||||
<FiUser
|
||||
<User
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
@@ -490,7 +491,7 @@ const Icon: FunctionComponent<ComponentProps> = ({
|
||||
)}
|
||||
|
||||
{icon === IconProp.Circle && (
|
||||
<FiCircle
|
||||
<Circle
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
@@ -498,7 +499,7 @@ const Icon: FunctionComponent<ComponentProps> = ({
|
||||
)}
|
||||
|
||||
{icon === IconProp.Graph && (
|
||||
<FiBarChart2
|
||||
<BarChart2
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
@@ -506,7 +507,7 @@ const Icon: FunctionComponent<ComponentProps> = ({
|
||||
)}
|
||||
|
||||
{icon === IconProp.Globe && (
|
||||
<FiGlobe
|
||||
<Globe
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
@@ -514,7 +515,7 @@ const Icon: FunctionComponent<ComponentProps> = ({
|
||||
)}
|
||||
|
||||
{icon === IconProp.Image && (
|
||||
<FiImage
|
||||
<Image
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
@@ -522,7 +523,7 @@ const Icon: FunctionComponent<ComponentProps> = ({
|
||||
)}
|
||||
|
||||
{icon === IconProp.Text && (
|
||||
<FiType
|
||||
<Type
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
@@ -530,7 +531,7 @@ const Icon: FunctionComponent<ComponentProps> = ({
|
||||
)}
|
||||
|
||||
{icon === IconProp.Drag && (
|
||||
<FiMoreVertical
|
||||
<MoreVertical
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
@@ -538,7 +539,7 @@ const Icon: FunctionComponent<ComponentProps> = ({
|
||||
)}
|
||||
|
||||
{icon === IconProp.Webhook && (
|
||||
<FiLink2
|
||||
<Link2
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
@@ -546,7 +547,7 @@ const Icon: FunctionComponent<ComponentProps> = ({
|
||||
)}
|
||||
|
||||
{icon === IconProp.Link && (
|
||||
<FiLink2
|
||||
<Link2
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
@@ -554,7 +555,7 @@ const Icon: FunctionComponent<ComponentProps> = ({
|
||||
)}
|
||||
|
||||
{icon === IconProp.SendMessage && (
|
||||
<FiSend
|
||||
<Send
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
@@ -562,15 +563,15 @@ const Icon: FunctionComponent<ComponentProps> = ({
|
||||
)}
|
||||
|
||||
{icon === IconProp.Disc && (
|
||||
<FiDisc
|
||||
<Disc
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
/>
|
||||
)}
|
||||
|
||||
{icon === IconProp.TextFile && (
|
||||
<FiFileText
|
||||
{icon === IconProp.Textle && (
|
||||
<FileText
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
@@ -578,7 +579,7 @@ const Icon: FunctionComponent<ComponentProps> = ({
|
||||
)}
|
||||
|
||||
{icon === IconProp.ExternalLink && (
|
||||
<FiExternalLink
|
||||
<ExternalLink
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
@@ -586,14 +587,21 @@ const Icon: FunctionComponent<ComponentProps> = ({
|
||||
)}
|
||||
|
||||
{icon === IconProp.RSS && (
|
||||
<FiRss
|
||||
<Rss
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
/>
|
||||
)}
|
||||
{icon === IconProp.Layers && (
|
||||
<FiLayers
|
||||
<Layers
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
/>
|
||||
)}
|
||||
{icon === IconProp.Clock && (
|
||||
<Clock
|
||||
size={size}
|
||||
strokeWidth={thick ? thick : ''}
|
||||
color={color ? color.toString() : ''}
|
||||
|
||||
@@ -43,6 +43,15 @@ import IncidentInternalNote from './Pages/Incidents/View/InternalNote';
|
||||
import IncidentPublicNote from './Pages/Incidents/View/PublicNote';
|
||||
import UnresolvedIncidents from './Pages/Incidents/Unresolved';
|
||||
|
||||
|
||||
import ScheduledMaintenanceEvents from './Pages/ScheduledMaintenanceEvents/ScheduledMaintenanceEvents';
|
||||
import ScheduledMaintenanceEventView from './Pages/ScheduledMaintenanceEvents/View/Index';
|
||||
import ScheduledMaintenanceEventViewDelete from './Pages/ScheduledMaintenanceEvents/View/Delete';
|
||||
import ScheduledMaintenanceEventViewStateTimeline from './Pages/ScheduledMaintenanceEvents/View/StateTimeline';
|
||||
import ScheduledMaintenanceEventInternalNote from './Pages/ScheduledMaintenanceEvents/View/InternalNote';
|
||||
import ScheduledMaintenanceEventPublicNote from './Pages/ScheduledMaintenanceEvents/View/PublicNote';
|
||||
import OngoingScheduledMaintenanceEvents from './Pages/ScheduledMaintenanceEvents/Ongoing';
|
||||
|
||||
import Logs from './Pages/Logs/Logs';
|
||||
import Navigation from 'CommonUI/src/Utils/Navigation';
|
||||
import RouteMap from './Utils/RouteMap';
|
||||
@@ -59,6 +68,7 @@ import SettingsTeams from './Pages/Settings/Teams';
|
||||
import SettingsTeamView from './Pages/Settings/TeamView';
|
||||
import SettingsMonitors from './Pages/Settings/MonitorStatus';
|
||||
import SettingsIncidents from './Pages/Settings/IncidentState';
|
||||
import SettingsScheduledMaintenanceState from './Pages/Settings/ScheduledMaintenanceState';
|
||||
import SettingsDomains from './Pages/Settings/Domains';
|
||||
import SettingsIncidentSeverity from './Pages/Settings/IncidentSeverity';
|
||||
|
||||
@@ -674,6 +684,105 @@ const App: FunctionComponent = () => {
|
||||
}
|
||||
/>
|
||||
|
||||
|
||||
|
||||
{/* Scheduled Events */}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<PageRoute
|
||||
path={RouteMap[PageMap.SCHEDULED_MAINTENANCE_EVENTS]?.toString()}
|
||||
element={
|
||||
<ScheduledMaintenanceEvents
|
||||
pageRoute={RouteMap[PageMap.SCHEDULED_MAINTENANCE_EVENTS] as Route}
|
||||
currentProject={selectedProject}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
|
||||
<PageRoute
|
||||
path={RouteMap[PageMap.ONGOING_SCHEDULED_MAINTENANCE_EVENTS]?.toString()}
|
||||
element={
|
||||
<OngoingScheduledMaintenanceEvents
|
||||
pageRoute={
|
||||
RouteMap[PageMap.ONGOING_SCHEDULED_MAINTENANCE_EVENTS] as Route
|
||||
}
|
||||
currentProject={selectedProject}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
|
||||
<PageRoute
|
||||
path={RouteMap[PageMap.SCHEDULED_MAINTENANCE_VIEW]?.toString()}
|
||||
element={
|
||||
<ScheduledMaintenanceEventView
|
||||
pageRoute={RouteMap[PageMap.SCHEDULED_MAINTENANCE_VIEW] as Route}
|
||||
currentProject={selectedProject}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
|
||||
<PageRoute
|
||||
path={RouteMap[PageMap.SCHEDULED_MAINTENANCE_VIEW_DELETE]?.toString()}
|
||||
element={
|
||||
<ScheduledMaintenanceEventViewDelete
|
||||
pageRoute={
|
||||
RouteMap[PageMap.SCHEDULED_MAINTENANCE_VIEW_DELETE] as Route
|
||||
}
|
||||
currentProject={selectedProject}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
|
||||
<PageRoute
|
||||
path={RouteMap[
|
||||
PageMap.SCHEDULED_MAINTENANCE_VIEW_STATE_TIMELINE
|
||||
]?.toString()}
|
||||
element={
|
||||
<ScheduledMaintenanceEventViewStateTimeline
|
||||
pageRoute={
|
||||
RouteMap[
|
||||
PageMap.SCHEDULED_MAINTENANCE_VIEW_STATE_TIMELINE
|
||||
] as Route
|
||||
}
|
||||
currentProject={selectedProject}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
|
||||
<PageRoute
|
||||
path={RouteMap[PageMap.SCHEDULED_MAINTENANCE_INTERNAL_NOTE]?.toString()}
|
||||
element={
|
||||
<ScheduledMaintenanceEventInternalNote
|
||||
pageRoute={
|
||||
RouteMap[
|
||||
PageMap.SCHEDULED_MAINTENANCE_INTERNAL_NOTE
|
||||
] as Route
|
||||
}
|
||||
currentProject={selectedProject}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
|
||||
<PageRoute
|
||||
path={RouteMap[PageMap.SCHEDULED_MAINTENANCE_PUBLIC_NOTE]?.toString()}
|
||||
element={
|
||||
<ScheduledMaintenanceEventPublicNote
|
||||
pageRoute={
|
||||
RouteMap[PageMap.SCHEDULED_MAINTENANCE_PUBLIC_NOTE] as Route
|
||||
}
|
||||
currentProject={selectedProject}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
|
||||
|
||||
|
||||
{/* Logs */}
|
||||
|
||||
<PageRoute
|
||||
@@ -748,6 +857,22 @@ const App: FunctionComponent = () => {
|
||||
}
|
||||
/>
|
||||
|
||||
<PageRoute
|
||||
path={RouteMap[
|
||||
PageMap.SETTINGS_SCHEDULED_MAINTENANCE_STATE
|
||||
]?.toString()}
|
||||
element={
|
||||
<SettingsScheduledMaintenanceState
|
||||
pageRoute={
|
||||
RouteMap[
|
||||
PageMap.SETTINGS_SCHEDULED_MAINTENANCE_STATE
|
||||
] as Route
|
||||
}
|
||||
currentProject={selectedProject}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
|
||||
<PageRoute
|
||||
path={RouteMap[
|
||||
PageMap.SETTINGS_INCIDENTS_SEVERITY
|
||||
|
||||
@@ -57,13 +57,15 @@ const DashboardNavbar: FunctionComponent<ComponentProps> = (
|
||||
></NavBarItem>
|
||||
|
||||
<NavBarItem
|
||||
title="On-Call Duty"
|
||||
title="Scheduled Maintenance"
|
||||
route={RouteUtil.populateRouteParams(
|
||||
RouteMap[PageMap.ON_CALL_DUTY] as Route
|
||||
RouteMap[PageMap.SCHEDULED_MAINTENANCE_EVENTS] as Route
|
||||
)}
|
||||
icon={IconProp.Call}
|
||||
icon={IconProp.Clock}
|
||||
></NavBarItem>
|
||||
|
||||
|
||||
|
||||
<NavBarItem
|
||||
title="Status Pages"
|
||||
icon={IconProp.CheckCircle}
|
||||
@@ -89,6 +91,13 @@ const DashboardNavbar: FunctionComponent<ComponentProps> = (
|
||||
)}
|
||||
icon={IconProp.Error}
|
||||
/>
|
||||
<NavBarMenuItem
|
||||
title="On-Call Duty"
|
||||
route={RouteUtil.populateRouteParams(
|
||||
RouteMap[PageMap.ON_CALL_DUTY] as Route
|
||||
)}
|
||||
icon={IconProp.Call}
|
||||
></NavBarMenuItem>
|
||||
</NavBarMenuColumn>
|
||||
<NavBarMenuColumn title="Advanced">
|
||||
<NavBarMenuItem
|
||||
|
||||
49
Dashboard/src/Pages/ScheduledMaintenanceEvents/Ongoing.tsx
Normal file
49
Dashboard/src/Pages/ScheduledMaintenanceEvents/Ongoing.tsx
Normal file
@@ -0,0 +1,49 @@
|
||||
import Page from 'CommonUI/src/Components/Page/Page';
|
||||
import React, { FunctionComponent, ReactElement } from 'react';
|
||||
import PageComponentProps from '../PageComponentProps';
|
||||
import RouteMap from '../../Utils/RouteMap';
|
||||
import PageMap from '../../Utils/PageMap';
|
||||
import Route from 'Common/Types/API/Route';
|
||||
import IncidentsTable from '../../Components/Incident/IncidentsTable';
|
||||
import SideMenu from './SideMenu';
|
||||
|
||||
const IncidentsPage: FunctionComponent<PageComponentProps> = (
|
||||
props: PageComponentProps
|
||||
): ReactElement => {
|
||||
return (
|
||||
<Page
|
||||
title={'Incidents'}
|
||||
sideMenu={<SideMenu project={props.currentProject || undefined} />}
|
||||
breadcrumbLinks={[
|
||||
{
|
||||
title: 'Project',
|
||||
to: RouteMap[PageMap.HOME] as Route,
|
||||
},
|
||||
{
|
||||
title: 'Incidents',
|
||||
to: RouteMap[PageMap.INCIDENTS] as Route,
|
||||
},
|
||||
{
|
||||
title: 'Unresolved Incidents',
|
||||
to: RouteMap[PageMap.UNRESOLVED_INCIDENTS] as Route,
|
||||
},
|
||||
]}
|
||||
>
|
||||
<IncidentsTable
|
||||
currentProject={props.currentProject || undefined}
|
||||
viewPageRoute={RouteMap[PageMap.INCIDENTS] as Route}
|
||||
query={{
|
||||
projectId: props.currentProject?._id,
|
||||
currentIncidentState: {
|
||||
isResolvedState: false,
|
||||
},
|
||||
}}
|
||||
noItemsMessage="Nice work! No unresolved incidents so far."
|
||||
title="Unresolved Incidents"
|
||||
description="Here is a list of all the unresolved incidents for this project."
|
||||
/>
|
||||
</Page>
|
||||
);
|
||||
};
|
||||
|
||||
export default IncidentsPage;
|
||||
@@ -0,0 +1,39 @@
|
||||
import Page from 'CommonUI/src/Components/Page/Page';
|
||||
import React, { FunctionComponent, ReactElement } from 'react';
|
||||
import PageComponentProps from '../PageComponentProps';
|
||||
import RouteMap from '../../Utils/RouteMap';
|
||||
import PageMap from '../../Utils/PageMap';
|
||||
import Route from 'Common/Types/API/Route';
|
||||
import IncidentsTable from '../../Components/Incident/IncidentsTable';
|
||||
import SideMenu from './SideMenu';
|
||||
|
||||
const IncidentsPage: FunctionComponent<PageComponentProps> = (
|
||||
props: PageComponentProps
|
||||
): ReactElement => {
|
||||
return (
|
||||
<Page
|
||||
title={'Incidents'}
|
||||
sideMenu={<SideMenu project={props.currentProject || undefined} />}
|
||||
breadcrumbLinks={[
|
||||
{
|
||||
title: 'Project',
|
||||
to: RouteMap[PageMap.HOME] as Route,
|
||||
},
|
||||
{
|
||||
title: 'Incidents',
|
||||
to: RouteMap[PageMap.INCIDENTS] as Route,
|
||||
},
|
||||
]}
|
||||
>
|
||||
<IncidentsTable
|
||||
currentProject={props.currentProject || undefined}
|
||||
viewPageRoute={props.pageRoute}
|
||||
query={{
|
||||
projectId: props.currentProject?._id,
|
||||
}}
|
||||
/>
|
||||
</Page>
|
||||
);
|
||||
};
|
||||
|
||||
export default IncidentsPage;
|
||||
56
Dashboard/src/Pages/ScheduledMaintenanceEvents/SideMenu.tsx
Normal file
56
Dashboard/src/Pages/ScheduledMaintenanceEvents/SideMenu.tsx
Normal file
@@ -0,0 +1,56 @@
|
||||
import React, { FunctionComponent, ReactElement } from 'react';
|
||||
import Route from 'Common/Types/API/Route';
|
||||
import { IconProp } from 'CommonUI/src/Components/Icon/Icon';
|
||||
import SideMenu from 'CommonUI/src/Components/SideMenu/SideMenu';
|
||||
import SideMenuItem from 'CommonUI/src/Components/SideMenu/SideMenuItem';
|
||||
import SideMenuSection from 'CommonUI/src/Components/SideMenu/SideMenuSection';
|
||||
import RouteMap, { RouteUtil } from '../../Utils/RouteMap';
|
||||
import PageMap from '../../Utils/PageMap';
|
||||
import { BadgeType } from 'CommonUI/src/Components/Badge/Badge';
|
||||
import Incident from 'Model/Models/Incident';
|
||||
import Project from 'Model/Models/Project';
|
||||
import CountModelSideMenuItem from 'CommonUI/src/Components/SideMenu/CountModelSideMenuItem';
|
||||
|
||||
export interface ComponentProps {
|
||||
project?: Project | undefined;
|
||||
}
|
||||
|
||||
const DashboardSideMenu: FunctionComponent<ComponentProps> = (
|
||||
props: ComponentProps
|
||||
): ReactElement => {
|
||||
return (
|
||||
<SideMenu>
|
||||
<SideMenuSection title="Overview">
|
||||
<SideMenuItem
|
||||
link={{
|
||||
title: 'All Incidents',
|
||||
to: RouteUtil.populateRouteParams(
|
||||
RouteMap[PageMap.INCIDENTS] as Route
|
||||
),
|
||||
}}
|
||||
icon={IconProp.List}
|
||||
/>
|
||||
|
||||
<CountModelSideMenuItem<Incident>
|
||||
link={{
|
||||
title: 'Unresolved Incidents',
|
||||
to: RouteUtil.populateRouteParams(
|
||||
RouteMap[PageMap.UNRESOLVED_INCIDENTS] as Route
|
||||
),
|
||||
}}
|
||||
icon={IconProp.Alert}
|
||||
badgeType={BadgeType.DANGER}
|
||||
modelType={Incident}
|
||||
countQuery={{
|
||||
projectId: props.project?._id,
|
||||
currentIncidentState: {
|
||||
isResolvedState: false,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</SideMenuSection>
|
||||
</SideMenu>
|
||||
);
|
||||
};
|
||||
|
||||
export default DashboardSideMenu;
|
||||
@@ -0,0 +1,66 @@
|
||||
import Route from 'Common/Types/API/Route';
|
||||
import Page from 'CommonUI/src/Components/Page/Page';
|
||||
import React, { FunctionComponent, ReactElement } from 'react';
|
||||
import PageMap from '../../../Utils/PageMap';
|
||||
import RouteMap, { RouteUtil } from '../../../Utils/RouteMap';
|
||||
import PageComponentProps from '../../PageComponentProps';
|
||||
import SideMenu from './SideMenu';
|
||||
import Navigation from 'CommonUI/src/Utils/Navigation';
|
||||
import ModelDelete from 'CommonUI/src/Components/ModelDelete/ModelDelete';
|
||||
import ObjectID from 'Common/Types/ObjectID';
|
||||
import Incident from 'Model/Models/Incident';
|
||||
|
||||
const IncidentDelete: FunctionComponent<PageComponentProps> = (
|
||||
_props: PageComponentProps
|
||||
): ReactElement => {
|
||||
const modelId: ObjectID = new ObjectID(
|
||||
Navigation.getLastParam(1)?.toString().substring(1) || ''
|
||||
);
|
||||
|
||||
return (
|
||||
<Page
|
||||
title={'Incidents'}
|
||||
breadcrumbLinks={[
|
||||
{
|
||||
title: 'Project',
|
||||
to: RouteUtil.populateRouteParams(
|
||||
RouteMap[PageMap.HOME] as Route,
|
||||
modelId
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Incidents',
|
||||
to: RouteUtil.populateRouteParams(
|
||||
RouteMap[PageMap.INCIDENTS] as Route,
|
||||
modelId
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'View Incident',
|
||||
to: RouteUtil.populateRouteParams(
|
||||
RouteMap[PageMap.INCIDENT_VIEW] as Route,
|
||||
modelId
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Delete Incident',
|
||||
to: RouteUtil.populateRouteParams(
|
||||
RouteMap[PageMap.INCIDENT_VIEW_DELETE] as Route,
|
||||
modelId
|
||||
),
|
||||
},
|
||||
]}
|
||||
sideMenu={<SideMenu modelId={modelId} />}
|
||||
>
|
||||
<ModelDelete
|
||||
modelType={Incident}
|
||||
modelId={modelId}
|
||||
onDeleteSuccess={() => {
|
||||
Navigation.navigate(RouteMap[PageMap.INCIDENTS] as Route);
|
||||
}}
|
||||
/>
|
||||
</Page>
|
||||
);
|
||||
};
|
||||
|
||||
export default IncidentDelete;
|
||||
369
Dashboard/src/Pages/ScheduledMaintenanceEvents/View/Index.tsx
Normal file
369
Dashboard/src/Pages/ScheduledMaintenanceEvents/View/Index.tsx
Normal file
@@ -0,0 +1,369 @@
|
||||
import Route from 'Common/Types/API/Route';
|
||||
import Page from 'CommonUI/src/Components/Page/Page';
|
||||
import React, { FunctionComponent, ReactElement } from 'react';
|
||||
import PageMap from '../../../Utils/PageMap';
|
||||
import RouteMap, { RouteUtil } from '../../../Utils/RouteMap';
|
||||
import PageComponentProps from '../../PageComponentProps';
|
||||
import SideMenu from './SideMenu';
|
||||
import FieldType from 'CommonUI/src/Components/Types/FieldType';
|
||||
import FormFieldSchemaType from 'CommonUI/src/Components/Forms/Types/FormFieldSchemaType';
|
||||
import { IconProp } from 'CommonUI/src/Components/Icon/Icon';
|
||||
import CardModelDetail from 'CommonUI/src/Components/ModelDetail/CardModelDetail';
|
||||
import Navigation from 'CommonUI/src/Utils/Navigation';
|
||||
import { JSONArray, JSONObject } from 'Common/Types/JSON';
|
||||
import ObjectID from 'Common/Types/ObjectID';
|
||||
import BadDataException from 'Common/Types/Exception/BadDataException';
|
||||
import Incident from 'Model/Models/Incident';
|
||||
import Color from 'Common/Types/Color';
|
||||
import Pill from 'CommonUI/src/Components/Pill/Pill';
|
||||
import MonitorsElement from '../../../Components/Monitor/Monitors';
|
||||
import Monitor from 'Model/Models/Monitor';
|
||||
import IncidentStateTimeline from 'Model/Models/IncidentStateTimeline';
|
||||
import ModelAPI, { ListResult } from 'CommonUI/src/Utils/ModelAPI/ModelAPI';
|
||||
import ChangeIncidentState, {
|
||||
IncidentType,
|
||||
} from '../../../Components/Incident/ChangeState';
|
||||
import BaseModel from 'Common/Models/BaseModel';
|
||||
import IncidentSeverity from 'Model/Models/IncidentSeverity';
|
||||
import Label from 'Model/Models/Label';
|
||||
import LabelsElement from '../../../Components/Label/Labels';
|
||||
|
||||
const IncidentView: FunctionComponent<PageComponentProps> = (
|
||||
_props: PageComponentProps
|
||||
): ReactElement => {
|
||||
const modelId: ObjectID = new ObjectID(
|
||||
Navigation.getLastParam()?.toString().substring(1) || ''
|
||||
);
|
||||
|
||||
return (
|
||||
<Page
|
||||
title={'Incidents'}
|
||||
breadcrumbLinks={[
|
||||
{
|
||||
title: 'Project',
|
||||
to: RouteUtil.populateRouteParams(
|
||||
RouteMap[PageMap.HOME] as Route,
|
||||
modelId
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Incidents',
|
||||
to: RouteUtil.populateRouteParams(
|
||||
RouteMap[PageMap.INCIDENTS] as Route,
|
||||
modelId
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'View Incident',
|
||||
to: RouteUtil.populateRouteParams(
|
||||
RouteMap[PageMap.INCIDENT_VIEW] as Route,
|
||||
modelId
|
||||
),
|
||||
},
|
||||
]}
|
||||
sideMenu={<SideMenu modelId={modelId} />}
|
||||
>
|
||||
{/* Incident View */}
|
||||
<CardModelDetail
|
||||
cardProps={{
|
||||
title: 'Incident Details',
|
||||
description: "Here's more details for this monitor.",
|
||||
icon: IconProp.Activity,
|
||||
}}
|
||||
isEditable={true}
|
||||
formFields={[
|
||||
{
|
||||
field: {
|
||||
title: true,
|
||||
},
|
||||
title: 'Incident Title',
|
||||
fieldType: FormFieldSchemaType.Text,
|
||||
required: true,
|
||||
placeholder: 'Incident Title',
|
||||
validation: {
|
||||
minLength: 2,
|
||||
},
|
||||
},
|
||||
{
|
||||
field: {
|
||||
description: true,
|
||||
},
|
||||
title: 'Description',
|
||||
fieldType: FormFieldSchemaType.LongText,
|
||||
required: true,
|
||||
placeholder: 'Description',
|
||||
},
|
||||
|
||||
{
|
||||
field: {
|
||||
incidentSeverity: true,
|
||||
},
|
||||
title: 'Incident Severity',
|
||||
description: 'What type of incident is this?',
|
||||
fieldType: FormFieldSchemaType.Dropdown,
|
||||
dropdownModal: {
|
||||
type: IncidentSeverity,
|
||||
labelField: 'name',
|
||||
valueField: '_id',
|
||||
},
|
||||
required: true,
|
||||
placeholder: 'Incident Severity',
|
||||
},
|
||||
{
|
||||
field: {
|
||||
labels: true,
|
||||
},
|
||||
title: 'Labels (Optional)',
|
||||
description:
|
||||
'Team members with access to these labels will only be able to access this resource. This is optional and an advanced feature.',
|
||||
fieldType: FormFieldSchemaType.MultiSelectDropdown,
|
||||
dropdownModal: {
|
||||
type: Label,
|
||||
labelField: 'name',
|
||||
valueField: '_id',
|
||||
},
|
||||
required: false,
|
||||
placeholder: 'Labels',
|
||||
},
|
||||
]}
|
||||
modelDetailProps={{
|
||||
onBeforeFetch: async (): Promise<JSONObject> => {
|
||||
// get ack incident.
|
||||
|
||||
const incidentTimelines: ListResult<IncidentStateTimeline> =
|
||||
await ModelAPI.getList(
|
||||
IncidentStateTimeline,
|
||||
{
|
||||
incidentId: modelId,
|
||||
},
|
||||
99,
|
||||
0,
|
||||
{
|
||||
_id: true,
|
||||
|
||||
createdAt: true,
|
||||
},
|
||||
{},
|
||||
{
|
||||
createdByUser: {
|
||||
name: true,
|
||||
email: true,
|
||||
},
|
||||
incidentState: {
|
||||
name: true,
|
||||
isResolvedState: true,
|
||||
isAcknowledgedState: true,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
return incidentTimelines;
|
||||
},
|
||||
showDetailsInNumberOfColumns: 2,
|
||||
modelType: Incident,
|
||||
id: 'model-detail-incidents',
|
||||
fields: [
|
||||
{
|
||||
field: {
|
||||
_id: true,
|
||||
},
|
||||
title: 'Incident ID',
|
||||
fieldType: FieldType.ObjectID,
|
||||
},
|
||||
{
|
||||
field: {
|
||||
title: true,
|
||||
},
|
||||
title: 'Incident Title',
|
||||
fieldType: FieldType.Text,
|
||||
},
|
||||
{
|
||||
field: {
|
||||
description: true,
|
||||
},
|
||||
title: 'Description',
|
||||
fieldType: FieldType.LongText,
|
||||
},
|
||||
{
|
||||
field: {
|
||||
currentIncidentState: {
|
||||
color: true,
|
||||
name: true,
|
||||
},
|
||||
},
|
||||
title: 'Current State',
|
||||
fieldType: FieldType.Entity,
|
||||
getElement: (item: JSONObject): ReactElement => {
|
||||
if (!item['currentIncidentState']) {
|
||||
throw new BadDataException(
|
||||
'Incident Status not found'
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Pill
|
||||
color={
|
||||
(
|
||||
item[
|
||||
'currentIncidentState'
|
||||
] as JSONObject
|
||||
)['color'] as Color
|
||||
}
|
||||
text={
|
||||
(
|
||||
item[
|
||||
'currentIncidentState'
|
||||
] as JSONObject
|
||||
)['name'] as string
|
||||
}
|
||||
/>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
field: {
|
||||
incidentSeverity: {
|
||||
color: true,
|
||||
name: true,
|
||||
},
|
||||
},
|
||||
title: 'Incident Severity',
|
||||
fieldType: FieldType.Entity,
|
||||
getElement: (item: JSONObject): ReactElement => {
|
||||
if (!item['incidentSeverity']) {
|
||||
throw new BadDataException(
|
||||
'Incident Severity not found'
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Pill
|
||||
color={
|
||||
(
|
||||
item[
|
||||
'incidentSeverity'
|
||||
] as JSONObject
|
||||
)['color'] as Color
|
||||
}
|
||||
text={
|
||||
(
|
||||
item[
|
||||
'incidentSeverity'
|
||||
] as JSONObject
|
||||
)['name'] as string
|
||||
}
|
||||
/>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
field: {
|
||||
monitors: {
|
||||
name: true,
|
||||
_id: true,
|
||||
},
|
||||
},
|
||||
title: 'Monitors Affected',
|
||||
fieldType: FieldType.Text,
|
||||
getElement: (item: JSONObject): ReactElement => {
|
||||
return (
|
||||
<MonitorsElement
|
||||
monitors={
|
||||
Monitor.fromJSON(
|
||||
(item[
|
||||
'monitors'
|
||||
] as JSONArray) || [],
|
||||
Monitor
|
||||
) as Array<Monitor>
|
||||
}
|
||||
/>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
field: {
|
||||
createdAt: true,
|
||||
},
|
||||
title: 'Created At',
|
||||
fieldType: FieldType.DateTime,
|
||||
},
|
||||
{
|
||||
field: {
|
||||
labels: {
|
||||
name: true,
|
||||
color: true,
|
||||
},
|
||||
},
|
||||
title: 'Labels',
|
||||
type: FieldType.Text,
|
||||
getElement: (item: JSONObject): ReactElement => {
|
||||
return (
|
||||
<LabelsElement
|
||||
labels={
|
||||
Label.fromJSON(
|
||||
(item['labels'] as JSONArray) ||
|
||||
[],
|
||||
Label
|
||||
) as Array<Label>
|
||||
}
|
||||
/>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'Acknowledge Incident',
|
||||
fieldType: FieldType.Text,
|
||||
getElement: (
|
||||
_item: JSONObject,
|
||||
onBeforeFetchData: JSONObject,
|
||||
fetchItems: Function
|
||||
): ReactElement => {
|
||||
return (
|
||||
<ChangeIncidentState
|
||||
incidentId={modelId}
|
||||
incidentTimeline={
|
||||
onBeforeFetchData[
|
||||
'data'
|
||||
] as Array<BaseModel>
|
||||
}
|
||||
incidentType={IncidentType.Ack}
|
||||
onActionComplete={() => {
|
||||
fetchItems();
|
||||
}}
|
||||
/>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'Resolve Incident',
|
||||
fieldType: FieldType.Text,
|
||||
getElement: (
|
||||
_item: JSONObject,
|
||||
onBeforeFetchData: JSONObject,
|
||||
fetchItems: Function
|
||||
): ReactElement => {
|
||||
return (
|
||||
<ChangeIncidentState
|
||||
incidentId={modelId}
|
||||
incidentTimeline={
|
||||
onBeforeFetchData[
|
||||
'data'
|
||||
] as Array<BaseModel>
|
||||
}
|
||||
incidentType={IncidentType.Resolve}
|
||||
onActionComplete={() => {
|
||||
fetchItems();
|
||||
}}
|
||||
/>
|
||||
);
|
||||
},
|
||||
},
|
||||
],
|
||||
modelId: modelId,
|
||||
}}
|
||||
/>
|
||||
</Page>
|
||||
);
|
||||
};
|
||||
|
||||
export default IncidentView;
|
||||
@@ -0,0 +1,155 @@
|
||||
import Route from 'Common/Types/API/Route';
|
||||
import Page from 'CommonUI/src/Components/Page/Page';
|
||||
import React, { FunctionComponent, ReactElement } from 'react';
|
||||
import PageMap from '../../../Utils/PageMap';
|
||||
import RouteMap, { RouteUtil } from '../../../Utils/RouteMap';
|
||||
import PageComponentProps from '../../PageComponentProps';
|
||||
import SideMenu from './SideMenu';
|
||||
import Navigation from 'CommonUI/src/Utils/Navigation';
|
||||
import ObjectID from 'Common/Types/ObjectID';
|
||||
import IncidentInternalNote from 'Model/Models/IncidentInternalNote';
|
||||
import ModelTable, {
|
||||
ShowTableAs,
|
||||
} from 'CommonUI/src/Components/ModelTable/ModelTable';
|
||||
import BadDataException from 'Common/Types/Exception/BadDataException';
|
||||
import { IconProp } from 'CommonUI/src/Components/Icon/Icon';
|
||||
import FormFieldSchemaType from 'CommonUI/src/Components/Forms/Types/FormFieldSchemaType';
|
||||
import FieldType from 'CommonUI/src/Components/Types/FieldType';
|
||||
import { JSONObject } from 'Common/Types/JSON';
|
||||
import UserElement from '../../../Components/User/User';
|
||||
import User from 'Model/Models/User';
|
||||
|
||||
const IncidentDelete: FunctionComponent<PageComponentProps> = (
|
||||
props: PageComponentProps
|
||||
): ReactElement => {
|
||||
const modelId: ObjectID = new ObjectID(
|
||||
Navigation.getLastParam(1)?.toString().substring(1) || ''
|
||||
);
|
||||
|
||||
return (
|
||||
<Page
|
||||
title={'Incidents'}
|
||||
breadcrumbLinks={[
|
||||
{
|
||||
title: 'Project',
|
||||
to: RouteUtil.populateRouteParams(
|
||||
RouteMap[PageMap.HOME] as Route,
|
||||
modelId
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Incidents',
|
||||
to: RouteUtil.populateRouteParams(
|
||||
RouteMap[PageMap.INCIDENTS] as Route,
|
||||
modelId
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'View Incident',
|
||||
to: RouteUtil.populateRouteParams(
|
||||
RouteMap[PageMap.INCIDENT_VIEW] as Route,
|
||||
modelId
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Private Notes',
|
||||
to: RouteUtil.populateRouteParams(
|
||||
RouteMap[PageMap.INCIDENT_INTERNAL_NOTE] as Route,
|
||||
modelId
|
||||
),
|
||||
},
|
||||
]}
|
||||
sideMenu={<SideMenu modelId={modelId} />}
|
||||
>
|
||||
<ModelTable<IncidentInternalNote>
|
||||
modelType={IncidentInternalNote}
|
||||
id="table-incident-internal-note"
|
||||
isDeleteable={true}
|
||||
isCreateable={true}
|
||||
isEditable={true}
|
||||
isViewable={false}
|
||||
query={{
|
||||
incidentId: modelId,
|
||||
projectId: props.currentProject?._id,
|
||||
}}
|
||||
onBeforeCreate={(
|
||||
item: IncidentInternalNote
|
||||
): Promise<IncidentInternalNote> => {
|
||||
if (!props.currentProject || !props.currentProject.id) {
|
||||
throw new BadDataException('Project ID cannot be null');
|
||||
}
|
||||
item.incidentId = modelId;
|
||||
item.projectId = props.currentProject.id;
|
||||
return Promise.resolve(item);
|
||||
}}
|
||||
cardProps={{
|
||||
icon: IconProp.Lock,
|
||||
title: 'Private Notes',
|
||||
description: 'Here are private notes for this incident.',
|
||||
}}
|
||||
noItemsMessage={
|
||||
'No private notes created for this incident so far.'
|
||||
}
|
||||
formFields={[
|
||||
{
|
||||
field: {
|
||||
note: true,
|
||||
},
|
||||
title: 'Private Incident Note',
|
||||
description:
|
||||
'This is in markdown. This note is private to your team members and is not visible to public.',
|
||||
fieldType: FormFieldSchemaType.Markdown,
|
||||
required: true,
|
||||
placeholder:
|
||||
'Add a private note to this incident here.',
|
||||
},
|
||||
]}
|
||||
showRefreshButton={true}
|
||||
viewPageRoute={props.pageRoute}
|
||||
showTableAs={ShowTableAs.List}
|
||||
columns={[
|
||||
{
|
||||
field: {
|
||||
note: true,
|
||||
},
|
||||
title: 'Note',
|
||||
type: FieldType.Markdown,
|
||||
},
|
||||
{
|
||||
field: {
|
||||
createdByUser: {
|
||||
name: true,
|
||||
email: true,
|
||||
},
|
||||
},
|
||||
title: 'Posted By',
|
||||
type: FieldType.Entity,
|
||||
getElement: (item: JSONObject): ReactElement => {
|
||||
if (item['createdByUser']) {
|
||||
return (
|
||||
<UserElement
|
||||
user={new User().fromJSON(
|
||||
item['createdByUser'] as JSONObject,
|
||||
User
|
||||
)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return <></>;
|
||||
},
|
||||
},
|
||||
{
|
||||
field: {
|
||||
createdAt: true,
|
||||
},
|
||||
title: 'Posted At',
|
||||
type: FieldType.DateTime,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Page>
|
||||
);
|
||||
};
|
||||
|
||||
export default IncidentDelete;
|
||||
@@ -0,0 +1,156 @@
|
||||
import Route from 'Common/Types/API/Route';
|
||||
import Page from 'CommonUI/src/Components/Page/Page';
|
||||
import React, { FunctionComponent, ReactElement } from 'react';
|
||||
import PageMap from '../../../Utils/PageMap';
|
||||
import RouteMap, { RouteUtil } from '../../../Utils/RouteMap';
|
||||
import PageComponentProps from '../../PageComponentProps';
|
||||
import SideMenu from './SideMenu';
|
||||
import Navigation from 'CommonUI/src/Utils/Navigation';
|
||||
import ObjectID from 'Common/Types/ObjectID';
|
||||
import IncidentPublicNote from 'Model/Models/IncidentPublicNote';
|
||||
import ModelTable, {
|
||||
ShowTableAs,
|
||||
} from 'CommonUI/src/Components/ModelTable/ModelTable';
|
||||
import BadDataException from 'Common/Types/Exception/BadDataException';
|
||||
import { IconProp } from 'CommonUI/src/Components/Icon/Icon';
|
||||
import FormFieldSchemaType from 'CommonUI/src/Components/Forms/Types/FormFieldSchemaType';
|
||||
import FieldType from 'CommonUI/src/Components/Types/FieldType';
|
||||
import { JSONObject } from 'Common/Types/JSON';
|
||||
import UserElement from '../../../Components/User/User';
|
||||
import User from 'Model/Models/User';
|
||||
|
||||
const PublicNote: FunctionComponent<PageComponentProps> = (
|
||||
props: PageComponentProps
|
||||
): ReactElement => {
|
||||
const modelId: ObjectID = new ObjectID(
|
||||
Navigation.getLastParam(1)?.toString().substring(1) || ''
|
||||
);
|
||||
|
||||
return (
|
||||
<Page
|
||||
title={'Incidents'}
|
||||
breadcrumbLinks={[
|
||||
{
|
||||
title: 'Project',
|
||||
to: RouteUtil.populateRouteParams(
|
||||
RouteMap[PageMap.HOME] as Route,
|
||||
modelId
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Incidents',
|
||||
to: RouteUtil.populateRouteParams(
|
||||
RouteMap[PageMap.INCIDENTS] as Route,
|
||||
modelId
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'View Incident',
|
||||
to: RouteUtil.populateRouteParams(
|
||||
RouteMap[PageMap.INCIDENT_VIEW] as Route,
|
||||
modelId
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Internal Notes',
|
||||
to: RouteUtil.populateRouteParams(
|
||||
RouteMap[PageMap.INCIDENT_INTERNAL_NOTE] as Route,
|
||||
modelId
|
||||
),
|
||||
},
|
||||
]}
|
||||
sideMenu={<SideMenu modelId={modelId} />}
|
||||
>
|
||||
<ModelTable<IncidentPublicNote>
|
||||
modelType={IncidentPublicNote}
|
||||
id="table-incident-internal-note"
|
||||
isDeleteable={true}
|
||||
isCreateable={true}
|
||||
isEditable={true}
|
||||
isViewable={false}
|
||||
query={{
|
||||
incidentId: modelId,
|
||||
projectId: props.currentProject?._id,
|
||||
}}
|
||||
onBeforeCreate={(
|
||||
item: IncidentPublicNote
|
||||
): Promise<IncidentPublicNote> => {
|
||||
if (!props.currentProject || !props.currentProject.id) {
|
||||
throw new BadDataException('Project ID cannot be null');
|
||||
}
|
||||
item.incidentId = modelId;
|
||||
item.projectId = props.currentProject.id;
|
||||
return Promise.resolve(item);
|
||||
}}
|
||||
cardProps={{
|
||||
icon: IconProp.User,
|
||||
title: 'Public Notes',
|
||||
description:
|
||||
'Here are public notes for this incident. This will show up on the status page.',
|
||||
}}
|
||||
noItemsMessage={
|
||||
'No public notes created for this incident so far.'
|
||||
}
|
||||
formFields={[
|
||||
{
|
||||
field: {
|
||||
note: true,
|
||||
},
|
||||
title: 'Public Incident Note',
|
||||
description:
|
||||
'This is in markdown. This note is private to your team members and is not visible to public.',
|
||||
fieldType: FormFieldSchemaType.Markdown,
|
||||
required: true,
|
||||
placeholder:
|
||||
'Add a private note to this incident here.',
|
||||
},
|
||||
]}
|
||||
showRefreshButton={true}
|
||||
viewPageRoute={props.pageRoute}
|
||||
showTableAs={ShowTableAs.List}
|
||||
columns={[
|
||||
{
|
||||
field: {
|
||||
note: true,
|
||||
},
|
||||
title: 'Note',
|
||||
type: FieldType.Markdown,
|
||||
},
|
||||
{
|
||||
field: {
|
||||
createdByUser: {
|
||||
name: true,
|
||||
email: true,
|
||||
},
|
||||
},
|
||||
title: 'Posted By',
|
||||
type: FieldType.Entity,
|
||||
getElement: (item: JSONObject): ReactElement => {
|
||||
if (item['createdByUser']) {
|
||||
return (
|
||||
<UserElement
|
||||
user={new User().fromJSON(
|
||||
item['createdByUser'] as JSONObject,
|
||||
User
|
||||
)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return <></>;
|
||||
},
|
||||
},
|
||||
{
|
||||
field: {
|
||||
createdAt: true,
|
||||
},
|
||||
title: 'Posted At',
|
||||
type: FieldType.DateTime,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Page>
|
||||
);
|
||||
};
|
||||
|
||||
export default PublicNote;
|
||||
@@ -0,0 +1,85 @@
|
||||
import React, { FunctionComponent, ReactElement } from 'react';
|
||||
import Route from 'Common/Types/API/Route';
|
||||
import { IconProp } from 'CommonUI/src/Components/Icon/Icon';
|
||||
import SideMenu from 'CommonUI/src/Components/SideMenu/SideMenu';
|
||||
import SideMenuItem from 'CommonUI/src/Components/SideMenu/SideMenuItem';
|
||||
import SideMenuSection from 'CommonUI/src/Components/SideMenu/SideMenuSection';
|
||||
import RouteMap, { RouteUtil } from '../../../Utils/RouteMap';
|
||||
import PageMap from '../../../Utils/PageMap';
|
||||
import ObjectID from 'Common/Types/ObjectID';
|
||||
|
||||
export interface ComponentProps {
|
||||
modelId: ObjectID;
|
||||
}
|
||||
|
||||
const DashboardSideMenu: FunctionComponent<ComponentProps> = (
|
||||
props: ComponentProps
|
||||
): ReactElement => {
|
||||
return (
|
||||
<SideMenu>
|
||||
<SideMenuSection title="Basic">
|
||||
<SideMenuItem
|
||||
link={{
|
||||
title: 'Overview',
|
||||
to: RouteUtil.populateRouteParams(
|
||||
RouteMap[PageMap.INCIDENT_VIEW] as Route,
|
||||
props.modelId
|
||||
),
|
||||
}}
|
||||
icon={IconProp.Info}
|
||||
/>
|
||||
<SideMenuItem
|
||||
link={{
|
||||
title: 'State Timeline',
|
||||
to: RouteUtil.populateRouteParams(
|
||||
RouteMap[
|
||||
PageMap.INCIDENT_VIEW_STATE_TIMELINE
|
||||
] as Route,
|
||||
props.modelId
|
||||
),
|
||||
}}
|
||||
icon={IconProp.List}
|
||||
/>
|
||||
</SideMenuSection>
|
||||
|
||||
<SideMenuSection title="Incident Notes">
|
||||
<SideMenuItem
|
||||
link={{
|
||||
title: 'Private Notes',
|
||||
to: RouteUtil.populateRouteParams(
|
||||
RouteMap[PageMap.INCIDENT_INTERNAL_NOTE] as Route,
|
||||
props.modelId
|
||||
),
|
||||
}}
|
||||
icon={IconProp.Lock}
|
||||
/>
|
||||
<SideMenuItem
|
||||
link={{
|
||||
title: 'Public Notes',
|
||||
to: RouteUtil.populateRouteParams(
|
||||
RouteMap[PageMap.INCIDENT_PUBLIC_NOTE] as Route,
|
||||
props.modelId
|
||||
),
|
||||
}}
|
||||
icon={IconProp.Public}
|
||||
/>
|
||||
</SideMenuSection>
|
||||
|
||||
<SideMenuSection title="Advanced">
|
||||
<SideMenuItem
|
||||
link={{
|
||||
title: 'Delete Incident',
|
||||
to: RouteUtil.populateRouteParams(
|
||||
RouteMap[PageMap.INCIDENT_VIEW_DELETE] as Route,
|
||||
props.modelId
|
||||
),
|
||||
}}
|
||||
icon={IconProp.Trash}
|
||||
className="danger-on-hover"
|
||||
/>
|
||||
</SideMenuSection>
|
||||
</SideMenu>
|
||||
);
|
||||
};
|
||||
|
||||
export default DashboardSideMenu;
|
||||
@@ -0,0 +1,158 @@
|
||||
import Route from 'Common/Types/API/Route';
|
||||
import Page from 'CommonUI/src/Components/Page/Page';
|
||||
import React, { FunctionComponent, ReactElement } from 'react';
|
||||
import PageMap from '../../../Utils/PageMap';
|
||||
import RouteMap, { RouteUtil } from '../../../Utils/RouteMap';
|
||||
import PageComponentProps from '../../PageComponentProps';
|
||||
import SideMenu from './SideMenu';
|
||||
import Navigation from 'CommonUI/src/Utils/Navigation';
|
||||
import ObjectID from 'Common/Types/ObjectID';
|
||||
import ModelTable from 'CommonUI/src/Components/ModelTable/ModelTable';
|
||||
import IncidentStateTimeline from 'Model/Models/IncidentStateTimeline';
|
||||
import { IconProp } from 'CommonUI/src/Components/Icon/Icon';
|
||||
import BadDataException from 'Common/Types/Exception/BadDataException';
|
||||
import FormFieldSchemaType from 'CommonUI/src/Components/Forms/Types/FormFieldSchemaType';
|
||||
import IncidentState from 'Model/Models/IncidentState';
|
||||
import FieldType from 'CommonUI/src/Components/Types/FieldType';
|
||||
import { JSONObject } from 'Common/Types/JSON';
|
||||
import Color from 'Common/Types/Color';
|
||||
import Pill from 'CommonUI/src/Components/Pill/Pill';
|
||||
|
||||
const IncidentDelete: FunctionComponent<PageComponentProps> = (
|
||||
props: PageComponentProps
|
||||
): ReactElement => {
|
||||
const modelId: ObjectID = new ObjectID(
|
||||
Navigation.getLastParam(1)?.toString().substring(1) || ''
|
||||
);
|
||||
|
||||
return (
|
||||
<Page
|
||||
title={'Incidents'}
|
||||
breadcrumbLinks={[
|
||||
{
|
||||
title: 'Project',
|
||||
to: RouteUtil.populateRouteParams(
|
||||
RouteMap[PageMap.HOME] as Route,
|
||||
modelId
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Incidents',
|
||||
to: RouteUtil.populateRouteParams(
|
||||
RouteMap[PageMap.INCIDENTS] as Route,
|
||||
modelId
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'View Incident',
|
||||
to: RouteUtil.populateRouteParams(
|
||||
RouteMap[PageMap.INCIDENT_VIEW] as Route,
|
||||
modelId
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Status Timeline',
|
||||
to: RouteUtil.populateRouteParams(
|
||||
RouteMap[PageMap.INCIDENT_VIEW_STATE_TIMELINE] as Route,
|
||||
modelId
|
||||
),
|
||||
},
|
||||
]}
|
||||
sideMenu={<SideMenu modelId={modelId} />}
|
||||
>
|
||||
<ModelTable<IncidentStateTimeline>
|
||||
modelType={IncidentStateTimeline}
|
||||
id="table-incident-status-timeline"
|
||||
isDeleteable={true}
|
||||
isCreateable={true}
|
||||
isViewable={false}
|
||||
query={{
|
||||
incidentId: modelId,
|
||||
projectId: props.currentProject?._id,
|
||||
}}
|
||||
onBeforeCreate={(
|
||||
item: IncidentStateTimeline
|
||||
): Promise<IncidentStateTimeline> => {
|
||||
if (!props.currentProject || !props.currentProject.id) {
|
||||
throw new BadDataException('Project ID cannot be null');
|
||||
}
|
||||
item.incidentId = modelId;
|
||||
item.projectId = props.currentProject.id;
|
||||
return Promise.resolve(item);
|
||||
}}
|
||||
cardProps={{
|
||||
icon: IconProp.List,
|
||||
title: 'Status Timeline',
|
||||
description:
|
||||
'Here is the status timeline for this incident',
|
||||
}}
|
||||
noItemsMessage={
|
||||
'No status timeline created for this incident so far.'
|
||||
}
|
||||
formFields={[
|
||||
{
|
||||
field: {
|
||||
incidentState: true,
|
||||
},
|
||||
title: 'Incident Status',
|
||||
fieldType: FormFieldSchemaType.Dropdown,
|
||||
required: true,
|
||||
placeholder: 'Incident Status',
|
||||
dropdownModal: {
|
||||
type: IncidentState,
|
||||
labelField: 'name',
|
||||
valueField: '_id',
|
||||
},
|
||||
},
|
||||
]}
|
||||
showRefreshButton={true}
|
||||
showFilterButton={true}
|
||||
viewPageRoute={props.pageRoute}
|
||||
columns={[
|
||||
{
|
||||
field: {
|
||||
incidentState: {
|
||||
name: true,
|
||||
color: true,
|
||||
},
|
||||
},
|
||||
title: 'Incident Status',
|
||||
type: FieldType.Text,
|
||||
isFilterable: true,
|
||||
getElement: (item: JSONObject): ReactElement => {
|
||||
if (!item['incidentState']) {
|
||||
throw new BadDataException(
|
||||
'Incident Status not found'
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Pill
|
||||
color={
|
||||
(item['incidentState'] as JSONObject)[
|
||||
'color'
|
||||
] as Color
|
||||
}
|
||||
text={
|
||||
(item['incidentState'] as JSONObject)[
|
||||
'name'
|
||||
] as string
|
||||
}
|
||||
/>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
field: {
|
||||
createdAt: true,
|
||||
},
|
||||
title: 'Reported At',
|
||||
type: FieldType.DateTime,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Page>
|
||||
);
|
||||
};
|
||||
|
||||
export default IncidentDelete;
|
||||
158
Dashboard/src/Pages/Settings/ScheduledMaintenanceState.tsx
Normal file
158
Dashboard/src/Pages/Settings/ScheduledMaintenanceState.tsx
Normal file
@@ -0,0 +1,158 @@
|
||||
import Route from 'Common/Types/API/Route';
|
||||
import Page from 'CommonUI/src/Components/Page/Page';
|
||||
import React, { FunctionComponent, ReactElement } from 'react';
|
||||
import PageMap from '../../Utils/PageMap';
|
||||
import RouteMap from '../../Utils/RouteMap';
|
||||
import PageComponentProps from '../PageComponentProps';
|
||||
import DashboardSideMenu from './SideMenu';
|
||||
import ModelTable, {
|
||||
ShowTableAs,
|
||||
} from 'CommonUI/src/Components/ModelTable/ModelTable';
|
||||
import IncidentState from 'Model/Models/IncidentState';
|
||||
import FormFieldSchemaType from 'CommonUI/src/Components/Forms/Types/FormFieldSchemaType';
|
||||
import { IconProp } from 'CommonUI/src/Components/Icon/Icon';
|
||||
import FieldType from 'CommonUI/src/Components/Types/FieldType';
|
||||
import { JSONObject } from 'Common/Types/JSON';
|
||||
import Pill from 'CommonUI/src/Components/Pill/Pill';
|
||||
import Color from 'Common/Types/Color';
|
||||
import SortOrder from 'Common/Types/Database/SortOrder';
|
||||
import BadDataException from 'Common/Types/Exception/BadDataException';
|
||||
|
||||
const IncidentsPage: FunctionComponent<PageComponentProps> = (
|
||||
props: PageComponentProps
|
||||
): ReactElement => {
|
||||
return (
|
||||
<Page
|
||||
title={'Project Settings'}
|
||||
breadcrumbLinks={[
|
||||
{
|
||||
title: 'Project',
|
||||
to: RouteMap[PageMap.HOME] as Route,
|
||||
},
|
||||
{
|
||||
title: 'Settings',
|
||||
to: RouteMap[PageMap.SETTINGS] as Route,
|
||||
},
|
||||
{
|
||||
title: 'Incidents',
|
||||
to: RouteMap[PageMap.SETTINGS_INCIDENTS_STATE] as Route,
|
||||
},
|
||||
]}
|
||||
sideMenu={<DashboardSideMenu />}
|
||||
>
|
||||
<ModelTable<IncidentState>
|
||||
modelType={IncidentState}
|
||||
id="incident-state-table"
|
||||
isDeleteable={true}
|
||||
isEditable={true}
|
||||
isCreateable={true}
|
||||
cardProps={{
|
||||
icon: IconProp.Disc,
|
||||
title: 'Incident State',
|
||||
description:
|
||||
'Incidents have multiple states like - created, acknowledged and resolved. You can more states help you manage incidents here.',
|
||||
}}
|
||||
sortBy="order"
|
||||
sortOrder={SortOrder.Ascending}
|
||||
onBeforeDelete={(item: IncidentState) => {
|
||||
if (item.isCreatedState) {
|
||||
throw new BadDataException(
|
||||
'This incident cannot be deleted because its the created incident state of for this project. Created, Acknowledged, Resolved incident states cannot be deleted.'
|
||||
);
|
||||
}
|
||||
|
||||
if (item.isAcknowledgedState) {
|
||||
throw new BadDataException(
|
||||
'This incident cannot be deleted because its the acknowledged incident state of for this project. Created, Acknowledged, Resolved incident states cannot be deleted.'
|
||||
);
|
||||
}
|
||||
|
||||
if (item.isResolvedState) {
|
||||
throw new BadDataException(
|
||||
'This incident cannot be deleted because its the resolved incident state of for this project. Created, Acknowledged, Resolved incident states cannot be deleted.'
|
||||
);
|
||||
}
|
||||
|
||||
return item;
|
||||
}}
|
||||
selectMoreFields={{
|
||||
color: true,
|
||||
isCreatedState: true,
|
||||
isAcknowledgedState: true,
|
||||
isResolvedState: true,
|
||||
order: true,
|
||||
}}
|
||||
columns={[
|
||||
{
|
||||
field: {
|
||||
name: true,
|
||||
},
|
||||
title: 'Name',
|
||||
type: FieldType.Text,
|
||||
getElement: (item: JSONObject): ReactElement => {
|
||||
return (
|
||||
<Pill
|
||||
color={item['color'] as Color}
|
||||
text={item['name'] as string}
|
||||
/>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
field: {
|
||||
description: true,
|
||||
},
|
||||
title: 'Description',
|
||||
type: FieldType.Text,
|
||||
},
|
||||
]}
|
||||
noItemsMessage={'No incident state found.'}
|
||||
viewPageRoute={props.pageRoute}
|
||||
formFields={[
|
||||
{
|
||||
field: {
|
||||
name: true,
|
||||
},
|
||||
title: 'Name',
|
||||
fieldType: FormFieldSchemaType.Text,
|
||||
required: true,
|
||||
placeholder: 'Investigating',
|
||||
validation: {
|
||||
minLength: 2,
|
||||
},
|
||||
},
|
||||
{
|
||||
field: {
|
||||
description: true,
|
||||
},
|
||||
title: 'Description',
|
||||
fieldType: FormFieldSchemaType.LongText,
|
||||
required: true,
|
||||
placeholder:
|
||||
'This incident state happens when the incident is investigated',
|
||||
},
|
||||
{
|
||||
field: {
|
||||
color: true,
|
||||
},
|
||||
title: 'Color',
|
||||
fieldType: FormFieldSchemaType.Color,
|
||||
required: true,
|
||||
placeholder:
|
||||
'Please select color for this incident state.',
|
||||
},
|
||||
]}
|
||||
showRefreshButton={true}
|
||||
showTableAs={ShowTableAs.OrderedStatesList}
|
||||
orderedStatesListProps={{
|
||||
titleField: 'name',
|
||||
descriptionField: 'description',
|
||||
orderField: 'order',
|
||||
shouldAddItemInTheEnd: true,
|
||||
}}
|
||||
/>
|
||||
</Page>
|
||||
);
|
||||
};
|
||||
|
||||
export default IncidentsPage;
|
||||
@@ -16,6 +16,14 @@ enum PageMap {
|
||||
INCIDENT_INTERNAL_NOTE = 'INCIDENT_INTERNAL_NOTE',
|
||||
INCIDENT_PUBLIC_NOTE = 'INCIDENT_PUBLIC_NOTE',
|
||||
|
||||
SCHEDULED_MAINTENANCE_EVENTS = 'SCHEDULED_MAINTENANCE_EVENTS',
|
||||
ONGOING_SCHEDULED_MAINTENANCE_EVENTS = 'ONGOING_SCHEDULED_MAINTENANCE_EVENTS',
|
||||
SCHEDULED_MAINTENANCE_VIEW = 'SCHEDULED_MAINTENANCE_VIEW',
|
||||
SCHEDULED_MAINTENANCE_VIEW_DELETE = 'SCHEDULED_MAINTENANCE_VIEW_DELETE',
|
||||
SCHEDULED_MAINTENANCE_VIEW_STATE_TIMELINE = 'SCHEDULED_MAINTENANCE_VIEW_STATE_TIMELINE',
|
||||
SCHEDULED_MAINTENANCE_INTERNAL_NOTE = 'SCHEDULED_MAINTENANCE_INTERNAL_NOTE',
|
||||
SCHEDULED_MAINTENANCE_PUBLIC_NOTE = 'SCHEDULED_MAINTENANCE_PUBLIC_NOTE',
|
||||
|
||||
MONITORS = 'MONITORS',
|
||||
MONITORS_INOPERATIONAL = 'MONITORS_INOPERATIONAL',
|
||||
MONITOR_VIEW = 'MONITOR_VIEW',
|
||||
@@ -64,8 +72,14 @@ enum PageMap {
|
||||
// Resource settings.
|
||||
SETTINGS_INCIDENTS_STATE = 'SETTINGS_INCIDENTS_STATE',
|
||||
SETTINGS_INCIDENTS_SEVERITY = 'SETTINGS_INCIDENTS_SEVERITY',
|
||||
|
||||
|
||||
// monitors
|
||||
SETTINGS_MONITORS_STATUS = 'SETTINGS_MONITORS_STATUS',
|
||||
|
||||
// Scheduled Events
|
||||
SETTINGS_SCHEDULED_MAINTENANCE_STATE = 'SETTINGS_SCHEDULED_MAINTENANCE_STATE',
|
||||
|
||||
// Labels.
|
||||
SETTINGS_LABELS = 'SETTINGS_LABELS',
|
||||
|
||||
|
||||
@@ -18,6 +18,10 @@ const RouteMap: Dictionary<Route> = {
|
||||
`/dashboard/${RouteParams.ProjectID}/home/monitors-inoperational`
|
||||
),
|
||||
|
||||
[PageMap.MONITOR_VIEW_INCIDENTS]: new Route(
|
||||
`/dashboard/${RouteParams.ProjectID}/monitor/${RouteParams.ModelID}/incidents`
|
||||
),
|
||||
|
||||
[PageMap.INCIDENTS]: new Route(
|
||||
`/dashboard/${RouteParams.ProjectID}/incidents`
|
||||
),
|
||||
@@ -34,9 +38,7 @@ const RouteMap: Dictionary<Route> = {
|
||||
`/dashboard/${RouteParams.ProjectID}/incidents/${RouteParams.ModelID}/state-timeline`
|
||||
),
|
||||
|
||||
[PageMap.MONITOR_VIEW_INCIDENTS]: new Route(
|
||||
`/dashboard/${RouteParams.ProjectID}/incidents/${RouteParams.ModelID}/incidents`
|
||||
),
|
||||
|
||||
|
||||
[PageMap.INCIDENT_VIEW_DELETE]: new Route(
|
||||
`/dashboard/${RouteParams.ProjectID}/incidents/${RouteParams.ModelID}/delete`
|
||||
@@ -50,6 +52,39 @@ const RouteMap: Dictionary<Route> = {
|
||||
`/dashboard/${RouteParams.ProjectID}/incidents/${RouteParams.ModelID}/public-notes`
|
||||
),
|
||||
|
||||
|
||||
|
||||
[PageMap.SCHEDULED_MAINTENANCE_EVENTS]: new Route(
|
||||
`/dashboard/${RouteParams.ProjectID}/scheduled-maintenance-events`
|
||||
),
|
||||
|
||||
[PageMap.ONGOING_SCHEDULED_MAINTENANCE_EVENTS]: new Route(
|
||||
`/dashboard/${RouteParams.ProjectID}/scheduled-maintenance-events/ongoing`
|
||||
),
|
||||
|
||||
[PageMap.SCHEDULED_MAINTENANCE_VIEW]: new Route(
|
||||
`/dashboard/${RouteParams.ProjectID}/scheduled-maintenance-events/${RouteParams.ModelID}`
|
||||
),
|
||||
|
||||
[PageMap.SCHEDULED_MAINTENANCE_VIEW_STATE_TIMELINE]: new Route(
|
||||
`/dashboard/${RouteParams.ProjectID}/scheduled-maintenance-events/${RouteParams.ModelID}/state-timeline`
|
||||
),
|
||||
|
||||
|
||||
|
||||
[PageMap.SCHEDULED_MAINTENANCE_VIEW_DELETE]: new Route(
|
||||
`/dashboard/${RouteParams.ProjectID}/scheduled-maintenance-events/${RouteParams.ModelID}/delete`
|
||||
),
|
||||
|
||||
[PageMap.SCHEDULED_MAINTENANCE_INTERNAL_NOTE]: new Route(
|
||||
`/dashboard/${RouteParams.ProjectID}/scheduled-maintenance-events/${RouteParams.ModelID}/internal-notes`
|
||||
),
|
||||
|
||||
[PageMap.SCHEDULED_MAINTENANCE_PUBLIC_NOTE]: new Route(
|
||||
`/dashboard/${RouteParams.ProjectID}/scheduled-maintenance-events/${RouteParams.ModelID}/public-notes`
|
||||
),
|
||||
|
||||
|
||||
[PageMap.STATUS_PAGES]: new Route(
|
||||
`/dashboard/${RouteParams.ProjectID}/status-pages`
|
||||
),
|
||||
@@ -186,6 +221,10 @@ const RouteMap: Dictionary<Route> = {
|
||||
`/dashboard/${RouteParams.ProjectID}/settings/incidents-state`
|
||||
),
|
||||
|
||||
[PageMap.SETTINGS_SCHEDULED_MAINTENANCE_STATE]: new Route(
|
||||
`/dashboard/${RouteParams.ProjectID}/settings/scheduled-maintenance-state`
|
||||
),
|
||||
|
||||
[PageMap.SETTINGS_INCIDENTS_SEVERITY]: new Route(
|
||||
`/dashboard/${RouteParams.ProjectID}/settings/incidents-severity`
|
||||
),
|
||||
|
||||
@@ -111,6 +111,32 @@ import MonitorTimelineStatusService, {
|
||||
Service as MonitorTimelineStatusServiceType,
|
||||
} from 'CommonServer/Services/MonitorStatusTimelineService';
|
||||
|
||||
import ScheduledMaintenanceState from 'Model/Models/ScheduledMaintenanceState';
|
||||
import ScheduledMaintenanceStateService, {
|
||||
Service as ScheduledMaintenanceStateServiceType,
|
||||
} from 'CommonServer/Services/ScheduledMaintenanceStateService';
|
||||
|
||||
import ScheduledMaintenance from 'Model/Models/ScheduledMaintenance';
|
||||
import ScheduledMaintenanceService, {
|
||||
Service as ScheduledMaintenanceServiceType,
|
||||
} from 'CommonServer/Services/ScheduledMaintenanceService';
|
||||
|
||||
import ScheduledMaintenanceStateTimeline from 'Model/Models/ScheduledMaintenanceStateTimeline';
|
||||
import ScheduledMaintenanceStateTimelineService, {
|
||||
Service as ScheduledMaintenanceStateTimelineServiceType,
|
||||
} from 'CommonServer/Services/ScheduledMaintenanceStateTimelineService';
|
||||
|
||||
import ScheduledMaintenanceInternalNote from 'Model/Models/ScheduledMaintenanceInternalNote';
|
||||
import ScheduledMaintenanceInternalNoteService, {
|
||||
Service as ScheduledMaintenanceInternalNoteServiceType,
|
||||
} from 'CommonServer/Services/ScheduledMaintenanceInternalNoteService';
|
||||
|
||||
import ScheduledMaintenancePublicNote from 'Model/Models/ScheduledMaintenancePublicNote';
|
||||
import ScheduledMaintenancePublicNoteService, {
|
||||
Service as ScheduledMaintenancePublicNoteServiceType,
|
||||
} from 'CommonServer/Services/ScheduledMaintenancePublicNoteService';
|
||||
|
||||
|
||||
import IncidentState from 'Model/Models/IncidentState';
|
||||
import IncidentStateService, {
|
||||
Service as IncidentStateServiceType,
|
||||
@@ -136,6 +162,7 @@ import IncidentPublicNoteService, {
|
||||
Service as IncidentPublicNoteServiceType,
|
||||
} from 'CommonServer/Services/IncidentPublicNoteService';
|
||||
|
||||
|
||||
import Domain from 'Model/Models/Domain';
|
||||
import DomainService, {
|
||||
Service as DomainServiceType,
|
||||
@@ -212,6 +239,13 @@ app.use(
|
||||
).getRouter()
|
||||
);
|
||||
|
||||
app.use(
|
||||
new BaseAPI<ScheduledMaintenanceState, ScheduledMaintenanceStateServiceType>(
|
||||
ScheduledMaintenanceState,
|
||||
ScheduledMaintenanceStateService
|
||||
).getRouter()
|
||||
);
|
||||
|
||||
app.use(
|
||||
new BaseAPI<StatusPageResource, StatusPageResourceServiceType>(
|
||||
StatusPageResource,
|
||||
@@ -244,6 +278,13 @@ app.use(
|
||||
).getRouter()
|
||||
);
|
||||
|
||||
app.use(
|
||||
new BaseAPI<ScheduledMaintenanceStateTimeline, ScheduledMaintenanceStateTimelineServiceType>(
|
||||
ScheduledMaintenanceStateTimeline,
|
||||
ScheduledMaintenanceStateTimelineService
|
||||
).getRouter()
|
||||
);
|
||||
|
||||
app.use(
|
||||
new BaseAPI<StatusPageSubscriber, StatusPageSubscriberServiceType>(
|
||||
StatusPageSubscriber,
|
||||
@@ -258,6 +299,13 @@ app.use(
|
||||
).getRouter()
|
||||
);
|
||||
|
||||
app.use(
|
||||
new BaseAPI<ScheduledMaintenance, ScheduledMaintenanceServiceType>(
|
||||
ScheduledMaintenance,
|
||||
ScheduledMaintenanceService
|
||||
).getRouter()
|
||||
);
|
||||
|
||||
app.use(
|
||||
new BaseAPI<ApiKey, ApiKeyServiceType>(ApiKey, ApiKeyService).getRouter()
|
||||
);
|
||||
@@ -335,6 +383,21 @@ app.use(
|
||||
).getRouter()
|
||||
);
|
||||
|
||||
app.use(
|
||||
new BaseAPI<ScheduledMaintenancePublicNote, ScheduledMaintenancePublicNoteServiceType>(
|
||||
ScheduledMaintenancePublicNote,
|
||||
ScheduledMaintenancePublicNoteService
|
||||
).getRouter()
|
||||
);
|
||||
|
||||
app.use(
|
||||
new BaseAPI<ScheduledMaintenanceInternalNote, ScheduledMaintenanceInternalNoteServiceType>(
|
||||
ScheduledMaintenanceInternalNote,
|
||||
ScheduledMaintenanceInternalNoteService
|
||||
).getRouter()
|
||||
);
|
||||
|
||||
|
||||
app.use(
|
||||
new BaseAPI<IncidentPublicNote, IncidentPublicNoteServiceType>(
|
||||
IncidentPublicNote,
|
||||
|
||||
Reference in New Issue
Block a user