mirror of
https://github.com/aclindsa/moneygo.git
synced 2024-12-26 23:42:29 -05:00
Add ability to create new accounts to UI
This also incorporates a bunch of other changes needed to support adding this.
This commit is contained in:
parent
7772f0bca5
commit
7ea9fb3b73
@ -2,25 +2,227 @@
|
|||||||
var ListGroup = ReactBootstrap.ListGroup;
|
var ListGroup = ReactBootstrap.ListGroup;
|
||||||
var ListGroupItem = ReactBootstrap.ListGroupItem;
|
var ListGroupItem = ReactBootstrap.ListGroupItem;
|
||||||
|
|
||||||
var AccountList = React.createClass({
|
var Grid = ReactBootstrap.Grid;
|
||||||
|
var Row = ReactBootstrap.Row;
|
||||||
|
var Col = ReactBootstrap.Col;
|
||||||
|
|
||||||
|
var Button = ReactBootstrap.Button;
|
||||||
|
var ButtonGroup = ReactBootstrap.ButtonGroup;
|
||||||
|
var Glyphicon = ReactBootstrap.Glyphicon;
|
||||||
|
|
||||||
|
var Modal = ReactBootstrap.Modal;
|
||||||
|
|
||||||
|
var Combobox = ReactWidgets.Combobox;
|
||||||
|
|
||||||
|
const recursiveAccountDisplayInfo = function(account, 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 + "/"));
|
||||||
|
return accounts
|
||||||
|
};
|
||||||
|
const getAccountDisplayList = function(account_list, 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].ParentAccountId == -1)
|
||||||
|
accounts = accounts.concat(recursiveAccountDisplayInfo(account_list[i], ""));
|
||||||
|
}
|
||||||
|
return accounts;
|
||||||
|
};
|
||||||
|
|
||||||
|
const AccountCombobox = React.createClass({
|
||||||
|
handleAccountChange: function(account) {
|
||||||
|
if (this.props.onSelect != null &&
|
||||||
|
account.hasOwnProperty('AccountId') &&
|
||||||
|
this.props.account_map.hasOwnProperty([account.AccountId])) {
|
||||||
|
this.props.onSelect(this.props.account_map[account.AccountId])
|
||||||
|
}
|
||||||
|
},
|
||||||
|
render: function() {
|
||||||
|
var accounts = getAccountDisplayList(this.props.accounts, true, "New Root Account");
|
||||||
|
return (
|
||||||
|
<Combobox
|
||||||
|
data={accounts}
|
||||||
|
valueField='AccountId'
|
||||||
|
textField='Name'
|
||||||
|
value={this.props.value}
|
||||||
|
onSelect={this.handleAccountChange}
|
||||||
|
ref="account" />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const NewAccountModal = React.createClass({
|
||||||
getInitialState: function() {
|
getInitialState: function() {
|
||||||
return {
|
return {
|
||||||
|
security: 1,
|
||||||
|
parentaccountid: -1,
|
||||||
|
type: 1,
|
||||||
|
name: ""
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
handleCancel: function() {
|
||||||
|
if (this.props.onCancel != null)
|
||||||
|
this.props.onCancel();
|
||||||
|
},
|
||||||
|
handleChange: function() {
|
||||||
|
this.setState({
|
||||||
|
name: this.refs.name.getValue(),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
handleSecurityChange: function(security) {
|
||||||
|
if (security.hasOwnProperty('SecurityId'))
|
||||||
|
this.setState({
|
||||||
|
security: security.SecurityId
|
||||||
|
});
|
||||||
|
},
|
||||||
|
handleTypeChange: function(type) {
|
||||||
|
if (type.hasOwnProperty('TypeId'))
|
||||||
|
this.setState({
|
||||||
|
type: type.TypeId
|
||||||
|
});
|
||||||
|
},
|
||||||
|
handleParentChange: function(parentAccount) {
|
||||||
|
this.setState({parentaccountid: parentAccount.AccountId});
|
||||||
|
},
|
||||||
|
handleSubmit: function() {
|
||||||
|
var a = new Account();
|
||||||
|
|
||||||
|
a.Name = this.state.name;
|
||||||
|
a.ParentAccountId = this.state.parentaccountid;
|
||||||
|
a.SecurityId = this.state.security;
|
||||||
|
a.Type = this.state.type;
|
||||||
|
|
||||||
|
this.handleSaveSettings(a);
|
||||||
|
},
|
||||||
|
handleSaveSettings: function(account) {
|
||||||
|
if (this.props.onSubmit != null)
|
||||||
|
this.props.onSubmit(account);
|
||||||
|
},
|
||||||
|
render: function() {
|
||||||
|
return (
|
||||||
|
<Modal show={this.props.show} onHide={this.handleCancel}>
|
||||||
|
<Modal.Header closeButton>
|
||||||
|
<Modal.Title>Create New Account</Modal.Title>
|
||||||
|
</Modal.Header>
|
||||||
|
<Modal.Body>
|
||||||
|
<form onSubmit={this.handleSubmit}
|
||||||
|
className="form-horizontal">
|
||||||
|
<Input type="text"
|
||||||
|
label="Name"
|
||||||
|
value={this.state.name}
|
||||||
|
onChange={this.handleChange}
|
||||||
|
ref="name"
|
||||||
|
labelClassName="col-xs-2"
|
||||||
|
wrapperClassName="col-xs-10"/>
|
||||||
|
<Input wrapperClassName="wrapper"
|
||||||
|
label="Parent Account"
|
||||||
|
labelClassName="col-xs-2"
|
||||||
|
wrapperClassName="col-xs-10">
|
||||||
|
<AccountCombobox
|
||||||
|
accounts={this.props.accounts}
|
||||||
|
account_map={this.props.account_map}
|
||||||
|
value={this.state.parentaccountid}
|
||||||
|
onSelect={this.handleParentChange}
|
||||||
|
ref="parent" />
|
||||||
|
</Input>
|
||||||
|
<Input wrapperClassName="wrapper"
|
||||||
|
label="Security"
|
||||||
|
labelClassName="col-xs-2"
|
||||||
|
wrapperClassName="col-xs-10">
|
||||||
|
<Combobox
|
||||||
|
data={this.props.securities}
|
||||||
|
valueField='SecurityId'
|
||||||
|
textField='Name'
|
||||||
|
value={this.state.security}
|
||||||
|
onSelect={this.handleSecurityChange}
|
||||||
|
ref="security" />
|
||||||
|
</Input>
|
||||||
|
<Input wrapperClassName="wrapper"
|
||||||
|
label="Account Type"
|
||||||
|
labelClassName="col-xs-2"
|
||||||
|
wrapperClassName="col-xs-10">
|
||||||
|
<Combobox
|
||||||
|
data={AccountTypeList}
|
||||||
|
valueField='TypeId'
|
||||||
|
textField='Name'
|
||||||
|
value={this.state.type}
|
||||||
|
onSelect={this.handleTypeChange}
|
||||||
|
ref="type" />
|
||||||
|
</Input>
|
||||||
|
</form>
|
||||||
|
</Modal.Body>
|
||||||
|
<Modal.Footer>
|
||||||
|
<ButtonGroup className="pull-right">
|
||||||
|
<Button onClick={this.handleCancel} bsStyle="warning">Cancel</Button>
|
||||||
|
<Button onClick={this.handleSubmit} bsStyle="success">Create Account</Button>
|
||||||
|
</ButtonGroup>
|
||||||
|
</Modal.Footer>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const AccountsTab = React.createClass({
|
||||||
|
getInitialState: function() {
|
||||||
|
return {
|
||||||
|
creatingNewAccount: false
|
||||||
|
};
|
||||||
|
},
|
||||||
|
handleNewAccount: function() {
|
||||||
|
this.setState({creatingNewAccount: true});
|
||||||
|
},
|
||||||
|
handleEditAccount: function() {
|
||||||
|
console.log("handleEditAccount");
|
||||||
|
},
|
||||||
|
handleDeleteAccount: function() {
|
||||||
|
console.log("handleDeleteAccount");
|
||||||
|
},
|
||||||
|
handleCreationCancel: function() {
|
||||||
|
this.setState({creatingNewAccount: false});
|
||||||
|
},
|
||||||
|
handleCreateAccount: function(account) {
|
||||||
|
if (this.props.onCreateAccount != null)
|
||||||
|
this.props.onCreateAccount(account);
|
||||||
|
this.setState({creatingNewAccount: false});
|
||||||
|
},
|
||||||
render: function() {
|
render: function() {
|
||||||
var accounts = this.props.accounts;
|
var accounts = this.props.accounts;
|
||||||
var account_map = this.props.account_map;
|
var account_map = this.props.account_map;
|
||||||
|
|
||||||
var listGroupItems;
|
var listGroupItems = accounts.map(function(account) {
|
||||||
|
return (
|
||||||
for (var i = 0; i < accounts.length; i++) {
|
<ListGroupItem>{account.Name}</ListGroupItem>
|
||||||
listGroupItems += <ListGroupItem>{accounts[i].Name}</ListGroupItem>;
|
);
|
||||||
}
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<Grid fluid><Row>
|
||||||
|
<Col xs={2}>
|
||||||
|
<NewAccountModal
|
||||||
|
show={this.state.creatingNewAccount}
|
||||||
|
accounts={this.props.accounts}
|
||||||
|
account_map={this.props.account_map}
|
||||||
|
onCancel={this.handleCreationCancel}
|
||||||
|
onSubmit={this.handleCreateAccount}
|
||||||
|
securities={this.props.securities}/>
|
||||||
<ListGroup>
|
<ListGroup>
|
||||||
{listGroupItems}
|
{listGroupItems}
|
||||||
</ListGroup>
|
</ListGroup>
|
||||||
|
<ButtonGroup className="pull-right">
|
||||||
|
<Button onClick={this.handleNewAccount} bsStyle="success">
|
||||||
|
<Glyphicon glyph='plus-sign' /></Button>
|
||||||
|
<Button onClick={this.handleEditAccount} bsStyle="primary">
|
||||||
|
<Glyphicon glyph='cog' /></Button>
|
||||||
|
<Button onClick={this.handleDeleteAccount} bsStyle="danger">
|
||||||
|
<Glyphicon glyph='trash' /></Button>
|
||||||
|
</ButtonGroup>
|
||||||
|
</Col><Col xs={10}>
|
||||||
|
blah
|
||||||
|
</Col>
|
||||||
|
</Row></Grid>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -16,7 +16,7 @@ function User() {
|
|||||||
this.Email = "";
|
this.Email = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
var BogusPassword = "password";
|
const BogusPassword = "password";
|
||||||
|
|
||||||
User.prototype.toJSON = function() {
|
User.prototype.toJSON = function() {
|
||||||
var json_obj = {};
|
var json_obj = {};
|
||||||
@ -76,7 +76,55 @@ Session.prototype.isSession = function() {
|
|||||||
this.UserId != empty_session.UserId;
|
this.UserId != empty_session.UserId;
|
||||||
}
|
}
|
||||||
|
|
||||||
var AccountType = {
|
const SecurityType = {
|
||||||
|
Banknote: 1,
|
||||||
|
Bond: 2,
|
||||||
|
Stock: 3,
|
||||||
|
MutualFund: 4
|
||||||
|
}
|
||||||
|
var SecurityTypeList = [];
|
||||||
|
for (var type in SecurityType) {
|
||||||
|
if (SecurityType.hasOwnProperty(type)) {
|
||||||
|
SecurityTypeList.push({'TypeId': SecurityType[type], 'Name': type});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Security() {
|
||||||
|
this.SecurityId = -1;
|
||||||
|
this.Name = "";
|
||||||
|
this.Precision = -1;
|
||||||
|
this.Type = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Security.prototype.toJSON = function() {
|
||||||
|
var json_obj = {};
|
||||||
|
json_obj.SecurityId = this.SecurityId;
|
||||||
|
json_obj.Name = this.Name;
|
||||||
|
json_obj.Precision = this.Precision;
|
||||||
|
json_obj.Type = this.Type;
|
||||||
|
return JSON.stringify(json_obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
Security.prototype.fromJSON = function(json_input) {
|
||||||
|
var json_obj = getJSONObj(json_input);
|
||||||
|
|
||||||
|
if (json_obj.hasOwnProperty("SecurityId"))
|
||||||
|
this.SecurityId = json_obj.SecurityId;
|
||||||
|
if (json_obj.hasOwnProperty("Name"))
|
||||||
|
this.Name = json_obj.Name;
|
||||||
|
if (json_obj.hasOwnProperty("Precision"))
|
||||||
|
this.Precision = json_obj.Precision;
|
||||||
|
if (json_obj.hasOwnProperty("Type"))
|
||||||
|
this.Type = json_obj.Type;
|
||||||
|
}
|
||||||
|
|
||||||
|
Security.prototype.isSecurity = function() {
|
||||||
|
var empty_account = new Security();
|
||||||
|
return this.SecurityId != empty_account.SecurityId ||
|
||||||
|
this.Type != empty_account.Type;
|
||||||
|
}
|
||||||
|
|
||||||
|
const AccountType = {
|
||||||
Bank: 1,
|
Bank: 1,
|
||||||
Cash: 2,
|
Cash: 2,
|
||||||
Asset: 3,
|
Asset: 3,
|
||||||
@ -85,6 +133,12 @@ var AccountType = {
|
|||||||
Income: 6,
|
Income: 6,
|
||||||
Expense: 7
|
Expense: 7
|
||||||
}
|
}
|
||||||
|
var AccountTypeList = [];
|
||||||
|
for (var type in AccountType) {
|
||||||
|
if (AccountType.hasOwnProperty(type)) {
|
||||||
|
AccountTypeList.push({'TypeId': AccountType[type], 'Name': type});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function Account() {
|
function Account() {
|
||||||
this.AccountId = -1;
|
this.AccountId = -1;
|
||||||
@ -183,7 +237,7 @@ Split.prototype.isSplit = function() {
|
|||||||
this.AccountId != empty_split.AccountId;
|
this.AccountId != empty_split.AccountId;
|
||||||
}
|
}
|
||||||
|
|
||||||
var TransactionStatus = {
|
const TransactionStatus = {
|
||||||
Entered: 1,
|
Entered: 1,
|
||||||
Cleared: 2,
|
Cleared: 2,
|
||||||
Reconciled: 3,
|
Reconciled: 3,
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
div#content {
|
div#content {
|
||||||
width: 95%;
|
width: 95%;
|
||||||
|
height: 100%;
|
||||||
min-width: 75em;
|
min-width: 75em;
|
||||||
max-width: 100em;
|
max-width: 100em;
|
||||||
display: block;
|
display: block;
|
||||||
|
48
static/ui.js
48
static/ui.js
@ -1,5 +1,7 @@
|
|||||||
// Import all the objects we want to use from ReactBootstrap
|
// Import all the objects we want to use from ReactBootstrap
|
||||||
var Jumbotron = ReactBootstrap.Jumbotron;
|
var Jumbotron = ReactBootstrap.Jumbotron;
|
||||||
|
var TabbedArea = ReactBootstrap.TabbedArea;
|
||||||
|
var TabPane = ReactBootstrap.TabPane;
|
||||||
var Panel = ReactBootstrap.Panel;
|
var Panel = ReactBootstrap.Panel;
|
||||||
var ButtonGroup = ReactBootstrap.ButtonGroup;
|
var ButtonGroup = ReactBootstrap.ButtonGroup;
|
||||||
|
|
||||||
@ -299,6 +301,8 @@ var MoneyGoApp = React.createClass({
|
|||||||
user: new User(),
|
user: new User(),
|
||||||
accounts: [],
|
accounts: [],
|
||||||
account_map: {},
|
account_map: {},
|
||||||
|
securities: [],
|
||||||
|
security_map: {},
|
||||||
error: new Error()
|
error: new Error()
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@ -345,6 +349,7 @@ var MoneyGoApp = React.createClass({
|
|||||||
this.setState({session: s});
|
this.setState({session: s});
|
||||||
this.getUser();
|
this.getUser();
|
||||||
this.getAccounts();
|
this.getAccounts();
|
||||||
|
this.getSecurities();
|
||||||
}.bind(this),
|
}.bind(this),
|
||||||
error: this.ajaxError
|
error: this.ajaxError
|
||||||
});
|
});
|
||||||
@ -370,6 +375,35 @@ var MoneyGoApp = React.createClass({
|
|||||||
error: this.ajaxError
|
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() {
|
getAccounts: function() {
|
||||||
if (!this.state.session.isSession()) {
|
if (!this.state.session.isSession()) {
|
||||||
this.setState({accounts: [], account_map: {}});
|
this.setState({accounts: [], account_map: {}});
|
||||||
@ -518,17 +552,29 @@ var MoneyGoApp = React.createClass({
|
|||||||
mainContent = <AccountSettings user={this.state.user} onSettingsSubmitted={this.handleSettingsSubmitted} onCancel={this.handleGoHome}/>
|
mainContent = <AccountSettings user={this.state.user} onSettingsSubmitted={this.handleSettingsSubmitted} onCancel={this.handleGoHome}/>
|
||||||
} else {
|
} else {
|
||||||
if (this.state.user.isUser())
|
if (this.state.user.isUser())
|
||||||
mainContent = <AccountList
|
mainContent =
|
||||||
|
<TabbedArea defaultActiveKey='1'>
|
||||||
|
<TabPane tab="Accounts" eventKey='1'>
|
||||||
|
<AccountsTab
|
||||||
accounts={this.state.accounts}
|
accounts={this.state.accounts}
|
||||||
account_map={this.state.account_map}
|
account_map={this.state.account_map}
|
||||||
|
securities={this.state.securities}
|
||||||
|
security_map={this.state.security_map}
|
||||||
onCreateAccount={this.handleCreateAccount}
|
onCreateAccount={this.handleCreateAccount}
|
||||||
onUpdateAccount={this.handleUpdateAccount}
|
onUpdateAccount={this.handleUpdateAccount}
|
||||||
onDeleteAccount={this.handleDeleteAccount} />
|
onDeleteAccount={this.handleDeleteAccount} />
|
||||||
|
</TabPane>
|
||||||
|
<TabPane tab="Scheduled Transactions" eventKey='2'>Scheduled transactions go here...</TabPane>
|
||||||
|
<TabPane tab="Budgets" eventKey='3'>Budgets go here...</TabPane>
|
||||||
|
<TabPane tab="Reports" eventKey='4'>Reports go here...</TabPane>
|
||||||
|
</TabbedArea>
|
||||||
else
|
else
|
||||||
mainContent =
|
mainContent =
|
||||||
<Jumbotron>
|
<Jumbotron>
|
||||||
|
<center>
|
||||||
<h1>Money<i>Go</i></h1>
|
<h1>Money<i>Go</i></h1>
|
||||||
<p><i>Go</i> manage your money.</p>
|
<p><i>Go</i> manage your money.</p>
|
||||||
|
</center>
|
||||||
</Jumbotron>
|
</Jumbotron>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user