diff --git a/frontend/src/container/Trace/Search/AllTags/Tag/DebounceSelect/index.tsx b/frontend/src/container/Trace/Search/AllTags/Tag/DebounceSelect/index.tsx new file mode 100644 index 000000000000..19719478209b --- /dev/null +++ b/frontend/src/container/Trace/Search/AllTags/Tag/DebounceSelect/index.tsx @@ -0,0 +1,63 @@ +import { Select, Spin } from 'antd'; +import { SelectProps } from 'antd/es/select'; +import debounce from 'lodash-es/debounce'; +import React, { useRef, useState } from 'react'; + +export interface DebounceSelectProps + extends Omit, 'options' | 'children'> { + fetchOptions: (search: string) => Promise; + debounceTimeout: number; +} + +function DebounceSelect< + ValueType extends { + key?: string; + label: React.ReactNode; + value: string | number; + } = never +>({ + fetchOptions, + debounceTimeout = 800, + ...props +}: DebounceSelectProps): JSX.Element { + const [fetching, setFetching] = useState(false); + const [options, setOptions] = useState([]); + const fetchRef = useRef(0); + + const debounceFetcher = React.useMemo(() => { + const loadOptions = (value: string): void => { + fetchRef.current += 1; + const fetchId = fetchRef.current; + setOptions([]); + setFetching(true); + + fetchOptions(value).then((newOptions) => { + if (fetchId !== fetchRef.current) { + // for fetch callback order + return; + } + + setOptions(newOptions); + setFetching(false); + }); + }; + + return debounce(loadOptions, debounceTimeout); + }, [fetchOptions, debounceTimeout]); + + return ( + + labelInValue + filterOption={false} + onSearch={debounceFetcher} + notFoundContent={fetching ? : null} + style={{ minWidth: '170px' }} + // as all other props are from SelectProps only + // eslint-disable-next-line react/jsx-props-no-spreading + {...props} + options={options} + /> + ); +} + +export default DebounceSelect; diff --git a/frontend/src/container/Trace/Search/AllTags/Tag/config.ts b/frontend/src/container/Trace/Search/AllTags/Tag/config.ts new file mode 100644 index 000000000000..07ee042621cb --- /dev/null +++ b/frontend/src/container/Trace/Search/AllTags/Tag/config.ts @@ -0,0 +1,32 @@ +import getTagValue from 'api/trace/getTagValue'; + +// Usage of DebounceSelect +export interface TagValue { + label: string; + value: string; +} + +export async function fetchTag( + globalStart: number, + globalEnd: number, + tagKey: string, +): Promise { + const response = await getTagValue({ + end: globalEnd, + start: globalStart, + tagKey, + }); + + if (response.statusCode !== 200 || !response.payload) { + return []; + } + + console.log(response.payload); + + return [ + { + label: 'asd', + value: 'asd', + }, + ]; +} diff --git a/frontend/src/container/Trace/Search/AllTags/Tag/index.tsx b/frontend/src/container/Trace/Search/AllTags/Tag/index.tsx index e6ad17956f66..8bcf15757a20 100644 --- a/frontend/src/container/Trace/Search/AllTags/Tag/index.tsx +++ b/frontend/src/container/Trace/Search/AllTags/Tag/index.tsx @@ -3,14 +3,12 @@ import { Select } from 'antd'; import React from 'react'; import { useSelector } from 'react-redux'; import { AppState } from 'store/reducers'; +import { GlobalReducer } from 'types/reducer/globalTime'; import { TraceReducer } from 'types/reducer/trace'; -import { - Container, - IconContainer, - SelectComponent, - ValueSelect, -} from './styles'; +import { fetchTag, TagValue } from './config'; +import DebounceSelect from './DebounceSelect'; +import { Container, IconContainer, SelectComponent } from './styles'; import TagsKey from './TagKey'; const { Option } = Select; @@ -35,6 +33,9 @@ const AllMenu: AllMenuProps[] = [ function SingleTags(props: AllTagsProps): JSX.Element { const traces = useSelector((state) => state.traces); + const globalReducer = useSelector( + (state) => state.globalTime, + ); const { tag, onCloseHandler, setLocalSelectedTags, index } = props; const { @@ -80,7 +81,15 @@ function SingleTags(props: AllTagsProps): JSX.Element { ))} - => + fetchTag(globalReducer.minTime, globalReducer.maxTime, selectedKey[0]) + } + debounceTimeout={300} + mode="tags" + /> + + {/* { setLocalSelectedTags((tags) => [ @@ -94,7 +103,7 @@ function SingleTags(props: AllTagsProps): JSX.Element { ]); }} mode="tags" - /> + /> */} onDeleteTagHandler(index)}> diff --git a/frontend/src/container/Trace/Search/AllTags/Tag/styles.ts b/frontend/src/container/Trace/Search/AllTags/Tag/styles.ts index 8da702197d35..347bc287f271 100644 --- a/frontend/src/container/Trace/Search/AllTags/Tag/styles.ts +++ b/frontend/src/container/Trace/Search/AllTags/Tag/styles.ts @@ -15,12 +15,6 @@ export const SelectComponent = styled(Select)` } `; -export const ValueSelect = styled(Select)` - &&& { - width: 100%; - } -`; - export const Container = styled.div` &&& { display: flex; diff --git a/frontend/src/types/api/trace/getTagValue.ts b/frontend/src/types/api/trace/getTagValue.ts new file mode 100644 index 000000000000..221be8dfba34 --- /dev/null +++ b/frontend/src/types/api/trace/getTagValue.ts @@ -0,0 +1,11 @@ +import { GlobalReducer } from 'types/reducer/globalTime'; + +export interface Props { + start: GlobalReducer['minTime']; + end: GlobalReducer['maxTime']; + tagKey: string; +} + +export interface PayloadProps { + key: string; +}