Configurable heatmap maximum bucket number (#39578) (#40875)

* Add visualization:heatmap:maxBuckets to settings (default: 50)

* Use visualization:heatmap:maxBuckets at heatmap (before it was hardcoded)

* Convert heatmap tests from mocha to jest
This commit is contained in:
Matthias Wilhelm 2019-07-11 19:33:33 +02:00 committed by GitHub
parent 025517950c
commit ca2f2606d4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 132 additions and 46 deletions

View file

@ -572,6 +572,19 @@ export function getUiSettingDefaults() {
}),
category: ['visualization'],
},
'visualization:heatmap:maxBuckets': {
name: i18n.translate('kbn.advancedSettings.visualization.heatmap.maxBucketsTitle', {
defaultMessage: 'Heatmap maximum buckets',
}),
value: 50,
type: 'number',
description: i18n.translate('kbn.advancedSettings.visualization.heatmap.maxBucketsText', {
defaultMessage:
'The maximum number of buckets a single datasource can return. ' +
'A higher number might have negative impact on browser rendering performance'
}),
category: ['visualization'],
},
'csv:separator': {
name: i18n.translate('kbn.advancedSettings.csv.separatorTitle', {
defaultMessage: 'CSV separator',

View file

@ -19,7 +19,6 @@
import ngMock from 'ng_mock';
import expect from '@kbn/expect';
import stackedSeries from 'fixtures/vislib/mock_data/date_histogram/_stacked_series';
import { vislibPointSeriesTypes as pointSeriesConfig } from '../../../lib/types/point_series';
import percentileTestdata from './testdata_linechart_percentile.json';
import percentileTestdataResult from './testdata_linechart_percentile_result.json';
@ -47,18 +46,6 @@ describe('Point Series Config Type Class Test Suite', function () {
}]
};
const heatmapConfig = {
type: 'heatmap',
addLegend: true,
addTooltip: true,
colorsNumber: 4,
colorSchema: 'Greens',
setColorRange: false,
percentageMode: true,
invertColors: false,
colorsRange: []
};
const data = {
get: (prop) => { return data[prop] || data.data[prop] || null; },
getLabels: () => [],
@ -135,32 +122,4 @@ describe('Point Series Config Type Class Test Suite', function () {
});
});
describe('heatmap chart', function () {
beforeEach(function () {
const stackedData = {
get: (prop) => { return data[prop] || null; },
getLabels: () => [],
data: stackedSeries
};
parsedConfig = pointSeriesConfig.heatmap(heatmapConfig, stackedData);
});
it('should throw an error when more than 25 series are provided', function () {
parsedConfig = pointSeriesConfig.heatmap(heatmapConfig, data);
expect(parsedConfig.error).to.be('There are too many series defined.');
});
it('should not throw an error when less than 25 series are provided', function () {
expect(parsedConfig.error).to.be.undefined;
});
it('should hide first value axis', function () {
expect(parsedConfig.valueAxes[0].show).to.be(false);
});
it('should add second category axis', function () {
expect(parsedConfig.categoryAxes.length).to.equal(2);
});
});
});

View file

