From 913670f0d0140a941eb3031f612d7d13d91dec7c Mon Sep 17 00:00:00 2001 From: Tisha Soumya Date: Fri, 23 Aug 2024 10:14:12 +0530 Subject: [PATCH] Refactor Change password (#5044) --- packages/volto/news/5044.feature | 1 + .../manage/Preferences/ChangePassword.jsx | 266 +++++++----------- .../Preferences/ChangePassword.stories.jsx | 41 +++ 3 files changed, 136 insertions(+), 172 deletions(-) create mode 100644 packages/volto/news/5044.feature create mode 100644 packages/volto/src/components/manage/Preferences/ChangePassword.stories.jsx diff --git a/packages/volto/news/5044.feature b/packages/volto/news/5044.feature new file mode 100644 index 0000000000..60833498c6 --- /dev/null +++ b/packages/volto/news/5044.feature @@ -0,0 +1 @@ +Refactor Preference/Change Password from class to functional component. @Tishasoumya-02 diff --git a/packages/volto/src/components/manage/Preferences/ChangePassword.jsx b/packages/volto/src/components/manage/Preferences/ChangePassword.jsx index 994a6aa632..62c87e13b2 100644 --- a/packages/volto/src/components/manage/Preferences/ChangePassword.jsx +++ b/packages/volto/src/components/manage/Preferences/ChangePassword.jsx @@ -1,25 +1,16 @@ -/** - * Change password component. - * @module components/manage/Preferences/ChangePassword - */ - -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, withRouter } from 'react-router-dom'; +import { useSelector, useDispatch, shallowEqual } from 'react-redux'; +import { Link, useHistory, useLocation } from 'react-router-dom'; +import { defineMessages, useIntl } from 'react-intl'; import { createPortal } from 'react-dom'; -import { defineMessages, injectIntl } from 'react-intl'; import { Container } from 'semantic-ui-react'; import jwtDecode from 'jwt-decode'; import { toast } from 'react-toastify'; -import { Icon, Toast, Toolbar } from '@plone/volto/components'; -import { Form } from '@plone/volto/components/manage/Form'; +import { Helmet } from '@plone/volto/helpers'; +import { useClient } from '@plone/volto/hooks'; +import { Form, Icon, Toast, Toolbar } from '@plone/volto/components'; import { updatePassword } from '@plone/volto/actions'; import { getBaseUrl } from '@plone/volto/helpers'; - import backSVG from '@plone/volto/icons/back.svg'; const messages = defineMessages({ @@ -70,169 +61,100 @@ const messages = defineMessages({ }, }); -/** - * ChangePassword class. - * @class ChangePassword - * @extends Component - */ -class ChangePassword extends Component { - /** - * Property types. - * @property {Object} propTypes Property types. - * @static - */ - static propTypes = { - userId: PropTypes.string.isRequired, - loading: PropTypes.bool.isRequired, - updatePassword: PropTypes.func.isRequired, - pathname: PropTypes.string.isRequired, - }; - - /** - * Constructor - * @method constructor - * @param {Object} props Component properties - * @constructs ChangePassword - */ - constructor(props) { - super(props); - this.onCancel = this.onCancel.bind(this); - this.onSubmit = this.onSubmit.bind(this); - this.state = { isClient: false }; - } +const ChangePassword = () => { + const intl = useIntl(); + const dispatch = useDispatch(); + const isClient = useClient(); - /** - * Component did mount - * @method componentDidMount - * @returns {undefined} - */ - componentDidMount() { - this.setState({ isClient: true }); - } + const userId = useSelector( + (state) => + state.userSession.token ? jwtDecode(state.userSession.token).sub : '', + shallowEqual, + ); + const loading = useSelector((state) => state.users.update_password.loading); + const { pathname } = useLocation(); + const history = useHistory(); - /** - * Submit handler - * @method onSubmit - * @param {object} data Form data. - * @returns {undefined} - */ - onSubmit(data) { + const onSubmit = (data) => { if (data.newPassword === data.newPasswordRepeat) { - this.props.updatePassword( - this.props.userId, - data.oldPassword, - data.newPassword, - ); - toast.success( - , + dispatch(updatePassword(userId, data.oldPassword, data.newPassword)).then( + () => { + toast.success( + , + ); + }, ); } - } + }; - /** - * Cancel handler - * @method onCancel - * @returns {undefined} - */ - onCancel() { - this.props.history.goBack(); - } + const onCancel = () => { + history.goBack(); + }; - /** - * Render method. - * @method render - * @returns {string} Markup for the component. - */ - render() { - return ( - - -
+ + - {this.state.isClient && - createPortal( - - - - } - />, - document.getElementById('toolbar'), - )} - - ); - } -} + ], + properties: { + oldPassword: { + description: intl.formatMessage(messages.oldPasswordDescription), + title: intl.formatMessage(messages.oldPasswordTitle), + type: 'string', + widget: 'password', + }, + newPassword: { + description: intl.formatMessage(messages.newPasswordDescription), + title: intl.formatMessage(messages.newPasswordTitle), + type: 'string', + widget: 'password', + }, + newPasswordRepeat: { + description: intl.formatMessage( + messages.newPasswordRepeatDescription, + ), + title: intl.formatMessage(messages.newPasswordRepeatTitle), + type: 'string', + widget: 'password', + }, + }, + required: ['oldPassword', 'newPassword', 'newPasswordRepeat'], + }} + onSubmit={onSubmit} + onCancel={onCancel} + loading={loading} + /> + {isClient && + createPortal( + + + + } + />, + document.getElementById('toolbar'), + )} + + ); +}; -export default compose( - withRouter, - injectIntl, - connect( - (state, props) => ({ - userId: state.userSession.token - ? jwtDecode(state.userSession.token).sub - : '', - loading: state.users.update_password.loading, - pathname: props.location.pathname, - }), - { updatePassword }, - ), -)(ChangePassword); +export default ChangePassword; diff --git a/packages/volto/src/components/manage/Preferences/ChangePassword.stories.jsx b/packages/volto/src/components/manage/Preferences/ChangePassword.stories.jsx new file mode 100644 index 0000000000..8a7b090aad --- /dev/null +++ b/packages/volto/src/components/manage/Preferences/ChangePassword.stories.jsx @@ -0,0 +1,41 @@ +import { injectIntl } from 'react-intl'; +import React from 'react'; +import ChangePasswordComponent from './ChangePassword'; +import { RealStoreWrapper as Wrapper } from '@plone/volto/storybook'; +const IntlChangePasswordComponent = injectIntl(ChangePasswordComponent); + +function StoryComponent(args) { + return ( + +
+ + + ); +} + +export const ChangePassword = StoryComponent.bind({}); + +export default { + title: 'Public components/ChangePassword', + component: ChangePassword, + decorators: [ + (Story) => ( +
+ +
+ ), + ], + argTypes: {}, +};