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

Refactor the contact form to use React Router #6504

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 0 additions & 1 deletion src/apps/contacts/__test__/router.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ describe('Contacts router', () => {
it('should define contacts routes', () => {
const paths = router.stack.filter((r) => r.route).map((r) => r.route.path)
expect(paths).to.deep.equal([
['/create', '/:contactId/edit'],
'/export',
'/:contactId',
'/:contactId/details',
Expand Down
12 changes: 0 additions & 12 deletions src/apps/contacts/controllers/create-and-edit.js

This file was deleted.

3 changes: 0 additions & 3 deletions src/apps/contacts/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ const {
handleRoutePermissions,
} = require('../middleware')
const { getCommon, getDetails } = require('./controllers/details')
const createAndEdit = require('./controllers/create-and-edit')
const { unarchiveContact } = require('./controllers/archive')
const { getAudit } = require('./controllers/audit')
const { renderContactActivityForEntity } = require('./controllers/activity')
Expand All @@ -26,8 +25,6 @@ const {
fetchActivitiesForContact,
} = require('../companies/apps/activity-feed/controllers')

router.get(['/create', '/:contactId/edit'], createAndEdit)

router.get('/export', getRequestBody(QUERY_FIELDS), exportCollection('contact'))

router.use(
Expand Down
8 changes: 0 additions & 8 deletions src/apps/contacts/views/create-and-edit.njk

This file was deleted.

2 changes: 2 additions & 0 deletions src/apps/routers.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ const appsRouters = []
const reactRoutes = [
'/companies',
'/contacts',
'/contacts/create',
'/contacts/:contactId/edit',
'/events',
'/interactions',
'/omis',
Expand Down
1 change: 1 addition & 0 deletions src/client/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ export const EXPORT_WINS__SELECT_PAGE = 'EXPORT_WINS__SELECT_PAGE'
export const EXPORT_COUNTRIES_EDIT__SAVE = 'EXPORT_COUNTRIES_EDIT__SAVE'

export const FORM__LOADED = 'FORM__LOADED'
export const FORM__UNMOUNT = 'FORM__UNMOUNT'
export const FORM__FIELD_SET_VALUE = 'FORM__FIELD_SET_VALUE'
export const FORM__FIELD_TOUCHED = 'FORM__FIELD_TOUCHED'
export const FORM__FIELD_REGISTER = 'FORM__FIELD_REGISTER'
Expand Down
78 changes: 43 additions & 35 deletions src/client/components/ContactForm/index.jsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import qs from 'qs'
import React, { useEffect } from 'react'
import PropTypes from 'prop-types'
import _ from 'lodash'
import Link from '@govuk-react/link'
import { Switch, Route } from 'react-router-dom'
import { FONT_WEIGHTS, SPACING } from '@govuk-react/constants'
import styled from 'styled-components'
import Label from '@govuk-react/label'

import multiInstance from '../../utils/multiinstance'
import { CONTACT_FORM__SUBMIT } from '../../actions'
import Link from '@govuk-react/link'
import PropTypes from 'prop-types'
import _ from 'lodash'
import qs from 'qs'

import Form from '../Form'
import {
Expand All @@ -33,6 +31,7 @@ import {

import useAdministrativeAreaLookup from '../AdministrativeAreaSearch/useAdministrativeAreaLookup'
import useAdministrativeAreaSearch from '../AdministrativeAreaSearch/useAdministrativeAreaSearch'
import { getQueryParamsFromLocation } from '../../utils/url'
import urls from '../../../lib/urls'

const YES = 'Yes'
Expand Down Expand Up @@ -70,7 +69,7 @@ const StyledLabel = styled(Label)`
font-weight: ${FONT_WEIGHTS.bold};
`

const _ContactForm = ({
const ContactForm = ({
update,
contactId,
// Needed for linking the newly created contact to a company and breadcrumbs
Expand All @@ -88,8 +87,8 @@ const _ContactForm = ({
addressCountry,
// State props
dispatch,
id,
notes: moreDetails,
redirectMode = 'hard',
...props
}) => {
const findAdministrativeAreas = useAdministrativeAreaLookup()
Expand Down Expand Up @@ -219,14 +218,16 @@ const _ContactForm = ({
onSuccess={(
result,
values,
{ hardRedirect, flashMessage }
{ flashMessage, hardRedirect, softRedirect }
) => {
flashMessage(
update
? 'Contact record updated'
: `You have successfully added a new contact ${result.name}`
)
hardRedirect(redirectTo(result))
redirectMode === 'hard'
? hardRedirect(redirectTo(result))
: softRedirect(redirectTo(result))
}}
submitButtonLabel={
update ? 'Save and return' : 'Add contact'
Expand Down Expand Up @@ -361,20 +362,6 @@ const _ContactForm = ({
)
}

export const ContactForm = multiInstance({
name: 'ContactForm',
actionPattern: 'CONTACT_FORM__',
reducer: (state, { type }) => {
switch (type) {
case CONTACT_FORM__SUBMIT:
return {}
default:
return state
}
},
component: _ContactForm,
})

const requiredProps = {
update: PropTypes.any,
company: PropTypes.shape({
Expand All @@ -400,20 +387,24 @@ ContactForm.propTypes = {
addressCounty: PropTypes.string,
addressPostcode: PropTypes.string,
notes: PropTypes.string,
redirectMode: PropTypes.oneOf([
'hard', // window.location.href
'soft', // React Router
]),
}

export const CreateContactForm = ({ companyId, id }) => (
<ContactForm companyId={companyId} id={id} />
export const CreateContactForm = ({ companyId, redirectMode }) => (
<ContactForm companyId={companyId} redirectMode={redirectMode} />
)

CreateContactForm.propTypes = requiredProps

export const UpdateContactForm = ({ contactId, id }) => (
export const UpdateContactForm = ({ contactId, redirectMode }) => (
<ContactResource id={contactId}>
{(contact) => (
<ContactForm
{...contact}
id={id}
redirectMode={redirectMode}
contactId={contact.id}
update={true}
companyId={contact.company.id}
Expand All @@ -427,9 +418,26 @@ UpdateContactForm.propTypes = {
contactId: PropTypes.string.isRequired,
}

export default ({ contactId, companyId, id }) =>
contactId ? (
<UpdateContactForm contactId={contactId} id={id} />
) : (
<CreateContactForm companyId={companyId} id={id} />
)
export default () => (
<Switch>
<Route
exact={true}
paths={['/contacts/create', '/contacts/:contactId/edit']}
>
{({ location, match }) => {
const queryParams = getQueryParamsFromLocation(location)
return match.params.contactId ? (
<UpdateContactForm
contactId={match.params.contactId}
redirectMode={queryParams.redirect_mode}
/>
) : (
<CreateContactForm
companyId={queryParams.company}
redirectMode={queryParams.redirect_mode}
/>
)
}}
</Route>
</Switch>
)
37 changes: 25 additions & 12 deletions src/client/components/ContactInformation/index.jsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,45 @@
import React from 'react'
import { Link as ReactRouterLink } from 'react-router-dom'
import { Details, Link, Paragraph, ListItem, UnorderedList } from 'govuk-react'
import styled from 'styled-components'
import { SPACING_POINTS } from '@govuk-react/constants'
import styled from 'styled-components'

import urls from '../../../lib/urls'

const StyledDetails = styled(Details)`
margin-top: ${SPACING_POINTS[1]};
`

const ContactInformation = ({ onOpenContactForm, companyId }) => {
const ContactInformation = ({
onOpenContactForm,
companyId,
redirectMode = 'hard',
}) => {
const redirectUrl = urls.contacts.create(companyId, {
redirect_mode: redirectMode,
origin_url: window.location.pathname,
origin_search: btoa(window.location.search),
})
return (
<>
If your contact is not listed{' '}
<Link
data-test="add-a-new-contact-link"
onClick={(e) => {
e.preventDefault()
onOpenContactForm({ event: e, redirectUrl })
}}
href={redirectUrl}
>
add a new contact
</Link>
{redirectMode === 'hard' ? (
<Link
data-test="add-a-new-contact-link"
onClick={(e) => {
e.preventDefault()
onOpenContactForm({ event: e, redirectUrl })
}}
href={redirectUrl}
>
add a new contact
</Link>
) : (
// A soft redirect using React Router
<ReactRouterLink data-test="add-a-new-contact-link" to={redirectUrl}>
add a new contact
</ReactRouterLink>
)}
. You will leave this page to enter details, once added you will return
here. The information you added will have been saved.
<StyledDetails
Expand Down
6 changes: 6 additions & 0 deletions src/client/components/Form/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ const _Form = ({

useEffect(() => {
onLoad(initialValues, initialStepIndex)
return () => props.onUnmount(values)
}, [])
useEffect(() => {
scrollToTopOnStep && window.scrollTo(0, 0)
Expand Down Expand Up @@ -402,6 +403,11 @@ const dispatchToProps = (dispatch) => ({
initialValues,
initialStepIndex,
}),
onUnmount: (values) =>
dispatch({
type: 'FORM__UNMOUNT',
values,
}),
resetResolved: () =>
dispatch({
type: 'FORM__RESET_RESOLVED',
Expand Down
7 changes: 7 additions & 0 deletions src/client/components/Form/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
FORM__ERRORED,
FORM__FORWARD,
FORM__LOADED,
FORM__UNMOUNT,
FORM__RESOLVED,
FORM__STEP_DEREGISTER,
FORM__STEP_REGISTER,
Expand Down Expand Up @@ -36,6 +37,7 @@ export default (
values: {
...state.values,
...action.initialValues,
...state.previousValues,
},
currentStep: action.initialStepIndex,
}
Expand Down Expand Up @@ -124,6 +126,11 @@ export default (
currentStep: state.currentStep + 1,
previousValues: state.values,
}
case FORM__UNMOUNT:
return {
...state,
previousValues: state.values,
}
case FORM__BACK:
return {
...state,
Expand Down
4 changes: 0 additions & 4 deletions src/client/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ import CompanyHierarchy from './modules/Companies/CompanyHierarchy'

import Footer from '../client/components/Footer'

import ContactForm from '../client/components/ContactForm'
import { ProtectedRoute } from '../client/components'
import AddRemoveFromListForm from '../client/components/CompanyLists/AddRemoveFromListForm'

Expand Down Expand Up @@ -202,9 +201,6 @@ function App() {
)}
</Mount>
<Mount selector="#ie-banner">{() => <IEBanner />}</Mount>
<Mount selector="#contact-form">
{(props) => <ContactForm {...props} id="contact-form" />}
</Mount>
<Mount selector="#dashboard-local-header">
{(props) => (
<SearchLocalHeader
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react'
import { connect } from 'react-redux'
import { useLocation, withRouter } from 'react-router-dom'
import { connect } from 'react-redux'
import PropTypes from 'prop-types'

import urls from '../../../../lib/urls'
import { COMPANY_LOADED } from '../../../actions'
Expand Down Expand Up @@ -79,4 +80,8 @@ const ExportFormAdd = ({ exportItem }) => {
)
}

ExportFormAdd.propTypes = {
exportItem: PropTypes.object,
}

export default withRouter(connect(state2props)(ExportFormAdd))
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from 'react'
import { connect } from 'react-redux'
import PropTypes from 'prop-types'
import { useParams, withRouter } from 'react-router-dom'

import urls from '../../../../lib/urls'
Expand Down Expand Up @@ -64,4 +65,8 @@ const ExportFormEdit = ({ exportItem }) => {
)
}

ExportFormEdit.propTypes = {
exportItem: PropTypes.object,
}

export default withRouter(connect(state2props)(ExportFormEdit))
Loading
Loading