Skip to content

Commit

Permalink
Merge branch 'main' into PIMS-1869-BCA-XREF
Browse files Browse the repository at this point in the history
  • Loading branch information
LawrenceLau2020 authored Oct 23, 2024
2 parents b88817b + e95d9b8 commit 6e8d617
Show file tree
Hide file tree
Showing 10 changed files with 113 additions and 6 deletions.
1 change: 1 addition & 0 deletions express-api/src/controllers/properties/propertiesSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
10 changes: 9 additions & 1 deletion express-api/src/services/ches/chesServices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,19 @@ const sendAsync = async (endpoint: string, method: string, data: Record<string,
body: data ? JSON.stringify(data) : undefined,
});

if (!response.ok) {
logger.error({
message: 'CHES Error',
chesResponse: JSON.parse(await response.text()),
});
return null;
}

const text = await response.text();
if (text.length) {
return JSON.parse(text);
} else {
return {};
return null;
}
};

Expand Down
1 change: 1 addition & 0 deletions express-api/src/services/properties/propertiesServices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
6 changes: 4 additions & 2 deletions express-api/src/utilities/winstonLogger.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { format, createLogger, transports } from 'winston';
import constants from '@/constants';

const { timestamp, combine, json } = format;
const { timestamp, combine, json, prettyPrint } = format;
const { TESTING } = constants;
const { CONTAINERIZED } = process.env;

/**
* Creates a logger object that can be called to generate log messages.
Expand All @@ -19,7 +20,8 @@ const logger = createLogger({
timestamp({
format: 'YYYY-MM-DD hh:mm:ss.SSS A',
}),
json(),
CONTAINERIZED ? json() : prettyPrint(),
format.errors({ stack: true }),
),
transports: [new transports.Console()],
silent: TESTING,
Expand Down
36 changes: 35 additions & 1 deletion express-api/tests/unit/services/ches/chesServices.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,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);
Expand All @@ -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: ['[email protected]'], bcc: ['[email protected]'] });
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: ['[email protected]'], bcc: ['[email protected]'] });
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();
Expand All @@ -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);
Expand All @@ -67,8 +96,8 @@ describe('UNIT - Ches Services', () => {
text: () => '{"access_token":"eyAiYSI6IDEgfQ==.ewoiZXhwIjoxCn0="}',
}));
_fetch.mockImplementationOnce(() => ({
ok: true,
text: () => `
{
"createdTS": 1560000000,
Expand Down Expand Up @@ -102,6 +131,7 @@ describe('UNIT - Ches Services', () => {
text: () => '{"access_token":"eyAiYSI6IDEgfQ==.ewoiZXhwIjoxCn0="}',
}));
_fetch.mockImplementationOnce(() => ({
ok: true,
text: () => `
[
{
Expand Down Expand Up @@ -143,6 +173,7 @@ describe('UNIT - Ches Services', () => {
text: () => '{"access_token":"eyAiYSI6IDEgfQ==.ewoiZXhwIjoxCn0="}',
}));
_fetch.mockImplementationOnce(() => ({
ok: true,
text: () => `
{
Expand Down Expand Up @@ -177,6 +208,7 @@ describe('UNIT - Ches Services', () => {
text: () => '{"access_token":"eyAiYSI6IDEgfQ==.ewoiZXhwIjoxCn0="}',
}));
_fetch.mockImplementationOnce(() => ({
ok: true,
text: () => `
{
Expand All @@ -202,6 +234,7 @@ describe('UNIT - Ches Services', () => {
text: () => '{"access_token":"eyAiYSI6IDEgfQ==.ewoiZXhwIjoxCn0="}',
}));
_fetch.mockImplementationOnce(() => ({
ok: true,
text: () => `
{
Expand Down Expand Up @@ -238,6 +271,7 @@ describe('UNIT - Ches Services', () => {
text: () => '{"access_token":"eyAiYSI6IDEgfQ==.ewoiZXhwIjoxCn0="}',
}));
_fetch.mockImplementationOnce(() => ({
ok: true,
text: () => `
[
{
Expand Down
55 changes: 55 additions & 0 deletions react-app/src/components/form/ToggleSwitch.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<Controller
name={name}
control={control}
rules={{ validate: (value) => !required || value || 'Required field.' }}
render={({ field: { onChange, value, onBlur }, fieldState: { error } }) => (
<>
<Box
sx={{
display: 'flex',
alignItems: 'center',
}}
>
<Switch
id={`single-checkbox-${name}`}
onChange={(_, data) => onChange(data)}
onBlur={onBlur}
checked={!!value}
required={required}
/>
<Typography>
{label} {required ? <sup>{'*'}</sup> : <></>}
</Typography>
</Box>
{!!error && !!error.message ? (
<Box>
<Typography ml={'3.2em'} fontSize={'smaller'} color={theme.palette.error.main}>
{error.message}
</Typography>
</Box>
) : (
<></>
)}
</>
)}
/>
);
};

export default ToggleSwitch;
5 changes: 5 additions & 0 deletions react-app/src/components/map/controls/FilterControl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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<SetStateAction<MapFilter>>;
Expand Down Expand Up @@ -51,6 +53,7 @@ const FilterControl = (props: FilterControlProps) => {
PropertyTypes: [],
RegionalDistricts: [],
Name: '',
InERP: false,
},
});

Expand Down Expand Up @@ -131,6 +134,7 @@ const FilterControl = (props: FilterControlProps) => {
})) ?? []
}
/>
<ToggleSwitch name={'InERP'} label="In ERP" />
<Grid item xs={12} justifyContent={'space-between'} display={'inline-flex'} gap={1}>
<Button
variant="outlined"
Expand Down Expand Up @@ -167,6 +171,7 @@ const FilterControl = (props: FilterControlProps) => {
(option) => option.value,
),
RegionalDistrictIds: formValues.RegionalDistricts.map((option) => option.value),
ProjectStatusId: formValues.InERP ? ProjectStatus.APPROVED_FOR_ERP : undefined,
};
setFilter({
Polygon: filter.Polygon,
Expand Down
2 changes: 1 addition & 1 deletion react-app/src/components/property/propertyRowStyle.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
* Styles the row in the property table.
*/
.erp-property-row {
background-color: #fae6b94d;
background-color: #fff8e8;
}
1 change: 1 addition & 0 deletions react-app/src/hooks/api/usePropertiesApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export interface MapFilter {
RegionalDistrictIds?: number[];
Name?: string;
Polygon?: string;
ProjectStatusId?: number;
}

export interface PropertyUnion {
Expand Down
2 changes: 1 addition & 1 deletion react-app/src/themes/appTheme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ const appTheme = createTheme({
palette: {
gold: {
main: '#FCBA19',
light: '#FAE6B94D',
light: '#fff8e8',
},
blue: {
main: '#0e3468',
Expand Down

0 comments on commit 6e8d617

Please sign in to comment.