mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
UI: Use SelectableValue as Segment value (#20867)
* Use SelectableValue for segment value * Update cloudwatch components to use new segment props
This commit is contained in:
parent
b111fee642
commit
e0229045f2
@ -18,8 +18,9 @@ const toOption = (value: any) => ({ label: value, value: value });
|
|||||||
|
|
||||||
SegmentStories.add('Array Options', () => {
|
SegmentStories.add('Array Options', () => {
|
||||||
const options = ['Option1', 'Option2', 'OptionWithLooongLabel', 'Option4'].map(toOption);
|
const options = ['Option1', 'Option2', 'OptionWithLooongLabel', 'Option4'].map(toOption);
|
||||||
|
options[0].label = 'Option1 Label';
|
||||||
return (
|
return (
|
||||||
<UseState initialState={options[0].value}>
|
<UseState initialState={options[0] as SelectableValue}>
|
||||||
{(value, updateValue) => (
|
{(value, updateValue) => (
|
||||||
<>
|
<>
|
||||||
<div className="gf-form-inline">
|
<div className="gf-form-inline">
|
||||||
@ -29,9 +30,9 @@ SegmentStories.add('Array Options', () => {
|
|||||||
<Segment
|
<Segment
|
||||||
value={value}
|
value={value}
|
||||||
options={options}
|
options={options}
|
||||||
onChange={(value: SelectableValue<string>) => {
|
onChange={item => {
|
||||||
updateValue(value);
|
updateValue(item);
|
||||||
action('Segment value changed')(value);
|
action('Segment value changed')(item.value);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Segment
|
<Segment
|
||||||
@ -53,7 +54,7 @@ const groupedOptions = [
|
|||||||
|
|
||||||
SegmentStories.add('Grouped Array Options', () => {
|
SegmentStories.add('Grouped Array Options', () => {
|
||||||
return (
|
return (
|
||||||
<UseState initialState={groupedOptions[0].options[0].value}>
|
<UseState initialState={groupedOptions[0].options[0] as SelectableValue}>
|
||||||
{(value, updateValue) => (
|
{(value, updateValue) => (
|
||||||
<>
|
<>
|
||||||
<div className="gf-form-inline">
|
<div className="gf-form-inline">
|
||||||
@ -63,9 +64,9 @@ SegmentStories.add('Grouped Array Options', () => {
|
|||||||
<Segment
|
<Segment
|
||||||
value={value}
|
value={value}
|
||||||
options={groupedOptions}
|
options={groupedOptions}
|
||||||
onChange={(value: SelectableValue<string>) => {
|
onChange={item => {
|
||||||
updateValue(value);
|
updateValue(item);
|
||||||
action('Segment value changed')(value);
|
action('Segment value changed')(item.value);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Segment
|
<Segment
|
||||||
@ -83,7 +84,7 @@ SegmentStories.add('Grouped Array Options', () => {
|
|||||||
SegmentStories.add('With custom options allowed', () => {
|
SegmentStories.add('With custom options allowed', () => {
|
||||||
const options = ['Option1', 'Option2', 'OptionWithLooongLabel', 'Option4'].map(toOption);
|
const options = ['Option1', 'Option2', 'OptionWithLooongLabel', 'Option4'].map(toOption);
|
||||||
return (
|
return (
|
||||||
<UseState initialState={options[0].value}>
|
<UseState initialState={options[0] as SelectableValue}>
|
||||||
{(value, updateValue) => (
|
{(value, updateValue) => (
|
||||||
<>
|
<>
|
||||||
<div className="gf-form-inline">
|
<div className="gf-form-inline">
|
||||||
@ -94,9 +95,9 @@ SegmentStories.add('With custom options allowed', () => {
|
|||||||
allowCustomValue
|
allowCustomValue
|
||||||
value={value}
|
value={value}
|
||||||
options={options}
|
options={options}
|
||||||
onChange={(value: SelectableValue<string>) => {
|
onChange={item => {
|
||||||
updateValue(value);
|
updateValue(item);
|
||||||
action('Segment value changed')(value);
|
action('Segment value changed')(item.value);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Segment
|
<Segment
|
||||||
@ -112,11 +113,11 @@ SegmentStories.add('With custom options allowed', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
const CustomLabelComponent = ({ value }: any) => <div className="gf-form-label">custom({value})</div>;
|
const CustomLabelComponent = ({ value: { value } }: any) => <div className="gf-form-label">custom({value})</div>;
|
||||||
|
|
||||||
SegmentStories.add('Custom Label Field', () => {
|
SegmentStories.add('Custom Label Field', () => {
|
||||||
return (
|
return (
|
||||||
<UseState initialState={groupedOptions[0].options[0].value}>
|
<UseState initialState={groupedOptions[0].options[0] as SelectableValue}>
|
||||||
{(value, setValue) => (
|
{(value, setValue) => (
|
||||||
<>
|
<>
|
||||||
<div className="gf-form-inline">
|
<div className="gf-form-inline">
|
||||||
@ -126,9 +127,9 @@ SegmentStories.add('Custom Label Field', () => {
|
|||||||
<Segment
|
<Segment
|
||||||
Component={<CustomLabelComponent value={value} />}
|
Component={<CustomLabelComponent value={value} />}
|
||||||
options={groupedOptions}
|
options={groupedOptions}
|
||||||
onChange={(value: SelectableValue<string>) => {
|
onChange={item => {
|
||||||
setValue(value);
|
setValue(item);
|
||||||
action('Segment value changed')(value);
|
action('Segment value changed')(item.value);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Segment
|
<Segment
|
||||||
|
@ -18,18 +18,23 @@ export function Segment<T>({
|
|||||||
const [Label, width, expanded, setExpanded] = useExpandableLabel(false);
|
const [Label, width, expanded, setExpanded] = useExpandableLabel(false);
|
||||||
|
|
||||||
if (!expanded) {
|
if (!expanded) {
|
||||||
return <Label Component={Component || <a className={cx('gf-form-label', 'query-part', className)}>{value}</a>} />;
|
return (
|
||||||
|
<Label
|
||||||
|
Component={Component || <a className={cx('gf-form-label', 'query-part', className)}>{value && value.label}</a>}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SegmentSelect
|
<SegmentSelect
|
||||||
width={width}
|
value={value}
|
||||||
options={options}
|
options={options}
|
||||||
|
width={width}
|
||||||
onClickOutside={() => setExpanded(false)}
|
onClickOutside={() => setExpanded(false)}
|
||||||
allowCustomValue={allowCustomValue}
|
allowCustomValue={allowCustomValue}
|
||||||
onChange={value => {
|
onChange={item => {
|
||||||
setExpanded(false);
|
setExpanded(false);
|
||||||
onChange(value);
|
onChange(item);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -20,7 +20,7 @@ const loadOptions = (options: any): Promise<Array<SelectableValue<string>>> =>
|
|||||||
SegmentStories.add('Array Options', () => {
|
SegmentStories.add('Array Options', () => {
|
||||||
const options = ['Option1', 'Option2', 'OptionWithLooongLabel', 'Option4'].map(toOption);
|
const options = ['Option1', 'Option2', 'OptionWithLooongLabel', 'Option4'].map(toOption);
|
||||||
return (
|
return (
|
||||||
<UseState initialState={options[0].value}>
|
<UseState initialState={options[0] as SelectableValue}>
|
||||||
{(value, updateValue) => (
|
{(value, updateValue) => (
|
||||||
<>
|
<>
|
||||||
<div className="gf-form-inline">
|
<div className="gf-form-inline">
|
||||||
@ -30,9 +30,9 @@ SegmentStories.add('Array Options', () => {
|
|||||||
<SegmentAsync
|
<SegmentAsync
|
||||||
value={value}
|
value={value}
|
||||||
loadOptions={() => loadOptions(options)}
|
loadOptions={() => loadOptions(options)}
|
||||||
onChange={value => {
|
onChange={item => {
|
||||||
updateValue(value);
|
updateValue(item);
|
||||||
action('Segment value changed')(value);
|
action('Segment value changed')(item.value);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<SegmentAsync
|
<SegmentAsync
|
||||||
@ -54,7 +54,7 @@ const groupedOptions = [
|
|||||||
|
|
||||||
SegmentStories.add('Grouped Array Options', () => {
|
SegmentStories.add('Grouped Array Options', () => {
|
||||||
return (
|
return (
|
||||||
<UseState initialState={groupedOptions[0].options[0].value}>
|
<UseState initialState={groupedOptions[0].options[0] as SelectableValue}>
|
||||||
{(value, updateValue) => (
|
{(value, updateValue) => (
|
||||||
<>
|
<>
|
||||||
<div className="gf-form-inline">
|
<div className="gf-form-inline">
|
||||||
@ -64,9 +64,9 @@ SegmentStories.add('Grouped Array Options', () => {
|
|||||||
<SegmentAsync
|
<SegmentAsync
|
||||||
value={value}
|
value={value}
|
||||||
loadOptions={() => loadOptions(groupedOptions)}
|
loadOptions={() => loadOptions(groupedOptions)}
|
||||||
onChange={value => {
|
onChange={item => {
|
||||||
updateValue(value);
|
updateValue(item);
|
||||||
action('Segment value changed')(value);
|
action('Segment value changed')(item.value);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<SegmentAsync
|
<SegmentAsync
|
||||||
@ -84,7 +84,7 @@ SegmentStories.add('Grouped Array Options', () => {
|
|||||||
SegmentStories.add('With custom options allowed', () => {
|
SegmentStories.add('With custom options allowed', () => {
|
||||||
const options = ['Option1', 'Option2', 'OptionWithLooongLabel', 'Option4'].map(toOption);
|
const options = ['Option1', 'Option2', 'OptionWithLooongLabel', 'Option4'].map(toOption);
|
||||||
return (
|
return (
|
||||||
<UseState initialState={options[0].value}>
|
<UseState initialState={options[0] as SelectableValue}>
|
||||||
{(value, updateValue) => (
|
{(value, updateValue) => (
|
||||||
<>
|
<>
|
||||||
<div className="gf-form-inline">
|
<div className="gf-form-inline">
|
||||||
@ -95,9 +95,9 @@ SegmentStories.add('With custom options allowed', () => {
|
|||||||
allowCustomValue
|
allowCustomValue
|
||||||
value={value}
|
value={value}
|
||||||
loadOptions={() => loadOptions(options)}
|
loadOptions={() => loadOptions(options)}
|
||||||
onChange={value => {
|
onChange={item => {
|
||||||
updateValue(value);
|
updateValue(item);
|
||||||
action('Segment value changed')(value);
|
action('Segment value changed')(item.value);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<SegmentAsync
|
<SegmentAsync
|
||||||
@ -113,10 +113,10 @@ SegmentStories.add('With custom options allowed', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
const CustomLabelComponent = ({ value }: any) => <div className="gf-form-label">custom({value})</div>;
|
const CustomLabelComponent = ({ value: { value } }: any) => <div className="gf-form-label">custom({value})</div>;
|
||||||
SegmentStories.add('Custom Label Field', () => {
|
SegmentStories.add('Custom Label Field', () => {
|
||||||
return (
|
return (
|
||||||
<UseState initialState={groupedOptions[0].options[0].value}>
|
<UseState initialState={groupedOptions[0].options[0] as SelectableValue}>
|
||||||
{(value, updateValue) => (
|
{(value, updateValue) => (
|
||||||
<>
|
<>
|
||||||
<div className="gf-form-inline">
|
<div className="gf-form-inline">
|
||||||
@ -126,9 +126,9 @@ SegmentStories.add('Custom Label Field', () => {
|
|||||||
<SegmentAsync
|
<SegmentAsync
|
||||||
Component={<CustomLabelComponent value={value} />}
|
Component={<CustomLabelComponent value={value} />}
|
||||||
loadOptions={() => loadOptions(groupedOptions)}
|
loadOptions={() => loadOptions(groupedOptions)}
|
||||||
onChange={value => {
|
onChange={item => {
|
||||||
updateValue(value);
|
updateValue(item);
|
||||||
action('Segment value changed')(value);
|
action('Segment value changed')(item.value);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<SegmentAsync
|
<SegmentAsync
|
||||||
|
@ -29,15 +29,16 @@ export function SegmentAsync<T>({
|
|||||||
setLoadedOptions(opts);
|
setLoadedOptions(opts);
|
||||||
setSelectPlaceholder(opts.length ? '' : 'No options found');
|
setSelectPlaceholder(opts.length ? '' : 'No options found');
|
||||||
}}
|
}}
|
||||||
Component={Component || <a className={cx('gf-form-label', 'query-part', className)}>{value}</a>}
|
Component={Component || <a className={cx('gf-form-label', 'query-part', className)}>{value && value.label}</a>}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SegmentSelect
|
<SegmentSelect
|
||||||
width={width}
|
value={value}
|
||||||
options={loadedOptions}
|
options={loadedOptions}
|
||||||
|
width={width}
|
||||||
noOptionsMessage={selectPlaceholder}
|
noOptionsMessage={selectPlaceholder}
|
||||||
allowCustomValue={allowCustomValue}
|
allowCustomValue={allowCustomValue}
|
||||||
onClickOutside={() => {
|
onClickOutside={() => {
|
||||||
@ -45,11 +46,11 @@ export function SegmentAsync<T>({
|
|||||||
setLoadedOptions([]);
|
setLoadedOptions([]);
|
||||||
setExpanded(false);
|
setExpanded(false);
|
||||||
}}
|
}}
|
||||||
onChange={value => {
|
onChange={item => {
|
||||||
setSelectPlaceholder('');
|
setSelectPlaceholder('');
|
||||||
setLoadedOptions([]);
|
setLoadedOptions([]);
|
||||||
setExpanded(false);
|
setExpanded(false);
|
||||||
onChange(value);
|
onChange(item);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -5,8 +5,9 @@ import { SelectableValue } from '@grafana/data';
|
|||||||
import { Select } from '../Select/Select';
|
import { Select } from '../Select/Select';
|
||||||
|
|
||||||
export interface Props<T> {
|
export interface Props<T> {
|
||||||
|
value?: SelectableValue<T>;
|
||||||
options: Array<SelectableValue<T>>;
|
options: Array<SelectableValue<T>>;
|
||||||
onChange: (value: T) => void;
|
onChange: (item: SelectableValue<T>) => void;
|
||||||
onClickOutside: () => void;
|
onClickOutside: () => void;
|
||||||
width: number;
|
width: number;
|
||||||
noOptionsMessage?: string;
|
noOptionsMessage?: string;
|
||||||
@ -14,6 +15,7 @@ export interface Props<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function SegmentSelect<T>({
|
export function SegmentSelect<T>({
|
||||||
|
value,
|
||||||
options = [],
|
options = [],
|
||||||
onChange,
|
onChange,
|
||||||
onClickOutside,
|
onClickOutside,
|
||||||
@ -39,8 +41,9 @@ export function SegmentSelect<T>({
|
|||||||
placeholder=""
|
placeholder=""
|
||||||
autoFocus={true}
|
autoFocus={true}
|
||||||
isOpen={true}
|
isOpen={true}
|
||||||
onChange={({ value }) => onChange(value!)}
|
onChange={onChange}
|
||||||
options={options}
|
options={options}
|
||||||
|
value={value}
|
||||||
allowCustomValue={allowCustomValue}
|
allowCustomValue={allowCustomValue}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import { ReactElement } from 'react';
|
import { ReactElement } from 'react';
|
||||||
|
import { SelectableValue } from '@grafana/data';
|
||||||
|
|
||||||
export interface SegmentProps<T> {
|
export interface SegmentProps<T> {
|
||||||
onChange: (item: T) => void;
|
onChange: (item: SelectableValue<T>) => void;
|
||||||
value?: T;
|
value?: SelectableValue<T>;
|
||||||
Component?: ReactElement;
|
Component?: ReactElement;
|
||||||
className?: string;
|
className?: string;
|
||||||
allowCustomValue?: boolean;
|
allowCustomValue?: boolean;
|
||||||
|
@ -34,15 +34,17 @@ export const Dimensions: FunctionComponent<Props> = ({ dimensions, loadValues, l
|
|||||||
return options.filter(({ value }) => !Object.keys(data).includes(value));
|
return options.filter(({ value }) => !Object.keys(data).includes(value));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const toOption = (value: any) => ({ label: value, value });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{Object.entries(data).map(([key, value], index) => (
|
{Object.entries(data).map(([key, value], index) => (
|
||||||
<Fragment key={index}>
|
<Fragment key={index}>
|
||||||
<SegmentAsync
|
<SegmentAsync
|
||||||
allowCustomValue
|
allowCustomValue
|
||||||
value={key}
|
value={toOption(key)}
|
||||||
loadOptions={() => loadKeys().then(keys => [removeOption, ...excludeUsedKeys(keys)])}
|
loadOptions={() => loadKeys().then(keys => [removeOption, ...excludeUsedKeys(keys)])}
|
||||||
onChange={newKey => {
|
onChange={({ value: newKey }) => {
|
||||||
const { [key]: value, ...newDimensions } = data;
|
const { [key]: value, ...newDimensions } = data;
|
||||||
if (newKey === removeText) {
|
if (newKey === removeText) {
|
||||||
setData({ ...newDimensions });
|
setData({ ...newDimensions });
|
||||||
@ -54,9 +56,9 @@ export const Dimensions: FunctionComponent<Props> = ({ dimensions, loadValues, l
|
|||||||
<label className="gf-form-label query-segment-operator">=</label>
|
<label className="gf-form-label query-segment-operator">=</label>
|
||||||
<SegmentAsync
|
<SegmentAsync
|
||||||
allowCustomValue
|
allowCustomValue
|
||||||
value={value || 'select dimension value'}
|
value={toOption(value || 'select dimension value')}
|
||||||
loadOptions={() => loadValues(key)}
|
loadOptions={() => loadValues(key)}
|
||||||
onChange={newValue => setData({ ...data, [key]: newValue })}
|
onChange={({ value: newValue }) => setData({ ...data, [key]: newValue })}
|
||||||
/>
|
/>
|
||||||
{Object.values(data).length > 1 && index + 1 !== Object.values(data).length && (
|
{Object.values(data).length > 1 && index + 1 !== Object.values(data).length && (
|
||||||
<label className="gf-form-label query-keyword">AND</label>
|
<label className="gf-form-label query-keyword">AND</label>
|
||||||
@ -72,7 +74,7 @@ export const Dimensions: FunctionComponent<Props> = ({ dimensions, loadValues, l
|
|||||||
</a>
|
</a>
|
||||||
}
|
}
|
||||||
loadOptions={() => loadKeys().then(excludeUsedKeys)}
|
loadOptions={() => loadKeys().then(excludeUsedKeys)}
|
||||||
onChange={(newKey: string) => setData({ ...data, [newKey]: '' })}
|
onChange={({ value: newKey }) => setData({ ...data, [newKey]: '' })}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
@ -112,10 +112,10 @@ export class QueryEditor extends PureComponent<Props, State> {
|
|||||||
<>
|
<>
|
||||||
<QueryInlineField label="Region">
|
<QueryInlineField label="Region">
|
||||||
<Segment
|
<Segment
|
||||||
value={query.region || 'Select region'}
|
value={this.toOption(query.region || 'Select region')}
|
||||||
options={regions}
|
options={regions}
|
||||||
allowCustomValue
|
allowCustomValue
|
||||||
onChange={region => this.onChange({ ...query, region })}
|
onChange={({ value: region }) => this.onChange({ ...query, region })}
|
||||||
/>
|
/>
|
||||||
</QueryInlineField>
|
</QueryInlineField>
|
||||||
|
|
||||||
@ -123,19 +123,19 @@ export class QueryEditor extends PureComponent<Props, State> {
|
|||||||
<>
|
<>
|
||||||
<QueryInlineField label="Namespace">
|
<QueryInlineField label="Namespace">
|
||||||
<Segment
|
<Segment
|
||||||
value={query.namespace || 'Select namespace'}
|
value={this.toOption(query.namespace || 'Select namespace')}
|
||||||
allowCustomValue
|
allowCustomValue
|
||||||
options={namespaces}
|
options={namespaces}
|
||||||
onChange={namespace => this.onChange({ ...query, namespace })}
|
onChange={({ value: namespace }) => this.onChange({ ...query, namespace })}
|
||||||
/>
|
/>
|
||||||
</QueryInlineField>
|
</QueryInlineField>
|
||||||
|
|
||||||
<QueryInlineField label="Metric Name">
|
<QueryInlineField label="Metric Name">
|
||||||
<SegmentAsync
|
<SegmentAsync
|
||||||
value={query.metricName || 'Select metric name'}
|
value={this.toOption(query.metricName || 'Select metric name')}
|
||||||
allowCustomValue
|
allowCustomValue
|
||||||
loadOptions={this.loadMetricNames}
|
loadOptions={this.loadMetricNames}
|
||||||
onChange={metricName => this.onChange({ ...query, metricName })}
|
onChange={({ value: metricName }) => this.onChange({ ...query, metricName })}
|
||||||
/>
|
/>
|
||||||
</QueryInlineField>
|
</QueryInlineField>
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ export interface Props {
|
|||||||
|
|
||||||
const removeText = '-- remove stat --';
|
const removeText = '-- remove stat --';
|
||||||
const removeOption: SelectableValue<string> = { label: removeText, value: removeText };
|
const removeOption: SelectableValue<string> = { label: removeText, value: removeText };
|
||||||
|
const toOption = (value: any) => ({ label: value, value });
|
||||||
|
|
||||||
export const Stats: FunctionComponent<Props> = ({ stats, values, onChange, variableOptionGroup }) => (
|
export const Stats: FunctionComponent<Props> = ({ stats, values, onChange, variableOptionGroup }) => (
|
||||||
<>
|
<>
|
||||||
@ -20,9 +21,9 @@ export const Stats: FunctionComponent<Props> = ({ stats, values, onChange, varia
|
|||||||
<Segment
|
<Segment
|
||||||
allowCustomValue
|
allowCustomValue
|
||||||
key={value + index}
|
key={value + index}
|
||||||
value={value}
|
value={toOption(value)}
|
||||||
options={[removeOption, ...stats, variableOptionGroup]}
|
options={[removeOption, ...stats, variableOptionGroup]}
|
||||||
onChange={value =>
|
onChange={({ value }) =>
|
||||||
onChange(
|
onChange(
|
||||||
value === removeText
|
value === removeText
|
||||||
? values.filter((_, i) => i !== index)
|
? values.filter((_, i) => i !== index)
|
||||||
@ -39,7 +40,7 @@ export const Stats: FunctionComponent<Props> = ({ stats, values, onChange, varia
|
|||||||
</a>
|
</a>
|
||||||
}
|
}
|
||||||
allowCustomValue
|
allowCustomValue
|
||||||
onChange={(value: string) => onChange([...values, value])}
|
onChange={({ value }) => onChange([...values, value])}
|
||||||
options={[...stats.filter(({ value }) => !values.includes(value)), variableOptionGroup]}
|
options={[...stats.filter(({ value }) => !values.includes(value)), variableOptionGroup]}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
Loading…
Reference in New Issue
Block a user