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(
keysAutocomplete,
[fieldKey],
)[0];
fieldKey,
);
const nextQuery: Query = {
...currentQuery,

View File

@ -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<ExtendedSelectOption[]>([]);
const [searchText, setSearchText] = useState<string>(
query.aggregateAttribute.key,
);
const handleChangeAttribute = useCallback(
(data: BaseAutocompleteData[]) => {
const attribute = chooseAutocompleteFromCustomValue(data, [searchText]);
onChange(attribute[0]);
},
[onChange, searchText],
);
const [searchText, setSearchText] = useState<string>('');
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<SuccessResponse<IQueryAutocompleteResponse>>(
[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 (
<AutoComplete
placeholder={placeholder}
style={selectStyle}
showArrow={false}
searchValue={searchText}
onSearch={handleSearchText}
filterOption={false}
onSearch={handleSearchText}
notFoundContent={isFetching ? <Spin size="small" /> : null}
options={optionsData}
value={searchText}
onSelect={handleSelect}
value={value}
onBlur={handleBlur}
onChange={handleChange}
disabled={disabled}
/>
);

View File

@ -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<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 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<SuccessResponse<IQueryAutocompleteResponse>>(
[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<string, string>[]): 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);

View File

@ -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(
() =>

View File

@ -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;
};