mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
updating vislib to correctly render all new features
This commit is contained in:
parent
066c3fefa9
commit
6d642caecc
15 changed files with 109 additions and 156 deletions
|
@ -1,5 +1,5 @@
|
|||
export default function PointSeriesAddToSiri() {
|
||||
return function addToSiri(series, point, id, label) {
|
||||
return function addToSiri(series, point, id, label, agg) {
|
||||
id = id == null ? '' : id + '';
|
||||
|
||||
if (series.has(id)) {
|
||||
|
@ -9,6 +9,9 @@ export default function PointSeriesAddToSiri() {
|
|||
|
||||
series.set(id, {
|
||||
label: label == null ? id : label,
|
||||
aggLabel: agg.type.makeLabel(agg),
|
||||
aggId: agg.parentId ? agg.parentId : agg.id,
|
||||
count: 0,
|
||||
values: [point]
|
||||
});
|
||||
};
|
||||
|
|
|
@ -15,7 +15,7 @@ export default function PointSeriesGetSeries(Private) {
|
|||
.transform(function (series, row) {
|
||||
if (!multiY) {
|
||||
const point = partGetPoint(row, aspects.y, aspects.z);
|
||||
if (point) addToSiri(series, point, point.series);
|
||||
if (point) addToSiri(series, point, point.series, point.series, aspects.y.agg);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@ export default function PointSeriesGetSeries(Private) {
|
|||
seriesLabel = prefix + seriesLabel;
|
||||
}
|
||||
|
||||
addToSiri(series, point, seriesId, seriesLabel);
|
||||
addToSiri(series, point, seriesId, seriesLabel, y.agg);
|
||||
});
|
||||
|
||||
}, new Map())
|
||||
|
|
|
@ -43,124 +43,21 @@ export default function AxisFactory(Private) {
|
|||
|
||||
const stackedMode = ['normal', 'grouped'].includes(this.axisConfig.get('scale.mode'));
|
||||
if (stackedMode) {
|
||||
this.stack.out((d, y0, y) => {
|
||||
return this._stackNegAndPosVals(d, y0, y);
|
||||
const self = this;
|
||||
this.stack = this._stackNegAndPosVals;
|
||||
}
|
||||
}
|
||||
|
||||
_stackNegAndPosVals(data) {
|
||||
const cache = {};
|
||||
data.forEach(series => {
|
||||
series.forEach(value => {
|
||||
if (!cache[value.x]) cache[value.x] = [0, 0];
|
||||
value.y0 = cache[value.x][value.y < 0 ? 0 : 1];
|
||||
cache[value.x][value.y < 0 ? 0 : 1] += value.y;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true for positive numbers
|
||||
*/
|
||||
_isPositive(num) {
|
||||
return num >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true for negative numbers
|
||||
*/
|
||||
_isNegative(num) {
|
||||
return num < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds two input values
|
||||
*/
|
||||
_addVals(a, b) {
|
||||
return a + b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the results of the addition of numbers in a filtered array.
|
||||
*/
|
||||
_sumYs(arr, callback) {
|
||||
const filteredArray = arr.filter(callback);
|
||||
|
||||
return (filteredArray.length) ? filteredArray.reduce(this._addVals) : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the d.y0 value for stacked data in D3.
|
||||
*/
|
||||
_calcYZero(y, arr) {
|
||||
if (y === 0 && this._lastY0) return this._sumYs(arr, this._lastY0 > 0 ? this._isPositive : this._isNegative);
|
||||
if (y >= 0) return this._sumYs(arr, this._isPositive);
|
||||
return this._sumYs(arr, this._isNegative);
|
||||
}
|
||||
|
||||
_getCounts(i, j) {
|
||||
const data = this.visConfig.data.chartData();
|
||||
const dataLengths = {};
|
||||
|
||||
dataLengths.charts = data.length;
|
||||
dataLengths.stacks = dataLengths.charts ? data[i].series.length : 0;
|
||||
dataLengths.values = dataLengths.stacks ? data[i].series[j].values.length : 0;
|
||||
|
||||
return dataLengths;
|
||||
}
|
||||
|
||||
_createCache() {
|
||||
const cache = {
|
||||
index: {
|
||||
chart: 0,
|
||||
stack: 0,
|
||||
value: 0
|
||||
},
|
||||
yValsArr: []
|
||||
};
|
||||
|
||||
cache.count = this._getCounts(cache.index.chart, cache.index.stack);
|
||||
|
||||
return cache;
|
||||
}
|
||||
/**
|
||||
* Stacking function passed to the D3 Stack Layout `.out` API.
|
||||
* See: https://github.com/mbostock/d3/wiki/Stack-Layout
|
||||
* It is responsible for calculating the correct d.y0 value for
|
||||
* mixed datasets containing both positive and negative values.
|
||||
*/
|
||||
_stackNegAndPosVals(d, y0, y) {
|
||||
const data = this.visConfig.data.chartData();
|
||||
|
||||
// Storing counters and data characteristics needed to stack values properly
|
||||
if (!this._cache) {
|
||||
this._cache = this._createCache();
|
||||
}
|
||||
|
||||
d.y0 = this._calcYZero(y, this._cache.yValsArr);
|
||||
if (d.y0 > 0) this._lastY0 = 1;
|
||||
if (d.y0 < 0) this._lastY0 = -1;
|
||||
++this._cache.index.stack;
|
||||
|
||||
|
||||
// last stack, or last value, reset the stack count and y value array
|
||||
const lastStack = (this._cache.index.stack >= this._cache.count.stacks);
|
||||
if (lastStack) {
|
||||
this._cache.index.stack = 0;
|
||||
++this._cache.index.value;
|
||||
this._cache.yValsArr = [];
|
||||
// still building the stack collection, push v value to array
|
||||
} else if (y !== 0) {
|
||||
this._cache.yValsArr.push(y);
|
||||
}
|
||||
|
||||
// last value, prepare for the next chart, if one exists
|
||||
const lastValue = (this._cache.index.value >= this._cache.count.values);
|
||||
if (lastValue) {
|
||||
this._cache.index.value = 0;
|
||||
++this._cache.index.chart;
|
||||
|
||||
// no more charts, reset the queue and finish
|
||||
if (this._cache.index.chart >= this._cache.count.charts) {
|
||||
this._cache = this._createCache();
|
||||
return;
|
||||
}
|
||||
|
||||
// get stack and value count for next chart
|
||||
const chartSeries = data[this._cache.index.chart].series;
|
||||
this._cache.count.stacks = chartSeries.length;
|
||||
this._cache.count.values = chartSeries.length ? chartSeries[this._cache.index.stack].values.length : 0;
|
||||
}
|
||||
});
|
||||
return data;
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -173,6 +70,7 @@ export default function AxisFactory(Private) {
|
|||
const elSelector = this.axisConfig.get('elSelector');
|
||||
const rootEl = this.axisConfig.get('rootEl');
|
||||
$(rootEl).find(elSelector).find('svg').remove();
|
||||
this.axisTitle.destroy();
|
||||
}
|
||||
|
||||
getAxis(length) {
|
||||
|
@ -277,7 +175,7 @@ export default function AxisFactory(Private) {
|
|||
|
||||
return function (selection) {
|
||||
const n = selection[0].length;
|
||||
if (config.get('show') && self.axisTitle) {
|
||||
if (config.get('show') && self.axisTitle && ['left', 'top'].includes(config.get('position'))) {
|
||||
self.axisTitle.render(selection);
|
||||
}
|
||||
selection.each(function () {
|
||||
|
@ -316,6 +214,10 @@ export default function AxisFactory(Private) {
|
|||
svg.call(self.adjustSize());
|
||||
}
|
||||
});
|
||||
|
||||
if (self.axisTitle && ['right', 'bottom'].includes(config.get('position'))) {
|
||||
self.axisTitle.render(selection);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ export default function AxisConfigFactory() {
|
|||
},
|
||||
title: {
|
||||
text: '',
|
||||
elSelector: '.axis-wrapper-{pos} .axis-title'
|
||||
elSelector: '.axis-wrapper-{pos} .axis-div',
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -77,8 +77,11 @@ export default function AxisConfigFactory() {
|
|||
const typeDefaults = axisConfigArgs.type === 'category' ? categoryDefaults : valueDefaults;
|
||||
// _.defaultsDeep mutates axisConfigArgs nested values so we clone it first
|
||||
const axisConfigArgsClone = _.cloneDeep(axisConfigArgs);
|
||||
const isHorizontal = (axisConfigArgsClone.position &&
|
||||
['top', 'bottom'].includes(axisConfigArgsClone.position)) ||
|
||||
axisConfigArgsClone.type === 'category';
|
||||
_.merge(typeDefaults, isHorizontal ? horizontalDefaults : verticalDefaults);
|
||||
this._values = _.defaultsDeep({}, axisConfigArgsClone, typeDefaults, defaults);
|
||||
_.merge(this._values, this.isHorizontal() ? horizontalDefaults : verticalDefaults);
|
||||
|
||||
this._values.elSelector = this._values.elSelector.replace('{pos}', this._values.position);
|
||||
this._values.rootEl = chartConfig.get('el');
|
||||
|
|
|
@ -12,6 +12,10 @@ export default function AxisTitleFactory(Private) {
|
|||
d3.select(this.axisConfig.get('rootEl')).selectAll(this.elSelector).call(this.draw());
|
||||
}
|
||||
|
||||
destroy() {
|
||||
$(this.axisConfig.get('rootEl')).find(this.elSelector).find('svg').remove();
|
||||
}
|
||||
|
||||
draw() {
|
||||
const config = this.axisConfig;
|
||||
|
||||
|
@ -31,9 +35,9 @@ export default function AxisTitleFactory(Private) {
|
|||
const bbox = svg.append('text')
|
||||
.attr('transform', function () {
|
||||
if (config.isHorizontal()) {
|
||||
return 'translate(' + width / 2 + ',11)';
|
||||
return 'translate(' + width / 2 + ',15)';
|
||||
}
|
||||
return 'translate(11,' + height / 2 + ') rotate(270)';
|
||||
return 'translate(15,' + height / 2 + ') rotate(270)';
|
||||
})
|
||||
.attr('text-anchor', 'middle')
|
||||
.text(config.get('title.text'))
|
||||
|
|
|
@ -41,6 +41,8 @@ export default function DataFactory(Private) {
|
|||
newData[key] = data[key].map(seri => {
|
||||
return {
|
||||
label: seri.label,
|
||||
aggLabel: seri.aggLabel,
|
||||
aggId: seri.aggId,
|
||||
values: seri.values.map(val => {
|
||||
const newVal = _.clone(val);
|
||||
newVal.aggConfig = val.aggConfig;
|
||||
|
@ -111,11 +113,7 @@ export default function DataFactory(Private) {
|
|||
|
||||
shouldBeStacked(seriesConfig) {
|
||||
if (!seriesConfig) return false;
|
||||
const isHistogram = (seriesConfig.type === 'histogram');
|
||||
const isArea = (seriesConfig.type === 'area');
|
||||
const stacked = (seriesConfig.mode === 'stacked');
|
||||
|
||||
return (isHistogram || isArea) && stacked;
|
||||
return (seriesConfig.mode === 'stacked');
|
||||
}
|
||||
|
||||
getStackedSeries(chartConfig, axis, series, first = false) {
|
||||
|
@ -135,6 +133,7 @@ export default function DataFactory(Private) {
|
|||
const id = axis.axisConfig.get('id');
|
||||
stackedData[id] = this.getStackedSeries(chartConfig, axis, data, i === 0);
|
||||
stackedData[id] = this.injectZeros(stackedData[id], handler.visConfig.get('orderBucketsBySum', false));
|
||||
axis.axisConfig.set('stackedSeries', stackedData[id].length);
|
||||
axis.stack(_.map(stackedData[id], 'values'));
|
||||
});
|
||||
return stackedData;
|
||||
|
|
|
@ -3,25 +3,49 @@ import errors from 'ui/errors';
|
|||
|
||||
export default function ColumnHandler(Private) {
|
||||
|
||||
const createSeries = (cfg, series) => {
|
||||
const stacked = ['stacked', 'percentage', 'wiggle', 'silhouette'].includes(cfg.mode);
|
||||
const createSerieFromParams = (cfg, seri) => {
|
||||
// todo this wont work with splits ... same issue exists in dispatch
|
||||
const matchingSeriParams = cfg.seriesParams ? cfg.seriesParams.find(seriConfig => {
|
||||
return seri.aggLabel === seriConfig.data.label;
|
||||
}) : null;
|
||||
|
||||
|
||||
let interpolate = cfg.interpolate;
|
||||
// for backward compatibility when loading URLs or configs we need to check smoothLines
|
||||
if (cfg.smoothLines) interpolate = 'cardinal';
|
||||
|
||||
if (!matchingSeriParams) {
|
||||
const stacked = ['stacked', 'percentage', 'wiggle', 'silhouette'].includes(cfg.mode);
|
||||
return {
|
||||
show: true,
|
||||
type: cfg.type || 'line',
|
||||
mode: stacked ? 'stacked' : 'normal',
|
||||
interpolate: interpolate,
|
||||
drawLinesBetweenPoints: cfg.drawLinesBetweenPoints,
|
||||
showCircles: cfg.showCircles,
|
||||
radiusRatio: cfg.radiusRatio,
|
||||
data: seri
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
show: matchingSeriParams.show,
|
||||
type: matchingSeriParams.type,
|
||||
mode: matchingSeriParams.mode,
|
||||
valueAxis: matchingSeriParams.valueAxis,
|
||||
smoothLines: matchingSeriParams.smoothLines,
|
||||
drawLinesBetweenPoints: matchingSeriParams.drawLinesBetweenPoints,
|
||||
showCircles: matchingSeriParams.showCircles,
|
||||
radiusRatio: matchingSeriParams.radiusRatio,
|
||||
data: seri
|
||||
};
|
||||
};
|
||||
|
||||
const createSeries = (cfg, series) => {
|
||||
return {
|
||||
type: 'point_series',
|
||||
series: _.map(series, (seri) => {
|
||||
return {
|
||||
show: true,
|
||||
type: cfg.type || 'line',
|
||||
mode: stacked ? 'stacked' : 'normal',
|
||||
interpolate: interpolate,
|
||||
drawLinesBetweenPoints: cfg.drawLinesBetweenPoints,
|
||||
showCircles: cfg.showCircles,
|
||||
radiusRatio: cfg.radiusRatio,
|
||||
data: seri
|
||||
};
|
||||
return createSerieFromParams(cfg, seri);
|
||||
})
|
||||
};
|
||||
};
|
||||
|
|
|
@ -187,6 +187,10 @@
|
|||
width: 100%;
|
||||
}
|
||||
|
||||
.x-axis-div svg {
|
||||
float: left; /* for some reason svg wont get positioned in top left corner of container div without this */
|
||||
}
|
||||
|
||||
.axis-wrapper-top .axis-div svg {
|
||||
margin-bottom: -5px;
|
||||
}
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
|
||||
/* SVG Element Default Styling */
|
||||
rect {
|
||||
stroke: none;
|
||||
opacity: 1;
|
||||
|
||||
&:hover {
|
||||
|
@ -50,6 +49,12 @@ circle {
|
|||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.series > path,
|
||||
.series > rect {
|
||||
fill-opacity: 0.6;
|
||||
stroke-opacity: 1;
|
||||
}
|
||||
|
||||
.blur_shape {
|
||||
opacity: 0.3 !important;
|
||||
}
|
||||
|
|
|
@ -55,6 +55,14 @@ export default function PointSeriesFactory(Private) {
|
|||
.attr('class', 'background');
|
||||
}
|
||||
|
||||
addGrid(svg) {
|
||||
const { width, height } = svg.node().getBBox();
|
||||
return svg
|
||||
.append('g')
|
||||
.attr('class', 'grid')
|
||||
.call(this.handler.grid.draw(width, height));
|
||||
}
|
||||
|
||||
addClipPath(svg) {
|
||||
const { width, height } = svg.node().getBBox();
|
||||
const startX = 0;
|
||||
|
@ -219,6 +227,7 @@ export default function PointSeriesFactory(Private) {
|
|||
.attr('height', height);
|
||||
|
||||
self.addBackground(svg, width, height);
|
||||
self.addGrid(svg);
|
||||
self.addClipPath(svg);
|
||||
self.addEvents(svg);
|
||||
self.createEndZones(svg);
|
||||
|
@ -227,7 +236,7 @@ export default function PointSeriesFactory(Private) {
|
|||
self.series = [];
|
||||
_.each(self.chartConfig.series, (seriArgs, i) => {
|
||||
if (!seriArgs.show) return;
|
||||
const SeriClass = seriTypes[seriArgs.type || self.handler.visConfig.get('chart.type')];
|
||||
const SeriClass = seriTypes[seriArgs.type || self.handler.visConfig.get('chart.type')] || seriTypes.line;
|
||||
const series = new SeriClass(self.handler, svg, data.series[i], seriArgs);
|
||||
series.events = self.events;
|
||||
svg.call(series.draw());
|
||||
|
|
|
@ -29,8 +29,8 @@ export default function PointSeriesProvider(Private) {
|
|||
|
||||
getGroupedCount() {
|
||||
const stacks = [];
|
||||
return this.baseChart.chartConfig.series.reduce(function (sum, series) {
|
||||
const valueAxis = series.valueAxis;
|
||||
return this.baseChart.chartConfig.series.reduce((sum, series) => {
|
||||
const valueAxis = series.valueAxis || this.baseChart.handler.valueAxes[0].id;
|
||||
const isStacked = series.mode === 'stacked';
|
||||
const isHistogram = series.type === 'histogram';
|
||||
if (!isHistogram) return sum;
|
||||
|
@ -53,7 +53,7 @@ export default function PointSeriesProvider(Private) {
|
|||
let i = 0;
|
||||
const stacks = [];
|
||||
for (const seri of this.baseChart.chartConfig.series) {
|
||||
const valueAxis = seri.valueAxis;
|
||||
const valueAxis = seri.valueAxis || this.baseChart.handler.valueAxes[0].id;
|
||||
const isStacked = seri.mode === 'stacked';
|
||||
if (!isStacked) {
|
||||
if (seri.data === data) return i;
|
||||
|
|
|
@ -79,9 +79,8 @@ export default function AreaChartFactory(Private) {
|
|||
// Append path
|
||||
const path = layer.append('path')
|
||||
.attr('data-label', data.label)
|
||||
.style('fill', () => {
|
||||
return color(data.label);
|
||||
})
|
||||
.style('fill', () => color(data.label))
|
||||
.style('stroke', () => color(data.label))
|
||||
.classed('overlap_area', function () {
|
||||
return isOverlapping;
|
||||
})
|
||||
|
|
|
@ -50,9 +50,8 @@ export default function ColumnChartFactory(Private) {
|
|||
.enter()
|
||||
.append('rect')
|
||||
.attr('data-label', data.label)
|
||||
.attr('fill', () => {
|
||||
return color(data.label);
|
||||
});
|
||||
.attr('fill', () => color(data.label))
|
||||
.attr('stroke', () => color(data.label));
|
||||
|
||||
self.updateBars(bars);
|
||||
|
||||
|
@ -117,7 +116,6 @@ export default function ColumnChartFactory(Private) {
|
|||
if ((isHorizontal && d.y < 0) || (!isHorizontal && d.y > 0)) {
|
||||
return yScale(d.y0);
|
||||
}
|
||||
/*if (!isHorizontal && d.y < 0) return yScale(d.y);*/
|
||||
return yScale(d.y0 + d.y);
|
||||
}
|
||||
|
||||
|
|
|
@ -69,8 +69,9 @@ export default function LineChartFactory(Private) {
|
|||
}
|
||||
|
||||
function cy(d) {
|
||||
const y0 = d.y0 || 0;
|
||||
const y = d.y || 0;
|
||||
return yScale(y);
|
||||
return yScale(y0 + y);
|
||||
}
|
||||
|
||||
function cColor(d) {
|
||||
|
@ -158,7 +159,8 @@ export default function LineChartFactory(Private) {
|
|||
|
||||
function cy(d) {
|
||||
const y = d.y || 0;
|
||||
return yScale(y);
|
||||
const y0 = d.y0 || 0;
|
||||
return yScale(y0 + y);
|
||||
}
|
||||
|
||||
line.append('path')
|
||||
|
|
|
@ -4,6 +4,7 @@ import 'plugins/kbn_vislib_vis_types/controls/vislib_basic_options';
|
|||
import 'plugins/kbn_vislib_vis_types/controls/point_series_options';
|
||||
import 'plugins/kbn_vislib_vis_types/controls/line_interpolation_option';
|
||||
import 'plugins/kbn_vislib_vis_types/controls/heatmap_options';
|
||||
import 'plugins/kbn_vislib_vis_types/controls/point_series';
|
||||
import VisSchemasProvider from 'ui/vis/schemas';
|
||||
import VisVisTypeProvider from 'ui/vis/vis_type';
|
||||
import AggResponsePointSeriesPointSeriesProvider from 'ui/agg_response/point_series/point_series';
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue