mirror of
https://github.com/aclindsa/moneygo.git
synced 2024-10-30 07:40:05 -04:00
Hook (almost) everything up to Redux
This commit is contained in:
parent
071b7ff1e3
commit
6257e9193f
@ -16,13 +16,13 @@ module.exports = React.createClass({
|
||||
handleAccountChange: function(account) {
|
||||
if (this.props.onChange != null &&
|
||||
account.hasOwnProperty('AccountId') &&
|
||||
(this.props.account_map.hasOwnProperty([account.AccountId]) ||
|
||||
(this.props.accounts.hasOwnProperty([account.AccountId]) ||
|
||||
account.AccountId == -1)) {
|
||||
this.props.onChange(account)
|
||||
}
|
||||
},
|
||||
render: function() {
|
||||
var accounts = getAccountDisplayList(this.props.accounts, this.props.includeRoot, this.props.rootName);
|
||||
var accounts = getAccountDisplayList(this.props.accounts, this.props.accountChildren, this.props.includeRoot, this.props.rootName);
|
||||
var className = "";
|
||||
if (this.props.className)
|
||||
className = this.props.className;
|
||||
|
@ -62,7 +62,7 @@ const TransactionRow = React.createClass({
|
||||
var number = ""
|
||||
var accountName = "";
|
||||
var status = "";
|
||||
var security = this.props.security_map[this.props.account.SecurityId];
|
||||
var security = this.props.securities[this.props.account.SecurityId];
|
||||
|
||||
if (this.props.transaction.isTransaction()) {
|
||||
var thisAccountSplit;
|
||||
@ -78,9 +78,9 @@ const TransactionRow = React.createClass({
|
||||
var otherSplit = this.props.transaction.Splits[1];
|
||||
|
||||
if (otherSplit.AccountId == -1)
|
||||
var accountName = "Unbalanced " + this.props.security_map[otherSplit.SecurityId].Symbol + " transaction";
|
||||
var accountName = "Unbalanced " + this.props.securities[otherSplit.SecurityId].Symbol + " transaction";
|
||||
else
|
||||
var accountName = getAccountDisplayName(this.props.account_map[otherSplit.AccountId], this.props.account_map);
|
||||
var accountName = getAccountDisplayName(this.props.accounts[otherSplit.AccountId], this.props.accounts);
|
||||
} else {
|
||||
accountName = "--Split Transaction--";
|
||||
}
|
||||
@ -277,12 +277,12 @@ const AddEditTransactionModal = React.createClass({
|
||||
},
|
||||
handleSubmit: function() {
|
||||
var errorString = ""
|
||||
var imbalancedSecurityList = this.state.transaction.imbalancedSplitSecurities(this.props.account_map);
|
||||
var imbalancedSecurityList = this.state.transaction.imbalancedSplitSecurities(this.props.accounts);
|
||||
if (imbalancedSecurityList.length > 0)
|
||||
errorString = "Transaction must balance"
|
||||
for (var i = 0; i < this.state.transaction.Splits.length; i++) {
|
||||
var s = this.state.transaction.Splits[i];
|
||||
if (!(s.AccountId in this.props.account_map)) {
|
||||
if (!(s.AccountId in this.props.accounts)) {
|
||||
errorString = "All accounts must be valid"
|
||||
}
|
||||
}
|
||||
@ -312,7 +312,7 @@ const AddEditTransactionModal = React.createClass({
|
||||
);
|
||||
}
|
||||
|
||||
var imbalancedSecurityList = this.state.transaction.imbalancedSplitSecurities(this.props.account_map);
|
||||
var imbalancedSecurityList = this.state.transaction.imbalancedSplitSecurities(this.props.accounts);
|
||||
var imbalancedSecurityMap = {};
|
||||
for (i = 0; i < imbalancedSecurityList.length; i++)
|
||||
imbalancedSecurityMap[imbalancedSecurityList[i]] = i;
|
||||
@ -324,11 +324,11 @@ const AddEditTransactionModal = React.createClass({
|
||||
var security = null;
|
||||
var amountValidation = undefined;
|
||||
var accountValidation = "";
|
||||
if (s.AccountId in this.props.account_map) {
|
||||
security = this.props.security_map[this.props.account_map[s.AccountId].SecurityId];
|
||||
if (s.AccountId in this.props.accounts) {
|
||||
security = this.props.securities[this.props.accounts[s.AccountId].SecurityId];
|
||||
} else {
|
||||
if (s.SecurityId in this.props.security_map) {
|
||||
security = this.props.security_map[s.SecurityId];
|
||||
if (s.SecurityId in this.props.securities) {
|
||||
security = this.props.securities[s.SecurityId];
|
||||
}
|
||||
accountValidation = "has-error";
|
||||
}
|
||||
@ -380,7 +380,7 @@ const AddEditTransactionModal = React.createClass({
|
||||
ref={"memo-"+i} /></Col>
|
||||
<Col xs={3}><AccountCombobox
|
||||
accounts={this.props.accounts}
|
||||
account_map={this.props.account_map}
|
||||
accountChildren={this.props.accountChildren}
|
||||
value={s.AccountId}
|
||||
includeRoot={false}
|
||||
onChange={updateAccountFn}
|
||||
@ -569,7 +569,7 @@ const ImportTransactionsModal = React.createClass({
|
||||
render: function() {
|
||||
var accountNameLabel = "Performing global import:"
|
||||
if (this.props.account != null && this.state.importType != ImportType.Gnucash)
|
||||
accountNameLabel = "Importing to '" + getAccountDisplayName(this.props.account, this.props.account_map) + "' account:";
|
||||
accountNameLabel = "Importing to '" + getAccountDisplayName(this.props.account, this.props.accounts) + "' account:";
|
||||
|
||||
// Display the progress bar if an upload/import is in progress
|
||||
var progressBar = [];
|
||||
@ -684,7 +684,7 @@ module.exports = React.createClass({
|
||||
newTransaction.Date = new Date();
|
||||
newTransaction.Splits.push(new Split());
|
||||
newTransaction.Splits.push(new Split());
|
||||
newTransaction.Splits[0].AccountId = this.props.selectedAccount.AccountId;
|
||||
newTransaction.Splits[0].AccountId = this.props.accounts[this.props.selectedAccount].AccountId;
|
||||
|
||||
this.setState({
|
||||
editingTransaction: true,
|
||||
@ -731,7 +731,7 @@ module.exports = React.createClass({
|
||||
// Keep a talley of the running balance of these transactions
|
||||
for (var j = 0; j < data.Transactions[i].Splits.length; j++) {
|
||||
var split = data.Transactions[i].Splits[j];
|
||||
if (this.props.selectedAccount.AccountId == split.AccountId) {
|
||||
if (this.props.accounts[this.props.selectedAccount].AccountId == split.AccountId) {
|
||||
balance = balance.minus(split.Amount);
|
||||
}
|
||||
}
|
||||
@ -758,20 +758,20 @@ module.exports = React.createClass({
|
||||
if (newpage >= this.state.numPages)
|
||||
newpage = this.state.numPages-1;
|
||||
if (newpage != this.state.currentPage) {
|
||||
if (this.props.selectedAccount != null) {
|
||||
this.getTransactionPage(this.props.selectedAccount, newpage);
|
||||
if (this.props.selectedAccount != -1) {
|
||||
this.getTransactionPage(this.props.accounts[this.props.selectedAccount], newpage);
|
||||
}
|
||||
this.setState({currentPage: newpage});
|
||||
}
|
||||
},
|
||||
onNewTransaction: function() {
|
||||
this.getTransactionPage(this.props.selectedAccount, this.state.currentPage);
|
||||
this.getTransactionPage(this.props.accounts[this.props.selectedAccount], this.state.currentPage);
|
||||
},
|
||||
onUpdatedTransaction: function() {
|
||||
this.getTransactionPage(this.props.selectedAccount, this.state.currentPage);
|
||||
this.getTransactionPage(this.props.accounts[this.props.selectedAccount], this.state.currentPage);
|
||||
},
|
||||
onDeletedTransaction: function() {
|
||||
this.getTransactionPage(this.props.selectedAccount, this.state.currentPage);
|
||||
this.getTransactionPage(this.props.accounts[this.props.selectedAccount], this.state.currentPage);
|
||||
},
|
||||
createNewTransaction: function(transaction) {
|
||||
$.ajax({
|
||||
@ -828,7 +828,7 @@ module.exports = React.createClass({
|
||||
},
|
||||
handleImportComplete: function() {
|
||||
this.setState({importingTransactions: false});
|
||||
this.getTransactionPage(this.props.selectedAccount, this.state.currentPage);
|
||||
this.getTransactionPage(this.props.accounts[this.props.selectedAccount], this.state.currentPage);
|
||||
},
|
||||
handleDeleteTransaction: function(transaction) {
|
||||
this.setState({
|
||||
@ -853,16 +853,16 @@ module.exports = React.createClass({
|
||||
transactions: [],
|
||||
currentPage: 0
|
||||
});
|
||||
if (nextProps.selectedAccount != null)
|
||||
this.getTransactionPage(nextProps.selectedAccount, 0);
|
||||
if (nextProps.selectedAccount != -1)
|
||||
this.getTransactionPage(nextProps.accounts[nextProps.selectedAccount], 0);
|
||||
}
|
||||
},
|
||||
render: function() {
|
||||
var name = "Please select an account";
|
||||
register = [];
|
||||
|
||||
if (this.props.selectedAccount != null) {
|
||||
name = this.props.selectedAccount.Name;
|
||||
if (this.props.selectedAccount != -1) {
|
||||
name = this.props.accounts[this.props.selectedAccount].Name;
|
||||
|
||||
var transactionRows = [];
|
||||
for (var i = 0; i < this.state.transactions.length; i++) {
|
||||
@ -871,11 +871,9 @@ module.exports = React.createClass({
|
||||
<TransactionRow
|
||||
key={t.TransactionId}
|
||||
transaction={t}
|
||||
account={this.props.selectedAccount}
|
||||
account={this.props.accounts[this.props.selectedAccount]}
|
||||
accounts={this.props.accounts}
|
||||
account_map={this.props.account_map}
|
||||
securities={this.props.securities}
|
||||
security_map={this.props.security_map}
|
||||
onEdit={this.handleEditTransaction}/>
|
||||
));
|
||||
}
|
||||
@ -901,7 +899,7 @@ module.exports = React.createClass({
|
||||
);
|
||||
}
|
||||
|
||||
var disabled = (this.props.selectedAccount == null) ? true : false;
|
||||
var disabled = (this.props.selectedAccount == -1) ? true : false;
|
||||
|
||||
return (
|
||||
<div className="transactions-container">
|
||||
@ -909,17 +907,15 @@ module.exports = React.createClass({
|
||||
show={this.state.editingTransaction}
|
||||
transaction={this.state.selectedTransaction}
|
||||
accounts={this.props.accounts}
|
||||
account_map={this.props.account_map}
|
||||
accountChildren={this.props.accountChildren}
|
||||
onCancel={this.handleEditingCancel}
|
||||
onSubmit={this.handleUpdateTransaction}
|
||||
onDelete={this.handleDeleteTransaction}
|
||||
securities={this.props.securities}
|
||||
security_map={this.props.security_map}/>
|
||||
securities={this.props.securities} />
|
||||
<ImportTransactionsModal
|
||||
show={this.state.importingTransactions}
|
||||
account={this.props.selectedAccount}
|
||||
account={this.props.accounts[this.props.selectedAccount]}
|
||||
accounts={this.props.accounts}
|
||||
account_map={this.props.account_map}
|
||||
onCancel={this.handleImportingCancel}
|
||||
onSubmit={this.handleImportComplete}/>
|
||||
<div className="transactions-register-toolbar">
|
||||
|
@ -14,7 +14,6 @@ var Col = ReactBootstrap.Col;
|
||||
|
||||
var models = require('./models.js');
|
||||
var User = models.User;
|
||||
var Error = models.Error;
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: "AccountSettingsModal",
|
||||
@ -71,7 +70,6 @@ module.exports = React.createClass({
|
||||
},
|
||||
handleSubmit: function(e) {
|
||||
var u = new User();
|
||||
var error = "";
|
||||
e.preventDefault();
|
||||
|
||||
u.UserId = this.props.user.UserId;
|
||||
@ -88,31 +86,8 @@ module.exports = React.createClass({
|
||||
u.Password = models.BogusPassword;
|
||||
}
|
||||
|
||||
this.handleSaveSettings(u);
|
||||
},
|
||||
handleSaveSettings: function(user) {
|
||||
$.ajax({
|
||||
type: "PUT",
|
||||
dataType: "json",
|
||||
url: "user/"+user.UserId+"/",
|
||||
data: {user: user.toJSON()},
|
||||
success: function(data, status, jqXHR) {
|
||||
var e = new Error();
|
||||
e.fromJSON(data);
|
||||
if (e.isError()) {
|
||||
this.setState({error: e});
|
||||
} else {
|
||||
user.Password = "";
|
||||
this.props.onSubmit(user);
|
||||
}
|
||||
}.bind(this),
|
||||
error: function(jqXHR, status, error) {
|
||||
var e = new Error();
|
||||
e.ErrorId = 5;
|
||||
e.ErrorString = "Request Failed: " + status + error;
|
||||
this.setState({error: e});
|
||||
}.bind(this),
|
||||
});
|
||||
this.props.onUpdateUser(u);
|
||||
this.props.onSubmit();
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
|
@ -119,7 +119,7 @@ const AddEditAccountModal = React.createClass({
|
||||
<Col xs={10}>
|
||||
<AccountCombobox
|
||||
accounts={this.props.accounts}
|
||||
account_map={this.props.account_map}
|
||||
accountChildren={this.props.accountChildren}
|
||||
value={this.state.parentaccountid}
|
||||
rootName={rootName}
|
||||
onChange={this.handleParentChange}
|
||||
@ -130,7 +130,7 @@ const AddEditAccountModal = React.createClass({
|
||||
<Col componentClass={ControlLabel} xs={2}>Security</Col>
|
||||
<Col xs={10}>
|
||||
<Combobox
|
||||
data={this.props.securities}
|
||||
data={this.props.security_list}
|
||||
valueField='SecurityId'
|
||||
textField={item => item.Name + " - " + item.Description}
|
||||
defaultValue={this.state.security}
|
||||
@ -188,10 +188,10 @@ const DeleteAccountModal = React.createClass({
|
||||
this.setState({checked: !this.state.checked});
|
||||
},
|
||||
handleSubmit: function() {
|
||||
if (this.props.account_map.hasOwnProperty(this.state.accountid)) {
|
||||
if (this.props.accounts.hasOwnProperty(this.state.accountid)) {
|
||||
if (this.state.checked) {
|
||||
if (this.props.onSubmit != null)
|
||||
this.props.onSubmit(this.props.account_map[this.state.accountid]);
|
||||
this.props.onSubmit(this.props.accounts[this.state.accountid]);
|
||||
} else {
|
||||
this.setState({error: "You must confirm you wish to delete this account."});
|
||||
}
|
||||
@ -206,11 +206,11 @@ const DeleteAccountModal = React.createClass({
|
||||
},
|
||||
render: function() {
|
||||
var checkbox = [];
|
||||
if (this.props.account_map.hasOwnProperty(this.state.accountid)) {
|
||||
var parentAccountId = this.props.account_map[this.state.accountid].ParentAccountId;
|
||||
if (this.props.accounts.hasOwnProperty(this.state.accountid)) {
|
||||
var parentAccountId = this.props.accounts[this.state.accountid].ParentAccountId;
|
||||
var parentAccount = "will be deleted and any child accounts will become top-level accounts.";
|
||||
if (parentAccountId != -1)
|
||||
parentAccount = "and any child accounts will be re-parented to: " + this.props.account_map[parentAccountId].Name;
|
||||
parentAccount = "and any child accounts will be re-parented to: " + this.props.accounts[parentAccountId].Name;
|
||||
|
||||
var warningString = "I understand that deleting this account cannot be undone and that all transactions " + parentAccount;
|
||||
checkbox = (
|
||||
@ -248,7 +248,7 @@ const DeleteAccountModal = React.createClass({
|
||||
<AccountCombobox
|
||||
includeRoot={false}
|
||||
accounts={this.props.accounts}
|
||||
account_map={this.props.account_map}
|
||||
accountChildren={this.props.accountChildren}
|
||||
value={this.state.accountid}
|
||||
onChange={this.handleChange}/>
|
||||
</Col>
|
||||
@ -285,17 +285,20 @@ const AccountTreeNode = React.createClass({
|
||||
},
|
||||
render: function() {
|
||||
var glyph = this.state.expanded ? 'minus' : 'plus';
|
||||
var active = (this.props.selectedAccount != null &&
|
||||
this.props.account.AccountId == this.props.selectedAccount.AccountId);
|
||||
var active = (this.props.selectedAccount != -1 &&
|
||||
this.props.account.AccountId == this.props.selectedAccount);
|
||||
var buttonStyle = active ? "info" : "link";
|
||||
|
||||
var self = this;
|
||||
var children = this.props.account.Children.map(function(account) {
|
||||
var children = this.props.accountChildren[this.props.account.AccountId].map(function(childId) {
|
||||
var account = self.props.accounts[childId];
|
||||
return (
|
||||
<AccountTreeNode
|
||||
key={account.AccountId}
|
||||
account={account}
|
||||
selectedAccount={self.props.selectedAccount}
|
||||
accounts={self.props.accounts}
|
||||
accountChildren={self.props.accountChildren}
|
||||
onSelect={self.handleChildSelect}/>
|
||||
);
|
||||
});
|
||||
@ -334,11 +337,9 @@ const AccountTreeNode = React.createClass({
|
||||
|
||||
const AccountTree = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {selectedAccount: null,
|
||||
height: 0};
|
||||
return {height: 0};
|
||||
},
|
||||
handleSelect: function(account) {
|
||||
this.setState({selectedAccount: account});
|
||||
if (this.props.onSelect != null) {
|
||||
this.props.onSelect(account);
|
||||
}
|
||||
@ -356,13 +357,17 @@ const AccountTree = React.createClass({
|
||||
var accounts = this.props.accounts;
|
||||
|
||||
var children = [];
|
||||
for (var i = 0; i < accounts.length; i++) {
|
||||
if (accounts[i].isRootAccount())
|
||||
for (var accountId in accounts) {
|
||||
if (accounts.hasOwnProperty(accountId) &&
|
||||
accounts[accountId].isRootAccount()) {
|
||||
children.push((<AccountTreeNode
|
||||
key={accounts[i].AccountId}
|
||||
account={accounts[i]}
|
||||
selectedAccount={this.state.selectedAccount}
|
||||
key={accounts[accountId].AccountId}
|
||||
account={accounts[accountId]}
|
||||
selectedAccount={this.props.selectedAccount}
|
||||
accounts={this.props.accounts}
|
||||
accountChildren={this.props.accountChildren}
|
||||
onSelect={this.handleSelect}/>));
|
||||
}
|
||||
}
|
||||
|
||||
var style = {height: this.state.height + "px"};
|
||||
@ -379,7 +384,6 @@ module.exports = React.createClass({
|
||||
displayName: "AccountsTab",
|
||||
getInitialState: function() {
|
||||
return {
|
||||
selectedAccount: null,
|
||||
creatingNewAccount: false,
|
||||
editingAccount: false,
|
||||
deletingAccount: false
|
||||
@ -416,46 +420,48 @@ module.exports = React.createClass({
|
||||
handleRemoveAccount: function(account) {
|
||||
if (this.props.onDeleteAccount != null)
|
||||
this.props.onDeleteAccount(account);
|
||||
this.setState({deletingAccount: false,
|
||||
selectedAccount: null});
|
||||
this.setState({deletingAccount: false});
|
||||
},
|
||||
handleAccountSelected: function(account) {
|
||||
this.setState({selectedAccount: account});
|
||||
this.props.onSelectAccount(account.AccountId);
|
||||
},
|
||||
render: function() {
|
||||
var accounts = this.props.accounts;
|
||||
var account_map = this.props.account_map;
|
||||
var disabled = (this.props.selectedAccount == -1) ? true : false;
|
||||
|
||||
var disabled = (this.state.selectedAccount == null) ? true : false;
|
||||
var selectedAccount = null;
|
||||
if (this.props.accounts.hasOwnProperty(this.props.selectedAccount))
|
||||
selectedAccount = this.props.accounts[this.props.selectedAccount];
|
||||
|
||||
return (
|
||||
<Grid fluid className="fullheight"><Row className="fullheight">
|
||||
<Col xs={2} className="fullheight account-column">
|
||||
<AddEditAccountModal
|
||||
show={this.state.creatingNewAccount}
|
||||
initialParentAccount={this.state.selectedAccount}
|
||||
initialParentAccount={selectedAccount}
|
||||
accounts={this.props.accounts}
|
||||
account_map={this.props.account_map}
|
||||
accountChildren={this.props.accountChildren}
|
||||
onCancel={this.handleCreationCancel}
|
||||
onSubmit={this.handleCreateAccount}
|
||||
securities={this.props.securities}/>
|
||||
security_list={this.props.security_list}/>
|
||||
<AddEditAccountModal
|
||||
show={this.state.editingAccount}
|
||||
editAccount={this.state.selectedAccount}
|
||||
editAccount={selectedAccount}
|
||||
accounts={this.props.accounts}
|
||||
account_map={this.props.account_map}
|
||||
accountChildren={this.props.accountChildren}
|
||||
onCancel={this.handleEditingCancel}
|
||||
onSubmit={this.handleUpdateAccount}
|
||||
securities={this.props.securities}/>
|
||||
security_list={this.props.security_list}/>
|
||||
<DeleteAccountModal
|
||||
show={this.state.deletingAccount}
|
||||
initialAccount={this.state.selectedAccount}
|
||||
initialAccount={selectedAccount}
|
||||
accounts={this.props.accounts}
|
||||
account_map={this.props.account_map}
|
||||
accountChildren={this.props.accountChildren}
|
||||
onCancel={this.handleDeletionCancel}
|
||||
onSubmit={this.handleRemoveAccount}/>
|
||||
<AccountTree
|
||||
accounts={accounts}
|
||||
accounts={this.props.accounts}
|
||||
accountChildren={this.props.accountChildren}
|
||||
selectedAccount={this.props.selectedAccount}
|
||||
onSelect={this.handleAccountSelected}/>
|
||||
<ButtonGroup className="account-buttongroup">
|
||||
<Button onClick={this.handleNewAccount} bsStyle="success">
|
||||
@ -469,11 +475,10 @@ module.exports = React.createClass({
|
||||
</ButtonGroup>
|
||||
</Col><Col xs={10} className="fullheight transactions-column">
|
||||
<AccountRegister
|
||||
selectedAccount={this.state.selectedAccount}
|
||||
selectedAccount={this.props.selectedAccount}
|
||||
accounts={this.props.accounts}
|
||||
account_map={this.props.account_map}
|
||||
securities={this.props.securities}
|
||||
security_map={this.props.security_map} />
|
||||
accountChildren={this.props.accountChildren}
|
||||
securities={this.props.securities} />
|
||||
</Col>
|
||||
</Row></Grid>
|
||||
);
|
||||
|
258
js/MoneyGoApp.js
258
js/MoneyGoApp.js
@ -6,35 +6,21 @@ var Tabs = ReactBootstrap.Tabs;
|
||||
var Tab = ReactBootstrap.Tab;
|
||||
var Modal = ReactBootstrap.Modal;
|
||||
|
||||
var models = require('./models.js');
|
||||
var User = models.User;
|
||||
var Session = models.Session;
|
||||
var Security = models.Security;
|
||||
var Account = models.Account;
|
||||
var Error = models.Error;
|
||||
|
||||
var TopBar = require('./TopBar.js');
|
||||
var TopBarContainer = require('./containers/TopBarContainer');
|
||||
var NewUserForm = require('./NewUserForm.js');
|
||||
var AccountSettingsModal = require('./AccountSettingsModal.js');
|
||||
var AccountsTab = require('./AccountsTab.js');
|
||||
var AccountSettingsModalContainer = require('./containers/AccountSettingsModalContainer');
|
||||
var AccountsTabContainer = require('./containers/AccountsTabContainer');
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: "MoneyGoApp",
|
||||
getInitialState: function() {
|
||||
return {
|
||||
hash: "home",
|
||||
session: new Session(),
|
||||
user: new User(),
|
||||
accounts: [],
|
||||
account_map: {},
|
||||
securities: [],
|
||||
security_map: {},
|
||||
error: new Error(),
|
||||
showAccountSettingsModal: false
|
||||
};
|
||||
},
|
||||
componentDidMount: function() {
|
||||
this.getSession();
|
||||
this.props.tryResumingSession();
|
||||
this.handleHashChange();
|
||||
if ("onhashchange" in window) {
|
||||
window.onhashchange = this.handleHashChange;
|
||||
@ -52,248 +38,34 @@ module.exports = React.createClass({
|
||||
if (this.state.hash != hash)
|
||||
this.setState({hash: hash});
|
||||
},
|
||||
ajaxError: function(jqXHR, status, error) {
|
||||
var e = new Error();
|
||||
e.ErrorId = 5;
|
||||
e.ErrorString = "Request Failed: " + status + error;
|
||||
this.setState({error: e});
|
||||
},
|
||||
getSession: function() {
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
dataType: "json",
|
||||
url: "session/",
|
||||
success: function(data, status, jqXHR) {
|
||||
var e = new Error();
|
||||
var s = new Session();
|
||||
e.fromJSON(data);
|
||||
if (e.isError()) {
|
||||
if (e.ErrorId != 1 /* Not Signed In*/)
|
||||
this.setState({error: e});
|
||||
} else {
|
||||
s.fromJSON(data);
|
||||
}
|
||||
this.setState({session: s});
|
||||
this.getUser();
|
||||
this.getAccounts();
|
||||
this.getSecurities();
|
||||
}.bind(this),
|
||||
error: this.ajaxError
|
||||
});
|
||||
},
|
||||
getUser: function() {
|
||||
if (!this.state.session.isSession())
|
||||
return;
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
dataType: "json",
|
||||
url: "user/"+this.state.session.UserId+"/",
|
||||
success: function(data, status, jqXHR) {
|
||||
var e = new Error();
|
||||
var u = new User();
|
||||
e.fromJSON(data);
|
||||
if (e.isError()) {
|
||||
this.setState({error: e});
|
||||
} else {
|
||||
u.fromJSON(data);
|
||||
}
|
||||
this.setState({user: u});
|
||||
}.bind(this),
|
||||
error: this.ajaxError
|
||||
});
|
||||
},
|
||||
getSecurities: function() {
|
||||
if (!this.state.session.isSession()) {
|
||||
this.setState({securities: [], security_map: {}});
|
||||
return;
|
||||
}
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
dataType: "json",
|
||||
url: "security/",
|
||||
success: function(data, status, jqXHR) {
|
||||
var e = new Error();
|
||||
var securities = [];
|
||||
var security_map = {};
|
||||
e.fromJSON(data);
|
||||
if (e.isError()) {
|
||||
this.setState({error: e});
|
||||
} else {
|
||||
for (var i = 0; i < data.securities.length; i++) {
|
||||
var s = new Security();
|
||||
s.fromJSON(data.securities[i]);
|
||||
securities.push(s);
|
||||
security_map[s.SecurityId] = s;
|
||||
}
|
||||
}
|
||||
this.setState({securities: securities, security_map: security_map});
|
||||
}.bind(this),
|
||||
error: this.ajaxError
|
||||
});
|
||||
},
|
||||
getAccounts: function() {
|
||||
if (!this.state.session.isSession()) {
|
||||
this.setState({accounts: [], account_map: {}});
|
||||
return;
|
||||
}
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
dataType: "json",
|
||||
url: "account/",
|
||||
success: function(data, status, jqXHR) {
|
||||
var e = new Error();
|
||||
var accounts = [];
|
||||
var account_map = {};
|
||||
e.fromJSON(data);
|
||||
if (e.isError()) {
|
||||
this.setState({error: e});
|
||||
} else {
|
||||
for (var i = 0; i < data.accounts.length; i++) {
|
||||
var a = new Account();
|
||||
a.fromJSON(data.accounts[i]);
|
||||
accounts.push(a);
|
||||
account_map[a.AccountId] = a;
|
||||
}
|
||||
//Populate Children arrays in account objects
|
||||
for (var i = 0; i < accounts.length; i++) {
|
||||
var a = accounts[i];
|
||||
if (!a.isRootAccount())
|
||||
account_map[a.ParentAccountId].Children.push(a);
|
||||
}
|
||||
}
|
||||
this.setState({accounts: accounts, account_map: account_map});
|
||||
}.bind(this),
|
||||
error: this.ajaxError
|
||||
});
|
||||
},
|
||||
handleErrorClear: function() {
|
||||
this.setState({error: new Error()});
|
||||
},
|
||||
handleLoginSubmit: function(user) {
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
dataType: "json",
|
||||
url: "session/",
|
||||
data: {user: user.toJSON()},
|
||||
success: function(data, status, jqXHR) {
|
||||
var e = new Error();
|
||||
e.fromJSON(data);
|
||||
if (e.isError()) {
|
||||
this.setState({error: e});
|
||||
} else {
|
||||
this.getSession();
|
||||
this.setHash("home");
|
||||
}
|
||||
}.bind(this),
|
||||
error: this.ajaxError
|
||||
});
|
||||
},
|
||||
handleLogoutSubmit: function() {
|
||||
this.setState({accounts: [], account_map: {}});
|
||||
$.ajax({
|
||||
type: "DELETE",
|
||||
dataType: "json",
|
||||
url: "session/",
|
||||
success: function(data, status, jqXHR) {
|
||||
var e = new Error();
|
||||
e.fromJSON(data);
|
||||
if (e.isError()) {
|
||||
this.setState({error: e});
|
||||
}
|
||||
this.setState({session: new Session(), user: new User()});
|
||||
}.bind(this),
|
||||
error: this.ajaxError
|
||||
});
|
||||
},
|
||||
handleAccountSettings: function() {
|
||||
this.setState({showAccountSettingsModal: true});
|
||||
},
|
||||
handleSettingsSubmitted: function(user) {
|
||||
this.setState({
|
||||
user: user,
|
||||
showAccountSettingsModal: false
|
||||
});
|
||||
},
|
||||
handleSettingsCanceled: function(user) {
|
||||
handleSettingsCanceled: function() {
|
||||
this.setState({showAccountSettingsModal: false});
|
||||
},
|
||||
handleCreateNewUser: function() {
|
||||
this.setHash("new_user");
|
||||
},
|
||||
handleGoHome: function(user) {
|
||||
handleGoHome: function() {
|
||||
this.setHash("home");
|
||||
},
|
||||
handleCreateAccount: function(account) {
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
dataType: "json",
|
||||
url: "account/",
|
||||
data: {account: account.toJSON()},
|
||||
success: function(data, status, jqXHR) {
|
||||
var e = new Error();
|
||||
e.fromJSON(data);
|
||||
if (e.isError()) {
|
||||
this.setState({error: e});
|
||||
} else {
|
||||
this.getAccounts();
|
||||
}
|
||||
}.bind(this),
|
||||
error: this.ajaxError
|
||||
});
|
||||
},
|
||||
handleUpdateAccount: function(account) {
|
||||
$.ajax({
|
||||
type: "PUT",
|
||||
dataType: "json",
|
||||
url: "account/"+account.AccountId+"/",
|
||||
data: {account: account.toJSON()},
|
||||
success: function(data, status, jqXHR) {
|
||||
var e = new Error();
|
||||
e.fromJSON(data);
|
||||
if (e.isError()) {
|
||||
this.setState({error: e});
|
||||
} else {
|
||||
this.getAccounts();
|
||||
}
|
||||
}.bind(this),
|
||||
error: this.ajaxError
|
||||
});
|
||||
},
|
||||
handleDeleteAccount: function(account) {
|
||||
$.ajax({
|
||||
type: "DELETE",
|
||||
dataType: "json",
|
||||
url: "account/"+account.AccountId+"/",
|
||||
success: function(data, status, jqXHR) {
|
||||
var e = new Error();
|
||||
e.fromJSON(data);
|
||||
if (e.isError()) {
|
||||
this.setState({error: e});
|
||||
} else {
|
||||
this.getAccounts();
|
||||
}
|
||||
}.bind(this),
|
||||
error: this.ajaxError
|
||||
});
|
||||
},
|
||||
render: function() {
|
||||
var mainContent;
|
||||
if (this.state.hash == "new_user") {
|
||||
mainContent = <NewUserForm onNewUser={this.handleGoHome} onCancel={this.handleGoHome}/>
|
||||
} else {
|
||||
if (this.state.user.isUser())
|
||||
if (this.props.user.isUser())
|
||||
mainContent = (
|
||||
<Tabs defaultActiveKey={1} id='mainNavigationTabs'>
|
||||
<Tab title="Accounts" eventKey={1} >
|
||||
<AccountsTab
|
||||
className="fullheight"
|
||||
accounts={this.state.accounts}
|
||||
account_map={this.state.account_map}
|
||||
securities={this.state.securities}
|
||||
security_map={this.state.security_map}
|
||||
onCreateAccount={this.handleCreateAccount}
|
||||
onUpdateAccount={this.handleUpdateAccount}
|
||||
onDeleteAccount={this.handleDeleteAccount} />
|
||||
<AccountsTabContainer
|
||||
className="fullheight" />
|
||||
</Tab>
|
||||
<Tab title="Scheduled Transactions" eventKey={2} >Scheduled transactions go here...</Tab>
|
||||
<Tab title="Budgets" eventKey={3} >Budgets go here...</Tab>
|
||||
@ -311,18 +83,12 @@ module.exports = React.createClass({
|
||||
|
||||
return (
|
||||
<div className="fullheight ui">
|
||||
<TopBar
|
||||
error={this.state.error}
|
||||
onErrorClear={this.handleErrorClear}
|
||||
onLoginSubmit={this.handleLoginSubmit}
|
||||
<TopBarContainer
|
||||
onCreateNewUser={this.handleCreateNewUser}
|
||||
user={this.state.user}
|
||||
onAccountSettings={this.handleAccountSettings}
|
||||
onLogoutSubmit={this.handleLogoutSubmit} />
|
||||
onAccountSettings={this.handleAccountSettings} />
|
||||
{mainContent}
|
||||
<AccountSettingsModal
|
||||
<AccountSettingsModalContainer
|
||||
show={this.state.showAccountSettingsModal}
|
||||
user={this.state.user}
|
||||
onSubmit={this.handleSettingsSubmitted}
|
||||
onCancel={this.handleSettingsCanceled}/>
|
||||
</div>
|
||||
|
12
js/TopBar.js
12
js/TopBar.js
@ -29,7 +29,7 @@ const LoginBar = React.createClass({
|
||||
e.preventDefault();
|
||||
user.Username = ReactDOM.findDOMNode(this.refs.username).value;
|
||||
user.Password = ReactDOM.findDOMNode(this.refs.password).value;
|
||||
this.props.onLoginSubmit(user);
|
||||
this.props.onLogin(user);
|
||||
},
|
||||
handleNewUserSubmit: function(e) {
|
||||
e.preventDefault();
|
||||
@ -72,7 +72,7 @@ const LogoutBar = React.createClass({
|
||||
if (this.props.onAccountSettings != null)
|
||||
this.props.onAccountSettings();
|
||||
} else if (key == 2) {
|
||||
this.props.onLogoutSubmit();
|
||||
this.props.onLogout();
|
||||
}
|
||||
},
|
||||
render: function() {
|
||||
@ -102,15 +102,15 @@ module.exports = React.createClass({
|
||||
var barContents;
|
||||
var errorAlert;
|
||||
if (!this.props.user.isUser())
|
||||
barContents = <LoginBar onLoginSubmit={this.props.onLoginSubmit} onCreateNewUser={this.props.onCreateNewUser} />;
|
||||
barContents = <LoginBar onLogin={this.props.onLogin} onCreateNewUser={this.props.onCreateNewUser} />;
|
||||
else
|
||||
barContents = <LogoutBar user={this.props.user} onLogoutSubmit={this.props.onLogoutSubmit} onAccountSettings={this.props.onAccountSettings}/>;
|
||||
barContents = <LogoutBar user={this.props.user} onLogout={this.props.onLogout} onAccountSettings={this.props.onAccountSettings}/>;
|
||||
if (this.props.error.isError())
|
||||
errorAlert =
|
||||
<Alert bsStyle="danger" onDismiss={this.props.onErrorClear}>
|
||||
<Alert bsStyle="danger" onDismiss={this.props.onClearError}>
|
||||
<h4>Error!</h4>
|
||||
<p>Error {this.props.error.ErrorId}: {this.props.error.ErrorString}</p>
|
||||
<Button onClick={this.props.onErrorClear}>Clear</Button>
|
||||
<Button onClick={this.props.onClearError}>Clear</Button>
|
||||
</Alert>;
|
||||
|
||||
return (
|
||||
|
@ -1,6 +1,6 @@
|
||||
var AccountConstants = require('../constants/AccountConstants');
|
||||
|
||||
var ErrorActions = require('ErrorActions');
|
||||
var ErrorActions = require('./ErrorActions');
|
||||
|
||||
var models = require('../models.js');
|
||||
var Account = models.Account;
|
||||
@ -75,7 +75,6 @@ function fetchAll() {
|
||||
url: "account/",
|
||||
success: function(data, status, jqXHR) {
|
||||
var e = new Error();
|
||||
var accounts = [];
|
||||
e.fromJSON(data);
|
||||
if (e.isError()) {
|
||||
ErrorActions.serverError(e);
|
||||
|
@ -21,7 +21,14 @@ function ajaxError(error) {
|
||||
};
|
||||
}
|
||||
|
||||
function clearError() {
|
||||
return {
|
||||
type: ErrorConstants.CLEAR_ERROR,
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
serverError: serverError,
|
||||
ajaxError: ajaxError
|
||||
ajaxError: ajaxError,
|
||||
clearError: clearError
|
||||
};
|
||||
|
52
js/actions/SecurityActions.js
Normal file
52
js/actions/SecurityActions.js
Normal file
@ -0,0 +1,52 @@
|
||||
var SecurityConstants = require('../constants/SecurityConstants');
|
||||
|
||||
var ErrorActions = require('./ErrorActions');
|
||||
|
||||
var models = require('../models.js');
|
||||
var Security = models.Security;
|
||||
var Error = models.Error;
|
||||
|
||||
function fetchSecurities() {
|
||||
return {
|
||||
type: SecurityConstants.FETCH_SECURITIES
|
||||
}
|
||||
}
|
||||
|
||||
function securitiesFetched(securities) {
|
||||
return {
|
||||
type: SecurityConstants.SECURITIES_FETCHED,
|
||||
securities: securities
|
||||
}
|
||||
}
|
||||
|
||||
function fetchAll() {
|
||||
return function (dispatch) {
|
||||
dispatch(fetchSecurities());
|
||||
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
dataType: "json",
|
||||
url: "security/",
|
||||
success: function(data, status, jqXHR) {
|
||||
var e = new Error();
|
||||
e.fromJSON(data);
|
||||
if (e.isError()) {
|
||||
ErrorActions.serverError(e);
|
||||
} else {
|
||||
dispatch(securitiesFetched(data.securities.map(function(json) {
|
||||
var s = new Security();
|
||||
s.fromJSON(json);
|
||||
return s;
|
||||
})));
|
||||
}
|
||||
},
|
||||
error: function(jqXHR, status, error) {
|
||||
ErrorActions.ajaxError(e);
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
fetchAll: fetchAll
|
||||
};
|
208
js/actions/UserActions.js
Normal file
208
js/actions/UserActions.js
Normal file
@ -0,0 +1,208 @@
|
||||
var UserConstants = require('../constants/UserConstants');
|
||||
|
||||
var AccountActions = require('./AccountActions');
|
||||
var SecurityActions = require('./SecurityActions');
|
||||
var ErrorActions = require('./ErrorActions');
|
||||
|
||||
var models = require('../models.js');
|
||||
var User = models.User;
|
||||
var Session = models.Session;
|
||||
var Error = models.Error;
|
||||
|
||||
function loginUser() {
|
||||
return {
|
||||
type: UserConstants.LOGIN_USER
|
||||
}
|
||||
}
|
||||
|
||||
function userLoggedIn(session) {
|
||||
return {
|
||||
type: UserConstants.USER_LOGGEDIN,
|
||||
session: session
|
||||
}
|
||||
}
|
||||
|
||||
function logoutUser() {
|
||||
return {
|
||||
type: UserConstants.LOGOUT_USER
|
||||
}
|
||||
}
|
||||
|
||||
function userLoggedOut() {
|
||||
return {
|
||||
type: UserConstants.USER_LOGGEDOUT
|
||||
}
|
||||
}
|
||||
|
||||
function fetchUser(userId) {
|
||||
return {
|
||||
type: UserConstants.FETCH_USER,
|
||||
userId: userId
|
||||
}
|
||||
}
|
||||
|
||||
function userFetched(user) {
|
||||
return {
|
||||
type: UserConstants.USER_FETCHED,
|
||||
user: user
|
||||
}
|
||||
}
|
||||
|
||||
function updateUser(user) {
|
||||
return {
|
||||
type: UserConstants.UPDATE_USER,
|
||||
user: user
|
||||
}
|
||||
}
|
||||
|
||||
function userUpdated(user) {
|
||||
return {
|
||||
type: UserConstants.USER_UPDATED,
|
||||
user: user
|
||||
}
|
||||
}
|
||||
|
||||
function fetch(userId) {
|
||||
return function (dispatch) {
|
||||
dispatch(fetchUser());
|
||||
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
dataType: "json",
|
||||
url: "user/"+userId+"/",
|
||||
success: function(data, status, jqXHR) {
|
||||
var e = new Error();
|
||||
e.fromJSON(data);
|
||||
if (e.isError()) {
|
||||
ErrorActions.serverError(e);
|
||||
} else {
|
||||
var u = new User();
|
||||
u.fromJSON(data);
|
||||
dispatch(userFetched(u));
|
||||
}
|
||||
},
|
||||
error: function(jqXHR, status, error) {
|
||||
ErrorActions.ajaxError(e);
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function initializeSession(dispatch, session) {
|
||||
dispatch(userLoggedIn(session));
|
||||
dispatch(fetch(session.UserId));
|
||||
dispatch(AccountActions.fetchAll());
|
||||
dispatch(SecurityActions.fetchAll());
|
||||
}
|
||||
|
||||
function login(user) {
|
||||
return function (dispatch) {
|
||||
dispatch(loginUser());
|
||||
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
dataType: "json",
|
||||
url: "session/",
|
||||
data: {user: user.toJSON()},
|
||||
success: function(data, status, jqXHR) {
|
||||
var e = new Error();
|
||||
e.fromJSON(data);
|
||||
if (e.isError()) {
|
||||
ErrorActions.serverError(e);
|
||||
} else {
|
||||
var s = new Session();
|
||||
s.fromJSON(data);
|
||||
initializeSession(dispatch, s);
|
||||
}
|
||||
},
|
||||
error: function(jqXHR, status, error) {
|
||||
ErrorActions.ajaxError(e);
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function tryResumingSession() {
|
||||
return function (dispatch) {
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
dataType: "json",
|
||||
url: "session/",
|
||||
success: function(data, status, jqXHR) {
|
||||
var e = new Error();
|
||||
e.fromJSON(data);
|
||||
if (e.isError()) {
|
||||
if (e.ErrorId != 1 /* Not Signed In*/)
|
||||
ErrorActions.serverError(e);
|
||||
} else {
|
||||
var s = new Session();
|
||||
s.fromJSON(data);
|
||||
dispatch(loginUser());
|
||||
initializeSession(dispatch, s);
|
||||
}
|
||||
},
|
||||
error: function(jqXHR, status, error) {
|
||||
ErrorActions.ajaxError(e);
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function logout() {
|
||||
return function (dispatch) {
|
||||
dispatch(logoutUser());
|
||||
|
||||
$.ajax({
|
||||
type: "DELETE",
|
||||
dataType: "json",
|
||||
url: "session/",
|
||||
success: function(data, status, jqXHR) {
|
||||
var e = new Error();
|
||||
e.fromJSON(data);
|
||||
if (e.isError()) {
|
||||
ErrorActions.serverError(e);
|
||||
} else {
|
||||
dispatch(userLoggedOut());
|
||||
}
|
||||
},
|
||||
error: function(jqXHR, status, error) {
|
||||
ErrorActions.ajaxError(e);
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function update(user) {
|
||||
return function (dispatch) {
|
||||
dispatch(updateUser());
|
||||
|
||||
$.ajax({
|
||||
type: "PUT",
|
||||
dataType: "json",
|
||||
url: "user/"+user.UserId+"/",
|
||||
data: {user: user.toJSON()},
|
||||
success: function(data, status, jqXHR) {
|
||||
var e = new Error();
|
||||
e.fromJSON(data);
|
||||
if (e.isError()) {
|
||||
ErrorActions.serverError(e);
|
||||
} else {
|
||||
var u = new User();
|
||||
u.fromJSON(data);
|
||||
dispatch(userUpdated(u));
|
||||
}
|
||||
},
|
||||
error: function(jqXHR, status, error) {
|
||||
ErrorActions.ajaxError(e);
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
fetch: fetch,
|
||||
login: login,
|
||||
logout: logout,
|
||||
update: update,
|
||||
tryResumingSession: tryResumingSession
|
||||
};
|
@ -5,4 +5,5 @@ module.exports = keyMirror({
|
||||
ERROR_SERVER: null,
|
||||
ERROR_CLIENT: null,
|
||||
ERROR_USER: null,
|
||||
CLEAR_ERROR: null
|
||||
});
|
||||
|
12
js/constants/SecurityConstants.js
Normal file
12
js/constants/SecurityConstants.js
Normal file
@ -0,0 +1,12 @@
|
||||
var keyMirror = require('keymirror');
|
||||
|
||||
module.exports = keyMirror({
|
||||
FETCH_SECURITIES: null,
|
||||
SECURITIES_FETCHED: null,
|
||||
CREATE_SECURITY: null,
|
||||
SECURITY_CREATED: null,
|
||||
UPDATE_SECURITY: null,
|
||||
SECURITY_UPDATED: null,
|
||||
REMOVE_SECURITY: null,
|
||||
SECURITY_REMOVED: null
|
||||
});
|
12
js/constants/UserConstants.js
Normal file
12
js/constants/UserConstants.js
Normal file
@ -0,0 +1,12 @@
|
||||
var keyMirror = require('keymirror');
|
||||
|
||||
module.exports = keyMirror({
|
||||
LOGIN_USER: null,
|
||||
USER_LOGGEDIN: null,
|
||||
LOGOUT_USER: null,
|
||||
USER_LOGGEDOUT: null,
|
||||
FETCH_USER: null,
|
||||
USER_FETCHED: null,
|
||||
UPDATE_USER: null,
|
||||
USER_UPDATED: null
|
||||
});
|
21
js/containers/AccountSettingsModalContainer.js
Normal file
21
js/containers/AccountSettingsModalContainer.js
Normal file
@ -0,0 +1,21 @@
|
||||
var connect = require('react-redux').connect;
|
||||
|
||||
var UserActions = require('../actions/UserActions');
|
||||
var AccountSettingsModal = require('../AccountSettingsModal');
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
user: state.user
|
||||
}
|
||||
}
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
onUpdateUser: function(user) {dispatch(UserActions.update(user))}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(AccountSettingsModal)
|
33
js/containers/AccountsTabContainer.js
Normal file
33
js/containers/AccountsTabContainer.js
Normal file
@ -0,0 +1,33 @@
|
||||
var connect = require('react-redux').connect;
|
||||
|
||||
var AccountActions = require('../actions/AccountActions');
|
||||
var AccountsTab = require('../AccountsTab');
|
||||
|
||||
function mapStateToProps(state) {
|
||||
var security_list = [];
|
||||
for (var securityId in state.securities) {
|
||||
if (state.securities.hasOwnProperty(securityId))
|
||||
security_list.push(state.securities[securityId]);
|
||||
}
|
||||
return {
|
||||
accounts: state.accounts.map,
|
||||
accountChildren: state.accounts.children,
|
||||
securities: state.securities,
|
||||
security_list: security_list,
|
||||
selectedAccount: state.selectedAccount
|
||||
}
|
||||
}
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
onCreateAccount: function(account) {dispatch(AccountActions.create(account))},
|
||||
onUpdateAccount: function(account) {dispatch(AccountActions.update(account))},
|
||||
onDeleteAccount: function(accountId) {dispatch(AccountActions.remove(accountId))},
|
||||
onSelectAccount: function(accountId) {dispatch(AccountActions.select(accountId))}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(AccountsTab)
|
22
js/containers/MoneyGoAppContainer.js
Normal file
22
js/containers/MoneyGoAppContainer.js
Normal file
@ -0,0 +1,22 @@
|
||||
var connect = require('react-redux').connect;
|
||||
|
||||
var UserActions = require('../actions/UserActions');
|
||||
|
||||
var MoneyGoApp = require('../MoneyGoApp');
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
user: state.user
|
||||
}
|
||||
}
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
tryResumingSession: function() {dispatch(UserActions.tryResumingSession())},
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(MoneyGoApp)
|
27
js/containers/TopBarContainer.js
Normal file
27
js/containers/TopBarContainer.js
Normal file
@ -0,0 +1,27 @@
|
||||
var connect = require('react-redux').connect;
|
||||
|
||||
var UserActions = require('../actions/UserActions');
|
||||
var ErrorActions = require('../actions/ErrorActions');
|
||||
|
||||
var TopBar = require('../TopBar');
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
user: state.user,
|
||||
error: state.error
|
||||
}
|
||||
}
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
onLogin: function(user) {dispatch(UserActions.login(user))},
|
||||
onLogout: function() {dispatch(UserActions.logout())},
|
||||
onUpdateUser: function(user) {dispatch(UserActions.update(user))},
|
||||
onClearError: function() {dispatch(ErrorActions.clearError())}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(TopBar)
|
@ -8,7 +8,7 @@ var ReduxThunk = require('redux-thunk').default;
|
||||
var Globalize = require('globalize');
|
||||
var globalizeLocalizer = require('react-widgets/lib/localizers/globalize');
|
||||
|
||||
var MoneyGoApp = require('./MoneyGoApp.js');
|
||||
var MoneyGoAppContainer = require('./containers/MoneyGoAppContainer');
|
||||
var MoneyGoReducer = require('./reducers/MoneyGoReducer');
|
||||
|
||||
// Setup globalization for react-widgets
|
||||
@ -33,7 +33,7 @@ $(document).ready(function() {
|
||||
|
||||
ReactDOM.render(
|
||||
<Provider store={store}>
|
||||
<MoneyGoApp />
|
||||
<MoneyGoAppContainer />
|
||||
</Provider>,
|
||||
document.getElementById("content")
|
||||
);
|
||||
|
@ -157,7 +157,6 @@ function Account() {
|
||||
this.ParentAccountId = -1;
|
||||
this.Type = -1;
|
||||
this.Name = "";
|
||||
this.Children = []; // Not sent across JSON, just used internally
|
||||
}
|
||||
|
||||
Account.prototype.toJSON = function() {
|
||||
|
@ -1,8 +1,26 @@
|
||||
var assign = require('object-assign');
|
||||
|
||||
var AccountConstants = require('../constants/AccountConstants');
|
||||
var UserConstants = require('../constants/UserConstants');
|
||||
|
||||
module.exports = function(state = {}, action) {
|
||||
function accountChildren(accounts) {
|
||||
var children = {};
|
||||
for (var accountId in accounts) {
|
||||
if (accounts.hasOwnProperty(accountId)) {
|
||||
var parentAccountId = accounts[accountId].ParentAccountId;
|
||||
if (!children.hasOwnProperty(parentAccountId))
|
||||
children[parentAccountId] = [];
|
||||
if (!children.hasOwnProperty(accountId))
|
||||
children[accountId] = [];
|
||||
children[parentAccountId].push(accountId);
|
||||
}
|
||||
}
|
||||
return children;
|
||||
}
|
||||
|
||||
const initialState = {map: {}, children: {}};
|
||||
|
||||
module.exports = function(state = initialState, action) {
|
||||
switch (action.type) {
|
||||
case AccountConstants.ACCOUNTS_FETCHED:
|
||||
var accounts = {};
|
||||
@ -10,17 +28,29 @@ module.exports = function(state = {}, action) {
|
||||
var account = action.accounts[i];
|
||||
accounts[account.AccountId] = account;
|
||||
}
|
||||
return accounts;
|
||||
return {
|
||||
map: accounts,
|
||||
children: accountChildren(accounts)
|
||||
};
|
||||
case AccountConstants.ACCOUNT_CREATED:
|
||||
case AccountConstants.ACCOUNT_UPDATED:
|
||||
var account = action.account;
|
||||
return assign({}, state, {
|
||||
var accounts = assign({}, state.map, {
|
||||
[account.AccountId]: account
|
||||
});
|
||||
return {
|
||||
map: accounts,
|
||||
children: accountChildren(accounts)
|
||||
};
|
||||
case AccountConstants.ACCOUNT_REMOVED:
|
||||
var newstate = assign({}, state);
|
||||
delete newstate[action.accountId];
|
||||
return newstate;
|
||||
var accounts = assign({}, state.map);
|
||||
delete accounts[action.accountId];
|
||||
return {
|
||||
map: accounts,
|
||||
children: accountChildren(accounts)
|
||||
};
|
||||
case UserConstants.USER_LOGGEDOUT:
|
||||
return initialState;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
17
js/reducers/ErrorReducer.js
Normal file
17
js/reducers/ErrorReducer.js
Normal file
@ -0,0 +1,17 @@
|
||||
var ErrorConstants = require('../constants/ErrorConstants');
|
||||
|
||||
var Error = require('../models').Error;
|
||||
|
||||
module.exports = function(state = new Error(), action) {
|
||||
switch (action.type) {
|
||||
case ErrorConstants.ERROR_AJAX:
|
||||
case ErrorConstants.ERROR_SERVER:
|
||||
case ErrorConstants.ERROR_CLIENT:
|
||||
case ErrorConstants.ERROR_USER:
|
||||
return action.error;
|
||||
case ErrorConstants.CLEAR_ERROR:
|
||||
return new Error();
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
@ -1,9 +1,17 @@
|
||||
var Redux = require('redux');
|
||||
|
||||
var UserReducer = require('./UserReducer');
|
||||
var SessionReducer = require('./SessionReducer');
|
||||
var AccountReducer = require('./AccountReducer');
|
||||
var SecurityReducer = require('./SecurityReducer');
|
||||
var SelectedAccountReducer = require('./SelectedAccountReducer');
|
||||
var ErrorReducer = require('./ErrorReducer');
|
||||
|
||||
module.exports = Redux.combineReducers({
|
||||
user: UserReducer,
|
||||
session: SessionReducer,
|
||||
accounts: AccountReducer,
|
||||
selectedAccount: SelectedAccountReducer
|
||||
securities: SecurityReducer,
|
||||
selectedAccount: SelectedAccountReducer,
|
||||
error: ErrorReducer
|
||||
});
|
||||
|
30
js/reducers/SecurityReducer.js
Normal file
30
js/reducers/SecurityReducer.js
Normal file
@ -0,0 +1,30 @@
|
||||
var assign = require('object-assign');
|
||||
|
||||
var SecurityConstants = require('../constants/SecurityConstants');
|
||||
var UserConstants = require('../constants/UserConstants');
|
||||
|
||||
module.exports = function(state = {}, action) {
|
||||
switch (action.type) {
|
||||
case SecurityConstants.SECURITIES_FETCHED:
|
||||
var securities = {};
|
||||
for (var i = 0; i < action.securities.length; i++) {
|
||||
var security = action.securities[i];
|
||||
securities[security.SecurityId] = security;
|
||||
}
|
||||
return securities;
|
||||
case SecurityConstants.SECURITY_CREATED:
|
||||
case SecurityConstants.SECURITY_UPDATED:
|
||||
var security = action.security;
|
||||
return assign({}, state, {
|
||||
[security.SecurityId]: security
|
||||
});
|
||||
case SecurityConstants.SECURITY_REMOVED:
|
||||
var newstate = assign({}, state);
|
||||
delete newstate[action.securityId];
|
||||
return newstate;
|
||||
case UserConstants.USER_LOGGEDOUT:
|
||||
return {};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
@ -1,4 +1,5 @@
|
||||
var AccountConstants = require('../constants/AccountConstants');
|
||||
var UserConstants = require('../constants/UserConstants');
|
||||
|
||||
module.exports = function(state = -1, action) {
|
||||
switch (action.type) {
|
||||
@ -14,6 +15,8 @@ module.exports = function(state = -1, action) {
|
||||
return state;
|
||||
case AccountConstants.ACCOUNT_SELECTED:
|
||||
return action.accountId;
|
||||
case UserConstants.USER_LOGGEDOUT:
|
||||
return -1;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
14
js/reducers/SessionReducer.js
Normal file
14
js/reducers/SessionReducer.js
Normal file
@ -0,0 +1,14 @@
|
||||
var UserConstants = require('../constants/UserConstants');
|
||||
|
||||
var Session = require('../models').Session;
|
||||
|
||||
module.exports = function(state = new Session(), action) {
|
||||
switch (action.type) {
|
||||
case UserConstants.USER_LOGGEDIN:
|
||||
return action.session;
|
||||
case UserConstants.USER_LOGGEDOUT:
|
||||
return new Session();
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
15
js/reducers/UserReducer.js
Normal file
15
js/reducers/UserReducer.js
Normal file
@ -0,0 +1,15 @@
|
||||
var UserConstants = require('../constants/UserConstants');
|
||||
|
||||
var User = require('../models').User;
|
||||
|
||||
module.exports = function(state = new User(), action) {
|
||||
switch (action.type) {
|
||||
case UserConstants.USER_FETCHED:
|
||||
case UserConstants.USER_UPDATED:
|
||||
return action.user;
|
||||
case UserConstants.USER_LOGGEDOUT:
|
||||
return new User();
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
15
js/utils.js
15
js/utils.js
@ -1,18 +1,19 @@
|
||||
const recursiveAccountDisplayInfo = function(account, prefix) {
|
||||
const recursiveAccountDisplayInfo = function(account, account_map, accountChildren, prefix) {
|
||||
var name = prefix + account.Name;
|
||||
var accounts = [{AccountId: account.AccountId, Name: name}];
|
||||
for (var i = 0; i < account.Children.length; i++)
|
||||
accounts = accounts.concat(recursiveAccountDisplayInfo(account.Children[i], name + "/"));
|
||||
for (var i = 0; i < accountChildren[account.AccountId].length; i++)
|
||||
accounts = accounts.concat(recursiveAccountDisplayInfo(account_map[accountChildren[account.AccountId][i]], account_map, accountChildren, name + "/"));
|
||||
return accounts
|
||||
};
|
||||
|
||||
const getAccountDisplayList = function(account_list, includeRoot, rootName) {
|
||||
const getAccountDisplayList = function(account_map, accountChildren, includeRoot, rootName) {
|
||||
var accounts = []
|
||||
if (includeRoot)
|
||||
accounts.push({AccountId: -1, Name: rootName});
|
||||
for (var i = 0; i < account_list.length; i++) {
|
||||
if (account_list[i].isRootAccount())
|
||||
accounts = accounts.concat(recursiveAccountDisplayInfo(account_list[i], ""));
|
||||
for (var accountId in account_map) {
|
||||
if (account_map.hasOwnProperty(accountId) &&
|
||||
account_map[accountId].isRootAccount())
|
||||
accounts = accounts.concat(recursiveAccountDisplayInfo(account_map[accountId], account_map, accountChildren, ""));
|
||||
}
|
||||
return accounts;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user