mirror of
https://github.com/wassname/talk.git
synced 2026-09-09 11:38:08 +08:00
More refactoring
This commit is contained in:
@@ -5,8 +5,6 @@ import { Button, TextField } from 'plugin-api/beta/client/components/ui';
|
||||
import t from 'coral-framework/services/i18n';
|
||||
|
||||
class ForgotPassword extends React.Component {
|
||||
state = { value: '' };
|
||||
|
||||
handleSignUpLink = e => {
|
||||
e.preventDefault();
|
||||
this.props.onSignUpLink();
|
||||
|
||||
@@ -3,7 +3,9 @@ import { Dialog } from 'plugin-api/beta/client/components/ui';
|
||||
import styles from './Main.css';
|
||||
import PropTypes from 'prop-types';
|
||||
import SignIn from '../containers/SignIn';
|
||||
import SignUp from '../containers/SignUp';
|
||||
import ForgotPassword from '../containers/ForgotPassword';
|
||||
import ResendEmailConfirmation from '../containers/ResendEmailConfirmation';
|
||||
import * as views from '../enums/views';
|
||||
|
||||
const Main = ({ view, onResetView }) => (
|
||||
@@ -14,7 +16,9 @@ const Main = ({ view, onResetView }) => (
|
||||
</span>
|
||||
)}
|
||||
{view === views.SIGN_IN && <SignIn />}
|
||||
{view === views.SIGN_UP && <SignUp />}
|
||||
{view === views.FORGOT_PASSWORD && <ForgotPassword />}
|
||||
{view === views.RESEND_EMAIL_CONFIRMATION && <ResendEmailConfirmation />}
|
||||
</Dialog>
|
||||
);
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
.header {
|
||||
margin-bottom: 20px;
|
||||
text-align: center;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
.notVerified {
|
||||
padding: 10px;
|
||||
margin-bottom: 20px;
|
||||
border-radius: 2px;
|
||||
border: solid 1px #dddd00;
|
||||
background: #FFFF9C;
|
||||
color: #777700;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
Button,
|
||||
Spinner,
|
||||
Success,
|
||||
Alert,
|
||||
} from 'plugin-api/beta/client/components/ui';
|
||||
import PropTypes from 'prop-types';
|
||||
import styles from './ResendEmailConfirmation.css';
|
||||
import t from 'coral-framework/services/i18n';
|
||||
|
||||
class ResendVerification extends React.Component {
|
||||
handleSubmit = e => {
|
||||
e.preventDefault();
|
||||
this.props.onSubmit();
|
||||
};
|
||||
|
||||
render() {
|
||||
const { email, errorMessage, loading, success } = this.props;
|
||||
return (
|
||||
<div className="talk-resend-verification">
|
||||
<h1 className={styles.header}>{t('sign_in.email_verify_cta')}</h1>
|
||||
|
||||
{errorMessage && <Alert>{errorMessage}</Alert>}
|
||||
<div className={styles.notVerified}>
|
||||
{t('error.email_not_verified', email)}
|
||||
</div>
|
||||
<div>
|
||||
{!loading &&
|
||||
!success && (
|
||||
<Button
|
||||
id="resendConfirmEmail"
|
||||
cStyle="black"
|
||||
onClick={this.handleSubmit}
|
||||
full
|
||||
>
|
||||
{t('sign_in.request_new_verify_email')}
|
||||
</Button>
|
||||
)}
|
||||
{loading && <Spinner />}
|
||||
{success && <Success />}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ResendVerification.propTypes = {
|
||||
success: PropTypes.bool.isRequired,
|
||||
loading: PropTypes.bool.isRequired,
|
||||
email: PropTypes.string.isRequired,
|
||||
onSubmit: PropTypes.func.isRequired,
|
||||
errorMessage: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
export default ResendVerification;
|
||||
@@ -0,0 +1,49 @@
|
||||
.header {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.header h1, .separator h1{
|
||||
text-align: center;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
.socialConnections {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.separator h1{
|
||||
text-align: center;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
.hint {
|
||||
color: grey;
|
||||
font-weight: 600;
|
||||
padding: 3px 0 16px;
|
||||
}
|
||||
|
||||
.action {
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
.signInButton {
|
||||
margin-top: 10px;
|
||||
background-color: #2a2a2a;
|
||||
}
|
||||
|
||||
.footer {
|
||||
margin: 20px auto 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.footer span {
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.footer a {
|
||||
color: #2c69b6;
|
||||
cursor: pointer;
|
||||
margin: 0 5px;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
Button,
|
||||
TextField,
|
||||
Spinner,
|
||||
Success,
|
||||
Alert,
|
||||
} from 'plugin-api/beta/client/components/ui';
|
||||
import t from 'coral-framework/services/i18n';
|
||||
import styles from './SignUp.css';
|
||||
|
||||
class SignUp extends React.Component {
|
||||
handleSignInLink = e => {
|
||||
e.preventDefault();
|
||||
this.props.onSignInLink();
|
||||
};
|
||||
|
||||
handleUsernameChange = e => this.props.onUsernameChange(e.target.value);
|
||||
handleEmailChange = e => this.props.onEmailChange(e.target.value);
|
||||
handlePasswordChange = e => this.props.onPasswordChange(e.target.value);
|
||||
handlePasswordRepeatChange = e =>
|
||||
this.props.onPasswordRepeatChange(e.target.value);
|
||||
|
||||
handleSubmit = e => {
|
||||
e.preventDefault();
|
||||
this.props.onSubmit();
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
username,
|
||||
email,
|
||||
password,
|
||||
passwordRepeat,
|
||||
usernameError,
|
||||
emailError,
|
||||
passwordError,
|
||||
passwordRepeatError,
|
||||
loading,
|
||||
errorMessage,
|
||||
requireEmailConfirmation,
|
||||
success,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className={styles.header}>
|
||||
<h1>{t('sign_in.sign_up')}</h1>
|
||||
</div>
|
||||
|
||||
{errorMessage && <Alert>{errorMessage}</Alert>}
|
||||
{!success && (
|
||||
<div>
|
||||
<div className={styles.socialConnections}>Social</div>
|
||||
<div className={styles.separator}>
|
||||
<h1>{t('sign_in.or')}</h1>
|
||||
</div>
|
||||
<form onSubmit={this.handleSubmit}>
|
||||
<TextField
|
||||
id="email"
|
||||
type="email"
|
||||
label={t('sign_in.email')}
|
||||
value={email}
|
||||
style={{ fontSize: 16 }}
|
||||
showErrors={!!emailError}
|
||||
errorMsg={emailError}
|
||||
onChange={this.handleEmailChange}
|
||||
/>
|
||||
<TextField
|
||||
id="username"
|
||||
type="text"
|
||||
label={t('sign_in.username')}
|
||||
value={username}
|
||||
style={{ fontSize: 16 }}
|
||||
showErrors={!!usernameError}
|
||||
errorMsg={usernameError}
|
||||
onChange={this.handleUsernameChange}
|
||||
/>
|
||||
<TextField
|
||||
id="password"
|
||||
type="password"
|
||||
label={t('sign_in.password')}
|
||||
value={password}
|
||||
style={{ fontSize: 16 }}
|
||||
showErrors={!!passwordError}
|
||||
errorMsg={passwordError}
|
||||
onChange={this.handlePasswordChange}
|
||||
minLength="8"
|
||||
/>
|
||||
{passwordError && (
|
||||
<span className={styles.hint}>
|
||||
{' '}
|
||||
Password must be at least 8 characters.{' '}
|
||||
</span>
|
||||
)}
|
||||
<TextField
|
||||
id="confirmPassword"
|
||||
type="password"
|
||||
label={t('sign_in.confirm_password')}
|
||||
value={passwordRepeat}
|
||||
style={{ fontSize: 16 }}
|
||||
showErrors={!!passwordRepeatError}
|
||||
errorMsg={passwordRepeatError}
|
||||
onChange={this.handlePasswordRepeatChange}
|
||||
minLength="8"
|
||||
/>
|
||||
<div className={styles.action}>
|
||||
<Button
|
||||
type="submit"
|
||||
cStyle="black"
|
||||
id="coralSignUpButton"
|
||||
className={styles.signInButton}
|
||||
full
|
||||
>
|
||||
{t('sign_in.sign_up')}
|
||||
</Button>
|
||||
{loading && <Spinner />}
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
)}
|
||||
{success && (
|
||||
<div>
|
||||
<Success />
|
||||
{requireEmailConfirmation && (
|
||||
<p>
|
||||
{t('sign_in.verify_email')}
|
||||
<br />
|
||||
<br />
|
||||
{t('sign_in.verify_email2')}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<div className={styles.footer}>
|
||||
{t('sign_in.already_have_an_account')}{' '}
|
||||
<a id="coralSignInViewTrigger" onClick={this.handleSignInLink}>
|
||||
{t('sign_in.sign_in')}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
SignUp.propTypes = {
|
||||
loading: PropTypes.bool.isRequired,
|
||||
username: PropTypes.string.isRequired,
|
||||
usernameError: PropTypes.string.isRequired,
|
||||
email: PropTypes.string.isRequired,
|
||||
emailError: PropTypes.string.isRequired,
|
||||
password: PropTypes.string.isRequired,
|
||||
passwordError: PropTypes.string.isRequired,
|
||||
passwordRepeat: PropTypes.string.isRequired,
|
||||
passwordRepeatError: PropTypes.string.isRequired,
|
||||
onUsernameChange: PropTypes.func.isRequired,
|
||||
onEmailChange: PropTypes.func.isRequired,
|
||||
onPasswordChange: PropTypes.func.isRequired,
|
||||
onPasswordRepeatChange: PropTypes.func.isRequired,
|
||||
onSignInLink: PropTypes.func.isRequired,
|
||||
onSubmit: PropTypes.func.isRequired,
|
||||
errorMessage: PropTypes.string.isRequired,
|
||||
requireEmailConfirmation: PropTypes.bool.isRequired,
|
||||
success: PropTypes.bool.isRequired,
|
||||
};
|
||||
|
||||
export default SignUp;
|
||||
@@ -11,6 +11,22 @@ class MainContainer extends React.Component {
|
||||
this.props.setView(views.SIGN_IN);
|
||||
};
|
||||
|
||||
resizeHeight() {
|
||||
setTimeout(() => {
|
||||
const height = document.getElementById('signInDialog').offsetHeight + 100;
|
||||
window.resizeTo(500, height);
|
||||
}, 20);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.resizeHeight();
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
if (prevProps.view !== this.props.view) {
|
||||
this.resizeHeight();
|
||||
}
|
||||
}
|
||||
render() {
|
||||
return <Main onResetView={this.resetView} view={this.props.view} />;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { withResendEmailConfirmation } from 'coral-framework/hocs';
|
||||
import { compose } from 'recompose';
|
||||
import ResendEmailConfirmaton from '../components/ResendEmailConfirmation';
|
||||
import { connect } from 'plugin-api/beta/client/hocs';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import * as views from '../enums/views';
|
||||
import { setView } from '../actions';
|
||||
|
||||
class ResendEmailConfirmatonContainer extends Component {
|
||||
handleSubmit = () => {
|
||||
this.props.resendEmailConfirmation(this.props.email);
|
||||
};
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.success) {
|
||||
setTimeout(() => {
|
||||
// allow success UI to be shown for a second, and then close the modal
|
||||
this.props.setView(views.SIGN_IN);
|
||||
}, 2500);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<ResendEmailConfirmaton
|
||||
onSubmit={this.handleSubmit}
|
||||
email={this.props.email}
|
||||
errorMessage={this.props.errorMessage}
|
||||
success={this.props.success}
|
||||
loading={this.props.loading}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ResendEmailConfirmatonContainer.propTypes = {
|
||||
success: PropTypes.bool.isRequired,
|
||||
loading: PropTypes.bool.isRequired,
|
||||
resendEmailConfirmation: PropTypes.func.isRequired,
|
||||
errorMessage: PropTypes.string.isRequired,
|
||||
setView: PropTypes.func.isRequired,
|
||||
email: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
const mapStateToProps = ({ talkPluginAuth: state }) => ({
|
||||
email: state.email,
|
||||
});
|
||||
|
||||
const mapDispatchToProps = dispatch =>
|
||||
bindActionCreators(
|
||||
{
|
||||
setView,
|
||||
},
|
||||
dispatch
|
||||
);
|
||||
|
||||
export default compose(
|
||||
connect(mapStateToProps, mapDispatchToProps),
|
||||
withResendEmailConfirmation
|
||||
)(ResendEmailConfirmatonContainer);
|
||||
@@ -34,7 +34,9 @@ class SignInContainer extends Component {
|
||||
};
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.success) {
|
||||
if (nextProps.requireEmailConfirmation) {
|
||||
this.props.setView(views.RESEND_EMAIL_CONFIRMATION);
|
||||
} else if (nextProps.success) {
|
||||
window.close();
|
||||
}
|
||||
}
|
||||
@@ -47,8 +49,8 @@ class SignInContainer extends Component {
|
||||
onPasswordChange={this.props.setPassword}
|
||||
onForgotPasswordLink={this.handleForgotPasswordLink}
|
||||
onSignUpLink={this.handleSignUpLink}
|
||||
email={this.state.email}
|
||||
password={this.state.password}
|
||||
email={this.props.email}
|
||||
password={this.props.password}
|
||||
errorMessage={this.props.errorMessage}
|
||||
onRecaptchaVerify={this.handleRecaptchaVerify}
|
||||
requireRecaptcha={this.props.requireRecaptcha}
|
||||
@@ -62,6 +64,7 @@ SignInContainer.propTypes = {
|
||||
signIn: PropTypes.func.isRequired,
|
||||
errorMessage: PropTypes.string.isRequired,
|
||||
requireRecaptcha: PropTypes.bool.isRequired,
|
||||
requireEmailConfirmation: PropTypes.bool.isRequired,
|
||||
loading: PropTypes.bool.isRequired,
|
||||
success: PropTypes.bool.isRequired,
|
||||
setView: PropTypes.func.isRequired,
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { withSignUp } from 'coral-framework/hocs';
|
||||
import { compose } from 'recompose';
|
||||
import SignUp from '../components/SignUp';
|
||||
import { connect } from 'plugin-api/beta/client/hocs';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import * as views from '../enums/views';
|
||||
import { setView, setEmail, setPassword } from '../actions';
|
||||
import t from 'coral-framework/services/i18n';
|
||||
|
||||
class SignUpContainer extends Component {
|
||||
state = {
|
||||
username: '',
|
||||
passwordRepeat: '',
|
||||
usernameError: '',
|
||||
emailError: '',
|
||||
passwordError: '',
|
||||
passwordRepeatError: '',
|
||||
};
|
||||
|
||||
validate = data => {
|
||||
let valid = true;
|
||||
const changes = {};
|
||||
Object.keys(data).forEach(name => {
|
||||
const error = this.props.validate(name, data[name]);
|
||||
if (error) {
|
||||
valid = false;
|
||||
}
|
||||
changes[`${name}Error`] = error;
|
||||
});
|
||||
|
||||
if (data.password !== data.passwordRepeat) {
|
||||
changes['passwordRepeatError'] = t('sign_in.passwords_dont_match');
|
||||
valid = false;
|
||||
}
|
||||
|
||||
this.setState(changes);
|
||||
return valid;
|
||||
};
|
||||
|
||||
handleSubmit = () => {
|
||||
const data = {
|
||||
username: this.state.username,
|
||||
email: this.props.email,
|
||||
password: this.props.password,
|
||||
passwordRepeat: this.state.passwordRepeat,
|
||||
};
|
||||
|
||||
if (this.validate(data)) {
|
||||
this.props.signUp(data);
|
||||
}
|
||||
};
|
||||
|
||||
setUsername = username => this.setState({ username });
|
||||
setPasswordRepeat = passwordRepeat => this.setState({ passwordRepeat });
|
||||
|
||||
handleForgotPasswordLink = () => {
|
||||
this.props.setView(views.FORGOT_PASSWORD);
|
||||
};
|
||||
|
||||
handleSignInLink = () => {
|
||||
this.props.setView(views.SIGN_IN);
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<SignUp
|
||||
onSubmit={this.handleSubmit}
|
||||
onUsernameChange={this.setUsername}
|
||||
onEmailChange={this.props.setEmail}
|
||||
onPasswordChange={this.props.setPassword}
|
||||
onPasswordRepeatChange={this.setPasswordRepeat}
|
||||
onForgotPasswordLink={this.handleForgotPasswordLink}
|
||||
onSignInLink={this.handleSignInLink}
|
||||
username={this.state.username}
|
||||
email={this.props.email}
|
||||
password={this.props.password}
|
||||
passwordRepeat={this.state.passwordRepeat}
|
||||
errorMessage={this.props.errorMessage}
|
||||
onRecaptchaVerify={this.handleRecaptchaVerify}
|
||||
requireEmailConfirmation={this.props.requireEmailConfirmation}
|
||||
loading={this.props.loading}
|
||||
success={this.props.success}
|
||||
usernameError={this.state.usernameError}
|
||||
emailError={this.state.emailError}
|
||||
passwordError={this.state.passwordError}
|
||||
passwordRepeatError={this.state.passwordRepeatError}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
SignUpContainer.propTypes = {
|
||||
setView: PropTypes.func.isRequired,
|
||||
email: PropTypes.string.isRequired,
|
||||
password: PropTypes.string.isRequired,
|
||||
setEmail: PropTypes.func.isRequired,
|
||||
setPassword: PropTypes.func.isRequired,
|
||||
signUp: PropTypes.func.isRequired,
|
||||
loading: PropTypes.bool.isRequired,
|
||||
errorMessage: PropTypes.string.isRequired,
|
||||
requireEmailConfirmation: PropTypes.bool.isRequired,
|
||||
success: PropTypes.bool.isRequired,
|
||||
validate: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
const mapStateToProps = ({ talkPluginAuth: state }) => ({
|
||||
email: state.email,
|
||||
password: state.password,
|
||||
});
|
||||
|
||||
const mapDispatchToProps = dispatch =>
|
||||
bindActionCreators(
|
||||
{
|
||||
setView,
|
||||
setEmail,
|
||||
setPassword,
|
||||
},
|
||||
dispatch
|
||||
);
|
||||
|
||||
export default compose(
|
||||
connect(mapStateToProps, mapDispatchToProps),
|
||||
withSignUp
|
||||
)(SignUpContainer);
|
||||
@@ -1,4 +1,4 @@
|
||||
export const SIGN_IN = 'SIGN_IN';
|
||||
export const FORGOT_PASSWORD = 'FORGOT_PASSWORD';
|
||||
export const SIGN_UP = 'SIGN_UP';
|
||||
export const VERIFY_EMAIL = 'VERIFY_EMAIL';
|
||||
export const RESEND_EMAIL_CONFIRMATION = 'RESEND_EMAIL_CONFIRMATION';
|
||||
|
||||
Reference in New Issue
Block a user