Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MDS-5927] Bring Projects Form to CORE #3145

Merged
merged 37 commits into from
Jun 12, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
4586872
remove some test noise using mocks, move components into common
taraepp Jun 6, 2024
6c99c39
update components for CORE: change route to be able to use GLOBAL_ROU…
taraepp Jun 6, 2024
bdecc9d
authorizations document bug- get rid of redux form state being double…
taraepp Jun 6, 2024
9d4588c
fix indent error on BE
taraepp Jun 6, 2024
3aaf367
add ministry contact page, fix bug on project contacts, put the proje…
taraepp Jun 7, 2024
c12ab4b
take out save draft
taraepp Jun 7, 2024
ac373c7
make test work without mocking component, remove some temporary text
taraepp Jun 7, 2024
eee764e
fix document upload snap test
taraepp Jun 7, 2024
ccdb035
try fixing a cypress test
taraepp Jun 7, 2024
f50477b
fix text
taraepp Jun 7, 2024
eef25ac
fix text
taraepp Jun 7, 2024
50e2930
click after on next page
taraepp Jun 7, 2024
1dc02b6
fix text in selector
taraepp Jun 7, 2024
bf9b2b7
make edit/view mode persistent on CORE
taraepp Jun 10, 2024
d49aeef
take out unnecessary step from test
taraepp Jun 10, 2024
ee0c151
update selector
taraepp Jun 10, 2024
47bfc54
syntax error
taraepp Jun 10, 2024
565b2a4
add missing fields in contact
taraepp Jun 10, 2024
c20f887
change selector
taraepp Jun 10, 2024
d9e181b
update a snap, clear up some of the console warnings
taraepp Jun 10, 2024
510cdd7
fix case
taraepp Jun 10, 2024
74227b0
add missing pages. Make select boxes easier to select
taraepp Jun 10, 2024
40c349e
quiet core-web tests too. Update a snap
taraepp Jun 10, 2024
5062083
missed selector fix
taraepp Jun 10, 2024
98f42c5
add missing fields
taraepp Jun 10, 2024
5917ac8
selector
taraepp Jun 10, 2024
bb802d4
fighting with select inputs
taraepp Jun 10, 2024
c060f49
scroll to top. Start fixing other test
taraepp Jun 10, 2024
c863a13
select differently
taraepp Jun 10, 2024
4eb4949
scroll differently
taraepp Jun 10, 2024
6133eae
scroll
taraepp Jun 11, 2024
90920af
selector before going to Declaration page
taraepp Jun 11, 2024
648d1f7
fix bug with submitting on last page
taraepp Jun 11, 2024
e1e2c6f
change documents up a bit: different condition for view/download from…
taraepp Jun 11, 2024
3185dd4
fix a documents bug. Make updateAmendmentDocuments update the corresp…
taraepp Jun 11, 2024
3c8bccb
revert showing version history on doc upload
taraepp Jun 11, 2024
f8afa66
make SteppedForm extend FormWrapper props
taraepp Jun 12, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion services/common/src/components/forms/RenderFileUpload.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,11 @@ export const FileUpload = (props: FileUploadProps) => {
const fileTypeList = listedFileTypes ?? Object.keys(acceptedFileTypesMap);
const fileTypeDisplayString =
fileTypeList.slice(0, -1).join(", ") + ", and " + fileTypeList.slice(-1);
const fileSize = props.maxFileSize
? ` with max individual file size of ${props.maxFileSize}`
: "";
const secondLine = abbrevLabel
? `<div>We accept most common ${fileTypeDisplayString} files</div>`
? `<div>We accept most common ${fileTypeDisplayString} files${fileSize}.</div>`
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just for Denise- making file-size show up by default.

: `<div>Accepted filetypes: ${fileTypeDisplayString}</div>`;
return `${labelInstruction}<br>${secondLine}`;
};
Expand Down
12 changes: 12 additions & 0 deletions services/common/src/components/forms/Step.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React, { FC } from "react";
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One of many, many components to get moved or copied to common

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More more more!


export interface StepProps {
disabled?: boolean;
key: string;
}

const Step: FC<StepProps> = (props) => {
return <>{props.children}</>;
};

