Compare commits
2 Commits
sarina/upd
...
build/remo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
71553c98a7 | ||
|
|
29c21c1b1d |
16
.github/workflows/ci.yml
vendored
16
.github/workflows/ci.yml
vendored
@@ -1,5 +1,5 @@
|
||||
---
|
||||
name: ci
|
||||
name: validate
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
@@ -12,21 +12,15 @@ jobs:
|
||||
matrix:
|
||||
node-version:
|
||||
- 12
|
||||
npm-test:
|
||||
- i18n_extract
|
||||
- is-es5
|
||||
- lint
|
||||
- test
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- run: npm install -g npm@6
|
||||
- run: make requirements
|
||||
- run: make test NPM_TESTS=build
|
||||
- run: make test NPM_TESTS=${{ matrix.npm-test }}
|
||||
- run: make test
|
||||
- name: upload coverage
|
||||
uses: codecov/codecov-action@v2
|
||||
uses: codecov/codecov-action@v1
|
||||
with:
|
||||
fail_ci_if_error: false
|
||||
fail_ci_if_error: true
|
||||
|
||||
2
Makefile
2
Makefile
@@ -10,7 +10,7 @@ tx_url2 = https://www.transifex.com/api/2/project/edx-platform/resource/$(transi
|
||||
# This directory must match .babelrc .
|
||||
transifex_temp = ./temp/babel-plugin-react-intl
|
||||
|
||||
NPM_TESTS=build i18n_extract lint test is-es5
|
||||
NPM_TESTS=i18n_extract lint test build is-es5
|
||||
|
||||
.PHONY: test
|
||||
test: $(addprefix test.npm.,$(NPM_TESTS)) ## validate ci suite
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
|ci-badge| |Codecov| |npm_version| |npm_downloads| |license| |semantic-release|
|
||||
|Build Status| |Codecov| |npm_version| |npm_downloads| |license| |semantic-release|
|
||||
|
||||
frontend-app-account
|
||||
====================
|
||||
@@ -102,9 +102,8 @@ In the future, it's possible that demographics could be modeled as a plugin rath
|
||||
|
||||
==============================
|
||||
|
||||
.. |ci-badge| image:: https://github.com/edx/edx-developer-docs/actions/workflows/ci.yml/badge.svg
|
||||
:target: https://github.com/edx/edx-developer-docs/actions/workflows/ci.yml
|
||||
:alt: Continuous Integration
|
||||
.. |Build Status| image:: https://api.travis-ci.com/edx/frontend-app-account.svg?branch=master
|
||||
:target: https://travis-ci.com/edx/frontend-app-account
|
||||
.. |Codecov| image:: https://img.shields.io/codecov/c/github/edx/frontend-app-account
|
||||
:target: https://codecov.io/gh/edx/frontend-app-account
|
||||
.. |npm_version| image:: https://img.shields.io/npm/v/@edx/frontend-app-account.svg
|
||||
|
||||
@@ -3,4 +3,5 @@
|
||||
|
||||
nick: acct
|
||||
oeps: {}
|
||||
owner: edx/arch-team
|
||||
openedx-release: {ref: master}
|
||||
|
||||
14094
package-lock.json
generated
14094
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
66
package.json
66
package.json
@@ -30,26 +30,26 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@edx/brand": "npm:@edx/brand-openedx@1.1.0",
|
||||
"@edx/frontend-component-footer": "10.1.6",
|
||||
"@edx/frontend-component-header": "2.3.0",
|
||||
"@edx/frontend-platform": "1.12.6",
|
||||
"@edx/paragon": "16.1.0",
|
||||
"@fortawesome/fontawesome-svg-core": "1.2.36",
|
||||
"@fortawesome/free-brands-svg-icons": "5.15.4",
|
||||
"@fortawesome/free-regular-svg-icons": "5.15.4",
|
||||
"@fortawesome/free-solid-svg-icons": "5.15.4",
|
||||
"@fortawesome/react-fontawesome": "0.1.15",
|
||||
"@edx/frontend-component-footer": "10.1.4",
|
||||
"@edx/frontend-component-header": "2.2.4",
|
||||
"@edx/frontend-platform": "1.9.5",
|
||||
"@edx/paragon": "13.1.2",
|
||||
"@fortawesome/fontawesome-svg-core": "1.2.34",
|
||||
"@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.14",
|
||||
"@tensorflow-models/blazeface": "0.0.7",
|
||||
"@tensorflow/tfjs-converter": "1.7.4",
|
||||
"@tensorflow/tfjs-core": "1.7.4",
|
||||
"@tensorflow/tfjs-converter": "1.6.1",
|
||||
"@tensorflow/tfjs-core": "1.6.1",
|
||||
"babel-polyfill": "6.26.0",
|
||||
"bowser": "2.11.0",
|
||||
"classnames": "2.3.1",
|
||||
"bowser": "2.10.0",
|
||||
"classnames": "2.2.6",
|
||||
"font-awesome": "4.7.0",
|
||||
"form-urlencoded": "4.0.1",
|
||||
"formdata-polyfill": "4.0.7",
|
||||
"formdata-polyfill": "3.0.20",
|
||||
"history": "4.10.1",
|
||||
"jslib-html5-camera-photo": "3.1.8",
|
||||
"jslib-html5-camera-photo": "3.1.6",
|
||||
"lodash.debounce": "4.0.8",
|
||||
"lodash.findindex": "4.6.0",
|
||||
"lodash.get": "4.4.2",
|
||||
@@ -58,20 +58,20 @@
|
||||
"lodash.omit": "4.5.0",
|
||||
"lodash.pick": "4.4.0",
|
||||
"lodash.pickby": "4.6.0",
|
||||
"memoize-one": "5.2.1",
|
||||
"memoize-one": "5.1.1",
|
||||
"newrelic": "5.13.1",
|
||||
"prop-types": "15.7.2",
|
||||
"qs": "6.10.1",
|
||||
"react": "16.14.0",
|
||||
"react-dom": "16.14.0",
|
||||
"react-redux": "7.2.5",
|
||||
"react-router": "5.2.1",
|
||||
"react-router-dom": "5.3.0",
|
||||
"qs": "6.9.6",
|
||||
"react": "16.10.2",
|
||||
"react-dom": "16.10.2",
|
||||
"react-redux": "7.1.3",
|
||||
"react-router": "5.1.2",
|
||||
"react-router-dom": "5.1.2",
|
||||
"react-router-hash-link": "1.2.2",
|
||||
"react-scrollspy": "3.4.3",
|
||||
"react-transition-group": "4.4.2",
|
||||
"redux": "4.1.1",
|
||||
"redux-devtools-extension": "2.13.9",
|
||||
"react-transition-group": "4.3.0",
|
||||
"redux": "4.0.5",
|
||||
"redux-devtools-extension": "2.13.8",
|
||||
"redux-logger": "3.0.6",
|
||||
"redux-saga": "1.1.3",
|
||||
"redux-thunk": "2.3.0",
|
||||
@@ -79,15 +79,15 @@
|
||||
"universal-cookie": "4.0.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@edx/frontend-build": "8.0.4",
|
||||
"@testing-library/jest-dom": "5.14.1",
|
||||
"@testing-library/react": "12.0.0",
|
||||
"codecov": "3.8.3",
|
||||
"enzyme": "3.11.0",
|
||||
"@edx/frontend-build": "5.6.9",
|
||||
"@testing-library/jest-dom": "5.11.9",
|
||||
"@testing-library/react": "10.4.9",
|
||||
"codecov": "3.7.2",
|
||||
"enzyme": "3.10.0",
|
||||
"enzyme-adapter-react-16": "1.15.6",
|
||||
"es-check": "6.0.0",
|
||||
"husky": "7.0.2",
|
||||
"react-test-renderer": "16.14.0",
|
||||
"es-check": "5.0.0",
|
||||
"husky": "3.0.9",
|
||||
"react-test-renderer": "16.8.6",
|
||||
"reactifex": "1.1.1",
|
||||
"redux-mock-store": "1.5.4"
|
||||
}
|
||||
|
||||
@@ -1,28 +1,15 @@
|
||||
{
|
||||
"extends": [
|
||||
"config:base",
|
||||
"schedule:weekly",
|
||||
":automergeLinters",
|
||||
":automergeMinor",
|
||||
":automergeTesters",
|
||||
":enableVulnerabilityAlerts",
|
||||
":rebaseStalePrs",
|
||||
":semanticCommits",
|
||||
":updateNotScheduled"
|
||||
":automergeMinor",
|
||||
":noUnscheduledUpdates",
|
||||
":semanticCommits"
|
||||
],
|
||||
"packageRules": [
|
||||
{
|
||||
"matchDepTypes": [
|
||||
"devDependencies"
|
||||
],
|
||||
"matchUpdateTypes": [
|
||||
"lockFileMaintenance",
|
||||
"minor",
|
||||
"patch",
|
||||
"pin"
|
||||
],
|
||||
"automerge": true
|
||||
}
|
||||
"rebaseStalePrs": true,
|
||||
"schedule": [
|
||||
"every weekend"
|
||||
],
|
||||
"timezone": "America/New_York"
|
||||
}
|
||||
|
||||
@@ -13,15 +13,13 @@ import {
|
||||
getCountryList,
|
||||
getLanguageList,
|
||||
} from '@edx/frontend-platform/i18n';
|
||||
import {
|
||||
Button, Hyperlink, Icon, Alert,
|
||||
} from '@edx/paragon';
|
||||
import { CheckCircle, Error, WarningFilled } from '@edx/paragon/icons';
|
||||
import { Hyperlink } from '@edx/paragon';
|
||||
|
||||
import messages from './AccountSettingsPage.messages';
|
||||
import { fetchSettings, saveSettings, updateDraft } from './data/actions';
|
||||
import { accountSettingsPageSelector } from './data/selectors';
|
||||
import PageLoading from './PageLoading';
|
||||
import Alert from './Alert';
|
||||
import JumpNav from './JumpNav';
|
||||
import DeleteAccount from './delete-account';
|
||||
import EditableField from './EditableField';
|
||||
@@ -29,7 +27,6 @@ import ResetPassword from './reset-password';
|
||||
import ThirdPartyAuth from './third-party-auth';
|
||||
import BetaLanguageBanner from './BetaLanguageBanner';
|
||||
import EmailField from './EmailField';
|
||||
import OneTimeDismissibleAlert from './OneTimeDismissibleAlert';
|
||||
import {
|
||||
YEAR_OF_BIRTH_OPTIONS,
|
||||
EDUCATION_LEVELS,
|
||||
@@ -139,28 +136,13 @@ class AccountSettingsPage extends React.Component {
|
||||
})),
|
||||
}));
|
||||
|
||||
sortDates = (a, b) => {
|
||||
const aTimeSinceEpoch = new Date(a).getTime();
|
||||
const bTimeSinceEpoch = new Date(b).getTime();
|
||||
|
||||
return bTimeSinceEpoch - aTimeSinceEpoch;
|
||||
}
|
||||
|
||||
sortVerifiedNameRecords = verifiedNameHistory => {
|
||||
if (Array.isArray(verifiedNameHistory)) {
|
||||
return [...verifiedNameHistory].sort(this.sortDates);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
handleEditableFieldChange = (name, value) => {
|
||||
this.props.updateDraft(name, value);
|
||||
}
|
||||
};
|
||||
|
||||
handleSubmit = (formId, values) => {
|
||||
this.props.saveSettings(formId, values);
|
||||
}
|
||||
};
|
||||
|
||||
isEditable(fieldName) {
|
||||
return !this.props.staticFields.includes(fieldName);
|
||||
@@ -179,7 +161,7 @@ class AccountSettingsPage extends React.Component {
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Alert variant="danger">
|
||||
<Alert className="alert alert-danger" role="alert">
|
||||
<FormattedMessage
|
||||
id="account.settings.message.duplicate.tpa.provider"
|
||||
defaultMessage="The {provider} account you selected is already linked to another {siteName} account."
|
||||
@@ -201,7 +183,7 @@ class AccountSettingsPage extends React.Component {
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Alert variant="info">
|
||||
<Alert className="alert alert-primary" role="alert">
|
||||
<FormattedMessage
|
||||
id="account.settings.message.managed.settings"
|
||||
defaultMessage="Your profile settings are managed by {managerTitle}. Contact your administrator or {support} for help."
|
||||
@@ -224,111 +206,6 @@ class AccountSettingsPage extends React.Component {
|
||||
);
|
||||
}
|
||||
|
||||
renderVerifiedNameSuccessMessage = () => (
|
||||
<OneTimeDismissibleAlert
|
||||
id="dismissedVerifiedNameSuccessMessage"
|
||||
variant="success"
|
||||
icon={CheckCircle}
|
||||
header={this.props.intl.formatMessage(messages['account.settings.field.name.verified.success.message.header'])}
|
||||
body={this.props.intl.formatMessage(messages['account.settings.field.name.verified.success.message'])}
|
||||
/>
|
||||
)
|
||||
|
||||
renderVerifiedNameFailureMessage = (verifiedName, created) => {
|
||||
const dateValue = new Date(created).valueOf();
|
||||
const id = `dismissedVerifiedNameFailureMessage-${verifiedName}-${dateValue}`;
|
||||
|
||||
return (
|
||||
<OneTimeDismissibleAlert
|
||||
id={id}
|
||||
variant="danger"
|
||||
icon={Error}
|
||||
header={this.props.intl.formatMessage(messages['account.settings.field.name.verified.failure.message.header'])}
|
||||
body={
|
||||
(
|
||||
<>
|
||||
<div className="d-flex flex-row">
|
||||
{this.props.intl.formatMessage(
|
||||
messages['account.settings.field.name.verified.failure.message'], {
|
||||
verifiedName,
|
||||
},
|
||||
)}
|
||||
</div>
|
||||
<div className="d-flex flex-row-reverse mt-3">
|
||||
<Button
|
||||
variant="primary"
|
||||
href="https://support.edx.org/hc/en-us/articles/360004381594-Why-was-my-ID-verification-denied"
|
||||
>
|
||||
{this.props.intl.formatMessage(messages['account.settings.field.name.verified.failure.message.help.link'])}
|
||||
</Button>{' '}
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
renderVerifiedNameSubmittedMessage = () => (
|
||||
<Alert
|
||||
variant="warning"
|
||||
icon={WarningFilled}
|
||||
>
|
||||
<Alert.Heading>
|
||||
{this.props.intl.formatMessage(messages['account.settings.field.name.verified.submitted.message.header'])}
|
||||
</Alert.Heading>
|
||||
<p>
|
||||
{this.props.intl.formatMessage(messages['account.settings.field.name.verified.submitted.message'])}
|
||||
</p>
|
||||
</Alert>
|
||||
)
|
||||
|
||||
renderVerifiedNameMessage = verifiedNameRecord => {
|
||||
const { created, status, verified_name: verifiedName } = verifiedNameRecord;
|
||||
|
||||
switch (status) {
|
||||
case 'approved':
|
||||
return this.renderVerifiedNameSuccessMessage();
|
||||
case 'denied':
|
||||
return this.renderVerifiedNameFailureMessage(verifiedName, created);
|
||||
case 'submitted':
|
||||
return this.renderVerifiedNameSubmittedMessage();
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
renderVerifiedNameIcon = (status) => {
|
||||
switch (status) {
|
||||
case 'approved':
|
||||
return (<Icon src={CheckCircle} className="ml-1" style={{ height: '18px', width: '18px', color: 'green' }} />);
|
||||
case 'submitted':
|
||||
return (<Icon src={WarningFilled} className="ml-1" style={{ height: '18px', width: '18px', color: 'yellow' }} />);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
renderVerifiedNameHelpText = (status) => {
|
||||
switch (status) {
|
||||
case 'approved':
|
||||
return (this.props.intl.formatMessage(messages['account.settings.field.name.verified.help.text.verified']));
|
||||
case 'submitted':
|
||||
return (this.props.intl.formatMessage(messages['account.settings.field.name.verified.help.text.submitted']));
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
renderFullNameHelpText = (status) => {
|
||||
switch (status) {
|
||||
case 'submitted':
|
||||
return (this.props.intl.formatMessage(messages['account.settings.field.full.name.help.text.submitted']));
|
||||
default:
|
||||
return (this.props.intl.formatMessage(messages['account.settings.field.full.name.help.text']));
|
||||
}
|
||||
}
|
||||
|
||||
renderEmptyStaticFieldMessage() {
|
||||
if (this.isManagedProfile()) {
|
||||
return this.props.intl.formatMessage(messages['account.settings.static.field.empty'], {
|
||||
@@ -384,9 +261,6 @@ class AccountSettingsPage extends React.Component {
|
||||
// Show State field only if the country is US (could include Canada later)
|
||||
const showState = this.props.formValues.country === COUNTRY_WITH_STATES;
|
||||
|
||||
const { verifiedName } = this.props.formValues;
|
||||
const verifiedNameEnabled = this.props.formValues.verifiedNameHistory.verified_name_enabled;
|
||||
|
||||
const timeZoneOptions = this.getLocalizedTimeZoneOptions(
|
||||
this.props.timeZoneOptions,
|
||||
this.props.countryTimeZoneOptions,
|
||||
@@ -394,11 +268,10 @@ class AccountSettingsPage extends React.Component {
|
||||
);
|
||||
|
||||
const hasLinkedTPA = findIndex(this.props.tpaProviders, provider => provider.connected) >= 0;
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="account-section" id="basic-information" ref={this.navLinkRefs['#basic-information']}>
|
||||
{verifiedNameEnabled && this.renderVerifiedNameMessage(this.props.formValues.mostRecentVerifiedName)}
|
||||
|
||||
<h2 className="section-heading">
|
||||
{this.props.intl.formatMessage(messages['account.settings.section.account.information'])}
|
||||
</h2>
|
||||
@@ -427,44 +300,10 @@ class AccountSettingsPage extends React.Component {
|
||||
? this.props.intl.formatMessage(messages['account.settings.field.full.name.empty'])
|
||||
: this.renderEmptyStaticFieldMessage()
|
||||
}
|
||||
helpText={
|
||||
verifiedNameEnabled && verifiedName
|
||||
? this.renderFullNameHelpText(verifiedName.status)
|
||||
: this.props.intl.formatMessage(messages['account.settings.field.full.name.help.text'])
|
||||
}
|
||||
isEditable={
|
||||
verifiedNameEnabled && verifiedName
|
||||
? this.isEditable('verifiedName') && this.isEditable('name')
|
||||
: this.isEditable('name')
|
||||
}
|
||||
isGrayedOut={
|
||||
verifiedNameEnabled && verifiedName && !this.isEditable('verifiedName')
|
||||
}
|
||||
helpText={this.props.intl.formatMessage(messages['account.settings.field.full.name.help.text'])}
|
||||
isEditable={this.isEditable('name')}
|
||||
{...editableFieldProps}
|
||||
/>
|
||||
{verifiedNameEnabled && verifiedName
|
||||
&& (
|
||||
<EditableField
|
||||
name="verifiedName"
|
||||
type="text"
|
||||
value={this.props.formValues.verifiedName.verified_name}
|
||||
label={
|
||||
(
|
||||
<div className="d-flex">
|
||||
{this.props.intl.formatMessage(messages['account.settings.field.name.verified'])}
|
||||
{
|
||||
this.renderVerifiedNameIcon(verifiedName.status)
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
helpText={this.renderVerifiedNameHelpText(verifiedName.status)}
|
||||
isEditable={this.isEditable('verifiedName')}
|
||||
isGrayedOut={!this.isEditable('verifiedName')}
|
||||
{...(this.isEditable('verifiedName') && editableFieldProps)}
|
||||
/>
|
||||
)}
|
||||
|
||||
<EmailField
|
||||
name="email"
|
||||
label={this.props.intl.formatMessage(messages['account.settings.field.email'])}
|
||||
@@ -739,24 +578,6 @@ AccountSettingsPage.propTypes = {
|
||||
}),
|
||||
state: PropTypes.string,
|
||||
shouldDisplayDemographicsSection: PropTypes.bool,
|
||||
verifiedNameHistory: PropTypes.shape({
|
||||
verified_name_enabled: PropTypes.bool,
|
||||
use_verified_name_for_certs: PropTypes.bool,
|
||||
results: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
verified_name: PropTypes.string,
|
||||
status: PropTypes.string,
|
||||
}),
|
||||
),
|
||||
}),
|
||||
verifiedName: PropTypes.shape({
|
||||
verified_name: PropTypes.string,
|
||||
status: PropTypes.string,
|
||||
}),
|
||||
mostRecentVerifiedName: PropTypes.shape({
|
||||
verified_name: PropTypes.string,
|
||||
status: PropTypes.string,
|
||||
}),
|
||||
}).isRequired,
|
||||
siteLanguage: PropTypes.shape({
|
||||
previousValue: PropTypes.string,
|
||||
|
||||
@@ -91,61 +91,6 @@ const messages = defineMessages({
|
||||
defaultMessage: 'The name that is used for ID verification and that appears on your certificates.',
|
||||
description: 'Help text for the account settings name field.',
|
||||
},
|
||||
'account.settings.field.name.verified': {
|
||||
id: 'account.settings.field.name.verified',
|
||||
defaultMessage: 'Verified name',
|
||||
description: 'Label for account settings verified name field.',
|
||||
},
|
||||
'account.settings.field.name.verified.help.text.verified': {
|
||||
id: 'account.settings.field.name.verified.help.text.verified',
|
||||
defaultMessage: 'This name has been verified by government ID.',
|
||||
description: 'Help text for the account settings verified name field when the name is verified.',
|
||||
},
|
||||
'account.settings.field.name.verified.help.text.submitted': {
|
||||
id: 'account.settings.field.name.verified.help.text.submitted',
|
||||
defaultMessage: 'Verification has been submitted. This usually takes 48 hours or less. Verified name cannot be changed at this time.',
|
||||
description: 'Help text for the account settings verified name field when a verified name has been submitted.',
|
||||
},
|
||||
'account.settings.field.full.name.help.text.submitted': {
|
||||
id: 'account.settings.field.full.name.help.text.submitted',
|
||||
defaultMessage: 'When identity verification is successful, this name will appear on your certificates and public-facing records. Full name cannot be changed at this time.',
|
||||
description: 'Help text for the account settings full name field when a verified name has been submitted.',
|
||||
},
|
||||
'account.settings.field.name.verified.success.message': {
|
||||
id: 'account.settings.field.name.verified.success.message',
|
||||
defaultMessage: 'Your identity verification request has successfully completed. You now have the option of selecting which name you prefer to appear on your certificates and public-records.',
|
||||
description: 'The body of the success alert indicating that a user\'s name has been verified',
|
||||
},
|
||||
'account.settings.field.name.verified.success.message.header': {
|
||||
id: 'account.settings.field.name.verified.success.message.header',
|
||||
defaultMessage: 'Your name change request is complete!',
|
||||
description: 'The header of the success alert indicating that a user\'s name has been verified',
|
||||
},
|
||||
'account.settings.field.name.verified.failure.message': {
|
||||
id: 'account.settings.field.name.verified.failure.message',
|
||||
defaultMessage: 'Your Verified name change attempt, “{verifiedName}”, did not pass ID verification. Your previous Verified name settings have been restored.',
|
||||
description: 'The body of the failure alert indicating that a user\'s name was not able to be verified',
|
||||
},
|
||||
'account.settings.field.name.verified.failure.message.header': {
|
||||
id: 'account.settings.field.name.verified.failure.message.header',
|
||||
defaultMessage: 'We were not able to verify your identity.',
|
||||
description: 'The header of the failure alert indicating that a user\'s name was not able to be verified',
|
||||
},
|
||||
'account.settings.field.name.verified.failure.message.help.link': {
|
||||
id: 'account.settings.field.name.verified.failure.message.help.link',
|
||||
defaultMessage: 'Learn more about ID verification',
|
||||
description: 'The text of the button displayed when a user\'s name was not able to be verified, intended to direct the user to a help article about ID verification.',
|
||||
},
|
||||
'account.settings.field.name.verified.submitted.message': {
|
||||
id: 'account.settings.field.name.verified.submitted.message',
|
||||
defaultMessage: 'Your identity verification request has been submitted and usually takes between 24 and 48 hours to complete. When your request is approved, your updated name will appear on all associated certificates and public-facing records.',
|
||||
description: 'The body of the submitted alert indicating that a user\'s name has been submitted for verification',
|
||||
},
|
||||
'account.settings.field.name.verified.submitted.message.header': {
|
||||
id: 'account.settings.field.name.verified.submitted.message.header',
|
||||
defaultMessage: 'Your name change request is almost complete!',
|
||||
description: 'The header of the submitted alert indicating that a user\'s name has been submitted for verification',
|
||||
},
|
||||
'account.settings.field.email': {
|
||||
id: 'account.settings.field.email',
|
||||
defaultMessage: 'Email address (Sign in)',
|
||||
|
||||
@@ -37,7 +37,6 @@ function EditableField(props) {
|
||||
onChange,
|
||||
isEditing,
|
||||
isEditable,
|
||||
isGrayedOut,
|
||||
intl,
|
||||
...others
|
||||
} = props;
|
||||
@@ -162,7 +161,7 @@ function EditableField(props) {
|
||||
</Button>
|
||||
) : null}
|
||||
</div>
|
||||
<p data-hj-suppress className={isGrayedOut ? 'grayed-out' : null}>{renderValue(value)}</p>
|
||||
<p data-hj-suppress>{renderValue(value)}</p>
|
||||
<p className="small text-muted mt-n2">{renderConfirmationMessage() || helpText}</p>
|
||||
</div>
|
||||
),
|
||||
@@ -173,7 +172,7 @@ function EditableField(props) {
|
||||
|
||||
EditableField.propTypes = {
|
||||
name: PropTypes.string.isRequired,
|
||||
label: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.node]),
|
||||
label: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||
emptyLabel: PropTypes.node,
|
||||
type: PropTypes.string.isRequired,
|
||||
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||
@@ -197,7 +196,6 @@ EditableField.propTypes = {
|
||||
onChange: PropTypes.func.isRequired,
|
||||
isEditing: PropTypes.bool,
|
||||
isEditable: PropTypes.bool,
|
||||
isGrayedOut: PropTypes.bool,
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
@@ -213,7 +211,6 @@ EditableField.defaultProps = {
|
||||
helpText: undefined,
|
||||
isEditing: false,
|
||||
isEditable: true,
|
||||
isGrayedOut: false,
|
||||
userSuppliedValue: undefined,
|
||||
};
|
||||
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
import React, { useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { Alert } from '@edx/paragon';
|
||||
|
||||
export default function OneTimeDismissibleAlert(props) {
|
||||
const [dismissed, setDismissed] = useState(localStorage.getItem(props.id) !== 'true');
|
||||
|
||||
const onClose = () => {
|
||||
localStorage.setItem(props.id, 'true');
|
||||
setDismissed(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<Alert
|
||||
variant={props.variant}
|
||||
dismissible
|
||||
icon={props.icon}
|
||||
onClose={onClose}
|
||||
show={dismissed}
|
||||
>
|
||||
<Alert.Heading>{props.header}</Alert.Heading>
|
||||
<p>
|
||||
{props.body}
|
||||
</p>
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
|
||||
OneTimeDismissibleAlert.propTypes = {
|
||||
id: PropTypes.string.isRequired,
|
||||
variant: PropTypes.string,
|
||||
icon: PropTypes.func,
|
||||
header: PropTypes.string,
|
||||
body: PropTypes.string,
|
||||
};
|
||||
|
||||
OneTimeDismissibleAlert.defaultProps = {
|
||||
variant: 'success',
|
||||
icon: undefined,
|
||||
header: undefined,
|
||||
body: undefined,
|
||||
};
|
||||
@@ -50,8 +50,4 @@
|
||||
line-height: 1.6rem;
|
||||
}
|
||||
}
|
||||
.grayed-out{
|
||||
opacity: 0.6; /* Real browsers */
|
||||
filter: alpha(opacity = 60); /* MSIE */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,11 +38,7 @@ import {
|
||||
import { saga as thirdPartyAuthSaga } from '../third-party-auth';
|
||||
|
||||
// Services
|
||||
import {
|
||||
getSettings,
|
||||
patchSettings,
|
||||
getTimeZones,
|
||||
} from './service';
|
||||
import { getSettings, patchSettings, getTimeZones } from './service';
|
||||
|
||||
export function* handleFetchSettings() {
|
||||
try {
|
||||
|
||||
@@ -7,63 +7,9 @@ export const accountSettingsSelector = state => ({ ...state[storeName] });
|
||||
|
||||
const editableFieldNameSelector = (state, props) => props.name;
|
||||
|
||||
const sortedVerifiedNameHistorySelector = createSelector(
|
||||
accountSettingsSelector,
|
||||
accountSettings => {
|
||||
function sortDates(a, b) {
|
||||
const aTimeSinceEpoch = new Date(a).getTime();
|
||||
const bTimeSinceEpoch = new Date(b).getTime();
|
||||
return bTimeSinceEpoch - aTimeSinceEpoch;
|
||||
}
|
||||
|
||||
const history = accountSettings.values.verifiedNameHistory && accountSettings.values.verifiedNameHistory.results;
|
||||
|
||||
if (Array.isArray(history)) {
|
||||
return history.sort(sortDates);
|
||||
}
|
||||
|
||||
return [];
|
||||
},
|
||||
);
|
||||
|
||||
const mostRecentVerifiedNameSelector = createSelector(
|
||||
sortedVerifiedNameHistorySelector,
|
||||
sortedHistory => (sortedHistory.length > 0 ? sortedHistory[0] : null),
|
||||
);
|
||||
|
||||
const mostRecentApprovedVerifiedNameValueSelector = createSelector(
|
||||
sortedVerifiedNameHistorySelector,
|
||||
mostRecentVerifiedNameSelector,
|
||||
(sortedHistory, mostRecentVerifiedName) => {
|
||||
const approvedVerifiedNames = sortedHistory.filter(name => name.status === 'approved');
|
||||
const approvedVerifiedName = approvedVerifiedNames.length > 0 ? approvedVerifiedNames[0] : null;
|
||||
|
||||
let verifiedName = null;
|
||||
switch (mostRecentVerifiedName && mostRecentVerifiedName.status) {
|
||||
case 'approved':
|
||||
case 'denied':
|
||||
verifiedName = approvedVerifiedName;
|
||||
break;
|
||||
case 'submitted':
|
||||
verifiedName = mostRecentVerifiedName;
|
||||
break;
|
||||
default:
|
||||
verifiedName = null;
|
||||
}
|
||||
return verifiedName;
|
||||
},
|
||||
);
|
||||
|
||||
const valuesSelector = createSelector(
|
||||
accountSettingsSelector,
|
||||
mostRecentVerifiedNameSelector,
|
||||
mostRecentApprovedVerifiedNameValueSelector,
|
||||
(accountSettings, mostRecentVerifiedNameValue, mostRecentApprovedVerifiedNameValue) => (
|
||||
{
|
||||
...accountSettings.values,
|
||||
verifiedName: mostRecentApprovedVerifiedNameValue,
|
||||
mostRecentVerifiedName: mostRecentVerifiedNameValue,
|
||||
}),
|
||||
accountSettings => accountSettings.values,
|
||||
);
|
||||
|
||||
const draftsSelector = createSelector(
|
||||
@@ -123,18 +69,7 @@ export const profileDataManagerSelector = createSelector(
|
||||
|
||||
export const staticFieldsSelector = createSelector(
|
||||
accountSettingsSelector,
|
||||
mostRecentVerifiedNameSelector,
|
||||
(accountSettings, verifiedName) => {
|
||||
const staticFields = [];
|
||||
if (accountSettings.profileDataManager) {
|
||||
staticFields.push('name', 'email', 'country');
|
||||
}
|
||||
if (verifiedName && ['pending', 'submitted'].includes(verifiedName.status)) {
|
||||
staticFields.push('verifiedName');
|
||||
}
|
||||
|
||||
return staticFields;
|
||||
},
|
||||
accountSettings => (accountSettings.profileDataManager ? ['name', 'email', 'country'] : []),
|
||||
);
|
||||
|
||||
/**
|
||||
|
||||
@@ -176,49 +176,12 @@ export async function shouldDisplayDemographicsQuestions() {
|
||||
return false;
|
||||
}
|
||||
|
||||
export async function getVerifiedName() {
|
||||
let data;
|
||||
const client = getAuthenticatedHttpClient();
|
||||
try {
|
||||
const requestUrl = `${getConfig().LMS_BASE_URL}/api/edx_name_affirmation/v1/verified_name`;
|
||||
({ data } = await client.get(requestUrl));
|
||||
} catch (error) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
export async function getVerifiedNameHistory() {
|
||||
let data;
|
||||
const client = getAuthenticatedHttpClient();
|
||||
try {
|
||||
const requestUrl = `${getConfig().LMS_BASE_URL}/api/edx_name_affirmation/v1/verified_name/history`;
|
||||
({ data } = await client.get(requestUrl));
|
||||
} catch (error) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* A single function to GET everything considered a setting.
|
||||
* Currently encapsulates Account, Preferences, Coaching, ThirdPartyAuth, and Demographics
|
||||
*/
|
||||
export async function getSettings(username, userRoles, userId) {
|
||||
const [
|
||||
account,
|
||||
preferences,
|
||||
thirdPartyAuthProviders,
|
||||
profileDataManager,
|
||||
timeZones,
|
||||
coaching,
|
||||
shouldDisplayDemographicsQuestionsResponse,
|
||||
demographics,
|
||||
demographicsOptions,
|
||||
verifiedNameHistory,
|
||||
] = await Promise.all([
|
||||
const results = await Promise.all([
|
||||
getAccount(username),
|
||||
getPreferences(username),
|
||||
getThirdPartyAuthProviders(),
|
||||
@@ -228,20 +191,18 @@ export async function getSettings(username, userRoles, userId) {
|
||||
getConfig().ENABLE_DEMOGRAPHICS_COLLECTION && shouldDisplayDemographicsQuestions(),
|
||||
getConfig().ENABLE_DEMOGRAPHICS_COLLECTION && getDemographics(userId),
|
||||
getConfig().ENABLE_DEMOGRAPHICS_COLLECTION && getDemographicsOptions(),
|
||||
getVerifiedNameHistory(),
|
||||
]);
|
||||
|
||||
return {
|
||||
...account,
|
||||
...preferences,
|
||||
thirdPartyAuthProviders,
|
||||
profileDataManager,
|
||||
timeZones,
|
||||
coaching,
|
||||
shouldDisplayDemographicsSection: shouldDisplayDemographicsQuestionsResponse,
|
||||
...demographics,
|
||||
demographicsOptions,
|
||||
verifiedNameHistory,
|
||||
...results[0],
|
||||
...results[1],
|
||||
thirdPartyAuthProviders: results[2],
|
||||
profileDataManager: results[3],
|
||||
timeZones: results[4],
|
||||
coaching: results[5],
|
||||
shouldDisplayDemographicsSection: results[6],
|
||||
...results[7], // demographics
|
||||
demographicsOptions: results[8],
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -21,10 +21,15 @@ const BeforeProceedingBanner = (props) => {
|
||||
icon={<FontAwesomeIcon className="mr-2" icon={faExclamationTriangle} />}
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage=intl.formatMessage(
|
||||
messages[instructionMessageId], {linkStart: <Hyperlink destination={supportArticleURL}>, linkEnd=</Hyperlink>}
|
||||
)
|
||||
id="account.settings.delete.account.before.proceeding"
|
||||
defaultMessage="Before proceeding, please {actionLink}."
|
||||
description="Error that appears if you are trying to delete your account, but something about your account needs attention first. The actionLink will be instructions, such as 'unlink your Facebook account'."
|
||||
values={{
|
||||
actionLink: (
|
||||
<Hyperlink destination={supportArticleUrl}>
|
||||
{intl.formatMessage(messages[instructionMessageId])}
|
||||
</Hyperlink>
|
||||
),
|
||||
siteName: getConfig().SITE_NAME,
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -28,7 +28,6 @@ exports[`DeleteAccount should match default section snapshot 1`] = `
|
||||
</p>
|
||||
<p>
|
||||
<a
|
||||
className="default-link standalone-link"
|
||||
href="https://support.edx.org/hc/en-us/sections/115004139268-Manage-Your-Account-Settings"
|
||||
onClick={[Function]}
|
||||
target="_self"
|
||||
@@ -77,7 +76,6 @@ exports[`DeleteAccount should match unverified account section snapshot 1`] = `
|
||||
</p>
|
||||
<p>
|
||||
<a
|
||||
className="default-link standalone-link"
|
||||
href="https://support.edx.org/hc/en-us/sections/115004139268-Manage-Your-Account-Settings"
|
||||
onClick={[Function]}
|
||||
target="_self"
|
||||
@@ -121,7 +119,6 @@ exports[`DeleteAccount should match unverified account section snapshot 1`] = `
|
||||
<span>
|
||||
Before proceeding, please
|
||||
<a
|
||||
className="default-link standalone-link"
|
||||
href="https://support.edx.org/hc/en-us/articles/115000940568-How-do-I-activate-my-account-"
|
||||
onClick={[Function]}
|
||||
target="_self"
|
||||
@@ -163,7 +160,6 @@ exports[`DeleteAccount should match unverified account section snapshot 2`] = `
|
||||
</p>
|
||||
<p>
|
||||
<a
|
||||
className="default-link standalone-link"
|
||||
href="https://support.edx.org/hc/en-us/sections/115004139268-Manage-Your-Account-Settings"
|
||||
onClick={[Function]}
|
||||
target="_self"
|
||||
@@ -207,7 +203,6 @@ exports[`DeleteAccount should match unverified account section snapshot 2`] = `
|
||||
<span>
|
||||
Before proceeding, please
|
||||
<a
|
||||
className="default-link standalone-link"
|
||||
href="https://support.edx.org/hc/en-us/articles/207206067"
|
||||
onClick={[Function]}
|
||||
target="_self"
|
||||
|
||||
@@ -24,7 +24,7 @@ const messages = defineMessages({
|
||||
'account.settings.delete.account.text.2.edX': {
|
||||
id: 'account.settings.delete.account.text.2.edX',
|
||||
defaultMessage: 'Once your account is deleted, you cannot use it to take courses on the edX app, edx.org, or any other site hosted by edX. This includes access to edx.org from your employer’s or university’s system and access to private sites offered by MIT Open Learning, Wharton Executive Education, and Harvard Medical School.',
|
||||
description: 'A message in the user account deletion area. This message will NOT be used on Open edX installations. Please do not translate \'MIT Open Learning\', \'Wharton Executive Education\', or \'Harvard Medical School\'',
|
||||
description: 'A message in the user account deletion area',
|
||||
},
|
||||
'account.settings.delete.account.text.3.link': {
|
||||
id: 'account.settings.delete.account.text.3.link',
|
||||
@@ -48,13 +48,13 @@ const messages = defineMessages({
|
||||
},
|
||||
'account.settings.delete.account.please.activate': {
|
||||
id: 'account.settings.delete.account.please.activate',
|
||||
defaultMessage: 'Before proceeding, please {linkStart}activate your account{linkEnd}',
|
||||
description: 'This message links to a support article',
|
||||
defaultMessage: 'activate your account',
|
||||
description: 'This is the text on a link that goes to the support page. It is part of this sentence: Before proceeding, please activate your account.',
|
||||
},
|
||||
'account.settings.delete.account.please.unlink': {
|
||||
id: 'account.settings.delete.account.please.unlink',
|
||||
defaultMessage: 'Before proceeding, please {linkStart}unlink all social media accounts{linkEnd}',
|
||||
description: 'This message links to a support article',
|
||||
defaultMessage: 'unlink all social media accounts',
|
||||
description: 'This is the text on a link that goes to the support page. It is part of this sentence: Before proceeding, please unlink all social media accounts.',
|
||||
},
|
||||
'account.settings.delete.account.modal.header': {
|
||||
id: 'account.settings.delete.account.modal.header',
|
||||
@@ -74,7 +74,7 @@ const messages = defineMessages({
|
||||
'account.settings.delete.account.modal.text.2.edX': {
|
||||
id: 'account.settings.delete.account.modal.text.2.edX',
|
||||
defaultMessage: 'If you proceed, you will be unable to use this account to take courses on the edX app, edx.org, or any other site hosted by edX. This includes access to edx.org from your employer\'s or university\'s system and access to private sites offered by MIT Open Learning, Wharton Executive Education, and Harvard Medical School.',
|
||||
description: 'Messaging in the dialog asking user to confirm that they want to delete their entire account. This message will NOT be used on Open edX installations. Please do not translate \'MIT Open Learning\', \'Wharton Executive Education\', or \'Harvard Medical School\'',
|
||||
description: 'Messaging in the dialog asking user to confirm that they want to delete their entire account',
|
||||
},
|
||||
'account.settings.delete.account.modal.enter.password': {
|
||||
id: 'account.settings.delete.account.modal.enter.password',
|
||||
|
||||
@@ -12,43 +12,20 @@ exports[`DemographicsSection should render 1`] = `
|
||||
</h2>
|
||||
<p>
|
||||
<a
|
||||
className="default-link standalone-link"
|
||||
href="http://localhost:5335/demographics"
|
||||
onClick={[Function]}
|
||||
rel="noopener noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Why does localhost collect this information?
|
||||
<span
|
||||
className="d-inline-block align-text-top"
|
||||
>
|
||||
<span>
|
||||
|
||||
<span
|
||||
className="pgn__icon"
|
||||
style={
|
||||
Object {
|
||||
"height": "1em",
|
||||
"width": "1em",
|
||||
}
|
||||
}
|
||||
>
|
||||
<svg
|
||||
aria-hidden={true}
|
||||
aria-label=""
|
||||
fill="none"
|
||||
focusable={false}
|
||||
height={24}
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
width={24}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M19 19H5V5h7V3H3v18h18v-9h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
aria-hidden={false}
|
||||
aria-label="Opens in a new window"
|
||||
className="fa fa-external-link"
|
||||
title="Opens in a new window"
|
||||
/>
|
||||
</span>
|
||||
</a>
|
||||
</p>
|
||||
@@ -108,7 +85,6 @@ exports[`DemographicsSection should render 1`] = `
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
Prefer not to respond
|
||||
@@ -172,7 +148,6 @@ exports[`DemographicsSection should render 1`] = `
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
<button
|
||||
@@ -243,7 +218,6 @@ exports[`DemographicsSection should render 1`] = `
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
Prefer not to respond
|
||||
@@ -307,7 +281,6 @@ exports[`DemographicsSection should render 1`] = `
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
Prefer not to respond
|
||||
@@ -371,7 +344,6 @@ exports[`DemographicsSection should render 1`] = `
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
Prefer not to respond
|
||||
@@ -435,7 +407,6 @@ exports[`DemographicsSection should render 1`] = `
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
Prefer not to respond
|
||||
@@ -499,7 +470,6 @@ exports[`DemographicsSection should render 1`] = `
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
Prefer not to respond
|
||||
@@ -563,7 +533,6 @@ exports[`DemographicsSection should render 1`] = `
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
Prefer not to respond
|
||||
@@ -627,7 +596,6 @@ exports[`DemographicsSection should render 1`] = `
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
Prefer not to respond
|
||||
@@ -654,43 +622,20 @@ exports[`DemographicsSection should render an Alert if an error occurs 1`] = `
|
||||
</h2>
|
||||
<p>
|
||||
<a
|
||||
className="default-link standalone-link"
|
||||
href="http://localhost:5335/demographics"
|
||||
onClick={[Function]}
|
||||
rel="noopener noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Why does localhost collect this information?
|
||||
<span
|
||||
className="d-inline-block align-text-top"
|
||||
>
|
||||
<span>
|
||||
|
||||
<span
|
||||
className="pgn__icon"
|
||||
style={
|
||||
Object {
|
||||
"height": "1em",
|
||||
"width": "1em",
|
||||
}
|
||||
}
|
||||
>
|
||||
<svg
|
||||
aria-hidden={true}
|
||||
aria-label=""
|
||||
fill="none"
|
||||
focusable={false}
|
||||
height={24}
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
width={24}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M19 19H5V5h7V3H3v18h18v-9h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
aria-hidden={false}
|
||||
aria-label="Opens in a new window"
|
||||
className="fa fa-external-link"
|
||||
title="Opens in a new window"
|
||||
/>
|
||||
</span>
|
||||
</a>
|
||||
</p>
|
||||
@@ -764,7 +709,6 @@ exports[`DemographicsSection should render an Alert if an error occurs 1`] = `
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
Prefer not to respond
|
||||
@@ -828,7 +772,6 @@ exports[`DemographicsSection should render an Alert if an error occurs 1`] = `
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
<button
|
||||
@@ -899,7 +842,6 @@ exports[`DemographicsSection should render an Alert if an error occurs 1`] = `
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
Prefer not to respond
|
||||
@@ -963,7 +905,6 @@ exports[`DemographicsSection should render an Alert if an error occurs 1`] = `
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
Prefer not to respond
|
||||
@@ -1027,7 +968,6 @@ exports[`DemographicsSection should render an Alert if an error occurs 1`] = `
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
Prefer not to respond
|
||||
@@ -1091,7 +1031,6 @@ exports[`DemographicsSection should render an Alert if an error occurs 1`] = `
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
Prefer not to respond
|
||||
@@ -1155,7 +1094,6 @@ exports[`DemographicsSection should render an Alert if an error occurs 1`] = `
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
Prefer not to respond
|
||||
@@ -1219,7 +1157,6 @@ exports[`DemographicsSection should render an Alert if an error occurs 1`] = `
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
Prefer not to respond
|
||||
@@ -1283,7 +1220,6 @@ exports[`DemographicsSection should render an Alert if an error occurs 1`] = `
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
Prefer not to respond
|
||||
@@ -1310,43 +1246,20 @@ exports[`DemographicsSection should render an Alert when demographicsOptions pro
|
||||
</h2>
|
||||
<p>
|
||||
<a
|
||||
className="default-link standalone-link"
|
||||
href="http://localhost:5335/demographics"
|
||||
onClick={[Function]}
|
||||
rel="noopener noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Why does localhost collect this information?
|
||||
<span
|
||||
className="d-inline-block align-text-top"
|
||||
>
|
||||
<span>
|
||||
|
||||
<span
|
||||
className="pgn__icon"
|
||||
style={
|
||||
Object {
|
||||
"height": "1em",
|
||||
"width": "1em",
|
||||
}
|
||||
}
|
||||
>
|
||||
<svg
|
||||
aria-hidden={true}
|
||||
aria-label=""
|
||||
fill="none"
|
||||
focusable={false}
|
||||
height={24}
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
width={24}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M19 19H5V5h7V3H3v18h18v-9h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
aria-hidden={false}
|
||||
aria-label="Opens in a new window"
|
||||
className="fa fa-external-link"
|
||||
title="Opens in a new window"
|
||||
/>
|
||||
</span>
|
||||
</a>
|
||||
</p>
|
||||
@@ -1379,43 +1292,20 @@ exports[`DemographicsSection should render ethnicity correctly when multiple opt
|
||||
</h2>
|
||||
<p>
|
||||
<a
|
||||
className="default-link standalone-link"
|
||||
href="http://localhost:5335/demographics"
|
||||
onClick={[Function]}
|
||||
rel="noopener noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Why does localhost collect this information?
|
||||
<span
|
||||
className="d-inline-block align-text-top"
|
||||
>
|
||||
<span>
|
||||
|
||||
<span
|
||||
className="pgn__icon"
|
||||
style={
|
||||
Object {
|
||||
"height": "1em",
|
||||
"width": "1em",
|
||||
}
|
||||
}
|
||||
>
|
||||
<svg
|
||||
aria-hidden={true}
|
||||
aria-label=""
|
||||
fill="none"
|
||||
focusable={false}
|
||||
height={24}
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
width={24}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M19 19H5V5h7V3H3v18h18v-9h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
aria-hidden={false}
|
||||
aria-label="Opens in a new window"
|
||||
className="fa fa-external-link"
|
||||
title="Opens in a new window"
|
||||
/>
|
||||
</span>
|
||||
</a>
|
||||
</p>
|
||||
@@ -1475,7 +1365,6 @@ exports[`DemographicsSection should render ethnicity correctly when multiple opt
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
Prefer not to respond
|
||||
@@ -1539,7 +1428,6 @@ exports[`DemographicsSection should render ethnicity correctly when multiple opt
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
Hispanic, Latin, or Spanish origin, White
|
||||
@@ -1603,7 +1491,6 @@ exports[`DemographicsSection should render ethnicity correctly when multiple opt
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
Prefer not to respond
|
||||
@@ -1667,7 +1554,6 @@ exports[`DemographicsSection should render ethnicity correctly when multiple opt
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
Prefer not to respond
|
||||
@@ -1731,7 +1617,6 @@ exports[`DemographicsSection should render ethnicity correctly when multiple opt
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
Prefer not to respond
|
||||
@@ -1795,7 +1680,6 @@ exports[`DemographicsSection should render ethnicity correctly when multiple opt
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
Prefer not to respond
|
||||
@@ -1859,7 +1743,6 @@ exports[`DemographicsSection should render ethnicity correctly when multiple opt
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
Prefer not to respond
|
||||
@@ -1923,7 +1806,6 @@ exports[`DemographicsSection should render ethnicity correctly when multiple opt
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
Prefer not to respond
|
||||
@@ -1987,7 +1869,6 @@ exports[`DemographicsSection should render ethnicity correctly when multiple opt
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
Prefer not to respond
|
||||
@@ -2014,43 +1895,20 @@ exports[`DemographicsSection should render ethnicity text correctly 1`] = `
|
||||
</h2>
|
||||
<p>
|
||||
<a
|
||||
className="default-link standalone-link"
|
||||
href="http://localhost:5335/demographics"
|
||||
onClick={[Function]}
|
||||
rel="noopener noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Why does localhost collect this information?
|
||||
<span
|
||||
className="d-inline-block align-text-top"
|
||||
>
|
||||
<span>
|
||||
|
||||
<span
|
||||
className="pgn__icon"
|
||||
style={
|
||||
Object {
|
||||
"height": "1em",
|
||||
"width": "1em",
|
||||
}
|
||||
}
|
||||
>
|
||||
<svg
|
||||
aria-hidden={true}
|
||||
aria-label=""
|
||||
fill="none"
|
||||
focusable={false}
|
||||
height={24}
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
width={24}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M19 19H5V5h7V3H3v18h18v-9h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
aria-hidden={false}
|
||||
aria-label="Opens in a new window"
|
||||
className="fa fa-external-link"
|
||||
title="Opens in a new window"
|
||||
/>
|
||||
</span>
|
||||
</a>
|
||||
</p>
|
||||
@@ -2110,7 +1968,6 @@ exports[`DemographicsSection should render ethnicity text correctly 1`] = `
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
Prefer not to respond
|
||||
@@ -2174,7 +2031,6 @@ exports[`DemographicsSection should render ethnicity text correctly 1`] = `
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
Asian
|
||||
@@ -2238,7 +2094,6 @@ exports[`DemographicsSection should render ethnicity text correctly 1`] = `
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
Prefer not to respond
|
||||
@@ -2302,7 +2157,6 @@ exports[`DemographicsSection should render ethnicity text correctly 1`] = `
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
Prefer not to respond
|
||||
@@ -2366,7 +2220,6 @@ exports[`DemographicsSection should render ethnicity text correctly 1`] = `
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
Prefer not to respond
|
||||
@@ -2430,7 +2283,6 @@ exports[`DemographicsSection should render ethnicity text correctly 1`] = `
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
Prefer not to respond
|
||||
@@ -2494,7 +2346,6 @@ exports[`DemographicsSection should render ethnicity text correctly 1`] = `
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
Prefer not to respond
|
||||
@@ -2558,7 +2409,6 @@ exports[`DemographicsSection should render ethnicity text correctly 1`] = `
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
Prefer not to respond
|
||||
@@ -2622,7 +2472,6 @@ exports[`DemographicsSection should render ethnicity text correctly 1`] = `
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
Prefer not to respond
|
||||
@@ -2649,43 +2498,20 @@ exports[`DemographicsSection should set user input correctly when user provides
|
||||
</h2>
|
||||
<p>
|
||||
<a
|
||||
className="default-link standalone-link"
|
||||
href="http://localhost:5335/demographics"
|
||||
onClick={[Function]}
|
||||
rel="noopener noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Why does localhost collect this information?
|
||||
<span
|
||||
className="d-inline-block align-text-top"
|
||||
>
|
||||
<span>
|
||||
|
||||
<span
|
||||
className="pgn__icon"
|
||||
style={
|
||||
Object {
|
||||
"height": "1em",
|
||||
"width": "1em",
|
||||
}
|
||||
}
|
||||
>
|
||||
<svg
|
||||
aria-hidden={true}
|
||||
aria-label=""
|
||||
fill="none"
|
||||
focusable={false}
|
||||
height={24}
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
width={24}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M19 19H5V5h7V3H3v18h18v-9h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
aria-hidden={false}
|
||||
aria-label="Opens in a new window"
|
||||
className="fa fa-external-link"
|
||||
title="Opens in a new window"
|
||||
/>
|
||||
</span>
|
||||
</a>
|
||||
</p>
|
||||
@@ -2745,7 +2571,6 @@ exports[`DemographicsSection should set user input correctly when user provides
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
Prefer not to respond
|
||||
@@ -2809,7 +2634,6 @@ exports[`DemographicsSection should set user input correctly when user provides
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
<button
|
||||
@@ -2880,7 +2704,6 @@ exports[`DemographicsSection should set user input correctly when user provides
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
Prefer not to respond
|
||||
@@ -2944,7 +2767,6 @@ exports[`DemographicsSection should set user input correctly when user provides
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
Prefer not to respond
|
||||
@@ -3008,7 +2830,6 @@ exports[`DemographicsSection should set user input correctly when user provides
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
Prefer not to respond
|
||||
@@ -3072,7 +2893,6 @@ exports[`DemographicsSection should set user input correctly when user provides
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
Prefer not to respond
|
||||
@@ -3136,7 +2956,6 @@ exports[`DemographicsSection should set user input correctly when user provides
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
Other: test
|
||||
@@ -3200,7 +3019,6 @@ exports[`DemographicsSection should set user input correctly when user provides
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
Prefer not to respond
|
||||
@@ -3264,7 +3082,6 @@ exports[`DemographicsSection should set user input correctly when user provides
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
Prefer not to respond
|
||||
@@ -3291,43 +3108,20 @@ exports[`DemographicsSection should set user input correctly when user provides
|
||||
</h2>
|
||||
<p>
|
||||
<a
|
||||
className="default-link standalone-link"
|
||||
href="http://localhost:5335/demographics"
|
||||
onClick={[Function]}
|
||||
rel="noopener noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Why does localhost collect this information?
|
||||
<span
|
||||
className="d-inline-block align-text-top"
|
||||
>
|
||||
<span>
|
||||
|
||||
<span
|
||||
className="pgn__icon"
|
||||
style={
|
||||
Object {
|
||||
"height": "1em",
|
||||
"width": "1em",
|
||||
}
|
||||
}
|
||||
>
|
||||
<svg
|
||||
aria-hidden={true}
|
||||
aria-label=""
|
||||
fill="none"
|
||||
focusable={false}
|
||||
height={24}
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
width={24}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M19 19H5V5h7V3H3v18h18v-9h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
aria-hidden={false}
|
||||
aria-label="Opens in a new window"
|
||||
className="fa fa-external-link"
|
||||
title="Opens in a new window"
|
||||
/>
|
||||
</span>
|
||||
</a>
|
||||
</p>
|
||||
@@ -3387,7 +3181,6 @@ exports[`DemographicsSection should set user input correctly when user provides
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
Prefer to self describe: test
|
||||
@@ -3451,7 +3244,6 @@ exports[`DemographicsSection should set user input correctly when user provides
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
<button
|
||||
@@ -3522,7 +3314,6 @@ exports[`DemographicsSection should set user input correctly when user provides
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
Prefer not to respond
|
||||
@@ -3586,7 +3377,6 @@ exports[`DemographicsSection should set user input correctly when user provides
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
Prefer not to respond
|
||||
@@ -3650,7 +3440,6 @@ exports[`DemographicsSection should set user input correctly when user provides
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
Prefer not to respond
|
||||
@@ -3714,7 +3503,6 @@ exports[`DemographicsSection should set user input correctly when user provides
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
Prefer not to respond
|
||||
@@ -3778,7 +3566,6 @@ exports[`DemographicsSection should set user input correctly when user provides
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
Prefer not to respond
|
||||
@@ -3842,7 +3629,6 @@ exports[`DemographicsSection should set user input correctly when user provides
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
Prefer not to respond
|
||||
@@ -3906,7 +3692,6 @@ exports[`DemographicsSection should set user input correctly when user provides
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
className={null}
|
||||
data-hj-suppress={true}
|
||||
>
|
||||
Prefer not to respond
|
||||
|
||||
@@ -20,17 +20,6 @@
|
||||
"account.settings.field.full.name": "الاسم الكامل",
|
||||
"account.settings.field.full.name.empty": "إضافة اسم",
|
||||
"account.settings.field.full.name.help.text": "الاسم المستخدم للتحقق من هويتك والذي سوف يظهر على الشهادات الخاصة بك.",
|
||||
"account.settings.field.name.verified": "Verified name",
|
||||
"account.settings.field.name.verified.help.text.verified": "This name has been verified by government ID.",
|
||||
"account.settings.field.name.verified.help.text.submitted": "Verification has been submitted. This usually takes 48 hours or less. Verified name cannot be changed at this time.",
|
||||
"account.settings.field.full.name.help.text.submitted": "When identity verification is successful, this name will appear on your certificates and public-facing records. Full name cannot be changed at this time.",
|
||||
"account.settings.field.name.verified.success.message": "Your identity verification request has successfully completed. You now have the option of selecting which name you prefer to appear on your certificates and public-records.",
|
||||
"account.settings.field.name.verified.success.message.header": "Your name change request is complete!",
|
||||
"account.settings.field.name.verified.failure.message": "Your Verified name change attempt, “{verifiedName}”, did not pass ID verification. Your previous Verified name settings have been restored.",
|
||||
"account.settings.field.name.verified.failure.message.header": "We were not able to verify your identity.",
|
||||
"account.settings.field.name.verified.failure.message.help.link": "Learn more about ID verification",
|
||||
"account.settings.field.name.verified.submitted.message": "Your identity verification request has been submitted and usually takes between 24 and 48 hours to complete. When your request is approved, your updated name will appear on all associated certificates and public-facing records.",
|
||||
"account.settings.field.name.verified.submitted.message.header": "Your name change request is almost complete!",
|
||||
"account.settings.field.email": "البريد الالكتروني (الدخول)",
|
||||
"account.settings.field.email.empty": "إضافة عنوان البريد الإلكتروني",
|
||||
"account.settings.field.email.confirmation": "لقد أرسلنا رسالة تأكيد إلى {value}. انقر فوق الرابط في الرسالة لتحديث عنوان بريدك الإلكتروني.",
|
||||
|
||||
@@ -20,17 +20,6 @@
|
||||
"account.settings.field.full.name": "Nombre completo",
|
||||
"account.settings.field.full.name.empty": "Añade nombre",
|
||||
"account.settings.field.full.name.help.text": "El nombre que es usado para la verificación de identidad y aparece en sus certificados.",
|
||||
"account.settings.field.name.verified": "Verified name",
|
||||
"account.settings.field.name.verified.help.text.verified": "This name has been verified by government ID.",
|
||||
"account.settings.field.name.verified.help.text.submitted": "Verification has been submitted. This usually takes 48 hours or less. Verified name cannot be changed at this time.",
|
||||
"account.settings.field.full.name.help.text.submitted": "When identity verification is successful, this name will appear on your certificates and public-facing records. Full name cannot be changed at this time.",
|
||||
"account.settings.field.name.verified.success.message": "Your identity verification request has successfully completed. You now have the option of selecting which name you prefer to appear on your certificates and public-records.",
|
||||
"account.settings.field.name.verified.success.message.header": "Your name change request is complete!",
|
||||
"account.settings.field.name.verified.failure.message": "Your Verified name change attempt, “{verifiedName}”, did not pass ID verification. Your previous Verified name settings have been restored.",
|
||||
"account.settings.field.name.verified.failure.message.header": "We were not able to verify your identity.",
|
||||
"account.settings.field.name.verified.failure.message.help.link": "Más información sobre la verificación de ID",
|
||||
"account.settings.field.name.verified.submitted.message": "Your identity verification request has been submitted and usually takes between 24 and 48 hours to complete. When your request is approved, your updated name will appear on all associated certificates and public-facing records.",
|
||||
"account.settings.field.name.verified.submitted.message.header": "Your name change request is almost complete!",
|
||||
"account.settings.field.email": "Correo electrónico (Ingresar)",
|
||||
"account.settings.field.email.empty": "Agregar correo electrónico",
|
||||
"account.settings.field.email.confirmation": "Le enviamos un mensaje de confirmación a {value}. Hacer click en la liga del mensaje para actualizar su correo electrónico.",
|
||||
@@ -114,7 +103,7 @@
|
||||
"account.settings.delete.account.subheader": "¡Sentimos que te vayas!",
|
||||
"account.settings.delete.account.text.1": "Please note: Deletion of your account and personal data is permanent and cannot be undone. {siteName} will not be able to recover your account or the data that is deleted.",
|
||||
"account.settings.delete.account.text.2": "Once your account is deleted, you cannot use it to take courses on {siteName}.",
|
||||
"account.settings.delete.account.text.2.edX": "Una vez su cuenta haya sido eliminada, no la podrá usar para tomar cursos en la app de edX, edx.org o en cualquier otro sitio administrado por edX. Esto incluye el acceso a edx.org desde el sistema de su empleador o universidad y el acceso a páginas privadas ofrecidas por MIT Open Learning, Wharton Executive Education y Harvard Medical School.",
|
||||
"account.settings.delete.account.text.2.edX": "Once your account is deleted, you cannot use it to take courses on the edX app, edx.org, or any other site hosted by edX. This includes access to edx.org from your employer’s or university’s system and access to private sites offered by MIT Open Learning, Wharton Executive Education, and Harvard Medical School.",
|
||||
"account.settings.delete.account.text.3.link": "Follow these instructions for printing or downloading a certificate",
|
||||
"account.settings.delete.account.text.warning": "Warning: Account deletion is permanent. Please read the above carefully before proceeding. This is an irreversible action, and you will no longer be able to use the same email on {siteName}.",
|
||||
"account.settings.delete.account.text.change.instead": "En lugar de eso, ¿quieres cambiar tu correo electrónico, nombre o contraseña?",
|
||||
@@ -124,7 +113,7 @@
|
||||
"account.settings.delete.account.modal.header": "¿Está seguro?",
|
||||
"account.settings.delete.account.modal.text.1": "You have selected \"Delete My Account\". Deletion of your account and personal data is permanent and cannot be undone. {siteName} will not be able to recover your account or the data that is deleted.",
|
||||
"account.settings.delete.account.modal.text.2": "If you proceed, you will be unable to use this account to take courses on {siteName}.",
|
||||
"account.settings.delete.account.modal.text.2.edX": "Si procedes, no será posible usar esta cuenta para tomar cursos ni en la aplicación móvil de edX, ni en edx.org, ni en cualquier otro sitio hospedado por edX. Esto incluye el acceso a edx.org desde el sistema de tu empleador o universidad, y el acceso a sitios privados ofrecidos por MIT Open Learning, Wharton Executive Education, y Harvard Medical School.",
|
||||
"account.settings.delete.account.modal.text.2.edX": "If you proceed, you will be unable to use this account to take courses on the edX app, edx.org, or any other site hosted by edX. This includes access to edx.org from your employer's or university's system and access to private sites offered by MIT Open Learning, Wharton Executive Education, and Harvard Medical School.",
|
||||
"account.settings.delete.account.modal.enter.password": "Si deseas continuar y eliminar tu cuenta, por favor introduce la contraseña de tu cuenta:",
|
||||
"account.settings.delete.account.modal.confirm.delete": "Si, Eliminar",
|
||||
"account.settings.delete.account.modal.confirm.cancel": "Cancelar",
|
||||
@@ -181,7 +170,7 @@
|
||||
"account.settings.sso.no.providers": "No se pueden vincular cuentas en este momento.",
|
||||
"id.verification.access.blocked.denied": "No puedes verificar tu identidad en este momento. Si aún tienes que activar tu cuenta, revisa tu carpeta de correo no deseado y busca el correo electrónico de activación de {email}.",
|
||||
"id.verification.next": "Siguiente",
|
||||
"id.verification.support": "soporte",
|
||||
"id.verification.support": "support",
|
||||
"id.verification.continue.upload": "Continue with Upload",
|
||||
"id.verification.example.card.alt": "Ejemplo de un documento de identidad válido con foto y nombre completo.",
|
||||
"id.verification.requirements.title": "Requerimientos de verificación por foto",
|
||||
@@ -199,7 +188,7 @@
|
||||
"id.verification.access.blocked.enrollment": "Actualmente, no estás inscrito en un curso que requiera verificación de identidad.",
|
||||
"id.verification.access.blocked.pending": "Ya has enviado tu información de verificación de identidad. Recibirás un mensaje en tu panel principal cuando el proceso de verificación esté completado (usualmente dentro de los 5 días).",
|
||||
"id.verification.photo.take": "Tomar la foto",
|
||||
"id.verification.photo.retake": "¿Tomar nuevamente la foto?",
|
||||
"id.verification.photo.retake": "Retake Photo?",
|
||||
"id.verification.photo.enable.detection": "Habilitar la detección de rostro",
|
||||
"id.verification.photo.enable.detection.portrait.help.text": "Si está marcada, aparecerá un cuadro alrededor de tu cara. Tu rostro se puede ver claramente si el cuadro que lo rodea es azul. Si Tu cara no está en una buena posición o es indetectable, el cuadro será rojo.",
|
||||
"id.verification.photo.enable.detection.id.help.text": "Si está marcada, aparecerá una casilla alrededor de la cara de tu documento de identificación. La cara se puede ver claramente si la caja que la rodea es azul. Si la cara no está en una buena posición o es indetectable, el cuadro será rojo.",
|
||||
@@ -283,7 +272,7 @@
|
||||
"id.verification.id.photo.instructions.camera": "Cuando tu identificación esté en su lugar, usa el botón Tomar foto a continuación para tomar tu foto.",
|
||||
"id.verification.id.photo.instructions.upload": "Please upload an ID photo. Ensure the entire ID fits inside the frame and is well-lit. The file size must be under 10 MB. Supported formats: ",
|
||||
"id.verification.id.photo.instructions.upload.error.invalidFileType": "The file you have selected is not a supported image type. Please choose from the following formats: ",
|
||||
"id.verification.id.photo.instructions.upload.error.fileTooLarge": "El archivo que has seleccionado es demasiado grande. Vuelve a intentarlo con un archivo de menos de 10 MB.",
|
||||
"id.verification.id.photo.instructions.upload.error.fileTooLarge": "The file you have selected is too large. Please try again with a file less than 10MB.",
|
||||
"id.verification.account.name.title": "Verificación de nombre de cuenta",
|
||||
"id.verification.account.name.instructions": "El nombre de tu cuenta y el nombre de tu identificación deben coincidir exactamente. De lo contrario, haz clic en \"No\" para actualizar el nombre de tu cuenta.",
|
||||
"id.verification.account.name.radio.label": "¿El nombre de tu identificación coincide con el nombre de la cuenta a continuación?",
|
||||
@@ -329,5 +318,5 @@
|
||||
"id.verification.requirements.card.device.text": "Necesitas un dispositivo que tenga una cámara. Si has recibido un aviso del navegador para habilitar acceso a tu cámara, por favor asegúrate de seleccionar [allow].",
|
||||
"id.verification.account.name.summary.alert": "Your account settings are managed by {managerTitle}. If the name on your photo ID does not match the name on your account, please contact your {profileDataManager} administrator or {support} for help.",
|
||||
"idv.submission.alert.error": "\n Se produjo un error técnico al intentar enviar la verificación de ID.\n Es posible que sea una cuestión temporal, así que inténtalo de nuevo en unos minutos.\n Si el problema continúa, dirígete a {support_link} para obtener ayuda.\n ",
|
||||
"id.verification.account.name.edit": "Editar {sr}"
|
||||
"id.verification.account.name.edit": "Edit {sr}"
|
||||
}
|
||||
@@ -20,17 +20,6 @@
|
||||
"account.settings.field.full.name": "Full name",
|
||||
"account.settings.field.full.name.empty": "Add name",
|
||||
"account.settings.field.full.name.help.text": "The name that is used for ID verification and that appears on your certificates.",
|
||||
"account.settings.field.name.verified": "Verified name",
|
||||
"account.settings.field.name.verified.help.text.verified": "This name has been verified by government ID.",
|
||||
"account.settings.field.name.verified.help.text.submitted": "Verification has been submitted. This usually takes 48 hours or less. Verified name cannot be changed at this time.",
|
||||
"account.settings.field.full.name.help.text.submitted": "When identity verification is successful, this name will appear on your certificates and public-facing records. Full name cannot be changed at this time.",
|
||||
"account.settings.field.name.verified.success.message": "Your identity verification request has successfully completed. You now have the option of selecting which name you prefer to appear on your certificates and public-records.",
|
||||
"account.settings.field.name.verified.success.message.header": "Your name change request is complete!",
|
||||
"account.settings.field.name.verified.failure.message": "Your Verified name change attempt, “{verifiedName}”, did not pass ID verification. Your previous Verified name settings have been restored.",
|
||||
"account.settings.field.name.verified.failure.message.header": "We were not able to verify your identity.",
|
||||
"account.settings.field.name.verified.failure.message.help.link": "Learn more about ID verification",
|
||||
"account.settings.field.name.verified.submitted.message": "Your identity verification request has been submitted and usually takes between 24 and 48 hours to complete. When your request is approved, your updated name will appear on all associated certificates and public-facing records.",
|
||||
"account.settings.field.name.verified.submitted.message.header": "Your name change request is almost complete!",
|
||||
"account.settings.field.email": "Email address (Sign in)",
|
||||
"account.settings.field.email.empty": "Add email address",
|
||||
"account.settings.field.email.confirmation": "We’ve sent a confirmation message to {value}. Click the link in the message to update your email address.",
|
||||
|
||||
@@ -20,17 +20,6 @@
|
||||
"account.settings.field.full.name": "Full name",
|
||||
"account.settings.field.full.name.empty": "Add name",
|
||||
"account.settings.field.full.name.help.text": "The name that is used for ID verification and that appears on your certificates.",
|
||||
"account.settings.field.name.verified": "Verified name",
|
||||
"account.settings.field.name.verified.help.text.verified": "This name has been verified by government ID.",
|
||||
"account.settings.field.name.verified.help.text.submitted": "Verification has been submitted. This usually takes 48 hours or less. Verified name cannot be changed at this time.",
|
||||
"account.settings.field.full.name.help.text.submitted": "When identity verification is successful, this name will appear on your certificates and public-facing records. Full name cannot be changed at this time.",
|
||||
"account.settings.field.name.verified.success.message": "Your identity verification request has successfully completed. You now have the option of selecting which name you prefer to appear on your certificates and public-records.",
|
||||
"account.settings.field.name.verified.success.message.header": "Your name change request is complete!",
|
||||
"account.settings.field.name.verified.failure.message": "Your Verified name change attempt, “{verifiedName}”, did not pass ID verification. Your previous Verified name settings have been restored.",
|
||||
"account.settings.field.name.verified.failure.message.header": "We were not able to verify your identity.",
|
||||
"account.settings.field.name.verified.failure.message.help.link": "Learn more about ID verification",
|
||||
"account.settings.field.name.verified.submitted.message": "Your identity verification request has been submitted and usually takes between 24 and 48 hours to complete. When your request is approved, your updated name will appear on all associated certificates and public-facing records.",
|
||||
"account.settings.field.name.verified.submitted.message.header": "Your name change request is almost complete!",
|
||||
"account.settings.field.email": "Email address (Sign in)",
|
||||
"account.settings.field.email.empty": "Add email address",
|
||||
"account.settings.field.email.confirmation": "We’ve sent a confirmation message to {value}. Click the link in the message to update your email address.",
|
||||
|
||||
@@ -2,7 +2,7 @@ import React, { useState, useContext, useEffect } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { AppContext } from '@edx/frontend-platform/react';
|
||||
|
||||
import { getProfileDataManager, getVerifiedName } from '../account-settings/data/service';
|
||||
import { getProfileDataManager } from '../account-settings/data/service';
|
||||
import PageLoading from '../account-settings/PageLoading';
|
||||
|
||||
import { getExistingIdVerification, getEnrollments } from './data/service';
|
||||
@@ -76,19 +76,6 @@ export default function IdVerificationContextProvider({ children }) {
|
||||
}
|
||||
}, [authenticatedUser]);
|
||||
|
||||
const [verifiedName, setVerifiedName] = useState('');
|
||||
useEffect(() => {
|
||||
// Make the API call to retrieve VerifiedName of the learner.
|
||||
// If the learner do not have such attribute from their account, that's OK.
|
||||
// If the learner do have the attribute, the VerifiedName is overriding authenticatedUser.name
|
||||
(async () => {
|
||||
const verifiedNameResponse = await getVerifiedName();
|
||||
if (verifiedNameResponse) {
|
||||
setVerifiedName(verifiedNameResponse.verified_name);
|
||||
}
|
||||
})();
|
||||
}, []);
|
||||
|
||||
const [optimizelyExperimentName, setOptimizelyExperimentName] = useState('');
|
||||
const [shouldUseCamera, setShouldUseCamera] = useState(false);
|
||||
|
||||
@@ -108,7 +95,7 @@ export default function IdVerificationContextProvider({ children }) {
|
||||
mediaStream,
|
||||
mediaAccess,
|
||||
userId: authenticatedUser.userId,
|
||||
nameOnAccount: verifiedName || authenticatedUser.name,
|
||||
nameOnAccount: authenticatedUser.name,
|
||||
profileDataManager,
|
||||
optimizelyExperimentName,
|
||||
shouldUseCamera,
|
||||
|
||||
@@ -146,15 +146,9 @@ function GetNameIdPanel(props) {
|
||||
onChange={e => setIdPhotoName(e.target.value)}
|
||||
data-testid="name-input"
|
||||
/>
|
||||
{(invalidName || profileDataManager) && (
|
||||
<Form.Control.Feedback
|
||||
id="photo-id-name-feedback"
|
||||
data-testid="id-name-feedback-message"
|
||||
type="invalid"
|
||||
>
|
||||
{getErrorMessage()}
|
||||
</Form.Control.Feedback>
|
||||
)}
|
||||
<Form.Control.Feedback id="photo-id-name-feedback" type="invalid">
|
||||
{getErrorMessage()}
|
||||
</Form.Control.Feedback>
|
||||
</Form.Group>
|
||||
</Form>
|
||||
|
||||
|
||||
@@ -5,14 +5,13 @@ import '@testing-library/jest-dom/extend-expect';
|
||||
import { IntlProvider } from '@edx/frontend-platform/i18n';
|
||||
import { AppContext } from '@edx/frontend-platform/react';
|
||||
|
||||
import { getProfileDataManager, getVerifiedName } from '../../account-settings/data/service';
|
||||
import { getProfileDataManager } from '../../account-settings/data/service';
|
||||
|
||||
import { getExistingIdVerification, getEnrollments } from '../data/service';
|
||||
import IdVerificationContextProvider from '../IdVerificationContextProvider';
|
||||
|
||||
jest.mock('../../account-settings/data/service', () => ({
|
||||
getProfileDataManager: jest.fn(),
|
||||
getVerifiedName: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('../data/service', () => ({
|
||||
@@ -63,16 +62,4 @@ describe('IdVerificationContextProvider', () => {
|
||||
context.authenticatedUser.roles,
|
||||
);
|
||||
});
|
||||
|
||||
it('calls getVerifiedName', async () => {
|
||||
const context = { authenticatedUser: { userId: 3, roles: [] } };
|
||||
await act(async () => render((
|
||||
<AppContext.Provider value={context}>
|
||||
<IntlProvider locale="en">
|
||||
<IdVerificationContextProvider {...defaultProps} />
|
||||
</IntlProvider>
|
||||
</AppContext.Provider>
|
||||
)));
|
||||
expect(getVerifiedName).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -54,10 +54,8 @@ describe('GetNameIdPanel', () => {
|
||||
const noButton = await screen.findByTestId('name-matches-no');
|
||||
const input = await screen.findByTestId('name-input');
|
||||
const nextButton = await screen.findByTestId('next-button');
|
||||
const errorMessageQuery = await screen.queryByTestId('id-name-feedback-message');
|
||||
|
||||
expect(input).toHaveProperty('readOnly');
|
||||
expect(errorMessageQuery).toBeNull();
|
||||
|
||||
fireEvent.click(noButton);
|
||||
expect(input).toHaveProperty('readOnly', false);
|
||||
@@ -65,8 +63,6 @@ describe('GetNameIdPanel', () => {
|
||||
|
||||
fireEvent.change(input, { target: { value: 'test change' } });
|
||||
expect(contextValue.setIdPhotoName).toHaveBeenCalled();
|
||||
// Ensure the feedback message on name shows when the user says the name does not match ID
|
||||
expect(await screen.queryByTestId('id-name-feedback-message')).toBeTruthy();
|
||||
|
||||
fireEvent.click(yesButton);
|
||||
expect(input).toHaveProperty('readOnly');
|
||||
@@ -81,13 +77,11 @@ describe('GetNameIdPanel', () => {
|
||||
const noButton = await screen.findByTestId('name-matches-no');
|
||||
const input = await screen.findByTestId('name-input');
|
||||
const nextButton = await screen.findByTestId('next-button');
|
||||
const errorMessageQuery = await screen.queryByTestId('id-name-feedback-message');
|
||||
|
||||
expect(yesButton).toHaveProperty('disabled');
|
||||
expect(noButton).toHaveProperty('disabled');
|
||||
expect(input).toHaveProperty('readOnly', false);
|
||||
expect(nextButton.classList.contains('disabled')).toBe(true);
|
||||
expect(errorMessageQuery).toBeTruthy();
|
||||
});
|
||||
|
||||
it('blocks the user from changing account name if managed by a third party', async () => {
|
||||
|
||||
Reference in New Issue
Block a user