diff --git a/packages/web/src/components/ForgotPasswordForm/index.ee.tsx b/packages/web/src/components/ForgotPasswordForm/index.ee.tsx index 2fb21a05..69b362d8 100644 --- a/packages/web/src/components/ForgotPasswordForm/index.ee.tsx +++ b/packages/web/src/components/ForgotPasswordForm/index.ee.tsx @@ -34,12 +34,12 @@ export default function ForgotPasswordForm() { }} gutterBottom > - {formatMessage('forgotPassword.title')} + {formatMessage('forgotPasswordForm.title')}
- {formatMessage('forgotPassword.submit')} + {formatMessage('forgotPasswordForm.submit')} {data && theme.palette.success.main }}> - {formatMessage('forgotPassword.instructionsSent')} + {formatMessage('forgotPasswordForm.instructionsSent')} } diff --git a/packages/web/src/components/ResetPasswordForm/index.ee.tsx b/packages/web/src/components/ResetPasswordForm/index.ee.tsx new file mode 100644 index 00000000..3ec40073 --- /dev/null +++ b/packages/web/src/components/ResetPasswordForm/index.ee.tsx @@ -0,0 +1,122 @@ +import * as React from 'react'; +import { useSearchParams, useNavigate } from 'react-router-dom'; +import { useMutation } from '@apollo/client'; +import Paper from '@mui/material/Paper'; +import Typography from '@mui/material/Typography'; +import LoadingButton from '@mui/lab/LoadingButton'; +import { useSnackbar } from 'notistack'; +import * as yup from 'yup'; +import { yupResolver } from '@hookform/resolvers/yup'; + +import * as URLS from 'config/urls'; +import Form from 'components/Form'; +import TextField from 'components/TextField'; +import useFormatMessage from 'hooks/useFormatMessage'; +import { RESET_PASSWORD } from 'graphql/mutations/reset-password.ee'; + +const validationSchema = yup.object().shape({ + password: yup.string().required('resetPasswordForm.mandatoryInput'), + confirmPassword: yup + .string() + .required('resetPasswordForm.mandatoryInput') + .oneOf([yup.ref('password')], 'resetPasswordForm.passwordsMustMatch'), +}); + +export default function ResetPasswordForm() { + const { enqueueSnackbar } = useSnackbar(); + const formatMessage = useFormatMessage(); + const navigate = useNavigate(); + const [searchParams] = useSearchParams(); + const [resetPassword, { data, loading }] = useMutation(RESET_PASSWORD); + + const token = searchParams.get('token'); + + const handleSubmit = async (values: any) => { + await resetPassword({ + variables: { + input: { + password: values.password, + token, + }, + }, + }); + + enqueueSnackbar(formatMessage('resetPasswordForm.passwordUpdated'), { variant: 'success' }); + + navigate(URLS.LOGIN); + }; + + return ( + + theme.palette.text.disabled, + pb: 2, + mb: 2, + }} + gutterBottom + > + {formatMessage('resetPasswordForm.title')} + + +
( + <> + + + + + + {formatMessage('resetPasswordForm.submit')} + + + )} + /> + + ); +} diff --git a/packages/web/src/components/SignUpForm/index.ee.tsx b/packages/web/src/components/SignUpForm/index.ee.tsx index eb7a55f6..9c14c5e5 100644 --- a/packages/web/src/components/SignUpForm/index.ee.tsx +++ b/packages/web/src/components/SignUpForm/index.ee.tsx @@ -5,13 +5,13 @@ import Paper from '@mui/material/Paper'; import Typography from '@mui/material/Typography'; import LoadingButton from '@mui/lab/LoadingButton'; import * as yup from 'yup'; +import { yupResolver } from '@hookform/resolvers/yup'; import useAuthentication from 'hooks/useAuthentication'; import * as URLS from 'config/urls'; import { CREATE_USER } from 'graphql/mutations/create-user.ee'; import Form from 'components/Form'; import TextField from 'components/TextField'; -import { yupResolver } from '@hookform/resolvers/yup'; import { LOGIN } from 'graphql/mutations/login'; import useFormatMessage from 'hooks/useFormatMessage'; @@ -22,7 +22,7 @@ const validationSchema = yup.object().shape({ confirmPassword: yup .string() .required('signupForm.mandatoryInput') - .oneOf([yup.ref('password')], 'signupForm.passwordMustMatch'), + .oneOf([yup.ref('password')], 'signupForm.passwordsMustMatch'), }); const initialValues = { diff --git a/packages/web/src/config/urls.ts b/packages/web/src/config/urls.ts index be5e5ef7..5500a6ab 100644 --- a/packages/web/src/config/urls.ts +++ b/packages/web/src/config/urls.ts @@ -7,6 +7,7 @@ export const EXECUTION = (executionId: string): string => export const LOGIN = '/login'; export const SIGNUP = '/sign-up'; export const FORGOT_PASSWORD = '/forgot-password'; +export const RESET_PASSWORD = '/reset-password'; export const APPS = '/apps'; export const NEW_APP_CONNECTION = '/apps/new'; diff --git a/packages/web/src/graphql/mutations/reset-password.ee.ts b/packages/web/src/graphql/mutations/reset-password.ee.ts new file mode 100644 index 00000000..aaf991f6 --- /dev/null +++ b/packages/web/src/graphql/mutations/reset-password.ee.ts @@ -0,0 +1,7 @@ +import { gql } from '@apollo/client'; + +export const RESET_PASSWORD = gql` + mutation ResetPassword($input: ResetPasswordInput) { + resetPassword(input: $input) + } +`; diff --git a/packages/web/src/locales/en.json b/packages/web/src/locales/en.json index 32221d33..87192f13 100644 --- a/packages/web/src/locales/en.json +++ b/packages/web/src/locales/en.json @@ -112,7 +112,7 @@ "signupForm.passwordFieldLabel": "Password", "signupForm.confirmPasswordFieldLabel": "Confirm password", "signupForm.submit": "Sign up", - "signupForm.passwordMustMatch": "Passwords must match.", + "signupForm.passwordsMustMatch": "Passwords must match.", "signupForm.mandatoryInput": "{inputName} is required.", "loginForm.title": "Login", "loginForm.emailFieldLabel": "Email", @@ -121,8 +121,15 @@ "loginForm.submit": "Login", "loginForm.noAccount": "Don't have an Automatisch account yet?", "loginForm.signUp": "Sign up", - "forgotPassword.title": "Forgot password", - "forgotPassword.submit": "Send reset instructions", - "forgotPassword.instructionsSent": "The instructions have been sent!", - "forgotPassword.emailFieldLabel": "Email" + "forgotPasswordForm.title": "Forgot password", + "forgotPasswordForm.submit": "Send reset instructions", + "forgotPasswordForm.instructionsSent": "The instructions have been sent!", + "forgotPasswordForm.emailFieldLabel": "Email", + "resetPasswordForm.passwordsMustMatch": "Passwords must match.", + "resetPasswordForm.mandatoryInput": "{inputName} is required.", + "resetPasswordForm.title": "Reset password", + "resetPasswordForm.submit": "Reset password", + "resetPasswordForm.passwordFieldLabel": "Password", + "resetPasswordForm.confirmPasswordFieldLabel": "Confirm password", + "resetPasswordForm.passwordUpdated": "The password has been updated. Now, you can login." } \ No newline at end of file diff --git a/packages/web/src/pages/ForgotPassword/index.ee.tsx b/packages/web/src/pages/ForgotPassword/index.ee.tsx index 42e7093c..4b75e703 100644 --- a/packages/web/src/pages/ForgotPassword/index.ee.tsx +++ b/packages/web/src/pages/ForgotPassword/index.ee.tsx @@ -3,7 +3,7 @@ import Box from '@mui/material/Box'; import Container from 'components/Container'; import ForgotPasswordForm from 'components/ForgotPasswordForm/index.ee'; -export default function Login(): React.ReactElement { +export default function ForgotPassword(): React.ReactElement { return ( diff --git a/packages/web/src/pages/ResetPassword/index.ee.tsx b/packages/web/src/pages/ResetPassword/index.ee.tsx new file mode 100644 index 00000000..eb41213e --- /dev/null +++ b/packages/web/src/pages/ResetPassword/index.ee.tsx @@ -0,0 +1,14 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import Container from 'components/Container'; +import ResetPasswordForm from 'components/ResetPasswordForm/index.ee'; + +export default function ResetPassword(): React.ReactElement { + return ( + + + + + + ); +} diff --git a/packages/web/src/routes.tsx b/packages/web/src/routes.tsx index 2147cd95..c06b8467 100644 --- a/packages/web/src/routes.tsx +++ b/packages/web/src/routes.tsx @@ -10,6 +10,7 @@ import Flow from 'pages/Flow'; import Login from 'pages/Login'; import SignUp from 'pages/SignUp/index.ee'; import ForgotPassword from 'pages/ForgotPassword/index.ee'; +import ResetPassword from 'pages/ResetPassword/index.ee'; import EditorRoutes from 'pages/Editor/routes'; import * as URLS from 'config/urls'; import settingsRoutes from './settingsRoutes'; @@ -100,6 +101,15 @@ export default ( } /> + + + + } + /> +