Add stateful buttons on forms (#37)
Add stateful button component from paragon to - LoginPage - RegistrationPage - ForgetPasswordPage - ResetPasswordPage VAN-123
This commit is contained in:
@@ -6,3 +6,7 @@ export const DEFAULT_REDIRECT_URL = '/dashboard';
|
||||
|
||||
// Constants
|
||||
export const SUPPORTED_ICON_CLASSES = ['apple', 'facebook', 'google', 'microsoft'];
|
||||
|
||||
// Stateful Submit Button States
|
||||
export const DEFAULT_STATE = 'default';
|
||||
export const PENDING_STATE = 'pending';
|
||||
|
||||
@@ -2,13 +2,14 @@ import React, { useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
import { Redirect } from 'react-router-dom';
|
||||
import { Button, Input, ValidationFormGroup } from '@edx/paragon';
|
||||
import { Input, StatefulButton, ValidationFormGroup } from '@edx/paragon';
|
||||
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import messages from './messages';
|
||||
import { forgotPassword } from './data/actions';
|
||||
import { forgotPasswordResultSelector } from './data/selectors';
|
||||
import RequestInProgressAlert from './RequestInProgressAlert';
|
||||
import { LOGIN_PAGE } from '../data/constants';
|
||||
import LoginHelpLinks from '../logistration/LoginHelpLinks';
|
||||
|
||||
const ForgotPasswordPage = (props) => {
|
||||
@@ -39,7 +40,7 @@ const ForgotPasswordPage = (props) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
{status === 'complete' ? <Redirect to="/login" /> : null}
|
||||
{status === 'complete' ? <Redirect to={LOGIN_PAGE} /> : null}
|
||||
<div className="d-flex justify-content-center forgot-password-container">
|
||||
<div className="d-flex flex-column" style={{ width: '450px' }}>
|
||||
<form className="m-4">
|
||||
@@ -79,12 +80,15 @@ const ForgotPasswordPage = (props) => {
|
||||
</p>
|
||||
<LoginHelpLinks page="forgot-password" />
|
||||
</div>
|
||||
<Button
|
||||
<StatefulButton
|
||||
type="submit"
|
||||
className="btn-primary submit"
|
||||
state={status}
|
||||
labels={{
|
||||
default: intl.formatMessage(messages['logisration.forgot.password.page.submit.button']),
|
||||
}}
|
||||
onClick={e => handleSubmit(e)}
|
||||
>
|
||||
{intl.formatMessage(messages['logisration.forgot.password.page.submit.button'])}
|
||||
</Button>
|
||||
/>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -49,6 +49,16 @@ describe('ForgotPasswordPage', () => {
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match pending section snapshot', () => {
|
||||
props = {
|
||||
...props,
|
||||
status: 'pending',
|
||||
};
|
||||
const tree = renderer.create(reduxWrapper(<IntlForgotPasswordPage {...props} />))
|
||||
.toJSON();
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match success section snapshot', () => {
|
||||
props = {
|
||||
...props,
|
||||
|
||||
@@ -110,12 +110,18 @@ exports[`ForgotPasswordPage should match default section snapshot 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
className="btn-primary submit btn btn-primary"
|
||||
aria-disabled={false}
|
||||
aria-live="assertive"
|
||||
className="pgn__stateful-btn pgn__stateful-btn-state-null btn-primary submit btn btn-primary"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
type="submit"
|
||||
>
|
||||
Recover my password
|
||||
<span
|
||||
className="d-flex align-items-center justify-content-center"
|
||||
>
|
||||
Recover my password
|
||||
</span>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
@@ -260,12 +266,155 @@ exports[`ForgotPasswordPage should match forbidden section snapshot 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
className="btn-primary submit btn btn-primary"
|
||||
aria-disabled={false}
|
||||
aria-live="assertive"
|
||||
className="pgn__stateful-btn pgn__stateful-btn-state-forbidden btn-primary submit btn btn-primary"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
type="submit"
|
||||
>
|
||||
Recover my password
|
||||
<span
|
||||
className="d-flex align-items-center justify-content-center"
|
||||
>
|
||||
Recover my password
|
||||
</span>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`ForgotPasswordPage should match pending section snapshot 1`] = `
|
||||
<div
|
||||
className="d-flex justify-content-center forgot-password-container"
|
||||
>
|
||||
<div
|
||||
className="d-flex flex-column"
|
||||
style={
|
||||
Object {
|
||||
"width": "450px",
|
||||
}
|
||||
}
|
||||
>
|
||||
<form
|
||||
className="m-4"
|
||||
>
|
||||
<div
|
||||
className="form-group"
|
||||
>
|
||||
<h3
|
||||
className="text-center mt-3"
|
||||
>
|
||||
Password assistance
|
||||
</h3>
|
||||
<p
|
||||
className="mb-4"
|
||||
>
|
||||
Please enter your log-in or recovery email address below and we will send you an email with instructions.
|
||||
</p>
|
||||
<div
|
||||
className="d-flex flex-column align-items-start"
|
||||
>
|
||||
<div
|
||||
className="form-group mb-0"
|
||||
>
|
||||
<label
|
||||
className="h6 mr-1"
|
||||
htmlFor="forgot-password-input"
|
||||
>
|
||||
Email
|
||||
</label>
|
||||
<input
|
||||
aria-describedby=""
|
||||
className="form-control"
|
||||
id="forgot-password-input"
|
||||
name="email"
|
||||
onChange={[Function]}
|
||||
placeholder="username@domain.com"
|
||||
style={
|
||||
Object {
|
||||
"width": "400px",
|
||||
}
|
||||
}
|
||||
type="email"
|
||||
value=""
|
||||
/>
|
||||
<strong
|
||||
className="invalid-feedback"
|
||||
id="email-invalid-feedback"
|
||||
>
|
||||
The email address you've provided isn't formatted correctly.
|
||||
</strong>
|
||||
</div>
|
||||
</div>
|
||||
<p
|
||||
className="mb-2"
|
||||
>
|
||||
The email address you used to register with edX.
|
||||
</p>
|
||||
<button
|
||||
className="mt-1 field-link"
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
className="svg-inline--fa fa-caret-right fa-w-6 mr-1"
|
||||
data-icon="caret-right"
|
||||
data-prefix="fas"
|
||||
focusable="false"
|
||||
role="img"
|
||||
style={Object {}}
|
||||
viewBox="0 0 192 512"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M0 384.662V127.338c0-17.818 21.543-26.741 34.142-14.142l128.662 128.662c7.81 7.81 7.81 20.474 0 28.284L34.142 398.804C21.543 411.404 0 402.48 0 384.662z"
|
||||
fill="currentColor"
|
||||
style={Object {}}
|
||||
/>
|
||||
</svg>
|
||||
Need other help signing in?
|
||||
</button>
|
||||
<div
|
||||
className="pgn-transition-replace-group position-relative"
|
||||
style={
|
||||
Object {
|
||||
"height": null,
|
||||
}
|
||||
}
|
||||
>
|
||||
<div
|
||||
style={
|
||||
Object {
|
||||
"padding": ".1px 0",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
aria-disabled={true}
|
||||
aria-live="assertive"
|
||||
className="pgn__stateful-btn pgn__stateful-btn-state-pending btn-primary submit disabled btn btn-primary"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
type="submit"
|
||||
>
|
||||
<span
|
||||
className="d-flex align-items-center justify-content-center"
|
||||
>
|
||||
<span
|
||||
className="pgn__stateful-btn-icon"
|
||||
>
|
||||
<span
|
||||
aria-hidden={true}
|
||||
className="icon fa fa-spinner fa-spin"
|
||||
id="Icon1"
|
||||
/>
|
||||
</span>
|
||||
Recover my password
|
||||
</span>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -1,22 +1,23 @@
|
||||
import React from 'react';
|
||||
|
||||
import { Button, Input, ValidationFormGroup } from '@edx/paragon';
|
||||
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
import { Input, StatefulButton, ValidationFormGroup } from '@edx/paragon';
|
||||
import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import { forgotPasswordResultSelector } from '../forgot-password';
|
||||
import ConfirmationAlert from './ConfirmationAlert';
|
||||
import { getThirdPartyAuthContext, loginRequest } from './data/actions';
|
||||
import { DEFAULT_REDIRECT_URL, REGISTER_PAGE } from '../data/constants';
|
||||
import { loginRequestSelector, thirdPartyAuthContextSelector } from './data/selectors';
|
||||
import InstitutionLogistration, { RenderInstitutionButton } from './InstitutionLogistration';
|
||||
import LoginHelpLinks from './LoginHelpLinks';
|
||||
import LoginFailureMessage from './LoginFailure';
|
||||
import messages from './messages';
|
||||
import RedirectLogistration from './RedirectLogistration';
|
||||
import SocialAuthProviders from './SocialAuthProviders';
|
||||
import ThirdPartyAuthAlert from './ThirdPartyAuthAlert';
|
||||
import InstitutionLogistration, { RenderInstitutionButton } from './InstitutionLogistration';
|
||||
import messages from './messages';
|
||||
|
||||
import { DEFAULT_REDIRECT_URL, DEFAULT_STATE, REGISTER_PAGE } from '../data/constants';
|
||||
import { forgotPasswordResultSelector } from '../forgot-password';
|
||||
|
||||
class LoginPage extends React.Component {
|
||||
constructor(props, context) {
|
||||
@@ -111,13 +112,13 @@ class LoginPage extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { intl } = this.props;
|
||||
const { currentProvider, finishAuthUrl, providers } = this.props.thirdPartyAuthContext;
|
||||
const { intl, submitState, thirdPartyAuthContext } = this.props;
|
||||
|
||||
if (this.state.institutionLogin) {
|
||||
return (
|
||||
<InstitutionLogistration
|
||||
onSubmitHandler={this.handleInstitutionLogin}
|
||||
secondaryProviders={this.props.thirdPartyAuthContext.secondaryProviders}
|
||||
secondaryProviders={thirdPartyAuthContext.secondaryProviders}
|
||||
headingTitle={intl.formatMessage(messages['logistration.login.institution.login.page.title'])}
|
||||
buttonTitle={intl.formatMessage(messages['logistration.login.institution.login.page.back.button'])}
|
||||
/>
|
||||
@@ -128,15 +129,15 @@ class LoginPage extends React.Component {
|
||||
<RedirectLogistration
|
||||
success={this.props.loginResult.success}
|
||||
redirectUrl={this.props.loginResult.redirectUrl}
|
||||
finishAuthUrl={finishAuthUrl}
|
||||
finishAuthUrl={thirdPartyAuthContext.finishAuthUrl}
|
||||
/>
|
||||
<div className="d-flex justify-content-center login-container">
|
||||
<div className="d-flex flex-column" style={{ width: '400px' }}>
|
||||
{currentProvider
|
||||
{thirdPartyAuthContext.currentProvider
|
||||
&& (
|
||||
<ThirdPartyAuthAlert
|
||||
currentProvider={currentProvider}
|
||||
platformName={this.props.thirdPartyAuthContext.platformName}
|
||||
currentProvider={thirdPartyAuthContext.currentProvider}
|
||||
platformName={thirdPartyAuthContext.platformName}
|
||||
/>
|
||||
)}
|
||||
{this.props.loginError ? <LoginFailureMessage errors={this.props.loginError} /> : null}
|
||||
@@ -146,15 +147,21 @@ class LoginPage extends React.Component {
|
||||
First time here?<a className="ml-1" href={REGISTER_PAGE}>Create an Account.</a>
|
||||
</p>
|
||||
</div>
|
||||
<h3 className="text-left mt-3">{intl.formatMessage(messages['logistration.login.institution.login.sign.in'])}</h3>
|
||||
<RenderInstitutionButton
|
||||
onSubmitHandler={this.handleInstitutionLogin}
|
||||
secondaryProviders={this.props.thirdPartyAuthContext.secondaryProviders}
|
||||
buttonTitle={intl.formatMessage(messages['logistration.login.institution.login.button'])}
|
||||
/>
|
||||
<div className="section-heading-line mb-4">
|
||||
<h4>{intl.formatMessage(messages['logistration.login.institution.login.sign.in.with'])}</h4>
|
||||
</div>
|
||||
<h2 className="font-color text-left mt-2 mb-3">
|
||||
{intl.formatMessage(messages['logistration.login.institution.login.sign.in'])}
|
||||
</h2>
|
||||
{thirdPartyAuthContext.secondaryProviders.length ? (
|
||||
<>
|
||||
<RenderInstitutionButton
|
||||
onSubmitHandler={this.handleInstitutionLogin}
|
||||
secondaryProviders={thirdPartyAuthContext.secondaryProviders}
|
||||
buttonTitle={intl.formatMessage(messages['logistration.login.institution.login.button'])}
|
||||
/>
|
||||
<div className="section-heading-line mb-4">
|
||||
<h4>{intl.formatMessage(messages['logistration.login.institution.login.sign.in.with'])}</h4>
|
||||
</div>
|
||||
</>
|
||||
) : null }
|
||||
<form className="m-0">
|
||||
<div className="form-group">
|
||||
<div className="d-flex flex-column align-items-start">
|
||||
@@ -196,20 +203,23 @@ class LoginPage extends React.Component {
|
||||
</div>
|
||||
<LoginHelpLinks page="login" />
|
||||
</div>
|
||||
<Button
|
||||
<StatefulButton
|
||||
type="submit"
|
||||
className="btn-primary submit"
|
||||
state={submitState}
|
||||
labels={{
|
||||
default: intl.formatMessage(messages['logistration.sign.in.button']),
|
||||
}}
|
||||
onClick={this.handleSubmit}
|
||||
>
|
||||
Sign in
|
||||
</Button>
|
||||
/>
|
||||
</form>
|
||||
{providers.length && !currentProvider ? (
|
||||
{thirdPartyAuthContext.providers.length && !thirdPartyAuthContext.currentProvider ? (
|
||||
<>
|
||||
<div className="section-heading-line mb-4">
|
||||
<h4>or sign in with</h4>
|
||||
</div>
|
||||
<div className="row tpa-container">
|
||||
<SocialAuthProviders socialAuthProviders={providers} />
|
||||
<SocialAuthProviders socialAuthProviders={thirdPartyAuthContext.providers} />
|
||||
</div>
|
||||
</>
|
||||
) : null}
|
||||
@@ -221,28 +231,32 @@ class LoginPage extends React.Component {
|
||||
}
|
||||
|
||||
LoginPage.defaultProps = {
|
||||
loginResult: null,
|
||||
forgotPassword: null,
|
||||
loginResult: null,
|
||||
loginError: null,
|
||||
submitState: DEFAULT_STATE,
|
||||
thirdPartyAuthContext: {
|
||||
currentProvider: null,
|
||||
finishAuthUrl: null,
|
||||
providers: [],
|
||||
secondaryProviders: [],
|
||||
},
|
||||
};
|
||||
|
||||
LoginPage.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
forgotPassword: PropTypes.shape({
|
||||
email: PropTypes.string,
|
||||
status: PropTypes.string,
|
||||
}),
|
||||
getThirdPartyAuthContext: PropTypes.func.isRequired,
|
||||
intl: intlShape.isRequired,
|
||||
loginError: PropTypes.string,
|
||||
loginRequest: PropTypes.func.isRequired,
|
||||
loginResult: PropTypes.shape({
|
||||
redirectUrl: PropTypes.string,
|
||||
success: PropTypes.bool,
|
||||
}),
|
||||
forgotPassword: PropTypes.shape({
|
||||
email: PropTypes.string,
|
||||
status: PropTypes.string,
|
||||
}),
|
||||
submitState: PropTypes.string,
|
||||
thirdPartyAuthContext: PropTypes.shape({
|
||||
currentProvider: PropTypes.string,
|
||||
platformName: PropTypes.string,
|
||||
@@ -250,7 +264,6 @@ LoginPage.propTypes = {
|
||||
secondaryProviders: PropTypes.array,
|
||||
finishAuthUrl: PropTypes.string,
|
||||
}),
|
||||
loginError: PropTypes.string,
|
||||
};
|
||||
|
||||
const mapStateToProps = state => {
|
||||
@@ -258,10 +271,11 @@ const mapStateToProps = state => {
|
||||
const loginResult = loginRequestSelector(state);
|
||||
const thirdPartyAuthContext = thirdPartyAuthContextSelector(state);
|
||||
return {
|
||||
loginError: state.logistration.loginError,
|
||||
submitState: state.logistration.submitState,
|
||||
forgotPassword,
|
||||
loginResult,
|
||||
thirdPartyAuthContext,
|
||||
loginError: state.logistration.loginError,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
Button, Input, ValidationFormGroup,
|
||||
} from '@edx/paragon';
|
||||
import { Input, StatefulButton, ValidationFormGroup } from '@edx/paragon';
|
||||
import {
|
||||
getLocale, getCountryList, injectIntl, intlShape,
|
||||
} from '@edx/frontend-platform/i18n';
|
||||
@@ -12,7 +10,9 @@ import { getThirdPartyAuthContext, registerNewUser } from './data/actions';
|
||||
import { registrationRequestSelector, thirdPartyAuthContextSelector } from './data/selectors';
|
||||
import RedirectLogistration from './RedirectLogistration';
|
||||
import RegistrationFailure from './RegistrationFailure';
|
||||
import { DEFAULT_REDIRECT_URL, LOGIN_PAGE, REGISTER_PAGE } from '../data/constants';
|
||||
import {
|
||||
DEFAULT_REDIRECT_URL, DEFAULT_STATE, LOGIN_PAGE, REGISTER_PAGE,
|
||||
} from '../data/constants';
|
||||
import SocialAuthProviders from './SocialAuthProviders';
|
||||
import ThirdPartyAuthAlert from './ThirdPartyAuthAlert';
|
||||
import InstitutionLogistration, { RenderInstitutionButton } from './InstitutionLogistration';
|
||||
@@ -159,7 +159,7 @@ class RegistrationPage extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { intl } = this.props;
|
||||
const { intl, submitState } = this.props;
|
||||
const {
|
||||
currentProvider, finishAuthUrl, providers, secondaryProviders,
|
||||
} = this.props.thirdPartyAuthContext;
|
||||
@@ -295,12 +295,15 @@ class RegistrationPage extends React.Component {
|
||||
/>
|
||||
</ValidationFormGroup>
|
||||
<span>By creating an account, you agree to the <a href="https://www.edx.org/edx-terms-service">Terms of Service and Honor Code</a> and you acknowledge that edX and each Member process your personal data in accordance with the <a href="https://www.edx.org/edx-privacy-policy">Privacy Policy</a>.</span>
|
||||
<Button
|
||||
className="btn-primary mt-4 submit"
|
||||
<StatefulButton
|
||||
type="submit"
|
||||
className="btn-primary submit mt-4"
|
||||
state={submitState}
|
||||
labels={{
|
||||
default: intl.formatMessage(messages['logistration.create.account.button']),
|
||||
}}
|
||||
onClick={this.handleSubmit}
|
||||
>
|
||||
Create Account
|
||||
</Button>
|
||||
/>
|
||||
</form>
|
||||
</div>
|
||||
</>
|
||||
@@ -312,6 +315,7 @@ RegistrationPage.defaultProps = {
|
||||
registrationResult: null,
|
||||
registerNewUser: null,
|
||||
registrationError: null,
|
||||
submitState: DEFAULT_STATE,
|
||||
thirdPartyAuthContext: {
|
||||
currentProvider: null,
|
||||
finishAuthUrl: null,
|
||||
@@ -333,6 +337,7 @@ RegistrationPage.propTypes = {
|
||||
email: PropTypes.array,
|
||||
username: PropTypes.array,
|
||||
}),
|
||||
submitState: PropTypes.string,
|
||||
thirdPartyAuthContext: PropTypes.shape({
|
||||
currentProvider: PropTypes.string,
|
||||
platformName: PropTypes.string,
|
||||
@@ -353,8 +358,9 @@ const mapStateToProps = state => {
|
||||
const registrationResult = registrationRequestSelector(state);
|
||||
const thirdPartyAuthContext = thirdPartyAuthContextSelector(state);
|
||||
return {
|
||||
registrationResult,
|
||||
registrationError: state.logistration.registrationError,
|
||||
submitState: state.logistration.submitState,
|
||||
registrationResult,
|
||||
thirdPartyAuthContext,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -4,11 +4,13 @@ import {
|
||||
THIRD_PARTY_AUTH_CONTEXT,
|
||||
} from './actions';
|
||||
|
||||
import { DEFAULT_STATE, PENDING_STATE } from '../../data/constants';
|
||||
|
||||
export const defaultState = {
|
||||
registrationResult: {},
|
||||
loginError: null,
|
||||
loginResult: {},
|
||||
registrationError: null,
|
||||
loginError: null,
|
||||
registrationResult: {},
|
||||
};
|
||||
|
||||
const reducer = (state = defaultState, action) => {
|
||||
@@ -16,21 +18,23 @@ const reducer = (state = defaultState, action) => {
|
||||
case REGISTER_NEW_USER.BEGIN:
|
||||
return {
|
||||
...state,
|
||||
submitState: PENDING_STATE,
|
||||
};
|
||||
case REGISTER_NEW_USER.SUCCESS:
|
||||
return {
|
||||
...state,
|
||||
|
||||
registrationResult: action.payload,
|
||||
};
|
||||
case REGISTER_NEW_USER.FAILURE:
|
||||
return {
|
||||
...state,
|
||||
registrationError: action.payload.error,
|
||||
submitState: DEFAULT_STATE,
|
||||
};
|
||||
case LOGIN_REQUEST.BEGIN:
|
||||
return {
|
||||
...state,
|
||||
submitState: PENDING_STATE,
|
||||
};
|
||||
case LOGIN_REQUEST.SUCCESS:
|
||||
return {
|
||||
@@ -41,6 +45,7 @@ const reducer = (state = defaultState, action) => {
|
||||
return {
|
||||
...state,
|
||||
loginError: action.payload.loginError,
|
||||
submitState: DEFAULT_STATE,
|
||||
};
|
||||
case THIRD_PARTY_AUTH_CONTEXT.BEGIN:
|
||||
return {
|
||||
|
||||
@@ -2,6 +2,16 @@
|
||||
import { defineMessages } from '@edx/frontend-platform/i18n';
|
||||
|
||||
const messages = defineMessages({
|
||||
'logistration.sign.in.button': {
|
||||
id: 'logistration.sign.in.button',
|
||||
defaultMessage: 'Sign in',
|
||||
description: 'Button label that appears on login page',
|
||||
},
|
||||
'logistration.create.account.button': {
|
||||
id: 'ogistration.create.account.button',
|
||||
defaultMessage: 'Create Account',
|
||||
description: 'Button label that appears on register page',
|
||||
},
|
||||
'logistration.need.help.signing.in.collapsible.menu': {
|
||||
id: 'logistration.need.help.signing.in.collapsible.menu',
|
||||
defaultMessage: 'Need help signing in?',
|
||||
|
||||
@@ -8,6 +8,7 @@ import { getConfig } from '@edx/frontend-platform';
|
||||
import { IntlProvider, injectIntl } from '@edx/frontend-platform/i18n';
|
||||
import LoginPage from '../LoginPage';
|
||||
import { RenderInstitutionButton } from '../InstitutionLogistration';
|
||||
import { PENDING_STATE } from '../../data/constants';
|
||||
|
||||
const IntlLoginPage = injectIntl(LoginPage);
|
||||
const mockStore = configureStore();
|
||||
@@ -64,6 +65,20 @@ describe('LoginPage', () => {
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match pending button state snapshot', () => {
|
||||
store = mockStore({
|
||||
...initialState,
|
||||
logistration: {
|
||||
...initialState.logistration,
|
||||
submitState: PENDING_STATE,
|
||||
},
|
||||
});
|
||||
|
||||
const tree = renderer.create(reduxWrapper(<IntlLoginPage {...props} />))
|
||||
.toJSON();
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match forget password alert message snapshot', () => {
|
||||
props = {
|
||||
...props,
|
||||
@@ -79,6 +94,7 @@ describe('LoginPage', () => {
|
||||
logistration: {
|
||||
...initialState.logistration,
|
||||
thirdPartyAuthContext: {
|
||||
...initialState.logistration.thirdPartyAuthContext,
|
||||
providers: [appleProvider],
|
||||
},
|
||||
},
|
||||
@@ -184,6 +200,7 @@ describe('LoginPage', () => {
|
||||
logistration: {
|
||||
...initialState.logistration,
|
||||
thirdPartyAuthContext: {
|
||||
...initialState.logistration.thirdPartyAuthContext,
|
||||
providers: [{
|
||||
...appleProvider,
|
||||
loginUrl,
|
||||
|
||||
@@ -8,6 +8,7 @@ import { IntlProvider, injectIntl, configure } from '@edx/frontend-platform/i18n
|
||||
|
||||
import RegistrationPage from '../RegistrationPage';
|
||||
import { RenderInstitutionButton } from '../InstitutionLogistration';
|
||||
import { PENDING_STATE } from '../../data/constants';
|
||||
|
||||
const IntlRegistrationPage = injectIntl(RegistrationPage);
|
||||
const mockStore = configureStore();
|
||||
@@ -78,6 +79,19 @@ describe('./RegistrationPage.js', () => {
|
||||
expect(tree.toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match pending button state snapshot', () => {
|
||||
store = mockStore({
|
||||
...initialState,
|
||||
logistration: {
|
||||
...initialState.logistration,
|
||||
submitState: PENDING_STATE,
|
||||
},
|
||||
});
|
||||
|
||||
const tree = renderer.create(reduxWrapper(<IntlRegistrationPage {...props} />));
|
||||
expect(tree.toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match TPA provider snapshot', () => {
|
||||
store = mockStore({
|
||||
...initialState,
|
||||
|
||||
@@ -25,18 +25,11 @@ exports[`LoginPage should match TPA provider snapshot 1`] = `
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
<h3
|
||||
className="text-left mt-3"
|
||||
<h2
|
||||
className="font-color text-left mt-2 mb-3"
|
||||
>
|
||||
Sign In
|
||||
</h3>
|
||||
<div
|
||||
className="section-heading-line mb-4"
|
||||
>
|
||||
<h4>
|
||||
or sign in with
|
||||
</h4>
|
||||
</div>
|
||||
</h2>
|
||||
<form
|
||||
className="m-0"
|
||||
>
|
||||
@@ -159,12 +152,18 @@ exports[`LoginPage should match TPA provider snapshot 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
className="btn-primary submit btn btn-primary"
|
||||
aria-disabled={false}
|
||||
aria-live="assertive"
|
||||
className="pgn__stateful-btn pgn__stateful-btn-state-default btn-primary submit btn btn-primary"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
type="submit"
|
||||
>
|
||||
Sign in
|
||||
<span
|
||||
className="d-flex align-items-center justify-content-center"
|
||||
>
|
||||
Sign in
|
||||
</span>
|
||||
</button>
|
||||
</form>
|
||||
<div
|
||||
@@ -230,18 +229,11 @@ exports[`LoginPage should match default section snapshot 1`] = `
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
<h3
|
||||
className="text-left mt-3"
|
||||
<h2
|
||||
className="font-color text-left mt-2 mb-3"
|
||||
>
|
||||
Sign In
|
||||
</h3>
|
||||
<div
|
||||
className="section-heading-line mb-4"
|
||||
>
|
||||
<h4>
|
||||
or sign in with
|
||||
</h4>
|
||||
</div>
|
||||
</h2>
|
||||
<form
|
||||
className="m-0"
|
||||
>
|
||||
@@ -364,12 +356,18 @@ exports[`LoginPage should match default section snapshot 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
className="btn-primary submit btn btn-primary"
|
||||
aria-disabled={false}
|
||||
aria-live="assertive"
|
||||
className="pgn__stateful-btn pgn__stateful-btn-state-default btn-primary submit btn btn-primary"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
type="submit"
|
||||
>
|
||||
Sign in
|
||||
<span
|
||||
className="d-flex align-items-center justify-content-center"
|
||||
>
|
||||
Sign in
|
||||
</span>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
@@ -401,18 +399,11 @@ exports[`LoginPage should match forget password alert message snapshot 1`] = `
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
<h3
|
||||
className="text-left mt-3"
|
||||
<h2
|
||||
className="font-color text-left mt-2 mb-3"
|
||||
>
|
||||
Sign In
|
||||
</h3>
|
||||
<div
|
||||
className="section-heading-line mb-4"
|
||||
>
|
||||
<h4>
|
||||
or sign in with
|
||||
</h4>
|
||||
</div>
|
||||
</h2>
|
||||
<form
|
||||
className="m-0"
|
||||
>
|
||||
@@ -535,12 +526,197 @@ exports[`LoginPage should match forget password alert message snapshot 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
className="btn-primary submit btn btn-primary"
|
||||
aria-disabled={false}
|
||||
aria-live="assertive"
|
||||
className="pgn__stateful-btn pgn__stateful-btn-state-default btn-primary submit btn btn-primary"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
type="submit"
|
||||
>
|
||||
Sign in
|
||||
<span
|
||||
className="d-flex align-items-center justify-content-center"
|
||||
>
|
||||
Sign in
|
||||
</span>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`LoginPage should match pending button state snapshot 1`] = `
|
||||
<div
|
||||
className="d-flex justify-content-center login-container"
|
||||
>
|
||||
<div
|
||||
className="d-flex flex-column"
|
||||
style={
|
||||
Object {
|
||||
"width": "400px",
|
||||
}
|
||||
}
|
||||
>
|
||||
<div
|
||||
className="d-flex flex-row"
|
||||
>
|
||||
<p>
|
||||
First time here?
|
||||
<a
|
||||
className="ml-1"
|
||||
href="/register"
|
||||
>
|
||||
Create an Account.
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
<h2
|
||||
className="font-color text-left mt-2 mb-3"
|
||||
>
|
||||
Sign In
|
||||
</h2>
|
||||
<form
|
||||
className="m-0"
|
||||
>
|
||||
<div
|
||||
className="form-group"
|
||||
>
|
||||
<div
|
||||
className="d-flex flex-column align-items-start"
|
||||
>
|
||||
<div
|
||||
className="form-group"
|
||||
>
|
||||
<label
|
||||
className="h6 mr-1"
|
||||
htmlFor="loginEmail"
|
||||
>
|
||||
Email
|
||||
</label>
|
||||
<input
|
||||
aria-describedby=""
|
||||
className="form-control"
|
||||
id="loginEmail"
|
||||
name="email"
|
||||
onChange={[Function]}
|
||||
placeholder="username@domain.com"
|
||||
style={
|
||||
Object {
|
||||
"width": "400px",
|
||||
}
|
||||
}
|
||||
type="email"
|
||||
value=""
|
||||
/>
|
||||
<strong
|
||||
className="invalid-feedback"
|
||||
id="email-invalid-feedback"
|
||||
>
|
||||
The email address you've provided isn't formatted correctly.
|
||||
</strong>
|
||||
</div>
|
||||
</div>
|
||||
<p
|
||||
className="mb-4"
|
||||
>
|
||||
The email address you used to register with edX.
|
||||
</p>
|
||||
<div
|
||||
className="d-flex flex-column align-items-start"
|
||||
>
|
||||
<div
|
||||
className="form-group mb-0"
|
||||
>
|
||||
<label
|
||||
className="h6 mr-1"
|
||||
htmlFor="loginPassword"
|
||||
>
|
||||
Password
|
||||
</label>
|
||||
<input
|
||||
aria-describedby=""
|
||||
className="form-control"
|
||||
id="loginPassword"
|
||||
name="password"
|
||||
onChange={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"width": "400px",
|
||||
}
|
||||
}
|
||||
type="password"
|
||||
value=""
|
||||
/>
|
||||
<strong
|
||||
className="invalid-feedback"
|
||||
id="password-invalid-feedback"
|
||||
>
|
||||
Please enter your password.
|
||||
</strong>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
className="mt-1 field-link"
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
className="svg-inline--fa fa-caret-right fa-w-6 mr-1"
|
||||
data-icon="caret-right"
|
||||
data-prefix="fas"
|
||||
focusable="false"
|
||||
role="img"
|
||||
style={Object {}}
|
||||
viewBox="0 0 192 512"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M0 384.662V127.338c0-17.818 21.543-26.741 34.142-14.142l128.662 128.662c7.81 7.81 7.81 20.474 0 28.284L34.142 398.804C21.543 411.404 0 402.48 0 384.662z"
|
||||
fill="currentColor"
|
||||
style={Object {}}
|
||||
/>
|
||||
</svg>
|
||||
Need help signing in?
|
||||
</button>
|
||||
<div
|
||||
className="pgn-transition-replace-group position-relative"
|
||||
style={
|
||||
Object {
|
||||
"height": null,
|
||||
}
|
||||
}
|
||||
>
|
||||
<div
|
||||
style={
|
||||
Object {
|
||||
"padding": ".1px 0",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
aria-disabled={true}
|
||||
aria-live="assertive"
|
||||
className="pgn__stateful-btn pgn__stateful-btn-state-pending btn-primary submit disabled btn btn-primary"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
type="submit"
|
||||
>
|
||||
<span
|
||||
className="d-flex align-items-center justify-content-center"
|
||||
>
|
||||
<span
|
||||
className="pgn__stateful-btn-icon"
|
||||
>
|
||||
<span
|
||||
aria-hidden={true}
|
||||
className="icon fa fa-spinner fa-spin"
|
||||
id="Icon1"
|
||||
/>
|
||||
</span>
|
||||
Sign in
|
||||
</span>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
@@ -595,18 +771,11 @@ exports[`LoginPage should show error message on 400 1`] = `
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
<h3
|
||||
className="text-left mt-3"
|
||||
<h2
|
||||
className="font-color text-left mt-2 mb-3"
|
||||
>
|
||||
Sign In
|
||||
</h3>
|
||||
<div
|
||||
className="section-heading-line mb-4"
|
||||
>
|
||||
<h4>
|
||||
or sign in with
|
||||
</h4>
|
||||
</div>
|
||||
</h2>
|
||||
<form
|
||||
className="m-0"
|
||||
>
|
||||
@@ -729,12 +898,18 @@ exports[`LoginPage should show error message on 400 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
className="btn-primary submit btn btn-primary"
|
||||
aria-disabled={false}
|
||||
aria-live="assertive"
|
||||
className="pgn__stateful-btn pgn__stateful-btn-state-default btn-primary submit btn btn-primary"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
type="submit"
|
||||
>
|
||||
Sign in
|
||||
<span
|
||||
className="d-flex align-items-center justify-content-center"
|
||||
>
|
||||
Sign in
|
||||
</span>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
@@ -797,18 +972,11 @@ exports[`LoginPage should show error message on 400 on receiving link 1`] = `
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
<h3
|
||||
className="text-left mt-3"
|
||||
<h2
|
||||
className="font-color text-left mt-2 mb-3"
|
||||
>
|
||||
Sign In
|
||||
</h3>
|
||||
<div
|
||||
className="section-heading-line mb-4"
|
||||
>
|
||||
<h4>
|
||||
or sign in with
|
||||
</h4>
|
||||
</div>
|
||||
</h2>
|
||||
<form
|
||||
className="m-0"
|
||||
>
|
||||
@@ -931,12 +1099,18 @@ exports[`LoginPage should show error message on 400 on receiving link 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
className="btn-primary submit btn btn-primary"
|
||||
aria-disabled={false}
|
||||
aria-live="assertive"
|
||||
className="pgn__stateful-btn pgn__stateful-btn-state-default btn-primary submit btn btn-primary"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
type="submit"
|
||||
>
|
||||
Sign in
|
||||
<span
|
||||
className="d-flex align-items-center justify-content-center"
|
||||
>
|
||||
Sign in
|
||||
</span>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -1464,12 +1464,18 @@ exports[`./RegistrationPage.js should match TPA provider snapshot 1`] = `
|
||||
.
|
||||
</span>
|
||||
<button
|
||||
className="btn-primary mt-4 submit btn btn-primary"
|
||||
aria-disabled={false}
|
||||
aria-live="assertive"
|
||||
className="pgn__stateful-btn pgn__stateful-btn-state-default btn-primary submit mt-4 btn btn-primary"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
type="submit"
|
||||
>
|
||||
Create Account
|
||||
<span
|
||||
className="d-flex align-items-center justify-content-center"
|
||||
>
|
||||
Create Account
|
||||
</span>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
@@ -2899,12 +2905,1468 @@ exports[`./RegistrationPage.js should match default section snapshot 1`] = `
|
||||
.
|
||||
</span>
|
||||
<button
|
||||
className="btn-primary mt-4 submit btn btn-primary"
|
||||
aria-disabled={false}
|
||||
aria-live="assertive"
|
||||
className="pgn__stateful-btn pgn__stateful-btn-state-default btn-primary submit mt-4 btn btn-primary"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
type="submit"
|
||||
>
|
||||
Create Account
|
||||
<span
|
||||
className="d-flex align-items-center justify-content-center"
|
||||
>
|
||||
Create Account
|
||||
</span>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`./RegistrationPage.js should match pending button state snapshot 1`] = `
|
||||
<div
|
||||
className="register-container mx-auto"
|
||||
>
|
||||
<div
|
||||
className="text-left"
|
||||
>
|
||||
<span>
|
||||
Already have an edX account?
|
||||
</span>
|
||||
<a
|
||||
href="/login"
|
||||
>
|
||||
Sign in.
|
||||
</a>
|
||||
</div>
|
||||
<form
|
||||
className="mb-4 mx-auto form-group"
|
||||
>
|
||||
<div
|
||||
className="form-group"
|
||||
>
|
||||
<label
|
||||
className="h6 pt-3"
|
||||
htmlFor="registrationEmail"
|
||||
>
|
||||
Email (required)
|
||||
</label>
|
||||
<input
|
||||
aria-describedby=""
|
||||
className="form-control"
|
||||
id="registrationEmail"
|
||||
name="email"
|
||||
onChange={[Function]}
|
||||
placeholder="username@domain.com"
|
||||
required={true}
|
||||
type="email"
|
||||
value=""
|
||||
/>
|
||||
<strong
|
||||
className="invalid-feedback"
|
||||
id="email-invalid-feedback"
|
||||
>
|
||||
Enter a valid email address that contains at least 3 characters.
|
||||
</strong>
|
||||
</div>
|
||||
<div
|
||||
className="form-group"
|
||||
>
|
||||
<label
|
||||
className="h6 pt-3"
|
||||
htmlFor="registrationName"
|
||||
>
|
||||
Full Name (required)
|
||||
</label>
|
||||
<input
|
||||
aria-describedby=""
|
||||
className="form-control"
|
||||
id="registrationName"
|
||||
name="fullname"
|
||||
onChange={[Function]}
|
||||
placeholder="Name"
|
||||
required={true}
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
<strong
|
||||
className="invalid-feedback"
|
||||
id="fullname-invalid-feedback"
|
||||
>
|
||||
Enter your full name.
|
||||
</strong>
|
||||
</div>
|
||||
<div
|
||||
className="form-group"
|
||||
>
|
||||
<label
|
||||
className="h6 pt-3"
|
||||
htmlFor="registrationUsername"
|
||||
>
|
||||
Public Username (required)
|
||||
</label>
|
||||
<input
|
||||
aria-describedby=""
|
||||
className="form-control"
|
||||
id="registrationUsername"
|
||||
name="username"
|
||||
onChange={[Function]}
|
||||
placeholder="Username"
|
||||
required={true}
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
<strong
|
||||
className="invalid-feedback"
|
||||
id="username-invalid-feedback"
|
||||
>
|
||||
Username must be between 2 and 30 characters long.
|
||||
</strong>
|
||||
</div>
|
||||
<div
|
||||
className="form-group"
|
||||
>
|
||||
<label
|
||||
className="h6 pt-3"
|
||||
htmlFor="registrationPassword"
|
||||
>
|
||||
Password (required)
|
||||
</label>
|
||||
<input
|
||||
aria-describedby=""
|
||||
className="form-control"
|
||||
id="registrationPassword"
|
||||
name="password"
|
||||
onChange={[Function]}
|
||||
placeholder="Password"
|
||||
required={true}
|
||||
type="password"
|
||||
value=""
|
||||
/>
|
||||
<strong
|
||||
className="invalid-feedback"
|
||||
id="password-invalid-feedback"
|
||||
>
|
||||
This password is too short. It must contain at least 8 characters. This password must contain at least 1 number.
|
||||
</strong>
|
||||
</div>
|
||||
<div
|
||||
className="form-group"
|
||||
>
|
||||
<label
|
||||
className="h6 pt-3"
|
||||
htmlFor="registrationCountry"
|
||||
>
|
||||
Country (required)
|
||||
</label>
|
||||
<select
|
||||
aria-describedby=""
|
||||
className="form-control"
|
||||
name="country"
|
||||
onChange={[Function]}
|
||||
placeholder="Country or Region of Residence"
|
||||
required={true}
|
||||
value=""
|
||||
>
|
||||
<option
|
||||
value=""
|
||||
>
|
||||
Country or Region of Residence (required)
|
||||
</option>
|
||||
<option
|
||||
value="AF"
|
||||
>
|
||||
Afghanistan
|
||||
</option>
|
||||
<option
|
||||
value="AL"
|
||||
>
|
||||
Albania
|
||||
</option>
|
||||
<option
|
||||
value="DZ"
|
||||
>
|
||||
Algeria
|
||||
</option>
|
||||
<option
|
||||
value="AS"
|
||||
>
|
||||
American Samoa
|
||||
</option>
|
||||
<option
|
||||
value="AD"
|
||||
>
|
||||
Andorra
|
||||
</option>
|
||||
<option
|
||||
value="AO"
|
||||
>
|
||||
Angola
|
||||
</option>
|
||||
<option
|
||||
value="AI"
|
||||
>
|
||||
Anguilla
|
||||
</option>
|
||||
<option
|
||||
value="AQ"
|
||||
>
|
||||
Antarctica
|
||||
</option>
|
||||
<option
|
||||
value="AG"
|
||||
>
|
||||
Antigua and Barbuda
|
||||
</option>
|
||||
<option
|
||||
value="AR"
|
||||
>
|
||||
Argentina
|
||||
</option>
|
||||
<option
|
||||
value="AM"
|
||||
>
|
||||
Armenia
|
||||
</option>
|
||||
<option
|
||||
value="AW"
|
||||
>
|
||||
Aruba
|
||||
</option>
|
||||
<option
|
||||
value="AU"
|
||||
>
|
||||
Australia
|
||||
</option>
|
||||
<option
|
||||
value="AT"
|
||||
>
|
||||
Austria
|
||||
</option>
|
||||
<option
|
||||
value="AZ"
|
||||
>
|
||||
Azerbaijan
|
||||
</option>
|
||||
<option
|
||||
value="BS"
|
||||
>
|
||||
Bahamas
|
||||
</option>
|
||||
<option
|
||||
value="BH"
|
||||
>
|
||||
Bahrain
|
||||
</option>
|
||||
<option
|
||||
value="BD"
|
||||
>
|
||||
Bangladesh
|
||||
</option>
|
||||
<option
|
||||
value="BB"
|
||||
>
|
||||
Barbados
|
||||
</option>
|
||||
<option
|
||||
value="BY"
|
||||
>
|
||||
Belarus
|
||||
</option>
|
||||
<option
|
||||
value="BE"
|
||||
>
|
||||
Belgium
|
||||
</option>
|
||||
<option
|
||||
value="BZ"
|
||||
>
|
||||
Belize
|
||||
</option>
|
||||
<option
|
||||
value="BJ"
|
||||
>
|
||||
Benin
|
||||
</option>
|
||||
<option
|
||||
value="BM"
|
||||
>
|
||||
Bermuda
|
||||
</option>
|
||||
<option
|
||||
value="BT"
|
||||
>
|
||||
Bhutan
|
||||
</option>
|
||||
<option
|
||||
value="BO"
|
||||
>
|
||||
Bolivia
|
||||
</option>
|
||||
<option
|
||||
value="BA"
|
||||
>
|
||||
Bosnia and Herzegovina
|
||||
</option>
|
||||
<option
|
||||
value="BW"
|
||||
>
|
||||
Botswana
|
||||
</option>
|
||||
<option
|
||||
value="BV"
|
||||
>
|
||||
Bouvet Island
|
||||
</option>
|
||||
<option
|
||||
value="BR"
|
||||
>
|
||||
Brazil
|
||||
</option>
|
||||
<option
|
||||
value="IO"
|
||||
>
|
||||
British Indian Ocean Territory
|
||||
</option>
|
||||
<option
|
||||
value="BN"
|
||||
>
|
||||
Brunei Darussalam
|
||||
</option>
|
||||
<option
|
||||
value="BG"
|
||||
>
|
||||
Bulgaria
|
||||
</option>
|
||||
<option
|
||||
value="BF"
|
||||
>
|
||||
Burkina Faso
|
||||
</option>
|
||||
<option
|
||||
value="BI"
|
||||
>
|
||||
Burundi
|
||||
</option>
|
||||
<option
|
||||
value="KH"
|
||||
>
|
||||
Cambodia
|
||||
</option>
|
||||
<option
|
||||
value="CM"
|
||||
>
|
||||
Cameroon
|
||||
</option>
|
||||
<option
|
||||
value="CA"
|
||||
>
|
||||
Canada
|
||||
</option>
|
||||
<option
|
||||
value="CV"
|
||||
>
|
||||
Cape Verde
|
||||
</option>
|
||||
<option
|
||||
value="KY"
|
||||
>
|
||||
Cayman Islands
|
||||
</option>
|
||||
<option
|
||||
value="CF"
|
||||
>
|
||||
Central African Republic
|
||||
</option>
|
||||
<option
|
||||
value="TD"
|
||||
>
|
||||
Chad
|
||||
</option>
|
||||
<option
|
||||
value="CL"
|
||||
>
|
||||
Chile
|
||||
</option>
|
||||
<option
|
||||
value="CN"
|
||||
>
|
||||
China
|
||||
</option>
|
||||
<option
|
||||
value="CX"
|
||||
>
|
||||
Christmas Island
|
||||
</option>
|
||||
<option
|
||||
value="CC"
|
||||
>
|
||||
Cocos (Keeling) Islands
|
||||
</option>
|
||||
<option
|
||||
value="CO"
|
||||
>
|
||||
Colombia
|
||||
</option>
|
||||
<option
|
||||
value="KM"
|
||||
>
|
||||
Comoros
|
||||
</option>
|
||||
<option
|
||||
value="CG"
|
||||
>
|
||||
Congo
|
||||
</option>
|
||||
<option
|
||||
value="CD"
|
||||
>
|
||||
Congo, the Democratic Republic of the
|
||||
</option>
|
||||
<option
|
||||
value="CK"
|
||||
>
|
||||
Cook Islands
|
||||
</option>
|
||||
<option
|
||||
value="CR"
|
||||
>
|
||||
Costa Rica
|
||||
</option>
|
||||
<option
|
||||
value="CI"
|
||||
>
|
||||
Cote D'Ivoire
|
||||
</option>
|
||||
<option
|
||||
value="HR"
|
||||
>
|
||||
Croatia
|
||||
</option>
|
||||
<option
|
||||
value="CU"
|
||||
>
|
||||
Cuba
|
||||
</option>
|
||||
<option
|
||||
value="CY"
|
||||
>
|
||||
Cyprus
|
||||
</option>
|
||||
<option
|
||||
value="CZ"
|
||||
>
|
||||
Czech Republic
|
||||
</option>
|
||||
<option
|
||||
value="DK"
|
||||
>
|
||||
Denmark
|
||||
</option>
|
||||
<option
|
||||
value="DJ"
|
||||
>
|
||||
Djibouti
|
||||
</option>
|
||||
<option
|
||||
value="DM"
|
||||
>
|
||||
Dominica
|
||||
</option>
|
||||
<option
|
||||
value="DO"
|
||||
>
|
||||
Dominican Republic
|
||||
</option>
|
||||
<option
|
||||
value="EC"
|
||||
>
|
||||
Ecuador
|
||||
</option>
|
||||
<option
|
||||
value="EG"
|
||||
>
|
||||
Egypt
|
||||
</option>
|
||||
<option
|
||||
value="SV"
|
||||
>
|
||||
El Salvador
|
||||
</option>
|
||||
<option
|
||||
value="GQ"
|
||||
>
|
||||
Equatorial Guinea
|
||||
</option>
|
||||
<option
|
||||
value="ER"
|
||||
>
|
||||
Eritrea
|
||||
</option>
|
||||
<option
|
||||
value="EE"
|
||||
>
|
||||
Estonia
|
||||
</option>
|
||||
<option
|
||||
value="ET"
|
||||
>
|
||||
Ethiopia
|
||||
</option>
|
||||
<option
|
||||
value="FK"
|
||||
>
|
||||
Falkland Islands (Malvinas)
|
||||
</option>
|
||||
<option
|
||||
value="FO"
|
||||
>
|
||||
Faroe Islands
|
||||
</option>
|
||||
<option
|
||||
value="FJ"
|
||||
>
|
||||
Fiji
|
||||
</option>
|
||||
<option
|
||||
value="FI"
|
||||
>
|
||||
Finland
|
||||
</option>
|
||||
<option
|
||||
value="FR"
|
||||
>
|
||||
France
|
||||
</option>
|
||||
<option
|
||||
value="GF"
|
||||
>
|
||||
French Guiana
|
||||
</option>
|
||||
<option
|
||||
value="PF"
|
||||
>
|
||||
French Polynesia
|
||||
</option>
|
||||
<option
|
||||
value="TF"
|
||||
>
|
||||
French Southern Territories
|
||||
</option>
|
||||
<option
|
||||
value="GA"
|
||||
>
|
||||
Gabon
|
||||
</option>
|
||||
<option
|
||||
value="GM"
|
||||
>
|
||||
Gambia
|
||||
</option>
|
||||
<option
|
||||
value="GE"
|
||||
>
|
||||
Georgia
|
||||
</option>
|
||||
<option
|
||||
value="DE"
|
||||
>
|
||||
Germany
|
||||
</option>
|
||||
<option
|
||||
value="GH"
|
||||
>
|
||||
Ghana
|
||||
</option>
|
||||
<option
|
||||
value="GI"
|
||||
>
|
||||
Gibraltar
|
||||
</option>
|
||||
<option
|
||||
value="GR"
|
||||
>
|
||||
Greece
|
||||
</option>
|
||||
<option
|
||||
value="GL"
|
||||
>
|
||||
Greenland
|
||||
</option>
|
||||
<option
|
||||
value="GD"
|
||||
>
|
||||
Grenada
|
||||
</option>
|
||||
<option
|
||||
value="GP"
|
||||
>
|
||||
Guadeloupe
|
||||
</option>
|
||||
<option
|
||||
value="GU"
|
||||
>
|
||||
Guam
|
||||
</option>
|
||||
<option
|
||||
value="GT"
|
||||
>
|
||||
Guatemala
|
||||
</option>
|
||||
<option
|
||||
value="GN"
|
||||
>
|
||||
Guinea
|
||||
</option>
|
||||
<option
|
||||
value="GW"
|
||||
>
|
||||
Guinea-Bissau
|
||||
</option>
|
||||
<option
|
||||
value="GY"
|
||||
>
|
||||
Guyana
|
||||
</option>
|
||||
<option
|
||||
value="HT"
|
||||
>
|
||||
Haiti
|
||||
</option>
|
||||
<option
|
||||
value="HM"
|
||||
>
|
||||
Heard Island and Mcdonald Islands
|
||||
</option>
|
||||
<option
|
||||
value="VA"
|
||||
>
|
||||
Holy See (Vatican City State)
|
||||
</option>
|
||||
<option
|
||||
value="HN"
|
||||
>
|
||||
Honduras
|
||||
</option>
|
||||
<option
|
||||
value="HK"
|
||||
>
|
||||
Hong Kong
|
||||
</option>
|
||||
<option
|
||||
value="HU"
|
||||
>
|
||||
Hungary
|
||||
</option>
|
||||
<option
|
||||
value="IS"
|
||||
>
|
||||
Iceland
|
||||
</option>
|
||||
<option
|
||||
value="IN"
|
||||
>
|
||||
India
|
||||
</option>
|
||||
<option
|
||||
value="ID"
|
||||
>
|
||||
Indonesia
|
||||
</option>
|
||||
<option
|
||||
value="IR"
|
||||
>
|
||||
Iran, Islamic Republic of
|
||||
</option>
|
||||
<option
|
||||
value="IQ"
|
||||
>
|
||||
Iraq
|
||||
</option>
|
||||
<option
|
||||
value="IE"
|
||||
>
|
||||
Ireland
|
||||
</option>
|
||||
<option
|
||||
value="IL"
|
||||
>
|
||||
Israel
|
||||
</option>
|
||||
<option
|
||||
value="IT"
|
||||
>
|
||||
Italy
|
||||
</option>
|
||||
<option
|
||||
value="JM"
|
||||
>
|
||||
Jamaica
|
||||
</option>
|
||||
<option
|
||||
value="JP"
|
||||
>
|
||||
Japan
|
||||
</option>
|
||||
<option
|
||||
value="JO"
|
||||
>
|
||||
Jordan
|
||||
</option>
|
||||
<option
|
||||
value="KZ"
|
||||
>
|
||||
Kazakhstan
|
||||
</option>
|
||||
<option
|
||||
value="KE"
|
||||
>
|
||||
Kenya
|
||||
</option>
|
||||
<option
|
||||
value="KI"
|
||||
>
|
||||
Kiribati
|
||||
</option>
|
||||
<option
|
||||
value="KP"
|
||||
>
|
||||
North Korea
|
||||
</option>
|
||||
<option
|
||||
value="KR"
|
||||
>
|
||||
South Korea
|
||||
</option>
|
||||
<option
|
||||
value="KW"
|
||||
>
|
||||
Kuwait
|
||||
</option>
|
||||
<option
|
||||
value="KG"
|
||||
>
|
||||
Kyrgyzstan
|
||||
</option>
|
||||
<option
|
||||
value="LA"
|
||||
>
|
||||
Lao People's Democratic Republic
|
||||
</option>
|
||||
<option
|
||||
value="LV"
|
||||
>
|
||||
Latvia
|
||||
</option>
|
||||
<option
|
||||
value="LB"
|
||||
>
|
||||
Lebanon
|
||||
</option>
|
||||
<option
|
||||
value="LS"
|
||||
>
|
||||
Lesotho
|
||||
</option>
|
||||
<option
|
||||
value="LR"
|
||||
>
|
||||
Liberia
|
||||
</option>
|
||||
<option
|
||||
value="LY"
|
||||
>
|
||||
Libya
|
||||
</option>
|
||||
<option
|
||||
value="LI"
|
||||
>
|
||||
Liechtenstein
|
||||
</option>
|
||||
<option
|
||||
value="LT"
|
||||
>
|
||||
Lithuania
|
||||
</option>
|
||||
<option
|
||||
value="LU"
|
||||
>
|
||||
Luxembourg
|
||||
</option>
|
||||
<option
|
||||
value="MO"
|
||||
>
|
||||
Macao
|
||||
</option>
|
||||
<option
|
||||
value="MG"
|
||||
>
|
||||
Madagascar
|
||||
</option>
|
||||
<option
|
||||
value="MW"
|
||||
>
|
||||
Malawi
|
||||
</option>
|
||||
<option
|
||||
value="MY"
|
||||
>
|
||||
Malaysia
|
||||
</option>
|
||||
<option
|
||||
value="MV"
|
||||
>
|
||||
Maldives
|
||||
</option>
|
||||
<option
|
||||
value="ML"
|
||||
>
|
||||
Mali
|
||||
</option>
|
||||
<option
|
||||
value="MT"
|
||||
>
|
||||
Malta
|
||||
</option>
|
||||
<option
|
||||
value="MH"
|
||||
>
|
||||
Marshall Islands
|
||||
</option>
|
||||
<option
|
||||
value="MQ"
|
||||
>
|
||||
Martinique
|
||||
</option>
|
||||
<option
|
||||
value="MR"
|
||||
>
|
||||
Mauritania
|
||||
</option>
|
||||
<option
|
||||
value="MU"
|
||||
>
|
||||
Mauritius
|
||||
</option>
|
||||
<option
|
||||
value="YT"
|
||||
>
|
||||
Mayotte
|
||||
</option>
|
||||
<option
|
||||
value="MX"
|
||||
>
|
||||
Mexico
|
||||
</option>
|
||||
<option
|
||||
value="FM"
|
||||
>
|
||||
Micronesia, Federated States of
|
||||
</option>
|
||||
<option
|
||||
value="MD"
|
||||
>
|
||||
Moldova, Republic of
|
||||
</option>
|
||||
<option
|
||||
value="MC"
|
||||
>
|
||||
Monaco
|
||||
</option>
|
||||
<option
|
||||
value="MN"
|
||||
>
|
||||
Mongolia
|
||||
</option>
|
||||
<option
|
||||
value="MS"
|
||||
>
|
||||
Montserrat
|
||||
</option>
|
||||
<option
|
||||
value="MA"
|
||||
>
|
||||
Morocco
|
||||
</option>
|
||||
<option
|
||||
value="MZ"
|
||||
>
|
||||
Mozambique
|
||||
</option>
|
||||
<option
|
||||
value="MM"
|
||||
>
|
||||
Myanmar
|
||||
</option>
|
||||
<option
|
||||
value="NA"
|
||||
>
|
||||
Namibia
|
||||
</option>
|
||||
<option
|
||||
value="NR"
|
||||
>
|
||||
Nauru
|
||||
</option>
|
||||
<option
|
||||
value="NP"
|
||||
>
|
||||
Nepal
|
||||
</option>
|
||||
<option
|
||||
value="NL"
|
||||
>
|
||||
Netherlands
|
||||
</option>
|
||||
<option
|
||||
value="NC"
|
||||
>
|
||||
New Caledonia
|
||||
</option>
|
||||
<option
|
||||
value="NZ"
|
||||
>
|
||||
New Zealand
|
||||
</option>
|
||||
<option
|
||||
value="NI"
|
||||
>
|
||||
Nicaragua
|
||||
</option>
|
||||
<option
|
||||
value="NE"
|
||||
>
|
||||
Niger
|
||||
</option>
|
||||
<option
|
||||
value="NG"
|
||||
>
|
||||
Nigeria
|
||||
</option>
|
||||
<option
|
||||
value="NU"
|
||||
>
|
||||
Niue
|
||||
</option>
|
||||
<option
|
||||
value="NF"
|
||||
>
|
||||
Norfolk Island
|
||||
</option>
|
||||
<option
|
||||
value="MK"
|
||||
>
|
||||
North Macedonia, Republic of
|
||||
</option>
|
||||
<option
|
||||
value="MP"
|
||||
>
|
||||
Northern Mariana Islands
|
||||
</option>
|
||||
<option
|
||||
value="NO"
|
||||
>
|
||||
Norway
|
||||
</option>
|
||||
<option
|
||||
value="OM"
|
||||
>
|
||||
Oman
|
||||
</option>
|
||||
<option
|
||||
value="PK"
|
||||
>
|
||||
Pakistan
|
||||
</option>
|
||||
<option
|
||||
value="PW"
|
||||
>
|
||||
Palau
|
||||
</option>
|
||||
<option
|
||||
value="PS"
|
||||
>
|
||||
Palestinian Territory, Occupied
|
||||
</option>
|
||||
<option
|
||||
value="PA"
|
||||
>
|
||||
Panama
|
||||
</option>
|
||||
<option
|
||||
value="PG"
|
||||
>
|
||||
Papua New Guinea
|
||||
</option>
|
||||
<option
|
||||
value="PY"
|
||||
>
|
||||
Paraguay
|
||||
</option>
|
||||
<option
|
||||
value="PE"
|
||||
>
|
||||
Peru
|
||||
</option>
|
||||
<option
|
||||
value="PH"
|
||||
>
|
||||
Philippines
|
||||
</option>
|
||||
<option
|
||||
value="PN"
|
||||
>
|
||||
Pitcairn
|
||||
</option>
|
||||
<option
|
||||
value="PL"
|
||||
>
|
||||
Poland
|
||||
</option>
|
||||
<option
|
||||
value="PT"
|
||||
>
|
||||
Portugal
|
||||
</option>
|
||||
<option
|
||||
value="PR"
|
||||
>
|
||||
Puerto Rico
|
||||
</option>
|
||||
<option
|
||||
value="QA"
|
||||
>
|
||||
Qatar
|
||||
</option>
|
||||
<option
|
||||
value="RE"
|
||||
>
|
||||
Reunion
|
||||
</option>
|
||||
<option
|
||||
value="RO"
|
||||
>
|
||||
Romania
|
||||
</option>
|
||||
<option
|
||||
value="RU"
|
||||
>
|
||||
Russian Federation
|
||||
</option>
|
||||
<option
|
||||
value="RW"
|
||||
>
|
||||
Rwanda
|
||||
</option>
|
||||
<option
|
||||
value="SH"
|
||||
>
|
||||
Saint Helena
|
||||
</option>
|
||||
<option
|
||||
value="KN"
|
||||
>
|
||||
Saint Kitts and Nevis
|
||||
</option>
|
||||
<option
|
||||
value="LC"
|
||||
>
|
||||
Saint Lucia
|
||||
</option>
|
||||
<option
|
||||
value="PM"
|
||||
>
|
||||
Saint Pierre and Miquelon
|
||||
</option>
|
||||
<option
|
||||
value="VC"
|
||||
>
|
||||
Saint Vincent and the Grenadines
|
||||
</option>
|
||||
<option
|
||||
value="WS"
|
||||
>
|
||||
Samoa
|
||||
</option>
|
||||
<option
|
||||
value="SM"
|
||||
>
|
||||
San Marino
|
||||
</option>
|
||||
<option
|
||||
value="ST"
|
||||
>
|
||||
Sao Tome and Principe
|
||||
</option>
|
||||
<option
|
||||
value="SA"
|
||||
>
|
||||
Saudi Arabia
|
||||
</option>
|
||||
<option
|
||||
value="SN"
|
||||
>
|
||||
Senegal
|
||||
</option>
|
||||
<option
|
||||
value="SC"
|
||||
>
|
||||
Seychelles
|
||||
</option>
|
||||
<option
|
||||
value="SL"
|
||||
>
|
||||
Sierra Leone
|
||||
</option>
|
||||
<option
|
||||
value="SG"
|
||||
>
|
||||
Singapore
|
||||
</option>
|
||||
<option
|
||||
value="SK"
|
||||
>
|
||||
Slovakia
|
||||
</option>
|
||||
<option
|
||||
value="SI"
|
||||
>
|
||||
Slovenia
|
||||
</option>
|
||||
<option
|
||||
value="SB"
|
||||
>
|
||||
Solomon Islands
|
||||
</option>
|
||||
<option
|
||||
value="SO"
|
||||
>
|
||||
Somalia
|
||||
</option>
|
||||
<option
|
||||
value="ZA"
|
||||
>
|
||||
South Africa
|
||||
</option>
|
||||
<option
|
||||
value="GS"
|
||||
>
|
||||
South Georgia and the South Sandwich Islands
|
||||
</option>
|
||||
<option
|
||||
value="ES"
|
||||
>
|
||||
Spain
|
||||
</option>
|
||||
<option
|
||||
value="LK"
|
||||
>
|
||||
Sri Lanka
|
||||
</option>
|
||||
<option
|
||||
value="SD"
|
||||
>
|
||||
Sudan
|
||||
</option>
|
||||
<option
|
||||
value="SR"
|
||||
>
|
||||
Suriname
|
||||
</option>
|
||||
<option
|
||||
value="SJ"
|
||||
>
|
||||
Svalbard and Jan Mayen
|
||||
</option>
|
||||
<option
|
||||
value="SZ"
|
||||
>
|
||||
Swaziland
|
||||
</option>
|
||||
<option
|
||||
value="SE"
|
||||
>
|
||||
Sweden
|
||||
</option>
|
||||
<option
|
||||
value="CH"
|
||||
>
|
||||
Switzerland
|
||||
</option>
|
||||
<option
|
||||
value="SY"
|
||||
>
|
||||
Syrian Arab Republic
|
||||
</option>
|
||||
<option
|
||||
value="TW"
|
||||
>
|
||||
Taiwan
|
||||
</option>
|
||||
<option
|
||||
value="TJ"
|
||||
>
|
||||
Tajikistan
|
||||
</option>
|
||||
<option
|
||||
value="TZ"
|
||||
>
|
||||
Tanzania, United Republic of
|
||||
</option>
|
||||
<option
|
||||
value="TH"
|
||||
>
|
||||
Thailand
|
||||
</option>
|
||||
<option
|
||||
value="TL"
|
||||
>
|
||||
Timor-Leste
|
||||
</option>
|
||||
<option
|
||||
value="TG"
|
||||
>
|
||||
Togo
|
||||
</option>
|
||||
<option
|
||||
value="TK"
|
||||
>
|
||||
Tokelau
|
||||
</option>
|
||||
<option
|
||||
value="TO"
|
||||
>
|
||||
Tonga
|
||||
</option>
|
||||
<option
|
||||
value="TT"
|
||||
>
|
||||
Trinidad and Tobago
|
||||
</option>
|
||||
<option
|
||||
value="TN"
|
||||
>
|
||||
Tunisia
|
||||
</option>
|
||||
<option
|
||||
value="TR"
|
||||
>
|
||||
Turkey
|
||||
</option>
|
||||
<option
|
||||
value="TM"
|
||||
>
|
||||
Turkmenistan
|
||||
</option>
|
||||
<option
|
||||
value="TC"
|
||||
>
|
||||
Turks and Caicos Islands
|
||||
</option>
|
||||
<option
|
||||
value="TV"
|
||||
>
|
||||
Tuvalu
|
||||
</option>
|
||||
<option
|
||||
value="UG"
|
||||
>
|
||||
Uganda
|
||||
</option>
|
||||
<option
|
||||
value="UA"
|
||||
>
|
||||
Ukraine
|
||||
</option>
|
||||
<option
|
||||
value="AE"
|
||||
>
|
||||
United Arab Emirates
|
||||
</option>
|
||||
<option
|
||||
value="GB"
|
||||
>
|
||||
United Kingdom
|
||||
</option>
|
||||
<option
|
||||
value="US"
|
||||
>
|
||||
United States of America
|
||||
</option>
|
||||
<option
|
||||
value="UM"
|
||||
>
|
||||
United States Minor Outlying Islands
|
||||
</option>
|
||||
<option
|
||||
value="UY"
|
||||
>
|
||||
Uruguay
|
||||
</option>
|
||||
<option
|
||||
value="UZ"
|
||||
>
|
||||
Uzbekistan
|
||||
</option>
|
||||
<option
|
||||
value="VU"
|
||||
>
|
||||
Vanuatu
|
||||
</option>
|
||||
<option
|
||||
value="VE"
|
||||
>
|
||||
Venezuela
|
||||
</option>
|
||||
<option
|
||||
value="VN"
|
||||
>
|
||||
Viet Nam
|
||||
</option>
|
||||
<option
|
||||
value="VG"
|
||||
>
|
||||
Virgin Islands, British
|
||||
</option>
|
||||
<option
|
||||
value="VI"
|
||||
>
|
||||
Virgin Islands, U.S.
|
||||
</option>
|
||||
<option
|
||||
value="WF"
|
||||
>
|
||||
Wallis and Futuna
|
||||
</option>
|
||||
<option
|
||||
value="EH"
|
||||
>
|
||||
Western Sahara
|
||||
</option>
|
||||
<option
|
||||
value="YE"
|
||||
>
|
||||
Yemen
|
||||
</option>
|
||||
<option
|
||||
value="ZM"
|
||||
>
|
||||
Zambia
|
||||
</option>
|
||||
<option
|
||||
value="ZW"
|
||||
>
|
||||
Zimbabwe
|
||||
</option>
|
||||
<option
|
||||
value="AX"
|
||||
>
|
||||
Åland Islands
|
||||
</option>
|
||||
<option
|
||||
value="BQ"
|
||||
>
|
||||
Bonaire, Sint Eustatius and Saba
|
||||
</option>
|
||||
<option
|
||||
value="CW"
|
||||
>
|
||||
Curaçao
|
||||
</option>
|
||||
<option
|
||||
value="GG"
|
||||
>
|
||||
Guernsey
|
||||
</option>
|
||||
<option
|
||||
value="IM"
|
||||
>
|
||||
Isle of Man
|
||||
</option>
|
||||
<option
|
||||
value="JE"
|
||||
>
|
||||
Jersey
|
||||
</option>
|
||||
<option
|
||||
value="ME"
|
||||
>
|
||||
Montenegro
|
||||
</option>
|
||||
<option
|
||||
value="BL"
|
||||
>
|
||||
Saint Barthélemy
|
||||
</option>
|
||||
<option
|
||||
value="MF"
|
||||
>
|
||||
Saint Martin (French part)
|
||||
</option>
|
||||
<option
|
||||
value="RS"
|
||||
>
|
||||
Serbia
|
||||
</option>
|
||||
<option
|
||||
value="SX"
|
||||
>
|
||||
Sint Maarten (Dutch part)
|
||||
</option>
|
||||
<option
|
||||
value="SS"
|
||||
>
|
||||
South Sudan
|
||||
</option>
|
||||
<option
|
||||
value="XK"
|
||||
>
|
||||
Kosovo
|
||||
</option>
|
||||
</select>
|
||||
<strong
|
||||
className="invalid-feedback"
|
||||
id="country-invalid-feedback"
|
||||
>
|
||||
Select your country or region of residence.
|
||||
</strong>
|
||||
</div>
|
||||
<span>
|
||||
By creating an account, you agree to the
|
||||
<a
|
||||
href="https://www.edx.org/edx-terms-service"
|
||||
>
|
||||
Terms of Service and Honor Code
|
||||
</a>
|
||||
and you acknowledge that edX and each Member process your personal data in accordance with the
|
||||
<a
|
||||
href="https://www.edx.org/edx-privacy-policy"
|
||||
>
|
||||
Privacy Policy
|
||||
</a>
|
||||
.
|
||||
</span>
|
||||
<button
|
||||
aria-disabled={true}
|
||||
aria-live="assertive"
|
||||
className="pgn__stateful-btn pgn__stateful-btn-state-pending btn-primary submit mt-4 disabled btn btn-primary"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
type="submit"
|
||||
>
|
||||
<span
|
||||
className="d-flex align-items-center justify-content-center"
|
||||
>
|
||||
<span
|
||||
className="pgn__stateful-btn-icon"
|
||||
>
|
||||
<span
|
||||
aria-hidden={true}
|
||||
className="icon fa fa-spinner fa-spin"
|
||||
id="Icon1"
|
||||
/>
|
||||
</span>
|
||||
Create Account
|
||||
</span>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
@@ -4372,12 +5834,18 @@ exports[`./RegistrationPage.js should show error message on 409 1`] = `
|
||||
.
|
||||
</span>
|
||||
<button
|
||||
className="btn-primary mt-4 submit btn btn-primary"
|
||||
aria-disabled={false}
|
||||
aria-live="assertive"
|
||||
className="pgn__stateful-btn pgn__stateful-btn-state-default btn-primary submit mt-4 btn btn-primary"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
type="submit"
|
||||
>
|
||||
Create Account
|
||||
<span
|
||||
className="d-flex align-items-center justify-content-center"
|
||||
>
|
||||
Create Account
|
||||
</span>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
import { Button, Input, ValidationFormGroup } from '@edx/paragon';
|
||||
import { Input, StatefulButton, ValidationFormGroup } from '@edx/paragon';
|
||||
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import { getQueryParameters } from '@edx/frontend-platform';
|
||||
@@ -123,12 +123,15 @@ const ResetPasswordPage = (props) => {
|
||||
</ValidationFormGroup>
|
||||
</div>
|
||||
</div>
|
||||
<Button
|
||||
<StatefulButton
|
||||
type="submit"
|
||||
className="btn-primary submit"
|
||||
state={props.status}
|
||||
labels={{
|
||||
default: intl.formatMessage(messages['logistration.reset.password.page.submit.button']),
|
||||
}}
|
||||
onClick={e => handleSubmit(e)}
|
||||
>
|
||||
{intl.formatMessage(messages['logistration.reset.password.page.submit.button'])}
|
||||
</Button>
|
||||
/>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -53,6 +53,21 @@ describe('ResetPasswordPage', () => {
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('show spinner component during token validation', () => {
|
||||
props = {
|
||||
...props,
|
||||
token_status: 'pending',
|
||||
match: {
|
||||
params: {
|
||||
token: 'test-token',
|
||||
},
|
||||
},
|
||||
};
|
||||
const tree = renderer.create(reduxWrapper(<IntlResetPasswordPage {...props} />))
|
||||
.toJSON();
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match invalid token message section snapshot', () => {
|
||||
props = {
|
||||
...props,
|
||||
@@ -63,6 +78,17 @@ describe('ResetPasswordPage', () => {
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match pending reset message section snapshot', () => {
|
||||
props = {
|
||||
...props,
|
||||
token_status: 'valid',
|
||||
status: 'pending',
|
||||
};
|
||||
const tree = renderer.create(reduxWrapper(<IntlResetPasswordPage {...props} />))
|
||||
.toJSON();
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match successful reset message section snapshot', () => {
|
||||
props = {
|
||||
...props,
|
||||
@@ -139,19 +165,4 @@ describe('ResetPasswordPage', () => {
|
||||
expect(store.dispatch).toHaveBeenCalledWith(resetPassword(formPayload, props.token, {}));
|
||||
resetPage.unmount();
|
||||
});
|
||||
|
||||
it('show spinner component during token validation', () => {
|
||||
props = {
|
||||
...props,
|
||||
token_status: 'pending',
|
||||
match: {
|
||||
params: {
|
||||
token: 'test-token',
|
||||
},
|
||||
},
|
||||
};
|
||||
const tree = renderer.create(reduxWrapper(<IntlResetPasswordPage {...props} />))
|
||||
.toJSON();
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -58,6 +58,122 @@ exports[`ResetPasswordPage should match invalid token message section snapshot 1
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`ResetPasswordPage should match pending reset message section snapshot 1`] = `
|
||||
<div
|
||||
className="d-flex justify-content-center reset-password-container"
|
||||
>
|
||||
<div
|
||||
className="d-flex flex-column"
|
||||
style={
|
||||
Object {
|
||||
"width": "450px",
|
||||
}
|
||||
}
|
||||
>
|
||||
<form
|
||||
className="m-4"
|
||||
>
|
||||
<div
|
||||
className="form-group"
|
||||
>
|
||||
<h3
|
||||
className="text-center mt-3"
|
||||
>
|
||||
Reset Your Password
|
||||
</h3>
|
||||
<p
|
||||
className="mb-4"
|
||||
>
|
||||
Enter and confirm your new password.
|
||||
</p>
|
||||
<div
|
||||
className="d-flex flex-column align-items-start"
|
||||
>
|
||||
<div
|
||||
className="form-group"
|
||||
>
|
||||
<label
|
||||
className="h6 mr-1"
|
||||
htmlFor="reset-password-input"
|
||||
>
|
||||
New Password
|
||||
</label>
|
||||
<input
|
||||
aria-describedby=""
|
||||
className="form-control"
|
||||
id="reset-password-input"
|
||||
name="new-password1"
|
||||
onBlur={[Function]}
|
||||
placeholder=""
|
||||
style={
|
||||
Object {
|
||||
"width": "400px",
|
||||
}
|
||||
}
|
||||
type="password"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className="form-group"
|
||||
>
|
||||
<label
|
||||
className="h6 mr-1"
|
||||
htmlFor="confirm-password-input"
|
||||
>
|
||||
Confirm Password
|
||||
</label>
|
||||
<input
|
||||
aria-describedby=""
|
||||
className="form-control"
|
||||
id="confirm-password-input"
|
||||
name="new-password2"
|
||||
onChange={[Function]}
|
||||
placeholder=""
|
||||
style={
|
||||
Object {
|
||||
"width": "400px",
|
||||
}
|
||||
}
|
||||
type="password"
|
||||
value=""
|
||||
/>
|
||||
<strong
|
||||
className="invalid-feedback"
|
||||
id="confirm-password-input-invalid-feedback"
|
||||
>
|
||||
Passwords do not match.
|
||||
</strong>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
aria-disabled={true}
|
||||
aria-live="assertive"
|
||||
className="pgn__stateful-btn pgn__stateful-btn-state-pending btn-primary submit disabled btn btn-primary"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
type="submit"
|
||||
>
|
||||
<span
|
||||
className="d-flex align-items-center justify-content-center"
|
||||
>
|
||||
<span
|
||||
className="pgn__stateful-btn-icon"
|
||||
>
|
||||
<span
|
||||
aria-hidden={true}
|
||||
className="icon fa fa-spinner fa-spin"
|
||||
id="Icon1"
|
||||
/>
|
||||
</span>
|
||||
Reset my password
|
||||
</span>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`ResetPasswordPage should match reset password default section snapshot 1`] = `
|
||||
<div
|
||||
className="d-flex justify-content-center reset-password-container"
|
||||
@@ -147,12 +263,18 @@ exports[`ResetPasswordPage should match reset password default section snapshot
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
className="btn-primary submit btn btn-primary"
|
||||
aria-disabled={false}
|
||||
aria-live="assertive"
|
||||
className="pgn__stateful-btn pgn__stateful-btn-state-null btn-primary submit btn btn-primary"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
type="submit"
|
||||
>
|
||||
Reset my password
|
||||
<span
|
||||
className="d-flex align-items-center justify-content-center"
|
||||
>
|
||||
Reset my password
|
||||
</span>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
@@ -345,12 +467,18 @@ Array [
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
className="btn-primary submit btn btn-primary"
|
||||
aria-disabled={false}
|
||||
aria-live="assertive"
|
||||
className="pgn__stateful-btn pgn__stateful-btn-state-failure btn-primary submit btn btn-primary"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
type="submit"
|
||||
>
|
||||
Reset my password
|
||||
<span
|
||||
className="d-flex align-items-center justify-content-center"
|
||||
>
|
||||
Reset my password
|
||||
</span>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user