diff --git a/frontend/app/components/ForgotPassword/ForgotPassword.js b/frontend/app/components/ForgotPassword/ForgotPassword.js index 1cd40c679..1ab158c1a 100644 --- a/frontend/app/components/ForgotPassword/ForgotPassword.js +++ b/frontend/app/components/ForgotPassword/ForgotPassword.js @@ -14,21 +14,23 @@ const LOGIN = loginRoute(); const recaptchaRef = React.createRef(); const ERROR_DONT_MATCH = "Passwords don't match."; const MIN_LENGTH = 8; -const PASSWORD_POLICY = `Password should contain at least ${ MIN_LENGTH } symbols.`; +const PASSWORD_POLICY = `Password should contain at least ${MIN_LENGTH} symbols.`; const checkDontMatch = (newPassword, newPasswordRepeat) => newPasswordRepeat.length > 0 && newPasswordRepeat !== newPassword; @connect( (state, props) => ({ - errors: state.getIn([ 'user', 'requestResetPassowrd', 'errors' ]), - resetErrors: state.getIn([ 'user', 'resetPassword', 'errors' ]), - loading: state.getIn([ 'user', 'requestResetPassowrd', 'loading' ]) || state.getIn([ 'user', 'resetPassword', 'loading' ]), - params: new URLSearchParams(props.location.search) + errors: state.getIn(['user', 'requestResetPassowrd', 'errors']), + resetErrors: state.getIn(['user', 'resetPassword', 'errors']), + loading: + state.getIn(['user', 'requestResetPassowrd', 'loading']) || + state.getIn(['user', 'resetPassword', 'loading']), + params: new URLSearchParams(props.location.search), }), - { requestResetPassword, resetPassword, resetErrors }, + { requestResetPassword, resetPassword, resetErrors } ) -@withPageTitle("Password Reset - OpenReplay") +@withPageTitle('Password Reset - OpenReplay') @withRouter export default class ForgotPassword extends React.PureComponent { state = { @@ -45,15 +47,17 @@ export default class ForgotPassword extends React.PureComponent { const { email, password } = this.state; const { params } = this.props; - const pass = params.get('pass') - const invitation = params.get('invitation') - const resetting = pass && invitation + const pass = params.get('pass'); + const invitation = params.get('invitation'); + const resetting = pass && invitation; if (!resetting) { - this.props.requestResetPassword({ email: email.trim(), 'g-recaptcha-response': token }).then(() => { - const { errors } = this.props; - if (!errors) this.setState({ requested: true }); - }); + this.props + .requestResetPassword({ email: email.trim(), 'g-recaptcha-response': token }) + .then(() => { + const { errors } = this.props; + if (!errors) this.setState({ requested: true }); + }); } else { if (this.isSubmitDisabled()) return; this.props.resetPassword({ email: email.trim(), invitation, pass, password }).then(() => { @@ -61,16 +65,15 @@ export default class ForgotPassword extends React.PureComponent { if (!resetErrors) this.setState({ updated: true }); }); } - } + }; isSubmitDisabled() { const { password, passwordRepeat } = this.state; - if (password !== passwordRepeat || - password.length < MIN_LENGTH) return true; + if (password !== passwordRepeat || password.length < MIN_LENGTH) return true; return false; } - write = ({ target: { value, name } }) => this.setState({ [ name ]: value }) + write = ({ target: { value, name } }) => this.setState({ [name]: value }); shouldShouwPolicy() { const { password } = this.state; @@ -79,152 +82,170 @@ export default class ForgotPassword extends React.PureComponent { return true; } - onSubmit = e => { + onSubmit = (e) => { e.preventDefault(); const { CAPTCHA_ENABLED } = this.state; if (CAPTCHA_ENABLED && recaptchaRef.current) { - recaptchaRef.current.execute() + recaptchaRef.current.execute(); } else if (!CAPTCHA_ENABLED) { this.handleSubmit(); } - } + }; componentWillUnmount() { - this.props.resetErrors() + this.props.resetErrors(); } render() { const { CAPTCHA_ENABLED } = this.state; const { errors, loading, params } = this.props; const { requested, updated, password, passwordRepeat, email } = this.state; - const dontMatch = checkDontMatch(password, passwordRepeat); - - const pass = params.get('pass') - const invitation = params.get('invitation') - const resetting = pass && invitation - const validEmail = validateEmail(email) + const dontMatch = checkDontMatch(password, passwordRepeat); + + const pass = params.get('pass'); + const invitation = params.get('invitation'); + const resetting = pass && invitation; + const validEmail = validateEmail(email); return ( -
-
-
- +
+
+
+
-
-
-
Welcome Back!
-
-
-
-
-
-
-

{`${resetting ? 'Create' : 'Reset'} Password`}

-
- -
- { CAPTCHA_ENABLED && ( -
- this.handleSubmit(token) } - /> -
- )} +
+

+ { resetting ? "Create Password" : "Reset Password" } +

- { !resetting && !requested && - - - - - } - - { - requested && !errors && ( -
Reset password link has been sent to your email.
- ) - } - - { - resetting && ( - - - - + {resetting &&
Provide your email address, so we can send you a link to reset your password.
} + + {/*
+

{`${ + resetting ? 'Create' : 'Reset' + } Password`}

+
*/} + +
+ {CAPTCHA_ENABLED && ( +
+ this.handleSubmit(token)} /> - -
- { PASSWORD_POLICY }
+ )} + + {!resetting && !requested && ( - + - - ) - } + )} - -
- -
- { errors && -
- { errors.map(error => { error }
) } + {requested && !errors && ( +
+
+ +
+
Alright! a reset link was emailed to {email}. Click on it to reset your account password.
+
+ )} + + {resetting && ( + + + + + +
+ {PASSWORD_POLICY} +
+ + + + +
+ )} + + +
+ +
+ {errors && ( +
+ {errors.map((error) => ( + + {error} +
+
+ ))} +
+ )} +
+ + {'Your password has been updated sucessfully.'} +
- } -
- - { 'Your password has been updated sucessfully.' } -
-
- {/*
*/} - {!(updated || requested) && ( - - )} -
- - { updated && ()} -
{'Back to Login'}
- -
- {/*
*/} - + {!(updated || requested) && ( + + )} + +
+ + {updated && ( + + )} +
{'Back to Login'}
+ +
+ +
+
); diff --git a/frontend/app/components/Login/Login.js b/frontend/app/components/Login/Login.js index 05702a2fe..5fce3d153 100644 --- a/frontend/app/components/Login/Login.js +++ b/frontend/app/components/Login/Login.js @@ -69,18 +69,16 @@ class Login extends React.Component { const { CAPTCHA_ENABLED } = this.state; return ( -
-
-
- +
+
+
+
- -
-
-
+
-
-

Login to OpenReplay

+

Login to your account

+
+ {!authDetails.tenants && (
Don't have an account?{' '} @@ -99,19 +97,19 @@ class Login extends React.Component { onChange={(token) => this.handleSubmit(token)} /> )} -
+
- +
@@ -142,15 +140,16 @@ class Login extends React.Component { ))}
) : null} - {/*
*/} - + +
+ -
- {'Forgot your password?'} +
+ Having trouble logging in? {'Reset password'} +
- {/*
*/}
@@ -182,6 +181,8 @@ class Login extends React.Component { )}
+ +
diff --git a/frontend/app/components/Signup/Signup.js b/frontend/app/components/Signup/Signup.js index f5d61564f..55e924d27 100644 --- a/frontend/app/components/Signup/Signup.js +++ b/frontend/app/components/Signup/Signup.js @@ -57,24 +57,19 @@ export default class Signup extends React.Component { } return ( -
-
-
- -
- -
+
+
+
-
- OpenReplay Cloud{' '} -
- +
+
+ +
{' '} +
+ Cloud
-
OpenReplay Cloud is the hosted version of our open-source project.
+
OpenReplay Cloud is the hosted version of our open-source project.
We’ll manage hosting, scaling and upgrades.
@@ -85,7 +80,7 @@ export default class Signup extends React.Component {
-
+
diff --git a/frontend/app/components/Signup/SignupForm/SignupForm.js b/frontend/app/components/Signup/SignupForm/SignupForm.js index f110d2dae..3641dd36d 100644 --- a/frontend/app/components/Signup/SignupForm/SignupForm.js +++ b/frontend/app/components/Signup/SignupForm/SignupForm.js @@ -1,26 +1,25 @@ -import React from 'react' -import { Form, Input, Icon, Button, Link } from 'UI' -import { login } from 'App/routes' -import ReCAPTCHA from 'react-google-recaptcha' -import stl from './signup.module.css' +import React from 'react'; +import { Form, Input, Icon, Button, Link } from 'UI'; +import { login } from 'App/routes'; +import ReCAPTCHA from 'react-google-recaptcha'; +import stl from './signup.module.css'; import { signup } from 'Duck/user'; -import { connect } from 'react-redux' -import Select from 'Shared/Select' +import { connect } from 'react-redux'; +import Select from 'Shared/Select'; import { SITE_ID_STORAGE_KEY } from 'App/constants/storageKeys'; -const LOGIN_ROUTE = login() -const recaptchaRef = React.createRef() +const LOGIN_ROUTE = login(); +const recaptchaRef = React.createRef(); @connect( - state => ({ + (state) => ({ tenants: state.getIn(['user', 'tenants']), - errors: state.getIn([ 'user', 'signupRequest', 'errors' ]), - loading: state.getIn([ 'user', 'signupRequest', 'loading' ]), + errors: state.getIn(['user', 'signupRequest', 'errors']), + loading: state.getIn(['user', 'signupRequest', 'loading']), }), - { signup }, + { signup } ) export default class SignupForm extends React.Component { - state = { tenantId: '', fullname: '', @@ -36,21 +35,30 @@ export default class SignupForm extends React.Component { if (props.errors && props.errors.size > 0 && state.reload) { recaptchaRef.current.reset(); return { - reload: false - } - } + reload: false, + }; + } return null; } handleSubmit = (token) => { const { tenantId, fullname, password, email, projectName, organizationName, auth } = this.state; - localStorage.removeItem(SITE_ID_STORAGE_KEY) - this.props.signup({ tenantId, fullname, password, email, projectName, organizationName, auth, 'g-recaptcha-response': token }) - this.setState({ reload: true }) - } + localStorage.removeItem(SITE_ID_STORAGE_KEY); + this.props.signup({ + tenantId, + fullname, + password, + email, + projectName, + organizationName, + auth, + 'g-recaptcha-response': token, + }); + this.setState({ reload: true }); + }; - write = ({ target: { value, name } }) => this.setState({ [ name ]: value }) - writeOption = ({ name, value }) => this.setState({ [ name ]: value.value }); + write = ({ target: { value, name } }) => this.setState({ [name]: value }); + writeOption = ({ name, value }) => this.setState({ [name]: value.value }); onSubmit = (e) => { e.preventDefault(); @@ -60,52 +68,51 @@ export default class SignupForm extends React.Component { } else if (!CAPTCHA_ENABLED) { this.handleSubmit(); } - } + }; render() { const { loading, errors, tenants } = this.props; const { CAPTCHA_ENABLED } = this.state; return ( -
+
-

Get Started

-
Already having an account? Sign in
+

Create Account

<> - { CAPTCHA_ENABLED && ( + {CAPTCHA_ENABLED && ( this.handleSubmit(token) } + sitekey={window.env.CAPTCHA_SITE_KEY} + onChange={(token) => this.handleSubmit(token)} /> )} -
- { tenants.length > 0 && ( +
+ {tenants.length > 0 && ( @@ -115,57 +122,72 @@ export default class SignupForm extends React.Component { placeholder="Min 8 Characters" minLength="8" name="password" - onChange={ this.write } - className={ stl.password } + onChange={this.write} required="true" + icon="key" /> - - - - -
-
By creating an account, you agree to our Terms of Service and Privacy Policy.
+ + +
+
+ By signing up, you agree to our{' '} + + terms of service + {' '} + and{' '} + + privacy policy + + . +
-
- { errors && -
- { errors.map(error => ( + {errors && ( +
+ {errors.map((error) => (
- - { error }
+ + + {error} +
+
- )) } + ))} +
+ )} +
+ Already having an account?{' '} + + Login +
- } -
- -
- ) + ); } -} \ No newline at end of file +} diff --git a/frontend/app/components/ui/Button/Button.tsx b/frontend/app/components/ui/Button/Button.tsx index 3b08f55f7..924a70141 100644 --- a/frontend/app/components/ui/Button/Button.tsx +++ b/frontend/app/components/ui/Button/Button.tsx @@ -60,7 +60,7 @@ export default (props: Props) => { } const render = () => ( -