Account creation dialog, tidy
This commit is contained in:
@@ -17,7 +17,8 @@ import { ReduxRouter} from "redux-router";
|
||||
|
||||
//import { configure as reduxAuthConfigure, authStateReducer } from "redux-auth";
|
||||
//import { authStateReducer } from "redux-auth";
|
||||
import authStateReducer from "./reducers/auth";
|
||||
import authStateReducer from './reducers/auth';
|
||||
import appStateReducer from './reducers/data'
|
||||
import { configure as reduxAuthConfigure } from './actions/configure';
|
||||
//import { AuthGlobals } from "redux-auth/bootstrap-theme";
|
||||
|
||||
@@ -52,9 +53,8 @@ export function initialize({cookies, isServer, currentLocation, userAgent} = {})
|
||||
|
||||
const reducer = combineReducers({
|
||||
auth: authStateReducer,
|
||||
app: appStateReducer,
|
||||
router: routerStateReducer
|
||||
//demoButtons,
|
||||
//demoUi
|
||||
});
|
||||
|
||||
const routes = (
|
||||
|
||||
@@ -35,7 +35,7 @@ export function authenticateError(errors) {
|
||||
}
|
||||
|
||||
|
||||
export function authenticate() {
|
||||
export function authenticate(forceReread) {
|
||||
return dispatch => {
|
||||
|
||||
dispatch(authenticateStart());
|
||||
@@ -51,7 +51,7 @@ export function authenticate() {
|
||||
|
||||
const savedUser = retrieveUserData();
|
||||
|
||||
if (savedUser) {
|
||||
if (savedUser && !forceReread) {
|
||||
return rs(savedUser);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
import T from '../constants/ACTION_TYPES'
|
||||
|
||||
|
||||
export function updateQuery(query) {
|
||||
return {
|
||||
type: T.DOCUMENT_LIST_VIEW.SET_QUERY,
|
||||
query,
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
import uuid from '../utils/uuid'
|
||||
import documentValidator from '../validators/documentValidator'
|
||||
import T from '../constants/ACTION_TYPES'
|
||||
import * as navigation from './navigation'
|
||||
|
||||
|
||||
export function updateChanges(id, data) {
|
||||
return [
|
||||
{
|
||||
type: T.DOCUMENT_VIEW.UPDATE_DATA,
|
||||
id,
|
||||
data,
|
||||
},
|
||||
{
|
||||
type: T.DOCUMENT_VIEW.REMOVE_STALE_ERRORS,
|
||||
id,
|
||||
errors: documentValidator(data),
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
export function clearChanges(id) {
|
||||
return {
|
||||
type: T.DOCUMENT_VIEW.CLEAR,
|
||||
id,
|
||||
}
|
||||
}
|
||||
|
||||
export function cancelChanges(id) {
|
||||
return [
|
||||
clearChanges(id),
|
||||
navigation.start('documentList'),
|
||||
]
|
||||
}
|
||||
|
||||
export function submitChanges(id) {
|
||||
return (dispatch, getState) => {
|
||||
const { view } = getState()
|
||||
const data = view.document.unsavedChanges[id]
|
||||
const errors = documentValidator(data)
|
||||
|
||||
if (errors) {
|
||||
dispatch({
|
||||
type: T.DOCUMENT_VIEW.SET_ERRORS,
|
||||
id,
|
||||
errors,
|
||||
})
|
||||
}
|
||||
else {
|
||||
const newId = id == 'new' ? uuid() : id
|
||||
dispatch(navigation.start('documentEdit', {id: newId}))
|
||||
dispatch(clearChanges(id))
|
||||
dispatch({
|
||||
type: T.DOCUMENT_DATA.UPDATE,
|
||||
id: newId,
|
||||
data,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,62 @@
|
||||
* Created by andrew on 27/02/16.
|
||||
*/
|
||||
import T from '../constants/ACTION_TYPES';
|
||||
import { makeActionCreator } from '../utils/actions';
|
||||
import * as api from '../utils/api';
|
||||
import { authenticate } from './authenticate';
|
||||
|
||||
export function entityReceived(id, entity) {
|
||||
return { type: T.ENTITIES.RECEIVED };
|
||||
export const entityRequested = makeActionCreator(T.ENTITIES.REQUESTED, 'id');
|
||||
export const entityReceived = makeActionCreator(T.ENTITIES.RECEIVED, 'id', 'entity');
|
||||
|
||||
export const accountsListRequested = makeActionCreator(T.ACCOUNTS.LIST_START);
|
||||
export const accountsListReceived = makeActionCreator(T.ACCOUNTS.LIST_COMPLETE, 'data');
|
||||
export const accountsListError = makeActionCreator(T.ACCOUNTS.LIST_ERROR, 'error');
|
||||
|
||||
//export const accountsRefListRequested = makeActionCreator(T.ACCOUNTS.LIST_REF_START, 'id');
|
||||
export const accountsRefListReceived = makeActionCreator(T.ACCOUNTS.LIST_REF_COMPLETE, 'data');
|
||||
//export const accountsRefListError = makeActionCreator(T.ACCOUNTS.LIST_REF_ERROR, 'id');
|
||||
|
||||
export const accountCreateStart = makeActionCreator(T.ACCOUNTS.CREATE_START);
|
||||
export const accountCreateComplete = makeActionCreator(T.ACCOUNTS.CREATE_COMPLETE, 'accountId');
|
||||
export const accountCreateError = makeActionCreator(T.ACCOUNTS.CREATE_ERROR, 'error');
|
||||
export const accountCreateFormUpdate = makeActionCreator(T.ACCOUNTS.CREATE_FORM_UPDATE, 'key', 'value');
|
||||
|
||||
export const accountRefCreateStart = makeActionCreator(T.ACCOUNTS.CREATE_REF_START, 'data');
|
||||
export const accountRefCreateComplete = makeActionCreator(T.ACCOUNTS.CREATE_REF_COMPLETE, 'data');
|
||||
export const accountRefCreateError = makeActionCreator(T.ACCOUNTS.CREATE_REF_ERROR, 'error');
|
||||
export const accountRefCreateFormUpdate = makeActionCreator(T.ACCOUNTS.CREATE_REF_FORM_UPDATE, 'key', 'value');
|
||||
|
||||
|
||||
export function accountsList(userId) {
|
||||
return dispatch => {
|
||||
dispatch(accountsListRequested());
|
||||
return api.apiRetrieveAccounts(userId)
|
||||
.then(list => {
|
||||
dispatch(accountsListReceived(list));
|
||||
})
|
||||
.catch(err => {
|
||||
dispatch(accountsListError(err));
|
||||
return Promise.resolve({ error: err });
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
export function accountCreate(customerId, payload) {
|
||||
return dispatch => {
|
||||
dispatch(accountCreateStart());
|
||||
return api.apiCreateAccount(customerId, payload)
|
||||
.then(({ accountId }) => {
|
||||
dispatch(accountCreateComplete({
|
||||
id: accountId,
|
||||
...payload
|
||||
}));
|
||||
dispatch(entityReceived(accountId, payload));
|
||||
return authenticate(true);
|
||||
})
|
||||
.catch(err => {
|
||||
dispatch(accountCreateError(err));
|
||||
return Promise.resolve({ error: err });
|
||||
|
||||
})
|
||||
};
|
||||
}
|
||||
@@ -24,34 +24,26 @@ export default defineActionTypes({
|
||||
`,
|
||||
|
||||
ENTITIES: `
|
||||
REQUESTED
|
||||
RECEIVED
|
||||
`,
|
||||
DOCUMENT_LIST_VIEW: `
|
||||
SET_QUERY
|
||||
RECEIVED_LIST
|
||||
`,
|
||||
|
||||
DOCUMENT_VIEW: `
|
||||
UPDATE_DATA
|
||||
SET_ERRORS
|
||||
REMOVE_STALE_ERRORS
|
||||
CLEAR
|
||||
`,
|
||||
|
||||
|
||||
/*
|
||||
* Data model
|
||||
*/
|
||||
|
||||
DOCUMENT_DATA: `
|
||||
UPDATE
|
||||
`,
|
||||
|
||||
/*
|
||||
* Application
|
||||
*/
|
||||
|
||||
NAVIGATION: `
|
||||
START
|
||||
COMPLETE
|
||||
ACCOUNTS: `
|
||||
LIST_START
|
||||
LIST_COMPLETE
|
||||
LIST_ERROR
|
||||
LIST_REF_START
|
||||
LIST_REF_COMPLETE
|
||||
LIST_REF_ERROR
|
||||
CREATE_START
|
||||
CREATE_COMPLETE
|
||||
CREATE_ERROR
|
||||
CREATE_FORM_UPDATE
|
||||
CREATE_REF_START
|
||||
CREATE_REF_COMPLETE
|
||||
CREATE_REF_ERROR
|
||||
CREATE_REF_FORM_UPDATE
|
||||
`
|
||||
|
||||
})
|
||||
|
||||
@@ -2,16 +2,13 @@
|
||||
* Created by andrew on 15/02/16.
|
||||
*/
|
||||
import React, {PropTypes} from "react";
|
||||
//import auth from "redux-auth";
|
||||
import * as BS from "react-bootstrap";
|
||||
import { connect } from "react-redux";
|
||||
import read from '../../utils/readProp';
|
||||
|
||||
import * as BS from "react-bootstrap";
|
||||
import Input from "./Input";
|
||||
import ButtonLoader from "./ButtonLoader";
|
||||
//import { emailSignInFormUpdate, emailSignIn } from "redux-auth";
|
||||
import { Glyphicon } from "react-bootstrap";
|
||||
import { connect } from "react-redux";
|
||||
|
||||
import read from '../../utils/readProp';
|
||||
|
||||
import { emailSignInFormUpdate, emailSignIn } from "../../actions/signIn";
|
||||
|
||||
@@ -83,7 +80,7 @@ class EmailSignInForm extends React.Component {
|
||||
|
||||
<ButtonLoader loading={read(this.props.auth, 'signIn.loading', false)}
|
||||
type="submit"
|
||||
icon={<Glyphicon glyph="log-in" />}
|
||||
icon={<BS.Glyphicon glyph="log-in" />}
|
||||
className='email-sign-in-submit pull-right'
|
||||
disabled={disabled}
|
||||
onClick={this.handleSubmit.bind(this)}
|
||||
|
||||
@@ -78,7 +78,7 @@ class EmailSignUpForm extends React.Component {
|
||||
className="email-sign-up-email"
|
||||
disabled={disabled}
|
||||
value={read(this.props.auth, 'signUp.form.fname', '')}
|
||||
errors={read(this.props.auth, 'signUp.errors.fname', {})}
|
||||
errors={read(this.props.auth, 'signUp.errors.fname', [])}
|
||||
onChange={this.handleInput.bind(this, "fname")}
|
||||
{...this.props.inputProps.fname} />
|
||||
|
||||
@@ -88,7 +88,7 @@ class EmailSignUpForm extends React.Component {
|
||||
className="email-sign-up-email"
|
||||
disabled={disabled}
|
||||
value={read(this.props.auth, 'signUp.form.lname', '')}
|
||||
errors={read(this.props.auth, 'signUp.errors.lname', {})}
|
||||
errors={read(this.props.auth, 'signUp.errors.lname', [])}
|
||||
onChange={this.handleInput.bind(this, "lname")}
|
||||
{...this.props.inputProps.lname} />
|
||||
|
||||
@@ -98,7 +98,7 @@ class EmailSignUpForm extends React.Component {
|
||||
className="email-sign-up-email"
|
||||
disabled={disabled}
|
||||
value={read(this.props.auth, 'signUp.form.email', '')}
|
||||
errors={read(this.props.auth, 'signUp.errors.email', {})}
|
||||
errors={read(this.props.auth, 'signUp.errors.email', [])}
|
||||
onChange={this.handleInput.bind(this, "email")}
|
||||
{...this.props.inputProps.email} />
|
||||
|
||||
@@ -110,9 +110,10 @@ class EmailSignUpForm extends React.Component {
|
||||
label="SSN"
|
||||
placeholder="SSN"
|
||||
className="email-sign-up-email"
|
||||
bsSize="small"
|
||||
disabled={disabled}
|
||||
value={read(this.props.auth, 'signUp.form.ssn', '')}
|
||||
errors={read(this.props.auth, 'signUp.errors.ssn', {})}
|
||||
errors={read(this.props.auth, 'signUp.errors.ssn', [])}
|
||||
onChange={this.handleInput.bind(this, "ssn")}
|
||||
{...this.props.inputProps.ssn} />
|
||||
|
||||
@@ -120,9 +121,10 @@ class EmailSignUpForm extends React.Component {
|
||||
label="Phone"
|
||||
placeholder="Phone"
|
||||
className="email-sign-up-email"
|
||||
bsSize="small"
|
||||
disabled={disabled}
|
||||
value={read(this.props.auth, 'signUp.form.phoneNumber', '')}
|
||||
errors={read(this.props.auth, 'signUp.errors.phoneNumber', {})}
|
||||
errors={read(this.props.auth, 'signUp.errors.phoneNumber', [])}
|
||||
onChange={this.handleInput.bind(this, "phoneNumber")}
|
||||
{...this.props.inputProps.phoneNumber} />
|
||||
|
||||
@@ -130,9 +132,10 @@ class EmailSignUpForm extends React.Component {
|
||||
label="Address 1"
|
||||
placeholder="Address 1"
|
||||
className="email-sign-up-email"
|
||||
bsSize="small"
|
||||
disabled={disabled}
|
||||
value={read(this.props.auth, 'signUp.form.address1', '')}
|
||||
errors={read(this.props.auth, 'signUp.errors.address1', {})}
|
||||
errors={read(this.props.auth, 'signUp.errors.address1', [])}
|
||||
onChange={this.handleInput.bind(this, "address1")}
|
||||
{...this.props.inputProps.address1} />
|
||||
|
||||
@@ -140,9 +143,10 @@ class EmailSignUpForm extends React.Component {
|
||||
label="Address 2"
|
||||
placeholder="Address 2"
|
||||
className="email-sign-up-email"
|
||||
bsSize="small"
|
||||
disabled={disabled}
|
||||
value={read(this.props.auth, 'signUp.form.address2', '')}
|
||||
errors={read(this.props.auth, 'signUp.errors.address2', {})}
|
||||
errors={read(this.props.auth, 'signUp.errors.address2', [])}
|
||||
onChange={this.handleInput.bind(this, "address2")}
|
||||
{...this.props.inputProps.address2} />
|
||||
|
||||
@@ -150,6 +154,7 @@ class EmailSignUpForm extends React.Component {
|
||||
label="City"
|
||||
placeholder="City"
|
||||
className="email-sign-up-email"
|
||||
bsSize="small"
|
||||
disabled={disabled}
|
||||
value={read(this.props.auth, 'signUp.form.city', '')}
|
||||
errors={read(this.props.auth, 'signUp.errors.city', {})}
|
||||
@@ -160,9 +165,10 @@ class EmailSignUpForm extends React.Component {
|
||||
label="State"
|
||||
placeholder="State"
|
||||
className="email-sign-up-email"
|
||||
bsSize="small"
|
||||
disabled={disabled}
|
||||
value={read(this.props.auth, 'signUp.form.state', '')}
|
||||
errors={read(this.props.auth, 'signUp.errors.state', {})}
|
||||
errors={read(this.props.auth, 'signUp.errors.state', [])}
|
||||
onChange={this.handleInput.bind(this, "state")}
|
||||
{...this.props.inputProps.state} />
|
||||
|
||||
@@ -170,9 +176,10 @@ class EmailSignUpForm extends React.Component {
|
||||
label="ZIP"
|
||||
placeholder="ZIP"
|
||||
className="email-sign-up-email"
|
||||
bsSize="small"
|
||||
disabled={disabled}
|
||||
value={read(this.props.auth, 'signUp.form.zip', '')}
|
||||
errors={read(this.props.auth, 'signUp.errors.zip', {})}
|
||||
errors={read(this.props.auth, 'signUp.errors.zip', [])}
|
||||
onChange={this.handleInput.bind(this, "zip")}
|
||||
{...this.props.inputProps.zip} />
|
||||
|
||||
|
||||
@@ -8,11 +8,11 @@ class AuthInput extends React.Component {
|
||||
static propTypes = {
|
||||
label: PropTypes.string,
|
||||
value: PropTypes.string,
|
||||
errors: PropTypes.object
|
||||
errors: PropTypes.array
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
label: "",
|
||||
label: '',
|
||||
value: null,
|
||||
errors: []
|
||||
};
|
||||
@@ -22,7 +22,8 @@ class AuthInput extends React.Component {
|
||||
}
|
||||
|
||||
renderErrorList () {
|
||||
if (this.props.errors.size) {
|
||||
|
||||
if (this.props.errors.length) {
|
||||
return (
|
||||
<div className='auth-error-message has-error'>
|
||||
{this.props.errors.map((err, i) => {
|
||||
|
||||
@@ -33,6 +33,10 @@ export const signUpReducer = (state = { ...signUpInitialState, form: {...signUpI
|
||||
const { key, value } = action;
|
||||
return {
|
||||
...state,
|
||||
errors: {
|
||||
...(state.errors || {}),
|
||||
[key]: []
|
||||
},
|
||||
form: {
|
||||
...state.form,
|
||||
[key]: value
|
||||
|
||||
128
js-frontend/src/reducers/data/accounts.js
Normal file
128
js-frontend/src/reducers/data/accounts.js
Normal file
@@ -0,0 +1,128 @@
|
||||
/**
|
||||
* Created by andrew on 15/03/16.
|
||||
*/
|
||||
/**
|
||||
* Created by andrew on 15/03/16.
|
||||
*/
|
||||
import T from '../../constants/ACTION_TYPES';
|
||||
import { combineReducers } from 'redux';
|
||||
|
||||
const initialState = {
|
||||
own: [],
|
||||
other: [],
|
||||
create: {
|
||||
form: {},
|
||||
loading: false,
|
||||
errors: {}
|
||||
}
|
||||
};
|
||||
|
||||
const nodeInitialState = {
|
||||
loading: false,
|
||||
data: {}
|
||||
};
|
||||
|
||||
const ownAccountsReducer = (state = [], action ) => {
|
||||
switch (action.type) {
|
||||
default: return state;
|
||||
}
|
||||
};
|
||||
const otherAccountsReducer = (state = [], action ) => {
|
||||
switch (action.type) {
|
||||
default: return state;
|
||||
}
|
||||
};
|
||||
|
||||
const createAccountInitialState = {
|
||||
form: {},
|
||||
loading: false,
|
||||
errors: {}
|
||||
};
|
||||
const createAccountReducer = (state = { ...createAccountInitialState }, action ) => {
|
||||
switch(action.type) {
|
||||
case T.ACCOUNTS.CREATE_START: {
|
||||
return {
|
||||
...state,
|
||||
loading: true
|
||||
};
|
||||
}
|
||||
case T.ACCOUNTS.CREATE_COMPLETE: {
|
||||
return {
|
||||
...createAccountInitialState
|
||||
};
|
||||
}
|
||||
case T.ACCOUNTS.CREATE_ERROR: {
|
||||
const { error = {} } = action;
|
||||
return {
|
||||
...state,
|
||||
loading: false,
|
||||
errors: {
|
||||
...error
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
case T.ACCOUNTS.CREATE_FORM_UPDATE: {
|
||||
const { key, value } = action;
|
||||
return {
|
||||
...state,
|
||||
form: {
|
||||
...state.form,
|
||||
[key]: value
|
||||
},
|
||||
errors: {
|
||||
...state.errors,
|
||||
[key]: []
|
||||
}
|
||||
};
|
||||
}
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
export const accounts = combineReducers({
|
||||
own: ownAccountsReducer,
|
||||
other: otherAccountsReducer,
|
||||
create: createAccountReducer
|
||||
});
|
||||
|
||||
|
||||
//export const accounts = (state = {...initialState}, action) => {
|
||||
// switch(action.type) {
|
||||
// case T.ACCOUNTS.LIST_START:
|
||||
// case T.ACCOUNTS.LIST_COMPLETE:
|
||||
// case T.ACCOUNTS.LIST_ERROR:
|
||||
//
|
||||
// //case T.ACCOUNTS.LIST_REF_START:
|
||||
// case T.AUTH.AUTHENTICATE_COMPLETE:
|
||||
// case T.AUTH.SIGN_IN_COMPLETE: {
|
||||
// const { user } = action;
|
||||
// const { toAccounts = [] } = user;
|
||||
// return accounts(state, {
|
||||
// type: T.ACCOUNTS.LIST_REF_COMPLETE, data: toAccounts
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// case T.ACCOUNTS.LIST_REF_COMPLETE: {
|
||||
// const { data = [] } = action;
|
||||
// return {
|
||||
// ...state,
|
||||
// other: [
|
||||
// ...data
|
||||
// ]
|
||||
// };
|
||||
// }
|
||||
// //case T.ACCOUNTS.LIST_REF_ERROR:
|
||||
//
|
||||
//
|
||||
//
|
||||
// case T.ACCOUNTS.CREATE_REF_START:
|
||||
// case T.ACCOUNTS.CREATE_REF_COMPLETE:
|
||||
// case T.ACCOUNTS.CREATE_REF_ERROR:
|
||||
// case T.ACCOUNTS.CREATE_REF_FORM_UPDATE:
|
||||
//
|
||||
// default:
|
||||
// return state;
|
||||
// }
|
||||
//};
|
||||
@@ -1,13 +0,0 @@
|
||||
import typeReducers from '../../utils/typeReducers'
|
||||
import ACTION_TYPES from '../../constants/ACTION_TYPES'
|
||||
|
||||
|
||||
const defaultState = {}
|
||||
|
||||
|
||||
export default typeReducers(ACTION_TYPES.DOCUMENT_DATA, defaultState, {
|
||||
UPDATE: (state, {id, data}) => ({
|
||||
...state,
|
||||
[id]: { ...state[id], ...data },
|
||||
})
|
||||
})
|
||||
43
js-frontend/src/reducers/data/entities.js
Normal file
43
js-frontend/src/reducers/data/entities.js
Normal file
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Created by andrew on 15/03/16.
|
||||
*/
|
||||
import T from '../../constants/ACTION_TYPES';
|
||||
|
||||
const initialState = {
|
||||
};
|
||||
|
||||
const nodeInitialState = {
|
||||
loading: false,
|
||||
data: {}
|
||||
};
|
||||
|
||||
export const entities = (state = {...initialState}, action) => {
|
||||
switch(action.type) {
|
||||
case T.ENTITIES.REQUESTED: {
|
||||
const { id } = action;
|
||||
return {
|
||||
...state,
|
||||
[id]: {
|
||||
...nodeInitialState,
|
||||
loading: true
|
||||
}
|
||||
}
|
||||
}
|
||||
case T.ENTITIES.RECEIVED: {
|
||||
const { id, entity = {} } = action;
|
||||
return {
|
||||
...state,
|
||||
[id]: {
|
||||
...(state[id] || nodeInitialState),
|
||||
loading: false,
|
||||
data: {
|
||||
...entity
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
case T.ENTITIES.RECEIVED_LIST:
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
19
js-frontend/src/reducers/data/index.js
Normal file
19
js-frontend/src/reducers/data/index.js
Normal file
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* Created by andrew on 15/03/16.
|
||||
*/
|
||||
/**
|
||||
* Created by andrew on 25/02/16.
|
||||
*/
|
||||
import { combineReducers } from 'redux';
|
||||
|
||||
import { accounts } from './accounts';
|
||||
import { transfers } from './transfers';
|
||||
import { entities } from './entities';
|
||||
|
||||
const dataReducer = combineReducers({
|
||||
accounts,
|
||||
transfers,
|
||||
entities
|
||||
});
|
||||
|
||||
export default dataReducer;
|
||||
46
js-frontend/src/reducers/data/transfers.js
Normal file
46
js-frontend/src/reducers/data/transfers.js
Normal file
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Created by andrew on 15/03/16.
|
||||
*/
|
||||
/**
|
||||
* Created by andrew on 15/03/16.
|
||||
*/
|
||||
import T from '../../constants/ACTION_TYPES';
|
||||
|
||||
const initialState = {
|
||||
};
|
||||
|
||||
const nodeInitialState = {
|
||||
loading: false,
|
||||
data: {}
|
||||
};
|
||||
|
||||
export const transfers = (state = {...initialState}, action) => {
|
||||
switch(action.type) {
|
||||
case T.ENTITIES.REQUESTED: {
|
||||
const { id } = action;
|
||||
return {
|
||||
...state,
|
||||
[id]: {
|
||||
...nodeInitialState,
|
||||
loading: true
|
||||
}
|
||||
}
|
||||
}
|
||||
case T.ENTITIES.RECEIVED: {
|
||||
const { id, entity = {} } = action;
|
||||
return {
|
||||
...state,
|
||||
[id]: {
|
||||
...(state[id] || nodeInitialState),
|
||||
loading: false,
|
||||
data: {
|
||||
...entity
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
case T.ENTITIES.RECEIVED_LIST:
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
@@ -1,21 +0,0 @@
|
||||
import { combineReducers } from 'redux'
|
||||
|
||||
|
||||
import navigation from './navigationReducer'
|
||||
|
||||
import documentListView from './view/documentListViewReducer'
|
||||
import documentView from './view/documentViewReducer'
|
||||
|
||||
import documentData from './data/documentDataReducer'
|
||||
|
||||
|
||||
export default combineReducers({
|
||||
navigation,
|
||||
view: combineReducers({
|
||||
documentList: documentListView,
|
||||
document: documentView,
|
||||
}),
|
||||
data: combineReducers({
|
||||
document: documentData,
|
||||
}),
|
||||
})
|
||||
@@ -1,19 +0,0 @@
|
||||
import typeReducers from '../utils/typeReducers'
|
||||
import ACTION_TYPES from '../constants/ACTION_TYPES'
|
||||
|
||||
|
||||
const defaultState = {
|
||||
transitioning: true,
|
||||
location: null,
|
||||
}
|
||||
|
||||
export default typeReducers(ACTION_TYPES.NAVIGATION, defaultState, {
|
||||
START: () => ({
|
||||
transitioning: true,
|
||||
}),
|
||||
|
||||
COMPLETE: (state, {location}) => ({
|
||||
transitioning: false,
|
||||
location,
|
||||
}),
|
||||
})
|
||||
@@ -1,10 +0,0 @@
|
||||
import typeReducers from '../../utils/typeReducers'
|
||||
import ACTION_TYPES from '../../constants/ACTION_TYPES'
|
||||
|
||||
|
||||
const defaultState = ''
|
||||
|
||||
|
||||
export default typeReducers(ACTION_TYPES.DOCUMENT_LIST_VIEW, defaultState, {
|
||||
SET_QUERY: (state, {query}) => query,
|
||||
})
|
||||
@@ -1,53 +0,0 @@
|
||||
import pick from 'object-pick'
|
||||
import typeReducers from '../../utils/typeReducers'
|
||||
import compact from '../../utils/compact'
|
||||
import ACTION_TYPES from '../../constants/ACTION_TYPES'
|
||||
|
||||
|
||||
const defaultState = {
|
||||
unsavedChanges: {},
|
||||
saveErrors: {},
|
||||
}
|
||||
|
||||
|
||||
export default typeReducers(ACTION_TYPES.DOCUMENT_VIEW, defaultState, {
|
||||
// Update the current document data
|
||||
UPDATE_DATA: (state, {id, data}) => ({
|
||||
...state,
|
||||
unsavedChanges: {
|
||||
...state.unsavedChanges,
|
||||
[id]: { ...state.unsavedChanges[id], ...data },
|
||||
},
|
||||
}),
|
||||
|
||||
// If there are fields marked as invalid which are now valid,
|
||||
// mark them as valid
|
||||
REMOVE_STALE_ERRORS: (state, {id, errors}) => ({
|
||||
...state,
|
||||
saveErrors: {
|
||||
...state.saveErrors,
|
||||
[id]: compact(pick(state.saveErrors[id], Object.keys(errors || {}))),
|
||||
},
|
||||
}),
|
||||
|
||||
// Set the errors to the passed in object
|
||||
SET_ERRORS: (state, {id, errors}) => ({
|
||||
...state,
|
||||
saveErrors: {
|
||||
...state.saveErrors,
|
||||
[id]: errors
|
||||
},
|
||||
}),
|
||||
|
||||
// Remove errors/data for an id
|
||||
CLEAR: (state, {id}) => ({
|
||||
unsavedChanges: {
|
||||
...state.unsavedChanges,
|
||||
[id]: null,
|
||||
},
|
||||
saveErrors: {
|
||||
...state.saveErrors,
|
||||
[id]: null,
|
||||
},
|
||||
}),
|
||||
})
|
||||
@@ -1,17 +0,0 @@
|
||||
/**
|
||||
* Created by andrew on 25/02/16.
|
||||
*/
|
||||
//import * as A from "../actions/auth";
|
||||
import T from '../constants/ACTION_TYPES';
|
||||
import {
|
||||
authenticateStart,
|
||||
authenticateComplete,
|
||||
authenticateError
|
||||
} from '../actions/auth';
|
||||
|
||||
|
||||
export function configure(endpoint = {}, settings = {}) {
|
||||
return dispatch => {
|
||||
dispatch(authenticateStart());
|
||||
};
|
||||
};
|
||||
12
js-frontend/src/utils/actions.js
Normal file
12
js-frontend/src/utils/actions.js
Normal file
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* Created by andrew on 15/03/16.
|
||||
*/
|
||||
export function makeActionCreator(type, ...argNames) {
|
||||
return function(...args) {
|
||||
const action = { type };
|
||||
argNames.forEach((arg, index) => {
|
||||
action[argNames[index]] = args[index]
|
||||
});
|
||||
return action;
|
||||
};
|
||||
}
|
||||
@@ -45,7 +45,8 @@ export function apiGetCurrentUser() {
|
||||
}).then(parseResponse);
|
||||
}
|
||||
|
||||
export function apiCreateAccount(customerId, title, initialBalance) {
|
||||
export function apiCreateAccount(customerId, {
|
||||
title, balance: initialBalance, description }) {
|
||||
//{
|
||||
//"accountId": "0000015377cf131b-a250093f26850000"
|
||||
//}
|
||||
@@ -56,7 +57,24 @@ export function apiCreateAccount(customerId, title, initialBalance) {
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
method: "post",
|
||||
body: root.JSON.stringify({ customerId, title, initialBalance })
|
||||
body: root.JSON.stringify({
|
||||
customerId,
|
||||
title,
|
||||
initialBalance,
|
||||
description })
|
||||
}).then(parseResponse);
|
||||
}
|
||||
|
||||
export function apiRetrieveAccounts(customerId) {
|
||||
return fetch(getAccountsUrl(), {
|
||||
headers: {
|
||||
"Accept": "application/json",
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
method: "get",
|
||||
body: {
|
||||
customerId
|
||||
}
|
||||
}).then(parseResponse);
|
||||
}
|
||||
|
||||
@@ -81,4 +99,5 @@ export function apiRetrieveUsers(search) {
|
||||
email: search
|
||||
}
|
||||
}).then(parseResponse);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -115,20 +115,20 @@ export function getSessionEndpoint (k) {
|
||||
// return `${getApiUrl(endpointKey)}${getSessionEndpoint(endpointKey).signOutPath}`
|
||||
//}
|
||||
|
||||
export function getEmailSignInUrl (endpointKey) {
|
||||
return `${getSessionEndpoint(endpointKey).emailSignInPath}`
|
||||
export function getEmailSignInUrl () {
|
||||
return `${getSessionEndpoint().emailSignInPath}`
|
||||
}
|
||||
|
||||
export function getEmailSignUpUrl (endpointKey) {
|
||||
return `${getSessionEndpoint(endpointKey).emailRegistrationPath}`
|
||||
export function getEmailSignUpUrl () {
|
||||
return `${getSessionEndpoint().emailRegistrationPath}`
|
||||
}
|
||||
|
||||
export function getCurrentUserUrl (endpointKey) {
|
||||
return `${getSessionEndpoint(endpointKey).currentUserPath}`
|
||||
export function getCurrentUserUrl () {
|
||||
return `${getSessionEndpoint().currentUserPath}`
|
||||
}
|
||||
|
||||
export function getAccountsUrl (endpointKey) {
|
||||
return `${getSessionEndpoint(endpointKey).accountsPath}`
|
||||
export function getAccountsUrl () {
|
||||
return `${getSessionEndpoint().accountsPath}`
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
import compact from '../utils/compact'
|
||||
|
||||
|
||||
export default function documentValidator(data) {
|
||||
return compact({
|
||||
titleExists:
|
||||
!data.title &&
|
||||
"You must specify a title for your document",
|
||||
})
|
||||
}
|
||||
@@ -10,6 +10,8 @@ import Select from "react-select";
|
||||
import * as Modals from './modals';
|
||||
import IndexPanel from "./../components/partials/IndexPanel";
|
||||
|
||||
import * as A from '../actions/entities';
|
||||
|
||||
|
||||
const resetModals = {
|
||||
showAccountModal: false,
|
||||
@@ -23,13 +25,6 @@ class MyAccounts extends React.Component {
|
||||
super(...args);
|
||||
this.state = { ...resetModals };
|
||||
}
|
||||
updateTheme (theme) {
|
||||
//this.props.dispatch(updateDemoTheme(theme));
|
||||
}
|
||||
|
||||
updateEndpoint (endpoint) {
|
||||
//this.props.dispatch(updateDemoEndpoint(endpoint));
|
||||
}
|
||||
|
||||
createAccountModal() {
|
||||
this.setState({
|
||||
@@ -37,7 +32,15 @@ class MyAccounts extends React.Component {
|
||||
});
|
||||
}
|
||||
|
||||
createAccountModalConfirmed() {
|
||||
createAccountModalConfirmed(evt, payload) {
|
||||
|
||||
const {
|
||||
id: customerId
|
||||
} = this.props.auth.user.attributes;
|
||||
|
||||
this.props.dispatch(A.accountCreate(customerId, payload))
|
||||
.then(this.close.bind(this));
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -52,9 +55,10 @@ class MyAccounts extends React.Component {
|
||||
|
||||
}
|
||||
|
||||
remove3rdPartyAccountModal() {
|
||||
remove3rdPartyAccountModal(evt, evtKey) {
|
||||
|
||||
const account = null;
|
||||
debugger;
|
||||
const account = evtKey;
|
||||
this.setState({
|
||||
accountToRemove: account,
|
||||
showDeleteAccountModal: true
|
||||
@@ -78,6 +82,7 @@ class MyAccounts extends React.Component {
|
||||
//</Tooltip>);
|
||||
const user = this.props.auth.user.attributes;
|
||||
const {
|
||||
id: customerId,
|
||||
email = '',
|
||||
ssn = '',
|
||||
name = {},
|
||||
@@ -86,10 +91,8 @@ class MyAccounts extends React.Component {
|
||||
toAccounts
|
||||
} = user;
|
||||
|
||||
const {
|
||||
firstName = '',
|
||||
lastName = ''
|
||||
} = name;
|
||||
const firstName = name.firstName || '';
|
||||
const lastName = name.lastName || '';
|
||||
|
||||
const {
|
||||
city,
|
||||
@@ -99,11 +102,25 @@ class MyAccounts extends React.Component {
|
||||
zipCode
|
||||
} = address;
|
||||
|
||||
|
||||
|
||||
const { showAccountModal, show3rdPartyAccountModal, showDeleteAccountModal } = this.state;
|
||||
const { accountToRemove = null } = this.state;
|
||||
|
||||
const refAccountsData = this.props.app.accounts.other || [];
|
||||
|
||||
const refAccounts = refAccountsData.map((item, idx) => (
|
||||
<tr key={`ref_${idx}`}>
|
||||
<td><a href="#">${item.title}</a>{
|
||||
(item.description) ? [
|
||||
(<br />),
|
||||
<span>{ item.description }</span>
|
||||
]: null
|
||||
}
|
||||
</td>
|
||||
<td><Button eventKey={item.id} bsStyle={"link"} onClick={this.remove3rdPartyAccountModal.bind(this)}>remove</Button>
|
||||
</td>
|
||||
</tr>
|
||||
));
|
||||
|
||||
return (
|
||||
<div>
|
||||
<PageHeader>
|
||||
@@ -142,7 +159,6 @@ class MyAccounts extends React.Component {
|
||||
|
||||
</IndexPanel>
|
||||
|
||||
|
||||
</Row>
|
||||
<Table>
|
||||
<thead>
|
||||
@@ -156,17 +172,14 @@ class MyAccounts extends React.Component {
|
||||
<td><a href="#">Account Title #1</a></td>
|
||||
<td>$100.00</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="#">Account Title #2</a></td>
|
||||
<td><Button bsStyle={"link"} onClick={this.remove3rdPartyAccountModal.bind(this)}>remove</Button>
|
||||
</td>
|
||||
</tr>
|
||||
{ refAccounts }
|
||||
</tbody>
|
||||
</Table>
|
||||
|
||||
|
||||
<Modals.NewAccountModal show={showAccountModal}
|
||||
action={this.createAccountModalConfirmed.bind(this)}
|
||||
account={ this.props.app.accounts.create }
|
||||
onHide={this.close.bind(this)}
|
||||
key={0} />
|
||||
|
||||
@@ -244,13 +257,8 @@ class MyAccounts extends React.Component {
|
||||
</IndexPanel>
|
||||
*/
|
||||
|
||||
export default connect(({auth, demoUi = new Map()}) => {
|
||||
export default connect(({ auth, app }) => {
|
||||
return ({
|
||||
auth,
|
||||
currentUserUid: auth.user && auth.user.attributes && auth.user.attributes.provider || "none",
|
||||
currentUserProvider: auth.user && auth.user.attributes && auth.user.attributes.uid || "none",
|
||||
currentUserEndpoint: "none",
|
||||
//theme: demoUi.get("theme"),
|
||||
pageEndpoint: null
|
||||
auth, app
|
||||
})
|
||||
})(MyAccounts);
|
||||
@@ -6,12 +6,10 @@ import { PageHeader } from "react-bootstrap";
|
||||
import { connect } from "react-redux";
|
||||
|
||||
//import ButtonLoader from "./ButtonLoader";
|
||||
import { Input } from "react-bootstrap";
|
||||
import * as BS from "react-bootstrap";
|
||||
|
||||
|
||||
import {pushState} from "redux-router";
|
||||
|
||||
import ButtonLoader from "../controls/bootstrap/ButtonLoader";
|
||||
|
||||
//export {bootstrap, materialUi} from "./views";
|
||||
|
||||
|
||||
@@ -1,37 +1,171 @@
|
||||
/**
|
||||
* Created by andrew on 20/02/16.
|
||||
*/
|
||||
import React from "react";
|
||||
import { PageHeader, OverlayTrigger, Modal, Tooltip, Grid, Col, Row, Nav, NavItem, ButtonGroup, Button, Table } from "react-bootstrap";
|
||||
import { Link, IndexLink} from "react-router";
|
||||
import React, { PropTypes } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import Select from "react-select";
|
||||
|
||||
import * as BS from "react-bootstrap";
|
||||
import Input from "../../controls/bootstrap/Input";
|
||||
import ButtonLoader from "../../controls/bootstrap/ButtonLoader";
|
||||
|
||||
//import { PageHeader, OverlayTrigger, Modal, Tooltip, Grid, Col, Row, Nav, NavItem, ButtonGroup, Button, Table } from "react-bootstrap";
|
||||
import { Link, IndexLink} from "react-router";
|
||||
import read from '../../utils/readProp';
|
||||
|
||||
import { accountCreateFormUpdate, accountCreateError } from '../../actions/entities';
|
||||
|
||||
const formValidation = (payload) => ['title', 'balance', 'description'].reduce((memo, prop) => {
|
||||
let result = [];
|
||||
const value = (payload[prop] || '').replace(/(^\s+)|(\s+$)/g, '');
|
||||
|
||||
switch (prop) {
|
||||
case 'title':
|
||||
case 'balance':
|
||||
if (/^$/.test(value)) {
|
||||
result.push('required');
|
||||
}
|
||||
}
|
||||
|
||||
switch (prop) {
|
||||
case 'balance':
|
||||
if (!/\d+/.test(value)) {
|
||||
result.push('need to be a number');
|
||||
}
|
||||
}
|
||||
|
||||
switch (prop) {
|
||||
case 'description':
|
||||
if (value.length > 400) {
|
||||
result.push('need to less than 400 symbols long');
|
||||
}
|
||||
|
||||
}
|
||||
if (result.length) {
|
||||
memo[prop] = result;
|
||||
memo.hasErrors = true;
|
||||
}
|
||||
return memo;
|
||||
}, {});
|
||||
|
||||
export class NewAccountModal extends React.Component {
|
||||
render() {
|
||||
return (<Modal show={this.props.show} onHide={this.props.onHide} key={0}>
|
||||
<Modal.Header closeButton>
|
||||
<Modal.Title>New Account</Modal.Title>
|
||||
</Modal.Header>
|
||||
<Modal.Body>
|
||||
<form>
|
||||
Title <br/>
|
||||
Balance <br/>
|
||||
Description
|
||||
</form>
|
||||
</Modal.Body>
|
||||
<Modal.Footer>
|
||||
<Button onClick={this.props.onHide}>Cancel</Button>
|
||||
<Button bsStyle="primary" onClick={this.props.action}>Create</Button>
|
||||
</Modal.Footer>
|
||||
</Modal>);
|
||||
|
||||
static propTypes = {
|
||||
inputProps: PropTypes.shape({
|
||||
title: PropTypes.object,
|
||||
balance: PropTypes.object,
|
||||
description: PropTypes.object,
|
||||
submit: PropTypes.object
|
||||
}),
|
||||
action: PropTypes.func,
|
||||
account: PropTypes.object.isRequired
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
inputProps: {
|
||||
title: {},
|
||||
balance: {},
|
||||
description: {},
|
||||
submit: {}
|
||||
}
|
||||
};
|
||||
|
||||
handleSubmit(event) {
|
||||
event.preventDefault();
|
||||
|
||||
const payload = { ...this.props.account.form };
|
||||
|
||||
const validationErrors = formValidation(payload);
|
||||
if (validationErrors.hasErrors) {
|
||||
this.props.dispatch(accountCreateError(validationErrors));
|
||||
return;
|
||||
}
|
||||
|
||||
const { action } = this.props;
|
||||
|
||||
if (action) {
|
||||
action(event, payload);
|
||||
}
|
||||
}
|
||||
|
||||
handleInput(key, val) {
|
||||
this.props.dispatch(accountCreateFormUpdate(key, val));
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
const disabled = (
|
||||
this.props.account.loading
|
||||
);
|
||||
|
||||
const actionLabel = 'Create';
|
||||
|
||||
return (<BS.Modal show={this.props.show} onHide={this.props.onHide} key={0}>
|
||||
<BS.Modal.Header closeButton>
|
||||
<BS.Modal.Title>New Account</BS.Modal.Title>
|
||||
</BS.Modal.Header>
|
||||
<BS.Modal.Body>
|
||||
<form className='account-create-form clearfix'
|
||||
onSubmit={this.handleSubmit.bind(this)}>
|
||||
|
||||
<Input type="text"
|
||||
className="account-create-title"
|
||||
label="Title"
|
||||
placeholder="Title"
|
||||
name="title"
|
||||
disabled={disabled}
|
||||
value={read(this.props.account, 'form.title', '')}
|
||||
errors={read(this.props.account, 'errors.title', [])}
|
||||
onChange={this.handleInput.bind(this, "title")}
|
||||
{...this.props.inputProps.title} />
|
||||
|
||||
<Input type="text"
|
||||
className="account-create-balance"
|
||||
label="Balance"
|
||||
placeholder="Balance"
|
||||
name="balance"
|
||||
addonBefore={
|
||||
(<BS.Glyphicon glyph="usd" />)
|
||||
}
|
||||
addonAfter=".00"
|
||||
disabled={disabled}
|
||||
value={read(this.props.account, 'form.balance', '')}
|
||||
errors={read(this.props.account, 'errors.balance', [])}
|
||||
onChange={this.handleInput.bind(this, 'balance')}
|
||||
{...this.props.inputProps.balance} />
|
||||
|
||||
<Input type="textarea"
|
||||
className="account-create-description"
|
||||
label="Description"
|
||||
placeholder="Description"
|
||||
name="description"
|
||||
disabled={disabled}
|
||||
value={read(this.props.account, 'form.description', '')}
|
||||
errors={read(this.props.account, 'errors.description', [])}
|
||||
onChange={this.handleInput.bind(this, 'description')}
|
||||
{...this.props.inputProps.description} />
|
||||
|
||||
|
||||
</form>
|
||||
|
||||
</BS.Modal.Body>
|
||||
<BS.Modal.Footer>
|
||||
<BS.Button onClick={this.props.onHide}>Cancel</BS.Button>
|
||||
<ButtonLoader loading={read(this.props.account, 'loading', false)}
|
||||
type="submit"
|
||||
bsStyle="primary"
|
||||
icon={<BS.Glyphicon glyph="plus" />}
|
||||
disabled={disabled}
|
||||
onClick={this.handleSubmit.bind(this)}
|
||||
{...this.props.inputProps.submit}>
|
||||
{actionLabel}
|
||||
</ButtonLoader>
|
||||
</BS.Modal.Footer>
|
||||
</BS.Modal>);
|
||||
}
|
||||
// className='account-create-submit pull-right'
|
||||
|
||||
}
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
//token: state.auth.token,
|
||||
//userName: state.auth.userName,
|
||||
//isAuthenticated: state.auth.isAuthenticated
|
||||
});
|
||||
const mapStateToProps = ({ }) => ({ });
|
||||
|
||||
export default connect(mapStateToProps)(NewAccountModal);
|
||||
Reference in New Issue
Block a user