bug: Trace filter page fixes (#846)

* order is added in the url
* local min max duration is kept in memory to show min and max even after filtering by duration
* checkbox ordering does not change when the user selects or un-selects a checkbox
This commit is contained in:
palash-signoz 2022-04-05 13:23:08 +05:30 committed by GitHub
parent 147ed9f24b
commit 3f2a4d6eac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 308 additions and 167 deletions

View File

@ -93,11 +93,15 @@ function CheckBoxComponent(props: CheckBoxProps): JSX.Element {
if (response.statusCode === 200) {
const updatedFilter = getFilter(response.payload);
updatedFilter.forEach((value, key) => {
if (key !== 'duration' && name !== key) {
preUserSelectedMap.set(key, Object.keys(value));
}
});
// updatedFilter.forEach((value, key) => {
// if (key !== 'duration' && name !== key) {
// preUserSelectedMap.set(key, Object.keys(value));
// }
// if (key === 'duration') {
// newSelectedMap.set('duration', [value.maxDuration, value.minDuration]);
// }
// });
updatedFilter.set(name, {
[`${keyValue}`]: '-1',
@ -115,6 +119,7 @@ function CheckBoxComponent(props: CheckBoxProps): JSX.Element {
selectedFilter: newSelectedMap,
userSelected: preUserSelectedMap,
isFilterExclude: preIsFilterExclude,
order: spansAggregate.order,
},
});
@ -128,6 +133,7 @@ function CheckBoxComponent(props: CheckBoxProps): JSX.Element {
updatedFilter,
preIsFilterExclude,
preUserSelectedMap,
spansAggregate.order,
);
} else {
setIsLoading(false);

View File

@ -18,16 +18,26 @@ function CommonCheckBox(props: CommonCheckBoxProps): JSX.Element {
return (
<>
{statusObj.map((e) => (
<CheckBoxComponent
key={e}
{...{
name,
keyValue: e,
value: status[e],
}}
/>
))}
{statusObj
.sort((a, b) => {
const countA = +status[a];
const countB = +status[b];
if (countA === countB) {
return a.length - b.length;
}
return countA - countB;
})
.map((e) => (
<CheckBoxComponent
key={e}
{...{
name,
keyValue: e,
value: status[e],
}}
/>
))}
</>
);
}

View File

@ -5,7 +5,7 @@ import getFilters from 'api/trace/getFilters';
import dayjs from 'dayjs';
import durationPlugin from 'dayjs/plugin/duration';
import useDebouncedFn from 'hooks/useDebouncedFunction';
import React, { useState } from 'react';
import React, { useEffect, useMemo, useRef, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Dispatch } from 'redux';
import { getFilter, updateURL } from 'store/actions/trace/util';
@ -20,11 +20,13 @@ import { Container, InputContainer, Text } from './styles';
dayjs.extend(durationPlugin);
const getMs = (value: string): string => {
return dayjs
.duration({
milliseconds: parseInt(value, 10) / 1000000,
})
.format('SSS');
return parseFloat(
dayjs
.duration({
milliseconds: parseInt(value, 10) / 1000000,
})
.format('SSS'),
).toFixed(2);
};
function Duration(): JSX.Element {
@ -43,9 +45,10 @@ function Duration(): JSX.Element {
(state) => state.globalTime,
);
const getDuration = ():
| { maxDuration: string; minDuration: string }
| Record<string, string> => {
const preLocalMaxDuration = useRef<number>();
const preLocalMinDuration = useRef<number>();
const getDuration = useMemo(() => {
const selectedDuration = selectedFilter.get('duration');
if (selectedDuration) {
@ -56,17 +59,29 @@ function Duration(): JSX.Element {
}
return filter.get('duration') || {};
};
}, [selectedFilter, filter]);
const duration = getDuration();
const [preMax, setPreMax] = useState<string>('');
const [preMin, setPreMin] = useState<string>('');
const maxDuration = duration.maxDuration || '0';
const minDuration = duration.minDuration || '0';
useEffect(() => {
const duration = getDuration || {};
const [localMax, setLocalMax] = useState<string>(maxDuration);
const [localMin, setLocalMin] = useState<string>(minDuration);
const maxDuration = duration.maxDuration || '0';
const minDuration = duration.minDuration || '0';
const defaultValue = [parseFloat(minDuration), parseFloat(maxDuration)];
if (preLocalMaxDuration.current === undefined) {
preLocalMaxDuration.current = parseFloat(maxDuration);
}
if (preLocalMinDuration.current === undefined) {
preLocalMinDuration.current = parseFloat(minDuration);
}
setPreMax(maxDuration);
setPreMin(minDuration);
}, [getDuration]);
const defaultValue = [parseFloat(preMin), parseFloat(preMax)];
const updatedUrl = async (min: number, max: number): Promise<void> => {
const preSelectedFilter = new Map(selectedFilter);
@ -74,7 +89,6 @@ function Duration(): JSX.Element {
preSelectedFilter.set('duration', [String(max), String(min)]);
console.log('on the update Url');
const response = await getFilters({
end: String(globalTime.maxTime),
getFilters: filterToFetchData,
@ -87,8 +101,9 @@ function Duration(): JSX.Element {
const preFilter = getFilter(response.payload);
preFilter.forEach((value, key) => {
if (key !== 'duration') {
preUserSelected.set(key, Object.keys(value));
const values = Object.keys(value);
if (key !== 'duration' && values.length) {
preUserSelected.set(key, values);
}
});
@ -102,6 +117,7 @@ function Duration(): JSX.Element {
selectedTags,
userSelected: preUserSelected,
isFilterExclude,
order: spansAggregate.order,
},
});
@ -113,6 +129,7 @@ function Duration(): JSX.Element {
preFilter,
isFilterExclude,
userSelectedFilter,
spansAggregate.order,
);
}
};
@ -120,13 +137,12 @@ function Duration(): JSX.Element {
const onRangeSliderHandler = (number: [number, number]): void => {
const [min, max] = number;
setLocalMin(min.toString());
setLocalMax(max.toString());
setPreMin(min.toString());
setPreMax(max.toString());
};
const debouncedFunction = useDebouncedFn(
(min, max) => {
console.log('debounce function');
updatedUrl(min as number, max as number);
},
500,
@ -137,11 +153,9 @@ function Duration(): JSX.Element {
event,
) => {
const { value } = event.target;
const min = parseFloat(localMin);
const min = parseFloat(preMin);
const max = parseFloat(value) * 1000000;
console.log('on change in max');
onRangeSliderHandler([min, max]);
debouncedFunction(min, max);
};
@ -151,9 +165,8 @@ function Duration(): JSX.Element {
) => {
const { value } = event.target;
const min = parseFloat(value) * 1000000;
const max = parseFloat(localMax);
const max = parseFloat(preMax);
onRangeSliderHandler([min, max]);
console.log('on change in min');
debouncedFunction(min, max);
};
@ -170,7 +183,7 @@ function Duration(): JSX.Element {
<Input
addonAfter="ms"
onChange={onChangeMinHandler}
value={getMs(localMin)}
value={getMs(preMin)}
/>
<InputContainer>
@ -179,27 +192,27 @@ function Duration(): JSX.Element {
<Input
addonAfter="ms"
onChange={onChangeMaxHandler}
value={getMs(localMax)}
value={getMs(preMax)}
/>
</Container>
<Container>
<Slider
defaultValue={[defaultValue[0], defaultValue[1]]}
min={parseFloat((filter.get('duration') || {}).minDuration)}
max={parseFloat((filter.get('duration') || {}).maxDuration)}
min={parseFloat((preLocalMinDuration.current || 0).toString())}
max={parseFloat((preLocalMaxDuration.current || 0).toString())}
range
tipFormatter={(value): JSX.Element => {
if (value === undefined) {
return <div />;
}
return <div>{`${getMs(value.toString())}ms`}</div>;
return <div>{`${getMs(value?.toString())}ms`}</div>;
}}
onChange={([min, max]): void => {
onRangeSliderHandler([min, max]);
}}
onAfterChange={onRangeHandler}
value={[parseFloat(localMin), parseFloat(localMax)]}
value={[parseFloat(preMin), parseFloat(preMax)]}
/>
</Container>
</div>

View File

@ -21,7 +21,7 @@ import {
ButtonContainer,
Container,
IconContainer,
TextCotainer,
TextContainer,
} from './styles';
const { Text } = Typography;
@ -64,16 +64,7 @@ function PanelHeading(props: PanelHeadingProps): JSX.Element {
const getprepdatedSelectedFilter = new Map(selectedFilter);
const getPreUserSelected = new Map(userSelectedFilter);
if (!isDefaultOpen) {
updatedFilterData = [PanelName];
} else {
// removing the selected filter
updatedFilterData = [
...filterToFetchData.filter((name) => name !== PanelName),
];
getprepdatedSelectedFilter.delete(PanelName);
getPreUserSelected.delete(PanelName);
}
updatedFilterData = [PanelName];
const response = await getFilters({
end: String(global.maxTime),
@ -86,33 +77,14 @@ function PanelHeading(props: PanelHeadingProps): JSX.Element {
if (response.statusCode === 200) {
const updatedFilter = getFilter(response.payload);
// is closed
if (!isDefaultOpen) {
// getprepdatedSelectedFilter.set(
// props.name,
// Object.keys(updatedFilter.get(props.name) || {}),
// );
if (!getPreUserSelected.has(PanelName)) {
getPreUserSelected.set(
PanelName,
Object.keys(updatedFilter.get(PanelName) || {}),
Object.keys(updatedFilter.get(PanelName) || []),
);
updatedFilterData = [...filterToFetchData, PanelName];
}
// now append the non prop.name trace filter enum over the list
// selectedFilter.forEach((value, key) => {
// if (key !== props.name) {
// getprepdatedSelectedFilter.set(key, value);
// }
// });
getPreUserSelected.forEach((value, key) => {
if (key !== PanelName) {
getPreUserSelected.set(key, value);
}
});
updatedFilterData = [...filterToFetchData, PanelName];
filter.forEach((value, key) => {
if (key !== PanelName) {
updatedFilter.set(key, value);
@ -129,6 +101,7 @@ function PanelHeading(props: PanelHeadingProps): JSX.Element {
selectedTags,
userSelected: getPreUserSelected,
isFilterExclude,
order: spansAggregate.order,
},
});
@ -140,6 +113,7 @@ function PanelHeading(props: PanelHeadingProps): JSX.Element {
updatedFilter,
isFilterExclude,
getPreUserSelected,
spansAggregate.order,
);
} else {
notification.error({
@ -155,6 +129,44 @@ function PanelHeading(props: PanelHeadingProps): JSX.Element {
}
};
/**
* @description this function removes the selected filter
*/
const onCloseHandler = (): void => {
const preSelectedFilter = new Map(selectedFilter);
// removing the filter from filter to fetch the data
const preFilterToFetchTheData = [
...filterToFetchData.filter((name) => name !== PanelName),
];
preSelectedFilter.delete(PanelName);
dispatch({
type: UPDATE_ALL_FILTERS,
payload: {
current: spansAggregate.currentPage,
filter,
filterToFetchData: preFilterToFetchTheData,
selectedFilter: preSelectedFilter,
selectedTags,
userSelected: userSelectedFilter,
isFilterExclude,
order: spansAggregate.order,
},
});
updateURL(
preSelectedFilter,
preFilterToFetchTheData,
spansAggregate.currentPage,
selectedTags,
filter,
isFilterExclude,
userSelectedFilter,
spansAggregate.order,
);
};
const onClearAllHandler = async (): Promise<void> => {
try {
setIsLoading(true);
@ -177,18 +189,19 @@ function PanelHeading(props: PanelHeadingProps): JSX.Element {
});
if (response.statusCode === 200 && response.payload) {
const getUpatedFilter = getFilter(response.payload);
const getUpdatedFilter = getFilter(response.payload);
dispatch({
type: UPDATE_ALL_FILTERS,
payload: {
current: spansAggregate.currentPage,
filter: getUpatedFilter,
filter: getUpdatedFilter,
filterToFetchData,
selectedFilter: updatedFilter,
selectedTags,
userSelected: preUserSelected,
isFilterExclude: postIsFilterExclude,
order: spansAggregate.order,
},
});
@ -197,9 +210,10 @@ function PanelHeading(props: PanelHeadingProps): JSX.Element {
filterToFetchData,
spansAggregate.currentPage,
selectedTags,
getUpatedFilter,
getUpdatedFilter,
postIsFilterExclude,
preUserSelected,
spansAggregate.order,
);
} else {
notification.error({
@ -280,7 +294,7 @@ function PanelHeading(props: PanelHeadingProps): JSX.Element {
aria-disabled={filterLoading || isLoading}
aria-expanded={IsPanelOpen}
>
<TextCotainer onClick={onExpandHandler}>
<TextContainer onClick={isDefaultOpen ? onCloseHandler : onExpandHandler}>
<IconContainer>
{!IsPanelOpen ? <RightOutlined /> : <DownOutlined />}
</IconContainer>
@ -288,7 +302,7 @@ function PanelHeading(props: PanelHeadingProps): JSX.Element {
<Text style={{ textTransform: 'capitalize' }} ellipsis>
{AllPanelHeading.find((e) => e.key === PanelName)?.displayValue || ''}
</Text>
</TextCotainer>
</TextContainer>
{PanelName !== 'duration' && (
<ButtonContainer>

View File

@ -30,7 +30,7 @@ export const IconContainer = styled.div`
}
`;
export const TextCotainer = styled.div`
export const TextContainer = styled.div`
&&& {
display: flex;
cursor: pointer;

View File

@ -5,7 +5,7 @@ import { connect, useSelector } from 'react-redux';
import { bindActionCreators } from 'redux';
import { ThunkDispatch } from 'redux-thunk';
import { UpdateTagIsError } from 'store/actions/trace/updateIsTagsError';
import { UpdateTagVisiblity } from 'store/actions/trace/updateTagPanelVisiblity';
import { UpdateTagVisibility } from 'store/actions/trace/updateTagPanelVisiblity';
import { AppState } from 'store/reducers';
import AppActions from 'types/actions';
import { TraceReducer } from 'types/reducer/trace';
@ -27,7 +27,7 @@ const { Paragraph } = Typography;
function AllTags({
updateTagIsError,
onChangeHandler,
updateTagVisiblity,
updateTagVisibility,
updateFilters,
}: AllTagsProps): JSX.Element {
const traces = useSelector<AppState, TraceReducer>((state) => state.traces);
@ -63,7 +63,7 @@ function AllTags({
onChangeHandler(parsedQuery.payload);
updateFilters(localSelectedTags);
updateTagIsError(false);
updateTagVisiblity(false);
updateTagVisibility(false);
}
};
@ -75,7 +75,7 @@ function AllTags({
return (
<ErrorContainer>
<Paragraph style={{ color: '#E89A3C' }}>
Unrecognised query format. Please reset your query by clicking `X` in the
Unrecognized query format. Please reset your query by clicking `X` in the
search bar above.
</Paragraph>
@ -131,14 +131,14 @@ function AllTags({
interface DispatchProps {
updateTagIsError: (value: boolean) => void;
updateTagVisiblity: (value: boolean) => void;
updateTagVisibility: (value: boolean) => void;
}
const mapDispatchToProps = (
dispatch: ThunkDispatch<unknown, unknown, AppActions>,
): DispatchProps => ({
updateTagIsError: bindActionCreators(UpdateTagIsError, dispatch),
updateTagVisiblity: bindActionCreators(UpdateTagVisiblity, dispatch),
updateTagVisibility: bindActionCreators(UpdateTagVisibility, dispatch),
});
interface AllTagsProps extends DispatchProps {

View File

@ -6,7 +6,7 @@ import { connect, useDispatch, useSelector } from 'react-redux';
import { bindActionCreators, Dispatch } from 'redux';
import { ThunkDispatch } from 'redux-thunk';
import { UpdateTagIsError } from 'store/actions/trace/updateIsTagsError';
import { UpdateTagVisiblity } from 'store/actions/trace/updateTagPanelVisiblity';
import { UpdateTagVisibility } from 'store/actions/trace/updateTagPanelVisiblity';
import { updateURL } from 'store/actions/trace/util';
import { AppState } from 'store/reducers';
import AppActions from 'types/actions';
@ -18,7 +18,7 @@ import { Container, SearchComponent } from './styles';
import { parseQueryToTags, parseTagsToQuery } from './util';
function Search({
updateTagVisiblity,
updateTagVisibility,
updateTagIsError,
}: SearchProps): JSX.Element {
const traces = useSelector<AppState, TraceReducer>((state) => state.traces);
@ -66,7 +66,7 @@ function Search({
!(e.ariaSelected === 'true') &&
traces.isTagModalOpen
) {
updateTagVisiblity(false);
updateTagVisibility(false);
}
});
@ -75,7 +75,7 @@ function Search({
};
const setIsTagsModalHandler = (value: boolean): void => {
updateTagVisiblity(value);
updateTagVisibility(value);
};
const onFocusHandler: React.FocusEventHandler<HTMLInputElement> = (e) => {
@ -96,6 +96,7 @@ function Search({
selectedFilter: traces.selectedFilter,
userSelected: traces.userSelectedFilter,
isFilterExclude: traces.isFilterExclude,
order: traces.spansAggregate.order,
},
});
@ -107,6 +108,7 @@ function Search({
traces.filter,
traces.isFilterExclude,
traces.userSelectedFilter,
traces.spansAggregate.order,
);
};
@ -124,7 +126,7 @@ function Search({
enterButton={<CaretRightFilled />}
onSearch={(string): void => {
if (string.length === 0) {
updateTagVisiblity(false);
updateTagVisibility(false);
updateFilters([]);
return;
}
@ -135,7 +137,7 @@ function Search({
updateTagIsError(true);
} else {
updateTagIsError(false);
updateTagVisiblity(false);
updateTagVisibility(false);
updateFilters(payload);
}
}}
@ -150,14 +152,14 @@ function Search({
}
interface DispatchProps {
updateTagVisiblity: (value: boolean) => void;
updateTagVisibility: (value: boolean) => void;
updateTagIsError: (value: boolean) => void;
}
const mapDispatchToProps = (
dispatch: ThunkDispatch<unknown, unknown, AppActions>,
): DispatchProps => ({
updateTagVisiblity: bindActionCreators(UpdateTagVisiblity, dispatch),
updateTagVisibility: bindActionCreators(UpdateTagVisibility, dispatch),
updateTagIsError: bindActionCreators(UpdateTagIsError, dispatch),
});

View File

@ -4,34 +4,32 @@ import ROUTES from 'constants/routes';
import dayjs from 'dayjs';
import duration from 'dayjs/plugin/duration';
import React from 'react';
import { connect, useSelector } from 'react-redux';
import { useDispatch, useSelector } from 'react-redux';
import { Link } from 'react-router-dom';
import { bindActionCreators } from 'redux';
import { ThunkDispatch } from 'redux-thunk';
import {
GetSpansAggregate,
GetSpansAggregateProps,
} from 'store/actions/trace/getInitialSpansAggregate';
import { Dispatch } from 'redux';
import { updateURL } from 'store/actions/trace/util';
import { AppState } from 'store/reducers';
import AppActions from 'types/actions';
import { GlobalReducer } from 'types/reducer/globalTime';
import { UPDATE_SPAN_ORDER } from 'types/actions/trace';
import { TraceReducer } from 'types/reducer/trace';
dayjs.extend(duration);
function TraceTable({ getSpansAggregate }: TraceProps): JSX.Element {
function TraceTable(): JSX.Element {
const {
spansAggregate,
selectedFilter,
selectedTags,
filterLoading,
userSelectedFilter,
filter,
isFilterExclude,
filterToFetchData,
} = useSelector<AppState, TraceReducer>((state) => state.traces);
const globalTime = useSelector<AppState, GlobalReducer>(
(state) => state.globalTime,
);
const dispatch = useDispatch<Dispatch<AppActions>>();
const { loading, total } = spansAggregate;
const { loading, total, order: spansAggregateOrder } = spansAggregate;
type TableType = FlatArray<TraceReducer['spansAggregate']['data'], 1>;
@ -101,7 +99,8 @@ function TraceTable({ getSpansAggregate }: TraceProps): JSX.Element {
<Typography>
{`${dayjs
.duration({ milliseconds: value / 1000000 })
.asMilliseconds()} ms`}
.asMilliseconds()
.toFixed(2)} ms`}
</Typography>
</Link>
),
@ -126,17 +125,27 @@ function TraceTable({ getSpansAggregate }: TraceProps): JSX.Element {
sort,
) => {
if (!Array.isArray(sort)) {
const { order = 'ascend' } = sort;
const { order = spansAggregateOrder } = sort;
if (props.current && props.pageSize) {
getSpansAggregate({
maxTime: globalTime.maxTime,
minTime: globalTime.minTime,
selectedFilter,
current: props.current,
pageSize: props.pageSize,
selectedTags,
order: order === 'ascend' ? 'ascending' : 'descending',
const spanOrder = order || spansAggregateOrder;
dispatch({
type: UPDATE_SPAN_ORDER,
payload: {
order: spanOrder,
},
});
updateURL(
selectedFilter,
filterToFetchData,
props.current,
selectedTags,
filter,
isFilterExclude,
userSelectedFilter,
spanOrder,
);
}
}
};
@ -147,7 +156,7 @@ function TraceTable({ getSpansAggregate }: TraceProps): JSX.Element {
dataSource={spansAggregate.data}
loading={loading || filterLoading}
columns={columns}
rowKey="timestamp"
rowKey={(record): string => `${record.traceID}-${record.spanID}`}
style={{
cursor: 'pointer',
}}
@ -158,20 +167,9 @@ function TraceTable({ getSpansAggregate }: TraceProps): JSX.Element {
position: ['bottomLeft'],
total,
}}
sortDirections={['ascend', 'descend']}
/>
);
}
interface DispatchProps {
getSpansAggregate: (props: GetSpansAggregateProps) => void;
}
const mapDispatchToProps = (
dispatch: ThunkDispatch<unknown, unknown, AppActions>,
): DispatchProps => ({
getSpansAggregate: bindActionCreators(GetSpansAggregate, dispatch),
});
type TraceProps = DispatchProps;
export default connect(null, mapDispatchToProps)(TraceTable);
export default TraceTable;

View File

@ -63,7 +63,7 @@ function Trace({
current: spansAggregate.currentPage,
pageSize: spansAggregate.pageSize,
selectedTags,
order: 'ascending',
order: spansAggregate.order === 'ascend' ? 'ascending' : 'descending',
});
}, [
selectedTags,
@ -73,6 +73,7 @@ function Trace({
getSpansAggregate,
spansAggregate.currentPage,
spansAggregate.pageSize,
spansAggregate.order,
]);
useEffect(() => {
@ -93,8 +94,8 @@ function Trace({
selectedTags,
maxTime,
minTime,
isFilterExclude,
getSpans,
isFilterExclude,
]);
useEffect(() => {

View File

@ -18,6 +18,7 @@ import {
parseIsSkippedSelection,
parseQueryIntoCurrent,
parseQueryIntoFilter,
parseQueryIntoOrder,
parseQueryIntoSelectedTags,
parseSelectedFilter,
} from './util';
@ -66,6 +67,11 @@ export const GetInitialTraceFilter = (
traces.spansAggregate.currentPage,
);
const parsedQueryOrder = parseQueryIntoOrder(
query,
traces.spansAggregate.order,
);
const isSelectionSkipped = parseIsSkippedSelection(query);
const parsedSelectedTags = parseQueryIntoSelectedTags(
@ -148,6 +154,7 @@ export const GetInitialTraceFilter = (
selectedTags: parsedSelectedTags.currentValue,
userSelected: getUserSelected.currentValue,
isFilterExclude: getIsFilterExcluded.currentValue,
order: parsedQueryOrder.currentValue,
},
});
} else {

View File

@ -3,11 +3,13 @@ import getSpansAggregate from 'api/trace/getSpansAggregate';
import { Dispatch, Store } from 'redux';
import { AppState } from 'store/reducers';
import AppActions from 'types/actions';
import { UPDATE_SPANS_AGGREEGATE } from 'types/actions/trace';
import { UPDATE_SPANS_AGGREGATE } from 'types/actions/trace';
import { Props as GetSpanAggregateProps } from 'types/api/trace/getSpanAggregate';
import { GlobalReducer } from 'types/reducer/globalTime';
import { TraceReducer } from 'types/reducer/trace';
import { updateURL } from './util';
export const GetSpansAggregate = (
props: GetSpansAggregateProps,
): ((
@ -29,10 +31,12 @@ export const GetSpansAggregate = (
return;
}
const order = props.order === 'ascending' ? 'ascend' : 'descend';
try {
// triggering loading
dispatch({
type: UPDATE_SPANS_AGGREEGATE,
type: UPDATE_SPANS_AGGREGATE,
payload: {
spansAggregate: {
currentPage: props.current,
@ -41,6 +45,7 @@ export const GetSpansAggregate = (
error: false,
total: spansAggregate.total,
pageSize: props.pageSize,
order,
},
},
});
@ -53,12 +58,12 @@ export const GetSpansAggregate = (
offset: props.current * props.pageSize - props.pageSize,
selectedTags: props.selectedTags,
isFilterExclude: traces.isFilterExclude,
order: props.order,
order,
});
if (response.statusCode === 200) {
dispatch({
type: UPDATE_SPANS_AGGREEGATE,
type: UPDATE_SPANS_AGGREGATE,
payload: {
spansAggregate: {
currentPage: props.current,
@ -67,16 +72,28 @@ export const GetSpansAggregate = (
error: false,
total: response.payload.totalSpans,
pageSize: props.pageSize,
order,
},
},
});
updateURL(
traces.selectedFilter,
traces.filterToFetchData,
props.current,
traces.selectedTags,
traces.filter,
traces.isFilterExclude,
traces.userSelectedFilter,
order,
);
} else {
notification.error({
message: response.error || 'Something went wrong',
});
dispatch({
type: UPDATE_SPANS_AGGREEGATE,
type: UPDATE_SPANS_AGGREGATE,
payload: {
spansAggregate: {
currentPage: props.current,
@ -85,13 +102,14 @@ export const GetSpansAggregate = (
error: true,
total: spansAggregate.total,
pageSize: props.pageSize,
order,
},
},
});
}
} catch (error) {
dispatch({
type: UPDATE_SPANS_AGGREEGATE,
type: UPDATE_SPANS_AGGREGATE,
payload: {
spansAggregate: {
currentPage: props.current,
@ -100,6 +118,7 @@ export const GetSpansAggregate = (
error: true,
total: spansAggregate.total,
pageSize: props.pageSize,
order,
},
},
});

View File

@ -1,4 +1,3 @@
export * from './current';
export * from './filter';
export * from './filterToFetchData';
export * from './isFilterExclude';
@ -6,3 +5,5 @@ export * from './minMaxTime';
export * from './selectedFilter';
export * from './selectedTags';
export * from './skippedSelected';
export * from './spanAggregateCurrentPage';
export * from './spanAggregateOrder';

View File

@ -10,7 +10,7 @@ export const parseQueryIntoCurrent = (
let current = 1;
const selected = url.get('current');
const selected = url.get('spanAggregateCurrentPage');
if (selected) {
try {

View File

@ -0,0 +1,39 @@
import { TraceReducer } from 'types/reducer/trace';
import { ParsedUrl } from '../util';
export const parseQueryIntoOrder = (
query: string,
stateCurrent: TraceReducer['spansAggregate']['order'],
): ParsedUrl<TraceReducer['spansAggregate']['order']> => {
const url = new URLSearchParams(query);
let current = 'ascend';
const selected = url.get('spanAggregateOrder');
if (selected) {
try {
const parsedValue = selected;
if (parsedValue && typeof parsedValue === 'string') {
current = parsedValue;
}
} catch (error) {
console.log(error);
console.log('error while parsing json');
}
}
if (selected) {
return {
currentValue: current,
urlValue: current,
};
}
return {
currentValue: stateCurrent,
urlValue: current,
};
};

View File

@ -47,6 +47,7 @@ export const SelectedTraceFilter = (props: {
traces.filter,
traces.isFilterExclude,
traces.userSelectedFilter,
traces.spansAggregate.order,
);
};
};

View File

@ -1,14 +1,14 @@
import { Dispatch } from 'redux';
import AppActions from 'types/actions';
import { UPDATE_TAG_MODAL_VISIBLITY } from 'types/actions/trace';
import { UPDATE_TAG_MODAL_VISIBILITY } from 'types/actions/trace';
import { TraceReducer } from 'types/reducer/trace';
export const UpdateTagVisiblity = (
export const UpdateTagVisibility = (
isTagModalOpen: TraceReducer['isTagModalOpen'],
): ((dispatch: Dispatch<AppActions>) => void) => {
return (dispatch): void => {
dispatch({
type: UPDATE_TAG_MODAL_VISIBLITY,
type: UPDATE_TAG_MODAL_VISIBILITY,
payload: {
isTagModalOpen,
},

View File

@ -18,11 +18,12 @@ export function isTraceFilterEnum(
export const updateURL = (
selectedFilter: TraceReducer['selectedFilter'],
filterToFetchData: TraceReducer['filterToFetchData'],
current: TraceReducer['spansAggregate']['total'],
spanAggregateCurrentPage: TraceReducer['spansAggregate']['currentPage'],
selectedTags: TraceReducer['selectedTags'],
filter: TraceReducer['filter'],
isFilterExclude: TraceReducer['isFilterExclude'],
userSelectedFilter: TraceReducer['userSelectedFilter'],
spanAggregateOrder: TraceReducer['spansAggregate']['order'],
): void => {
const search = new URLSearchParams(window.location.search);
const preResult: { key: string; value: string }[] = [];
@ -30,11 +31,12 @@ export const updateURL = (
const keyToSkip = [
'selected',
'filterToFetchData',
'current',
'selectedTags',
'filter',
'isFilterExclude',
'userSelectedFilter',
'spanAggregateCurrentPage',
'spanAggregateOrder',
];
search.forEach((value, key) => {
@ -51,7 +53,7 @@ export const updateURL = (
Object.fromEntries(selectedFilter),
)}&filterToFetchData=${JSON.stringify(
filterToFetchData,
)}&current=${current}&selectedTags=${JSON.stringify(
)}&spanAggregateCurrentPage=${spanAggregateCurrentPage}&selectedTags=${JSON.stringify(
selectedTags,
)}&filter=${JSON.stringify(Object.fromEntries(filter))}&${preResult
.map((e) => `${e.key}=${e.value}`)
@ -59,7 +61,7 @@ export const updateURL = (
Object.fromEntries(isFilterExclude),
)}&userSelectedFilter=${JSON.stringify(
Object.fromEntries(userSelectedFilter),
)}`,
)}&spanAggregateCurrentPage=${spanAggregateCurrentPage}&spanAggregateOrder=${spanAggregateOrder}`,
);
};

View File

@ -9,8 +9,9 @@ import {
UPDATE_SELECTED_FUNCTION,
UPDATE_SELECTED_GROUP_BY,
UPDATE_SELECTED_TAGS,
UPDATE_SPANS_AGGREEGATE,
UPDATE_TAG_MODAL_VISIBLITY,
UPDATE_SPAN_ORDER,
UPDATE_SPANS_AGGREGATE,
UPDATE_TAG_MODAL_VISIBILITY,
UPDATE_TRACE_FILTER,
UPDATE_TRACE_FILTER_LOADING,
UPDATE_TRACE_GRAPH_ERROR,
@ -37,6 +38,7 @@ const initialValue: TraceReducer = {
error: false,
total: 0,
pageSize: 10,
order: 'ascend',
},
selectedGroupBy: '',
selectedFunction: 'count',
@ -71,6 +73,7 @@ const traceReducer = (
selectedTags,
userSelected,
isFilterExclude,
order,
} = payload;
return {
@ -84,6 +87,7 @@ const traceReducer = (
spansAggregate: {
...state.spansAggregate,
currentPage: current,
order,
},
};
}
@ -115,14 +119,14 @@ const traceReducer = (
};
}
case UPDATE_SPANS_AGGREEGATE: {
case UPDATE_SPANS_AGGREGATE: {
return {
...state,
spansAggregate: action.payload.spansAggregate,
};
}
case UPDATE_TAG_MODAL_VISIBLITY: {
case UPDATE_TAG_MODAL_VISIBILITY: {
return {
...state,
isTagModalOpen: action.payload.isTagModalOpen,
@ -199,6 +203,16 @@ const traceReducer = (
};
}
case UPDATE_SPAN_ORDER: {
return {
...state,
spansAggregate: {
...state.spansAggregate,
order: action.payload.order,
},
};
}
default:
return state;
}

View File

@ -7,9 +7,9 @@ export const UPDATE_TRACE_FILTER_LOADING = 'UPDATE_TRACE_FILTER_LOADING';
export const SELECT_TRACE_FILTER = 'SELECT_TRACE_FILTER';
export const UPDATE_ALL_FILTERS = 'UPDATE_ALL_FILTERS';
export const UPDATE_SELECTED_TAGS = 'UPDATE_SELECTED_TAGS';
export const UPDATE_TAG_MODAL_VISIBLITY = 'UPDATE_TAG_MODAL_VISIBLITY';
export const UPDATE_TAG_MODAL_VISIBILITY = 'UPDATE_TAG_MODAL_VISIBILITY';
export const UPDATE_SPANS_AGGREEGATE = 'UPDATE_SPANS_AGGREEGATE';
export const UPDATE_SPANS_AGGREGATE = 'UPDATE_SPANS_AGGREGATE';
export const UPDATE_IS_TAG_ERROR = 'UPDATE_IS_TAG_ERROR';
@ -25,6 +25,8 @@ export const UPDATE_FILTER_RESPONSE_SELECTED =
'UPDATE_FILTER_RESPONSE_SELECTED';
export const UPDATE_FILTER_EXCLUDE = 'UPDATE_FILTER_EXCLUDE';
export const UPDATE_SPAN_ORDER = 'UPDATE_SPAN_ORDER';
export interface UpdateFilter {
type: typeof UPDATE_TRACE_FILTER;
payload: {
@ -33,14 +35,14 @@ export interface UpdateFilter {
}
export interface UpdateSpansAggregate {
type: typeof UPDATE_SPANS_AGGREEGATE;
type: typeof UPDATE_SPANS_AGGREGATE;
payload: {
spansAggregate: TraceReducer['spansAggregate'];
};
}
export interface UpdateTagVisiblity {
type: typeof UPDATE_TAG_MODAL_VISIBLITY;
export interface UpdateTagVisibility {
type: typeof UPDATE_TAG_MODAL_VISIBILITY;
payload: {
isTagModalOpen: TraceReducer['isTagModalOpen'];
};
@ -70,6 +72,7 @@ export interface UpdateAllFilters {
selectedTags: TraceReducer['selectedTags'];
userSelected: TraceReducer['userSelectedFilter'];
isFilterExclude: TraceReducer['isFilterExclude'];
order: TraceReducer['spansAggregate']['order'];
};
}
@ -149,6 +152,13 @@ export interface UpdateSpans {
};
}
export interface UpdateSpanOrder {
type: typeof UPDATE_SPAN_ORDER;
payload: {
order: TraceReducer['spansAggregate']['order'];
};
}
export type TraceActions =
| UpdateFilter
| GetTraceFilter
@ -156,7 +166,7 @@ export type TraceActions =
| SelectTraceFilter
| UpdateAllFilters
| UpdateSelectedTags
| UpdateTagVisiblity
| UpdateTagVisibility
| UpdateSpansAggregate
| UpdateIsTagError
| UpdateSelectedGroupBy
@ -166,4 +176,5 @@ export type TraceActions =
| UpdateSpans
| ResetTraceFilter
| UpdateSelected
| UpdateFilterExclude;
| UpdateFilterExclude
| UpdateSpanOrder;

View File

@ -7,7 +7,7 @@ export interface Props {
limit: number;
offset: number;
selectedTags: TraceReducer['selectedTags'];
order?: 'descending' | 'ascending';
order?: TraceReducer['spansAggregate']['order'];
isFilterExclude: TraceReducer['isFilterExclude'];
}

View File

@ -4,8 +4,10 @@ export interface TraceReducer {
filter: Map<TraceFilterEnum, Record<string, string>>;
filterToFetchData: TraceFilterEnum[];
filterLoading: boolean;
selectedFilter: Map<TraceFilterEnum, string[]>;
userSelectedFilter: Map<TraceFilterEnum, string[]>;
isFilterExclude: Map<TraceFilterEnum, boolean>;
selectedTags: Tags[];
isTagModalOpen: boolean;
@ -18,6 +20,7 @@ export interface TraceReducer {
error: boolean;
total: number;
pageSize: number;
order: string;
};
selectedGroupBy: string;
selectedFunction: string;