Client - add password reset - #50
This commit is contained in:
parent
51d627fa1c
commit
1860cfe320
3
Makefile
3
Makefile
@ -69,6 +69,9 @@ lint-react:
|
|||||||
lint-react-fix:
|
lint-react-fix:
|
||||||
$(NPM) lint-fix
|
$(NPM) lint-fix
|
||||||
|
|
||||||
|
mail:
|
||||||
|
docker run -d -e "MH_STORAGE=maildir" -v /tmp/maildir:/maildir -p 1025:1025 -p 8025:8025 mailhog/mailhog
|
||||||
|
|
||||||
migrate-db:
|
migrate-db:
|
||||||
$(FLASK) db migrate --directory $(MIGRATIONS)
|
$(FLASK) db migrate --directory $(MIGRATIONS)
|
||||||
|
|
||||||
|
@ -46,15 +46,27 @@ export const getProfile = () => dispatch =>
|
|||||||
throw error
|
throw error
|
||||||
})
|
})
|
||||||
|
|
||||||
export const loginOrRegister = (target, formData) => dispatch =>
|
export const loginOrRegisterOrPasswordReset = (target, formData) => dispatch =>
|
||||||
FitTrackeeApi.loginOrRegister(target, formData)
|
FitTrackeeApi.loginOrRegisterOrPasswordReset(target, formData)
|
||||||
.then(ret => {
|
.then(ret => {
|
||||||
if (ret.status === 'success') {
|
if (ret.status === 'success') {
|
||||||
window.localStorage.setItem('authToken', ret.auth_token)
|
if (target === 'password/reset-request') {
|
||||||
if (target === 'register') {
|
return history.push({
|
||||||
dispatch(getAppData('config'))
|
pathname: '/password-reset/sent',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (target === 'password/update') {
|
||||||
|
return history.push({
|
||||||
|
pathname: '/updated-password',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (target === 'login' || target === 'register') {
|
||||||
|
window.localStorage.setItem('authToken', ret.auth_token)
|
||||||
|
if (target === 'register') {
|
||||||
|
dispatch(getAppData('config'))
|
||||||
|
}
|
||||||
|
return dispatch(getProfile())
|
||||||
}
|
}
|
||||||
return dispatch(getProfile())
|
|
||||||
}
|
}
|
||||||
return dispatch(AuthError(ret.message))
|
return dispatch(AuthError(ret.message))
|
||||||
})
|
})
|
||||||
@ -62,9 +74,12 @@ export const loginOrRegister = (target, formData) => dispatch =>
|
|||||||
throw error
|
throw error
|
||||||
})
|
})
|
||||||
|
|
||||||
const RegisterFormControl = formData => {
|
const RegisterFormControl = (formData, onlyPasswords = false) => {
|
||||||
const errMsg = []
|
const errMsg = []
|
||||||
if (formData.username.length < 3 || formData.username.length > 12) {
|
if (
|
||||||
|
!onlyPasswords &&
|
||||||
|
(formData.username.length < 3 || formData.username.length > 12)
|
||||||
|
) {
|
||||||
errMsg.push('3 to 12 characters required for username.')
|
errMsg.push('3 to 12 characters required for username.')
|
||||||
}
|
}
|
||||||
if (formData.password !== formData.password_conf) {
|
if (formData.password !== formData.password_conf) {
|
||||||
@ -77,13 +92,13 @@ const RegisterFormControl = formData => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const handleUserFormSubmit = (formData, formType) => dispatch => {
|
export const handleUserFormSubmit = (formData, formType) => dispatch => {
|
||||||
if (formType === 'register') {
|
if (formType === 'register' || formType === 'password/update') {
|
||||||
const ret = RegisterFormControl(formData)
|
const ret = RegisterFormControl(formData, formType === 'password/update')
|
||||||
if (ret.length > 0) {
|
if (ret.length > 0) {
|
||||||
return dispatch(AuthErrors(generateIds(ret)))
|
return dispatch(AuthErrors(generateIds(ret)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return dispatch(loginOrRegister(formType, formData))
|
return dispatch(loginOrRegisterOrPasswordReset(formType, formData))
|
||||||
}
|
}
|
||||||
|
|
||||||
export const handleProfileFormSubmit = formData => dispatch => {
|
export const handleProfileFormSubmit = formData => dispatch => {
|
||||||
|
@ -312,7 +312,6 @@ label {
|
|||||||
.dropdown-item {
|
.dropdown-item {
|
||||||
cursor: default;
|
cursor: default;
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.dropdown-item-selected {
|
.dropdown-item-selected {
|
||||||
@ -437,6 +436,12 @@ label {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.password-forget {
|
||||||
|
margin: 10px;
|
||||||
|
font-size: .9em;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
.radioLabel {
|
.radioLabel {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
@ -467,6 +472,14 @@ label {
|
|||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.svg-icon {
|
||||||
|
fill: #405976;
|
||||||
|
height: 70px;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
width: 70px;
|
||||||
|
}
|
||||||
|
|
||||||
.time-frames {
|
.time-frames {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
|
@ -12,6 +12,7 @@ import Footer from './Footer'
|
|||||||
import Logout from './User/Logout'
|
import Logout from './User/Logout'
|
||||||
import NavBar from './NavBar'
|
import NavBar from './NavBar'
|
||||||
import NotFound from './Others/NotFound'
|
import NotFound from './Others/NotFound'
|
||||||
|
import PasswordReset from './User/PasswordReset'
|
||||||
import ProfileEdit from './User/ProfileEdit'
|
import ProfileEdit from './User/ProfileEdit'
|
||||||
import Statistics from './Statistics'
|
import Statistics from './Statistics'
|
||||||
import UserForm from './User/UserForm'
|
import UserForm from './User/UserForm'
|
||||||
@ -43,6 +44,27 @@ class App extends React.Component {
|
|||||||
path="/login"
|
path="/login"
|
||||||
render={() => <UserForm formType={'login'} />}
|
render={() => <UserForm formType={'login'} />}
|
||||||
/>
|
/>
|
||||||
|
<Route
|
||||||
|
exact
|
||||||
|
path="/password-reset"
|
||||||
|
render={() => <UserForm formType={'password reset'} />}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
exact
|
||||||
|
path="/password-reset/request"
|
||||||
|
render={() => <UserForm formType={'reset your password'} />}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
exact
|
||||||
|
path="/password-reset/sent"
|
||||||
|
render={() => <PasswordReset action={'sent'} />}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
exact
|
||||||
|
path="/updated-password"
|
||||||
|
render={() => <PasswordReset action={'updated'} />}
|
||||||
|
/>
|
||||||
|
<Route exact path="/password-reset/sent" component={PasswordReset} />
|
||||||
<Route exact path="/logout" component={Logout} />
|
<Route exact path="/logout" component={Logout} />
|
||||||
<Route exact path="/profile/edit" component={ProfileEdit} />
|
<Route exact path="/profile/edit" component={ProfileEdit} />
|
||||||
<Route exact path="/profile" component={CurrentUserProfile} />
|
<Route exact path="/profile" component={CurrentUserProfile} />
|
||||||
|
@ -101,7 +101,7 @@ class NavBar extends React.PureComponent {
|
|||||||
pathname: '/register',
|
pathname: '/register',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{t('common:Register')}
|
{t('user:Register')}
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
)}
|
)}
|
||||||
@ -113,7 +113,7 @@ class NavBar extends React.PureComponent {
|
|||||||
pathname: '/login',
|
pathname: '/login',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{t('common:Login')}
|
{t('user:Login')}
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
)}
|
)}
|
||||||
@ -148,7 +148,7 @@ class NavBar extends React.PureComponent {
|
|||||||
pathname: '/logout',
|
pathname: '/logout',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{t('common:Logout')}
|
{t('user:Logout')}
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
</>
|
</>
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { Helmet } from 'react-helmet'
|
import { Helmet } from 'react-helmet'
|
||||||
|
import { Link } from 'react-router-dom'
|
||||||
|
|
||||||
import { history } from '../../index'
|
import { history } from '../../index'
|
||||||
|
|
||||||
export default function Form(props) {
|
export default function Form(props) {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const pageTitle = `common:${props.formType
|
const pageTitle = `user:${props.formType
|
||||||
.charAt(0)
|
.charAt(0)
|
||||||
.toUpperCase()}${props.formType.slice(1)}`
|
.toUpperCase()}${props.formType.slice(1)}`
|
||||||
return (
|
return (
|
||||||
@ -34,65 +35,86 @@ export default function Form(props) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<form
|
<>
|
||||||
onSubmit={event =>
|
<form
|
||||||
props.handleUserFormSubmit(event, props.formType)
|
onSubmit={event =>
|
||||||
}
|
props.handleUserFormSubmit(event, props.formType)
|
||||||
>
|
}
|
||||||
{props.formType === 'register' && (
|
>
|
||||||
<div className="form-group">
|
{props.formType === 'register' && (
|
||||||
<input
|
<div className="form-group">
|
||||||
className="form-control input-lg"
|
<input
|
||||||
name="username"
|
className="form-control input-lg"
|
||||||
placeholder={t('user:Enter a username')}
|
name="username"
|
||||||
required
|
placeholder={t('user:Enter a username')}
|
||||||
type="text"
|
required
|
||||||
value={props.userForm.username}
|
type="text"
|
||||||
onChange={props.onHandleFormChange}
|
value={props.userForm.username}
|
||||||
/>
|
onChange={props.onHandleFormChange}
|
||||||
</div>
|
/>
|
||||||
)}
|
</div>
|
||||||
<div className="form-group">
|
)}
|
||||||
|
{props.formType !== 'password reset' && (
|
||||||
|
<div className="form-group">
|
||||||
|
<input
|
||||||
|
className="form-control input-lg"
|
||||||
|
name="email"
|
||||||
|
placeholder={t('user:Enter an email address')}
|
||||||
|
required
|
||||||
|
type="email"
|
||||||
|
value={props.userForm.email}
|
||||||
|
onChange={props.onHandleFormChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{props.formType !== 'reset your password' && (
|
||||||
|
<>
|
||||||
|
<div className="form-group">
|
||||||
|
<input
|
||||||
|
className="form-control input-lg"
|
||||||
|
name="password"
|
||||||
|
placeholder={t('user:Enter a password')}
|
||||||
|
required
|
||||||
|
type="password"
|
||||||
|
value={props.userForm.password}
|
||||||
|
onChange={props.onHandleFormChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{props.formType !== 'login' && (
|
||||||
|
<div className="form-group">
|
||||||
|
<input
|
||||||
|
className="form-control input-lg"
|
||||||
|
name="password_conf"
|
||||||
|
placeholder={t(
|
||||||
|
'user:Enter the password confirmation'
|
||||||
|
)}
|
||||||
|
required
|
||||||
|
type="password"
|
||||||
|
value={props.userForm.password_conf}
|
||||||
|
onChange={props.onHandleFormChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
<input
|
<input
|
||||||
className="form-control input-lg"
|
type="submit"
|
||||||
name="email"
|
className="btn btn-primary btn-lg btn-block"
|
||||||
placeholder={t('user:Enter an email address')}
|
value={t('Submit')}
|
||||||
required
|
|
||||||
type="email"
|
|
||||||
value={props.userForm.email}
|
|
||||||
onChange={props.onHandleFormChange}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</form>
|
||||||
<div className="form-group">
|
<p className="password-forget">
|
||||||
<input
|
{props.formType === 'login' && (
|
||||||
className="form-control input-lg"
|
<Link
|
||||||
name="password"
|
to={{
|
||||||
placeholder={t('user:Enter a password')}
|
pathname: '/password-reset/request',
|
||||||
required
|
}}
|
||||||
type="password"
|
>
|
||||||
value={props.userForm.password}
|
{t('user:Forgot password?')}
|
||||||
onChange={props.onHandleFormChange}
|
</Link>
|
||||||
/>
|
)}
|
||||||
</div>
|
</p>
|
||||||
{props.formType === 'register' && (
|
</>
|
||||||
<div className="form-group">
|
|
||||||
<input
|
|
||||||
className="form-control input-lg"
|
|
||||||
name="password_conf"
|
|
||||||
placeholder={t('user:Enter the password confirmation')}
|
|
||||||
required
|
|
||||||
type="password"
|
|
||||||
value={props.userForm.password_conf}
|
|
||||||
onChange={props.onHandleFormChange}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
<input
|
|
||||||
type="submit"
|
|
||||||
className="btn btn-primary btn-lg btn-block"
|
|
||||||
value={t('Submit')}
|
|
||||||
/>
|
|
||||||
</form>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="col-md-3" />
|
<div className="col-md-3" />
|
||||||
|
48
fittrackee_client/src/components/User/PasswordReset.jsx
Normal file
48
fittrackee_client/src/components/User/PasswordReset.jsx
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import { Trans, useTranslation } from 'react-i18next'
|
||||||
|
import { Link } from 'react-router-dom'
|
||||||
|
|
||||||
|
import { ReactComponent as Password } from '../../images/password.svg'
|
||||||
|
import { ReactComponent as MailSend } from '../../images/mail-send.svg'
|
||||||
|
|
||||||
|
export default function PasswordReset(props) {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
const { action } = props
|
||||||
|
return (
|
||||||
|
<div className="container dashboard">
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-2" />
|
||||||
|
<div className="card col-8">
|
||||||
|
<div className="card-body">
|
||||||
|
<div className="text-center ">
|
||||||
|
{action === 'sent' && (
|
||||||
|
<>
|
||||||
|
<div className="svg-icon">
|
||||||
|
<MailSend />
|
||||||
|
</div>
|
||||||
|
{t(
|
||||||
|
// eslint-disable-next-line max-len
|
||||||
|
"user:Check your email. If your address is in our database, you'll received an email with a link to reset your password."
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{action === 'updated' && (
|
||||||
|
<>
|
||||||
|
<div className="svg-icon">
|
||||||
|
<Password />
|
||||||
|
</div>
|
||||||
|
<Trans i18nKey="user:updatedPasswordText">
|
||||||
|
{/* prettier-ignore */}
|
||||||
|
Your password have been updated. Click
|
||||||
|
<Link to="/login">here</Link> to log in.
|
||||||
|
</Trans>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="col-2" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
@ -49,9 +49,10 @@ class UserForm extends React.Component {
|
|||||||
t,
|
t,
|
||||||
} = this.props
|
} = this.props
|
||||||
const { formData } = this.state
|
const { formData } = this.state
|
||||||
|
const { token } = this.props.location.query
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{isLoggedIn() ? (
|
{isLoggedIn() || (formType === 'password reset' && !token) ? (
|
||||||
<Redirect to="/" />
|
<Redirect to="/" />
|
||||||
) : (
|
) : (
|
||||||
<div>
|
<div>
|
||||||
@ -63,6 +64,9 @@ class UserForm extends React.Component {
|
|||||||
onHandleFormChange={event => this.onHandleFormChange(event)}
|
onHandleFormChange={event => this.onHandleFormChange(event)}
|
||||||
handleUserFormSubmit={event => {
|
handleUserFormSubmit={event => {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
if (formType === 'password reset') {
|
||||||
|
formData.token = token
|
||||||
|
}
|
||||||
onHandleUserFormSubmit(formData, formType)
|
onHandleUserFormSubmit(formData, formType)
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@ -82,6 +86,12 @@ export default withTranslation()(
|
|||||||
}),
|
}),
|
||||||
dispatch => ({
|
dispatch => ({
|
||||||
onHandleUserFormSubmit: (formData, formType) => {
|
onHandleUserFormSubmit: (formData, formType) => {
|
||||||
|
formType =
|
||||||
|
formType === 'password reset'
|
||||||
|
? 'password/update'
|
||||||
|
: formType === 'reset your password'
|
||||||
|
? 'password/reset-request'
|
||||||
|
: formType
|
||||||
dispatch(handleUserFormSubmit(formData, formType))
|
dispatch(handleUserFormSubmit(formData, formType))
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { createApiRequest } from '../utils'
|
import { createApiRequest } from '../utils'
|
||||||
|
|
||||||
export default class FitTrackeeApi {
|
export default class FitTrackeeApi {
|
||||||
static loginOrRegister(target, data) {
|
static loginOrRegisterOrPasswordReset(target, data) {
|
||||||
const params = {
|
const params = {
|
||||||
url: `auth/${target}`,
|
url: `auth/${target}`,
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
|
42
fittrackee_client/src/images/mail-send.svg
Normal file
42
fittrackee_client/src/images/mail-send.svg
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 17.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 345.834 345.834" style="enable-background:new 0 0 345.834 345.834;" xml:space="preserve">
|
||||||
|
<g>
|
||||||
|
<path d="M339.798,260.429c0.13-0.026,0.257-0.061,0.385-0.094c0.109-0.028,0.219-0.051,0.326-0.084
|
||||||
|
c0.125-0.038,0.247-0.085,0.369-0.129c0.108-0.039,0.217-0.074,0.324-0.119c0.115-0.048,0.226-0.104,0.338-0.157
|
||||||
|
c0.109-0.052,0.22-0.1,0.327-0.158c0.107-0.057,0.208-0.122,0.312-0.184c0.107-0.064,0.215-0.124,0.319-0.194
|
||||||
|
c0.111-0.074,0.214-0.156,0.321-0.236c0.09-0.067,0.182-0.13,0.27-0.202c0.162-0.133,0.316-0.275,0.466-0.421
|
||||||
|
c0.027-0.026,0.056-0.048,0.083-0.075c0.028-0.028,0.052-0.059,0.079-0.088c0.144-0.148,0.284-0.3,0.416-0.46
|
||||||
|
c0.077-0.094,0.144-0.192,0.216-0.289c0.074-0.1,0.152-0.197,0.221-0.301c0.074-0.111,0.139-0.226,0.207-0.34
|
||||||
|
c0.057-0.096,0.118-0.19,0.171-0.289c0.062-0.115,0.114-0.234,0.169-0.351c0.049-0.104,0.101-0.207,0.146-0.314
|
||||||
|
c0.048-0.115,0.086-0.232,0.128-0.349c0.041-0.114,0.085-0.227,0.12-0.343c0.036-0.118,0.062-0.238,0.092-0.358
|
||||||
|
c0.029-0.118,0.063-0.234,0.086-0.353c0.028-0.141,0.045-0.283,0.065-0.425c0.014-0.1,0.033-0.199,0.043-0.3
|
||||||
|
c0.025-0.249,0.038-0.498,0.038-0.748V92.76c0-4.143-3.357-7.5-7.5-7.5h-236.25c-0.066,0-0.13,0.008-0.196,0.01
|
||||||
|
c-0.143,0.004-0.285,0.01-0.427,0.022c-0.113,0.009-0.225,0.022-0.337,0.037c-0.128,0.016-0.255,0.035-0.382,0.058
|
||||||
|
c-0.119,0.021-0.237,0.046-0.354,0.073c-0.119,0.028-0.238,0.058-0.356,0.092c-0.117,0.033-0.232,0.069-0.346,0.107
|
||||||
|
c-0.117,0.04-0.234,0.082-0.349,0.128c-0.109,0.043-0.216,0.087-0.322,0.135c-0.118,0.053-0.235,0.11-0.351,0.169
|
||||||
|
c-0.099,0.051-0.196,0.103-0.292,0.158c-0.116,0.066-0.23,0.136-0.343,0.208c-0.093,0.06-0.184,0.122-0.274,0.185
|
||||||
|
c-0.106,0.075-0.211,0.153-0.314,0.235c-0.094,0.075-0.186,0.152-0.277,0.231c-0.09,0.079-0.179,0.158-0.266,0.242
|
||||||
|
c-0.099,0.095-0.194,0.194-0.288,0.294c-0.047,0.05-0.097,0.094-0.142,0.145c-0.027,0.03-0.048,0.063-0.074,0.093
|
||||||
|
c-0.094,0.109-0.182,0.223-0.27,0.338c-0.064,0.084-0.13,0.168-0.19,0.254c-0.078,0.112-0.15,0.227-0.222,0.343
|
||||||
|
c-0.059,0.095-0.12,0.189-0.174,0.286c-0.063,0.112-0.118,0.227-0.175,0.342c-0.052,0.105-0.106,0.21-0.153,0.317
|
||||||
|
c-0.049,0.113-0.092,0.23-0.135,0.345c-0.043,0.113-0.087,0.225-0.124,0.339c-0.037,0.115-0.067,0.232-0.099,0.349
|
||||||
|
c-0.032,0.12-0.066,0.239-0.093,0.36c-0.025,0.113-0.042,0.228-0.062,0.342c-0.022,0.13-0.044,0.26-0.06,0.39
|
||||||
|
c-0.013,0.108-0.019,0.218-0.027,0.328c-0.01,0.14-0.019,0.28-0.021,0.421c-0.001,0.041-0.006,0.081-0.006,0.122v46.252
|
||||||
|
c0,4.143,3.357,7.5,7.5,7.5s7.5-3.357,7.5-7.5v-29.595l66.681,59.037c-0.348,0.245-0.683,0.516-0.995,0.827l-65.687,65.687v-49.288
|
||||||
|
c0-4.143-3.357-7.5-7.5-7.5s-7.5,3.357-7.5,7.5v9.164h-38.75c-4.143,0-7.5,3.357-7.5,7.5s3.357,7.5,7.5,7.5h38.75v43.231
|
||||||
|
c0,4.143,3.357,7.5,7.5,7.5h236.25c0.247,0,0.494-0.013,0.74-0.037c0.115-0.011,0.226-0.033,0.339-0.049
|
||||||
|
C339.542,260.469,339.67,260.454,339.798,260.429z M330.834,234.967l-65.688-65.687c-0.042-0.042-0.087-0.077-0.13-0.117
|
||||||
|
l49.383-41.897c3.158-2.68,3.546-7.412,0.866-10.571c-2.678-3.157-7.41-3.547-10.571-0.866l-84.381,71.59l-98.444-87.158h208.965
|
||||||
|
V234.967z M185.878,179.888c0.535-0.535,0.969-1.131,1.308-1.765l28.051,24.835c1.418,1.255,3.194,1.885,4.972,1.885
|
||||||
|
c1.726,0,3.451-0.593,4.853-1.781l28.587-24.254c0.26,0.38,0.553,0.743,0.89,1.08l65.687,65.687H120.191L185.878,179.888z"/>
|
||||||
|
<path d="M7.5,170.676h126.667c4.143,0,7.5-3.357,7.5-7.5s-3.357-7.5-7.5-7.5H7.5c-4.143,0-7.5,3.357-7.5,7.5
|
||||||
|
S3.357,170.676,7.5,170.676z"/>
|
||||||
|
<path d="M20.625,129.345H77.5c4.143,0,7.5-3.357,7.5-7.5s-3.357-7.5-7.5-7.5H20.625c-4.143,0-7.5,3.357-7.5,7.5
|
||||||
|
S16.482,129.345,20.625,129.345z"/>
|
||||||
|
<path d="M62.5,226.51h-55c-4.143,0-7.5,3.357-7.5,7.5s3.357,7.5,7.5,7.5h55c4.143,0,7.5-3.357,7.5-7.5S66.643,226.51,62.5,226.51z"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 4.0 KiB |
65
fittrackee_client/src/images/password.svg
Normal file
65
fittrackee_client/src/images/password.svg
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 512.001 512.001" style="enable-background:new 0 0 512.001 512.001;" xml:space="preserve">
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<path d="M468.683,287.265h-69.07c-4.147,0-7.508,3.361-7.508,7.508c0,4.147,3.361,7.508,7.508,7.508h69.07
|
||||||
|
c4.147,0,7.508-3.361,7.508-7.508C476.191,290.626,472.83,287.265,468.683,287.265z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<path d="M105.012,268.377L85.781,256l19.231-12.376c3.487-2.243,4.495-6.888,2.251-10.376c-2.244-3.486-6.888-4.497-10.376-2.25
|
||||||
|
l-17.471,11.243v-20.776c0-4.147-3.361-7.508-7.508-7.508c-4.147,0-7.508,3.361-7.508,7.508v20.775l-17.47-11.243
|
||||||
|
c-3.486-2.245-8.132-1.238-10.376,2.25c-2.245,3.487-1.237,8.133,2.25,10.376L58.034,256l-19.231,12.376
|
||||||
|
c-3.487,2.244-4.495,6.889-2.25,10.376c1.435,2.23,3.852,3.446,6.32,3.446c1.391,0,2.799-0.386,4.056-1.196l17.47-11.243v20.775
|
||||||
|
c0,4.147,3.361,7.508,7.508,7.508c4.147,0,7.508-3.361,7.508-7.508V269.76l17.471,11.243c1.257,0.809,2.664,1.196,4.056,1.196
|
||||||
|
c2.467,0,4.885-1.216,6.32-3.446C109.507,275.266,108.499,270.62,105.012,268.377z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<path d="M194.441,268.377L175.21,256l19.231-12.376c3.487-2.244,4.495-6.889,2.25-10.376c-2.245-3.486-6.888-4.497-10.376-2.25
|
||||||
|
l-17.47,11.243v-20.775c0-4.147-3.361-7.508-7.508-7.508c-4.147,0-7.508,3.361-7.508,7.508v20.776l-17.471-11.243
|
||||||
|
c-3.487-2.245-8.133-1.238-10.376,2.25c-2.245,3.487-1.237,8.133,2.25,10.376L147.463,256l-19.231,12.376
|
||||||
|
c-3.487,2.244-4.495,6.889-2.25,10.376c1.435,2.23,3.852,3.446,6.32,3.446c1.391,0,2.799-0.386,4.056-1.196l17.471-11.243v20.776
|
||||||
|
c0,4.147,3.361,7.508,7.508,7.508c4.147,0,7.508-3.361,7.508-7.508V269.76l17.47,11.243c1.257,0.809,2.664,1.196,4.056,1.196
|
||||||
|
c2.467,0,4.885-1.216,6.32-3.446C198.936,275.266,197.928,270.62,194.441,268.377z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<path d="M283.871,268.377L264.64,256l19.231-12.376c3.487-2.243,4.495-6.888,2.251-10.376c-2.245-3.486-6.888-4.497-10.376-2.25
|
||||||
|
l-17.471,11.243v-20.775c0-4.147-3.361-7.508-7.508-7.508c-4.147,0-7.508,3.361-7.508,7.508v20.775l-17.471-11.243
|
||||||
|
c-3.486-2.245-8.134-1.238-10.376,2.25c-2.245,3.487-1.237,8.133,2.25,10.376L236.892,256l-19.231,12.376
|
||||||
|
c-3.487,2.244-4.495,6.889-2.25,10.376c1.435,2.23,3.852,3.446,6.32,3.446c1.391,0,2.799-0.386,4.056-1.196l17.471-11.243v20.775
|
||||||
|
c0,4.147,3.361,7.508,7.508,7.508c4.147,0,7.508-3.361,7.508-7.508V269.76l17.471,11.243c1.257,0.809,2.664,1.196,4.056,1.196
|
||||||
|
c2.467,0,4.886-1.216,6.32-3.446C288.366,275.266,287.358,270.62,283.871,268.377z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<path d="M373.3,268.377L354.069,256l19.231-12.376c3.487-2.244,4.495-6.889,2.25-10.376c-2.244-3.486-6.888-4.497-10.376-2.25
|
||||||
|
l-17.471,11.243v-20.776c0-4.147-3.361-7.508-7.508-7.508c-4.147,0-7.508,3.361-7.508,7.508v20.775l-17.47-11.243
|
||||||
|
c-3.486-2.245-8.132-1.238-10.376,2.25c-2.245,3.487-1.237,8.133,2.25,10.376L326.322,256l-19.231,12.376
|
||||||
|
c-3.487,2.244-4.495,6.889-2.25,10.376c1.435,2.23,3.852,3.446,6.32,3.446c1.391,0,2.799-0.386,4.056-1.196l17.47-11.243v20.776
|
||||||
|
c0,4.147,3.361,7.508,7.508,7.508c4.147,0,7.508-3.361,7.508-7.508V269.76l17.471,11.243c1.257,0.809,2.664,1.196,4.056,1.196
|
||||||
|
c2.467,0,4.885-1.216,6.32-3.446C377.795,275.266,376.787,270.62,373.3,268.377z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<path d="M271.792,330.359H15.016V181.642h93.1c4.147,0,7.508-3.361,7.508-7.508c0-4.147-3.361-7.508-7.508-7.508H12.513
|
||||||
|
C5.613,166.626,0,172.24,0,179.14v153.722c0,6.9,5.613,12.513,12.513,12.513h259.278c4.147,0,7.508-3.361,7.508-7.508
|
||||||
|
C279.299,333.72,275.939,330.359,271.792,330.359z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<path d="M499.487,166.626H162.174c-4.147,0-7.508,3.361-7.508,7.508c0,4.147,3.361,7.508,7.508,7.508h334.811v148.716H323.848
|
||||||
|
c-4.147,0-7.508,3.361-7.508,7.508c0,4.147,3.361,7.508,7.508,7.508h175.64c6.9,0,12.513-5.613,12.513-12.513V179.14
|
||||||
|
C512.001,172.24,506.387,166.626,499.487,166.626z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 4.0 KiB |
@ -12,8 +12,6 @@
|
|||||||
"Edit": "Edit",
|
"Edit": "Edit",
|
||||||
"day": "day",
|
"day": "day",
|
||||||
"days": "days",
|
"days": "days",
|
||||||
"Login": "Login",
|
|
||||||
"Logout": "Logout",
|
|
||||||
"Next": "Next",
|
"Next": "Next",
|
||||||
"No": "No",
|
"No": "No",
|
||||||
"no": "no",
|
"no": "no",
|
||||||
@ -21,7 +19,6 @@
|
|||||||
"No workouts.": "No workouts.",
|
"No workouts.": "No workouts.",
|
||||||
"Page not found": "Page not found",
|
"Page not found": "Page not found",
|
||||||
"Previous": "Prev",
|
"Previous": "Prev",
|
||||||
"Register": "Register",
|
|
||||||
"registration date": "registration date",
|
"registration date": "registration date",
|
||||||
"Sort": "Sort",
|
"Sort": "Sort",
|
||||||
"Sort by": "Sort by",
|
"Sort by": "Sort by",
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
"Are you sure you want to delete your account? All data will be deleted, this cannot be undone.": "Are you sure you want to delete your account? All data will be deleted, this cannot be undone.",
|
"Are you sure you want to delete your account? All data will be deleted, this cannot be undone.": "Are you sure you want to delete your account? All data will be deleted, this cannot be undone.",
|
||||||
"Bio": "Bio",
|
"Bio": "Bio",
|
||||||
"Birth Date": "Birth Date",
|
"Birth Date": "Birth Date",
|
||||||
|
"Check your email. If your address is in our database, you'll received an email with a link to reset your password.": "Check your email. If your address is in our database, you'll received an email with a link to reset your password.",
|
||||||
"Delete my account": "Delete my account",
|
"Delete my account": "Delete my account",
|
||||||
"Delete picture": "Delete picture",
|
"Delete picture": "Delete picture",
|
||||||
"Delete user account": "Delete user account",
|
"Delete user account": "Delete user account",
|
||||||
@ -15,20 +16,30 @@
|
|||||||
"Enter the password confirmation": "Enter the password confirmation",
|
"Enter the password confirmation": "Enter the password confirmation",
|
||||||
"First day of week": "First day of week",
|
"First day of week": "First day of week",
|
||||||
"First Name": "First Name",
|
"First Name": "First Name",
|
||||||
|
"Forgot password?": "Forgot password?",
|
||||||
|
"Invalid token. Please request a new token.": "Invalid token. Please request a new token.",
|
||||||
"Language": "Language",
|
"Language": "Language",
|
||||||
"Last Name": "Last Name",
|
"Last Name": "Last Name",
|
||||||
"Location": "Location",
|
"Location": "Location",
|
||||||
"loggedOut": "You are now logged out. Click <1>here</1> to log back in.",
|
"loggedOut": "You are now logged out. Click <1>here</1> to log back in.",
|
||||||
|
"Login": "Login",
|
||||||
"login": "login",
|
"login": "login",
|
||||||
|
"Logout": "Logout",
|
||||||
"Monday": "Monday",
|
"Monday": "Monday",
|
||||||
"Password": "Password",
|
"Password": "Password",
|
||||||
"Password Confirmation": "Password Confirmation",
|
"Password Confirmation": "Password Confirmation",
|
||||||
|
"Password reset": "Password reset",
|
||||||
|
"password reset": "password reset",
|
||||||
"Profile": "Profile",
|
"Profile": "Profile",
|
||||||
"Profile Edition": "Profile Edition",
|
"Profile Edition": "Profile Edition",
|
||||||
|
"Register": "Register",
|
||||||
"register": "register",
|
"register": "register",
|
||||||
"Registration Date": "Registration Date",
|
"Registration Date": "Registration Date",
|
||||||
|
"Reset your password": "Reset your password",
|
||||||
|
"reset your password": "reset your password",
|
||||||
"Send": "Send",
|
"Send": "Send",
|
||||||
"Sunday": "Sunday",
|
"Sunday": "Sunday",
|
||||||
"Timezone": "Timezone",
|
"Timezone": "Timezone",
|
||||||
|
"updatedPasswordText": "Your password have been updated. Click <1>here</1> to log in." ,
|
||||||
"Username": "Username"
|
"Username": "Username"
|
||||||
}
|
}
|
||||||
|
@ -12,8 +12,6 @@
|
|||||||
"Edit": "Modifier",
|
"Edit": "Modifier",
|
||||||
"day": "jour",
|
"day": "jour",
|
||||||
"days": "jours",
|
"days": "jours",
|
||||||
"Login": "Se connecter",
|
|
||||||
"Logout": "Se déconnecter",
|
|
||||||
"Next": "Page suivante",
|
"Next": "Page suivante",
|
||||||
"No": "Non",
|
"No": "Non",
|
||||||
"no": "non",
|
"no": "non",
|
||||||
@ -21,7 +19,6 @@
|
|||||||
"No workouts.": "Pas d'activités.",
|
"No workouts.": "Pas d'activités.",
|
||||||
"Page not found": "Page introuvable",
|
"Page not found": "Page introuvable",
|
||||||
"Previous": "Page précédente",
|
"Previous": "Page précédente",
|
||||||
"Register": "S'inscrire",
|
|
||||||
"registration date": "date d'inscription",
|
"registration date": "date d'inscription",
|
||||||
"Sort": "Tri",
|
"Sort": "Tri",
|
||||||
"Sort by": "Trier par",
|
"Sort by": "Trier par",
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
"Are you sure you want to delete your account? All data will be deleted, this cannot be undone.": "Etes-vous sûr de vouloir supprimer votre compte ? Toutes les données seront définitivement effacés.",
|
"Are you sure you want to delete your account? All data will be deleted, this cannot be undone.": "Etes-vous sûr de vouloir supprimer votre compte ? Toutes les données seront définitivement effacés.",
|
||||||
"Bio": "Bio",
|
"Bio": "Bio",
|
||||||
"Birth Date": "Date de naissance",
|
"Birth Date": "Date de naissance",
|
||||||
|
"Check your email. If your address is in our database, you'll received an email with a link to reset your password.": "Vérifiez vore boite mail. Si vote adresse est dans notre base de données, vous recevrez un email avec un lien pour réinitialiser votre mot de passe",
|
||||||
"Delete my account": "Supprimer mon compte",
|
"Delete my account": "Supprimer mon compte",
|
||||||
"Delete picture": "Supprimer l'image",
|
"Delete picture": "Supprimer l'image",
|
||||||
"Delete user account": "Supprimer le compte",
|
"Delete user account": "Supprimer le compte",
|
||||||
@ -15,20 +16,30 @@
|
|||||||
"Enter the password confirmation": "Confirmer le mot de passe",
|
"Enter the password confirmation": "Confirmer le mot de passe",
|
||||||
"First day of week": "Premier jour de la semaine",
|
"First day of week": "Premier jour de la semaine",
|
||||||
"First Name": "Prénom",
|
"First Name": "Prénom",
|
||||||
|
"Forgot password?": "Mot de passe oublié ?",
|
||||||
|
"Invalid token. Please request a new token.": "Token invalid. Veuillez demander un nouveau token.",
|
||||||
"Language": "Langue",
|
"Language": "Langue",
|
||||||
"Last Name": "Nom",
|
"Last Name": "Nom",
|
||||||
"Location": "Lieu",
|
"Location": "Lieu",
|
||||||
"loggedOut": "Vous êtes déconnecté. Cliquez <1>ici</1> pour vous reconnecter.",
|
"loggedOut": "Vous êtes déconnecté. Cliquez <1>ici</1> pour vous reconnecter.",
|
||||||
|
"Login": "Se connecter",
|
||||||
"login": "se connecter",
|
"login": "se connecter",
|
||||||
|
"Logout": "Se déconnecter",
|
||||||
"Monday": "Lundi",
|
"Monday": "Lundi",
|
||||||
"Password": "Mot de passe",
|
"Password": "Mot de passe",
|
||||||
"Password Confirmation": "Confirmation du mot de passe",
|
"Password Confirmation": "Confirmation du mot de passe",
|
||||||
|
"Password reset": "Réinitialiser votre mot de passe",
|
||||||
|
"password reset": "réinitialiser votre mot de passe",
|
||||||
"Profile": "Profil",
|
"Profile": "Profil",
|
||||||
"Profile Edition": "Edition du profil",
|
"Profile Edition": "Edition du profil",
|
||||||
|
"Register": "S'inscrire",
|
||||||
"register": "s'inscrire",
|
"register": "s'inscrire",
|
||||||
"Registration Date": "Date d'inscription",
|
"Registration Date": "Date d'inscription",
|
||||||
|
"Reset your password": "Réinitialiser votre mot de passe",
|
||||||
|
"reset your password": "réinitialiser votre mot de passe",
|
||||||
"Send": "Envoyer",
|
"Send": "Envoyer",
|
||||||
"Sunday": "Dimanche",
|
"Sunday": "Dimanche",
|
||||||
"Timezone": "Fuseau horaire",
|
"Timezone": "Fuseau horaire",
|
||||||
|
"updatedPasswordText": "Votre mot de passe a été mis à jour. Cliquez <1>ici</1> pour vous connecter.",
|
||||||
"Username": "Nom d'utilisateur"
|
"Username": "Nom d'utilisateur"
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,12 @@
|
|||||||
|
const routesWithoutAuthentication = [
|
||||||
|
'/login',
|
||||||
|
'/register',
|
||||||
|
'/password-reset',
|
||||||
|
'/password-reset/request',
|
||||||
|
'/password-reset/sent',
|
||||||
|
'/updated-password',
|
||||||
|
]
|
||||||
|
|
||||||
const updatePath = (toPath, newPath) => {
|
const updatePath = (toPath, newPath) => {
|
||||||
if (typeof toPath === 'string' || toPath instanceof String) {
|
if (typeof toPath === 'string' || toPath instanceof String) {
|
||||||
toPath = newPath
|
toPath = newPath
|
||||||
@ -10,13 +19,13 @@ const updatePath = (toPath, newPath) => {
|
|||||||
const pathInterceptor = toPath => {
|
const pathInterceptor = toPath => {
|
||||||
if (
|
if (
|
||||||
!window.localStorage.authToken &&
|
!window.localStorage.authToken &&
|
||||||
!['/login', '/register'].includes(toPath.pathname)
|
!routesWithoutAuthentication.includes(toPath.pathname)
|
||||||
) {
|
) {
|
||||||
toPath = updatePath(toPath, '/login')
|
toPath = updatePath(toPath, '/login')
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
window.localStorage.authToken &&
|
window.localStorage.authToken &&
|
||||||
['/login', '/register'].includes(toPath.pathname)
|
routesWithoutAuthentication.includes(toPath.pathname)
|
||||||
) {
|
) {
|
||||||
toPath = updatePath(toPath, '/')
|
toPath = updatePath(toPath, '/')
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user