ydb-embedded-ui 4.2.0 → 4.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (29) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/containers/Tenant/Diagnostics/Diagnostics.tsx +2 -2
  3. package/dist/containers/Tenant/Diagnostics/Partitions/Partitions.tsx +111 -193
  4. package/dist/containers/Tenant/Diagnostics/Partitions/PartitionsControls/PartitionsControls.tsx +182 -0
  5. package/dist/containers/Tenant/Diagnostics/Partitions/columns/Columns.scss +1 -1
  6. package/dist/containers/Tenant/Diagnostics/Partitions/columns/columns.tsx +15 -6
  7. package/dist/containers/Tenant/Diagnostics/Partitions/utils/constants.ts +13 -1
  8. package/dist/containers/Tenant/Diagnostics/Partitions/utils/index.ts +26 -0
  9. package/dist/containers/Tenant/Diagnostics/Partitions/utils/types.ts +2 -2
  10. package/dist/containers/Tenant/Diagnostics/Partitions/utils/useGetPartitionsColumns.ts +27 -0
  11. package/dist/services/api.ts +1 -1
  12. package/dist/store/reducers/index.ts +2 -2
  13. package/dist/store/reducers/partitions/partitions.ts +104 -0
  14. package/dist/store/reducers/partitions/types.ts +47 -0
  15. package/dist/store/reducers/partitions/utils.ts +99 -0
  16. package/dist/store/reducers/settings.js +2 -2
  17. package/dist/store/reducers/topic.ts +7 -0
  18. package/dist/store/state-url-mapping.js +1 -1
  19. package/dist/types/api/topic.ts +1 -1
  20. package/dist/utils/constants.ts +1 -1
  21. package/dist/utils/createToast.tsx +1 -1
  22. package/dist/utils/hooks/index.ts +1 -0
  23. package/dist/utils/hooks/useSetting.ts +23 -0
  24. package/dist/utils/tablet.ts +14 -13
  25. package/package.json +1 -1
  26. package/dist/containers/Tenant/Diagnostics/Partitions/PartitionsWrapper.tsx +0 -81
  27. package/dist/containers/Tenant/Diagnostics/Partitions/index.ts +0 -1
  28. package/dist/store/reducers/consumer.ts +0 -174
  29. package/dist/types/store/consumer.ts +0 -63
@@ -71,4 +71,16 @@ export const PARTITIONS_READ_LAGS_SUB_COLUMNS_TITLES = {
71
71
  [PARTITIONS_READ_LAGS_SUB_COLUMNS_IDS.CONSUMER_READ_IDLE_TIME]: 'read idle time',
72
72
  } as const;
73
73
 
74
- export const PARTITIONS_DEFAULT_SELECTED_COLUMNS = Object.values(PARTITIONS_COLUMNS_IDS);
74
+ // Topics without consumers have partitions data with no data corresponding to consumers
75
+ // These columns will be empty and should not be displayed
76
+ export const generalPartitionColumnsIds = [
77
+ PARTITIONS_COLUMNS_IDS.PARTITION_ID,
78
+ PARTITIONS_COLUMNS_IDS.STORE_SIZE,
79
+ PARTITIONS_COLUMNS_IDS.WRITE_SPEED,
80
+ PARTITIONS_COLUMNS_IDS.WRITE_LAGS,
81
+ PARTITIONS_COLUMNS_IDS.START_OFFSET,
82
+ PARTITIONS_COLUMNS_IDS.END_OFFSET,
83
+ PARTITIONS_COLUMNS_IDS.PARTITION_HOST,
84
+ ];
85
+
86
+ export const allPartitionsColumnsIds = Object.values(PARTITIONS_COLUMNS_IDS);
@@ -0,0 +1,26 @@
1
+ import type {PreparedPartitionData} from '../../../../../store/reducers/partitions/types';
2
+ import type {NodesMap} from '../../../../../types/store/nodesList';
3
+ import type {PreparedPartitionDataWithHosts} from './types';
4
+
5
+ export const addHostToPartitions = (
6
+ partitions: PreparedPartitionData[] = [],
7
+ nodesMap?: NodesMap,
8
+ ): PreparedPartitionDataWithHosts[] => {
9
+ return partitions?.map((partition) => {
10
+ const partitionHost =
11
+ partition.partitionNodeId && nodesMap
12
+ ? nodesMap.get(partition.partitionNodeId)
13
+ : undefined;
14
+
15
+ const connectionHost =
16
+ partition.connectionNodeId && nodesMap
17
+ ? nodesMap.get(partition.connectionNodeId)
18
+ : undefined;
19
+
20
+ return {
21
+ ...partition,
22
+ partitionHost,
23
+ connectionHost,
24
+ };
25
+ });
26
+ };
@@ -1,6 +1,6 @@
1
- import type {IPreparedPartitionData} from '../../../../../types/store/consumer';
1
+ import type {PreparedPartitionData} from '../../../../../store/reducers/partitions/types';
2
2
 
