mirror of
https://github.com/grafana/grafana.git
synced 2024-11-24 09:50:29 -06:00
Transformations: Grouping to matrix empty value option (#55591)
* feat: grouping matrix transformer empty value Allow grouping matrix data transformer to define the value used when the matrix entry is not defined * fix: grouping to matrix empty value test * remove balel width for empty value text Co-authored-by: bohandley <brendan.ohandley@gmail.com>
This commit is contained in:
parent
c4b4baea2a
commit
8adb16b662
@ -1,5 +1,5 @@
|
||||
import { toDataFrame } from '../../dataframe';
|
||||
import { DataTransformerConfig, FieldType, Field } from '../../types';
|
||||
import { DataTransformerConfig, FieldType, Field, SpecialValue } from '../../types';
|
||||
import { mockTransformationsRegistry } from '../../utils/tests/mockTransformationsRegistry';
|
||||
import { ArrayVector } from '../../vector';
|
||||
import { transformDataFrame } from '../transformDataFrame';
|
||||
@ -105,6 +105,49 @@ describe('Grouping to Matrix', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('generates Matrix with empty entries', async () => {
|
||||
const cfg: DataTransformerConfig<GroupingToMatrixTransformerOptions> = {
|
||||
id: DataTransformerID.groupingToMatrix,
|
||||
options: {
|
||||
emptyValue: SpecialValue.Null,
|
||||
},
|
||||
};
|
||||
|
||||
const seriesA = toDataFrame({
|
||||
name: 'A',
|
||||
fields: [
|
||||
{ name: 'Time', type: FieldType.time, values: [1000, 1001] },
|
||||
{ name: 'Value', type: FieldType.number, values: [1, 2] },
|
||||
],
|
||||
});
|
||||
|
||||
await expect(transformDataFrame([cfg], [seriesA])).toEmitValuesWith((received) => {
|
||||
const processed = received[0];
|
||||
const expected: Field[] = [
|
||||
{
|
||||
name: 'Time\\Time',
|
||||
type: FieldType.string,
|
||||
values: new ArrayVector([1000, 1001]),
|
||||
config: {},
|
||||
},
|
||||
{
|
||||
name: '1000',
|
||||
type: FieldType.number,
|
||||
values: new ArrayVector([1, null]),
|
||||
config: {},
|
||||
},
|
||||
{
|
||||
name: '1001',
|
||||
type: FieldType.number,
|
||||
values: new ArrayVector([null, 2]),
|
||||
config: {},
|
||||
},
|
||||
];
|
||||
|
||||
expect(processed[0].fields).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
it('generates Matrix with multiple fields and value type', async () => {
|
||||
const cfg: DataTransformerConfig<GroupingToMatrixTransformerOptions> = {
|
||||
id: DataTransformerID.groupingToMatrix,
|
||||
|
@ -2,7 +2,7 @@ import { map } from 'rxjs/operators';
|
||||
|
||||
import { MutableDataFrame } from '../../dataframe';
|
||||
import { getFieldDisplayName } from '../../field/fieldState';
|
||||
import { DataFrame, DataTransformerInfo, Field, FieldType, Vector } from '../../types';
|
||||
import { DataFrame, DataTransformerInfo, Field, FieldType, SpecialValue, Vector } from '../../types';
|
||||
|
||||
import { DataTransformerID } from './ids';
|
||||
|
||||
@ -10,11 +10,13 @@ export interface GroupingToMatrixTransformerOptions {
|
||||
columnField?: string;
|
||||
rowField?: string;
|
||||
valueField?: string;
|
||||
emptyValue?: SpecialValue;
|
||||
}
|
||||
|
||||
const DEFAULT_COLUMN_FIELD = 'Time';
|
||||
const DEFAULT_ROW_FIELD = 'Time';
|
||||
const DEFAULT_VALUE_FIELD = 'Value';
|
||||
const DEFAULT_EMPTY_VALUE = SpecialValue.Empty;
|
||||
|
||||
export const groupingToMatrixTransformer: DataTransformerInfo<GroupingToMatrixTransformerOptions> = {
|
||||
id: DataTransformerID.groupingToMatrix,
|
||||
@ -32,6 +34,7 @@ export const groupingToMatrixTransformer: DataTransformerInfo<GroupingToMatrixTr
|
||||
const columnFieldMatch = options.columnField || DEFAULT_COLUMN_FIELD;
|
||||
const rowFieldMatch = options.rowField || DEFAULT_ROW_FIELD;
|
||||
const valueFieldMatch = options.valueField || DEFAULT_VALUE_FIELD;
|
||||
const emptyValue = options.emptyValue || DEFAULT_EMPTY_VALUE;
|
||||
|
||||
// Accept only single queries
|
||||
if (data.length !== 1) {
|
||||
@ -76,7 +79,7 @@ export const groupingToMatrixTransformer: DataTransformerInfo<GroupingToMatrixTr
|
||||
for (const columnName of columnValues) {
|
||||
let values = [];
|
||||
for (const rowName of rowValues) {
|
||||
const value = matrixValues[columnName][rowName] ?? '';
|
||||
const value = matrixValues[columnName][rowName] ?? getSpecialValue(emptyValue);
|
||||
values.push(value);
|
||||
}
|
||||
|
||||
@ -114,3 +117,17 @@ function findKeyField(frame: DataFrame, matchTitle: string): Field | null {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function getSpecialValue(specialValue: SpecialValue) {
|
||||
switch (specialValue) {
|
||||
case SpecialValue.False:
|
||||
return false;
|
||||
case SpecialValue.True:
|
||||
return true;
|
||||
case SpecialValue.Null:
|
||||
return null;
|
||||
case SpecialValue.Empty:
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
@ -84,3 +84,13 @@ export interface MatcherConfig<TOptions = any> {
|
||||
id: string;
|
||||
options?: TOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export enum SpecialValue {
|
||||
True = 'true',
|
||||
False = 'false',
|
||||
Null = 'null',
|
||||
Empty = 'empty',
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import {
|
||||
TransformerRegistryItem,
|
||||
TransformerUIProps,
|
||||
GroupingToMatrixTransformerOptions,
|
||||
SpecialValue,
|
||||
} from '@grafana/data';
|
||||
import { InlineField, InlineFieldRow, Select } from '@grafana/ui';
|
||||
|
||||
@ -49,6 +50,23 @@ export const GroupingToMatrixTransformerEditor: React.FC<TransformerUIProps<Grou
|
||||
[onChange, options]
|
||||
);
|
||||
|
||||
const specialValueOptions: Array<SelectableValue<SpecialValue>> = [
|
||||
{ label: 'Null', value: SpecialValue.Null, description: 'Null value' },
|
||||
{ label: 'True', value: SpecialValue.True, description: 'Boolean true value' },
|
||||
{ label: 'False', value: SpecialValue.False, description: 'Boolean false value' },
|
||||
{ label: 'Empty', value: SpecialValue.Empty, description: 'Empty string' },
|
||||
];
|
||||
|
||||
const onSelectEmptyValue = useCallback(
|
||||
(value: SelectableValue<SpecialValue>) => {
|
||||
onChange({
|
||||
...options,
|
||||
emptyValue: value?.value,
|
||||
});
|
||||
},
|
||||
[onChange, options]
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<InlineFieldRow>
|
||||
@ -61,6 +79,9 @@ export const GroupingToMatrixTransformerEditor: React.FC<TransformerUIProps<Grou
|
||||
<InlineField label="Cell Value" labelWidth={10}>
|
||||
<Select options={fieldNames} value={options.valueField} onChange={onSelectValue} isClearable />
|
||||
</InlineField>
|
||||
<InlineField label="Empty Value">
|
||||
<Select options={specialValueOptions} value={options.emptyValue} onChange={onSelectEmptyValue} isClearable />
|
||||
</InlineField>
|
||||
</InlineFieldRow>
|
||||
</>
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user