Upstream grafana/grafana state of the touched files before 5492c79366
This commit is contained in:
commit
00681578cc
2 files changed
+728
No files matched your search
@@ -0,0 +1,485 @@
|
||||
import { toDataFrame } from '../../dataframe/processDataFrame';
|
||||
import { type DataFrame, FieldType } from '../../types/dataFrame';
|
||||
import { getFieldMatcher } from '../matchers';
|
||||
|
||||
import { FieldMatcherID } from './ids';
|
||||
import { ByNamesMatcherMode } from './nameMatcher';
|
||||
|
||||
describe('Field Name by Regexp Matcher', () => {
|
||||
it('Match all with wildcard regex', () => {
|
||||
const seriesWithNames = toDataFrame({
|
||||
fields: [{ name: 'A hello world' }, { name: 'AAA' }, { name: 'C' }],
|
||||
});
|
||||
const config = {
|
||||
id: FieldMatcherID.byRegexp,
|
||||
options: '/.*/',
|
||||
};
|
||||
|
||||
const matcher = getFieldMatcher(config);
|
||||
|
||||
for (const field of seriesWithNames.fields) {
|
||||
expect(matcher(field, seriesWithNames, [seriesWithNames])).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
it('Match all with decimals regex', () => {
|
||||
const seriesWithNames = toDataFrame({
|
||||
fields: [{ name: '12' }, { name: '112' }, { name: '13' }],
|
||||
});
|
||||
const config = {
|
||||
id: FieldMatcherID.byRegexp,
|
||||
options: '/^\\d+$/',
|
||||
};
|
||||
|
||||
const matcher = getFieldMatcher(config);
|
||||
|
||||
for (const field of seriesWithNames.fields) {
|
||||
expect(matcher(field, seriesWithNames, [seriesWithNames])).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
it('Match complex regex', () => {
|
||||
const seriesWithNames = toDataFrame({
|
||||
fields: [{ name: 'some.instance.path' }, { name: '112' }, { name: '13' }],
|
||||
});
|
||||
const config = {
|
||||
id: FieldMatcherID.byRegexp,
|
||||
options: '/\\b(?:\\S+?\\.)+\\S+\\b$/',
|
||||
};
|
||||
|
||||
const matcher = getFieldMatcher(config);
|
||||
let resultCount = 0;
|
||||
for (const field of seriesWithNames.fields) {
|
||||
if (matcher(field, seriesWithNames, [seriesWithNames])) {
|
||||
resultCount++;
|
||||
}
|
||||
expect(resultCount).toBe(1);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('Field Name Matcher', () => {
|
||||
it('Match only exact name', () => {
|
||||
const seriesWithNames = toDataFrame({
|
||||
fields: [{ name: 'A hello world' }, { name: 'AAA' }, { name: 'C' }],
|
||||
});
|
||||
const config = {
|
||||
id: FieldMatcherID.byName,
|
||||
options: 'C',
|
||||
};
|
||||
|
||||
const matcher = getFieldMatcher(config);
|
||||
|
||||
for (const field of seriesWithNames.fields) {
|
||||
const didMatch = matcher(field, seriesWithNames, [seriesWithNames]);
|
||||
expect(didMatch).toBe(field.name === 'C');
|
||||
}
|
||||
});
|
||||
|
||||
it('Match should respect letter case', () => {
|
||||
const seriesWithNames = toDataFrame({
|
||||
fields: [{ name: '12' }, { name: '112' }, { name: '13' }, { name: 'C' }],
|
||||
});
|
||||
const config = {
|
||||
id: FieldMatcherID.byName,
|
||||
options: 'c',
|
||||
};
|
||||
|
||||
const matcher = getFieldMatcher(config);
|
||||
|
||||
for (const field of seriesWithNames.fields) {
|
||||
expect(matcher(field, seriesWithNames, [seriesWithNames])).toBe(false);
|
||||
}
|
||||
});
|
||||
|
||||
it('Match name or displayName', () => {
|
||||
const seriesWithNames = toDataFrame({
|
||||
fields: [{ name: 'a', config: { displayName: 'LongerName' } }],
|
||||
});
|
||||
const field = seriesWithNames.fields[0];
|
||||
expect(
|
||||
getFieldMatcher({
|
||||
id: FieldMatcherID.byName,
|
||||
options: 'c',
|
||||
})(field, seriesWithNames, [seriesWithNames])
|
||||
).toBe(false); // No match
|
||||
|
||||
expect(
|
||||
getFieldMatcher({
|
||||
id: FieldMatcherID.byName,
|
||||
options: 'a',
|
||||
})(field, seriesWithNames, [seriesWithNames])
|
||||
).toBe(true);
|
||||
|
||||
expect(
|
||||
getFieldMatcher({
|
||||
id: FieldMatcherID.byName,
|
||||
options: 'LongerName',
|
||||
})(field, seriesWithNames, [seriesWithNames])
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('Match none of the field names', () => {
|
||||
const seriesWithNames = toDataFrame({
|
||||
fields: [{ name: 'some.instance.path' }, { name: '112' }, { name: '13' }],
|
||||
});
|
||||
const config = {
|
||||
id: FieldMatcherID.byName,
|
||||
options: '',
|
||||
};
|
||||
|
||||
const matcher = getFieldMatcher(config);
|
||||
|
||||
for (const field of seriesWithNames.fields) {
|
||||
expect(matcher(field, seriesWithNames, [seriesWithNames])).toBe(false);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('Field Multiple Names Matcher', () => {
|
||||
it('Match only exact name', () => {
|
||||
const seriesWithNames = toDataFrame({
|
||||
fields: [{ name: 'A hello world' }, { name: 'AAA' }, { name: 'C' }],
|
||||
});
|
||||
const config = {
|
||||
id: FieldMatcherID.byNames,
|
||||
options: {
|
||||
mode: ByNamesMatcherMode.include,
|
||||
names: ['C'],
|
||||
},
|
||||
};
|
||||
|
||||
const matcher = getFieldMatcher(config);
|
||||
|
||||
for (const field of seriesWithNames.fields) {
|
||||
const didMatch = matcher(field, seriesWithNames, [seriesWithNames]);
|
||||
expect(didMatch).toBe(field.name === 'C');
|
||||
}
|
||||
});
|
||||
|
||||
it('Match should default to include mode', () => {
|
||||
const seriesWithNames = toDataFrame({
|
||||
fields: [{ name: 'A hello world' }, { name: 'AAA' }, { name: 'C' }],
|
||||
});
|
||||
const config = {
|
||||
id: FieldMatcherID.byNames,
|
||||
options: {
|
||||
names: ['C'],
|
||||
},
|
||||
};
|
||||
|
||||
const matcher = getFieldMatcher(config);
|
||||
|
||||
for (const field of seriesWithNames.fields) {
|
||||
const didMatch = matcher(field, seriesWithNames, [seriesWithNames]);
|
||||
expect(didMatch).toBe(field.name === 'C');
|
||||
}
|
||||
});
|
||||
|
||||
it('Match should respect letter case', () => {
|
||||
const seriesWithNames = toDataFrame({
|
||||
fields: [{ name: '12' }, { name: '112' }, { name: '13' }, { name: 'C' }],
|
||||
});
|
||||
const config = {
|
||||
id: FieldMatcherID.byNames,
|
||||
options: {
|
||||
mode: ByNamesMatcherMode.include,
|
||||
names: ['c'],
|
||||
},
|
||||
};
|
||||
|
||||
const matcher = getFieldMatcher(config);
|
||||
|
||||
for (const field of seriesWithNames.fields) {
|
||||
expect(matcher(field, seriesWithNames, [seriesWithNames])).toBe(false);
|
||||
}
|
||||
});
|
||||
|
||||
it('Match none of the field names', () => {
|
||||
const seriesWithNames = toDataFrame({
|
||||
fields: [{ name: 'some.instance.path' }, { name: '112' }, { name: '13' }],
|
||||
});
|
||||
const config = {
|
||||
id: FieldMatcherID.byNames,
|
||||
options: {
|
||||
mode: ByNamesMatcherMode.include,
|
||||
names: [],
|
||||
},
|
||||
};
|
||||
|
||||
const matcher = getFieldMatcher(config);
|
||||
|
||||
for (const field of seriesWithNames.fields) {
|
||||
expect(matcher(field, seriesWithNames, [seriesWithNames])).toBe(false);
|
||||
}
|
||||
});
|
||||
|
||||
it('Match all of the field names', () => {
|
||||
const seriesWithNames = toDataFrame({
|
||||
fields: [{ name: 'some.instance.path' }, { name: '112' }, { name: '13' }],
|
||||
});
|
||||
const config = {
|
||||
id: FieldMatcherID.byNames,
|
||||
options: {
|
||||
mode: ByNamesMatcherMode.include,
|
||||
names: ['some.instance.path', '112', '13'],
|
||||
},
|
||||
};
|
||||
|
||||
const matcher = getFieldMatcher(config);
|
||||
|
||||
for (const field of seriesWithNames.fields) {
|
||||
expect(matcher(field, seriesWithNames, [seriesWithNames])).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
it('Match all but supplied names', () => {
|
||||
const seriesWithNames = toDataFrame({
|
||||
fields: [{ name: 'A hello world' }, { name: 'AAA' }, { name: 'C' }],
|
||||
});
|
||||
const config = {
|
||||
id: FieldMatcherID.byNames,
|
||||
options: {
|
||||
mode: ByNamesMatcherMode.exclude,
|
||||
names: ['C'],
|
||||
},
|
||||
};
|
||||
|
||||
const matcher = getFieldMatcher(config);
|
||||
|
||||
for (const field of seriesWithNames.fields) {
|
||||
const didMatch = matcher(field, seriesWithNames, [seriesWithNames]);
|
||||
expect(didMatch).toBe(field.name !== 'C');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('Field Regexp or Names Matcher', () => {
|
||||
it('Match only exact name by name', () => {
|
||||
const seriesWithNames = toDataFrame({
|
||||
fields: [{ name: 'A hello world' }, { name: 'AAA' }, { name: 'C' }],
|
||||
});
|
||||
const config = {
|
||||
id: FieldMatcherID.byRegexpOrNames,
|
||||
options: {
|
||||
names: ['C'],
|
||||
},
|
||||
};
|
||||
|
||||
const matcher = getFieldMatcher(config);
|
||||
|
||||
for (const field of seriesWithNames.fields) {
|
||||
const didMatch = matcher(field, seriesWithNames, [seriesWithNames]);
|
||||
expect(didMatch).toBe(field.name === 'C');
|
||||
}
|
||||
});
|
||||
|
||||
it('Match all starting with AA', () => {
|
||||
const seriesWithNames = toDataFrame({
|
||||
fields: [{ name: 'A hello world' }, { name: 'AAA' }, { name: 'C' }],
|
||||
});
|
||||
const config = {
|
||||
id: FieldMatcherID.byRegexpOrNames,
|
||||
options: {
|
||||
pattern: '/^AA/',
|
||||
},
|
||||
};
|
||||
|
||||
const matcher = getFieldMatcher(config);
|
||||
|
||||
for (const field of seriesWithNames.fields) {
|
||||
const didMatch = matcher(field, seriesWithNames, [seriesWithNames]);
|
||||
expect(didMatch).toBe(field.name === 'AAA');
|
||||
}
|
||||
});
|
||||
|
||||
it('Match all starting with AA and C', () => {
|
||||
const seriesWithNames = toDataFrame({
|
||||
fields: [{ name: 'A hello world' }, { name: 'AAA' }, { name: 'C' }],
|
||||
});
|
||||
const config = {
|
||||
id: FieldMatcherID.byRegexpOrNames,
|
||||
options: {
|
||||
pattern: '/^AA/',
|
||||
names: ['C'],
|
||||
},
|
||||
};
|
||||
|
||||
const matcher = getFieldMatcher(config);
|
||||
|
||||
for (const field of seriesWithNames.fields) {
|
||||
const didMatch = matcher(field, seriesWithNames, [seriesWithNames]);
|
||||
expect(didMatch).toBe(field.name === 'AAA' || field.name === 'C');
|
||||
}
|
||||
});
|
||||
|
||||
it('Match should respect letter case by name if not igored in pattern', () => {
|
||||
const seriesWithNames = toDataFrame({
|
||||
fields: [{ name: '12' }, { name: '112' }, { name: '13' }, { name: 'C' }],
|
||||
});
|
||||
const config = {
|
||||
id: FieldMatcherID.byRegexpOrNames,
|
||||
options: {
|
||||
names: ['c'],
|
||||
pattern: '/c/i',
|
||||
},
|
||||
};
|
||||
|
||||
const matcher = getFieldMatcher(config);
|
||||
|
||||
for (const field of seriesWithNames.fields) {
|
||||
const didMatch = matcher(field, seriesWithNames, [seriesWithNames]);
|
||||
expect(didMatch).toBe(field.name === 'C');
|
||||
}
|
||||
});
|
||||
|
||||
it('Match none of the field names by name', () => {
|
||||
const seriesWithNames = toDataFrame({
|
||||
fields: [{ name: 'some.instance.path' }, { name: '112' }, { name: '13' }],
|
||||
});
|
||||
const config = {
|
||||
id: FieldMatcherID.byRegexpOrNames,
|
||||
options: {
|
||||
names: [],
|
||||
},
|
||||
};
|
||||
|
||||
const matcher = getFieldMatcher(config);
|
||||
|
||||
for (const field of seriesWithNames.fields) {
|
||||
expect(matcher(field, seriesWithNames, [seriesWithNames])).toBe(false);
|
||||
}
|
||||
});
|
||||
|
||||
it('Match all of the field names by name', () => {
|
||||
const seriesWithNames = toDataFrame({
|
||||
fields: [{ name: 'some.instance.path' }, { name: '112' }, { name: '13' }],
|
||||
});
|
||||
const config = {
|
||||
id: FieldMatcherID.byRegexpOrNames,
|
||||
options: {
|
||||
names: ['some.instance.path', '112', '13'],
|
||||
},
|
||||
};
|
||||
|
||||
const matcher = getFieldMatcher(config);
|
||||
|
||||
for (const field of seriesWithNames.fields) {
|
||||
expect(matcher(field, seriesWithNames, [seriesWithNames])).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
it('Match all of the field names by regexp', () => {
|
||||
const seriesWithNames = toDataFrame({
|
||||
fields: [{ name: 'some.instance.path' }, { name: '112' }, { name: '13' }],
|
||||
});
|
||||
const config = {
|
||||
id: FieldMatcherID.byRegexpOrNames,
|
||||
options: {
|
||||
pattern: '/.*/',
|
||||
},
|
||||
};
|
||||
|
||||
const matcher = getFieldMatcher(config);
|
||||
|
||||
for (const field of seriesWithNames.fields) {
|
||||
expect(matcher(field, seriesWithNames, [seriesWithNames])).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
it('Support fallback name matchers', () => {
|
||||
const frame: DataFrame = {
|
||||
fields: [
|
||||
{ name: 'time', type: FieldType.time, config: {}, values: [1, 2] },
|
||||
{
|
||||
name: 'UP',
|
||||
type: FieldType.number,
|
||||
config: {},
|
||||
values: [1, 2],
|
||||
labels: { __name__: 'UP' },
|
||||
},
|
||||
],
|
||||
name: 'X',
|
||||
length: 2,
|
||||
};
|
||||
|
||||
let matcher = getFieldMatcher({
|
||||
id: FieldMatcherID.byName,
|
||||
options: 'Value',
|
||||
});
|
||||
expect(matcher(frame.fields[0], frame, [])).toBeFalsy();
|
||||
expect(matcher(frame.fields[1], frame, [])).toBeTruthy();
|
||||
|
||||
matcher = getFieldMatcher({
|
||||
id: FieldMatcherID.byName,
|
||||
options: 'Time',
|
||||
});
|
||||
expect(matcher(frame.fields[0], frame, [])).toBeTruthy();
|
||||
expect(matcher(frame.fields[1], frame, [])).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
it('Support fallback multiple names matchers', () => {
|
||||
const frame: DataFrame = {
|
||||
fields: [
|
||||
{ name: 'time', type: FieldType.time, config: {}, values: [1, 2] },
|
||||
{
|
||||
name: 'UP',
|
||||
type: FieldType.number,
|
||||
config: {},
|
||||
values: [1, 2],
|
||||
labels: { __name__: 'UP' },
|
||||
},
|
||||
],
|
||||
name: 'X',
|
||||
length: 2,
|
||||
};
|
||||
|
||||
let matcher = getFieldMatcher({
|
||||
id: FieldMatcherID.byNames,
|
||||
options: {
|
||||
mode: ByNamesMatcherMode.include,
|
||||
names: ['Value'],
|
||||
},
|
||||
});
|
||||
expect(matcher(frame.fields[0], frame, [])).toBeFalsy();
|
||||
expect(matcher(frame.fields[1], frame, [])).toBeTruthy();
|
||||
|
||||
matcher = getFieldMatcher({
|
||||
id: FieldMatcherID.byNames,
|
||||
options: {
|
||||
mode: ByNamesMatcherMode.include,
|
||||
names: ['Time'],
|
||||
},
|
||||
});
|
||||
expect(matcher(frame.fields[0], frame, [])).toBeTruthy();
|
||||
expect(matcher(frame.fields[1], frame, [])).toBeFalsy();
|
||||
});
|
||||
|
||||
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);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,243 @@
|
||||
import { getFieldDisplayName } from '../../field/fieldState';
|
||||
import { stringToJsRegex } from '../../text/string';
|
||||
import { type DataFrame, type Field, FieldType, TIME_SERIES_VALUE_FIELD_NAME } from '../../types/dataFrame';
|
||||
import { type FieldMatcher, type FieldMatcherInfo, type FrameMatcherInfo } from '../../types/transformations';
|
||||
|
||||
import { FieldMatcherID, FrameMatcherID } from './ids';
|
||||
|
||||
export interface RegexpOrNamesMatcherOptions {
|
||||
pattern?: string;
|
||||
names?: string[];
|
||||
variable?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mode to be able to toggle if the names matcher should match fields in provided
|
||||
* list or all except provided names.
|
||||
* @public
|
||||
*/
|
||||
export enum ByNamesMatcherMode {
|
||||
exclude = 'exclude',
|
||||
include = 'include',
|
||||
}
|
||||
|
||||
/**
|
||||
* Options to instruct the by names matcher to either match all fields in given list
|
||||
* or all except the fields in the list.
|
||||
* @public
|
||||
*/
|
||||
export interface ByNamesMatcherOptions {
|
||||
mode?: ByNamesMatcherMode;
|
||||
names?: string[];
|
||||
readOnly?: boolean;
|
||||
prefix?: string;
|
||||
}
|
||||
|
||||
// General Field matcher
|
||||
const fieldNameMatcher: FieldMatcherInfo<string> = {
|
||||
id: FieldMatcherID.byName,
|
||||
name: 'Field Name',
|
||||
description: 'match the field name',
|
||||
defaultOptions: '',
|
||||
|
||||
get: (name: string): FieldMatcher => {
|
||||
const uniqueNames = new Set<string>([name]);
|
||||
|
||||
const fallback = fieldNameFallback(uniqueNames);
|
||||
|
||||
return (field: Field, frame: DataFrame, allFrames: DataFrame[]) => {
|
||||
return (
|
||||
name === field.name ||
|
||||
name === getFieldDisplayName(field, frame, allFrames) ||
|
||||
Boolean(fallback && fallback(field, frame, allFrames))
|
||||
);
|
||||
};
|
||||
},
|
||||
|
||||
getOptionsDisplayText: (name: string) => {
|
||||
return `Field name: ${name}`;
|
||||
},
|
||||
};
|
||||
|
||||
const multipleFieldNamesMatcher: FieldMatcherInfo<ByNamesMatcherOptions> = {
|
||||
id: FieldMatcherID.byNames,
|
||||
name: 'Field Names',
|
||||
description: 'match any of the given the field names',
|
||||
defaultOptions: {
|
||||
mode: ByNamesMatcherMode.include,
|
||||
names: [],
|
||||
},
|
||||
|
||||
get: (options: ByNamesMatcherOptions): FieldMatcher => {
|
||||
const { names, mode = ByNamesMatcherMode.include } = options;
|
||||
const uniqueNames = new Set<string>(names ?? []);
|
||||
|
||||
const fallback = fieldNameFallback(uniqueNames);
|
||||
|
||||
const matcher = (field: Field, frame: DataFrame, frames: DataFrame[]) => {
|
||||
return (
|
||||
uniqueNames.has(field.name) ||
|
||||
uniqueNames.has(getFieldDisplayName(field, frame, frames)) ||
|
||||
Boolean(fallback && fallback(field, frame, frames))
|
||||
);
|
||||
};
|
||||
|
||||
if (mode === ByNamesMatcherMode.exclude) {
|
||||
return (field: Field, frame: DataFrame, frames: DataFrame[]) => {
|
||||
return !matcher(field, frame, frames);
|
||||
};
|
||||
}
|
||||
return matcher;
|
||||
},
|
||||
|
||||
getOptionsDisplayText: (options: ByNamesMatcherOptions): string => {
|
||||
const { names, mode } = options;
|
||||
const displayText = (names ?? []).join(', ');
|
||||
if (mode === ByNamesMatcherMode.exclude) {
|
||||
return `All except: ${displayText}`;
|
||||
}
|
||||
return `All of: ${displayText}`;
|
||||
},
|
||||
};
|
||||
|
||||
// In an effort to support migrating to a consistent data contract, the
|
||||
// naming conventions need to get normalized. However, many existing setups
|
||||
// exist that would no longer match names if that changes. This injects
|
||||
// fallback logic when the data frame has not type version specified
|
||||
function fieldNameFallback(fields: Set<string>) {
|
||||
let fallback: FieldMatcher | undefined = undefined;
|
||||
|
||||
if (fields.has(TIME_SERIES_VALUE_FIELD_NAME)) {
|
||||
fallback = (field: Field, frame: DataFrame) => {
|
||||
return (
|
||||
Boolean(field.labels) && // Value was reasonable when the name was set in labels or on the frame
|
||||
field.labels?.__name__ === field.name
|
||||
);
|
||||
};
|
||||
} else if (fields.has('Time') || fields.has('time')) {
|
||||
fallback = (field: Field, frame: DataFrame) => {
|
||||
return frame.meta?.typeVersion == null && field.type === FieldType.time;
|
||||
};
|
||||
}
|
||||
|
||||
return fallback;
|
||||
}
|
||||
|
||||
const regexpFieldNameMatcher: FieldMatcherInfo<string> = {
|
||||
id: FieldMatcherID.byRegexp,
|
||||
name: 'Field Name by Regexp',
|
||||
description: 'match the field name by a given regexp pattern',
|
||||
defaultOptions: '/.*/',
|
||||
|
||||
get: (pattern: string): FieldMatcher => {
|
||||
const regexp = patternToRegex(pattern);
|
||||
|
||||
return (field: Field, frame: DataFrame, allFrames: DataFrame[]) => {
|
||||
const displayName = getFieldDisplayName(field, frame, allFrames);
|
||||
return !!regexp && regexp.test(displayName);
|
||||
};
|
||||
},
|
||||
|
||||
getOptionsDisplayText: (pattern: string): string => {
|
||||
return `Field name by pattern: ${pattern}`;
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* 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',
|
||||
description: 'match the field name by a given regexp pattern or given names',
|
||||
defaultOptions: {
|
||||
pattern: '/.*/',
|
||||
names: [],
|
||||
},
|
||||
|
||||
get: (options: RegexpOrNamesMatcherOptions): FieldMatcher => {
|
||||
const regexpMatcher = regexpFieldNameMatcher.get(options?.pattern || '');
|
||||
const namesMatcher = multipleFieldNamesMatcher.get({
|
||||
mode: ByNamesMatcherMode.include,
|
||||
names: options?.names ?? [],
|
||||
});
|
||||
|
||||
return (field: Field, frame: DataFrame, allFrames: DataFrame[]) => {
|
||||
return namesMatcher(field, frame, allFrames) || regexpMatcher(field, frame, allFrames);
|
||||
};
|
||||
},
|
||||
|
||||
getOptionsDisplayText: (options: RegexpOrNamesMatcherOptions): string => {
|
||||
const pattern = options?.pattern ?? '';
|
||||
const names = options?.names?.join(',') ?? '';
|
||||
return `Field name by pattern: ${pattern} or names: ${names}`;
|
||||
},
|
||||
};
|
||||
|
||||
const patternToRegex = (pattern?: string): RegExp | undefined => {
|
||||
if (!pattern) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
try {
|
||||
return stringToJsRegex(pattern);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
// General Frame matcher
|
||||
const frameNameMatcher: FrameMatcherInfo<string> = {
|
||||
id: FrameMatcherID.byName,
|
||||
name: 'Frame Name',
|
||||
description: 'match the frame name',
|
||||
defaultOptions: '/.*/',
|
||||
|
||||
get: (pattern: string) => {
|
||||
const regex = stringToJsRegex(pattern);
|
||||
return (frame: DataFrame) => {
|
||||
return regex.test(frame.name || '');
|
||||
};
|
||||
},
|
||||
|
||||
getOptionsDisplayText: (pattern: string) => {
|
||||
return `Frame name: ${pattern}`;
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Registry Initialization
|
||||
*/
|
||||
export function getFieldNameMatchers(): FieldMatcherInfo[] {
|
||||
return [
|
||||
fieldNameMatcher,
|
||||
regexpFieldNameMatcher,
|
||||
multipleFieldNamesMatcher,
|
||||
regexpOrMultipleNamesMatcher,
|
||||
fieldsInFrameMatcher,
|
||||
];
|
||||
}
|
||||
|
||||
export function getFrameNameMatchers(): FrameMatcherInfo[] {
|
||||
return [frameNameMatcher];
|
||||
}
|
||||
Reference in new issue
Block a user