Skip to content
This repository has been archived by the owner on Nov 23, 2022. It is now read-only.

Commit

Permalink
fix: customize password reset routes until we use Volto 16 (volto #34…
Browse files Browse the repository at this point in the history
…48) (#602)
  • Loading branch information
cekk authored Oct 27, 2022
1 parent 59bebef commit 40ac240
Show file tree
Hide file tree
Showing 3 changed files with 355 additions and 0 deletions.
6 changes: 6 additions & 0 deletions src/config/italiaConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,12 @@ export default function applyConfig(voltoConfig) {
},
videoAllowExternalsDefault: false,
showTrasparenzaFields: false,
// TO DO: DA RIMUOVERE QUANDO AGGIORNIAMO A VOLTO16
nonContentRoutes: [
...config.settings.nonContentRoutes,
/\/passwordreset\/.*$/,
'/passwordreset',
],
};

/******************************************************************************
Expand Down
326 changes: 326 additions & 0 deletions src/customizations/volto/components/theme/Login/Login.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,326 @@
/**
* Login container.
* @module components/theme/Login/Login
* TO DO: DA RIMUOVERE QUANDO AGGIORNIAMO A VOLTO16
*/

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Helmet } from '@plone/volto/helpers';
import { connect } from 'react-redux';
import { compose } from 'redux';
import { Link } from 'react-router-dom';
import {
Container,
Button,
Form,
Input,
Segment,
Grid,
} from 'semantic-ui-react';
import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
import qs from 'query-string';
import { withRouter } from 'react-router-dom';

import { Icon } from '@plone/volto/components';
import { login } from '@plone/volto/actions';
import { toast } from 'react-toastify';
import { Toast } from '@plone/volto/components';

import aheadSVG from '@plone/volto/icons/ahead.svg';
import clearSVG from '@plone/volto/icons/clear.svg';

import config from '@plone/volto/registry';

const messages = defineMessages({
login: {
id: 'Log in',
defaultMessage: 'Log in',
},
loginName: {
id: 'Login Name',
defaultMessage: 'Login Name',
},
Login: {
id: 'Login',
defaultMessage: 'Login',
},
password: {
id: 'Password',
defaultMessage: 'Password',
},
cancel: {
id: 'Cancel',
defaultMessage: 'Cancel',
},
error: {
id: 'Error',
defaultMessage: 'Error',
},
loginFailed: {
id: 'Login Failed',
defaultMessage: 'Login Failed',
},
loginFailedContent: {
id:
'Both email address and password are case sensitive, check that caps lock is not enabled.',
defaultMessage:
'Both email address and password are case sensitive, check that caps lock is not enabled.',
},
register: {
id: 'Register',
defaultMessage: 'Register',
},
forgotPassword: {
id: 'box_forgot_password_option',
defaultMessage: 'Forgot your password?',
},
});

