ydb-embedded-ui 4.2.1 → 4.3.0
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +12 -0
- package/dist/containers/Tenant/Diagnostics/Diagnostics.tsx +2 -2
- package/dist/containers/Tenant/Diagnostics/Partitions/Partitions.tsx +111 -193
- package/dist/containers/Tenant/Diagnostics/Partitions/PartitionsControls/PartitionsControls.tsx +182 -0
- package/dist/containers/Tenant/Diagnostics/Partitions/columns/Columns.scss +1 -1
- package/dist/containers/Tenant/Diagnostics/Partitions/columns/columns.tsx +15 -6
- package/dist/containers/Tenant/Diagnostics/Partitions/utils/constants.ts +13 -1
- package/dist/containers/Tenant/Diagnostics/Partitions/utils/index.ts +26 -0
- package/dist/containers/Tenant/Diagnostics/Partitions/utils/types.ts +2 -2
- package/dist/containers/Tenant/Diagnostics/Partitions/utils/useGetPartitionsColumns.ts +27 -0
- package/dist/services/api.ts +1 -1
- package/dist/store/reducers/index.ts +2 -2
- package/dist/store/reducers/partitions/partitions.ts +104 -0
- package/dist/store/reducers/partitions/types.ts +47 -0
- package/dist/store/reducers/partitions/utils.ts +99 -0
- package/dist/store/reducers/settings.js +2 -2
- package/dist/store/reducers/topic.ts +7 -0
- package/dist/store/state-url-mapping.js +1 -1
- package/dist/types/api/topic.ts +1 -1
- package/dist/utils/constants.ts +1 -1
- package/dist/utils/hooks/index.ts +1 -0
- package/dist/utils/hooks/useSetting.ts +23 -0
- package/dist/utils/tablet.ts +14 -13
- package/package.json +1 -1
- package/dist/containers/Tenant/Diagnostics/Partitions/PartitionsWrapper.tsx +0 -81
- package/dist/containers/Tenant/Diagnostics/Partitions/index.ts +0 -1
- package/dist/store/reducers/consumer.ts +0 -174
- package/dist/types/store/consumer.ts +0 -63
@@ -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 {
|
1
|
+
import type {PreparedPartitionData} from '../../../../../store/reducers/partitions/types';
|
2
2
|
|
3
|
-
export interface
|
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
|
+
};
|
package/dist/services/api.ts
CHANGED
@@ -216,7 +216,7 @@ export class YdbEmbeddedAPI extends AxiosWrapper {
|
|
216
216
|
);
|
217
217
|
}
|
218
218
|
getConsumer(
|
219
|
-
{path, consumer}: {path
|
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
|
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
|
-
|
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
|
-
|
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
|
-
[
|
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
|
package/dist/types/api/topic.ts
CHANGED
package/dist/utils/constants.ts
CHANGED
@@ -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
|
124
|
+
export const PARTITIONS_HIDDEN_COLUMNS_KEY = 'partitionsHiddenColumns';
|
@@ -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
|
+
};
|
package/dist/utils/tablet.ts
CHANGED
@@ -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.
|
6
|
-
[ETabletState.Deleted]: EFlag.Green,
|
6
|
+
[ETabletState.Dead]: EFlag.Red,
|
7
7
|
|
8
|
-
[ETabletState.
|
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.
|
12
|
-
[ETabletState.
|
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,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';
|