mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
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:
@@ -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}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user