diff --git a/static/accounts.js b/static/accounts.js index 9ce2906..43c1718 100644 --- a/static/accounts.js +++ b/static/accounts.js @@ -12,6 +12,8 @@ var Glyphicon = ReactBootstrap.Glyphicon; var Modal = ReactBootstrap.Modal; +var CollapsibleMixin = ReactBootstrap.CollapsibleMixin; + var Combobox = ReactWidgets.Combobox; const recursiveAccountDisplayInfo = function(account, prefix) { @@ -26,7 +28,7 @@ const getAccountDisplayList = function(account_list, includeRoot, rootName) { if (includeRoot) accounts.push({AccountId: -1, Name: rootName}); for (var i = 0; i < account_list.length; i++) { - if (account_list[i].ParentAccountId == -1) + if (account_list[i].isRootAccount()) accounts = accounts.concat(recursiveAccountDisplayInfo(account_list[i], "")); } return accounts; @@ -167,9 +169,105 @@ const NewAccountModal = React.createClass({ } }); +const AccountTreeNode = React.createClass({ + mixins: [CollapsibleMixin], + getCollapsibleDOMNode: function() { + return React.findDOMNode(this.refs.children); + }, + getCollapsibleDimensionValue: function() { + return React.findDOMNode(this.refs.children).scrollHeight; + }, + handleToggle: function(e) { + e.preventDefault(); + this.setState({expanded:!this.state.expanded}); + }, + handleChildSelect: function(account) { + if (this.props.onSelect != null) + this.props.onSelect(account); + }, + handleSelect: function() { + if (this.props.onSelect != null) + this.props.onSelect(this.props.account); + }, + render: function() { + var styles = this.getCollapsibleClassSet(); + var glyph = this.isExpanded() ? 'minus' : 'plus'; + var active = (this.props.selectedAccount != null && + this.props.account.AccountId == this.props.selectedAccount.AccountId); + var buttonStyle = active ? "info" : "link"; + + var self = this; + var children = this.props.account.Children.map(function(account) { + return ( + + ); + }); + var accounttreeClasses = "accounttree" + var expandButton = []; + if (children.length > 0) + expandButton.push(( + + )); + else + accounttreeClasses += "-nochildren"; + return ( +
+ {expandButton} + +
+ {children} +
+
+ ); + } +}); + +const AccountTree = React.createClass({ + getInitialState: function() { + return {selectedAccount: null}; + }, + handleSelect: function(account) { + this.setState({selectedAccount: account}); + if (this.props.onSelect != null) { + this.props.onSelect(account); + } + }, + render: function() { + var accounts = this.props.accounts; + + var children = []; + for (var i = 0; i < accounts.length; i++) { + if (accounts[i].isRootAccount()) + children.push(()); + } + + return ( +
+ {children} +
+ ); + } +}); + const AccountsTab = React.createClass({ getInitialState: function() { return { + selectedAccount: null, creatingNewAccount: false }; }, @@ -190,16 +288,13 @@ const AccountsTab = React.createClass({ this.props.onCreateAccount(account); this.setState({creatingNewAccount: false}); }, + handleAccountSelected: function(account) { + this.setState({selectedAccount: account}); + }, render: function() { var accounts = this.props.accounts; var account_map = this.props.account_map; - var listGroupItems = accounts.map(function(account) { - return ( - {account.Name} - ); - }); - return ( @@ -210,9 +305,9 @@ const AccountsTab = React.createClass({ onCancel={this.handleCreationCancel} onSubmit={this.handleCreateAccount} securities={this.props.securities}/> - - {listGroupItems} - + diff --git a/static/external/classnames/index.js b/static/external/classnames/index.js new file mode 100644 index 0000000..afb8eed --- /dev/null +++ b/static/external/classnames/index.js @@ -0,0 +1,49 @@ +/*! + Copyright (c) 2015 Jed Watson. + Licensed under the MIT License (MIT), see + http://jedwatson.github.io/classnames +*/ + +(function () { + 'use strict'; + + function classNames () { + + var classes = ''; + + for (var i = 0; i < arguments.length; i++) { + var arg = arguments[i]; + if (!arg) continue; + + var argType = typeof arg; + + if ('string' === argType || 'number' === argType) { + classes += ' ' + arg; + + } else if (Array.isArray(arg)) { + classes += ' ' + classNames.apply(null, arg); + + } else if ('object' === argType) { + for (var key in arg) { + if (arg.hasOwnProperty(key) && arg[key]) { + classes += ' ' + key; + } + } + } + } + + return classes.substr(1); + } + + if (typeof module !== 'undefined' && module.exports) { + module.exports = classNames; + } else if (typeof define === 'function' && typeof define.amd === 'object' && define.amd){ + // AMD. Register as an anonymous module. + define(function () { + return classNames; + }); + } else { + window.classNames = classNames; + } + +}()); diff --git a/static/index.html b/static/index.html index 9e14a8c..825fd09 100644 --- a/static/index.html +++ b/static/index.html @@ -15,6 +15,7 @@ + diff --git a/static/stylesheet.css b/static/stylesheet.css index cfeaad3..88d5767 100644 --- a/static/stylesheet.css +++ b/static/stylesheet.css @@ -7,3 +7,26 @@ div#content { margin-left: auto; margin-right: auto; } + +div.accounttree-root-nochildren { + position: relative; + left: 24px; +} +div.accounttree { + position: relative; + left: -24px; +} +div.accounttree-nochildren { + position: relative; + left: 0px; +} + +div.accounttree div { + padding-left: 24px; +} +div.accounttree-root div { + padding-left: 24px; +} +.accounttree-name { + padding: 3px; +}