Transform: fixes so we match the field based on the proper name. (#24659)

* fixes so we match the transformer based on name properly.

* changed the signature on the FieldMatcher.

* introduced a names option so you can filter in name specificly.

* changed so the matcher UI uses the new options format.

* moved the exported functions together.

* changing editors a bit.

* made the filter by name work with both regex and name filtering.

* fixed failing tests and make sure we always parse regex the same way.

* removed unused code.

* simplified to make the existing field overrides still working.

* fixed issue reported by hugo.

* added tests for the name matcher.

* added tests for filter by name.

* added more tests.
This commit is contained in:
Marcus Andersson
2020-05-14 20:48:43 +02:00
committed by GitHub
parent 0e8638ec92
commit 96f26cbd5b
24 changed files with 806 additions and 185 deletions

View File

@@ -27,7 +27,7 @@ import defaults from 'lodash/defaults';
interface CalculateFieldTransformerEditorProps extends TransformerUIProps<CalculateFieldTransformerOptions> {}
interface CalculateFieldTransformerEditorState {
include: string;
include: string[];
names: string[];
selected: string[];
}
@@ -45,7 +45,7 @@ export class CalculateFieldTransformerEditor extends React.PureComponent<
super(props);
this.state = {
include: props.options?.reduce?.include || '',
include: props.options?.reduce?.include || [],
names: [],
selected: [],
};
@@ -62,9 +62,9 @@ export class CalculateFieldTransformerEditor extends React.PureComponent<
}
private initOptions() {
const { input, options } = this.props;
const include = options?.reduce?.include || '';
const configuredOptions = include.split('|');
const { options } = this.props;
const configuredOptions = options?.reduce?.include || [];
const input = standardTransformers.ensureColumnsTransformer.transformer(null)(this.props.input);
const allNames: string[] = [];
const byName: KeyValue<boolean> = {};
@@ -156,7 +156,7 @@ export class CalculateFieldTransformerEditor extends React.PureComponent<
const { reduce } = this.props.options;
this.updateReduceOptions({
...reduce!,
include: selected.join('|'),
include: selected,
});
};
@@ -274,7 +274,6 @@ export class CalculateFieldTransformerEditor extends React.PureComponent<
</div>
<div className="gf-form">
<Select
allowCustomValue
placeholder="Field or number"
options={leftNames}
className="min-width-18 gf-form-spacing"
@@ -290,7 +289,6 @@ export class CalculateFieldTransformerEditor extends React.PureComponent<
menuPlacement="bottom"
/>
<Select
allowCustomValue
placeholder="Field or number"
className="min-width-10"
options={rightNames}

View File

@@ -6,6 +6,7 @@ import {
TransformerRegistyItem,
TransformerUIProps,
getFieldDisplayName,
stringToJsRegex,
} from '@grafana/data';
import { Field, Input, FilterPill, HorizontalGroup } from '@grafana/ui';
import { css } from 'emotion';
@@ -32,7 +33,8 @@ export class FilterByNameTransformerEditor extends React.PureComponent<
constructor(props: FilterByNameTransformerEditorProps) {
super(props);
this.state = {
include: props.options.include || [],
include: props.options.include?.names || [],
regex: props.options.include?.pattern,
options: [],
selected: [],
isRegexValid: true,
@@ -51,7 +53,7 @@ export class FilterByNameTransformerEditor extends React.PureComponent<
private initOptions() {
const { input, options } = this.props;
const configuredOptions = options.include ? options.include : [];
const configuredOptions = Array.from(options.include?.names ?? []);
const allNames: FieldNameInfo[] = [];
const byName: KeyValue<FieldNameInfo> = {};
@@ -73,28 +75,34 @@ export class FilterByNameTransformerEditor extends React.PureComponent<
}
}
let regexOption;
if (options.include?.pattern) {
try {
const regex = stringToJsRegex(options.include.pattern);
for (const info of allNames) {
if (regex.test(info.name)) {
configuredOptions.push(info.name);
}
}
} catch (error) {
console.log(error);
}
}
if (configuredOptions.length) {
let selected: FieldNameInfo[] = [];
for (const o of configuredOptions) {
const selectedFields = allNames.filter(n => n.name === o);
if (selectedFields.length > 0) {
selected = selected.concat(selectedFields);
} else {
// there can be only one regex in the options
regexOption = o;
}
}
const selected: FieldNameInfo[] = allNames.filter(n => configuredOptions.includes(n.name));
this.setState({
options: allNames,
selected: selected.map(s => s.name),
regex: regexOption,
regex: options.include?.pattern,
});
} else {
this.setState({ options: allNames, selected: allNames.map(n => n.name) });
this.setState({
options: allNames,
selected: allNames.map(n => n.name),
regex: options.include?.pattern,
});
}
}
@@ -109,44 +117,46 @@ export class FilterByNameTransformerEditor extends React.PureComponent<
onChange = (selected: string[]) => {
const { regex, isRegexValid } = this.state;
let include = selected;
const options: FilterFieldsByNameTransformerOptions = {
...this.props.options,
include: { names: selected },
};
if (regex && isRegexValid) {
include = include.concat([regex]);
options.include = options.include ?? {};
options.include.pattern = regex;
}
this.setState({ selected }, () => {
this.props.onChange({
...this.props.options,
include,
});
this.props.onChange(options);
});
};
onInputBlur = (e: React.FocusEvent<HTMLInputElement>) => {
const { selected, regex } = this.state;
let isRegexValid = true;
try {
if (regex) {
new RegExp(regex);
stringToJsRegex(regex);
}
} catch (e) {
isRegexValid = false;
}
if (isRegexValid) {
this.props.onChange({
...this.props.options,
include: regex ? [...selected, regex] : selected,
include: { pattern: regex },
});
} else {
this.props.onChange({
...this.props.options,
include: selected,
include: { names: selected },
});
}
this.setState({
isRegexValid,
});
this.setState({ isRegexValid });
};
render() {