From 225a345baa29ed4cf8fa74e18b43c82194830c78 Mon Sep 17 00:00:00 2001 From: Palash gupta Date: Tue, 29 Mar 2022 00:02:16 +0530 Subject: [PATCH 1/4] chore: getTagValue api is added --- frontend/src/api/trace/getTagValue.ts | 28 +++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 frontend/src/api/trace/getTagValue.ts diff --git a/frontend/src/api/trace/getTagValue.ts b/frontend/src/api/trace/getTagValue.ts new file mode 100644 index 0000000000..25156d32ef --- /dev/null +++ b/frontend/src/api/trace/getTagValue.ts @@ -0,0 +1,28 @@ +import axios from 'api'; +import { ErrorResponseHandler } from 'api/ErrorResponseHandler'; +import { AxiosError } from 'axios'; +import { ErrorResponse, SuccessResponse } from 'types/api'; +import { PayloadProps, Props } from 'types/api/trace/getTagValue'; + +const getTagValue = async ( + props: Props, +): Promise | ErrorResponse> => { + try { + const response = await axios.post(`/getTagValues`, { + start: props.start.toString(), + end: props.end.toString(), + tagKey: props.tagKey, + }); + + return { + statusCode: 200, + error: null, + message: 'Success', + payload: response.data, + }; + } catch (error) { + return ErrorResponseHandler(error as AxiosError); + } +}; + +export default getTagValue; From d4d1104a5328c574165f99da2ed02d9fe9c834f1 Mon Sep 17 00:00:00 2001 From: Palash gupta Date: Tue, 29 Mar 2022 00:02:56 +0530 Subject: [PATCH 2/4] WIP: value suggestion is added --- .../AllTags/Tag/DebounceSelect/index.tsx | 63 +++++++++++++++++++ .../Trace/Search/AllTags/Tag/config.ts | 32 ++++++++++ .../Trace/Search/AllTags/Tag/index.tsx | 25 +++++--- .../Trace/Search/AllTags/Tag/styles.ts | 6 -- frontend/src/types/api/trace/getTagValue.ts | 11 ++++ 5 files changed, 123 insertions(+), 14 deletions(-) create mode 100644 frontend/src/container/Trace/Search/AllTags/Tag/DebounceSelect/index.tsx create mode 100644 frontend/src/container/Trace/Search/AllTags/Tag/config.ts create mode 100644 frontend/src/types/api/trace/getTagValue.ts 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 0000000000..1971947820 --- /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 0000000000..07ee042621 --- /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 e6ad17956f..8bcf15757a 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 8da702197d..347bc287f2 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 0000000000..221be8dfba --- /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; +} From 5556d1d6fc8f87f343669a36ba0b49745f57f6f9 Mon Sep 17 00:00:00 2001 From: Palash gupta Date: Tue, 29 Mar 2022 09:59:50 +0530 Subject: [PATCH 3/4] feat: tag value suggestion is updated --- .../AllTags/Tag/DebounceSelect/index.tsx | 2 +- .../Trace/Search/AllTags/Tag/config.ts | 12 ++++------- .../Trace/Search/AllTags/Tag/index.tsx | 21 ++++++++++--------- frontend/src/types/api/trace/getTagValue.ts | 6 ++++-- 4 files changed, 20 insertions(+), 21 deletions(-) diff --git a/frontend/src/container/Trace/Search/AllTags/Tag/DebounceSelect/index.tsx b/frontend/src/container/Trace/Search/AllTags/Tag/DebounceSelect/index.tsx index 1971947820..2576e782e0 100644 --- a/frontend/src/container/Trace/Search/AllTags/Tag/DebounceSelect/index.tsx +++ b/frontend/src/container/Trace/Search/AllTags/Tag/DebounceSelect/index.tsx @@ -51,7 +51,7 @@ function DebounceSelect< filterOption={false} onSearch={debounceFetcher} notFoundContent={fetching ? : null} - style={{ minWidth: '170px' }} + style={{ width: '170px' }} // as all other props are from SelectProps only // eslint-disable-next-line react/jsx-props-no-spreading {...props} diff --git a/frontend/src/container/Trace/Search/AllTags/Tag/config.ts b/frontend/src/container/Trace/Search/AllTags/Tag/config.ts index 07ee042621..ce414a5f15 100644 --- a/frontend/src/container/Trace/Search/AllTags/Tag/config.ts +++ b/frontend/src/container/Trace/Search/AllTags/Tag/config.ts @@ -21,12 +21,8 @@ export async function fetchTag( return []; } - console.log(response.payload); - - return [ - { - label: 'asd', - value: 'asd', - }, - ]; + return response.payload.map((e) => ({ + label: e.tagValues, + value: e.tagValues, + })); } diff --git a/frontend/src/container/Trace/Search/AllTags/Tag/index.tsx b/frontend/src/container/Trace/Search/AllTags/Tag/index.tsx index 8bcf15757a..37b42347a1 100644 --- a/frontend/src/container/Trace/Search/AllTags/Tag/index.tsx +++ b/frontend/src/container/Trace/Search/AllTags/Tag/index.tsx @@ -83,27 +83,22 @@ function SingleTags(props: AllTagsProps): JSX.Element { => - fetchTag(globalReducer.minTime, globalReducer.maxTime, selectedKey[0]) + fetchTag(globalReducer.minTime, globalReducer.maxTime, selectedKey[index]) } debounceTimeout={300} - mode="tags" - /> - - {/* { + onSelect={(value: Value): void => { setLocalSelectedTags((tags) => [ ...tags.slice(0, index), { Key: selectedKey, Operator: selectedOperator, - Values: value as string[], + Values: [...selectedValues, value.value], }, ...tags.slice(index + 1, tags.length), ]); }} - mode="tags" - /> */} + mode="multiple" + /> onDeleteTagHandler(index)}> @@ -121,4 +116,10 @@ interface AllTagsProps { >; } +interface Value { + key: string; + label: string; + value: string; +} + export default SingleTags; diff --git a/frontend/src/types/api/trace/getTagValue.ts b/frontend/src/types/api/trace/getTagValue.ts index 221be8dfba..e90975d1d5 100644 --- a/frontend/src/types/api/trace/getTagValue.ts +++ b/frontend/src/types/api/trace/getTagValue.ts @@ -6,6 +6,8 @@ export interface Props { tagKey: string; } -export interface PayloadProps { - key: string; +interface Value { + tagValues: string; } + +export type PayloadProps = Value[]; From 32e8e489280cb7832ef7532d87febc8bc2555497 Mon Sep 17 00:00:00 2001 From: Palash gupta Date: Mon, 4 Apr 2022 08:24:28 +0530 Subject: [PATCH 4/4] chore: behaviour for dropdown is updated --- .../AllTags/Tag/DebounceSelect/index.tsx | 63 ----------------- .../Trace/Search/AllTags/Tag/TagValue.tsx | 69 +++++++++++++++++++ .../Trace/Search/AllTags/Tag/config.ts | 28 -------- .../Trace/Search/AllTags/Tag/index.tsx | 38 ++++------ 4 files changed, 81 insertions(+), 117 deletions(-) delete mode 100644 frontend/src/container/Trace/Search/AllTags/Tag/DebounceSelect/index.tsx create mode 100644 frontend/src/container/Trace/Search/AllTags/Tag/TagValue.tsx delete mode 100644 frontend/src/container/Trace/Search/AllTags/Tag/config.ts diff --git a/frontend/src/container/Trace/Search/AllTags/Tag/DebounceSelect/index.tsx b/frontend/src/container/Trace/Search/AllTags/Tag/DebounceSelect/index.tsx deleted file mode 100644 index 2576e782e0..0000000000 --- a/frontend/src/container/Trace/Search/AllTags/Tag/DebounceSelect/index.tsx +++ /dev/null @@ -1,63 +0,0 @@ -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={{ width: '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/TagValue.tsx b/frontend/src/container/Trace/Search/AllTags/Tag/TagValue.tsx new file mode 100644 index 0000000000..378001bec4 --- /dev/null +++ b/frontend/src/container/Trace/Search/AllTags/Tag/TagValue.tsx @@ -0,0 +1,69 @@ +import { Select } from 'antd'; +import { DefaultOptionType } from 'antd/lib/select'; +import getTagValue from 'api/trace/getTagValue'; +import useFetch from 'hooks/useFetch'; +import React from 'react'; +import { useSelector } from 'react-redux'; +import { AppState } from 'store/reducers'; +import { PayloadProps, Props } from 'types/api/trace/getTagValue'; +import { GlobalReducer } from 'types/reducer/globalTime'; +import { TraceReducer } from 'types/reducer/trace'; + +import { Value } from '.'; +import { SelectComponent } from './styles'; + +function TagValue(props: TagValueProps): JSX.Element { + const { tag, setLocalSelectedTags, index, tagKey } = props; + const { + Key: selectedKey, + Operator: selectedOperator, + Values: selectedValues, + } = tag; + + const globalReducer = useSelector( + (state) => state.globalTime, + ); + + const valueSuggestion = useFetch(getTagValue, { + end: globalReducer.maxTime, + start: globalReducer.minTime, + tagKey, + }); + + return ( + { + if (typeof value === 'string') { + setLocalSelectedTags((tags) => [ + ...tags.slice(0, index), + { + Key: selectedKey, + Operator: selectedOperator, + Values: [...selectedValues, value], + }, + ...tags.slice(index + 1, tags.length), + ]); + } + }} + loading={valueSuggestion.loading || false} + > + {valueSuggestion.payload && + valueSuggestion.payload.map((suggestion) => ( + + {suggestion.tagValues} + + ))} + + ); +} + +interface TagValueProps { + index: number; + tag: FlatArray; + setLocalSelectedTags: React.Dispatch< + React.SetStateAction + >; + tagKey: string; +} + +export default TagValue; diff --git a/frontend/src/container/Trace/Search/AllTags/Tag/config.ts b/frontend/src/container/Trace/Search/AllTags/Tag/config.ts deleted file mode 100644 index ce414a5f15..0000000000 --- a/frontend/src/container/Trace/Search/AllTags/Tag/config.ts +++ /dev/null @@ -1,28 +0,0 @@ -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 []; - } - - return response.payload.map((e) => ({ - label: e.tagValues, - value: e.tagValues, - })); -} diff --git a/frontend/src/container/Trace/Search/AllTags/Tag/index.tsx b/frontend/src/container/Trace/Search/AllTags/Tag/index.tsx index 37b42347a1..ad9b0e7972 100644 --- a/frontend/src/container/Trace/Search/AllTags/Tag/index.tsx +++ b/frontend/src/container/Trace/Search/AllTags/Tag/index.tsx @@ -3,13 +3,11 @@ 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 { fetchTag, TagValue } from './config'; -import DebounceSelect from './DebounceSelect'; import { Container, IconContainer, SelectComponent } from './styles'; import TagsKey from './TagKey'; +import TagValue from './TagValue'; const { Option } = Select; @@ -33,9 +31,6 @@ 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 { @@ -69,7 +64,6 @@ function SingleTags(props: AllTagsProps): JSX.Element { tag={tag} setLocalSelectedTags={setLocalSelectedTags} /> - e.key === selectedOperator)?.value || ''} @@ -81,24 +75,16 @@ function SingleTags(props: AllTagsProps): JSX.Element { ))} - => - fetchTag(globalReducer.minTime, globalReducer.maxTime, selectedKey[index]) - } - debounceTimeout={300} - onSelect={(value: Value): void => { - setLocalSelectedTags((tags) => [ - ...tags.slice(0, index), - { - Key: selectedKey, - Operator: selectedOperator, - Values: [...selectedValues, value.value], - }, - ...tags.slice(index + 1, tags.length), - ]); - }} - mode="multiple" - /> + {selectedKey[0] ? ( + + ) : ( + + )} onDeleteTagHandler(index)}> @@ -116,7 +102,7 @@ interface AllTagsProps { >; } -interface Value { +export interface Value { key: string; label: string; value: string;