ydb-embedded-ui 3.2.3 → 3.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/dist/components/InfoViewer/InfoViewer.scss +10 -0
  3. package/dist/components/InfoViewer/InfoViewer.tsx +12 -2
  4. package/dist/components/InfoViewer/formatters/cdcStream.ts +10 -0
  5. package/dist/components/InfoViewer/formatters/index.ts +3 -0
  6. package/dist/components/InfoViewer/formatters/pqGroup.ts +51 -0
  7. package/dist/components/InfoViewer/formatters/schema.ts +1 -29
  8. package/dist/components/InfoViewer/formatters/topicStats.tsx +50 -0
  9. package/dist/components/InfoViewer/schemaInfo/index.ts +0 -2
  10. package/dist/components/InfoViewer/utils.ts +15 -0
  11. package/dist/components/InternalLink/InternalLink.tsx +17 -0
  12. package/dist/components/InternalLink/index.ts +1 -0
  13. package/dist/components/Tablet/Tablet.js +1 -1
  14. package/dist/components/TabletsStatistic/TabletsStatistic.tsx +1 -1
  15. package/dist/components/VerticalBars/VerticalBars.scss +15 -0
  16. package/dist/components/VerticalBars/VerticalBars.tsx +38 -0
  17. package/dist/components/VerticalBars/index.ts +1 -0
  18. package/dist/containers/App/App.js +0 -11
  19. package/dist/containers/App/App.scss +0 -1
  20. package/dist/containers/Cluster/Cluster.tsx +2 -2
  21. package/dist/containers/Nodes/Nodes.scss +5 -1
  22. package/dist/containers/Nodes/Nodes.tsx +196 -0
  23. package/dist/containers/{App → Nodes}/NodesTable.scss +2 -2
  24. package/dist/{utils/getNodesColumns.js → containers/Nodes/getNodesColumns.tsx} +60 -35
  25. package/dist/containers/Nodes/i18n/en.json +3 -0
  26. package/dist/containers/Nodes/i18n/index.ts +11 -0
  27. package/dist/containers/Nodes/i18n/ru.json +3 -0
  28. package/dist/containers/Nodes/index.ts +1 -0
  29. package/dist/containers/Storage/DiskStateProgressBar/DiskStateProgressBar.scss +14 -20
  30. package/dist/containers/Storage/DiskStateProgressBar/DiskStateProgressBar.tsx +32 -16
  31. package/dist/containers/Storage/DiskStateProgressBar/index.ts +1 -0
  32. package/dist/containers/Storage/{Pdisk/Pdisk.scss → PDisk/PDisk.scss} +15 -4
  33. package/dist/containers/Storage/PDisk/PDisk.tsx +145 -0
  34. package/dist/containers/Storage/PDisk/__tests__/colors.tsx +37 -0
  35. package/dist/containers/Storage/PDisk/index.ts +1 -0
  36. package/dist/containers/Storage/PDiskPopup/PDiskPopup.scss +3 -0
  37. package/dist/containers/Storage/PDiskPopup/PDiskPopup.tsx +82 -0
  38. package/dist/containers/Storage/PDiskPopup/index.ts +1 -0
  39. package/dist/containers/Storage/Storage.js +1 -1
  40. package/dist/containers/Storage/StorageGroups/StorageGroups.tsx +10 -10
  41. package/dist/containers/Storage/StorageNodes/StorageNodes.scss +1 -0
  42. package/dist/containers/Storage/StorageNodes/StorageNodes.tsx +7 -4
  43. package/dist/containers/Storage/VDisk/VDisk.scss +7 -0
  44. package/dist/containers/Storage/VDisk/VDisk.tsx +148 -0
  45. package/dist/containers/Storage/VDisk/__tests__/colors.tsx +209 -0
  46. package/dist/containers/Storage/VDisk/index.ts +1 -0
  47. package/dist/containers/Storage/VDiskPopup/VDiskPopup.scss +14 -0
  48. package/dist/containers/Storage/VDiskPopup/VDiskPopup.tsx +134 -0
  49. package/dist/containers/Storage/VDiskPopup/index.ts +1 -0
  50. package/dist/containers/Storage/utils/constants.ts +2 -9
  51. package/dist/containers/TabletsFilters/TabletsFilters.js +10 -6
  52. package/dist/containers/Tenant/Diagnostics/Diagnostics.scss +2 -2
  53. package/dist/containers/Tenant/Diagnostics/Diagnostics.tsx +3 -4
  54. package/dist/containers/Tenant/Diagnostics/OverloadedShards/OverloadedShards.tsx +1 -1
  55. package/dist/containers/Tenant/Diagnostics/Overview/ChangefeedInfo/ChangefeedInfo.tsx +69 -0
  56. package/dist/containers/Tenant/Diagnostics/Overview/ChangefeedInfo/index.ts +1 -0
  57. package/dist/containers/Tenant/Diagnostics/Overview/Overview.tsx +18 -16
  58. package/dist/containers/Tenant/Diagnostics/Overview/TopicInfo/TopicInfo.tsx +37 -0
  59. package/dist/containers/Tenant/Diagnostics/Overview/TopicInfo/index.ts +1 -0
  60. package/dist/containers/Tenant/Diagnostics/Overview/TopicStats/TopicStats.scss +30 -0
  61. package/dist/containers/Tenant/Diagnostics/Overview/TopicStats/TopicStats.tsx +94 -0
  62. package/dist/containers/Tenant/Diagnostics/Overview/TopicStats/i18n/en.json +3 -0
  63. package/dist/containers/Tenant/Diagnostics/Overview/TopicStats/i18n/index.ts +11 -0
  64. package/dist/containers/Tenant/Diagnostics/Overview/TopicStats/i18n/ru.json +3 -0
  65. package/dist/containers/Tenant/Diagnostics/Overview/TopicStats/index.ts +1 -0
  66. package/dist/containers/Tenant/Diagnostics/Overview/utils/index.ts +1 -0
  67. package/dist/containers/Tenant/Diagnostics/Overview/utils/prepareTopicSchemaInfo.ts +42 -0
  68. package/dist/containers/Tenant/utils/schema.ts +19 -0
  69. package/dist/containers/UserSettings/UserSettings.scss +9 -0
  70. package/dist/containers/UserSettings/UserSettings.tsx +41 -11
  71. package/dist/services/api.d.ts +8 -1
  72. package/dist/services/api.js +27 -8
  73. package/dist/store/reducers/index.ts +3 -1
  74. package/dist/store/reducers/nodes.ts +148 -14
  75. package/dist/store/reducers/{clusterNodes.js → nodesList.js} +0 -41
  76. package/dist/store/reducers/settings.js +10 -4
  77. package/dist/store/reducers/storage.js +24 -13
  78. package/dist/store/reducers/tenant.js +5 -4
  79. package/dist/store/reducers/tooltip.ts +1 -1
  80. package/dist/store/reducers/topic.ts +52 -0
  81. package/dist/styles/mixins.scss +19 -11
  82. package/dist/types/api/common.ts +5 -0
  83. package/dist/types/api/compute.ts +1 -1
  84. package/dist/types/api/consumer.ts +12 -10
  85. package/dist/types/api/nodes.ts +2 -0
  86. package/dist/types/api/pdisk.ts +1 -0
  87. package/dist/types/api/schema.ts +3 -3
  88. package/dist/types/api/topic.ts +5 -4
  89. package/dist/types/api/vdisk.ts +2 -1
  90. package/dist/types/store/nodes.ts +56 -6
  91. package/dist/types/store/tooltip.ts +1 -1
  92. package/dist/types/store/topic.ts +21 -0
  93. package/dist/utils/constants.ts +5 -1
  94. package/dist/utils/i18n/i18n.ts +10 -2
  95. package/dist/utils/index.js +1 -1
  96. package/dist/utils/timeParsers/__test__/formatDuration.test.ts +50 -0
  97. package/dist/utils/timeParsers/__test__/protobuf.test.ts +74 -0
  98. package/dist/utils/timeParsers/formatDuration.ts +46 -0
  99. package/dist/utils/timeParsers/i18n/en.json +7 -0
  100. package/dist/utils/timeParsers/i18n/index.ts +11 -0
  101. package/dist/utils/timeParsers/i18n/ru.json +7 -0
  102. package/dist/utils/timeParsers/index.ts +2 -0
  103. package/dist/utils/timeParsers/protobuf.ts +36 -0
  104. package/package.json +1 -1
  105. package/dist/components/InfoViewer/schemaInfo/CDCStreamInfo.tsx +0 -48
  106. package/dist/components/InfoViewer/schemaInfo/PersQueueGroupInfo.tsx +0 -30
  107. package/dist/components/InternalLink/InternalLink.js +0 -23
  108. package/dist/containers/Nodes/Nodes.js +0 -214
  109. package/dist/containers/NodesViewer/NodesViewer.js +0 -163
  110. package/dist/containers/NodesViewer/NodesViewer.scss +0 -66
  111. package/dist/containers/Storage/Pdisk/Pdisk.tsx +0 -153
  112. package/dist/containers/Storage/Pdisk/__tests__/colors.tsx +0 -41
  113. package/dist/containers/Storage/Vdisk/Vdisk.js +0 -275
  114. package/dist/containers/Storage/Vdisk/Vdisk.scss +0 -22
  115. package/dist/containers/Storage/Vdisk/__tests__/colors.tsx +0 -163
  116. package/dist/containers/Tenant/Diagnostics/Compute/Compute.js +0 -139
  117. package/dist/containers/Tenant/Diagnostics/Compute/Compute.scss +0 -14
