Skip to content

Commit

Permalink
Merge branch 'main' into js-283-frontend-updates
Browse files Browse the repository at this point in the history
Conflicts:
	frontend/src/pages/ActivityReport/Pages/components/Goal.js
	src/seeders/20201124160449-users.js
  • Loading branch information
jasalisbury committed Mar 8, 2021
2 parents 64db2a9 + e7db658 commit eadf312
Show file tree
Hide file tree
Showing 66 changed files with 1,350 additions and 260 deletions.
10 changes: 6 additions & 4 deletions docs/logical_data_model.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Logical Data Model
==================

<img src="http://www.plantuml.com/plantuml/png/nLVlRjis4F-kf-2tRGLY31k60KLGjCtS8S2M1N7w06Vf8dEZUDpnbDP8ykupHLSsBJbXBMpxaa2_-__Z7Oz-wmLOsiOKlWI3wllPppyLnJSAxabNoZ4j3JPUVTAoKc1hWvKgcJvvTOSeXVzBMmSCZJBQegmTAc9PKL6K1hnN7psoUYYKUgLqfLuhRGNh3NH-NgD51i7gpPkDUENH1ztBeEI5jQqtg8K6zx_TYYnUjSqIUHz-fR01RVOXqMBmjKBRDi4xDNY3jIPxkPV4jp_-y9swcN-OtyolBkOBvTgbqUKiAlgPhZhN1hpyHhMs6qFH3Ng1ndMIaZ7a_qu6ajPL8vAdBwJ423cql4efsBbObEJm50zALUXBrauqsHwTLCurSgEzpowfzSWPvn3QeJy5Fl7qVE0fmwpZCrXDFTc_smqsPoRsEMoG2n-QxFu9jQptFnkK5ILpmJ7CUwhMAUmTMO_7y0kgiCSd5afchFsUQzbRShhCiqd2HBkipc8ocDCZP7PdBS7zPVMIJPV5z0RvbS3aSQ2K5v3MxoF1uHqVg6d_WQbPDC3YLuXoAt1j83JKaiWWs6aPTuK_btQzaMMG7bpyJwHVuMTP2BhTHAOLG2dwNilw1Xsnl9pMkqJ_ItgM19FX2i3jsk7un1sjORnl6AnWtiXD8Yj6EXfdi7jFlPZhM526uRRqQ3YOYO2m_0A21uMYhGReT6925-VSHISKc5AJQnUiJXZ3gHD5DcPzuXjaGkXq-7B2CtfgkUmUcCaQXQhIOVU2kIB1fAjYe_znTmqikjGkC9tCGeL6toElVnyivwhjDtg5fMx09DqOYalQjeTsrz0ce4OhuV8OMVk7Zz_XJ3Yccg49zW47PbYVHsaWH81hb6johUao7TDX14zsHE1IHWx4yMOV5GZ4UWQIagpWPqaAW1eN4jdvqvFTG0tO3SZfIPtydZJWvMDijFVhV_ankZMRtlAxPipg--5YKwTijg-wZgA9xQ-73BlTNJAPg3Jz2p86biGWnFyLNr_RaC5aFFtSLJCzxHCso3RjK85wV3oZ1nLRFI9FT7Rs-B3tkx28FrU7UBGQ4v3fzRjNOD7zLK-F7HHoA6BNz6hzVYx2dm4QNSvcAlpVTpaAnQ0xRoaI0uVA-n3RKb8ivJauETwXaRhdLOR--gVjYx6IMew9jlIcukIS3qJfPwAJt5UHio0V5-ykWUCwRz5MRMF-0G00" alt="logical data model diagram">
![logical data model diagram](http://www.plantuml.com/plantuml/png/nLTjRzis4FwkNy5lUm5Y31k60KLGDCtS8S2M1N7w0yxIHUP6yRZZAQsHvBzFD1FPjEI4jR3rIm8zz_xmZaU_ym8iRMCANu91zSFibv-BuXi5TwGhvPYM1XklFcbPAR2rmKgLJ9-ykaMKml-jhGE6HXbjKTOE5R6ig2XA0zwhZnvPtHTAVQywRs-Kje9r1vsUrcYHGR1w-tOZNddqGViYg7bXRUi4jz3WhYJWPsqNYhLez9q8c65z6XM2ptqBjoABbsspHDw5iG5jTW7HOl2DGjis8GurU8sr9dknKy2tF_tudRgUVvXVpo_FvmlbsgNHvImg-fckDhaRyF8xrTfsXg8Rz0ADsqXAnb3xcGmahQj698_FXCO8UPIc1FGk5YKvFCQ3KXNwahKJJRP79vLpXTnexxDBQZronZc4XkbFWOyyFHzuoZ3Ry1ciffxiFss7pPc9VGuRvCA79hjxGYthtSy6PKN9H74CyvwgTGfxHzRZ8VoSAkpnYOMI6Mk_brhsXfmkispICD4kgxEOJCvX1w_zMKjmVr6zPhF9Odg3_4PWyZXGoWj8wtUHuF2MzzIq_y3KB1fWyIj4kH6uCX0QQaba4EoaZEEnlPHstSaoI0yklXBfb_XP5e9kEv5f1L2AljEolaP7BA-dTPReFwTdIJ0PhW3Sh1sEJzp16iRxXi4APexS5B9Yf8Dn1flts8kvZWNbD4xK38Q3cOW8owyWk5Sescg8JYOcT776NNHCWIarkNR1wjWnd31HP6FMnxn1feLEXoydFAEdbilD4pHPer1LEknUC9Sac7HLRFG_Rw-0HPVQ1QQJMQZGw3lazH-3vLor_KQliDGDcAGRGt5zsoOGz9Lr0JLQ2PV7oDf7JgaSpeHZgXcQO3_sg1RW6kMAN6iscOxfC88dEo9m2IFxudYpZme4OZq3IKbMyBCa1K2D2udi_EN9Tb03jWCvFQcZtvC6l7oCZVP-_Hy_Hf_CfhVyjXcp-dwusDGHc-tBhgDeOllh8SDkUvTC9YfD_voCWIKn2F7_oDSNDMGm6Ky_VzLCJVk83VAKTgX0FJoSqBsAhHwHHpevURZV-LrOn9-hGpnQZGd8FEl75sYn-QiU7pPGoA68NTEhzVkv27y6Q7GvcwdmVyVbE1I3RhsbI0mSAkz3F9MIOYdFmSdX3etKlQmozDS_RL-DbTHoI1JftHCdvxmdIZyJdUI-Yfm5-RXuUmaSrdc7jceRyoy0)

UML Source
----------
Expand All @@ -15,10 +15,12 @@ skinparam linetype ortho
class User {
* id : integer <<generated>>
hsesUserId : string
* hsesUserId : string
* hsesUsername : string
hsesAuthorities : array<string>
name : string
phoneNumber : string
* email : string
email : string
title: enum
homeRegionId : integer(32) REFERENCES public.Regions.id
* lastLogin : timestamp
Expand Down Expand Up @@ -220,7 +222,7 @@ NonGrantee ||-{ ActivityParticipant
Instructions
------------

1. [Edit this diagram with plantuml.com](http://www.plantuml.com/plantuml/uml/nLVlRjis4F-kf-2tRGLY31k60KLGjCtS8S2M1N7w06Vf8dEZUDpnbDP8ykupHLSsBJbXBMpxaa2_-__Z7Oz-wmLOsiOKlWI3wllPppyLnJSAxabNoZ4j3JPUVTAoKc1hWvKgcJvvTOSeXVzBMmSCZJBQegmTAc9PKL6K1hnN7psoUYYKUgLqfLuhRGNh3NH-NgD51i7gpPkDUENH1ztBeEI5jQqtg8K6zx_TYYnUjSqIUHz-fR01RVOXqMBmjKBRDi4xDNY3jIPxkPV4jp_-y9swcN-OtyolBkOBvTgbqUKiAlgPhZhN1hpyHhMs6qFH3Ng1ndMIaZ7a_qu6ajPL8vAdBwJ423cql4efsBbObEJm50zALUXBrauqsHwTLCurSgEzpowfzSWPvn3QeJy5Fl7qVE0fmwpZCrXDFTc_smqsPoRsEMoG2n-QxFu9jQptFnkK5ILpmJ7CUwhMAUmTMO_7y0kgiCSd5afchFsUQzbRShhCiqd2HBkipc8ocDCZP7PdBS7zPVMIJPV5z0RvbS3aSQ2K5v3MxoF1uHqVg6d_WQbPDC3YLuXoAt1j83JKaiWWs6aPTuK_btQzaMMG7bpyJwHVuMTP2BhTHAOLG2dwNilw1Xsnl9pMkqJ_ItgM19FX2i3jsk7un1sjORnl6AnWtiXD8Yj6EXfdi7jFlPZhM526uRRqQ3YOYO2m_0A21uMYhGReT6925-VSHISKc5AJQnUiJXZ3gHD5DcPzuXjaGkXq-7B2CtfgkUmUcCaQXQhIOVU2kIB1fAjYe_znTmqikjGkC9tCGeL6toElVnyivwhjDtg5fMx09DqOYalQjeTsrz0ce4OhuV8OMVk7Zz_XJ3Yccg49zW47PbYVHsaWH81hb6johUao7TDX14zsHE1IHWx4yMOV5GZ4UWQIagpWPqaAW1eN4jdvqvFTG0tO3SZfIPtydZJWvMDijFVhV_ankZMRtlAxPipg--5YKwTijg-wZgA9xQ-73BlTNJAPg3Jz2p86biGWnFyLNr_RaC5aFFtSLJCzxHCso3RjK85wV3oZ1nLRFI9FT7Rs-B3tkx28FrU7UBGQ4v3fzRjNOD7zLK-F7HHoA6BNz6hzVYx2dm4QNSvcAlpVTpaAnQ0xRoaI0uVA-n3RKb8ivJauETwXaRhdLOR--gVjYx6IMew9jlIcukIS3qJfPwAJt5UHio0V5-ykWUCwRz5MRMF-0G00)
1. [Edit this diagram with plantuml.com](http://www.plantuml.com/plantuml/uml/nLTjRzis4FwkNy5lUm5Y31k60KLGDCtS8S2M1N7w0yxIHUP6yRZZAQsHvBzFD1FPjEI4jR3rIm8zz_xmZaU_ym8iRMCANu91zSFibv-BuXi5TwGhvPYM1XklFcbPAR2rmKgLJ9-ykaMKml-jhGE6HXbjKTOE5R6ig2XA0zwhZnvPtHTAVQywRs-Kje9r1vsUrcYHGR1w-tOZNddqGViYg7bXRUi4jz3WhYJWPsqNYhLez9q8c65z6XM2ptqBjoABbsspHDw5iG5jTW7HOl2DGjis8GurU8sr9dknKy2tF_tudRgUVvXVpo_FvmlbsgNHvImg-fckDhaRyF8xrTfsXg8Rz0ADsqXAnb3xcGmahQj698_FXCO8UPIc1FGk5YKvFCQ3KXNwahKJJRP79vLpXTnexxDBQZronZc4XkbFWOyyFHzuoZ3Ry1ciffxiFss7pPc9VGuRvCA79hjxGYthtSy6PKN9H74CyvwgTGfxHzRZ8VoSAkpnYOMI6Mk_brhsXfmkispICD4kgxEOJCvX1w_zMKjmVr6zPhF9Odg3_4PWyZXGoWj8wtUHuF2MzzIq_y3KB1fWyIj4kH6uCX0QQaba4EoaZEEnlPHstSaoI0yklXBfb_XP5e9kEv5f1L2AljEolaP7BA-dTPReFwTdIJ0PhW3Sh1sEJzp16iRxXi4APexS5B9Yf8Dn1flts8kvZWNbD4xK38Q3cOW8owyWk5Sescg8JYOcT776NNHCWIarkNR1wjWnd31HP6FMnxn1feLEXoydFAEdbilD4pHPer1LEknUC9Sac7HLRFG_Rw-0HPVQ1QQJMQZGw3lazH-3vLor_KQliDGDcAGRGt5zsoOGz9Lr0JLQ2PV7oDf7JgaSpeHZgXcQO3_sg1RW6kMAN6iscOxfC88dEo9m2IFxudYpZme4OZq3IKbMyBCa1K2D2udi_EN9Tb03jWCvFQcZtvC6l7oCZVP-_Hy_Hf_CfhVyjXcp-dwusDGHc-tBhgDeOllh8SDkUvTC9YfD_voCWIKn2F7_oDSNDMGm6Ky_VzLCJVk83VAKTgX0FJoSqBsAhHwHHpevURZV-LrOn9-hGpnQZGd8FEl75sYn-QiU7pPGoA68NTEhzVkv27y6Q7GvcwdmVyVbE1I3RhsbI0mSAkz3F9MIOYdFmSdX3etKlQmozDS_RL-DbTHoI1JftHCdvxmdIZyJdUI-Yfm5-RXuUmaSrdc7jceRyoy0)
2. Copy and paste the final UML into the UML Source section
3. Update the img src and edit link target to the current values

Expand Down
5 changes: 5 additions & 0 deletions docs/openapi/index.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,11 @@ components:
type: string
hsesUserId:
type: number
hsesUsername:
type: string
hsesAuthorities:
type: array
description: List of authorities (user types) returned from HSES
email:
type: string
phoneNumber:
Expand Down
3 changes: 2 additions & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@
"simplebar-react": "^2.3.0",
"url-join": "^4.0.1",
"use-deep-compare-effect": "^1.6.1",
"uswds": "^2.9.0"
"uswds": "^2.9.0",
"uuid": "^8.3.2"
},
"engines": {
"node": "14.16.0"
Expand Down
1 change: 1 addition & 0 deletions frontend/src/components/ContextMenu.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ function ContextMenu({
aria-haspopup
onClick={() => updateShown((previous) => !previous)}
aria-label={label}
type="button"
>
<FontAwesomeIcon color="black" icon={faEllipsisH} />
</Button>
Expand Down
1 change: 1 addition & 0 deletions frontend/src/components/DatePicker.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ const DateInput = ({
onChange(newDate);
}}
onFocusChange={({ focused }) => updateFocus(focused)}
hideKeyboardShortcutsPanel
/>
</div>
);
Expand Down
15 changes: 9 additions & 6 deletions frontend/src/components/FormItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@ import './FormItem.css';
const labelPropTypes = {
label: PropTypes.node.isRequired,
children: PropTypes.node.isRequired,
className: PropTypes.string.isRequired,
};

function FieldSetWrapper({ label, children }) {
function FieldSetWrapper({ label, children, className }) {
return (
<Fieldset unstyled>
<Fieldset unstyled className={className}>
<legend>{label}</legend>
{children}
</Fieldset>
Expand All @@ -24,9 +25,9 @@ function FieldSetWrapper({ label, children }) {

FieldSetWrapper.propTypes = labelPropTypes;

function LabelWrapper({ label, children }) {
function LabelWrapper({ label, children, className }) {
return (
<Label>
<Label className={className}>
{label}
{children}
</Label>
Expand All @@ -36,7 +37,7 @@ function LabelWrapper({ label, children }) {
LabelWrapper.propTypes = labelPropTypes;

function FormItem({
label, children, required, name, fieldSetWrapper,
label, children, required, name, fieldSetWrapper, className,
}) {
const { formState: { errors } } = useFormContext();
const fieldErrors = errors[name];
Expand All @@ -51,7 +52,7 @@ function FormItem({

return (
<FormGroup error={fieldErrors}>
<LabelType label={labelWithRequiredTag}>
<LabelType label={labelWithRequiredTag} className={className}>
<ReactHookFormError
errors={errors}
name={name}
Expand All @@ -69,11 +70,13 @@ FormItem.propTypes = {
name: PropTypes.string.isRequired,
fieldSetWrapper: PropTypes.bool,
required: PropTypes.bool,
className: PropTypes.string,
};

FormItem.defaultProps = {
required: true,
fieldSetWrapper: false,
className: '',
};

export default FormItem;
23 changes: 20 additions & 3 deletions frontend/src/components/MultiSelect.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,9 @@ function MultiSelect({
labelProperty,
valueProperty,
simple,
rules,
multiSelectOptions,
onItemSelected,
components: componentReplacements,
}) {
/*
Expand All @@ -95,7 +97,11 @@ function MultiSelect({
value: v, label: v,
}));
}
return value.map((item) => ({ label: item[labelProperty], value: item[valueProperty] }));
return value.map((item) => ({
...item,
label: item[labelProperty],
value: item[valueProperty],
}));
};

/*
Expand All @@ -109,7 +115,11 @@ function MultiSelect({
controllerOnChange(event.map((v) => v.value));
} else {
controllerOnChange(
event.map((item) => ({ [labelProperty]: item.label, [valueProperty]: item.value })),
event.map((item) => ({
...item,
[labelProperty]: item.label,
[valueProperty]: item.value,
})),
);
}
};
Expand All @@ -124,7 +134,9 @@ function MultiSelect({
id={name}
value={values}
onChange={(event) => {
if (event) {
if (onItemSelected) {
onItemSelected(event);
} else if (event) {
onChange(event, controllerOnChange);
} else {
controllerOnChange([]);
Expand All @@ -151,6 +163,7 @@ function MultiSelect({
}
return true;
},
...rules,
}}
name={name}
/>
Expand Down Expand Up @@ -182,13 +195,15 @@ MultiSelect.propTypes = {
// eslint-disable-next-line react/forbid-prop-types
control: PropTypes.object.isRequired,
components: PropTypes.shape({}),
onItemSelected: PropTypes.func,
multiSelectOptions: PropTypes.shape({
isClearable: PropTypes.bool,
closeMenuOnSelect: PropTypes.bool,
controlShouldRenderValue: PropTypes.bool,
hideSelectedOptions: PropTypes.bool,
}),
disabled: PropTypes.bool,
rules: PropTypes.shape({}),
required: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
};

Expand All @@ -200,6 +215,8 @@ MultiSelect.defaultProps = {
valueProperty: 'value',
multiSelectOptions: {},
components: {},
rules: {},
onItemSelected: null,
};

export default MultiSelect;
23 changes: 15 additions & 8 deletions frontend/src/components/Navigator/components/NavigatorHeader.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,23 @@
USWDS step indicator header, grabbed from https://designsystem.digital.gov/components/step-indicator/
The uswds react library we use doesn't have this component yet.
*/
import React from 'react';
import React, { useEffect } from 'react';
import PropTypes from 'prop-types';

const NavigatorHeader = ({ label }) => (
<div className="usa-step-indicator__header">
<h2 className="usa-step-indicator__heading">
<span className="usa-step-indicator__heading-text">{label}</span>
</h2>
</div>
);
const NavigatorHeader = ({ label }) => {
useEffect(() => {
document.getElementsByClassName('usa-step-indicator__heading-text')[0].focus();
}, []);

return (
<div className="usa-step-indicator__header">
<h2 className="usa-step-indicator__heading">
{/* eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex */}
<span tabIndex="0" className="usa-step-indicator__heading-text">{label}</span>
</h2>
</div>
);
};

NavigatorHeader.propTypes = {
label: PropTypes.string.isRequired,
Expand Down
33 changes: 22 additions & 11 deletions frontend/src/components/Navigator/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,22 +65,21 @@ function Navigator({
const { isDirty, errors, isValid } = formState;
const hasErrors = Object.keys(errors).length > 0;

useEffect(() => {
if (showValidationErrors && !page.review) {
trigger();
}
}, [page.review, trigger, showValidationErrors]);

const newNavigatorState = () => {
if (page.review) {
return pageState;
}

const currentPageState = pageState[page.position];
const isComplete = page.isPageComplete ? page.isPageComplete(getValues()) : isValid;

const newPageState = { ...pageState };
if (isValid) {
if (isComplete) {
newPageState[page.position] = COMPLETE;
} else if (currentPageState === COMPLETE) {
newPageState[page.position] = IN_PROGRESS;
} else {
newPageState[page.position] = isDirty ? IN_PROGRESS : pageState[page.position];
newPageState[page.position] = isDirty ? IN_PROGRESS : currentPageState;
}
return newPageState;
};
Expand All @@ -105,9 +104,10 @@ function Navigator({
};

const onUpdatePage = async (index) => {
const newIndex = index === page.position ? null : index;
await onSaveForm();
updatePage(newIndex);
if (index !== page.position) {
updatePage(index);
}
};

const onContinue = () => {
Expand All @@ -124,6 +124,14 @@ function Navigator({
reset(formData);
}, [currentPage, reset, formData]);

useEffect(() => {
if (showValidationErrors && !page.review) {
setTimeout(() => {
trigger();
});
}
}, [page.path, page.review, trigger, showValidationErrors]);

const navigatorPages = pages.map((p) => {
const current = p.position === page.position;

Expand All @@ -135,7 +143,9 @@ function Navigator({
const state = p.review ? formData.status : stateOfPage;
return {
label: p.label,
onNavigation: () => onUpdatePage(p.position),
onNavigation: () => {
onUpdatePage(p.position);
},
state,
current,
review: p.review,
Expand Down Expand Up @@ -173,6 +183,7 @@ function Navigator({
&& (
<Container skipTopPadding>
<NavigatorHeader
key={page.label}
label={page.label}
/>
{hasErrors
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import fetchMock from 'fetch-mock';
import React from 'react';
import { FormProvider, useForm } from 'react-hook-form';
import join from 'url-join';
import { Router } from 'react-router-dom';
import { createMemoryHistory } from 'history';

import goalsObjectives from '../goalsObjectives';

Expand Down Expand Up @@ -40,6 +42,21 @@ const renderGoals = (grantIds, activityRecipientType, initialData, goals = []) =
);
};

// eslint-disable-next-line react/prop-types
const RenderReview = ({ goals }) => {
const history = createMemoryHistory();
const hookForm = useForm({
defaultValues: { goals },
});
return (
<Router history={history}>
<FormProvider {...hookForm}>
{goalsObjectives.reviewSection()}
</FormProvider>
</Router>
);
};

describe('goals objectives', () => {
afterEach(() => fetchMock.restore());
describe('when activity recipient type is "grantee"', () => {
Expand All @@ -63,4 +80,25 @@ describe('goals objectives', () => {
expect(screen.queryByText('Goals and objectives')).toBeNull();
});
});

describe('review page', () => {
it('displays goals with no objectives', async () => {
render(<RenderReview goals={[{ id: 1, name: 'goal' }]} />);
const goal = await screen.findByText('goal');
expect(goal).toBeVisible();
});

it('displays goals with objectives', async () => {
render(<RenderReview goals={[{
id: 1,
name: 'goal',
objectives: [{
id: 1, title: 'title', ttaProvided: 'ttaProvided', status: 'Not Started',
}],
}]}
/>);
const objective = await screen.findByText('title');
expect(objective).toBeVisible();
});
});
});
15 changes: 15 additions & 0 deletions frontend/src/pages/ActivityReport/Pages/__tests__/nextSteps.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import '@testing-library/jest-dom';
import { render, screen } from '@testing-library/react';

import nextSteps from '../nextSteps';

const renderNextSteps = () => {
render(nextSteps.render());
};

describe('next steps', () => {
it('displays the next steps header', async () => {
renderNextSteps();
expect(await screen.findByText('Next Steps')).toBeVisible();
});
});
Loading

0 comments on commit eadf312

Please sign in to comment.