export default Step;
175 changes: 114 additions & 61 deletions services/common/src/components/forms/SteppedForm.tsx
Original file line number Diff line number Diff line change
@@ -1,54 +1,57 @@
import { Button, Col, Form, Menu, Popconfirm, Row } from "antd";
import React, { FC, ReactElement, useEffect, useState } from "react";
import { useSelector, useDispatch } from "react-redux";
import { getFormSyncErrors, getFormValues, submit } from "redux-form";
import { Button, Col, Menu, Popconfirm, Row, StepProps } from "antd";
import LeftOutlined from "@ant-design/icons/LeftOutlined";
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Basically, SteppedForm in this state:

  • makes its own FormWrapper with the settings that are ideal for it
  • checks for errors
  • passes down isEditMode to FormWrapper to enable a view mode
  • transforms the values according to a function prop

import RightOutlined from "@ant-design/icons/RightOutlined";
import React, { useEffect, useState } from "react";

import PropTypes from "prop-types";
import { indexOf } from "lodash";
import { formatUrlToUpperCaseString } from "@mds/common/redux/utils/helpers";

const propTypes = {
children: PropTypes.arrayOf(PropTypes.any).isRequired,
handleTabChange: PropTypes.func.isRequired,
handleSaveDraft: PropTypes.func,
handleSaveData: PropTypes.func,
handleCancel: PropTypes.func,
activeTab: PropTypes.string.isRequired,
errors: PropTypes.arrayOf(PropTypes.string),
submitText: PropTypes.string,
cancelText: PropTypes.string,
cancelConfirmMessage: PropTypes.string,
sectionChangeText: PropTypes.string,
};

const defaultProps = {
submitText: undefined,
cancelText: undefined,
handleSaveDraft: undefined,
handleSaveData: undefined,
handleCancel: undefined,
cancelConfirmMessage: undefined,
errors: [],
sectionChangeText: undefined,
};

