added option for image upload

added friction to allowing users to upload id image

only shows picture within component if it has been uploaded, not if it was captured through the webcam
This commit is contained in:
Alie Langston
2020-08-24 12:56:51 -04:00
parent 11dbbad20b
commit 74bb2fb45f
6 changed files with 76 additions and 25 deletions

View File

@@ -0,0 +1,53 @@
import React, { useState, useContext } from 'react';
import PropTypes from 'prop-types';
import { Collapsible } from '@edx/paragon';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { sendTrackEvent } from '@edx/frontend-platform/analytics';
import messages from './IdVerification.messages';
import ImageFileUpload from './ImageFileUpload';
import { IdVerificationContext } from './IdVerificationContext';
import ImagePreview from './ImagePreview';
function CameraHelpWithUpload(props) {
const { setIdPhotoFile, idPhotoFile, userId } = useContext(IdVerificationContext);
const [hasUploadedImage, setHasUploadedImage] = useState(false);
function setAndTrackIdPhotoFile(image) {
sendTrackEvent('edx.id_verification.upload_id', {
category: 'id_verification',
user_id: userId,
});
setHasUploadedImage(true);
setIdPhotoFile(image);
}
return (
<div>
<Collapsible
styling="card"
title={props.intl.formatMessage(messages['id.verification.id.photo.unclear.question'])}
data-testid="collapsible"
className="mb-4 shadow"
defaultOpen={props.isOpen}
>
{idPhotoFile && hasUploadedImage && <ImagePreview src={idPhotoFile} alt={props.intl.formatMessage(messages['id.verification.id.photo.preview.alt'])} />}
<p>
{props.intl.formatMessage(messages['id.verification.id.photo.instructions.upload'])}
</p>
<ImageFileUpload onFileChange={setAndTrackIdPhotoFile} />
</Collapsible>
</div>
);
}
CameraHelpWithUpload.propTypes = {
intl: intlShape.isRequired,
isOpen: PropTypes.bool,
};
CameraHelpWithUpload.defaultProps = {
isOpen: false,
};
export default injectIntl(CameraHelpWithUpload);

View File

@@ -341,6 +341,11 @@ const messages = defineMessages({
defaultMessage: 'If you require assistance with taking a photo for submission, contact edX support for additional suggestions.',
description: 'Confirming what to do if the user has difficult holding their head relative to the camera.',
},
'id.verification.id.photo.unclear.question': {
id: 'id.verification.id.photo.unclear.question',
defaultMessage: 'Is your ID image not clear or too blurry?',
description: 'Question on what to do if the user\'s ID image is unclear',
},
'id.verification.id.tips.title': {
id: 'id.verification.id.tips.title',
defaultMessage: 'Helpful ID Tips',

View File

@@ -17,6 +17,7 @@ export default function ImageFileUpload({ onFileChange }) {
<input
type="file"
accept="image/*"
data-testid="fileUpload"
onChange={handleChange}
/>
);

View File

@@ -11,6 +11,7 @@ import { IdVerificationContext } from '../IdVerificationContext';
import ImagePreview from '../ImagePreview';
import messages from '../IdVerification.messages';
import CameraHelpWithUpload from '../CameraHelpWithUpload';
function SummaryPanel(props) {
const panelSlug = 'summary';
@@ -101,6 +102,7 @@ function SummaryPanel(props) {
</Link>
</div>
</div>
<CameraHelpWithUpload />
<div className="form-group">
<label htmlFor="name-to-be-used">
{props.intl.formatMessage(messages['id.verification.account.name.label'])}

View File

@@ -4,47 +4,29 @@ import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { useNextPanelSlug } from '../routing-utilities';
import BasePanel from './BasePanel';
import ImageFileUpload from '../ImageFileUpload';
import ImagePreview from '../ImagePreview';
import Camera from '../Camera';
import CameraHelp from '../CameraHelp';
import { IdVerificationContext } from '../IdVerificationContext';
import messages from '../IdVerification.messages';
import CameraHelp from '../CameraHelp';
function TakeIdPhotoPanel(props) {
const panelSlug = 'take-id-photo';
const nextPanelSlug = useNextPanelSlug(panelSlug);
const { setIdPhotoFile, idPhotoFile } = useContext(IdVerificationContext);
const shouldUseCamera = true;
// to reenable upload component:
// const shouldUseCamera = mediaAccess === MEDIA_ACCESS.GRANTED;
return (
<BasePanel
name={panelSlug}
title={shouldUseCamera ? props.intl.formatMessage(messages['id.verification.id.photo.title.camera']) : props.intl.formatMessage(messages['id.verification.id.photo.title.upload'])}
title={props.intl.formatMessage(messages['id.verification.id.photo.title.camera'])}
>
<div>
{idPhotoFile && !shouldUseCamera && <ImagePreview src={idPhotoFile} alt={props.intl.formatMessage(messages['id.verification.id.photo.preview.alt'])} />}
{shouldUseCamera ? (
<div>
<p>
{props.intl.formatMessage(messages['id.verification.id.photo.instructions.camera'])}
</p>
<Camera onImageCapture={setIdPhotoFile} />
</div>
) : (
<div>
<p>
{props.intl.formatMessage(messages['id.verification.id.photo.instructions.upload'])}
</p>
<ImageFileUpload onFileChange={setIdPhotoFile} />
</div>
)}
<p>
{props.intl.formatMessage(messages['id.verification.id.photo.instructions.camera'])}
</p>
<Camera onImageCapture={setIdPhotoFile} />
</div>
{shouldUseCamera && <CameraHelp />}
<CameraHelp />
<div className="action-row" style={{ visibility: idPhotoFile ? 'unset' : 'hidden' }}>
<Link to={nextPanelSlug} className="btn btn-primary" data-testid="next-button">
{props.intl.formatMessage(messages['id.verification.next'])}

View File

@@ -2,6 +2,7 @@ import React from 'react';
import { Router } from 'react-router-dom';
import { createMemoryHistory } from 'history';
import { render, cleanup, act, screen, fireEvent } from '@testing-library/react';
import '@testing-library/jest-dom/extend-expect';
import '@edx/frontend-platform/analytics';
import { injectIntl, IntlProvider } from '@edx/frontend-platform/i18n';
import { submitIdVerification } from '../../data/service';
@@ -62,6 +63,13 @@ describe('SummaryPanel', () => {
expect(history.location.state.fromSummary).toEqual(true);
});
it('allows user to upload ID photo', async () => {
const collapsible = await screen.getAllByRole('button', { 'aria-expanded': false })[0];
fireEvent.click(collapsible);
const uploadButton = await screen.getByTestId('fileUpload');
expect(uploadButton).toBeVisible();
});
it('submits', async () => {
const button = await screen.findByTestId('submit-button');
fireEvent.click(button);