mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Feat: Angular panels & SeriesData to Table/TimeSeries (#16266)
Similar to how the react panels make sure all data is SeriesData before passing it to the react panels, this makes sure SeriesData is converted to TableData|TimeSeries before passing it to the angular panels. It also changes the typing to encourage using SeriesData for future development
This commit is contained in:
committed by
Torkel Ödegaard
parent
236074ea47
commit
03951c00cb
@@ -2,7 +2,12 @@ import { TimeRange, RawTimeRange } from './time';
|
||||
import { PluginMeta } from './plugin';
|
||||
import { TableData, TimeSeries, SeriesData } from './data';
|
||||
|
||||
export type DataQueryResponseData = TimeSeries | TableData | SeriesData | any;
|
||||
/**
|
||||
* Starting in v6.2 SeriesData can represent both TimeSeries and TableData
|
||||
*/
|
||||
export type LegacyResponseData = TimeSeries | TableData | any;
|
||||
|
||||
export type DataQueryResponseData = SeriesData | LegacyResponseData;
|
||||
|
||||
export interface DataQueryResponse {
|
||||
data: DataQueryResponseData[];
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
import { toSeriesData, guessFieldTypes, guessFieldTypeFromValue } from './processSeriesData';
|
||||
import { FieldType } from '../types/data';
|
||||
import {
|
||||
isSeriesData,
|
||||
toLegacyResponseData,
|
||||
isTableData,
|
||||
toSeriesData,
|
||||
guessFieldTypes,
|
||||
guessFieldTypeFromValue,
|
||||
} from './processSeriesData';
|
||||
import { FieldType, TimeSeries } from '../types/data';
|
||||
import moment from 'moment';
|
||||
|
||||
describe('toSeriesData', () => {
|
||||
@@ -63,3 +70,33 @@ describe('toSeriesData', () => {
|
||||
expect(norm.fields[3].type).toBe(FieldType.time); // based on name
|
||||
});
|
||||
});
|
||||
|
||||
describe('SerisData backwards compatibility', () => {
|
||||
it('converts TimeSeries to series and back again', () => {
|
||||
const timeseries = {
|
||||
target: 'Field Name',
|
||||
datapoints: [[100, 1], [200, 2]],
|
||||
};
|
||||
const series = toSeriesData(timeseries);
|
||||
expect(isSeriesData(timeseries)).toBeFalsy();
|
||||
expect(isSeriesData(series)).toBeTruthy();
|
||||
|
||||
const roundtrip = toLegacyResponseData(series) as TimeSeries;
|
||||
expect(isSeriesData(roundtrip)).toBeFalsy();
|
||||
expect(roundtrip.target).toBe(timeseries.target);
|
||||
});
|
||||
|
||||
it('converts TableData to series and back again', () => {
|
||||
const table = {
|
||||
columns: [{ text: 'a', unit: 'ms' }, { text: 'b', unit: 'zz' }, { text: 'c', unit: 'yy' }],
|
||||
rows: [[100, 1, 'a'], [200, 2, 'a']],
|
||||
};
|
||||
const series = toSeriesData(table);
|
||||
expect(isTableData(table)).toBeTruthy();
|
||||
expect(isSeriesData(series)).toBeTruthy();
|
||||
|
||||
const roundtrip = toLegacyResponseData(series) as TimeSeries;
|
||||
expect(isTableData(roundtrip)).toBeTruthy();
|
||||
expect(roundtrip).toMatchObject(table);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -157,6 +157,32 @@ export const toSeriesData = (data: any): SeriesData => {
|
||||
throw new Error('Unsupported data format');
|
||||
};
|
||||
|
||||
export const toLegacyResponseData = (series: SeriesData): TimeSeries | TableData => {
|
||||
const { fields, rows } = series;
|
||||
|
||||
if (fields.length === 2) {
|
||||
const type = guessFieldTypeFromTable(series, 1);
|
||||
if (type === FieldType.time) {
|
||||
return {
|
||||
target: fields[0].name || series.name,
|
||||
datapoints: rows,
|
||||
unit: fields[0].unit,
|
||||
} as TimeSeries;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
columns: fields.map(f => {
|
||||
return {
|
||||
text: f.name,
|
||||
filterable: f.filterable,
|
||||
unit: f.unit,
|
||||
};
|
||||
}),
|
||||
rows,
|
||||
};
|
||||
};
|
||||
|
||||
export function sortSeriesData(data: SeriesData, sortIndex?: number, reverse = false): SeriesData {
|
||||
if (isNumber(sortIndex)) {
|
||||
const copy = {
|
||||
|
||||
@@ -6,6 +6,7 @@ import { PanelCtrl } from 'app/features/panel/panel_ctrl';
|
||||
import { getExploreUrl } from 'app/core/utils/explore';
|
||||
import { applyPanelTimeOverrides, getResolution } from 'app/features/dashboard/utils/panel';
|
||||
import { ContextSrv } from 'app/core/services/context_srv';
|
||||
import { toLegacyResponseData, isSeriesData } from '@grafana/ui';
|
||||
|
||||
class MetricsPanelCtrl extends PanelCtrl {
|
||||
scope: any;
|
||||
@@ -188,7 +189,14 @@ class MetricsPanelCtrl extends PanelCtrl {
|
||||
result = { data: [] };
|
||||
}
|
||||
|
||||
this.events.emit('data-received', result.data);
|
||||
// Make sure the data is TableData | TimeSeries
|
||||
const data = result.data.map(v => {
|
||||
if (isSeriesData(v)) {
|
||||
return toLegacyResponseData(v);
|
||||
}
|
||||
return v;
|
||||
});
|
||||
this.events.emit('data-received', data);
|
||||
}
|
||||
|
||||
handleDataStream(stream) {
|
||||
|
||||
Reference in New Issue
Block a user