Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add: Heatmap chart visualization by Plotly #2080

Merged
merged 18 commits into from
Oct 21, 2018
Merged
10 changes: 10 additions & 0 deletions client/app/services/query-result.js
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ function QueryResultService($resource, $timeout, $q, QueryResultError) {
const yValues = {};
let eValue = null;
let sizeValue = null;
let zValue = null;

forOwn(row, (v, definition) => {
definition = '' + definition;
Expand Down Expand Up @@ -320,6 +321,11 @@ function QueryResultService($resource, $timeout, $q, QueryResultError) {
sizeValue = value;
}

if (type === 'zVal') {
point[type] = value;
zValue = value;
}

if (type === 'multiFilter' || type === 'multi-filter') {
seriesName = String(value);
}
Expand All @@ -335,6 +341,10 @@ function QueryResultService($resource, $timeout, $q, QueryResultError) {
if (sizeValue !== null) {
point.size = sizeValue;
}

if (zValue !== null) {
point.zVal = zValue;
}
addPointToSeries(point, series, ySeriesName);
});
} else {
Expand Down
90 changes: 84 additions & 6 deletions client/app/visualizations/chart/chart-editor.html
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@

</div>

<div class="form-group" ng-if="options.globalSeriesType != 'custom'">
<div class="form-group" ng-if="['custom', 'heatmap'].indexOf(options.globalSeriesType) == -1">
<label class="control-label">Group by</label>
<ui-select name="groupby" ng-model="form.groupby" class="clearable">
<ui-select-match allow-clear="true" placeholder="Choose column...">
Expand All @@ -97,7 +97,19 @@
</ui-select>
</div>

<div class="form-group" ng-if="options.globalSeriesType != 'custom'">
<div class="form-group" ng-if="showZColumnPicker()">
<label class="control-label">Color Column</label>

<ui-select name="zValColumn" ng-model="form.zValColumn">
<ui-select-match allow-clear="true" placeholder="Choose column...">{{$select.selected}}</ui-select-match>
<ui-select-choices repeat="column in columnNames | remove:form.yAxisColumns | remove:form.groupby">
<span ng-bind-html="column | highlight: $select.search"></span><span> </span>
<small class="text-muted" ng-bind="columns[column].type"></small>
</ui-select-choices>
</ui-select>
</div>

<div class="form-group" ng-if="['custom', 'heatmap'].indexOf(options.globalSeriesType) == -1">
<label class="control-label">Errors column</label>

<ui-select name="errorColumn" ng-model="form.errorColumn">
Expand All @@ -110,7 +122,7 @@
</ui-select>
</div>

<div class="checkbox" ng-if="options.globalSeriesType != 'custom'">
<div class="checkbox" ng-if="['custom', 'heatmap'].indexOf(options.globalSeriesType) == -1">
<label>
<input type="checkbox" ng-model="options.legend.enabled">
<i class="input-helper"></i> Show Legend
Expand All @@ -124,7 +136,7 @@
</label>
</div>

<div class="form-group" ng-if="options.globalSeriesType != 'custom'">
<div class="form-group" ng-if="['custom', 'heatmap'].indexOf(options.globalSeriesType) == -1">
<label class="control-label">Stacking</label>

<div ng-if="stackingOptions">
Expand Down Expand Up @@ -190,6 +202,13 @@
</label>
</div>

<div class="checkbox">
<label>
<input type="checkbox" ng-model="options.reverseX">
<i class="input-helper"></i> Reverse Order
</label>
</div>

<div class="checkbox">
<label>
<input type="checkbox" ng-model="options.xAxis.labels.enabled">
Expand Down Expand Up @@ -223,6 +242,21 @@ <h4>{{$index == 0 ? 'Left' : 'Right'}} Y Axis</h4>
<label class="control-label">Max Value</label>
<input ng-model="yAxis.rangeMax" type="number" step="any" placeholder="Auto" class="form-control">
</div>

<div class="checkbox">
<label>
<input type="checkbox" ng-model="options.sortY">
<i class="input-helper"></i> Sort Values
</label>
</div>

<div class="checkbox">
<label>
<input type="checkbox" ng-model="options.reverseY">
<i class="input-helper"></i> Reverse Order
</label>
</div>

</div>
</div>

Expand Down Expand Up @@ -272,7 +306,7 @@ <h4>{{$index == 0 ? 'Left' : 'Right'}} Y Axis</h4>
</table>
</div>

<div ng-if="(currentTab == 'colors') && (options.globalSeriesType != 'pie')" class="m-t-10 m-b-10">
<div ng-if="(currentTab == 'colors') && (['pie', 'heatmap'].indexOf(options.globalSeriesType) == -1)" class="m-t-10 m-b-10">
<table class="table table-condensed col-table">
<tbody>
<tr ng-repeat="name in form.seriesList">
Expand All @@ -295,6 +329,50 @@ <h4>{{$index == 0 ? 'Left' : 'Right'}} Y Axis</h4>
</table>
</div>

<div ng-if="(currentTab == 'colors') && (options.globalSeriesType == 'heatmap')" class="m-t-10 m-b-10">
<div class="form-group" ng-if="options.globalSeriesType == 'heatmap'">
<label class="control-label">Color Scheme</label>

<ui-select ng-model="options.colorScheme">
<ui-select-match allow-clear="true" placeholder="Choose Color Scheme...">{{$select.selected | capitalize}}</ui-select-match>
<ui-select-choices repeat="value in colorScheme">
<div ng-bind-html="value | highlight: $select.search"></div>
</ui-select-choices>
</ui-select>
</div>

<div class="row">
<div class="col-xs-6">
<div class="form-group" ng-if="options.colorScheme == 'Custom...'">
<label class="control-label">Min Color</label>
<ui-select ng-model="options.heatMinColor">
<ui-select-match>
<color-box color="$select.selected.value"></color-box>
</ui-select-match>
<ui-select-choices repeat="color.value as (key, color) in colors">
<color-box color="color.value"></color-box>
<span ng-bind-html="color.key | capitalize | highlight: $select.search"></span>
</ui-select-choices>
</ui-select>
</div>
</div>
<div class="col-xs-6">
<div class="form-group" ng-if="options.colorScheme == 'Custom...'">
<label class="control-label">Max Color</label>
<ui-select ng-model="options.heatMaxColor">
<ui-select-match>
<color-box color="$select.selected.value"></color-box>
</ui-select-match>
<ui-select-choices repeat="color.value as (key, color) in colors">
<color-box color="color.value"></color-box>
<span ng-bind-html="color.key | capitalize | highlight: $select.search"></span>
</ui-select-choices>
</ui-select>
</div>
</div>
</div>
</div>

<div ng-if="(currentTab == 'colors') && (options.globalSeriesType == 'pie')" class="m-t-10 m-b-10">
<table class="table table-condensed col-table">
<tbody>
Expand All @@ -319,7 +397,7 @@ <h4>{{$index == 0 ? 'Left' : 'Right'}} Y Axis</h4>
</div>

<div ng-if="currentTab == 'dataLabels'" class="m-t-10 m-b-10">
<div ng-if="['line', 'area', 'column', 'scatter', 'pie'].indexOf(options.globalSeriesType) >= 0" class="checkbox">
<div ng-if="['line', 'area', 'column', 'scatter', 'pie', 'heatmap'].indexOf(options.globalSeriesType) >= 0" class="checkbox">
<label>
<input type="checkbox" ng-model="options.showDataLabels"> Show Data Labels</label>
</div>
Expand Down
16 changes: 16 additions & 0 deletions client/app/visualizations/chart/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ function ChartEditor(ColorPalette, clientConfig) {
pie: { name: 'Pie', icon: 'pie-chart' },
scatter: { name: 'Scatter', icon: 'circle-o' },
bubble: { name: 'Bubble', icon: 'circle-o' },
heatmap: { name: 'Heatmap', icon: 'th' },
box: { name: 'Box', icon: 'square-o' },
};

Expand All @@ -121,7 +122,12 @@ function ChartEditor(ColorPalette, clientConfig) {
scope.$applyAsync();
};

scope.colorScheme = ['Blackbody', 'Bluered', 'Blues', 'Earth', 'Electric',
'Greens', 'Greys', 'Hot', 'Jet', 'Picnic', 'Portland',
'Rainbow', 'RdBu', 'Reds', 'Viridis', 'YlGnBu', 'YlOrRd', 'Custom...'];

scope.showSizeColumnPicker = () => some(scope.options.seriesOptions, options => options.type === 'bubble');
scope.showZColumnPicker = () => some(scope.options.seriesOptions, options => options.type === 'heatmap');

if (scope.options.customCode === undefined) {
scope.options.customCode = `// Available variables are x, ys, element, and Plotly
Expand Down Expand Up @@ -268,6 +274,14 @@ function ChartEditor(ColorPalette, clientConfig) {
}
});

scope.$watch('form.zValColumn', (value, old) => {
if (old !== undefined) {
unsetColumn(old);
}
if (value !== undefined) {
setColumnRole('zVal', value);
}
});

scope.$watch('form.groupby', (value, old) => {
if (old !== undefined) {
Expand Down Expand Up @@ -297,6 +311,8 @@ function ChartEditor(ColorPalette, clientConfig) {
scope.form.errorColumn = key;
} else if (value === 'size') {
scope.form.sizeColumn = key;
} else if (value === 'zVal') {
scope.form.zValColumn = key;
}
});
}
Expand Down
3 changes: 2 additions & 1 deletion client/app/visualizations/chart/plotly/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ 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 {
ColorPalette,
Expand All @@ -15,7 +16,7 @@ import {
normalizeValue,
} from './utils';

Plotly.register([bar, pie, histogram, box]);
Plotly.register([bar, pie, histogram, box, heatmap]);
Plotly.setPlotConfig({
modeBarButtonsToRemove: ['sendDataToCloud'],
});
Expand Down
Loading