mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-06-04 11:25:52 +08:00
feat: add autofill autocomplete data from response (#3092)
Co-authored-by: Palash Gupta <palashgdev@gmail.com>
This commit is contained in:
parent
652bd52ea7
commit
cc62d2cf71
@ -3,6 +3,7 @@ import { GRAPH_TYPES } from 'container/NewDashboard/ComponentsSlider';
|
|||||||
import { createIdFromObjectFields } from 'lib/createIdFromObjectFields';
|
import { createIdFromObjectFields } from 'lib/createIdFromObjectFields';
|
||||||
import { createNewBuilderItemName } from 'lib/newQueryBuilder/createNewBuilderItemName';
|
import { createNewBuilderItemName } from 'lib/newQueryBuilder/createNewBuilderItemName';
|
||||||
import {
|
import {
|
||||||
|
AutocompleteType,
|
||||||
BaseAutocompleteData,
|
BaseAutocompleteData,
|
||||||
LocalDataType,
|
LocalDataType,
|
||||||
} from 'types/api/queryBuilder/queryAutocompleteResponse';
|
} from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||||
@ -50,6 +51,11 @@ export const baseAutoCompleteIdKeysOrder: (keyof Omit<
|
|||||||
'id'
|
'id'
|
||||||
>)[] = ['key', 'dataType', 'type', 'isColumn'];
|
>)[] = ['key', 'dataType', 'type', 'isColumn'];
|
||||||
|
|
||||||
|
export const autocompleteType: Record<AutocompleteType, AutocompleteType> = {
|
||||||
|
resource: 'resource',
|
||||||
|
tag: 'tag',
|
||||||
|
};
|
||||||
|
|
||||||
export const formulasNames: string[] = Array.from(
|
export const formulasNames: string[] = Array.from(
|
||||||
Array(MAX_FORMULAS),
|
Array(MAX_FORMULAS),
|
||||||
(_, i) => `F${i + 1}`,
|
(_, i) => `F${i + 1}`,
|
||||||
|
@ -3,3 +3,5 @@ export const FORMULA_REGEXP = /F\d+/;
|
|||||||
export const HAVING_FILTER_REGEXP = /^[-\d.,\s]+$/;
|
export const HAVING_FILTER_REGEXP = /^[-\d.,\s]+$/;
|
||||||
|
|
||||||
export const TYPE_ADDON_REGEXP = /_(.+)/;
|
export const TYPE_ADDON_REGEXP = /_(.+)/;
|
||||||
|
|
||||||
|
export const SPLIT_FIRST_UNDERSCORE = /(?<!^)_/;
|
||||||
|
@ -11,6 +11,8 @@ import {
|
|||||||
} from 'constants/queryBuilder';
|
} from 'constants/queryBuilder';
|
||||||
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 { 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 } from 'react-query';
|
||||||
@ -33,7 +35,27 @@ export const AggregatorFilter = memo(function AggregatorFilter({
|
|||||||
onChange,
|
onChange,
|
||||||
}: AgregatorFilterProps): JSX.Element {
|
}: AgregatorFilterProps): JSX.Element {
|
||||||
const [optionsData, setOptionsData] = useState<ExtendedSelectOption[]>([]);
|
const [optionsData, setOptionsData] = useState<ExtendedSelectOption[]>([]);
|
||||||
const debouncedValue = useDebounce(query.aggregateAttribute.key, 300);
|
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(() => {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/naming-convention, @typescript-eslint/no-unused-vars
|
||||||
|
const [_, value] = getAutocompleteValueAndType(searchText);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}, [searchText]);
|
||||||
|
|
||||||
|
const debouncedValue = useDebounce(debouncedSearchText, 300);
|
||||||
const { isFetching } = useQuery(
|
const { isFetching } = useQuery(
|
||||||
[
|
[
|
||||||
QueryBuilderKeys.GET_AGGREGATE_ATTRIBUTE,
|
QueryBuilderKeys.GET_AGGREGATE_ATTRIBUTE,
|
||||||
@ -64,13 +86,23 @@ export const AggregatorFilter = memo(function AggregatorFilter({
|
|||||||
key: createIdFromObjectFields(item, baseAutoCompleteIdKeysOrder),
|
key: createIdFromObjectFields(item, baseAutoCompleteIdKeysOrder),
|
||||||
})) || [];
|
})) || [];
|
||||||
|
|
||||||
|
handleChangeAttribute(data.payload?.attributeKeys || []);
|
||||||
|
|
||||||
setOptionsData(options);
|
setOptionsData(options);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleChangeAttribute = useCallback(
|
const handleSearchText = useCallback((text: string): void => {
|
||||||
(
|
setSearchText(text);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const placeholder: string =
|
||||||
|
query.dataSource === DataSource.METRICS
|
||||||
|
? `${transformToUpperCase(query.dataSource)} name`
|
||||||
|
: 'Aggregate attribute';
|
||||||
|
|
||||||
|
const handleSelect = (
|
||||||
value: string,
|
value: string,
|
||||||
option: ExtendedSelectOption | ExtendedSelectOption[],
|
option: ExtendedSelectOption | ExtendedSelectOption[],
|
||||||
): void => {
|
): void => {
|
||||||
@ -85,41 +117,45 @@ export const AggregatorFilter = memo(function AggregatorFilter({
|
|||||||
isColumn: isColumn === 'true',
|
isColumn: isColumn === 'true',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const text = transformStringWithPrefix({
|
||||||
|
str: attribute.key,
|
||||||
|
prefix: attribute.type || '',
|
||||||
|
condition: !attribute.isColumn,
|
||||||
|
});
|
||||||
|
|
||||||
|
setSearchText(text);
|
||||||
|
|
||||||
onChange(attribute);
|
onChange(attribute);
|
||||||
} else {
|
} else {
|
||||||
const attribute = { ...initialAutocompleteData, key: value };
|
const customAttribute: BaseAutocompleteData = {
|
||||||
|
...initialAutocompleteData,
|
||||||
|
key: value,
|
||||||
|
};
|
||||||
|
|
||||||
onChange(attribute);
|
const text = transformStringWithPrefix({
|
||||||
|
str: customAttribute.key,
|
||||||
|
prefix: customAttribute.type || '',
|
||||||
|
condition: !customAttribute.isColumn,
|
||||||
|
});
|
||||||
|
|
||||||
|
setSearchText(text);
|
||||||
|
|
||||||
|
onChange(customAttribute);
|
||||||
}
|
}
|
||||||
},
|
};
|
||||||
[onChange],
|
|
||||||
);
|
|
||||||
|
|
||||||
const value = useMemo(
|
|
||||||
() =>
|
|
||||||
transformStringWithPrefix({
|
|
||||||
str: query.aggregateAttribute.key,
|
|
||||||
prefix: query.aggregateAttribute.type || '',
|
|
||||||
condition: !query.aggregateAttribute.isColumn,
|
|
||||||
}),
|
|
||||||
[query],
|
|
||||||
);
|
|
||||||
|
|
||||||
const placeholder: string =
|
|
||||||
query.dataSource === DataSource.METRICS
|
|
||||||
? `${transformToUpperCase(query.dataSource)} name`
|
|
||||||
: 'Aggregate attribute';
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AutoComplete
|
<AutoComplete
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
style={selectStyle}
|
style={selectStyle}
|
||||||
showArrow={false}
|
showArrow={false}
|
||||||
|
searchValue={searchText}
|
||||||
|
onSearch={handleSearchText}
|
||||||
filterOption={false}
|
filterOption={false}
|
||||||
notFoundContent={isFetching ? <Spin size="small" /> : null}
|
notFoundContent={isFetching ? <Spin size="small" /> : null}
|
||||||
options={optionsData}
|
options={optionsData}
|
||||||
value={value}
|
value={searchText}
|
||||||
onChange={handleChangeAttribute}
|
onSelect={handleSelect}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -0,0 +1,19 @@
|
|||||||
|
import { initialAutocompleteData } from 'constants/queryBuilder';
|
||||||
|
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||||
|
|
||||||
|
export const chooseAutocompleteFromCustomValue = (
|
||||||
|
sourceList: BaseAutocompleteData[],
|
||||||
|
values: string[],
|
||||||
|
): BaseAutocompleteData[] => {
|
||||||
|
console.log({ sourceList });
|
||||||
|
return values.map((value) => {
|
||||||
|
const firstBaseAutoCompleteValue = sourceList.find(
|
||||||
|
(sourceAutoComplete) => value === sourceAutoComplete.key,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!firstBaseAutoCompleteValue)
|
||||||
|
return { ...initialAutocompleteData, key: value };
|
||||||
|
|
||||||
|
return firstBaseAutoCompleteValue;
|
||||||
|
});
|
||||||
|
};
|
@ -0,0 +1,17 @@
|
|||||||
|
import { autocompleteType } from 'constants/queryBuilder';
|
||||||
|
import { SPLIT_FIRST_UNDERSCORE } from 'constants/regExp';
|
||||||
|
|
||||||
|
export const getAutocompleteValueAndType = (str: string): [string, string] => {
|
||||||
|
if (str === '') return [str, str];
|
||||||
|
|
||||||
|
const [firstValue, secondValue] = str.split(SPLIT_FIRST_UNDERSCORE);
|
||||||
|
|
||||||
|
if (
|
||||||
|
firstValue === autocompleteType.tag ||
|
||||||
|
firstValue === autocompleteType.resource
|
||||||
|
) {
|
||||||
|
return [firstValue, secondValue];
|
||||||
|
}
|
||||||
|
|
||||||
|
return ['', firstValue];
|
||||||
|
};
|
Loading…
x
Reference in New Issue
Block a user