From 722fe30c8fe9bff90d2cc322443c279d5eb3279c Mon Sep 17 00:00:00 2001 From: Simon Larsen Date: Mon, 27 Jan 2025 17:37:08 +0000 Subject: [PATCH] feat: implement FetchMonitors, FetchMonitorStatuses, and FetchOnCallPolicies components; update Field interface for summary element handling --- .../1737997557974-MigrationName.ts | 19 ++- .../Postgres/SchemaMigrations/Index.ts | 2 +- Common/UI/Components/Forms/BasicForm.tsx | 6 +- Common/UI/Components/Forms/FormSummary.tsx | 77 +++++----- Common/UI/Components/Forms/Types/Field.ts | 2 +- .../FetchIncidentSeverity.tsx | 71 +++++++++ .../IncidentSeveritiesElement.tsx | 31 ++++ .../IncidentSeverityElement.tsx | 23 +++ .../src/Components/Label/FetchLabels.tsx | 89 +++++------ .../src/Components/Monitor/FetchMonitors.tsx | 71 +++++++++ .../MonitorStatus/FetchMonitorStatuses.tsx | 71 +++++++++ .../OnCallPolicy/FetchOnCallPolicies.tsx | 71 +++++++++ Dashboard/src/Components/Team/FetchTeams.tsx | 93 ++++++------ Dashboard/src/Components/User/FetchUsers.tsx | 91 +++++------ Dashboard/src/Pages/Incidents/Create.tsx | 143 +++++++++++++++++- 15 files changed, 659 insertions(+), 201 deletions(-) create mode 100644 Dashboard/src/Components/IncidentSeverity/FetchIncidentSeverity.tsx create mode 100644 Dashboard/src/Components/IncidentSeverity/IncidentSeveritiesElement.tsx create mode 100644 Dashboard/src/Components/IncidentSeverity/IncidentSeverityElement.tsx create mode 100644 Dashboard/src/Components/Monitor/FetchMonitors.tsx create mode 100644 Dashboard/src/Components/MonitorStatus/FetchMonitorStatuses.tsx create mode 100644 Dashboard/src/Components/OnCallPolicy/FetchOnCallPolicies.tsx diff --git a/Common/Server/Infrastructure/Postgres/SchemaMigrations/1737997557974-MigrationName.ts b/Common/Server/Infrastructure/Postgres/SchemaMigrations/1737997557974-MigrationName.ts index 8cb65ca9456..5b86e1ab110 100644 --- a/Common/Server/Infrastructure/Postgres/SchemaMigrations/1737997557974-MigrationName.ts +++ b/Common/Server/Infrastructure/Postgres/SchemaMigrations/1737997557974-MigrationName.ts @@ -1,14 +1,17 @@ import { MigrationInterface, QueryRunner } from "typeorm"; export class MigrationName1737997557974 implements MigrationInterface { - public name = 'MigrationName1737997557974' + public name = "MigrationName1737997557974"; - public async up(queryRunner: QueryRunner): Promise { - await queryRunner.query(`CREATE INDEX "IDX_4d5e62631b2b63aaecb00950ef" ON "MonitorTest" ("isInQueue") `); - } - - public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query(`DROP INDEX "public"."IDX_4d5e62631b2b63aaecb00950ef"`); - } + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `CREATE INDEX "IDX_4d5e62631b2b63aaecb00950ef" ON "MonitorTest" ("isInQueue") `, + ); + } + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `DROP INDEX "public"."IDX_4d5e62631b2b63aaecb00950ef"`, + ); + } } diff --git a/Common/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts b/Common/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts index 6636fc3d31e..fdb3402d8d0 100644 --- a/Common/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +++ b/Common/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts @@ -201,5 +201,5 @@ export default [ MigrationName1737141420441, MigrationName1737713529424, MigrationName1737715240684, - MigrationName1737997557974 + MigrationName1737997557974, ]; diff --git a/Common/UI/Components/Forms/BasicForm.tsx b/Common/UI/Components/Forms/BasicForm.tsx index e6543929368..73539771749 100644 --- a/Common/UI/Components/Forms/BasicForm.tsx +++ b/Common/UI/Components/Forms/BasicForm.tsx @@ -37,7 +37,6 @@ import React, { } from "react"; import useAsyncEffect from "use-async-effect"; - export type FormProps = FormikProps; export type FormErrors = FormikErrors; @@ -633,7 +632,10 @@ const BasicForm: ForwardRefExoticComponent = forwardRef( {/* If Summary, show Model detail */} {currentFormStepId === "summary" && ( - + )} diff --git a/Common/UI/Components/Forms/FormSummary.tsx b/Common/UI/Components/Forms/FormSummary.tsx index 2f6da5d3962..fe845f64bbb 100644 --- a/Common/UI/Components/Forms/FormSummary.tsx +++ b/Common/UI/Components/Forms/FormSummary.tsx @@ -10,53 +10,50 @@ import Field from "./Types/Field"; import FieldType from "../Types/FieldType"; export interface ComponentProps { - formValues: FormValues; - formFields: Fields; + formValues: FormValues; + formFields: Fields; } const FormSummary: ( - props: ComponentProps, + props: ComponentProps, ) => ReactElement = ( - props: ComponentProps, + props: ComponentProps, ): ReactElement => { - const { formValues, formFields } = props; + const { formValues, formFields } = props; - const getDetailForFormFields: ( - formValues: FormValues, - formFields: Fields, - ) => ReactElement = ( - formValues: FormValues, - formFields: Fields, - ): ReactElement => { - return ( - ) => { - const detailField: DetailField = { - title: field.title || "", - fieldType: field.getSummaryElement ? - FieldType.Element : - FormFieldSchemaTypeUtil.toFieldType( - field.fieldType || FormFieldSchemaType.Text, - ), - description: field.description || "", - getElement: field.getSummaryElement as any, - sideLink: field.sideLink, - key: (Object.keys( - field.field || {}, - )[0]?.toString() || "") as keyof T, - }; - return detailField; - }) as DetailField[] - } - /> - - ); + const getDetailForFormFields: ( + formValues: FormValues, + formFields: Fields, + ) => ReactElement = ( + formValues: FormValues, + formFields: Fields, + ): ReactElement => { + return ( + ) => { + const detailField: DetailField = { + title: field.title || "", + fieldType: field.getSummaryElement + ? FieldType.Element + : FormFieldSchemaTypeUtil.toFieldType( + field.fieldType || FormFieldSchemaType.Text, + ), + description: field.description || "", + getElement: field.getSummaryElement as any, + sideLink: field.sideLink, + key: (Object.keys(field.field || {})[0]?.toString() || + "") as keyof T, }; + return detailField; + }) as DetailField[] + } + /> + ); + }; - return getDetailForFormFields(formValues, formFields); - }; + return getDetailForFormFields(formValues, formFields); +}; export default FormSummary; - diff --git a/Common/UI/Components/Forms/Types/Field.ts b/Common/UI/Components/Forms/Types/Field.ts index 806d48af099..fdfd48e2e1d 100644 --- a/Common/UI/Components/Forms/Types/Field.ts +++ b/Common/UI/Components/Forms/Types/Field.ts @@ -103,5 +103,5 @@ export default interface Field { hideOptionalLabel?: boolean | undefined; - getSummaryElement?: (item: TEntity) => ReactElement | undefined; + getSummaryElement?: (item: FormValues) => ReactElement | undefined; } diff --git a/Dashboard/src/Components/IncidentSeverity/FetchIncidentSeverity.tsx b/Dashboard/src/Components/IncidentSeverity/FetchIncidentSeverity.tsx new file mode 100644 index 00000000000..68bfdcdd16a --- /dev/null +++ b/Dashboard/src/Components/IncidentSeverity/FetchIncidentSeverity.tsx @@ -0,0 +1,71 @@ +import IncidentSeverity from "Common/Models/DatabaseModels/IncidentSeverity"; +import React, { FunctionComponent, ReactElement, useEffect } from "react"; +import ObjectID from "Common/Types/ObjectID"; +import API from "Common/UI/Utils/API/API"; +import ModelAPI from "Common/UI/Utils/ModelAPI/ModelAPI"; +import Includes from "Common/Types/BaseDatabase/Includes"; +import { LIMIT_PER_PROJECT } from "Common/Types/Database/LimitMax"; +import SortOrder from "Common/Types/BaseDatabase/SortOrder"; +import ListResult from "Common/UI/Utils/BaseDatabase/ListResult"; +import ErrorMessage from "Common/UI/Components/ErrorMessage/ErrorMessage"; +import ComponentLoader from "Common/UI/Components/ComponentLoader/ComponentLoader"; +import IncidentSeveritiesElement from "./IncidentSeveritiesElement"; + +export interface ComponentProps { + onCallDutyPolicyIds: Array; +} + +const FetchIncidentSeverities: FunctionComponent = ( + props: ComponentProps, +): ReactElement => { + const [isLoading, setIsLoading] = React.useState(true); + const [error, setError] = React.useState(""); + const [incidentSeverities, setIncidentSeverities] = React.useState>([]); + + const fetchIncidentSeverities = async () => { + setIsLoading(true); + setError(""); + + try { + const incidentSeverities: ListResult = await ModelAPI.getList({ + modelType: IncidentSeverity, + query: { + _id: new Includes(props.onCallDutyPolicyIds), + }, + skip: 0, + limit: LIMIT_PER_PROJECT, + select: { + name: true, + _id: true, + }, + sort: { + name: SortOrder.Ascending, + }, + }); + + setIncidentSeverities(incidentSeverities.data); + } catch (err) { + setError(API.getFriendlyMessage(err)); + } + + setIsLoading(false); + }; + + useEffect(() => { + fetchIncidentSeverities().catch((err) => { + setError(API.getFriendlyMessage(err)); + }); + }, []); + + if (error) { + return ; + } + + if (isLoading) { + return ; + } + + return ; +}; + +export default FetchIncidentSeverities; diff --git a/Dashboard/src/Components/IncidentSeverity/IncidentSeveritiesElement.tsx b/Dashboard/src/Components/IncidentSeverity/IncidentSeveritiesElement.tsx new file mode 100644 index 00000000000..f2ef8aa2257 --- /dev/null +++ b/Dashboard/src/Components/IncidentSeverity/IncidentSeveritiesElement.tsx @@ -0,0 +1,31 @@ +import IncidentSeverityElement from "./IncidentSeverityElement"; +import TableColumnListComponent from "Common/UI/Components/TableColumnList/TableColumnListComponent"; +import IncidentSeverity from "Common/Models/DatabaseModels/IncidentSeverity"; +import React, { FunctionComponent, ReactElement } from "react"; + +export interface ComponentProps { + incidentSeverities: Array; + onNavigateComplete?: (() => void) | undefined; +} + +const IncidentSeveritiesElement: FunctionComponent = ( + props: ComponentProps, +): ReactElement => { + return ( + { + return ( + + ); + }} + noItemsMessage="No Incident Severities." + /> + ); +}; + +export default IncidentSeveritiesElement; diff --git a/Dashboard/src/Components/IncidentSeverity/IncidentSeverityElement.tsx b/Dashboard/src/Components/IncidentSeverity/IncidentSeverityElement.tsx new file mode 100644 index 00000000000..dca0db075bf --- /dev/null +++ b/Dashboard/src/Components/IncidentSeverity/IncidentSeverityElement.tsx @@ -0,0 +1,23 @@ +import IncidentSeverity from "Common/Models/DatabaseModels/IncidentSeverity"; +import React, { FunctionComponent, ReactElement } from "react"; +import { Black } from "Common/Types/BrandColors"; +import Pill from "Common/UI/Components/Pill/Pill"; + +export interface ComponentProps { + incidentSeverity: IncidentSeverity; + onNavigateComplete?: (() => void) | undefined; + showIcon?: boolean | undefined; +} + +const IncidentSeverityElement: FunctionComponent = ( + props: ComponentProps, +): ReactElement => { + return ( + + ); +}; + +export default IncidentSeverityElement; diff --git a/Dashboard/src/Components/Label/FetchLabels.tsx b/Dashboard/src/Components/Label/FetchLabels.tsx index 967feca7c4d..24bee506f07 100644 --- a/Dashboard/src/Components/Label/FetchLabels.tsx +++ b/Dashboard/src/Components/Label/FetchLabels.tsx @@ -18,62 +18,55 @@ export interface ComponentProps { const FetchLabels: FunctionComponent = ( props: ComponentProps, ): ReactElement => { + const [isLoading, setIsLoading] = React.useState(true); + const [error, setError] = React.useState(""); + const [labels, setLabels] = React.useState>([]); - const [isLoading, setIsLoading] = React.useState(true); - const [error, setError] = React.useState(""); - const [labels, setLabels] = React.useState>([]); + const fetchLabels = async () => { + setIsLoading(true); + setError(""); + try { + const labels: ListResult