const SteppedForm = (props) => {
const {
children,
handleTabChange,
activeTab,
handleSaveDraft,
handleSaveData,
submitText,
cancelText,
handleCancel,
cancelConfirmMessage,
errors,
sectionChangeText,
} = props;
import { flattenObject, formatUrlToUpperCaseString } from "@mds/common/redux/utils/helpers";
import FormWrapper from "./FormWrapper";

interface SteppedFormProps {
formName: string;
initialValues?: any;
isEditMode?: boolean;
children: Array<ReactElement<StepProps>>;
handleTabChange: (newTab: string) => void | Promise<void>;
handleSaveDraft?: (formValues) => Promise<void>;
handleSaveData?: (values, newActiveTab?: string) => Promise<void>;
handleCancel?: () => void | Promise<void>;
transformPayload?: (values: any) => any;
activeTab: string;
submitText?: string; // "Submit"
cancelText?: string; // "Cancel"
cancelConfirmMessage?: string;
sectionChangeText?: string; // Save & Continue
nextText?: string; // "Next"
disableTabsOnError?: boolean;
}

const SteppedForm: FC<SteppedFormProps> = ({
formName,
initialValues,
children,
transformPayload,
handleTabChange,
handleSaveDraft,
handleSaveData,
handleCancel,
activeTab,
isEditMode = true,
submitText = "Submit",
cancelText = "Cancel",
cancelConfirmMessage,
sectionChangeText = "Save & Continue",
nextText = "Next",
disableTabsOnError = true,
}) => {
const [isSubmitting, setIsSubmitting] = useState(false);
const [tabIndex, setTabIndex] = useState(0);
const tabs = children.map((child) => child.key);
const dispatch = useDispatch();
const formValues = useSelector(getFormValues(formName));
const formErrors = useSelector((state) => getFormSyncErrors(formName)(state));
const errors = Object.keys(flattenObject(formErrors));

useEffect(() => {
setTabIndex(tabs.indexOf(activeTab));
Expand All @@ -70,17 +73,29 @@ const SteppedForm = (props) => {
}
};

const handleNextClick = async (evt, tab) => {
evt.preventDefault();
// checks for validation errors before saving draft or save & continues
const saveCheck = async () => {
await dispatch(submit(formName));
const valid = !errors.length;
return valid;
};

const getValues = (formValues) => {
if (transformPayload) {
return transformPayload(formValues);
}
return formValues;
};

const handleDraftClick = async (evt, tab) => {
evt.preventDefault();
setIsSubmitting(true);

try {
if (handleSaveData) {
await handleSaveData(null, tab);
if (handleSaveDraft && (await saveCheck())) {
await handleSaveDraft(getValues(formValues));
}
if (errors.length > 0) return;

setTabIndex(indexOf(tabs, tab));
} finally {
setIsSubmitting(false);
Expand All @@ -90,12 +105,26 @@ const SteppedForm = (props) => {
const isFirst = tabIndex === 0;
const isLast = tabs.length - 1 === tabIndex;

const handleNextClick = async (evt, tab) => {
evt.preventDefault();
setIsSubmitting(true);
try {
if (handleSaveData && (await saveCheck())) {
await handleSaveData(getValues(formValues), tab);
}
if (errors.length > 0) return;
setTabIndex(indexOf(tabs, tab));
} finally {
setIsSubmitting(false);
}
};

const items = tabs.map((tab) => {
const child = children.find((childTab) => childTab.key === tab);
return {
label: formatUrlToUpperCaseString(tab),
key: tab,
disabled: child?.props?.disabled,
disabled: child?.props?.disabled || (disableTabsOnError && errors.length > 0),
className: "stepped-menu-item",
onClick: () => handleTabClick(tabs[indexOf(tabs, tab)]),
};
Expand All @@ -104,12 +133,29 @@ const SteppedForm = (props) => {
return (
<Row>
<Col span={6} className="stepped-form-menu-container">
<Menu className="stepped-form" mode="inline" selectedKeys={tabs[tabIndex]} items={items} />
<Menu
className="stepped-form"
mode="inline"
selectedKeys={[tabs[tabIndex].toString()]}
items={items}
/>
</Col>
<Col span={18}>
{children && (
<div className="stepped-form-form-container">
<Form layout="vertical">{children.find((child) => child.key === tabs[tabIndex])}</Form>
<FormWrapper
name={formName}
onSubmit={() => {}}
initialValues={initialValues}
isEditMode={isEditMode}
reduxFormConfig={{
touchOnBlur: true,
touchOnChange: false,
enableReinitialize: true,
taraepp marked this conversation as resolved.
Show resolved Hide resolved
}}
>
{children.find((child) => child.key === tabs[tabIndex])}
</FormWrapper>
<Row
justify={isFirst && tabs.length > 1 ? "end" : "space-between"}
className="stepped-form-button-row"
Expand Down Expand Up @@ -137,30 +183,40 @@ const SteppedForm = (props) => {
</Popconfirm>
)}

{!isLast && (
{isEditMode && !isLast && (
<div>
{handleSaveDraft && (
<Button
type="text"
className="full-mobile draft-button"
onClick={handleSaveDraft}
onClick={(e) => handleDraftClick(e, tabs[tabIndex + 1])}
style={{ marginRight: 16 }}
>
Save Draft
</Button>
)}
<Button
type="primary"
htmlType="button"
disabled={isSubmitting}
onClick={(e) => handleNextClick(e, tabs[tabIndex + 1])}
>
{sectionChangeText ?? <>Save &amp; Continue</>}
{sectionChangeText}
<RightOutlined />
</Button>
</div>
)}
{isLast && (
<Button type="primary" disabled={isSubmitting} onClick={handleSaveData}>
{!isEditMode && !isLast && (
<Button type="primary" htmlType="button" onClick={() => setTabIndex(tabIndex + 1)}>
{nextText}
</Button>
)}
{isEditMode && isLast && (
<Button
type="primary"
onClick={(e) => handleNextClick(e, null)}
disabled={isSubmitting}
>
{submitText || "Submit"}
</Button>
)}
Expand All @@ -172,7 +228,4 @@ const SteppedForm = (props) => {
);
};

SteppedForm.propTypes = propTypes;
SteppedForm.defaultProps = defaultProps;

export default SteppedForm;
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { FC, useEffect, useState } from "react";
import { useSelector, useDispatch } from "react-redux";
import { Field, change, getFormValues } from "redux-form";
import { Col, Row, Typography, Alert } from "antd";
import { FORM } from "@mds/common";
import { FORM } from "@mds/common/constants/forms";
import RenderField from "@mds/common/components/forms/RenderField";
import RenderRadioButtons from "@mds/common/components/forms/RenderRadioButtons";
import RenderSelect from "@mds/common/components/forms/RenderSelect";
Expand All @@ -15,14 +15,15 @@ import {
requiredRadioButton,
} from "@mds/common/redux/utils/Validate";
import { getDropdownProvinceOptions } from "@mds/common/redux/selectors/staticContentSelectors";
import { CONTACTS_COUNTRY_OPTIONS, IOrgbookCredential } from "@mds/common";
import { IOrgbookCredential } from "@mds/common/interfaces/party";
import { CONTACTS_COUNTRY_OPTIONS } from "@mds/common/constants/strings";
import RenderOrgBookSearch from "@mds/common/components/forms/RenderOrgBookSearch";
import {
fetchOrgBookCredential,
verifyOrgBookCredential,
} from "@mds/common/redux/actionCreators/orgbookActionCreator";
import { getOrgBookCredential } from "@mds/common/redux/selectors/orgbookSelectors";
import { normalizePhone } from "@common/utils/helpers";
import { normalizePhone } from "@mds/common/redux/utils/helpers";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faCircleCheck, faCircleX, faSpinner } from "@fortawesome/pro-light-svg-icons";

Expand Down Expand Up @@ -260,15 +261,6 @@ export const Agent: FC = () => {
)}

<Row gutter={16}>
{/* TODO: With Orgbook integration, this should probably be the agent.party_name */}
{/* <Col md={12} sm={24}>
<Field
name="agent.doing_business_as"
label="Doing Business As"
component={RenderField}
help="if different than the Company Legal Name"
/>
</Col> */}
<Col md={12} sm={24}>
<Field name="agent.job_title" label="Agent's Title" component={RenderField} />
</Col>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ import {
requiredRadioButton,
} from "@mds/common/redux/utils/Validate";
import RenderRadioButtons from "@mds/common/components/forms/RenderRadioButtons";
import { CONTACTS_COUNTRY_OPTIONS, FORM, IOrgbookCredential } from "@mds/common";
import { FORM } from "@mds/common/constants/forms";
import { CONTACTS_COUNTRY_OPTIONS } from "@mds/common/constants/strings";
import { IOrgbookCredential } from "@mds/common/interfaces/party";
import RenderOrgBookSearch from "@mds/common/components/forms/RenderOrgBookSearch";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faCircleCheck, faCircleX, faSpinner } from "@fortawesome/pro-light-svg-icons";
Expand All @@ -23,7 +25,7 @@ import RenderField from "@mds/common/components/forms/RenderField";
import { getDropdownProvinceOptions } from "@mds/common/redux/selectors/staticContentSelectors";
import RenderSelect from "@mds/common/components/forms/RenderSelect";
import RenderCheckbox from "@mds/common/components/forms/RenderCheckbox";
import { normalizePhone } from "@common/utils/helpers";
import { normalizePhone } from "@mds/common/redux/utils/helpers";
import { getOrgBookCredential } from "@mds/common/redux/selectors/orgbookSelectors";

const { Title, Paragraph } = Typography;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { FORM } from "@mds/common";
import React, { FC, useEffect, useState } from "react";
import { getFormValues } from "redux-form";
import { useSelector } from "react-redux";
Expand All @@ -11,9 +10,9 @@ import { renderTextColumn } from "@mds/common/components/common/CoreTableCommonC
import CoreTable from "@mds/common/components/common/CoreTable";
import { ColumnsType } from "antd/es/table";
import { Button, Alert, Typography, Col, Row } from "antd";
import { EDIT_PROJECT_SUMMARY } from "@/constants/routes";
import { useHistory } from "react-router-dom";
import { getPermits } from "@mds/common/redux/selectors/permitSelectors";
import { FORM } from "@mds/common/constants/forms";

interface IAuthorizationSummaryColumn {
type: string;
Expand Down Expand Up @@ -221,7 +220,7 @@ export const ApplicationSummary: FC = () => {
const handleEditClicked = () => {
const projectGuid = formValues?.project_guid;
const projectSummaryGuid = formValues?.project_summary_guid;
const url = EDIT_PROJECT_SUMMARY.dynamicRoute(
const url = GLOBAL_ROUTES?.EDIT_PROJECT_SUMMARY.dynamicRoute(
projectGuid,
projectSummaryGuid,
"purpose-and-authorization"
Expand Down
Loading
Loading