catreact
Version:
Catavolt Core React Components
255 lines (254 loc) • 16.1 kB
JavaScript
/**
* Created by rburson on 4/27/16.
*/
"use strict";
var __assign = (this && this.__assign) || Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
///<reference path="../../../typings/recharts/recharts.d.ts"/>
var React = require('react');
var catreact_1 = require('../catreact');
var catavolt_sdk_1 = require('catavolt-sdk');
var recharts_1 = require('recharts');
/* Base mixin for Charts */
exports.CvChart = {
colorForDataPointDef: function (dataPointDef, i) {
return dataPointDef.seriesColor || this.props.defaultSeriesColors[i % this.props.defaultSeriesColors.length];
},
getMetaValues: function (graphDef) {
var minX = graphDef.xAxisRangeFrom ? graphDef.xAxisRangeFrom : 0;
var maxX = graphDef.xAxisRangeTo ? graphDef.xAxisRangeTo : 'auto';
var minY = graphDef.yAxisRangeFrom ? graphDef.yAxisRangeFrom : 0;
var maxY = graphDef.yAxisRangeTo ? graphDef.yAxisRangeTo : 'auto';
var xAxisLabel = graphDef.xAxisLabel;
var yAxisLabel = graphDef.yAxisLabel;
return { minX: minX, maxX: maxX, minY: minY, maxY: maxY, xAxisLabel: xAxisLabel, yAxisLabel: yAxisLabel };
},
handleClick: function (id) {
if (this.props.clickHandler) {
this.props.clickHandler(id);
}
},
isNumeric: function (graphContext, propName) {
var propDef = graphContext.propDefAtName(propName);
return propDef && propDef.isNumericType;
}
};
/* Cartesian style line chart */
exports.CvLineChart = React.createClass({
mixins: [exports.CvChart],
render: function () {
var _this = this;
var graphDef = this.props.graphContext.graphDef;
var _a = this.getMetaValues(graphDef), minX = _a.minX, maxX = _a.maxX, minY = _a.minY, maxY = _a.maxY, xAxisLabel = _a.xAxisLabel, yAxisLabel = _a.yAxisLabel;
var xType = this.isNumeric(this.props.graphContext, graphDef.identityDataPointDef.name) ? 'numeric' : 'category';
var yType = this.isNumeric(this.props.graphContext, graphDef.dataPointDefs[0].name) ? 'numeric' : 'category';
return (React.createElement("div", {className: "cv-graph-container"}, React.createElement(recharts_1.ResponsiveContainer, {width: "99%", height: "95%"}, React.createElement(recharts_1.LineChart, {data: this.props.data, margin: { top: 20, right: 50, left: 20, bottom: 5 }}, React.createElement(recharts_1.XAxis, {dataKey: this.props.identPropName, domain: [minX, maxX], label: xAxisLabel}), React.createElement(recharts_1.YAxis, {domain: [minY, maxY], label: yAxisLabel}), React.createElement(recharts_1.CartesianGrid, {strokeDasharray: "3 3"}), React.createElement(recharts_1.Tooltip, null), React.createElement(recharts_1.Legend, null), graphDef.dataPointDefs.map(function (dataPointDef, i) {
var color = _this.colorForDataPointDef(dataPointDef, i);
var legendKey = dataPointDef.legendKey || dataPointDef.name;
return React.createElement(recharts_1.Line, {type: "monotone", dataKey: dataPointDef.name, name: legendKey, dot: true, activeDot: true, stroke: color});
})))));
},
});
exports.CvBarChart = React.createClass({
mixins: [exports.CvChart],
render: function () {
var _this = this;
var graphDef = this.props.graphContext.graphDef;
var _a = this.getMetaValues(graphDef), minX = _a.minX, maxX = _a.maxX, minY = _a.minY, maxY = _a.maxY, xAxisLabel = _a.xAxisLabel, yAxisLabel = _a.yAxisLabel;
var xType = this.isNumeric(this.props.graphContext, graphDef.identityDataPointDef.name) ? 'numeric' : 'category';
var yType = this.isNumeric(this.props.graphContext, graphDef.dataPointDefs[0].name) ? 'numeric' : 'category';
return (React.createElement("div", {className: "cv-graph-container"}, React.createElement(recharts_1.ResponsiveContainer, {width: "99%", height: "95%"}, React.createElement(recharts_1.BarChart, {data: this.props.data, margin: { top: 20, right: 50, left: 20, bottom: 5 }}, React.createElement(recharts_1.XAxis, {dataKey: this.props.identPropName, domain: [minX, maxX], label: xAxisLabel}), React.createElement(recharts_1.YAxis, {domain: [minY, maxY], label: yAxisLabel}), React.createElement(recharts_1.CartesianGrid, {strokeDasharray: "3 3"}), React.createElement(recharts_1.Tooltip, null), React.createElement(recharts_1.Legend, null), graphDef.dataPointDefs.map(function (dataPointDef, i) {
var legendKey = dataPointDef.legendKey || dataPointDef.name;
var props = {
dataKey: dataPointDef.name,
name: legendKey,
fill: _this.colorForDataPointDef(dataPointDef, i),
onClick: function (data) { _this.handleClick(data.id); }
};
if (_this.props.stack)
props['stackId'] = 'a';
return React.createElement(recharts_1.Bar, __assign({}, props));
})))));
}
});
exports.CvScatterChart = React.createClass({
mixins: [exports.CvChart],
render: function () {
var _this = this;
var graphDef = this.props.graphContext.graphDef;
var _a = this.getMetaValues(graphDef), minX = _a.minX, maxX = _a.maxX, minY = _a.minY, maxY = _a.maxY, xAxisLabel = _a.xAxisLabel, yAxisLabel = _a.yAxisLabel;
//note: to support multiple 'scatter series' the data set has to be broken in corresponding discrete sets
//for now, we're taking the first dataPointDef only
var dataPointDef = graphDef.dataPointDefs[0];
var xType = this.isNumeric(this.props.graphContext, dataPointDef.xAxisName) ? 'numeric' : 'category';
var yType = this.isNumeric(this.props.graphContext, dataPointDef.name) ? 'numeric' : 'category';
if (dataPointDef) {
var legendKey = dataPointDef.legendKey || dataPointDef.name;
return (React.createElement("div", {className: "cv-graph-container"}, React.createElement(recharts_1.ResponsiveContainer, {width: "99%", height: "95%"}, React.createElement(recharts_1.ScatterChart, {margin: { top: 20, right: 50, left: 20, bottom: 5 }}, React.createElement(recharts_1.XAxis, {dataKey: dataPointDef.xAxisName, name: dataPointDef.xAxisName, domain: [minX, maxX], label: xAxisLabel}), React.createElement(recharts_1.YAxis, {dataKey: dataPointDef.name, name: legendKey, domain: [minY, maxY], label: yAxisLabel}), (function () {
if (_this.props.bubble) {
if (dataPointDef.bubbleRadiusName) {
return React.createElement(recharts_1.ZAxis, {dataKey: dataPointDef.bubbleRadiusName, name: dataPointDef.bubbleRadiusName, range: [10000, 50000]});
}
else {
return React.createElement(recharts_1.ZAxis, {dataKey: dataPointDef.bubbleRadiusName, name: dataPointDef.bubbleRadiusName, range: [10000, 10000]});
}
}
else {
return React.createElement(recharts_1.ZAxis, null);
}
})(), React.createElement(recharts_1.CartesianGrid, null), React.createElement(recharts_1.Tooltip, {cursor: { strokeDasharray: '3 3' }}), React.createElement(recharts_1.Legend, null), React.createElement(recharts_1.Scatter, {data: this.props.data, fill: this.colorForDataPointDef(dataPointDef, 0), onClick: function (data) { }})))));
}
else {
return null;
}
}
});
exports.CvPieChart = React.createClass({
mixins: [exports.CvChart],
render: function () {
var _this = this;
var graphDef = this.props.graphContext.graphDef;
//note: to support multiple 'pie levels' the data set has to be broken in corresponding discrete sets
//for now, we're taking the first dataPointDef only
var dataPointDef = graphDef.dataPointDefs[0];
if (dataPointDef) {
var legendKey = dataPointDef.legendKey || dataPointDef.name;
return (React.createElement("div", {className: "cv-graph-container"}, React.createElement(recharts_1.ResponsiveContainer, {width: "99%", height: "95%"}, React.createElement(recharts_1.PieChart, {margin: { top: 20, right: 50, left: 20, bottom: 5 }, onClick: function (data) { _this.handleClick(data.payload.id); }}, React.createElement(recharts_1.Tooltip, {cursor: { strokeDasharray: '3 3' }}), React.createElement(recharts_1.Legend, null), React.createElement(recharts_1.Pie, {data: this.props.data, fill: this.colorForDataPointDef(dataPointDef, 0), nameKey: this.props.identPropName, valueKey: dataPointDef.name, label: true})))));
}
else {
return null;
}
}
});
/*
***************************************************
* Render a Graph
***************************************************
*/
exports.CvGraphPanel = React.createClass({
mixins: [catreact_1.CvBaseMixin],
componentDidMount: function () {
},
getDefaultProps: function () {
return {
paneRef: null,
formContext: null,
graphContext: null,
navigationListeners: [],
selectionListener: null,
stateChangeListeners: [],
actionListeners: [],
defaultSeriesColors: ['#1E6FF2', '#F29500', '#15BFA2', '#6F5F5A'],
navTarget: null,
actionProvider: null
};
},
getInitialState: function () {
return {};
},
render: function () {
var _this = this;
var _a = this.state;
var graphPaneProps = {
paneRef: this.props.paneRef,
formContext: this.props.formContext,
queryContext: this.props.graphContext,
stateChangeListeners: this.props.stateChangeListeners,
actionProvider: this.props.actionProvider
};
return (React.createElement(catreact_1.CvQueryPane, __assign({}, graphPaneProps, {queryRenderer: function (cvContext, callback) {
var graphContext = cvContext.scopeCtx.scopeObj;
var selectionAdapter = new catreact_1.CvValueAdapter();
var selectionListener = selectionAdapter.createValueListener();
return React.createElement(catreact_1.CvAction, {actionId: graphContext.graphDef.defaultActionId, paneContext: graphContext, navigationListeners: _this.props.navigationListeners, actionListeners: _this.props.actionListeners, stateChangeListeners: _this.props.stateChangeListeners, selectionProvider: selectionAdapter, renderer: function (cvContext, callback) {
var clickHandler = function (id) { selectionListener([id]); callback.fireAction(); };
var graphDef = graphContext.graphDef;
var records = catavolt_sdk_1.ArrayUtil.copy(graphContext.scroller.buffer);
var points = graphDef.graphType === catavolt_sdk_1.GraphDef.GRAPH_TYPE_PIE ?
_this._generateDataForPieChart(graphContext, records) : _this._generateData(graphContext, records);
var identPropName = graphDef.identityDataPointDef.name;
var plotTypes = graphDef.dataPointDefs.map(function (dataPointDef) { return dataPointDef.plotType; }).filter(function (v) { return !!v; });
if (graphDef.graphType === catavolt_sdk_1.GraphDef.GRAPH_TYPE_CARTESIAN) {
if (plotTypes.length === 0 || plotTypes.indexOf(catavolt_sdk_1.GraphDef.PLOT_TYPE_BAR) > -1) {
return React.createElement(exports.CvBarChart, {graphContext: graphContext, data: points, identPropName: identPropName, defaultSeriesColors: _this.props.defaultSeriesColors, clickHandler: clickHandler});
}
else if (plotTypes.indexOf(catavolt_sdk_1.GraphDef.PLOT_TYPE_LINE) > -1) {
return React.createElement(exports.CvLineChart, {graphContext: graphContext, data: points, identPropName: identPropName, defaultSeriesColors: _this.props.defaultSeriesColors, clickHandler: clickHandler});
}
else if (plotTypes.indexOf(catavolt_sdk_1.GraphDef.PLOT_TYPE_STACKED) > -1) {
return React.createElement(exports.CvBarChart, {graphContext: graphContext, data: points, identPropName: identPropName, defaultSeriesColors: _this.props.defaultSeriesColors, stack: true, clickHandler: clickHandler});
}
else if (plotTypes.indexOf(catavolt_sdk_1.GraphDef.PLOT_TYPE_SCATTER) > -1) {
return React.createElement(exports.CvScatterChart, {graphContext: graphContext, data: points, identPropName: identPropName, defaultSeriesColors: _this.props.defaultSeriesColors, clickHandler: clickHandler});
}
else if (plotTypes.indexOf(catavolt_sdk_1.GraphDef.PLOT_TYPE_BUBBLE) > -1) {
return React.createElement(exports.CvScatterChart, {graphContext: graphContext, data: points, identPropName: identPropName, defaultSeriesColors: _this.props.defaultSeriesColors, bubble: true, clickHandler: clickHandler});
}
else {
return null;
}
}
else if (graphDef.graphType === catavolt_sdk_1.GraphDef.GRAPH_TYPE_PIE) {
return React.createElement(exports.CvPieChart, {graphContext: graphContext, data: points, identPropName: identPropName, defaultSeriesColors: _this.props.defaultSeriesColors, clickHandler: clickHandler});
}
else {
return null;
}
}});
}})));
},
_formatProp: function (prop, propDef) {
return catreact_1.CvProp.formatDataType(prop, propDef);
},
_generateData: function (graphContext, records) {
var _this = this;
var graphDef = graphContext.graphDef;
//prop for 1 axis (or dimension)
var identPropName = graphDef.identityDataPointDef.name;
var points = records.map(function (record) {
var item = {};
item['id'] = record.objectId;
item[identPropName] = _this._formatProp(record.propAtName(identPropName), graphContext.propDefAtName(identPropName));
//possible props for other axes (or dimensions)
graphDef.dataPointDefs.forEach(function (dataPointDef) {
var propName = dataPointDef.name;
if (propName)
item[propName] = _this._formatProp(record.propAtName(propName), graphContext.propDefAtName(propName));
var xAxisName = dataPointDef.xAxisName;
if (xAxisName)
item[xAxisName] = _this._formatProp(record.propAtName(xAxisName), graphContext.propDefAtName(xAxisName));
var radiusName = dataPointDef.bubbleRadiusName;
if (radiusName)
item[radiusName] = Number(record.propAtName(radiusName).value);
});
return item;
});
return points;
},
_generateDataForPieChart: function (graphContext, records) {
var _this = this;
/* The pie chart requires the primary series to be numeric */
var graphDef = graphContext.graphDef;
//prop for 1 axis (or dimension)
var identPropName = graphDef.identityDataPointDef.name;
var points = records.map(function (record) {
var item = {};
item['id'] = record.objectId;
item[identPropName] = _this._formatProp(record.propAtName(identPropName), graphContext.propDefAtName(identPropName));
graphDef.dataPointDefs.forEach(function (dataPointDef) {
var propName = dataPointDef.name;
//force numeric typing
if (propName)
item[propName] = Number(record.propAtName(propName).value);
});
return item;
});
return points;
},
});