@@ -1,214 +0,0 @@
1
- import React from 'react';
2
- import PropTypes from 'prop-types';
3
- import cn from 'bem-cn-lite';
4
- import {connect} from 'react-redux';
5
- import {escapeRegExp} from 'lodash/fp';
6
-
7
- import DataTable from '@yandex-cloud/react-data-table';
8
- import {Loader, TextInput, Label} from '@gravity-ui/uikit';
9
-
10
- import {ProblemFilter} from '../../components/ProblemFilter';
11
- import {Illustration} from '../../components/Illustration';
12
- import {AccessDenied} from '../../components/Errors/403';
13
- import {UptimeFilter} from '../../components/UptimeFIlter';
14
-
15
- import {hideTooltip, showTooltip} from '../../store/reducers/tooltip';
16
- import {withSearch} from '../../HOCS';
17
- import {AUTO_RELOAD_INTERVAL, ALL, DEFAULT_TABLE_SETTINGS} from '../../utils/constants';
18
- import {getFilteredNodes} from '../../store/reducers/clusterNodes';
19
- import {getNodes, setNodesUptimeFilter} from '../../store/reducers/nodes';
20
- import {changeFilter} from '../../store/reducers/settings';
21
- import {setHeader} from '../../store/reducers/header';
22
- import routes, {CLUSTER_PAGES, createHref} from '../../routes';
23
- import {calcUptime} from '../../utils';
24
- import {getNodesColumns} from '../../utils/getNodesColumns';
25
- import {NodesUptimeFilterValues} from '../../utils/nodes';
26
-
27
- import './Nodes.scss';
28
-
29
- const b = cn('cluster-nodes');
30
-
31
- class Nodes extends React.Component {
32
- static renderLoader() {
33
- return (
34
- <div className={'loader'}>
35
- <Loader size="l" />
36
- </div>
37
- );
38
- }
39
-
40
- static propTypes = {
41
- loading: PropTypes.bool,
42
- wasLoaded: PropTypes.bool,
43
- error: PropTypes.bool,
44
- getNodesList: PropTypes.func,
45
- nodes: PropTypes.array,
46
- showTooltip: PropTypes.func,
47
- hideTooltip: PropTypes.func,
48
- searchQuery: PropTypes.string,
49
- handleSearchQuery: PropTypes.func,
50
- problemFilter: PropTypes.string,
51
- changeFilter: PropTypes.func,
52
- setHeader: PropTypes.func,
53
- className: PropTypes.string,
54
- singleClusterMode: PropTypes.bool,
55
- additionalNodesInfo: PropTypes.object,
56
- nodesUptimeFilter: PropTypes.string,
57
- setNodesUptimeFilter: PropTypes.func,
58
- };
59
-
60
- componentDidMount() {
61
- const {getNodesList, setHeader} = this.props;
62
- getNodesList();
63
- this.reloadDescriptor = setInterval(() => getNodesList(), AUTO_RELOAD_INTERVAL);
64
- setHeader([
65
- {
66
- text: CLUSTER_PAGES.nodes.title,
67
- link: createHref(routes.cluster, {activeTab: CLUSTER_PAGES.nodes.id}),
68
- },
69
- ]);
70
- }
71
-
72
- componentWillUnmount() {
73
- this.props.hideTooltip();
74
- clearInterval(this.reloadDescriptor);
75
- }
76
-
77
- handleSearchQueryChange = (search) => {
78
- this.props.handleSearchQuery(search);
79
- };
80
-
81
- handleProblemFilterChange = (value) => {
82
- this.props.changeFilter(value);
83
- };
84
-
85
- handleUptimeFilterChange = (value) => {
86
- this.props.setNodesUptimeFilter(value);
87
- };
88
-
89
- renderControls() {
90
- const {nodes, searchQuery, problemFilter, nodesUptimeFilter} = this.props;
91
-
92
- return (
93
- <div className={b('controls')}>
94
- <TextInput
95
- className={b('search')}
96
- placeholder="Host name"
97
- value={searchQuery}
98
- onUpdate={this.handleSearchQueryChange}
99
- hasClear
100
- autoFocus
101
- />
102
- <ProblemFilter value={problemFilter} onChange={this.handleProblemFilterChange} />
103
- <UptimeFilter value={nodesUptimeFilter} onChange={this.handleUptimeFilterChange} />
104
- <Label theme="info" size="m">{`Nodes: ${nodes?.length}`}</Label>
105
- </div>
106
- );
107
- }
108
-
109
- renderTable = () => {
110
- const {
111
- nodes = [],
112
- problemFilter,
113
- nodesUptimeFilter,
114
- searchQuery,
115
- showTooltip,
116
- hideTooltip,
117
- singleClusterMode,
118
- additionalNodesInfo = {},
119
- } = this.props;
120
-
121
- const columns = getNodesColumns({
122
- showTooltip,
123
- hideTooltip,
124
- singleClusterMode,
125
- getNodeRef: additionalNodesInfo.getNodeRef,
126
- });
127
-
128
- let preparedNodes = searchQuery
129
- ? nodes.filter((node) => {
130
- const re = new RegExp(escapeRegExp(searchQuery), 'i');
131
- return node.Host ? re.test(node.Host) || re.test(String(node.NodeId)) : true;
132
- })
133
- : nodes;
134
- preparedNodes = preparedNodes.map((node) => ({
135
- ...node,
136
- uptime: calcUptime(node.StartTime),
137
- }));
138
-
139
- if (preparedNodes.length === 0) {
140
- if (problemFilter !== ALL || nodesUptimeFilter !== NodesUptimeFilterValues.All) {
141
- return <Illustration name="thumbsUp" width="200" />;
142
- }
143
- }
144
-
145
- return (
146
- <div className={b('table-wrapper')}>
147
- <div className={b('table-content')}>
148
- <DataTable
149
- theme="yandex-cloud"
150
- data={preparedNodes}
151
- columns={columns}
152
- settings={DEFAULT_TABLE_SETTINGS}
153
- initialSortOrder={{
154
- columnId: 'NodeId',
155
- order: DataTable.ASCENDING,
156
- }}
157
- emptyDataMessage="No such nodes"
158
- />
159
- </div>
160
- </div>
161
- );
162
- };
163
-
164
- renderContent = () => {
165
- return (
166
- <div className={b(null, this.props.className)}>
167
- {this.renderControls()}
168
- {this.renderTable()}
169
- </div>
170
- );
171
- };
172
-
173
- render() {
174
- const {loading, wasLoaded, error} = this.props;
175
-
176
- if (loading && !wasLoaded) {
177
- return Nodes.renderLoader();
178
- } else if (error) {
179
- if (error.status === 403) {
180
- return <AccessDenied />;
181
- }
182
-
183
- return <div>{error.statusText}</div>;
184
- } else {
185
- return this.renderContent();
186
- }
187
- }
188
- }
189
-
190
- const mapStateToProps = (state) => {
191
- const {wasLoaded, loading, error, nodesUptimeFilter} = state.nodes;
192
-
193
- const nodes = getFilteredNodes(state);
194
- return {
195
- singleClusterMode: state.singleClusterMode,
196
- nodes,
197
- wasLoaded,
198
- loading,
199
- error,
200
- problemFilter: state.settings.problemFilter,
201
- nodesUptimeFilter,
202
- };
203
- };
204
-
205
- const mapDispatchToProps = {
206
- getNodesList: getNodes,
207
- hideTooltip,
208
- showTooltip,
209
- changeFilter,
210
- setHeader,
211
- setNodesUptimeFilter,
212
- };
213
-
214
- export default withSearch(connect(mapStateToProps, mapDispatchToProps)(Nodes));
@@ -1,163 +0,0 @@
1
- import React from 'react';
2
- import cn from 'bem-cn-lite';
3
- import PropTypes from 'prop-types';
4
- import {connect} from 'react-redux';
5
-
6
- import {TextInput, Label} from '@gravity-ui/uikit';
7
- import DataTable from '@yandex-cloud/react-data-table';
8
-
9
- import {ProblemFilter} from '../../components/ProblemFilter';
10
- import {UptimeFilter} from '../../components/UptimeFIlter';
11
- import {Illustration} from '../../components/Illustration';
12
-
13
- import {withSearch} from '../../HOCS';
14
- import {calcUptime} from '../../utils';
15
- import {DEFAULT_TABLE_SETTINGS} from '../../utils/constants';
16
- import {changeFilter} from '../../store/reducers/settings';
17
- import {filterNodesByStatusAndUptime} from '../../store/reducers/clusterNodes';
18
- import {setNodesUptimeFilter} from '../../store/reducers/nodes';
19
- import {hideTooltip, showTooltip} from '../../store/reducers/tooltip';
20
- import {getNodesColumns} from '../../utils/getNodesColumns';
21
-
22
- import './NodesViewer.scss';
23
-
24
- const b = cn('nodes-viewer');
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
-
44
- static propTypes = {
45
- nodes: PropTypes.array.isRequired,
46
- className: PropTypes.string,
47
- searchQuery: PropTypes.string,
48
- handleSearchQuery: PropTypes.func,
49
- showTooltip: PropTypes.func,
50
- hideTooltip: PropTypes.func,
51
- problemFilter: PropTypes.string,
52
- nodesUptimeFilter: PropTypes.string,
53
- setNodesUptimeFilter: PropTypes.func,
54
- changeFilter: PropTypes.func,
55
- showControls: PropTypes.bool,
56
- additionalNodesInfo: PropTypes.object,
57
- };
58
-
59
- static defaultProps = {
60
- className: '',
61
- showSearch: true,
62
- showControls: true,
63
- };
64
-
65
- handleProblemFilterChange = (value) => {
66
- this.props.changeFilter(value);
67
- };
68
-
69
- handleUptimeFilterChange = (value) => {
70
- this.props.setNodesUptimeFilter(value);
71
- };
72
-
73
- renderControls() {
74
- const {nodes, searchQuery, handleSearchQuery, nodesUptimeFilter, problemFilter} =
75
- this.props;
76
- const nodesToShow = NodesViewer.selectNodesToShow(nodes, searchQuery);
77
-
78
- return (
79
- <div className={b('controls')}>
80
- <TextInput
81
- className={b('search')}
82
- size="s"
83
- placeholder="Host name…"
84
- value={searchQuery}
85
- onUpdate={handleSearchQuery}
86
- hasClear
87
- autoFocus
88
- />
89
- <ProblemFilter value={problemFilter} onChange={this.handleProblemFilterChange} />
90
- <UptimeFilter value={nodesUptimeFilter} onChange={this.handleUptimeFilterChange} />
91
- <Label theme="info" size="m">{`Nodes: ${nodesToShow.length}`}</Label>
92
- </div>
93
- );
94
- }
95
-
96
- render() {
97
- const {
98
- className,
99
- searchQuery,
100
- path,
101
- problemFilter,
102
- showControls,
103
- hideTooltip,
104
- showTooltip,
105
- additionalNodesInfo = {},
106
- nodes,
107
- } = this.props;
108
-
109
- const columns = getNodesColumns({
110
- tabletsPath: path,
111
- hideTooltip,
112
- showTooltip,
113
- getNodeRef: additionalNodesInfo.getNodeRef,
114
- });
115
-
116
- const nodesToShow = NodesViewer.selectNodesToShow(nodes, searchQuery);
117
-
118
- return (
119
- <div className={`${b()} ${className}`}>
120
- {showControls ? this.renderControls() : null}
121
- <div className={b('table-wrapper')}>
122
- {nodesToShow.length === 0 ? (
123
- <Illustration name="thumbsUp" width="200" />
124
- ) : (
125
- <div className={b('table-content')}>
126
- <DataTable
127
- theme="yandex-cloud"
128
- key={problemFilter}
129
- data={nodesToShow}
130
- columns={columns}
131
- settings={DEFAULT_TABLE_SETTINGS}
132
- emptyDataMessage="No such nodes"
133
- />
134
- </div>
135
- )}
136
- </div>
137
- </div>
138
- );
139
- }
140
- }
141
-
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
-
148
- return {
149
- problemFilter,
150
- nodesUptimeFilter,
151
- nodes,
152
- };
153
- };
154
-
155
- const mapDispatchToProps = {
156
- changeFilter,
157
- hideTooltip,
158
- showTooltip,
159
- setNodesUptimeFilter,
160
- };
161
-
162
- const ConnectedNodesViewer = connect(mapStateToProps, mapDispatchToProps)(NodesViewer);
163
- export default withSearch(ConnectedNodesViewer);
@@ -1,66 +0,0 @@
1
- @import '../../styles/mixins.scss';
2
-
3
- .nodes-viewer {
4
- overflow: auto;
5
- @include flex-container();
6
-
7
- &__controls {
8
- @include controls;
9
- }
10
-
11
- &__name {
12
- display: inline-block;
13
-
14
- cursor: pointer;
15
- text-decoration: none;
16
-
17
- color: var(--yc-color-base-special);
18
- }
19
-
20
- &__search {
21
- width: 255px;
22
- }
23
-
24
- &__progress {
25
- margin: 0 auto;
26
- }
27
-
28
- &__tablets {
29
- overflow-x: auto;
30
-
31
- padding: 0 !important;
32
-
33
- .tablets-viewer__grid {
34
- justify-content: center;
35
- grid-template-columns: 125px;
36
- }
37
- }
38
-
39
- &__table-wrapper {
40
- overflow: auto;
41
- @include flex-container();
42
- }
43
-
44
- &__table-content {
45
- overflow: auto;
46
-
47
- height: 100%;
48
- @include freeze-nth-column(1);
49
- @include freeze-nth-column(2, 80px);
50
- @include freeze-nth-column(3, 430px);
51
-
52
- @include table-styles;
53
- @include table-sticky-styles;
54
- }
55
- &__version-tooltip {
56
- width: 100%;
57
- span {
58
- display: block;
59
- overflow: hidden;
60
-
61
- width: 100%;
62
-
63
- text-overflow: ellipsis;
64
- }
65
- }
66
- }
@@ -1,153 +0,0 @@
1
- import React, {useEffect, useState, useRef, useMemo} from 'react';
2
- import cn from 'bem-cn-lite';
3
-
4
- import {Popup} from '@gravity-ui/uikit';
5
-
6
- import {InfoViewer} from '../../../components/InfoViewer';
7
- import InternalLink from '../../../components/InternalLink/InternalLink';
8
-
9
- import routes, {createHref} from '../../../routes';
10
- import type {RequiredField} from '../../../types';
11
- import {TPDiskStateInfo, TPDiskState} from '../../../types/api/pdisk';
12
- import {getPDiskId} from '../../../utils';
13
- import {getPDiskType} from '../../../utils/pdisk';
14
- import {bytesToGB} from '../../../utils/utils';
15
-
16
- import {STRUCTURE} from '../../Node/NodePages';
17
-
18
- import DiskStateProgressBar, {
19
- diskProgressColors,
20
- } from '../DiskStateProgressBar/DiskStateProgressBar';
21
-
22
- import {colorSeverity, NOT_AVAILABLE_SEVERITY} from '../utils';
23
-
24
- import './Pdisk.scss';
25
-
26
- const b = cn('pdisk-storage');
27
-
28
- const stateSeverity = {
29
- [TPDiskState.Initial]: 0,
30
- [TPDiskState.Normal]: 1,
31
- [TPDiskState.InitialFormatRead]: 3,
32
- [TPDiskState.InitialSysLogRead]: 3,
33
- [TPDiskState.InitialCommonLogRead]: 3,
34
- [TPDiskState.InitialFormatReadError]: 5,
35
- [TPDiskState.InitialSysLogReadError]: 5,
36
- [TPDiskState.InitialSysLogParseError]: 5,
37
- [TPDiskState.InitialCommonLogReadError]: 5,
38
- [TPDiskState.InitialCommonLogParseError]: 5,
39
- [TPDiskState.CommonLoggerInitError]: 5,
40
- [TPDiskState.OpenFileError]: 5,
41
- [TPDiskState.ChunkQuotaError]: 5,
42
- [TPDiskState.DeviceIoError]: 5,
43
- };
44
-
45
- type PDiskProps = RequiredField<TPDiskStateInfo, 'NodeId'>;
46
-
47
- const isSeverityKey = (key?: TPDiskState): key is keyof typeof stateSeverity =>
48
- key !== undefined && key in stateSeverity;
49
-
50
- const getStateSeverity = (pDiskState?: TPDiskState) => {
51
- return isSeverityKey(pDiskState) ? stateSeverity[pDiskState] : NOT_AVAILABLE_SEVERITY;
52
- };
53
-
54
- function Pdisk(props: PDiskProps) {
55
- const [severity, setSeverity] = useState(getStateSeverity(props.State));
56
- const [isPopupVisible, setIsPopupVisible] = useState(false);
57
-
58
- const anchor = useRef(null);
59
-
60
- useEffect(() => {
61
- const newSeverity = getStateSeverity(props.State);
62
- if (severity !== newSeverity) {
63
- setSeverity(newSeverity);
64
- }
65
- }, [props.State]);
66
-
67
- const showPopup = () => {
68
- setIsPopupVisible(true);
69
- };
70
-
71
- const hidePopup = () => {
72
- setIsPopupVisible(false);
73
- };
74
- /* eslint-disable */
75
- const preparePdiskData = () => {
76
- const {AvailableSize, TotalSize, State, PDiskId, NodeId, Path, Realtime, Device} = props;
77
- const errorColors = [
78
- diskProgressColors[colorSeverity.Orange as keyof typeof diskProgressColors],
79
- diskProgressColors[colorSeverity.Red as keyof typeof diskProgressColors],
80
- diskProgressColors[colorSeverity.Yellow as keyof typeof diskProgressColors],
81
- ];
82
-
83
- const pdiskData: {label: string; value: string | number}[] = [
84
- {label: 'PDisk', value: getPDiskId({NodeId, PDiskId})},
85
- ];
86
-
87
- pdiskData.push({label: 'State', value: State || 'not available'});
88
- pdiskData.push({label: 'Type', value: getPDiskType(props) || 'unknown'});
89
- NodeId && pdiskData.push({label: 'Node Id', value: NodeId});
90
-
91
- Path && pdiskData.push({label: 'Path', value: Path});
92
- pdiskData.push({
93
- label: 'Available',
94
- value: `${bytesToGB(AvailableSize)} of ${bytesToGB(TotalSize)}`,
95
- });
96
- Realtime &&
97
- errorColors.includes(Realtime) &&
98
- pdiskData.push({label: 'Realtime', value: Realtime});
99
- Device && errorColors.includes(Device) && pdiskData.push({label: 'Device', value: Device});
100
- return pdiskData;
101
- };
102
- /* eslint-enable */
103
-
104
- const renderPopup = () => (
105
- <Popup
106
- className={b('popup-wrapper')}
107
- anchorRef={anchor}
108
- open={isPopupVisible}
109
- placement={['top', 'bottom']}
110
- // bigger offset for easier switching to neighbour nodes
111
- // matches the default offset for popup with arrow out of a sense of beauty
112
- offset={[0, 12]}
113
- >
114
- <InfoViewer title="PDisk" info={preparePdiskData()} size="s" />
115
- </Popup>
116
- );
117
-
118
- const pdiskAllocatedPercent = useMemo(() => {
119
- const {AvailableSize, TotalSize} = props;
120
-
121
- if (!AvailableSize || !TotalSize) {
122
- return undefined;
123
- }
124
-
125
- return !isNaN(Number(AvailableSize)) && !isNaN(Number(TotalSize))
126
- ? Math.round(((Number(TotalSize) - Number(AvailableSize)) * 100) / Number(TotalSize))
127
- : undefined;
128
- }, [props.AvailableSize, props.TotalSize]);
129
-
130
- return (
131
- <React.Fragment>
132
- {renderPopup()}
133
- <div className={b()} ref={anchor} onMouseEnter={showPopup} onMouseLeave={hidePopup}>
134
- <InternalLink
135
- to={createHref(
136
- routes.node,
137
- {id: props.NodeId, activeTab: STRUCTURE},
138
- {pdiskId: props.PDiskId || ''},
139
- )}
140
- className={b('content')}
141
- >
142
- <DiskStateProgressBar
143
- diskAllocatedPercent={pdiskAllocatedPercent}
144
- severity={severity as keyof typeof diskProgressColors}
145
- />
146
- <div className={b('media-type')}>{getPDiskType(props)}</div>
147
- </InternalLink>
148
- </div>
149
- </React.Fragment>
150
- );
151
- }
152
-
153
- export default Pdisk;
@@ -1,41 +0,0 @@
1
- import {MemoryRouter} from 'react-router-dom';
2
-
3
- import {renderWithStore} from '../../../../utils/tests/providers';
4
-
5
- import {TPDiskState} from '../../../../types/api/pdisk'
6
-
7
- import PDisk from '../Pdisk'
8
-
9
- describe('PDisk state', () => {
10
- it('Should determine severity based on State', () => {
11
- const {getAllByRole} = renderWithStore(
12
- <MemoryRouter>
13
- <PDisk
14
- NodeId={1}
15
- State={TPDiskState.Normal}
16
- />
17
- <PDisk
18
- NodeId={2}
19
- State={TPDiskState.ChunkQuotaError}
20
- />
21
- </MemoryRouter>
22
- );
23
-
24
- const [normalDisk, erroredDisk] = getAllByRole('meter');
25
-
26
- expect(normalDisk.className).not.toBe(erroredDisk.className);
27
- });
28
-
29
- it('Should display as unavailabe when no State is provided', () => {
30
- const {getByRole} = renderWithStore(
31
- <MemoryRouter>
32
- <PDisk NodeId={1} />
33
- </MemoryRouter>
34
- );
35
-
36
- const disk = getByRole('meter');
37
-
38
- // unavailable disks display with the highest severity
39
- expect(disk.className).toMatch(/_red\b/i);
40
- });
41
- });