diff --git a/packages/grafana-data/src/transformations/transformers/calculateField.test.ts b/packages/grafana-data/src/transformations/transformers/calculateField.test.ts index 4e0fc5a013f..d119af9bd19 100644 --- a/packages/grafana-data/src/transformations/transformers/calculateField.test.ts +++ b/packages/grafana-data/src/transformations/transformers/calculateField.test.ts @@ -21,6 +21,7 @@ const seriesBC = toDataFrame({ { name: 'B', type: FieldType.number, values: [2, 200] }, { name: 'C', type: FieldType.number, values: [3, 300] }, { name: 'D', type: FieldType.string, values: ['first', 'second'] }, + { name: 'E', type: FieldType.boolean, values: [true, false] }, ], }); @@ -48,6 +49,7 @@ describe('calculateField transformer w/ timeseries', () => { B: 2, C: 3, D: 'first', + E: true, 'The Total': 6, TheTime: 1000, }, @@ -56,6 +58,7 @@ describe('calculateField transformer w/ timeseries', () => { B: 200, C: 300, D: 'second', + E: false, 'The Total': 600, TheTime: 2000, }, @@ -129,7 +132,7 @@ describe('calculateField transformer w/ timeseries', () => { mode: CalculateFieldMode.BinaryOperation, binary: { left: 'B', - operation: BinaryOperationID.Add, + operator: BinaryOperationID.Add, right: 'C', }, replaceFields: true, @@ -160,7 +163,7 @@ describe('calculateField transformer w/ timeseries', () => { mode: CalculateFieldMode.BinaryOperation, binary: { left: 'B', - operation: BinaryOperationID.Add, + operator: BinaryOperationID.Add, right: '2', }, replaceFields: true, @@ -183,4 +186,37 @@ describe('calculateField transformer w/ timeseries', () => { ]); }); }); + + it('boolean field', async () => { + const cfg = { + id: DataTransformerID.calculateField, + options: { + mode: CalculateFieldMode.BinaryOperation, + binary: { + left: 'E', + operator: BinaryOperationID.Multiply, + right: '1', + }, + replaceFields: true, + }, + }; + + await expect(transformDataFrame([cfg], [seriesBC])).toEmitValuesWith((received) => { + const data = received[0]; + const filtered = data[0]; + const rows = new DataFrameView(filtered).toArray(); + expect(rows).toMatchInlineSnapshot(` + Array [ + Object { + "E * 1": 1, + "TheTime": 1000, + }, + Object { + "E * 1": 0, + "TheTime": 2000, + }, + ] + `); + }); + }); }); diff --git a/packages/grafana-data/src/transformations/transformers/calculateField.ts b/packages/grafana-data/src/transformations/transformers/calculateField.ts index 6dddd055124..8dd1812e151 100644 --- a/packages/grafana-data/src/transformations/transformers/calculateField.ts +++ b/packages/grafana-data/src/transformations/transformers/calculateField.ts @@ -7,6 +7,7 @@ import { getFieldMatcher } from '../matchers'; import { FieldMatcherID } from '../matchers/ids'; import { RowVector } from '../../vector/RowVector'; import { ArrayVector, BinaryOperationVector, ConstantVector } from '../../vector'; +import { AsNumberVector } from '../../vector/AsNumberVector'; import { getTimeField } from '../../dataframe/processDataFrame'; import defaults from 'lodash/defaults'; import { BinaryOperationID, binaryOperators } from '../../utils/binaryOperators'; @@ -187,6 +188,9 @@ function findFieldValuesWithNameOrConstant(frame: DataFrame, name: string, allFr for (const f of frame.fields) { if (name === getFieldDisplayName(f, frame, allFrames)) { + if (f.type === FieldType.boolean) { + return new AsNumberVector(f.values); + } return f.values; } } diff --git a/packages/grafana-data/src/vector/AsNumberVector.ts b/packages/grafana-data/src/vector/AsNumberVector.ts new file mode 100644 index 00000000000..25645187de3 --- /dev/null +++ b/packages/grafana-data/src/vector/AsNumberVector.ts @@ -0,0 +1,16 @@ +import { Vector } from '../types'; +import { FunctionalVector } from './FunctionalVector'; + +export class AsNumberVector extends FunctionalVector { + constructor(private field: Vector) { + super(); + } + + get length() { + return this.field.length; + } + + get(index: number) { + return +this.field.get(index); + } +} diff --git a/packages/grafana-data/src/vector/index.ts b/packages/grafana-data/src/vector/index.ts index 805048065c3..5401189d278 100644 --- a/packages/grafana-data/src/vector/index.ts +++ b/packages/grafana-data/src/vector/index.ts @@ -6,5 +6,6 @@ export * from './BinaryOperationVector'; export * from './SortedVector'; export * from './FormattedVector'; export * from './IndexVector'; +export * from './AsNumberVector'; export { vectorator } from './FunctionalVector'; diff --git a/public/app/core/components/TransformersUI/CalculateFieldTransformerEditor.tsx b/public/app/core/components/TransformersUI/CalculateFieldTransformerEditor.tsx index 07233fd33d7..50c23bf806f 100644 --- a/public/app/core/components/TransformersUI/CalculateFieldTransformerEditor.tsx +++ b/public/app/core/components/TransformersUI/CalculateFieldTransformerEditor.tsx @@ -39,6 +39,8 @@ const calculationModes = [ { value: CalculateFieldMode.ReduceRow, label: 'Reduce row' }, ]; +const okTypes = new Set([FieldType.time, FieldType.number, FieldType.string]); + export class CalculateFieldTransformerEditor extends React.PureComponent< CalculateFieldTransformerEditorProps, CalculateFieldTransformerEditorState @@ -86,7 +88,7 @@ export class CalculateFieldTransformerEditor extends React.PureComponent< for (const frame of input) { for (const field of frame.fields) { - if (field.type !== FieldType.number) { + if (!okTypes.has(field.type)) { continue; }