mirror of
https://bitbucket.org/wisemapping/wisemapping-frontend.git
synced 2024-11-22 14:47:56 +01:00
Complete forgot password page.
This commit is contained in:
parent
bc3b7104dd
commit
bec0c7998c
@ -2,9 +2,10 @@ import React, { useEffect, useState } from 'react';
|
|||||||
import { Service, RestService } from './services/Service';
|
import { Service, RestService } from './services/Service';
|
||||||
import { IntlProvider } from 'react-intl'
|
import { IntlProvider } from 'react-intl'
|
||||||
|
|
||||||
import {GlobalStyle} from './theme/global-style';
|
import { GlobalStyle } from './theme/global-style';
|
||||||
import { RegistrationSuccessPage } from './components/registration-success-page';
|
import RegistrationSuccessPage from './components/registration-success-page';
|
||||||
import { RegistationPage } from './components/registration-page';
|
import ForgotPasswordSuccessPage from './components/forgot-password-success-page';
|
||||||
|
import RegistationPage from './components/registration-page';
|
||||||
import LoginPage from './components/login-page';
|
import LoginPage from './components/login-page';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -49,20 +50,23 @@ const App = () => {
|
|||||||
|
|
||||||
return messages ? (
|
return messages ? (
|
||||||
<IntlProvider locale={locale} defaultLocale='en' messages={messages}>
|
<IntlProvider locale={locale} defaultLocale='en' messages={messages}>
|
||||||
<GlobalStyle/>
|
<GlobalStyle />
|
||||||
<Router>
|
<Router>
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route exact path="/">
|
<Route exact path="/">
|
||||||
<Redirect to="/c/login" />
|
<Redirect to="/c/login" />
|
||||||
</Route>
|
</Route>
|
||||||
<Route path="/c/login" component={LoginPage} />
|
<Route path="/c/login" component={LoginPage} />
|
||||||
<Route path="/c/user/registration">
|
<Route path="/c/user/registration">
|
||||||
<RegistationPage service={service} />
|
<RegistationPage service={service} />
|
||||||
</Route>
|
</Route>
|
||||||
<Route path="/c/user/registrationSuccess" component={RegistrationSuccessPage} />
|
<Route path="/c/user/registrationSuccess" component={RegistrationSuccessPage} />
|
||||||
<Route path="/c/user/resetPassword" component={ForgotPasswordPage} />
|
<Route path="/c/user/resetPassword">
|
||||||
</Switch>
|
<ForgotPasswordPage service={service} />
|
||||||
</Router>
|
</Route>
|
||||||
|
<Route path="/c/user/forgotPasswordSuccess" component={ForgotPasswordSuccessPage} />
|
||||||
|
</Switch>
|
||||||
|
</Router>
|
||||||
</IntlProvider>
|
</IntlProvider>
|
||||||
) : <div>Loading ... </div>
|
) : <div>Loading ... </div>
|
||||||
}
|
}
|
||||||
|
@ -6,25 +6,17 @@ import { Service } from '../../services/Service'
|
|||||||
import { PageContent } from '../../theme/global-style';
|
import { PageContent } from '../../theme/global-style';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import Header from '../header'
|
import Header from '../header'
|
||||||
import Footer from '../footer'
|
import Footer from '../footer'
|
||||||
|
import FormErrorDialog from '../form-error-dialog'
|
||||||
|
|
||||||
import SubmitButton from '../submit-button'
|
import SubmitButton from '../submit-button'
|
||||||
|
|
||||||
interface ErrorMessageDialogProps {
|
|
||||||
message: string
|
|
||||||
}
|
|
||||||
|
|
||||||
const ErrorMessageDialog = (props: ErrorMessageDialogProps) => {
|
|
||||||
const message = props.message;
|
|
||||||
return message ? <p className='form-error-dialog'>{message}</p> : <span></span>;
|
|
||||||
}
|
|
||||||
|
|
||||||
type ForgotPasswordProps = {
|
type ForgotPasswordProps = {
|
||||||
email: string;
|
email: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const RegistrationForm = (props: ServiceProps) => {
|
const ForgotPassword = (props: ServiceProps) => {
|
||||||
const [email, setEmail] = useState("");
|
const [email, setEmail] = useState("");
|
||||||
const [errorMsg, setErrorMsg] = useState("");
|
const [errorMsg, setErrorMsg] = useState("");
|
||||||
|
|
||||||
@ -37,7 +29,6 @@ const RegistrationForm = (props: ServiceProps) => {
|
|||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
setDisableButton(true);
|
setDisableButton(true);
|
||||||
|
|
||||||
|
|
||||||
// Call Service ...
|
// Call Service ...
|
||||||
props.service.resetPassword(
|
props.service.resetPassword(
|
||||||
email,
|
email,
|
||||||
@ -51,10 +42,10 @@ const RegistrationForm = (props: ServiceProps) => {
|
|||||||
<h1><FormattedMessage id="forgot.title" defaultMessage="Reset your password" /></h1>
|
<h1><FormattedMessage id="forgot.title" defaultMessage="Reset your password" /></h1>
|
||||||
<p><FormattedMessage id="forgot.desc" defaultMessage="We will send you an email to reset your password" /></p>
|
<p><FormattedMessage id="forgot.desc" defaultMessage="We will send you an email to reset your password" /></p>
|
||||||
|
|
||||||
<form method="POST" onSubmit={e => handleSubmit(e)}>
|
<form onSubmit={e => handleSubmit(e)}>
|
||||||
<input type="email" name="email" onChange={e => setEmail(e.target.value)} placeholder={intl.formatMessage({ id: "forgot.email", defaultMessage: "Email" })} required={true} autoComplete="email" />
|
<input type="email" name="email" onChange={e => setEmail(e.target.value)} placeholder={intl.formatMessage({ id: "forgot.email", defaultMessage: "Email" })} required={true} autoComplete="email" />
|
||||||
|
|
||||||
<ErrorMessageDialog message={errorMsg} />
|
<FormErrorDialog message={errorMsg} />
|
||||||
|
|
||||||
<SubmitButton disabled={disableButton} value={intl.formatMessage({ id: "forgot.register", defaultMessage: "Send recovery link" })} />
|
<SubmitButton disabled={disableButton} value={intl.formatMessage({ id: "forgot.register", defaultMessage: "Send recovery link" })} />
|
||||||
</form>
|
</form>
|
||||||
@ -68,13 +59,13 @@ type ServiceProps = {
|
|||||||
const ForgotPasswordPage = (props: ServiceProps) => {
|
const ForgotPasswordPage = (props: ServiceProps) => {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
document.title = 'Forgot Password | WiseMapping';
|
document.title = 'Reset Password | WiseMapping';
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Header type='only-signin' />
|
<Header type='only-signin' />
|
||||||
<RegistrationForm service={props.service} />
|
<ForgotPassword service={props.service} />
|
||||||
<Footer />
|
<Footer />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -0,0 +1,36 @@
|
|||||||
|
import React, { useEffect } from 'react'
|
||||||
|
import { FormattedMessage } from 'react-intl'
|
||||||
|
|
||||||
|
import {PageContent} from '../../theme/global-style';
|
||||||
|
|
||||||
|
import Header, { SignInButton } from '../header'
|
||||||
|
import Footer from '../footer'
|
||||||
|
|
||||||
|
const ForgotPasswordSuccessPage = () => {
|
||||||
|
useEffect(() => {
|
||||||
|
document.title = 'Reset Password | WiseMapping';
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Header type='none' />
|
||||||
|
<div>
|
||||||
|
<PageContent>
|
||||||
|
<h1>
|
||||||
|
<FormattedMessage id="forgot.success.title" defaultMessage="Your temporal password has been sent" />
|
||||||
|
</h1>
|
||||||
|
<p>
|
||||||
|
<FormattedMessage id="forgot.success.desc" defaultMessage="We've sent you an email that will allow you to reset your password. Please check your email now." />
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<SignInButton style='style1' />
|
||||||
|
</PageContent>
|
||||||
|
</div>
|
||||||
|
<Footer />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ForgotPasswordSuccessPage
|
||||||
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
import React, { useEffect } from 'react'
|
import React from 'react'
|
||||||
import { StyleDiv } from './styled'
|
import { StyleDiv } from './styled'
|
||||||
|
|
||||||
type FormErrorDialogProps = {
|
type FormErrorDialogProps = {
|
||||||
|
@ -51,7 +51,7 @@ const RegistrationForm = (props: ServiceProps) => {
|
|||||||
<h1><FormattedMessage id="registration.title" defaultMessage="Become a member of our comunity" /></h1>
|
<h1><FormattedMessage id="registration.title" defaultMessage="Become a member of our comunity" /></h1>
|
||||||
<p><FormattedMessage id="registration.desc" defaultMessage="Signing up is free and just take a moment " /></p>
|
<p><FormattedMessage id="registration.desc" defaultMessage="Signing up is free and just take a moment " /></p>
|
||||||
|
|
||||||
<form method="POST" onSubmit={e => handleSubmit(e)}>
|
<form onSubmit={e => handleSubmit(e)}>
|
||||||
<input type="email" name="email" onChange={e => setEmail(e.target.value)} placeholder={intl.formatMessage({ id: "registration.email", defaultMessage: "Email" })} required={true} autoComplete="email" />
|
<input type="email" name="email" onChange={e => setEmail(e.target.value)} placeholder={intl.formatMessage({ id: "registration.email", defaultMessage: "Email" })} required={true} autoComplete="email" />
|
||||||
<input type="text" name="firstname" onChange={e => setFirstname(e.target.value)} placeholder={intl.formatMessage({ id: "registration.firstname", defaultMessage: "First Name" })} required={true} autoComplete="given-name" />
|
<input type="text" name="firstname" onChange={e => setFirstname(e.target.value)} placeholder={intl.formatMessage({ id: "registration.firstname", defaultMessage: "First Name" })} required={true} autoComplete="given-name" />
|
||||||
<input type="text" name="lastname" onChange={e => setLastname(e.target.value)} placeholder={intl.formatMessage({ id: "registration.lastname", defaultMessage: "Last Name" })} required={true} autoComplete="family-name" />
|
<input type="text" name="lastname" onChange={e => setLastname(e.target.value)} placeholder={intl.formatMessage({ id: "registration.lastname", defaultMessage: "Last Name" })} required={true} autoComplete="family-name" />
|
||||||
@ -93,6 +93,6 @@ const RegistationPage = (props: ServiceProps) => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export { RegistationPage }
|
export default RegistationPage;
|
||||||
|
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ import Footer from '../footer'
|
|||||||
|
|
||||||
const RegistrationSuccessPage = () => {
|
const RegistrationSuccessPage = () => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
document.title = 'Registration | WiseMapping';
|
document.title = 'Reset Password | WiseMapping';
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -19,7 +19,7 @@ const RegistrationSuccessPage = () => {
|
|||||||
<div>
|
<div>
|
||||||
<PageContent>
|
<PageContent>
|
||||||
<h1>
|
<h1>
|
||||||
<FormattedMessage id="registration.success.title" defaultMessage="Your account has been created successfully" />
|
<FormattedMessage id="resetpassword.success.title" defaultMessage="Your account has been created successfully" />
|
||||||
</h1>
|
</h1>
|
||||||
<p>
|
<p>
|
||||||
<FormattedMessage id="registration.success.desc" defaultMessage="Click 'Sign In' button below and start creating mind maps." />
|
<FormattedMessage id="registration.success.desc" defaultMessage="Click 'Sign In' button below and start creating mind maps." />
|
||||||
@ -33,6 +33,6 @@ const RegistrationSuccessPage = () => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export { RegistrationSuccessPage }
|
export default RegistrationSuccessPage;
|
||||||
|
|
||||||
|
|
||||||
|
@ -9,18 +9,11 @@ const SubmitButton = (props: SubmitButton) => {
|
|||||||
const [disabled, setDisabled] = useState(props.disabled ? true : false);
|
const [disabled, setDisabled] = useState(props.disabled ? true : false);
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
document.title = 'WiseMapping - Login';
|
|
||||||
});
|
|
||||||
|
|
||||||
let valueTxt = props.value;
|
let valueTxt = props.value;
|
||||||
if (disabled) {
|
if (disabled) {
|
||||||
valueTxt = intl.formatMessage({ id: "common.wait", defaultMessage: "Please wait ..." });
|
valueTxt = intl.formatMessage({ id: "common.wait", defaultMessage: "Please wait ..." });
|
||||||
}
|
}
|
||||||
const [value, setValue] = useState(valueTxt);
|
const [value, setValue] = useState(valueTxt);
|
||||||
|
|
||||||
console.log(disabled);
|
|
||||||
console.log(value);
|
|
||||||
return (
|
return (
|
||||||
<input type="submit" disabled={disabled} value={value} />
|
<input type="submit" disabled={disabled} value={value} />
|
||||||
);
|
);
|
||||||
|
@ -6,12 +6,12 @@ type NewUser = {
|
|||||||
lastname: string;
|
lastname: string;
|
||||||
password: string;
|
password: string;
|
||||||
recaptcha: string | null;
|
recaptcha: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
interface Service {
|
interface Service {
|
||||||
registerNewUser(user: NewUser, onSuccess: () => void, onError: (msg: string) => void): void;
|
registerNewUser(user: NewUser, onSuccess: () => void, onError: (msg: string) => void): void;
|
||||||
resetPassword(email:string, onSuccess: () => void, onError: (msg: string) => void): void;
|
resetPassword(email: string, onSuccess: () => void, onError: (msg: string) => void): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
class RestService implements Service {
|
class RestService implements Service {
|
||||||
@ -24,7 +24,7 @@ class RestService implements Service {
|
|||||||
|
|
||||||
async registerNewUser(user: NewUser, onSuccess: () => void, onError: (msg: string) => void) {
|
async registerNewUser(user: NewUser, onSuccess: () => void, onError: (msg: string) => void) {
|
||||||
|
|
||||||
await axios.post(this.baseUrl + '/service/user',
|
await axios.post(this.baseUrl + '/service/users',
|
||||||
JSON.stringify(user),
|
JSON.stringify(user),
|
||||||
{ headers: { 'Content-Type': 'application/json' } }
|
{ headers: { 'Content-Type': 'application/json' } }
|
||||||
).then(response => {
|
).then(response => {
|
||||||
@ -32,36 +32,61 @@ class RestService implements Service {
|
|||||||
onSuccess();
|
onSuccess();
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
const response = error.response;
|
const response = error.response;
|
||||||
let msg = '';
|
const errorMsg = this.parseResponseOnError(response);
|
||||||
if (response) {
|
onError(errorMsg);
|
||||||
const status: number = response.status;
|
|
||||||
const data = response.data;
|
|
||||||
|
|
||||||
switch (status) {
|
|
||||||
case 401:
|
|
||||||
this.authFailed();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
console.log(data);
|
|
||||||
// Is a server error ?
|
|
||||||
if (!data.fieldErrors) {
|
|
||||||
msg = response.statusText;
|
|
||||||
} else if (data) {
|
|
||||||
const fieldsError = data.fieldErrors;
|
|
||||||
msg = Object.values(fieldsError)[0] as string;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// Network related problem ...
|
|
||||||
msg = 'Unexpected error. Please, try latter';
|
|
||||||
}
|
|
||||||
onError(msg);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
resetPassword(email:string, onSuccess: () => void, onError: (msg: string) => void): void {
|
async resetPassword(email: string, onSuccess: () => void, onError: (msg: string) => void) {
|
||||||
|
await axios.put(this.baseUrl + '/service/users/resetPassword?email=' + email,
|
||||||
|
null,
|
||||||
|
{ headers: { 'Content-Type': 'application/json' } }
|
||||||
|
).then(response => {
|
||||||
|
// All was ok, let's sent to success page ...
|
||||||
|
onSuccess();
|
||||||
|
}).catch(error => {
|
||||||
|
const response = error.response;
|
||||||
|
const errorMsg = this.parseResponseOnError(response);
|
||||||
|
onError(errorMsg);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private parseResponseOnError = (response: any) => {
|
||||||
|
let msg;
|
||||||
|
if (response) {
|
||||||
|
const status: number = response.status;
|
||||||
|
const data = response.data;
|
||||||
|
console.log(data);
|
||||||
|
|
||||||
|
switch (status) {
|
||||||
|
case 401:
|
||||||
|
this.authFailed();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (data) {
|
||||||
|
let errors: string[] = [];
|
||||||
|
if (data.globalErrors) {
|
||||||
|
errors = data.globalErrors;
|
||||||
|
} else if (data.fieldErrors) {
|
||||||
|
errors = Object.values(data.fieldErrors);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errors.length > 0) {
|
||||||
|
msg = errors[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
msg = response.statusText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Network related problem ...
|
||||||
|
if (!msg) {
|
||||||
|
msg = 'Unexpected error. Please, try latter';
|
||||||
|
}
|
||||||
|
|
||||||
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -124,6 +124,10 @@ padding: 20px 10px 20px 10px;
|
|||||||
background-color: #f9a826;
|
background-color: #f9a826;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
& label {
|
||||||
|
font-size:15px;
|
||||||
|
}
|
||||||
|
|
||||||
& input:placeholder {
|
& input:placeholder {
|
||||||
color: grey;
|
color: grey;
|
||||||
}
|
}
|
||||||
@ -147,7 +151,7 @@ padding: 20px 10px 20px 10px;
|
|||||||
}
|
}
|
||||||
|
|
||||||
& a {
|
& a {
|
||||||
font-size: 17px;
|
font-size: 15px;
|
||||||
color: #f9a826;
|
color: #f9a826;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||||
const HtmlWebpackDynamicEnvPlugin = require('html-webpack-dynamic-env-plugin');
|
|
||||||
|
|
||||||
const webpack = require('webpack');
|
const webpack = require('webpack');
|
||||||
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
|
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
|
||||||
@ -17,13 +16,11 @@ module.exports = {
|
|||||||
extensions: ['.ts', '.tsx', '.js', '.jsx']
|
extensions: ['.ts', '.tsx', '.js', '.jsx']
|
||||||
},
|
},
|
||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [{
|
||||||
|
|
||||||
{
|
|
||||||
test: /\.tsx?$/,
|
test: /\.tsx?$/,
|
||||||
use: 'ts-loader',
|
use: 'ts-loader',
|
||||||
exclude: '/node_modules/'
|
exclude: '/node_modules/'
|
||||||
}, ,
|
},
|
||||||
{
|
{
|
||||||
test: /\.(png|jpe?g|gif|svg)$/,
|
test: /\.(png|jpe?g|gif|svg)$/,
|
||||||
use: [{
|
use: [{
|
||||||
@ -31,7 +28,7 @@ module.exports = {
|
|||||||
options: {
|
options: {
|
||||||
esModule: false,
|
esModule: false,
|
||||||
}
|
}
|
||||||
}, ],
|
}]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user