fix: verify parity (#25)

* fix: style and order update

* fix: password reset sends email along with request

* fix: add best guess for help text
This commit is contained in:
Adam Butterworth
2019-05-10 13:17:37 -06:00
committed by GitHub
parent efb99185e3
commit cfe1be3361
9 changed files with 90 additions and 46 deletions

6
package-lock.json generated
View File

@@ -1009,9 +1009,9 @@
"integrity": "sha512-APBpZvdQrC1MJWMzk33V7FR2RhBRtnH2QPLqZzS+qia7PixwgWNlnX7UfHjhx+YWkM53GdsZKs40EBkSwADuMA=="
},
"@edx/edx-bootstrap": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@edx/edx-bootstrap/-/edx-bootstrap-2.0.1.tgz",
"integrity": "sha512-tq9ScRJBkUYw+0ypTshd+9+9Hnow00FkS6Rvh0RfK4xZ+rh8wNAUIVkG3TMclaW5qxvXSIE7Qo7YO7i7JrqV6A==",
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@edx/edx-bootstrap/-/edx-bootstrap-2.1.0.tgz",
"integrity": "sha512-9/CkIP1IsldKvOAS/T2OYeBnyuNWwX+u5GVR1kxw1YUCQbFw0W2M/Nz0HbIhG82H4O64uQqfdxnd1QpRJn07LA==",
"requires": {
"bootstrap": "^4.3.1"
}

View File

