ydb-embedded-ui 3.4.1 → 3.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
- <div
114
- key={stringifyVdiskId(vdisk.VDiskId)}
115
- className={b('vdisks-item')}
116
- style={{
117
- // 1 is small enough for empty disks to be of the minimum width
118
- // but if all of them are empty, `flex-grow: 1` would size them evenly
119
- flexGrow: Number(vdisk.AllocatedSize) || 1,
120
- }}
121
- >
122
- <VDisk data={vdisk} compact />
123
- </div>
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,8 +1,10 @@
1
1
  .global-storage-nodes {
2
+ &__pdisks-column {
3
+ overflow: visible; // to enable stacked disks overflow the row
4
+ }
5
+
2
6
  &__pdisks-wrapper {
3
7
  display: flex;
4
- overflow-x: auto;
5
- overflow-y: hidden;
6
8
  justify-content: left;
7
9
  align-items: flex-end;
8
10
 
@@ -128,6 +128,7 @@ function StorageNodes({
128
128
  },
129
129
  {
130
130
  name: TableColumnsIds.PDisks,
131
+ className: b('pdisks-column'),
131
132
  header: tableColumnsNames[TableColumnsIds.PDisks],
132
133
  render: ({value, row}) => (
133
134
  <div className={b('pdisks-wrapper')}>
@@ -1,5 +1,5 @@
1
1
  import block from 'bem-cn-lite';
2
- import {useCallback, useEffect, useMemo, useRef, useState} from 'react';
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
- if (consumersToSelect && consumersToSelect.length && !selectedConsumer) {
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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ydb-embedded-ui",
3
- "version": "3.4.1",
3
+ "version": "3.4.2",
4
4
  "files": [
5
5
  "dist"
6
6
  ],