Fully functional Sign Up & Sign Incontrols.
This commit is contained in:
@@ -48,11 +48,13 @@
|
||||
"babel-polyfill": "6.1.4",
|
||||
"babel-runtime": "6.0.14",
|
||||
"history": "1.17.0",
|
||||
"immutable": "^3.7.6",
|
||||
"invariant": "^2.1.1",
|
||||
"object-pick": "^0.1.1",
|
||||
"react": "^0.14.7",
|
||||
"react-bootstrap": "^0.28.3",
|
||||
"react-dom": "^0.14.0",
|
||||
"react-loader": "^2.0.0",
|
||||
"react-pacomo": "^0.5.1",
|
||||
"react-redux": "^4.4.0",
|
||||
"react-router": "^1.0.3",
|
||||
|
||||
@@ -182,25 +182,26 @@ export function initialize({cookies, isServer, currentLocation, userAgent} = {})
|
||||
//apiUrl: __API_URL__
|
||||
apiUrl: '/api'
|
||||
}
|
||||
}, {
|
||||
evilUser: {
|
||||
//apiUrl: __API_URL__,
|
||||
apiUrl: '/api',
|
||||
signOutPath: "/mangs/sign_out",
|
||||
emailSignInPath: "/mangs/sign_in",
|
||||
emailRegistrationPath: "/mangs",
|
||||
accountUpdatePath: "/mangs",
|
||||
accountDeletePath: "/mangs",
|
||||
passwordResetPath: "/mangs/password",
|
||||
passwordUpdatePath: "/mangs/password",
|
||||
tokenValidationPath: "/mangs/validate_token",
|
||||
authProviderPaths: {
|
||||
github: "/mangs/github",
|
||||
facebook: "/mangs/facebook",
|
||||
google: "/mangs/google_oauth2"
|
||||
}
|
||||
}
|
||||
}
|
||||
//, {
|
||||
// evilUser: {
|
||||
// //apiUrl: __API_URL__,
|
||||
// apiUrl: '/api',
|
||||
// signOutPath: "/mangs/sign_out",
|
||||
// emailSignInPath: "/mangs/sign_in",
|
||||
// emailRegistrationPath: "/mangs",
|
||||
// accountUpdatePath: "/mangs",
|
||||
// accountDeletePath: "/mangs",
|
||||
// passwordResetPath: "/mangs/password",
|
||||
// passwordUpdatePath: "/mangs/password",
|
||||
// tokenValidationPath: "/mangs/validate_token",
|
||||
// authProviderPaths: {
|
||||
// github: "/mangs/github",
|
||||
// facebook: "/mangs/facebook",
|
||||
// google: "/mangs/google_oauth2"
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
], {
|
||||
cookies,
|
||||
isServer,
|
||||
|
||||
78
js-frontend/src/controls/bootstrap/ButtonLoader.js
Normal file
78
js-frontend/src/controls/bootstrap/ButtonLoader.js
Normal file
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* Created by andrew on 15/02/16.
|
||||
*/
|
||||
import React, { PropTypes } from "react";
|
||||
import { Button, Glyphicon } from "react-bootstrap";
|
||||
import Spinner from "react-loader";
|
||||
|
||||
class ButtonLoader extends React.Component {
|
||||
static propTypes = {
|
||||
icon: PropTypes.node,
|
||||
loading: PropTypes.bool,
|
||||
spinConfig: PropTypes.object,
|
||||
spinColorDark: PropTypes.string,
|
||||
spinColorLight: PropTypes.string,
|
||||
children: PropTypes.node,
|
||||
onClick: PropTypes.func.isRequired,
|
||||
style: PropTypes.object
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
icon: <Glyphicon glyph="heart" />,
|
||||
loading: false,
|
||||
spinConfig: {
|
||||
lines: 10,
|
||||
length: 4,
|
||||
width: 2,
|
||||
radius: 3
|
||||
},
|
||||
spinColorDark: "#444",
|
||||
spinColorLight: "#fff",
|
||||
children: <span>Submit</span>,
|
||||
style: {}
|
||||
};
|
||||
|
||||
renderIcon () {
|
||||
let icon;
|
||||
|
||||
if (this.props.loading) {
|
||||
let spinColor = (!this.props.bsStyle || this.props.bsStyle === "default")
|
||||
? this.props.spinColorDark
|
||||
: this.props.spinColorLight;
|
||||
|
||||
icon = <Spinner ref="spinner" {...this.props.spinConfig} color={spinColor} loaded={false} />;
|
||||
} else {
|
||||
icon = this.props.icon;
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={{
|
||||
position: "relative",
|
||||
display: "inline-block",
|
||||
marginRight: "6px",
|
||||
width: "10px",
|
||||
height: "10px",
|
||||
top: "1px"
|
||||
}}>
|
||||
{icon}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
render () {
|
||||
return (
|
||||
<Button
|
||||
onClick={this.props.onClick}
|
||||
disabled={this.props.disabled || this.props.loading}
|
||||
bsStyle={this.props.bsStyle}
|
||||
className={this.props.className}
|
||||
type={this.props.type}
|
||||
style={this.props.style}
|
||||
bsSize={this.props.bsSize}>
|
||||
{this.renderIcon()} {this.props.children}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default ButtonLoader;
|
||||
94
js-frontend/src/controls/bootstrap/EmailSignInForm.js
Normal file
94
js-frontend/src/controls/bootstrap/EmailSignInForm.js
Normal file
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
* Created by andrew on 15/02/16.
|
||||
*/
|
||||
import React, {PropTypes} from "react";
|
||||
import auth from "redux-auth";
|
||||
import Input from "./Input";
|
||||
import ButtonLoader from "./ButtonLoader";
|
||||
import { emailSignInFormUpdate, emailSignIn } from "redux-auth";
|
||||
import { Glyphicon } from "react-bootstrap";
|
||||
import { connect } from "react-redux";
|
||||
|
||||
/*
|
||||
<Input type="password"
|
||||
label="Password"
|
||||
className="email-sign-in-password"
|
||||
placeholder="Password"
|
||||
disabled={disabled}
|
||||
value={this.props.auth.getIn(["emailSignIn", this.getEndpoint(), "form", "password"])}
|
||||
errors={this.props.auth.getIn(["emailSignIn", this.getEndpoint(), "errors", "password"])}
|
||||
onChange={this.handleInput.bind(this, "password")}
|
||||
{...this.props.inputProps.password} />
|
||||
*/
|
||||
|
||||
class EmailSignInForm extends React.Component {
|
||||
static propTypes = {
|
||||
endpoint: PropTypes.string,
|
||||
inputProps: PropTypes.shape({
|
||||
email: PropTypes.object,
|
||||
password: PropTypes.object,
|
||||
submit: PropTypes.object
|
||||
})
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
inputProps: {
|
||||
email: {},
|
||||
password: {},
|
||||
submit: {}
|
||||
}
|
||||
};
|
||||
|
||||
getEndpoint () {
|
||||
return (
|
||||
this.props.endpoint ||
|
||||
this.props.auth.getIn(["configure", "currentEndpointKey"]) ||
|
||||
this.props.auth.getIn(["configure", "defaultEndpointKey"])
|
||||
);
|
||||
}
|
||||
|
||||
handleInput (key, val) {
|
||||
this.props.dispatch(emailSignInFormUpdate(this.getEndpoint(), key, val));
|
||||
}
|
||||
|
||||
handleSubmit (event) {
|
||||
event.preventDefault();
|
||||
let formData = this.props.auth.getIn(["emailSignIn", this.getEndpoint(), "form"]).toJS();
|
||||
debugger;
|
||||
this.props.dispatch(emailSignIn(formData, this.getEndpoint()));
|
||||
}
|
||||
|
||||
render () {
|
||||
let disabled = (
|
||||
this.props.auth.getIn(["user", "isSignedIn"]) ||
|
||||
this.props.auth.getIn(["emailSignIn", this.getEndpoint(), "loading"])
|
||||
);
|
||||
|
||||
return (
|
||||
<form className='redux-auth email-sign-in-form clearfix'
|
||||
onSubmit={this.handleSubmit.bind(this)}>
|
||||
<Input type="text"
|
||||
className="email-sign-in-email"
|
||||
label="Email"
|
||||
placeholder="Email"
|
||||
disabled={disabled}
|
||||
value={this.props.auth.getIn(["emailSignIn", this.getEndpoint(), "form", "email"])}
|
||||
errors={this.props.auth.getIn(["emailSignIn", this.getEndpoint(), "errors", "email"])}
|
||||
onChange={this.handleInput.bind(this, "email")}
|
||||
{...this.props.inputProps.email} />
|
||||
|
||||
<ButtonLoader loading={this.props.auth.getIn(["emailSignIn", this.getEndpoint(), "loading"])}
|
||||
type="submit"
|
||||
icon={<Glyphicon glyph="log-in" />}
|
||||
className='email-sign-in-submit pull-right'
|
||||
disabled={disabled}
|
||||
onClick={this.handleSubmit.bind(this)}
|
||||
{...this.props.inputProps.submit}>
|
||||
Sign In
|
||||
</ButtonLoader>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default connect(({auth}) => ({auth}))(EmailSignInForm);
|
||||
195
js-frontend/src/controls/bootstrap/EmailSignUpForm.js
Normal file
195
js-frontend/src/controls/bootstrap/EmailSignUpForm.js
Normal file
@@ -0,0 +1,195 @@
|
||||
/**
|
||||
* Created by andrew on 15/02/16.
|
||||
*/
|
||||
import React, {PropTypes} from "react";
|
||||
import auth from "redux-auth";
|
||||
import Input from "./Input";
|
||||
import ButtonLoader from "./ButtonLoader";
|
||||
import { emailSignUpFormUpdate, emailSignUp } from "redux-auth";
|
||||
import { Glyphicon } from "react-bootstrap";
|
||||
import { connect } from "react-redux";
|
||||
|
||||
class EmailSignUpForm extends React.Component {
|
||||
static propTypes = {
|
||||
endpoint: PropTypes.string,
|
||||
inputProps: PropTypes.shape({
|
||||
email: PropTypes.object,
|
||||
password: PropTypes.object,
|
||||
passwordConfirmation: PropTypes.object,
|
||||
submit: PropTypes.object
|
||||
})
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
inputProps: {
|
||||
email: {},
|
||||
password: {},
|
||||
submit: {}
|
||||
}
|
||||
};
|
||||
|
||||
getEndpoint () {
|
||||
return (
|
||||
this.props.endpoint ||
|
||||
this.props.auth.getIn(["configure", "currentEndpointKey"]) ||
|
||||
this.props.auth.getIn(["configure", "defaultEndpointKey"])
|
||||
);
|
||||
}
|
||||
|
||||
handleInput (key, val) {
|
||||
this.props.dispatch(emailSignUpFormUpdate(this.getEndpoint(), key, val));
|
||||
}
|
||||
|
||||
handleSubmit (event) {
|
||||
event.preventDefault();
|
||||
let formData = this.props.auth.getIn(["emailSignUp", this.getEndpoint(), "form"]).toJS();
|
||||
this.props.dispatch(emailSignUp(formData, this.getEndpoint()));
|
||||
}
|
||||
|
||||
render () {
|
||||
let disabled = (
|
||||
this.props.auth.getIn(["user", "isSignedIn"]) ||
|
||||
this.props.auth.getIn(["emailSignUp", this.getEndpoint(), "loading"])
|
||||
);
|
||||
|
||||
/*
|
||||
* <Input type="password"
|
||||
label="Password"
|
||||
placeholder="Password"
|
||||
className="email-sign-up-password"
|
||||
disabled={disabled}
|
||||
value={this.props.auth.getIn(["emailSignUp", this.getEndpoint(), "form", "password"])}
|
||||
errors={this.props.auth.getIn(["emailSignUp", this.getEndpoint(), "errors", "password"])}
|
||||
onChange={this.handleInput.bind(this, "password")}
|
||||
{...this.props.inputProps.password} />
|
||||
|
||||
<Input type="password"
|
||||
label="Password Confirmation"
|
||||
placeholder="Password Confirmation"
|
||||
className="email-sign-up-password-confirmation"
|
||||
disabled={disabled}
|
||||
value={this.props.auth.getIn(["emailSignUp", this.getEndpoint(), "form", "password_confirmation"])}
|
||||
errors={this.props.auth.getIn(["emailSignUp", this.getEndpoint(), "errors", "password_confirmation"])}
|
||||
onChange={this.handleInput.bind(this, "password_confirmation")}
|
||||
{...this.props.inputProps.passwordConfirmation} />
|
||||
*/
|
||||
return (
|
||||
<form className='redux-auth email-sign-up-form clearfix'
|
||||
onSubmit={this.handleSubmit.bind(this)}>
|
||||
|
||||
<Input type="text"
|
||||
label="First name"
|
||||
placeholder="First name"
|
||||
className="email-sign-up-email"
|
||||
disabled={disabled}
|
||||
value={this.props.auth.getIn(["emailSignUp", this.getEndpoint(), "form", "fname"])}
|
||||
errors={this.props.auth.getIn(["emailSignUp", this.getEndpoint(), "errors", "fname"])}
|
||||
onChange={this.handleInput.bind(this, "fname")}
|
||||
{...this.props.inputProps.fname} />
|
||||
|
||||
<Input type="text"
|
||||
label="Last name"
|
||||
placeholder="Last name"
|
||||
className="email-sign-up-email"
|
||||
disabled={disabled}
|
||||
value={this.props.auth.getIn(["emailSignUp", this.getEndpoint(), "form", "lname"])}
|
||||
errors={this.props.auth.getIn(["emailSignUp", this.getEndpoint(), "errors", "lname"])}
|
||||
onChange={this.handleInput.bind(this, "lname")}
|
||||
{...this.props.inputProps.lname} />
|
||||
|
||||
<Input type="text"
|
||||
label="Email"
|
||||
placeholder="Email"
|
||||
className="email-sign-up-email"
|
||||
disabled={disabled}
|
||||
value={this.props.auth.getIn(["emailSignUp", this.getEndpoint(), "form", "email"])}
|
||||
errors={this.props.auth.getIn(["emailSignUp", this.getEndpoint(), "errors", "email"])}
|
||||
onChange={this.handleInput.bind(this, "email")}
|
||||
{...this.props.inputProps.email} />
|
||||
|
||||
|
||||
<Input type="text"
|
||||
label="SSN"
|
||||
placeholder="SSN"
|
||||
className="email-sign-up-email"
|
||||
disabled={disabled}
|
||||
value={this.props.auth.getIn(["emailSignUp", this.getEndpoint(), "form", "ssn"])}
|
||||
errors={this.props.auth.getIn(["emailSignUp", this.getEndpoint(), "errors", "ssn"])}
|
||||
onChange={this.handleInput.bind(this, "ssn")}
|
||||
{...this.props.inputProps.ssn} />
|
||||
|
||||
<Input type="text"
|
||||
label="Phone"
|
||||
placeholder="Phone"
|
||||
className="email-sign-up-email"
|
||||
disabled={disabled}
|
||||
value={this.props.auth.getIn(["emailSignUp", this.getEndpoint(), "form", "phone"])}
|
||||
errors={this.props.auth.getIn(["emailSignUp", this.getEndpoint(), "errors", "phone"])}
|
||||
onChange={this.handleInput.bind(this, "phone")}
|
||||
{...this.props.inputProps.phone} />
|
||||
|
||||
<Input type="text"
|
||||
label="Address 1"
|
||||
placeholder="Address 1"
|
||||
className="email-sign-up-email"
|
||||
disabled={disabled}
|
||||
value={this.props.auth.getIn(["emailSignUp", this.getEndpoint(), "form", "address1"])}
|
||||
errors={this.props.auth.getIn(["emailSignUp", this.getEndpoint(), "errors", "address1"])}
|
||||
onChange={this.handleInput.bind(this, "address1")}
|
||||
{...this.props.inputProps.address1} />
|
||||
|
||||
<Input type="text"
|
||||
label="Address 2"
|
||||
placeholder="Address 2"
|
||||
className="email-sign-up-email"
|
||||
disabled={disabled}
|
||||
value={this.props.auth.getIn(["emailSignUp", this.getEndpoint(), "form", "address2"])}
|
||||
errors={this.props.auth.getIn(["emailSignUp", this.getEndpoint(), "errors", "address2"])}
|
||||
onChange={this.handleInput.bind(this, "address2")}
|
||||
{...this.props.inputProps.address2} />
|
||||
|
||||
<Input type="text"
|
||||
label="City"
|
||||
placeholder="City"
|
||||
className="email-sign-up-email"
|
||||
disabled={disabled}
|
||||
value={this.props.auth.getIn(["emailSignUp", this.getEndpoint(), "form", "city"])}
|
||||
errors={this.props.auth.getIn(["emailSignUp", this.getEndpoint(), "errors", "city"])}
|
||||
onChange={this.handleInput.bind(this, "city")}
|
||||
{...this.props.inputProps.city} />
|
||||
|
||||
<Input type="text"
|
||||
label="State"
|
||||
placeholder="State"
|
||||
className="email-sign-up-email"
|
||||
disabled={disabled}
|
||||
value={this.props.auth.getIn(["emailSignUp", this.getEndpoint(), "form", "state"])}
|
||||
errors={this.props.auth.getIn(["emailSignUp", this.getEndpoint(), "errors", "state"])}
|
||||
onChange={this.handleInput.bind(this, "state")}
|
||||
{...this.props.inputProps.state} />
|
||||
|
||||
<Input type="text"
|
||||
label="ZIP"
|
||||
placeholder="ZIP"
|
||||
className="email-sign-up-email"
|
||||
disabled={disabled}
|
||||
value={this.props.auth.getIn(["emailSignUp", this.getEndpoint(), "form", "zip"])}
|
||||
errors={this.props.auth.getIn(["emailSignUp", this.getEndpoint(), "errors", "zip"])}
|
||||
onChange={this.handleInput.bind(this, "zip")}
|
||||
{...this.props.inputProps.zip} />
|
||||
|
||||
<ButtonLoader loading={this.props.auth.getIn(["emailSignUp", this.getEndpoint(), "loading"])}
|
||||
type="submit"
|
||||
className="email-sign-up-submit pull-right"
|
||||
icon={<Glyphicon glyph="send" />}
|
||||
disabled={disabled}
|
||||
onClick={this.handleSubmit.bind(this)}
|
||||
{...this.props.inputProps.submit}>
|
||||
Sign Up
|
||||
</ButtonLoader>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default connect(({auth}) => ({auth}))(EmailSignUpForm);
|
||||
64
js-frontend/src/controls/bootstrap/Input.js
Normal file
64
js-frontend/src/controls/bootstrap/Input.js
Normal file
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* Created by andrew on 15/02/16.
|
||||
*/
|
||||
import React, { PropTypes } from "react";
|
||||
import { Input, Glyphicon } from "react-bootstrap";
|
||||
import Immutable from "immutable";
|
||||
|
||||
class AuthInput extends React.Component {
|
||||
static propTypes = {
|
||||
label: PropTypes.string,
|
||||
value: PropTypes.string,
|
||||
errors: PropTypes.object
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
label: "",
|
||||
value: null,
|
||||
errors: Immutable.fromJS([])
|
||||
};
|
||||
|
||||
handleInput (ev) {
|
||||
this.props.onChange(ev.target.value);
|
||||
}
|
||||
|
||||
renderErrorList () {
|
||||
if (this.props.errors.size) {
|
||||
return (
|
||||
<div className='auth-error-message has-error'>
|
||||
{this.props.errors.map((err, i) => {
|
||||
return (
|
||||
<p className="control-label inline-error-item"
|
||||
style={{paddingLeft: "20px", position: "relative", marginBottom: "28px"}}
|
||||
key={i}>
|
||||
|
||||
<Glyphicon glyph="exclamation-sign"
|
||||
style={{
|
||||
position: "absolute",
|
||||
left: 0,
|
||||
top: 2
|
||||
}}
|
||||
/> {this.props.label} {err}
|
||||
</p>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
return <span />;
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
return (
|
||||
<div>
|
||||
<Input {...this.props}
|
||||
bsStyle={(this.props.errors.size) ? "error" : null}
|
||||
onChange={this.handleInput.bind(this)} />
|
||||
{this.renderErrorList()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default AuthInput;
|
||||
@@ -5,11 +5,32 @@ import React from "react";
|
||||
import { PageHeader } from "react-bootstrap";
|
||||
import { connect } from "react-redux";
|
||||
|
||||
//import ButtonLoader from "./ButtonLoader";
|
||||
import { Input } from "react-bootstrap";
|
||||
import ButtonLoader from "../controls/bootstrap/ButtonLoader";
|
||||
|
||||
//export {bootstrap, materialUi} from "./views";
|
||||
|
||||
|
||||
// bootstrap theme
|
||||
import { EmailSignInForm } from "redux-auth/bootstrap-theme";
|
||||
//import { EmailSignInForm } from "redux-auth/bootstrap-theme";
|
||||
import EmailSignInForm from "../controls/bootstrap/EmailSignInForm";
|
||||
|
||||
|
||||
export class SignIn extends React.Component {
|
||||
|
||||
render () {
|
||||
const signInProps = {
|
||||
inputProps: {
|
||||
password: {
|
||||
className: 'hide hidden',
|
||||
style: { display: 'none' },
|
||||
value: null,
|
||||
disabled: true
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return <EmailSignInForm />;
|
||||
//return (
|
||||
// <div>
|
||||
|
||||
@@ -5,18 +5,14 @@ import React from "react";
|
||||
import { PageHeader } from "react-bootstrap";
|
||||
import { connect } from "react-redux";
|
||||
|
||||
import { EmailSignUpForm } from "redux-auth/bootstrap-theme"
|
||||
//import { EmailSignUpForm } from "redux-auth/bootstrap-theme"
|
||||
import EmailSignUpForm from "../controls/bootstrap/EmailSignUpForm";
|
||||
|
||||
export class SignUp extends React.Component {
|
||||
render () {
|
||||
|
||||
return <EmailSignUpForm />;
|
||||
//return (
|
||||
// <div>
|
||||
// <PageHeader>Sign Up Page</PageHeader>
|
||||
// <p>Here you can register.</p>
|
||||
// </div>
|
||||
//);
|
||||
return <EmailSignUpForm endpoint="default" />;
|
||||
|
||||
}
|
||||
}
|
||||
export default connect(({routes}) => ({routes}))(SignUp);
|
||||
@@ -30,6 +30,7 @@ export default (DEBUG, PATH, PORT=3000) => ({
|
||||
{ test: /\.jsx?$/,
|
||||
include: [
|
||||
path.resolve(__dirname, "src"),
|
||||
path.resolve(__dirname, "node_modules/redux-auth/src/views/bootstrap")
|
||||
],
|
||||
loader: "babel-loader",
|
||||
query: {
|
||||
|
||||
Reference in New Issue
Block a user