From d150cfa46ca07244afcc1733cc30bd4b98312bba Mon Sep 17 00:00:00 2001 From: Palash gupta Date: Mon, 6 Jun 2022 10:48:12 +0530 Subject: [PATCH 1/7] fix: using legacy_createStore instead of createStore as it seem it is depecreated --- frontend/src/store/index.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/frontend/src/store/index.ts b/frontend/src/store/index.ts index 39f43fdf85..3ff983b82e 100644 --- a/frontend/src/store/index.ts +++ b/frontend/src/store/index.ts @@ -1,4 +1,8 @@ -import { applyMiddleware, compose, createStore } from 'redux'; +import { + applyMiddleware, + compose, + legacy_createStore as createStore, +} from 'redux'; import thunk, { ThunkMiddleware } from 'redux-thunk'; import AppActions from 'types/actions'; From 224ec8d0d9d3ce0b9422c6c35dd378d3d5cd6449 Mon Sep 17 00:00:00 2001 From: Palash Date: Thu, 23 Jun 2022 01:04:38 +0530 Subject: [PATCH 2/7] feat: search filter is added in the trace filter --- .../Panel/PanelBody/CommonCheckBox/index.tsx | 51 +++++++++++++++++-- frontend/src/store/reducers/trace.ts | 21 ++++++++ frontend/src/types/actions/trace.ts | 10 +++- frontend/src/types/reducer/trace.ts | 1 + 4 files changed, 79 insertions(+), 4 deletions(-) diff --git a/frontend/src/container/Trace/Filters/Panel/PanelBody/CommonCheckBox/index.tsx b/frontend/src/container/Trace/Filters/Panel/PanelBody/CommonCheckBox/index.tsx index 0681e7e5d5..72d7439ade 100644 --- a/frontend/src/container/Trace/Filters/Panel/PanelBody/CommonCheckBox/index.tsx +++ b/frontend/src/container/Trace/Filters/Panel/PanelBody/CommonCheckBox/index.tsx @@ -1,12 +1,19 @@ -import React from 'react'; -import { useSelector } from 'react-redux'; +import { Button, Input } from 'antd'; +import React, { useState } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import { Dispatch } from 'redux'; import { AppState } from 'store/reducers'; +import { INITIAL_FILTER_VALUE } from 'store/reducers/trace'; +import AppActions from 'types/actions'; +import { UPDATE_SPAN_UPDATE_FILTER_DISPLAY_VALUE } from 'types/actions/trace'; import { TraceFilterEnum, TraceReducer } from 'types/reducer/trace'; import CheckBoxComponent from '../Common/Checkbox'; +const { Search } = Input; + function CommonCheckBox(props: CommonCheckBoxProps): JSX.Element { - const { filter } = useSelector( + const { filter, filterDisplayValue } = useSelector( (state) => state.traces, ); @@ -15,9 +22,34 @@ function CommonCheckBox(props: CommonCheckBoxProps): JSX.Element { const status = filter.get(name) || {}; const statusObj = Object.keys(status); + const numberOfFilters = filterDisplayValue.get(name) || 0; + const dispatch = useDispatch>(); + const [searchFilter, setSearchFilter] = useState(''); + + const onClickMoreHandler = (): void => { + const newFilterDisplayValue = new Map(filterDisplayValue); + const preValue = + (newFilterDisplayValue.get(name) || 0) + INITIAL_FILTER_VALUE; + + newFilterDisplayValue.set(name, preValue); + + dispatch({ + type: UPDATE_SPAN_UPDATE_FILTER_DISPLAY_VALUE, + payload: newFilterDisplayValue, + }); + }; return ( <> + setSearchFilter(e.target.value)} + style={{ + padding: '0 3%', + }} + placeholder="Filter Values" + /> + {statusObj .sort((a, b) => { const countA = +status[a]; @@ -28,6 +60,13 @@ function CommonCheckBox(props: CommonCheckBoxProps): JSX.Element { } return countA - countB; }) + .filter((_, index) => index < numberOfFilters) + .filter((filter) => { + if (searchFilter.length === 0) { + return true; + } + return filter.includes(searchFilter); + }) .map((e) => ( ))} + + {numberOfFilters && statusObj.length > numberOfFilters && ( + + )} ); } diff --git a/frontend/src/store/reducers/trace.ts b/frontend/src/store/reducers/trace.ts index b99ee7dd3a..4023d375ca 100644 --- a/frontend/src/store/reducers/trace.ts +++ b/frontend/src/store/reducers/trace.ts @@ -11,6 +11,7 @@ import { UPDATE_SELECTED_TAGS, UPDATE_SPAN_ORDER, UPDATE_SPAN_ORDER_PARAMS, + UPDATE_SPAN_UPDATE_FILTER_DISPLAY_VALUE, UPDATE_SPANS_AGGREGATE, UPDATE_SPANS_AGGREGATE_PAGE_NUMBER, UPDATE_SPANS_AGGREGATE_PAGE_SIZE, @@ -23,6 +24,8 @@ import { } from 'types/actions/trace'; import { TraceFilterEnum, TraceReducer } from 'types/reducer/trace'; +export const INITIAL_FILTER_VALUE = 4; + const initialValue: TraceReducer = { filter: new Map(), filterToFetchData: ['duration', 'status', 'serviceName'], @@ -53,6 +56,17 @@ const initialValue: TraceReducer = { loading: true, payload: { items: {} }, }, + filterDisplayValue: new Map([ + ['component', INITIAL_FILTER_VALUE], + ['duration', INITIAL_FILTER_VALUE], + ['httpCode', INITIAL_FILTER_VALUE], + ['httpHost', INITIAL_FILTER_VALUE], + ['httpMethod', INITIAL_FILTER_VALUE], + ['httpUrl', INITIAL_FILTER_VALUE], + ['operation', INITIAL_FILTER_VALUE], + ['serviceName', INITIAL_FILTER_VALUE], + ['status', INITIAL_FILTER_VALUE], + ]), }; const traceReducer = ( @@ -251,6 +265,13 @@ const traceReducer = ( }; } + case UPDATE_SPAN_UPDATE_FILTER_DISPLAY_VALUE: { + return { + ...state, + filterDisplayValue: action.payload, + }; + } + default: return state; } diff --git a/frontend/src/types/actions/trace.ts b/frontend/src/types/actions/trace.ts index da97d05129..f043926142 100644 --- a/frontend/src/types/actions/trace.ts +++ b/frontend/src/types/actions/trace.ts @@ -31,6 +31,8 @@ export const UPDATE_SPANS_AGGREGATE_PAGE_NUMBER = export const UPDATE_SPANS_AGGREGATE_PAGE_SIZE = 'UPDATE_SPANS_AGGREGATE_PAGE_SIZE'; export const UPDATE_SPAN_ORDER_PARAMS = 'UPDATE_SPAN_ORDER_PARAMS'; +export const UPDATE_SPAN_UPDATE_FILTER_DISPLAY_VALUE = + 'UPDATE_SPAN_UPDATE_FILTER_DISPLAY_VALUE'; export interface UpdateFilter { type: typeof UPDATE_TRACE_FILTER; @@ -187,6 +189,11 @@ export interface UpdateSpanParams { }; } +export interface UpdateTraceFilterDisplayValue { + type: typeof UPDATE_SPAN_UPDATE_FILTER_DISPLAY_VALUE; + payload: TraceReducer['filterDisplayValue']; +} + export type TraceActions = | UpdateFilter | GetTraceFilter @@ -208,4 +215,5 @@ export type TraceActions = | UpdateSpanOrder | UpdateSpansAggregatePageNumber | UpdateSpanSize - | UpdateSpanParams; + | UpdateSpanParams + | UpdateTraceFilterDisplayValue; diff --git a/frontend/src/types/reducer/trace.ts b/frontend/src/types/reducer/trace.ts index babeb344c6..fc1c08f4fc 100644 --- a/frontend/src/types/reducer/trace.ts +++ b/frontend/src/types/reducer/trace.ts @@ -32,6 +32,7 @@ export interface TraceReducer { payload: PayloadProps; }; yAxisUnit: string | undefined; + filterDisplayValue: Map; } interface SpansAggregateData { From 729c7fce7b84d67f8433d984ae87152306e3ef43 Mon Sep 17 00:00:00 2001 From: Palash Date: Thu, 23 Jun 2022 01:08:51 +0530 Subject: [PATCH 3/7] chore: initial value is made 8 --- frontend/src/store/reducers/trace.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/store/reducers/trace.ts b/frontend/src/store/reducers/trace.ts index 4023d375ca..3f7672cdd5 100644 --- a/frontend/src/store/reducers/trace.ts +++ b/frontend/src/store/reducers/trace.ts @@ -24,7 +24,7 @@ import { } from 'types/actions/trace'; import { TraceFilterEnum, TraceReducer } from 'types/reducer/trace'; -export const INITIAL_FILTER_VALUE = 4; +export const INITIAL_FILTER_VALUE = 8; const initialValue: TraceReducer = { filter: new Map(), From d7d0d70aa5e281834f87087f996e5a95e37aede4 Mon Sep 17 00:00:00 2001 From: Palash Date: Thu, 23 Jun 2022 01:12:12 +0530 Subject: [PATCH 4/7] chore: search filter is made conditional as filters need to be present --- .../Panel/PanelBody/CommonCheckBox/index.tsx | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/frontend/src/container/Trace/Filters/Panel/PanelBody/CommonCheckBox/index.tsx b/frontend/src/container/Trace/Filters/Panel/PanelBody/CommonCheckBox/index.tsx index 72d7439ade..29255ae549 100644 --- a/frontend/src/container/Trace/Filters/Panel/PanelBody/CommonCheckBox/index.tsx +++ b/frontend/src/container/Trace/Filters/Panel/PanelBody/CommonCheckBox/index.tsx @@ -41,14 +41,16 @@ function CommonCheckBox(props: CommonCheckBoxProps): JSX.Element { return ( <> - setSearchFilter(e.target.value)} - style={{ - padding: '0 3%', - }} - placeholder="Filter Values" - /> + {statusObj.length > 0 && ( + setSearchFilter(e.target.value)} + style={{ + padding: '0 3%', + }} + placeholder="Filter Values" + /> + )} {statusObj .sort((a, b) => { From 1e980c3886701dc12c3b59e3ff29ceb44944da60 Mon Sep 17 00:00:00 2001 From: Palash Date: Thu, 23 Jun 2022 12:37:42 +0530 Subject: [PATCH 5/7] feat: condition is updated --- .../Filters/Panel/PanelBody/CommonCheckBox/index.tsx | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/frontend/src/container/Trace/Filters/Panel/PanelBody/CommonCheckBox/index.tsx b/frontend/src/container/Trace/Filters/Panel/PanelBody/CommonCheckBox/index.tsx index 29255ae549..440c9652a7 100644 --- a/frontend/src/container/Trace/Filters/Panel/PanelBody/CommonCheckBox/index.tsx +++ b/frontend/src/container/Trace/Filters/Panel/PanelBody/CommonCheckBox/index.tsx @@ -39,6 +39,10 @@ function CommonCheckBox(props: CommonCheckBoxProps): JSX.Element { }); }; + const isMoreButtonAvilable = Boolean( + numberOfFilters && statusObj.length > numberOfFilters, + ); + return ( <> {statusObj.length > 0 && ( @@ -62,13 +66,15 @@ function CommonCheckBox(props: CommonCheckBoxProps): JSX.Element { } return countA - countB; }) - .filter((_, index) => index < numberOfFilters) .filter((filter) => { if (searchFilter.length === 0) { return true; } - return filter.includes(searchFilter); + return filter + .toLocaleLowerCase() + .includes(searchFilter.toLocaleLowerCase()); }) + .filter((_, index) => index < numberOfFilters) .map((e) => ( ))} - {numberOfFilters && statusObj.length > numberOfFilters && ( + {isMoreButtonAvilable && ( From 1ebf3dbf657f00e3dee4ef221e1087ef8b9a2233 Mon Sep 17 00:00:00 2001 From: Palash Date: Thu, 23 Jun 2022 19:11:19 +0530 Subject: [PATCH 6/7] feat: select tags key and value are updated to autocomplete filtering (#1267) * feat: select tags key and value are updated to autocomplete filtering Co-authored-by: Palash gupta --- .../Trace/Search/AllTags/Tag/TagKey.tsx | 23 ++++++++++---- .../Trace/Search/AllTags/Tag/TagValue.tsx | 31 ++++++++++++++----- .../Trace/Search/AllTags/Tag/styles.ts | 21 ++++++++++--- 3 files changed, 57 insertions(+), 18 deletions(-) diff --git a/frontend/src/container/Trace/Search/AllTags/Tag/TagKey.tsx b/frontend/src/container/Trace/Search/AllTags/Tag/TagKey.tsx index b57b4fc361..bb9794d8e7 100644 --- a/frontend/src/container/Trace/Search/AllTags/Tag/TagKey.tsx +++ b/frontend/src/container/Trace/Search/AllTags/Tag/TagKey.tsx @@ -73,11 +73,24 @@ function TagsKey(props: TagsKeysProps): JSX.Element { { - if (options && options.find((option) => option.value === value)) { + allowClear + showSearch + options={options?.map((e) => ({ + label: e.label?.toString(), + value: e.value, + }))} + filterOption={(inputValue, option): boolean => + option?.label?.toUpperCase().indexOf(inputValue.toUpperCase()) !== -1 + } + onChange={(e): void => setSelectedKey(e)} + onSelect={(value: unknown): void => { + if ( + typeof value === 'string' && + options && + options.find((option) => option.value === value) + ) { setSelectedKey(value); setLocalSelectedTags((tags) => [ @@ -89,8 +102,6 @@ function TagsKey(props: TagsKeysProps): JSX.Element { }, ...tags.slice(index + 1, tags.length), ]); - } else { - setSelectedKey(''); } }} > diff --git a/frontend/src/container/Trace/Search/AllTags/Tag/TagValue.tsx b/frontend/src/container/Trace/Search/AllTags/Tag/TagValue.tsx index 756bb54225..60b2d4118b 100644 --- a/frontend/src/container/Trace/Search/AllTags/Tag/TagValue.tsx +++ b/frontend/src/container/Trace/Search/AllTags/Tag/TagValue.tsx @@ -1,13 +1,13 @@ import { Select } from 'antd'; import getTagValue from 'api/trace/getTagValue'; -import React from 'react'; +import React, { useState } from 'react'; import { useQuery } from 'react-query'; import { useSelector } from 'react-redux'; import { AppState } from 'store/reducers'; import { GlobalReducer } from 'types/reducer/globalTime'; import { TraceReducer } from 'types/reducer/trace'; -import { SelectComponent } from './styles'; +import { AutoCompleteComponent } from './styles'; function TagValue(props: TagValueProps): JSX.Element { const { tag, setLocalSelectedTags, index, tagKey } = props; @@ -16,6 +16,7 @@ function TagValue(props: TagValueProps): JSX.Element { Operator: selectedOperator, Values: selectedValues, } = tag; + const [localValue, setLocalValue] = useState(selectedValues[0]); const globalReducer = useSelector( (state) => state.globalTime, @@ -34,22 +35,38 @@ function TagValue(props: TagValueProps): JSX.Element { ); return ( - ({ + label: e.tagValues, + value: e.tagValues, + }))} + allowClear + defaultOpen + showSearch + filterOption={(inputValue, option): boolean => + option?.label.toUpperCase().indexOf(inputValue.toUpperCase()) !== -1 + } + disabled={isLoading} + value={localValue} + onChange={(values): void => { + if (typeof values === 'string') { + setLocalValue(values); + } + }} onSelect={(value: unknown): void => { if (typeof value === 'string') { + setLocalValue(value); setLocalSelectedTags((tags) => [ ...tags.slice(0, index), { Key: selectedKey, Operator: selectedOperator, - Values: [...selectedValues, value], + Values: [value], }, ...tags.slice(index + 1, tags.length), ]); } }} - loading={isLoading || false} > {data && data.payload && @@ -58,7 +75,7 @@ function TagValue(props: TagValueProps): JSX.Element { {suggestion.tagValues} ))} - + ); } diff --git a/frontend/src/container/Trace/Search/AllTags/Tag/styles.ts b/frontend/src/container/Trace/Search/AllTags/Tag/styles.ts index 347bc287f2..e604a444d7 100644 --- a/frontend/src/container/Trace/Search/AllTags/Tag/styles.ts +++ b/frontend/src/container/Trace/Search/AllTags/Tag/styles.ts @@ -1,4 +1,4 @@ -import { Select, Space } from 'antd'; +import { AutoComplete, Select, Space } from 'antd'; import styled from 'styled-components'; export const SpaceComponent = styled(Space)` @@ -9,18 +9,23 @@ export const SpaceComponent = styled(Space)` export const SelectComponent = styled(Select)` &&& { - min-width: 170px; - margin-right: 21.91px; - margin-left: 21.92px; + width: 100%; } `; -export const Container = styled.div` +export const Container = styled(Space)` &&& { display: flex; margin-top: 1rem; margin-bottom: 1rem; } + + .ant-space-item:not(:last-child, :nth-child(2)) { + width: 100%; + } + .ant-space-item:nth-child(2) { + width: 50%; + } `; export const IconContainer = styled.div` @@ -31,3 +36,9 @@ export const IconContainer = styled.div` margin-left: 1.125rem; `; + +export const AutoCompleteComponent = styled(AutoComplete)` + &&& { + width: 100%; + } +`; From bef83d30cce8e3d86dc39c8e312c4759b44ef5f5 Mon Sep 17 00:00:00 2001 From: Palash Date: Thu, 23 Jun 2022 19:12:43 +0530 Subject: [PATCH 7/7] feat: duration filter is updated (#1272) * feat: duration filter is updated * feat: search filter is added in the trace filter Co-authored-by: Palash gupta --- .../Panel/PanelBody/CommonCheckBox/index.tsx | 51 ++++++++++- .../Panel/PanelBody/Duration/index.tsx | 89 +++++++++---------- .../Panel/PanelBody/Duration/styles.ts | 15 +++- .../Filters/Panel/PanelBody/Duration/util.ts | 13 +++ frontend/src/store/reducers/trace.ts | 21 +++++ frontend/src/types/actions/trace.ts | 10 ++- frontend/src/types/reducer/trace.ts | 1 + 7 files changed, 149 insertions(+), 51 deletions(-) create mode 100644 frontend/src/container/Trace/Filters/Panel/PanelBody/Duration/util.ts diff --git a/frontend/src/container/Trace/Filters/Panel/PanelBody/CommonCheckBox/index.tsx b/frontend/src/container/Trace/Filters/Panel/PanelBody/CommonCheckBox/index.tsx index 0681e7e5d5..72d7439ade 100644 --- a/frontend/src/container/Trace/Filters/Panel/PanelBody/CommonCheckBox/index.tsx +++ b/frontend/src/container/Trace/Filters/Panel/PanelBody/CommonCheckBox/index.tsx @@ -1,12 +1,19 @@ -import React from 'react'; -import { useSelector } from 'react-redux'; +import { Button, Input } from 'antd'; +import React, { useState } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import { Dispatch } from 'redux'; import { AppState } from 'store/reducers'; +import { INITIAL_FILTER_VALUE } from 'store/reducers/trace'; +import AppActions from 'types/actions'; +import { UPDATE_SPAN_UPDATE_FILTER_DISPLAY_VALUE } from 'types/actions/trace'; import { TraceFilterEnum, TraceReducer } from 'types/reducer/trace'; import CheckBoxComponent from '../Common/Checkbox'; +const { Search } = Input; + function CommonCheckBox(props: CommonCheckBoxProps): JSX.Element { - const { filter } = useSelector( + const { filter, filterDisplayValue } = useSelector( (state) => state.traces, ); @@ -15,9 +22,34 @@ function CommonCheckBox(props: CommonCheckBoxProps): JSX.Element { const status = filter.get(name) || {}; const statusObj = Object.keys(status); + const numberOfFilters = filterDisplayValue.get(name) || 0; + const dispatch = useDispatch>(); + const [searchFilter, setSearchFilter] = useState(''); + + const onClickMoreHandler = (): void => { + const newFilterDisplayValue = new Map(filterDisplayValue); + const preValue = + (newFilterDisplayValue.get(name) || 0) + INITIAL_FILTER_VALUE; + + newFilterDisplayValue.set(name, preValue); + + dispatch({ + type: UPDATE_SPAN_UPDATE_FILTER_DISPLAY_VALUE, + payload: newFilterDisplayValue, + }); + }; return ( <> + setSearchFilter(e.target.value)} + style={{ + padding: '0 3%', + }} + placeholder="Filter Values" + /> + {statusObj .sort((a, b) => { const countA = +status[a]; @@ -28,6 +60,13 @@ function CommonCheckBox(props: CommonCheckBoxProps): JSX.Element { } return countA - countB; }) + .filter((_, index) => index < numberOfFilters) + .filter((filter) => { + if (searchFilter.length === 0) { + return true; + } + return filter.includes(searchFilter); + }) .map((e) => ( ))} + + {numberOfFilters && statusObj.length > numberOfFilters && ( + + )} ); } diff --git a/frontend/src/container/Trace/Filters/Panel/PanelBody/Duration/index.tsx b/frontend/src/container/Trace/Filters/Panel/PanelBody/Duration/index.tsx index a2a5d163a1..81bd6e7faa 100644 --- a/frontend/src/container/Trace/Filters/Panel/PanelBody/Duration/index.tsx +++ b/frontend/src/container/Trace/Filters/Panel/PanelBody/Duration/index.tsx @@ -1,11 +1,14 @@ -/* eslint-disable react/no-unstable-nested-components */ -import { Input, Slider } from 'antd'; +import { Slider } from 'antd'; import { SliderRangeProps } from 'antd/lib/slider'; import getFilters from 'api/trace/getFilters'; -import dayjs from 'dayjs'; -import durationPlugin from 'dayjs/plugin/duration'; import useDebouncedFn from 'hooks/useDebouncedFunction'; -import React, { useEffect, useMemo, useRef, useState } from 'react'; +import React, { + useCallback, + useEffect, + useMemo, + useRef, + useState, +} from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { Dispatch } from 'redux'; import { getFilter, updateURL } from 'store/actions/trace/util'; @@ -15,19 +18,8 @@ import { UPDATE_ALL_FILTERS } from 'types/actions/trace'; import { GlobalReducer } from 'types/reducer/globalTime'; import { TraceReducer } from 'types/reducer/trace'; -import { Container, InputContainer, Text } from './styles'; - -dayjs.extend(durationPlugin); - -const getMs = (value: string): string => { - return parseFloat( - dayjs - .duration({ - milliseconds: parseInt(value, 10) / 1000000, - }) - .format('SSS'), - ).toFixed(2); -}; +import { Container, InputComponent, InputContainer, Text } from './styles'; +import { getMs } from './util'; function Duration(): JSX.Element { const { @@ -77,17 +69,18 @@ function Duration(): JSX.Element { preLocalMinDuration.current = parseFloat(minDuration); } - setPreMax(maxDuration); - setPreMin(minDuration); + setPreMax(getMs(maxDuration)); + setPreMin(getMs(minDuration)); }, [getDuration]); - const defaultValue = [parseFloat(preMin), parseFloat(preMax)]; - const updatedUrl = async (min: number, max: number): Promise => { const preSelectedFilter = new Map(selectedFilter); const preUserSelected = new Map(userSelectedFilter); - preSelectedFilter.set('duration', [String(max), String(min)]); + preSelectedFilter.set('duration', [ + String(max * 1000000), + String(min * 1000000), + ]); const response = await getFilters({ end: String(globalTime.maxTime), @@ -137,18 +130,18 @@ function Duration(): JSX.Element { } }; - const onRangeSliderHandler = (number: [number, number]): void => { + const onRangeSliderHandler = (number: [string, string]): void => { const [min, max] = number; - setPreMin(min.toString()); - setPreMax(max.toString()); + setPreMin(min); + setPreMax(max); }; const debouncedFunction = useDebouncedFn( (min, max) => { updatedUrl(min as number, max as number); }, - 500, + 1500, undefined, ); @@ -156,8 +149,8 @@ function Duration(): JSX.Element { event, ) => { const { value } = event.target; - const min = parseFloat(preMin); - const max = parseFloat(value) * 1000000; + const min = preMin; + const max = value; onRangeSliderHandler([min, max]); debouncedFunction(min, max); @@ -167,8 +160,9 @@ function Duration(): JSX.Element { event, ) => { const { value } = event.target; - const min = parseFloat(value) * 1000000; - const max = parseFloat(preMax); + const min = value; + const max = preMax; + onRangeSliderHandler([min, max]); debouncedFunction(min, max); }; @@ -177,45 +171,48 @@ function Duration(): JSX.Element { updatedUrl(min, max); }; + const TipComponent = useCallback((value) => { + if (value === undefined) { + return
; + } + return
{`${getMs(value?.toString())}ms`}
; + }, []); + return (
Min - Max - { - if (value === undefined) { - return
; - } - return
{`${getMs(value?.toString())}ms`}
; - }} + tipFormatter={TipComponent} onChange={([min, max]): void => { - onRangeSliderHandler([min, max]); + onRangeSliderHandler([String(min), String(max)]); }} onAfterChange={onRangeHandler} - value={[parseFloat(preMin), parseFloat(preMax)]} + value={[Number(preMin), Number(preMax)]} />
diff --git a/frontend/src/container/Trace/Filters/Panel/PanelBody/Duration/styles.ts b/frontend/src/container/Trace/Filters/Panel/PanelBody/Duration/styles.ts index d80c0e503d..1cab3f8954 100644 --- a/frontend/src/container/Trace/Filters/Panel/PanelBody/Duration/styles.ts +++ b/frontend/src/container/Trace/Filters/Panel/PanelBody/Duration/styles.ts @@ -1,4 +1,4 @@ -import { Typography } from 'antd'; +import { Input, Typography } from 'antd'; import styled from 'styled-components'; export const DurationText = styled.div` @@ -9,6 +9,19 @@ export const DurationText = styled.div` flex-direction: column; `; +export const InputComponent = styled(Input)` + input::-webkit-outer-spin-button, + input::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; + } + + /* Firefox */ + input[type='number'] { + -moz-appearance: textfield; + } +`; + export const InputContainer = styled.div` width: 100%; margin-top: 0.5rem; diff --git a/frontend/src/container/Trace/Filters/Panel/PanelBody/Duration/util.ts b/frontend/src/container/Trace/Filters/Panel/PanelBody/Duration/util.ts new file mode 100644 index 0000000000..2a6bcf9586 --- /dev/null +++ b/frontend/src/container/Trace/Filters/Panel/PanelBody/Duration/util.ts @@ -0,0 +1,13 @@ +import dayjs from 'dayjs'; +import durationPlugin from 'dayjs/plugin/duration'; + +dayjs.extend(durationPlugin); + +export const getMs = (value: string): string => + parseFloat( + dayjs + .duration({ + milliseconds: parseInt(value, 10) / 1000000, + }) + .format('SSS'), + ).toFixed(2); diff --git a/frontend/src/store/reducers/trace.ts b/frontend/src/store/reducers/trace.ts index b99ee7dd3a..4023d375ca 100644 --- a/frontend/src/store/reducers/trace.ts +++ b/frontend/src/store/reducers/trace.ts @@ -11,6 +11,7 @@ import { UPDATE_SELECTED_TAGS, UPDATE_SPAN_ORDER, UPDATE_SPAN_ORDER_PARAMS, + UPDATE_SPAN_UPDATE_FILTER_DISPLAY_VALUE, UPDATE_SPANS_AGGREGATE, UPDATE_SPANS_AGGREGATE_PAGE_NUMBER, UPDATE_SPANS_AGGREGATE_PAGE_SIZE, @@ -23,6 +24,8 @@ import { } from 'types/actions/trace'; import { TraceFilterEnum, TraceReducer } from 'types/reducer/trace'; +export const INITIAL_FILTER_VALUE = 4; + const initialValue: TraceReducer = { filter: new Map(), filterToFetchData: ['duration', 'status', 'serviceName'], @@ -53,6 +56,17 @@ const initialValue: TraceReducer = { loading: true, payload: { items: {} }, }, + filterDisplayValue: new Map([ + ['component', INITIAL_FILTER_VALUE], + ['duration', INITIAL_FILTER_VALUE], + ['httpCode', INITIAL_FILTER_VALUE], + ['httpHost', INITIAL_FILTER_VALUE], + ['httpMethod', INITIAL_FILTER_VALUE], + ['httpUrl', INITIAL_FILTER_VALUE], + ['operation', INITIAL_FILTER_VALUE], + ['serviceName', INITIAL_FILTER_VALUE], + ['status', INITIAL_FILTER_VALUE], + ]), }; const traceReducer = ( @@ -251,6 +265,13 @@ const traceReducer = ( }; } + case UPDATE_SPAN_UPDATE_FILTER_DISPLAY_VALUE: { + return { + ...state, + filterDisplayValue: action.payload, + }; + } + default: return state; } diff --git a/frontend/src/types/actions/trace.ts b/frontend/src/types/actions/trace.ts index da97d05129..f043926142 100644 --- a/frontend/src/types/actions/trace.ts +++ b/frontend/src/types/actions/trace.ts @@ -31,6 +31,8 @@ export const UPDATE_SPANS_AGGREGATE_PAGE_NUMBER = export const UPDATE_SPANS_AGGREGATE_PAGE_SIZE = 'UPDATE_SPANS_AGGREGATE_PAGE_SIZE'; export const UPDATE_SPAN_ORDER_PARAMS = 'UPDATE_SPAN_ORDER_PARAMS'; +export const UPDATE_SPAN_UPDATE_FILTER_DISPLAY_VALUE = + 'UPDATE_SPAN_UPDATE_FILTER_DISPLAY_VALUE'; export interface UpdateFilter { type: typeof UPDATE_TRACE_FILTER; @@ -187,6 +189,11 @@ export interface UpdateSpanParams { }; } +export interface UpdateTraceFilterDisplayValue { + type: typeof UPDATE_SPAN_UPDATE_FILTER_DISPLAY_VALUE; + payload: TraceReducer['filterDisplayValue']; +} + export type TraceActions = | UpdateFilter | GetTraceFilter @@ -208,4 +215,5 @@ export type TraceActions = | UpdateSpanOrder | UpdateSpansAggregatePageNumber | UpdateSpanSize - | UpdateSpanParams; + | UpdateSpanParams + | UpdateTraceFilterDisplayValue; diff --git a/frontend/src/types/reducer/trace.ts b/frontend/src/types/reducer/trace.ts index babeb344c6..fc1c08f4fc 100644 --- a/frontend/src/types/reducer/trace.ts +++ b/frontend/src/types/reducer/trace.ts @@ -32,6 +32,7 @@ export interface TraceReducer { payload: PayloadProps; }; yAxisUnit: string | undefined; + filterDisplayValue: Map; } interface SpansAggregateData {