Pie chart: sectors colors

This commit is contained in:
Levko Kravets
2018-06-21 15:25:10 +03:00
parent 140d0ae14f
commit 3772612a97
3 changed files with 107 additions and 28 deletions

View File

@@ -12,6 +12,9 @@
<li ng-class="{active: currentTab == 'series'}" ng-if="options.globalSeriesType != 'custom'">
<a ng-click="changeTab('series')">Series</a>
</li>
<li ng-class="{active: currentTab == 'colors'}" ng-if="options.globalSeriesType != 'custom'">
<a ng-click="changeTab('colors')">Colors</a>
</li>
<li ng-class="{active: currentTab == 'dataLabels'}" ng-if="options.globalSeriesType != 'custom'">
<a ng-click="changeTab('dataLabels')">Data Labels</a>
</li>
@@ -210,15 +213,15 @@
</div>
<div class="form-group">
<label class="control-label">Name</label>
<input ng-model="yAxis.title.text" type="text" class="form-control"></input>
<input ng-model="yAxis.title.text" type="text" class="form-control">
</div>
<div class="form-group">
<label class="control-label">Min Value</label>
<input ng-model="yAxis.rangeMin" type="number" step="any" placeholder="Auto" class="form-control"></input>
<input ng-model="yAxis.rangeMin" type="number" step="any" placeholder="Auto" class="form-control">
</div>
<div class="form-group">
<label class="control-label">Max Value</label>
<input ng-model="yAxis.rangeMax" type="number" step="any" placeholder="Auto" class="form-control"></input>
<input ng-model="yAxis.rangeMax" type="number" step="any" placeholder="Auto" class="form-control">
</div>
</div>
</div>
@@ -226,40 +229,28 @@
<div ng-if="currentTab == 'series'" class="m-t-10 m-b-10">
<table class="table table-condensed col-table">
<thead>
<th>zIndex</th>
<th>Left Y Axis</th>
<th>Right Y Axis</th>
<th style="width: 1%;">zIndex</th>
<th ng-if="options.globalSeriesType != 'pie'">Left Y Axis</th>
<th ng-if="options.globalSeriesType != 'pie'">Right Y Axis</th>
<th>Label</th>
<th>Color</th>
<th>Type</th>
<th ng-if="options.globalSeriesType != 'pie'">Type</th>
</thead>
<tbody ui-sortable ng-model="form.seriesList">
<tr ng-repeat="name in form.seriesList">
<td style="cursor: move;">
<td style="width: 1%; cursor: move;">
<i class="fa fa-arrows-v"></i>
<span ng-bind="options.seriesOptions[name].zIndex + 1"></span>
</td>
<td>
<td ng-if="options.globalSeriesType != 'pie'">
<input type="radio" ng-value="0" ng-model="options.seriesOptions[name].yAxis">
</td>
<td>
<td ng-if="options.globalSeriesType != 'pie'">
<input type="radio" ng-value="1" ng-model="options.seriesOptions[name].yAxis">
</td>
<td style="padding: 3px; width: 140px;">
<input placeholder="{{name}}" class="form-control input-sm super-small-input" type="text" ng-model="options.seriesOptions[name].name">
</td>
<td style="padding: 3px; width: 35px;">
<ui-select ng-model="options.seriesOptions[name].color">
<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>
</td>
<td style="padding: 3px; width: 105px;">
<td ng-if="options.globalSeriesType != 'pie'" style="padding: 3px; width: 105px;">
<ui-select ng-model="options.seriesOptions[name].type">
<ui-select-match placeholder="Chart Type">
<div>
@@ -281,6 +272,52 @@
</table>
</div>
<div ng-if="(currentTab == 'colors') && (options.globalSeriesType != 'pie')" class="m-t-10 m-b-10">
<table class="table table-condensed col-table">
<tbody>
<tr ng-repeat="name in form.seriesList">
<td style="padding: 3px; width: 140px;">
<div>{{ name }}</div>
</td>
<td style="padding: 3px; width: 35px;">
<ui-select ng-model="options.seriesOptions[name].color">
<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>
</td>
</tr>
</tbody>
</table>
</div>
<div ng-if="(currentTab == 'colors') && (options.globalSeriesType == 'pie')" class="m-t-10 m-b-10">
<table class="table table-condensed col-table">
<tbody>
<tr ng-repeat="name in form.valuesList">
<td style="padding: 3px; width: 140px;">
<div>{{ name }}</div>
</td>
<td style="padding: 3px; width: 35px;">
<ui-select ng-model="options.valuesOptions[name].color">
<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>
</td>
</tr>
</tbody>
</table>
</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">
<label>
@@ -329,4 +366,4 @@
placeholder="(auto)">
</div>
</div>
</div>
</div>

View File

@@ -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 = `
<div class="p-b-5">Use special names to access additional properties:</div>

View File

@@ -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',