From 8622f39ed327e9e7597f04e11cd88c0f69fa5bab Mon Sep 17 00:00:00 2001 From: Arjun G <91885483+Arjun-Go@users.noreply.github.com> Date: Wed, 17 Jan 2024 18:33:12 +0530 Subject: [PATCH] A-1206201728816127 | Other Attributes handled through Configuration (#156) * update. Other information to handle configurable fields * handle visibilty of other attributes --- src/api/personApi.js | 13 + src/components/common/constants.js | 13 +- src/containers/CreatePerson.css | 6 + src/containers/CreatePerson.js | 331 +++++++--------------- src/containers/EditPerson.js | 423 ++++++++--------------------- 5 files changed, 240 insertions(+), 546 deletions(-) diff --git a/src/api/personApi.js b/src/api/personApi.js index 5d95b38..082ab8c 100644 --- a/src/api/personApi.js +++ b/src/api/personApi.js @@ -81,3 +81,16 @@ export async function updatePerson(uuid, payload) { return error.response; } } + +export async function fetchPersonAttributeConfig() { + try { + const url = Constants.registrationConfig; + return await fetch(url, { + method: 'GET', + credentials: 'include' + }); + } catch (error) { + console.error(error); + return error.response; + } +} diff --git a/src/components/common/constants.js b/src/components/common/constants.js index ca88590..65e1bf4 100644 --- a/src/components/common/constants.js +++ b/src/components/common/constants.js @@ -2,19 +2,12 @@ const hostUrl = localStorage.getItem('host') ? 'https://' + localStorage.getItem('host') : ''; const RESTWS_V1 = hostUrl + '/openmrs/ws/rest/v1'; +const bahmniConfig = hostUrl + '/bahmni_config'; export const Constants = { person: RESTWS_V1 + '/person', - personAttributeType: RESTWS_V1 + '/personattributetype' + personAttributeType: RESTWS_V1 + '/personattributetype', + registrationConfig: bahmniConfig + '/openmrs/apps/registration/app.json' }; export const genderOptions = ['', 'Male', 'Female', 'Other']; -export const personAttributes = { - organization: 'organization', - email: 'email', - mobilePhone: 'mobilePhone', - workPhone: 'workPhone', - residencePhone: 'residencePhone', - otherPhone: 'otherPhone', - occupation: 'occupationNew' -}; export const phoneNumberPattern = '[0-9]{10}'; export const emailPattern = '[a-z0-9._%+-]+@[a-z0-9.-]+.[a-z]{2,4}$'; diff --git a/src/containers/CreatePerson.css b/src/containers/CreatePerson.css index 532951b..0f3dd94 100644 --- a/src/containers/CreatePerson.css +++ b/src/containers/CreatePerson.css @@ -3,10 +3,16 @@ width: 80%; } +.other-attributes { + display: flex; + flex-wrap: wrap; +} + /* outer flex container with Name, Age, Gender sections */ .flex-container-row { display: flex; flex-wrap: wrap; + flex: 0 0 50%; width: 100%; padding-top: 10px; } diff --git a/src/containers/CreatePerson.js b/src/containers/CreatePerson.js index 6f3e735..11ae611 100644 --- a/src/containers/CreatePerson.js +++ b/src/containers/CreatePerson.js @@ -1,17 +1,16 @@ import moment from 'moment'; import React, { Component } from 'react'; -import { getPersonAttributeTypeUuid, savePerson } from '../api/personApi'; +import { + getPersonAttributeTypeUuid, + savePerson, + fetchPersonAttributeConfig +} from '../api/personApi'; import Button from '../components/common/Button'; import Checkbox from '../components/common/Checkbox'; import Dropdown from '../components/common/Dropdown'; import Input from '../components/common/Input'; import Navbar from '../components/common/Navbar'; -import { - emailPattern, - genderOptions, - personAttributes, - phoneNumberPattern -} from '../components/common/constants'; +import { genderOptions } from '../components/common/constants'; import ModalError from '../components/common/modals/ModalError'; import ModalSuccess from '../components/common/modals/ModalSuccess'; import './CreatePerson.css'; @@ -31,61 +30,51 @@ class CreatePerson extends Component { months: 0, days: 0 }, - birthdateEstimated: false, - organization: '', - email: '', - mobilePhone: '', - workPhone: '', - residencePhone: '', - otherPhone: '', - occupation: '' + birthdateEstimated: false }, showModal: false, isAPIError: false, isRequestError: false, isRequestLoading: false, lastCreatedPerson: '', - attributes: { - organizationUuid: '', - emailUuid: '', - mobilePhoneUuid: '', - workPhoneUuid: '', - residencePhoneUuid: '', - otherPhoneUuid: '', - occupationUuid: '' - } + attributes: [] }; this.handleClearForm = this.handleClearForm.bind(this); } componentDidMount() { - this.setPersonAttributeIDs(); - } + this.getAttributes().then(response => { + const attributes = response.config.personAttributesForRelations.map( + async attribute => { + const uuid = await getPersonAttributeTypeUuid( + attribute.attributeName + ); + return { + ...attribute, + value: '', + uuid: uuid + }; + } + ); - setPersonAttributeIDs = async () => { - this.setState({ - attributes: { - organizationUuid: await getPersonAttributeTypeUuid( - personAttributes.organization - ), - emailUuid: await getPersonAttributeTypeUuid(personAttributes.email), - mobilePhoneUuid: await getPersonAttributeTypeUuid( - personAttributes.mobilePhone - ), - workPhoneUuid: await getPersonAttributeTypeUuid( - personAttributes.workPhone - ), - residencePhoneUuid: await getPersonAttributeTypeUuid( - personAttributes.residencePhone - ), - otherPhoneUuid: await getPersonAttributeTypeUuid( - personAttributes.otherPhone - ), - occupationUuid: await getPersonAttributeTypeUuid( - personAttributes.occupation - ) - } + Promise.all(attributes).then(resolvedAttributes => { + this.setState({ + attributes: resolvedAttributes + }); + }); }); + } + + getAttributes = async () => { + const response = await fetchPersonAttributeConfig(); + if (response.status === 200) { + return response.json(); + } else { + return Promise.reject({ + status: response.status, + statusText: response.statusText + }); + } }; handleChange = ({ target: input }) => { @@ -115,6 +104,15 @@ class CreatePerson extends Component { this.setState({ person }); }; + handleOtherAttributesChange = ({ target: input }) => { + const attributes = [...this.state.attributes]; + const index = attributes.findIndex( + attribute => attribute.name === input.name + ); + attributes[index].value = input.value; + this.setState({ attributes }); + }; + handleCheckbox = ({ target: input }) => { const person = { ...this.state.person }; person[input.name] = input.checked; @@ -133,13 +131,6 @@ class CreatePerson extends Component { firstName: '', middleName: '', lastName: '', - organization: '', - email: '', - mobilePhone: '', - workPhone: '', - residencePhone: '', - otherPhone: '', - occupation: '', gender: '', birthdate: moment(), age: { @@ -151,6 +142,10 @@ class CreatePerson extends Component { }, isRequestError: false }); + this.state.attributes.map(attribute => { + attribute.value = ''; + return attribute; + }); } isVoided = value => { @@ -176,17 +171,20 @@ class CreatePerson extends Component { middleName, lastName, gender, - organization, - email, - mobilePhone, - workPhone, - residencePhone, - otherPhone, - occupation, birthdate, birthdateEstimated } = this.state.person; + const attributes = this.state.attributes.map(attribute => { + return { + attributeType: { + uuid: attribute.uuid + }, + voided: this.isVoided(attribute.value), + value: attribute.value + }; + }); + const formPayload = { names: [ { @@ -199,57 +197,7 @@ class CreatePerson extends Component { birthdate: birthdate + 'T12:00:00.000+0000', age: moment.duration(moment().diff(birthdate)).years(), birthdateEstimated, - attributes: [ - { - attributeType: { - uuid: this.state.attributes.organizationUuid - }, - voided: this.isVoided(organization), - value: organization - }, - { - attributeType: { - uuid: this.state.attributes.emailUuid - }, - voided: this.isVoided(email), - value: email - }, - { - attributeType: { - uuid: this.state.attributes.mobilePhoneUuid - }, - voided: this.isVoided(mobilePhone), - value: mobilePhone - }, - { - attributeType: { - uuid: this.state.attributes.workPhoneUuid - }, - voided: this.isVoided(workPhone), - value: workPhone - }, - { - attributeType: { - uuid: this.state.attributes.residencePhoneUuid - }, - voided: this.isVoided(residencePhone), - value: residencePhone - }, - { - attributeType: { - uuid: this.state.attributes.otherPhoneUuid - }, - voided: this.isVoided(otherPhone), - value: otherPhone - }, - { - attributeType: { - uuid: this.state.attributes.occupationUuid - }, - voided: this.isVoided(occupation), - value: occupation - } - ] + attributes: attributes }; return formPayload; }; @@ -323,16 +271,10 @@ class CreatePerson extends Component { middleName, lastName, gender, - organization, - email, - mobilePhone, - workPhone, - residencePhone, - otherPhone, - occupation, birthdate, birthdateEstimated } = this.state.person; + const personAttributes = this.state.attributes; const { years, months, days } = this.state.person.age; @@ -500,123 +442,54 @@ class CreatePerson extends Component { -
-
-
- Other Information + {personAttributes.length > 0 && ( +
+
+
+
+ Other Information + {personAttributes.map(attribute => { + return ( +
+
+ +
+
+ ); + })} +
+
+
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-
-
-
-
-
-
-
-
-
+ )} {modal} diff --git a/src/containers/EditPerson.js b/src/containers/EditPerson.js index 4e81ebd..6af44cd 100644 --- a/src/containers/EditPerson.js +++ b/src/containers/EditPerson.js @@ -3,19 +3,15 @@ import React, { Component } from 'react'; import { fetchPerson, getPersonAttributeTypeUuid, - updatePerson + updatePerson, + fetchPersonAttributeConfig } from '../api/personApi'; import Button from '../components/common/Button'; import Checkbox from '../components/common/Checkbox'; import Dropdown from '../components/common/Dropdown'; import Input from '../components/common/Input'; import Navbar from '../components/common/Navbar'; -import { - emailPattern, - genderOptions, - personAttributes, - phoneNumberPattern -} from '../components/common/constants'; +import { genderOptions } from '../components/common/constants'; import ModalError from '../components/common/modals/ModalError'; import ModalSuccess from '../components/common/modals/ModalSuccess'; import './EditPerson.css'; @@ -31,62 +27,56 @@ class EditPerson extends Component { lastName: '', gender: '', birthdate: moment(), - birthdateEstimated: false, - organization: '', - email: '', - mobilePhone: '', - workPhone: '', - residencePhone: '', - otherPhone: '', - occupation: '' + birthdateEstimated: false }, showModal: false, isAPIError: false, isRequestError: false, isRequestLoading: false, lastUpdatedPerson: '', - attributes: { - organizationUuid: '', - emailUuid: '', - mobilePhoneUuid: '', - workPhoneUuid: '', - residencePhoneUuid: '', - otherPhoneUuid: '', - occupationUuid: '' - } + attributes: [], + attributesData: [] }; this.handleClearForm = this.handleClearForm.bind(this); } componentDidMount() { - this.setPersonAttributeIDs(); - this.loadPersonData(); - } + this.getAttributes().then(response => { + const attributes = response.config.personAttributesForRelations.map( + async attribute => { + const uuid = await getPersonAttributeTypeUuid( + attribute.attributeName + ); + return { + ...attribute, + value: '', + uuid: uuid + }; + } + ); - setPersonAttributeIDs = async () => { - this.setState({ - attributes: { - organizationUuid: await getPersonAttributeTypeUuid( - personAttributes.organization - ), - emailUuid: await getPersonAttributeTypeUuid(personAttributes.email), - mobilePhoneUuid: await getPersonAttributeTypeUuid( - personAttributes.mobilePhone - ), - workPhoneUuid: await getPersonAttributeTypeUuid( - personAttributes.workPhone - ), - residencePhoneUuid: await getPersonAttributeTypeUuid( - personAttributes.residencePhone - ), - otherPhoneUuid: await getPersonAttributeTypeUuid( - personAttributes.otherPhone - ), - occupationUuid: await getPersonAttributeTypeUuid( - personAttributes.occupation - ) - } + Promise.all(attributes) + .then(resolvedAttributes => { + this.setState({ + attributes: resolvedAttributes + }); + }) + .then(() => { + this.loadPersonData(); + }); }); + } + + getAttributes = async () => { + const response = await fetchPersonAttributeConfig(); + if (response.status === 200) { + return response.json(); + } else { + return Promise.reject({ + status: response.status, + statusText: response.statusText + }); + } }; loadPersonData = async () => { @@ -119,7 +109,10 @@ class EditPerson extends Component { birthdateEstimated: data.birthdateEstimated } }); - data.attributes && this.setPersonAttributeValues(data.attributes); + if (data.attributes != []) { + this.setState({ attributesData: data.attributes }); + this.setPersonAttributeValues(data.attributes); + } }); }; @@ -138,73 +131,16 @@ class EditPerson extends Component { setPersonAttributeValues = attributes => { attributes.forEach(attribute => { - switch (attribute.display.split(' = ')[0]) { - case personAttributes.organization: { - this.setState({ - person: { - ...this.state.person, - organization: attribute.display.split(' = ')[1] - } - }); - break; - } - case personAttributes.email: { - this.setState({ - person: { - ...this.state.person, - email: attribute.display.split(' = ')[1] - } - }); - break; - } - case personAttributes.mobilePhone: { - this.setState({ - person: { - ...this.state.person, - mobilePhone: attribute.display.split(' = ')[1] - } - }); - break; - } - case personAttributes.workPhone: { - this.setState({ - person: { - ...this.state.person, - workPhone: attribute.display.split(' = ')[1] - } - }); - break; - } - case personAttributes.residencePhone: { - this.setState({ - person: { - ...this.state.person, - residencePhone: attribute.display.split(' = ')[1] - } - }); - break; - } - case personAttributes.otherPhone: { - this.setState({ - person: { - ...this.state.person, - otherPhone: attribute.display.split(' = ')[1] - } - }); - break; - } - case personAttributes.occupation: { - this.setState({ - person: { - ...this.state.person, - occupation: attribute.display.split(' = ')[1] - } - }); - break; - } - default: - break; - } + const attributeName = attribute.display.split(' = ')[0]; + const attributeValue = attribute.display.split(' = ')[1]; + this.setState(prevState => ({ + attributes: prevState.attributes.map(stateAttribute => { + if (stateAttribute.attributeName === attributeName) { + return { ...stateAttribute, value: attributeValue }; + } + return stateAttribute; + }) + })); }); }; @@ -234,16 +170,8 @@ class EditPerson extends Component { }; handleClearForm() { + this.setPersonAttributeValues(this.state.attributesData); this.setState({ - person: { - organization: '', - email: '', - mobilePhone: '', - workPhone: '', - residencePhone: '', - otherPhone: '', - occupation: '' - }, isRequestError: false }); } @@ -258,17 +186,20 @@ class EditPerson extends Component { middleName, lastName, gender, - organization, - email, - mobilePhone, - workPhone, - residencePhone, - otherPhone, - occupation, birthdate, birthdateEstimated } = this.state.person; + const attributes = this.state.attributes.map(attribute => { + return { + attributeType: { + uuid: attribute.uuid + }, + voided: this.isVoided(attribute.value), + value: !this.isVoided(attribute.value) ? attribute.value : null + }; + }); + const formPayload = { names: [ { @@ -279,68 +210,11 @@ class EditPerson extends Component { ], gender, birthdateEstimated, - attributes: [ - { - attributeType: { - uuid: this.state.attributes.organizationUuid - }, - voided: this.isVoided(organization), - value: organization - }, - { - attributeType: { - uuid: this.state.attributes.emailUuid - }, - voided: this.isVoided(email), - value: email - }, - { - attributeType: { - uuid: this.state.attributes.mobilePhoneUuid - }, - voided: this.isVoided(mobilePhone), - value: mobilePhone - }, - { - attributeType: { - uuid: this.state.attributes.workPhoneUuid - }, - voided: this.isVoided(workPhone), - value: workPhone - }, - { - attributeType: { - uuid: this.state.attributes.residencePhoneUuid - }, - voided: this.isVoided(residencePhone), - value: residencePhone - }, - { - attributeType: { - uuid: this.state.attributes.otherPhoneUuid - }, - voided: this.isVoided(otherPhone), - value: otherPhone - }, - { - attributeType: { - uuid: this.state.attributes.occupationUuid - }, - voided: this.isVoided(occupation), - value: occupation - } - ] + attributes: attributes }; if (this.isVoided(birthdate)) { formPayload.birthdate = birthdate + 'T12:00:00.000+0000'; } - this.isVoided(organization) && delete formPayload.attributes[0].value; - this.isVoided(email) && delete formPayload.attributes[1].value; - this.isVoided(mobilePhone) && delete formPayload.attributes[2].value; - this.isVoided(workPhone) && delete formPayload.attributes[3].value; - this.isVoided(residencePhone) && delete formPayload.attributes[4].value; - this.isVoided(otherPhone) && delete formPayload.attributes[5].value; - this.isVoided(occupation) && delete formPayload.attributes[6].value; return formPayload; }; @@ -350,6 +224,15 @@ class EditPerson extends Component { this.updateRequest(payload); }; + handleOtherAttributesChange = ({ target: input }) => { + const attributes = [...this.state.attributes]; + const index = attributes.findIndex( + attribute => attribute.name === input.name + ); + attributes[index].value = input.value; + this.setState({ attributes }); + }; + updateRequest(formPayload) { const { firstName, lastName } = this.state.person; this.setState({ @@ -412,13 +295,6 @@ class EditPerson extends Component { middleName, lastName, gender, - organization, - email, - mobilePhone, - workPhone, - residencePhone, - otherPhone, - occupation, birthdate, birthdateEstimated } = this.state.person; @@ -430,6 +306,8 @@ class EditPerson extends Component { lastUpdatedPerson: lastCreatedPerson } = this.state; + const personAttributes = this.state.attributes; + const isEnabled = !isRequestLoading; let modal = null; @@ -582,123 +460,54 @@ class EditPerson extends Component { -
-
-
- Other Information + {personAttributes.length > 0 && ( +
+
+
+
+ Other Information + {personAttributes.map(attribute => { + return ( +
+
+ +
+
+ ); + })} +
+
+
- -
-
- -
-
- -
-
-
- -
-
- -
-
-
-
-
-
-
-
-
-
-
-
+ )} {modal}