feat: multiple values can be selected (#2365)

* feat: multiple values can be selected

* chore: tag value is updated

* fix: handle few edge cases

---------

Co-authored-by: makeavish <makeavish786@gmail.com>
This commit is contained in:
palashgdev 2023-02-23 23:54:16 +05:30 committed by GitHub
parent 174fc107c2
commit 1f44f089e0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 77 additions and 91 deletions

View File

@ -1,7 +1,7 @@
import { Select } from 'antd';
import { BaseOptionType } from 'antd/es/select';
import getTagValue from 'api/trace/getTagValue';
import React, { useCallback, useMemo, useState } from 'react';
import React, { memo, useCallback, useMemo, useState } from 'react';
import { useQuery } from 'react-query';
import { useSelector } from 'react-redux';
import { AppState } from 'store/reducers';
@ -17,6 +17,7 @@ import {
getTagValueOptions,
onTagValueChange,
selectOptions,
separateTagValues,
TagValueTypes,
} from './utils';
@ -81,66 +82,27 @@ function TagValue(props: TagValueProps): JSX.Element {
[index, selectedKey, selectedOperator, setLocalSelectedTags],
);
const onSetLocalValue = useCallback(() => {
setLocalTagValue([]);
}, []);
const onSelectedHandler = useCallback(
(value: unknown) => {
if (
typeof value === 'number' ||
(typeof value === 'string' && !Number.isNaN(Number(value)) && value !== ' ')
) {
setLocalTagValue([value]);
setLocalSelectedTags((tags) => [
...tags.slice(0, index),
{
Key: selectedKey,
Operator: selectedOperator,
StringValues: [],
NumberValues: [Number(value)],
BoolValues: [],
},
...tags.slice(index + 1, tags.length),
]);
} else if (
typeof value === 'boolean' ||
value === 'true' ||
value === 'false'
) {
setLocalTagValue([value]);
setLocalSelectedTags((tags) => [
...tags.slice(0, index),
{
Key: selectedKey,
Operator: selectedOperator,
StringValues: [],
NumberValues: [],
BoolValues: [value === 'true' || value === true],
},
...tags.slice(index + 1, tags.length),
]);
} else if (typeof value === 'string') {
setLocalTagValue([value]);
setLocalSelectedTags((tags) => [
...tags.slice(0, index),
{
Key: selectedKey,
Operator: selectedOperator,
StringValues: [value],
NumberValues: [],
BoolValues: [],
},
...tags.slice(index + 1, tags.length),
]);
}
},
[index, selectedKey, selectedOperator, setLocalSelectedTags],
);
const onChangeHandler = useCallback(
(value: unknown) => onTagValueChange(value, setLocalTagValue),
[],
(value: unknown) => {
const updatedValues = onTagValueChange(value);
setLocalTagValue(updatedValues);
const { boolValues, numberValues, stringValues } = separateTagValues(
updatedValues,
selectedKey,
);
setLocalSelectedTags((tags) => [
...tags.slice(0, index),
{
...tags[index],
BoolValues: boolValues,
NumberValues: numberValues,
StringValues: stringValues,
},
...tags.slice(index + 1),
]);
},
[index, setLocalSelectedTags, selectedKey],
);
const getFilterOptions = useCallback(
@ -159,14 +121,11 @@ function TagValue(props: TagValueProps): JSX.Element {
options={getTagValueOptions(data?.payload, tagType)}
mode="tags"
allowClear
onClear={onSetLocalValue}
onDeselect={onSetLocalValue}
showSearch
filterOption={getFilterOptions}
disabled={isLoading || tagValueDisabled}
value={localTagValue}
onChange={onChangeHandler}
onSelect={onSelectedHandler}
>
{selectOptions(data?.payload, tagType)?.map((suggestion) => (
<Select.Option key={suggestion.toString()} value={suggestion}>
@ -186,4 +145,4 @@ interface TagValueProps {
tagKey: string;
}
export default TagValue;
export default memo(TagValue);

View File

@ -50,23 +50,56 @@ export const extractTagKey = (tagKey: string): string => {
return '';
};
export function onTagValueChange(
values: unknown,
setLocalValue: React.Dispatch<React.SetStateAction<TagValueTypes[]>>,
): void {
if (Array.isArray(values) && values.length > 0) {
if (typeof values[0] === 'number' || typeof values[0] === 'boolean') {
setLocalValue(values);
} else if (typeof values[0] === 'string') {
if (values[0] === 'true' || values[0] === 'false') {
setLocalValue([values[0] === 'true']);
} else if (values[0] !== ' ' && !Number.isNaN(Number(values[0]))) {
setLocalValue([Number(values[0])]);
} else {
setLocalValue([values[0]]);
}
}
export function onTagValueChange(values: unknown): TagValueTypes[] {
const stringValues = values as string[];
if (!Array.isArray(stringValues) || stringValues.length === 0) {
return [];
}
return values as TagValueTypes[];
}
export function separateTagValues(
values: TagValueTypes[],
selectedKey: string,
): { boolValues: boolean[]; numberValues: number[]; stringValues: string[] } {
if (selectedKey.includes('.(bool)')) {
const boolValues = values.filter(
(value) => typeof value === 'boolean',
) as boolean[];
return {
boolValues,
numberValues: [],
stringValues: [],
};
}
if (selectedKey.includes('.(number)')) {
const numberValues = values
.filter((value) => typeof value === 'number' || !Number.isNaN(Number(value)))
.map((value) => Number(value)) as number[];
return {
boolValues: [],
numberValues,
stringValues: [],
};
}
const stringValues = values.filter(
(value) =>
typeof value === 'string' &&
value !== 'true' &&
value !== 'false' &&
Number.isNaN(Number(value)),
) as string[];
return {
boolValues: [],
numberValues: [],
stringValues,
};
}
export function disableTagValue(
@ -93,22 +126,16 @@ export function disableTagValue(
}
return false;
}
export function getInitialLocalValue(
selectedNumberValues: number[],
selectedBoolValues: boolean[],
selectedStringValues: string[],
): TagValueTypes[] {
if (selectedStringValues && selectedStringValues.length > 0) {
return selectedStringValues;
}
if (selectedNumberValues && selectedNumberValues.length > 0) {
return selectedNumberValues;
}
if (selectedBoolValues && selectedBoolValues.length > 0) {
return selectedBoolValues;
}
return selectedStringValues;
return [
...selectedBoolValues,
...selectedNumberValues,
...selectedStringValues,
];
}
export function getTagValueOptions(