mirror of
				https://github.com/aclindsa/moneygo.git
				synced 2025-11-03 18:13:27 -05:00 
			
		
		
		
	Move to using npm/browserify to package everything
This means it now requires the Javascript to be compiled before it can be run. This move also required a massive reorganization and lots of debugging/fixups to make everything work properly again.
This commit is contained in:
		
							
								
								
									
										13
									
								
								README
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								README
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					MoneyGo README
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Installation
 | 
				
			||||||
 | 
					============
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					First, install npm in your distribution:
 | 
				
			||||||
 | 
					$ sudo pacman -S npm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Install browserify globally:
 | 
				
			||||||
 | 
					$ sudo npm install -g browserify
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Next, install browserify, babel, react, react-bootstrap, react-widgets, and globalize in our directory using npm:
 | 
				
			||||||
 | 
					$ cd static && npm install browserify react react-dom react-addons-update react-bootstrap react-widgets babelify babel-preset-react globalize cldr-data
 | 
				
			||||||
							
								
								
									
										37
									
								
								static/AccountCombobox.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								static/AccountCombobox.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
				
			|||||||
 | 
					var React = require('react');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var Combobox = require('react-widgets').Combobox;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = React.createClass({
 | 
				
			||||||
 | 
						displayName: "AccountCombobox",
 | 
				
			||||||
 | 
						getDefaultProps: function() {
 | 
				
			||||||
 | 
							return {
 | 
				
			||||||
 | 
								includeRoot: true,
 | 
				
			||||||
 | 
								rootName: "New Top-level Account"
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						handleAccountChange: function(account) {
 | 
				
			||||||
 | 
							if (this.props.onChange != null &&
 | 
				
			||||||
 | 
									account.hasOwnProperty('AccountId') &&
 | 
				
			||||||
 | 
									(this.props.account_map.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 className = "";
 | 
				
			||||||
 | 
							if (this.props.className)
 | 
				
			||||||
 | 
								className = this.props.className;
 | 
				
			||||||
 | 
							return (
 | 
				
			||||||
 | 
								<Combobox
 | 
				
			||||||
 | 
									data={accounts}
 | 
				
			||||||
 | 
									valueField='AccountId'
 | 
				
			||||||
 | 
									textField='Name'
 | 
				
			||||||
 | 
									defaultValue={this.props.value}
 | 
				
			||||||
 | 
									onChange={this.handleAccountChange}
 | 
				
			||||||
 | 
									ref="account"
 | 
				
			||||||
 | 
									className={className} />
 | 
				
			||||||
 | 
						   );
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
@@ -1,28 +1,35 @@
 | 
				
			|||||||
// Import all the objects we want to use from ReactBootstrap
 | 
					var React = require('react');
 | 
				
			||||||
 | 
					var ReactDOM = require('react-dom');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var react_update = require('react-addons-update');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var ReactBootstrap = require('react-bootstrap');
 | 
				
			||||||
var Alert = ReactBootstrap.Alert;
 | 
					var Alert = ReactBootstrap.Alert;
 | 
				
			||||||
var Modal = ReactBootstrap.Modal;
 | 
					var Modal = ReactBootstrap.Modal;
 | 
				
			||||||
var Pagination = ReactBootstrap.Pagination;
 | 
					var Pagination = ReactBootstrap.Pagination;
 | 
				
			||||||
 | 
					 | 
				
			||||||
var Label = ReactBootstrap.Label;
 | 
					var Label = ReactBootstrap.Label;
 | 
				
			||||||
var Table = ReactBootstrap.Table;
 | 
					var Table = ReactBootstrap.Table;
 | 
				
			||||||
var Grid = ReactBootstrap.Grid;
 | 
					var Grid = ReactBootstrap.Grid;
 | 
				
			||||||
var Row = ReactBootstrap.Row;
 | 
					var Row = ReactBootstrap.Row;
 | 
				
			||||||
var Col = ReactBootstrap.Col;
 | 
					var Col = ReactBootstrap.Col;
 | 
				
			||||||
var Panel = ReactBootstrap.Panel;
 | 
					var Panel = ReactBootstrap.Panel;
 | 
				
			||||||
 | 
					var Input = ReactBootstrap.Input;
 | 
				
			||||||
var Button = ReactBootstrap.Button;
 | 
					var Button = ReactBootstrap.Button;
 | 
				
			||||||
 | 
					var ButtonGroup = ReactBootstrap.ButtonGroup;
 | 
				
			||||||
var ButtonToolbar = ReactBootstrap.ButtonToolbar;
 | 
					var ButtonToolbar = ReactBootstrap.ButtonToolbar;
 | 
				
			||||||
 | 
					 | 
				
			||||||
var ProgressBar = ReactBootstrap.ProgressBar;
 | 
					var ProgressBar = ReactBootstrap.ProgressBar;
 | 
				
			||||||
 | 
					var Glyphicon = ReactBootstrap.Glyphicon;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var DateTimePicker = ReactWidgets.DateTimePicker;
 | 
					var DateTimePicker = require('react-widgets').DateTimePicker;
 | 
				
			||||||
 | 
					var Combobox = require('react-widgets').Combobox;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var AccountCombobox = require('./AccountCombobox.js');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const TransactionRow = React.createClass({
 | 
					const TransactionRow = React.createClass({
 | 
				
			||||||
	handleClick: function(e) {
 | 
						handleClick: function(e) {
 | 
				
			||||||
		const refs = ["date", "number", "description", "account", "status", "amount"];
 | 
							const refs = ["date", "number", "description", "account", "status", "amount"];
 | 
				
			||||||
		for (var ref in refs) {
 | 
							for (var ref in refs) {
 | 
				
			||||||
			if (this.refs[refs[ref]].getDOMNode() == e.target) {
 | 
								if (this.refs[refs[ref]] == e.target) {
 | 
				
			||||||
				this.props.onEdit(this.props.transaction, refs[ref]);
 | 
									this.props.onEdit(this.props.transaction, refs[ref]);
 | 
				
			||||||
				return;
 | 
									return;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@@ -135,7 +142,7 @@ const AmountInput = React.createClass({
 | 
				
			|||||||
		var symbol = "?";
 | 
							var symbol = "?";
 | 
				
			||||||
		if (this.props.security)
 | 
							if (this.props.security)
 | 
				
			||||||
			symbol = this.props.security.Symbol;
 | 
								symbol = this.props.security.Symbol;
 | 
				
			||||||
		var bsStyle = "";
 | 
							var bsStyle = undefined;
 | 
				
			||||||
		if (this.props.bsStyle)
 | 
							if (this.props.bsStyle)
 | 
				
			||||||
			bsStyle = this.props.bsStyle;
 | 
								bsStyle = this.props.bsStyle;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -173,7 +180,7 @@ const AddEditTransactionModal = React.createClass({
 | 
				
			|||||||
	},
 | 
						},
 | 
				
			||||||
	handleDescriptionChange: function() {
 | 
						handleDescriptionChange: function() {
 | 
				
			||||||
		this.setState({
 | 
							this.setState({
 | 
				
			||||||
			transaction: React.addons.update(this.state.transaction, {
 | 
								transaction: react_update(this.state.transaction, {
 | 
				
			||||||
				Description: {$set: this.refs.description.getValue()}
 | 
									Description: {$set: this.refs.description.getValue()}
 | 
				
			||||||
			})
 | 
								})
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
@@ -182,7 +189,7 @@ const AddEditTransactionModal = React.createClass({
 | 
				
			|||||||
		if (date == null)
 | 
							if (date == null)
 | 
				
			||||||
			return;
 | 
								return;
 | 
				
			||||||
		this.setState({
 | 
							this.setState({
 | 
				
			||||||
			transaction: React.addons.update(this.state.transaction, {
 | 
								transaction: react_update(this.state.transaction, {
 | 
				
			||||||
				Date: {$set: date}
 | 
									Date: {$set: date}
 | 
				
			||||||
			})
 | 
								})
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
@@ -190,7 +197,7 @@ const AddEditTransactionModal = React.createClass({
 | 
				
			|||||||
	handleStatusChange: function(status) {
 | 
						handleStatusChange: function(status) {
 | 
				
			||||||
		if (status.hasOwnProperty('StatusId')) {
 | 
							if (status.hasOwnProperty('StatusId')) {
 | 
				
			||||||
			this.setState({
 | 
								this.setState({
 | 
				
			||||||
				transaction: React.addons.update(this.state.transaction, {
 | 
									transaction: react_update(this.state.transaction, {
 | 
				
			||||||
					Status: {$set: status.StatusId}
 | 
										Status: {$set: status.StatusId}
 | 
				
			||||||
				})
 | 
									})
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
@@ -198,21 +205,21 @@ const AddEditTransactionModal = React.createClass({
 | 
				
			|||||||
	},
 | 
						},
 | 
				
			||||||
	handleAddSplit: function() {
 | 
						handleAddSplit: function() {
 | 
				
			||||||
		this.setState({
 | 
							this.setState({
 | 
				
			||||||
			transaction: React.addons.update(this.state.transaction, {
 | 
								transaction: react_update(this.state.transaction, {
 | 
				
			||||||
				Splits: {$push: [new Split()]}
 | 
									Splits: {$push: [new Split()]}
 | 
				
			||||||
			})
 | 
								})
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	handleDeleteSplit: function(split) {
 | 
						handleDeleteSplit: function(split) {
 | 
				
			||||||
		this.setState({
 | 
							this.setState({
 | 
				
			||||||
			transaction: React.addons.update(this.state.transaction, {
 | 
								transaction: react_update(this.state.transaction, {
 | 
				
			||||||
				Splits: {$splice: [[split, 1]]}
 | 
									Splits: {$splice: [[split, 1]]}
 | 
				
			||||||
			})
 | 
								})
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	handleUpdateNumber: function(split) {
 | 
						handleUpdateNumber: function(split) {
 | 
				
			||||||
		var transaction = this.state.transaction;
 | 
							var transaction = this.state.transaction;
 | 
				
			||||||
		transaction.Splits[split] = React.addons.update(transaction.Splits[split], {
 | 
							transaction.Splits[split] = react_update(transaction.Splits[split], {
 | 
				
			||||||
			Number: {$set: this.refs['number-'+split].getValue()}
 | 
								Number: {$set: this.refs['number-'+split].getValue()}
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
		this.setState({
 | 
							this.setState({
 | 
				
			||||||
@@ -221,7 +228,7 @@ const AddEditTransactionModal = React.createClass({
 | 
				
			|||||||
	},
 | 
						},
 | 
				
			||||||
	handleUpdateMemo: function(split) {
 | 
						handleUpdateMemo: function(split) {
 | 
				
			||||||
		var transaction = this.state.transaction;
 | 
							var transaction = this.state.transaction;
 | 
				
			||||||
		transaction.Splits[split] = React.addons.update(transaction.Splits[split], {
 | 
							transaction.Splits[split] = react_update(transaction.Splits[split], {
 | 
				
			||||||
			Memo: {$set: this.refs['memo-'+split].getValue()}
 | 
								Memo: {$set: this.refs['memo-'+split].getValue()}
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
		this.setState({
 | 
							this.setState({
 | 
				
			||||||
@@ -230,7 +237,7 @@ const AddEditTransactionModal = React.createClass({
 | 
				
			|||||||
	},
 | 
						},
 | 
				
			||||||
	handleUpdateAccount: function(account, split) {
 | 
						handleUpdateAccount: function(account, split) {
 | 
				
			||||||
		var transaction = this.state.transaction;
 | 
							var transaction = this.state.transaction;
 | 
				
			||||||
		transaction.Splits[split] = React.addons.update(transaction.Splits[split], {
 | 
							transaction.Splits[split] = react_update(transaction.Splits[split], {
 | 
				
			||||||
			SecurityId: {$set: -1},
 | 
								SecurityId: {$set: -1},
 | 
				
			||||||
			AccountId: {$set: account.AccountId}
 | 
								AccountId: {$set: account.AccountId}
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
@@ -240,7 +247,7 @@ const AddEditTransactionModal = React.createClass({
 | 
				
			|||||||
	},
 | 
						},
 | 
				
			||||||
	handleUpdateAmount: function(split) {
 | 
						handleUpdateAmount: function(split) {
 | 
				
			||||||
		var transaction = this.state.transaction;
 | 
							var transaction = this.state.transaction;
 | 
				
			||||||
		transaction.Splits[split] = React.addons.update(transaction.Splits[split], {
 | 
							transaction.Splits[split] = react_update(transaction.Splits[split], {
 | 
				
			||||||
			Amount: {$set: new Big(this.refs['amount-'+split].getValue())}
 | 
								Amount: {$set: new Big(this.refs['amount-'+split].getValue())}
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
		this.setState({
 | 
							this.setState({
 | 
				
			||||||
@@ -294,7 +301,7 @@ const AddEditTransactionModal = React.createClass({
 | 
				
			|||||||
			var self = this;
 | 
								var self = this;
 | 
				
			||||||
			var s = this.state.transaction.Splits[i];
 | 
								var s = this.state.transaction.Splits[i];
 | 
				
			||||||
			var security = null;
 | 
								var security = null;
 | 
				
			||||||
			var amountValidation = "";
 | 
								var amountValidation = undefined;
 | 
				
			||||||
			var accountValidation = "";
 | 
								var accountValidation = "";
 | 
				
			||||||
			if (s.AccountId in this.props.account_map) {
 | 
								if (s.AccountId in this.props.account_map) {
 | 
				
			||||||
				security = this.props.security_map[this.props.account_map[s.AccountId].SecurityId];
 | 
									security = this.props.security_map[this.props.account_map[s.AccountId].SecurityId];
 | 
				
			||||||
@@ -355,7 +362,7 @@ const AddEditTransactionModal = React.createClass({
 | 
				
			|||||||
					account_map={this.props.account_map}
 | 
										account_map={this.props.account_map}
 | 
				
			||||||
					value={s.AccountId}
 | 
										value={s.AccountId}
 | 
				
			||||||
					includeRoot={false}
 | 
										includeRoot={false}
 | 
				
			||||||
					onSelect={updateAccountFn}
 | 
										onChange={updateAccountFn}
 | 
				
			||||||
					ref={"account-"+i}
 | 
										ref={"account-"+i}
 | 
				
			||||||
					className={accountValidation}/></Col>
 | 
										className={accountValidation}/></Col>
 | 
				
			||||||
				<Col xs={2}><AmountInput type="text"
 | 
									<Col xs={2}><AmountInput type="text"
 | 
				
			||||||
@@ -401,7 +408,7 @@ const AddEditTransactionModal = React.createClass({
 | 
				
			|||||||
						data={TransactionStatusList}
 | 
											data={TransactionStatusList}
 | 
				
			||||||
						valueField='StatusId'
 | 
											valueField='StatusId'
 | 
				
			||||||
						textField='Name'
 | 
											textField='Name'
 | 
				
			||||||
						value={this.state.transaction.Status}
 | 
											defaultValue={this.state.transaction.Status}
 | 
				
			||||||
						onSelect={this.handleStatusChange}
 | 
											onSelect={this.handleStatusChange}
 | 
				
			||||||
						ref="status" />
 | 
											ref="status" />
 | 
				
			||||||
					</Input>
 | 
										</Input>
 | 
				
			||||||
@@ -536,7 +543,7 @@ const ImportTransactionsModal = React.createClass({
 | 
				
			|||||||
			panel = (<Panel header="Successfully Imported Transactions" bsStyle="success">Your import is now complete.</Panel>);
 | 
								panel = (<Panel header="Successfully Imported Transactions" bsStyle="success">Your import is now complete.</Panel>);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		var buttonsDisabled = (this.state.importing) ? "disabled" : "";
 | 
							var buttonsDisabled = (this.state.importing) ? true : false;
 | 
				
			||||||
		var button1 = [];
 | 
							var button1 = [];
 | 
				
			||||||
		var button2 = [];
 | 
							var button2 = [];
 | 
				
			||||||
		if (!this.state.imported && this.state.error == null) {
 | 
							if (!this.state.imported && this.state.error == null) {
 | 
				
			||||||
@@ -545,9 +552,9 @@ const ImportTransactionsModal = React.createClass({
 | 
				
			|||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			button1 = (<Button onClick={this.handleCancel} disabled={buttonsDisabled} bsStyle="success">OK</Button>);
 | 
								button1 = (<Button onClick={this.handleCancel} disabled={buttonsDisabled} bsStyle="success">OK</Button>);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		var inputDisabled = (this.state.importing || this.state.error != null || this.state.imported) ? "disabled" : "";
 | 
							var inputDisabled = (this.state.importing || this.state.error != null || this.state.imported) ? true : false;
 | 
				
			||||||
		return (
 | 
							return (
 | 
				
			||||||
			<Modal show={this.props.show} onHide={this.handleCancel} bsSize="medium">
 | 
								<Modal show={this.props.show} onHide={this.handleCancel} bsSize="small">
 | 
				
			||||||
				<Modal.Header closeButton>
 | 
									<Modal.Header closeButton>
 | 
				
			||||||
					<Modal.Title>Import Transactions</Modal.Title>
 | 
										<Modal.Title>Import Transactions</Modal.Title>
 | 
				
			||||||
				</Modal.Header>
 | 
									</Modal.Header>
 | 
				
			||||||
@@ -577,7 +584,8 @@ const ImportTransactionsModal = React.createClass({
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const AccountRegister = React.createClass({
 | 
					module.exports = React.createClass({
 | 
				
			||||||
 | 
						displayName: "AccountRegister",
 | 
				
			||||||
	getInitialState: function() {
 | 
						getInitialState: function() {
 | 
				
			||||||
		return {
 | 
							return {
 | 
				
			||||||
			importingTransactions: false,
 | 
								importingTransactions: false,
 | 
				
			||||||
@@ -591,7 +599,7 @@ const AccountRegister = React.createClass({
 | 
				
			|||||||
		};
 | 
							};
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	resize: function() {
 | 
						resize: function() {
 | 
				
			||||||
		var div = React.findDOMNode(this);
 | 
							var div = ReactDOM.findDOMNode(this);
 | 
				
			||||||
		this.setState({height: div.parentElement.clientHeight - 64});
 | 
							this.setState({height: div.parentElement.clientHeight - 64});
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	componentDidMount: function() {
 | 
						componentDidMount: function() {
 | 
				
			||||||
@@ -830,7 +838,7 @@ const AccountRegister = React.createClass({
 | 
				
			|||||||
			);
 | 
								);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		var disabled = (this.props.selectedAccount == null) ? "disabled" : "";
 | 
							var disabled = (this.props.selectedAccount == null) ? true : false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return (
 | 
							return (
 | 
				
			||||||
			<div className="transactions-container">
 | 
								<div className="transactions-container">
 | 
				
			||||||
							
								
								
									
										166
									
								
								static/AccountSettingsModal.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										166
									
								
								static/AccountSettingsModal.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,166 @@
 | 
				
			|||||||
 | 
					var React = require('react');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var Modal = require('react-bootstrap').Modal;
 | 
				
			||||||
 | 
					var Button = require('react-bootstrap').Button;
 | 
				
			||||||
 | 
					var ButtonGroup = require('react-bootstrap').ButtonGroup;
 | 
				
			||||||
 | 
					var Input = require('react-bootstrap').Input;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = React.createClass({
 | 
				
			||||||
 | 
						displayName: "AccountSettingsModal",
 | 
				
			||||||
 | 
						_getInitialState: function(props) {
 | 
				
			||||||
 | 
							return {error: "",
 | 
				
			||||||
 | 
								name: props.user.Name,
 | 
				
			||||||
 | 
								username: props.user.Username,
 | 
				
			||||||
 | 
								email: props.user.Email,
 | 
				
			||||||
 | 
								password: BogusPassword,
 | 
				
			||||||
 | 
								confirm_password: BogusPassword,
 | 
				
			||||||
 | 
								passwordChanged: false,
 | 
				
			||||||
 | 
								initial_password: BogusPassword};
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						getInitialState: function() {
 | 
				
			||||||
 | 
							 return this._getInitialState(this.props);
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						componentWillReceiveProps: function(nextProps) {
 | 
				
			||||||
 | 
							if (nextProps.show && !this.props.show) {
 | 
				
			||||||
 | 
								this.setState(this._getInitialState(nextProps));
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						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.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),
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						render: function() {
 | 
				
			||||||
 | 
							return (
 | 
				
			||||||
 | 
								<Modal show={this.props.show} onHide={this.handleCancel} bsSize="large">
 | 
				
			||||||
 | 
									<Modal.Header closeButton>
 | 
				
			||||||
 | 
										<Modal.Title>Edit Account Settings</Modal.Title>
 | 
				
			||||||
 | 
									</Modal.Header>
 | 
				
			||||||
 | 
									<Modal.Body>
 | 
				
			||||||
 | 
									<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/>
 | 
				
			||||||
 | 
									</form>
 | 
				
			||||||
 | 
									</Modal.Body>
 | 
				
			||||||
 | 
									<Modal.Footer>
 | 
				
			||||||
 | 
										<ButtonGroup>
 | 
				
			||||||
 | 
											<Button onClick={this.handleCancel} bsStyle="warning">Cancel</Button>
 | 
				
			||||||
 | 
											<Button onClick={this.handleSubmit} bsStyle="success">Save Settings</Button>
 | 
				
			||||||
 | 
										</ButtonGroup>
 | 
				
			||||||
 | 
									</Modal.Footer>
 | 
				
			||||||
 | 
								</Modal>
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
@@ -1,51 +1,24 @@
 | 
				
			|||||||
// Import all the objects we want to use from ReactBootstrap
 | 
					var React = require('react');
 | 
				
			||||||
var ListGroup = ReactBootstrap.ListGroup;
 | 
					var ReactDOM = require('react-dom');
 | 
				
			||||||
var ListGroupItem = ReactBootstrap.ListGroupItem;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var ReactBootstrap = require('react-bootstrap');
 | 
				
			||||||
var Grid = ReactBootstrap.Grid;
 | 
					var Grid = ReactBootstrap.Grid;
 | 
				
			||||||
var Row = ReactBootstrap.Row;
 | 
					var Row = ReactBootstrap.Row;
 | 
				
			||||||
var Col = ReactBootstrap.Col;
 | 
					var Col = ReactBootstrap.Col;
 | 
				
			||||||
 | 
					var Input = ReactBootstrap.Input;
 | 
				
			||||||
var Button = ReactBootstrap.Button;
 | 
					var Button = ReactBootstrap.Button;
 | 
				
			||||||
var ButtonGroup = ReactBootstrap.ButtonGroup;
 | 
					var ButtonGroup = ReactBootstrap.ButtonGroup;
 | 
				
			||||||
var Glyphicon = ReactBootstrap.Glyphicon;
 | 
					var Glyphicon = ReactBootstrap.Glyphicon;
 | 
				
			||||||
 | 
					var ListGroup = ReactBootstrap.ListGroup;
 | 
				
			||||||
 | 
					var ListGroupItem = ReactBootstrap.ListGroupItem;
 | 
				
			||||||
 | 
					var Collapse = ReactBootstrap.Collapse;
 | 
				
			||||||
 | 
					var Modal = ReactBootstrap.Modal;
 | 
				
			||||||
 | 
					var Collapse = ReactBootstrap.Collapse;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var CollapsibleMixin = ReactBootstrap.CollapsibleMixin;
 | 
					var Combobox = require('react-widgets').Combobox;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var Combobox = ReactWidgets.Combobox;
 | 
					var AccountCombobox = require('./AccountCombobox.js');
 | 
				
			||||||
 | 
					var AccountRegister = require('./AccountRegister.js');
 | 
				
			||||||
const AccountCombobox = React.createClass({
 | 
					 | 
				
			||||||
	getDefaultProps: function() {
 | 
					 | 
				
			||||||
		return {
 | 
					 | 
				
			||||||
			includeRoot: true,
 | 
					 | 
				
			||||||
			rootName: "New Top-level Account"
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	handleAccountChange: function(account) {
 | 
					 | 
				
			||||||
		if (this.props.onSelect != null &&
 | 
					 | 
				
			||||||
				account.hasOwnProperty('AccountId') &&
 | 
					 | 
				
			||||||
				(this.props.account_map.hasOwnProperty([account.AccountId]) ||
 | 
					 | 
				
			||||||
				 account.AccountId == -1)) {
 | 
					 | 
				
			||||||
			this.props.onSelect(account)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	render: function() {
 | 
					 | 
				
			||||||
		var accounts = getAccountDisplayList(this.props.accounts, this.props.includeRoot, this.props.rootName);
 | 
					 | 
				
			||||||
		var className = "";
 | 
					 | 
				
			||||||
		if (this.props.className)
 | 
					 | 
				
			||||||
			className = this.props.className;
 | 
					 | 
				
			||||||
		return (
 | 
					 | 
				
			||||||
			<Combobox
 | 
					 | 
				
			||||||
				data={accounts}
 | 
					 | 
				
			||||||
				valueField='AccountId'
 | 
					 | 
				
			||||||
				textField='Name'
 | 
					 | 
				
			||||||
				value={this.props.value}
 | 
					 | 
				
			||||||
				onSelect={this.handleAccountChange}
 | 
					 | 
				
			||||||
				ref="account"
 | 
					 | 
				
			||||||
				className={className} />
 | 
					 | 
				
			||||||
	   );
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
const AddEditAccountModal = React.createClass({
 | 
					const AddEditAccountModal = React.createClass({
 | 
				
			||||||
	getInitialState: function() {
 | 
						getInitialState: function() {
 | 
				
			||||||
@@ -139,7 +112,7 @@ const AddEditAccountModal = React.createClass({
 | 
				
			|||||||
						account_map={this.props.account_map}
 | 
											account_map={this.props.account_map}
 | 
				
			||||||
						value={this.state.parentaccountid}
 | 
											value={this.state.parentaccountid}
 | 
				
			||||||
						rootName={rootName}
 | 
											rootName={rootName}
 | 
				
			||||||
						onSelect={this.handleParentChange}
 | 
											onChange={this.handleParentChange}
 | 
				
			||||||
						ref="parent" />
 | 
											ref="parent" />
 | 
				
			||||||
					</Input>
 | 
										</Input>
 | 
				
			||||||
					<Input wrapperClassName="wrapper"
 | 
										<Input wrapperClassName="wrapper"
 | 
				
			||||||
@@ -151,7 +124,7 @@ const AddEditAccountModal = React.createClass({
 | 
				
			|||||||
						valueField='SecurityId'
 | 
											valueField='SecurityId'
 | 
				
			||||||
						textField='Name'
 | 
											textField='Name'
 | 
				
			||||||
						value={this.state.security}
 | 
											value={this.state.security}
 | 
				
			||||||
						onSelect={this.handleSecurityChange}
 | 
											onChange={this.handleSecurityChange}
 | 
				
			||||||
						ref="security" />
 | 
											ref="security" />
 | 
				
			||||||
					</Input>
 | 
										</Input>
 | 
				
			||||||
					<Input wrapperClassName="wrapper"
 | 
										<Input wrapperClassName="wrapper"
 | 
				
			||||||
@@ -163,7 +136,7 @@ const AddEditAccountModal = React.createClass({
 | 
				
			|||||||
						valueField='TypeId'
 | 
											valueField='TypeId'
 | 
				
			||||||
						textField='Name'
 | 
											textField='Name'
 | 
				
			||||||
						value={this.state.type}
 | 
											value={this.state.type}
 | 
				
			||||||
						onSelect={this.handleTypeChange}
 | 
											onChange={this.handleTypeChange}
 | 
				
			||||||
						ref="type" />
 | 
											ref="type" />
 | 
				
			||||||
					</Input>
 | 
										</Input>
 | 
				
			||||||
				</form>
 | 
									</form>
 | 
				
			||||||
@@ -179,6 +152,7 @@ const AddEditAccountModal = React.createClass({
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const DeleteAccountModal = React.createClass({
 | 
					const DeleteAccountModal = React.createClass({
 | 
				
			||||||
	getInitialState: function() {
 | 
						getInitialState: function() {
 | 
				
			||||||
		if (this.props.initialAccount != null)
 | 
							if (this.props.initialAccount != null)
 | 
				
			||||||
@@ -263,7 +237,7 @@ const DeleteAccountModal = React.createClass({
 | 
				
			|||||||
						accounts={this.props.accounts}
 | 
											accounts={this.props.accounts}
 | 
				
			||||||
						account_map={this.props.account_map}
 | 
											account_map={this.props.account_map}
 | 
				
			||||||
						value={this.state.accountid}
 | 
											value={this.state.accountid}
 | 
				
			||||||
						onSelect={this.handleChange}/>
 | 
											onChange={this.handleChange}/>
 | 
				
			||||||
					</Input>
 | 
										</Input>
 | 
				
			||||||
					{checkbox}
 | 
										{checkbox}
 | 
				
			||||||
				</form>
 | 
									</form>
 | 
				
			||||||
@@ -280,12 +254,8 @@ const DeleteAccountModal = React.createClass({
 | 
				
			|||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const AccountTreeNode = React.createClass({
 | 
					const AccountTreeNode = React.createClass({
 | 
				
			||||||
	mixins: [CollapsibleMixin],
 | 
						getInitialState: function() {
 | 
				
			||||||
	getCollapsibleDOMNode: function() {
 | 
							return {expanded: false};
 | 
				
			||||||
		return React.findDOMNode(this.refs.children);
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	getCollapsibleDimensionValue: function() {
 | 
					 | 
				
			||||||
		return React.findDOMNode(this.refs.children).scrollHeight;
 | 
					 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	handleToggle: function(e) {
 | 
						handleToggle: function(e) {
 | 
				
			||||||
		e.preventDefault();
 | 
							e.preventDefault();
 | 
				
			||||||
@@ -300,8 +270,7 @@ const AccountTreeNode = React.createClass({
 | 
				
			|||||||
			this.props.onSelect(this.props.account);
 | 
								this.props.onSelect(this.props.account);
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	render: function() {
 | 
						render: function() {
 | 
				
			||||||
		var styles = this.getCollapsibleClassSet();
 | 
							var glyph = this.state.expanded ? 'minus' : 'plus';
 | 
				
			||||||
		var glyph = this.isExpanded() ? 'minus' : 'plus';
 | 
					 | 
				
			||||||
		var active = (this.props.selectedAccount != null &&
 | 
							var active = (this.props.selectedAccount != null &&
 | 
				
			||||||
			this.props.account.AccountId == this.props.selectedAccount.AccountId);
 | 
								this.props.account.AccountId == this.props.selectedAccount.AccountId);
 | 
				
			||||||
		var buttonStyle = active ? "info" : "link";
 | 
							var buttonStyle = active ? "info" : "link";
 | 
				
			||||||
@@ -317,7 +286,7 @@ const AccountTreeNode = React.createClass({
 | 
				
			|||||||
		});
 | 
							});
 | 
				
			||||||
		var accounttreeClasses = "accounttree"
 | 
							var accounttreeClasses = "accounttree"
 | 
				
			||||||
		var expandButton = [];
 | 
							var expandButton = [];
 | 
				
			||||||
		if (children.length > 0)
 | 
							if (children.length > 0) {
 | 
				
			||||||
			expandButton.push((
 | 
								expandButton.push((
 | 
				
			||||||
				<Button onClick={this.handleToggle}
 | 
									<Button onClick={this.handleToggle}
 | 
				
			||||||
						bsSize="xsmall"
 | 
											bsSize="xsmall"
 | 
				
			||||||
@@ -326,8 +295,9 @@ const AccountTreeNode = React.createClass({
 | 
				
			|||||||
					<Glyphicon glyph={glyph} bsSize="xsmall"/>
 | 
										<Glyphicon glyph={glyph} bsSize="xsmall"/>
 | 
				
			||||||
				</Button>
 | 
									</Button>
 | 
				
			||||||
			));
 | 
								));
 | 
				
			||||||
		else
 | 
							} else {
 | 
				
			||||||
			accounttreeClasses += "-nochildren";
 | 
								accounttreeClasses += "-nochildren";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		return (
 | 
							return (
 | 
				
			||||||
			<div className={accounttreeClasses}>
 | 
								<div className={accounttreeClasses}>
 | 
				
			||||||
				{expandButton}
 | 
									{expandButton}
 | 
				
			||||||
@@ -336,9 +306,11 @@ const AccountTreeNode = React.createClass({
 | 
				
			|||||||
						className="accounttree-name">
 | 
											className="accounttree-name">
 | 
				
			||||||
					{this.props.account.Name}
 | 
										{this.props.account.Name}
 | 
				
			||||||
				</Button>
 | 
									</Button>
 | 
				
			||||||
				<div ref='children' className={classNames(styles)}>
 | 
									<Collapse in={this.state.expanded}>
 | 
				
			||||||
					{children}
 | 
										<div>
 | 
				
			||||||
				</div>
 | 
											{children}
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
 | 
									</Collapse>
 | 
				
			||||||
			</div>
 | 
								</div>
 | 
				
			||||||
		);
 | 
							);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -356,7 +328,7 @@ const AccountTree = React.createClass({
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	resize: function() {
 | 
						resize: function() {
 | 
				
			||||||
		var div = React.findDOMNode(this);
 | 
							var div = ReactDOM.findDOMNode(this);
 | 
				
			||||||
		this.setState({height: div.parentElement.clientHeight - 73});
 | 
							this.setState({height: div.parentElement.clientHeight - 73});
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	componentDidMount: function() {
 | 
						componentDidMount: function() {
 | 
				
			||||||
@@ -386,7 +358,8 @@ const AccountTree = React.createClass({
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const AccountsTab = React.createClass({
 | 
					module.exports = React.createClass({
 | 
				
			||||||
 | 
						displayName: "AccountsTab",
 | 
				
			||||||
	getInitialState: function() {
 | 
						getInitialState: function() {
 | 
				
			||||||
		return {
 | 
							return {
 | 
				
			||||||
			selectedAccount: null,
 | 
								selectedAccount: null,
 | 
				
			||||||
@@ -436,7 +409,7 @@ const AccountsTab = React.createClass({
 | 
				
			|||||||
		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 disabled = (this.state.selectedAccount == null) ? "disabled" : "";
 | 
							var disabled = (this.state.selectedAccount == null) ? true : false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return (
 | 
							return (
 | 
				
			||||||
			<Grid fluid className="fullheight"><Row className="fullheight">
 | 
								<Grid fluid className="fullheight"><Row className="fullheight">
 | 
				
			||||||
							
								
								
									
										4
									
								
								static/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								static/Makefile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					all:
 | 
				
			||||||
 | 
						browserify -t [ babelify --presets [ react ] ] main.js -o bundle.js
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PHONY = all
 | 
				
			||||||
							
								
								
									
										324
									
								
								static/MoneyGoApp.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										324
									
								
								static/MoneyGoApp.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,324 @@
 | 
				
			|||||||
 | 
					var React = require('react');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var ReactBootstrap = require('react-bootstrap');
 | 
				
			||||||
 | 
					var Jumbotron = ReactBootstrap.Jumbotron;
 | 
				
			||||||
 | 
					var Tabs = ReactBootstrap.Tabs;
 | 
				
			||||||
 | 
					var Tab = ReactBootstrap.Tab;
 | 
				
			||||||
 | 
					var Modal = ReactBootstrap.Modal;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var TopBar = require('./TopBar.js');
 | 
				
			||||||
 | 
					var NewUserForm = require('./NewUserForm.js');
 | 
				
			||||||
 | 
					var AccountSettingsModal = require('./AccountSettingsModal.js');
 | 
				
			||||||
 | 
					var AccountsTab = require('./AccountsTab.js');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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.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();
 | 
				
			||||||
 | 
									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) {
 | 
				
			||||||
 | 
							this.setState({showAccountSettingsModal: false});
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						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.user.isUser())
 | 
				
			||||||
 | 
									mainContent = (
 | 
				
			||||||
 | 
										<Tabs defaultActiveKey={1}>
 | 
				
			||||||
 | 
											<Tab title="Accounts" eventKey={1} tabClassName="fullheight">
 | 
				
			||||||
 | 
											<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} />
 | 
				
			||||||
 | 
											</Tab>
 | 
				
			||||||
 | 
											<Tab title="Scheduled Transactions" eventKey={2} tabClassName="fullheight">Scheduled transactions go here...</Tab>
 | 
				
			||||||
 | 
											<Tab title="Budgets" eventKey={3} tabClassName="fullheight">Budgets go here...</Tab>
 | 
				
			||||||
 | 
											<Tab title="Reports" eventKey={4} tabClassName="fullheight">Reports go here...</Tab>
 | 
				
			||||||
 | 
										</Tabs>);
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									mainContent = (
 | 
				
			||||||
 | 
										<Jumbotron>
 | 
				
			||||||
 | 
											<center>
 | 
				
			||||||
 | 
												<h1>Money<i>Go</i></h1>
 | 
				
			||||||
 | 
												<p><i>Go</i> manage your money.</p>
 | 
				
			||||||
 | 
											</center>
 | 
				
			||||||
 | 
										</Jumbotron>);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return (
 | 
				
			||||||
 | 
								<div className="fullheight ui">
 | 
				
			||||||
 | 
									<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}
 | 
				
			||||||
 | 
									<AccountSettingsModal
 | 
				
			||||||
 | 
										show={this.state.showAccountSettingsModal}
 | 
				
			||||||
 | 
										user={this.state.user}
 | 
				
			||||||
 | 
										onSubmit={this.handleSettingsSubmitted}
 | 
				
			||||||
 | 
										onCancel={this.handleSettingsCanceled}/>
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
							
								
								
									
										147
									
								
								static/NewUserForm.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										147
									
								
								static/NewUserForm.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,147 @@
 | 
				
			|||||||
 | 
					var React = require('react');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var Panel = require('react-bootstrap').Panel;
 | 
				
			||||||
 | 
					var Input = require('react-bootstrap').Input;
 | 
				
			||||||
 | 
					var Button = require('react-bootstrap').Button;
 | 
				
			||||||
 | 
					var ButtonGroup = require('react-bootstrap').ButtonGroup;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = 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>
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
@@ -1,11 +1,11 @@
 | 
				
			|||||||
// Import all the objects we want to use from ReactBootstrap
 | 
					var React = require('react');
 | 
				
			||||||
var Alert = ReactBootstrap.Alert;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var ReactBootstrap = require('react-bootstrap');
 | 
				
			||||||
 | 
					var Alert = ReactBootstrap.Alert;
 | 
				
			||||||
var Input = ReactBootstrap.Input;
 | 
					var Input = ReactBootstrap.Input;
 | 
				
			||||||
var Button = ReactBootstrap.Button;
 | 
					var Button = ReactBootstrap.Button;
 | 
				
			||||||
var DropdownButton = ReactBootstrap.DropdownButton;
 | 
					var DropdownButton = ReactBootstrap.DropdownButton;
 | 
				
			||||||
var MenuItem = ReactBootstrap.MenuItem;
 | 
					var MenuItem = ReactBootstrap.MenuItem;
 | 
				
			||||||
 | 
					 | 
				
			||||||
var Row = ReactBootstrap.Row;
 | 
					var Row = ReactBootstrap.Row;
 | 
				
			||||||
var Col = ReactBootstrap.Col;
 | 
					var Col = ReactBootstrap.Col;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -62,7 +62,7 @@ const LoginBar = React.createClass({
 | 
				
			|||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const LogoutBar = React.createClass({
 | 
					const LogoutBar = React.createClass({
 | 
				
			||||||
	handleOnSelect: function(key) {
 | 
						handleOnSelect: function(e, key) {
 | 
				
			||||||
		if (key == 1) {
 | 
							if (key == 1) {
 | 
				
			||||||
			if (this.props.onAccountSettings != null)
 | 
								if (this.props.onAccountSettings != null)
 | 
				
			||||||
				this.props.onAccountSettings();
 | 
									this.props.onAccountSettings();
 | 
				
			||||||
@@ -79,7 +79,7 @@ const LogoutBar = React.createClass({
 | 
				
			|||||||
					<Col xs={6}></Col>
 | 
										<Col xs={6}></Col>
 | 
				
			||||||
					<Col xs={4}>
 | 
										<Col xs={4}>
 | 
				
			||||||
						<div className="pull-right">
 | 
											<div className="pull-right">
 | 
				
			||||||
						<DropdownButton title={signedInString} onSelect={this.handleOnSelect} bsStyle="info">
 | 
											<DropdownButton id="logout-settings-dropdown" title={signedInString} onSelect={this.handleOnSelect} bsStyle="info">
 | 
				
			||||||
							<MenuItem eventKey="1">Account Settings</MenuItem>
 | 
												<MenuItem eventKey="1">Account Settings</MenuItem>
 | 
				
			||||||
							<MenuItem eventKey="2">Logout</MenuItem>
 | 
												<MenuItem eventKey="2">Logout</MenuItem>
 | 
				
			||||||
						</DropdownButton>
 | 
											</DropdownButton>
 | 
				
			||||||
@@ -91,7 +91,8 @@ const LogoutBar = React.createClass({
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const TopBar = React.createClass({
 | 
					module.exports = React.createClass({
 | 
				
			||||||
 | 
						displayName: "TopBar",
 | 
				
			||||||
	render: function() {
 | 
						render: function() {
 | 
				
			||||||
		var barContents;
 | 
							var barContents;
 | 
				
			||||||
		var errorAlert;
 | 
							var errorAlert;
 | 
				
			||||||
							
								
								
									
										
											BIN
										
									
								
								static/external/fonts/rw-widgets.eot
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								static/external/fonts/rw-widgets.eot
									
									
									
									
										vendored
									
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										18
									
								
								static/external/fonts/rw-widgets.svg
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										18
									
								
								static/external/fonts/rw-widgets.svg
									
									
									
									
										vendored
									
									
								
							@@ -1,18 +0,0 @@
 | 
				
			|||||||
<?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) 2015 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="m571 171q0-14-10-25t-25-10h-500q-15 0-25 10t-11 25 11 26l250 250q10 10 25 10t25-10l250-250q10-11 10-26z" horiz-adv-x="571.4" />
 | 
					 | 
				
			||||||
<glyph glyph-name="left-dir" unicode="" d="m357 600v-500q0-14-10-25t-26-11-25 11l-250 250q-10 11-10 25t10 25l250 250q11 11 25 11t26-11 10-25z" horiz-adv-x="357.1" />
 | 
					 | 
				
			||||||
<glyph glyph-name="right-dir" unicode="" d="m321 350q0-14-10-25l-250-250q-11-11-25-11t-25 11-11 25v500q0 15 11 25t25 11 25-11l250-250q10-10 10-25z" horiz-adv-x="357.1" />
 | 
					 | 
				
			||||||
<glyph glyph-name="down-dir" unicode="" d="m571 457q0-14-10-25l-250-250q-11-11-25-11t-25 11l-250 250q-11 11-11 25t11 25 25 11h500q14 0 25-11t10-25z" horiz-adv-x="571.4" />
 | 
					 | 
				
			||||||
<glyph glyph-name="calendar" unicode="" d="m71-79h161v161h-161v-161z m197 0h178v161h-178v-161z m-197 197h161v178h-161v-178z m197 0h178v178h-178v-178z m-197 214h161v161h-161v-161z m411-411h179v161h-179v-161z m-214 411h178v161h-178v-161z m428-411h161v161h-161v-161z m-214 197h179v178h-179v-178z m-196 482v161q0 7-6 12t-12 6h-36q-7 0-12-6t-6-12v-161q0-7 6-13t12-5h36q7 0 12 5t6 13z m410-482h161v178h-161v-178z m-214 214h179v161h-179v-161z m214 0h161v161h-161v-161z m18 268v161q0 7-5 12t-13 6h-35q-8 0-13-6t-5-12v-161q0-7 5-13t13-5h35q8 0 13 5t5 13z m215 36v-715q0-29-22-50t-50-21h-786q-29 0-50 21t-21 50v715q0 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-50z" horiz-adv-x="928.6" />
 | 
					 | 
				
			||||||
<glyph glyph-name="clock" unicode="" d="m500 546v-250q0-7-5-12t-13-5h-178q-8 0-13 5t-5 12v36q0 8 5 13t13 5h125v196q0 8 5 13t12 5h36q8 0 13-5t5-13z m232-196q0 83-41 152t-110 111-152 41-153-41-110-111-41-152 41-152 110-111 153-41 152 41 110 111 41 152z m125 0q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
 | 
					 | 
				
			||||||
<glyph glyph-name="search" unicode="" d="m643 386q0 103-74 176t-176 74-177-74-73-176 73-177 177-73 176 73 74 177z m286-465q0-29-22-50t-50-21q-30 0-50 21l-191 191q-100-69-223-69-80 0-153 31t-125 84-84 125-31 153 31 152 84 126 125 84 153 31 152-31 126-84 84-126 31-152q0-123-69-223l191-191q21-21 21-51z" horiz-adv-x="928.6" />
 | 
					 | 
				
			||||||
</font>
 | 
					 | 
				
			||||||
</defs>
 | 
					 | 
				
			||||||
</svg>
 | 
					 | 
				
			||||||
| 
		 Before Width: | Height: | Size: 2.6 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								static/external/fonts/rw-widgets.ttf
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								static/external/fonts/rw-widgets.ttf
									
									
									
									
										vendored
									
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								static/external/fonts/rw-widgets.woff
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								static/external/fonts/rw-widgets.woff
									
									
									
									
										vendored
									
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										307
									
								
								static/external/react-widgets/core.css
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										307
									
								
								static/external/react-widgets/core.css
									
									
									
									
										vendored
									
									
								
							@@ -1,307 +0,0 @@
 | 
				
			|||||||
/* for debugging */
 | 
					 | 
				
			||||||
.rw-widget {
 | 
					 | 
				
			||||||
  outline: 0;
 | 
					 | 
				
			||||||
  -moz-background-clip: border-box;
 | 
					 | 
				
			||||||
  -webkit-background-clip: border-box;
 | 
					 | 
				
			||||||
  background-clip: border-box;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-btn {
 | 
					 | 
				
			||||||
  color: #333333;
 | 
					 | 
				
			||||||
  line-height: 2.286em;
 | 
					 | 
				
			||||||
  display: inline-block;
 | 
					 | 
				
			||||||
  margin: 0;
 | 
					 | 
				
			||||||
  text-align: center;
 | 
					 | 
				
			||||||
  vertical-align: middle;
 | 
					 | 
				
			||||||
  background: none;
 | 
					 | 
				
			||||||
  background-image: none;
 | 
					 | 
				
			||||||
  border: 1px solid transparent;
 | 
					 | 
				
			||||||
  padding: 0;
 | 
					 | 
				
			||||||
  white-space: nowrap;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-rtl {
 | 
					 | 
				
			||||||
  direction: rtl;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-input {
 | 
					 | 
				
			||||||
  color: #555555;
 | 
					 | 
				
			||||||
  height: 2.286em;
 | 
					 | 
				
			||||||
  line-height: 2.286em;
 | 
					 | 
				
			||||||
  padding: 0.429em 0.857em;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-input[disabled] {
 | 
					 | 
				
			||||||
  -webkit-box-shadow: none;
 | 
					 | 
				
			||||||
  box-shadow: none;
 | 
					 | 
				
			||||||
  cursor: not-allowed;
 | 
					 | 
				
			||||||
  opacity: 1;
 | 
					 | 
				
			||||||
  background-color: #eeeeee;
 | 
					 | 
				
			||||||
  border-color: #cccccc;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-input[readonly] {
 | 
					 | 
				
			||||||
  cursor: not-allowed;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-i.rw-loading {
 | 
					 | 
				
			||||||
  background: url("../img/loading.gif") no-repeat center;
 | 
					 | 
				
			||||||
  width: 16px;
 | 
					 | 
				
			||||||
  height: 100%;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-i.rw-loading:before {
 | 
					 | 
				
			||||||
  content: "";
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-loading-mask {
 | 
					 | 
				
			||||||
  border-radius: 4px;
 | 
					 | 
				
			||||||
  position: relative;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-loading-mask:after {
 | 
					 | 
				
			||||||
  content: '';
 | 
					 | 
				
			||||||
  background: url("../img/loader-big.gif") no-repeat center;
 | 
					 | 
				
			||||||
  position: absolute;
 | 
					 | 
				
			||||||
  background-color: #fff;
 | 
					 | 
				
			||||||
  opacity: 0.7;
 | 
					 | 
				
			||||||
  top: 0;
 | 
					 | 
				
			||||||
  left: 0;
 | 
					 | 
				
			||||||
  height: 100%;
 | 
					 | 
				
			||||||
  width: 100%;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-now {
 | 
					 | 
				
			||||||
  font-weight: 600;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-state-focus {
 | 
					 | 
				
			||||||
  background-color: #ffffff;
 | 
					 | 
				
			||||||
  border: #66afe9 1px solid;
 | 
					 | 
				
			||||||
  color: #333333;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-state-selected {
 | 
					 | 
				
			||||||
  background-color: #adadad;
 | 
					 | 
				
			||||||
  border: #adadad 1px solid;
 | 
					 | 
				
			||||||
  color: #333333;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-state-disabled {
 | 
					 | 
				
			||||||
  -webkit-box-shadow: none;
 | 
					 | 
				
			||||||
  box-shadow: none;
 | 
					 | 
				
			||||||
  cursor: not-allowed;
 | 
					 | 
				
			||||||
  opacity: 1;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-btn,
 | 
					 | 
				
			||||||
.rw-dropdownlist {
 | 
					 | 
				
			||||||
  cursor: pointer;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-btn[disabled],
 | 
					 | 
				
			||||||
.rw-state-disabled .rw-btn,
 | 
					 | 
				
			||||||
.rw-state-readonly .rw-btn {
 | 
					 | 
				
			||||||
  -webkit-box-shadow: none;
 | 
					 | 
				
			||||||
  box-shadow: none;
 | 
					 | 
				
			||||||
  pointer-events: none;
 | 
					 | 
				
			||||||
  cursor: not-allowed;
 | 
					 | 
				
			||||||
  filter: alpha(opacity=65);
 | 
					 | 
				
			||||||
  opacity: .65;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
ul.rw-list,
 | 
					 | 
				
			||||||
ul.rw-selectlist {
 | 
					 | 
				
			||||||
  margin: 0;
 | 
					 | 
				
			||||||
  padding-left: 0;
 | 
					 | 
				
			||||||
  list-style: none;
 | 
					 | 
				
			||||||
  padding: 5px 0;
 | 
					 | 
				
			||||||
  overflow: auto;
 | 
					 | 
				
			||||||
  outline: 0;
 | 
					 | 
				
			||||||
  height: 100%;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
ul.rw-list > li.rw-list-optgroup,
 | 
					 | 
				
			||||||
ul.rw-selectlist > li.rw-list-optgroup {
 | 
					 | 
				
			||||||
  font-weight: bold;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
ul.rw-list > li.rw-list-option,
 | 
					 | 
				
			||||||
ul.rw-selectlist > li.rw-list-option {
 | 
					 | 
				
			||||||
  cursor: pointer;
 | 
					 | 
				
			||||||
  border: 1px solid transparent;
 | 
					 | 
				
			||||||
  padding-left: 10px;
 | 
					 | 
				
			||||||
  padding-right: 10px;
 | 
					 | 
				
			||||||
  border-radius: 3px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
ul.rw-list > li.rw-list-option:hover,
 | 
					 | 
				
			||||||
ul.rw-selectlist > li.rw-list-option:hover {
 | 
					 | 
				
			||||||
  background-color: #e6e6e6;
 | 
					 | 
				
			||||||
  border-color: #adadad;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
ul.rw-list > li.rw-list-option.rw-state-focus,
 | 
					 | 
				
			||||||
ul.rw-selectlist > li.rw-list-option.rw-state-focus {
 | 
					 | 
				
			||||||
  background-color: #ffffff;
 | 
					 | 
				
			||||||
  border: #66afe9 1px solid;
 | 
					 | 
				
			||||||
  color: #333333;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
ul.rw-list > li.rw-list-option.rw-state-selected,
 | 
					 | 
				
			||||||
ul.rw-selectlist > li.rw-list-option.rw-state-selected {
 | 
					 | 
				
			||||||
  background-color: #adadad;
 | 
					 | 
				
			||||||
  border: #adadad 1px solid;
 | 
					 | 
				
			||||||
  color: #333333;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
ul.rw-list.rw-list-grouped > li.rw-list-optgroup {
 | 
					 | 
				
			||||||
  padding-left: 10px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
ul.rw-list.rw-list-grouped > li.rw-list-option {
 | 
					 | 
				
			||||||
  padding-left: 20px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-widget {
 | 
					 | 
				
			||||||
  position: relative;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-open.rw-widget,
 | 
					 | 
				
			||||||
.rw-open > .rw-multiselect-wrapper {
 | 
					 | 
				
			||||||
  border-bottom-right-radius: 0;
 | 
					 | 
				
			||||||
  border-bottom-left-radius: 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-open-up.rw-widget,
 | 
					 | 
				
			||||||
.rw-open-up > .rw-multiselect-wrapper {
 | 
					 | 
				
			||||||
  border-top-right-radius: 0;
 | 
					 | 
				
			||||||
  border-top-left-radius: 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-combobox .rw-list,
 | 
					 | 
				
			||||||
.rw-datetimepicker .rw-list,
 | 
					 | 
				
			||||||
.rw-numberpicker .rw-list,
 | 
					 | 
				
			||||||
.rw-dropdownlist .rw-list,
 | 
					 | 
				
			||||||
.rw-multiselect .rw-list {
 | 
					 | 
				
			||||||
  max-height: 200px;
 | 
					 | 
				
			||||||
  height: auto;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-widget {
 | 
					 | 
				
			||||||
  background-color: #ffffff;
 | 
					 | 
				
			||||||
  border: #cccccc 1px solid;
 | 
					 | 
				
			||||||
  border-radius: 4px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-widget .rw-input {
 | 
					 | 
				
			||||||
  border-bottom-left-radius: 4px;
 | 
					 | 
				
			||||||
  border-top-left-radius: 4px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-rtl.rw-widget .rw-input {
 | 
					 | 
				
			||||||
  border-bottom-left-radius: 0;
 | 
					 | 
				
			||||||
  border-top-left-radius: 0;
 | 
					 | 
				
			||||||
  border-bottom-right-radius: 4px;
 | 
					 | 
				
			||||||
  border-top-right-radius: 4px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-widget > .rw-select {
 | 
					 | 
				
			||||||
  border-left: #cccccc 1px solid;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-rtl.rw-widget > .rw-select {
 | 
					 | 
				
			||||||
  border-right: #cccccc 1px solid;
 | 
					 | 
				
			||||||
  border-left: none;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-widget.rw-state-focus,
 | 
					 | 
				
			||||||
.rw-widget.rw-state-focus:hover {
 | 
					 | 
				
			||||||
  -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
 | 
					 | 
				
			||||||
  box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
 | 
					 | 
				
			||||||
  border-color: #66afe9;
 | 
					 | 
				
			||||||
  outline: 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-widget.rw-state-readonly,
 | 
					 | 
				
			||||||
.rw-widget.rw-state-readonly > .rw-multiselect-wrapper {
 | 
					 | 
				
			||||||
  cursor: not-allowed;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-widget.rw-state-disabled,
 | 
					 | 
				
			||||||
.rw-widget.rw-state-disabled:hover,
 | 
					 | 
				
			||||||
.rw-widget.rw-state-disabled:active {
 | 
					 | 
				
			||||||
  -webkit-box-shadow: none;
 | 
					 | 
				
			||||||
  box-shadow: none;
 | 
					 | 
				
			||||||
  background-color: #eeeeee;
 | 
					 | 
				
			||||||
  border-color: #cccccc;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-combobox,
 | 
					 | 
				
			||||||
.rw-datetimepicker,
 | 
					 | 
				
			||||||
.rw-numberpicker,
 | 
					 | 
				
			||||||
.rw-dropdownlist {
 | 
					 | 
				
			||||||
  padding-right: 1.9em;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-combobox.rw-rtl,
 | 
					 | 
				
			||||||
.rw-datetimepicker.rw-rtl,
 | 
					 | 
				
			||||||
.rw-numberpicker.rw-rtl,
 | 
					 | 
				
			||||||
.rw-dropdownlist.rw-rtl {
 | 
					 | 
				
			||||||
  padding-right: 0;
 | 
					 | 
				
			||||||
  padding-left: 1.9em;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-combobox > .rw-input,
 | 
					 | 
				
			||||||
.rw-datetimepicker > .rw-input,
 | 
					 | 
				
			||||||
.rw-numberpicker > .rw-input,
 | 
					 | 
				
			||||||
.rw-dropdownlist > .rw-input {
 | 
					 | 
				
			||||||
  width: 100%;
 | 
					 | 
				
			||||||
  border: none;
 | 
					 | 
				
			||||||
  outline: 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-combobox > .rw-input::-moz-placeholder,
 | 
					 | 
				
			||||||
.rw-datetimepicker > .rw-input::-moz-placeholder,
 | 
					 | 
				
			||||||
.rw-numberpicker > .rw-input::-moz-placeholder,
 | 
					 | 
				
			||||||
.rw-dropdownlist > .rw-input::-moz-placeholder {
 | 
					 | 
				
			||||||
  color: #999999;
 | 
					 | 
				
			||||||
  opacity: 1;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-combobox > .rw-input:-ms-input-placeholder,
 | 
					 | 
				
			||||||
.rw-datetimepicker > .rw-input:-ms-input-placeholder,
 | 
					 | 
				
			||||||
.rw-numberpicker > .rw-input:-ms-input-placeholder,
 | 
					 | 
				
			||||||
.rw-dropdownlist > .rw-input:-ms-input-placeholder {
 | 
					 | 
				
			||||||
  color: #999999;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-combobox > .rw-input::-webkit-input-placeholder,
 | 
					 | 
				
			||||||
.rw-datetimepicker > .rw-input::-webkit-input-placeholder,
 | 
					 | 
				
			||||||
.rw-numberpicker > .rw-input::-webkit-input-placeholder,
 | 
					 | 
				
			||||||
.rw-dropdownlist > .rw-input::-webkit-input-placeholder {
 | 
					 | 
				
			||||||
  color: #999999;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-select {
 | 
					 | 
				
			||||||
  position: absolute;
 | 
					 | 
				
			||||||
  width: 1.9em;
 | 
					 | 
				
			||||||
  height: 100%;
 | 
					 | 
				
			||||||
  right: 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-select.rw-btn,
 | 
					 | 
				
			||||||
.rw-select > .rw-btn {
 | 
					 | 
				
			||||||
  height: 100%;
 | 
					 | 
				
			||||||
  vertical-align: middle;
 | 
					 | 
				
			||||||
  outline: 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-rtl .rw-select {
 | 
					 | 
				
			||||||
  left: 0;
 | 
					 | 
				
			||||||
  right: auto;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-multiselect,
 | 
					 | 
				
			||||||
.rw-combobox input.rw-input,
 | 
					 | 
				
			||||||
.rw-datetimepicker input.rw-input,
 | 
					 | 
				
			||||||
.rw-numberpicker input.rw-input {
 | 
					 | 
				
			||||||
  -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075);
 | 
					 | 
				
			||||||
  box-shadow: inset 0 1px 1px rgba(0,0,0,.075);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-combobox:active,
 | 
					 | 
				
			||||||
.rw-datetimepicker:active,
 | 
					 | 
				
			||||||
.rw-dropdownlist:active,
 | 
					 | 
				
			||||||
.rw-header > .rw-btn:active,
 | 
					 | 
				
			||||||
.rw-numberpicker .rw-btn.rw-state-active,
 | 
					 | 
				
			||||||
.rw-combobox:active.rw-state-focus,
 | 
					 | 
				
			||||||
.rw-datetimepicker:active.rw-state-focus,
 | 
					 | 
				
			||||||
.rw-dropdownlist:active.rw-state-focus,
 | 
					 | 
				
			||||||
.rw-header > .rw-btn:active.rw-state-focus,
 | 
					 | 
				
			||||||
.rw-numberpicker .rw-btn.rw-state-active.rw-state-focus {
 | 
					 | 
				
			||||||
  background-image: none;
 | 
					 | 
				
			||||||
  -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
 | 
					 | 
				
			||||||
  box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-combobox:hover,
 | 
					 | 
				
			||||||
.rw-datetimepicker:hover,
 | 
					 | 
				
			||||||
.rw-numberpicker:hover,
 | 
					 | 
				
			||||||
.rw-dropdownlist:hover {
 | 
					 | 
				
			||||||
  background-color: #e6e6e6;
 | 
					 | 
				
			||||||
  border-color: #adadad;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-dropdownlist.rw-state-disabled,
 | 
					 | 
				
			||||||
.rw-dropdownlist.rw-state-readonly {
 | 
					 | 
				
			||||||
  cursor: not-allowed;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-dropdownlist > .rw-input {
 | 
					 | 
				
			||||||
  background-color: transparent;
 | 
					 | 
				
			||||||
  padding-top: 0;
 | 
					 | 
				
			||||||
  padding-bottom: 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-dropdownlist > .rw-select,
 | 
					 | 
				
			||||||
.rw-dropdownlist > .rw-select.rw-rtl {
 | 
					 | 
				
			||||||
  border-width: 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-numberpicker .rw-btn {
 | 
					 | 
				
			||||||
  display: block;
 | 
					 | 
				
			||||||
  height: 1.143em;
 | 
					 | 
				
			||||||
  line-height: 1.143em;
 | 
					 | 
				
			||||||
  width: 100%;
 | 
					 | 
				
			||||||
  border-width: 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										
											BIN
										
									
								
								static/external/react-widgets/loader-big.gif
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								static/external/react-widgets/loader-big.gif
									
									
									
									
										vendored
									
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 23 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								static/external/react-widgets/loading.gif
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								static/external/react-widgets/loading.gif
									
									
									
									
										vendored
									
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 673 B  | 
							
								
								
									
										730
									
								
								static/external/react-widgets/react-widgets.css
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										730
									
								
								static/external/react-widgets/react-widgets.css
									
									
									
									
										vendored
									
									
								
							@@ -1,730 +0,0 @@
 | 
				
			|||||||
/* Noramlize.css */
 | 
					 | 
				
			||||||
.rw-btn,
 | 
					 | 
				
			||||||
.rw-input {
 | 
					 | 
				
			||||||
  color: inherit;
 | 
					 | 
				
			||||||
  font: inherit;
 | 
					 | 
				
			||||||
  margin: 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
button.rw-input {
 | 
					 | 
				
			||||||
  overflow: visible;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
button.rw-input,
 | 
					 | 
				
			||||||
select.rw-input {
 | 
					 | 
				
			||||||
  text-transform: none;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
button.rw-input,
 | 
					 | 
				
			||||||
html input[type="button"].rw-input,
 | 
					 | 
				
			||||||
input[type="reset"].rw-input,
 | 
					 | 
				
			||||||
input[type="submit"].rw-input {
 | 
					 | 
				
			||||||
  -webkit-appearance: button;
 | 
					 | 
				
			||||||
  cursor: pointer;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
button[disabled].rw-input,
 | 
					 | 
				
			||||||
html input[disabled].rw-input {
 | 
					 | 
				
			||||||
  cursor: not-allowed;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
button.rw-input::-moz-focus-inner,
 | 
					 | 
				
			||||||
input.rw-input::-moz-focus-inner {
 | 
					 | 
				
			||||||
  border: 0;
 | 
					 | 
				
			||||||
  padding: 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
/* -------------- */
 | 
					 | 
				
			||||||
.rw-sr {
 | 
					 | 
				
			||||||
  position: absolute;
 | 
					 | 
				
			||||||
  width: 1px;
 | 
					 | 
				
			||||||
  height: 1px;
 | 
					 | 
				
			||||||
  margin: -1px;
 | 
					 | 
				
			||||||
  padding: 0;
 | 
					 | 
				
			||||||
  overflow: hidden;
 | 
					 | 
				
			||||||
  clip: rect(0, 0, 0, 0);
 | 
					 | 
				
			||||||
  border: 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-widget,
 | 
					 | 
				
			||||||
.rw-widget * {
 | 
					 | 
				
			||||||
  -webkit-box-sizing: border-box;
 | 
					 | 
				
			||||||
  -moz-box-sizing: border-box;
 | 
					 | 
				
			||||||
  box-sizing: border-box;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-widget:before,
 | 
					 | 
				
			||||||
.rw-widget *:before,
 | 
					 | 
				
			||||||
.rw-widget:after,
 | 
					 | 
				
			||||||
.rw-widget *:after {
 | 
					 | 
				
			||||||
  -webkit-box-sizing: border-box;
 | 
					 | 
				
			||||||
  -moz-box-sizing: border-box;
 | 
					 | 
				
			||||||
  box-sizing: border-box;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@font-face {
 | 
					 | 
				
			||||||
  font-family: 'RwWidgets';
 | 
					 | 
				
			||||||
  src: url('../fonts/rw-widgets.eot?v=4.1.0');
 | 
					 | 
				
			||||||
  src: url('../fonts/rw-widgets.eot?#iefix&v=4.1.0') format('embedded-opentype'), url('../fonts/rw-widgets.woff?v=4.1.0') format('woff'), url('../fonts/rw-widgets.ttf?v=4.1.0') format('truetype'), url('../fonts/rw-widgets.svg?v=4.1.0#fontawesomeregular') format('svg');
 | 
					 | 
				
			||||||
  font-weight: normal;
 | 
					 | 
				
			||||||
  font-style: normal;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-i {
 | 
					 | 
				
			||||||
  display: inline-block;
 | 
					 | 
				
			||||||
  font-family: RwWidgets;
 | 
					 | 
				
			||||||
  font-style: normal;
 | 
					 | 
				
			||||||
  font-weight: normal;
 | 
					 | 
				
			||||||
  line-height: 1em;
 | 
					 | 
				
			||||||
  font-variant: normal;
 | 
					 | 
				
			||||||
  text-transform: none;
 | 
					 | 
				
			||||||
  -webkit-font-smoothing: antialiased;
 | 
					 | 
				
			||||||
  -moz-osx-font-smoothing: grayscale;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-i-caret-down:before {
 | 
					 | 
				
			||||||
  content: '\e803';
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-i-caret-up:before {
 | 
					 | 
				
			||||||
  content: '\e800';
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-i-caret-left:before {
 | 
					 | 
				
			||||||
  content: '\e801';
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-i-caret-right:before {
 | 
					 | 
				
			||||||
  content: '\e802';
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-i-clock-o:before {
 | 
					 | 
				
			||||||
  content: '\e805';
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-i-calendar:before {
 | 
					 | 
				
			||||||
  content: '\e804';
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-i-search:before {
 | 
					 | 
				
			||||||
  content: '\e806';
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
/* for debugging */
 | 
					 | 
				
			||||||
.rw-widget {
 | 
					 | 
				
			||||||
  outline: 0;
 | 
					 | 
				
			||||||
  -moz-background-clip: border-box;
 | 
					 | 
				
			||||||
  -webkit-background-clip: border-box;
 | 
					 | 
				
			||||||
  background-clip: border-box;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-btn {
 | 
					 | 
				
			||||||
  color: #333333;
 | 
					 | 
				
			||||||
  line-height: 2.286em;
 | 
					 | 
				
			||||||
  display: inline-block;
 | 
					 | 
				
			||||||
  margin: 0;
 | 
					 | 
				
			||||||
  text-align: center;
 | 
					 | 
				
			||||||
  vertical-align: middle;
 | 
					 | 
				
			||||||
  background: none;
 | 
					 | 
				
			||||||
  background-image: none;
 | 
					 | 
				
			||||||
  border: 1px solid transparent;
 | 
					 | 
				
			||||||
  padding: 0;
 | 
					 | 
				
			||||||
  white-space: nowrap;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-rtl {
 | 
					 | 
				
			||||||
  direction: rtl;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-input {
 | 
					 | 
				
			||||||
  color: #555555;
 | 
					 | 
				
			||||||
  height: 2.286em;
 | 
					 | 
				
			||||||
  padding: 0.429em 0.857em;
 | 
					 | 
				
			||||||
  background-color: #ffffff;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-input[disabled] {
 | 
					 | 
				
			||||||
  -webkit-box-shadow: none;
 | 
					 | 
				
			||||||
  box-shadow: none;
 | 
					 | 
				
			||||||
  cursor: not-allowed;
 | 
					 | 
				
			||||||
  opacity: 1;
 | 
					 | 
				
			||||||
  background-color: #eeeeee;
 | 
					 | 
				
			||||||
  border-color: #cccccc;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-input[readonly] {
 | 
					 | 
				
			||||||
  cursor: not-allowed;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-filter-input {
 | 
					 | 
				
			||||||
  position: relative;
 | 
					 | 
				
			||||||
  width: 100%;
 | 
					 | 
				
			||||||
  padding-right: 1.9em;
 | 
					 | 
				
			||||||
  border: #cccccc 1px solid;
 | 
					 | 
				
			||||||
  border-radius: 4px;
 | 
					 | 
				
			||||||
  margin-bottom: 2px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-rtl .rw-filter-input {
 | 
					 | 
				
			||||||
  padding-left: 1.9em;
 | 
					 | 
				
			||||||
  padding-right: 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-filter-input > .rw-input {
 | 
					 | 
				
			||||||
  width: 100%;
 | 
					 | 
				
			||||||
  border: none;
 | 
					 | 
				
			||||||
  outline: none;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-filter-input > span {
 | 
					 | 
				
			||||||
  margin-top: -2px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-i.rw-loading {
 | 
					 | 
				
			||||||
  background: url("../img/loading.gif") no-repeat center;
 | 
					 | 
				
			||||||
  width: 16px;
 | 
					 | 
				
			||||||
  height: 100%;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-i.rw-loading:before {
 | 
					 | 
				
			||||||
  content: "";
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-loading-mask {
 | 
					 | 
				
			||||||
  border-radius: 4px;
 | 
					 | 
				
			||||||
  position: relative;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-loading-mask:after {
 | 
					 | 
				
			||||||
  content: '';
 | 
					 | 
				
			||||||
  background: url("../img/loader-big.gif") no-repeat center;
 | 
					 | 
				
			||||||
  position: absolute;
 | 
					 | 
				
			||||||
  background-color: #fff;
 | 
					 | 
				
			||||||
  opacity: 0.7;
 | 
					 | 
				
			||||||
  top: 0;
 | 
					 | 
				
			||||||
  left: 0;
 | 
					 | 
				
			||||||
  height: 100%;
 | 
					 | 
				
			||||||
  width: 100%;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-now {
 | 
					 | 
				
			||||||
  font-weight: 600;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-state-focus {
 | 
					 | 
				
			||||||
  background-color: #ffffff;
 | 
					 | 
				
			||||||
  border: #66afe9 1px solid;
 | 
					 | 
				
			||||||
  color: #333333;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-state-selected {
 | 
					 | 
				
			||||||
  background-color: #adadad;
 | 
					 | 
				
			||||||
  border: #adadad 1px solid;
 | 
					 | 
				
			||||||
  color: #333333;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-state-disabled {
 | 
					 | 
				
			||||||
  -webkit-box-shadow: none;
 | 
					 | 
				
			||||||
  box-shadow: none;
 | 
					 | 
				
			||||||
  cursor: not-allowed;
 | 
					 | 
				
			||||||
  opacity: 1;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-btn,
 | 
					 | 
				
			||||||
.rw-dropdownlist {
 | 
					 | 
				
			||||||
  cursor: pointer;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-btn[disabled],
 | 
					 | 
				
			||||||
.rw-state-disabled .rw-btn,
 | 
					 | 
				
			||||||
.rw-state-readonly .rw-btn {
 | 
					 | 
				
			||||||
  -webkit-box-shadow: none;
 | 
					 | 
				
			||||||
  box-shadow: none;
 | 
					 | 
				
			||||||
  pointer-events: none;
 | 
					 | 
				
			||||||
  cursor: not-allowed;
 | 
					 | 
				
			||||||
  filter: alpha(opacity=65);
 | 
					 | 
				
			||||||
  opacity: .65;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
ul.rw-list,
 | 
					 | 
				
			||||||
.rw-selectlist {
 | 
					 | 
				
			||||||
  margin: 0;
 | 
					 | 
				
			||||||
  padding-left: 0;
 | 
					 | 
				
			||||||
  list-style: none;
 | 
					 | 
				
			||||||
  padding: 5px 0;
 | 
					 | 
				
			||||||
  overflow: auto;
 | 
					 | 
				
			||||||
  outline: 0;
 | 
					 | 
				
			||||||
  height: 100%;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
ul.rw-list > li,
 | 
					 | 
				
			||||||
.rw-selectlist > li {
 | 
					 | 
				
			||||||
  -webkit-touch-callout: none;
 | 
					 | 
				
			||||||
  -webkit-user-select: none;
 | 
					 | 
				
			||||||
  -moz-user-select: none;
 | 
					 | 
				
			||||||
  -ms-user-select: none;
 | 
					 | 
				
			||||||
  user-select: none;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
ul.rw-list > li.rw-list-optgroup,
 | 
					 | 
				
			||||||
.rw-selectlist > li.rw-list-optgroup {
 | 
					 | 
				
			||||||
  font-weight: bold;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
ul.rw-list > li.rw-list-option,
 | 
					 | 
				
			||||||
ul.rw-list > li.rw-list-empty,
 | 
					 | 
				
			||||||
.rw-selectlist > li.rw-list-option,
 | 
					 | 
				
			||||||
.rw-selectlist > li.rw-list-empty {
 | 
					 | 
				
			||||||
  padding-left: 10px;
 | 
					 | 
				
			||||||
  padding-right: 10px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
ul.rw-list > li.rw-list-option,
 | 
					 | 
				
			||||||
.rw-selectlist > li.rw-list-option {
 | 
					 | 
				
			||||||
  cursor: pointer;
 | 
					 | 
				
			||||||
  border: 1px solid transparent;
 | 
					 | 
				
			||||||
  border-radius: 3px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
ul.rw-list > li.rw-list-option:hover,
 | 
					 | 
				
			||||||
.rw-selectlist > li.rw-list-option:hover {
 | 
					 | 
				
			||||||
  background-color: #e6e6e6;
 | 
					 | 
				
			||||||
  border-color: #adadad;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
ul.rw-list > li.rw-list-option.rw-state-focus,
 | 
					 | 
				
			||||||
.rw-selectlist > li.rw-list-option.rw-state-focus {
 | 
					 | 
				
			||||||
  background-color: #ffffff;
 | 
					 | 
				
			||||||
  border: #66afe9 1px solid;
 | 
					 | 
				
			||||||
  color: #333333;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
ul.rw-list > li.rw-list-option.rw-state-selected,
 | 
					 | 
				
			||||||
.rw-selectlist > li.rw-list-option.rw-state-selected {
 | 
					 | 
				
			||||||
  background-color: #adadad;
 | 
					 | 
				
			||||||
  border: #adadad 1px solid;
 | 
					 | 
				
			||||||
  color: #333333;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
ul.rw-list.rw-list-grouped > li.rw-list-optgroup,
 | 
					 | 
				
			||||||
.rw-selectlist.rw-list-grouped > li.rw-list-optgroup {
 | 
					 | 
				
			||||||
  padding-left: 10px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
ul.rw-list.rw-list-grouped > li.rw-list-option,
 | 
					 | 
				
			||||||
.rw-selectlist.rw-list-grouped > li.rw-list-option {
 | 
					 | 
				
			||||||
  padding-left: 20px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-widget {
 | 
					 | 
				
			||||||
  position: relative;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-open.rw-widget,
 | 
					 | 
				
			||||||
.rw-open > .rw-multiselect-wrapper {
 | 
					 | 
				
			||||||
  border-bottom-right-radius: 0;
 | 
					 | 
				
			||||||
  border-bottom-left-radius: 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-open-up.rw-widget,
 | 
					 | 
				
			||||||
.rw-open-up > .rw-multiselect-wrapper {
 | 
					 | 
				
			||||||
  border-top-right-radius: 0;
 | 
					 | 
				
			||||||
  border-top-left-radius: 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-combobox .rw-list,
 | 
					 | 
				
			||||||
.rw-datetimepicker .rw-list,
 | 
					 | 
				
			||||||
.rw-numberpicker .rw-list,
 | 
					 | 
				
			||||||
.rw-dropdownlist .rw-list,
 | 
					 | 
				
			||||||
.rw-multiselect .rw-list {
 | 
					 | 
				
			||||||
  max-height: 200px;
 | 
					 | 
				
			||||||
  height: auto;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-widget {
 | 
					 | 
				
			||||||
  background-color: #ffffff;
 | 
					 | 
				
			||||||
  border: #cccccc 1px solid;
 | 
					 | 
				
			||||||
  border-radius: 4px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-widget .rw-input {
 | 
					 | 
				
			||||||
  border-bottom-left-radius: 4px;
 | 
					 | 
				
			||||||
  border-top-left-radius: 4px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-rtl.rw-widget .rw-input {
 | 
					 | 
				
			||||||
  border-bottom-left-radius: 0;
 | 
					 | 
				
			||||||
  border-top-left-radius: 0;
 | 
					 | 
				
			||||||
  border-bottom-right-radius: 4px;
 | 
					 | 
				
			||||||
  border-top-right-radius: 4px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-widget > .rw-select {
 | 
					 | 
				
			||||||
  border-left: #cccccc 1px solid;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-rtl.rw-widget > .rw-select {
 | 
					 | 
				
			||||||
  border-right: #cccccc 1px solid;
 | 
					 | 
				
			||||||
  border-left: none;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-widget.rw-state-focus,
 | 
					 | 
				
			||||||
.rw-widget.rw-state-focus:hover {
 | 
					 | 
				
			||||||
  -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
 | 
					 | 
				
			||||||
  box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
 | 
					 | 
				
			||||||
  border-color: #66afe9;
 | 
					 | 
				
			||||||
  outline: 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-widget.rw-state-readonly,
 | 
					 | 
				
			||||||
.rw-widget.rw-state-readonly > .rw-multiselect-wrapper {
 | 
					 | 
				
			||||||
  cursor: not-allowed;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-widget.rw-state-disabled,
 | 
					 | 
				
			||||||
.rw-widget.rw-state-disabled:hover,
 | 
					 | 
				
			||||||
.rw-widget.rw-state-disabled:active {
 | 
					 | 
				
			||||||
  -webkit-box-shadow: none;
 | 
					 | 
				
			||||||
  box-shadow: none;
 | 
					 | 
				
			||||||
  background-color: #eeeeee;
 | 
					 | 
				
			||||||
  border-color: #cccccc;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-combobox,
 | 
					 | 
				
			||||||
.rw-datetimepicker,
 | 
					 | 
				
			||||||
.rw-numberpicker,
 | 
					 | 
				
			||||||
.rw-dropdownlist {
 | 
					 | 
				
			||||||
  padding-right: 1.9em;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-combobox.rw-rtl,
 | 
					 | 
				
			||||||
.rw-datetimepicker.rw-rtl,
 | 
					 | 
				
			||||||
.rw-numberpicker.rw-rtl,
 | 
					 | 
				
			||||||
.rw-dropdownlist.rw-rtl {
 | 
					 | 
				
			||||||
  padding-right: 0;
 | 
					 | 
				
			||||||
  padding-left: 1.9em;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-combobox > .rw-input,
 | 
					 | 
				
			||||||
.rw-datetimepicker > .rw-input,
 | 
					 | 
				
			||||||
.rw-numberpicker > .rw-input,
 | 
					 | 
				
			||||||
.rw-dropdownlist > .rw-input {
 | 
					 | 
				
			||||||
  width: 100%;
 | 
					 | 
				
			||||||
  border: none;
 | 
					 | 
				
			||||||
  outline: 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-combobox > .rw-input::-moz-placeholder,
 | 
					 | 
				
			||||||
.rw-datetimepicker > .rw-input::-moz-placeholder,
 | 
					 | 
				
			||||||
.rw-numberpicker > .rw-input::-moz-placeholder,
 | 
					 | 
				
			||||||
.rw-dropdownlist > .rw-input::-moz-placeholder {
 | 
					 | 
				
			||||||
  color: #999999;
 | 
					 | 
				
			||||||
  opacity: 1;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-combobox > .rw-input:-ms-input-placeholder,
 | 
					 | 
				
			||||||
.rw-datetimepicker > .rw-input:-ms-input-placeholder,
 | 
					 | 
				
			||||||
.rw-numberpicker > .rw-input:-ms-input-placeholder,
 | 
					 | 
				
			||||||
.rw-dropdownlist > .rw-input:-ms-input-placeholder {
 | 
					 | 
				
			||||||
  color: #999999;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-combobox > .rw-input::-webkit-input-placeholder,
 | 
					 | 
				
			||||||
.rw-datetimepicker > .rw-input::-webkit-input-placeholder,
 | 
					 | 
				
			||||||
.rw-numberpicker > .rw-input::-webkit-input-placeholder,
 | 
					 | 
				
			||||||
.rw-dropdownlist > .rw-input::-webkit-input-placeholder {
 | 
					 | 
				
			||||||
  color: #999999;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-placeholder {
 | 
					 | 
				
			||||||
  color: #999999;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-select {
 | 
					 | 
				
			||||||
  position: absolute;
 | 
					 | 
				
			||||||
  width: 1.9em;
 | 
					 | 
				
			||||||
  height: 100%;
 | 
					 | 
				
			||||||
  right: 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-select.rw-btn,
 | 
					 | 
				
			||||||
.rw-select > .rw-btn {
 | 
					 | 
				
			||||||
  height: 100%;
 | 
					 | 
				
			||||||
  vertical-align: middle;
 | 
					 | 
				
			||||||
  outline: 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-rtl .rw-select {
 | 
					 | 
				
			||||||
  left: 0;
 | 
					 | 
				
			||||||
  right: auto;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-multiselect,
 | 
					 | 
				
			||||||
.rw-combobox input.rw-input,
 | 
					 | 
				
			||||||
.rw-datetimepicker input.rw-input,
 | 
					 | 
				
			||||||
.rw-numberpicker input.rw-input {
 | 
					 | 
				
			||||||
  -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075);
 | 
					 | 
				
			||||||
  box-shadow: inset 0 1px 1px rgba(0,0,0,.075);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-combobox:active,
 | 
					 | 
				
			||||||
.rw-datetimepicker:active,
 | 
					 | 
				
			||||||
.rw-dropdownlist:active,
 | 
					 | 
				
			||||||
.rw-header > .rw-btn:active,
 | 
					 | 
				
			||||||
.rw-numberpicker .rw-btn.rw-state-active,
 | 
					 | 
				
			||||||
.rw-combobox:active.rw-state-focus,
 | 
					 | 
				
			||||||
.rw-datetimepicker:active.rw-state-focus,
 | 
					 | 
				
			||||||
.rw-dropdownlist:active.rw-state-focus,
 | 
					 | 
				
			||||||
.rw-header > .rw-btn:active.rw-state-focus,
 | 
					 | 
				
			||||||
.rw-numberpicker .rw-btn.rw-state-active.rw-state-focus {
 | 
					 | 
				
			||||||
  background-image: none;
 | 
					 | 
				
			||||||
  -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
 | 
					 | 
				
			||||||
  box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-combobox:hover,
 | 
					 | 
				
			||||||
.rw-datetimepicker:hover,
 | 
					 | 
				
			||||||
.rw-numberpicker:hover,
 | 
					 | 
				
			||||||
.rw-dropdownlist:hover {
 | 
					 | 
				
			||||||
  background-color: #e6e6e6;
 | 
					 | 
				
			||||||
  border-color: #adadad;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-dropdownlist.rw-state-disabled,
 | 
					 | 
				
			||||||
.rw-dropdownlist.rw-state-readonly {
 | 
					 | 
				
			||||||
  cursor: not-allowed;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-dropdownlist > .rw-input {
 | 
					 | 
				
			||||||
  line-height: 2.286em;
 | 
					 | 
				
			||||||
  background-color: transparent;
 | 
					 | 
				
			||||||
  padding-top: 0;
 | 
					 | 
				
			||||||
  padding-bottom: 0;
 | 
					 | 
				
			||||||
  padding-right: 0;
 | 
					 | 
				
			||||||
  overflow: hidden;
 | 
					 | 
				
			||||||
  text-overflow: ellipsis;
 | 
					 | 
				
			||||||
  white-space: nowrap;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-dropdownlist.rw-rtl > .rw-input {
 | 
					 | 
				
			||||||
  padding: 0.429em 0.857em;
 | 
					 | 
				
			||||||
  padding-top: 0;
 | 
					 | 
				
			||||||
  padding-bottom: 0;
 | 
					 | 
				
			||||||
  padding-left: 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-dropdownlist > .rw-select,
 | 
					 | 
				
			||||||
.rw-dropdownlist.rw-rtl > .rw-select {
 | 
					 | 
				
			||||||
  border-width: 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-numberpicker .rw-btn {
 | 
					 | 
				
			||||||
  display: block;
 | 
					 | 
				
			||||||
  height: 1.143em;
 | 
					 | 
				
			||||||
  line-height: 1.143em;
 | 
					 | 
				
			||||||
  width: 100%;
 | 
					 | 
				
			||||||
  border-width: 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-popup {
 | 
					 | 
				
			||||||
  position: absolute;
 | 
					 | 
				
			||||||
  -webkit-box-shadow: 0 5px 6px rgba(0, 0, 0, 0.2);
 | 
					 | 
				
			||||||
  box-shadow: 0 5px 6px rgba(0, 0, 0, 0.2);
 | 
					 | 
				
			||||||
  border-top-right-radius: 0;
 | 
					 | 
				
			||||||
  border-top-left-radius: 0;
 | 
					 | 
				
			||||||
  border-bottom-right-radius: 3px;
 | 
					 | 
				
			||||||
  border-bottom-left-radius: 3px;
 | 
					 | 
				
			||||||
  border: #cccccc 1px solid;
 | 
					 | 
				
			||||||
  background: #ffffff;
 | 
					 | 
				
			||||||
  padding: 2px;
 | 
					 | 
				
			||||||
  overflow: auto;
 | 
					 | 
				
			||||||
  margin-bottom: 10px;
 | 
					 | 
				
			||||||
  left: 10px;
 | 
					 | 
				
			||||||
  right: 10px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-dropup > .rw-popup {
 | 
					 | 
				
			||||||
  margin-bottom: 0;
 | 
					 | 
				
			||||||
  margin-top: 10px;
 | 
					 | 
				
			||||||
  border-top-right-radius: 3px;
 | 
					 | 
				
			||||||
  border-top-left-radius: 3px;
 | 
					 | 
				
			||||||
  border-bottom-right-radius: 0;
 | 
					 | 
				
			||||||
  border-bottom-left-radius: 0;
 | 
					 | 
				
			||||||
  -webkit-box-shadow: 0 0 6px rgba(0, 0, 0, 0.2);
 | 
					 | 
				
			||||||
  box-shadow: 0 0 6px rgba(0, 0, 0, 0.2);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-popup-container {
 | 
					 | 
				
			||||||
  position: absolute;
 | 
					 | 
				
			||||||
  top: 100%;
 | 
					 | 
				
			||||||
  margin-top: 1px;
 | 
					 | 
				
			||||||
  z-index: 1005;
 | 
					 | 
				
			||||||
  left: -11px;
 | 
					 | 
				
			||||||
  right: -11px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-popup-container.rw-dropup {
 | 
					 | 
				
			||||||
  top: auto;
 | 
					 | 
				
			||||||
  bottom: 100%;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-popup-container.rw-calendar-popup {
 | 
					 | 
				
			||||||
  right: auto;
 | 
					 | 
				
			||||||
  width: 18em;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-datetimepicker .rw-btn {
 | 
					 | 
				
			||||||
  width: 1.8em;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-datetimepicker.rw-has-neither {
 | 
					 | 
				
			||||||
  padding-left: 0;
 | 
					 | 
				
			||||||
  padding-right: 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-datetimepicker.rw-has-neither .rw-input {
 | 
					 | 
				
			||||||
  border-radius: 4px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-datetimepicker.rw-has-both {
 | 
					 | 
				
			||||||
  padding-right: 3.8em;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-datetimepicker.rw-has-both.rw-rtl {
 | 
					 | 
				
			||||||
  padding-right: 0;
 | 
					 | 
				
			||||||
  padding-left: 3.8em;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-datetimepicker.rw-has-both > .rw-select {
 | 
					 | 
				
			||||||
  width: 3.8em;
 | 
					 | 
				
			||||||
  height: 100%;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-calendar {
 | 
					 | 
				
			||||||
  background-color: #ffffff;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-calendar thead > tr {
 | 
					 | 
				
			||||||
  border-bottom: 2px solid #cccccc;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-calendar .rw-header {
 | 
					 | 
				
			||||||
  padding-bottom: 5px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-calendar .rw-header .rw-btn-left,
 | 
					 | 
				
			||||||
.rw-calendar .rw-header .rw-btn-right {
 | 
					 | 
				
			||||||
  width: 12.5%;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-calendar .rw-header .rw-btn-view {
 | 
					 | 
				
			||||||
  width: 75%;
 | 
					 | 
				
			||||||
  background-color: #eeeeee;
 | 
					 | 
				
			||||||
  border-radius: 4px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-calendar .rw-header .rw-btn-view[disabled] {
 | 
					 | 
				
			||||||
  -webkit-box-shadow: none;
 | 
					 | 
				
			||||||
  box-shadow: none;
 | 
					 | 
				
			||||||
  cursor: not-allowed;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-calendar .rw-footer {
 | 
					 | 
				
			||||||
  border-top: 1px solid #cccccc;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-calendar .rw-footer .rw-btn {
 | 
					 | 
				
			||||||
  width: 100%;
 | 
					 | 
				
			||||||
  white-space: normal;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-calendar .rw-footer .rw-btn:hover {
 | 
					 | 
				
			||||||
  background-color: #e6e6e6;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-calendar .rw-footer .rw-btn[disabled] {
 | 
					 | 
				
			||||||
  -webkit-box-shadow: none;
 | 
					 | 
				
			||||||
  box-shadow: none;
 | 
					 | 
				
			||||||
  cursor: not-allowed;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-calendar-grid {
 | 
					 | 
				
			||||||
  height: 14.28571429em;
 | 
					 | 
				
			||||||
  table-layout: fixed;
 | 
					 | 
				
			||||||
  width: 100%;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-calendar-grid th {
 | 
					 | 
				
			||||||
  text-align: right;
 | 
					 | 
				
			||||||
  padding: 0 .4em 0 .1em;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-calendar-grid .rw-btn {
 | 
					 | 
				
			||||||
  width: 100%;
 | 
					 | 
				
			||||||
  text-align: right;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-calendar-grid td .rw-btn {
 | 
					 | 
				
			||||||
  border-radius: 4px;
 | 
					 | 
				
			||||||
  padding: 0 .4em 0 .1em;
 | 
					 | 
				
			||||||
  outline: 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-calendar-grid td .rw-btn:hover {
 | 
					 | 
				
			||||||
  background-color: #e6e6e6;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-calendar-grid td .rw-btn.rw-off-range {
 | 
					 | 
				
			||||||
  color: #b3b3b3;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-calendar-grid.rw-nav-view .rw-btn {
 | 
					 | 
				
			||||||
  padding: .25em 0 .3em;
 | 
					 | 
				
			||||||
  display: block;
 | 
					 | 
				
			||||||
  overflow: hidden;
 | 
					 | 
				
			||||||
  text-align: center;
 | 
					 | 
				
			||||||
  white-space: normal;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-selectlist {
 | 
					 | 
				
			||||||
  padding: 2px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-selectlist > ul {
 | 
					 | 
				
			||||||
  height: 100%;
 | 
					 | 
				
			||||||
  overflow: auto;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-selectlist > ul > li.rw-list-option {
 | 
					 | 
				
			||||||
  position: relative;
 | 
					 | 
				
			||||||
  min-height: 27px;
 | 
					 | 
				
			||||||
  cursor: auto;
 | 
					 | 
				
			||||||
  padding-left: 5px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-selectlist > ul > li.rw-list-option > label > input {
 | 
					 | 
				
			||||||
  position: absolute;
 | 
					 | 
				
			||||||
  margin: 4px 0 0 -20px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-selectlist > ul > li.rw-list-option > label {
 | 
					 | 
				
			||||||
  padding-left: 20px;
 | 
					 | 
				
			||||||
  line-height: 1.423em;
 | 
					 | 
				
			||||||
  display: inline-block;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-selectlist.rw-rtl > ul > li.rw-list-option {
 | 
					 | 
				
			||||||
  padding-left: 0;
 | 
					 | 
				
			||||||
  padding-right: 5px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-selectlist.rw-rtl > ul > li.rw-list-option > label > input {
 | 
					 | 
				
			||||||
  margin: 4px -20px 0 0px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-selectlist.rw-rtl > ul > li.rw-list-option > label {
 | 
					 | 
				
			||||||
  padding-left: 0;
 | 
					 | 
				
			||||||
  padding-right: 20px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-selectlist.rw-rtl > ul > li.rw-list-option {
 | 
					 | 
				
			||||||
  padding-left: 0;
 | 
					 | 
				
			||||||
  padding-right: 5px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-selectlist.rw-rtl > ul > li.rw-list-option > label > input {
 | 
					 | 
				
			||||||
  margin: 4px -20px 0 0px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-selectlist.rw-rtl > ul > li.rw-list-option > label {
 | 
					 | 
				
			||||||
  padding-left: 0;
 | 
					 | 
				
			||||||
  padding-right: 20px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-selectlist.rw-state-disabled > ul > li:hover,
 | 
					 | 
				
			||||||
.rw-selectlist.rw-state-readonly > ul > li:hover {
 | 
					 | 
				
			||||||
  background: none;
 | 
					 | 
				
			||||||
  border-color: transparent;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-multiselect {
 | 
					 | 
				
			||||||
  background-color: #ffffff;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-multiselect:hover {
 | 
					 | 
				
			||||||
  border-color: #adadad;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-multiselect-wrapper {
 | 
					 | 
				
			||||||
  border-radius: 4px;
 | 
					 | 
				
			||||||
  position: relative;
 | 
					 | 
				
			||||||
  cursor: text;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-multiselect-wrapper:before,
 | 
					 | 
				
			||||||
.rw-multiselect-wrapper:after {
 | 
					 | 
				
			||||||
  content: " ";
 | 
					 | 
				
			||||||
  display: table;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-multiselect-wrapper:after {
 | 
					 | 
				
			||||||
  clear: both;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-multiselect-wrapper i.rw-loading {
 | 
					 | 
				
			||||||
  position: absolute;
 | 
					 | 
				
			||||||
  right: 3px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-multiselect-wrapper > .rw-input {
 | 
					 | 
				
			||||||
  float: left;
 | 
					 | 
				
			||||||
  outline: 0;
 | 
					 | 
				
			||||||
  border-width: 0;
 | 
					 | 
				
			||||||
  line-height: normal;
 | 
					 | 
				
			||||||
  width: auto;
 | 
					 | 
				
			||||||
  max-width: 100%;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-multiselect-wrapper > .rw-input::-moz-placeholder {
 | 
					 | 
				
			||||||
  color: #999999;
 | 
					 | 
				
			||||||
  opacity: 1;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-multiselect-wrapper > .rw-input:-ms-input-placeholder {
 | 
					 | 
				
			||||||
  color: #999999;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-multiselect-wrapper > .rw-input::-webkit-input-placeholder {
 | 
					 | 
				
			||||||
  color: #999999;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-state-readonly > .rw-multiselect-wrapper,
 | 
					 | 
				
			||||||
.rw-state-disabled > .rw-multiselect-wrapper {
 | 
					 | 
				
			||||||
  cursor: not-allowed;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-rtl .rw-multiselect-wrapper > .rw-input {
 | 
					 | 
				
			||||||
  float: right;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-multiselect-create-tag {
 | 
					 | 
				
			||||||
  border-top: 1px #cccccc solid;
 | 
					 | 
				
			||||||
  padding-top: 5px;
 | 
					 | 
				
			||||||
  margin-top: 5px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-multiselect-taglist {
 | 
					 | 
				
			||||||
  margin: 0;
 | 
					 | 
				
			||||||
  padding-left: 0;
 | 
					 | 
				
			||||||
  list-style: none;
 | 
					 | 
				
			||||||
  padding-right: 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-multiselect-taglist > li {
 | 
					 | 
				
			||||||
  display: inline-block;
 | 
					 | 
				
			||||||
  padding-left: 5px;
 | 
					 | 
				
			||||||
  padding-right: 5px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-multiselect-taglist > li {
 | 
					 | 
				
			||||||
  float: left;
 | 
					 | 
				
			||||||
  display: inline-block;
 | 
					 | 
				
			||||||
  margin: 1px;
 | 
					 | 
				
			||||||
  padding: 0.214em 0.15em 0.214em 0.4em;
 | 
					 | 
				
			||||||
  line-height: 1.4em;
 | 
					 | 
				
			||||||
  text-align: center;
 | 
					 | 
				
			||||||
  vertical-align: middle;
 | 
					 | 
				
			||||||
  white-space: nowrap;
 | 
					 | 
				
			||||||
  border-radius: 3px;
 | 
					 | 
				
			||||||
  border: 1px solid #cccccc;
 | 
					 | 
				
			||||||
  background-color: #cccccc;
 | 
					 | 
				
			||||||
  cursor: pointer;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-multiselect-taglist > li.rw-state-focus {
 | 
					 | 
				
			||||||
  background-color: #ffffff;
 | 
					 | 
				
			||||||
  border: #66afe9 1px solid;
 | 
					 | 
				
			||||||
  color: #333333;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-multiselect-taglist > li.rw-state-readonly,
 | 
					 | 
				
			||||||
.rw-multiselect-taglist > li.rw-state-disabled,
 | 
					 | 
				
			||||||
.rw-multiselect.rw-state-readonly .rw-multiselect-taglist > li,
 | 
					 | 
				
			||||||
.rw-multiselect.rw-state-disabled .rw-multiselect-taglist > li {
 | 
					 | 
				
			||||||
  cursor: not-allowed;
 | 
					 | 
				
			||||||
  filter: alpha(opacity=65);
 | 
					 | 
				
			||||||
  opacity: .65;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-multiselect-taglist > li .rw-btn {
 | 
					 | 
				
			||||||
  outline: 0;
 | 
					 | 
				
			||||||
  font-size: 115%;
 | 
					 | 
				
			||||||
  line-height: normal;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.rw-rtl .rw-multiselect-taglist > li {
 | 
					 | 
				
			||||||
  float: right;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							@@ -2,28 +2,18 @@
 | 
				
			|||||||
<head>
 | 
					<head>
 | 
				
			||||||
<title>MoneyGo</title>
 | 
					<title>MoneyGo</title>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
 | 
					<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
 | 
				
			||||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
 | 
					<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css">
 | 
				
			||||||
<link rel="stylesheet" href="static/external/react-widgets/react-widgets.css">
 | 
					<link rel="stylesheet" href="static/node_modules/react-widgets/dist/css/react-widgets.css">
 | 
				
			||||||
<link rel="stylesheet" href="static/stylesheet.css">
 | 
					<link rel="stylesheet" href="static/stylesheet.css">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
 | 
					<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
 | 
				
			||||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
 | 
					 | 
				
			||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.13.3/react-with-addons.js"></script>
 | 
					 | 
				
			||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.13.3/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 src="static/external/big/big.min.js"></script>
 | 
				
			||||||
<script src="static/external/classnames/index.js"></script>
 | 
					<script src="static/external/classnames/index.js"></script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script type="text/javascript" src="static/utils.js"></script>
 | 
					<script type="text/javascript" src="static/utils.js"></script>
 | 
				
			||||||
<script type="text/javascript" src="static/models.js"></script>
 | 
					<script type="text/javascript" src="static/models.js"></script>
 | 
				
			||||||
 | 
					<script type="text/javascript" src="static/bundle.js"></script>
 | 
				
			||||||
<script type="text/jsx" src="static/top_bar.js"></script>
 | 
					 | 
				
			||||||
<script type="text/jsx" src="static/account_register.js"></script>
 | 
					 | 
				
			||||||
<script type="text/jsx" src="static/accounts.js"></script>
 | 
					 | 
				
			||||||
<script type="text/jsx" src="static/ui.js"></script>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
</head>
 | 
					</head>
 | 
				
			||||||
<body>
 | 
					<body>
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										23
									
								
								static/main.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								static/main.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
				
			|||||||
 | 
					var React = require('react');
 | 
				
			||||||
 | 
					var ReactDOM = require('react-dom');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var Globalize = require('globalize');
 | 
				
			||||||
 | 
					var globalizeLocalizer = require('react-widgets/lib/localizers/globalize');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var MoneyGoApp = require('./MoneyGoApp.js');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Setup globalization for react-widgets
 | 
				
			||||||
 | 
					//Globalize.load(require("cldr-data").entireSupplemental());
 | 
				
			||||||
 | 
					Globalize.load(
 | 
				
			||||||
 | 
						require("cldr-data/main/en/ca-gregorian"),
 | 
				
			||||||
 | 
						require("cldr-data/main/en/numbers"),
 | 
				
			||||||
 | 
						require("cldr-data/supplemental/likelySubtags"),
 | 
				
			||||||
 | 
						require("cldr-data/supplemental/timeData"),
 | 
				
			||||||
 | 
						require("cldr-data/supplemental/weekData")
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					Globalize.locale('en');
 | 
				
			||||||
 | 
					globalizeLocalizer(Globalize);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$(document).ready(function() {
 | 
				
			||||||
 | 
						ReactDOM.render(<MoneyGoApp />, document.getElementById("content"));
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
							
								
								
									
										620
									
								
								static/ui.js
									
									
									
									
									
								
							
							
						
						
									
										620
									
								
								static/ui.js
									
									
									
									
									
								
							@@ -1,620 +0,0 @@
 | 
				
			|||||||
// 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;
 | 
					 | 
				
			||||||
var Modal = ReactBootstrap.Modal;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const 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>
 | 
					 | 
				
			||||||
		);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const AccountSettingsModal = React.createClass({
 | 
					 | 
				
			||||||
	_getInitialState: function(props) {
 | 
					 | 
				
			||||||
		return {error: "",
 | 
					 | 
				
			||||||
			name: props.user.Name,
 | 
					 | 
				
			||||||
			username: props.user.Username,
 | 
					 | 
				
			||||||
			email: props.user.Email,
 | 
					 | 
				
			||||||
			password: BogusPassword,
 | 
					 | 
				
			||||||
			confirm_password: BogusPassword,
 | 
					 | 
				
			||||||
			passwordChanged: false,
 | 
					 | 
				
			||||||
			initial_password: BogusPassword};
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	getInitialState: function() {
 | 
					 | 
				
			||||||
		 return this._getInitialState(this.props);
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	componentWillReceiveProps: function(nextProps) {
 | 
					 | 
				
			||||||
		if (nextProps.show && !this.props.show) {
 | 
					 | 
				
			||||||
			this.setState(this._getInitialState(nextProps));
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	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.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),
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	render: function() {
 | 
					 | 
				
			||||||
		return (
 | 
					 | 
				
			||||||
			<Modal show={this.props.show} onHide={this.handleCancel} bsSize="large">
 | 
					 | 
				
			||||||
				<Modal.Header closeButton>
 | 
					 | 
				
			||||||
					<Modal.Title>Edit Account Settings</Modal.Title>
 | 
					 | 
				
			||||||
				</Modal.Header>
 | 
					 | 
				
			||||||
				<Modal.Body>
 | 
					 | 
				
			||||||
				<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/>
 | 
					 | 
				
			||||||
				</form>
 | 
					 | 
				
			||||||
				</Modal.Body>
 | 
					 | 
				
			||||||
				<Modal.Footer>
 | 
					 | 
				
			||||||
					<ButtonGroup>
 | 
					 | 
				
			||||||
						<Button onClick={this.handleCancel} bsStyle="warning">Cancel</Button>
 | 
					 | 
				
			||||||
						<Button onClick={this.handleSubmit} bsStyle="success">Save Settings</Button>
 | 
					 | 
				
			||||||
					</ButtonGroup>
 | 
					 | 
				
			||||||
				</Modal.Footer>
 | 
					 | 
				
			||||||
			</Modal>
 | 
					 | 
				
			||||||
		);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const MoneyGoApp = React.createClass({
 | 
					 | 
				
			||||||
	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.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();
 | 
					 | 
				
			||||||
				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) {
 | 
					 | 
				
			||||||
		this.setState({showAccountSettingsModal: false});
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	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.user.isUser())
 | 
					 | 
				
			||||||
				mainContent =
 | 
					 | 
				
			||||||
					<TabbedArea defaultActiveKey='1' className="">
 | 
					 | 
				
			||||||
						<TabPane tab="Accounts" eventKey='1' className="fullheight">
 | 
					 | 
				
			||||||
						<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} />
 | 
					 | 
				
			||||||
						</TabPane>
 | 
					 | 
				
			||||||
						<TabPane tab="Scheduled Transactions" eventKey='2' className="fullheight">Scheduled transactions go here...</TabPane>
 | 
					 | 
				
			||||||
						<TabPane tab="Budgets" eventKey='3' className="fullheight">Budgets go here...</TabPane>
 | 
					 | 
				
			||||||
						<TabPane tab="Reports" eventKey='4' className="fullheight">Reports go here...</TabPane>
 | 
					 | 
				
			||||||
					</TabbedArea>
 | 
					 | 
				
			||||||
			else
 | 
					 | 
				
			||||||
				mainContent =
 | 
					 | 
				
			||||||
					<Jumbotron>
 | 
					 | 
				
			||||||
						<center>
 | 
					 | 
				
			||||||
							<h1>Money<i>Go</i></h1>
 | 
					 | 
				
			||||||
							<p><i>Go</i> manage your money.</p>
 | 
					 | 
				
			||||||
						</center>
 | 
					 | 
				
			||||||
					</Jumbotron>
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		return (
 | 
					 | 
				
			||||||
			<div className="fullheight ui">
 | 
					 | 
				
			||||||
				<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}
 | 
					 | 
				
			||||||
				<AccountSettingsModal
 | 
					 | 
				
			||||||
					show={this.state.showAccountSettingsModal}
 | 
					 | 
				
			||||||
					user={this.state.user}
 | 
					 | 
				
			||||||
					onSubmit={this.handleSettingsSubmitted}
 | 
					 | 
				
			||||||
					onCancel={this.handleSettingsCanceled}/>
 | 
					 | 
				
			||||||
			</div>
 | 
					 | 
				
			||||||
		);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
React.render(<MoneyGoApp />, document.getElementById("content"));
 | 
					 | 
				
			||||||
		Reference in New Issue
	
	Block a user