Skip to content

Commit a8f7d07

Browse files
committed
fix: use use-query-params instead of redux-location-state
1 parent 598f9da commit a8f7d07

File tree

12 files changed

+124
-126
lines changed

12 files changed

+124
-126
lines changed

src/containers/Tenant/Diagnostics/Consumers/Consumers.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
selectPreparedConsumersData,
1111
selectPreparedTopicStats,
1212
topicApi,
13-
} from '../../../../store/reducers/topic/topic';
13+
} from '../../../../store/reducers/topic';
1414
import type {EPathType} from '../../../../types/api/schema';
1515
import {cn} from '../../../../utils/cn';
1616
import {DEFAULT_TABLE_SETTINGS} from '../../../../utils/constants';

src/containers/Tenant/Diagnostics/Overview/TopicStats/TopicStats.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {LabelWithPopover} from '../../../../../components/LabelWithPopover';
77
import {LagPopoverContent} from '../../../../../components/LagPopoverContent';
88
import {Loader} from '../../../../../components/Loader';
99
import {SpeedMultiMeter} from '../../../../../components/SpeedMultiMeter';
10-
import {selectPreparedTopicStats, topicApi} from '../../../../../store/reducers/topic/topic';
10+
import {selectPreparedTopicStats, topicApi} from '../../../../../store/reducers/topic';
1111
import type {IPreparedTopicStats} from '../../../../../types/store/topic';
1212
import {cn} from '../../../../../utils/cn';
1313
import {formatBps, formatBytes} from '../../../../../utils/dataFormatters/dataFormatters';

