feat: choose autocomplete group by (#3108)

This commit is contained in:
Yevhen Shevchenko 2023-07-12 01:14:52 +03:00 committed by GitHub
parent 915738e1f7
commit 149fdebfaa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 103 additions and 91 deletions

View File

@ -0,0 +1 @@
export const DEBOUNCE_DELAY = 200;

View File

@ -31,8 +31,8 @@ function LogExplorerDetailedView({
const existAutocompleteKey = chooseAutocompleteFromCustomValue( const existAutocompleteKey = chooseAutocompleteFromCustomValue(
keysAutocomplete, keysAutocomplete,
[fieldKey], fieldKey,
)[0]; );
const nextQuery: Query = { const nextQuery: Query = {
...currentQuery, ...currentQuery,

View File

@ -4,22 +4,21 @@ import { AutoComplete, Spin } from 'antd';
import { getAggregateAttribute } from 'api/queryBuilder/getAggregateAttribute'; import { getAggregateAttribute } from 'api/queryBuilder/getAggregateAttribute';
import { import {
baseAutoCompleteIdKeysOrder, baseAutoCompleteIdKeysOrder,
idDivider,
initialAutocompleteData,
QueryBuilderKeys, QueryBuilderKeys,
selectValueDivider, selectValueDivider,
} from 'constants/queryBuilder'; } from 'constants/queryBuilder';
import { DEBOUNCE_DELAY } from 'constants/queryBuilderFilterConfig';
import useDebounce from 'hooks/useDebounce'; import useDebounce from 'hooks/useDebounce';
import { createIdFromObjectFields } from 'lib/createIdFromObjectFields'; import { createIdFromObjectFields } from 'lib/createIdFromObjectFields';
import { chooseAutocompleteFromCustomValue } from 'lib/newQueryBuilder/chooseAutocompleteFromCustomValue'; import { chooseAutocompleteFromCustomValue } from 'lib/newQueryBuilder/chooseAutocompleteFromCustomValue';
import { getAutocompleteValueAndType } from 'lib/newQueryBuilder/getAutocompleteValueAndType'; import { getAutocompleteValueAndType } from 'lib/newQueryBuilder/getAutocompleteValueAndType';
import { transformStringWithPrefix } from 'lib/query/transformStringWithPrefix'; import { transformStringWithPrefix } from 'lib/query/transformStringWithPrefix';
import { memo, useCallback, useMemo, useState } from 'react'; import { memo, useCallback, useMemo, useState } from 'react';
import { useQuery } from 'react-query'; import { useQuery, useQueryClient } from 'react-query';
import { SuccessResponse } from 'types/api';
import { import {
AutocompleteType,
BaseAutocompleteData, BaseAutocompleteData,
DataType, IQueryAutocompleteResponse,
} from 'types/api/queryBuilder/queryAutocompleteResponse'; } from 'types/api/queryBuilder/queryAutocompleteResponse';
import { DataSource } from 'types/common/queryBuilder'; import { DataSource } from 'types/common/queryBuilder';
import { ExtendedSelectOption } from 'types/common/select'; import { ExtendedSelectOption } from 'types/common/select';
@ -34,19 +33,9 @@ export const AggregatorFilter = memo(function AggregatorFilter({
disabled, disabled,
onChange, onChange,
}: AgregatorFilterProps): JSX.Element { }: AgregatorFilterProps): JSX.Element {
const queryClient = useQueryClient();
const [optionsData, setOptionsData] = useState<ExtendedSelectOption[]>([]); const [optionsData, setOptionsData] = useState<ExtendedSelectOption[]>([]);
const [searchText, setSearchText] = useState<string>( const [searchText, setSearchText] = useState<string>('');
query.aggregateAttribute.key,
);
const handleChangeAttribute = useCallback(
(data: BaseAutocompleteData[]) => {
const attribute = chooseAutocompleteFromCustomValue(data, [searchText]);
onChange(attribute[0]);
},
[onChange, searchText],
);
const debouncedSearchText = useMemo(() => { const debouncedSearchText = useMemo(() => {
// eslint-disable-next-line @typescript-eslint/naming-convention, @typescript-eslint/no-unused-vars // 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; return value;
}, [searchText]); }, [searchText]);
const debouncedValue = useDebounce(debouncedSearchText, 300); const debouncedValue = useDebounce(debouncedSearchText, DEBOUNCE_DELAY);
const { isFetching } = useQuery( const { isFetching } = useQuery(
[ [
QueryBuilderKeys.GET_AGGREGATE_ATTRIBUTE, QueryBuilderKeys.GET_AGGREGATE_ATTRIBUTE,
@ -86,8 +75,6 @@ export const AggregatorFilter = memo(function AggregatorFilter({
key: createIdFromObjectFields(item, baseAutoCompleteIdKeysOrder), key: createIdFromObjectFields(item, baseAutoCompleteIdKeysOrder),
})) || []; })) || [];
handleChangeAttribute(data.payload?.attributeKeys || []);
setOptionsData(options); setOptionsData(options);
}, },
}, },
@ -102,60 +89,79 @@ export const AggregatorFilter = memo(function AggregatorFilter({
? `${transformToUpperCase(query.dataSource)} name` ? `${transformToUpperCase(query.dataSource)} name`
: 'Aggregate attribute'; : 'Aggregate attribute';
const handleSelect = ( const getAttributes = useCallback(
(): BaseAutocompleteData[] =>
queryClient.getQueryData<SuccessResponse<IQueryAutocompleteResponse>>(
[QueryBuilderKeys.GET_AGGREGATE_ATTRIBUTE],
{ exact: false },
)?.payload.attributeKeys || [],
[queryClient],
);
const handleChangeCustomValue = useCallback(
(value: string) => {
const aggregateAttributes = getAttributes();
const customAttribute: BaseAutocompleteData = chooseAutocompleteFromCustomValue(
aggregateAttributes,
value,
);
onChange(customAttribute);
},
[getAttributes, onChange],
);
const handleBlur = useCallback(() => {
if (searchText) {
handleChangeCustomValue(searchText);
}
}, [handleChangeCustomValue, searchText]);
const handleChange = useCallback(
(
value: string, value: string,
option: ExtendedSelectOption | ExtendedSelectOption[], option: ExtendedSelectOption | ExtendedSelectOption[],
): void => { ): void => {
const currentOption = option as ExtendedSelectOption; const currentOption = option as ExtendedSelectOption;
const aggregateAttributes = getAttributes();
if (currentOption.key) { if (currentOption.key) {
const [key, dataType, type, isColumn] = currentOption.key.split(idDivider); const attribute = aggregateAttributes.find(
const attribute: BaseAutocompleteData = { (item) => item.id === currentOption.key,
key, );
dataType: dataType as DataType,
type: type as AutocompleteType,
isColumn: isColumn === 'true',
};
const text = transformStringWithPrefix({
str: attribute.key,
prefix: attribute.type || '',
condition: !attribute.isColumn,
});
setSearchText(text);
if (attribute) {
onChange(attribute); onChange(attribute);
} else {
const customAttribute: BaseAutocompleteData = {
...initialAutocompleteData,
key: value,
};
const text = transformStringWithPrefix({
str: customAttribute.key,
prefix: customAttribute.type || '',
condition: !customAttribute.isColumn,
});
setSearchText(text);
onChange(customAttribute);
} }
}; } else {
handleChangeCustomValue(value);
}
setSearchText('');
},
[getAttributes, handleChangeCustomValue, onChange],
);
const value = transformStringWithPrefix({
str: query.aggregateAttribute.key,
prefix: query.aggregateAttribute.type || '',
condition: !query.aggregateAttribute.isColumn,
});
return ( return (
<AutoComplete <AutoComplete
placeholder={placeholder} placeholder={placeholder}
style={selectStyle} style={selectStyle}
showArrow={false} showArrow={false}
searchValue={searchText}
onSearch={handleSearchText}
filterOption={false} filterOption={false}
onSearch={handleSearchText}
notFoundContent={isFetching ? <Spin size="small" /> : null} notFoundContent={isFetching ? <Spin size="small" /> : null}
options={optionsData} options={optionsData}
value={searchText} value={value}
onSelect={handleSelect} onBlur={handleBlur}
onChange={handleChange}
disabled={disabled} disabled={disabled}
/> />
); );

View File

@ -3,21 +3,22 @@ import { getAggregateKeys } from 'api/queryBuilder/getAttributeKeys';
// ** Constants // ** Constants
import { import {
idDivider, idDivider,
initialAutocompleteData,
QueryBuilderKeys, QueryBuilderKeys,
selectValueDivider, selectValueDivider,
} from 'constants/queryBuilder'; } from 'constants/queryBuilder';
import { DEBOUNCE_DELAY } from 'constants/queryBuilderFilterConfig';
import useDebounce from 'hooks/useDebounce'; import useDebounce from 'hooks/useDebounce';
import { chooseAutocompleteFromCustomValue } from 'lib/newQueryBuilder/chooseAutocompleteFromCustomValue';
// ** Components // ** Components
// ** Helpers // ** Helpers
import { transformStringWithPrefix } from 'lib/query/transformStringWithPrefix'; import { transformStringWithPrefix } from 'lib/query/transformStringWithPrefix';
import { isEqual, uniqWith } from 'lodash-es'; import { isEqual, uniqWith } from 'lodash-es';
import { memo, useCallback, useEffect, useState } from 'react'; import { memo, useCallback, useEffect, useState } from 'react';
import { useQuery } from 'react-query'; import { useQuery, useQueryClient } from 'react-query';
import { SuccessResponse } from 'types/api';
import { import {
AutocompleteType,
BaseAutocompleteData, BaseAutocompleteData,
DataType, IQueryAutocompleteResponse,
} from 'types/api/queryBuilder/queryAutocompleteResponse'; } from 'types/api/queryBuilder/queryAutocompleteResponse';
import { SelectOption } from 'types/common/select'; import { SelectOption } from 'types/common/select';
@ -29,6 +30,7 @@ export const GroupByFilter = memo(function GroupByFilter({
onChange, onChange,
disabled, disabled,
}: GroupByFilterProps): JSX.Element { }: GroupByFilterProps): JSX.Element {
const queryClient = useQueryClient();
const [searchText, setSearchText] = useState<string>(''); const [searchText, setSearchText] = useState<string>('');
const [optionsData, setOptionsData] = useState<SelectOption<string, string>[]>( const [optionsData, setOptionsData] = useState<SelectOption<string, string>[]>(
[], [],
@ -38,7 +40,7 @@ export const GroupByFilter = memo(function GroupByFilter({
); );
const [isFocused, setIsFocused] = useState<boolean>(false); const [isFocused, setIsFocused] = useState<boolean>(false);
const debouncedValue = useDebounce(searchText, 300); const debouncedValue = useDebounce(searchText, DEBOUNCE_DELAY);
const { isFetching } = useQuery( const { isFetching } = useQuery(
[QueryBuilderKeys.GET_AGGREGATE_KEYS, debouncedValue, isFocused], [QueryBuilderKeys.GET_AGGREGATE_KEYS, debouncedValue, isFocused],
@ -81,6 +83,15 @@ export const GroupByFilter = memo(function GroupByFilter({
}, },
); );
const getAttributeKeys = useCallback(
(): BaseAutocompleteData[] =>
queryClient.getQueryData<SuccessResponse<IQueryAutocompleteResponse>>(
[QueryBuilderKeys.GET_AGGREGATE_KEYS],
{ exact: false },
)?.payload.attributeKeys || [],
[queryClient],
);
const handleSearchKeys = (searchText: string): void => { const handleSearchKeys = (searchText: string): void => {
setSearchText(searchText); setSearchText(searchText);
}; };
@ -97,21 +108,17 @@ export const GroupByFilter = memo(function GroupByFilter({
const handleChange = (values: SelectOption<string, string>[]): void => { const handleChange = (values: SelectOption<string, string>[]): void => {
const groupByValues: BaseAutocompleteData[] = values.map((item) => { const groupByValues: BaseAutocompleteData[] = values.map((item) => {
const [currentValue, id] = item.value.split(selectValueDivider); const [currentValue, id] = item.value.split(selectValueDivider);
if (id && id.includes(idDivider)) { const keys = getAttributeKeys();
const [key, dataType, type, isColumn] = id.split(idDivider);
return { if (id && id.includes(idDivider)) {
id, const attribute = keys.find((item) => item.id === id);
key: key || currentValue,
dataType: (dataType as DataType) || initialAutocompleteData.dataType, if (attribute) {
type: (type as AutocompleteType) || initialAutocompleteData.type, return attribute;
isColumn: isColumn }
? isColumn === 'true'
: initialAutocompleteData.isColumn,
};
} }
return { ...initialAutocompleteData, key: currentValue }; return chooseAutocompleteFromCustomValue(keys, currentValue);
}); });
const result = uniqWith(groupByValues, isEqual); const result = uniqWith(groupByValues, isEqual);

View File

@ -1,6 +1,7 @@
import { getAggregateKeys } from 'api/queryBuilder/getAttributeKeys'; import { getAggregateKeys } from 'api/queryBuilder/getAttributeKeys';
import { getAttributesValues } from 'api/queryBuilder/getAttributesValues'; import { getAttributesValues } from 'api/queryBuilder/getAttributesValues';
import { QueryBuilderKeys } from 'constants/queryBuilder'; import { QueryBuilderKeys } from 'constants/queryBuilder';
import { DEBOUNCE_DELAY } from 'constants/queryBuilderFilterConfig';
import { import {
getRemovePrefixFromKey, getRemovePrefixFromKey,
getTagToken, getTagToken,
@ -54,7 +55,7 @@ export const useFetchKeysAndValues = (
], ],
); );
const searchParams = useDebounceValue(memoizedSearchParams, 300); const searchParams = useDebounceValue(memoizedSearchParams, DEBOUNCE_DELAY);
const isQueryEnabled = useMemo( const isQueryEnabled = useMemo(
() => () =>

View File

@ -3,10 +3,8 @@ import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteRe
export const chooseAutocompleteFromCustomValue = ( export const chooseAutocompleteFromCustomValue = (
sourceList: BaseAutocompleteData[], sourceList: BaseAutocompleteData[],
values: string[], value: string,
): BaseAutocompleteData[] => { ): BaseAutocompleteData => {
console.log({ sourceList });
return values.map((value) => {
const firstBaseAutoCompleteValue = sourceList.find( const firstBaseAutoCompleteValue = sourceList.find(
(sourceAutoComplete) => value === sourceAutoComplete.key, (sourceAutoComplete) => value === sourceAutoComplete.key,
); );
@ -15,5 +13,4 @@ export const chooseAutocompleteFromCustomValue = (
return { ...initialAutocompleteData, key: value }; return { ...initialAutocompleteData, key: value };
return firstBaseAutoCompleteValue; return firstBaseAutoCompleteValue;
});
}; };