Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
d4955ce
wip
aduth Oct 15, 2021
54fe987
Extract FormStepsContinueButton from FormSteps
aduth Oct 21, 2021
4afc52a
Move CaptureAttemptsTroubleshooting to DocumentsStep
aduth Oct 21, 2021
1e8b66f
Track metadata of last capture attempt
aduth Oct 21, 2021
a62d2d8
Rename CaptureAttempts context as FailedCaptureAttempts
aduth Oct 21, 2021
a143950
Temporarily disable prompt on navigate
aduth Oct 21, 2021
a7b8ee8
Fix TroubleshootingOptions markup
aduth Oct 21, 2021
fc2d6f7
Add capture attempts troubleshooting content
aduth Oct 21, 2021
ceaf54e
Trigger onFailedCaptureAttempt on failed capture attempt
aduth Oct 21, 2021
6fd1870
Revert "Temporarily disable prompt on navigate"
aduth Oct 21, 2021
4f49f34
Use warning component for attempts troubleshooting
aduth Oct 21, 2021
095250f
useCounter: Add support for reset
aduth Oct 21, 2021
9b75e35
Reset failed attempts after success
aduth Oct 21, 2021
94b4e47
Warning: Margin between warning icon and page heading
aduth Oct 21, 2021
aafc6b6
Translate capture tips content
aduth Oct 21, 2021
5ce074b
Add troubleshooting links
aduth Oct 21, 2021
605bece
Taking the title out of form-steps and requiring each step to create …
amathews-fs Oct 22, 2021
8a12999
Fixing a few things after comment and fixing a couple of tests. More …
amathews-fs Oct 22, 2021
081bb31
Oops! Forgot to remove the title prop typescript doc.
amathews-fs Oct 22, 2021
f0e0bea
It seems a few svgs could be further optimized.
amathews-fs Oct 22, 2021
165515b
start fixing formsteps specs
aduth Oct 22, 2021
cd4b6dd
Fixed a few more tests.
amathews-fs Oct 22, 2021
e62edd5
A quick attempt at fixing the failing SubmissionInterstitial test. Th…
amathews-fs Oct 22, 2021
58ffc4c
Assign Node global in spec helper
aduth Oct 25, 2021
a2f8642
Restore behavior to move focus ahead of alert on errors
aduth Oct 25, 2021
2cf720c
Temporary translations for beginning of step content
aduth Oct 25, 2021
b55fdb5
Specs asserting focus target label text
aduth Oct 25, 2021
9746140
Spec for document steps troubleshooting
aduth Oct 25, 2021
df24140
Update BlockLink spec description
aduth Oct 25, 2021
f0730b7
Add TroubleshootingOptions specs
aduth Oct 25, 2021
fe7e4ef
Restore SubmissionInterstitial autoFocus behavior
aduth Oct 25, 2021
8a3510e
Add MarketingSiteContext displayName
aduth Oct 25, 2021
7d91cda
Specs for FailedCaptureAttemptsContext
aduth Oct 25, 2021
18a2a46
Specs for MarketingSiteContext
aduth Oct 25, 2021
ac0941f
More exhaustive DocumentStep failed attempts spec
aduth Oct 25, 2021
6faf77c
Move documents footer specs to DocumentsStep
aduth Oct 25, 2021
dcc594d
Add CaptureTroubleshooting component specs
aduth Oct 25, 2021
f9c402b
Remove unnecessary async function
aduth Oct 25, 2021
599831a
Update document-capture-spec to click correct submit button
aduth Oct 25, 2021
511c0e0
Combine maxCaptureAttemptsBeforeTips into AppRoot type destructure
aduth Oct 25, 2021
eadf947
merge main
aduth Oct 27, 2021
e49ce28
Revert "merge main"
aduth Oct 27, 2021
4a9e753
Merge branch 'main' into aduth-lg-5213-docauth-tips
aduth Oct 27, 2021
e8ceb90
Remove explicit focus anchor in favor of first content as anchor
aduth Oct 27, 2021
fca6abf
Add spec for MarketingSite.help_document_capture_tips_url
aduth Oct 27, 2021
346a639
Increase failed attempts before tips from 2 to 3
aduth Oct 27, 2021
c3361bc
Increase vertical margin of try again to 2.5rem
aduth Oct 27, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/assets/images/idv/capture-tips-clean.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions app/assets/images/idv/capture-tips-lighting.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions app/assets/images/idv/capture-tips-surface.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { render } from '@testing-library/react';
import BlockLink from '@18f/identity-document-capture/components/block-link';
import BlockLink from './block-link';