/**
* Login class.
* @class Login
* @extends Component
*/
class Login extends Component {
/**
* Property types.
* @property {Object} propTypes Property types.
* @static
*/
static propTypes = {
login: PropTypes.func.isRequired,
error: PropTypes.shape({
message: PropTypes.string,
}),
loading: PropTypes.bool,
token: PropTypes.string, // eslint-disable-line react/no-unused-prop-types
returnUrl: PropTypes.string,
};

/**
* Default properties.
* @property {Object} defaultProps Default properties.
* @static
*/
static defaultProps = {
error: null,
loading: null,
token: null,
returnUrl: null,
};

/**
* Constructor
* @method constructor
* @param {Object} props Component properties
* @constructs WysiwygEditor
*/
constructor(props) {
super(props);
this.onLogin = this.onLogin.bind(this);
}

/**
* Component will receive props
* @method componentWillReceiveProps
* @param {Object} nextProps Next properties
* @returns {undefined}
*/
UNSAFE_componentWillReceiveProps(nextProps) {
if (nextProps.token) {
this.props.history.push(this.props.returnUrl || '/');
if (toast.isActive('loginFailed')) {
toast.dismiss('loginFailed');
}
}
if (nextProps.error) {
if (!toast.isActive('loginFailed')) {
toast.error(
<Toast
error
title={this.props.intl.formatMessage(messages.loginFailed)}
content={this.props.intl.formatMessage(messages.loginFailedContent)}
/>,
{ autoClose: false, toastId: 'loginFailed' },
);
}
}
}

componentWillUnmount() {
if (toast.isActive('loginFailed')) {
toast.dismiss('loginFailed');
}
}

/**
* On login handler
* @method onLogin
* @param {Object} event Event object.
* @returns {undefined}
*/
onLogin(event) {
this.props.login(
document.getElementsByName('login')[0].value,
document.getElementsByName('password')[0].value,
);
event.preventDefault();
}

/**
* Render method.
* @method render
* @returns {string} Markup for the component.
*/
render() {
return (
<div id="page-login">
<Helmet title={this.props.intl.formatMessage(messages.Login)} />
<Container text>
<Form method="post" onSubmit={this.onLogin}>
<Segment.Group raised>
<Segment className="primary">
<FormattedMessage id="Log In" defaultMessage="Login" />
</Segment>
<Segment secondary>
<FormattedMessage
id="Sign in to start session"
defaultMessage="Sign in to start session"
/>
</Segment>
<Segment className="form">
<Form.Field inline className="help">
<Grid>
<Grid.Row stretched>
<Grid.Column width="4">
<div className="wrapper">
<label htmlFor="login">
<FormattedMessage
id="Login Name"
defaultMessage="Login Name"
/>
</label>
</div>
</Grid.Column>
<Grid.Column width="8">
{/* eslint-disable jsx-a11y/no-autofocus */}
<Input
id="login"
name="login"
placeholder={this.props.intl.formatMessage(
messages.loginName,
)}
autoFocus
/>
</Grid.Column>
</Grid.Row>
</Grid>
</Form.Field>
<Form.Field inline className="help">
<Grid>
<Grid.Row stretched>
<Grid.Column stretched width="4">
<div className="wrapper">
<label htmlFor="password">
<FormattedMessage
id="Password"
defaultMessage="Password"
/>
</label>
</div>
</Grid.Column>
<Grid.Column stretched width="8">
<Input
type="password"
id="password"
name="password"
placeholder={this.props.intl.formatMessage(
messages.password,
)}
tabIndex={0}
/>
</Grid.Column>
</Grid.Row>
</Grid>
</Form.Field>
<Form.Field inline className="help">
<Grid>
<Grid.Row stretched>
{config.settings.showSelfRegistration && (
<Grid.Column stretched width="12">
<p className="help">
<Link to="/register">
{this.props.intl.formatMessage(messages.register)}
</Link>
</p>
</Grid.Column>
)}
<Grid.Column stretched width="12">
<p className="help">
<Link to="/passwordreset">
{this.props.intl.formatMessage(
messages.forgotPassword,
)}
</Link>
</p>
</Grid.Column>
</Grid.Row>
</Grid>
</Form.Field>
</Segment>
<Segment className="actions" clearing>
<Button
basic
primary
icon
floated="right"
type="submit"
id="login-form-submit"
aria-label={this.props.intl.formatMessage(messages.login)}
title={this.props.intl.formatMessage(messages.login)}
loading={this.props.loading}
>
<Icon className="circled" name={aheadSVG} size="30px" />
</Button>

<Button
basic
secondary
icon
floated="right"
id="login-form-cancel"
as={Link}
to="/"
aria-label={this.props.intl.formatMessage(messages.cancel)}
title={this.props.intl.formatMessage(messages.cancel)}
>
<Icon className="circled" name={clearSVG} size="30px" />
</Button>
</Segment>
</Segment.Group>
</Form>
</Container>
</div>
);
}
}

export default compose(
withRouter,
injectIntl,
connect(
(state, props) => ({
error: state.userSession.login.error,
loading: state.userSession.login.loading,
token: state.userSession.token,
returnUrl:
qs.parse(props.location.search).return_url ||
props.location.pathname
.replace(/\/login$/, '')
.replace(/\/logout$/, '') ||
'/',
}),
{ login },
),
)(Login);
23 changes: 23 additions & 0 deletions src/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import { App, Search, Contents } from '@plone/volto/components';
import { defaultRoutes, multilingualRoutes } from '@plone/volto/routes';
import { PasswordReset, RequestPasswordReset } from '@plone/volto/components'; // TO DO: DA RIMUOVERE QUANDO AGGIORNIAMO A VOLTO16
import config from '@plone/volto/registry';

export const italiaRoutes = [
Expand All @@ -18,6 +19,28 @@ export const italiaRoutes = [
path: ['/contents', '/**/contents'],
component: Contents,
},
{
path: `/(${config.settings?.supportedLanguages.join('|')})/passwordreset`,
component: RequestPasswordReset,
exact: true,
},
{
path: `/(${config.settings?.supportedLanguages.join(
'|',
)})/passwordreset/:token`,
component: PasswordReset,
exact: true,
},
{
path: '/passwordreset',
component: RequestPasswordReset,
exact: true,
},
{
path: '/passwordreset/:token',
component: PasswordReset,
exact: true,
},
];

/**
Expand Down

0 comments on commit 40ac240

Please sign in to comment.