refactor: Replace of injectIntl with useIntl()
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { useContext } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { AppContext } from '@edx/frontend-platform/react';
|
||||
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
import { connect } from 'react-redux';
|
||||
import { Button, Hyperlink } from '@openedx/paragon';
|
||||
|
||||
@@ -11,18 +11,11 @@ import { saveSettings } from './data/actions';
|
||||
import { TRANSIFEX_LANGUAGE_BASE_URL } from './data/constants';
|
||||
import Alert from './Alert';
|
||||
|
||||
class BetaLanguageBanner extends React.Component {
|
||||
getSiteLanguageEntry(languageCode) {
|
||||
return this.props.siteLanguageList.filter(l => l.code === languageCode)[0];
|
||||
}
|
||||
const BetaLanguageBanner = ({ siteLanguage = null, siteLanguageList }) => {
|
||||
const intl = useIntl();
|
||||
const { locale } = useContext(AppContext);
|
||||
|
||||
/**
|
||||
* Returns a link to the Transifex URL where contributors can provide translations.
|
||||
* This code is tightly coupled to how Transifex chooses to design its URLs.
|
||||
*/
|
||||
getTransifexLink(languageCode) {
|
||||
return TRANSIFEX_LANGUAGE_BASE_URL + this.getTransifexURLPath(languageCode);
|
||||
}
|
||||
const getSiteLanguageEntry = (languageCode) => siteLanguageList.filter(l => l.code === languageCode)[0];
|
||||
|
||||
/**
|
||||
* Returns the URL path that Transifex chooses to use for its language sub-pages.
|
||||
@@ -34,67 +27,70 @@ class BetaLanguageBanner extends React.Component {
|
||||
* For short language codes, it returns the code as is.
|
||||
* example: fr -> fr
|
||||
*/
|
||||
getTransifexURLPath(languageCode) {
|
||||
const getTransifexURLPath = (languageCode) => {
|
||||
const tokenizedCode = languageCode.split('-');
|
||||
if (tokenizedCode.length > 1) {
|
||||
return `${tokenizedCode[0]}_${tokenizedCode[1].toUpperCase()}`;
|
||||
}
|
||||
return tokenizedCode[0];
|
||||
}
|
||||
|
||||
handleRevertLanguage = () => {
|
||||
const previousSiteLanguage = this.props.siteLanguage.previousValue;
|
||||
this.props.saveSettings('siteLanguage', previousSiteLanguage);
|
||||
};
|
||||
|
||||
render() {
|
||||
const savedLanguage = this.getSiteLanguageEntry(this.context.locale);
|
||||
if (!savedLanguage) {
|
||||
return null;
|
||||
}
|
||||
const isSavedLanguageReleased = savedLanguage.released === true;
|
||||
const noPreviousLanguageSet = this.props.siteLanguage.previousValue === null;
|
||||
if (isSavedLanguageReleased || noPreviousLanguageSet) {
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* Returns a link to the Transifex URL where contributors can provide translations.
|
||||
* This code is tightly coupled to how Transifex chooses to design its URLs.
|
||||
*/
|
||||
const getTransifexLink = (languageCode) => TRANSIFEX_LANGUAGE_BASE_URL + getTransifexURLPath(languageCode);
|
||||
|
||||
const previousLanguage = this.getSiteLanguageEntry(this.props.siteLanguage.previousValue);
|
||||
return (
|
||||
<div>
|
||||
<Alert className="beta_language_alert alert alert-warning" role="alert">
|
||||
<p>
|
||||
{this.props.intl.formatMessage(messages['account.settings.banner.beta.language'], {
|
||||
beta_language: savedLanguage.name,
|
||||
})}
|
||||
</p>
|
||||
<div>
|
||||
<Button onClick={this.handleRevertLanguage} className="mr-2">
|
||||
{this.props.intl.formatMessage(
|
||||
messages['account.settings.banner.beta.language.action.switch.back'],
|
||||
{ previous_language: previousLanguage.name },
|
||||
)}
|
||||
</Button>
|
||||
<Hyperlink
|
||||
destination={this.getTransifexLink(savedLanguage.code)}
|
||||
className="btn btn-outline-secondary"
|
||||
target="_blank"
|
||||
>
|
||||
{this.props.intl.formatMessage(
|
||||
messages['account.settings.banner.beta.language.action.help.translate'],
|
||||
{ beta_language: savedLanguage.name },
|
||||
)}
|
||||
</Hyperlink>
|
||||
</div>
|
||||
</Alert>
|
||||
</div>
|
||||
);
|
||||
const handleRevertLanguage = () => {
|
||||
const previousSiteLanguage = siteLanguage.previousValue;
|
||||
saveSettings('siteLanguage', previousSiteLanguage);
|
||||
};
|
||||
|
||||
const savedLanguage = getSiteLanguageEntry(locale);
|
||||
if (!savedLanguage) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
const isSavedLanguageReleased = savedLanguage.released === true;
|
||||
const noPreviousLanguageSet = siteLanguage.previousValue === null;
|
||||
if (isSavedLanguageReleased || noPreviousLanguageSet) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const previousLanguage = getSiteLanguageEntry(siteLanguage.previousValue);
|
||||
return (
|
||||
<div>
|
||||
<Alert className="beta_language_alert alert alert-warning" role="alert">
|
||||
<p>
|
||||
{intl.formatMessage(messages['account.settings.banner.beta.language'], {
|
||||
beta_language: savedLanguage.name,
|
||||
})}
|
||||
</p>
|
||||
<div>
|
||||
<Button onClick={handleRevertLanguage} className="mr-2">
|
||||
{intl.formatMessage(
|
||||
messages['account.settings.banner.beta.language.action.switch.back'],
|
||||
{ previous_language: previousLanguage.name },
|
||||
)}
|
||||
</Button>
|
||||
<Hyperlink
|
||||
destination={getTransifexLink(savedLanguage.code)}
|
||||
className="btn btn-outline-secondary"
|
||||
target="_blank"
|
||||
>
|
||||
{intl.formatMessage(
|
||||
messages['account.settings.banner.beta.language.action.help.translate'],
|
||||
{ beta_language: savedLanguage.name },
|
||||
)}
|
||||
</Hyperlink>
|
||||
</div>
|
||||
</Alert>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
BetaLanguageBanner.contextType = AppContext;
|
||||
|
||||
BetaLanguageBanner.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
siteLanguage: PropTypes.shape({
|
||||
previousValue: PropTypes.string,
|
||||
draft: PropTypes.string,
|
||||
@@ -104,11 +100,6 @@ BetaLanguageBanner.propTypes = {
|
||||
code: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||
released: PropTypes.bool,
|
||||
})).isRequired,
|
||||
saveSettings: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
BetaLanguageBanner.defaultProps = {
|
||||
siteLanguage: null,
|
||||
};
|
||||
|
||||
export default connect(
|
||||
@@ -116,4 +107,4 @@ export default connect(
|
||||
{
|
||||
saveSettings,
|
||||
},
|
||||
)(injectIntl(BetaLanguageBanner));
|
||||
)(BetaLanguageBanner);
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import {
|
||||
AlertModal,
|
||||
Button, Form, ActionRow,
|
||||
} from '@openedx/paragon';
|
||||
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
import { faExclamationCircle, faExclamationTriangle } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { getConfig } from '@edx/frontend-platform';
|
||||
@@ -13,12 +12,20 @@ import messages from './messages';
|
||||
import Alert from '../Alert';
|
||||
import PrintingInstructions from './PrintingInstructions';
|
||||
|
||||
export class ConfirmationModal extends Component {
|
||||
export const ConfirmationModal = ({
|
||||
status = null,
|
||||
errorType = null,
|
||||
onCancel,
|
||||
onChange,
|
||||
onSubmit,
|
||||
password,
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
/**
|
||||
* @returns String The message id for a short description of the error, suitable for a header or
|
||||
* as the error message under an input field.
|
||||
*/
|
||||
getShortErrorMessageId(reason) {
|
||||
const getShortErrorMessageId = (reason) => {
|
||||
switch (reason) {
|
||||
case 'empty-password':
|
||||
return 'account.settings.delete.account.error.no.password';
|
||||
@@ -27,15 +34,13 @@ export class ConfirmationModal extends Component {
|
||||
default:
|
||||
return 'account.settings.delete.account.error.unable.to.delete';
|
||||
}
|
||||
}
|
||||
|
||||
renderError(reason) {
|
||||
const { errorType, intl } = this.props;
|
||||
};
|
||||
|
||||
const renderError = (reason) => {
|
||||
if (errorType === null) {
|
||||
return null;
|
||||
}
|
||||
const headerMessageId = this.getShortErrorMessageId(errorType);
|
||||
const headerMessageId = getShortErrorMessageId(errorType);
|
||||
const detailsMessageId = reason === 'empty-password'
|
||||
? null
|
||||
: 'account.settings.delete.account.error.unable.to.delete.details';
|
||||
@@ -51,103 +56,86 @@ export class ConfirmationModal extends Component {
|
||||
) : null}
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
status,
|
||||
errorType,
|
||||
intl,
|
||||
onCancel,
|
||||
onChange,
|
||||
onSubmit,
|
||||
password,
|
||||
} = this.props;
|
||||
const open = ['confirming', 'pending', 'failed'].includes(status);
|
||||
const passwordFieldId = 'passwordFieldId';
|
||||
const invalidMessage = messages[this.getShortErrorMessageId(errorType)];
|
||||
const open = ['confirming', 'pending', 'failed'].includes(status);
|
||||
const passwordFieldId = 'passwordFieldId';
|
||||
const invalidMessage = messages[getShortErrorMessageId(errorType)];
|
||||
|
||||
// TODO: We lack a good way of providing custom language for a particular site. This is a hack
|
||||
// to allow edx.org to fulfill its business requirements.
|
||||
const deleteAccountModalText2MessageKey = getConfig().SITE_NAME === 'edX'
|
||||
? 'account.settings.delete.account.modal.text.2.edX'
|
||||
: 'account.settings.delete.account.modal.text.2';
|
||||
// TODO: We lack a good way of providing custom language for a particular site. This is a hack
|
||||
// to allow edx.org to fulfill its business requirements.
|
||||
const deleteAccountModalText2MessageKey = getConfig().SITE_NAME === 'edX'
|
||||
? 'account.settings.delete.account.modal.text.2.edX'
|
||||
: 'account.settings.delete.account.modal.text.2';
|
||||
|
||||
return (
|
||||
<AlertModal
|
||||
isOpen={open}
|
||||
title={intl.formatMessage(messages['account.settings.delete.account.modal.header'])}
|
||||
onClose={onCancel}
|
||||
isOverflowVisible
|
||||
footerNode={(
|
||||
<ActionRow>
|
||||
<Button variant="link" onClick={onCancel}>Cancel</Button>
|
||||
<Button variant="danger" onClick={onSubmit}>Yes, Delete</Button>
|
||||
</ActionRow>
|
||||
return (
|
||||
<AlertModal
|
||||
isOpen={open}
|
||||
title={intl.formatMessage(messages['account.settings.delete.account.modal.header'])}
|
||||
onClose={onCancel}
|
||||
isOverflowVisible
|
||||
footerNode={(
|
||||
<ActionRow>
|
||||
<Button variant="link" onClick={onCancel}>Cancel</Button>
|
||||
<Button variant="danger" onClick={onSubmit}>Yes, Delete</Button>
|
||||
</ActionRow>
|
||||
)}
|
||||
>
|
||||
<div className="p-3">
|
||||
{this.renderError()}
|
||||
<Alert
|
||||
className="alert-warning mt-n2"
|
||||
icon={<FontAwesomeIcon className="mr-2" icon={faExclamationTriangle} />}
|
||||
>
|
||||
<h6>
|
||||
{intl.formatMessage(
|
||||
messages['account.settings.delete.account.modal.text.1'],
|
||||
{ siteName: getConfig().SITE_NAME },
|
||||
)}
|
||||
</h6>
|
||||
<p>
|
||||
{intl.formatMessage(
|
||||
messages[deleteAccountModalText2MessageKey],
|
||||
{ siteName: getConfig().SITE_NAME },
|
||||
)}
|
||||
</p>
|
||||
<p>
|
||||
<PrintingInstructions />
|
||||
</p>
|
||||
</Alert>
|
||||
<Form.Group
|
||||
for={passwordFieldId}
|
||||
isInvalid={errorType !== null}
|
||||
>
|
||||
<Form.Label className="d-block" htmlFor={passwordFieldId}>
|
||||
{intl.formatMessage(messages['account.settings.delete.account.modal.enter.password'])}
|
||||
</Form.Label>
|
||||
<Form.Control
|
||||
name="password"
|
||||
id={passwordFieldId}
|
||||
type="password"
|
||||
value={password}
|
||||
onChange={onChange}
|
||||
/>
|
||||
{errorType !== null && (
|
||||
<Form.Control.Feedback type="invalid" feedback-for={passwordFieldId}>
|
||||
{intl.formatMessage(invalidMessage)}
|
||||
</Form.Control.Feedback>
|
||||
>
|
||||
<div className="p-3">
|
||||
{renderError()}
|
||||
<Alert
|
||||
className="alert-warning mt-n2"
|
||||
icon={<FontAwesomeIcon className="mr-2" icon={faExclamationTriangle} />}
|
||||
>
|
||||
<h6>
|
||||
{intl.formatMessage(
|
||||
messages['account.settings.delete.account.modal.text.1'],
|
||||
{ siteName: getConfig().SITE_NAME },
|
||||
)}
|
||||
</Form.Group>
|
||||
</div>
|
||||
</h6>
|
||||
<p>
|
||||
{intl.formatMessage(
|
||||
messages[deleteAccountModalText2MessageKey],
|
||||
{ siteName: getConfig().SITE_NAME },
|
||||
)}
|
||||
</p>
|
||||
<p>
|
||||
<PrintingInstructions />
|
||||
</p>
|
||||
</Alert>
|
||||
<Form.Group
|
||||
for={passwordFieldId}
|
||||
isInvalid={errorType !== null}
|
||||
>
|
||||
<Form.Label className="d-block" htmlFor={passwordFieldId}>
|
||||
{intl.formatMessage(messages['account.settings.delete.account.modal.enter.password'])}
|
||||
</Form.Label>
|
||||
<Form.Control
|
||||
name="password"
|
||||
id={passwordFieldId}
|
||||
type="password"
|
||||
value={password}
|
||||
onChange={onChange}
|
||||
/>
|
||||
{errorType !== null && (
|
||||
<Form.Control.Feedback type="invalid" feedback-for={passwordFieldId}>
|
||||
{intl.formatMessage(invalidMessage)}
|
||||
</Form.Control.Feedback>
|
||||
)}
|
||||
</Form.Group>
|
||||
</div>
|
||||
|
||||
</AlertModal>
|
||||
);
|
||||
}
|
||||
}
|
||||
</AlertModal>
|
||||
);
|
||||
};
|
||||
|
||||
ConfirmationModal.propTypes = {
|
||||
status: PropTypes.oneOf(['confirming', 'pending', 'deleted', 'failed']),
|
||||
errorType: PropTypes.oneOf(['empty-password', 'server']),
|
||||
intl: intlShape.isRequired,
|
||||
onCancel: PropTypes.func.isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
onSubmit: PropTypes.func.isRequired,
|
||||
password: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
ConfirmationModal.defaultProps = {
|
||||
status: null,
|
||||
errorType: null,
|
||||
};
|
||||
|
||||
export default injectIntl(ConfirmationModal);
|
||||
export default ConfirmationModal;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import React from 'react';
|
||||
import renderer from 'react-test-renderer';
|
||||
import { IntlProvider, injectIntl } from '@edx/frontend-platform/i18n';
|
||||
import { IntlProvider } from '@edx/frontend-platform/i18n';
|
||||
|
||||
// Modal creates a portal. Overriding createPortal allows portals to be tested in jest.
|
||||
jest.mock('react-dom', () => ({
|
||||
@@ -10,8 +9,6 @@ jest.mock('react-dom', () => ({
|
||||
|
||||
import { ConfirmationModal } from './ConfirmationModal'; // eslint-disable-line import/first
|
||||
|
||||
const IntlConfirmationModal = injectIntl(ConfirmationModal);
|
||||
|
||||
describe('ConfirmationModal', () => {
|
||||
let props = {};
|
||||
|
||||
@@ -30,7 +27,7 @@ describe('ConfirmationModal', () => {
|
||||
const tree = renderer
|
||||
.create((
|
||||
<IntlProvider locale="en">
|
||||
<IntlConfirmationModal
|
||||
<ConfirmationModal
|
||||
{...props}
|
||||
/>
|
||||
</IntlProvider>
|
||||
@@ -43,7 +40,7 @@ describe('ConfirmationModal', () => {
|
||||
const tree = renderer
|
||||
.create((
|
||||
<IntlProvider locale="en">
|
||||
<IntlConfirmationModal
|
||||
<ConfirmationModal
|
||||
{...props}
|
||||
status="pending" // This will cause 'modal-backdrop' and 'show' to appear on the modal as CSS classes.
|
||||
/>
|
||||
@@ -57,7 +54,7 @@ describe('ConfirmationModal', () => {
|
||||
const tree = renderer
|
||||
.create((
|
||||
<IntlProvider locale="en">
|
||||
<IntlConfirmationModal
|
||||
<ConfirmationModal
|
||||
{...props}
|
||||
errorType="empty-password"
|
||||
status="pending" // This will cause 'modal-backdrop' and 'show' to appear on the modal as CSS classes.
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import React from 'react';
|
||||
import { useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
import { getConfig } from '@edx/frontend-platform';
|
||||
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
import { Button, Hyperlink } from '@openedx/paragon';
|
||||
|
||||
// Actions
|
||||
@@ -23,61 +23,58 @@ import PrintingInstructions from './PrintingInstructions';
|
||||
import ConnectedSuccessModal from './SuccessModal';
|
||||
import BeforeProceedingBanner from './BeforeProceedingBanner';
|
||||
|
||||
export class DeleteAccount extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
export const DeleteAccount = ({
|
||||
hasLinkedTPA = false,
|
||||
isVerifiedAccount = true,
|
||||
status = null,
|
||||
errorType = null,
|
||||
canDeleteAccount = true,
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
const [password, setPassword] = useState('');
|
||||
|
||||
this.state = {
|
||||
password: '',
|
||||
};
|
||||
}
|
||||
|
||||
handleSubmit = () => {
|
||||
if (this.state.password === '') {
|
||||
this.props.deleteAccountFailure('empty-password');
|
||||
const handleSubmit = () => {
|
||||
if (password === '') {
|
||||
deleteAccountFailure('empty-password');
|
||||
} else {
|
||||
this.props.deleteAccount(this.state.password);
|
||||
deleteAccount(password);
|
||||
}
|
||||
};
|
||||
|
||||
handleCancel = () => {
|
||||
this.setState({ password: '' });
|
||||
this.props.deleteAccountCancel();
|
||||
const handleCancel = () => {
|
||||
setPassword('');
|
||||
deleteAccountCancel();
|
||||
};
|
||||
|
||||
handlePasswordChange = (e) => {
|
||||
this.setState({ password: e.target.value.trim() });
|
||||
this.props.deleteAccountReset();
|
||||
const handlePasswordChange = (e) => {
|
||||
setPassword(e.target.value.trim());
|
||||
deleteAccountReset();
|
||||
};
|
||||
|
||||
handleFinalClose = () => {
|
||||
const handleFinalClose = () => {
|
||||
global.location = getConfig().LOGOUT_URL;
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
hasLinkedTPA, isVerifiedAccount, status, errorType, intl,
|
||||
} = this.props;
|
||||
const canDelete = isVerifiedAccount && !hasLinkedTPA;
|
||||
const supportArticleUrl = process.env.SUPPORT_URL_TO_UNLINK_SOCIAL_MEDIA_ACCOUNT;
|
||||
const canDelete = isVerifiedAccount && !hasLinkedTPA;
|
||||
const supportArticleUrl = process.env.SUPPORT_URL_TO_UNLINK_SOCIAL_MEDIA_ACCOUNT || '';
|
||||
|
||||
// TODO: We lack a good way of providing custom language for a particular site. This is a hack
|
||||
// to allow edx.org to fulfill its business requirements.
|
||||
const deleteAccountText2MessageKey = getConfig().SITE_NAME === 'edX'
|
||||
? 'account.settings.delete.account.text.2.edX'
|
||||
: 'account.settings.delete.account.text.2';
|
||||
// TODO: We lack a good way of providing custom language for a particular site. This is a hack
|
||||
// to allow edx.org to fulfill its business requirements.
|
||||
const deleteAccountText2MessageKey = getConfig().SITE_NAME === 'edX'
|
||||
? 'account.settings.delete.account.text.2.edX'
|
||||
: 'account.settings.delete.account.text.2';
|
||||
|
||||
const optInInstructionMessageId = getConfig().MARKETING_EMAILS_OPT_IN
|
||||
? 'account.settings.delete.account.please.confirm'
|
||||
: 'account.settings.delete.account.please.activate';
|
||||
const optInInstructionMessageId = getConfig().MARKETING_EMAILS_OPT_IN
|
||||
? 'account.settings.delete.account.please.confirm'
|
||||
: 'account.settings.delete.account.please.activate';
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h2 className="section-heading h4 mb-3">
|
||||
{intl.formatMessage(messages['account.settings.delete.account.header'])}
|
||||
</h2>
|
||||
{
|
||||
this.props.canDeleteAccount ? (
|
||||
return (
|
||||
<div>
|
||||
<h2 className="section-heading h4 mb-3">
|
||||
{intl.formatMessage(messages['account.settings.delete.account.header'])}
|
||||
</h2>
|
||||
{
|
||||
canDeleteAccount ? (
|
||||
<>
|
||||
<p>{intl.formatMessage(messages['account.settings.delete.account.subheader'])}</p>
|
||||
<p>
|
||||
@@ -109,7 +106,7 @@ export class DeleteAccount extends React.Component {
|
||||
<p>
|
||||
<Button
|
||||
variant="outline-danger"
|
||||
onClick={canDelete ? this.props.deleteAccountConfirmation : null}
|
||||
onClick={canDelete ? deleteAccountConfirmation : null}
|
||||
disabled={!canDelete}
|
||||
>
|
||||
{intl.formatMessage(messages['account.settings.delete.account.button'])}
|
||||
@@ -127,48 +124,30 @@ export class DeleteAccount extends React.Component {
|
||||
supportArticleUrl={supportArticleUrl}
|
||||
/>
|
||||
) : null}
|
||||
|
||||
<ConnectedConfirmationModal
|
||||
status={status}
|
||||
errorType={errorType}
|
||||
onSubmit={this.handleSubmit}
|
||||
onCancel={this.handleCancel}
|
||||
onChange={this.handlePasswordChange}
|
||||
password={this.state.password}
|
||||
onSubmit={handleSubmit}
|
||||
onCancel={handleCancel}
|
||||
onChange={handlePasswordChange}
|
||||
password={password}
|
||||
/>
|
||||
|
||||
<ConnectedSuccessModal status={status} onClose={this.handleFinalClose} />
|
||||
<ConnectedSuccessModal status={status} onClose={handleFinalClose} />
|
||||
</>
|
||||
) : (
|
||||
<p>{intl.formatMessage(messages['account.settings.cannot.delete.account.text'])}</p>
|
||||
)
|
||||
}
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
DeleteAccount.propTypes = {
|
||||
deleteAccount: PropTypes.func.isRequired,
|
||||
deleteAccountConfirmation: PropTypes.func.isRequired,
|
||||
deleteAccountFailure: PropTypes.func.isRequired,
|
||||
deleteAccountReset: PropTypes.func.isRequired,
|
||||
deleteAccountCancel: PropTypes.func.isRequired,
|
||||
status: PropTypes.oneOf(['confirming', 'pending', 'deleted', 'failed']),
|
||||
errorType: PropTypes.oneOf(['empty-password', 'server']),
|
||||
hasLinkedTPA: PropTypes.bool,
|
||||
isVerifiedAccount: PropTypes.bool,
|
||||
canDeleteAccount: PropTypes.bool,
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
DeleteAccount.defaultProps = {
|
||||
hasLinkedTPA: false,
|
||||
isVerifiedAccount: true,
|
||||
status: null,
|
||||
errorType: null,
|
||||
canDeleteAccount: true,
|
||||
};
|
||||
|
||||
// Assume we're part of the accountSettings state.
|
||||
@@ -183,4 +162,4 @@ export default connect(
|
||||
deleteAccountReset,
|
||||
deleteAccountCancel,
|
||||
},
|
||||
)(injectIntl(DeleteAccount));
|
||||
)(DeleteAccount);
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/* eslint-disable react/jsx-no-useless-fragment */
|
||||
import React from 'react';
|
||||
import renderer from 'react-test-renderer';
|
||||
import { IntlProvider, injectIntl } from '@edx/frontend-platform/i18n';
|
||||
import { IntlProvider } from '@edx/frontend-platform/i18n';
|
||||
|
||||
// Testing the modals separately, they just clutter up the snapshots if included here.
|
||||
jest.mock('./ConfirmationModal', () => function ConfirmationModalMock() {
|
||||
@@ -11,20 +10,21 @@ jest.mock('./SuccessModal', () => function SuccessModalMock() {
|
||||
return <></>;
|
||||
});
|
||||
|
||||
import { DeleteAccount } from './DeleteAccount'; // eslint-disable-line import/first
|
||||
jest.mock('./data/actions', () => ({
|
||||
deleteAccount: jest.fn(),
|
||||
deleteAccountConfirmation: jest.fn(),
|
||||
deleteAccountFailure: jest.fn(),
|
||||
deleteAccountReset: jest.fn(),
|
||||
deleteAccountCancel: jest.fn(),
|
||||
}));
|
||||
|
||||
const IntlDeleteAccount = injectIntl(DeleteAccount);
|
||||
import { DeleteAccount } from './DeleteAccount'; // eslint-disable-line import/first
|
||||
|
||||
describe('DeleteAccount', () => {
|
||||
let props = {};
|
||||
|
||||
beforeEach(() => {
|
||||
props = {
|
||||
deleteAccount: jest.fn(),
|
||||
deleteAccountConfirmation: jest.fn(),
|
||||
deleteAccountFailure: jest.fn(),
|
||||
deleteAccountReset: jest.fn(),
|
||||
deleteAccountCancel: jest.fn(),
|
||||
status: null,
|
||||
errorType: null,
|
||||
hasLinkedTPA: false,
|
||||
@@ -36,7 +36,7 @@ describe('DeleteAccount', () => {
|
||||
const tree = renderer
|
||||
.create((
|
||||
<IntlProvider locale="en">
|
||||
<IntlDeleteAccount
|
||||
<DeleteAccount
|
||||
{...props}
|
||||
/>
|
||||
</IntlProvider>
|
||||
@@ -50,7 +50,7 @@ describe('DeleteAccount', () => {
|
||||
const tree = renderer
|
||||
.create((
|
||||
<IntlProvider locale="en">
|
||||
<IntlDeleteAccount
|
||||
<DeleteAccount
|
||||
{...props}
|
||||
isVerifiedAccount={false}
|
||||
/>
|
||||
@@ -64,7 +64,7 @@ describe('DeleteAccount', () => {
|
||||
const tree = renderer
|
||||
.create((
|
||||
<IntlProvider locale="en">
|
||||
<IntlDeleteAccount
|
||||
<DeleteAccount
|
||||
{...props}
|
||||
hasLinkedTPA
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user