mirror of
				https://github.com/aclindsa/moneygo.git
				synced 2025-11-04 02:23:26 -05:00 
			
		
		
		
	Basic Report UI complete!
This commit is contained in:
		
							
								
								
									
										6
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								Makefile
									
									
									
									
									
								
							@@ -1,6 +1,6 @@
 | 
			
		||||
JS_SOURCES = $(wildcard js/*.js) $(wildcard js/*/*.js)
 | 
			
		||||
 | 
			
		||||
all: static/bundle.js static/react-widgets security_templates.go
 | 
			
		||||
all: static/bundle.js static/react-widgets static/codemirror/codemirror.css security_templates.go
 | 
			
		||||
 | 
			
		||||
node_modules:
 | 
			
		||||
	npm install
 | 
			
		||||
@@ -11,6 +11,10 @@ static/bundle.js: $(JS_SOURCES) node_modules
 | 
			
		||||
static/react-widgets: node_modules/react-widgets/dist node_modules
 | 
			
		||||
	rsync -a node_modules/react-widgets/dist/ static/react-widgets/
 | 
			
		||||
 | 
			
		||||
static/codemirror/codemirror.css: node_modules/codemirror/lib/codemirror.js node_modules
 | 
			
		||||
	mkdir -p static/codemirror
 | 
			
		||||
	cp node_modules/codemirror/lib/codemirror.css static/codemirror/codemirror.css
 | 
			
		||||
 | 
			
		||||
