From 6c9077c0c9169a3aa249fa6122fb11778b5a30c0 Mon Sep 17 00:00:00 2001 From: Dylan Barkowsky <37922247+dbarkowsky@users.noreply.github.com> Date: Tue, 22 Oct 2024 09:53:19 -0700 Subject: [PATCH 1/3] CHES Notifications & Logger Adjustment (#2730) Co-authored-by: LawrenceLau2020 <68400651+LawrenceLau2020@users.noreply.github.com> --- express-api/src/services/ches/chesServices.ts | 10 +++++- express-api/src/utilities/winstonLogger.ts | 6 ++-- .../unit/services/ches/chesServices.test.ts | 36 ++++++++++++++++++- 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/express-api/src/services/ches/chesServices.ts b/express-api/src/services/ches/chesServices.ts index 5f564dc0d..1ab194f99 100644 --- a/express-api/src/services/ches/chesServices.ts +++ b/express-api/src/services/ches/chesServices.ts @@ -97,11 +97,19 @@ const sendAsync = async (endpoint: string, method: string, data: Record { text: () => '{"access_token":"eyAiYSI6IDEgfQ==.ewoiZXhwIjoxCn0="}', })); _fetch.mockImplementationOnce(() => ({ + ok: true, text: () => `{ "messages": [{}], "txId": "${randomUUID()}" }`, })); const response = await chesServices.sendEmailAsync(email, keycloak); @@ -35,10 +36,37 @@ describe('UNIT - Ches Services', () => { text: () => '{"access_token":"eyAiYSI6IDEgfQ==.ewoiZXhwIjoxCn0="}', })); _fetch.mockImplementationOnce(() => ({ + ok: false, text: () => `{ "messages": [{}], "txId": "${randomUUID()}" }`, })); expect(async () => await chesServices.sendEmailAsync(email, keycloak)).rejects.toThrow(); }); + it('should return null if the CHES response is not OK', async () => { + const email = produceEmail({ cc: ['john@doe.com'], bcc: ['john@doe.com'] }); + const keycloak = producePimsRequestUser(); + _fetch.mockImplementationOnce(() => ({ + text: () => '{"access_token":"eyAiYSI6IDEgfQ==.ewoiZXhwIjoxCn0="}', + })); + _fetch.mockImplementationOnce(() => ({ + ok: false, + text: () => `{ "messages": [{}], "txId": "${randomUUID()}" }`, + })); + const result = await chesServices.sendEmailAsync(email, keycloak); + expect(result).toBeNull(); + }); + it('should return null if the CHES response has no text length', async () => { + const email = produceEmail({ cc: ['john@doe.com'], bcc: ['john@doe.com'] }); + const keycloak = producePimsRequestUser(); + _fetch.mockImplementationOnce(() => ({ + text: () => '{"access_token":"eyAiYSI6IDEgfQ==.ewoiZXhwIjoxCn0="}', + })); + _fetch.mockImplementationOnce(() => ({ + ok: true, + text: () => ``, + })); + const result = await chesServices.sendEmailAsync(email, keycloak); + expect(result).toBeNull(); + }); it('should send email with extra config', async () => { const email: IEmail = produceEmail({}); const keycloak = producePimsRequestUser(); @@ -55,6 +83,7 @@ describe('UNIT - Ches Services', () => { text: () => '{"access_token":"eyAiYSI6IDEgfQ==.ewoiZXhwIjoxCn0="}', })); _fetch.mockImplementationOnce(() => ({ + ok: true, text: () => `{ "messages": [{}], "txId": "${randomUUID()}" }`, })); const response = await chesServices.sendEmailAsync(email, keycloak); @@ -67,8 +96,8 @@ describe('UNIT - Ches Services', () => { text: () => '{"access_token":"eyAiYSI6IDEgfQ==.ewoiZXhwIjoxCn0="}', })); _fetch.mockImplementationOnce(() => ({ + ok: true, text: () => ` - { "createdTS": 1560000000, @@ -102,6 +131,7 @@ describe('UNIT - Ches Services', () => { text: () => '{"access_token":"eyAiYSI6IDEgfQ==.ewoiZXhwIjoxCn0="}', })); _fetch.mockImplementationOnce(() => ({ + ok: true, text: () => ` [ { @@ -143,6 +173,7 @@ describe('UNIT - Ches Services', () => { text: () => '{"access_token":"eyAiYSI6IDEgfQ==.ewoiZXhwIjoxCn0="}', })); _fetch.mockImplementationOnce(() => ({ + ok: true, text: () => ` { @@ -177,6 +208,7 @@ describe('UNIT - Ches Services', () => { text: () => '{"access_token":"eyAiYSI6IDEgfQ==.ewoiZXhwIjoxCn0="}', })); _fetch.mockImplementationOnce(() => ({ + ok: true, text: () => ` { @@ -202,6 +234,7 @@ describe('UNIT - Ches Services', () => { text: () => '{"access_token":"eyAiYSI6IDEgfQ==.ewoiZXhwIjoxCn0="}', })); _fetch.mockImplementationOnce(() => ({ + ok: true, text: () => ` { @@ -238,6 +271,7 @@ describe('UNIT - Ches Services', () => { text: () => '{"access_token":"eyAiYSI6IDEgfQ==.ewoiZXhwIjoxCn0="}', })); _fetch.mockImplementationOnce(() => ({ + ok: true, text: () => ` [ { From 62411d04dd5bf45009977725ed5829433a8271f3 Mon Sep 17 00:00:00 2001 From: LawrenceLau2020 <68400651+LawrenceLau2020@users.noreply.github.com> Date: Tue, 22 Oct 2024 15:31:54 -0700 Subject: [PATCH 2/3] PIMS-2036: Map Filter - ERP Projects (#2733) --- .../properties/propertiesSchema.ts | 1 + .../services/properties/propertiesServices.ts | 1 + .../src/components/form/ToggleSwitch.tsx | 55 +++++++++++++++++++ .../components/map/controls/FilterControl.tsx | 5 ++ react-app/src/hooks/api/usePropertiesApi.ts | 1 + 5 files changed, 63 insertions(+) create mode 100644 react-app/src/components/form/ToggleSwitch.tsx diff --git a/express-api/src/controllers/properties/propertiesSchema.ts b/express-api/src/controllers/properties/propertiesSchema.ts index aed1a71b3..877cad54e 100644 --- a/express-api/src/controllers/properties/propertiesSchema.ts +++ b/express-api/src/controllers/properties/propertiesSchema.ts @@ -30,6 +30,7 @@ export const MapFilterSchema = z.object({ AdministrativeAreaIds: arrayFromString(numberSchema), ClassificationIds: arrayFromString(numberSchema), PropertyTypeIds: arrayFromString(numberSchema), + ProjectStatusId: z.coerce.number().optional(), Name: z.string().optional(), RegionalDistrictIds: arrayFromString(numberSchema), UserAgencies: z.array(z.number().int()).optional(), diff --git a/express-api/src/services/properties/propertiesServices.ts b/express-api/src/services/properties/propertiesServices.ts index e38ee3bee..108b7e574 100644 --- a/express-api/src/services/properties/propertiesServices.ts +++ b/express-api/src/services/properties/propertiesServices.ts @@ -212,6 +212,7 @@ const getPropertiesForMap = async (filter?: MapFilter) => { : undefined, PID: filter.PID, PIN: filter.PIN, + ProjectStatusId: filter.ProjectStatusId, Address1: filter.Address ? ILike(`%${filter.Address}%`) : undefined, Name: filter.Name ? ILike(`%${filter.Name}%`) : undefined, PropertyTypeId: filter.PropertyTypeIds ? In(filter.PropertyTypeIds) : undefined, diff --git a/react-app/src/components/form/ToggleSwitch.tsx b/react-app/src/components/form/ToggleSwitch.tsx new file mode 100644 index 000000000..8c6100538 --- /dev/null +++ b/react-app/src/components/form/ToggleSwitch.tsx @@ -0,0 +1,55 @@ +import React from 'react'; +import { SxProps, Typography, Box, useTheme, Switch } from '@mui/material'; +import { Controller, useFormContext } from 'react-hook-form'; + +interface ToggleSwitchProps { + name: string; + label: string; + sx?: SxProps; + required?: boolean; +} + +const ToggleSwitch = (props: ToggleSwitchProps) => { + const { control } = useFormContext(); + const theme = useTheme(); + const { name, label, required } = props; + return ( + !required || value || 'Required field.' }} + render={({ field: { onChange, value, onBlur }, fieldState: { error } }) => ( + <> + + onChange(data)} + onBlur={onBlur} + checked={!!value} + required={required} + /> + + {label} {required ? {'*'} : <>} + + + {!!error && !!error.message ? ( + + + {error.message} + + + ) : ( + <> + )} + + )} + /> + ); +}; + +export default ToggleSwitch; diff --git a/react-app/src/components/map/controls/FilterControl.tsx b/react-app/src/components/map/controls/FilterControl.tsx index 510f7327a..2c45a7622 100644 --- a/react-app/src/components/map/controls/FilterControl.tsx +++ b/react-app/src/components/map/controls/FilterControl.tsx @@ -10,6 +10,8 @@ import usePimsApi from '@/hooks/usePimsApi'; import { Box, Typography, Grid, Button } from '@mui/material'; import React, { Dispatch, SetStateAction, useContext } from 'react'; import { FormProvider, useForm } from 'react-hook-form'; +import { ProjectStatus } from '@/constants/projectStatuses'; +import ToggleSwitch from '@/components/form/ToggleSwitch'; interface FilterControlProps { setFilter: Dispatch>; @@ -51,6 +53,7 @@ const FilterControl = (props: FilterControlProps) => { PropertyTypes: [], RegionalDistricts: [], Name: '', + InERP: false, }, }); @@ -131,6 +134,7 @@ const FilterControl = (props: FilterControlProps) => { })) ?? [] } /> +