mirror of
				https://github.com/aclindsa/moneygo.git
				synced 2025-10-29 17:13:26 -04: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:
		| @@ -2,25 +2,227 @@ | ||||
| var ListGroup = ReactBootstrap.ListGroup; | ||||
| 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() { | ||||
| 		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() { | ||||
| 		var accounts = this.props.accounts; | ||||
| 		var account_map = this.props.account_map; | ||||
|  | ||||
| 		var listGroupItems; | ||||
|  | ||||
| 		for (var i = 0; i < accounts.length; i++) { | ||||
| 			listGroupItems += <ListGroupItem>{accounts[i].Name}</ListGroupItem>; | ||||
| 		} | ||||
| 		var listGroupItems = accounts.map(function(account) { | ||||
| 			return ( | ||||
| 				<ListGroupItem>{account.Name}</ListGroupItem> | ||||
| 		   ); | ||||
| 		}); | ||||
|  | ||||
| 		return ( | ||||
| 			<ListGroup> | ||||
| 				{listGroupItems} | ||||
| 			</ListGroup> | ||||
| 			<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> | ||||
| 						{listGroupItems} | ||||
| 					</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 = ""; | ||||
| } | ||||
|  | ||||
| var BogusPassword = "password"; | ||||
| const BogusPassword = "password"; | ||||
|  | ||||
| User.prototype.toJSON = function() { | ||||
| 	var json_obj = {}; | ||||
| @@ -76,7 +76,55 @@ Session.prototype.isSession = function() { | ||||
| 		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, | ||||
| 	Cash: 2, | ||||
| 	Asset: 3, | ||||
| @@ -85,6 +133,12 @@ var AccountType = { | ||||
| 	Income: 6, | ||||
| 	Expense: 7 | ||||
| } | ||||
| var AccountTypeList = []; | ||||
| for (var type in AccountType) { | ||||
| 	if (AccountType.hasOwnProperty(type)) { | ||||
| 		AccountTypeList.push({'TypeId': AccountType[type], 'Name': type}); | ||||
|    } | ||||
| } | ||||
|  | ||||
| function Account() { | ||||
| 	this.AccountId = -1; | ||||
| @@ -183,7 +237,7 @@ Split.prototype.isSplit = function() { | ||||
| 		this.AccountId != empty_split.AccountId; | ||||
| } | ||||
|  | ||||
| var TransactionStatus = { | ||||
| const TransactionStatus = { | ||||
| 	Entered: 1, | ||||
| 	Cleared: 2, | ||||
| 	Reconciled: 3, | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| div#content { | ||||
| 	width: 95%; | ||||
| 	height: 100%; | ||||
| 	min-width: 75em; | ||||
| 	max-width: 100em; | ||||
|     display: block; | ||||
|   | ||||
							
								
								
									
										62
									
								
								static/ui.js
									
									
									
									
									
								
							
							
						
						
									
										62
									
								
								static/ui.js
									
									
									
									
									
								
							| @@ -1,5 +1,7 @@ | ||||
| // Import all the objects we want to use from ReactBootstrap | ||||
| var Jumbotron = ReactBootstrap.Jumbotron; | ||||
| var TabbedArea = ReactBootstrap.TabbedArea; | ||||
| var TabPane = ReactBootstrap.TabPane; | ||||
| var Panel = ReactBootstrap.Panel; | ||||
| var ButtonGroup = ReactBootstrap.ButtonGroup; | ||||
|  | ||||
| @@ -299,6 +301,8 @@ var MoneyGoApp = React.createClass({ | ||||
| 			user: new User(), | ||||
| 			accounts: [], | ||||
| 			account_map: {}, | ||||
| 			securities: [], | ||||
| 			security_map: {}, | ||||
| 			error: new Error() | ||||
| 		}; | ||||
| 	}, | ||||
| @@ -345,6 +349,7 @@ var MoneyGoApp = React.createClass({ | ||||
| 				this.setState({session: s}); | ||||
| 				this.getUser(); | ||||
| 				this.getAccounts(); | ||||
| 				this.getSecurities(); | ||||
| 			}.bind(this), | ||||
| 			error: this.ajaxError | ||||
| 		}); | ||||
| @@ -370,6 +375,35 @@ var MoneyGoApp = React.createClass({ | ||||
| 			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: {}}); | ||||
| @@ -518,17 +552,29 @@ var MoneyGoApp = React.createClass({ | ||||
| 			mainContent = <AccountSettings user={this.state.user} onSettingsSubmitted={this.handleSettingsSubmitted} onCancel={this.handleGoHome}/> | ||||
| 		} else { | ||||
| 			if (this.state.user.isUser()) | ||||
| 				mainContent = <AccountList | ||||
| 						accounts={this.state.accounts} | ||||
| 						account_map={this.state.account_map} | ||||
| 						onCreateAccount={this.handleCreateAccount} | ||||
| 						onUpdateAccount={this.handleUpdateAccount} | ||||
| 						onDeleteAccount={this.handleDeleteAccount} /> | ||||
| 				mainContent = | ||||
| 					<TabbedArea defaultActiveKey='1'> | ||||
| 						<TabPane tab="Accounts" eventKey='1'> | ||||
| 						<AccountsTab | ||||
| 							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} /> | ||||
| 						</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 | ||||
| 				mainContent = | ||||
| 					<Jumbotron> | ||||
| 						<h1>Money<i>Go</i></h1> | ||||
| 						<p><i>Go</i> manage your money.</p> | ||||
| 						<center> | ||||
| 							<h1>Money<i>Go</i></h1> | ||||
| 							<p><i>Go</i> manage your money.</p> | ||||
| 						</center> | ||||
| 					</Jumbotron> | ||||
| 		} | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user