Files
redash/client/app/visualizations/chart/getChartData.js
Levko Kravets 2c98f0425d Allow the user to decide how to handle null values in charts (#4071)
* getredash/redash#2629 Refactor Chart visualization, add option for handling NULL values (keep/convert to 0.0)

* Handle null values in line/area stacking code; some cleanup

* Handle edge case: line/area stacking when last value of one of series is missing

* Mjnor update to line/area stacking code

* Fix line/area normalize to percents feature

* Unit tests

* Refine tests; add tests for prepareLayout function

* Tests for prepareData (heatmap) function

* Tests for prepareData (pie) function

* Tests for prepareData (bar, line, area) function

* Tests for prepareData (scatter, bubble) function

* Tests for prepareData (box) function

* Remove unused file
2019-09-09 13:00:26 +03:00

98 lines
2.3 KiB
JavaScript

import { isNil, each, forOwn, sortBy, values } from 'lodash';
function addPointToSeries(point, seriesCollection, seriesName) {
if (seriesCollection[seriesName] === undefined) {
seriesCollection[seriesName] = {
name: seriesName,
type: 'column',
data: [],
};
}
seriesCollection[seriesName].data.push(point);
}
export default function getChartData(data, options) {
const series = {};
const mappings = options.columnMapping;
each(data, (row) => {
let point = { $raw: row };
let seriesName = null;
let xValue = 0;
const yValues = {};
let eValue = null;
let sizeValue = null;
let zValue = null;
forOwn(row, (value, definition) => {
definition = '' + definition;
const definitionParts = definition.split('::') || definition.split('__');
const name = definitionParts[0];
const type = mappings ? mappings[definition] : definitionParts[1];
if (type === 'unused') {
return;
}
if (type === 'x') {
xValue = value;
point[type] = value;
}
if (type === 'y') {
yValues[name] = value;
point[type] = value;
}
if (type === 'yError') {
eValue = value;
point[type] = value;
}
if (type === 'series') {
seriesName = String(value);
}
if (type === 'size') {
point[type] = value;
sizeValue = value;
}
if (type === 'zVal') {
point[type] = value;
zValue = value;
}
if (type === 'multiFilter' || type === 'multi-filter') {
seriesName = String(value);
}
});
if (isNil(seriesName)) {
each(yValues, (yValue, ySeriesName) => {
point = { x: xValue, y: yValue, $raw: point.$raw };
if (eValue !== null) {
point.yError = eValue;
}
if (sizeValue !== null) {
point.size = sizeValue;
}
if (zValue !== null) {
point.zVal = zValue;
}
addPointToSeries(point, series, ySeriesName);
});
} else {
addPointToSeries(point, series, seriesName);
}
});
return sortBy(values(series), ({ name }) => {
if (options.seriesOptions[name]) {
return options.seriesOptions[name].zIndex;
}
return 0;
});
}