graph panel: fix csv export (series as col) (#10769)
This commit is contained in:
committed by
Torkel Ödegaard
parent
5ca03972a8
commit
81dc051ae9
@@ -0,0 +1,64 @@
|
||||
import * as fileExport from '../utils/file_export';
|
||||
import { beforeEach, expect } from 'test/lib/common';
|
||||
|
||||
describe('file_export', () => {
|
||||
let ctx: any = {};
|
||||
|
||||
beforeEach(() => {
|
||||
ctx.seriesList = [
|
||||
{
|
||||
alias: 'series_1',
|
||||
datapoints: [
|
||||
[1, 1500026100000],
|
||||
[2, 1500026200000],
|
||||
[null, 1500026300000],
|
||||
[null, 1500026400000],
|
||||
[null, 1500026500000],
|
||||
[6, 1500026600000],
|
||||
],
|
||||
},
|
||||
{
|
||||
alias: 'series_2',
|
||||
datapoints: [[11, 1500026100000], [12, 1500026200000], [13, 1500026300000], [15, 1500026500000]],
|
||||
},
|
||||
];
|
||||
|
||||
ctx.timeFormat = 'X'; // Unix timestamp (seconds)
|
||||
});
|
||||
|
||||
describe('when exporting series as rows', () => {
|
||||
it('should export points in proper order', () => {
|
||||
let text = fileExport.convertSeriesListToCsv(ctx.seriesList, ctx.timeFormat);
|
||||
const expectedText =
|
||||
'Series;Time;Value\n' +
|
||||
'series_1;1500026100;1\n' +
|
||||
'series_1;1500026200;2\n' +
|
||||
'series_1;1500026300;null\n' +
|
||||
'series_1;1500026400;null\n' +
|
||||
'series_1;1500026500;null\n' +
|
||||
'series_1;1500026600;6\n' +
|
||||
'series_2;1500026100;11\n' +
|
||||
'series_2;1500026200;12\n' +
|
||||
'series_2;1500026300;13\n' +
|
||||
'series_2;1500026500;15\n';
|
||||
|
||||
expect(text).toBe(expectedText);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when exporting series as columns', () => {
|
||||
it('should export points in proper order', () => {
|
||||
let text = fileExport.convertSeriesListToCsvColumns(ctx.seriesList, ctx.timeFormat);
|
||||
const expectedText =
|
||||
'Time;series_1;series_2\n' +
|
||||
'1500026100;1;11\n' +
|
||||
'1500026200;2;12\n' +
|
||||
'1500026300;null;13\n' +
|
||||
'1500026400;null;null\n' +
|
||||
'1500026500;null;15\n' +
|
||||
'1500026600;6;null\n';
|
||||
|
||||
expect(text).toBe(expectedText);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -3,19 +3,27 @@ import moment from 'moment';
|
||||
import { saveAs } from 'file-saver';
|
||||
|
||||
const DEFAULT_DATETIME_FORMAT = 'YYYY-MM-DDTHH:mm:ssZ';
|
||||
const POINT_TIME_INDEX = 1;
|
||||
const POINT_VALUE_INDEX = 0;
|
||||
|
||||
export function exportSeriesListToCsv(seriesList, dateTimeFormat = DEFAULT_DATETIME_FORMAT, excel = false) {
|
||||
export function convertSeriesListToCsv(seriesList, dateTimeFormat = DEFAULT_DATETIME_FORMAT, excel = false) {
|
||||
var text = (excel ? 'sep=;\n' : '') + 'Series;Time;Value\n';
|
||||
_.each(seriesList, function(series) {
|
||||
_.each(series.datapoints, function(dp) {
|
||||
text += series.alias + ';' + moment(dp[1]).format(dateTimeFormat) + ';' + dp[0] + '\n';
|
||||
text +=
|
||||
series.alias + ';' + moment(dp[POINT_TIME_INDEX]).format(dateTimeFormat) + ';' + dp[POINT_VALUE_INDEX] + '\n';
|
||||
});
|
||||
});
|
||||
return text;
|
||||
}
|
||||
|
||||
export function exportSeriesListToCsv(seriesList, dateTimeFormat = DEFAULT_DATETIME_FORMAT, excel = false) {
|
||||
var text = convertSeriesListToCsv(seriesList, dateTimeFormat, excel);
|
||||
saveSaveBlob(text, 'grafana_data_export.csv');
|
||||
}
|
||||
|
||||
export function exportSeriesListToCsvColumns(seriesList, dateTimeFormat = DEFAULT_DATETIME_FORMAT, excel = false) {
|
||||
var text = (excel ? 'sep=;\n' : '') + 'Time;';
|
||||
export function convertSeriesListToCsvColumns(seriesList, dateTimeFormat = DEFAULT_DATETIME_FORMAT, excel = false) {
|
||||
let text = (excel ? 'sep=;\n' : '') + 'Time;';
|
||||
// add header
|
||||
_.each(seriesList, function(series) {
|
||||
text += series.alias + ';';
|
||||
@@ -24,14 +32,15 @@ export function exportSeriesListToCsvColumns(seriesList, dateTimeFormat = DEFAUL
|
||||
text += '\n';
|
||||
|
||||
// process data
|
||||
seriesList = mergeSeriesByTime(seriesList);
|
||||
var dataArr = [[]];
|
||||
var sIndex = 1;
|
||||
_.each(seriesList, function(series) {
|
||||
var cIndex = 0;
|
||||
dataArr.push([]);
|
||||
_.each(series.datapoints, function(dp) {
|
||||
dataArr[0][cIndex] = moment(dp[1]).format(dateTimeFormat);
|
||||
dataArr[sIndex][cIndex] = dp[0];
|
||||
dataArr[0][cIndex] = moment(dp[POINT_TIME_INDEX]).format(dateTimeFormat);
|
||||
dataArr[sIndex][cIndex] = dp[POINT_VALUE_INDEX];
|
||||
cIndex++;
|
||||
});
|
||||
sIndex++;
|
||||
@@ -46,6 +55,44 @@ export function exportSeriesListToCsvColumns(seriesList, dateTimeFormat = DEFAUL
|
||||
text = text.substring(0, text.length - 1);
|
||||
text += '\n';
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect all unique timestamps from series list and use it to fill
|
||||
* missing points by null.
|
||||
*/
|
||||
function mergeSeriesByTime(seriesList) {
|
||||
let timestamps = [];
|
||||
for (let i = 0; i < seriesList.length; i++) {
|
||||
let seriesPoints = seriesList[i].datapoints;
|
||||
for (let j = 0; j < seriesPoints.length; j++) {
|
||||
timestamps.push(seriesPoints[j][POINT_TIME_INDEX]);
|
||||
}
|
||||
}
|
||||
timestamps = _.sortedUniq(timestamps.sort());
|
||||
|
||||
for (let i = 0; i < seriesList.length; i++) {
|
||||
let seriesPoints = seriesList[i].datapoints;
|
||||
let seriesTimestamps = _.map(seriesPoints, p => p[POINT_TIME_INDEX]);
|
||||
let extendedSeries = [];
|
||||
let pointIndex;
|
||||
for (let j = 0; j < timestamps.length; j++) {
|
||||
pointIndex = _.sortedIndexOf(seriesTimestamps, timestamps[j]);
|
||||
if (pointIndex !== -1) {
|
||||
extendedSeries.push(seriesPoints[pointIndex]);
|
||||
} else {
|
||||
extendedSeries.push([null, timestamps[j]]);
|
||||
}
|
||||
}
|
||||
seriesList[i].datapoints = extendedSeries;
|
||||
}
|
||||
return seriesList;
|
||||
}
|
||||
|
||||
export function exportSeriesListToCsvColumns(seriesList, dateTimeFormat = DEFAULT_DATETIME_FORMAT, excel = false) {
|
||||
let text = convertSeriesListToCsvColumns(seriesList, dateTimeFormat, excel);
|
||||
saveSaveBlob(text, 'grafana_data_export.csv');
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user