mirror of
https://github.com/wassname/talk.git
synced 2026-07-06 05:17:19 +08:00
More refactoring
This commit is contained in:
@@ -2,6 +2,7 @@ import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import styles from './ForgotPassword.css';
|
||||
import { Button, TextField, Alert, Success } from 'coral-ui';
|
||||
import t from 'coral-framework/services/i18n';
|
||||
|
||||
class ForgotPassword extends React.Component {
|
||||
constructor(props) {
|
||||
@@ -23,8 +24,7 @@ class ForgotPassword extends React.Component {
|
||||
renderSuccess() {
|
||||
return (
|
||||
<div className={styles.success} onClick={this.handleSignInLink}>
|
||||
If you have a registered account, a password reset link was sent to that
|
||||
email.{' '}
|
||||
{t('password_reset.mail_sent')}{' '}
|
||||
<a
|
||||
className={styles.signInLink}
|
||||
href="#"
|
||||
|
||||
@@ -7,7 +7,6 @@ import ForgotPassword from '../components/ForgotPassword';
|
||||
class ForgotPasswordContainer extends Component {
|
||||
state = {
|
||||
email: '',
|
||||
password: '',
|
||||
};
|
||||
|
||||
handleSubmit = () => {
|
||||
|
||||
@@ -23,6 +23,7 @@ en:
|
||||
click_to_confirm: "Click below to confirm your email address"
|
||||
confirm: "Confirm"
|
||||
password_reset:
|
||||
mail_sent: 'If you have a registered account, a password reset link was sent to that email'
|
||||
set_new_password: "Change Your Password"
|
||||
new_password: "New Password"
|
||||
new_password_help: "Password must be at least 8 characters"
|
||||
|
||||
@@ -2,8 +2,10 @@ import UserBox from './stream/containers/UserBox';
|
||||
import SignInButton from './stream/containers/SignInButton';
|
||||
import translations from './translations.yml';
|
||||
import Login from './login/containers/Main';
|
||||
import reducer from './login/reducer';
|
||||
|
||||
export default {
|
||||
reducer,
|
||||
translations,
|
||||
slots: {
|
||||
stream: [UserBox, SignInButton],
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
import * as actions from './constants';
|
||||
|
||||
export const setView = view => ({
|
||||
type: actions.SET_VIEW,
|
||||
view,
|
||||
});
|
||||
|
||||
export const setEmail = email => ({
|
||||
type: actions.SET_EMAIL,
|
||||
email,
|
||||
});
|
||||
|
||||
export const setPassword = password => ({
|
||||
type: actions.SET_PASSWORD,
|
||||
password,
|
||||
});
|
||||
@@ -0,0 +1,42 @@
|
||||
.header {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.header h1, .separator h1{
|
||||
text-align: center;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
.button {
|
||||
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;
|
||||
}
|
||||
|
||||
.success {
|
||||
border: 1px solid green;
|
||||
background-color: lightgreen;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.failure {
|
||||
border: 1px solid orange;
|
||||
background-color: 1px solid coral;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import styles from './ForgotPassword.css';
|
||||
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();
|
||||
};
|
||||
handleSignInLink = e => {
|
||||
e.preventDefault();
|
||||
this.props.onSignInLink();
|
||||
};
|
||||
handleEmailChange = e => this.props.onEmailChange(e.target.value);
|
||||
handleSubmit = e => {
|
||||
e.preventDefault();
|
||||
this.props.onSubmit();
|
||||
};
|
||||
|
||||
render() {
|
||||
const { email, errorMessage, success } = this.props;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className={styles.header}>
|
||||
<h1>{t('sign_in.recover_password')}</h1>
|
||||
</div>
|
||||
<form onSubmit={this.handleSubmit}>
|
||||
<div className={styles.textField}>
|
||||
<TextField
|
||||
type="email"
|
||||
style={{ fontSize: 16 }}
|
||||
id="email"
|
||||
name="email"
|
||||
label={t('sign_in.email')}
|
||||
onChange={this.handleEmailChange}
|
||||
value={email}
|
||||
/>
|
||||
</div>
|
||||
<Button type="submit" cStyle="black" className={styles.button} full>
|
||||
{t('sign_in.recover_password')}
|
||||
</Button>
|
||||
{success ? (
|
||||
<p className={styles.success}>{t('password_reset.mail_sent')} </p>
|
||||
) : null}
|
||||
{errorMessage ? (
|
||||
<p className={styles.failure}>{errorMessage}</p>
|
||||
) : null}
|
||||
</form>
|
||||
<div className={styles.footer}>
|
||||
<span>
|
||||
{t('sign_in.need_an_account')}{' '}
|
||||
<a onClick={this.handleSignUpLink}>{t('sign_in.register')}</a>
|
||||
</span>
|
||||
<span>
|
||||
{t('sign_in.already_have_an_account')}{' '}
|
||||
<a onClick={this.handleSignInLink}>{t('sign_in.sign_in')}</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ForgotPassword.propTypes = {
|
||||
success: PropTypes.bool.isRequired,
|
||||
email: PropTypes.string.isRequired,
|
||||
onEmailChange: PropTypes.func.isRequired,
|
||||
onSubmit: PropTypes.func.isRequired,
|
||||
errorMessage: PropTypes.string.isRequired,
|
||||
onSignInLink: PropTypes.func.isRequired,
|
||||
onSignUpLink: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default ForgotPassword;
|
||||
@@ -6,3 +6,19 @@
|
||||
font-family: Helvetica, 'Helvetica Neue', Verdana, sans-serif;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.close {
|
||||
font-size: 20px;
|
||||
line-height: 14px;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
position: absolute;
|
||||
display: block;
|
||||
font-weight: bold;
|
||||
color: #363636;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.close:hover {
|
||||
color: #6b6b6b;
|
||||
}
|
||||
|
||||
@@ -1,13 +1,26 @@
|
||||
import React from 'react';
|
||||
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 ForgotPassword from '../containers/ForgotPassword';
|
||||
import * as views from '../enums/views';
|
||||
|
||||
const SignDialog = () => (
|
||||
const Main = ({ view, onResetView }) => (
|
||||
<Dialog className={styles.dialog} id="signInDialog" open={true}>
|
||||
<SignIn />
|
||||
{view !== views.SIGN_IN && (
|
||||
<span className={styles.close} onClick={onResetView}>
|
||||
×
|
||||
</span>
|
||||
)}
|
||||
{view === views.SIGN_IN && <SignIn />}
|
||||
{view === views.FORGOT_PASSWORD && <ForgotPassword />}
|
||||
</Dialog>
|
||||
);
|
||||
|
||||
export default SignDialog;
|
||||
Main.propTypes = {
|
||||
view: PropTypes.string.isRequired,
|
||||
onResetView: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default Main;
|
||||
|
||||
@@ -18,9 +18,9 @@ class SignIn extends React.Component {
|
||||
e.preventDefault();
|
||||
this.props.onForgotPasswordLink();
|
||||
};
|
||||
handleRegisterLink = e => {
|
||||
handleSignUpLink = e => {
|
||||
e.preventDefault();
|
||||
this.props.onRegisterLink();
|
||||
this.props.onSignUpLink();
|
||||
};
|
||||
handleEmailChange = e => this.props.onEmailChange(e.target.value);
|
||||
handlePasswordChange = e => this.props.onPasswordChange(e.target.value);
|
||||
@@ -113,7 +113,7 @@ class SignIn extends React.Component {
|
||||
</span>
|
||||
<span>
|
||||
{t('sign_in.need_an_account')}
|
||||
<a onClick={this.handleRegisterLink} id="coralRegister">
|
||||
<a onClick={this.handleSignUpLink} id="coralRegister">
|
||||
{t('sign_in.register')}
|
||||
</a>
|
||||
</span>
|
||||
@@ -130,7 +130,7 @@ SignIn.propTypes = {
|
||||
onEmailChange: PropTypes.func.isRequired,
|
||||
onPasswordChange: PropTypes.func.isRequired,
|
||||
onForgotPasswordLink: PropTypes.func.isRequired,
|
||||
onRegisterLink: PropTypes.func.isRequired,
|
||||
onSignUpLink: PropTypes.func.isRequired,
|
||||
onRecaptchaVerify: PropTypes.func.isRequired,
|
||||
onSubmit: PropTypes.func.isRequired,
|
||||
errorMessage: PropTypes.string.isRequired,
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
const prefix = 'TALK_AUTH';
|
||||
|
||||
export const SET_VIEW = `${prefix}_SET_VIEW`;
|
||||
export const SET_EMAIL = `${prefix}_SET_EMAIL`;
|
||||
export const SET_PASSWORD = `${prefix}_SET_PASSWORD`;
|
||||
@@ -0,0 +1,64 @@
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { withForgotPassword } from 'coral-framework/hocs';
|
||||
import { compose } from 'recompose';
|
||||
import ForgotPassword from '../components/ForgotPassword';
|
||||
import { connect } from 'plugin-api/beta/client/hocs';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import * as views from '../enums/views';
|
||||
import { setView, setEmail } from '../actions';
|
||||
|
||||
class ForgotPasswordContainer extends Component {
|
||||
handleSubmit = () => {
|
||||
this.props.forgotPassword(this.props.email);
|
||||
};
|
||||
|
||||
handleSignUpLink = () => {
|
||||
this.props.setView(views.SIGN_UP);
|
||||
};
|
||||
|
||||
handleSignInLink = () => {
|
||||
this.props.setView(views.SIGN_IN);
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<ForgotPassword
|
||||
onSubmit={this.handleSubmit}
|
||||
onEmailChange={this.props.setEmail}
|
||||
email={this.props.email}
|
||||
errorMessage={this.props.errorMessage}
|
||||
success={this.props.success}
|
||||
onSignInLink={this.handleSignInLink}
|
||||
onSignUpLink={this.handleSignUpLink}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ForgotPasswordContainer.propTypes = {
|
||||
success: PropTypes.bool.isRequired,
|
||||
forgotPassword: PropTypes.func.isRequired,
|
||||
errorMessage: PropTypes.string.isRequired,
|
||||
setView: PropTypes.func.isRequired,
|
||||
email: PropTypes.string.isRequired,
|
||||
setEmail: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
const mapStateToProps = ({ talkPluginAuth: state }) => ({
|
||||
email: state.email,
|
||||
});
|
||||
|
||||
const mapDispatchToProps = dispatch =>
|
||||
bindActionCreators(
|
||||
{
|
||||
setView,
|
||||
setEmail,
|
||||
},
|
||||
dispatch
|
||||
);
|
||||
|
||||
export default compose(
|
||||
connect(mapStateToProps, mapDispatchToProps),
|
||||
withForgotPassword
|
||||
)(ForgotPasswordContainer);
|
||||
@@ -1,10 +1,36 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import Main from '../components/Main';
|
||||
import { connect } from 'plugin-api/beta/client/hocs';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import { setView } from '../actions';
|
||||
import * as views from '../enums/views';
|
||||
|
||||
class MainContainer extends React.Component {
|
||||
resetView = () => {
|
||||
this.props.setView(views.SIGN_IN);
|
||||
};
|
||||
|
||||
render() {
|
||||
return <Main />;
|
||||
return <Main onResetView={this.resetView} view={this.props.view} />;
|
||||
}
|
||||
}
|
||||
|
||||
export default MainContainer;
|
||||
MainContainer.propTypes = {
|
||||
view: PropTypes.string.isRequired,
|
||||
setView: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
const mapStateToProps = ({ talkPluginAuth: state }) => ({
|
||||
view: state.view,
|
||||
});
|
||||
|
||||
const mapDispatchToProps = dispatch =>
|
||||
bindActionCreators(
|
||||
{
|
||||
setView,
|
||||
},
|
||||
dispatch
|
||||
);
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(MainContainer);
|
||||
|
||||
@@ -3,34 +3,36 @@ import PropTypes from 'prop-types';
|
||||
import { withSignIn } from 'coral-framework/hocs';
|
||||
import { compose } from 'recompose';
|
||||
import SignIn from '../components/SignIn';
|
||||
import { connect } from 'plugin-api/beta/client/hocs';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import * as views from '../enums/views';
|
||||
import { setView, setEmail, setPassword } from '../actions';
|
||||
|
||||
class SignInContainer extends Component {
|
||||
state = {
|
||||
email: '',
|
||||
password: '',
|
||||
recaptchaResponse: '',
|
||||
};
|
||||
|
||||
handleSubmit = () => {
|
||||
this.props.signIn(
|
||||
this.state.email,
|
||||
this.state.password,
|
||||
this.props.email,
|
||||
this.props.password,
|
||||
this.state.recaptchaResponse
|
||||
);
|
||||
};
|
||||
|
||||
handleEmailChange = email => {
|
||||
this.setState({ email });
|
||||
};
|
||||
|
||||
handlePasswordChange = password => {
|
||||
this.setState({ password });
|
||||
};
|
||||
|
||||
handleRecaptchaVerify = recaptchaResponse => {
|
||||
this.setState({ recaptchaResponse });
|
||||
};
|
||||
|
||||
handleForgotPasswordLink = () => {
|
||||
this.props.setView(views.FORGOT_PASSWORD);
|
||||
};
|
||||
|
||||
handleSignUpLink = () => {
|
||||
this.props.setView(views.SIGN_UP);
|
||||
};
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.success) {
|
||||
window.close();
|
||||
@@ -41,8 +43,10 @@ class SignInContainer extends Component {
|
||||
return (
|
||||
<SignIn
|
||||
onSubmit={this.handleSubmit}
|
||||
onEmailChange={this.handleEmailChange}
|
||||
onPasswordChange={this.handlePasswordChange}
|
||||
onEmailChange={this.props.setEmail}
|
||||
onPasswordChange={this.props.setPassword}
|
||||
onForgotPasswordLink={this.handleForgotPasswordLink}
|
||||
onSignUpLink={this.handleSignUpLink}
|
||||
email={this.state.email}
|
||||
password={this.state.password}
|
||||
errorMessage={this.props.errorMessage}
|
||||
@@ -60,6 +64,29 @@ SignInContainer.propTypes = {
|
||||
requireRecaptcha: PropTypes.bool.isRequired,
|
||||
loading: PropTypes.bool.isRequired,
|
||||
success: PropTypes.bool.isRequired,
|
||||
setView: PropTypes.func.isRequired,
|
||||
email: PropTypes.string.isRequired,
|
||||
password: PropTypes.string.isRequired,
|
||||
setEmail: PropTypes.func.isRequired,
|
||||
setPassword: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default compose(withSignIn)(SignInContainer);
|
||||
const mapStateToProps = ({ talkPluginAuth: state }) => ({
|
||||
email: state.email,
|
||||
password: state.password,
|
||||
});
|
||||
|
||||
const mapDispatchToProps = dispatch =>
|
||||
bindActionCreators(
|
||||
{
|
||||
setView,
|
||||
setEmail,
|
||||
setPassword,
|
||||
},
|
||||
dispatch
|
||||
);
|
||||
|
||||
export default compose(
|
||||
connect(mapStateToProps, mapDispatchToProps),
|
||||
withSignIn
|
||||
)(SignInContainer);
|
||||
|
||||
@@ -0,0 +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';
|
||||
@@ -0,0 +1,30 @@
|
||||
import * as actions from './constants';
|
||||
import * as views from './enums/views';
|
||||
|
||||
const initialState = {
|
||||
view: views.SIGN_IN,
|
||||
email: '',
|
||||
password: '',
|
||||
};
|
||||
|
||||
export default function reducer(state = initialState, action) {
|
||||
switch (action.type) {
|
||||
case actions.SET_VIEW:
|
||||
return {
|
||||
...state,
|
||||
view: action.view,
|
||||
};
|
||||
case actions.SET_EMAIL:
|
||||
return {
|
||||
...state,
|
||||
email: action.email,
|
||||
};
|
||||
case actions.SET_PASSWORD:
|
||||
return {
|
||||
...state,
|
||||
password: action.password,
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user