diff --git a/js-frontend/src/actions/entities.js b/js-frontend/src/actions/entities.js index d684d21..2ec3499 100644 --- a/js-frontend/src/actions/entities.js +++ b/js-frontend/src/actions/entities.js @@ -56,7 +56,7 @@ export function accountCreate(customerId, payload) { ...payload })); dispatch(entityReceived(accountId, payload)); - return authenticate(true); + return dispatch(authenticate(true)); }) .catch(err => { dispatch(accountCreateError(err)); @@ -87,4 +87,36 @@ export function fetchAccount(accountId) { dispatch(accountError(err)); }); }; +} + +export const deleteAccountRequested = makeActionCreator(T.ACCOUNT.DELETE_START); +export const deleteAccountComplete = makeActionCreator(T.ACCOUNT.DELETE_COMPLETE); +export const deleteAccountError = makeActionCreator(T.ACCOUNT.DELETE_ERROR); + +export function deleteAccount(customerId, accountId) { + return dispatch => { + dispatch(deleteAccountRequested()); + return api.apiDeleteAccount(accountId) + .then(data => { + //debugger; + dispatch(deleteAccountComplete()); + return Promise.resolve('ok'); + }) + .catch(err => { + dispatch(deleteAccountError()); + return Promise.reject(err); + }) + }; +} + +export const errorMessageStart = makeActionCreator(T.ERROR.START, 'payload'); +export const errorMessageStop = makeActionCreator(T.ERROR.STOP); + +export function errorMessageTimedOut(error, timeout) { + return dispatch => { + dispatch(errorMessageStart(error)); + setTimeout(() => { + dispatch(errorMessageStop()); + }, timeout || 5000); + }; } \ No newline at end of file diff --git a/js-frontend/src/components/AuthComponent.js b/js-frontend/src/components/AuthComponent.js index 64d288d..e93ed2d 100644 --- a/js-frontend/src/components/AuthComponent.js +++ b/js-frontend/src/components/AuthComponent.js @@ -5,6 +5,8 @@ import React from 'react'; import { connect } from 'react-redux'; import { pushState } from 'redux-router'; +import read from '../utils/readProp'; + export function requireAuthentication(Component) { class AuthComponent extends React.Component { @@ -45,12 +47,8 @@ export function requireAuthentication(Component) { const mapStateToProps = (state) => { - console.info('state', state); return ({ - //token: state.auth.token, - //userName: state.auth.userName, - //isAuthenticated: state.auth.isAuthenticated - isAuthenticated: state.app.auth.user.isSignedIn + isAuthenticated: read(state, 'app.auth.user.isSignedIn', false) }) }; diff --git a/js-frontend/src/constants/ACTION_TYPES.js b/js-frontend/src/constants/ACTION_TYPES.js index cf2c11c..d77fbda 100644 --- a/js-frontend/src/constants/ACTION_TYPES.js +++ b/js-frontend/src/constants/ACTION_TYPES.js @@ -50,6 +50,14 @@ export default defineActionTypes({ SINGLE_START SINGLE_COMPLETE SINGLE_ERROR + DELETE_START + DELETE_COMPLETE + DELETE_ERROR + `, + + ERROR: ` + START + STOP ` }) diff --git a/js-frontend/src/reducers/ui/bookmarkAccount.js b/js-frontend/src/reducers/ui/bookmarkAccount.js new file mode 100644 index 0000000..43ce61e --- /dev/null +++ b/js-frontend/src/reducers/ui/bookmarkAccount.js @@ -0,0 +1,9 @@ +/** + * Created by andrew on 18/03/16. + */ +export const bookmarkAccount = (state = {}, action) => { + switch (action.type) { + default: + return state; + } +}; \ No newline at end of file diff --git a/js-frontend/src/reducers/ui/errors.js b/js-frontend/src/reducers/ui/errors.js new file mode 100644 index 0000000..146aba0 --- /dev/null +++ b/js-frontend/src/reducers/ui/errors.js @@ -0,0 +1,17 @@ +/** + * Created by andrew on 18/03/16. + */ + +import T from '../../constants/ACTION_TYPES'; + +export const error = (state = null, action ) => { + switch (action.type) { + case T.ERROR.STOP: { + return null; + } + case T.ERROR.START: + return action.payload; + default: + return state; + } +}; \ No newline at end of file diff --git a/js-frontend/src/reducers/ui/index.js b/js-frontend/src/reducers/ui/index.js index 16fd213..2e4ada8 100644 --- a/js-frontend/src/reducers/ui/index.js +++ b/js-frontend/src/reducers/ui/index.js @@ -7,9 +7,13 @@ import { combineReducers } from 'redux'; import { account } from './account'; +import { error } from './errors'; +import { bookmarkAccount } from './bookmarkAccount'; const uiReducer = combineReducers({ - account + account, + error, + bookmarkAccount }); export default uiReducer; \ No newline at end of file diff --git a/js-frontend/src/utils/api.js b/js-frontend/src/utils/api.js index 7306710..cebca74 100644 --- a/js-frontend/src/utils/api.js +++ b/js-frontend/src/utils/api.js @@ -93,6 +93,20 @@ export function apiRetrieveAccount(accountId) { }).then(parseResponse); } +export function apiDeleteAccount(accountId) { + return Promise.reject({ + message: '\'Delete Account\' is not implemented.' + }); + + return fetch(`${getAccountsUrl()}/${accountId}`, { + headers: { + "Accept": "application/json", + "Content-Type": "application/json" + }, + method: "delete" + }).then(parseResponse); +} + export function apiRetrieveUsers(search) { return fetch(getCurrentUserUrl(), { headers: { diff --git a/js-frontend/src/views/Account.js b/js-frontend/src/views/Account.js index 3b7efb6..213032a 100644 --- a/js-frontend/src/views/Account.js +++ b/js-frontend/src/views/Account.js @@ -101,11 +101,11 @@ export class Account extends React.Component { return memo; }, [])); - const { title = '[No title]', description: descriptionRaw, balance: balanceRaw } = account; + const { title: titleRaw, description: descriptionRaw, balance: balanceRaw } = account; + const title = titleRaw || '[No title]'; const balance = ((balanceRaw > 0 && balanceRaw < 1) ? '$0' : '$') + Number(balanceRaw).toFixed(2); - - const description = descriptionRaw || '[No description provided]'; + const description = descriptionRaw || '[No description]'; return (
diff --git a/js-frontend/src/views/MyAccounts.js b/js-frontend/src/views/MyAccounts.js index da0ebc3..300a93d 100644 --- a/js-frontend/src/views/MyAccounts.js +++ b/js-frontend/src/views/MyAccounts.js @@ -3,6 +3,7 @@ */ import React from "react"; import { PageHeader, OverlayTrigger, Tooltip, Grid, Col, Row, Nav, NavItem, ButtonGroup, Button, Table } from "react-bootstrap"; +import * as BS from "react-bootstrap"; import { Link, IndexLink} from "react-router"; import { connect } from "react-redux"; //import * as DefaultTheme from "redux-auth"; @@ -11,6 +12,7 @@ import * as Modals from './modals'; import IndexPanel from "./../components/partials/IndexPanel"; import * as A from '../actions/entities'; +import read from '../utils/readProp'; const resetModals = { @@ -39,15 +41,17 @@ class MyAccounts extends React.Component { }); } - createAccountModalConfirmed(evt, payload) { + createAccountModalConfirmed(payload) { const { id: customerId } = this.props.auth.user.attributes; this.props.dispatch(A.accountCreate(customerId, payload)) - .then(this.close.bind(this)); - + .then(() => { + this.close.bind(this); + this.props.dispatch(A.fetchOwnAccounts(customerId)); + }); } create3rdPartyAccountModal() { @@ -61,18 +65,22 @@ class MyAccounts extends React.Component { } - remove3rdPartyAccountModal(evt, evtKey) { - - debugger; - const account = evtKey; + remove3rdPartyAccountModal(accountId, evt) { + const account = this.props.app.entities[accountId]; this.setState({ accountToRemove: account, showDeleteAccountModal: true }); } - remove3rdPartyAccountModalConfirmed() { - + remove3rdPartyAccountModalConfirmed(accountId) { + const { customerId } = this.props; + this.props.dispatch(A.deleteAccount(customerId, accountId)) + .then(this.close.bind(this), + err => { + this.props.dispatch(A.errorMessageTimedOut(err && err.message || err)); + this.close(); + }); } close() { @@ -109,7 +117,10 @@ class MyAccounts extends React.Component { } = address; const { showAccountModal, show3rdPartyAccountModal, showDeleteAccountModal } = this.state; - const { accountToRemove = null } = this.state; + const { accountToRemove = null} = this.state; + + const { error } = this.props; + const errorLine = error ? ({ error }) : []; const ownAccountsData = this.props.app.accounts.own || []; @@ -122,15 +133,17 @@ class MyAccounts extends React.Component { accountId, balance, description = '', title }, idx) => ( - { title }{ + { title }{ (description) ? [ (
), { description } ]: null } - ${ balance } + ${ balance } + )); + const refAccountsData = this.props.app.accounts.other || []; const refAccounts = refAccountsData.map(({ title, @@ -138,14 +151,15 @@ class MyAccounts extends React.Component { id }, idx) => ( - { title }{ + { title }{ (description) ? [ (
), { description } ]: null } - + + )); @@ -162,6 +176,8 @@ class MyAccounts extends React.Component { + { errorLine } + @@ -194,6 +210,7 @@ class MyAccounts extends React.Component { Account Title Balance + @@ -286,6 +303,8 @@ class MyAccounts extends React.Component { export default connect(({ app }) => { return ({ auth: app.auth, - app: app.data + app: app.data, + customerId: read(app, 'auth.user.isSignedIn', false) ? read(app, 'auth.user.attributes.id', null): null, + error: app.ui.error }) })(MyAccounts); \ No newline at end of file diff --git a/js-frontend/src/views/modals/Add3rdPartyAccountModal.js b/js-frontend/src/views/modals/Add3rdPartyAccountModal.js index aff5b97..890259e 100644 --- a/js-frontend/src/views/modals/Add3rdPartyAccountModal.js +++ b/js-frontend/src/views/modals/Add3rdPartyAccountModal.js @@ -3,12 +3,21 @@ */ import React from "react"; import { PageHeader, OverlayTrigger, Modal, Tooltip, Grid, Col, Row, Nav, NavItem, ButtonGroup, Button, Table } from "react-bootstrap"; +import * as BS from "react-bootstrap"; +import Input from "../../controls/bootstrap/Input"; +import read from '../../utils/readProp'; + import { Link, IndexLink} from "react-router"; import { connect } from "react-redux"; import Select from "react-select"; export class Add3rdPartyAccountModal extends React.Component { + + ownerTypeIn(argq, arg2, arg3) { + debugger; + } + ownerChanged(argq, arg2, arg3) { debugger; } @@ -17,8 +26,12 @@ export class Add3rdPartyAccountModal extends React.Component { debugger; } + handleInput() {} + render() { + const disabled = false; + return ( @@ -35,7 +48,9 @@ export class Add3rdPartyAccountModal extends React.Component { {value: "bootstrap", label: "Bootstrap"}, {value: "materialUi", label: "Material UI"} ]} + onInputChange={this.ownerTypeIn.bind(this)} onChange={this.ownerChanged.bind(this)} /> + @@ -59,10 +82,8 @@ export class Add3rdPartyAccountModal extends React.Component { } } -const mapStateToProps = (state) => ({ - //token: state.auth.token, - //userName: state.auth.userName, - //isAuthenticated: state.auth.isAuthenticated +const mapStateToProps = ({ app }) => ({ + ui: app.ui.bookmarkAccount }); export default connect(mapStateToProps)(Add3rdPartyAccountModal); \ No newline at end of file diff --git a/js-frontend/src/views/modals/NewAccountModal.js b/js-frontend/src/views/modals/NewAccountModal.js index b32cf89..45ff4a4 100644 --- a/js-frontend/src/views/modals/NewAccountModal.js +++ b/js-frontend/src/views/modals/NewAccountModal.js @@ -7,8 +7,8 @@ import { connect } from "react-redux"; 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'; @@ -83,7 +83,7 @@ export class NewAccountModal extends React.Component { const { action } = this.props; if (action) { - action(event, payload); + action(payload); } } @@ -162,10 +162,6 @@ export class NewAccountModal extends React.Component { ); } - // className='account-create-submit pull-right' - } -const mapStateToProps = ({ }) => ({ }); - -export default connect(mapStateToProps)(NewAccountModal); \ No newline at end of file +export default connect()(NewAccountModal); \ No newline at end of file diff --git a/js-frontend/src/views/modals/RemoveAccountBookmarkModal.js b/js-frontend/src/views/modals/RemoveAccountBookmarkModal.js deleted file mode 100644 index b47f8ea..0000000 --- a/js-frontend/src/views/modals/RemoveAccountBookmarkModal.js +++ /dev/null @@ -1,44 +0,0 @@ -/** - * 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 { connect } from "react-redux"; -import Select from "react-select"; - -export class NewAccountModal extends React.Component { - render() { - const account = this.props.account; - - return ( - - Remove Account Bookmark - - -
- -
Acct one
- -
$105.00
- - -
$105.00
- -
-
- - - - -
); - } -} - -const mapStateToProps = (state) => ({ - //token: state.auth.token, - //userName: state.auth.userName, - //isAuthenticated: state.auth.isAuthenticated -}); - -export default connect(mapStateToProps)(NewAccountModal); \ No newline at end of file diff --git a/js-frontend/src/views/modals/RemoveAccountModal.js b/js-frontend/src/views/modals/RemoveAccountModal.js new file mode 100644 index 0000000..8316d72 --- /dev/null +++ b/js-frontend/src/views/modals/RemoveAccountModal.js @@ -0,0 +1,68 @@ +/** + * Created by andrew on 20/02/16. + */ +import React, { PropTypes } from "react"; +import * as BS from 'react-bootstrap'; +import { PageHeader, OverlayTrigger, Modal, Tooltip, Grid, Col, Row, Nav, NavItem, ButtonGroup, Button, Table } from "react-bootstrap"; +import { Link, IndexLink} from "react-router"; +import { connect } from "react-redux"; +import Select from "react-select"; + +export class RemoveAccountBookmarkModal extends React.Component { + + static propTypes = { + action: PropTypes.func, + account: PropTypes.object + }; + + handleAction(evt) { + evt.preventDefault(); + const { action } = this.props; + const { account } = this.props; + const { + id, + accountId + } = account || {}; + + if (action) { + action(id || accountId); + } + } + + render() { + const { account } = this.props; + + const { title: titleRaw, + description: descriptionRaw, + balance: balanceRaw, + id, + accountId } = account || {}; + + const entityId = id || accountId; + + const title = titleRaw || '[No title]'; + const balance = ((balanceRaw > 0 && balanceRaw < 1) ? '$0' : '$') + Number(balanceRaw).toFixed(2); + const description = descriptionRaw || '[No description]'; + + return ( + + Remove Account Bookmark + + + +
+ { title } + { balance } + { description } +
+ +
+ + + + +
); + } +} + +export default RemoveAccountBookmarkModal; \ No newline at end of file diff --git a/js-frontend/src/views/modals/index.js b/js-frontend/src/views/modals/index.js index 185d5bf..d848b87 100644 --- a/js-frontend/src/views/modals/index.js +++ b/js-frontend/src/views/modals/index.js @@ -3,4 +3,4 @@ */ export { default as Add3rdPartyAccountModal } from './Add3rdPartyAccountModal'; export { default as NewAccountModal } from './NewAccountModal'; -export { default as RemoveAccountBookmarkModal } from './RemoveAccountBookmarkModal'; +export { default as RemoveAccountBookmarkModal } from './RemoveAccountModal';