3
- export interface IPreparedPartitionDataWithHosts extends IPreparedPartitionData {
3
+ export interface PreparedPartitionDataWithHosts extends PreparedPartitionData {
4
4
  partitionHost: string | undefined;
5
5
  connectionHost: string | undefined;
6
6
  }
@@ -0,0 +1,27 @@
1
+ import {useEffect, useState} from 'react';
2
+
3
+ import type {Column} from '@gravity-ui/react-data-table';
4
+
5
+ import type {PreparedPartitionDataWithHosts} from './types';
6
+ import {allColumns, generalColumns} from '../columns';
7
+ import {allPartitionsColumnsIds, generalPartitionColumnsIds} from './constants';
8
+
9
+ // Columns are different for partitions with consumers and without
10
+ export const useGetPartitionsColumns = (
11
+ selectedConsumer: string | undefined,
12
+ ): [Column<PreparedPartitionDataWithHosts>[], string[]] => {
13
+ const [columns, setColumns] = useState<Column<PreparedPartitionDataWithHosts>[]>([]);
14
+ const [columnsIdsForSelector, setColumnsIdsForSelector] = useState<string[]>([]);
15
+
16
+ useEffect(() => {
17
+ if (selectedConsumer) {
18
+ setColumns(allColumns);
19
+ setColumnsIdsForSelector(allPartitionsColumnsIds);
20
+ } else {
21
+ setColumns(generalColumns);
22
+ setColumnsIdsForSelector(generalPartitionColumnsIds);
23
+ }
24
+ }, [selectedConsumer]);
25
+
26
+ return [columns, columnsIdsForSelector];
27
+ };
@@ -216,7 +216,7 @@ export class YdbEmbeddedAPI extends AxiosWrapper {
216
216
  );
217
217
  }
