Skip to content

Commit fa79081

Browse files
fix(Consumers): enable navigation to Partitions tab
1 parent 5ebaafd commit fa79081

File tree

5 files changed

+77
-16
lines changed

5 files changed

+77
-16
lines changed

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

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
import DataTable, {Column} from '@gravity-ui/react-data-table';
22
import block from 'bem-cn-lite';
3+
import qs from 'qs';
34

45
import type {IPreparedConsumerData} from '../../../../../types/store/topic';
56
import {SpeedMultiMeter} from '../../../../../components/SpeedMultiMeter';
7+
import {InternalLink} from '../../../../../components/InternalLink';
68
import {formatMsToUptime} from '../../../../../utils';
9+
import routes, {createHref} from '../../../../../routes';
10+
11+
import {TenantTabsGroups} from '../../../TenantPages';
12+
import {GeneralPagesIds} from '../../DiagnosticsPages';
713

814
import {
915
CONSUMERS_COLUMNS_IDS,
@@ -23,7 +29,27 @@ export const columns: Column<IPreparedConsumerData>[] = [
2329
name: CONSUMERS_COLUMNS_IDS.CONSUMER,
2430
header: CONSUMERS_COLUMNS_TITILES[CONSUMERS_COLUMNS_IDS.CONSUMER],
2531
align: DataTable.LEFT,
26-
render: ({row}) => row.name || '-',
32+
render: ({row}) => {
33+
if (!row.name) {
34+
return '–';
35+
}
36+
37+
const queryParams = qs.parse(location.search, {
38+
ignoreQueryPrefix: true,
39+
});
40+
41+
return (
42+
<InternalLink
43+
to={createHref(routes.tenant, undefined, {
44+
...queryParams,
45+
[TenantTabsGroups.generalTab]: GeneralPagesIds.partitions,
46+
selectedConsumer: row.name,
47+
})}
48+
>
49+
{row.name}
50+
</InternalLink>
51+
);
52+
},
2753
},
2854
{
2955
name: CONSUMERS_COLUMNS_IDS.READ_SPEED,

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

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import block from 'bem-cn-lite';
2-
import {useCallback, useEffect, useMemo, useState} from 'react';
2+
import {useCallback, useEffect, useMemo, useRef, useState} from 'react';
33
import {useDispatch} from 'react-redux';
44
import {escapeRegExp} from 'lodash/fp';
55

@@ -17,6 +17,7 @@ import {
1717
getConsumer,
1818
selectPreparedPartitionsData,
1919
setDataWasNotLoaded,
20+
setSelectedConsumer,
2021
} from '../../../../store/reducers/consumer';
2122

2223
import {TableSkeleton} from '../../../../components/TableSkeleton/TableSkeleton';
@@ -52,14 +53,17 @@ export const Partitions = ({path, type, nodes, consumers}: PartitionsProps) => {
5253

5354
const dispatch = useDispatch();
5455

55-
const [selectedConsumer, setSelectedConsumer] = useState<string[]>();
56+
const isFirstRenderRef = useRef(true);
57+
5658
const [generalSearchValue, setGeneralSearchValue] = useState('');
5759
const [partitionIdSearchValue, setPartitionIdSearchValue] = useState('');
5860

5961
const [componentCurrentPath, setComponentCurrentPath] = useState(path);
6062

6163
const {autorefresh} = useTypedSelector((state) => state.schema);
62-
const {loading, wasLoaded, error} = useTypedSelector((state) => state.consumer);
64+
const {loading, wasLoaded, error, selectedConsumer} = useTypedSelector(
65+
(state) => state.consumer,
66+
);
6367

6468
const partitions = useTypedSelector((state) => selectPreparedPartitionsData(state));
6569

@@ -70,16 +74,24 @@ export const Partitions = ({path, type, nodes, consumers}: PartitionsProps) => {
7074
useEffect(() => {
7175
// Manual path control to ensure it updates with other values so no request with wrong params will be sent
7276
setComponentCurrentPath(path);
73-
}, [path]);
77+
78+
// Do not reset selected consumer on first effect call
79+
// To enable navigating to specific consumer
80+
if (isFirstRenderRef.current) {
81+
isFirstRenderRef.current = false;
82+
} else {
83+
dispatch(setSelectedConsumer(undefined));
84+
}
85+
}, [dispatch, path]);
7486

7587
const fetchConsumerData = useCallback(
7688
(isBackground: boolean) => {
7789
if (!isBackground) {
7890
dispatch(setDataWasNotLoaded());
7991
}
8092

81-
if (selectedConsumer && selectedConsumer.length) {
82-
dispatch(getConsumer(componentCurrentPath, selectedConsumer[0]));
93+
if (selectedConsumer) {
94+
dispatch(getConsumer(componentCurrentPath, selectedConsumer));
8395
}
8496
},
8597
[dispatch, selectedConsumer, componentCurrentPath],
@@ -99,12 +111,10 @@ export const Partitions = ({path, type, nodes, consumers}: PartitionsProps) => {
99111
);
100112

101113
useEffect(() => {
102-
if (consumersToSelect && consumersToSelect.length) {
103-
setSelectedConsumer([consumersToSelect[0].value]);
104-
} else {
105-
setSelectedConsumer(undefined);
114+
if (consumersToSelect && consumersToSelect.length && !selectedConsumer) {
115+
dispatch(setSelectedConsumer(consumersToSelect[0].value));
106116
}
107-
}, [consumersToSelect]);
117+
}, [dispatch, consumersToSelect, selectedConsumer]);
108118

109119
const selectedColumns: string[] = useMemo(
110120
() =>
@@ -183,7 +193,7 @@ export const Partitions = ({path, type, nodes, consumers}: PartitionsProps) => {
183193
};
184194

185195
const handleConsumerSelectChange = (value: string[]) => {
186-
setSelectedConsumer(value);
196+
dispatch(setSelectedConsumer(value[0]));
187197
};
188198

189199
const handlePartitionIdSearchChange = (value: string) => {
@@ -210,7 +220,7 @@ export const Partitions = ({path, type, nodes, consumers}: PartitionsProps) => {
210220
placeholder={i18n('controls.consumerSelector.placeholder')}
211221
label={i18n('controls.consumerSelector')}
212222
options={consumersToSelect}
213-
value={selectedConsumer}
223+
value={[selectedConsumer || '']}
214224
onUpdate={handleConsumerSelectChange}
215225
/>
216226
<Search

src/store/reducers/consumer.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {createRequestActionTypes, createApiRequest} from '../utils';
2020
export const FETCH_CONSUMER = createRequestActionTypes('consumer', 'FETCH_CONSUMER');
2121

2222
const SET_DATA_WAS_NOT_LOADED = 'consumer/SET_DATA_WAS_NOT_LOADED';
23+
const SET_SELECTED_CONSUMER = 'consumer/SET_SELECTED_CONSUMER';
2324

2425
const initialState = {
2526
loading: false,
@@ -66,6 +67,12 @@ const consumer: Reducer<IConsumerState, IConsumerAction> = (state = initialState
6667
wasLoaded: false,
6768
};
6869
}
70+
case SET_SELECTED_CONSUMER: {
71+
return {
72+
...state,
73+
selectedConsumer: action.data,
74+
};
75+
}
6976
default:
7077
return state;
7178
}
@@ -77,6 +84,13 @@ export const setDataWasNotLoaded = () => {
7784
} as const;
7885
};
7986

87+
export const setSelectedConsumer = (value?: string) => {
88+
return {
89+
type: SET_SELECTED_CONSUMER,
90+
data: value,
91+
} as const;
92+
};
93+
8094
export function getConsumer(path?: string, consumerName?: string) {
8195
return createApiRequest({
8296
request: window.api.getConsumer({path, consumer: consumerName}),

src/store/state-url-mapping.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ const paramSetup = {
6767
stateKey: 'executeTopQueries.filters.to',
6868
type: 'number',
6969
},
70+
selectedConsumer: {
71+
stateKey: 'consumer.selectedConsumer',
72+
},
7073
},
7174
};
7275

src/types/store/consumer.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
import type {IProcessSpeedStats} from '../../utils/bytesParsers';
22
import type {ApiRequestAction} from '../../store/utils';
33

4-
import {FETCH_CONSUMER, setDataWasNotLoaded} from '../../store/reducers/consumer';
4+
import {
5+
FETCH_CONSUMER,
6+
setDataWasNotLoaded,
7+
setSelectedConsumer,
8+
} from '../../store/reducers/consumer';
59

610
import type {DescribeConsumerResult} from '../api/consumer';
711
import type {IResponseError} from '../api/error';
@@ -38,6 +42,7 @@ export interface IPreparedPartitionData {
3842
export interface IConsumerState {
3943
loading: boolean;
4044
wasLoaded: boolean;
45+
selectedConsumer?: string;
4146
data?: DescribeConsumerResult;
4247
error?: IResponseError;
4348
}
@@ -48,7 +53,10 @@ type IConsumerApiRequestAction = ApiRequestAction<
4853
IResponseError
4954
>;
5055

51-
export type IConsumerAction = IConsumerApiRequestAction | ReturnType<typeof setDataWasNotLoaded>;
56+
export type IConsumerAction =
57+
| IConsumerApiRequestAction
58+
| ReturnType<typeof setDataWasNotLoaded>
59+
| ReturnType<typeof setSelectedConsumer>;
5260

5361
export interface IConsumerRootStateSlice {
5462
consumer: IConsumerState;

0 commit comments

Comments
 (0)