Compare commits
1 Commits
split-full
...
abutterwor
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ad85e2cebc |
6849
package-lock.json
generated
6849
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -12,7 +12,7 @@
|
|||||||
"build": "fedx-scripts webpack",
|
"build": "fedx-scripts webpack",
|
||||||
"i18n_extract": "BABEL_ENV=i18n fedx-scripts babel src --quiet > /dev/null",
|
"i18n_extract": "BABEL_ENV=i18n fedx-scripts babel src --quiet > /dev/null",
|
||||||
"is-es5": "es-check es5 ./dist/*.js",
|
"is-es5": "es-check es5 ./dist/*.js",
|
||||||
"lint": "fedx-scripts eslint",
|
"lint": "fedx-scripts eslint . --ext .js,.jsx",
|
||||||
"snapshot": "fedx-scripts jest --updateSnapshot",
|
"snapshot": "fedx-scripts jest --updateSnapshot",
|
||||||
"start": "fedx-scripts webpack-dev-server --progress",
|
"start": "fedx-scripts webpack-dev-server --progress",
|
||||||
"test": "fedx-scripts jest --coverage --passWithNoTests"
|
"test": "fedx-scripts jest --coverage --passWithNoTests"
|
||||||
@@ -73,7 +73,7 @@
|
|||||||
"universal-cookie": "4.0.3"
|
"universal-cookie": "4.0.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@edx/frontend-build": "2.0.6",
|
"@edx/frontend-build": "3.1.14",
|
||||||
"codecov": "3.6.5",
|
"codecov": "3.6.5",
|
||||||
"enzyme": "3.10.0",
|
"enzyme": "3.10.0",
|
||||||
"enzyme-adapter-react-16": "1.15.2",
|
"enzyme-adapter-react-16": "1.15.2",
|
||||||
|
|||||||
@@ -105,16 +105,6 @@ class AccountSettingsPage extends React.Component {
|
|||||||
})),
|
})),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
isEditable(fieldName) {
|
|
||||||
return !this.props.staticFields.includes(fieldName);
|
|
||||||
}
|
|
||||||
|
|
||||||
isManagedProfile() {
|
|
||||||
// Enterprise customer profiles are managed by their organizations. We determine whether
|
|
||||||
// a profile is managed or not by the presence of the profileDataManager prop.
|
|
||||||
return Boolean(this.props.profileDataManager);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleEditableFieldChange = (name, value) => {
|
handleEditableFieldChange = (name, value) => {
|
||||||
this.props.updateDraft(name, value);
|
this.props.updateDraft(name, value);
|
||||||
};
|
};
|
||||||
@@ -123,6 +113,17 @@ class AccountSettingsPage extends React.Component {
|
|||||||
this.props.saveSettings(formId, values);
|
this.props.saveSettings(formId, values);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
isManagedProfile() {
|
||||||
|
// Enterprise customer profiles are managed by their organizations. We determine whether
|
||||||
|
// a profile is managed or not by the presence of the profileDataManager prop.
|
||||||
|
return Boolean(this.props.profileDataManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
isEditable(fieldName) {
|
||||||
|
return !this.props.staticFields.includes(fieldName);
|
||||||
|
}
|
||||||
|
|
||||||
renderDuplicateTpaProviderMessage() {
|
renderDuplicateTpaProviderMessage() {
|
||||||
if (!this.state.duplicateTpaProvider) {
|
if (!this.state.duplicateTpaProvider) {
|
||||||
return null;
|
return null;
|
||||||
@@ -224,7 +225,7 @@ class AccountSettingsPage extends React.Component {
|
|||||||
const hasLinkedTPA = findIndex(this.props.tpaProviders, provider => provider.connected) >= 0;
|
const hasLinkedTPA = findIndex(this.props.tpaProviders, provider => provider.connected) >= 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<>
|
||||||
<div className="account-section" id="basic-information">
|
<div className="account-section" id="basic-information">
|
||||||
<h2 className="section-heading">
|
<h2 className="section-heading">
|
||||||
{this.props.intl.formatMessage(messages['account.settings.section.account.information'])}
|
{this.props.intl.formatMessage(messages['account.settings.section.account.information'])}
|
||||||
@@ -247,9 +248,9 @@ class AccountSettingsPage extends React.Component {
|
|||||||
value={this.props.formValues.name}
|
value={this.props.formValues.name}
|
||||||
label={this.props.intl.formatMessage(messages['account.settings.field.full.name'])}
|
label={this.props.intl.formatMessage(messages['account.settings.field.full.name'])}
|
||||||
emptyLabel={
|
emptyLabel={
|
||||||
this.isEditable('name') ?
|
this.isEditable('name')
|
||||||
this.props.intl.formatMessage(messages['account.settings.field.full.name.empty']) :
|
? this.props.intl.formatMessage(messages['account.settings.field.full.name.empty'])
|
||||||
this.renderEmptyStaticFieldMessage()
|
: this.renderEmptyStaticFieldMessage()
|
||||||
}
|
}
|
||||||
helpText={this.props.intl.formatMessage(messages['account.settings.field.full.name.help.text'])}
|
helpText={this.props.intl.formatMessage(messages['account.settings.field.full.name.help.text'])}
|
||||||
isEditable={this.isEditable('name')}
|
isEditable={this.isEditable('name')}
|
||||||
@@ -259,9 +260,9 @@ class AccountSettingsPage extends React.Component {
|
|||||||
name="email"
|
name="email"
|
||||||
label={this.props.intl.formatMessage(messages['account.settings.field.email'])}
|
label={this.props.intl.formatMessage(messages['account.settings.field.email'])}
|
||||||
emptyLabel={
|
emptyLabel={
|
||||||
this.isEditable('email') ?
|
this.isEditable('email')
|
||||||
this.props.intl.formatMessage(messages['account.settings.field.email.empty']) :
|
? this.props.intl.formatMessage(messages['account.settings.field.email.empty'])
|
||||||
this.renderEmptyStaticFieldMessage()
|
: this.renderEmptyStaticFieldMessage()
|
||||||
}
|
}
|
||||||
value={this.props.formValues.email}
|
value={this.props.formValues.email}
|
||||||
confirmationMessageDefinition={messages['account.settings.field.email.confirmation']}
|
confirmationMessageDefinition={messages['account.settings.field.email.confirmation']}
|
||||||
@@ -287,9 +288,9 @@ class AccountSettingsPage extends React.Component {
|
|||||||
options={countryOptions}
|
options={countryOptions}
|
||||||
label={this.props.intl.formatMessage(messages['account.settings.field.country'])}
|
label={this.props.intl.formatMessage(messages['account.settings.field.country'])}
|
||||||
emptyLabel={
|
emptyLabel={
|
||||||
this.isEditable('country') ?
|
this.isEditable('country')
|
||||||
this.props.intl.formatMessage(messages['account.settings.field.country.empty']) :
|
? this.props.intl.formatMessage(messages['account.settings.field.country.empty'])
|
||||||
this.renderEmptyStaticFieldMessage()
|
: this.renderEmptyStaticFieldMessage()
|
||||||
}
|
}
|
||||||
isEditable={this.isEditable('country')}
|
isEditable={this.isEditable('country')}
|
||||||
{...editableFieldProps}
|
{...editableFieldProps}
|
||||||
@@ -328,14 +329,15 @@ class AccountSettingsPage extends React.Component {
|
|||||||
emptyLabel={this.props.intl.formatMessage(messages['account.settings.field.language.proficiencies.empty'])}
|
emptyLabel={this.props.intl.formatMessage(messages['account.settings.field.language.proficiencies.empty'])}
|
||||||
{...editableFieldProps}
|
{...editableFieldProps}
|
||||||
/>
|
/>
|
||||||
{getConfig().COACHING_ENABLED &&
|
{getConfig().COACHING_ENABLED
|
||||||
this.props.formValues.coaching.eligible_for_coaching &&
|
&& this.props.formValues.coaching.eligible_for_coaching
|
||||||
|
&& (
|
||||||
<CoachingToggle
|
<CoachingToggle
|
||||||
name="coaching"
|
name="coaching"
|
||||||
phone_number={this.props.formValues.phone_number}
|
phone_number={this.props.formValues.phone_number}
|
||||||
coaching={this.props.formValues.coaching}
|
coaching={this.props.formValues.coaching}
|
||||||
/>
|
/>
|
||||||
}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="account-section" id="social-media">
|
<div className="account-section" id="social-media">
|
||||||
@@ -414,7 +416,7 @@ class AccountSettingsPage extends React.Component {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</React.Fragment>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,9 @@ import React from 'react';
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||||
import { Button, Input, StatefulButton, ValidationFormGroup } from '@edx/paragon';
|
import {
|
||||||
|
Button, Input, StatefulButton, ValidationFormGroup,
|
||||||
|
} from '@edx/paragon';
|
||||||
import { faPencilAlt } from '@fortawesome/free-solid-svg-icons';
|
import { faPencilAlt } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
|
|
||||||
@@ -65,20 +67,20 @@ function EditableField(props) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const renderValue = (rawValue) => {
|
const renderValue = (rawValue) => {
|
||||||
if (!rawValue) return renderEmptyLabel();
|
if (!rawValue) { return renderEmptyLabel(); }
|
||||||
|
|
||||||
if (options) {
|
if (options) {
|
||||||
// Use == instead of === to prevent issues when HTML casts numbers as strings
|
// Use == instead of === to prevent issues when HTML casts numbers as strings
|
||||||
// eslint-disable-next-line eqeqeq
|
// eslint-disable-next-line eqeqeq
|
||||||
const selectedOption = options.find(option => option.value == rawValue);
|
const selectedOption = options.find(option => option.value == rawValue);
|
||||||
if (selectedOption) return selectedOption.label;
|
if (selectedOption) { return selectedOption.label; }
|
||||||
}
|
}
|
||||||
|
|
||||||
return rawValue;
|
return rawValue;
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderConfirmationMessage = () => {
|
const renderConfirmationMessage = () => {
|
||||||
if (!confirmationMessageDefinition || !confirmationValue) return null;
|
if (!confirmationMessageDefinition || !confirmationValue) { return null; }
|
||||||
return intl.formatMessage(confirmationMessageDefinition, {
|
return intl.formatMessage(confirmationMessageDefinition, {
|
||||||
value: confirmationValue,
|
value: confirmationValue,
|
||||||
});
|
});
|
||||||
@@ -123,7 +125,7 @@ function EditableField(props) {
|
|||||||
// Swallowing the onSubmit event on the form would be better, but
|
// Swallowing the onSubmit event on the form would be better, but
|
||||||
// we would have to add that logic for every field given our
|
// we would have to add that logic for every field given our
|
||||||
// current structure of the application.
|
// current structure of the application.
|
||||||
if (saveState === 'pending') e.preventDefault();
|
if (saveState === 'pending') { e.preventDefault(); }
|
||||||
}}
|
}}
|
||||||
disabledStates={[]}
|
disabledStates={[]}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -2,7 +2,9 @@ import React from 'react';
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { injectIntl, intlShape, FormattedMessage } from '@edx/frontend-platform/i18n';
|
import { injectIntl, intlShape, FormattedMessage } from '@edx/frontend-platform/i18n';
|
||||||
import { Button, StatefulButton, Input, ValidationFormGroup } from '@edx/paragon';
|
import {
|
||||||
|
Button, StatefulButton, Input, ValidationFormGroup,
|
||||||
|
} from '@edx/paragon';
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import { faExclamationTriangle, faPencilAlt } from '@fortawesome/free-solid-svg-icons';
|
import { faExclamationTriangle, faPencilAlt } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
|
||||||
@@ -56,7 +58,7 @@ function EmailField(props) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const renderConfirmationMessage = () => {
|
const renderConfirmationMessage = () => {
|
||||||
if (!confirmationMessageDefinition || !confirmationValue) return null;
|
if (!confirmationMessageDefinition || !confirmationValue) { return null; }
|
||||||
return (
|
return (
|
||||||
<Alert
|
<Alert
|
||||||
className="alert-warning mt-n2"
|
className="alert-warning mt-n2"
|
||||||
@@ -91,7 +93,7 @@ function EmailField(props) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const renderValue = () => {
|
const renderValue = () => {
|
||||||
if (confirmationValue) return renderConfirmationValue();
|
if (confirmationValue) { return renderConfirmationValue(); }
|
||||||
return value || renderEmptyLabel();
|
return value || renderEmptyLabel();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -132,7 +134,7 @@ function EmailField(props) {
|
|||||||
// Swallowing the onSubmit event on the form would be better, but
|
// Swallowing the onSubmit event on the form would be better, but
|
||||||
// we would have to add that logic for every field given our
|
// we would have to add that logic for every field given our
|
||||||
// current structure of the application.
|
// current structure of the application.
|
||||||
if (saveState === 'pending') e.preventDefault();
|
if (saveState === 'pending') { e.preventDefault(); }
|
||||||
}}
|
}}
|
||||||
disabledStates={[]}
|
disabledStates={[]}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ const onChildExit = (htmlNode) => {
|
|||||||
const enteringChild = htmlNode.previousSibling || htmlNode.nextSibling;
|
const enteringChild = htmlNode.previousSibling || htmlNode.nextSibling;
|
||||||
|
|
||||||
// There's no replacement, do nothing.
|
// There's no replacement, do nothing.
|
||||||
if (!enteringChild) return;
|
if (!enteringChild) { return; }
|
||||||
|
|
||||||
// Get all the focusable elements in the entering child and focus the first one
|
// Get all the focusable elements in the entering child and focus the first one
|
||||||
const focusableElements = enteringChild.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');
|
const focusableElements = enteringChild.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');
|
||||||
@@ -29,7 +29,7 @@ function SwitchContent({ expression, cases, className }) {
|
|||||||
return getContent(cases[caseKey]);
|
return getContent(cases[caseKey]);
|
||||||
}
|
}
|
||||||
return React.cloneElement(cases[caseKey], { key: caseKey });
|
return React.cloneElement(cases[caseKey], { key: caseKey });
|
||||||
} else if (cases.default) {
|
} if (cases.default) {
|
||||||
if (typeof cases.default === 'string') {
|
if (typeof cases.default === 'string') {
|
||||||
return getContent(cases.default);
|
return getContent(cases.default);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,11 +47,12 @@ const reducer = (state = defaultState, action) => {
|
|||||||
case FETCH_SETTINGS.SUCCESS:
|
case FETCH_SETTINGS.SUCCESS:
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
values: Object.assign({}, state.values, action.payload.values),
|
values: { ...state.values, ...action.payload.values },
|
||||||
// Dump the providers into thirdPartyAuth.
|
// Dump the providers into thirdPartyAuth.
|
||||||
thirdPartyAuth: Object.assign({}, state.thirdPartyAuth, {
|
thirdPartyAuth: {
|
||||||
|
...state.thirdPartyAuth,
|
||||||
providers: action.payload.thirdPartyAuthProviders,
|
providers: action.payload.thirdPartyAuthProviders,
|
||||||
}),
|
},
|
||||||
profileDataManager: action.payload.profileDataManager,
|
profileDataManager: action.payload.profileDataManager,
|
||||||
timeZones: action.payload.timeZones,
|
timeZones: action.payload.timeZones,
|
||||||
loading: false,
|
loading: false,
|
||||||
@@ -96,9 +97,10 @@ const reducer = (state = defaultState, action) => {
|
|||||||
case UPDATE_DRAFT:
|
case UPDATE_DRAFT:
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
drafts: Object.assign({}, state.drafts, {
|
drafts: {
|
||||||
|
...state.drafts,
|
||||||
[action.payload.name]: action.payload.value,
|
[action.payload.name]: action.payload.value,
|
||||||
}),
|
},
|
||||||
saveState: null,
|
saveState: null,
|
||||||
errors: {},
|
errors: {},
|
||||||
};
|
};
|
||||||
@@ -119,19 +121,18 @@ const reducer = (state = defaultState, action) => {
|
|||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
saveState: 'complete',
|
saveState: 'complete',
|
||||||
values: Object.assign({}, state.values, action.payload.values),
|
values: { ...state.values, ...action.payload.values },
|
||||||
errors: {},
|
errors: {},
|
||||||
confirmationValues: Object.assign(
|
confirmationValues: {
|
||||||
{},
|
...state.confirmationValues,
|
||||||
state.confirmationValues,
|
...action.payload.confirmationValues,
|
||||||
action.payload.confirmationValues,
|
},
|
||||||
),
|
|
||||||
};
|
};
|
||||||
case SAVE_SETTINGS.FAILURE:
|
case SAVE_SETTINGS.FAILURE:
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
saveState: 'error',
|
saveState: 'error',
|
||||||
errors: Object.assign({}, state.errors, action.payload.errors),
|
errors: { ...state.errors, ...action.payload.errors },
|
||||||
};
|
};
|
||||||
case SAVE_SETTINGS.RESET:
|
case SAVE_SETTINGS.RESET:
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import { call, put, delay, takeEvery, all } from 'redux-saga/effects';
|
import {
|
||||||
|
call, put, delay, takeEvery, all,
|
||||||
|
} from 'redux-saga/effects';
|
||||||
|
|
||||||
import { publish } from '@edx/frontend-platform';
|
import { publish } from '@edx/frontend-platform';
|
||||||
import { getLocale, handleRtl, LOCALE_CHANGED } from '@edx/frontend-platform/i18n';
|
import { getLocale, handleRtl, LOCALE_CHANGED } from '@edx/frontend-platform/i18n';
|
||||||
@@ -48,7 +50,9 @@ export function* handleFetchSettings() {
|
|||||||
userId,
|
userId,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (values.country) yield put(fetchTimeZones(values.country));
|
if (values.country) {
|
||||||
|
yield put(fetchTimeZones(values.country));
|
||||||
|
}
|
||||||
|
|
||||||
yield put(fetchSettingsSuccess({
|
yield put(fetchSettingsSuccess({
|
||||||
values,
|
values,
|
||||||
@@ -87,7 +91,9 @@ export function* handleSaveSettings(action) {
|
|||||||
savedValues = yield call(patchSettings, username, commitData, userId);
|
savedValues = yield call(patchSettings, username, commitData, userId);
|
||||||
}
|
}
|
||||||
yield put(saveSettingsSuccess(savedValues, commitData));
|
yield put(saveSettingsSuccess(savedValues, commitData));
|
||||||
if (savedValues.country) yield put(fetchTimeZones(savedValues.country));
|
if (savedValues.country) {
|
||||||
|
yield put(fetchTimeZones(savedValues.country));
|
||||||
|
}
|
||||||
yield delay(1000);
|
yield delay(1000);
|
||||||
yield put(closeForm(action.payload.formId));
|
yield put(closeForm(action.payload.formId));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
@@ -41,7 +41,9 @@ function packAccountCommitData(commitData) {
|
|||||||
|
|
||||||
SOCIAL_PLATFORMS.forEach(({ id, key }) => {
|
SOCIAL_PLATFORMS.forEach(({ id, key }) => {
|
||||||
// Skip missing values. Empty strings are valid values and should be preserved.
|
// Skip missing values. Empty strings are valid values and should be preserved.
|
||||||
if (commitData[key] === undefined) return;
|
if (commitData[key] === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
packedData.social_links = [{ platform: id, social_link: commitData[key] }];
|
packedData.social_links = [{ platform: id, social_link: commitData[key] }];
|
||||||
delete packedData[key];
|
delete packedData[key];
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ import snakeCase from 'lodash.snakecase';
|
|||||||
export function modifyObjectKeys(object, modify) {
|
export function modifyObjectKeys(object, modify) {
|
||||||
// If the passed in object is not an object, return it.
|
// If the passed in object is not an object, return it.
|
||||||
if (
|
if (
|
||||||
object === undefined ||
|
object === undefined
|
||||||
object === null ||
|
|| object === null
|
||||||
(typeof object !== 'object' && !Array.isArray(object))
|
|| (typeof object !== 'object' && !Array.isArray(object))
|
||||||
) {
|
) {
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import { Button, Input, Modal, ValidationFormGroup } from '@edx/paragon';
|
import {
|
||||||
|
Button, Input, Modal, ValidationFormGroup,
|
||||||
|
} from '@edx/paragon';
|
||||||
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||||
import { faExclamationCircle, faExclamationTriangle } from '@fortawesome/free-solid-svg-icons';
|
import { faExclamationCircle, faExclamationTriangle } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
@@ -31,10 +33,9 @@ export class ConfirmationModal extends Component {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const headerMessageId = this.getShortErrorMessageId(errorType);
|
const headerMessageId = this.getShortErrorMessageId(errorType);
|
||||||
const detailsMessageId =
|
const detailsMessageId = reason === 'empty-password'
|
||||||
reason === 'empty-password'
|
? null
|
||||||
? null
|
: 'account.settings.delete.account.error.unable.to.delete.details';
|
||||||
: 'account.settings.delete.account.error.unable.to.delete.details';
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Alert
|
<Alert
|
||||||
@@ -66,7 +67,7 @@ export class ConfirmationModal extends Component {
|
|||||||
<Modal
|
<Modal
|
||||||
open={open}
|
open={open}
|
||||||
title={intl.formatMessage(messages['account.settings.delete.account.modal.header'])}
|
title={intl.formatMessage(messages['account.settings.delete.account.modal.header'])}
|
||||||
body={
|
body={(
|
||||||
<div>
|
<div>
|
||||||
{this.renderError()}
|
{this.renderError()}
|
||||||
<Alert
|
<Alert
|
||||||
@@ -98,7 +99,7 @@ export class ConfirmationModal extends Component {
|
|||||||
/>
|
/>
|
||||||
</ValidationFormGroup>
|
</ValidationFormGroup>
|
||||||
</div>
|
</div>
|
||||||
}
|
)}
|
||||||
buttons={[
|
buttons={[
|
||||||
<Button className="btn-danger" onClick={onSubmit}>
|
<Button className="btn-danger" onClick={onSubmit}>
|
||||||
{intl.formatMessage(messages['account.settings.delete.account.modal.confirm.delete'])}
|
{intl.formatMessage(messages['account.settings.delete.account.modal.confirm.delete'])}
|
||||||
|
|||||||
@@ -24,9 +24,12 @@ import ConnectedSuccessModal from './SuccessModal';
|
|||||||
import BeforeProceedingBanner from './BeforeProceedingBanner';
|
import BeforeProceedingBanner from './BeforeProceedingBanner';
|
||||||
|
|
||||||
export class DeleteAccount extends React.Component {
|
export class DeleteAccount extends React.Component {
|
||||||
state = {
|
constructor(props) {
|
||||||
password: '',
|
super(props);
|
||||||
};
|
this.state = {
|
||||||
|
password: '',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
handleSubmit = () => {
|
handleSubmit = () => {
|
||||||
if (this.state.password === '') {
|
if (this.state.password === '') {
|
||||||
|
|||||||
@@ -11,13 +11,13 @@ export const SuccessModal = (props) => {
|
|||||||
<Modal
|
<Modal
|
||||||
open={status === 'deleted'}
|
open={status === 'deleted'}
|
||||||
title={intl.formatMessage(messages['account.settings.delete.account.modal.after.header'])}
|
title={intl.formatMessage(messages['account.settings.delete.account.modal.after.header'])}
|
||||||
body={
|
body={(
|
||||||
<div>
|
<div>
|
||||||
<p className="h6">
|
<p className="h6">
|
||||||
{intl.formatMessage(messages['account.settings.delete.account.modal.after.text'])}
|
{intl.formatMessage(messages['account.settings.delete.account.modal.after.text'])}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
}
|
)}
|
||||||
closeText={intl.formatMessage(messages['account.settings.delete.account.modal.after.button'])}
|
closeText={intl.formatMessage(messages['account.settings.delete.account.modal.after.button'])}
|
||||||
renderHeaderCloseButton={false}
|
renderHeaderCloseButton={false}
|
||||||
onClose={onClose}
|
onClose={onClose}
|
||||||
|
|||||||
@@ -12,9 +12,8 @@ export const siteLanguageListSelector = createSelector(
|
|||||||
|
|
||||||
export const siteLanguageOptionsSelector = createSelector(
|
export const siteLanguageOptionsSelector = createSelector(
|
||||||
siteLanguageSelector,
|
siteLanguageSelector,
|
||||||
siteLanguage =>
|
siteLanguage => siteLanguage.siteLanguageList.map(({ code, name }) => ({
|
||||||
siteLanguage.siteLanguageList.map(({ code, name }) => ({
|
value: code,
|
||||||
value: code,
|
label: name,
|
||||||
label: name,
|
})),
|
||||||
})),
|
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -11,14 +11,16 @@ class ThirdPartyAuth extends Component {
|
|||||||
onClickDisconnect = (e) => {
|
onClickDisconnect = (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const providerId = e.currentTarget.getAttribute('data-provider-id');
|
const providerId = e.currentTarget.getAttribute('data-provider-id');
|
||||||
if (this.props.disconnectionStatuses[providerId] === 'pending') return;
|
if (this.props.disconnectionStatuses[providerId] === 'pending') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const disconnectUrl = e.currentTarget.getAttribute('data-disconnect-url');
|
const disconnectUrl = e.currentTarget.getAttribute('data-disconnect-url');
|
||||||
this.props.disconnectAuth(disconnectUrl, providerId);
|
this.props.disconnectAuth(disconnectUrl, providerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderUnconnectedProvider(url, name) {
|
renderUnconnectedProvider(url, name) {
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<>
|
||||||
<h6 aria-level="3">{name}</h6>
|
<h6 aria-level="3">{name}</h6>
|
||||||
<Hyperlink destination={url} className="btn btn-outline-primary">
|
<Hyperlink destination={url} className="btn btn-outline-primary">
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
@@ -28,7 +30,7 @@ class ThirdPartyAuth extends Component {
|
|||||||
values={{ name }}
|
values={{ name }}
|
||||||
/>
|
/>
|
||||||
</Hyperlink>
|
</Hyperlink>
|
||||||
</React.Fragment>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,7 +38,7 @@ class ThirdPartyAuth extends Component {
|
|||||||
const hasError = this.props.errors[id];
|
const hasError = this.props.errors[id];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<>
|
||||||
<h6 aria-level="3">
|
<h6 aria-level="3">
|
||||||
{name}
|
{name}
|
||||||
<span className="small font-weight-normal text-muted ml-2">
|
<span className="small font-weight-normal text-muted ml-2">
|
||||||
@@ -75,7 +77,7 @@ class ThirdPartyAuth extends Component {
|
|||||||
data-disconnect-url={url}
|
data-disconnect-url={url}
|
||||||
data-provider-id={id}
|
data-provider-id={id}
|
||||||
/>
|
/>
|
||||||
</React.Fragment>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,9 +87,9 @@ class ThirdPartyAuth extends Component {
|
|||||||
return (
|
return (
|
||||||
<div className="form-group" key={id}>
|
<div className="form-group" key={id}>
|
||||||
{
|
{
|
||||||
connected ?
|
connected
|
||||||
this.renderConnectedProvider(disconnectUrl, name, id) :
|
? this.renderConnectedProvider(disconnectUrl, name, id)
|
||||||
this.renderUnconnectedProvider(connectUrl, name)
|
: this.renderUnconnectedProvider(connectUrl, name)
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -104,7 +106,7 @@ class ThirdPartyAuth extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
if (this.props.providers === undefined) return null;
|
if (this.props.providers === undefined) { return null; }
|
||||||
|
|
||||||
if (this.props.providers.length === 0) {
|
if (this.props.providers.length === 0) {
|
||||||
return this.renderNoProviders();
|
return this.renderNoProviders();
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import 'babel-polyfill';
|
import 'babel-polyfill';
|
||||||
import 'formdata-polyfill';
|
import 'formdata-polyfill';
|
||||||
import { AppProvider, ErrorPage } from '@edx/frontend-platform/react';
|
import { AppProvider, ErrorPage } from '@edx/frontend-platform/react';
|
||||||
import { subscribe, initialize, APP_INIT_ERROR, APP_READY, mergeConfig } from '@edx/frontend-platform';
|
import {
|
||||||
|
subscribe, initialize, APP_INIT_ERROR, APP_READY, mergeConfig,
|
||||||
|
} from '@edx/frontend-platform';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
import { Route, Switch } from 'react-router-dom';
|
import { Route, Switch } from 'react-router-dom';
|
||||||
|
|||||||
Reference in New Issue
Block a user