Commit 59bea141 by Torkel Ödegaard Committed by GitHub

Transformations: Simple fix for labels to fields problem with time series field names (#23828)

* Simple fix for labels to fields transform problem

* Added unit test
parent fb8a555f
......@@ -43,6 +43,38 @@ describe('Labels as Columns', () => {
expect(result[0].fields).toEqual(expected);
});
it('data frames where frame name is same as value field name replace field name with name Value', () => {
const cfg: DataTransformerConfig<LabelsToFieldsOptions> = {
id: DataTransformerID.labelsToFields,
options: {},
};
const oneValueOneLabelA = toDataFrame({
name: 'A',
fields: [
{ name: 'time', type: FieldType.time, values: [1000] },
{ name: 'A', type: FieldType.number, values: [1], labels: { location: 'inside' } },
],
});
const oneValueOneLabelB = toDataFrame({
name: 'B',
fields: [
{ name: 'time', type: FieldType.time, values: [2000] },
{ name: 'B', type: FieldType.number, values: [-1], labels: { location: 'outside' } },
],
});
const result = transformDataFrame([cfg], [oneValueOneLabelA, oneValueOneLabelB]);
const expected: Field[] = [
{ name: 'time', type: FieldType.time, values: new ArrayVector([1000, 2000]), config: {} },
{ name: 'location', type: FieldType.string, values: new ArrayVector(['inside', 'outside']), config: {} },
{ name: 'Value', type: FieldType.number, values: new ArrayVector([1, -1]), config: {} },
];
expect(result[0].fields).toEqual(expected);
});
it('data frame with 2 values and 1 label', () => {
const cfg: DataTransformerConfig<LabelsToFieldsOptions> = {
id: DataTransformerID.labelsToFields,
......
import { DataFrame, DataTransformerInfo, FieldType } from '../../types';
import { DataFrame, DataTransformerInfo, FieldType, Field } from '../../types';
import { DataTransformerID } from './ids';
import { MutableDataFrame } from '../../dataframe';
import { ArrayVector } from '../../vector';
......@@ -21,7 +21,8 @@ export const labelsToFieldsTransformer: DataTransformerInfo<LabelsToFieldsOption
return data;
}
const framesWithoutTimeField = filterFieldsTransformer.transformer({ exclude: { id: FieldMatcherID.time } })(data);
// get frames with only value fields
const framesWithoutTimeField = getFramesWithOnlyValueFields(data);
if (!framesWithoutTimeField.length || !framesWithoutTimeField[0].fields.length) {
return data;
}
......@@ -64,6 +65,46 @@ export const labelsToFieldsTransformer: DataTransformerInfo<LabelsToFieldsOption
},
};
function getFramesWithOnlyValueFields(data: DataFrame[]): DataFrame[] {
const processed: DataFrame[] = [];
for (const series of data) {
const fields: Field[] = [];
for (let i = 0; i < series.fields.length; i++) {
const field = series.fields[i];
if (field.type !== FieldType.number) {
continue;
}
// When we transform a time series to DataFrame we put series name in field name.
// This casues problems for this transformer that want all time series values in a Value column
// So here we change field names that have same name as DataFrame to just Value
if (field.name === series.name) {
fields.push({
...field,
name: 'Value',
});
} else {
fields.push(field);
}
}
if (!fields.length) {
continue;
}
const copy = {
...series, // all the other properties
fields, // but a different set of fields
};
processed.push(copy);
}
return processed;
}
function addOrAppendMapItem(args: { map: Map; series: number; column: string; type: FieldType; isValue?: boolean }) {
const { map, column, type, series, isValue = false } = args;
// we're using the fact that the series (number) will automatically become a string prop on the object
......@@ -85,6 +126,7 @@ function createColumnsMap(framesWithTimeField: DataFrame[], framesWithoutTimeFie
const timeFrame = framesWithTimeField[frameIndex];
const otherFrame = framesWithoutTimeField[frameIndex];
const timeField = timeFrame.fields[0];
addOrAppendMapItem({ map, column: timeField.name, series: frameIndex, type: timeField.type });
for (let valueIndex = 0; valueIndex < timeFrame.length; valueIndex++) {
......
......@@ -10,10 +10,10 @@ export const LabelsAsFieldsTransformerEditor: React.FC<TransformerUIProps<Labels
return null;
};
export const labelsAsFieldsTransformerRegistryItem: TransformerRegistyItem<LabelsToFieldsOptions> = {
export const labelsToFieldsTransformerRegistryItem: TransformerRegistyItem<LabelsToFieldsOptions> = {
id: DataTransformerID.labelsToFields,
editor: LabelsAsFieldsTransformerEditor,
transformation: standardTransformers.labelsToFieldsTransformer,
name: 'Labels as fields',
description: 'Groups series by time and return labels as fields',
name: 'Labels to fields',
description: 'Groups series by time and return labels or tags as fields',
};
......@@ -5,7 +5,7 @@ import { filterFramesByRefIdTransformRegistryItem } from '../components/Transfor
import { organizeFieldsTransformRegistryItem } from '../components/TransformersUI/OrganizeFieldsTransformerEditor';
import { seriesToFieldsTransformerRegistryItem } from '../components/TransformersUI/SeriesToFieldsTransformerEditor';
import { calculateFieldTransformRegistryItem } from '../components/TransformersUI/CalculateFieldTransformerEditor';
import { labelsAsFieldsTransformerRegistryItem } from '../components/TransformersUI/LabelsAsFieldsTransformerEditor';
import { labelsToFieldsTransformerRegistryItem } from '../components/TransformersUI/LabelsToFieldsTransformerEditor';
export const getStandardTransformers = (): Array<TransformerRegistyItem<any>> => {
return [
......@@ -15,6 +15,6 @@ export const getStandardTransformers = (): Array<TransformerRegistyItem<any>> =>
organizeFieldsTransformRegistryItem,
seriesToFieldsTransformerRegistryItem,
calculateFieldTransformRegistryItem,
labelsAsFieldsTransformerRegistryItem,
labelsToFieldsTransformerRegistryItem,
];
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment