mirror of
				https://github.com/aclindsa/moneygo.git
				synced 2025-10-29 17:13:26 -04:00 
			
		
		
		
	Add initial UI for user-editable securities
This commit is contained in:
		| @@ -19,6 +19,52 @@ function securitiesFetched(securities) { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| function createSecurity() { | ||||
| 	return { | ||||
| 		type: SecurityConstants.CREATE_SECURITY | ||||
| 	} | ||||
| } | ||||
|  | ||||
| function securityCreated(security) { | ||||
| 	return { | ||||
| 		type: SecurityConstants.SECURITY_CREATED, | ||||
| 		security: security | ||||
| 	} | ||||
| } | ||||
|  | ||||
| function updateSecurity() { | ||||
| 	return { | ||||
| 		type: SecurityConstants.UPDATE_SECURITY | ||||
| 	} | ||||
| } | ||||
|  | ||||
| function securityUpdated(security) { | ||||
| 	return { | ||||
| 		type: SecurityConstants.SECURITY_UPDATED, | ||||
| 		security: security | ||||
| 	} | ||||
| } | ||||
|  | ||||
| function removeSecurity() { | ||||
| 	return { | ||||
| 		type: SecurityConstants.REMOVE_SECURITY | ||||
| 	} | ||||
| } | ||||
|  | ||||
| function securityRemoved(securityId) { | ||||
| 	return { | ||||
| 		type: SecurityConstants.SECURITY_REMOVED, | ||||
| 		securityId: securityId | ||||
| 	} | ||||
| } | ||||
|  | ||||
| function securitySelected(securityId) { | ||||
| 	return { | ||||
| 		type: SecurityConstants.SECURITY_SELECTED, | ||||
| 		securityId: securityId | ||||
| 	} | ||||
| } | ||||
|  | ||||
| function fetchAll() { | ||||
| 	return function (dispatch) { | ||||
| 		dispatch(fetchSecurities()); | ||||
| @@ -47,6 +93,88 @@ function fetchAll() { | ||||
| 	}; | ||||
| } | ||||
|  | ||||
| function create(security) { | ||||
| 	return function (dispatch) { | ||||
| 		dispatch(createSecurity()); | ||||
|  | ||||
| 		$.ajax({ | ||||
| 			type: "POST", | ||||
| 			dataType: "json", | ||||
| 			url: "security/", | ||||
| 			data: {security: security.toJSON()}, | ||||
| 			success: function(data, status, jqXHR) { | ||||
| 				var e = new Error(); | ||||
| 				e.fromJSON(data); | ||||
| 				if (e.isError()) { | ||||
| 					ErrorActions.serverError(e); | ||||
| 				} else { | ||||
| 					var s = new Security(); | ||||
| 					s.fromJSON(data); | ||||
| 					dispatch(securityCreated(s)); | ||||
| 				} | ||||
| 			}, | ||||
| 			error: function(jqXHR, status, error) { | ||||
| 				ErrorActions.ajaxError(e); | ||||
| 			} | ||||
| 		}); | ||||
| 	}; | ||||
| } | ||||
|  | ||||
| function update(security) { | ||||
| 	return function (dispatch) { | ||||
| 		dispatch(updateSecurity()); | ||||
|  | ||||
| 		$.ajax({ | ||||
| 			type: "PUT", | ||||
| 			dataType: "json", | ||||
| 			url: "security/"+security.SecurityId+"/", | ||||
| 			data: {security: security.toJSON()}, | ||||
| 			success: function(data, status, jqXHR) { | ||||
| 				var e = new Error(); | ||||
| 				e.fromJSON(data); | ||||
| 				if (e.isError()) { | ||||
| 					ErrorActions.serverError(e); | ||||
| 				} else { | ||||
| 					var s = new Security(); | ||||
| 					s.fromJSON(data); | ||||
| 					dispatch(securityUpdated(s)); | ||||
| 				} | ||||
| 			}, | ||||
| 			error: function(jqXHR, status, error) { | ||||
| 				ErrorActions.ajaxError(e); | ||||
| 			} | ||||
| 		}); | ||||
| 	}; | ||||
| } | ||||
|  | ||||
| function remove(security) { | ||||
| 	return function(dispatch) { | ||||
| 		dispatch(removeSecurity()); | ||||
|  | ||||
| 		$.ajax({ | ||||
| 			type: "DELETE", | ||||
| 			dataType: "json", | ||||
| 			url: "security/"+security.SecurityId+"/", | ||||
| 			success: function(data, status, jqXHR) { | ||||
| 				var e = new Error(); | ||||
| 				e.fromJSON(data); | ||||
| 				if (e.isError()) { | ||||
| 					ErrorActions.serverError(e); | ||||
| 				} else { | ||||
| 					dispatch(securityRemoved(security.SecurityId)); | ||||
| 				} | ||||
| 			}, | ||||
| 			error: function(jqXHR, status, error) { | ||||
| 				ErrorActions.ajaxError(e); | ||||
| 			} | ||||
| 		}); | ||||
| 	}; | ||||
| } | ||||
|  | ||||
| module.exports = { | ||||
| 	fetchAll: fetchAll | ||||
| 	fetchAll: fetchAll, | ||||
| 	create: create, | ||||
| 	update: update, | ||||
| 	remove: remove, | ||||
| 	select: securitySelected | ||||
| }; | ||||
|   | ||||
							
								
								
									
										62
									
								
								js/actions/SecurityTemplateActions.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								js/actions/SecurityTemplateActions.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,62 @@ | ||||
| var SecurityTemplateConstants = require('../constants/SecurityTemplateConstants'); | ||||
|  | ||||
| var ErrorActions = require('./ErrorActions'); | ||||
|  | ||||
| var models = require('../models.js'); | ||||
| var Security = models.Security; | ||||
| var Error = models.Error; | ||||
|  | ||||
| function searchSecurityTemplates(searchString, searchType) { | ||||
| 	return { | ||||
| 		type: SecurityTemplateConstants.SEARCH_SECURITY_TEMPLATES, | ||||
| 		searchString: searchString, | ||||
| 		searchType: searchType | ||||
| 	} | ||||
| } | ||||
|  | ||||
| function securityTemplatesSearched(searchString, searchType, securities) { | ||||
| 	return { | ||||
| 		type: SecurityTemplateConstants.SECURITY_TEMPLATES_SEARCHED, | ||||
| 		searchString: searchString, | ||||
| 		searchType: searchType, | ||||
| 		securities: securities | ||||
| 	} | ||||
| } | ||||
|  | ||||
| function search(searchString, searchType, limit) { | ||||
| 	return function (dispatch) { | ||||
| 		dispatch(searchSecurityTemplates(searchString, searchType)); | ||||
|  | ||||
| 		if (searchString == "") | ||||
| 			return; | ||||
|  | ||||
| 		$.ajax({ | ||||
| 			type: "GET", | ||||
| 			dataType: "json", | ||||
| 			url: "securitytemplate/?search="+searchString+"&type="+searchType+"&limit="+limit, | ||||
| 			success: function(data, status, jqXHR) { | ||||
| 				var e = new Error(); | ||||
| 				e.fromJSON(data); | ||||
| 				if (e.isError()) { | ||||
| 					ErrorActions.serverError(e); | ||||
| 				} else if (data.securities == null) { | ||||
| 					dispatch(securityTemplatesSearched(searchString, searchType, new Array())); | ||||
| 				} else { | ||||
| 					dispatch(securityTemplatesSearched(searchString, searchType, | ||||
| 							data.securities.map(function(json) { | ||||
| 						var s = new Security(); | ||||
| 						s.fromJSON(json); | ||||
| 						return s; | ||||
| 					}))); | ||||
| 				} | ||||
| 			}, | ||||
| 			error: function(jqXHR, status, error) { | ||||
| 				ErrorActions.ajaxError(e); | ||||
| 			} | ||||
| 		}); | ||||
| 	}; | ||||
| } | ||||
|  | ||||
| module.exports = { | ||||
| 	search: search | ||||
| }; | ||||
| @@ -15,7 +15,6 @@ var ButtonGroup = ReactBootstrap.ButtonGroup; | ||||
| var Glyphicon = ReactBootstrap.Glyphicon; | ||||
| var ListGroup = ReactBootstrap.ListGroup; | ||||
| var ListGroupItem = ReactBootstrap.ListGroupItem; | ||||
| var Collapse = ReactBootstrap.Collapse; | ||||
| var Alert = ReactBootstrap.Alert; | ||||
| var Modal = ReactBootstrap.Modal; | ||||
| var Collapse = ReactBootstrap.Collapse; | ||||
|   | ||||
| @@ -10,6 +10,7 @@ var TopBarContainer = require('../containers/TopBarContainer'); | ||||
| var NewUserForm = require('./NewUserForm'); | ||||
| var AccountSettingsModalContainer = require('../containers/AccountSettingsModalContainer'); | ||||
| var AccountsTabContainer = require('../containers/AccountsTabContainer'); | ||||
| var SecuritiesTabContainer = require('../containers/SecuritiesTabContainer'); | ||||
|  | ||||
| module.exports = React.createClass({ | ||||
| 	displayName: "MoneyGoApp", | ||||
| @@ -67,9 +68,13 @@ module.exports = React.createClass({ | ||||
| 						<AccountsTabContainer | ||||
| 							className="fullheight" /> | ||||
| 						</Tab> | ||||
| 						<Tab title="Scheduled Transactions" eventKey={2} >Scheduled transactions go here...</Tab> | ||||
| 						<Tab title="Budgets" eventKey={3} >Budgets go here...</Tab> | ||||
| 						<Tab title="Reports" eventKey={4} >Reports go here...</Tab> | ||||
| 						<Tab title="Securities" eventKey={2} > | ||||
| 						<SecuritiesTabContainer | ||||
| 							className="fullheight" /> | ||||
| 						</Tab> | ||||
| 						<Tab title="Scheduled Transactions" eventKey={3} >Scheduled transactions go here...</Tab> | ||||
| 						<Tab title="Budgets" eventKey={4} >Budgets go here...</Tab> | ||||
| 						<Tab title="Reports" eventKey={5} >Reports go here...</Tab> | ||||
| 					</Tabs>); | ||||
| 			else | ||||
| 				mainContent = ( | ||||
|   | ||||
							
								
								
									
										363
									
								
								js/components/SecuritiesTab.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										363
									
								
								js/components/SecuritiesTab.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,363 @@ | ||||
| var React = require('react'); | ||||
| var ReactDOM = require('react-dom'); | ||||
|  | ||||
| var ReactBootstrap = require('react-bootstrap'); | ||||
| var Grid = ReactBootstrap.Grid; | ||||
| var Row = ReactBootstrap.Row; | ||||
| var Col = ReactBootstrap.Col; | ||||
| var Form = ReactBootstrap.Form; | ||||
| var FormGroup = ReactBootstrap.FormGroup; | ||||
| var FormControl = ReactBootstrap.FormControl; | ||||
| var ControlLabel = ReactBootstrap.ControlLabel; | ||||
| var Button = ReactBootstrap.Button; | ||||
| var ButtonGroup = ReactBootstrap.ButtonGroup; | ||||
| var ButtonToolbar = ReactBootstrap.ButtonToolbar; | ||||
| var Glyphicon = ReactBootstrap.Glyphicon; | ||||
| var ListGroup = ReactBootstrap.ListGroup; | ||||
| var ListGroupItem = ReactBootstrap.ListGroupItem; | ||||
| var Modal = ReactBootstrap.Modal; | ||||
| var Panel = ReactBootstrap.Panel; | ||||
|  | ||||
| var Combobox = require('react-widgets').Combobox; | ||||
|  | ||||
| var models = require('../models'); | ||||
| var Security = models.Security; | ||||
| var SecurityType = models.SecurityType; | ||||
| var SecurityTypeList = models.SecurityTypeList; | ||||
|  | ||||
| const SecurityTemplatePanel = React.createClass({ | ||||
| 	handleSearchChange: function(){ | ||||
| 		this.props.onSearchTemplates(ReactDOM.findDOMNode(this.refs.search).value, 0, this.props.maxResults + 1); | ||||
| 	}, | ||||
| 	renderTemplateList: function() { | ||||
| 		var templates = this.props.securityTemplates; | ||||
| 		if (this.props.search != "") { | ||||
| 			var items = []; | ||||
| 			for (var i = 0; i < templates.length && i < 15; i++) { | ||||
| 				var template = templates[i]; | ||||
| 				var self = this; | ||||
| 				var onClickFn = (function() { | ||||
| 					var j = i; | ||||
| 					return function(){self.props.onSelectTemplate(templates[j])}; | ||||
| 				})(); | ||||
| 				var key = template.Type.toString() + template.AlternateId; | ||||
| 				items.push(( | ||||
| 					<ListGroupItem onClick={onClickFn} key={key}> | ||||
| 						{template.Name} - {template.Description} | ||||
| 					</ListGroupItem> | ||||
| 				)); | ||||
| 			} | ||||
| 			if (templates.length > this.props.maxResults) { | ||||
| 				items.push(( | ||||
| 					<ListGroupItem disabled key="too-many-templates"> | ||||
| 						Too many templates to display, please refine your search... | ||||
| 					</ListGroupItem> | ||||
| 				)); | ||||
| 			} else if (templates.length == 0) { | ||||
| 				items.push(( | ||||
| 					<ListGroupItem disabled key="no-templates"> | ||||
| 						Sorry, no templates matched your search... | ||||
| 					</ListGroupItem> | ||||
| 				)); | ||||
| 			} | ||||
| 			return ( | ||||
| 				<div> | ||||
| 					<br /> | ||||
| 					<ControlLabel>Select a template to populate your security:</ControlLabel> | ||||
| 					<ListGroup> | ||||
| 					{items} | ||||
| 					</ListGroup> | ||||
| 				</div> | ||||
| 			); | ||||
| 		} | ||||
| 	}, | ||||
| 	render: function() { | ||||
| 		return ( | ||||
| 			<Panel collapsible header="Populate Security from Template..."> | ||||
| 				<FormControl type="text" | ||||
| 					placeholder="Search..." | ||||
| 					value={this.props.search} | ||||
| 					onChange={this.handleSearchChange} | ||||
| 					ref="search"/> | ||||
| 				{this.renderTemplateList()} | ||||
| 			</Panel> | ||||
| 		); | ||||
| 	} | ||||
| }); | ||||
|  | ||||
| const AddEditSecurityModal = React.createClass({ | ||||
| 	getInitialState: function() { | ||||
| 		var s = { | ||||
| 			securityid: -1, | ||||
| 			name: "", | ||||
| 			description: "", | ||||
| 			symbol: "", | ||||
| 			precision: 0, | ||||
| 			type: 1, | ||||
| 			alternateid: "" | ||||
| 		}; | ||||
| 		if (this.props.editSecurity != null) { | ||||
| 			s.securityid = this.props.editSecurity.SecurityId; | ||||
| 			s.name = this.props.editSecurity.Name; | ||||
| 			s.description = this.props.editSecurity.Description; | ||||
| 			s.symbol = this.props.editSecurity.Symbol; | ||||
| 			s.precision = this.props.editSecurity.Precision; | ||||
| 			s.type = this.props.editSecurity.Type; | ||||
| 			s.alternateid = this.props.editSecurity.AlternateId; | ||||
| 		} | ||||
| 		return s; | ||||
| 	}, | ||||
| 	onSelectTemplate: function(template) { | ||||
| 		this.setState({ | ||||
| 			name: template.Name, | ||||
| 			description: template.Description, | ||||
| 			symbol: template.Symbol, | ||||
| 			precision: template.Precision, | ||||
| 			type: template.Type, | ||||
| 			alternateid: template.AlternateId  | ||||
| 		}); | ||||
| 	}, | ||||
| 	handleCancel: function() { | ||||
| 		if (this.props.onCancel != null) | ||||
| 			this.props.onCancel(); | ||||
| 	}, | ||||
| 	handleNameChange: function() { | ||||
| 		this.setState({ | ||||
| 			name: ReactDOM.findDOMNode(this.refs.name).value, | ||||
| 		}); | ||||
| 	}, | ||||
| 	handleDescriptionChange: function() { | ||||
| 		this.setState({ | ||||
| 			description: ReactDOM.findDOMNode(this.refs.description).value, | ||||
| 		}); | ||||
| 	}, | ||||
| 	handleSymbolChange: function() { | ||||
| 		this.setState({ | ||||
| 			symbol: ReactDOM.findDOMNode(this.refs.symbol).value, | ||||
| 		}); | ||||
| 	}, | ||||
| 	handlePrecisionChange: function() { | ||||
| 		this.setState({ | ||||
| 			precision: +ReactDOM.findDOMNode(this.refs.precision).value, | ||||
| 		}); | ||||
| 	}, | ||||
| 	handleTypeChange: function(type) { | ||||
| 		if (type.hasOwnProperty('TypeId')) | ||||
| 			this.setState({ | ||||
| 				type: type.TypeId | ||||
| 			}); | ||||
| 	}, | ||||
| 	handleAlternateIdChange: function() { | ||||
| 		this.setState({ | ||||
| 			alternateid: ReactDOM.findDOMNode(this.refs.alternateid).value, | ||||
| 		}); | ||||
| 	}, | ||||
| 	handleSubmit: function() { | ||||
| 		var s = new Security(); | ||||
|  | ||||
| 		if (this.props.editSecurity != null) | ||||
| 			s.SecurityId = this.state.securityid; | ||||
| 		s.Name = this.state.name; | ||||
| 		s.Description = this.state.description; | ||||
| 		s.Symbol = this.state.symbol; | ||||
| 		s.Precision = this.state.precision; | ||||
| 		s.Type = this.state.type; | ||||
| 		s.AlternateId = this.state.alternateid; | ||||
|  | ||||
| 		if (this.props.onSubmit != null) | ||||
| 			this.props.onSubmit(s); | ||||
| 	}, | ||||
| 	componentWillReceiveProps: function(nextProps) { | ||||
| 		if (nextProps.show && !this.props.show) { | ||||
| 			this.setState(this.getInitialState()); | ||||
| 		} | ||||
| 	}, | ||||
| 	render: function() { | ||||
| 		var headerText = (this.props.editSecurity != null) ? "Edit" : "Create New"; | ||||
| 		var buttonText = (this.props.editSecurity != null) ? "Save Changes" : "Create Security"; | ||||
| 		var alternateidname = (this.state.type == SecurityType.Currency) ? "ISO 4217 Code" : "CUSIP"; | ||||
| 		return ( | ||||
| 			<Modal show={this.props.show} onHide={this.handleCancel}> | ||||
| 				<Modal.Header closeButton> | ||||
| 					<Modal.Title>{headerText} Security</Modal.Title> | ||||
| 				</Modal.Header> | ||||
| 				<Modal.Body> | ||||
| 				<SecurityTemplatePanel | ||||
| 					search={this.props.securityTemplates.search} | ||||
| 					securityTemplates={this.props.securityTemplates.templates} | ||||
| 					onSearchTemplates={this.props.onSearchTemplates} | ||||
| 					maxResults={15} | ||||
| 					onSelectTemplate={this.onSelectTemplate} /> | ||||
| 				<Form horizontal onSubmit={this.handleSubmit}> | ||||
| 					<FormGroup> | ||||
| 						<Col componentClass={ControlLabel} xs={3}>Name</Col> | ||||
| 						<Col xs={9}> | ||||
| 						<FormControl type="text" | ||||
| 							value={this.state.name} | ||||
| 							onChange={this.handleNameChange} | ||||
| 							ref="name"/> | ||||
| 						</Col> | ||||
| 					</FormGroup> | ||||
| 					<FormGroup> | ||||
| 						<Col componentClass={ControlLabel} xs={3}>Description</Col> | ||||
| 						<Col xs={9}> | ||||
| 						<FormControl type="text" | ||||
| 							value={this.state.description} | ||||
| 							onChange={this.handleDescriptionChange} | ||||
| 							ref="description"/> | ||||
| 						</Col> | ||||
| 					</FormGroup> | ||||
| 					<FormGroup> | ||||
| 						<Col componentClass={ControlLabel} xs={3}>Symbol or Ticker</Col> | ||||
| 						<Col xs={9}> | ||||
| 						<FormControl type="text" | ||||
| 							value={this.state.symbol} | ||||
| 							onChange={this.handleSymbolChange} | ||||
| 							ref="symbol"/> | ||||
| 						</Col> | ||||
| 					</FormGroup> | ||||
| 					<FormGroup> | ||||
| 						<Col componentClass={ControlLabel} xs={3}>Smallest Fraction Traded</Col> | ||||
| 						<Col xs={9}> | ||||
| 						<FormControl componentClass="select" | ||||
| 							placeholder={this.state.precision} | ||||
| 							value={this.state.precision} | ||||
| 							onChange={this.handlePrecisionChange} | ||||
| 							ref="precision"> | ||||
| 								<option value={0}>1</option> | ||||
| 								<option value={1}>0.1 (1/10)</option> | ||||
| 								<option value={2}>0.01 (1/100)</option> | ||||
| 								<option value={3}>0.001 (1/1000)</option> | ||||
| 								<option value={4}>0.0001 (1/10000)</option> | ||||
| 								<option value={5}>0.00001 (1/100000)</option> | ||||
| 						</FormControl> | ||||
| 						</Col> | ||||
| 					</FormGroup> | ||||
| 					<FormGroup> | ||||
| 						<Col componentClass={ControlLabel} xs={3}>Security Type</Col> | ||||
| 						<Col xs={9}> | ||||
| 						<Combobox | ||||
| 							suggest | ||||
| 							data={SecurityTypeList} | ||||
| 							valueField='TypeId' | ||||
| 							textField='Name' | ||||
| 							value={this.state.type} | ||||
| 							onChange={this.handleTypeChange} | ||||
| 							ref="type" /> | ||||
| 						</Col> | ||||
| 					</FormGroup> | ||||
| 					<FormGroup> | ||||
| 						<Col componentClass={ControlLabel} xs={3}>{alternateidname}</Col> | ||||
| 						<Col xs={9}> | ||||
| 						<FormControl type="text" | ||||
| 							value={this.state.alternateid} | ||||
| 							onChange={this.handleAlternateIdChange} | ||||
| 							ref="alternateid"/> | ||||
| 						</Col> | ||||
| 					</FormGroup> | ||||
| 				</Form> | ||||
| 				</Modal.Body> | ||||
| 				<Modal.Footer> | ||||
| 					<ButtonGroup className="pull-right"> | ||||
| 						<Button onClick={this.handleCancel} bsStyle="warning">Cancel</Button> | ||||
| 						<Button onClick={this.handleSubmit} bsStyle="success">{buttonText}</Button> | ||||
| 					</ButtonGroup> | ||||
| 				</Modal.Footer> | ||||
| 			</Modal> | ||||
| 		); | ||||
| 	} | ||||
| }); | ||||
|  | ||||
| const SecurityList = React.createClass({ | ||||
| 	render: function() { | ||||
| 		var children = []; | ||||
| 		var self = this; | ||||
| 		for (var securityId in this.props.securities) { | ||||
| 			if (this.props.securities.hasOwnProperty(securityId)) { | ||||
| 				var buttonStyle = (securityId == this.props.selectedSecurity) ? "info" : "link"; | ||||
| 				var onClickFn = (function() { | ||||
| 					var id = securityId; | ||||
| 					return function(){self.props.onSelectSecurity(id)}; | ||||
| 				})(); | ||||
| 				children.push((<Button | ||||
| 						bsStyle={buttonStyle} | ||||
| 						key={securityId} | ||||
| 						onClick={onClickFn}> | ||||
| 					{this.props.securities[securityId].Name} - {this.props.securities[securityId].Description} | ||||
| 				</Button>)); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		return ( | ||||
| 			<div> | ||||
| 				{children} | ||||
| 			</div> | ||||
| 		); | ||||
| 	} | ||||
| }); | ||||
|  | ||||
| module.exports = React.createClass({ | ||||
| 	displayName: "SecuritiesTab", | ||||
| 	getInitialState: function() { | ||||
| 		return { | ||||
| 			creatingNewSecurity: false, | ||||
| 			editingSecurity: false | ||||
| 		}; | ||||
| 	}, | ||||
| 	handleNewSecurity: function() { | ||||
| 		this.setState({creatingNewSecurity: true}); | ||||
| 	}, | ||||
| 	handleEditSecurity: function() { | ||||
| 		this.setState({editingSecurity: true}); | ||||
| 	}, | ||||
| 	handleCreationCancel: function() { | ||||
| 		this.setState({creatingNewSecurity: false}); | ||||
| 	}, | ||||
| 	handleCreationSubmit: function(security) { | ||||
| 		this.setState({creatingNewSecurity: false}); | ||||
| 		this.props.onCreateSecurity(security); | ||||
| 	}, | ||||
| 	handleEditingCancel: function() { | ||||
| 		this.setState({editingSecurity: false}); | ||||
| 	}, | ||||
| 	handleEditingSubmit: function(security) { | ||||
| 		this.setState({editingSecurity: false}); | ||||
| 		this.props.onUpdateSecurity(security); | ||||
| 	}, | ||||
| 	render: function() { | ||||
| 		var editDisabled = this.props.selectedSecurity == -1; | ||||
|  | ||||
| 		var selectedSecurity = null; | ||||
| 		if (this.props.securities.hasOwnProperty(this.props.selectedSecurity)) | ||||
| 			selectedSecurity = this.props.securities[this.props.selectedSecurity]; | ||||
|  | ||||
| 		return ( | ||||
| 			<Grid fluid className="fullheight"><Row className="fullheight"> | ||||
| 				<Col xs={3} className="fullheight securitylist-column"> | ||||
| 				<AddEditSecurityModal | ||||
| 					show={this.state.creatingNewSecurity} | ||||
| 					onCancel={this.handleCreationCancel} | ||||
| 					onSubmit={this.handleCreationSubmit} | ||||
| 					onSearchTemplates={this.props.onSearchTemplates} | ||||
| 					securityTemplates={this.props.securityTemplates} /> | ||||
| 				<AddEditSecurityModal | ||||
| 					show={this.state.editingSecurity} | ||||
| 					editSecurity={selectedSecurity} | ||||
| 					onCancel={this.handleEditingCancel} | ||||
| 					onSubmit={this.handleEditingSubmit} | ||||
| 					onSearchTemplates={this.props.onSearchTemplates} | ||||
| 					securityTemplates={this.props.securityTemplates} /> | ||||
| 				<SecurityList | ||||
| 					selectedSecurity={this.props.selectedSecurity} | ||||
| 					securities={this.props.securities} | ||||
| 					onSelectSecurity={this.props.onSelectSecurity} /> | ||||
| 				</Col><Col xs={9} className="fullheight securities-column"> | ||||
| 					<ButtonToolbar className="pull-right"><ButtonGroup> | ||||
| 						<Button onClick={this.handleEditSecurity} bsStyle="primary" disabled={editDisabled}><Glyphicon glyph='cog'/> Edit Security</Button> | ||||
| 						<Button onClick={this.handleNewSecurity} bsStyle="success"><Glyphicon glyph='plus-sign'/> New Security</Button> | ||||
| 					</ButtonGroup></ButtonToolbar> | ||||
| 				</Col> | ||||
| 			</Row></Grid> | ||||
| 		); | ||||
| 	} | ||||
| }); | ||||
| @@ -8,5 +8,6 @@ module.exports = keyMirror({ | ||||
| 	UPDATE_SECURITY: null, | ||||
| 	SECURITY_UPDATED: null, | ||||
| 	REMOVE_SECURITY: null, | ||||
| 	SECURITY_REMOVED: null | ||||
| 	SECURITY_REMOVED: null, | ||||
| 	SECURITY_SELECTED: null | ||||
| }); | ||||
|   | ||||
							
								
								
									
										6
									
								
								js/constants/SecurityTemplateConstants.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								js/constants/SecurityTemplateConstants.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| var keyMirror = require('keymirror'); | ||||
|  | ||||
| module.exports = keyMirror({ | ||||
| 	SEARCH_SECURITY_TEMPLATES: null, | ||||
| 	SECURITY_TEMPLATES_SEARCHED: null | ||||
| }); | ||||
							
								
								
									
										35
									
								
								js/containers/SecuritiesTabContainer.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								js/containers/SecuritiesTabContainer.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | ||||
| var connect = require('react-redux').connect; | ||||
|  | ||||
| var SecurityActions = require('../actions/SecurityActions'); | ||||
| var SecurityTemplateActions = require('../actions/SecurityTemplateActions'); | ||||
| var SecuritiesTab = require('../components/SecuritiesTab'); | ||||
|  | ||||
| function mapStateToProps(state) { | ||||
| 	var selectedSecurityAccounts = []; | ||||
| 	for (var accountId in state.accounts) { | ||||
| 		if (state.accounts.hasOwnProperty(accountId) | ||||
| 				&& state.accounts[accountId].SecurityId == state.selectedSecurity) | ||||
| 			selectedSecurityAccounts.push(state.accounts[accountId]); | ||||
| 	} | ||||
| 	return { | ||||
| 		securities: state.securities, | ||||
| 		selectedSecurityAccounts: selectedSecurityAccounts, | ||||
| 		selectedSecurity: state.selectedSecurity, | ||||
| 		securityTemplates: state.securityTemplates | ||||
| 	} | ||||
| } | ||||
|  | ||||
| function mapDispatchToProps(dispatch) { | ||||
| 	return { | ||||
| 		onCreateSecurity: function(security) {dispatch(SecurityActions.create(security))}, | ||||
| 		onUpdateSecurity: function(security) {dispatch(SecurityActions.update(security))}, | ||||
| 		onDeleteSecurity: function(securityId) {dispatch(SecurityActions.remove(securityId))}, | ||||
| 		onSelectSecurity: function(securityId) {dispatch(SecurityActions.select(securityId))}, | ||||
| 		onSearchTemplates: function(search, type, limit) {dispatch(SecurityTemplateActions.search(search, type, limit))} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| module.exports = connect( | ||||
| 	mapStateToProps, | ||||
| 	mapDispatchToProps | ||||
| )(SecuritiesTab) | ||||
| @@ -94,6 +94,7 @@ function Security() { | ||||
| 	this.Symbol = ""; | ||||
| 	this.Precision = -1; | ||||
| 	this.Type = -1; | ||||
| 	this.AlternateId = ""; | ||||
| } | ||||
|  | ||||
| Security.prototype.toJSON = function() { | ||||
| @@ -104,6 +105,7 @@ Security.prototype.toJSON = function() { | ||||
| 	json_obj.Symbol = this.Symbol; | ||||
| 	json_obj.Precision = this.Precision; | ||||
| 	json_obj.Type = this.Type; | ||||
| 	json_obj.AlternateId = this.AlternateId; | ||||
| 	return JSON.stringify(json_obj); | ||||
| } | ||||
|  | ||||
| @@ -122,6 +124,8 @@ Security.prototype.fromJSON = function(json_input) { | ||||
| 		this.Precision = json_obj.Precision; | ||||
| 	if (json_obj.hasOwnProperty("Type")) | ||||
| 		this.Type = json_obj.Type; | ||||
| 	if (json_obj.hasOwnProperty("AlternateId")) | ||||
| 		this.AlternateId = json_obj.AlternateId; | ||||
| } | ||||
|  | ||||
| Security.prototype.isSecurity = function() { | ||||
|   | ||||
| @@ -4,7 +4,9 @@ var UserReducer = require('./UserReducer'); | ||||
| var SessionReducer = require('./SessionReducer'); | ||||
| var AccountReducer = require('./AccountReducer'); | ||||
| var SecurityReducer = require('./SecurityReducer'); | ||||
| var SecurityTemplateReducer = require('./SecurityTemplateReducer'); | ||||
| var SelectedAccountReducer = require('./SelectedAccountReducer'); | ||||
| var SelectedSecurityReducer = require('./SelectedSecurityReducer'); | ||||
| var ErrorReducer = require('./ErrorReducer'); | ||||
|  | ||||
| module.exports = Redux.combineReducers({ | ||||
| @@ -12,6 +14,8 @@ module.exports = Redux.combineReducers({ | ||||
| 	session: SessionReducer, | ||||
| 	accounts: AccountReducer, | ||||
| 	securities: SecurityReducer, | ||||
| 	securityTemplates: SecurityTemplateReducer, | ||||
| 	selectedAccount: SelectedAccountReducer, | ||||
| 	selectedSecurity: SelectedSecurityReducer, | ||||
| 	error: ErrorReducer | ||||
| }); | ||||
|   | ||||
							
								
								
									
										33
									
								
								js/reducers/SecurityTemplateReducer.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								js/reducers/SecurityTemplateReducer.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | ||||
| var assign = require('object-assign'); | ||||
|  | ||||
| var SecurityTemplateConstants = require('../constants/SecurityTemplateConstants'); | ||||
| var UserConstants = require('../constants/UserConstants'); | ||||
|  | ||||
| var SecurityType = require('../models').SecurityType; | ||||
|  | ||||
| module.exports = function(state = {search: "", type: 0, templates: [], searchNumber: 0}, action) { | ||||
| 	switch (action.type) { | ||||
| 		case SecurityTemplateConstants.SEARCH_SECURITY_TEMPLATES: | ||||
| 			return { | ||||
| 				search: action.searchString, | ||||
| 				type: action.searchType, | ||||
| 				templates: [] | ||||
| 			}; | ||||
| 		case SecurityTemplateConstants.SECURITY_TEMPLATES_SEARCHED: | ||||
| 			if ((action.searchString != state.search) || (action.searchType != state.type)) | ||||
| 				return state; | ||||
| 			return { | ||||
| 				search: action.searchString, | ||||
| 				type: action.searchType, | ||||
| 				templates: action.securities | ||||
| 			}; | ||||
| 		case UserConstants.USER_LOGGEDOUT: | ||||
| 			return { | ||||
| 				search: "", | ||||
| 				type: 0, | ||||
| 				templates: [] | ||||
| 			}; | ||||
| 		default: | ||||
| 			return state; | ||||
| 	} | ||||
| }; | ||||
							
								
								
									
										23
									
								
								js/reducers/SelectedSecurityReducer.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								js/reducers/SelectedSecurityReducer.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | ||||
| var SecurityConstants = require('../constants/SecurityConstants'); | ||||
| var UserConstants = require('../constants/UserConstants'); | ||||
|  | ||||
| module.exports = function(state = -1, action) { | ||||
| 	switch (action.type) { | ||||
| 		case SecurityConstants.SECURITIES_FETCHED: | ||||
| 			for (var i = 0; i < action.securities.length; i++) { | ||||
| 				if (action.securities[i].SecurityId == state) | ||||
| 					return state; | ||||
| 			} | ||||
| 			return -1; | ||||
| 		case SecurityConstants.SECURITY_REMOVED: | ||||
| 			if (action.securityId == state) | ||||
| 				return -1; | ||||
| 			return state; | ||||
| 		case SecurityConstants.SECURITY_SELECTED: | ||||
| 			return action.securityId; | ||||
| 		case UserConstants.USER_LOGGEDOUT: | ||||
| 			return -1; | ||||
| 		default: | ||||
| 			return state; | ||||
| 	} | ||||
| }; | ||||
		Reference in New Issue
	
	Block a user