Transformations: Use `FrameMultiSelectionEditor` in Filter data by refId (#97212)

Co-authored-by: Sergej-Vlasov <sergej.s.vlasov@gmail.com>
pull/95808/head
Leon Sorokin 5 months ago committed by GitHub
parent a03f897cd5
commit 1c858caec3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 5
      .betterer.results
  2. 16
      packages/grafana-ui/src/components/MatchersUI/FieldsByFrameRefIdMatcher.tsx
  3. 146
      public/app/features/transformers/editors/FilterByRefIdTransformerEditor.tsx

@ -6406,10 +6406,7 @@ exports[`better eslint`] = {
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "7"]
],
"public/app/features/transformers/editors/FilterByRefIdTransformerEditor.tsx:5381": [
[0, 0, 0, "\'@grafana/data/src/transformations/transformers/filterByRefId\' import is restricted from being used by a pattern. Import from the public export instead.", "0"],
[0, 0, 0, "\'HorizontalGroup\' import from \'@grafana/ui\' is restricted from being used by a pattern. Use Stack component instead.", "1"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "2"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "3"]
[0, 0, 0, "\'@grafana/data/src/transformations/transformers/filterByRefId\' import is restricted from being used by a pattern. Import from the public export instead.", "0"]
],
"public/app/features/transformers/editors/FormatStringTransformerEditor.tsx:5381": [
[0, 0, 0, "\'@grafana/data/src/transformations/transformers/formatString\' import is restricted from being used by a pattern. Import from the public export instead.", "0"],

@ -1,6 +1,13 @@
import { useMemo, useState, useCallback } from 'react';
import { DataFrame, getFrameDisplayName, FieldMatcherID, fieldMatchers, SelectableValue } from '@grafana/data';
import {
DataFrame,
getFrameDisplayName,
FieldMatcherID,
fieldMatchers,
SelectableValue,
toOption,
} from '@grafana/data';
import { MultiSelect, Select } from '../Select/Select';
@ -129,6 +136,9 @@ export function RefIDMultiPicker({ value, data, onChange, placeholder }: MultiPr
} catch {
extractedRefIds.add(value);
}
} else if (value.includes('|')) {
// old format that was simply unescaped pipe-joined strings -> regexp
extractedRefIds = new Set(value.split('|'));
} else {
extractedRefIds.add(value);
}
@ -140,7 +150,9 @@ export function RefIDMultiPicker({ value, data, onChange, placeholder }: MultiPr
return matchedRefIds;
}
return recoverMultiRefIdMissing(listOfRefIds, priorSelectionState.refIds, priorSelectionState.value);
const newRefIds = [...extractedRefIds].map(toOption);
return recoverMultiRefIdMissing(newRefIds, priorSelectionState.refIds, priorSelectionState.value);
}, [value, listOfRefIds, priorSelectionState]);
const onFilterChange = useCallback(

@ -1,141 +1,33 @@
import { PureComponent } from 'react';
import {
DataTransformerID,
KeyValue,
standardTransformers,
TransformerRegistryItem,
TransformerUIProps,
TransformerCategory,
FrameMatcherID,
} from '@grafana/data';
import { FilterFramesByRefIdTransformerOptions } from '@grafana/data/src/transformations/transformers/filterByRefId';
import { HorizontalGroup, FilterPill, FieldValidationMessage, InlineField } from '@grafana/ui';
import { FrameMultiSelectionEditor } from 'app/plugins/panel/geomap/editor/FrameSelectionEditor';
import { getTransformationContent } from '../docs/getTransformationContent';
interface FilterByRefIdTransformerEditorProps extends TransformerUIProps<FilterFramesByRefIdTransformerOptions> {}
interface FilterByRefIdTransformerEditorState {
include: string;
options: RefIdInfo[];
selected: string[];
}
interface RefIdInfo {
refId: string;
count: number;
}
export class FilterByRefIdTransformerEditor extends PureComponent<
FilterByRefIdTransformerEditorProps,
FilterByRefIdTransformerEditorState
> {
constructor(props: FilterByRefIdTransformerEditorProps) {
super(props);
this.state = {
include: props.options.include || '',
options: [],
selected: [],
};
}
componentDidMount() {
this.initOptions();
}
componentDidUpdate(oldProps: FilterByRefIdTransformerEditorProps) {
if (this.props.input !== oldProps.input) {
this.initOptions();
}
}
private initOptions() {
const { input, options } = this.props;
const configuredOptions = options.include ? options.include.split('|') : [];
const allNames: RefIdInfo[] = [];
const byName: KeyValue<RefIdInfo> = {};
for (const frame of input) {
if (frame.refId) {
let v = byName[frame.refId];
if (!v) {
v = byName[frame.refId] = {
refId: frame.refId,
count: 0,
};
allNames.push(v);
}
v.count++;
}
}
if (configuredOptions.length) {
const options: RefIdInfo[] = [];
const selected: RefIdInfo[] = [];
for (const v of allNames) {
if (configuredOptions.includes(v.refId)) {
selected.push(v);
}
options.push(v);
}
this.setState({
options,
selected: selected.map((s) => s.refId),
});
} else {
this.setState({ options: allNames, selected: [] });
}
}
onFieldToggle = (fieldName: string) => {
const { selected } = this.state;
if (selected.indexOf(fieldName) > -1) {
this.onChange(selected.filter((s) => s !== fieldName));
} else {
this.onChange([...selected, fieldName]);
}
};
onChange = (selected: string[]) => {
this.setState({ selected });
this.props.onChange({
...this.props.options,
include: selected.join('|'),
});
};
render() {
const { options, selected } = this.state;
const { input } = this.props;
return (
<>
{input.length <= 1 && (
<div>
<FieldValidationMessage>Filter data by query expects multiple queries in the input.</FieldValidationMessage>
</div>
)}
<InlineField label="Series refId" labelWidth={16} shrink>
<HorizontalGroup spacing="xs" align="flex-start" wrap>
{options.map((o, i) => {
const label = `${o.refId}${o.count > 1 ? ' (' + o.count + ')' : ''}`;
const isSelected = selected.indexOf(o.refId) > -1;
return (
<FilterPill
key={`${o.refId}/${i}`}
onClick={() => {
this.onFieldToggle(o.refId);
}}
label={label}
selected={isSelected}
/>
);
})}
</HorizontalGroup>
</InlineField>
</>
);
}
}
export const FilterByRefIdTransformerEditor = (props: TransformerUIProps<FilterFramesByRefIdTransformerOptions>) => {
return (
<FrameMultiSelectionEditor
value={{
id: FrameMatcherID.byRefId,
options: props.options.include || '',
}}
onChange={(value) => {
props.onChange({
...props.options,
include: value?.options || '',
});
}}
context={{ data: props.input }}
/>
);
};
export const filterFramesByRefIdTransformRegistryItem: TransformerRegistryItem<FilterFramesByRefIdTransformerOptions> =
{

Loading…
Cancel
Save