ydb-embedded-ui 2.4.4 → 2.6.0
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 +42 -0
- package/dist/components/InfoViewer/InfoViewer.scss +3 -3
- package/dist/components/InfoViewer/formatters/schema.ts +2 -1
- package/dist/components/InfoViewer/schemaInfo/CDCStreamInfo.tsx +23 -22
- package/dist/components/InfoViewer/schemaInfo/PersQueueGroupInfo.tsx +8 -13
- package/dist/components/InfoViewer/schemaInfo/TableIndexInfo.tsx +2 -12
- package/dist/components/InfoViewer/schemaOverview/CDCStreamOverview.tsx +3 -16
- package/dist/components/InfoViewer/schemaOverview/PersQueueGroupOverview.tsx +8 -13
- package/dist/components/InfoViewer/utils.ts +6 -6
- package/dist/components/Loader/Loader.scss +6 -3
- package/dist/components/Loader/Loader.tsx +7 -5
- package/dist/components/Loader/index.ts +1 -0
- package/dist/components/UptimeFIlter/UptimeFilter.tsx +21 -0
- package/dist/components/UptimeFIlter/index.ts +1 -0
- package/dist/containers/Node/Node.scss +1 -0
- package/dist/containers/Node/Node.tsx +3 -8
- package/dist/containers/Node/NodeStructure/NodeStructure.scss +0 -6
- package/dist/containers/Node/NodeStructure/NodeStructure.tsx +1 -1
- package/dist/containers/Nodes/Nodes.js +22 -10
- package/dist/{components → containers}/NodesViewer/NodesViewer.js +49 -62
- package/dist/{components → containers}/NodesViewer/NodesViewer.scss +0 -0
- package/dist/containers/Storage/Pdisk/Pdisk.scss +1 -1
- package/dist/containers/Storage/Pdisk/Pdisk.tsx +3 -9
- package/dist/containers/Storage/Pdisk/__tests__/colors.tsx +1 -1
- package/dist/containers/Storage/Storage.js +46 -11
- package/dist/containers/Storage/StorageGroups/StorageGroups.tsx +39 -32
- package/dist/containers/Storage/StorageNodes/StorageNodes.scss +2 -2
- package/dist/containers/Storage/StorageNodes/StorageNodes.tsx +35 -17
- package/dist/containers/Storage/StorageNodes/i18n/en.json +6 -4
- package/dist/containers/Storage/StorageNodes/i18n/ru.json +6 -4
- package/dist/containers/Storage/UsageFilter/UsageFilter.scss +10 -5
- package/dist/containers/Tenant/Acl/Acl.js +1 -7
- package/dist/containers/Tenant/Diagnostics/Compute/Compute.js +22 -14
- package/dist/containers/Tenant/Diagnostics/Consumers/Consumers.tsx +52 -10
- package/dist/containers/Tenant/Diagnostics/Describe/Describe.scss +0 -8
- package/dist/containers/Tenant/Diagnostics/Describe/Describe.tsx +42 -15
- package/dist/containers/Tenant/Diagnostics/Diagnostics.scss +0 -7
- package/dist/containers/Tenant/Diagnostics/Diagnostics.tsx +19 -15
- package/dist/containers/Tenant/Diagnostics/DiagnosticsPages.ts +1 -1
- package/dist/containers/Tenant/Diagnostics/Healthcheck/Healthcheck.tsx +13 -5
- package/dist/containers/Tenant/Diagnostics/Network/Network.js +17 -4
- package/dist/containers/Tenant/Diagnostics/Overview/Overview.tsx +50 -16
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.js +16 -2
- package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.js +1 -0
- package/dist/containers/Tenant/Diagnostics/TopShards/TopShards.js +21 -13
- package/dist/containers/Tenant/ObjectGeneral/ObjectGeneral.tsx +1 -5
- package/dist/containers/Tenant/QueryEditor/QueryExplain/QueryExplain.js +4 -4
- package/dist/containers/Tenant/QueryEditor/SaveQuery/SaveQuery.js +1 -4
- package/dist/containers/Tenant/Schema/SchemaInfoViewer/SchemaInfoViewer.js +23 -28
- package/dist/containers/Tenant/Schema/SchemaTree/SchemaTree.tsx +2 -2
- package/dist/containers/Tenant/TenantPages.tsx +1 -1
- package/dist/containers/Tenant/utils/schema.ts +84 -0
- package/dist/containers/Tenant/utils/schemaActions.ts +9 -20
- package/dist/services/api.d.ts +17 -11
- package/dist/store/reducers/clusterNodes.js +29 -10
- package/dist/store/reducers/describe.ts +56 -14
- package/dist/store/reducers/healthcheckInfo.ts +23 -8
- package/dist/store/reducers/network.js +22 -1
- package/dist/store/reducers/nodes.js +37 -3
- package/dist/store/reducers/schema.ts +229 -0
- package/dist/store/reducers/storage.js +59 -5
- package/dist/types/api/enums.ts +10 -0
- package/dist/types/api/nodes.ts +96 -0
- package/dist/types/api/pdisk.ts +48 -0
- package/dist/types/api/schema.ts +148 -9
- package/dist/types/api/storage.ts +3 -173
- package/dist/types/api/tablet.ts +97 -0
- package/dist/types/api/vdisk.ts +120 -0
- package/dist/types/store/describe.ts +8 -2
- package/dist/types/store/healthcheck.ts +12 -0
- package/dist/types/store/schema.ts +52 -0
- package/dist/utils/index.js +6 -2
- package/dist/utils/nodes.ts +9 -0
- package/dist/utils/pdisk.ts +1 -1
- package/dist/utils/storage.ts +1 -1
- package/package.json +1 -1
- package/dist/store/reducers/schema.js +0 -148
@@ -1,28 +1,46 @@
|
|
1
1
|
import React from 'react';
|
2
2
|
import cn from 'bem-cn-lite';
|
3
3
|
import PropTypes from 'prop-types';
|
4
|
-
import _ from 'lodash';
|
5
4
|
import {connect} from 'react-redux';
|
6
5
|
|
7
6
|
import {TextInput, Label} from '@gravity-ui/uikit';
|
8
7
|
import DataTable from '@yandex-cloud/react-data-table';
|
9
8
|
|
10
|
-
import ProblemFilter, {problemFilterType} from '
|
9
|
+
import ProblemFilter, {problemFilterType} from '../../components/ProblemFilter/ProblemFilter';
|
10
|
+
import {UptimeFilter} from '../../components/UptimeFIlter';
|
11
|
+
import {Illustration} from '../../components/Illustration';
|
11
12
|
|
12
13
|
import {withSearch} from '../../HOCS';
|
13
14
|
import {calcUptime} from '../../utils';
|
14
|
-
import {
|
15
|
+
import {DEFAULT_TABLE_SETTINGS} from '../../utils/constants';
|
15
16
|
import {changeFilter} from '../../store/reducers/settings';
|
17
|
+
import {filterNodesByStatusAndUptime} from '../../store/reducers/clusterNodes';
|
18
|
+
import {setNodesUptimeFilter} from '../../store/reducers/nodes';
|
16
19
|
import {hideTooltip, showTooltip} from '../../store/reducers/tooltip';
|
17
20
|
import {getNodesColumns} from '../../utils/getNodesColumns';
|
18
21
|
|
19
|
-
import {Illustration} from '../Illustration';
|
20
|
-
|
21
22
|
import './NodesViewer.scss';
|
22
23
|
|
23
24
|
const b = cn('nodes-viewer');
|
24
25
|
|
25
26
|
class NodesViewer extends React.PureComponent {
|
27
|
+
static selectNodesToShow(nodes, searchQuery) {
|
28
|
+
let preparedNodes = nodes;
|
29
|
+
if (nodes && Array.isArray(nodes)) {
|
30
|
+
preparedNodes = nodes
|
31
|
+
.map((node) => {
|
32
|
+
node.uptime = calcUptime(node.StartTime);
|
33
|
+
return node;
|
34
|
+
})
|
35
|
+
/* Filter by nodes with the Host field.
|
36
|
+
If a node does not have a Host field it is also
|
37
|
+
included in the filter and displayed with a dash in the corresponding column
|
38
|
+
*/
|
39
|
+
.filter((node) => (node.Host ? node.Host.includes(searchQuery) : true));
|
40
|
+
}
|
41
|
+
return preparedNodes;
|
42
|
+
}
|
43
|
+
|
26
44
|
static propTypes = {
|
27
45
|
nodes: PropTypes.array.isRequired,
|
28
46
|
className: PropTypes.string,
|
@@ -30,7 +48,9 @@ class NodesViewer extends React.PureComponent {
|
|
30
48
|
handleSearchQuery: PropTypes.func,
|
31
49
|
showTooltip: PropTypes.func,
|
32
50
|
hideTooltip: PropTypes.func,
|
33
|
-
|
51
|
+
problemFilter: problemFilterType,
|
52
|
+
nodesUptimeFilter: PropTypes.string,
|
53
|
+
setNodesUptimeFilter: PropTypes.func,
|
34
54
|
changeFilter: PropTypes.func,
|
35
55
|
showControls: PropTypes.bool,
|
36
56
|
additionalNodesInfo: PropTypes.object,
|
@@ -42,60 +62,18 @@ class NodesViewer extends React.PureComponent {
|
|
42
62
|
showControls: true,
|
43
63
|
};
|
44
64
|
|
45
|
-
|
46
|
-
|
47
|
-
nodesToShow: [],
|
65
|
+
handleProblemFilterChange = (value) => {
|
66
|
+
this.props.changeFilter(value);
|
48
67
|
};
|
49
68
|
|
50
|
-
|
51
|
-
|
52
|
-
if (!_.isEqual(nodes, state.nodes)) {
|
53
|
-
return {
|
54
|
-
nodes,
|
55
|
-
filteredNodes: NodesViewer.filterNodes(nodes, filter),
|
56
|
-
};
|
57
|
-
}
|
58
|
-
return null;
|
59
|
-
}
|
60
|
-
|
61
|
-
static filterNodes(nodes, filter) {
|
62
|
-
if (filter === ALL) {
|
63
|
-
return nodes;
|
64
|
-
}
|
65
|
-
|
66
|
-
return _.filter(nodes, (node) => {
|
67
|
-
return node.Overall && node.Overall !== 'Green';
|
68
|
-
});
|
69
|
-
}
|
70
|
-
|
71
|
-
static selectNodesToShow(nodes, searchQuery) {
|
72
|
-
let preparedNodes = nodes;
|
73
|
-
if (nodes && Array.isArray(nodes)) {
|
74
|
-
preparedNodes = nodes
|
75
|
-
.map((node) => {
|
76
|
-
node.uptime = calcUptime(node.StartTime);
|
77
|
-
return node;
|
78
|
-
})
|
79
|
-
/* Filter by nodes with the Host field.
|
80
|
-
If a node does not have a Host field it is also
|
81
|
-
included in the filter and displayed with a dash in the corresponding column
|
82
|
-
*/
|
83
|
-
.filter((node) => (node.Host ? node.Host.includes(searchQuery) : true));
|
84
|
-
}
|
85
|
-
return preparedNodes;
|
86
|
-
}
|
87
|
-
|
88
|
-
onChangeProblemFilter = (filter) => {
|
89
|
-
const {nodes, changeFilter} = this.props;
|
90
|
-
const filteredNodes = NodesViewer.filterNodes(nodes, filter);
|
91
|
-
|
92
|
-
changeFilter(filter);
|
93
|
-
this.setState({filteredNodes});
|
69
|
+
handleUptimeFilterChange = (value) => {
|
70
|
+
this.props.setNodesUptimeFilter(value);
|
94
71
|
};
|
95
72
|
|
96
73
|
renderControls() {
|
97
|
-
const {searchQuery, handleSearchQuery,
|
98
|
-
|
74
|
+
const {nodes, searchQuery, handleSearchQuery, nodesUptimeFilter, problemFilter} =
|
75
|
+
this.props;
|
76
|
+
const nodesToShow = NodesViewer.selectNodesToShow(nodes, searchQuery);
|
99
77
|
|
100
78
|
return (
|
101
79
|
<div className={b('controls')}>
|
@@ -108,7 +86,8 @@ class NodesViewer extends React.PureComponent {
|
|
108
86
|
hasClear
|
109
87
|
autoFocus
|
110
88
|
/>
|
111
|
-
<ProblemFilter value={
|
89
|
+
<ProblemFilter value={problemFilter} onChange={this.handleProblemFilterChange} />
|
90
|
+
<UptimeFilter value={nodesUptimeFilter} onChange={this.handleUptimeFilterChange} />
|
112
91
|
<Label theme="info" size="m">{`Nodes: ${nodesToShow.length}`}</Label>
|
113
92
|
</div>
|
114
93
|
);
|
@@ -119,13 +98,13 @@ class NodesViewer extends React.PureComponent {
|
|
119
98
|
className,
|
120
99
|
searchQuery,
|
121
100
|
path,
|
122
|
-
|
101
|
+
problemFilter,
|
123
102
|
showControls,
|
124
103
|
hideTooltip,
|
125
104
|
showTooltip,
|
126
105
|
additionalNodesInfo = {},
|
106
|
+
nodes,
|
127
107
|
} = this.props;
|
128
|
-
const {filteredNodes = []} = this.state;
|
129
108
|
|
130
109
|
const columns = getNodesColumns({
|
131
110
|
tabletsPath: path,
|
@@ -134,7 +113,7 @@ class NodesViewer extends React.PureComponent {
|
|
134
113
|
getNodeRef: additionalNodesInfo.getNodeRef,
|
135
114
|
});
|
136
115
|
|
137
|
-
const nodesToShow = NodesViewer.selectNodesToShow(
|
116
|
+
const nodesToShow = NodesViewer.selectNodesToShow(nodes, searchQuery);
|
138
117
|
|
139
118
|
return (
|
140
119
|
<div className={`${b()} ${className}`}>
|
@@ -146,7 +125,7 @@ class NodesViewer extends React.PureComponent {
|
|
146
125
|
<div className={b('table-content')}>
|
147
126
|
<DataTable
|
148
127
|
theme="yandex-cloud"
|
149
|
-
key={
|
128
|
+
key={problemFilter}
|
150
129
|
data={nodesToShow}
|
151
130
|
columns={columns}
|
152
131
|
settings={DEFAULT_TABLE_SETTINGS}
|
@@ -160,9 +139,16 @@ class NodesViewer extends React.PureComponent {
|
|
160
139
|
}
|
161
140
|
}
|
162
141
|
|
163
|
-
const mapStateToProps = (state) => {
|
142
|
+
const mapStateToProps = (state, ownProps) => {
|
143
|
+
const {nodesUptimeFilter} = state.nodes;
|
144
|
+
const {problemFilter} = state.settings;
|
145
|
+
|
146
|
+
const nodes = filterNodesByStatusAndUptime(ownProps.nodes, problemFilter, nodesUptimeFilter);
|
147
|
+
|
164
148
|
return {
|
165
|
-
|
149
|
+
problemFilter,
|
150
|
+
nodesUptimeFilter,
|
151
|
+
nodes,
|
166
152
|
};
|
167
153
|
};
|
168
154
|
|
@@ -170,6 +156,7 @@ const mapDispatchToProps = {
|
|
170
156
|
changeFilter,
|
171
157
|
hideTooltip,
|
172
158
|
showTooltip,
|
159
|
+
setNodesUptimeFilter,
|
173
160
|
};
|
174
161
|
|
175
162
|
const ConnectedNodesViewer = connect(mapStateToProps, mapDispatchToProps)(NodesViewer);
|
File without changes
|
@@ -8,7 +8,7 @@ import InternalLink from '../../../components/InternalLink/InternalLink';
|
|
8
8
|
|
9
9
|
import routes, {createHref} from '../../../routes';
|
10
10
|
import type {RequiredField} from '../../../types';
|
11
|
-
import {TPDiskStateInfo, TPDiskState} from '../../../types/api/
|
11
|
+
import {TPDiskStateInfo, TPDiskState} from '../../../types/api/pdisk';
|
12
12
|
import {getPDiskId} from '../../../utils';
|
13
13
|
import {getPDiskType} from '../../../utils/pdisk';
|
14
14
|
import {bytesToGB} from '../../../utils/utils';
|
@@ -96,9 +96,7 @@ function Pdisk(props: PDiskProps) {
|
|
96
96
|
Realtime &&
|
97
97
|
errorColors.includes(Realtime) &&
|
98
98
|
pdiskData.push({label: 'Realtime', value: Realtime});
|
99
|
-
Device &&
|
100
|
-
errorColors.includes(Device) &&
|
101
|
-
pdiskData.push({label: 'Device', value: Device});
|
99
|
+
Device && errorColors.includes(Device) && pdiskData.push({label: 'Device', value: Device});
|
102
100
|
return pdiskData;
|
103
101
|
};
|
104
102
|
/* eslint-enable */
|
@@ -113,11 +111,7 @@ function Pdisk(props: PDiskProps) {
|
|
113
111
|
// matches the default offset for popup with arrow out of a sense of beauty
|
114
112
|
offset={[0, 12]}
|
115
113
|
>
|
116
|
-
<InfoViewer
|
117
|
-
title="PDisk"
|
118
|
-
info={preparePdiskData()}
|
119
|
-
size="s"
|
120
|
-
/>
|
114
|
+
<InfoViewer title="PDisk" info={preparePdiskData()} size="s" />
|
121
115
|
</Popup>
|
122
116
|
);
|
123
117
|
|
@@ -2,7 +2,7 @@ import {MemoryRouter} from 'react-router-dom';
|
|
2
2
|
|
3
3
|
import {renderWithStore} from '../../../../utils/tests/providers';
|
4
4
|
|
5
|
-
import {TPDiskState} from '../../../../types/api/
|
5
|
+
import {TPDiskState} from '../../../../types/api/pdisk'
|
6
6
|
|
7
7
|
import PDisk from '../Pdisk'
|
8
8
|
|
@@ -8,7 +8,9 @@ import {RadioButton, Label} from '@gravity-ui/uikit';
|
|
8
8
|
import {Search} from '../../components/Search';
|
9
9
|
import {UsageFilter} from './UsageFilter';
|
10
10
|
import {AutoFetcher} from '../../utils/autofetcher';
|
11
|
+
import {NodesUptimeFilterValues} from '../../utils/nodes';
|
11
12
|
import {TableSkeleton} from '../../components/TableSkeleton/TableSkeleton';
|
13
|
+
import {UptimeFilter} from '../../components/UptimeFIlter';
|
12
14
|
import {AccessDenied} from '../../components/Errors/403';
|
13
15
|
|
14
16
|
import {
|
@@ -22,6 +24,8 @@ import {
|
|
22
24
|
getNodesObject,
|
23
25
|
StorageTypes,
|
24
26
|
setStorageType,
|
27
|
+
setNodesUptimeFilter,
|
28
|
+
setDataWasNotLoaded,
|
25
29
|
VisibleEntitiesTitles,
|
26
30
|
getStoragePoolsGroupsCount,
|
27
31
|
getStorageNodesCount,
|
@@ -66,6 +70,9 @@ class Storage extends React.Component {
|
|
66
70
|
setHeader: PropTypes.func,
|
67
71
|
tenant: PropTypes.string,
|
68
72
|
nodeId: PropTypes.string,
|
73
|
+
nodesUptimeFilter: PropTypes.string,
|
74
|
+
setNodesUptimeFilter: PropTypes.func,
|
75
|
+
setDataWasNotLoaded: PropTypes.func,
|
69
76
|
};
|
70
77
|
|
71
78
|
componentDidMount() {
|
@@ -101,7 +108,8 @@ class Storage extends React.Component {
|
|
101
108
|
}
|
102
109
|
|
103
110
|
componentDidUpdate(prevProps) {
|
104
|
-
const {visibleEntities, storageType, autorefresh, database} =
|
111
|
+
const {visibleEntities, storageType, autorefresh, database, tenant, setDataWasNotLoaded} =
|
112
|
+
this.props;
|
105
113
|
|
106
114
|
const startFetch = () => {
|
107
115
|
this.getStorageInfo({
|
@@ -139,6 +147,12 @@ class Storage extends React.Component {
|
|
139
147
|
restartAutorefresh();
|
140
148
|
}
|
141
149
|
}
|
150
|
+
|
151
|
+
if (tenant !== prevProps.tenant) {
|
152
|
+
setDataWasNotLoaded();
|
153
|
+
startFetch();
|
154
|
+
restartAutorefresh();
|
155
|
+
}
|
142
156
|
}
|
143
157
|
|
144
158
|
componentWillUnmount() {
|
@@ -166,7 +180,8 @@ class Storage extends React.Component {
|
|
166
180
|
}
|
167
181
|
|
168
182
|
renderDataTable() {
|
169
|
-
const {flatListStorageEntities, visibleEntities, nodes, storageType} =
|
183
|
+
const {flatListStorageEntities, visibleEntities, nodesUptimeFilter, nodes, storageType} =
|
184
|
+
this.props;
|
170
185
|
|
171
186
|
return (
|
172
187
|
<div className={b('table-wrapper')}>
|
@@ -182,9 +197,10 @@ class Storage extends React.Component {
|
|
182
197
|
{storageType === StorageTypes.nodes && (
|
183
198
|
<StorageNodes
|
184
199
|
visibleEntities={visibleEntities}
|
200
|
+
nodesUptimeFilter={nodesUptimeFilter}
|
185
201
|
data={flatListStorageEntities}
|
186
202
|
tableSettings={tableSettings}
|
187
|
-
onShowAll={
|
203
|
+
onShowAll={this.onShowAllNodes}
|
188
204
|
/>
|
189
205
|
)}
|
190
206
|
</div>
|
@@ -201,6 +217,15 @@ class Storage extends React.Component {
|
|
201
217
|
setStorageType(value);
|
202
218
|
};
|
203
219
|
|
220
|
+
onUptimeFilterChange = (value) => {
|
221
|
+
this.props.setNodesUptimeFilter(value);
|
222
|
+
};
|
223
|
+
|
224
|
+
onShowAllNodes = () => {
|
225
|
+
this.onGroupVisibilityChange(VisibleEntities.All);
|
226
|
+
this.onUptimeFilterChange(NodesUptimeFilterValues.All);
|
227
|
+
};
|
228
|
+
|
204
229
|
renderEntitiesCount() {
|
205
230
|
const {storageType, groupsCount, nodesCount, flatListStorageEntities, loading, wasLoaded} =
|
206
231
|
this.props;
|
@@ -230,6 +255,7 @@ class Storage extends React.Component {
|
|
230
255
|
visibleEntities,
|
231
256
|
storageType,
|
232
257
|
usageFilter,
|
258
|
+
nodesUptimeFilter,
|
233
259
|
setUsageFilter,
|
234
260
|
usageFilterOptions,
|
235
261
|
} = this.props;
|
@@ -247,6 +273,16 @@ class Storage extends React.Component {
|
|
247
273
|
value={filter}
|
248
274
|
/>
|
249
275
|
</div>
|
276
|
+
|
277
|
+
<RadioButton value={storageType} onUpdate={this.onStorageTypeChange}>
|
278
|
+
<RadioButton.Option value={StorageTypes.groups}>
|
279
|
+
{StorageTypes.groups}
|
280
|
+
</RadioButton.Option>
|
281
|
+
<RadioButton.Option value={StorageTypes.nodes}>
|
282
|
+
{StorageTypes.nodes}
|
283
|
+
</RadioButton.Option>
|
284
|
+
</RadioButton>
|
285
|
+
|
250
286
|
<RadioButton value={visibleEntities} onUpdate={this.onGroupVisibilityChange}>
|
251
287
|
<RadioButton.Option value={VisibleEntities.Missing}>
|
252
288
|
{VisibleEntitiesTitles[VisibleEntities.Missing]}
|
@@ -259,14 +295,9 @@ class Storage extends React.Component {
|
|
259
295
|
</RadioButton.Option>
|
260
296
|
</RadioButton>
|
261
297
|
|
262
|
-
|
263
|
-
<
|
264
|
-
|
265
|
-
</RadioButton.Option>
|
266
|
-
<RadioButton.Option value={StorageTypes.nodes}>
|
267
|
-
{StorageTypes.nodes}
|
268
|
-
</RadioButton.Option>
|
269
|
-
</RadioButton>
|
298
|
+
{storageType === StorageTypes.nodes && (
|
299
|
+
<UptimeFilter value={nodesUptimeFilter} onChange={this.onUptimeFilterChange} />
|
300
|
+
)}
|
270
301
|
|
271
302
|
{storageType === StorageTypes.groups && (
|
272
303
|
<UsageFilter
|
@@ -314,6 +345,7 @@ function mapStateToProps(state) {
|
|
314
345
|
type: storageType,
|
315
346
|
filter,
|
316
347
|
usageFilter,
|
348
|
+
nodesUptimeFilter,
|
317
349
|
} = state.storage;
|
318
350
|
|
319
351
|
return {
|
@@ -329,6 +361,7 @@ function mapStateToProps(state) {
|
|
329
361
|
storageType,
|
330
362
|
filter,
|
331
363
|
usageFilter,
|
364
|
+
nodesUptimeFilter,
|
332
365
|
usageFilterOptions: getUsageFilterOptions(state),
|
333
366
|
};
|
334
367
|
}
|
@@ -339,9 +372,11 @@ const mapDispatchToProps = {
|
|
339
372
|
setStorageFilter,
|
340
373
|
setUsageFilter,
|
341
374
|
setVisibleEntities: setVisibleEntities,
|
375
|
+
setNodesUptimeFilter,
|
342
376
|
getNodesList,
|
343
377
|
setStorageType,
|
344
378
|
setHeader,
|
379
|
+
setDataWasNotLoaded,
|
345
380
|
};
|
346
381
|
|
347
382
|
export default connect(mapStateToProps, mapDispatchToProps)(Storage);
|
@@ -9,7 +9,7 @@ import {Stack} from '../../../components/Stack/Stack';
|
|
9
9
|
//@ts-ignore
|
10
10
|
import EntityStatus from '../../../components/EntityStatus/EntityStatus';
|
11
11
|
|
12
|
-
import {TVDiskStateInfo} from '../../../types/api/
|
12
|
+
import {TVDiskStateInfo} from '../../../types/api/vdisk';
|
13
13
|
//@ts-ignore
|
14
14
|
import {VisibleEntities} from '../../../store/reducers/storage';
|
15
15
|
//@ts-ignore
|
@@ -92,7 +92,13 @@ function setSortOrder(visibleEntities: keyof typeof VisibleEntities): SortOrder
|
|
92
92
|
}
|
93
93
|
}
|
94
94
|
|
95
|
-
function StorageGroups({
|
95
|
+
function StorageGroups({
|
96
|
+
data,
|
97
|
+
tableSettings,
|
98
|
+
visibleEntities,
|
99
|
+
nodes,
|
100
|
+
onShowAll,
|
101
|
+
}: StorageGroupsProps) {
|
96
102
|
const allColumns: Column<any>[] = [
|
97
103
|
{
|
98
104
|
name: TableColumnsIds.PoolName,
|
@@ -123,7 +129,7 @@ function StorageGroups({data, tableSettings, visibleEntities, nodes, onShowAll}:
|
|
123
129
|
header: tableColumnsNames[TableColumnsIds.Type],
|
124
130
|
render: ({value, row}) => (
|
125
131
|
<>
|
126
|
-
<Label>{value as string || '—'}</Label>
|
132
|
+
<Label>{(value as string) || '—'}</Label>
|
127
133
|
{' '}
|
128
134
|
{row.Encryption && (
|
129
135
|
<Popover
|
@@ -143,9 +149,8 @@ function StorageGroups({data, tableSettings, visibleEntities, nodes, onShowAll}:
|
|
143
149
|
name: TableColumnsIds.Missing,
|
144
150
|
header: tableColumnsNames[TableColumnsIds.Missing],
|
145
151
|
width: 100,
|
146
|
-
render: ({value, row}) =>
|
147
|
-
<Label theme={getDegradedSeverity(row)}>Degraded: {value}</Label>
|
148
|
-
) : '-',
|
152
|
+
render: ({value, row}) =>
|
153
|
+
value ? <Label theme={getDegradedSeverity(row)}>Degraded: {value}</Label> : '-',
|
149
154
|
align: DataTable.LEFT,
|
150
155
|
defaultOrder: DataTable.DESCENDING,
|
151
156
|
},
|
@@ -164,10 +169,12 @@ function StorageGroups({data, tableSettings, visibleEntities, nodes, onShowAll}:
|
|
164
169
|
>
|
165
170
|
{usage}%
|
166
171
|
</Label>
|
167
|
-
) :
|
172
|
+
) : (
|
173
|
+
'-'
|
174
|
+
);
|
168
175
|
},
|
169
176
|
// without a limit exclude usage from sort to display at the bottom
|
170
|
-
sortAccessor: (row) => row.Limit ? getUsage(row) : null,
|
177
|
+
sortAccessor: (row) => (row.Limit ? getUsage(row) : null),
|
171
178
|
align: DataTable.LEFT,
|
172
179
|
},
|
173
180
|
{
|
@@ -241,35 +248,35 @@ function StorageGroups({data, tableSettings, visibleEntities, nodes, onShowAll}:
|
|
241
248
|
render: ({value, row}) => (
|
242
249
|
<div className={b('vdisks-wrapper')}>
|
243
250
|
{_.map(value as TVDiskStateInfo[], (el) => {
|
244
|
-
const donors = Array.isArray(el.Donors)
|
251
|
+
const donors = Array.isArray(el.Donors)
|
252
|
+
? el.Donors.filter(isFullDonorData)
|
253
|
+
: [];
|
245
254
|
|
246
|
-
return (
|
247
|
-
|
248
|
-
<
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
{donors.map((donor) => (
|
255
|
-
<Vdisk
|
256
|
-
{...donor}
|
257
|
-
// donor and acceptor are always in the same group
|
258
|
-
PoolName={row[TableColumnsIds.PoolName]}
|
259
|
-
nodes={nodes}
|
260
|
-
key={stringifyVdiskId(donor.VDiskId)}
|
261
|
-
/>
|
262
|
-
))}
|
263
|
-
</Stack>
|
264
|
-
) : (
|
265
|
-
<div className={b('vdisks-item')} key={stringifyVdiskId(el.VDiskId)}>
|
255
|
+
return donors.length > 0 ? (
|
256
|
+
<Stack className={b('vdisks-item')} key={stringifyVdiskId(el.VDiskId)}>
|
257
|
+
<Vdisk
|
258
|
+
{...el}
|
259
|
+
PoolName={row[TableColumnsIds.PoolName]}
|
260
|
+
nodes={nodes}
|
261
|
+
/>
|
262
|
+
{donors.map((donor) => (
|
266
263
|
<Vdisk
|
267
|
-
{...
|
264
|
+
{...donor}
|
265
|
+
// donor and acceptor are always in the same group
|
268
266
|
PoolName={row[TableColumnsIds.PoolName]}
|
269
267
|
nodes={nodes}
|
268
|
+
key={stringifyVdiskId(donor.VDiskId)}
|
270
269
|
/>
|
271
|
-
|
272
|
-
|
270
|
+
))}
|
271
|
+
</Stack>
|
272
|
+
) : (
|
273
|
+
<div className={b('vdisks-item')} key={stringifyVdiskId(el.VDiskId)}>
|
274
|
+
<Vdisk
|
275
|
+
{...el}
|
276
|
+
PoolName={row[TableColumnsIds.PoolName]}
|
277
|
+
nodes={nodes}
|
278
|
+
/>
|
279
|
+
</div>
|
273
280
|
);
|
274
281
|
})}
|
275
282
|
</div>
|
@@ -5,6 +5,7 @@ import DataTable, {Column, Settings, SortOrder} from '@yandex-cloud/react-data-t
|
|
5
5
|
import {Popover, PopoverBehavior} from '@gravity-ui/uikit';
|
6
6
|
|
7
7
|
import {VisibleEntities} from '../../../store/reducers/storage';
|
8
|
+
import {NodesUptimeFilterValues} from '../../../utils/nodes';
|
8
9
|
|
9
10
|
import {EmptyFilter} from '../EmptyFilter/EmptyFilter';
|
10
11
|
import Pdisk from '../Pdisk/Pdisk';
|
@@ -28,6 +29,7 @@ interface StorageNodesProps {
|
|
28
29
|
nodes: any;
|
29
30
|
tableSettings: Settings;
|
30
31
|
visibleEntities: keyof typeof VisibleEntities;
|
32
|
+
nodesUptimeFilter: keyof typeof NodesUptimeFilterValues;
|
31
33
|
onShowAll?: VoidFunction;
|
32
34
|
}
|
33
35
|
|
@@ -61,7 +63,13 @@ function setSortOrder(visibleEntities: keyof typeof VisibleEntities): SortOrder
|
|
61
63
|
}
|
62
64
|
}
|
63
65
|
|
64
|
-
function StorageNodes({
|
66
|
+
function StorageNodes({
|
67
|
+
data,
|
68
|
+
tableSettings,
|
69
|
+
visibleEntities,
|
70
|
+
onShowAll,
|
71
|
+
nodesUptimeFilter,
|
72
|
+
}: StorageNodesProps) {
|
65
73
|
const allColumns: Column<any>[] = [
|
66
74
|
{
|
67
75
|
name: TableColumnsIds.NodeId,
|
@@ -124,23 +132,33 @@ function StorageNodes({data, tableSettings, visibleEntities, onShowAll}: Storage
|
|
124
132
|
|
125
133
|
if (visibleEntities === VisibleEntities.Space) {
|
126
134
|
columns = allColumns.filter((col) => col.name !== TableColumnsIds.Missing);
|
127
|
-
|
128
|
-
return (
|
129
|
-
<EmptyFilter
|
130
|
-
title={i18n('empty.out_of_space')}
|
131
|
-
showAll={i18n('show_all')}
|
132
|
-
onShowAll={onShowAll}
|
133
|
-
/>
|
134
|
-
);
|
135
135
|
}
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
136
|
+
|
137
|
+
if (!data.length) {
|
138
|
+
let message;
|
139
|
+
|
140
|
+
if (visibleEntities === VisibleEntities.Space) {
|
141
|
+
message = i18n('empty.out_of_space');
|
142
|
+
}
|
143
|
+
|
144
|
+
if (visibleEntities === VisibleEntities.Missing) {
|
145
|
+
message = i18n('empty.degraded');
|
146
|
+
}
|
147
|
+
|
148
|
+
if (nodesUptimeFilter === NodesUptimeFilterValues.SmallUptime) {
|
149
|
+
message = i18n('empty.small_uptime');
|
150
|
+
}
|
151
|
+
|
152
|
+
if (
|
153
|
+
visibleEntities !== VisibleEntities.All &&
|
154
|
+
nodesUptimeFilter !== NodesUptimeFilterValues.All
|
155
|
+
) {
|
156
|
+
message = i18n('empty.several_filters');
|
157
|
+
}
|
158
|
+
|
159
|
+
if (message) {
|
160
|
+
return <EmptyFilter title={message} showAll={i18n('show_all')} onShowAll={onShowAll} />;
|
161
|
+
}
|
144
162
|
}
|
145
163
|
|
146
164
|
return data ? (
|
@@ -1,6 +1,8 @@
|
|
1
1
|
{
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
2
|
+
"empty.default": "No such nodes",
|
3
|
+
"empty.out_of_space": "No nodes with out of space errors",
|
4
|
+
"empty.degraded": "No degraded nodes",
|
5
|
+
"empty.small_uptime": "No nodes with uptime < 1h",
|
6
|
+
"empty.several_filters": "No nodes match current filters combination",
|
7
|
+
"show_all": "Show all nodes"
|
6
8
|
}
|
@@ -1,6 +1,8 @@
|
|
1
1
|
{
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
2
|
+
"empty.default": "Нет узлов",
|
3
|
+
"empty.out_of_space": "Нет узлов, в которых кончается место",
|
4
|
+
"empty.degraded": "Нет деградировавших узлов",
|
5
|
+
"empty.small_uptime": "Нет узлов с uptime < 1h",
|
6
|
+
"empty.several_filters": "Нет узлов, подходящих под текущие фильтры",
|
7
|
+
"show_all": "Показать все узлы"
|
6
8
|
}
|