Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GH-1960 Intro Hub Forgot Password #507

Merged
merged 15 commits into from Apr 16, 2020
Merged
Changes from all commits
Commits
File filter
Filter file types
Jump to
Jump to file
Failed to load files.

Always

Just for now

@@ -500,7 +500,7 @@
}
}
},
"panel_forgot_password": {
"forgot_password": {
"message": "Forgot Password?"
},
"panel_help_panel_header": {
@@ -18,7 +18,9 @@ import {
GET_USER_SUCCESS,
GET_USER_SETTINGS_SUCCESS,
GET_USER_SUBSCRIPTION_DATA_FAIL,
GET_USER_SUBSCRIPTION_DATA_SUCCESS
GET_USER_SUBSCRIPTION_DATA_SUCCESS,
RESET_PASSWORD_SUCCESS,
RESET_PASSWORD_FAIL
} from './AccountConstants';
import { UPDATE_PANEL_DATA } from '../panel/constants/constants';

@@ -28,6 +30,8 @@ const initialState = {
user: null,
userSettings: null,
subscriptionData: null,
toastMessage: '',
resetPasswordError: false
};

export default (state = initialState, action) => {
@@ -84,6 +88,31 @@ export default (state = initialState, action) => {
subscriptionData
});
}
case RESET_PASSWORD_SUCCESS: {
const toastMessage = t('banner_check_your_email_title');
return Object.assign({}, state, {
toastMessage,
resetPasswordError: false
});
}
case RESET_PASSWORD_FAIL: {
const { errors } = action.payload;
let errorText = t('server_error_message');
errors.forEach((err) => {
switch (err.code) {
case '10050':
case '10110':
errorText = t('banner_email_not_in_system_message');
break;
default:
errorText = t('server_error_message');
}
});
return Object.assign({}, state, {
toastMessage: errorText,
resetPasswordError: true
});
}

default: return state;
}
@@ -90,6 +90,13 @@ const LogInView = (props) => {
{t('hub_login_label_password_invalid')}
</div>
)}
<div className="flex-container align-center">
<span className="LogInView__link text-center">
<NavLink to="/forgot-password">
{ t('forgot_password') }
</NavLink>
</span>
</div>
<div className="flex-container align-center">
<span className="LogInView__link text-center">
{ t('hub_login_link_dont_have_account') }
@@ -67,6 +67,21 @@ exports[`app/hub/Views/LogIn component Snapshot tests with react-test-renderer l
type="password"
value="examplePassword"
/>
<div
className="flex-container align-center"
>
<span
className="LogInView__link text-center"
>
<a
aria-current={null}
href="/forgot-password"
onClick={[Function]}
>
forgot_password
</a>
</span>
</div>
<div
className="flex-container align-center"
>
@@ -177,6 +192,21 @@ exports[`app/hub/Views/LogIn component Snapshot tests with react-test-renderer l
>
hub_login_label_password_invalid
</div>
<div
className="flex-container align-center"
>
<span
className="LogInView__link text-center"
>
<a
aria-current={null}
href="/forgot-password"
onClick={[Function]}
>
forgot_password
</a>
</span>
</div>
<div
className="flex-container align-center"
>
@@ -28,6 +28,7 @@ import PlusView from './Views/PlusView';
import RewardsView from './Views/RewardsView';
import ProductsView from './Views/ProductsView';
import CreateAccountView from './Views/CreateAccountView';
import ForgotPasswordView from '../shared-components/ForgotPassword/ForgotPasswordContainer';
import LogInView from './Views/LogInView';

const store = createStore();
@@ -45,6 +46,7 @@ const Hub = () => (
<Route exact path="/rewards" component={RewardsView} />
<Route exact path="/products" component={ProductsView} />
<Route exact path="/create-account" component={CreateAccountView} />
<Route exact path="/forgot-password" render={() => <ForgotPasswordView locale="hub" />} />
<Route exact path="/log-in" component={LogInView} />
</AppView>
);
@@ -137,7 +137,7 @@ class Login extends React.Component {
<div className="small-11 medium-8 columns">
<div className="row">
<div className="small-6 columns text-center">
<Link to="/forgot-password">{ t('panel_forgot_password') }</Link>
<Link to="/forgot-password">{ t('forgot_password') }</Link>
</div>
<div className="small-6 columns text-center">
<Link to="/create-account">{ t('create_account') }</Link>
@@ -25,7 +25,7 @@ import Settings from './containers/SettingsContainer';
import Subscription from './containers/SubscriptionContainer';
import Login from './containers/LoginContainer';
import CreateAccount from './containers/CreateAccountContainer';
import ForgotPassword from './containers/ForgotPasswordContainer';
import ForgotPassword from '../shared-components/ForgotPassword/ForgotPasswordContainer';
import AccountSuccess from './containers/AccountSuccessContainer';
import configureStore from './store/configureStore';
import Help from './components/Help';
@@ -51,7 +51,7 @@ const Ghostery = () => (
<Route path="/subscribe/:loggedIn" component={Subscribe} />
<Route path="/login" component={Login} />
<Route path="/create-account" component={CreateAccount} />
<Route path="/forgot-password" component={ForgotPassword} />
<Route path="/forgot-password" render={() => <ForgotPassword locale="panel" />} />
<Route path="/account-success" component={AccountSuccess} />
</Panel>
);
@@ -81,3 +81,4 @@ html, body, #root {
@import '../shared-components/ToastMessage/ToastMessage.scss';
@import '../shared-components/ToggleCheckbox/ToggleCheckbox.scss';
@import '../shared-components/ToggleSwitch/ToggleSwitch.scss';
@import '../shared-components/ForgotPassword/ForgotPassword.scss';
@@ -81,3 +81,4 @@ html body {
// Imports from ../shared-components directory
@import '../shared-components/Modal/Modal.scss';
@import '../shared-components/PremiumPromoModal/PremiumPromoModal.scss';
@import '../shared-components/ForgotPassword/ForgotPassword.scss'
@@ -12,11 +12,11 @@
*/

import React from 'react';
import { Link } from 'react-router-dom';
import { withRouter, Link } from 'react-router-dom';
import ClassNames from 'classnames';
import { validateEmail } from '../utils/utils';
import { validateEmail } from '../../panel/utils/utils';
/**
* @class Implement Forgot Password view which opens from the link on Sign In panel.
* @class Implement shared Forgot Password view which opens from the link on Sign In page inside the panel and hub
* @memberof PanelClasses
*/
class ForgotPassword extends React.Component {
@@ -46,6 +46,7 @@ class ForgotPassword extends React.Component {
e.preventDefault();
this.setState({ loading: true }, () => {
const { email } = this.state;
const { locale } = this.props;

// validate the email and password
if (!validateEmail(email)) {
@@ -59,7 +60,14 @@ class ForgotPassword extends React.Component {
this.props.actions.resetPassword(email)
.then((success) => {
this.setState({ loading: false });
if (success) {
if (success && locale === 'hub') {
this.props.history.push('/log-in');

this.props.actions.setToast({
toastMessage: t('banner_check_your_email_title'),
toastClass: 'success',
});
} else if (success && locale === 'panel') {
this.props.history.push('/login');
}
});
@@ -72,20 +80,39 @@ class ForgotPassword extends React.Component {
*/
render() {
const { email, loading, emailError } = this.state;
const { locale } = this.props;
const buttonClasses = ClassNames('button ghostery-button', { loading });

const ContainerClassNames = ClassNames('', {
'forgot-password-panel': locale === 'panel',
ForgotPasswordView: locale === 'hub',
});
const MessageClassNames = ClassNames('', {
'forgot-password-message': locale === 'panel',
ForgotPasswordMessage: locale === 'hub',
});
const EmailClassNames = ClassNames('', {
'forgot-input-email': locale === 'panel',
ForgotPasswordMessage: locale === 'hub',
});

const ButtonsContainerClassNames = ClassNames('row', {
'buttons-container': locale === 'panel',
ForgotPasswordButtonsContainer: locale === 'hub',
});
return (
<div id="forgot-password-panel">
<div id={ContainerClassNames}>
<div className="row align-center">
<div className="small-11 medium-8 columns">
<form onSubmit={this.handleSubmit}>
<h4 id="forgot-password-message">
<h4 id={MessageClassNames}>
{ t('forgot_password_message') }
</h4>
<div id="forgot-email" className={(emailError ? 'panel-error invalid-email' : '')}>
<label htmlFor="forgot-input-email">
<label htmlFor={EmailClassNames}>
{ t('email_colon') }
<span className="asterisk">*</span>
<input onChange={this.handleInputChange} value={email} id="forgot-input-email" type="text" name="email" pattern=".{1,}" autoComplete="off" required />
<input onChange={this.handleInputChange} value={email} id={EmailClassNames} type="text" name="email" pattern=".{1,}" autoComplete="off" required />
</label>
<p className="invalid-email warning">
{ t('invalid_email_forgot') }
@@ -94,7 +121,7 @@ class ForgotPassword extends React.Component {
{ t('error_email_forgot') }
</p>
</div>
<div className="buttons-container row">
<div className={ButtonsContainerClassNames}>
<div className="small-6 columns text-center">
<Link to="/login" id="forgot-password-cancel" className="cancel button hollow">
{ t('button_cancel') }
@@ -115,4 +142,4 @@ class ForgotPassword extends React.Component {
}
}

export default ForgotPassword;
export default withRouter(ForgotPassword);
ProTip! Use n and p to navigate between commits in a pull request.