From f9cca82014c7b56b5f2ca416ef606b472f7fa55f Mon Sep 17 00:00:00 2001 From: Kelly Innes Date: Fri, 21 Jun 2019 14:49:24 -0400 Subject: [PATCH] Add parent company to claim a facility - add parent_company field to facilityclaim model - add & use a parent company selection on the claim a facility form - display facility parent company on admin dashboard claim details page - display editable facility parent company on claimed facility profile form - display linked facility parent company on facility details page --- CHANGELOG.md | 1 + src/app/src/actions/claimFacility.js | 30 +++++++++ src/app/src/actions/claimedFacilityDetails.js | 2 + src/app/src/components/ClaimFacility.jsx | 21 ++++-- .../ClaimFacilityFacilityInfoStep.jsx | 65 ++++++++++++++++++- .../ClaimFacilityVerificationInfoStep.jsx | 14 ++++ .../components/ClaimedFacilitiesDetails.jsx | 45 ++++++++++++- .../src/components/DashboardClaimsDetails.jsx | 26 ++++++++ .../FacilityDetailSidebarClaimedInfo.jsx | 27 +++++++- src/app/src/reducers/ClaimFacilityReducer.js | 46 +++++++++++++ .../reducers/ClaimedFacilityDetailsReducer.js | 9 +++ src/app/src/util/constants.js | 4 ++ src/app/src/util/util.js | 1 + ...017_add_parent_company_to_facilityclaim.py | 24 +++++++ src/django/api/models.py | 7 ++ src/django/api/serializers.py | 44 ++++++++++++- src/django/api/views.py | 34 ++++++++++ 17 files changed, 385 insertions(+), 15 deletions(-) create mode 100644 src/django/api/migrations/0017_add_parent_company_to_facilityclaim.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b5500dfa..78c6f4f5f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Order facility claim notes from oldest to newest on dashboard [#596](https://github.com/open-apparel-registry/open-apparel-registry/pull/596) - Prevent users from submitting another claim for a facility when they have a first claim still pending [#601](https://github.com/open-apparel-registry/open-apparel-registry/pull/601) - Email contributors when facility claims are approved or claim profiles are updated [#611](https://github.com/open-apparel-registry/open-apparel-registry/pull/611) +- Add `parent_company` field to facility claims [#626](https://github.com/open-apparel-registry/open-apparel-registry/pull/626) ### Deprecated diff --git a/src/app/src/actions/claimFacility.js b/src/app/src/actions/claimFacility.js index fbff0b7fb..470342889 100644 --- a/src/app/src/actions/claimFacility.js +++ b/src/app/src/actions/claimFacility.js @@ -9,7 +9,9 @@ import { logErrorAndDispatchFailure, makeGetFacilityByOARIdURL, makeClaimFacilityAPIURL, + makeParentCompanyOptionsAPIURL, claimAFacilityFormIsValid, + mapDjangoChoiceTuplesToSelectOptions, } from '../util/util'; export const startFetchClaimFacilityData = createAction('START_FETCH_CLAIM_FACILITY_DATA'); @@ -40,6 +42,8 @@ export const updateClaimAFacilityPhoneNumber = createAction('UPDATE_CLAIM_A_FACILITY_PHONE_NUMBER'); export const updateClaimAFacilityCompany = createAction('UPDATE_CLAIM_A_FACILITY_COMPANY'); +export const updateClaimAFacilityParentCompany = + createAction('UPDATE_CLAIM_A_FACILITY_PARENT_COMPANY'); export const updateClaimAFacilityWebsite = createAction('UPDATE_CLAIM_A_FACILITY_WEBSITE'); export const updateClaimAFacilityDescription = @@ -73,6 +77,7 @@ export function submitClaimAFacilityData(oarID) { const postData = mapKeys( Object.assign({}, formData, { preferredContactMethod: get(formData, 'preferredContactMethod.value', null), + parentCompany: get(formData, 'parentCompany.value', null), }), (_, k) => snakeCase(k), ); @@ -89,3 +94,28 @@ export function submitClaimAFacilityData(oarID) { ))); }; } + +export const startFetchParentCompanyOptions = + createAction('START_FETCH_PARENT_COMPANY_OPTIONS'); +export const failFetchParentCompanyOptions = + createAction('FAIL_FETCH_PARENT_COMPANY_OPTIONS'); +export const completeFetchParentCompanyOptions = + createAction('COMPLETE_FETCH_PARENT_COMPANY_OPTIONS'); +export const resetParentCompanyOptions = + createAction('RESET_PARENT_COMPANY_OPTIONS'); + +export function fetchParentCompanyOptions() { + return (dispatch) => { + dispatch(startFetchParentCompanyOptions()); + + return csrfRequest + .get(makeParentCompanyOptionsAPIURL()) + .then(({ data }) => mapDjangoChoiceTuplesToSelectOptions(data)) + .then(data => dispatch(completeFetchParentCompanyOptions(data))) + .catch(err => dispatch(logErrorAndDispatchFailure( + err, + 'An error prevented fetching parent company options', + failFetchParentCompanyOptions, + ))); + }; +} diff --git a/src/app/src/actions/claimedFacilityDetails.js b/src/app/src/actions/claimedFacilityDetails.js index cae7d0591..813289685 100644 --- a/src/app/src/actions/claimedFacilityDetails.js +++ b/src/app/src/actions/claimedFacilityDetails.js @@ -115,3 +115,5 @@ export const updateClaimedFacilityOfficeCountry = createAction('UPDATE_CLAIMED_FACILITY_OFFICE_COUNTRY'); export const updateClaimedFacilityOfficePhone = createAction('UPDATE_CLAIMED_FACILITY_OFFICE_PHONE'); +export const updateClaimedFacilityParentCompany = + createAction('UPDATE_CLAIMED_FACILITY_PARENT_COMPANY'); diff --git a/src/app/src/components/ClaimFacility.jsx b/src/app/src/components/ClaimFacility.jsx index deb7cb138..953fb55ab 100644 --- a/src/app/src/components/ClaimFacility.jsx +++ b/src/app/src/components/ClaimFacility.jsx @@ -15,6 +15,7 @@ import ClaimFacilityStepper from '../components/ClaimFacilityStepper'; import { fetchClaimFacilityData, clearClaimFacilityDataAndForm, + fetchParentCompanyOptions, } from '../actions/claimFacility'; import { facilityDetailsPropType } from '../util/propTypes'; @@ -38,7 +39,7 @@ function ClaimFacility({ data, fetching, error, - getFacilityData, + getClaimData, clearClaimData, userHasSignedIn, match: { @@ -47,11 +48,13 @@ function ClaimFacility({ }, }, }) { + /* eslint-disable react-hooks/exhaustive-deps */ useEffect(() => { - getFacilityData(); + getClaimData(); return clearClaimData; - }, [getFacilityData, clearClaimData]); + }, []); + /* eslint-enable react-hooks/exhaustive-deps */ if (fetching) { return ; @@ -120,7 +123,7 @@ ClaimFacility.propTypes = { data: facilityDetailsPropType, fetching: bool.isRequired, error: arrayOf(string), - getFacilityData: func.isRequired, + getClaimData: func.isRequired, clearClaimData: func.isRequired, userHasSignedIn: bool.isRequired, }; @@ -128,6 +131,9 @@ ClaimFacility.propTypes = { function mapStateToProps({ claimFacility: { facilityData: { data, fetching, error }, + parentCompanyOptions: { + fetching: fetchingParentCompanyOptions, + }, }, auth: { user: { user }, @@ -136,7 +142,7 @@ function mapStateToProps({ }) { return { data, - fetching: fetching || sessionFetching, + fetching: fetching || sessionFetching || fetchingParentCompanyOptions, userHasSignedIn: !!user, error, }; @@ -151,7 +157,10 @@ function mapDispatchToProps( }, ) { return { - getFacilityData: () => dispatch(fetchClaimFacilityData(oarID)), + getClaimData: () => { + dispatch(fetchParentCompanyOptions()); + return dispatch(fetchClaimFacilityData(oarID)); + }, clearClaimData: () => dispatch(clearClaimFacilityDataAndForm()), }; } diff --git a/src/app/src/components/ClaimFacilityFacilityInfoStep.jsx b/src/app/src/components/ClaimFacilityFacilityInfoStep.jsx index 6e2b0a819..b2a08df8e 100644 --- a/src/app/src/components/ClaimFacilityFacilityInfoStep.jsx +++ b/src/app/src/components/ClaimFacilityFacilityInfoStep.jsx @@ -1,10 +1,11 @@ import React from 'react'; -import { bool, func, string } from 'prop-types'; +import { bool, func, number, shape, string } from 'prop-types'; import { connect } from 'react-redux'; import Typography from '@material-ui/core/Typography'; import TextField from '@material-ui/core/TextField'; import InputLabel from '@material-ui/core/InputLabel'; -import { isEmpty } from 'validator'; +import isEmpty from 'lodash/isEmpty'; +import Select from 'react-select'; import RequiredAsterisk from './RequiredAsterisk'; @@ -12,6 +13,7 @@ import { updateClaimAFacilityCompany, updateClaimAFacilityWebsite, updateClaimAFacilityDescription, + updateClaimAFacilityParentCompany, } from '../actions/claimFacility'; import { getValueFromEvent } from '../util/util'; @@ -20,12 +22,28 @@ import { claimAFacilityFormStyles } from '../util/styles'; import { claimAFacilityFormFields } from '../util/constants'; +import { contributorOptionsPropType } from '../util/propTypes'; + const { companyName: companyFormField, website: websiteFormField, facilityDescription: descriptionFormField, + parentCompany: parentCompanyFormField, } = claimAFacilityFormFields; +const selectStyles = Object.freeze({ + input: provided => + Object.freeze({ + ...provided, + padding: '10px', + }), + menu: provided => + Object.freeze({ + ...provided, + zIndex: '2', + }), +}); + function ClaimFacilityFacilityInfoStep({ companyName, updateCompany, @@ -34,6 +52,9 @@ function ClaimFacilityFacilityInfoStep({ facilityDescription, updateDescription, fetching, + contributorOptions, + parentCompany, + updateParentCompany, }) { return ( <> @@ -55,6 +76,27 @@ function ClaimFacilityFacilityInfoStep({ disabled={fetching} /> + { + contributorOptions && ( +
+ + + {parentCompanyFormField.label} + + +
+