@ -18,7 +18,7 @@
*/
import _ from 'lodash';
import { i18n } from '@kbn/i18n';
const createSeriesFromParams = (cfg, seri) => {
//percentile data id format is {mainId}.{percentileValue}, this has to be cleaned
@ -203,11 +203,17 @@ export const vislibPointSeriesTypes = {
heatmap: (cfg, data) => {
const defaults = create()(cfg, data);
const seriesLimit = 25;
const hasCharts = defaults.charts.length;
const tooManySeries = defaults.charts.length && defaults.charts[0].series.length > seriesLimit;
const tooManySeries = defaults.charts.length && defaults.charts[0].series.length > cfg.heatmapMaxBuckets;
if (hasCharts && tooManySeries) {
defaults.error = 'There are too many series defined.';
defaults.error = i18n.translate('common.ui.vislib.heatmap.maxBucketsText', {
defaultMessage: 'There are too many series defined ({nr}). The configured maximum is {max}.',
values: {
max: cfg.heatmapMaxBuckets,
nr: defaults.charts[0].series.length
},
description: 'This message appears at heatmap visualizations'
});
}
defaults.valueAxes[0].show = false;
defaults.categoryAxes[0].style = {

View file

@ -0,0 +1,108 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import stackedSeries from '../../../../../../fixtures/vislib/mock_data/date_histogram/_stacked_series';
import { vislibPointSeriesTypes } from './point_series';
describe('vislibPointSeriesTypes', () => {
const heatmapConfig = {
type: 'heatmap',
addLegend: true,
addTooltip: true,
colorsNumber: 4,
colorSchema: 'Greens',
setColorRange: false,
percentageMode: true,
invertColors: false,
colorsRange: [],
heatmapMaxBuckets: 20
};
const stackedData = {
get: prop => {
return stackedSeries[prop] || null;
},
getLabels: () => [],
data: stackedSeries,
};
const maxBucketData = {
get: prop => {
return maxBucketData[prop] || maxBucketData.data[prop] || null;
},
getLabels: () => [],
data: {
hits: 621,
ordered: {
date: true,
interval: 30000,
max: 1408734982458,
min: 1408734082458,
},
series: [
{ label: 's1', values: [{ x: 1408734060000, y: 8 }] },
{ label: 's2', values: [{ x: 1408734060000, y: 8 }] },
{ label: 's3', values: [{ x: 1408734060000, y: 8 }] },
{ label: 's4', values: [{ x: 1408734060000, y: 8 }] },
{ label: 's5', values: [{ x: 1408734060000, y: 8 }] },
{ label: 's6', values: [{ x: 1408734060000, y: 8 }] },
{ label: 's7', values: [{ x: 1408734060000, y: 8 }] },
{ label: 's8', values: [{ x: 1408734060000, y: 8 }] },
{ label: 's9', values: [{ x: 1408734060000, y: 8 }] },
{ label: 's10', values: [{ x: 1408734060000, y: 8 }] },
{ label: 's11', values: [{ x: 1408734060000, y: 8 }] },
{ label: 's12', values: [{ x: 1408734060000, y: 8 }] },
{ label: 's13', values: [{ x: 1408734060000, y: 8 }] },
{ label: 's14', values: [{ x: 1408734060000, y: 8 }] },
{ label: 's15', values: [{ x: 1408734060000, y: 8 }] },
{ label: 's16', values: [{ x: 1408734060000, y: 8 }] },
{ label: 's17', values: [{ x: 1408734060000, y: 8 }] },
{ label: 's18', values: [{ x: 1408734060000, y: 8 }] },
{ label: 's19', values: [{ x: 1408734060000, y: 8 }] },
{ label: 's20', values: [{ x: 1408734060000, y: 8 }] },
{ label: 's21', values: [{ x: 1408734060000, y: 8 }] },
{ label: 's22', values: [{ x: 1408734060000, y: 8 }] },
{ label: 's23', values: [{ x: 1408734060000, y: 8 }] },
{ label: 's24', values: [{ x: 1408734060000, y: 8 }] },
{ label: 's25', values: [{ x: 1408734060000, y: 8 }] },
{ label: 's26', values: [{ x: 1408734060000, y: 8 }] },
],
xAxisLabel: 'Date Histogram',
yAxisLabel: 'series',
yAxisFormatter: () => 'test',
},
};
describe('heatmap()', () => {
it('should return an error when more than 20 series are provided', () => {
const parsedConfig = vislibPointSeriesTypes.heatmap(heatmapConfig, maxBucketData);
expect(parsedConfig.error).toMatchInlineSnapshot(
`"There are too many series defined (26). The configured maximum is 20."`
);
});
it('should return valid config when less than 20 series are provided', () => {
const parsedConfig = vislibPointSeriesTypes.heatmap(heatmapConfig, stackedData);
expect(parsedConfig.error).toBeUndefined();
expect(parsedConfig.valueAxes[0].show).toBeFalsy();
expect(parsedConfig.categoryAxes.length).toBe(2);
expect(parsedConfig.error).toBeUndefined();
});
});
});

View file

@ -46,7 +46,7 @@ export function VislibVisProvider(Private, config) {
this.el = $el.get ? $el.get(0) : $el;
this.visConfigArgs = _.cloneDeep(visConfigArgs);
this.visConfigArgs.dimmingOpacity = config.get('visualization:dimmingOpacity');
this.visConfigArgs.heatmapMaxBuckets = config.get('visualization:heatmap:maxBuckets');
}
hasLegend() {