mirror of
				https://github.com/aclindsa/moneygo.git
				synced 2025-11-03 10:03:26 -05:00 
			
		
		
		
	Initial JavaScript UI commit
Definitely still a work in progress
This commit is contained in:
		
							
								
								
									
										26
									
								
								static/accounts.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								static/accounts.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
			
		||||
// Import all the objects we want to use from ReactBootstrap
 | 
			
		||||
var ListGroup = ReactBootstrap.ListGroup;
 | 
			
		||||
var ListGroupItem = ReactBootstrap.ListGroupItem;
 | 
			
		||||
 | 
			
		||||
var AccountList = React.createClass({
 | 
			
		||||
	getInitialState: function() {
 | 
			
		||||
		return {
 | 
			
		||||
		};
 | 
			
		||||
	},
 | 
			
		||||
	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>;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return (
 | 
			
		||||
			<ListGroup>
 | 
			
		||||
				{listGroupItems}
 | 
			
		||||
			</ListGroup>
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										1
									
								
								static/external/big/big.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								static/external/big/big.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								static/external/fonts/rw-widgets.eot
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								static/external/fonts/rw-widgets.eot
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										17
									
								
								static/external/fonts/rw-widgets.svg
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								static/external/fonts/rw-widgets.svg
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
			
		||||
<?xml version="1.0" standalone="no"?>
 | 
			
		||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
 | 
			
		||||
<svg xmlns="http://www.w3.org/2000/svg">
 | 
			
		||||
<metadata>Copyright (C) 2014 by original authors @ fontello.com</metadata>
 | 
			
		||||
<defs>
 | 
			
		||||
<font id="rw-widgets" horiz-adv-x="1000" >
 | 
			
		||||
<font-face font-family="rw-widgets" font-weight="400" font-stretch="normal" units-per-em="1000" ascent="850" descent="-150" />
 | 
			
		||||
<missing-glyph horiz-adv-x="1000" />
 | 
			
		||||
<glyph glyph-name="up-dir" unicode="" d="m0 171q0 15 11 26l250 250q10 10 25 10t25-10l250-250q10-11 10-26t-10-25-25-10h-500q-15 0-25 10t-11 25z" horiz-adv-x="571.4" />
 | 
			
		||||
<glyph glyph-name="down-dir" unicode="" d="m0 457q0 15 11 25t25 11h500q14 0 25-11t10-25-10-25l-250-250q-11-11-25-11t-25 11l-250 250q-11 11-11 25z" horiz-adv-x="571.4" />
 | 
			
		||||
<glyph glyph-name="right-dir" unicode="" d="m0 100v500q0 15 11 25t25 11 25-11l250-250q10-10 10-25t-10-25l-250-250q-11-11-25-11t-25 11-11 25z" horiz-adv-x="357.1" />
 | 
			
		||||
<glyph glyph-name="left-dir" unicode="" d="m36 350q0 15 10 25l250 250q11 11 25 11t26-11 10-25v-500q0-14-10-25t-26-11-25 11l-250 250q-10 11-10 25z" horiz-adv-x="357.1" />
 | 
			
		||||
<glyph glyph-name="calendar" unicode="" d="m0-79v715q0 29 21 50t50 21h72v54q0 36 26 63t63 26h36q37 0 63-26t26-63v-54h214v54q0 36 27 63t63 26h35q37 0 63-26t27-63v-54h71q29 0 50-21t22-50v-715q0-29-22-50t-50-21h-786q-29 0-50 21t-21 50z m71 0h161v161h-161v-161z m0 197h161v178h-161v-178z m0 214h161v161h-161v-161z m143 268q0-7 6-13t12-5h36q7 0 12 5t6 13v161q0 7-6 12t-12 6h-36q-7 0-12-6t-6-12v-161z m54-679h178v161h-178v-161z m0 197h178v178h-178v-178z m0 214h178v161h-178v-161z m214-411h179v161h-179v-161z m0 197h179v178h-179v-178z m0 214h179v161h-179v-161z m161 268q0-7 5-13t13-5h35q8 0 13 5t5 13v161q0 7-5 12t-13 6h-35q-8 0-13-6t-5-12v-161z m53-679h161v161h-161v-161z m0 197h161v178h-161v-178z m0 214h161v161h-161v-161z" horiz-adv-x="928.6" />
 | 
			
		||||
<glyph glyph-name="clock" unicode="" d="m0 350q0 117 58 215t155 156 216 58 215-58 156-156 57-215-57-215-156-156-215-58-216 58-155 156-58 215z m125 0q0-83 41-152t110-111 153-41 152 41 110 111 41 152-41 152-110 111-152 41-153-41-110-111-41-152z m161-54v36q0 8 5 13t13 5h125v196q0 8 5 13t12 5h36q8 0 13-5t5-13v-250q0-7-5-12t-13-5h-178q-8 0-13 5t-5 12z" horiz-adv-x="857.1" />
 | 
			
		||||
</font>
 | 
			
		||||
</defs>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 2.3 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								static/external/fonts/rw-widgets.ttf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								static/external/fonts/rw-widgets.ttf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								static/external/fonts/rw-widgets.woff
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								static/external/fonts/rw-widgets.woff
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										4
									
								
								static/external/react-bootstrap/react-bootstrap.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								static/external/react-bootstrap/react-bootstrap.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								static/external/react-widgets/loader-big.gif
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								static/external/react-widgets/loader-big.gif
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 23 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								static/external/react-widgets/loading.gif
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								static/external/react-widgets/loading.gif
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 673 B  | 
							
								
								
									
										1
									
								
								static/external/react-widgets/react-widgets.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								static/external/react-widgets/react-widgets.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										5
									
								
								static/external/react-widgets/react-widgets.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								static/external/react-widgets/react-widgets.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										34
									
								
								static/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								static/index.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
			
		||||
<html>
 | 
			
		||||
<head>
 | 
			
		||||
<title>MoneyGo</title>
 | 
			
		||||
 | 
			
		||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
 | 
			
		||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap-theme.min.css">
 | 
			
		||||
<link rel="stylesheet" href="static/external/react-widgets/react-widgets.css">
 | 
			
		||||
<link rel="stylesheet" href="static/stylesheet.css">
 | 
			
		||||
 | 
			
		||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
 | 
			
		||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
 | 
			
		||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.12.2/react.js"></script>
 | 
			
		||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.12.2/JSXTransformer.js"></script>
 | 
			
		||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/globalize/0.1.1/globalize.min.js"></script>
 | 
			
		||||
<script src="static/external/react-bootstrap/react-bootstrap.min.js"></script>
 | 
			
		||||
<script src="static/external/react-widgets/react-widgets.js"></script>
 | 
			
		||||
<script src="static/external/big/big.min.js"></script>
 | 
			
		||||
 | 
			
		||||
<script type="text/javascript" src="static/utils.js"></script>
 | 
			
		||||
<script type="text/javascript" src="static/models.js"></script>
 | 
			
		||||
 | 
			
		||||
<script type="text/jsx" src="static/top_bar.js"></script>
 | 
			
		||||
<script type="text/jsx" src="static/accounts.js"></script>
 | 
			
		||||
<script type="text/jsx" src="static/ui.js"></script>
 | 
			
		||||
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
 | 
			
		||||
<center>
 | 
			
		||||
    <div id="content"></div>
 | 
			
		||||
</center>
 | 
			
		||||
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										274
									
								
								static/models.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										274
									
								
								static/models.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,274 @@
 | 
			
		||||
function getJSONObj(json_input) {
 | 
			
		||||
	if (typeof json_input == "string")
 | 
			
		||||
		return $.parseJSON(json_input)
 | 
			
		||||
	else if (typeof json_input == "object")
 | 
			
		||||
		return json_input;
 | 
			
		||||
 | 
			
		||||
	console.error("Unable to parse json:", json_input);
 | 
			
		||||
	return null
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function User() {
 | 
			
		||||
	this.UserId = -1;
 | 
			
		||||
	this.Name = "";
 | 
			
		||||
	this.Username = "";
 | 
			
		||||
	this.Password = "";
 | 
			
		||||
	this.Email = "";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var BogusPassword = "password";
 | 
			
		||||
 | 
			
		||||
User.prototype.toJSON = function() {
 | 
			
		||||
	var json_obj = {};
 | 
			
		||||
	json_obj.UserId = this.UserId;
 | 
			
		||||
	json_obj.Name = this.Name;
 | 
			
		||||
	json_obj.Username = this.Username;
 | 
			
		||||
	json_obj.Password = this.Password;
 | 
			
		||||
	json_obj.Email = this.Email;
 | 
			
		||||
	return JSON.stringify(json_obj);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
User.prototype.fromJSON = function(json_input) {
 | 
			
		||||
	var json_obj = getJSONObj(json_input);
 | 
			
		||||
 | 
			
		||||
	if (json_obj.hasOwnProperty("UserId"))
 | 
			
		||||
		this.UserId = json_obj.UserId;
 | 
			
		||||
	if (json_obj.hasOwnProperty("Name"))
 | 
			
		||||
		this.Name = json_obj.Name;
 | 
			
		||||
	if (json_obj.hasOwnProperty("Username"))
 | 
			
		||||
		this.Username = json_obj.Username;
 | 
			
		||||
	if (json_obj.hasOwnProperty("Password"))
 | 
			
		||||
		this.Password = json_obj.Password;
 | 
			
		||||
	if (json_obj.hasOwnProperty("Email"))
 | 
			
		||||
		this.Email = json_obj.Email;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
User.prototype.isUser = function() {
 | 
			
		||||
	var empty_user = new User();
 | 
			
		||||
	return this.UserId != empty_user.UserId ||
 | 
			
		||||
		this.Username != empty_user.Username;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function Session() {
 | 
			
		||||
	this.SessionId = -1;
 | 
			
		||||
	this.UserId = -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Session.prototype.toJSON = function() {
 | 
			
		||||
	var json_obj = {};
 | 
			
		||||
	json_obj.SessionId = this.SessionId;
 | 
			
		||||
	json_obj.UserId = this.UserId;
 | 
			
		||||
	return JSON.stringify(json_obj);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Session.prototype.fromJSON = function(json_input) {
 | 
			
		||||
	var json_obj = getJSONObj(json_input);
 | 
			
		||||
 | 
			
		||||
	if (json_obj.hasOwnProperty("SessionId"))
 | 
			
		||||
		this.SessionId = json_obj.SessionId;
 | 
			
		||||
	if (json_obj.hasOwnProperty("UserId"))
 | 
			
		||||
		this.UserId = json_obj.UserId;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Session.prototype.isSession = function() {
 | 
			
		||||
	var empty_session = new Session();
 | 
			
		||||
	return this.SessionId != empty_session.SessionId ||
 | 
			
		||||
		this.UserId != empty_session.UserId;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var AccountType = {
 | 
			
		||||
	Bank: 1,
 | 
			
		||||
	Cash: 2,
 | 
			
		||||
	Asset: 3,
 | 
			
		||||
	Liability: 4,
 | 
			
		||||
	Investment: 5,
 | 
			
		||||
	Income: 6,
 | 
			
		||||
	Expense: 7
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function Account() {
 | 
			
		||||
	this.AccountId = -1;
 | 
			
		||||
	this.UserId = -1;
 | 
			
		||||
	this.SecurityId = -1;
 | 
			
		||||
	this.ParentAccountId = -1;
 | 
			
		||||
	this.Type = -1;
 | 
			
		||||
	this.Name = "";
 | 
			
		||||
	this.Children = []; // Not sent across JSON, just used internally
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Account.prototype.toJSON = function() {
 | 
			
		||||
	var json_obj = {};
 | 
			
		||||
	json_obj.AccountId = this.AccountId;
 | 
			
		||||
	json_obj.UserId = this.UserId;
 | 
			
		||||
	json_obj.SecurityId = this.SecurityId;
 | 
			
		||||
	json_obj.ParentAccountId = this.ParentAccountId;
 | 
			
		||||
	json_obj.Type = this.Type;
 | 
			
		||||
	json_obj.Name = this.Name;
 | 
			
		||||
	return JSON.stringify(json_obj);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Account.prototype.fromJSON = function(json_input) {
 | 
			
		||||
	var json_obj = getJSONObj(json_input);
 | 
			
		||||
 | 
			
		||||
	if (json_obj.hasOwnProperty("AccountId"))
 | 
			
		||||
		this.AccountId = json_obj.AccountId;
 | 
			
		||||
	if (json_obj.hasOwnProperty("UserId"))
 | 
			
		||||
		this.UserId = json_obj.UserId;
 | 
			
		||||
	if (json_obj.hasOwnProperty("SecurityId"))
 | 
			
		||||
		this.SecurityId = json_obj.SecurityId;
 | 
			
		||||
	if (json_obj.hasOwnProperty("ParentAccountId"))
 | 
			
		||||
		this.ParentAccountId = json_obj.ParentAccountId;
 | 
			
		||||
	if (json_obj.hasOwnProperty("Type"))
 | 
			
		||||
		this.Type = json_obj.Type;
 | 
			
		||||
	if (json_obj.hasOwnProperty("Name"))
 | 
			
		||||
		this.Name = json_obj.Name;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Account.prototype.isAccount = function() {
 | 
			
		||||
	var empty_account = new Account();
 | 
			
		||||
	return this.AccountId != empty_account.AccountId ||
 | 
			
		||||
		this.UserId != empty_account.UserId;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Account.prototype.isRootAccount = function() {
 | 
			
		||||
	var empty_account = new Account();
 | 
			
		||||
	return this.ParentAccountId == empty_account.ParentAccountId;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function Split() {
 | 
			
		||||
	this.SplitId = -1;
 | 
			
		||||
	this.TransactionId = -1;
 | 
			
		||||
	this.AccountId = -1;
 | 
			
		||||
	this.Number = "";
 | 
			
		||||
	this.Memo = "";
 | 
			
		||||
	this.Amount = new Big(0.0);
 | 
			
		||||
	this.Debit = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Split.prototype.toJSONobj = function() {
 | 
			
		||||
	var json_obj = {};
 | 
			
		||||
	json_obj.SplitId = this.SplitId;
 | 
			
		||||
	json_obj.TransactionId = this.TransactionId;
 | 
			
		||||
	json_obj.AccountId = this.AccountId;
 | 
			
		||||
	json_obj.Number = this.Number;
 | 
			
		||||
	json_obj.Memo = this.Memo;
 | 
			
		||||
	json_obj.Amount = this.Amount.toFixed();
 | 
			
		||||
	json_obj.Debit = this.Debit;
 | 
			
		||||
	return json_obj;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Split.prototype.fromJSONobj = function(json_obj) {
 | 
			
		||||
	var json_obj = getJSONObj(json_input);
 | 
			
		||||
 | 
			
		||||
	if (json_obj.hasOwnProperty("SplitId"))
 | 
			
		||||
		this.SplitId = json_obj.SplitId;
 | 
			
		||||
	if (json_obj.hasOwnProperty("TransactionId"))
 | 
			
		||||
		this.TransactionId = json_obj.TransactionId;
 | 
			
		||||
	if (json_obj.hasOwnProperty("AccountId"))
 | 
			
		||||
		this.AccountId = json_obj.AccountId;
 | 
			
		||||
	if (json_obj.hasOwnProperty("Number"))
 | 
			
		||||
		this.Number = json_obj.Number;
 | 
			
		||||
	if (json_obj.hasOwnProperty("Memo"))
 | 
			
		||||
		this.Memo = json_obj.Memo;
 | 
			
		||||
	if (json_obj.hasOwnProperty("Amount"))
 | 
			
		||||
		this.Amount = new Big(json_obj.Amount);
 | 
			
		||||
	if (json_obj.hasOwnProperty("Debit"))
 | 
			
		||||
		this.Debit = json_obj.Debit;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Split.prototype.isSplit = function() {
 | 
			
		||||
	var empty_split = new Split();
 | 
			
		||||
	return this.SplitId != empty_split.SplitId ||
 | 
			
		||||
		this.TransactionId != empty_split.TransactionId ||
 | 
			
		||||
		this.AccountId != empty_split.AccountId;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var TransactionStatus = {
 | 
			
		||||
	Entered: 1,
 | 
			
		||||
	Cleared: 2,
 | 
			
		||||
	Reconciled: 3,
 | 
			
		||||
	Voided: 4
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function Transaction() {
 | 
			
		||||
	this.TransactionId = -1;
 | 
			
		||||
	this.UserId = -1;
 | 
			
		||||
	this.Description = "";
 | 
			
		||||
	this.Status = -1;
 | 
			
		||||
	this.Date = new Date();
 | 
			
		||||
	this.Splits = [];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Transaction.prototype.toJSON = function() {
 | 
			
		||||
	var json_obj = {};
 | 
			
		||||
	json_obj.TransactionId = this.TransactionId;
 | 
			
		||||
	json_obj.UserId = this.UserId;
 | 
			
		||||
	json_obj.Description = this.Description;
 | 
			
		||||
	json_obj.Status = this.Status;
 | 
			
		||||
	json_obj.Date = this.Date.toJSON();
 | 
			
		||||
	json_obj.Splits = [];
 | 
			
		||||
	for (var i = 0; i < this.Splits.length; i++)
 | 
			
		||||
		json_obj.push(this.Splits[i].toJSONobj());
 | 
			
		||||
	return json_obj;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Transaction.prototype.fromJSON = function(json_input) {
 | 
			
		||||
	var json_obj = getJSONObj(json_input);
 | 
			
		||||
 | 
			
		||||
	if (json_obj.hasOwnProperty("TransactionId"))
 | 
			
		||||
		this.TransactionId = json_obj.TransactionId;
 | 
			
		||||
	if (json_obj.hasOwnProperty("UserId"))
 | 
			
		||||
		this.UserId = json_obj.UserId;
 | 
			
		||||
	if (json_obj.hasOwnProperty("Description"))
 | 
			
		||||
		this.Description = json_obj.Description;
 | 
			
		||||
	if (json_obj.hasOwnProperty("Status"))
 | 
			
		||||
		this.Status = json_obj.Status;
 | 
			
		||||
	if (json_obj.hasOwnProperty("Date")) {
 | 
			
		||||
		this.Date = json_obj.Date
 | 
			
		||||
		if (typeof this.Date === 'string') {
 | 
			
		||||
			var t = Date.parse(this.Date);
 | 
			
		||||
			if (t)
 | 
			
		||||
				this.Date = new Date(t);
 | 
			
		||||
			else
 | 
			
		||||
				this.Date = new Date(0);
 | 
			
		||||
		} else
 | 
			
		||||
			this.Date = new Date(0);
 | 
			
		||||
	}
 | 
			
		||||
	if (json_obj.hasOwnProperty("Splits")) {
 | 
			
		||||
		for (var i = 0; i < json_obj.Splits.length; i++)
 | 
			
		||||
			this.Splits.push(this.Splits[i].fromJSON());
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Transaction.prototype.isTransaction = function() {
 | 
			
		||||
	var empty_transaction = new Transaction();
 | 
			
		||||
	return this.TransactionId != empty_transaction.TransactionId ||
 | 
			
		||||
		this.UserId != empty_transaction.UserId;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function Error() {
 | 
			
		||||
	this.ErrorId = -1;
 | 
			
		||||
	this.ErrorString = "";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Error.prototype.toJSON = function() {
 | 
			
		||||
	var json_obj = {};
 | 
			
		||||
	json_obj.ErrorId = this.ErrorId;
 | 
			
		||||
	json_obj.ErrorString = this.ErrorString;
 | 
			
		||||
	return JSON.stringify(json_obj);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Error.prototype.fromJSON = function(json_input) {
 | 
			
		||||
	var json_obj = getJSONObj(json_input);
 | 
			
		||||
 | 
			
		||||
	if (json_obj.hasOwnProperty("ErrorId"))
 | 
			
		||||
		this.ErrorId = json_obj.ErrorId;
 | 
			
		||||
	if (json_obj.hasOwnProperty("ErrorString"))
 | 
			
		||||
		this.ErrorString = json_obj.ErrorString;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Error.prototype.isError = function() {
 | 
			
		||||
	var empty_error = new Error();
 | 
			
		||||
	return this.ErrorId != empty_error.ErrorId ||
 | 
			
		||||
		this.ErrorString != empty_error.ErrorString;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										5
									
								
								static/stylesheet.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								static/stylesheet.css
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
div#content {
 | 
			
		||||
	width: 95%;
 | 
			
		||||
	min-width: 75em;
 | 
			
		||||
	max-width: 100em;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										117
									
								
								static/top_bar.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								static/top_bar.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,117 @@
 | 
			
		||||
// Import all the objects we want to use from ReactBootstrap
 | 
			
		||||
var Alert = ReactBootstrap.Alert;
 | 
			
		||||
 | 
			
		||||
var Input = ReactBootstrap.Input;
 | 
			
		||||
var Button = ReactBootstrap.Button;
 | 
			
		||||
var DropdownButton = ReactBootstrap.DropdownButton;
 | 
			
		||||
var MenuItem = ReactBootstrap.MenuItem;
 | 
			
		||||
 | 
			
		||||
var Row = ReactBootstrap.Row;
 | 
			
		||||
var Col = ReactBootstrap.Col;
 | 
			
		||||
 | 
			
		||||
var LoginBar = React.createClass({
 | 
			
		||||
	getInitialState: function() {
 | 
			
		||||
		return {username: '', password: ''};
 | 
			
		||||
	},
 | 
			
		||||
	onUsernameChange: function(e) {
 | 
			
		||||
		this.setState({username: e.target.value});
 | 
			
		||||
	},
 | 
			
		||||
	onPasswordChange: function(e) {
 | 
			
		||||
		this.setState({password: e.target.value});
 | 
			
		||||
	},
 | 
			
		||||
	handleSubmit: function(e) {
 | 
			
		||||
		var user = new User();
 | 
			
		||||
		e.preventDefault();
 | 
			
		||||
		user.Username = this.refs.username.getValue();
 | 
			
		||||
		user.Password = this.refs.password.getValue();
 | 
			
		||||
		this.props.onLoginSubmit(user);
 | 
			
		||||
	},
 | 
			
		||||
	handleNewUserSubmit: function(e) {
 | 
			
		||||
		e.preventDefault();
 | 
			
		||||
		this.props.onCreateNewUser();
 | 
			
		||||
	},
 | 
			
		||||
	render: function() {
 | 
			
		||||
		return (
 | 
			
		||||
			<form onSubmit={this.handleSubmit}>
 | 
			
		||||
			<Input wrapperClassName="wrapper">
 | 
			
		||||
				<Row>
 | 
			
		||||
					<Col xs={4}></Col>
 | 
			
		||||
					<Col xs={2}>
 | 
			
		||||
						<Button bsStyle="link"
 | 
			
		||||
							onClick={this.handleNewUserSubmit}>Create New User</Button>
 | 
			
		||||
					</Col>
 | 
			
		||||
					<Col xs={2}>
 | 
			
		||||
						<Input type="text"
 | 
			
		||||
							placeholder="Username..."
 | 
			
		||||
							ref="username"/>
 | 
			
		||||
					</Col>
 | 
			
		||||
					<Col xs={2}>
 | 
			
		||||
						<Input type="password"
 | 
			
		||||
							placeholder="Password..."
 | 
			
		||||
							ref="password" block/>
 | 
			
		||||
					</Col>
 | 
			
		||||
					<Col xs={2}>
 | 
			
		||||
						<Button type="submit" bsStyle="primary" block>
 | 
			
		||||
							Login</Button>
 | 
			
		||||
					</Col>
 | 
			
		||||
				</Row>
 | 
			
		||||
			</Input>
 | 
			
		||||
			</form>
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
var LogoutBar = React.createClass({
 | 
			
		||||
	handleOnSelect: function(key) {
 | 
			
		||||
		if (key == 1) {
 | 
			
		||||
			if (this.props.onAccountSettings != null)
 | 
			
		||||
				this.props.onAccountSettings();
 | 
			
		||||
		} else if (key == 2) {
 | 
			
		||||
			this.props.onLogoutSubmit();
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	render: function() {
 | 
			
		||||
		var signedInString = "Signed in as "+this.props.user.Name;
 | 
			
		||||
		return (
 | 
			
		||||
			<Input wrapperClassName="wrapper">
 | 
			
		||||
				<Row>
 | 
			
		||||
					<Col xs={2}><label className="control-label pull-left">Money<i>Go</i></label></Col>
 | 
			
		||||
					<Col xs={6}></Col>
 | 
			
		||||
					<Col xs={4}>
 | 
			
		||||
						<div className="pull-right">
 | 
			
		||||
						<DropdownButton title={signedInString} onSelect={this.handleOnSelect} bsStyle="info">
 | 
			
		||||
							<MenuItem eventKey="1">Account Settings</MenuItem>
 | 
			
		||||
							<MenuItem eventKey="2">Logout</MenuItem>
 | 
			
		||||
						</DropdownButton>
 | 
			
		||||
						</div>
 | 
			
		||||
					</Col>
 | 
			
		||||
				</Row>
 | 
			
		||||
			</Input>
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
var TopBar = React.createClass({
 | 
			
		||||
	render: function() {
 | 
			
		||||
		var barContents;
 | 
			
		||||
		var errorAlert;
 | 
			
		||||
		if (!this.props.user.isUser())
 | 
			
		||||
			barContents = <LoginBar onLoginSubmit={this.props.onLoginSubmit} onCreateNewUser={this.props.onCreateNewUser} />;
 | 
			
		||||
		else
 | 
			
		||||
			barContents = <LogoutBar user={this.props.user} onLogoutSubmit={this.props.onLogoutSubmit} onAccountSettings={this.props.onAccountSettings}/>;
 | 
			
		||||
		if (this.props.error.isError())
 | 
			
		||||
			errorAlert =
 | 
			
		||||
					<Alert bsStyle="danger" onDismiss={this.props.onErrorClear}>
 | 
			
		||||
						<h4>Error!</h4>
 | 
			
		||||
						<p>Error {this.props.error.ErrorId}: {this.props.error.ErrorString}</p>
 | 
			
		||||
						<Button onClick={this.props.onErrorClear}>Clear</Button>
 | 
			
		||||
					</Alert>;
 | 
			
		||||
 | 
			
		||||
		return (
 | 
			
		||||
			<div>
 | 
			
		||||
				{barContents}
 | 
			
		||||
				{errorAlert}
 | 
			
		||||
			</div>
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										551
									
								
								static/ui.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										551
									
								
								static/ui.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,551 @@
 | 
			
		||||
// Import all the objects we want to use from ReactBootstrap
 | 
			
		||||
var Jumbotron = ReactBootstrap.Jumbotron;
 | 
			
		||||
var Panel = ReactBootstrap.Panel;
 | 
			
		||||
var ButtonGroup = ReactBootstrap.ButtonGroup;
 | 
			
		||||
 | 
			
		||||
var NewUserForm = React.createClass({
 | 
			
		||||
	getInitialState: function() {
 | 
			
		||||
		return {error: "",
 | 
			
		||||
			name: "",
 | 
			
		||||
			username: "",
 | 
			
		||||
			email: "",
 | 
			
		||||
			password: "",
 | 
			
		||||
			confirm_password: "",
 | 
			
		||||
			passwordChanged: false,
 | 
			
		||||
			initial_password: ""};
 | 
			
		||||
	},
 | 
			
		||||
	passwordValidationState: function() {
 | 
			
		||||
		if (this.state.passwordChanged) {
 | 
			
		||||
			if (this.state.password.length >= 10)
 | 
			
		||||
				return "success";
 | 
			
		||||
			else if (this.state.password.length >= 6)
 | 
			
		||||
				return "warning";
 | 
			
		||||
			else
 | 
			
		||||
				return "error";
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	confirmPasswordValidationState: function() {
 | 
			
		||||
		if (this.state.confirm_password.length > 0) {
 | 
			
		||||
			if (this.state.confirm_password == this.state.password)
 | 
			
		||||
				return "success";
 | 
			
		||||
			else
 | 
			
		||||
				return "error";
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	handleCancel: function() {
 | 
			
		||||
		if (this.props.onCancel != null)
 | 
			
		||||
			this.props.onCancel();
 | 
			
		||||
	},
 | 
			
		||||
	handleChange: function() {
 | 
			
		||||
		if (this.refs.password.getValue() != this.state.initial_password)
 | 
			
		||||
			this.setState({passwordChanged: true});
 | 
			
		||||
		this.setState({
 | 
			
		||||
			name: this.refs.name.getValue(),
 | 
			
		||||
			username: this.refs.username.getValue(),
 | 
			
		||||
			email: this.refs.email.getValue(),
 | 
			
		||||
			password: this.refs.password.getValue(),
 | 
			
		||||
			confirm_password: this.refs.confirm_password.getValue()
 | 
			
		||||
		});
 | 
			
		||||
	},
 | 
			
		||||
	handleSubmit: function(e) {
 | 
			
		||||
		var u = new User();
 | 
			
		||||
		var error = "";
 | 
			
		||||
		e.preventDefault();
 | 
			
		||||
 | 
			
		||||
		u.Name = this.state.name;
 | 
			
		||||
		u.Username = this.state.username;
 | 
			
		||||
		u.Email = this.state.email;
 | 
			
		||||
		u.Password = this.state.password;
 | 
			
		||||
		if (u.Password != this.state.confirm_password) {
 | 
			
		||||
			this.setState({error: "Error: password do not match"});
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		this.handleCreateNewUser(u);
 | 
			
		||||
	},
 | 
			
		||||
	handleCreateNewUser: function(user) {
 | 
			
		||||
		$.ajax({
 | 
			
		||||
			type: "POST",
 | 
			
		||||
			dataType: "json",
 | 
			
		||||
			url: "user/",
 | 
			
		||||
			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.props.onNewUser();
 | 
			
		||||
				}
 | 
			
		||||
			}.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),
 | 
			
		||||
		});
 | 
			
		||||
	},
 | 
			
		||||
	render: function() {
 | 
			
		||||
		var title = <h3>Create New User</h3>;
 | 
			
		||||
		return (
 | 
			
		||||
			<Panel header={title} bsStyle="info">
 | 
			
		||||
				<span color="red">{this.state.error}</span>
 | 
			
		||||
				<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 type="text"
 | 
			
		||||
							label="Username"
 | 
			
		||||
							value={this.state.username}
 | 
			
		||||
							onChange={this.handleChange}
 | 
			
		||||
							ref="username"
 | 
			
		||||
							labelClassName="col-xs-2"
 | 
			
		||||
							wrapperClassName="col-xs-10"/>
 | 
			
		||||
					<Input type="email"
 | 
			
		||||
							label="Email"
 | 
			
		||||
							value={this.state.email}
 | 
			
		||||
							onChange={this.handleChange}
 | 
			
		||||
							ref="email"
 | 
			
		||||
							labelClassName="col-xs-2"
 | 
			
		||||
							wrapperClassName="col-xs-10"/>
 | 
			
		||||
					<Input type="password"
 | 
			
		||||
							label="Password"
 | 
			
		||||
							value={this.state.password}
 | 
			
		||||
							onChange={this.handleChange}
 | 
			
		||||
							ref="password"
 | 
			
		||||
							labelClassName="col-xs-2"
 | 
			
		||||
							wrapperClassName="col-xs-10"
 | 
			
		||||
							bsStyle={this.passwordValidationState()}
 | 
			
		||||
							hasFeedback/>
 | 
			
		||||
					<Input type="password"
 | 
			
		||||
							label="Confirm Password"
 | 
			
		||||
							value={this.state.confirm_password}
 | 
			
		||||
							onChange={this.handleChange}
 | 
			
		||||
							ref="confirm_password"
 | 
			
		||||
							labelClassName="col-xs-2"
 | 
			
		||||
							wrapperClassName="col-xs-10"
 | 
			
		||||
							bsStyle={this.confirmPasswordValidationState()}
 | 
			
		||||
							hasFeedback/>
 | 
			
		||||
					<ButtonGroup className="pull-right">
 | 
			
		||||
						<Button onClick={this.handleCancel}
 | 
			
		||||
								bsStyle="warning">Cancel</Button>
 | 
			
		||||
						<Button type="submit"
 | 
			
		||||
								bsStyle="success">Create New User</Button>
 | 
			
		||||
					</ButtonGroup>
 | 
			
		||||
				</form>
 | 
			
		||||
			</Panel>
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
var AccountSettings = React.createClass({
 | 
			
		||||
	getInitialState: function() {
 | 
			
		||||
		return {error: "",
 | 
			
		||||
			name: this.props.user.Name,
 | 
			
		||||
			username: this.props.user.Username,
 | 
			
		||||
			email: this.props.user.Email,
 | 
			
		||||
			password: BogusPassword,
 | 
			
		||||
			confirm_password: BogusPassword,
 | 
			
		||||
			passwordChanged: false,
 | 
			
		||||
			initial_password: BogusPassword};
 | 
			
		||||
	},
 | 
			
		||||
	passwordValidationState: function() {
 | 
			
		||||
		if (this.state.passwordChanged) {
 | 
			
		||||
			if (this.state.password.length >= 10)
 | 
			
		||||
				return "success";
 | 
			
		||||
			else if (this.state.password.length >= 6)
 | 
			
		||||
				return "warning";
 | 
			
		||||
			else
 | 
			
		||||
				return "error";
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	confirmPasswordValidationState: function() {
 | 
			
		||||
		if (this.state.confirm_password.length > 0) {
 | 
			
		||||
			if (this.state.confirm_password == this.state.password)
 | 
			
		||||
				return "success";
 | 
			
		||||
			else
 | 
			
		||||
				return "error";
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	handleCancel: function() {
 | 
			
		||||
		if (this.props.onCancel != null)
 | 
			
		||||
			this.props.onCancel();
 | 
			
		||||
	},
 | 
			
		||||
	handleChange: function() {
 | 
			
		||||
		if (this.refs.password.getValue() != this.state.initial_password)
 | 
			
		||||
			this.setState({passwordChanged: true});
 | 
			
		||||
		this.setState({
 | 
			
		||||
			name: this.refs.name.getValue(),
 | 
			
		||||
			username: this.refs.username.getValue(),
 | 
			
		||||
			email: this.refs.email.getValue(),
 | 
			
		||||
			password: this.refs.password.getValue(),
 | 
			
		||||
			confirm_password: this.refs.confirm_password.getValue()
 | 
			
		||||
		});
 | 
			
		||||
	},
 | 
			
		||||
	handleSubmit: function(e) {
 | 
			
		||||
		var u = new User();
 | 
			
		||||
		var error = "";
 | 
			
		||||
		e.preventDefault();
 | 
			
		||||
 | 
			
		||||
		u.UserId = this.props.user.UserId;
 | 
			
		||||
		u.Name = this.state.name;
 | 
			
		||||
		u.Username = this.state.username;
 | 
			
		||||
		u.Email = this.state.email;
 | 
			
		||||
		if (this.state.passwordChanged) {
 | 
			
		||||
			u.Password = this.state.password;
 | 
			
		||||
			if (u.Password != this.state.confirm_password) {
 | 
			
		||||
				this.setState({error: "Error: password do not match"});
 | 
			
		||||
				return;
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			u.Password = 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.onSettingsSubmitted(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),
 | 
			
		||||
		});
 | 
			
		||||
	},
 | 
			
		||||
	render: function() {
 | 
			
		||||
		var title = <h3>Edit Account Settings</h3>;
 | 
			
		||||
		return (
 | 
			
		||||
			<Panel header={title} bsStyle="info">
 | 
			
		||||
				<span color="red">{this.state.error}</span>
 | 
			
		||||
				<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 type="text"
 | 
			
		||||
							label="Username"
 | 
			
		||||
							value={this.state.username}
 | 
			
		||||
							onChange={this.handleChange}
 | 
			
		||||
							ref="username"
 | 
			
		||||
							labelClassName="col-xs-2"
 | 
			
		||||
							wrapperClassName="col-xs-10"/>
 | 
			
		||||
					<Input type="email"
 | 
			
		||||
							label="Email"
 | 
			
		||||
							value={this.state.email}
 | 
			
		||||
							onChange={this.handleChange}
 | 
			
		||||
							ref="email"
 | 
			
		||||
							labelClassName="col-xs-2"
 | 
			
		||||
							wrapperClassName="col-xs-10"/>
 | 
			
		||||
					<Input type="password"
 | 
			
		||||
							label="Password"
 | 
			
		||||
							value={this.state.password}
 | 
			
		||||
							onChange={this.handleChange}
 | 
			
		||||
							ref="password"
 | 
			
		||||
							labelClassName="col-xs-2"
 | 
			
		||||
							wrapperClassName="col-xs-10"
 | 
			
		||||
							bsStyle={this.passwordValidationState()}
 | 
			
		||||
							hasFeedback/>
 | 
			
		||||
					<Input type="password"
 | 
			
		||||
							label="Confirm Password"
 | 
			
		||||
							value={this.state.confirm_password}
 | 
			
		||||
							onChange={this.handleChange}
 | 
			
		||||
							ref="confirm_password"
 | 
			
		||||
							labelClassName="col-xs-2"
 | 
			
		||||
							wrapperClassName="col-xs-10"
 | 
			
		||||
							bsStyle={this.confirmPasswordValidationState()}
 | 
			
		||||
							hasFeedback/>
 | 
			
		||||
					<ButtonGroup className="pull-right">
 | 
			
		||||
						<Button onClick={this.handleCancel}
 | 
			
		||||
								bsStyle="warning">Cancel</Button>
 | 
			
		||||
						<Button type="submit"
 | 
			
		||||
								bsStyle="success">Save Settings</Button>
 | 
			
		||||
					</ButtonGroup>
 | 
			
		||||
				</form>
 | 
			
		||||
			</Panel>
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
var MoneyGoApp = React.createClass({
 | 
			
		||||
	getInitialState: function() {
 | 
			
		||||
		return {
 | 
			
		||||
			hash: "home",
 | 
			
		||||
			session: new Session(),
 | 
			
		||||
			user: new User(),
 | 
			
		||||
			accounts: [],
 | 
			
		||||
			account_map: {},
 | 
			
		||||
			error: new Error()
 | 
			
		||||
		};
 | 
			
		||||
	},
 | 
			
		||||
	componentDidMount: function() {
 | 
			
		||||
		this.getSession();
 | 
			
		||||
		this.handleHashChange();
 | 
			
		||||
		if ("onhashchange" in window) {
 | 
			
		||||
			window.onhashchange = this.handleHashChange;
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	handleHashChange: function() {
 | 
			
		||||
		var hash = location.hash.replace(/^#/, '');
 | 
			
		||||
		if (hash.length == 0)
 | 
			
		||||
			hash = "home";
 | 
			
		||||
		if (hash != this.state.hash)
 | 
			
		||||
			this.setHash(hash);
 | 
			
		||||
	},
 | 
			
		||||
	setHash: function(hash) {
 | 
			
		||||
		location.hash = hash;
 | 
			
		||||
		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();
 | 
			
		||||
			}.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
 | 
			
		||||
		});
 | 
			
		||||
	},
 | 
			
		||||
	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.setHash("account");
 | 
			
		||||
	},
 | 
			
		||||
	handleSettingsSubmitted: function(user) {
 | 
			
		||||
		this.setState({user: user});
 | 
			
		||||
		this.setHash("home");
 | 
			
		||||
	},
 | 
			
		||||
	handleCreateNewUser: function() {
 | 
			
		||||
		this.setHash("new_user");
 | 
			
		||||
	},
 | 
			
		||||
	handleGoHome: function(user) {
 | 
			
		||||
		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.hash == "account" && this.state.user.isUser()) {
 | 
			
		||||
			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} />
 | 
			
		||||
			else
 | 
			
		||||
				mainContent =
 | 
			
		||||
					<Jumbotron>
 | 
			
		||||
						<h1>Money<i>Go</i></h1>
 | 
			
		||||
						<p><i>Go</i> manage your money.</p>
 | 
			
		||||
					</Jumbotron>
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return (
 | 
			
		||||
			<div>
 | 
			
		||||
				<TopBar
 | 
			
		||||
						error={this.state.error}
 | 
			
		||||
						onErrorClear={this.handleErrorClear}
 | 
			
		||||
						onLoginSubmit={this.handleLoginSubmit}
 | 
			
		||||
						onCreateNewUser={this.handleCreateNewUser}
 | 
			
		||||
						user={this.state.user}
 | 
			
		||||
						onAccountSettings={this.handleAccountSettings}
 | 
			
		||||
						onLogoutSubmit={this.handleLogoutSubmit} />
 | 
			
		||||
				{mainContent}
 | 
			
		||||
			</div>
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
React.render(<MoneyGoApp />, document.getElementById("content"));
 | 
			
		||||
		Reference in New Issue
	
	Block a user