Compare commits

...

20 Commits

Author SHA1 Message Date
morenol
8602561e55 fix: Update frontend-build (#340)
Update frontend-platform
2020-11-10 17:18:02 -05:00
Renovate Bot
b310574f18 fix(deps): update font awesome 2020-11-10 02:00:05 +00:00
Renovate Bot
73badaf916 fix(deps): update dependency universal-cookie to v4.0.4 2020-11-10 00:58:25 +00:00
Renovate Bot
f02cc43078 chore(deps): update dependency enzyme-adapter-react-16 to v1.15.5 2020-11-09 23:36:50 +00:00
edX Transifex Bot
bd5c2343be fix(i18n): update translations 2020-11-08 16:03:56 -05:00
alangsto
6349d487e4 Merge pull request #343 from edx/alangsto/camera_permissions
Ensure that first stream is stopped
2020-11-05 14:40:40 -05:00
Alie Langston
9c6137e668 testing to see if we need to request front/back camera
stopping initial stream
2020-11-05 14:30:39 -05:00
alangsto
2cf01270d7 Merge pull request #342 from edx/alangsto/fix_camera_access
Remove browser based resolution
2020-11-04 13:15:26 -05:00
Alie Langston
403df8926d removed browser based resolution, and instead optimized photo for all browsers
completed comment
2020-11-04 13:01:14 -05:00
Bianca Severino
4bd96c70af Merge pull request #341 from edx/bseverino/name-change-fix
Fix onSubmit for IDV name change form
2020-10-27 12:32:30 -04:00
Bianca Severino
d2a835f560 Fix submit functionality on name change form 2020-10-27 12:13:47 -04:00
Bianca Severino
d0b5d54d0a Merge pull request #339 from edx/bseverino/id-resolution
Increase camera resolution to 1080p for ID verification
2020-10-20 14:17:51 -04:00
Bianca Severino
26299eed65 Increase camera resolution to 1080p 2020-10-20 13:53:01 -04:00
adeelehsan
648bea8d84 Merge pull request #338 from edx/aehsan/suppressred_pii_for_accounts
suppressed pii for account
2020-10-09 01:59:13 +05:00
adeelehsan
7409f02056 suppressed pii for account 2020-10-09 00:54:07 +05:00
alangsto
f5dd409816 Merge pull request #337 from edx/alangsto/add_tracking_events
Add tracking events for face detection
2020-10-01 15:32:36 -04:00
Alie Langston
6ddac11dc0 added tracking events
added testing
2020-10-01 14:19:07 -04:00
adeelehsan
7019aea4fb Merge pull request #333 from edx/aehsan/van-23/suppressed_pii_for_accounts
suppressed pii for hot jar
2020-09-25 17:33:37 +05:00
adeelehsan
5424434599 suppressed pii for hot jar
VAN-23
2020-09-25 17:22:13 +05:00
edX Transifex Bot
8ca9dc78a9 fix(i18n): update translations 2020-09-20 17:06:06 -04:00
15 changed files with 9269 additions and 5482 deletions

14269
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -31,13 +31,13 @@
"dependencies": {
"@edx/frontend-component-footer": "10.0.11",
"@edx/frontend-component-header": "2.0.5",
"@edx/frontend-platform": "1.1.14",
"@edx/frontend-platform": "1.6.1",
"@edx/paragon": "9.1.1",
"@fortawesome/fontawesome-svg-core": "1.2.30",
"@fortawesome/fontawesome-svg-core": "1.2.32",
"@fortawesome/free-brands-svg-icons": "5.8.2",
"@fortawesome/free-regular-svg-icons": "5.7.2",
"@fortawesome/free-solid-svg-icons": "5.8.2",
"@fortawesome/react-fontawesome": "0.1.11",
"@fortawesome/react-fontawesome": "0.1.12",
"@tensorflow-models/blazeface": "git+https://github.com/alangsto/blazeface.git",
"@tensorflow/tfjs-converter": "1.6.1",
"@tensorflow/tfjs-core": "1.6.1",
@@ -77,15 +77,15 @@
"redux-saga": "1.1.3",
"redux-thunk": "2.3.0",
"reselect": "4.0.0",
"universal-cookie": "4.0.3"
"universal-cookie": "4.0.4"
},
"devDependencies": {
"@edx/frontend-build": "2.0.6",
"@edx/frontend-build": "5.3.2",
"@testing-library/jest-dom": "^5.11.2",
"@testing-library/react": "^10.4.7",
"codecov": "3.7.2",
"enzyme": "3.10.0",
"enzyme-adapter-react-16": "1.15.4",
"enzyme-adapter-react-16": "1.15.5",
"es-check": "5.0.0",
"husky": "3.0.9",
"jest": "^26.1.0",

View File

@@ -4,7 +4,7 @@
<title>Account | edX</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" />
<link rel="shortcut icon" href="<%=webpackConfig.output.publicPath%>favicon.ico" type="image/x-icon" />
</head>
<body>
<div id="root"></div>

View File

@@ -106,6 +106,7 @@ function EditableField(props) {
>
<label className="h6 d-block" htmlFor={id}>{label}</label>
<Input
data-hj-suppress
name={name}
id={id}
type={type}
@@ -155,7 +156,7 @@ function EditableField(props) {
</Button>
) : null}
</div>
<p>{renderValue(value)}</p>
<p data-hj-suppress>{renderValue(value)}</p>
<p className="small text-muted mt-n2">{renderConfirmationMessage() || helpText}</p>
</div>
),

View File

@@ -109,6 +109,7 @@ function EmailField(props) {
>
<label className="h6 d-block" htmlFor={id}>{label}</label>
<Input
data-hj-suppress
name={name}
id={id}
type="email"
@@ -156,7 +157,7 @@ function EmailField(props) {
</Button>
) : null}
</div>
<p>{renderValue()}</p>
<p data-hj-suppress>{renderValue()}</p>
{renderConfirmationMessage() || <p className="small text-muted mt-n2">{helpText}</p>}
</div>
),

