diff --git a/client/app/visualizations/chart/chart-editor.html b/client/app/visualizations/chart/chart-editor.html
index 202b92f0a..2d88d33c5 100644
--- a/client/app/visualizations/chart/chart-editor.html
+++ b/client/app/visualizations/chart/chart-editor.html
@@ -12,6 +12,9 @@
Series
+
+ Colors
+
Data Labels
@@ -210,15 +213,15 @@
-
+
-
+
-
+
@@ -226,40 +229,28 @@
+
+
+
+
+ |
+ {{ name }}
+ |
+
+
+
+
+
+
+
+
+
+
+ |
+
+
+
+
+
+
+
+
+
+ |
+ {{ name }}
+ |
+
+
+
+
+
+
+
+
+
+
+ |
+
+
+
+
+
-
\ No newline at end of file
+
diff --git a/client/app/visualizations/chart/index.js b/client/app/visualizations/chart/index.js
index 879750122..4946aeb43 100644
--- a/client/app/visualizations/chart/index.js
+++ b/client/app/visualizations/chart/index.js
@@ -14,6 +14,7 @@ const DEFAULT_OPTIONS = {
error_y: { type: 'data', visible: true },
series: { stacking: null, error_y: { type: 'data', visible: true } },
seriesOptions: {},
+ valuesOptions: {},
columnMapping: {},
// showDataLabels: false, // depends on chart type
@@ -156,7 +157,8 @@ function ChartEditor(ColorPalette, clientConfig) {
}
function refreshSeries() {
- const seriesNames = map(scope.queryResult.getChartData(scope.options.columnMapping), i => i.name);
+ const chartData = scope.queryResult.getChartData(scope.options.columnMapping);
+ const seriesNames = map(chartData, i => i.name);
const existing = keys(scope.options.seriesOptions);
each(difference(seriesNames, existing), (name) => {
scope.options.seriesOptions[name] = {
@@ -169,6 +171,31 @@ function ChartEditor(ColorPalette, clientConfig) {
scope.form.seriesList = without(scope.form.seriesList, name);
delete scope.options.seriesOptions[name];
});
+
+ if (scope.options.globalSeriesType === 'pie') {
+ const uniqueValuesNames = new Set();
+ each(chartData, (series) => {
+ each(series.data, (row) => {
+ uniqueValuesNames.add(row.x);
+ });
+ });
+ const valuesNames = [];
+ uniqueValuesNames.forEach(v => valuesNames.push(v));
+
+ // initialize newly added values
+ const newValues = difference(valuesNames, keys(scope.options.valuesOptions));
+ each(newValues, (name) => {
+ scope.options.valuesOptions[name] = {};
+ scope.form.valuesList.push(name);
+ });
+ // remove settings for values that are no longer available
+ each(keys(scope.options.valuesOptions), (name) => {
+ if (valuesNames.indexOf(name) === -1) {
+ delete scope.options.valuesOptions[name];
+ }
+ });
+ scope.form.valuesList = intersection(scope.form.valuesList, valuesNames);
+ }
}
function setColumnRole(role, column) {
@@ -200,6 +227,7 @@ function ChartEditor(ColorPalette, clientConfig) {
yAxisColumns: [],
seriesList: sortBy(keys(scope.options.seriesOptions), name =>
scope.options.seriesOptions[name].zIndex),
+ valuesList: keys(scope.options.valuesOptions),
};
scope.$watchCollection('form.seriesList', (value) => {
@@ -273,7 +301,7 @@ function ChartEditor(ColorPalette, clientConfig) {
});
}
- scope.$watch('options', () => {
+ function setOptionsDefaults() {
if (scope.options) {
// For existing visualization - set default options
defaults(scope.options, extend({}, DEFAULT_OPTIONS, {
@@ -281,7 +309,9 @@ function ChartEditor(ColorPalette, clientConfig) {
dateTimeFormat: clientConfig.dateTimeFormat,
}));
}
- });
+ }
+ setOptionsDefaults();
+ scope.$watch('options', setOptionsDefaults);
scope.templateHint = `
Use special names to access additional properties:
diff --git a/client/app/visualizations/chart/plotly/utils.js b/client/app/visualizations/chart/plotly/utils.js
index c118f49f7..537b7c7fe 100644
--- a/client/app/visualizations/chart/plotly/utils.js
+++ b/client/app/visualizations/chart/plotly/utils.js
@@ -3,6 +3,7 @@ import {
each, values, sortBy, identity, filter, map, extend, reduce,
} from 'lodash';
import moment from 'moment';
+import d3 from 'd3';
import { createFormatter, formatSimpleTemplate } from '@/lib/value-format';
// The following colors will be used if you pick "Automatic" color.
@@ -227,6 +228,15 @@ function preparePieData(seriesList, options) {
const hoverinfo = getPieHoverInfoPattern(options);
+ // we will use this to assign colors for values that have not explicitly set color
+ const getDefaultColor = d3.scale.ordinal().domain([]).range(ColorPaletteArray);
+ const valuesColors = {};
+ each(options.valuesOptions, (item, key) => {
+ if (isString(item.color) && (item.color !== '')) {
+ valuesColors[key] = item.color;
+ }
+ });
+
return map(seriesList, (serie, index) => {
const xPosition = (index % cellsInRow) * cellWidth;
const yPosition = Math.floor(index / cellsInRow) * cellHeight;
@@ -255,7 +265,9 @@ function preparePieData(seriesList, options) {
labels: map(serie.data, row => (hasX ? normalizeValue(row.x) : `Slice ${index}`)),
type: 'pie',
hole: 0.4,
- marker: { colors: ColorPaletteArray },
+ marker: {
+ colors: map(serie.data, row => valuesColors[row.x] || getDefaultColor(row.x)),
+ },
hoverinfo,
text: [],
textinfo: options.showDataLabels ? 'percent' : 'none',