diff --git a/frontend/src/constants/queryBuilderFilterConfig.ts b/frontend/src/constants/queryBuilderFilterConfig.ts new file mode 100644 index 0000000000..42e092ddee --- /dev/null +++ b/frontend/src/constants/queryBuilderFilterConfig.ts @@ -0,0 +1 @@ +export const DEBOUNCE_DELAY = 200; diff --git a/frontend/src/container/LogExplorerDetailedView/index.tsx b/frontend/src/container/LogExplorerDetailedView/index.tsx index 26bb067b88..3bbd7481f8 100644 --- a/frontend/src/container/LogExplorerDetailedView/index.tsx +++ b/frontend/src/container/LogExplorerDetailedView/index.tsx @@ -31,8 +31,8 @@ function LogExplorerDetailedView({ const existAutocompleteKey = chooseAutocompleteFromCustomValue( keysAutocomplete, - [fieldKey], - )[0]; + fieldKey, + ); const nextQuery: Query = { ...currentQuery, diff --git a/frontend/src/container/QueryBuilder/filters/AggregatorFilter/AggregatorFilter.tsx b/frontend/src/container/QueryBuilder/filters/AggregatorFilter/AggregatorFilter.tsx index dda50c7932..8905ba9f55 100644 --- a/frontend/src/container/QueryBuilder/filters/AggregatorFilter/AggregatorFilter.tsx +++ b/frontend/src/container/QueryBuilder/filters/AggregatorFilter/AggregatorFilter.tsx @@ -4,22 +4,21 @@ import { AutoComplete, Spin } from 'antd'; import { getAggregateAttribute } from 'api/queryBuilder/getAggregateAttribute'; import { baseAutoCompleteIdKeysOrder, - idDivider, - initialAutocompleteData, QueryBuilderKeys, selectValueDivider, } from 'constants/queryBuilder'; +import { DEBOUNCE_DELAY } from 'constants/queryBuilderFilterConfig'; import useDebounce from 'hooks/useDebounce'; import { createIdFromObjectFields } from 'lib/createIdFromObjectFields'; import { chooseAutocompleteFromCustomValue } from 'lib/newQueryBuilder/chooseAutocompleteFromCustomValue'; import { getAutocompleteValueAndType } from 'lib/newQueryBuilder/getAutocompleteValueAndType'; import { transformStringWithPrefix } from 'lib/query/transformStringWithPrefix'; import { memo, useCallback, useMemo, useState } from 'react'; -import { useQuery } from 'react-query'; +import { useQuery, useQueryClient } from 'react-query'; +import { SuccessResponse } from 'types/api'; import { - AutocompleteType, BaseAutocompleteData, - DataType, + IQueryAutocompleteResponse, } from 'types/api/queryBuilder/queryAutocompleteResponse'; import { DataSource } from 'types/common/queryBuilder'; import { ExtendedSelectOption } from 'types/common/select'; @@ -34,19 +33,9 @@ export const AggregatorFilter = memo(function AggregatorFilter({ disabled, onChange, }: AgregatorFilterProps): JSX.Element { + const queryClient = useQueryClient(); const [optionsData, setOptionsData] = useState([]); - const [searchText, setSearchText] = useState( - query.aggregateAttribute.key, - ); - - const handleChangeAttribute = useCallback( - (data: BaseAutocompleteData[]) => { - const attribute = chooseAutocompleteFromCustomValue(data, [searchText]); - - onChange(attribute[0]); - }, - [onChange, searchText], - ); + const [searchText, setSearchText] = useState(''); const debouncedSearchText = useMemo(() => { // eslint-disable-next-line @typescript-eslint/naming-convention, @typescript-eslint/no-unused-vars @@ -55,7 +44,7 @@ export const AggregatorFilter = memo(function AggregatorFilter({ return value; }, [searchText]); - const debouncedValue = useDebounce(debouncedSearchText, 300); + const debouncedValue = useDebounce(debouncedSearchText, DEBOUNCE_DELAY); const { isFetching } = useQuery( [ QueryBuilderKeys.GET_AGGREGATE_ATTRIBUTE, @@ -86,8 +75,6 @@ export const AggregatorFilter = memo(function AggregatorFilter({ key: createIdFromObjectFields(item, baseAutoCompleteIdKeysOrder), })) || []; - handleChangeAttribute(data.payload?.attributeKeys || []); - setOptionsData(options); }, }, @@ -102,60 +89,79 @@ export const AggregatorFilter = memo(function AggregatorFilter({ ? `${transformToUpperCase(query.dataSource)} name` : 'Aggregate attribute'; - const handleSelect = ( - value: string, - option: ExtendedSelectOption | ExtendedSelectOption[], - ): void => { - const currentOption = option as ExtendedSelectOption; + const getAttributes = useCallback( + (): BaseAutocompleteData[] => + queryClient.getQueryData>( + [QueryBuilderKeys.GET_AGGREGATE_ATTRIBUTE], + { exact: false }, + )?.payload.attributeKeys || [], + [queryClient], + ); - if (currentOption.key) { - const [key, dataType, type, isColumn] = currentOption.key.split(idDivider); - const attribute: BaseAutocompleteData = { - key, - dataType: dataType as DataType, - type: type as AutocompleteType, - isColumn: isColumn === 'true', - }; + const handleChangeCustomValue = useCallback( + (value: string) => { + const aggregateAttributes = getAttributes(); - const text = transformStringWithPrefix({ - str: attribute.key, - prefix: attribute.type || '', - condition: !attribute.isColumn, - }); - - setSearchText(text); - - onChange(attribute); - } else { - const customAttribute: BaseAutocompleteData = { - ...initialAutocompleteData, - key: value, - }; - - const text = transformStringWithPrefix({ - str: customAttribute.key, - prefix: customAttribute.type || '', - condition: !customAttribute.isColumn, - }); - - setSearchText(text); + const customAttribute: BaseAutocompleteData = chooseAutocompleteFromCustomValue( + aggregateAttributes, + value, + ); onChange(customAttribute); + }, + [getAttributes, onChange], + ); + + const handleBlur = useCallback(() => { + if (searchText) { + handleChangeCustomValue(searchText); } - }; + }, [handleChangeCustomValue, searchText]); + + const handleChange = useCallback( + ( + value: string, + option: ExtendedSelectOption | ExtendedSelectOption[], + ): void => { + const currentOption = option as ExtendedSelectOption; + + const aggregateAttributes = getAttributes(); + + if (currentOption.key) { + const attribute = aggregateAttributes.find( + (item) => item.id === currentOption.key, + ); + + if (attribute) { + onChange(attribute); + } + } else { + handleChangeCustomValue(value); + } + + setSearchText(''); + }, + [getAttributes, handleChangeCustomValue, onChange], + ); + + const value = transformStringWithPrefix({ + str: query.aggregateAttribute.key, + prefix: query.aggregateAttribute.type || '', + condition: !query.aggregateAttribute.isColumn, + }); return ( : null} options={optionsData} - value={searchText} - onSelect={handleSelect} + value={value} + onBlur={handleBlur} + onChange={handleChange} disabled={disabled} /> ); diff --git a/frontend/src/container/QueryBuilder/filters/GroupByFilter/GroupByFilter.tsx b/frontend/src/container/QueryBuilder/filters/GroupByFilter/GroupByFilter.tsx index 62bd165ffb..622b87bf7c 100644 --- a/frontend/src/container/QueryBuilder/filters/GroupByFilter/GroupByFilter.tsx +++ b/frontend/src/container/QueryBuilder/filters/GroupByFilter/GroupByFilter.tsx @@ -3,21 +3,22 @@ import { getAggregateKeys } from 'api/queryBuilder/getAttributeKeys'; // ** Constants import { idDivider, - initialAutocompleteData, QueryBuilderKeys, selectValueDivider, } from 'constants/queryBuilder'; +import { DEBOUNCE_DELAY } from 'constants/queryBuilderFilterConfig'; import useDebounce from 'hooks/useDebounce'; +import { chooseAutocompleteFromCustomValue } from 'lib/newQueryBuilder/chooseAutocompleteFromCustomValue'; // ** Components // ** Helpers import { transformStringWithPrefix } from 'lib/query/transformStringWithPrefix'; import { isEqual, uniqWith } from 'lodash-es'; import { memo, useCallback, useEffect, useState } from 'react'; -import { useQuery } from 'react-query'; +import { useQuery, useQueryClient } from 'react-query'; +import { SuccessResponse } from 'types/api'; import { - AutocompleteType, BaseAutocompleteData, - DataType, + IQueryAutocompleteResponse, } from 'types/api/queryBuilder/queryAutocompleteResponse'; import { SelectOption } from 'types/common/select'; @@ -29,6 +30,7 @@ export const GroupByFilter = memo(function GroupByFilter({ onChange, disabled, }: GroupByFilterProps): JSX.Element { + const queryClient = useQueryClient(); const [searchText, setSearchText] = useState(''); const [optionsData, setOptionsData] = useState[]>( [], @@ -38,7 +40,7 @@ export const GroupByFilter = memo(function GroupByFilter({ ); const [isFocused, setIsFocused] = useState(false); - const debouncedValue = useDebounce(searchText, 300); + const debouncedValue = useDebounce(searchText, DEBOUNCE_DELAY); const { isFetching } = useQuery( [QueryBuilderKeys.GET_AGGREGATE_KEYS, debouncedValue, isFocused], @@ -81,6 +83,15 @@ export const GroupByFilter = memo(function GroupByFilter({ }, ); + const getAttributeKeys = useCallback( + (): BaseAutocompleteData[] => + queryClient.getQueryData>( + [QueryBuilderKeys.GET_AGGREGATE_KEYS], + { exact: false }, + )?.payload.attributeKeys || [], + [queryClient], + ); + const handleSearchKeys = (searchText: string): void => { setSearchText(searchText); }; @@ -97,21 +108,17 @@ export const GroupByFilter = memo(function GroupByFilter({ const handleChange = (values: SelectOption[]): void => { const groupByValues: BaseAutocompleteData[] = values.map((item) => { const [currentValue, id] = item.value.split(selectValueDivider); - if (id && id.includes(idDivider)) { - const [key, dataType, type, isColumn] = id.split(idDivider); + const keys = getAttributeKeys(); - return { - id, - key: key || currentValue, - dataType: (dataType as DataType) || initialAutocompleteData.dataType, - type: (type as AutocompleteType) || initialAutocompleteData.type, - isColumn: isColumn - ? isColumn === 'true' - : initialAutocompleteData.isColumn, - }; + if (id && id.includes(idDivider)) { + const attribute = keys.find((item) => item.id === id); + + if (attribute) { + return attribute; + } } - return { ...initialAutocompleteData, key: currentValue }; + return chooseAutocompleteFromCustomValue(keys, currentValue); }); const result = uniqWith(groupByValues, isEqual); diff --git a/frontend/src/hooks/queryBuilder/useFetchKeysAndValues.ts b/frontend/src/hooks/queryBuilder/useFetchKeysAndValues.ts index b616398de4..514bbc8617 100644 --- a/frontend/src/hooks/queryBuilder/useFetchKeysAndValues.ts +++ b/frontend/src/hooks/queryBuilder/useFetchKeysAndValues.ts @@ -1,6 +1,7 @@ import { getAggregateKeys } from 'api/queryBuilder/getAttributeKeys'; import { getAttributesValues } from 'api/queryBuilder/getAttributesValues'; import { QueryBuilderKeys } from 'constants/queryBuilder'; +import { DEBOUNCE_DELAY } from 'constants/queryBuilderFilterConfig'; import { getRemovePrefixFromKey, getTagToken, @@ -54,7 +55,7 @@ export const useFetchKeysAndValues = ( ], ); - const searchParams = useDebounceValue(memoizedSearchParams, 300); + const searchParams = useDebounceValue(memoizedSearchParams, DEBOUNCE_DELAY); const isQueryEnabled = useMemo( () => diff --git a/frontend/src/lib/newQueryBuilder/chooseAutocompleteFromCustomValue.ts b/frontend/src/lib/newQueryBuilder/chooseAutocompleteFromCustomValue.ts index 1834822c6d..ccd69df45f 100644 --- a/frontend/src/lib/newQueryBuilder/chooseAutocompleteFromCustomValue.ts +++ b/frontend/src/lib/newQueryBuilder/chooseAutocompleteFromCustomValue.ts @@ -3,17 +3,14 @@ import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteRe export const chooseAutocompleteFromCustomValue = ( sourceList: BaseAutocompleteData[], - values: string[], -): BaseAutocompleteData[] => { - console.log({ sourceList }); - return values.map((value) => { - const firstBaseAutoCompleteValue = sourceList.find( - (sourceAutoComplete) => value === sourceAutoComplete.key, - ); + value: string, +): BaseAutocompleteData => { + const firstBaseAutoCompleteValue = sourceList.find( + (sourceAutoComplete) => value === sourceAutoComplete.key, + ); - if (!firstBaseAutoCompleteValue) - return { ...initialAutocompleteData, key: value }; + if (!firstBaseAutoCompleteValue) + return { ...initialAutocompleteData, key: value }; - return firstBaseAutoCompleteValue; - }); + return firstBaseAutoCompleteValue; };