Field overrides: added matcher to match all fields within frame/query. (#28872)

This commit is contained in:
Marcus Andersson 2020-12-01 09:38:35 +01:00 committed by GitHub
parent 3c229c6bee
commit cbb2c0a5d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 123 additions and 2 deletions

View File

@ -23,6 +23,7 @@ export enum FieldMatcherID {
byNames = 'byNames',
byRegexp = 'byRegexp',
byRegexpOrNames = 'byRegexpOrNames',
byFrameRefID = 'byFrameRefID',
// byIndex = 'byIndex',
// byLabel = 'byLabel',
}

View File

@ -306,3 +306,31 @@ describe('Field Regexp or Names Matcher', () => {
}
});
});
describe('Fields returned by query with refId', () => {
it('Match all fields in frame with refId: A', () => {
const data = [
toDataFrame({
refId: 'A',
fields: [{ name: 'field_1' }, { name: 'field_2' }],
}),
toDataFrame({
refId: 'B',
fields: [{ name: 'field_1' }, { name: 'field_2' }],
}),
];
const matcher = getFieldMatcher({
id: FieldMatcherID.byFrameRefID,
options: 'A',
});
const frameA = data[0];
expect(matcher(frameA.fields[0], frameA, data)).toBe(true);
expect(matcher(frameA.fields[1], frameA, data)).toBe(true);
const frameB = data[1];
expect(matcher(frameB.fields[0], frameB, data)).toBe(false);
expect(matcher(frameB.fields[1], frameB, data)).toBe(false);
});
});

View File

@ -66,6 +66,28 @@ const regexpFieldNameMatcher: FieldMatcherInfo<string> = {
},
};
/**
* Field matcher that will match all fields that exists in a
* data frame with configured refId.
* @public
*/
const fieldsInFrameMatcher: FieldMatcherInfo<string> = {
id: FieldMatcherID.byFrameRefID,
name: 'Fields by frame refId',
description: 'match all fields returned in data frame with refId.',
defaultOptions: '',
get: (refId: string): FieldMatcher => {
return (field: Field, frame: DataFrame, allFrames: DataFrame[]) => {
return frame.refId === refId;
};
},
getOptionsDisplayText: (refId: string): string => {
return `Math all fields returned by query with reference ID: ${refId}`;
},
};
const regexpOrMultipleNamesMatcher: FieldMatcherInfo<RegexpOrNamesMatcherOptions> = {
id: FieldMatcherID.byRegexpOrNames,
name: 'Field Name by Regexp or Names',
@ -127,7 +149,13 @@ const frameNameMatcher: FrameMatcherInfo<string> = {
* Registry Initialization
*/
export function getFieldNameMatchers(): FieldMatcherInfo[] {
return [fieldNameMatcher, regexpFieldNameMatcher, multipleFieldNamesMatcher, regexpOrMultipleNamesMatcher];
return [
fieldNameMatcher,
regexpFieldNameMatcher,
multipleFieldNamesMatcher,
regexpOrMultipleNamesMatcher,
fieldsInFrameMatcher,
];
}
export function getFrameNameMatchers(): FrameMatcherInfo[] {

View File

@ -0,0 +1,63 @@
import React, { memo, useMemo, useCallback } from 'react';
import { MatcherUIProps, FieldMatcherUIRegistryItem } from './types';
import { FieldMatcherID, fieldMatchers, SelectableValue, DataFrame } from '@grafana/data';
import { Select } from '../Select/Select';
/**
* UI to configure "fields by frame refId"-matcher.
* @public
*/
export const FieldsByFrameRefIdMatcher = memo<MatcherUIProps<string>>(props => {
const { data, options, onChange: onChangeFromProps } = props;
const referenceIDs = useFrameRefIds(data);
const selectOptions = useSelectOptions(referenceIDs);
const onChange = useCallback(
(selection: SelectableValue<string>) => {
if (!selection.value || !referenceIDs.has(selection.value)) {
return;
}
return onChangeFromProps(selection.value);
},
[referenceIDs, onChangeFromProps]
);
const selectedOption = selectOptions.find(v => v.value === options);
return <Select value={selectedOption} options={selectOptions} onChange={onChange} />;
});
/**
* Registry item for UI to configure "fields by frame refId"-matcher.
* @public
*/
export const fieldsByFrameRefIdItem: FieldMatcherUIRegistryItem<string> = {
id: FieldMatcherID.byFrameRefID,
component: FieldsByFrameRefIdMatcher,
matcher: fieldMatchers.get(FieldMatcherID.byFrameRefID),
name: 'Fields returned by query',
description: 'Set properties for fields from a specific query',
optionsToLabel: options => options,
};
const useFrameRefIds = (data: DataFrame[]): Set<string> => {
return useMemo(() => {
const refIds: Set<string> = new Set();
for (const frame of data) {
if (frame.refId) {
refIds.add(frame.refId);
}
}
return refIds;
}, [data]);
};
const useSelectOptions = (displayNames: Set<string>): Array<SelectableValue<string>> => {
return useMemo(() => {
return Array.from(displayNames).map(n => ({
value: n,
label: n,
}));
}, [displayNames]);
};

View File

@ -3,7 +3,8 @@ import { FieldMatcherUIRegistryItem } from './types';
import { fieldNameMatcherItem } from './FieldNameMatcherEditor';
import { fieldNameByRegexMatcherItem } from './FieldNameByRegexMatcherEditor';
import { fieldTypeMatcherItem } from './FieldTypeMatcherEditor';
import { fieldsByFrameRefIdItem } from './FieldsByFrameRefIdMatcher';
export const fieldMatchersUI = new Registry<FieldMatcherUIRegistryItem<any>>(() => {
return [fieldNameMatcherItem, fieldNameByRegexMatcherItem, fieldTypeMatcherItem];
return [fieldNameMatcherItem, fieldNameByRegexMatcherItem, fieldTypeMatcherItem, fieldsByFrameRefIdItem];
});