From bf48e9d5f42df27bba7a73e1a25c355088d1a5ec Mon Sep 17 00:00:00 2001 From: Dawei Wang Date: Tue, 7 Nov 2023 11:01:00 -0500 Subject: [PATCH 1/8] LG-11260: resolve conflicts from main --- .../components/document-capture-not-ready.tsx | 59 ++++++++ .../document-capture-review-issues.tsx | 2 + .../components/documents-step.jsx | 3 +- config/locales/doc_auth/en.yml | 8 ++ config/locales/doc_auth/es.yml | 8 ++ config/locales/doc_auth/fr.yml | 8 ++ .../document-capture-not-ready-spec.tsx | 127 ++++++++++++++++++ 7 files changed, 214 insertions(+), 1 deletion(-) create mode 100644 app/javascript/packages/document-capture/components/document-capture-not-ready.tsx create mode 100644 spec/javascript/packages/document-capture/components/document-capture-not-ready-spec.tsx diff --git a/app/javascript/packages/document-capture/components/document-capture-not-ready.tsx b/app/javascript/packages/document-capture/components/document-capture-not-ready.tsx new file mode 100644 index 00000000000..3331385f9ef --- /dev/null +++ b/app/javascript/packages/document-capture/components/document-capture-not-ready.tsx @@ -0,0 +1,59 @@ +import { Button } from '@18f/identity-components'; +import { useI18n } from '@18f/identity-react-i18n'; +import { useContext } from 'react'; +import FlowContext from '@18f/identity-verify-flow/context/flow-context'; +import { addSearchParams, forceRedirect, Navigate } from '@18f/identity-url'; +import { getConfigValue } from '@18f/identity-config'; +import AnalyticsContext from '../context/analytics'; +import { ServiceProviderContext } from '../context'; + +export interface DocumentCaptureNotReadyProps { + navigate?: Navigate; +} + +function DocumentCaptureNotReady({ navigate }: DocumentCaptureNotReadyProps) { + const { t } = useI18n(); + const { trackEvent } = useContext(AnalyticsContext); + const { currentStep } = useContext(FlowContext); + const { name: spName, failureToProofURL } = useContext(ServiceProviderContext); + const appName = getConfigValue('appName'); + const header =

{t('doc_auth.not_ready.header')}

; + + const content = ( +

+ {spName + ? t('doc_auth.not_ready.content_sp', { + sp_name: spName, + app_name: appName, + }) + : t('doc_auth.not_ready.content_nosp', { + app_name: appName, + })} +

+ ); + const handleExit = () => { + trackEvent('IdV: docauth not ready link clicked'); + forceRedirect( + addSearchParams(spName ? failureToProofURL : '/account', { + step: currentStep, + location: 'not_ready', + }), + navigate, + ); + }; + + return ( + <> + {header} + {content} + + + + ); +} + +export default DocumentCaptureNotReady; diff --git a/app/javascript/packages/document-capture/components/document-capture-review-issues.tsx b/app/javascript/packages/document-capture/components/document-capture-review-issues.tsx index 44dc1a798eb..b696c257f9d 100644 --- a/app/javascript/packages/document-capture/components/document-capture-review-issues.tsx +++ b/app/javascript/packages/document-capture/components/document-capture-review-issues.tsx @@ -10,6 +10,7 @@ import { useI18n } from '@18f/identity-react-i18n'; import UnknownError from './unknown-error'; import TipList from './tip-list'; import DocumentSideAcuantCapture from './document-side-acuant-capture'; +import DocumentCaptureNotReady from './document-capture-not-ready'; interface DocumentCaptureReviewIssuesProps { isFailedDocType: boolean; @@ -78,6 +79,7 @@ function DocumentCaptureReviewIssues({ /> ))} + ); diff --git a/app/javascript/packages/document-capture/components/documents-step.jsx b/app/javascript/packages/document-capture/components/documents-step.jsx index ccb2763f600..aa636251b29 100644 --- a/app/javascript/packages/document-capture/components/documents-step.jsx +++ b/app/javascript/packages/document-capture/components/documents-step.jsx @@ -8,6 +8,7 @@ import DocumentSideAcuantCapture from './document-side-acuant-capture'; import DeviceContext from '../context/device'; import UploadContext from '../context/upload'; import TipList from './tip-list'; +import DocumentCaptureNotReady from './document-capture-not-ready'; /** * @typedef {'front'|'back'} DocumentSide @@ -70,7 +71,7 @@ function DocumentsStep({ /> ))} {isLastStep ? : } - + ); diff --git a/config/locales/doc_auth/en.yml b/config/locales/doc_auth/en.yml index a20678ea2e1..bfa1c7f84ba 100644 --- a/config/locales/doc_auth/en.yml +++ b/config/locales/doc_auth/en.yml @@ -279,6 +279,14 @@ en: - 'Verify by mail: We’ll mail a letter to your home address. This takes 5 to 10 days.' welcome: 'You will need your:' + not_ready: + button_nosp: Cancel and return to your profile + button_sp: Exit %{app_name} and return to %{sp_name} + content_nosp: If you exit %{app_name} now, you will not have verified your + identity. You can return later to finish this process. + content_sp: If you exit %{app_name} and return to %{sp_name}, you will not have + verified your identity. You can return later to finish this process. + header: Not ready to add photos? phone_question: do_not_have: I don’t have a phone tips: diff --git a/config/locales/doc_auth/es.yml b/config/locales/doc_auth/es.yml index ec8aac78177..3fef7cce75b 100644 --- a/config/locales/doc_auth/es.yml +++ b/config/locales/doc_auth/es.yml @@ -321,6 +321,14 @@ es: - 'Verificar por correo: Le enviaremos una carta a su domicilio. Esto tarda entre 5 y 10 días.' welcome: 'Necesitará su:' + not_ready: + button_nosp: Exit %{app_name} + button_sp: Exit %{app_name} and return to %{sp_name} + content_nosp: If you exit %{app_name}, you will not have verified your identity. + You can return later to finish this process. + content_sp: If you exit %{app_name} and return to %{sp_name}, you will not have + verified your identity. You can return later to finish this process. + header: Not ready to add photos? phone_question: do_not_have: No tengo teléfono tips: diff --git a/config/locales/doc_auth/fr.yml b/config/locales/doc_auth/fr.yml index a3e6bb40593..f786b5eb572 100644 --- a/config/locales/doc_auth/fr.yml +++ b/config/locales/doc_auth/fr.yml @@ -333,6 +333,14 @@ fr: lettre à votre adresse personnelle. Cela prend 5 à 10 jours.' welcome: 'Vous aurez besoin de votre:' + not_ready: + button_nosp: Exit %{app_name} + button_sp: Exit %{app_name} and return to %{sp_name} + content_nosp: If you exit %{app_name}, you will not have verified your identity. + You can return later to finish this process. + content_sp: If you exit %{app_name} and return to %{sp_name}, you will not have + verified your identity. You can return later to finish this process. + header: Not ready to add photos? phone_question: do_not_have: Je n’ai pas de téléphone tips: diff --git a/spec/javascript/packages/document-capture/components/document-capture-not-ready-spec.tsx b/spec/javascript/packages/document-capture/components/document-capture-not-ready-spec.tsx new file mode 100644 index 00000000000..2f8dbbcf94f --- /dev/null +++ b/spec/javascript/packages/document-capture/components/document-capture-not-ready-spec.tsx @@ -0,0 +1,127 @@ +import sinon from 'sinon'; + +import { FlowContext } from '@18f/identity-verify-flow'; +import { I18nContext } from '@18f/identity-react-i18n'; +import { I18n } from '@18f/identity-i18n'; +import userEvent from '@testing-library/user-event'; +import type { Navigate } from '@18f/identity-url'; +import { + AnalyticsContextProvider, + ServiceProviderContextProvider, +} from '@18f/identity-document-capture/context'; +import DocumentCaptureNotReady from '@18f/identity-document-capture/components/document-capture-not-ready'; +import { expect } from 'chai'; +import { render } from '../../../support/document-capture'; + +describe('DocumentCaptureNotReady', () => { + beforeEach(() => { + const config = document.createElement('script'); + config.id = 'test-config'; + config.type = 'application/json'; + config.setAttribute('data-config', ''); + config.textContent = JSON.stringify({ appName: 'Login.gov' }); + document.body.append(config); + }); + const trackEvent = sinon.spy(); + const navigateSpy: Navigate = sinon.spy(); + context('with service provider', () => { + const spName = 'testSP'; + it('renders, track event and redirect', async () => { + const { getByRole } = render( + + '', + }} + > + + + + + + + , + ); + // header + expect(getByRole('heading', { name: 'header text', level: 2 })).to.be.ok(); + + // content and exit link + const exitLink = getByRole('button', { name: 'Exit Login.gov and return to testSP' }); + expect(exitLink).to.be.ok(); + await userEvent.click(exitLink); + expect(navigateSpy).to.be.called.calledWithMatch( + /failure-to-proof\?step=document_capture&location=not_ready/, + ); + expect(trackEvent).to.be.calledWithMatch(/IdV: docauth not ready link clicked/); + }); + }); + + context('without service provider', () => { + it('renders, track event and redirect', async () => { + const { getByRole } = render( + + '', + }} + > + + + + + + + , + ); + // header + expect(getByRole('heading', { name: 'header text', level: 2 })).to.be.ok(); + + // content and exit link + const exitLink = getByRole('button', { name: 'Cancel and return to your profile' }); + expect(exitLink).to.be.ok(); + await userEvent.click(exitLink); + expect(navigateSpy).to.be.called.calledWithMatch( + /account\?step=document_capture&location=not_ready/, + ); + expect(trackEvent).to.be.calledWithMatch(/IdV: docauth not ready link clicked/); + }); + }); +}); From d39f8c9cd0d9280a68355c7d262f83be665ec95e Mon Sep 17 00:00:00 2001 From: Dawei Wang Date: Mon, 6 Nov 2023 11:33:05 -0500 Subject: [PATCH 2/8] LG-11260: change from main --- .../document-capture-review-issues.tsx | 5 ++- .../components/documents-step.jsx | 5 ++- .../document-capture/context/index.ts | 1 + .../document-capture/context/ui-config.tsx | 17 +++++++++ app/javascript/packs/document-capture.tsx | 10 +++++ .../idv/shared/_document_capture.html.erb | 1 + config/application.yml.default | 6 ++- lib/identity_config.rb | 1 + .../idv/doc_auth/document_capture_spec.rb | 14 ++++++- .../components/documents-step-spec.jsx | 38 +++++++++++++++++++ 10 files changed, 92 insertions(+), 6 deletions(-) create mode 100644 app/javascript/packages/document-capture/context/ui-config.tsx diff --git a/app/javascript/packages/document-capture/components/document-capture-review-issues.tsx b/app/javascript/packages/document-capture/components/document-capture-review-issues.tsx index b696c257f9d..9906071ae08 100644 --- a/app/javascript/packages/document-capture/components/document-capture-review-issues.tsx +++ b/app/javascript/packages/document-capture/components/document-capture-review-issues.tsx @@ -1,3 +1,4 @@ +import { useContext } from 'react'; import { PageHeading } from '@18f/identity-components'; import { FormStepError, @@ -11,6 +12,7 @@ import UnknownError from './unknown-error'; import TipList from './tip-list'; import DocumentSideAcuantCapture from './document-side-acuant-capture'; import DocumentCaptureNotReady from './document-capture-not-ready'; +import { UIConfigContext } from '../context'; interface DocumentCaptureReviewIssuesProps { isFailedDocType: boolean; @@ -44,6 +46,7 @@ function DocumentCaptureReviewIssues({ hasDismissed, }: DocumentCaptureReviewIssuesProps) { const { t } = useI18n(); + const { notReadySectionEnabled } = useContext(UIConfigContext); return ( <> {t('doc_auth.headings.review_issues')} @@ -79,7 +82,7 @@ function DocumentCaptureReviewIssues({ /> ))} - + {notReadySectionEnabled && } ); diff --git a/app/javascript/packages/document-capture/components/documents-step.jsx b/app/javascript/packages/document-capture/components/documents-step.jsx index aa636251b29..24d2274e1a6 100644 --- a/app/javascript/packages/document-capture/components/documents-step.jsx +++ b/app/javascript/packages/document-capture/components/documents-step.jsx @@ -9,6 +9,7 @@ import DeviceContext from '../context/device'; import UploadContext from '../context/upload'; import TipList from './tip-list'; import DocumentCaptureNotReady from './document-capture-not-ready'; +import { UIConfigContext } from '../context'; /** * @typedef {'front'|'back'} DocumentSide @@ -44,7 +45,7 @@ function DocumentsStep({ const { isMobile } = useContext(DeviceContext); const { isLastStep } = useContext(FormStepsContext); const { flowPath } = useContext(UploadContext); - + const { notReadySectionEnabled } = useContext(UIConfigContext); return ( <> {flowPath === 'hybrid' && } @@ -71,7 +72,7 @@ function DocumentsStep({ /> ))} {isLastStep ? : } - + {notReadySectionEnabled && } ); diff --git a/app/javascript/packages/document-capture/context/index.ts b/app/javascript/packages/document-capture/context/index.ts index 128326c3ff3..2e24d539115 100644 --- a/app/javascript/packages/document-capture/context/index.ts +++ b/app/javascript/packages/document-capture/context/index.ts @@ -16,3 +16,4 @@ export { } from './failed-capture-attempts'; export type { DeviceContextValue } from './device'; export { default as InPersonContext } from './in-person'; +export { default as UIConfigContext } from './ui-config'; diff --git a/app/javascript/packages/document-capture/context/ui-config.tsx b/app/javascript/packages/document-capture/context/ui-config.tsx new file mode 100644 index 00000000000..c196d4cbaf4 --- /dev/null +++ b/app/javascript/packages/document-capture/context/ui-config.tsx @@ -0,0 +1,17 @@ +import { createContext } from 'react'; + +export interface UIConfigContextProps { + /** + * Specify whether to show the not-ready section on doc capture screen. + * Populated from backend configuration + */ + notReadySectionEnabled: boolean; +} + +const UIConfigContext = createContext({ + notReadySectionEnabled: false, +}); + +UIConfigContext.displayName = 'UIConfigContext'; + +export default UIConfigContext; diff --git a/app/javascript/packs/document-capture.tsx b/app/javascript/packs/document-capture.tsx index 9d9125f96db..710c67f26e8 100644 --- a/app/javascript/packs/document-capture.tsx +++ b/app/javascript/packs/document-capture.tsx @@ -10,6 +10,7 @@ import { FailedCaptureAttemptsContextProvider, MarketingSiteContextProvider, InPersonContext, + UIConfigContext, } from '@18f/identity-document-capture'; import { isCameraCapableMobile } from '@18f/identity-device'; import { FlowContext } from '@18f/identity-verify-flow'; @@ -175,6 +176,15 @@ const App = composeComponents( maxSubmissionAttemptsBeforeNativeCamera: Number(maxSubmissionAttemptsBeforeNativeCamera), }, ], + [ + UIConfigContext.Provider, + { + value: { + notReadySectionEnabled: + String(appRoot.getAttribute('data-ui-not-ready-section-enabled')) === 'true', + }, + }, + ], [ DocumentCapture, { diff --git a/app/views/idv/shared/_document_capture.html.erb b/app/views/idv/shared/_document_capture.html.erb index 170ee611e79..142f552a8e0 100644 --- a/app/views/idv/shared/_document_capture.html.erb +++ b/app/views/idv/shared/_document_capture.html.erb @@ -37,6 +37,7 @@ in_person_outage_expected_update_date: IdentityConfig.store.in_person_outage_expected_update_date, us_states_territories: us_states_territories, doc_auth_selfie_capture: IdentityConfig.store.doc_auth_selfie_capture, + ui_not_ready_section_enabled: IdentityConfig.store.doc_auth_not_ready_section_enabled, } %> <%= simple_form_for( :doc_auth, diff --git a/config/application.yml.default b/config/application.yml.default index 04818829f1e..a360f77bdff 100644 --- a/config/application.yml.default +++ b/config/application.yml.default @@ -85,6 +85,7 @@ doc_auth_error_sharpness_threshold: 40 doc_auth_max_attempts: 5 doc_auth_max_capture_attempts_before_native_camera: 3 doc_auth_max_submission_attempts_before_native_camera: 3 +doc_auth_not_ready_section_enabled: false doc_auth_selfie_capture: '{"enabled":false}' doc_auth_supported_country_codes: '["US", "GU", "VI", "AS", "MP", "PR", "USA" ,"GUM", "VIR", "ASM", "MNP", "PRI"]' doc_capture_request_valid_for_minutes: 15 @@ -380,11 +381,12 @@ development: database_worker_jobs_username: '' database_worker_jobs_host: '' database_worker_jobs_password: '' - doc_auth_selfie_capture: '{"enabled":false}' + doc_auth_selfie_capture: '{"enabled":false}' doc_auth_vendor: 'mock' doc_auth_vendor_randomize: false doc_auth_vendor_randomize_percent: 0 doc_auth_vendor_randomize_alternate_vendor: '' + doc_auth_not_ready_section_enabled: true domain_name: localhost:3000 enable_rate_limiting: false hmac_fingerprinter_key: a2c813d4dca919340866ba58063e4072adc459b767a74cf2666d5c1eef3861db26708e7437abde1755eb24f4034386b0fea1850a1cb7e56bff8fae3cc6ade96c @@ -523,7 +525,7 @@ test: doc_auth_vendor_randomize: false doc_auth_vendor_randomize_percent: 0 doc_auth_vendor_randomize_alternate_vendor: '' - doc_auth_selfie_capture: '{"enabled":false}' + doc_auth_selfie_capture: '{"enabled":false}' doc_capture_polling_enabled: false domain_name: www.example.com hmac_fingerprinter_key: a2c813d4dca919340866ba58063e4072adc459b767a74cf2666d5c1eef3861db26708e7437abde1755eb24f4034386b0fea1850a1cb7e56bff8fae3cc6ade96c diff --git a/lib/identity_config.rb b/lib/identity_config.rb index a9d884e4237..5e4c20eb141 100644 --- a/lib/identity_config.rb +++ b/lib/identity_config.rb @@ -180,6 +180,7 @@ def self.build_store(config_map) config.add(:doc_auth_error_dpi_threshold, type: :integer) config.add(:doc_auth_error_glare_threshold, type: :integer) config.add(:doc_auth_error_sharpness_threshold, type: :integer) + config.add(:doc_auth_not_ready_section_enabled, type: :boolean) config.add(:doc_auth_max_attempts, type: :integer) config.add(:doc_auth_max_capture_attempts_before_native_camera, type: :integer) config.add(:doc_auth_max_submission_attempts_before_native_camera, type: :integer) diff --git a/spec/features/idv/doc_auth/document_capture_spec.rb b/spec/features/idv/doc_auth/document_capture_spec.rb index eedb3fef6bc..314ca89f7e6 100644 --- a/spec/features/idv/doc_auth/document_capture_spec.rb +++ b/spec/features/idv/doc_auth/document_capture_spec.rb @@ -9,10 +9,12 @@ let(:user) { user_with_2fa } let(:fake_analytics) { FakeAnalytics.new } let(:sp_name) { 'Test SP' } + let(:enable_not_ready) { true } before do allow_any_instance_of(ApplicationController).to receive(:analytics).and_return(fake_analytics) allow_any_instance_of(ServiceProviderSession).to receive(:sp_name).and_return(sp_name) - + allow(IdentityConfig.store).to receive(:doc_auth_not_ready_section_enabled). + and_return(enable_not_ready) visit_idp_from_oidc_sp_with_ial2 sign_in_and_2fa_user(user) @@ -134,6 +136,16 @@ expect(DocAuthLog.find_by(user_id: user.id).state).to be_nil end + context 'not ready section' do + it 'renders not ready section when enabled' do + expect(page).to have_content( + I18n.t( + 'doc_auth.not_ready.content_sp', sp_name: sp_name, + app_name: APP_NAME + ), + ) + end + end end context 'standard mobile flow' do diff --git a/spec/javascript/packages/document-capture/components/documents-step-spec.jsx b/spec/javascript/packages/document-capture/components/documents-step-spec.jsx index d160d95c5b4..92f4747d754 100644 --- a/spec/javascript/packages/document-capture/components/documents-step-spec.jsx +++ b/spec/javascript/packages/document-capture/components/documents-step-spec.jsx @@ -1,12 +1,15 @@ import userEvent from '@testing-library/user-event'; import sinon from 'sinon'; +import { expect } from 'chai'; import { t } from '@18f/identity-i18n'; import { DeviceContext, UploadContextProvider, FailedCaptureAttemptsContextProvider, + UIConfigContext, } from '@18f/identity-document-capture'; import DocumentsStep from '@18f/identity-document-capture/components/documents-step'; +import { composeComponents } from '@18f/identity-compose-components'; import { render } from '../../../support/document-capture'; import { getFixtureFile } from '../../../support/file'; @@ -82,4 +85,39 @@ describe('document-capture/components/documents-step', () => { expect(queryByText(notExpectedText)).to.not.exist(); }); + + context('not ready section', () => { + it('is rendered when enabled', () => { + const App = composeComponents( + [ + UIConfigContext.Provider, + { + value: { + notReadySectionEnabled: true, + }, + }, + ], + [DocumentsStep], + ); + const { getByRole } = render(); + expect(getByRole('heading', { name: 'doc_auth.not_ready.header', level: 2 })).to.be.ok(); + const button = getByRole('button', { name: 'doc_auth.not_ready.button_nosp' }); + expect(button).to.be.ok(); + }); + it('is rendered when disabled', () => { + const App = composeComponents( + [ + UIConfigContext.Provider, + { + value: { + notReadySectionEnabled: false, + }, + }, + ], + [DocumentsStep], + ); + const { queryByRole } = render(); + expect(queryByRole('heading', { name: 'doc_auth.not_ready.header', level: 2 })).to.be.null(); + }); + }); }); From 639c281519b336188a6463d0016f7353f6ad280e Mon Sep 17 00:00:00 2001 From: Dawei Wang Date: Thu, 2 Nov 2023 10:47:08 -0400 Subject: [PATCH 3/8] LG-11260: translation updates. --- .../components/document-capture-not-ready.tsx | 2 +- config/locales/doc_auth/es.yml | 15 ++++++++------- config/locales/doc_auth/fr.yml | 15 ++++++++------- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/app/javascript/packages/document-capture/components/document-capture-not-ready.tsx b/app/javascript/packages/document-capture/components/document-capture-not-ready.tsx index 3331385f9ef..2db287d4ab0 100644 --- a/app/javascript/packages/document-capture/components/document-capture-not-ready.tsx +++ b/app/javascript/packages/document-capture/components/document-capture-not-ready.tsx @@ -50,7 +50,7 @@ function DocumentCaptureNotReady({ navigate }: DocumentCaptureNotReadyProps) { ); diff --git a/config/locales/doc_auth/es.yml b/config/locales/doc_auth/es.yml index 3fef7cce75b..8f7b03244e5 100644 --- a/config/locales/doc_auth/es.yml +++ b/config/locales/doc_auth/es.yml @@ -322,13 +322,14 @@ es: domicilio. Esto tarda entre 5 y 10 días.' welcome: 'Necesitará su:' not_ready: - button_nosp: Exit %{app_name} - button_sp: Exit %{app_name} and return to %{sp_name} - content_nosp: If you exit %{app_name}, you will not have verified your identity. - You can return later to finish this process. - content_sp: If you exit %{app_name} and return to %{sp_name}, you will not have - verified your identity. You can return later to finish this process. - header: Not ready to add photos? + button_nosp: Cancelar y volver a su perfil + button_sp: Salir de %{app_name} y volver a %{sp_name} + content_nosp: Si sale ahora de %{app_name}, no habrá verificado su identidad. + Puede volver más tarde para completar este proceso. + content_sp: Si sale ahora de %{app_name} y regresa a %{sp_name}, no habrá + verificado su identidad. Puede volver más tarde para completar este + proceso. + header: ¿No está listo para enviar las fotos? phone_question: do_not_have: No tengo teléfono tips: diff --git a/config/locales/doc_auth/fr.yml b/config/locales/doc_auth/fr.yml index f786b5eb572..06c97bf7484 100644 --- a/config/locales/doc_auth/fr.yml +++ b/config/locales/doc_auth/fr.yml @@ -334,13 +334,14 @@ fr: jours.' welcome: 'Vous aurez besoin de votre:' not_ready: - button_nosp: Exit %{app_name} - button_sp: Exit %{app_name} and return to %{sp_name} - content_nosp: If you exit %{app_name}, you will not have verified your identity. - You can return later to finish this process. - content_sp: If you exit %{app_name} and return to %{sp_name}, you will not have - verified your identity. You can return later to finish this process. - header: Not ready to add photos? + button_nosp: Annuler et revenir à votre profil + button_sp: Quittez %{app_name} et retournez à %{sp_name} + content_nosp: Si vous quittez %{app_name}, votre identité n’aura pas été + vérifiée. Vous pourrez revenir plus tard pour terminer ce processus. + content_sp: Si vous quittez %{app_name} maintenant et revenez sur %{sp_name}, + votre identité n’aura pas été vérifiée. Vous pourrez revenir plus tard + pour terminer ce processus. + header: Vous n’êtes pas prêt à ajouter des photos? phone_question: do_not_have: Je n’ai pas de téléphone tips: From aa0eaa150a65e2325febc5dfdf141c11ad6e136b Mon Sep 17 00:00:00 2001 From: Dawei Wang Date: Fri, 3 Nov 2023 08:50:26 -0400 Subject: [PATCH 4/8] LG-11260: test description. --- .../document-capture/components/documents-step-spec.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/javascript/packages/document-capture/components/documents-step-spec.jsx b/spec/javascript/packages/document-capture/components/documents-step-spec.jsx index 92f4747d754..950bdf435e1 100644 --- a/spec/javascript/packages/document-capture/components/documents-step-spec.jsx +++ b/spec/javascript/packages/document-capture/components/documents-step-spec.jsx @@ -104,7 +104,7 @@ describe('document-capture/components/documents-step', () => { const button = getByRole('button', { name: 'doc_auth.not_ready.button_nosp' }); expect(button).to.be.ok(); }); - it('is rendered when disabled', () => { + it('is not rendered when disabled', () => { const App = composeComponents( [ UIConfigContext.Provider, From 172b806dd8cb541178158389ab4846a81077fd75 Mon Sep 17 00:00:00 2001 From: Dawei Wang Date: Tue, 7 Nov 2023 11:02:33 -0500 Subject: [PATCH 5/8] LG-11260: resolve conflicts from main --- app/javascript/packs/document-capture.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/javascript/packs/document-capture.tsx b/app/javascript/packs/document-capture.tsx index 710c67f26e8..32f0edbbb18 100644 --- a/app/javascript/packs/document-capture.tsx +++ b/app/javascript/packs/document-capture.tsx @@ -34,6 +34,7 @@ interface AppRootData { exitUrl: string; idvInPersonUrl?: string; securityAndPrivacyHowItWorksUrl: string; + uiNotReadySectionEnabled: string; } const appRoot = document.getElementById('document-capture-form')!; @@ -100,6 +101,7 @@ const { inPersonOutageExpectedUpdateDate, usStatesTerritories = '', phoneWithCamera = '', + uiNotReadySectionEnabled = '', } = appRoot.dataset as DOMStringMap & AppRootData; let parsedUsStatesTerritories = []; @@ -180,8 +182,7 @@ const App = composeComponents( UIConfigContext.Provider, { value: { - notReadySectionEnabled: - String(appRoot.getAttribute('data-ui-not-ready-section-enabled')) === 'true', + notReadySectionEnabled: String(uiNotReadySectionEnabled) === 'true', }, }, ], From 359187a8fea66c2ef9641f18a3d7c790f3a5d71c Mon Sep 17 00:00:00 2001 From: Dawei Wang Date: Sat, 4 Nov 2023 09:58:57 -0400 Subject: [PATCH 6/8] LG-11260: rename context. --- .../components/document-capture-review-issues.tsx | 4 ++-- .../document-capture/components/documents-step.jsx | 4 ++-- .../context/{ui-config.tsx => feature-flag.tsx} | 8 ++++---- app/javascript/packages/document-capture/context/index.ts | 2 +- app/javascript/packs/document-capture.tsx | 4 ++-- .../document-capture/components/documents-step-spec.jsx | 6 +++--- 6 files changed, 14 insertions(+), 14 deletions(-) rename app/javascript/packages/document-capture/context/{ui-config.tsx => feature-flag.tsx} (54%) diff --git a/app/javascript/packages/document-capture/components/document-capture-review-issues.tsx b/app/javascript/packages/document-capture/components/document-capture-review-issues.tsx index 9906071ae08..89a3a07e50c 100644 --- a/app/javascript/packages/document-capture/components/document-capture-review-issues.tsx +++ b/app/javascript/packages/document-capture/components/document-capture-review-issues.tsx @@ -12,7 +12,7 @@ import UnknownError from './unknown-error'; import TipList from './tip-list'; import DocumentSideAcuantCapture from './document-side-acuant-capture'; import DocumentCaptureNotReady from './document-capture-not-ready'; -import { UIConfigContext } from '../context'; +import { FeatureFlagContext } from '../context'; interface DocumentCaptureReviewIssuesProps { isFailedDocType: boolean; @@ -46,7 +46,7 @@ function DocumentCaptureReviewIssues({ hasDismissed, }: DocumentCaptureReviewIssuesProps) { const { t } = useI18n(); - const { notReadySectionEnabled } = useContext(UIConfigContext); + const { notReadySectionEnabled } = useContext(FeatureFlagContext); return ( <> {t('doc_auth.headings.review_issues')} diff --git a/app/javascript/packages/document-capture/components/documents-step.jsx b/app/javascript/packages/document-capture/components/documents-step.jsx index 24d2274e1a6..16db622b7be 100644 --- a/app/javascript/packages/document-capture/components/documents-step.jsx +++ b/app/javascript/packages/document-capture/components/documents-step.jsx @@ -9,7 +9,7 @@ import DeviceContext from '../context/device'; import UploadContext from '../context/upload'; import TipList from './tip-list'; import DocumentCaptureNotReady from './document-capture-not-ready'; -import { UIConfigContext } from '../context'; +import { FeatureFlagContext } from '../context'; /** * @typedef {'front'|'back'} DocumentSide @@ -45,7 +45,7 @@ function DocumentsStep({ const { isMobile } = useContext(DeviceContext); const { isLastStep } = useContext(FormStepsContext); const { flowPath } = useContext(UploadContext); - const { notReadySectionEnabled } = useContext(UIConfigContext); + const { notReadySectionEnabled } = useContext(FeatureFlagContext); return ( <> {flowPath === 'hybrid' && } diff --git a/app/javascript/packages/document-capture/context/ui-config.tsx b/app/javascript/packages/document-capture/context/feature-flag.tsx similarity index 54% rename from app/javascript/packages/document-capture/context/ui-config.tsx rename to app/javascript/packages/document-capture/context/feature-flag.tsx index c196d4cbaf4..26048b8bcbd 100644 --- a/app/javascript/packages/document-capture/context/ui-config.tsx +++ b/app/javascript/packages/document-capture/context/feature-flag.tsx @@ -1,6 +1,6 @@ import { createContext } from 'react'; -export interface UIConfigContextProps { +export interface FeatureFlagContextProps { /** * Specify whether to show the not-ready section on doc capture screen. * Populated from backend configuration @@ -8,10 +8,10 @@ export interface UIConfigContextProps { notReadySectionEnabled: boolean; } -const UIConfigContext = createContext({ +const FeatureFlagContext = createContext({ notReadySectionEnabled: false, }); -UIConfigContext.displayName = 'UIConfigContext'; +FeatureFlagContext.displayName = 'FeatureFlagContext'; -export default UIConfigContext; +export default FeatureFlagContext; diff --git a/app/javascript/packages/document-capture/context/index.ts b/app/javascript/packages/document-capture/context/index.ts index 2e24d539115..dfbcbdf47bc 100644 --- a/app/javascript/packages/document-capture/context/index.ts +++ b/app/javascript/packages/document-capture/context/index.ts @@ -16,4 +16,4 @@ export { } from './failed-capture-attempts'; export type { DeviceContextValue } from './device'; export { default as InPersonContext } from './in-person'; -export { default as UIConfigContext } from './ui-config'; +export { default as FeatureFlagContext } from './feature-flag'; diff --git a/app/javascript/packs/document-capture.tsx b/app/javascript/packs/document-capture.tsx index 32f0edbbb18..b50b0a5c2f6 100644 --- a/app/javascript/packs/document-capture.tsx +++ b/app/javascript/packs/document-capture.tsx @@ -10,7 +10,7 @@ import { FailedCaptureAttemptsContextProvider, MarketingSiteContextProvider, InPersonContext, - UIConfigContext, + FeatureFlagContext, } from '@18f/identity-document-capture'; import { isCameraCapableMobile } from '@18f/identity-device'; import { FlowContext } from '@18f/identity-verify-flow'; @@ -179,7 +179,7 @@ const App = composeComponents( }, ], [ - UIConfigContext.Provider, + FeatureFlagContext.Provider, { value: { notReadySectionEnabled: String(uiNotReadySectionEnabled) === 'true', diff --git a/spec/javascript/packages/document-capture/components/documents-step-spec.jsx b/spec/javascript/packages/document-capture/components/documents-step-spec.jsx index 950bdf435e1..44b2e570d37 100644 --- a/spec/javascript/packages/document-capture/components/documents-step-spec.jsx +++ b/spec/javascript/packages/document-capture/components/documents-step-spec.jsx @@ -6,7 +6,7 @@ import { DeviceContext, UploadContextProvider, FailedCaptureAttemptsContextProvider, - UIConfigContext, + FeatureFlagContext, } from '@18f/identity-document-capture'; import DocumentsStep from '@18f/identity-document-capture/components/documents-step'; import { composeComponents } from '@18f/identity-compose-components'; @@ -90,7 +90,7 @@ describe('document-capture/components/documents-step', () => { it('is rendered when enabled', () => { const App = composeComponents( [ - UIConfigContext.Provider, + FeatureFlagContext.Provider, { value: { notReadySectionEnabled: true, @@ -107,7 +107,7 @@ describe('document-capture/components/documents-step', () => { it('is not rendered when disabled', () => { const App = composeComponents( [ - UIConfigContext.Provider, + FeatureFlagContext.Provider, { value: { notReadySectionEnabled: false, From bf023841f9b8d9fdce9c2dbe1ca9de86d5d317bf Mon Sep 17 00:00:00 2001 From: Dawei Wang Date: Mon, 6 Nov 2023 15:11:40 -0500 Subject: [PATCH 7/8] LG-11260: minor translation update. --- config/locales/doc_auth/en.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/config/locales/doc_auth/en.yml b/config/locales/doc_auth/en.yml index bfa1c7f84ba..191589bbb74 100644 --- a/config/locales/doc_auth/en.yml +++ b/config/locales/doc_auth/en.yml @@ -284,8 +284,9 @@ en: button_sp: Exit %{app_name} and return to %{sp_name} content_nosp: If you exit %{app_name} now, you will not have verified your identity. You can return later to finish this process. - content_sp: If you exit %{app_name} and return to %{sp_name}, you will not have - verified your identity. You can return later to finish this process. + content_sp: If you exit %{app_name} now and return to %{sp_name}, you will not + have verified your identity. You can return later to finish this + process. header: Not ready to add photos? phone_question: do_not_have: I don’t have a phone From db1cae72148af4d488c270536623c6e5fa1773a6 Mon Sep 17 00:00:00 2001 From: Dawei Wang Date: Tue, 7 Nov 2023 14:38:29 -0500 Subject: [PATCH 8/8] LG-11260: inline small pieces of react elements. changelog: User-Facing Improvements, Doc Auth, Not ready experience. --- .../components/document-capture-not-ready.tsx | 28 ++++++++----------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/app/javascript/packages/document-capture/components/document-capture-not-ready.tsx b/app/javascript/packages/document-capture/components/document-capture-not-ready.tsx index 2db287d4ab0..07c5923ab46 100644 --- a/app/javascript/packages/document-capture/components/document-capture-not-ready.tsx +++ b/app/javascript/packages/document-capture/components/document-capture-not-ready.tsx @@ -17,20 +17,6 @@ function DocumentCaptureNotReady({ navigate }: DocumentCaptureNotReadyProps) { const { currentStep } = useContext(FlowContext); const { name: spName, failureToProofURL } = useContext(ServiceProviderContext); const appName = getConfigValue('appName'); - const header =

{t('doc_auth.not_ready.header')}

; - - const content = ( -

- {spName - ? t('doc_auth.not_ready.content_sp', { - sp_name: spName, - app_name: appName, - }) - : t('doc_auth.not_ready.content_nosp', { - app_name: appName, - })} -

- ); const handleExit = () => { trackEvent('IdV: docauth not ready link clicked'); forceRedirect( @@ -44,9 +30,17 @@ function DocumentCaptureNotReady({ navigate }: DocumentCaptureNotReadyProps) { return ( <> - {header} - {content} - +

{t('doc_auth.not_ready.header')}

+

+ {spName + ? t('doc_auth.not_ready.content_sp', { + sp_name: spName, + app_name: appName, + }) + : t('doc_auth.not_ready.content_nosp', { + app_name: appName, + })} +