diff --git a/src/account-settings/AccountSettingsPage.jsx b/src/account-settings/AccountSettingsPage.jsx
index e55952a..5e3f9e7 100644
--- a/src/account-settings/AccountSettingsPage.jsx
+++ b/src/account-settings/AccountSettingsPage.jsx
@@ -5,43 +5,50 @@ import { injectIntl, intlShape } from 'react-intl';
import messages from './AccountSettingsPage.messages';
-import { fetchAccount, openForm, closeForm, saveAccount } from './actions';
+import { fetchAccount } from './actions';
import { pageSelector } from './selectors';
import { PageLoading } from '../common';
import EditableField from './components/EditableField';
-
+import { yearOfBirthOptions, yearOfBirthDefault } from './constants';
class AccountSettingsPage extends React.Component {
componentDidMount() {
this.props.fetchAccount();
}
- renderSection({
- sectionHeading, sectionDescription, fields,
- }) {
- return (
-
-
{this.props.intl.formatMessage(sectionHeading)}
-
{this.props.intl.formatMessage(sectionDescription)}
- {fields.map(field => (
-
- ), this)}
-
- );
- }
-
renderContent() {
return (
- {this.props.fieldSections.map(this.renderSection, this)}
+
{this.props.intl.formatMessage(messages['account.settings.section.account.information'])}
+
{this.props.intl.formatMessage(messages['account.settings.section.account.information.description'])}
+
+
+
+
+
@@ -89,73 +96,16 @@ AccountSettingsPage.propTypes = {
loading: PropTypes.bool,
loaded: PropTypes.bool,
loadingError: PropTypes.string,
- openFormId: PropTypes.string,
- fieldSections: PropTypes.arrayOf(PropTypes.shape({
- sectionHeading: PropTypes.object,
- sectionDescription: PropTypes.object,
- fields: PropTypes.array,
- })),
-
fetchAccount: PropTypes.func.isRequired,
- openForm: PropTypes.func.isRequired,
- closeForm: PropTypes.func.isRequired,
- saveAccount: PropTypes.func.isRequired,
};
AccountSettingsPage.defaultProps = {
loading: false,
loaded: false,
loadingError: null,
- openFormId: null,
- fieldSections: [
- {
- sectionHeading: messages['account.settings.section.account.information'],
- sectionDescription: messages['account.settings.section.account.information.description'],
- fields: [
- {
- name: 'username',
- isEditable: false,
- label: messages['account.settings.field.username'],
- type: 'text',
- },
- {
- name: 'name',
- isEditable: true,
- label: messages['account.settings.field.full.name'],
- type: 'text',
- },
- {
- name: 'email',
- isEditable: true,
- label: messages['account.settings.field.email'],
- type: 'email',
- },
- {
- name: 'year_of_birth',
- isEditable: true,
- label: messages['account.settings.field.dob'],
- type: 'select',
- options: (() => {
- const currentYear = new Date().getFullYear();
- const years = [];
- let startYear = currentYear - 120;
- while (startYear < currentYear) {
- startYear += 1;
- years.push({ value: startYear, label: startYear });
- }
- return years.reverse();
- })(),
- defaultValue: new Date().getFullYear() - 35,
- },
- ],
- },
- ],
};
export default connect(pageSelector, {
fetchAccount,
- openForm,
- closeForm,
- saveAccount,
})(injectIntl(AccountSettingsPage));
diff --git a/src/account-settings/AccountSettingsPage.messages.jsx b/src/account-settings/AccountSettingsPage.messages.jsx
index 4660b22..a70c2aa 100644
--- a/src/account-settings/AccountSettingsPage.messages.jsx
+++ b/src/account-settings/AccountSettingsPage.messages.jsx
@@ -31,6 +31,11 @@ const messages = defineMessages({
defaultMessage: 'Email address (Sign in)',
description: 'Label for account settings email field.',
},
+ 'account.settings.field.email.confirmation': {
+ id: 'account.settings.field.email.confirmation',
+ defaultMessage: 'We’ve sent a confirmation message to {value}. Click the link in the message to update your email address.',
+ description: 'Confirmation message for saving the account settings email field.',
+ },
'account.settings.field.dob': {
id: 'account.settings.field.dob',
defaultMessage: 'Year of birth',
diff --git a/src/account-settings/actions.js b/src/account-settings/actions.js
index f189905..ae5d585 100644
--- a/src/account-settings/actions.js
+++ b/src/account-settings/actions.js
@@ -69,9 +69,9 @@ export const saveAccountBegin = () => ({
type: SAVE_ACCOUNT.BEGIN,
});
-export const saveAccountSuccess = values => ({
+export const saveAccountSuccess = (values, confirmationValues) => ({
type: SAVE_ACCOUNT.SUCCESS,
- payload: { values },
+ payload: { values, confirmationValues },
});
export const saveAccountReset = () => ({
diff --git a/src/account-settings/components/EditableField.jsx b/src/account-settings/components/EditableField.jsx
index 3928dd0..7076a74 100644
--- a/src/account-settings/components/EditableField.jsx
+++ b/src/account-settings/components/EditableField.jsx
@@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
-import { FormattedMessage } from 'react-intl';
+import { FormattedMessage, injectIntl, intlShape } from 'react-intl';
import { Button } from '@edx/paragon';
import Input from './temp/Input';
@@ -25,6 +25,8 @@ function EditableField(props) {
type,
value,
error,
+ confirmationMessageDefinition,
+ confirmationValue,
helpText,
onEdit,
onCancel,
@@ -32,6 +34,7 @@ function EditableField(props) {
onChange,
isEditing,
isEditable,
+ intl,
...others
} = props;
const id = `field-${name}`;
@@ -55,6 +58,11 @@ function EditableField(props) {
onCancel(name);
};
+ const renderConfirmationMessage = () => {
+ if (!confirmationMessageDefinition || !confirmationValue) return null;
+ return intl.formatMessage(confirmationMessageDefinition, { value: confirmationValue });
+ };
+
return (
{value}
- {helpText}
+ {renderConfirmationMessage() || helpText}
),
}}
@@ -128,6 +136,12 @@ EditableField.propTypes = {
type: PropTypes.string.isRequired,
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
error: PropTypes.string,
+ confirmationMessageDefinition: PropTypes.shape({
+ id: PropTypes.string.isRequired,
+ defaultMessage: PropTypes.string.isRequired,
+ description: PropTypes.string,
+ }),
+ confirmationValue: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
helpText: PropTypes.node,
onEdit: PropTypes.func.isRequired,
onCancel: PropTypes.func.isRequired,
@@ -135,11 +149,14 @@ EditableField.propTypes = {
onChange: PropTypes.func.isRequired,
isEditing: PropTypes.bool,
isEditable: PropTypes.bool,
+ intl: intlShape.isRequired,
};
EditableField.defaultProps = {
value: undefined,
error: undefined,
+ confirmationMessageDefinition: undefined,
+ confirmationValue: undefined,
helpText: undefined,
isEditing: false,
isEditable: true,
@@ -151,4 +168,4 @@ export default connect(formSelector, {
onCancel: closeForm,
onChange: updateDraft,
onSubmit: saveAccount,
-})(EditableField);
+})(injectIntl(EditableField));
diff --git a/src/account-settings/constants.js b/src/account-settings/constants.js
new file mode 100644
index 0000000..79085d9
--- /dev/null
+++ b/src/account-settings/constants.js
@@ -0,0 +1,13 @@
+
+export const yearOfBirthOptions = (() => {
+ const currentYear = new Date().getFullYear();
+ const years = [];
+ let startYear = currentYear - 120;
+ while (startYear < currentYear) {
+ startYear += 1;
+ years.push({ value: startYear, label: startYear });
+ }
+ return years.reverse();
+})();
+
+export const yearOfBirthDefault = new Date().getFullYear() - 35;
diff --git a/src/account-settings/reducers.js b/src/account-settings/reducers.js
index cc8e671..f0de4e5 100644
--- a/src/account-settings/reducers.js
+++ b/src/account-settings/reducers.js
@@ -14,6 +14,7 @@ export const defaultState = {
data: null,
values: {},
errors: {},
+ confirmationValues: {},
drafts: {},
saveState: null,
};
@@ -95,6 +96,11 @@ const accountSettingsReducer = (state = defaultState, action) => {
saveState: 'complete',
values: Object.assign({}, state.values, action.payload.values),
errors: {},
+ confirmationValues: Object.assign(
+ {},
+ state.confirmationValues,
+ action.payload.confirmationValues,
+ ),
};
case SAVE_ACCOUNT.FAILURE:
return {
diff --git a/src/account-settings/sagas.js b/src/account-settings/sagas.js
index c7f312a..380213a 100644
--- a/src/account-settings/sagas.js
+++ b/src/account-settings/sagas.js
@@ -41,8 +41,7 @@ export function* handleSaveAccount(action) {
const username = yield select(getUsername);
const { commitValues } = action.payload;
const savedValues = yield call(ApiService.patchAccount, username, commitValues);
-
- yield put(saveAccountSuccess(savedValues));
+ yield put(saveAccountSuccess(savedValues, commitValues));
yield put(closeForm(action.payload.formId));
} catch (e) {
if (e.fieldErrors) {
diff --git a/src/account-settings/selectors.js b/src/account-settings/selectors.js
index 269bd65..40d8d7a 100644
--- a/src/account-settings/selectors.js
+++ b/src/account-settings/selectors.js
@@ -12,5 +12,7 @@ export const formSelector = (state, props) => {
return {
value,
error: state[storeName].errors[props.name],
+ confirmationValue: state[storeName].confirmationValues[props.name],
+ isEditing: state[storeName].openFormId === props.name,
};
};