Skip to content

Commit

Permalink
Merge branch 'develop' into MDS-5976-ams-payment-contact-info
Browse files Browse the repository at this point in the history
  • Loading branch information
henryoforeh-dev committed Jun 13, 2024
2 parents 5e6635c + c8431da commit 1066597
Show file tree
Hide file tree
Showing 84 changed files with 2,710 additions and 3,461 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE party_verifiable_credential_connection ADD deleted_ind boolean default false;
2 changes: 1 addition & 1 deletion services/common/src/components/forms/FormWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ NOTABLE OMISSIONS:
SEE ALSO:
- BaseInput.tsx
*/
interface FormWrapperProps {
export interface FormWrapperProps {
name: string;
initialValues?: any;
reduxFormConfig?: Partial<ConfigProps>;
Expand Down
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>`
: `<div>Accepted filetypes: ${fileTypeDisplayString}</div>`;
return `${labelInstruction}<br>${secondLine}`;
};
Expand Down
1 change: 1 addition & 0 deletions services/common/src/components/forms/RenderSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ export const RenderSelect: FC<SelectProps> = ({
>
<Select
virtual={false}
data-cy={input.name}
disabled={disabled}
allowClear={allowClear}
dropdownMatchSelectWidth
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";

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,55 @@
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";
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, { FormWrapperProps } from "./FormWrapper";

interface SteppedFormProps extends Omit<FormWrapperProps, "onSubmit"> {
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> = ({
name,
initialValues,
children,
reduxFormConfig,
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(name));
const formErrors = useSelector((state) => getFormSyncErrors(name)(state));
const errors = Object.keys(flattenObject(formErrors));

useEffect(() => {
setTabIndex(tabs.indexOf(activeTab));
Expand All @@ -70,17 +71,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(name));
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 +103,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 +131,31 @@ 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={name}
onSubmit={() => {}}
initialValues={initialValues}
isEditMode={isEditMode}
reduxFormConfig={
reduxFormConfig ?? {
touchOnBlur: true,
touchOnChange: false,
enableReinitialize: true,
}
}
>
{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;
17 changes: 16 additions & 1 deletion services/common/src/components/parties/OrgBookSearch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,14 @@ import { IOrgbookCredential } from "@mds/common/interfaces";
interface OrgBookSearchProps {
isDisabled?: boolean;
setCredential: (credential: IOrgbookCredential) => void;
current_party: string;
}

const OrgBookSearch: FC<OrgBookSearchProps> = ({ isDisabled = false, setCredential }) => {
const OrgBookSearch: FC<OrgBookSearchProps> = ({
isDisabled = false,
setCredential,
current_party,
}) => {
const dispatch = useDispatch();

const searchOrgBookResults = useSelector(getSearchOrgBookResults);
Expand All @@ -28,6 +33,7 @@ const OrgBookSearch: FC<OrgBookSearchProps> = ({ isDisabled = false, setCredenti

const [options, setOptions] = useState([]);
const [isSearching, setIsSearching] = useState(false);
const [selectedParty, setSelectedParty] = useState(current_party);

const handleChange = () => {
setIsSearching(false);
Expand All @@ -54,6 +60,12 @@ const OrgBookSearch: FC<OrgBookSearchProps> = ({ isDisabled = false, setCredenti
setIsSearching(false);
};

useEffect(() => {
if (selectedParty !== current_party) {
setSelectedParty(undefined);
}
}, [current_party]);

useEffect(() => {
if (searchOrgBookResults) {
const selectOptions = searchOrgBookResults
Expand All @@ -69,6 +81,7 @@ const OrgBookSearch: FC<OrgBookSearchProps> = ({ isDisabled = false, setCredenti
const handleSelect = async (value) => {
const credentialId = value.key;
await dispatch(fetchOrgBookCredential(credentialId));
setSelectedParty(value.label);
};

useEffect(() => {
Expand All @@ -95,6 +108,8 @@ const OrgBookSearch: FC<OrgBookSearchProps> = ({ isDisabled = false, setCredenti
onSelect={handleSelect}
style={{ width: "100%" }}
disabled={isDisabled}
defaultValue={current_party}
value={selectedParty}
>
{options.map((option) => (
<Select.Option key={option.value}>{option.text}</Select.Option>
Expand Down
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
Loading

0 comments on commit 1066597

Please sign in to comment.