View File

@@ -74,7 +74,9 @@ exports[`DemographicsSection should render 1`] = `
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
Prefer not to respond
</p>
<p
@@ -136,7 +138,9 @@ exports[`DemographicsSection should render 1`] = `
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
<button
className="btn btn-link p-0"
onBlur={[Function]}
@@ -206,7 +210,9 @@ exports[`DemographicsSection should render 1`] = `
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
Prefer not to respond
</p>
<p
@@ -268,7 +274,9 @@ exports[`DemographicsSection should render 1`] = `
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
Prefer not to respond
</p>
<p
@@ -330,7 +338,9 @@ exports[`DemographicsSection should render 1`] = `
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
Prefer not to respond
</p>
<p
@@ -392,7 +402,9 @@ exports[`DemographicsSection should render 1`] = `
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
Prefer not to respond
</p>
<p
@@ -454,7 +466,9 @@ exports[`DemographicsSection should render 1`] = `
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
Prefer not to respond
</p>
<p
@@ -516,7 +530,9 @@ exports[`DemographicsSection should render 1`] = `
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
Prefer not to respond
</p>
<p
@@ -578,7 +594,9 @@ exports[`DemographicsSection should render 1`] = `
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
Prefer not to respond
</p>
<p
@@ -679,7 +697,9 @@ exports[`DemographicsSection should render an Alert if an error occurs 1`] = `
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
Prefer not to respond
</p>
<p
@@ -741,7 +761,9 @@ exports[`DemographicsSection should render an Alert if an error occurs 1`] = `
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
<button
className="btn btn-link p-0"
onBlur={[Function]}
@@ -811,7 +833,9 @@ exports[`DemographicsSection should render an Alert if an error occurs 1`] = `
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
Prefer not to respond
</p>
<p
@@ -873,7 +897,9 @@ exports[`DemographicsSection should render an Alert if an error occurs 1`] = `
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
Prefer not to respond
</p>
<p
@@ -935,7 +961,9 @@ exports[`DemographicsSection should render an Alert if an error occurs 1`] = `
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
Prefer not to respond
</p>
<p
@@ -997,7 +1025,9 @@ exports[`DemographicsSection should render an Alert if an error occurs 1`] = `
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
Prefer not to respond
</p>
<p
@@ -1059,7 +1089,9 @@ exports[`DemographicsSection should render an Alert if an error occurs 1`] = `
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
Prefer not to respond
</p>
<p
@@ -1121,7 +1153,9 @@ exports[`DemographicsSection should render an Alert if an error occurs 1`] = `
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
Prefer not to respond
</p>
<p
@@ -1183,7 +1217,9 @@ exports[`DemographicsSection should render an Alert if an error occurs 1`] = `
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
Prefer not to respond
</p>
<p
@@ -1305,7 +1341,9 @@ exports[`DemographicsSection should render ethnicity correctly when multiple opt
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
Prefer not to respond
</p>
<p
@@ -1367,7 +1405,9 @@ exports[`DemographicsSection should render ethnicity correctly when multiple opt
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
Hispanic, Latin, or Spanish origin, White
</p>
<p
@@ -1429,7 +1469,9 @@ exports[`DemographicsSection should render ethnicity correctly when multiple opt
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
Prefer not to respond
</p>
<p
@@ -1491,7 +1533,9 @@ exports[`DemographicsSection should render ethnicity correctly when multiple opt
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
Prefer not to respond
</p>
<p
@@ -1553,7 +1597,9 @@ exports[`DemographicsSection should render ethnicity correctly when multiple opt
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
Prefer not to respond
</p>
<p
@@ -1615,7 +1661,9 @@ exports[`DemographicsSection should render ethnicity correctly when multiple opt
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
Prefer not to respond
</p>
<p
@@ -1677,7 +1725,9 @@ exports[`DemographicsSection should render ethnicity correctly when multiple opt
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
Prefer not to respond
</p>
<p
@@ -1739,7 +1789,9 @@ exports[`DemographicsSection should render ethnicity correctly when multiple opt
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
Prefer not to respond
</p>
<p
@@ -1801,7 +1853,9 @@ exports[`DemographicsSection should render ethnicity correctly when multiple opt
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
Prefer not to respond
</p>
<p
@@ -1888,7 +1942,9 @@ exports[`DemographicsSection should render ethnicity text correctly 1`] = `
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
Prefer not to respond
</p>
<p
@@ -1950,7 +2006,9 @@ exports[`DemographicsSection should render ethnicity text correctly 1`] = `
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
Asian
</p>
<p
@@ -2012,7 +2070,9 @@ exports[`DemographicsSection should render ethnicity text correctly 1`] = `
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
Prefer not to respond
</p>
<p
@@ -2074,7 +2134,9 @@ exports[`DemographicsSection should render ethnicity text correctly 1`] = `
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
Prefer not to respond
</p>
<p
@@ -2136,7 +2198,9 @@ exports[`DemographicsSection should render ethnicity text correctly 1`] = `
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
Prefer not to respond
</p>
<p
@@ -2198,7 +2262,9 @@ exports[`DemographicsSection should render ethnicity text correctly 1`] = `
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
Prefer not to respond
</p>
<p
@@ -2260,7 +2326,9 @@ exports[`DemographicsSection should render ethnicity text correctly 1`] = `
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
Prefer not to respond
</p>
<p
@@ -2322,7 +2390,9 @@ exports[`DemographicsSection should render ethnicity text correctly 1`] = `
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
Prefer not to respond
</p>
<p
@@ -2384,7 +2454,9 @@ exports[`DemographicsSection should render ethnicity text correctly 1`] = `
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
Prefer not to respond
</p>
<p
@@ -2471,7 +2543,9 @@ exports[`DemographicsSection should set user input correctly when user provides
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
Prefer not to respond
</p>
<p
@@ -2533,7 +2607,9 @@ exports[`DemographicsSection should set user input correctly when user provides
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
<button
className="btn btn-link p-0"
onBlur={[Function]}
@@ -2603,7 +2679,9 @@ exports[`DemographicsSection should set user input correctly when user provides
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
Prefer not to respond
</p>
<p
@@ -2665,7 +2743,9 @@ exports[`DemographicsSection should set user input correctly when user provides
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
Prefer not to respond
</p>
<p
@@ -2727,7 +2807,9 @@ exports[`DemographicsSection should set user input correctly when user provides
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
Prefer not to respond
</p>
<p
@@ -2789,7 +2871,9 @@ exports[`DemographicsSection should set user input correctly when user provides
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
Prefer not to respond
</p>
<p
@@ -2851,7 +2935,9 @@ exports[`DemographicsSection should set user input correctly when user provides
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
Other: test
</p>
<p
@@ -2913,7 +2999,9 @@ exports[`DemographicsSection should set user input correctly when user provides
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
Prefer not to respond
</p>
<p
@@ -2975,7 +3063,9 @@ exports[`DemographicsSection should set user input correctly when user provides
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
Prefer not to respond
</p>
<p
@@ -3062,7 +3152,9 @@ exports[`DemographicsSection should set user input correctly when user provides
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
Prefer to self describe: test
</p>
<p
@@ -3124,7 +3216,9 @@ exports[`DemographicsSection should set user input correctly when user provides
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
<button
className="btn btn-link p-0"
onBlur={[Function]}
@@ -3194,7 +3288,9 @@ exports[`DemographicsSection should set user input correctly when user provides
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
Prefer not to respond
</p>
<p
@@ -3256,7 +3352,9 @@ exports[`DemographicsSection should set user input correctly when user provides
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
Prefer not to respond
</p>
<p
@@ -3318,7 +3416,9 @@ exports[`DemographicsSection should set user input correctly when user provides
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
Prefer not to respond
</p>
<p
@@ -3380,7 +3480,9 @@ exports[`DemographicsSection should set user input correctly when user provides
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
Prefer not to respond
</p>
<p
@@ -3442,7 +3544,9 @@ exports[`DemographicsSection should set user input correctly when user provides
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
Prefer not to respond
</p>
<p
@@ -3504,7 +3608,9 @@ exports[`DemographicsSection should set user input correctly when user provides
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
Prefer not to respond
</p>
<p
@@ -3566,7 +3672,9 @@ exports[`DemographicsSection should set user input correctly when user provides
Edit
</button>
</div>
<p>
<p
data-hj-suppress={true}
>
Prefer not to respond
</p>
<p

View File

@@ -185,6 +185,18 @@
"id.verification.photo.enable.detection": "Enable Face Detection",
"id.verification.photo.enable.detection.portrait.help.text": "If checked, a box will appear around your face. Your face can be seen clearly if the box around it is blue. If your face is not in a good position or undetectable, the box will be red.",
"id.verification.photo.enable.detection.id.help.text": "If checked, a box will appear around the face on your ID card. The face can be seen clearly if the box around it is blue. If the face is not in a good position or undetectable, the box will be red.",
"id.verification.photo.feedback.correct": "Face is in a good position.",
"id.verification.photo.feedback.two.faces": "More than one face detected.",
"id.verification.photo.feedback.no.faces": "No face detected.",
"id.verification.photo.feedback.top.left": "Incorrect position. Top left.",
"id.verification.photo.feedback.top.center": "Incorrect position. Top center.",
"id.verification.photo.feedback.top.right": "Incorrect position. Top right.",
"id.verification.photo.feedback.center.left": "Incorrect position. Center left.",
"id.verification.photo.feedback.center.center": "Incorrect position. Too close to camera.",
"id.verification.photo.feedback.center.right": "Incorrect position. Center right.",
"id.verification.photo.feedback.bottom.left": "Incorrect position. Bottom left.",
"id.verification.photo.feedback.bottom.center": "Incorrect position. Bottom center.",
"id.verification.photo.feedback.bottom.right": "Incorrect position. Bottom right.",
"id.verification.camera.access.title": "Camera Permissions",
"id.verification.camera.access.title.success": "Camera Access Enabled",
"id.verification.camera.access.title.failed": "Camera Access Failed",

View File

@@ -11,7 +11,7 @@
"account.settings.section.account.information": "Información de la cuenta",
"account.settings.section.account.information.description": "Estas configuraciones incluyen información básica sobre tu cuenta.",
"account.settings.section.profile.information": "Información del perfil",
"account.settings.section.demographics.information": "Optional Information",
"account.settings.section.demographics.information": "Información opcional",
"account.settings.section.site.preferences": "Preferencias del sitio",
"account.settings.section.linked.accounts": "Cuentas vinculadas",
"account.settings.section.linked.accounts.description": "Puedes vincular tus cuentas de redes sociales para simplificar el proceso de iniciar sesión en edX.",
@@ -117,43 +117,43 @@
"account.settings.delete.account.modal.confirm.cancel": "Cancelar",
"account.settings.delete.account.error.unable.to.delete": "No es posible eliminar esta cuenta",
"account.settings.delete.account.error.no.password": "Se requiere una contraseña",
"account.settings.delete.account.error.invalid.password": "Password is incorrect",
"account.settings.delete.account.error.invalid.password": "Contraseña incorrecta",
"account.settings.delete.account.error.unable.to.delete.details": "Ocurrió un error al procesar tu solicitud. Por favor, intente nuevamente más tarde.",
"account.settings.delete.account.modal.after.header": "¡Sentimos que te vayas! Tu cuenta será eliminada en breve.",
"account.settings.delete.account.modal.after.text": "La eliminación de cuenta, incluyendo la eliminación de las listas de correo electrónico, puede tardar unas semanas en procesarse totalmente en nuestro sistema. Si quieres renunciar a recibir correos antes de que la eliminación se haya completado, por favor date de baja mediante el enlace que aparece al final de los correos.",
"account.settings.delete.account.modal.after.button": "Cerrar",
"account.settings.delete.account.text.3": "Puede que también pierdas el acceso a los certificados verificados y otros certificados de programas como los de los MicroMasters. Si quieres hacer una copia de dichos certificados para tus archivos antes de proceder a la eliminación, {actionLink}.",
"account.settings.message.demographics.service.issue": "An error occurred attempting to retrieve or save your account information. Please try again later.",
"account.settings.field.demographics.gender": "Gender identity",
"account.settings.field.demographics.gender.empty": "Add gender identity",
"account.settings.field.demographics.gender.options.empty": "Select a gender identity",
"account.settings.field.demographics.gender_description": "Gender identity description",
"account.settings.field.demographics.gender_description.empty": "Enter description",
"account.settings.field.demographics.ethnicity": "Race/Ethnicity identity",
"account.settings.field.demographics.ethnicity.empty": "Add race/ethnicity identity",
"account.settings.field.demographics.ethnicity.options.empty": "Select all that apply",
"account.settings.field.demographics.income": "Family income",
"account.settings.field.demographics.income.empty": "Add family income",
"account.settings.field.demographics.income.options.empty": "Select a family income range",
"account.settings.field.demographics.military_history": "U.S. Military status",
"account.settings.message.demographics.service.issue": "Ocurrió un error al intentar recuperar o guardar la información de tu cuenta. Por favor inténtalo más tarde.",
"account.settings.field.demographics.gender": "Identidad de género",
"account.settings.field.demographics.gender.empty": "Añade identidad de género",
"account.settings.field.demographics.gender.options.empty": "Selecciona una identidad de género",
"account.settings.field.demographics.gender_description": "Descripción de identidad de género",
"account.settings.field.demographics.gender_description.empty": "Ingresa descripción",
"account.settings.field.demographics.ethnicity": "Identidad étnica/raza",
"account.settings.field.demographics.ethnicity.empty": "Añade identidad étnica/raza",
"account.settings.field.demographics.ethnicity.options.empty": "Selecciona todas las que apliquen",
"account.settings.field.demographics.income": "Ingreso familiar",
"account.settings.field.demographics.income.empty": "Añade ingreso familiar",
"account.settings.field.demographics.income.options.empty": "Selecciona un rango de ingreso familiar",
"account.settings.field.demographics.military_history": "Estatus militar en EE.UU.",
"account.settings.field.demographics.military_history.empty": "Add military status",
"account.settings.field.demographics.military_history.options.empty": "Select military status",
"account.settings.field.demographics.learner_education_level": "Your education level",
"account.settings.field.demographics.learner_education_level.empty": "Add education level",
"account.settings.field.demographics.parent_education_level": "Parents/Guardians education level",
"account.settings.field.demographics.parent_education_level.empty": "Add education level",
"account.settings.field.demographics.education_level.options.empty": "Select education level",
"account.settings.field.demographics.work_status": "Employment status",
"account.settings.field.demographics.work_status.empty": "Add employment status",
"account.settings.field.demographics.work_status.options.empty": "Select employment status",
"account.settings.field.demographics.work_status_description": "Employment status description",
"account.settings.field.demographics.work_status_description.empty": "Enter description",
"account.settings.field.demographics.current_work_sector": "Current work industry",
"account.settings.field.demographics.current_work_sector.empty": "Add work industry",
"account.settings.field.demographics.future_work_sector": "Future work industry",
"account.settings.field.demographics.future_work_sector.empty": "Add work industry",
"account.settings.field.demographics.work_sector.options.empty": "Select work industry",
"account.settings.section.demographics.why": "Why does edX collect this information?",
"account.settings.field.demographics.military_history.options.empty": "Selecciona estatus militar",
"account.settings.field.demographics.learner_education_level": "Tu nivel educacional",
"account.settings.field.demographics.learner_education_level.empty": "Añade nivel educacional",
"account.settings.field.demographics.parent_education_level": "Nivel educacional de padres/tutores",
"account.settings.field.demographics.parent_education_level.empty": "Añade nivel educacional",
"account.settings.field.demographics.education_level.options.empty": "Selecciona nivel educacional",
"account.settings.field.demographics.work_status": "Estatus laboral",
"account.settings.field.demographics.work_status.empty": "Añade estatus laboral",
"account.settings.field.demographics.work_status.options.empty": "Selecciona estatus laboral",
"account.settings.field.demographics.work_status_description": "Descripción estatus laboral",
"account.settings.field.demographics.work_status_description.empty": "Ingresa descripción",
"account.settings.field.demographics.current_work_sector": "Área profesional actual",
"account.settings.field.demographics.current_work_sector.empty": "Añade área profesional",
"account.settings.field.demographics.future_work_sector": "Área profesional futura",
"account.settings.field.demographics.future_work_sector.empty": "Añade área profesional",
"account.settings.field.demographics.work_sector.options.empty": "Selecciona área profesional",
"account.settings.section.demographics.why": "¿Por qué edX obtiene esta información?",
"error.notfound.message": "La página que estas buscando no está disponible o hay un error en la URL. Por favor, comprueba la URL y vuelve a intentarlo.",
"account.settings.editable.field.password.reset.button.confirmation.support.link": "soporte técnico",
"account.settings.editable.field.password.reset.button.confirmation": "Hemos mandado un mensaje a {email}. Haz clic en el enlace en el mensaje para restablecer tu contraseña. ¿No recibiste el mensaje? Contáctate con {technicalSupportLink}.",
@@ -166,33 +166,45 @@
"account.settings.sso.unlink.account": "Desvincular la cuenta de {accountName} ",
"account.settings.sso.no.providers": "No se pueden vincular cuentas en este momento.",
"id.verification.existing.request.denied.text": "You cannot verify your identity at this time. If you have yet to activate your account, please check your spam folder for the activation email from {email}.",
"id.verification.next": "Next",
"id.verification.requirements.title": "Photo Verification Requirements",
"id.verification.requirements.description": "In order to complete Photo Verification online, you will need the following:",
"id.verification.requirements.card.device.title": "Device with Camera",
"id.verification.requirements.card.device.allow": "Allow",
"id.verification.requirements.card.id.title": "Photo Identification",
"id.verification.requirements.card.id.text": "You need a valid ID that contains your full name and photo.",
"id.verification.next": "Siguiente",
"id.verification.requirements.title": "Requerimientos de verificación por foto",
"id.verification.requirements.description": "Para completar la verificación por foto en línea, necesitarás lo siguiente:",
"id.verification.requirements.card.device.title": "Dispositivo con cámara",
"id.verification.requirements.card.device.allow": "Permitir",
"id.verification.requirements.card.id.title": "Identificación por foto",
"id.verification.requirements.card.id.text": "Necesitas un ID válido que contenga tu nombre completo y tu foto.",
"id.verification.privacy.title": "Privacy Information",
"id.verification.privacy.need.photo.question": "Why does edX need my photo?",
"id.verification.privacy.need.photo.answer": "We use your verification photos to confirm your identity and ensure the validity of your certificate.",
"id.verification.privacy.do.with.photo.question": "What does edX do with this photo?",
"id.verification.privacy.need.photo.question": "¿Por qué edX necesita mi foto?",
"id.verification.privacy.need.photo.answer": "Utilizamos tus fotos de verificación para confirmar tu identidad y garantizar la validez de tu certificado.",
"id.verification.privacy.do.with.photo.question": "¿Qué hace edX con esta foto?",
"id.verification.privacy.do.with.photo.answer": "We securely encrypt your photo and send it our authorization service for review. Your photo and information are not saved or visible anywhere on edX after the verification process is complete.",
"id.verification.existing.request.title": "Identity Verification",
"id.verification.existing.request.title": "Verificación de identidad",
"id.verification.existing.request.pending.text": "You have already submitted your verification information. You will see a message on your dashboard when the verification process is complete (usually within 5 days).",
"id.verification.photo.take": "Take Photo",
"id.verification.photo.retake": "Retake Photo",
"id.verification.photo.take": "Tomar la foto",
"id.verification.photo.retake": "Tomar nuevamente la foto",
"id.verification.photo.enable.detection": "Enable Face Detection",
"id.verification.photo.enable.detection.portrait.help.text": "If checked, a box will appear around your face. Your face can be seen clearly if the box around it is blue. If your face is not in a good position or undetectable, the box will be red.",
"id.verification.photo.enable.detection.id.help.text": "If checked, a box will appear around the face on your ID card. The face can be seen clearly if the box around it is blue. If the face is not in a good position or undetectable, the box will be red.",
"id.verification.camera.access.title": "Camera Permissions",
"id.verification.photo.feedback.correct": "Face is in a good position.",
"id.verification.photo.feedback.two.faces": "More than one face detected.",
"id.verification.photo.feedback.no.faces": "No face detected.",
"id.verification.photo.feedback.top.left": "Incorrect position. Top left.",
"id.verification.photo.feedback.top.center": "Incorrect position. Top center.",
"id.verification.photo.feedback.top.right": "Incorrect position. Top right.",
"id.verification.photo.feedback.center.left": "Incorrect position. Center left.",
"id.verification.photo.feedback.center.center": "Incorrect position. Too close to camera.",
"id.verification.photo.feedback.center.right": "Incorrect position. Center right.",
"id.verification.photo.feedback.bottom.left": "Incorrect position. Bottom left.",
"id.verification.photo.feedback.bottom.center": "Incorrect position. Bottom center.",
"id.verification.photo.feedback.bottom.right": "Incorrect position. Bottom right.",
"id.verification.camera.access.title": "Permisos de la cámara",
"id.verification.camera.access.title.success": "Camera Access Enabled",
"id.verification.camera.access.title.failed": "Camera Access Failed",
"id.verification.camera.access.click.allow": "Please make sure to click \"Allow\"",
"id.verification.camera.access.enable": "Enable Camera",
"id.verification.camera.access.problems": "Having problems?",
"id.verification.camera.access.skip": "Skip and upload image files instead",
"id.verification.camera.access.success": "Looks like your camera is working and ready.",
"id.verification.camera.access.click.allow": "Por favor asegúrate de hacer clic en \"Permitir\"",
"id.verification.camera.access.enable": "Habilitar cámara",
"id.verification.camera.access.problems": "¿Tienes problemas?",
"id.verification.camera.access.skip": "Omitir y cargar un archivo de imagen",
"id.verification.camera.access.success": "Parece que tu cámara está funcionando y está lista.",
"id.verification.camera.access.failure": "It looks like we're unable to access your camera. You will need to upload image files of you and your photo id.",
"id.verification.camera.access.failure.temporary": "It looks like we're unable to access your camera. Please verify that your webcam is connected and that you have allowed your browser to access it.",
"id.verification.camera.access.failure.temporary.chrome": "To enable camera access in Chrome:",
@@ -220,7 +232,7 @@
"id.verification.camera.access.failure.temporary.safari.step2": "Click on the Safari app menu, then select \"Preferences.\" You can also use Command+, as a keyboard shortcut.",
"id.verification.camera.access.failure.temporary.safari.step3": "Select the \"Websites\" tab and then select \"Camera.\"",
"id.verification.camera.access.failure.temporary.safari.step4": "Select \"edx.org\" and change the camera permissions to \"Allow.\"",
"id.verification.photo.tips.title": "Helpful Photo Tips",
"id.verification.photo.tips.title": "Consejos útiles de fotos",
"id.verification.photo.tips.description": "Next, we'll need you to take a photo of your face. Please review the helpful tips below.",
"id.verification.photo.tips.list.title": "Photo Tips",
"id.verification.photo.tips.list.description": "To take a successful photo, make sure that:",

View File

@@ -185,6 +185,18 @@
"id.verification.photo.enable.detection": "Enable Face Detection",
"id.verification.photo.enable.detection.portrait.help.text": "If checked, a box will appear around your face. Your face can be seen clearly if the box around it is blue. If your face is not in a good position or undetectable, the box will be red.",
"id.verification.photo.enable.detection.id.help.text": "If checked, a box will appear around the face on your ID card. The face can be seen clearly if the box around it is blue. If the face is not in a good position or undetectable, the box will be red.",
"id.verification.photo.feedback.correct": "Face is in a good position.",
"id.verification.photo.feedback.two.faces": "More than one face detected.",
"id.verification.photo.feedback.no.faces": "No face detected.",
"id.verification.photo.feedback.top.left": "Incorrect position. Top left.",
"id.verification.photo.feedback.top.center": "Incorrect position. Top center.",
"id.verification.photo.feedback.top.right": "Incorrect position. Top right.",
"id.verification.photo.feedback.center.left": "Incorrect position. Center left.",
"id.verification.photo.feedback.center.center": "Incorrect position. Too close to camera.",
"id.verification.photo.feedback.center.right": "Incorrect position. Center right.",
"id.verification.photo.feedback.bottom.left": "Incorrect position. Bottom left.",
"id.verification.photo.feedback.bottom.center": "Incorrect position. Bottom center.",
"id.verification.photo.feedback.bottom.right": "Incorrect position. Bottom right.",
"id.verification.camera.access.title": "Camera Permissions",
"id.verification.camera.access.title.success": "Camera Access Enabled",
"id.verification.camera.access.title.failed": "Camera Access Failed",

View File

@@ -185,6 +185,18 @@
"id.verification.photo.enable.detection": "Enable Face Detection",
"id.verification.photo.enable.detection.portrait.help.text": "If checked, a box will appear around your face. Your face can be seen clearly if the box around it is blue. If your face is not in a good position or undetectable, the box will be red.",
"id.verification.photo.enable.detection.id.help.text": "If checked, a box will appear around the face on your ID card. The face can be seen clearly if the box around it is blue. If the face is not in a good position or undetectable, the box will be red.",
"id.verification.photo.feedback.correct": "Face is in a good position.",
"id.verification.photo.feedback.two.faces": "More than one face detected.",
"id.verification.photo.feedback.no.faces": "No face detected.",
"id.verification.photo.feedback.top.left": "Incorrect position. Top left.",
"id.verification.photo.feedback.top.center": "Incorrect position. Top center.",
"id.verification.photo.feedback.top.right": "Incorrect position. Top right.",
"id.verification.photo.feedback.center.left": "Incorrect position. Center left.",
"id.verification.photo.feedback.center.center": "Incorrect position. Too close to camera.",
"id.verification.photo.feedback.center.right": "Incorrect position. Center right.",
"id.verification.photo.feedback.bottom.left": "Incorrect position. Bottom left.",
"id.verification.photo.feedback.bottom.center": "Incorrect position. Bottom center.",
"id.verification.photo.feedback.bottom.right": "Incorrect position. Bottom right.",
"id.verification.camera.access.title": "Camera Permissions",
"id.verification.camera.access.title.success": "Camera Access Enabled",
"id.verification.camera.access.title.failed": "Camera Access Failed",

View File

@@ -1,5 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
import { sendTrackEvent } from '@edx/frontend-platform/analytics';
import * as blazeface from '@tensorflow-models/blazeface';
import CameraPhoto, { FACING_MODES } from 'jslib-html5-camera-photo';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
@@ -37,6 +38,22 @@ class Camera extends React.Component {
this.cameraPhoto.stopCamera();
}
sendEvent() {
let eventName = 'edx.id_verification';
if (this.props.isPortrait) {
eventName += '.user_photo';
} else {
eventName += '.id_photo';
}
if (this.state.shouldDetect) {
eventName += '.face_detection_enabled';
} else {
eventName += '.face_detection_disabled';
}
sendTrackEvent(eventName);
}
setDetection() {
this.setState(
{ shouldDetect: !this.state.shouldDetect },
@@ -45,6 +62,7 @@ class Camera extends React.Component {
this.setState({ isFinishedLoadingDetection: false });
this.startDetection();
}
this.sendEvent();
},
);
}
@@ -230,10 +248,13 @@ class Camera extends React.Component {
// always be less than 10MB
const ratio = 9999999 / currentSize;
// if the current resolution creates an image larger than 10 MB, adjust sizeFactor (resolution)
// to ensure that image will have a file size of less than 10 MB.
if (ratio < 1) {
// if the current resolution creates an image larger than 10 MB, adjust sizeFactor (resolution)
// to ensure that image will have a file size of less than 10 MB.
sizeFactor = ratio;
} else if (videoWidth === 640 && videoHeight === 480) {
// otherwise increase the resolution to try and prevent blurry images.
sizeFactor = 2;
}
}
return sizeFactor;
@@ -302,6 +323,7 @@ class Camera extends React.Component {
height="480"
/>
<img
data-hj-suppress
alt="imgCamera"
src={this.state.dataUri}
className="camera-video"

View File

@@ -45,9 +45,9 @@ function IdVerificationContextProvider({ children }) {
const stream = await navigator.mediaDevices.getUserMedia({ video: true });
setMediaAccess(MEDIA_ACCESS.GRANTED);
setMediaStream(stream);
// If we would like to stop the stream immediately. I guess we can leave it open
// const tracks = stream.getTracks();
// tracks.forEach(track => track.stop());
// stop the stream, as we are not using it yet
const tracks = stream.getTracks();
tracks.forEach(track => track.stop());
} catch (err) {
setMediaAccess(MEDIA_ACCESS.DENIED);
}

View File

@@ -5,7 +5,7 @@ export default function ImagePreview({ src, alt, id }) {
return (
<div id={id} className="image-preview">
<img style={{ objectFit: 'contain' }} src={src} alt={alt} />
<img data-hj-suppress style={{ objectFit: 'contain' }} src={src} alt={alt} />
</div>
);

View File

@@ -1,6 +1,6 @@
import React, { useContext, useState, useEffect, useRef } from 'react';
import { Form } from '@edx/paragon';
import { Link } from 'react-router-dom';
import { Link, useHistory } from 'react-router-dom';
import { sendTrackEvent } from '@edx/frontend-platform/analytics';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
@@ -11,6 +11,7 @@ import { IdVerificationContext } from '../IdVerificationContext';
import messages from '../IdVerification.messages';
function GetNameIdPanel(props) {
const { push } = useHistory();
const panelSlug = 'get-name-id';
const [nameMatches, setNameMatches] = useState(true);
const nameInputRef = useRef();
@@ -42,6 +43,15 @@ function GetNameIdPanel(props) {
}
}, [nameMatches, blankName]);
const handleSubmit = (e) => {
e.preventDefault();
// If the input is empty, or if no changes have been made to the
// mismatching name, the user should not be able to proceed.
if (!invalidName && !blankName) {
push(nextPanelSlug);
}
};
return (
<BasePanel
name={panelSlug}
@@ -51,7 +61,7 @@ function GetNameIdPanel(props) {
{props.intl.formatMessage(messages['id.verification.account.name.instructions'])}
</p>
<Form>
<Form onSubmit={handleSubmit}>
<Form.Group>
<Form.Label htmlFor="nameMatchesYes">
{props.intl.formatMessage(messages['id.verification.account.name.radio.label'])}

View File

@@ -5,11 +5,15 @@ import '@testing-library/jest-dom/extend-expect';
import { render, cleanup, screen, act, fireEvent } from '@testing-library/react';
import { injectIntl, IntlProvider } from '@edx/frontend-platform/i18n';
import * as blazeface from '@tensorflow-models/blazeface';
import * as analytics from '@edx/frontend-platform/analytics';
import { IdVerificationContext } from '../IdVerificationContext';
import Camera from '../Camera';
jest.mock('jslib-html5-camera-photo');
jest.mock('@tensorflow-models/blazeface');
jest.mock('@edx/frontend-platform/analytics');
analytics.sendTrackEvent = jest.fn();
window.HTMLMediaElement.prototype.play = () => {};
@@ -135,4 +139,46 @@ describe('SubmittedPanel', () => {
await fireEvent.click(checkbox);
setTimeout(() => { expect(blazeface.load).toHaveBeenCalled(); }, 2000);
});
it('sends tracking events on portrait photo page', async () => {
blazeface.load = jest.fn().mockResolvedValue({ estimateFaces: jest.fn().mockResolvedValue([]) });
await act(async () => render((
<Router history={history}>
<IntlProvider locale="en">
<IdVerificationContext.Provider value={contextValue}>
<IntlCamera {...defaultProps} />
</IdVerificationContext.Provider>
</IntlProvider>
</Router>
)));
await fireEvent.loadedData(screen.queryByTestId('video'));
const checkbox = await screen.findByLabelText('Enable Face Detection');
await fireEvent.click(checkbox);
expect(analytics.sendTrackEvent).toHaveBeenCalledWith('edx.id_verification.user_photo.face_detection_enabled');
await fireEvent.click(checkbox);
expect(analytics.sendTrackEvent).toHaveBeenCalledWith('edx.id_verification.user_photo.face_detection_disabled');
});
it('sends tracking events on id photo page', async () => {
blazeface.load = jest.fn().mockResolvedValue({ estimateFaces: jest.fn().mockResolvedValue([]) });
await act(async () => render((
<Router history={history}>
<IntlProvider locale="en">
<IdVerificationContext.Provider value={contextValue}>
<IntlCamera {...idProps} />
</IdVerificationContext.Provider>
</IntlProvider>
</Router>
)));
await fireEvent.loadedData(screen.queryByTestId('video'));
const checkbox = await screen.findByLabelText('Enable Face Detection');
await fireEvent.click(checkbox);
expect(analytics.sendTrackEvent).toHaveBeenCalledWith('edx.id_verification.id_photo.face_detection_enabled');
await fireEvent.click(checkbox);
expect(analytics.sendTrackEvent).toHaveBeenCalledWith('edx.id_verification.id_photo.face_detection_disabled');
});
});