@@ -25,7 +25,7 @@
},
"dependencies": {
"@cospired/i18n-iso-languages": "^2.0.2",
"@edx/edx-bootstrap": "^2.0.1",
"@edx/edx-bootstrap": "^2.1.0",
"@edx/frontend-analytics": "^1.0.0",
"@edx/frontend-auth": "^5.2.0",
"@edx/frontend-component-footer": "^2.0.3",

View File

@@ -68,7 +68,9 @@ class AccountSettingsPage extends React.Component {
<div>
<div className="row">
<div className="col-md-8 col-lg-6">
<h2>{this.props.intl.formatMessage(messages['account.settings.section.account.information'])}</h2>
<h2 className="h4">{this.props.intl.formatMessage(messages['account.settings.section.account.information'])}</h2>
<p>{this.props.intl.formatMessage(messages['account.settings.section.account.information.description'])}</p>
<EditableField
@@ -76,6 +78,7 @@ class AccountSettingsPage extends React.Component {
type="text"
value={this.props.formValues.username}
label={this.props.intl.formatMessage(messages['account.settings.field.username'])}
helpText={this.props.intl.formatMessage(messages['account.settings.field.username.help.text'])}
isEditable={false}
{...editableFieldProps}
/>
@@ -84,6 +87,7 @@ class AccountSettingsPage extends React.Component {
type="text"
value={this.props.formValues.name}
label={this.props.intl.formatMessage(messages['account.settings.field.full.name'])}
helpText={this.props.intl.formatMessage(messages['account.settings.field.full.name.help.text'])}
{...editableFieldProps}
/>
<EmailField
@@ -91,8 +95,10 @@ class AccountSettingsPage extends React.Component {
label={this.props.intl.formatMessage(messages['account.settings.field.email'])}
value={this.props.formValues.email}
confirmationMessageDefinition={messages['account.settings.field.email.confirmation']}
helpText={this.props.intl.formatMessage(messages['account.settings.field.email.help.text'])}
{...editableFieldProps}
/>
<PasswordReset />
<EditableField
name="year_of_birth"
type="select"
@@ -101,16 +107,6 @@ class AccountSettingsPage extends React.Component {
options={YEAR_OF_BIRTH_OPTIONS}
{...editableFieldProps}
/>
<PasswordReset />
<EditableField
name="siteLanguage"
type="select"
options={this.props.siteLanguageOptions}
value={this.props.siteLanguage}
label={this.props.intl.formatMessage(messages['account.settings.field.site.language'])}
helpText={this.props.intl.formatMessage(messages['account.settings.field.site.language.help.text'])}
{...editableFieldProps}
/>
<EditableField
name="country"
type="select"
@@ -119,6 +115,10 @@ class AccountSettingsPage extends React.Component {
label={this.props.intl.formatMessage(messages['account.settings.field.country'])}
{...editableFieldProps}
/>
<h2 className="h4">{this.props.intl.formatMessage(messages['account.settings.section.profile.information'])}</h2>
<EditableField
name="level_of_education"
type="select"
@@ -143,10 +143,11 @@ class AccountSettingsPage extends React.Component {
label={this.props.intl.formatMessage(messages['account.settings.field.language.proficiencies'])}
{...editableFieldProps}
/>
<ThirdPartyAuth />
<h2>{this.props.intl.formatMessage(messages['account.settings.section.social.media'])}</h2>
<h2 className="h4">{this.props.intl.formatMessage(messages['account.settings.section.social.media'])}</h2>
<p>{this.props.intl.formatMessage(messages['account.settings.section.social.media.description'])}</p>
<EditableField
name="social_link_linkedin"
type="text"
@@ -168,6 +169,19 @@ class AccountSettingsPage extends React.Component {
label={this.props.intl.formatMessage(messages['account.settings.field.social.platform.name.twitter'])}
{...editableFieldProps}
/>
<h2 className="h4">{this.props.intl.formatMessage(messages['account.settings.section.site.preferences'])}</h2>
<EditableField
name="siteLanguage"
type="select"
options={this.props.siteLanguageOptions}
value={this.props.siteLanguage}
label={this.props.intl.formatMessage(messages['account.settings.field.site.language'])}
helpText={this.props.intl.formatMessage(messages['account.settings.field.site.language.help.text'])}
{...editableFieldProps}
/>
<EditableField
name="time_zone"
type="select"
@@ -181,6 +195,12 @@ class AccountSettingsPage extends React.Component {
this.handleSubmit(formId, value || null);
}}
/>
<h2 className="h4">{this.props.intl.formatMessage(messages['account.settings.section.linked.accounts'])}</h2>
<p>{this.props.intl.formatMessage(messages['account.settings.section.linked.accounts.description'])}</p>
<ThirdPartyAuth />
</div>
</div>
</div>

View File

@@ -26,16 +26,46 @@ const messages = defineMessages({
defaultMessage: 'These settings include basic information about your account.',
description: 'The basic account information section heading description.',
},
'account.settings.section.profile.information': {
id: 'account.settings.section.profile.information',
defaultMessage: 'Profile Information',
description: 'The profile information section heading.',
},
'account.settings.section.site.preferences': {
id: 'account.settings.section.site.preferences',
defaultMessage: 'Site Preferences',
description: 'The site preferences section heading.',
},
'account.settings.section.linked.accounts': {
id: 'account.settings.section.linked.accounts',
defaultMessage: 'Linked Accounts',
description: 'The linked accounts section heading.',
},
'account.settings.section.linked.accounts.description': {
id: 'account.settings.section.linked.accounts.description',
defaultMessage: 'You can link your identity accounts to simplify signing in to edX.',
description: 'The linked accounts section heading description.',
},
'account.settings.field.username': {
id: 'account.settings.field.username',
defaultMessage: 'Username',
description: 'Label for account settings username field.',
},
'account.settings.field.username.help.text': {
id: 'account.settings.field.username.help.text',
defaultMessage: 'The name that identifies you on edX. You cannot change your username.',
description: 'Help text for the account settings username field.',
},
'account.settings.field.full.name': {
id: 'account.settings.field.full.name',
defaultMessage: 'Full name',
description: 'Label for account settings name field.',
},
'account.settings.field.full.name.help.text': {
id: 'account.settings.field.full.name.help.text',
defaultMessage: 'The name that is used for ID verification and that appears on your certificates.',
description: 'Help text for the account settings name field.',
},
'account.settings.field.email': {
id: 'account.settings.field.email',
defaultMessage: 'Email address (Sign in)',
@@ -46,6 +76,11 @@ const messages = defineMessages({
defaultMessage: 'Weve 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.email.help.text': {
id: 'account.settings.field.email.help.text',
defaultMessage: 'You receive messages from edX and course teams at this address.',
description: 'Help text for the account settings email field.',
},
'account.settings.email.field.confirmation.header': {
id: 'account.settings.email.field.confirmation.header',
defaultMessage: 'One more step!',

View File

@@ -89,8 +89,9 @@ export const saveSettingsFailure = ({ fieldErrors, message }) => ({
// RESET PASSWORD ACTIONS
export const resetPassword = () => ({
export const resetPassword = email => ({
type: RESET_PASSWORD.BASE,
payload: { email },
});
export const resetPasswordBegin = () => ({

View File

@@ -54,7 +54,17 @@ function PasswordReset({ email, intl, ...props }) {
<StatefulButton
className="btn-link"
state={props.resetPasswordState}
onClick={props.resetPassword}
onClick={(e) => {
// Swallow clicks if the state is pending.
// We do this instead of disabling the button to prevent
// it from losing focus (disabled elements cannot have focus).
// Disabling it would causes upstream issues in focus management.
// Swallowing the onSubmit event on the form would be better, but
// we would have to add that logic for every field given our
// current structure of the application.
if (props.resetPasswordState === 'pending') e.preventDefault();
props.resetPassword(email);
}}
disabledStates={[]}
labels={{
default: intl.formatMessage(messages['account.settings.editable.field.password.reset.button']),

View File

@@ -72,7 +72,7 @@ class ThirdPartyAuth extends React.Component {
);
}
renderProviders() {
render() {
if (this.props.providers === undefined) return null;
if (this.props.providers.length === 0) {
@@ -81,28 +81,6 @@ class ThirdPartyAuth extends React.Component {
return this.props.providers.map(this.renderProvider, this);
}
render() {
return (
<div>
<h2>
<FormattedMessage
id="account.settings.sso.section.header"
defaultMessage="Linked Accounts"
description="Section header for the third party auth settings"
/>
</h2>
<p>
<FormattedMessage
id="account.settings.sso.section.subheader"
defaultMessage="You can link your identity accounts to simplify signing in to edX."
description="Section subheader for the third party auth settings"
/>
</p>
{this.renderProviders()}
</div>
);
}
}

View File

@@ -73,10 +73,10 @@ export function* handleSaveSettings(action) {
}
}
export function* handleResetPassword() {
export function* handleResetPassword(action) {
try {
yield put(resetPasswordBegin());
const response = yield call(ApiService.postResetPassword);
const response = yield call(ApiService.postResetPassword, action.payload.email);
yield put(resetPasswordSuccess(response));
} catch (e) {
logAPIErrorResponse(e);

View File

@@ -173,9 +173,9 @@ export async function patchSettings(username, commitValues) {
return combinedResults;
}
export async function postResetPassword() {
export async function postResetPassword(email) {
const { data } = await apiClient
.post(config.PASSWORD_RESET_URL)
.post(config.PASSWORD_RESET_URL, { email })
.catch(handleRequestError);
return data;