src/containers/Tenant/Diagnostics/Partitions/Partitions.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {TableSkeleton} from '../../../../components/TableSkeleton/TableSkeleton'
88
import {TableWithControlsLayout} from '../../../../components/TableWithControlsLayout/TableWithControlsLayout';
99
import {nodesListApi, selectNodesMap} from '../../../../store/reducers/nodesList';
1010
import {partitionsApi, setSelectedConsumer} from '../../../../store/reducers/partitions/partitions';
11-
import {selectConsumersNames, topicApi} from '../../../../store/reducers/topic/topic';
11+
import {selectConsumersNames, topicApi} from '../../../../store/reducers/topic';
1212
import {cn} from '../../../../utils/cn';
1313
import {DEFAULT_TABLE_SETTINGS, PARTITIONS_HIDDEN_COLUMNS_KEY} from '../../../../utils/constants';
1414
import {

src/containers/Tenant/Diagnostics/TopicData/TopicData.tsx

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,8 @@ import {NoSearchResults} from '@gravity-ui/illustrations';
55
import type {RenderControls} from '../../../../components/PaginatedTable';
66
import {ResizeablePaginatedTable} from '../../../../components/PaginatedTable';
77
import {partitionsApi} from '../../../../store/reducers/partitions/partitions';
8-
import {setSelectedOffset, setStartTimestamp} from '../../../../store/reducers/topic/topic';
98
import type {TopicMessageMetadataItem} from '../../../../types/api/topic';
10-
import {useAutoRefreshInterval, useTypedDispatch, useTypedSelector} from '../../../../utils/hooks';
9+
import {useAutoRefreshInterval} from '../../../../utils/hooks';
1110
import {useSelectedColumns} from '../../../../utils/hooks/useSelectedColumns';
1211
import {renderPaginatedTableErrorMessage} from '../../../../utils/renderPaginatedTableErrorMessage';
1312
import {convertToNumber} from '../../../../utils/utils';
@@ -22,6 +21,7 @@ import {
2221
} from './columns/columns';
2322
import {generateTopicDataGetter} from './getData';
2423
import i18n from './i18n';
24+
import {useTopicDataQueryParams} from './useTopicDataQueryParams';
2525
import {
2626
TOPIC_DATA_COLUMNS_TITLES,
2727
TOPIC_DATA_COLUMNS_WIDTH_LS_KEY,
@@ -37,7 +37,6 @@ interface TopicDataProps {
3737
}
3838

3939
export function TopicData({parentRef, path, database}: TopicDataProps) {
40-
const dispatch = useTypedDispatch();
4140
const [autoRefreshInterval] = useAutoRefreshInterval();
4241
const [startOffset, setStartOffset] = React.useState<number | undefined>(undefined);
4342
const [endOffset, setEndOffset] = React.useState<number | undefined>(undefined);
@@ -46,9 +45,14 @@ export function TopicData({parentRef, path, database}: TopicDataProps) {
4645
>(undefined);
4746
const [controlsKey, setControlsKey] = React.useState(0);
4847

49-
const {selectedPartition, selectedOffset, startTimestamp, topicDataFilter} = useTypedSelector(
50-
(state) => state.topic,
51-
);
48+
const {
49+
selectedPartition,
50+
selectedOffset,
51+
startTimestamp,
52+
topicDataFilter,
53+
handleSelectedOffsetChange,
54+
handleStartTimestampChange,
55+
} = useTopicDataQueryParams();
5256

5357
const {
5458
data: partitions,
@@ -123,9 +127,12 @@ export function TopicData({parentRef, path, database}: TopicDataProps) {
123127
const hasFilters = selectedOffset || startTimestamp;
124128

125129
const resetFilter = () => {
126-
dispatch(setSelectedOffset(undefined));
127-
dispatch(setStartTimestamp(undefined));
128-
setControlsKey((prev) => prev + 1);
130+
if (topicDataFilter === 'OFFSET') {
131+
handleSelectedOffsetChange(undefined);
132+
} else if (topicDataFilter === 'TIMESTAMP') {
133+
handleStartTimestampChange(undefined);
134+
setControlsKey((prev) => prev + 1);
135+
}
129136
};
130137

131138
return (

src/containers/Tenant/Diagnostics/TopicData/TopicDataControls/TopicDataControls.tsx

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,19 @@ import {RelativeDatePicker} from '@gravity-ui/date-components';
55
import {dateTimeParse} from '@gravity-ui/date-utils';
66
import type {TableColumnSetupItem} from '@gravity-ui/uikit';
77
import {RadioButton, Select, TableColumnSetup} from '@gravity-ui/uikit';
8+
import {isNil} from 'lodash';
89

910
import {DebouncedInput} from '../../../../../components/DebouncedInput/DebouncedInput';
1011
import {EntitiesCount} from '../../../../../components/EntitiesCount';
1112
import type {PreparedPartitionData} from '../../../../../store/reducers/partitions/types';
12-
import {
13-
setSelectedOffset,
14-
setSelectedPartition,
15-
setStartTimestamp,
16-
setTopicDataFilter,
17-
} from '../../../../../store/reducers/topic/topic';
18-
import {TopicDataFilterValues} from '../../../../../store/reducers/topic/types';
19-
import type {TopicDataFilterValue} from '../../../../../store/reducers/topic/types';
2013
import {formatNumber} from '../../../../../utils/dataFormatters/dataFormatters';
21-
import {useTypedDispatch, useTypedSelector} from '../../../../../utils/hooks';
2214
import {prepareErrorMessage} from '../../../../../utils/prepareErrorMessage';
2315
import {convertToNumber} from '../../../../../utils/utils';
2416
import i18n from '../i18n';
17+
import {useTopicDataQueryParams} from '../useTopicDataQueryParams';
2518
import {b} from '../utils/constants';
19+
import {TopicDataFilterValues} from '../utils/types';
20+
import type {TopicDataFilterValue} from '../utils/types';
2621

2722
interface TopicDataControlsProps {
2823
columnsToSelect: TableColumnSetupItem[];
@@ -46,9 +41,8 @@ export function TopicDataControls({
4641
partitionsLoading,
4742
partitionsError,
4843
}: TopicDataControlsProps) {
49-
const dispatch = useTypedDispatch();
50-
51-
const {selectedPartition} = useTypedSelector((state) => state.topic);
44+
const {selectedPartition, handleSelectedPartitionChange: handleSelectedPartitionParamChange} =
45+
useTopicDataQueryParams();
5246

5347
const partitionsToSelect = partitions?.map(({partitionId}) => ({
5448
content: partitionId,
@@ -57,13 +51,13 @@ export function TopicDataControls({
5751

5852
const handleSelectedPartitionChange = React.useCallback(
5953
(value: string[]) => {
60-
dispatch(setSelectedPartition(value[0]));
54+
handleSelectedPartitionParamChange(value[0]);
6155
},
62-
[dispatch],
56+
[handleSelectedPartitionParamChange],
6357
);
6458

6559
React.useEffect(() => {
66-
if (partitions && partitions.length && selectedPartition === undefined) {
60+
if (partitions && partitions.length && isNil(selectedPartition)) {
6761
handleSelectedPartitionChange([partitions[0].partitionId]);
6862
}
6963
}, [partitions, selectedPartition, handleSelectedPartitionChange]);
@@ -100,22 +94,26 @@ export function TopicDataControls({
10094
}
10195

10296
function TopicDataStartControls() {
103-
const dispatch = useTypedDispatch();
104-
const {selectedOffset, startTimestamp, topicDataFilter} = useTypedSelector(
105-
(state) => state.topic,
106-
);
97+
const {
98+
selectedOffset,
99+
startTimestamp,
100+
topicDataFilter,
101+
handleSelectedOffsetChange,
102+
handleStartTimestampChange,
103+
handleTopicDataFilterChange,
104+
} = useTopicDataQueryParams();
107105

108106
const onFilterChange = React.useCallback(
109107
(value: TopicDataFilterValue) => {
110-
dispatch(setTopicDataFilter(value));
108+
handleTopicDataFilterChange(value);
111109
},
112-
[dispatch],
110+
[handleTopicDataFilterChange],
113111
);
114112
const onStartOffsetChange = React.useCallback(
115113
(value: string) => {
116-
dispatch(setSelectedOffset(convertToNumber(value)));
114+
handleSelectedOffsetChange(convertToNumber(value));
117115
},
118-
[dispatch],
116+
[handleSelectedOffsetChange],
119117
);
120118
const handleFromTimestampChange = React.useCallback(
121119
(data: Value | null) => {
@@ -130,9 +128,9 @@ function TopicDataStartControls() {
130128
newValue = absoluteValue ? absoluteValue.valueOf() : undefined;
131129
}
132130
}
133-
dispatch(setStartTimestamp(newValue));
131+
handleStartTimestampChange(newValue);
134132
},
135-
[dispatch],
133+
[handleStartTimestampChange],
136134
);
137135

138136
const startDateTime = dateTimeParse(Number(startTimestamp));
@@ -154,6 +152,8 @@ function TopicDataStartControls() {
154152
label={i18n('label_from')}
155153
placeholder={i18n('label_offset')}
156154
type="number"
155+
debounce={600}
156+
autoFocus
157157
/>
158158
)}
159159
{topicDataFilter === 'TIMESTAMP' && (
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import React from 'react';
2+
3+
import {NumberParam, StringParam, useQueryParams} from 'use-query-params';
4+
5+
import type {TopicDataFilterValue} from './utils/types';
6+
import {TopicDataFilterValueParam} from './utils/types';
7+
8+
export function useTopicDataQueryParams() {
9+
const [{selectedPartition, selectedOffset, startTimestamp, topicDataFilter}, setQueryParams] =
10+
useQueryParams({
11+
selectedPartition: StringParam,
12+
selectedOffset: NumberParam,
13+
startTimestamp: NumberParam,
14+
topicDataFilter: TopicDataFilterValueParam,
15+
});
16+
17+
const handleSelectedPartitionChange = React.useCallback(
18+
(value: string) => {
19+
setQueryParams({selectedPartition: value}, 'replaceIn');
20+
},
21+
[setQueryParams],
22+
);
23+
24+
const handleSelectedOffsetChange = React.useCallback(
25+
(value?: number) => {
26+
setQueryParams({selectedOffset: value}, 'replaceIn');
27+
},
28+
[setQueryParams],
29+
);
30+
31+
const handleStartTimestampChange = React.useCallback(
32+
(value?: number) => {
33+
setQueryParams({startTimestamp: value}, 'replaceIn');
34+
},
35+
[setQueryParams],
36+
);
37+
38+
const handleTopicDataFilterChange = React.useCallback(
39+
(value: TopicDataFilterValue) => {
40+
setQueryParams({topicDataFilter: value}, 'replaceIn');
41+
},
42+
[setQueryParams],
43+
);
44+
45+
return {
46+
selectedPartition,
47+
selectedOffset,
48+
startTimestamp,
49+
topicDataFilter,
50+
handleSelectedPartitionChange,
51+
handleSelectedOffsetChange,
52+
handleStartTimestampChange,
53+
handleTopicDataFilterChange,
54+
};
55+
}

src/containers/Tenant/Diagnostics/TopicData/utils/types.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import type {TopicDataFilterValue} from '../../../../../store/reducers/topic/types';
1+
import {createEnumParam, withDefault} from 'use-query-params';
2+
23
import type {ValueOf} from '../../../../../types/common';
34

45
export const TOPIC_DATA_COLUMNS_IDS = {
@@ -26,3 +27,20 @@ export interface TopicDataFilters {
2627
database: string;
2728
path: string;
2829
}
30+
31+
export const TopicDataFilterValues = {
32+
TIMESTAMP: 'By Timestamp',
33+
OFFSET: 'By Offset',
34+
} as const;
35+
36+
export type TopicDataFilterValue = keyof typeof TopicDataFilterValues;
37+
38+
export const isValidTopicDataFilterValue = (value: string): value is TopicDataFilterValue => {
39+
return Object.keys(TopicDataFilterValues).some((v) => v === value);
40+
};
41+
42+
export const TopicDataFilterValueEnum = createEnumParam(['TIMESTAMP', 'OFFSET']);
43+
export const TopicDataFilterValueParam = withDefault<
44+
TopicDataFilterValue | undefined | null,
45+
'TIMESTAMP'
46+
>(TopicDataFilterValueEnum, 'TIMESTAMP');

src/containers/Tenant/TenantPages.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ type AdditionalQueryParams = {
1212
database?: string;
1313
name?: string;
1414
backend?: string;
15+
selectedPartition?: string;
1516
};
1617

1718
export type TenantQuery = TenantQueryParams | AdditionalQueryParams;

src/store/reducers/index.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import singleClusterMode from './singleClusterMode';
1818
import tenant from './tenant/tenant';
1919
import tenants from './tenants/tenants';
2020
import tooltip from './tooltip';
21-
import topic from './topic/topic';
2221

2322
export const rootReducer = {
2423
[api.reducerPath]: api.reducer,
@@ -39,7 +38,6 @@ export const rootReducer = {
3938
queryActions,
4039
fullscreen,
4140
clusters,
42-
topic,
4341
};
4442

4543
const combinedReducer = combineReducers({

src/store/reducers/topic/topic.ts renamed to src/store/reducers/topic.ts

Lines changed: 5 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,11 @@
11
/* eslint-disable camelcase */
2-
import type {PayloadAction} from '@reduxjs/toolkit';
3-
import {createSelector, createSlice} from '@reduxjs/toolkit';
2+
import {createSelector} from '@reduxjs/toolkit';
43

5-
import {convertBytesObjectToSpeed} from '../../../utils/bytesParsers';
6-
import {parseLag, parseTimestampToIdleTime} from '../../../utils/timeParsers';
7-
import type {RootState} from '../../defaultStore';
8-
import {api} from '../api';
4+
import {convertBytesObjectToSpeed} from '../../utils/bytesParsers';
5+
import {parseLag, parseTimestampToIdleTime} from '../../utils/timeParsers';
6+
import type {RootState} from '../defaultStore';
97

10-
import type {TopicDataFilterValue} from './types';
11-
12-
const initialState: {
13-
selectedPartition?: string;
14-
topicDataFilter: TopicDataFilterValue;
15-
selectedOffset?: number;
16-
startTimestamp?: number;
17-
} = {topicDataFilter: 'TIMESTAMP'};
18-
19-
const slice = createSlice({
20-
name: 'topic',
21-
initialState,
22-
reducers: {
23-
setSelectedPartition: (state, action: PayloadAction<string | undefined>) => {
24-
state.selectedPartition = action.payload;
25-
},
26-
setTopicDataFilter: (state, action: PayloadAction<TopicDataFilterValue>) => {
27-
state.topicDataFilter = action.payload;
28-
},
29-
setSelectedOffset: (state, action: PayloadAction<number | undefined>) => {
30-
state.selectedOffset = action.payload;
31-
},
32-
setStartTimestamp: (state, action: PayloadAction<number | undefined>) => {
33-
state.startTimestamp = action.payload;
34-
},
35-
},
36-
});
37-
38-
export const {setSelectedPartition, setTopicDataFilter, setSelectedOffset, setStartTimestamp} =
39-
slice.actions;
40-
export default slice.reducer;
8+
import {api} from './api';
419

4210
export const topicApi = api.injectEndpoints({
4311
endpoints: (build) => ({

0 commit comments

Comments
 (0)