ydb-embedded-ui 3.4.1 → 3.4.2
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +9 -0
- package/dist/containers/Storage/PDisk/PDisk.scss +15 -0
- package/dist/containers/Storage/PDisk/PDisk.tsx +38 -13
- package/dist/containers/Storage/StorageNodes/StorageNodes.scss +4 -2
- package/dist/containers/Storage/StorageNodes/StorageNodes.tsx +1 -0
- package/dist/containers/Tenant/Diagnostics/Partitions/Partitions.tsx +9 -15
- package/dist/containers/Tenant/Diagnostics/Partitions/PartitionsWrapper.tsx +2 -0
- package/dist/store/reducers/topic.ts +13 -0
- package/dist/types/store/topic.ts +3 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [3.4.2](https://github.com/ydb-platform/ydb-embedded-ui/compare/v3.4.1...v3.4.2) (2023-03-03)
|
4
|
+
|
5
|
+
|
6
|
+
### Bug Fixes
|
7
|
+
|
8
|
+
* **Partitions:** add search to consumers filter ([95e4462](https://github.com/ydb-platform/ydb-embedded-ui/commit/95e446295cb2b2729daf0d0ef719e37c7c8e0d3c))
|
9
|
+
* **Partitions:** fix error on wrong consumer in query string ([44269fa](https://github.com/ydb-platform/ydb-embedded-ui/commit/44269fa9240fe31c9ef69e061c20d58b2b55fae3))
|
10
|
+
* **PDisk:** display vdisks donors ([8b39b01](https://github.com/ydb-platform/ydb-embedded-ui/commit/8b39b01e8bf62624e9e12ac0a329fda5d03cc8df))
|
11
|
+
|
3
12
|
## [3.4.1](https://github.com/ydb-platform/ydb-embedded-ui/compare/v3.4.0...v3.4.1) (2023-03-01)
|
4
13
|
|
5
14
|
|
@@ -21,6 +21,21 @@
|
|
21
21
|
&__vdisks-item {
|
22
22
|
flex-basis: 5px;
|
23
23
|
flex-shrink: 0;
|
24
|
+
|
25
|
+
.stack__layer {
|
26
|
+
background: var(--yc-color-base-background);
|
27
|
+
|
28
|
+
.data-table__row:hover & {
|
29
|
+
background: var(--ydb-data-table-color-hover);
|
30
|
+
}
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
&__donors-stack {
|
35
|
+
--ydb-stack-offset-x: 0px;
|
36
|
+
--ydb-stack-offset-y: -2px;
|
37
|
+
--ydb-stack-offset-x-hover: 0px;
|
38
|
+
--ydb-stack-offset-y-hover: -7px;
|
24
39
|
}
|
25
40
|
|
26
41
|
&__media-type {
|
@@ -2,6 +2,7 @@ import React, {useEffect, useState, useRef, useMemo} from 'react';
|
|
2
2
|
import cn from 'bem-cn-lite';
|
3
3
|
|
4
4
|
import {InternalLink} from '../../../components/InternalLink';
|
5
|
+
import {Stack} from '../../../components/Stack/Stack';
|
5
6
|
|
6
7
|
import routes, {createHref} from '../../../routes';
|
7
8
|
import {getVDisksForPDisk} from '../../../store/reducers/storage';
|
@@ -10,6 +11,7 @@ import {TVDiskStateInfo} from '../../../types/api/vdisk';
|
|
10
11
|
import {stringifyVdiskId} from '../../../utils';
|
11
12
|
import {useTypedSelector} from '../../../utils/hooks';
|
12
13
|
import {getPDiskType} from '../../../utils/pdisk';
|
14
|
+
import {isFullVDiksData} from '../../../utils/storage';
|
13
15
|
|
14
16
|
import {STRUCTURE} from '../../Node/NodePages';
|
15
17
|
|
@@ -109,19 +111,42 @@ export const PDisk = ({nodeId, data: rawData = {}}: PDiskProps) => {
|
|
109
111
|
|
110
112
|
return (
|
111
113
|
<div className={b('vdisks')}>
|
112
|
-
{vdisks.map((vdisk) =>
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
114
|
+
{vdisks.map((vdisk) => {
|
115
|
+
const donors = vdisk.Donors;
|
116
|
+
|
117
|
+
return (
|
118
|
+
<div
|
119
|
+
key={stringifyVdiskId(vdisk.VDiskId)}
|
120
|
+
className={b('vdisks-item')}
|
121
|
+
style={{
|
122
|
+
// 1 is small enough for empty disks to be of the minimum width
|
123
|
+
// but if all of them are empty, `flex-grow: 1` would size them evenly
|
124
|
+
flexGrow: Number(vdisk.AllocatedSize) || 1,
|
125
|
+
}}
|
126
|
+
>
|
127
|
+
{donors && donors.length ? (
|
128
|
+
<Stack className={b('donors-stack')} key={stringifyVdiskId(vdisk.VDiskId)}>
|
129
|
+
<VDisk data={vdisk} compact />
|
130
|
+
{donors.map((donor) => {
|
131
|
+
const isFullData = isFullVDiksData(donor);
|
132
|
+
|
133
|
+
return (
|
134
|
+
<VDisk
|
135
|
+
compact
|
136
|
+
data={isFullData ? donor : {...donor, DonorMode: true}}
|
137
|
+
key={stringifyVdiskId(
|
138
|
+
isFullData ? donor.VDiskId : donor,
|
139
|
+
)}
|
140
|
+
/>
|
141
|
+
);
|
142
|
+
})}
|
143
|
+
</Stack>
|
144
|
+
) : (
|
145
|
+
<VDisk data={vdisk} compact />
|
146
|
+
)}
|
147
|
+
</div>
|
148
|
+
);
|
149
|
+
})}
|
125
150
|
</div>
|
126
151
|
);
|
127
152
|
};
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import block from 'bem-cn-lite';
|
2
|
-
import {useCallback, useEffect, useMemo,
|
2
|
+
import {useCallback, useEffect, useMemo, useState} from 'react';
|
3
3
|
import {useDispatch} from 'react-redux';
|
4
4
|
import {escapeRegExp} from 'lodash/fp';
|
5
5
|
|
@@ -53,8 +53,6 @@ export const Partitions = ({path, type, nodes, consumers}: PartitionsProps) => {
|
|
53
53
|
|
54
54
|
const dispatch = useDispatch();
|
55
55
|
|
56
|
-
const isFirstRenderRef = useRef(true);
|
57
|
-
|
58
56
|
const [generalSearchValue, setGeneralSearchValue] = useState('');
|
59
57
|
const [partitionIdSearchValue, setPartitionIdSearchValue] = useState('');
|
60
58
|
|
@@ -74,14 +72,6 @@ export const Partitions = ({path, type, nodes, consumers}: PartitionsProps) => {
|
|
74
72
|
useEffect(() => {
|
75
73
|
// Manual path control to ensure it updates with other values so no request with wrong params will be sent
|
76
74
|
setComponentCurrentPath(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
75
|
}, [dispatch, path]);
|
86
76
|
|
87
77
|
const fetchConsumerData = useCallback(
|
@@ -90,11 +80,11 @@ export const Partitions = ({path, type, nodes, consumers}: PartitionsProps) => {
|
|
90
80
|
dispatch(setDataWasNotLoaded());
|
91
81
|
}
|
92
82
|
|
93
|
-
if (selectedConsumer) {
|
83
|
+
if (selectedConsumer && consumers && consumers.includes(selectedConsumer)) {
|
94
84
|
dispatch(getConsumer(componentCurrentPath, selectedConsumer));
|
95
85
|
}
|
96
86
|
},
|
97
|
-
[dispatch, selectedConsumer, componentCurrentPath],
|
87
|
+
[dispatch, selectedConsumer, componentCurrentPath, consumers],
|
98
88
|
);
|
99
89
|
|
100
90
|
useAutofetcher(fetchConsumerData, [fetchConsumerData], autorefresh);
|
@@ -111,10 +101,13 @@ export const Partitions = ({path, type, nodes, consumers}: PartitionsProps) => {
|
|
111
101
|
);
|
112
102
|
|
113
103
|
useEffect(() => {
|
114
|
-
|
104
|
+
const shouldUpdateSelectedConsumer =
|
105
|
+
!selectedConsumer || (consumers && !consumers.includes(selectedConsumer));
|
106
|
+
|
107
|
+
if (consumersToSelect && consumersToSelect.length && shouldUpdateSelectedConsumer) {
|
115
108
|
dispatch(setSelectedConsumer(consumersToSelect[0].value));
|
116
109
|
}
|
117
|
-
}, [dispatch, consumersToSelect, selectedConsumer]);
|
110
|
+
}, [dispatch, consumersToSelect, selectedConsumer, consumers]);
|
118
111
|
|
119
112
|
const selectedColumns: string[] = useMemo(
|
120
113
|
() =>
|
@@ -222,6 +215,7 @@ export const Partitions = ({path, type, nodes, consumers}: PartitionsProps) => {
|
|
222
215
|
options={consumersToSelect}
|
223
216
|
value={[selectedConsumer || '']}
|
224
217
|
onUpdate={handleConsumerSelectChange}
|
218
|
+
filterable={consumers && consumers.length > 5}
|
225
219
|
/>
|
226
220
|
<Search
|
227
221
|
onChange={handlePartitionIdSearchChange}
|
@@ -6,6 +6,7 @@ import type {EPathType} from '../../../../types/api/schema';
|
|
6
6
|
import {useTypedSelector} from '../../../../utils/hooks';
|
7
7
|
|
8
8
|
import {
|
9
|
+
cleanTopicData,
|
9
10
|
getTopic,
|
10
11
|
setDataWasNotLoaded as setTopicDataWasNotLoaded,
|
11
12
|
} from '../../../../store/reducers/topic';
|
@@ -61,6 +62,7 @@ export const PartitionsWrapper = ({path, type}: PartitionsWrapperProps) => {
|
|
61
62
|
|
62
63
|
useEffect(() => {
|
63
64
|
dispatch(setTopicDataWasNotLoaded());
|
65
|
+
dispatch(cleanTopicData());
|
64
66
|
dispatch(setNodesDataWasNotLoaded());
|
65
67
|
|
66
68
|
dispatch(getTopic(path));
|
@@ -18,6 +18,7 @@ import {convertBytesObjectToSpeed} from '../../utils/bytesParsers';
|
|
18
18
|
export const FETCH_TOPIC = createRequestActionTypes('topic', 'FETCH_TOPIC');
|
19
19
|
|
20
20
|
const SET_DATA_WAS_NOT_LOADED = 'topic/SET_DATA_WAS_NOT_LOADED';
|
21
|
+
const CLEAN_TOPIC_DATA = 'topic/CLEAN_TOPIC_DATA';
|
21
22
|
|
22
23
|
const initialState = {
|
23
24
|
loading: true,
|
@@ -64,6 +65,12 @@ const topic: Reducer<ITopicState, ITopicAction> = (state = initialState, action)
|
|
64
65
|
wasLoaded: false,
|
65
66
|
};
|
66
67
|
}
|
68
|
+
case CLEAN_TOPIC_DATA: {
|
69
|
+
return {
|
70
|
+
...state,
|
71
|
+
data: undefined,
|
72
|
+
};
|
73
|
+
}
|
67
74
|
default:
|
68
75
|
return state;
|
69
76
|
}
|
@@ -75,6 +82,12 @@ export const setDataWasNotLoaded = () => {
|
|
75
82
|
} as const;
|
76
83
|
};
|
77
84
|
|
85
|
+
export const cleanTopicData = () => {
|
86
|
+
return {
|
87
|
+
type: CLEAN_TOPIC_DATA,
|
88
|
+
} as const;
|
89
|
+
};
|
90
|
+
|
78
91
|
export function getTopic(path?: string) {
|
79
92
|
return createApiRequest({
|
80
93
|
request: window.api.getTopic({path}),
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import {FETCH_TOPIC, setDataWasNotLoaded} from '../../store/reducers/topic';
|
1
|
+
import {FETCH_TOPIC, cleanTopicData, setDataWasNotLoaded} from '../../store/reducers/topic';
|
2
2
|
import type {ApiRequestAction} from '../../store/utils';
|
3
3
|
import type {IProcessSpeedStats} from '../../utils/bytesParsers';
|
4
4
|
import type {IResponseError} from '../api/error';
|
@@ -31,7 +31,8 @@ export interface ITopicState {
|
|
31
31
|
|
32
32
|
export type ITopicAction =
|
33
33
|
| ApiRequestAction<typeof FETCH_TOPIC, DescribeTopicResult, IResponseError>
|
34
|
-
| ReturnType<typeof setDataWasNotLoaded
|
34
|
+
| ReturnType<typeof setDataWasNotLoaded>
|
35
|
+
| ReturnType<typeof cleanTopicData>;
|
35
36
|
|
36
37
|
export interface ITopicRootStateSlice {
|
37
38
|
topic: ITopicState;
|