* fix: removing hard-coded edX from DemographicsSection messages
* fix: removing hard-coded “edX” strings from IDV messages
* fix: updating ThirdPartyAuth message description to remove hard-coded “edX” references.
* fix: replacing hard-coded “edX” strings with SITE_NAME in AccountSettingsPage
* fix: conditionalizing edx-specific strings in ConfirmationModal
If the SITE_NAME is ‘edX’, then edx.org-specific strings will be used. Otherwise, more general, Open edX-appropriate strings will be used.
* fix: conditionalizing edX-specific strings in delete account components.
If the SITE_NAME is ‘edX’, then edx.org-specific strings will be used. Otherwise, more general, Open edX-appropriate strings will be used.
* fix: replacing hard-coded ‘edX’ strings with SITE_NAME in ReviewRequirementsPanel
I missed a few because the messages were re-used.
* fix: review feedback, improving messages
- Removing unnecessary {siteName} references
- Improving some message descriptions
247 lines
8.2 KiB
JavaScript
247 lines
8.2 KiB
JavaScript
import React, { useState, useContext, useEffect } from 'react';
|
|
import { getConfig, history } from '@edx/frontend-platform';
|
|
import {
|
|
Alert, Hyperlink, Input, Button, Spinner,
|
|
} from '@edx/paragon';
|
|
import { Link } from 'react-router-dom';
|
|
import { injectIntl, intlShape, FormattedMessage } from '@edx/frontend-platform/i18n';
|
|
|
|
import { submitIdVerification } from '../data/service';
|
|
import { useNextPanelSlug } from '../routing-utilities';
|
|
import BasePanel from './BasePanel';
|
|
import IdVerificationContext from '../IdVerificationContext';
|
|
import ImagePreview from '../ImagePreview';
|
|
|
|
import messages from '../IdVerification.messages';
|
|
import CameraHelpWithUpload from '../CameraHelpWithUpload';
|
|
import SupportedMediaTypes from '../SupportedMediaTypes';
|
|
|
|
function SummaryPanel(props) {
|
|
const panelSlug = 'summary';
|
|
const nextPanelSlug = useNextPanelSlug(panelSlug);
|
|
const {
|
|
facePhotoFile,
|
|
idPhotoFile,
|
|
profileDataManager,
|
|
nameOnAccount,
|
|
idPhotoName,
|
|
stopUserMedia,
|
|
optimizelyExperimentName,
|
|
setReachedSummary,
|
|
} = useContext(IdVerificationContext);
|
|
const nameToBeUsed = idPhotoName || nameOnAccount || '';
|
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
const [submissionError, setSubmissionError] = useState(null);
|
|
|
|
useEffect(() => setReachedSummary(true), []);
|
|
|
|
function renderManagedProfileMessage() {
|
|
if (!profileDataManager) {
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
<p id="profile-manager-warning">
|
|
<FormattedMessage
|
|
id="id.verification.account.name.summary.alert"
|
|
defaultMessage="Your account settings are managed by {managerTitle}. If the name on your photo ID does not match the name on your account, please contact your {profileDataManager} administrator or {support} for help."
|
|
description="Alert message informing the user their account data is managed by a third party."
|
|
values={{
|
|
managerTitle: <strong>{profileDataManager}</strong>,
|
|
profileDataManager,
|
|
support: (
|
|
<Hyperlink destination={getConfig().SUPPORT_URL} target="_blank">
|
|
{props.intl.formatMessage(messages['id.verification.support'])}
|
|
</Hyperlink>
|
|
),
|
|
}}
|
|
/>
|
|
</p>
|
|
);
|
|
}
|
|
|
|
function SubmitButton() {
|
|
async function handleClick() {
|
|
setIsSubmitting(true);
|
|
const verificationData = {
|
|
facePhotoFile,
|
|
idPhotoFile,
|
|
courseRunKey: sessionStorage.getItem('courseRunKey'),
|
|
};
|
|
if (idPhotoName) {
|
|
verificationData.idPhotoName = idPhotoName;
|
|
}
|
|
if (optimizelyExperimentName) {
|
|
verificationData.optimizelyExperimentName = optimizelyExperimentName;
|
|
}
|
|
const result = await submitIdVerification(verificationData);
|
|
if (result.success) {
|
|
stopUserMedia();
|
|
history.push(nextPanelSlug);
|
|
} else {
|
|
stopUserMedia();
|
|
setIsSubmitting(false);
|
|
setSubmissionError(result);
|
|
}
|
|
}
|
|
return (
|
|
<Button
|
|
title="Confirmation"
|
|
disabled={isSubmitting}
|
|
onClick={handleClick}
|
|
data-testid="submit-button"
|
|
>
|
|
{props.intl.formatMessage(messages['id.verification.review.confirm'])}
|
|
</Button>
|
|
);
|
|
}
|
|
|
|
function getError() {
|
|
if (submissionError.status === 400) {
|
|
if (submissionError.message.includes('face_image')) {
|
|
return props.intl.formatMessage(messages['id.verification.submission.alert.error.face']);
|
|
}
|
|
if (submissionError.message.includes('Photo ID image')) {
|
|
return props.intl.formatMessage(messages['id.verification.submission.alert.error.id']);
|
|
}
|
|
if (submissionError.message.includes('Name')) {
|
|
return props.intl.formatMessage(messages['id.verification.submission.alert.error.name']);
|
|
}
|
|
if (submissionError.message.includes('unsupported format')) {
|
|
return (
|
|
<>
|
|
{props.intl.formatMessage(messages['id.verification.submission.alert.error.unsupported'])}
|
|
<SupportedMediaTypes />
|
|
</>
|
|
);
|
|
}
|
|
}
|
|
return (
|
|
<FormattedMessage
|
|
id="idv.submission.alert.error"
|
|
defaultMessage={`
|
|
We encountered a technical error while trying to submit ID verification.
|
|
This might be a temporary issue, so please try again in a few minutes.
|
|
If the problem persists, please go to {support_link} for help.
|
|
`}
|
|
values={{
|
|
support_link: (
|
|
<Alert.Link href="https://support.edx.org/hc/en-us">
|
|
{props.intl.formatMessage(
|
|
messages['id.verification.review.error'],
|
|
{ siteName: getConfig().SITE_NAME },
|
|
)}
|
|
</Alert.Link>
|
|
),
|
|
}}
|
|
/>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<BasePanel
|
|
name={panelSlug}
|
|
title={props.intl.formatMessage(messages['id.verification.review.title'])}
|
|
>
|
|
{submissionError && (
|
|
<Alert
|
|
variant="danger"
|
|
data-testid="submission-error"
|
|
dismissible
|
|
onClose={() => setSubmissionError(null)}
|
|
>
|
|
{getError()}
|
|
</Alert>
|
|
)}
|
|
<p>
|
|
{props.intl.formatMessage(messages['id.verification.review.description'])}
|
|
</p>
|
|
<div className="row mb-4">
|
|
<div className="col-6">
|
|
<label htmlFor="photo-of-face" className="font-weight-bold">
|
|
{props.intl.formatMessage(messages['id.verification.review.portrait.label'])}
|
|
</label>
|
|
<ImagePreview
|
|
id="photo-of-face"
|
|
src={facePhotoFile}
|
|
alt={props.intl.formatMessage(messages['id.verification.review.portrait.alt'])}
|
|
/>
|
|
<Link
|
|
className="btn btn-outline-primary"
|
|
to={{
|
|
pathname: 'take-portrait-photo',
|
|
state: { fromSummary: true },
|
|
}}
|
|
data-testid="portrait-retake"
|
|
>
|
|
{props.intl.formatMessage(messages['id.verification.review.portrait.retake'])}
|
|
</Link>
|
|
</div>
|
|
<div className="col-6">
|
|
<label htmlFor="photo-of-id/edit" className="font-weight-bold">
|
|
{props.intl.formatMessage(messages['id.verification.review.id.label'])}
|
|
</label>
|
|
<ImagePreview
|
|
id="photo-of-id"
|
|
src={idPhotoFile}
|
|
alt={props.intl.formatMessage(messages['id.verification.review.id.alt'])}
|
|
/>
|
|
<Link
|
|
className="btn btn-outline-primary"
|
|
to={{
|
|
pathname: 'take-id-photo',
|
|
state: { fromSummary: true },
|
|
}}
|
|
data-testid="id-retake"
|
|
>
|
|
{props.intl.formatMessage(messages['id.verification.review.id.retake'])}
|
|
</Link>
|
|
</div>
|
|
</div>
|
|
{!optimizelyExperimentName && <CameraHelpWithUpload />}
|
|
<div className="form-group">
|
|
<label htmlFor="name-to-be-used" className="font-weight-bold">
|
|
{props.intl.formatMessage(messages['id.verification.account.name.label'])}
|
|
</label>
|
|
{renderManagedProfileMessage()}
|
|
<div className="d-flex">
|
|
<Input
|
|
id="name-to-be-used"
|
|
type="text"
|
|
readOnly
|
|
value={nameToBeUsed}
|
|
onChange={() => {}}
|
|
aria-describedby={profileDataManager ? 'profile-manager-warning' : null}
|
|
/>
|
|
{!profileDataManager && (
|
|
<Link
|
|
className="btn btn-link ml-3 px-0"
|
|
to={{
|
|
pathname: 'get-name-id',
|
|
state: { fromSummary: true },
|
|
}}
|
|
>
|
|
<FormattedMessage
|
|
id="id.verification.account.name.edit"
|
|
defaultMessage="Edit {sr}"
|
|
description="Button to edit account name, with clarifying information for screen readers."
|
|
values={{
|
|
sr: <span className="sr-only">Account Name</span>,
|
|
}}
|
|
/>
|
|
</Link>
|
|
)}
|
|
</div>
|
|
</div>
|
|
<SubmitButton />{' '}
|
|
{isSubmitting && <Spinner animation="border" variant="primary" />}
|
|
</BasePanel>
|
|
);
|
|
}
|
|
|
|
SummaryPanel.propTypes = {
|
|
intl: intlShape.isRequired,
|
|
};
|
|
|
|
export default injectIntl(SummaryPanel);
|