Make optional fields configurable (#234)

Making optional fields configurable will help us in enabling and disabling
fields as required.

VAN-405
This commit is contained in:
Zainab Amir
2021-04-07 15:23:05 +05:00
committed by Waheed Ahmed
parent acb0f23f0a
commit 43e0372be5
4 changed files with 76 additions and 69 deletions

View File

@@ -23,7 +23,7 @@ AUTHN_MINIMAL_HEADER=true
LOGIN_ISSUE_SUPPORT_LINK=''
TOS_AND_HONOR_CODE='http://localhost:18000/honor'
PRIVACY_POLICY='http://localhost:18000/privacy'
REGISTRATION_OPTIONAL_FIELDS='gender,goals,level_of_education,year_of_birth'
REGISTRATION_OPTIONAL_FIELDS='gender,goals,levelOfEducation,yearOfBirth'
USER_SURVEY_COOKIE_NAME='openedx-user-survey-type'
COOKIE_DOMAIN='localhost'
WELCOME_PAGE_SUPPORT_LINK='http://localhost:1999/welcome'

View File

@@ -9,7 +9,9 @@ import messages from './messages';
import { AuthnValidationFormGroup } from '../common-components';
const OptionalFields = (props) => {
const { intl, onChangeHandler, values } = props;
const {
intl, optionalFields, onChangeHandler, values,
} = props;
const getOptions = () => ({
yearOfBirthOptions: [{
@@ -28,59 +30,65 @@ const OptionalFields = (props) => {
return (
<>
<AuthnValidationFormGroup
label={intl.formatMessage(messages['registration.field.gender.options.label'])}
for="gender"
name="gender"
type="select"
key="gender"
value={values.gender}
className="mb-20 opt-inline-field data-hj-suppress"
onChange={(e) => onChangeHandler('gender', e.target.value)}
selectOptions={getOptions().genderOptions}
inputFieldStyle="border-gray-600 custom-select-size"
/>
<AuthnValidationFormGroup
label={intl.formatMessage(messages['registration.year.of.birth.label'])}
for="yearOfBirth"
name="yearOfBirth"
type="select"
key="yearOfBirth"
value={values.yearOfBirth}
className="mb-20 opt-inline-field opt-year-field data-hj-suppress"
onChange={(e) => onChangeHandler('yearOfBirth', e.target.value)}
selectOptions={getOptions().yearOfBirthOptions}
inputFieldStyle="border-gray-600 custom-select-size"
/>
<AuthnValidationFormGroup
label={intl.formatMessage(messages['registration.field.education.levels.label'])}
for="levelOfEducation"
name="levelOfEducation"
type="select"
key="levelOfEducation"
value={values.levelOfEducation}
className="mb-20 data-hj-suppress"
onChange={(e) => onChangeHandler('levelOfEducation', e.target.value)}
selectOptions={getOptions().educationLevelOptions}
inputFieldStyle="border-gray-600 custom-select-size"
/>
<AuthnValidationFormGroup
label={intl.formatMessage(messages['registration.goals.label'])}
for="goals"
name="goals"
type="textarea"
key="goals"
value={values.goals}
className="mb-20"
onChange={(e) => onChangeHandler('goals', e.target.value)}
inputFieldStyle="border-gray-600 custom-select-size"
/>
{optionalFields.includes('gender') && (
<AuthnValidationFormGroup
label={intl.formatMessage(messages['registration.field.gender.options.label'])}
for="gender"
name="gender"
type="select"
key="gender"
value={values.gender}
className="mb-20 data-hj-suppress"
onChange={(e) => onChangeHandler('gender', e.target.value)}
selectOptions={getOptions().genderOptions}
/>
)}
{optionalFields.includes('yearOfBirth') && (
<AuthnValidationFormGroup
label={intl.formatMessage(messages['registration.year.of.birth.label'])}
for="yearOfBirth"
name="yearOfBirth"
type="select"
key="yearOfBirth"
value={values.yearOfBirth}
className="mb-20 data-hj-suppress"
onChange={(e) => onChangeHandler('yearOfBirth', e.target.value)}
selectOptions={getOptions().yearOfBirthOptions}
/>
)}
{optionalFields.includes('levelOfEducation') && (
<AuthnValidationFormGroup
label={intl.formatMessage(messages['registration.field.education.levels.label'])}
for="levelOfEducation"
name="levelOfEducation"
type="select"
key="levelOfEducation"
value={values.levelOfEducation}
className="mb-20 data-hj-suppress"
onChange={(e) => onChangeHandler('levelOfEducation', e.target.value)}
selectOptions={getOptions().educationLevelOptions}
/>
)}
{optionalFields.includes('goals') && (
<AuthnValidationFormGroup
label={intl.formatMessage(messages['registration.goals.label'])}
for="goals"
name="goals"
type="textarea"
key="goals"
value={values.goals}
className="mb-20"
onChange={(e) => onChangeHandler('goals', e.target.value)}
inputFieldStyle="border-gray-600"
/>
)}
</>
);
};
OptionalFields.propTypes = {
intl: intlShape.isRequired,
optionalFields: PropTypes.arrayOf(PropTypes.string).isRequired,
onChangeHandler: PropTypes.func.isRequired,
values: PropTypes.shape({
gender: PropTypes.string,

View File

@@ -1,6 +1,6 @@
import React from 'react';
import camelCase from 'lodash.camelcase';
import snakeCase from 'lodash.snakecase';
import { connect } from 'react-redux';
import Skeleton from 'react-loading-skeleton';
import { Helmet } from 'react-helmet';
@@ -44,16 +44,14 @@ class RegistrationPage extends React.Component {
this.queryParams = getAllPossibleQueryParam();
this.tpaHint = getTpaHint();
const optionalFields = getConfig().REGISTRATION_OPTIONAL_FIELDS ? getConfig().REGISTRATION_OPTIONAL_FIELDS.split(',') : [];
this.state = {
email: '',
name: '',
username: '',
password: '',
country: '',
gender: '',
yearOfBirth: '',
goals: '',
levelOfEducation: '',
enableOptionalField: false,
validationAlertMessages: {
name: [{ user_message: '' }],
@@ -71,6 +69,8 @@ class RegistrationPage extends React.Component {
},
institutionLogin: false,
formValid: false,
optionalFields,
optionalFieldsState: {},
startTime: Date.now(),
updateFieldErrors: false,
updateAlertErrors: false,
@@ -144,16 +144,17 @@ class RegistrationPage extends React.Component {
}
getOptionalFields() {
const values = {};
const optionalFields = getConfig().REGISTRATION_OPTIONAL_FIELDS.split(',');
optionalFields.forEach((key) => {
values[camelCase(key)] = this.state[camelCase(key)];
});
return (
<OptionalFields
values={values}
onChangeHandler={(fieldName, value) => { this.setState({ [fieldName]: value }); }}
optionalFields={this.state.optionalFields}
values={this.state.optionalFieldsState}
onChangeHandler={
(fieldName, value) => {
this.setState(prevState => ({
optionalFieldsState: { ...prevState.optionalFieldsState, [fieldName]: value },
}));
}
}
/>
);
}
@@ -190,11 +191,9 @@ class RegistrationPage extends React.Component {
}
// Since optional fields are not validated we can add it to payload after required fields
// have been validated. This will save us unwanted calls to validateInput()
const optionalFields = getConfig().REGISTRATION_OPTIONAL_FIELDS.split(',');
optionalFields.forEach((key) => {
const stateKey = camelCase(key);
if (this.state[stateKey]) {
payload[key] = this.state[stateKey];
this.state.optionalFields.forEach((key) => {
if (this.state.optionalFieldsState[key]) {
payload[snakeCase(key)] = this.state.optionalFieldsState[key];
}
});
if (finalValidation) {

View File

@@ -27,7 +27,7 @@ const mockStore = configureStore();
describe('RegistrationPageTests', () => {
mergeConfig({
PRIVACY_POLICY: 'http://privacy-policy.com',
REGISTRATION_OPTIONAL_FIELDS: 'gender,goals,level_of_education,year_of_birth',
REGISTRATION_OPTIONAL_FIELDS: 'gender,goals,levelOfEducation,yearOfBirth',
TOS_AND_HONOR_CODE: 'http://tos-and-honot-code.com',
USER_SURVEY_COOKIE_NAME: process.env.USER_SURVEY_COOKIE_NAME,
});
@@ -189,7 +189,7 @@ describe('RegistrationPageTests', () => {
expect(registrationPage.find('input#optional').length).toEqual(0);
mergeConfig({
REGISTRATION_OPTIONAL_FIELDS: 'gender,goals,level_of_education,year_of_birth',
REGISTRATION_OPTIONAL_FIELDS: 'gender,goals,levelOfEducation,yearOfBirth',
});
registrationPage = mount(reduxWrapper(<IntlRegistrationPage {...props} />));