security_templates.go: cusip_list.csv
 | 
			
		||||
	./scripts/gen_security_list.py > security_templates.go
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -138,9 +138,9 @@ function create(report) {
 | 
			
		||||
				if (e.isError()) {
 | 
			
		||||
					dispatch(ErrorActions.serverError(e));
 | 
			
		||||
				} else {
 | 
			
		||||
					var a = new Report();
 | 
			
		||||
					a.fromJSON(data);
 | 
			
		||||
					dispatch(reportCreated(a));
 | 
			
		||||
					var r = new Report();
 | 
			
		||||
					r.fromJSON(data);
 | 
			
		||||
					dispatch(reportCreated(r));
 | 
			
		||||
				}
 | 
			
		||||
			},
 | 
			
		||||
			error: function(jqXHR, status, error) {
 | 
			
		||||
@@ -165,9 +165,10 @@ function update(report) {
 | 
			
		||||
				if (e.isError()) {
 | 
			
		||||
					dispatch(ErrorActions.serverError(e));
 | 
			
		||||
				} else {
 | 
			
		||||
					var a = new Report();
 | 
			
		||||
					a.fromJSON(data);
 | 
			
		||||
					dispatch(reportUpdated(a));
 | 
			
		||||
					var r = new Report();
 | 
			
		||||
					r.fromJSON(data);
 | 
			
		||||
					dispatch(reportUpdated(r));
 | 
			
		||||
					dispatch(tabulate(r));
 | 
			
		||||
				}
 | 
			
		||||
			},
 | 
			
		||||
			error: function(jqXHR, status, error) {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,25 @@
 | 
			
		||||
var React = require('react');
 | 
			
		||||
var ReactDOM = require('react-dom');
 | 
			
		||||
 | 
			
		||||
var ReactBootstrap = require('react-bootstrap');
 | 
			
		||||
 | 
			
		||||
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 Panel = ReactBootstrap.Panel;
 | 
			
		||||
var Modal = ReactBootstrap.Modal;
 | 
			
		||||
var ProgressBar = ReactBootstrap.ProgressBar;
 | 
			
		||||
 | 
			
		||||
var Combobox = require('react-widgets').Combobox;
 | 
			
		||||
 | 
			
		||||
var CodeMirror = require('react-codemirror');
 | 
			
		||||
require('codemirror/mode/lua/lua');
 | 
			
		||||
 | 
			
		||||
var StackedBarChart = require('../components/StackedBarChart');
 | 
			
		||||
var PieChart = require('../components/PieChart');
 | 
			
		||||
@@ -12,13 +28,121 @@ var models = require('../models')
 | 
			
		||||
var Report = models.Report;
 | 
			
		||||
var Tabulation = models.Tabulation;
 | 
			
		||||
 | 
			
		||||
class AddEditReportModal extends React.Component {
 | 
			
		||||
	getInitialState(props) {
 | 
			
		||||
		var s = {
 | 
			
		||||
			reportid: -1,
 | 
			
		||||
			name: "",
 | 
			
		||||
			lua: ""
 | 
			
		||||
		};
 | 
			
		||||
		if (props && props.editReport != null) {
 | 
			
		||||
			s.reportid = props.editReport.ReportId;
 | 
			
		||||
			s.name = props.editReport.Name;
 | 
			
		||||
			s.lua = props.editReport.Lua;
 | 
			
		||||
		}
 | 
			
		||||
		return s;
 | 
			
		||||
	}
 | 
			
		||||
	constructor() {
 | 
			
		||||
		super();
 | 
			
		||||
		this.state = this.getInitialState();
 | 
			
		||||
		this.onCancel = this.handleCancel.bind(this);
 | 
			
		||||
		this.onNameChange = this.handleNameChange.bind(this);
 | 
			
		||||
		this.onLuaChange = this.handleLuaChange.bind(this);
 | 
			
		||||
		this.onSubmit = this.handleSubmit.bind(this);
 | 
			
		||||
	}
 | 
			
		||||
	componentWillReceiveProps(nextProps) {
 | 
			
		||||
		if (nextProps.show && !this.props.show) {
 | 
			
		||||
			this.setState(this.getInitialState(nextProps));
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	handleCancel() {
 | 
			
		||||
		if (this.props.onCancel != null)
 | 
			
		||||
			this.props.onCancel();
 | 
			
		||||
	}
 | 
			
		||||
	handleNameChange() {
 | 
			
		||||
		this.setState({
 | 
			
		||||
			name: ReactDOM.findDOMNode(this.refs.name).value,
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
	handleLuaChange(lua) {
 | 
			
		||||
		this.setState({
 | 
			
		||||
			lua: lua
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
	handleSubmit() {
 | 
			
		||||
		var r = new Report();
 | 
			
		||||
 | 
			
		||||
		if (this.props.editReport != null)
 | 
			
		||||
			r.ReportId = this.state.reportid;
 | 
			
		||||
		r.Name = this.state.name;
 | 
			
		||||
		r.Lua = this.state.lua;
 | 
			
		||||
 | 
			
		||||
		if (this.props.onSubmit != null)
 | 
			
		||||
			this.props.onSubmit(r);
 | 
			
		||||
	}
 | 
			
		||||
	render() {
 | 
			
		||||
		var headerText = (this.props.editReport != null) ? "Edit" : "Create New";
 | 
			
		||||
		var buttonText = (this.props.editReport != null) ? "Save Changes" : "Create Report";
 | 
			
		||||
 | 
			
		||||
		var codeMirrorOptions = {
 | 
			
		||||
			lineNumbers: true,
 | 
			
		||||
			mode: 'lua',
 | 
			
		||||
		};
 | 
			
		||||
		return (
 | 
			
		||||
			<Modal show={this.props.show} onHide={this.onCancel} bsSize="large">
 | 
			
		||||
				<Modal.Header closeButton>
 | 
			
		||||
					<Modal.Title>{headerText} Report</Modal.Title>
 | 
			
		||||
				</Modal.Header>
 | 
			
		||||
				<Modal.Body>
 | 
			
		||||
				<Form horizontal onSubmit={this.onSubmit}>
 | 
			
		||||
					<FormGroup>
 | 
			
		||||
						<Col componentClass={ControlLabel} xs={3}>Name</Col>
 | 
			
		||||
						<Col xs={9}>
 | 
			
		||||
						<FormControl type="text"
 | 
			
		||||
							value={this.state.name}
 | 
			
		||||
							onChange={this.onNameChange}
 | 
			
		||||
							ref="name"/>
 | 
			
		||||
						</Col>
 | 
			
		||||
					</FormGroup>
 | 
			
		||||
					<FormGroup>
 | 
			
		||||
						<Col componentClass={ControlLabel} xs={3}>Lua Code</Col>
 | 
			
		||||
						<Col xs={9}>
 | 
			
		||||
						<CodeMirror
 | 
			
		||||
							value={this.state.lua}
 | 
			
		||||
							onChange={this.onLuaChange}
 | 
			
		||||
							options={codeMirrorOptions} />
 | 
			
		||||
						</Col>
 | 
			
		||||
					</FormGroup>
 | 
			
		||||
				</Form>
 | 
			
		||||
				</Modal.Body>
 | 
			
		||||
				<Modal.Footer>
 | 
			
		||||
					<ButtonGroup className="pull-right">
 | 
			
		||||
						<Button onClick={this.onCancel} bsStyle="warning">Cancel</Button>
 | 
			
		||||
						<Button onClick={this.onSubmit} bsStyle="success">{buttonText}</Button>
 | 
			
		||||
					</ButtonGroup>
 | 
			
		||||
				</Modal.Footer>
 | 
			
		||||
			</Modal>
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class ReportsTab extends React.Component {
 | 
			
		||||
	constructor() {
 | 
			
		||||
		super();
 | 
			
		||||
		this.state = {
 | 
			
		||||
			initialized: false
 | 
			
		||||
			initialized: false,
 | 
			
		||||
			creatingNewReport: false,
 | 
			
		||||
			editingReport: false
 | 
			
		||||
		}
 | 
			
		||||
		this.onSelectSeries = this.handleSelectSeries.bind(this);
 | 
			
		||||
		this.onSelectReport = this.handleSelectReport.bind(this);
 | 
			
		||||
		this.onNewReport = this.handleNewReport.bind(this);
 | 
			
		||||
		this.onEditReport = this.handleEditReport.bind(this);
 | 
			
		||||
		this.onDeleteReport = this.handleDeleteReport.bind(this);
 | 
			
		||||
		this.onCreationCancel = this.handleCreationCancel.bind(this);
 | 
			
		||||
		this.onCreationSubmit = this.handleCreationSubmit.bind(this);
 | 
			
		||||
		this.onEditingCancel = this.handleEditingCancel.bind(this);
 | 
			
		||||
		this.onEditingSubmit = this.handleEditingSubmit.bind(this);
 | 
			
		||||
	}
 | 
			
		||||
	componentWillMount() {
 | 
			
		||||
		this.props.onFetchAllReports();
 | 
			
		||||
@@ -27,80 +151,164 @@ class ReportsTab extends React.Component {
 | 
			
		||||
		var selected = nextProps.reports.selected;
 | 
			
		||||
		if (!this.state.initialized) {
 | 
			
		||||
			if (selected == -1 &&
 | 
			
		||||
					nextProps.reports.list.length > 0)
 | 
			
		||||
					nextProps.reports.list.length > 0) {
 | 
			
		||||
				nextProps.onSelectReport(nextProps.reports.map[nextProps.reports.list[0]]);
 | 
			
		||||
			this.setState({initialized: true});
 | 
			
		||||
		} else if (selected != -1 && !nextProps.reports.tabulations.hasOwnProperty(selected)) {
 | 
			
		||||
			nextProps.onTabulateReport(nextProps.reports.map[nextProps.reports.list[0]]);
 | 
			
		||||
		} else if (selected != -1 && nextProps.reports.selectedTabulation == null) {
 | 
			
		||||
			nextProps.onSelectSeries(nextProps.reports.tabulations[nextProps.reports.list[0]]);
 | 
			
		||||
				nextProps.onTabulateReport(nextProps.reports.map[nextProps.reports.list[0]]);
 | 
			
		||||
				this.setState({initialized: true});
 | 
			
		||||
			}
 | 
			
		||||
		} else if (selected != -1 &&
 | 
			
		||||
				nextProps.reports.tabulations.hasOwnProperty(selected) &&
 | 
			
		||||
				nextProps.reports.selectedTabulation == null) {
 | 
			
		||||
			nextProps.onSelectSeries(nextProps.reports.tabulations[selected]);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	handleSelectSeries(series) {
 | 
			
		||||
		if (series == Tabulation.topLevelSeriesName())
 | 
			
		||||
			return;
 | 
			
		||||
		var seriesTraversal = this.props.selectedTabulation.seriesTraversal.slice();
 | 
			
		||||
		var seriesTraversal = this.props.reports.seriesTraversal.slice();
 | 
			
		||||
		seriesTraversal.push(series);
 | 
			
		||||
		var selectedTabulation = this.props.reports.tabulations[this.props.reports.selected];
 | 
			
		||||
		this.props.onSelectSeries(selectedTabulation, seriesTraversal);
 | 
			
		||||
	}
 | 
			
		||||
	handleSelectReport(report) {
 | 
			
		||||
		this.props.onSelectReport(report);
 | 
			
		||||
		if (!this.props.reports.tabulations.hasOwnProperty(report.ReportId))
 | 
			
		||||
			this.props.onTabulateReport(report);
 | 
			
		||||
	}
 | 
			
		||||
	handleNewReport() {
 | 
			
		||||
		this.setState({creatingNewReport: true});
 | 
			
		||||
	}
 | 
			
		||||
	handleEditReport() {
 | 
			
		||||
		this.setState({editingReport: true});
 | 
			
		||||
	}
 | 
			
		||||
	handleDeleteReport() {
 | 
			
		||||
		this.props.onDeleteReport(this.props.reports.map[this.props.reports.selected]);
 | 
			
		||||
	}
 | 
			
		||||
	handleCreationCancel() {
 | 
			
		||||
		this.setState({creatingNewReport: false});
 | 
			
		||||
	}
 | 
			
		||||
	handleCreationSubmit(report) {
 | 
			
		||||
		this.setState({creatingNewReport: false});
 | 
			
		||||
		this.props.onCreateReport(report);
 | 
			
		||||
	}
 | 
			
		||||
	handleEditingCancel() {
 | 
			
		||||
		this.setState({editingReport: false});
 | 
			
		||||
	}
 | 
			
		||||
	handleEditingSubmit(report) {
 | 
			
		||||
		this.setState({editingReport: false});
 | 
			
		||||
		this.props.onUpdateReport(report);
 | 
			
		||||
	}
 | 
			
		||||
	render() {
 | 
			
		||||
		var selectedTabulation = this.props.reports.selectedTabulation;
 | 
			
		||||
		if (!selectedTabulation) {
 | 
			
		||||
			return (
 | 
			
		||||
				<div></div>
 | 
			
		||||
		var reportPanel = [];
 | 
			
		||||
		if (selectedTabulation) {
 | 
			
		||||
			var titleTracks = [];
 | 
			
		||||
			var seriesTraversal = [];
 | 
			
		||||
 | 
			
		||||
			for (var i = 0; i < this.props.reports.seriesTraversal.length; i++) {
 | 
			
		||||
				var name = this.props.reports.selectedTabulation.Title;
 | 
			
		||||
				if (i > 0)
 | 
			
		||||
					name = this.props.reports.seriesTraversal[i-1];
 | 
			
		||||
 | 
			
		||||
				// Make a closure for going up the food chain
 | 
			
		||||
				var self = this;
 | 
			
		||||
				var navOnClick = function() {
 | 
			
		||||
					var onSelectSeries = self.props.onSelectSeries;
 | 
			
		||||
					var tabulation = self.props.reports.tabulations[self.props.reports.selected];
 | 
			
		||||
					var mySeriesTraversal = seriesTraversal.slice();
 | 
			
		||||
					return function() {
 | 
			
		||||
						onSelectSeries(tabulation, mySeriesTraversal);
 | 
			
		||||
					};
 | 
			
		||||
				}();
 | 
			
		||||
				titleTracks.push((
 | 
			
		||||
					<Button key={i*2} bsStyle="link"
 | 
			
		||||
							onClick={navOnClick}>
 | 
			
		||||
						{name}
 | 
			
		||||
					</Button>
 | 
			
		||||
				));
 | 
			
		||||
				titleTracks.push((<span key={i*2+1}>/</span>));
 | 
			
		||||
				seriesTraversal.push(this.props.reports.seriesTraversal[i]);
 | 
			
		||||
			}
 | 
			
		||||
			if (titleTracks.length == 0) {
 | 
			
		||||
				titleTracks.push((
 | 
			
		||||
					<Button key={0} bsStyle="link">
 | 
			
		||||
						{this.props.reports.selectedTabulation.Title}
 | 
			
		||||
					</Button>
 | 
			
		||||
				));
 | 
			
		||||
			} else {
 | 
			
		||||
				var i = this.props.reports.seriesTraversal.length-1;
 | 
			
		||||
				titleTracks.push((
 | 
			
		||||
					<Button key={i*2+2} bsStyle="link">
 | 
			
		||||
					{this.props.reports.seriesTraversal[i]}
 | 
			
		||||
					</Button>
 | 
			
		||||
				));
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (this.props.reports.selectedTabulation.Labels.length > 1)
 | 
			
		||||
				var report = (
 | 
			
		||||
					<StackedBarChart
 | 
			
		||||
						report={this.props.reports.selectedTabulation}
 | 
			
		||||
						onSelectSeries={this.onSelectSeries}
 | 
			
		||||
						seriesTraversal={this.props.reports.seriesTraversal} />
 | 
			
		||||
				);
 | 
			
		||||
			else
 | 
			
		||||
				var report = (
 | 
			
		||||
					<PieChart
 | 
			
		||||
						report={this.props.reports.selectedTabulation}
 | 
			
		||||
						onSelectSeries={this.onSelectSeries}
 | 
			
		||||
						seriesTraversal={this.props.reports.seriesTraversal} />
 | 
			
		||||
				);
 | 
			
		||||
 | 
			
		||||
			reportPanel = (
 | 
			
		||||
				<Panel header={titleTracks}>
 | 
			
		||||
					{report}
 | 
			
		||||
				</Panel>
 | 
			
		||||
			);
 | 
			
		||||
		} else if (this.props.reports.selected != -1) {
 | 
			
		||||
			reportPanel = (
 | 
			
		||||
				<Panel header={this.props.reports.map[this.props.reports.selected].Name}>
 | 
			
		||||
					<ProgressBar active now={100} label={"Tabulating Report..."} />
 | 
			
		||||
				</Panel>
 | 
			
		||||
			);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		var titleTracks = [];
 | 
			
		||||
		var seriesTraversal = [];
 | 
			
		||||
 | 
			
		||||
		for (var i = 0; i < this.props.selectedTabulation.seriesTraversal.length; i++) {
 | 
			
		||||
			var name = this.props.selectedTabulation.tabulation.Title;
 | 
			
		||||
			if (i > 0)
 | 
			
		||||
				name = this.props.selectedTabulation.seriesTraversal[i-1];
 | 
			
		||||
 | 
			
		||||
			// Make a closure for going up the food chain
 | 
			
		||||
			var self = this;
 | 
			
		||||
			var navOnClick = function() {
 | 
			
		||||
				var onSelectTabulation = self.props.onSelectTabulation;
 | 
			
		||||
				var report = self.props.reports[self.props.selectedTabulation.tabulation.ReportId];
 | 
			
		||||
				var mySeriesTraversal = seriesTraversal.slice();
 | 
			
		||||
				return function() {
 | 
			
		||||
					onSelectTabulation(report, mySeriesTraversal);
 | 
			
		||||
				};
 | 
			
		||||
			}();
 | 
			
		||||
			titleTracks.push((
 | 
			
		||||
				<Button key={i*2} bsStyle="link"
 | 
			
		||||
						onClick={navOnClick}>
 | 
			
		||||
					{name}
 | 
			
		||||
				</Button>
 | 
			
		||||
			));
 | 
			
		||||
			titleTracks.push((<span key={i*2+1}>/</span>));
 | 
			
		||||
			seriesTraversal.push(this.props.selectedTabulation.seriesTraversal[i]);
 | 
			
		||||
		}
 | 
			
		||||
		if (titleTracks.length == 0) {
 | 
			
		||||
			titleTracks.push((
 | 
			
		||||
				<Button key={0} bsStyle="link">
 | 
			
		||||
					{this.props.selectedTabulation.tabulation.Title}
 | 
			
		||||
				</Button>
 | 
			
		||||
			));
 | 
			
		||||
		} else {
 | 
			
		||||
			var i = this.props.selectedTabulation.seriesTraversal.length-1;
 | 
			
		||||
			titleTracks.push((
 | 
			
		||||
				<Button key={i*2+2} bsStyle="link">
 | 
			
		||||
				{this.props.selectedTabulation.seriesTraversal[i]}
 | 
			
		||||
				</Button>
 | 
			
		||||
			));
 | 
			
		||||
		}
 | 
			
		||||
		var noReportSelected = this.props.reports.selected == -1;
 | 
			
		||||
		var selectedReport = -1;
 | 
			
		||||
		if (this.props.reports.map.hasOwnProperty(this.props.reports.selected))
 | 
			
		||||
			selectedReport = this.props.reports.map[this.props.reports.selected];
 | 
			
		||||
 | 
			
		||||
		return (
 | 
			
		||||
			<Panel header={titleTracks}>
 | 
			
		||||
				<PieChart
 | 
			
		||||
					report={this.props.selectedTabulation.tabulation}
 | 
			
		||||
					onSelectSeries={this.onSelectSeries}
 | 
			
		||||
					seriesTraversal={this.props.selectedTabulation.seriesTraversal} />
 | 
			
		||||
			</Panel>
 | 
			
		||||
			<div>
 | 
			
		||||
			<AddEditReportModal
 | 
			
		||||
				show={this.state.creatingNewReport}
 | 
			
		||||
				onCancel={this.onCreationCancel}
 | 
			
		||||
				onSubmit={this.onCreationSubmit} />
 | 
			
		||||
			<AddEditReportModal
 | 
			
		||||
				show={this.state.editingReport}
 | 
			
		||||
				editReport={selectedReport}
 | 
			
		||||
				onCancel={this.onEditingCancel}
 | 
			
		||||
				onSubmit={this.onEditingSubmit} />
 | 
			
		||||
			<ButtonToolbar>
 | 
			
		||||
			<ButtonGroup>
 | 
			
		||||
				<Button onClick={this.onNewReport} bsStyle="success"><Glyphicon glyph='plus-sign'/> New Report</Button>
 | 
			
		||||
			</ButtonGroup>
 | 
			
		||||
			<ButtonGroup>
 | 
			
		||||
				<Combobox
 | 
			
		||||
					data={this.props.report_list}
 | 
			
		||||
					valueField='ReportId'
 | 
			
		||||
					textField={item => typeof item === 'string' ? item : item.Name}
 | 
			
		||||
					value={selectedReport}
 | 
			
		||||
					onChange={this.onSelectReport}
 | 
			
		||||
					suggest
 | 
			
		||||
					filter='contains'
 | 
			
		||||
					ref="report" />
 | 
			
		||||
			</ButtonGroup>
 | 
			
		||||
			<ButtonGroup>
 | 
			
		||||
				<Button onClick={this.onEditReport} bsStyle="primary" disabled={noReportSelected}><Glyphicon glyph='cog'/> Edit Report</Button>
 | 
			
		||||
				<Button onClick={this.onDeleteReport} bsStyle="danger" disabled={noReportSelected}><Glyphicon glyph='trash'/> Delete Report</Button>
 | 
			
		||||
			</ButtonGroup></ButtonToolbar>
 | 
			
		||||
			{reportPanel}
 | 
			
		||||
			</div>
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -135,12 +135,12 @@ class StackedBarChart extends React.Component {
 | 
			
		||||
				if (value == 0)
 | 
			
		||||
					continue;
 | 
			
		||||
				if (value > 0) {
 | 
			
		||||
					rectHeight = y(value) - y(0);
 | 
			
		||||
					var rectHeight = y(value) - y(0);
 | 
			
		||||
					positiveSum[j] += rectHeight;
 | 
			
		||||
					rectY = height - y(0) - positiveSum[j];
 | 
			
		||||
					var rectY = height - y(0) - positiveSum[j];
 | 
			
		||||
				} else {
 | 
			
		||||
					rectHeight = y(0) - y(value);
 | 
			
		||||
					rectY = height - y(0) + negativeSum[j];
 | 
			
		||||
					var rectHeight = y(0) - y(value);
 | 
			
		||||
					var rectY = height - y(0) + negativeSum[j];
 | 
			
		||||
					negativeSum[j] += rectHeight;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -4,8 +4,14 @@ var ReportActions = require('../actions/ReportActions');
 | 
			
		||||
var ReportsTab = require('../components/ReportsTab');
 | 
			
		||||
 | 
			
		||||
function mapStateToProps(state) {
 | 
			
		||||
	var report_list = [];
 | 
			
		||||
	for (var reportId in state.reports.map) {
 | 
			
		||||
		if (state.reports.map.hasOwnProperty(reportId))
 | 
			
		||||
			report_list.push(state.reports.map[reportId]);
 | 
			
		||||
	}
 | 
			
		||||
	return {
 | 
			
		||||
		reports: state.reports
 | 
			
		||||
		reports: state.reports,
 | 
			
		||||
		report_list: report_list
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										32
									
								
								js/models.js
									
									
									
									
									
								
							
							
						
						
									
										32
									
								
								js/models.js
									
									
									
									
									
								
							@@ -435,6 +435,35 @@ class Error {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class Report {
 | 
			
		||||
	constructor() {
 | 
			
		||||
		this.ReportId = -1;
 | 
			
		||||
		this.UserId = -1;
 | 
			
		||||
		this.Name = "";
 | 
			
		||||
		this.Lua = "";
 | 
			
		||||
	}
 | 
			
		||||
	toJSON() {
 | 
			
		||||
		var json_obj = {};
 | 
			
		||||
		json_obj.ReportId = this.ReportId;
 | 
			
		||||
		json_obj.UserId = this.UserId;
 | 
			
		||||
		json_obj.Name = this.Name;
 | 
			
		||||
		json_obj.Lua = this.Lua;
 | 
			
		||||
		return JSON.stringify(json_obj);
 | 
			
		||||
	}
 | 
			
		||||
	fromJSON(json_input) {
 | 
			
		||||
		var json_obj = getJSONObj(json_input)
 | 
			
		||||
 | 
			
		||||
		if (json_obj.hasOwnProperty("ReportId"))
 | 
			
		||||
			this.ReportId = json_obj.ReportId;
 | 
			
		||||
		if (json_obj.hasOwnProperty("UserId"))
 | 
			
		||||
			this.UserId = json_obj.UserId;
 | 
			
		||||
		if (json_obj.hasOwnProperty("Name"))
 | 
			
		||||
			this.Name = json_obj.Name;
 | 
			
		||||
		if (json_obj.hasOwnProperty("Lua"))
 | 
			
		||||
			this.Lua = json_obj.Lua;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class Series {
 | 
			
		||||
	constructor() {
 | 
			
		||||
		this.Values = [];
 | 
			
		||||
@@ -496,7 +525,7 @@ class Series {
 | 
			
		||||
 | 
			
		||||
class Tabulation {
 | 
			
		||||
	constructor() {
 | 
			
		||||
		this.ReportId = "";
 | 
			
		||||
		this.ReportId = -1;
 | 
			
		||||
		this.Title = "";
 | 
			
		||||
		this.Subtitle = "";
 | 
			
		||||
		this.Units = "";
 | 
			
		||||
@@ -578,6 +607,7 @@ module.exports = {
 | 
			
		||||
	Account: Account,
 | 
			
		||||
	Split: Split,
 | 
			
		||||
	Transaction: Transaction,
 | 
			
		||||
	Report: Report,
 | 
			
		||||
	Tabulation: Tabulation,
 | 
			
		||||
	OFXDownload: OFXDownload,
 | 
			
		||||
	Error: Error,
 | 
			
		||||
 
 | 
			
		||||
@@ -63,16 +63,19 @@ module.exports = function(state = initialState, action) {
 | 
			
		||||
				selectedTabulation: null,
 | 
			
		||||
				seriesTraversal: []
 | 
			
		||||
			});
 | 
			
		||||
		case ReportConstants.TABULATION_FETCHED:
 | 
			
		||||
		case ReportConstants.REPORT_TABULATED:
 | 
			
		||||
			var tabulation = action.tabulation;
 | 
			
		||||
			return assign({}, state, {
 | 
			
		||||
			var tabulations = assign({}, state.tabulations, {
 | 
			
		||||
				[tabulation.ReportId]: tabulation
 | 
			
		||||
			});
 | 
			
		||||
			return assign({}, state, {
 | 
			
		||||
				tabulations: tabulations
 | 
			
		||||
			});
 | 
			
		||||
		case ReportConstants.SERIES_SELECTED:
 | 
			
		||||
			return {
 | 
			
		||||
			return assign({}, state, {
 | 
			
		||||
				selectedTabulation: action.tabulation,
 | 
			
		||||
				seriesTraversal: action.seriesTraversal
 | 
			
		||||
			};
 | 
			
		||||
			});
 | 
			
		||||
		case UserConstants.USER_LOGGEDOUT:
 | 
			
		||||
			return initialState;
 | 
			
		||||
		default:
 | 
			
		||||
 
 | 
			
		||||
@@ -19,6 +19,7 @@
 | 
			
		||||
    "react-dom": "^15.3.2",
 | 
			
		||||
    "react-redux": "^5.0.5",
 | 
			
		||||
    "react-widgets": "^3.4.4",
 | 
			
		||||
    "react-codemirror": "^1.0.0",
 | 
			
		||||
    "redux": "^3.6.0",
 | 
			
		||||
    "redux-thunk": "^2.1.0"
 | 
			
		||||
  },
 | 
			
		||||
 
 | 
			
		||||
@@ -203,6 +203,8 @@ func ReportTabulationHandler(w http.ResponseWriter, r *http.Request, user *User,
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	tabulation.ReportId = reportid
 | 
			
		||||
 | 
			
		||||
	err = tabulation.Write(w)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		WriteError(w, 999 /*Internal Error*/)
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,7 @@
 | 
			
		||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
 | 
			
		||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css">
 | 
			
		||||
<link rel="stylesheet" href="static/react-widgets/css/react-widgets.css">
 | 
			
		||||
<link rel="stylesheet" href="static/codemirror/codemirror.css">
 | 
			
		||||
<link rel="stylesheet" href="static/css/stylesheet.css">
 | 
			
		||||
 | 
			
		||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.js"></script>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user