From 12f98f8a586573b14c7bab9723d405031d69197a Mon Sep 17 00:00:00 2001 From: Allen Short Date: Fri, 26 Oct 2018 21:43:36 -0500 Subject: [PATCH] catch up with #2080 --- .../visualizations/chart/ChartColorEditor.jsx | 20 +--- .../app/visualizations/chart/ChartEditor.jsx | 109 ++++++++++++++++-- .../visualizations/chart/ChartRenderer.jsx | 9 ++ .../visualizations/chart/ChartTypePicker.jsx | 1 + .../app/visualizations/chart/ColorSelect.jsx | 38 ++++++ .../app/visualizations/chart/PlotlyChart.jsx | 4 +- 6 files changed, 155 insertions(+), 26 deletions(-) create mode 100644 client/app/visualizations/chart/ColorSelect.jsx diff --git a/client/app/visualizations/chart/ChartColorEditor.jsx b/client/app/visualizations/chart/ChartColorEditor.jsx index 953079e9d6..711c8d6e01 100644 --- a/client/app/visualizations/chart/ChartColorEditor.jsx +++ b/client/app/visualizations/chart/ChartColorEditor.jsx @@ -1,13 +1,9 @@ import React from 'react'; import PropTypes from 'prop-types'; -import Select from 'antd/lib/select'; -import 'antd/lib/select/style'; import { map } from 'lodash'; -import { ColorPalette } from '@/visualizations/chart/plotly/utils'; import { SeriesOptions, ValuesOptions } from '@/components/proptypes'; - -const colors = { Automatic: null, ...ColorPalette }; +import ColorSelect from './ColorSelect'; export default class ChartColorEditor extends React.Component { static propTypes = { @@ -26,11 +22,6 @@ export default class ChartColorEditor extends React.Component { changeColor = (value, color) => this.updateOptions(value, { color }); render() { - const colorSelectItem = v => (); - const colorOptionItem = (v, k) => {colorSelectItem(v)}{k}; return (
@@ -41,13 +32,10 @@ export default class ChartColorEditor extends React.Component {
{name}
))} diff --git a/client/app/visualizations/chart/ChartEditor.jsx b/client/app/visualizations/chart/ChartEditor.jsx index 5c875dd09a..25e2f21b9b 100644 --- a/client/app/visualizations/chart/ChartEditor.jsx +++ b/client/app/visualizations/chart/ChartEditor.jsx @@ -15,6 +15,7 @@ import { QueryData } from '@/components/proptypes'; import ChartTypePicker from './ChartTypePicker'; import ChartSeriesEditor from './ChartSeriesEditor'; import ChartColorEditor from './ChartColorEditor'; +import ColorSelect from './ColorSelect'; import ChartRenderer from './ChartRenderer'; const DEFAULT_CUSTOM_CODE = `// Available variables are x, ys, element, and Plotly @@ -49,6 +50,10 @@ function PopoverHelp(props) { PopoverHelp.propTypes = { children: PropTypes.arrayOf(PropTypes.node).isRequired }; +const colorSchemes = ['Blackbody', 'Bluered', 'Blues', 'Earth', 'Electric', + 'Greens', 'Greys', 'Hot', 'Jet', 'Picnic', 'Portland', + 'Rainbow', 'RdBu', 'Reds', 'Viridis', 'YlGnBu', 'YlOrRd', 'Custom...']; + export default class ChartEditor extends React.Component { static propTypes = { data: QueryData.isRequired, @@ -117,6 +122,7 @@ export default class ChartEditor extends React.Component { getErrorColumn = () => findKey(this.props.options.columnMapping, c => c === 'yError') getSizeColumn = () => findKey(this.props.options.columnMapping, c => c === 'size') getGroupby = () => findKey(this.props.options.columnMapping, c => c === 'groupby') + getZValue = () => findKey(this.props.options.columnMapping, c => c === 'zVal') updateOptions = (newOptions) => { const opts = this.props.options; @@ -174,6 +180,9 @@ export default class ChartEditor extends React.Component { }) toggleSortX = e => this.updateOptions({ sortX: e.target.checked }) + toggleReverseX = e => this.updateOptions({ reverseX: e.target.checked }) + toggleSortY = e => this.updateOptions({ sortY: e.target.checked }) + toggleReverseY = e => this.updateOptions({ reverseY: e.target.checked }) toggleXLabels = e => this.updateOptions({ xAxis: { @@ -195,6 +204,7 @@ export default class ChartEditor extends React.Component { updateGroupby = groupby => this.updateColumn({ groupby }) updateSizeColumn = size => this.updateColumn({ size }) updateErrorColumn = yError => this.updateColumn({ yError }) + updateZValue = zVal => this.updateColumn({ zVal }) updateStacking = stacking => this.updateOptions({ series: { ...this.props.options.series, stacking }, }) @@ -221,6 +231,7 @@ export default class ChartEditor extends React.Component { updatePercentFormat = e => this.updateOptions({ percentFormat: e.target.value }) updateDateTimeFormat = e => this.updateOptions({ dateTImeFormat: e.target.value }) updateTextFormat = e => this.updateOptions({ textFormat: e.target.value }) + updateColorScheme = colorScheme => this.updateOptions({ colorScheme }) yAxisPanel = (side, i) => { const yAxis = this.props.options.yAxis[i]; return ( @@ -299,13 +310,14 @@ export default class ChartEditor extends React.Component { - {opts.globalSeriesType !== 'custom' ? + {!includes(['custom', 'heatmap'], opts.globalSeriesType) ?
@@ -318,24 +330,37 @@ export default class ChartEditor extends React.Component { placeholder="Choose column..." value={this.getSizeColumn()} onChange={this.updateSizeColumn} + allowClear > {this.sizeColumnOptions()} -
: '' } - - {opts.globalSeriesType !== 'custom' ? + : null } + {some(opts.seriesOptions, { type: 'heatmap' }) ? +
+ + +
: null } + {!includes(['custom', 'heatmap'], opts.globalSeriesType) ?
-
: ''} + : null} - {opts.globalSeriesType === 'custom' ? + {!includes(['custom', 'heatmap'], opts.globalSeriesType) ?
: ''} - {opts.globalSeriesType !== 'custom' ? + {!includes(['custom', 'heatmap'], opts.globalSeriesType) ?
+ Reverse Order + +
: null } {opts.globalSeriesType !== 'custom' ? @@ -486,7 +541,43 @@ export default class ChartEditor extends React.Component { clientConfig={this.props.clientConfig} /> : null } - {opts.globalSeriesType !== 'custom' ? + {opts.globalSeriesType === 'heatmap' ? + +
+ + +
+
+
+ {opts.colorScheme === 'Custom...' ? +
+ + +
: null } +
+
+ {opts.colorScheme === 'Custom...' ? +
+ + +
: null } +
+
+
: null } + {!includes(['custom', 'heatmap'], opts.globalSeriesType) ? { definition = '' + definition; @@ -68,6 +69,11 @@ function chartData(mapping, data) { sizeValue = value; } + if (type === 'zVal') { + point[type] = value; + zValue = value; + } + if (type === 'multiFilter' || type === 'multi-filter') { seriesName = String(value); } @@ -83,6 +89,9 @@ function chartData(mapping, data) { if (sizeValue !== null) { point.size = sizeValue; } + if (zValue !== null) { + point.zVal = zValue; + } addPointToSeries(point, series, ySeriesName); }); } else { diff --git a/client/app/visualizations/chart/ChartTypePicker.jsx b/client/app/visualizations/chart/ChartTypePicker.jsx index 013baeb9ae..7dbe21aa4b 100644 --- a/client/app/visualizations/chart/ChartTypePicker.jsx +++ b/client/app/visualizations/chart/ChartTypePicker.jsx @@ -10,6 +10,7 @@ const chartTypes = [ { value: 'pie', label: 'Pie', icon: 'pie-chart' }, { value: 'scatter', label: 'Scatter', icon: 'circle-o' }, { value: 'bubble', label: 'Bubble', icon: 'circle-o' }, + { value: 'heatmap', label: 'Heatmap', icon: 'th' }, { value: 'box', label: 'Box', icon: 'square-o' }, ]; diff --git a/client/app/visualizations/chart/ColorSelect.jsx b/client/app/visualizations/chart/ColorSelect.jsx new file mode 100644 index 0000000000..a12e01a9cd --- /dev/null +++ b/client/app/visualizations/chart/ColorSelect.jsx @@ -0,0 +1,38 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import Select from 'antd/lib/select'; +import 'antd/lib/select/style'; +import { map } from 'lodash'; + +import { ColorPalette } from '@/visualizations/chart/plotly/utils'; + + +const colors = { Automatic: null, ...ColorPalette }; +const colorSelectItem = v => ( + ); +const colorOptionItem = (v, k) => {colorSelectItem(v)}{k}; + + +export default function ColorSelect(props) { + return ( + ); +} + +ColorSelect.propTypes = { + value: PropTypes.string.isRequired, + onChange: PropTypes.func.isRequired, +}; diff --git a/client/app/visualizations/chart/PlotlyChart.jsx b/client/app/visualizations/chart/PlotlyChart.jsx index 89af316a9e..d9f8d1f049 100644 --- a/client/app/visualizations/chart/PlotlyChart.jsx +++ b/client/app/visualizations/chart/PlotlyChart.jsx @@ -6,13 +6,14 @@ import bar from 'plotly.js/lib/bar'; import pie from 'plotly.js/lib/pie'; import histogram from 'plotly.js/lib/histogram'; import box from 'plotly.js/lib/box'; +import heatmap from 'plotly.js/lib/heatmap'; import { each, isArray, isObject } from 'lodash'; import { SeriesOptions, ValuesOptions } from '@/components/proptypes'; import { normalizeValue, updateData, prepareData, prepareLayout } from '@/visualizations/chart/plotly/utils'; -Plotly.register([bar, pie, histogram, box]); +Plotly.register([bar, pie, histogram, box, heatmap]); Plotly.setPlotConfig({ modeBarButtonsToRemove: ['sendDataToCloud'], }); @@ -39,6 +40,7 @@ const Point = PropTypes.exact({ yError: PropTypes.any, unused: PropTypes.any, size: PropTypes.any, + zValue: PropTypes.any, }); const Series = PropTypes.exact({
- + />