diff --git a/frontend/src/pages/TracesExplorer/Filter/SectionContent.tsx b/frontend/src/pages/TracesExplorer/Filter/SectionContent.tsx index 05fc7bb1f3..4cefaaeca0 100644 --- a/frontend/src/pages/TracesExplorer/Filter/SectionContent.tsx +++ b/frontend/src/pages/TracesExplorer/Filter/SectionContent.tsx @@ -4,7 +4,7 @@ import { Button, Card, Checkbox, Input, Tooltip } from 'antd'; import { CheckboxChangeEvent } from 'antd/es/checkbox'; import { ParaGraph } from 'container/Trace/Filters/Panel/PanelBody/Common/styles'; import useDebouncedFn from 'hooks/useDebouncedFunction'; -import { defaultTo, isEmpty } from 'lodash-es'; +import { isArray, isEmpty } from 'lodash-es'; import { ChangeEvent, Dispatch, @@ -17,6 +17,7 @@ import { import { addFilter, AllTraceFilterKeys, + convertToStringArr, FilterType, HandleRunProps, removeFilter, @@ -37,15 +38,14 @@ export function SectionBody(props: SectionBodyProps): JSX.Element { const [searchFilter, setSearchFilter] = useState(''); const [searchText, setSearchText] = useState(''); const [checkedItems, setCheckedItems] = useState( - defaultTo(selectedFilters?.[type]?.values as string[], []), + convertToStringArr(selectedFilters?.[type]?.values), ); const [results, setResults] = useState([]); const [isFetching, setFetching] = useState(false); useEffect( - () => - setCheckedItems(defaultTo(selectedFilters?.[type]?.values as string[], [])), + () => setCheckedItems(convertToStringArr(selectedFilters?.[type]?.values)), [selectedFilters, type], ); @@ -92,17 +92,21 @@ export function SectionBody(props: SectionBodyProps): JSX.Element { if (checked) { addFilter(type, newValue, setSelectedFilters, keys); setCheckedItems((prev) => { - if (!prev.includes(newValue)) { - prev.push(newValue); + const arr = prev || []; + if (isArray(arr) && !arr.includes(newValue)) { + arr.push(newValue); } - return prev; + return convertToStringArr(arr); }); } else if (checkedItems.length === 1) { handleRun({ clearByType: type }); setCheckedItems([]); } else { removeFilter(type, newValue, setSelectedFilters, keys); - setCheckedItems((prev) => prev.filter((item) => item !== newValue)); + setCheckedItems((prev) => { + const prevValue = convertToStringArr(prev); + return prevValue.filter((item) => item !== newValue); + }); } }; diff --git a/frontend/src/pages/TracesExplorer/Filter/filterUtils.ts b/frontend/src/pages/TracesExplorer/Filter/filterUtils.ts index 86b52fdbb0..88f604a0dc 100644 --- a/frontend/src/pages/TracesExplorer/Filter/filterUtils.ts +++ b/frontend/src/pages/TracesExplorer/Filter/filterUtils.ts @@ -1,6 +1,5 @@ /* eslint-disable react-hooks/exhaustive-deps */ import { getAttributesValues } from 'api/queryBuilder/getAttributesValues'; -import { isArray } from 'lodash-es'; import { Dispatch, SetStateAction, useEffect, useState } from 'react'; import { BaseAutocompleteData, @@ -41,6 +40,18 @@ export type FilterType = Record< { values: string[] | string; keys: BaseAutocompleteData } >; +export function convertToStringArr( + value: string | string[] | undefined, +): string[] { + if (value) { + if (typeof value === 'string') { + return [value]; + } + return value; + } + return []; +} + export const addFilter = ( filterType: AllTraceFilterKeys, value: string, @@ -62,28 +73,36 @@ export const addFilter = ( 'durationNano', ].includes(filterType); + // Convert value to string array + const valueArray = convertToStringArr(value); + // If previous filters are undefined, initialize them if (!prevFilters) { return ({ - [filterType]: { values: isDuration ? value : [value], keys }, + [filterType]: { values: isDuration ? value : valueArray, keys }, } as unknown) as FilterType; } + // If the filter type doesn't exist, initialize it if (!prevFilters[filterType]?.values.length) { return { ...prevFilters, - [filterType]: { values: isDuration ? value : [value], keys }, + [filterType]: { values: isDuration ? value : valueArray, keys }, }; } + // If the value already exists, don't add it again - if (prevFilters[filterType].values.includes(value)) { + if (convertToStringArr(prevFilters[filterType].values).includes(value)) { return prevFilters; } + // Otherwise, add the value to the existing array return { ...prevFilters, [filterType]: { - values: isDuration ? value : [...prevFilters[filterType].values, value], + values: isDuration + ? value + : [...convertToStringArr(prevFilters[filterType].values), value], keys, }, }; @@ -110,10 +129,8 @@ export const removeFilter = ( return prevFilters; } - const prevValue = prevFilters[filterType]?.values; - const updatedValues = !isArray(prevValue) - ? prevValue - : prevValue?.filter((item: any) => item !== value); + const prevValue = convertToStringArr(prevFilters[filterType]?.values); + const updatedValues = prevValue.filter((item: any) => item !== value); if (updatedValues.length === 0) { const { [filterType]: item, ...remainingFilters } = prevFilters;