mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
CSV Export: Timezone based on dashboard setting (#18002)
* Timezone export CSV based on dashboard setting * Add options object and interface
This commit is contained in:
parent
25506829be
commit
9e87dbb153
@ -28,7 +28,7 @@ describe('file_export', () => {
|
|||||||
|
|
||||||
describe('when exporting series as rows', () => {
|
describe('when exporting series as rows', () => {
|
||||||
it('should export points in proper order', () => {
|
it('should export points in proper order', () => {
|
||||||
const text = fileExport.convertSeriesListToCsv(ctx.seriesList, ctx.timeFormat);
|
const text = fileExport.convertSeriesListToCsv(ctx.seriesList, { dateTimeFormat: ctx.timeFormat });
|
||||||
const expectedText =
|
const expectedText =
|
||||||
'"Series";"Time";"Value"\r\n' +
|
'"Series";"Time";"Value"\r\n' +
|
||||||
'"series_1";"1500026100";1\r\n' +
|
'"series_1";"1500026100";1\r\n' +
|
||||||
@ -48,7 +48,7 @@ describe('file_export', () => {
|
|||||||
|
|
||||||
describe('when exporting series as columns', () => {
|
describe('when exporting series as columns', () => {
|
||||||
it('should export points in proper order', () => {
|
it('should export points in proper order', () => {
|
||||||
const text = fileExport.convertSeriesListToCsvColumns(ctx.seriesList, ctx.timeFormat);
|
const text = fileExport.convertSeriesListToCsvColumns(ctx.seriesList, { dateTimeFormat: ctx.timeFormat });
|
||||||
const expectedText =
|
const expectedText =
|
||||||
'"Time";"series_1";"series_2"\r\n' +
|
'"Time";"series_1";"series_2"\r\n' +
|
||||||
'"1500026100";1;11\r\n' +
|
'"1500026100";1;11\r\n' +
|
||||||
@ -65,7 +65,7 @@ describe('file_export', () => {
|
|||||||
const expectedSeries1DataPoints = ctx.seriesList[0].datapoints.slice();
|
const expectedSeries1DataPoints = ctx.seriesList[0].datapoints.slice();
|
||||||
const expectedSeries2DataPoints = ctx.seriesList[1].datapoints.slice();
|
const expectedSeries2DataPoints = ctx.seriesList[1].datapoints.slice();
|
||||||
|
|
||||||
fileExport.convertSeriesListToCsvColumns(ctx.seriesList, ctx.timeFormat);
|
fileExport.convertSeriesListToCsvColumns(ctx.seriesList, { dateTimeFormat: ctx.timeFormat });
|
||||||
|
|
||||||
expect(expectedSeries1DataPoints).toEqual(ctx.seriesList[0].datapoints);
|
expect(expectedSeries1DataPoints).toEqual(ctx.seriesList[0].datapoints);
|
||||||
expect(expectedSeries2DataPoints).toEqual(ctx.seriesList[1].datapoints);
|
expect(expectedSeries2DataPoints).toEqual(ctx.seriesList[1].datapoints);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { isBoolean, isNumber, sortedUniq, sortedIndexOf, unescape as htmlUnescaped } from 'lodash';
|
import { isBoolean, isNumber, sortedUniq, sortedIndexOf, unescape as htmlUnescaped } from 'lodash';
|
||||||
import { saveAs } from 'file-saver';
|
import { saveAs } from 'file-saver';
|
||||||
import { isNullOrUndefined } from 'util';
|
import { isNullOrUndefined } from 'util';
|
||||||
import { dateTime } from '@grafana/data';
|
import { dateTime, TimeZone } from '@grafana/data';
|
||||||
|
|
||||||
const DEFAULT_DATETIME_FORMAT = 'YYYY-MM-DDTHH:mm:ssZ';
|
const DEFAULT_DATETIME_FORMAT = 'YYYY-MM-DDTHH:mm:ssZ';
|
||||||
const POINT_TIME_INDEX = 1;
|
const POINT_TIME_INDEX = 1;
|
||||||
@ -12,7 +12,19 @@ const END_ROW = '\r\n';
|
|||||||
const QUOTE = '"';
|
const QUOTE = '"';
|
||||||
const EXPORT_FILENAME = 'grafana_data_export.csv';
|
const EXPORT_FILENAME = 'grafana_data_export.csv';
|
||||||
|
|
||||||
function csvEscaped(text) {
|
interface SeriesListToCsvColumnsOptions {
|
||||||
|
dateTimeFormat: string;
|
||||||
|
excel: boolean;
|
||||||
|
timezone: TimeZone;
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultOptions: SeriesListToCsvColumnsOptions = {
|
||||||
|
dateTimeFormat: DEFAULT_DATETIME_FORMAT,
|
||||||
|
excel: false,
|
||||||
|
timezone: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
function csvEscaped(text: string) {
|
||||||
if (!text) {
|
if (!text) {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
@ -25,13 +37,13 @@ function csvEscaped(text) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const domParser = new DOMParser();
|
const domParser = new DOMParser();
|
||||||
function htmlDecoded(text) {
|
function htmlDecoded(text: string) {
|
||||||
if (!text) {
|
if (!text) {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
const regexp = /&[^;]+;/g;
|
const regexp = /&[^;]+;/g;
|
||||||
function htmlDecoded(value) {
|
function htmlDecoded(value: string) {
|
||||||
const parsedDom = domParser.parseFromString(value, 'text/html');
|
const parsedDom = domParser.parseFromString(value, 'text/html');
|
||||||
return parsedDom.body.textContent;
|
return parsedDom.body.textContent;
|
||||||
}
|
}
|
||||||
@ -58,14 +70,19 @@ function formatRow(row, addEndRowDelimiter = true) {
|
|||||||
return addEndRowDelimiter ? text + END_ROW : text;
|
return addEndRowDelimiter ? text + END_ROW : text;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function convertSeriesListToCsv(seriesList, dateTimeFormat = DEFAULT_DATETIME_FORMAT, excel = false) {
|
export function convertSeriesListToCsv(seriesList, options: Partial<SeriesListToCsvColumnsOptions>) {
|
||||||
|
const { dateTimeFormat, excel, timezone } = { ...defaultOptions, ...options };
|
||||||
let text = formatSpecialHeader(excel) + formatRow(['Series', 'Time', 'Value']);
|
let text = formatSpecialHeader(excel) + formatRow(['Series', 'Time', 'Value']);
|
||||||
for (let seriesIndex = 0; seriesIndex < seriesList.length; seriesIndex += 1) {
|
for (let seriesIndex = 0; seriesIndex < seriesList.length; seriesIndex += 1) {
|
||||||
for (let i = 0; i < seriesList[seriesIndex].datapoints.length; i += 1) {
|
for (let i = 0; i < seriesList[seriesIndex].datapoints.length; i += 1) {
|
||||||
text += formatRow(
|
text += formatRow(
|
||||||
[
|
[
|
||||||
seriesList[seriesIndex].alias,
|
seriesList[seriesIndex].alias,
|
||||||
dateTime(seriesList[seriesIndex].datapoints[i][POINT_TIME_INDEX]).format(dateTimeFormat),
|
timezone === 'utc'
|
||||||
|
? dateTime(seriesList[seriesIndex].datapoints[i][POINT_TIME_INDEX])
|
||||||
|
.utc()
|
||||||
|
.format(dateTimeFormat)
|
||||||
|
: dateTime(seriesList[seriesIndex].datapoints[i][POINT_TIME_INDEX]).format(dateTimeFormat),
|
||||||
seriesList[seriesIndex].datapoints[i][POINT_VALUE_INDEX],
|
seriesList[seriesIndex].datapoints[i][POINT_VALUE_INDEX],
|
||||||
],
|
],
|
||||||
i < seriesList[seriesIndex].datapoints.length - 1 || seriesIndex < seriesList.length - 1
|
i < seriesList[seriesIndex].datapoints.length - 1 || seriesIndex < seriesList.length - 1
|
||||||
@ -75,12 +92,13 @@ export function convertSeriesListToCsv(seriesList, dateTimeFormat = DEFAULT_DATE
|
|||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function exportSeriesListToCsv(seriesList, dateTimeFormat = DEFAULT_DATETIME_FORMAT, excel = false) {
|
export function exportSeriesListToCsv(seriesList, options: Partial<SeriesListToCsvColumnsOptions>) {
|
||||||
const text = convertSeriesListToCsv(seriesList, dateTimeFormat, excel);
|
const text = convertSeriesListToCsv(seriesList, options);
|
||||||
saveSaveBlob(text, EXPORT_FILENAME);
|
saveSaveBlob(text, EXPORT_FILENAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function convertSeriesListToCsvColumns(seriesList, dateTimeFormat = DEFAULT_DATETIME_FORMAT, excel = false) {
|
export function convertSeriesListToCsvColumns(seriesList, options: Partial<SeriesListToCsvColumnsOptions>) {
|
||||||
|
const { dateTimeFormat, excel, timezone } = { ...defaultOptions, ...options };
|
||||||
// add header
|
// add header
|
||||||
let text =
|
let text =
|
||||||
formatSpecialHeader(excel) +
|
formatSpecialHeader(excel) +
|
||||||
@ -96,7 +114,13 @@ export function convertSeriesListToCsvColumns(seriesList, dateTimeFormat = DEFAU
|
|||||||
|
|
||||||
// make text
|
// make text
|
||||||
for (let i = 0; i < extendedDatapointsList[0].length; i += 1) {
|
for (let i = 0; i < extendedDatapointsList[0].length; i += 1) {
|
||||||
const timestamp = dateTime(extendedDatapointsList[0][i][POINT_TIME_INDEX]).format(dateTimeFormat);
|
const timestamp =
|
||||||
|
timezone === 'utc'
|
||||||
|
? dateTime(extendedDatapointsList[0][i][POINT_TIME_INDEX])
|
||||||
|
.utc()
|
||||||
|
.format(dateTimeFormat)
|
||||||
|
: dateTime(extendedDatapointsList[0][i][POINT_TIME_INDEX]).format(dateTimeFormat);
|
||||||
|
|
||||||
text += formatRow(
|
text += formatRow(
|
||||||
[timestamp].concat(
|
[timestamp].concat(
|
||||||
extendedDatapointsList.map(datapoints => {
|
extendedDatapointsList.map(datapoints => {
|
||||||
@ -143,8 +167,8 @@ function mergeSeriesByTime(seriesList) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function exportSeriesListToCsvColumns(seriesList, dateTimeFormat = DEFAULT_DATETIME_FORMAT, excel = false) {
|
export function exportSeriesListToCsvColumns(seriesList, options: Partial<SeriesListToCsvColumnsOptions>) {
|
||||||
const text = convertSeriesListToCsvColumns(seriesList, dateTimeFormat, excel);
|
const text = convertSeriesListToCsvColumns(seriesList, options);
|
||||||
saveSaveBlob(text, EXPORT_FILENAME);
|
saveSaveBlob(text, EXPORT_FILENAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import angular from 'angular';
|
import angular from 'angular';
|
||||||
import * as fileExport from 'app/core/utils/file_export';
|
import * as fileExport from 'app/core/utils/file_export';
|
||||||
import appEvents from 'app/core/app_events';
|
import appEvents from 'app/core/app_events';
|
||||||
|
import { DashboardSrv } from 'app/features/dashboard/services/DashboardSrv';
|
||||||
|
|
||||||
export class ExportDataModalCtrl {
|
export class ExportDataModalCtrl {
|
||||||
private data: any[];
|
private data: any[];
|
||||||
@ -9,14 +10,23 @@ export class ExportDataModalCtrl {
|
|||||||
dateTimeFormat = 'YYYY-MM-DDTHH:mm:ssZ';
|
dateTimeFormat = 'YYYY-MM-DDTHH:mm:ssZ';
|
||||||
excel = false;
|
excel = false;
|
||||||
|
|
||||||
|
/** @ngInject */
|
||||||
|
constructor(private dashboardSrv: DashboardSrv) {}
|
||||||
|
|
||||||
export() {
|
export() {
|
||||||
|
const timezone = this.dashboardSrv.getCurrent().timezone;
|
||||||
|
const options = {
|
||||||
|
excel: this.excel,
|
||||||
|
dateTimeFormat: this.dateTimeFormat,
|
||||||
|
timezone,
|
||||||
|
};
|
||||||
if (this.panel === 'table') {
|
if (this.panel === 'table') {
|
||||||
fileExport.exportTableDataToCsv(this.data, this.excel);
|
fileExport.exportTableDataToCsv(this.data, this.excel);
|
||||||
} else {
|
} else {
|
||||||
if (this.asRows) {
|
if (this.asRows) {
|
||||||
fileExport.exportSeriesListToCsv(this.data, this.dateTimeFormat, this.excel);
|
fileExport.exportSeriesListToCsv(this.data, options);
|
||||||
} else {
|
} else {
|
||||||
fileExport.exportSeriesListToCsvColumns(this.data, this.dateTimeFormat, this.excel);
|
fileExport.exportSeriesListToCsvColumns(this.data, options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user