describe('document-capture/components/block-link', () => {
describe('BlockLink', () => {
const linkText = 'link text';
const url = '/example';

Expand Down
2 changes: 2 additions & 0 deletions app/javascript/packages/components/index.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
export { default as Alert } from './alert';
export { default as BlockLink } from './block-link';
export { default as Icon } from './icon';
export { default as TroubleshootingOptions } from './troubleshooting-options';
38 changes: 38 additions & 0 deletions app/javascript/packages/components/troubleshooting-options.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { BlockLink } from '@18f/identity-components';

/**
* @typedef TroubleshootingOption
*
* @prop {string} url
* @prop {string|JSX.Element} text
* @prop {boolean=} isExternal
*/

/**
* @typedef TroubleshootingOptionsProps
*
* @prop {string} heading
* @prop {TroubleshootingOption[]} options
*/

/**
* @param {TroubleshootingOptionsProps} props
*/
function TroubleshootingOptions({ heading, options }) {
return (
<section className="troubleshooting-options">
<h2>{heading}</h2>
<ul className="troubleshooting-options__options">
{options.map(({ url, text, isExternal }) => (
<li key={url}>
<BlockLink url={url} isNewTab={isExternal}>
{text}
</BlockLink>
</li>
))}
</ul>
</section>
);
}

export default TroubleshootingOptions;
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { render } from '@testing-library/react';
import TroubleshootingOptions from './troubleshooting-options';

describe('TroubleshootingOptions', () => {
it('renders a given heading', () => {
const { getByRole } = render(<TroubleshootingOptions heading="Need help?" options={[]} />);

const heading = getByRole('heading');

expect(heading.textContent).to.equal('Need help?');
});

it('renders given options', () => {
const { getAllByRole } = render(
<TroubleshootingOptions
heading=""
options={[
{ text: <>Option 1</>, url: 'https://example.com/1', isExternal: true },
{ text: 'Option 2', url: 'https://example.com/2' },
]}
/>,
);

const links = /** @type {HTMLAnchorElement[]} */ (getAllByRole('link'));

expect(links).to.have.lengthOf(2);
expect(links[0].textContent).to.equal('Option 1 links.new_window');
expect(links[0].href).to.equal('https://example.com/1');
expect(links[0].target).to.equal('_blank');
expect(links[1].textContent).to.equal('Option 2');
expect(links[1].href).to.equal('https://example.com/2');
expect(links[1].target).to.be.empty();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
import { useI18n } from '@18f/identity-react-i18n';
import AnalyticsContext from '../context/analytics';
import AcuantContext from '../context/acuant';
import FailedCaptureAttemptsContext from '../context/failed-capture-attempts';
import AcuantCaptureCanvas from './acuant-capture-canvas';
import FileInput from './file-input';
import FullScreen from './full-screen';
Expand Down Expand Up @@ -272,6 +273,9 @@ function AcuantCapture(
const { isMobile } = useContext(DeviceContext);
const { t, formatHTML } = useI18n();
const [attempt, incrementAttempt] = useCounter(1);
const { onFailedCaptureAttempt, onResetFailedCaptureAttempts } = useContext(
FailedCaptureAttemptsContext,
);
const hasCapture = !isError && (isReady ? isCameraSupported : isMobile);
useEffect(() => {
// If capture had started before Acuant was ready, stop capture if readiness reveals that no
Expand All @@ -297,7 +301,7 @@ function AcuantCapture(
/**
* Returns an analytics payload, decorated with common values.
*
* @template P
* @template {ImageAnalyticsPayload|AcuantImageAnalyticsPayload} P
*
* @param {P} payload
*
Expand Down Expand Up @@ -480,6 +484,9 @@ function AcuantCapture(

if (assessment === 'success') {
onChangeAndResetError(data, analyticsPayload);
onResetFailedCaptureAttempts();
} else {
onFailedCaptureAttempt({ isAssessedAsGlare, isAssessedAsBlurry });
}

setIsCapturingEnvironment(false);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { useContext } from 'react';
import { useI18n } from '@18f/identity-react-i18n';
import ServiceProviderContext from '../context/service-provider';
import MarketingSiteContext from '../context/marketing-site';
import useAsset from '../hooks/use-asset';
import Warning from './warning';

/** @typedef {import('@18f/identity-components/troubleshooting-options').TroubleshootingOption} TroubleshootingOption */

/**
* @typedef CaptureAdviceProps
*
* @prop {() => void} onTryAgain
* @prop {boolean} isAssessedAsGlare
* @prop {boolean} isAssessedAsBlurry
*/

/**
* @param {CaptureAdviceProps} props
*/
function CaptureAdvice({ onTryAgain, isAssessedAsGlare, isAssessedAsBlurry }) {
const { name: spName, getFailureToProofURL } = useContext(ServiceProviderContext);
const { documentCaptureTipsURL } = useContext(MarketingSiteContext);
const { getAssetPath } = useAsset();
const { t } = useI18n();

return (
<Warning
heading={t('doc_auth.headings.capture_troubleshooting_tips')}
autoFocus
actionText={t('idv.failure.button.warning')}
actionOnClick={onTryAgain}
troubleshootingHeading={t('idv.troubleshooting.headings.still_having_trouble')}
troubleshootingOptions={
/** @type {TroubleshootingOption[]} */ ([
{
url: documentCaptureTipsURL,
text: t('idv.troubleshooting.options.doc_capture_tips'),
isExternal: true,
},
spName && {
url: getFailureToProofURL('capture_tips'),
text: t('idv.troubleshooting.options.get_help_at_sp', { sp_name: spName }),
isExternal: true,
},
].filter(Boolean))
}
>
<p>
{isAssessedAsGlare && t('doc_auth.tips.capture_troubleshooting_glare')}
{isAssessedAsBlurry && t('doc_auth.tips.capture_troubleshooting_blurry')}{' '}
{t('doc_auth.tips.capture_troubleshooting_lead')}
</p>
<ul className="add-list-reset margin-y-3">
<li className="clearfix margin-bottom-3">
<img
width="82"
height="82"
src={getAssetPath('idv/capture-tips-surface.svg')}
alt={t('doc_auth.tips.capture_troubleshooting_surface_image')}
className="float-left margin-right-2"
/>
{t('doc_auth.tips.capture_troubleshooting_surface')}
</li>
<li className="clearfix margin-bottom-3">
<img
width="82"
height="82"
src={getAssetPath('idv/capture-tips-lighting.svg')}
alt={t('doc_auth.tips.capture_troubleshooting_lighting_image')}
className="float-left margin-right-2"
/>
{t('doc_auth.tips.capture_troubleshooting_lighting')}
</li>
<li className="clearfix">
<img
width="82"
height="82"
src={getAssetPath('idv/capture-tips-clean.svg')}
alt={t('doc_auth.tips.capture_troubleshooting_clean_image')}
className="float-left margin-right-2"
/>
{t('doc_auth.tips.capture_troubleshooting_clean')}
</li>
</ul>
</Warning>
);
}

export default CaptureAdvice;
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { useContext, useState } from 'react';
import FailedCaptureAttemptsContext from '../context/failed-capture-attempts';
import CaptureAdvice from './capture-advice';

/** @typedef {import('react').ReactNode} ReactNode */

/**
* @typedef CaptureTroubleshootingProps
*
* @prop {ReactNode} children
*/

/**
* @param {CaptureTroubleshootingProps} props
*/
function CaptureTroubleshooting({ children }) {
const [didShowTroubleshooting, setDidShowTroubleshooting] = useState(false);
const { failedCaptureAttempts, maxFailedAttemptsBeforeTips, lastAttemptMetadata } = useContext(
FailedCaptureAttemptsContext,
);
const { isAssessedAsGlare, isAssessedAsBlurry } = lastAttemptMetadata;

return failedCaptureAttempts >= maxFailedAttemptsBeforeTips && !didShowTroubleshooting ? (
<CaptureAdvice
onTryAgain={() => setDidShowTroubleshooting(true)}
isAssessedAsGlare={isAssessedAsGlare}
isAssessedAsBlurry={isAssessedAsBlurry}
/>
) : (
<>{children}</>
);
}

export default CaptureTroubleshooting;
Loading