218
218
  getConsumer(
219
- {path, consumer}: {path?: string; consumer?: string},
219
+ {path, consumer}: {path: string; consumer: string},
220
220
  {concurrentId}: AxiosOptions = {},
221
221
  ) {
222
222
  return this.get<DescribeConsumerResult>(
@@ -18,7 +18,7 @@ import pool from './pool';
18
18
  import tenants from './tenants/tenants';
19
19
  import tablet from './tablet';
20
20
  import topic from './topic';
21
- import consumer from './consumer';
21
+ import partitions from './partitions/partitions';
22
22
  import executeQuery from './executeQuery';
23
23
  import explainQuery from './explainQuery';
24
24
  import tabletsFilters from './tabletsFilters';
@@ -58,7 +58,7 @@ export const rootReducer = {
58
58
  tenants,
59
59
  tablet,
60
60
  topic,
61
- consumer,
61
+ partitions,
62
62
  executeQuery,
63
63
  explainQuery,
64
64
  tabletsFilters,
@@ -0,0 +1,104 @@
1
+ import type {Reducer} from 'redux';
2
+
3
+ import '../../../services/api';
4
+
5
+ import {createRequestActionTypes, createApiRequest} from '../../utils';
6
+
7
+ import type {PartitionsAction, PartitionsState} from './types';
8
+ import {prepareConsumerPartitions, prepareTopicPartitions} from './utils';
9
+
10
+ export const FETCH_PARTITIONS = createRequestActionTypes('partitions', 'FETCH_PARTITIONS');
11
+
12
+ const SET_SELECTED_CONSUMER = 'partitions/SET_SELECTED_CONSUMER';
13
+ const SET_DATA_WAS_NOT_LOADED = 'partitions/SET_DATA_WAS_NOT_LOADED';
14
+
15
+ const initialState = {
16
+ loading: false,
17
+ wasLoaded: false,
18
+ selectedConsumer: undefined,
19
+ };
20
+
21
+ const partitions: Reducer<PartitionsState, PartitionsAction> = (state = initialState, action) => {
22
+ switch (action.type) {
23
+ case FETCH_PARTITIONS.REQUEST: {
24
+ return {
25
+ ...state,
26
+ loading: true,
27
+ };
28
+ }
29
+ case FETCH_PARTITIONS.SUCCESS: {
30
+ return {
31
+ ...state,
32
+ partitions: action.data,
33
+ loading: false,
34
+ wasLoaded: true,
35
+ error: undefined,
36
+ };
37
+ }
38
+ case FETCH_PARTITIONS.FAILURE: {
39
+ if (action.error?.isCancelled) {
40
+ return state;
41
+ }
42
+
43
+ return {
44
+ ...state,
45
+ error: action.error,
46
+ loading: false,
47
+ };
48
+ }
49
+ case SET_SELECTED_CONSUMER: {
50
+ return {
51
+ ...state,
52
+ selectedConsumer: action.data,
53
+ };
54
+ }
55
+ case SET_DATA_WAS_NOT_LOADED: {
56
+ return {
57
+ ...state,
58
+ wasLoaded: false,
59
+ };
60
+ }
61
+ default:
62
+ return state;
63
+ }
64
+ };
65
+
66
+ export const setSelectedConsumer = (value?: string) => {
67
+ return {
68
+ type: SET_SELECTED_CONSUMER,
69
+ data: value,
70
+ } as const;
71
+ };
72
+
73
+ export const setDataWasNotLoaded = () => {
74
+ return {
75
+ type: SET_DATA_WAS_NOT_LOADED,
76
+ } as const;
77
+ };
78
+
79
+ export function getPartitions(path: string, consumerName?: string) {
80
+ if (consumerName) {
81
+ return createApiRequest({
82
+ request: window.api.getConsumer(
83
+ {path, consumer: consumerName},
84
+ {concurrentId: 'getPartitions'},
85
+ ),
86
+ actions: FETCH_PARTITIONS,
87
+ dataHandler: (data) => {
88
+ const rawPartitions = data.partitions;
89
+ return prepareConsumerPartitions(rawPartitions);
90
+ },
91
+ });
92
+ }
93
+
94
+ return createApiRequest({
95
+ request: window.api.getTopic({path}, {concurrentId: 'getPartitions'}),
96
+ actions: FETCH_PARTITIONS,
97
+ dataHandler: (data) => {
98
+ const rawPartitions = data.partitions;
99
+ return prepareTopicPartitions(rawPartitions);
100
+ },
101
+ });
102
+ }
103
+
104
+ export default partitions;
@@ -0,0 +1,47 @@
1
+ import type {IResponseError} from '../../../types/api/error';
2
+ import type {IProcessSpeedStats} from '../../../utils/bytesParsers';
3
+ import type {ApiRequestAction} from '../../utils';
4
+
5
+ import {FETCH_PARTITIONS, setDataWasNotLoaded, setSelectedConsumer} from './partitions';
6
+
7
+ // Fields that could be undefined corresponds to partitions without consumers
8
+ export interface PreparedPartitionData {
9
+ partitionId: string;
10
+ storeSize: string;
11
+
12
+ writeSpeed: IProcessSpeedStats;
13
+ readSpeed?: IProcessSpeedStats;
14
+
15
+ partitionWriteLag: number;
16
+ partitionWriteIdleTime: number;
17
+
18
+ consumerWriteLag?: number;
19
+ consumerReadLag?: number;
20
+ consumerReadIdleTime?: number;
21
+
22
+ uncommitedMessages?: number;
23
+ unreadMessages?: number;
24
+
25
+ startOffset: string;
26
+ endOffset: string;
27
+ commitedOffset?: string;
28
+
29
+ readSessionId?: string;
30
+ readerName?: string;
31
+
32
+ partitionNodeId: number;
33
+ connectionNodeId?: number;
34
+ }
35
+
36
+ export interface PartitionsState {
37
+ loading: boolean;
38
+ wasLoaded: boolean;
39
+ selectedConsumer: string | undefined;
40
+ partitions?: PreparedPartitionData[];
41
+ error?: IResponseError;
42
+ }
43
+
44
+ export type PartitionsAction =
45
+ | ApiRequestAction<typeof FETCH_PARTITIONS, PreparedPartitionData[], IResponseError>
46
+ | ReturnType<typeof setDataWasNotLoaded>
47
+ | ReturnType<typeof setSelectedConsumer>;
@@ -0,0 +1,99 @@
1
+ /* eslint-disable camelcase */
2
+ import type {
3
+ PartitionInfo as ConsumerPartitionInfo,
4
+ PartitionStats,
5
+ } from '../../../types/api/consumer';
6
+ import type {PartitionInfo as TopicPartitionInfo} from '../../../types/api/topic';
7
+
8
+ import {convertBytesObjectToSpeed} from '../../../utils/bytesParsers';
9
+ import {parseLag, parseTimestampToIdleTime} from '../../../utils/timeParsers';
10
+ import {isNumeric} from '../../../utils/utils';
11
+ import {PreparedPartitionData} from './types';
12
+
13
+ const prepareGeneralPartitionStats = (partitionStats: PartitionStats | undefined) => {
14
+ const {
15
+ partition_offsets,
16
+ store_size_bytes = '0',
17
+ last_write_time: partition_last_write_time,
18
+ max_write_time_lag: partition_write_lag,
19
+ bytes_written,
20
+ partition_node_id = 0,
21
+ } = partitionStats || {};
22
+
23
+ const {start: start_offset = '0', end: end_offset = '0'} = partition_offsets || {};
24
+
25
+ return {
26
+ storeSize: store_size_bytes,
27
+ writeSpeed: convertBytesObjectToSpeed(bytes_written),
28
+ partitionWriteLag: parseLag(partition_write_lag),
29
+ partitionWriteIdleTime: parseTimestampToIdleTime(partition_last_write_time),
30
+ startOffset: start_offset,
31
+ endOffset: end_offset,
32
+ partitionNodeId: partition_node_id,
33
+ };
34
+ };
35
+
36
+ export const prepareTopicPartitions = (
37
+ partitions?: TopicPartitionInfo[],
38
+ ): PreparedPartitionData[] | undefined => {
39
+ return partitions?.map((partition) => {
40
+ // describe_topic endpoint doesn't return zero values, so some values will be initialized with 0
41
+ const {partition_id = '0', partition_stats} = partition;
42
+
43
+ const preparedPartitionStats = prepareGeneralPartitionStats(partition_stats);
44
+
45
+ return {
46
+ partitionId: partition_id,
47
+ ...preparedPartitionStats,
48
+ };
49
+ });
50
+ };
51
+
52
+ export const prepareConsumerPartitions = (
53
+ partitions?: ConsumerPartitionInfo[],
54
+ ): PreparedPartitionData[] | undefined => {
55
+ return partitions?.map((partition) => {
56
+ // describe_consumer endpoint doesn't return zero values, so some values will be initialized with 0
57
+ const {partition_id = '0', partition_stats, partition_consumer_stats} = partition;
58
+
59
+ const preparedPartitionStats = prepareGeneralPartitionStats(partition_stats);
60
+ const endOffset = preparedPartitionStats;
61
+
62
+ const {
63
+ last_read_offset = '0',
64
+ committed_offset = '0',
65
+ read_session_id,
66
+ last_read_time: consumer_last_read_time,
67
+ max_read_time_lag: consumer_read_lag,
68
+ max_write_time_lag: consumer_write_lag,
69
+ bytes_read,
70
+ reader_name,
71
+ connection_node_id = 0,
72
+ } = partition_consumer_stats || {};
73
+
74
+ const uncommitedMessages =
75
+ isNumeric(endOffset) && isNumeric(committed_offset)
76
+ ? Number(endOffset) - Number(committed_offset)
77
+ : 0;
78
+
79
+ const unreadMessages =
80
+ isNumeric(endOffset) && isNumeric(last_read_offset)
81
+ ? Number(endOffset) - Number(last_read_offset)
82
+ : 0;
83
+
84
+ return {
85
+ ...preparedPartitionStats,
86
+ partitionId: partition_id,
87
+ readSpeed: convertBytesObjectToSpeed(bytes_read),
88
+ consumerWriteLag: parseLag(consumer_write_lag),
89
+ consumerReadLag: parseLag(consumer_read_lag),
90
+ consumerReadIdleTime: parseTimestampToIdleTime(consumer_last_read_time),
91
+ uncommitedMessages,
92
+ unreadMessages,
93
+ commitedOffset: committed_offset,
94
+ readSessionId: read_session_id,
95
+ readerName: reader_name,
96
+ connectionNodeId: connection_node_id,
97
+ };
98
+ });
99
+ };
@@ -6,7 +6,7 @@ import {
6
6
  INVERTED_DISKS_KEY,
7
7
  ASIDE_HEADER_COMPACT_KEY,
8
8
  USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY,
9
- PARTITIONS_SELECTED_COLUMNS_KEY,
9
+ PARTITIONS_HIDDEN_COLUMNS_KEY,
10
10
  QUERY_INITIAL_MODE_KEY,
11
11
  ENABLE_QUERY_MODES_FOR_EXPLAIN,
12
12
  } from '../../utils/constants';
@@ -44,7 +44,7 @@ export const initialState = {
44
44
  [TENANT_INITIAL_TAB_KEY]: readSavedSettingsValue(TENANT_INITIAL_TAB_KEY),
45
45
  [QUERY_INITIAL_MODE_KEY]: readSavedSettingsValue(QUERY_INITIAL_MODE_KEY, QueryModes.script),
46
46
  [ASIDE_HEADER_COMPACT_KEY]: readSavedSettingsValue(ASIDE_HEADER_COMPACT_KEY, 'true'),
47
- [PARTITIONS_SELECTED_COLUMNS_KEY]: readSavedSettingsValue(PARTITIONS_SELECTED_COLUMNS_KEY),
47
+ [PARTITIONS_HIDDEN_COLUMNS_KEY]: readSavedSettingsValue(PARTITIONS_HIDDEN_COLUMNS_KEY),
48
48
  },
49
49
  systemSettings,
50
50
  };
@@ -98,6 +98,13 @@ export function getTopic(path?: string) {
98
98
  const selectTopicStats = (state: ITopicRootStateSlice) => state.topic.data?.topic_stats;
99
99
  const selectConsumers = (state: ITopicRootStateSlice) => state.topic.data?.consumers;
100
100
 
101
+ export const selectConsumersNames: Selector<ITopicRootStateSlice, string[] | undefined> =
102
+ createSelector([selectConsumers], (consumers) => {
103
+ return consumers
104
+ ?.map((consumer) => consumer?.name)
105
+ .filter((consumer): consumer is string => consumer !== undefined);
106
+ });
107
+
101
108
  export const selectPreparedTopicStats: Selector<
102
109
  ITopicRootStateSlice,
103
110
  IPreparedTopicStats | undefined
@@ -68,7 +68,7 @@ const paramSetup = {
68
68
  type: 'number',
69
69
  },
70
70
  selectedConsumer: {
71
- stateKey: 'consumer.selectedConsumer',
71
+ stateKey: 'partitions.selectedConsumer',
72
72
  },
73
73
  },
74
74
  };
@@ -74,7 +74,7 @@ export interface DescribeTopicResult {
74
74
  }
75
75
 
76
76
  /** Partition info types differs for consumer and topic, although they are very similar */
77
- interface PartitionInfo {
77
+ export interface PartitionInfo {
78
78
  /** int64 */
79
79
  partition_id?: string;
80
80
 
@@ -121,4 +121,4 @@ export const DEFAULT_TABLE_SETTINGS = {
121
121
  export const TENANT_INITIAL_TAB_KEY = 'saved_tenant_initial_tab';
122
122
  export const QUERY_INITIAL_MODE_KEY = 'query_initial_mode';
123
123
 
124
- export const PARTITIONS_SELECTED_COLUMNS_KEY = 'partitionsSelectedColumns';
124
+ export const PARTITIONS_HIDDEN_COLUMNS_KEY = 'partitionsHiddenColumns';
@@ -1,6 +1,6 @@
1
1
  import {Toaster} from '@gravity-ui/uikit';
2
2
 
3
- const toaster = new Toaster();
3
+ export const toaster = new Toaster();
4
4
 
5
5
  interface CreateToastProps {
6
6
  name?: string;
@@ -1,2 +1,3 @@
1
1
  export * from './useAutofetcher';
2
2
  export * from './useTypedSelector';
3
+ export * from './useSetting';
@@ -0,0 +1,23 @@
1
+ import {useCallback} from 'react';
2
+ import {useDispatch} from 'react-redux';
3
+
4
+ import {getParsedSettingValue, setSettingValue} from '../../store/reducers/settings';
5
+
6
+ import {useTypedSelector} from './useTypedSelector';
7
+
8
+ export const useSetting = <T>(key: string, defaultValue: T): [T, (value: T) => void] => {
9
+ const dispatch = useDispatch();
10
+
11
+ const settingValue: T = useTypedSelector(
12
+ (state) => getParsedSettingValue(state, key) || defaultValue,
13
+ );
14
+
15
+ const setValue = useCallback(
16
+ (value: T) => {
17
+ dispatch(setSettingValue(key, JSON.stringify(value)));
18
+ },
19
+ [dispatch, key],
20
+ );
21
+
22
+ return [settingValue, setValue];
23
+ };
@@ -1,23 +1,24 @@
1
1
  import {EFlag} from '../types/api/enums';
2
2
  import {ETabletState} from '../types/api/tablet';
3
3
 
4
+ // Similar to mapping in https://github.com/ydb-platform/ydb/blob/main/ydb/core/viewer/viewer.cpp
4
5
  const tabletStateToColorState: Record<ETabletState, EFlag> = {
5
- [ETabletState.Active]: EFlag.Green,
6
- [ETabletState.Deleted]: EFlag.Green,
6
+ [ETabletState.Dead]: EFlag.Red,
7
7
 
8
- [ETabletState.RebuildGraph]: EFlag.Orange,
8
+ [ETabletState.Created]: EFlag.Yellow,
9
+ [ETabletState.ResolveStateStorage]: EFlag.Yellow,
10
+ [ETabletState.Candidate]: EFlag.Yellow,
11
+ [ETabletState.BlockBlobStorage]: EFlag.Yellow,
12
+ [ETabletState.WriteZeroEntry]: EFlag.Yellow,
13
+ [ETabletState.Restored]: EFlag.Yellow,
14
+ [ETabletState.Discover]: EFlag.Yellow,
15
+ [ETabletState.Lock]: EFlag.Yellow,
16
+ [ETabletState.Stopped]: EFlag.Yellow,
9
17
  [ETabletState.ResolveLeader]: EFlag.Yellow,
18
+ [ETabletState.RebuildGraph]: EFlag.Yellow,
10
19
 
11
- [ETabletState.Created]: EFlag.Red,
12
- [ETabletState.ResolveStateStorage]: EFlag.Red,
13
- [ETabletState.Candidate]: EFlag.Red,
14
- [ETabletState.BlockBlobStorage]: EFlag.Red,
15
- [ETabletState.WriteZeroEntry]: EFlag.Red,
16
- [ETabletState.Restored]: EFlag.Red,
17
- [ETabletState.Discover]: EFlag.Red,
18
- [ETabletState.Lock]: EFlag.Red,
19
- [ETabletState.Dead]: EFlag.Red,
20
- [ETabletState.Stopped]: EFlag.Red,
20
+ [ETabletState.Deleted]: EFlag.Green,
21
+ [ETabletState.Active]: EFlag.Green,
21
22
  };
22
23
 
23
24
  export const tabletStates = Object.keys(ETabletState);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ydb-embedded-ui",
3
- "version": "4.2.0",
3
+ "version": "4.3.0",
4
4
  "files": [
5
5
  "dist"
6
6
  ],
@@ -1,81 +0,0 @@
1
- import {useEffect, useMemo} from 'react';
2
- import {useDispatch} from 'react-redux';
3
-
4
- import type {EPathType} from '../../../../types/api/schema';
5
-
6
- import {useTypedSelector} from '../../../../utils/hooks';
7
-
8
- import {
9
- cleanTopicData,
10
- getTopic,
11
- setDataWasNotLoaded as setTopicDataWasNotLoaded,
12
- } from '../../../../store/reducers/topic';
13
- import {
14
- getNodes,
15
- setDataWasNotLoaded as setNodesDataWasNotLoaded,
16
- } from '../../../../store/reducers/nodes';
17
-
18
- import {Loader} from '../../../../components/Loader';
19
- import {ResponseError} from '../../../../components/Errors/ResponseError';
20
-
21
- import {Partitions} from './Partitions';
22
-
23
- interface PartitionsWrapperProps {
24
- path?: string;
25
- type?: EPathType;
26
- }
27
-
28
- export const PartitionsWrapper = ({path, type}: PartitionsWrapperProps) => {
29
- const dispatch = useDispatch();
30
-
31
- const {
32
- loading: topicLoading,
33
- wasLoaded: topicWasLoaded,
34
- error: topicError,
35
- data: topicData,
36
- } = useTypedSelector((state) => state.topic);
37
-
38
- const {
39
- loading: nodesLoading,
40
- wasLoaded: nodesWasLoaded,
41
- error: nodesError,
42
- data: nodesData,
43
- } = useTypedSelector((state) => state.nodes);
44
-
45
- const consumers = useMemo(
46
- () =>
47
- topicData?.consumers
48
- ?.map((consumer) => consumer?.name)
49
- .filter((consumer): consumer is string => consumer !== undefined),
50
- [topicData],
51
- );
52
-
53
- const nodes = useMemo(() => {
54
- const preparedNodesObject: Record<number, string> = {};
55
- nodesData?.forEach((node) => {
56
- if (node.NodeId && node.Host) {
57
- preparedNodesObject[node.NodeId] = node.Host;
58
- }
59
- });
60
- return preparedNodesObject;
61
- }, [nodesData]);
62
-
63
- useEffect(() => {
64
- dispatch(setTopicDataWasNotLoaded());
65
- dispatch(cleanTopicData());
66
- dispatch(setNodesDataWasNotLoaded());
67
-
68
- dispatch(getTopic(path));
69
- dispatch(getNodes({}));
70
- }, [dispatch, path]);
71
-
72
- if ((topicLoading && !topicWasLoaded) || (nodesLoading && !nodesWasLoaded)) {
73
- return <Loader />;
74
- }
75
-
76
- if (topicError || nodesError) {
77
- return <ResponseError error={topicError || nodesError} />;
78
- }
79
-
80
- return <Partitions path={path} type={type} consumers={consumers} nodes={nodes} />;
81
- };
@@ -1 +0,0 @@
1
- export * from './PartitionsWrapper';