ydb-embedded-ui 4.8.2 → 4.10.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.
Files changed (83) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/dist/components/BasicNodeViewer/BasicNodeViewer.tsx +7 -4
  3. package/dist/components/EntityStatus/EntityStatus.js +3 -1
  4. package/dist/components/FormattedBytes/FormattedBytes.tsx +10 -0
  5. package/dist/components/FormattedBytes/utils.tsx +13 -0
  6. package/dist/components/FullNodeViewer/FullNodeViewer.tsx +73 -0
  7. package/dist/components/InfoViewer/formatters/table.ts +6 -5
  8. package/dist/components/NodeHostWrapper/NodeHostWrapper.tsx +2 -2
  9. package/dist/components/ProblemFilter/ProblemFilter.tsx +2 -2
  10. package/dist/components/SpeedMultiMeter/SpeedMultiMeter.tsx +4 -4
  11. package/dist/components/TruncatedQuery/{TruncatedQuery.js → TruncatedQuery.tsx} +10 -8
  12. package/dist/containers/AsideNavigation/AsideNavigation.tsx +6 -6
  13. package/dist/containers/Cluster/Cluster.tsx +10 -6
  14. package/dist/containers/Node/Node.tsx +3 -3
  15. package/dist/containers/Nodes/Nodes.tsx +3 -3
  16. package/dist/containers/Nodes/getNodesColumns.tsx +2 -2
  17. package/dist/containers/Storage/PDisk/PDisk.tsx +2 -7
  18. package/dist/containers/Storage/Storage.tsx +240 -0
  19. package/dist/containers/Storage/StorageGroups/StorageGroups.tsx +59 -57
  20. package/dist/containers/Storage/StorageNodes/StorageNodes.tsx +23 -25
  21. package/dist/containers/Storage/StorageTypeFilter/StorageTypeFilter.tsx +27 -0
  22. package/dist/containers/Storage/StorageVisibleEntityFilter/StorageVisibleEntityFilter.tsx +31 -0
  23. package/dist/containers/Storage/UsageFilter/UsageFilter.scss +1 -0
  24. package/dist/containers/Storage/UsageFilter/UsageFilter.tsx +17 -17
  25. package/dist/containers/Tenant/Diagnostics/Diagnostics.tsx +3 -3
  26. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.js +7 -4
  27. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.scss +0 -15
  28. package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.tsx +10 -3
  29. package/dist/containers/Tenant/{Preview → Query/Preview}/Preview.scss +1 -1
  30. package/dist/containers/Tenant/Query/Preview/Preview.tsx +121 -0
  31. package/dist/containers/Tenant/Query/QueriesHistory/QueriesHistory.tsx +1 -1
  32. package/dist/containers/Tenant/Query/QueryEditor/QueryEditor.js +23 -51
  33. package/dist/containers/Tenant/Query/QueryEditorControls/QueryEditorControls.scss +20 -15
  34. package/dist/containers/Tenant/Query/QueryEditorControls/QueryEditorControls.tsx +74 -27
  35. package/dist/containers/Tenant/Query/SavedQueries/SavedQueries.tsx +1 -1
  36. package/dist/containers/Tenant/Query/i18n/en.json +9 -2
  37. package/dist/containers/Tenant/Query/i18n/ru.json +9 -2
  38. package/dist/containers/Tenants/Tenants.tsx +269 -0
  39. package/dist/containers/UserSettings/i18n/en.json +1 -1
  40. package/dist/containers/UserSettings/i18n/ru.json +1 -1
  41. package/dist/services/api.ts +14 -16
  42. package/dist/store/reducers/executeQuery.ts +2 -3
  43. package/dist/store/reducers/explainQuery.ts +2 -2
  44. package/dist/store/reducers/index.ts +2 -2
  45. package/dist/store/reducers/{nodes.ts → nodes/nodes.ts} +33 -32
  46. package/dist/{types/store/nodes.ts → store/reducers/nodes/types.ts} +24 -27
  47. package/dist/store/reducers/partitions/types.ts +3 -3
  48. package/dist/store/reducers/settings/settings.ts +14 -4
  49. package/dist/store/reducers/settings/types.ts +3 -1
  50. package/dist/store/reducers/storage/constants.ts +10 -0
  51. package/dist/store/reducers/storage/selectors.ts +279 -0
  52. package/dist/store/reducers/storage/storage.ts +191 -0
  53. package/dist/store/reducers/storage/types.ts +92 -0
  54. package/dist/store/reducers/tenants/selectors.ts +46 -0
  55. package/dist/store/reducers/tenants/tenants.ts +21 -14
  56. package/dist/store/reducers/tenants/types.ts +20 -5
  57. package/dist/store/reducers/tenants/utils.ts +68 -0
  58. package/dist/types/additionalProps.ts +8 -0
  59. package/dist/types/api/storage.ts +1 -1
  60. package/dist/types/store/query.ts +5 -6
  61. package/dist/types/store/topic.ts +3 -3
  62. package/dist/utils/bytesParsers/__test__/formatBytes.test.ts +38 -0
  63. package/dist/utils/bytesParsers/convertBytesObjectToSpeed.ts +2 -2
  64. package/dist/utils/bytesParsers/formatBytes.ts +132 -0
  65. package/dist/utils/bytesParsers/i18n/en.json +1 -0
  66. package/dist/utils/bytesParsers/i18n/ru.json +1 -0
  67. package/dist/utils/bytesParsers/index.ts +1 -1
  68. package/dist/utils/constants.ts +1 -0
  69. package/dist/utils/index.js +5 -10
  70. package/dist/utils/nodes.ts +2 -2
  71. package/dist/utils/numeral.ts +8 -0
  72. package/dist/utils/query.ts +12 -0
  73. package/package.json +1 -1
  74. package/dist/components/FullNodeViewer/FullNodeViewer.js +0 -89
  75. package/dist/containers/Node/NodeOverview/NodeOverview.scss +0 -0
  76. package/dist/containers/Node/NodeOverview/NodeOverview.tsx +0 -21
  77. package/dist/containers/Storage/Storage.js +0 -372
  78. package/dist/containers/Tenant/Preview/Preview.js +0 -168
  79. package/dist/containers/Tenant/Query/QueryEditorControls/OldQueryEditorControls.tsx +0 -90
  80. package/dist/containers/Tenant/Query/QueryEditorControls/shared.ts +0 -18
  81. package/dist/containers/Tenants/Tenants.js +0 -363
  82. package/dist/store/reducers/storage.js +0 -438
  83. package/dist/utils/bytesParsers/formatBytesCustom.ts +0 -57
@@ -0,0 +1,240 @@
1
+ import {useCallback, useEffect} from 'react';
2
+ import {useDispatch} from 'react-redux';
3
+ import cn from 'bem-cn-lite';
4
+
5
+ import DataTable, {Settings} from '@gravity-ui/react-data-table';
6
+
7
+ import {Search} from '../../components/Search';
8
+ import {TableSkeleton} from '../../components/TableSkeleton/TableSkeleton';
9
+ import {UptimeFilter} from '../../components/UptimeFIlter';
10
+ import {AccessDenied} from '../../components/Errors/403';
11
+ import {EntitiesCount} from '../../components/EntitiesCount';
12
+
13
+ import type {StorageType, VisibleEntities} from '../../store/reducers/storage/types';
14
+ import {
15
+ getStorageInfo,
16
+ setInitialState,
17
+ setVisibleEntities,
18
+ setStorageTextFilter,
19
+ setUsageFilter,
20
+ setStorageType,
21
+ setNodesUptimeFilter,
22
+ setDataWasNotLoaded,
23
+ } from '../../store/reducers/storage/storage';
24
+ import {
25
+ selectFilteredGroups,
26
+ selectFilteredNodes,
27
+ selectStorageNodesCount,
28
+ selectStorageGroupsCount,
29
+ selectUsageFilterOptions,
30
+ } from '../../store/reducers/storage/selectors';
31
+ import {VISIBLE_ENTITIES, STORAGE_TYPES} from '../../store/reducers/storage/constants';
32
+ import {getNodesList, selectNodesMap} from '../../store/reducers/nodesList';
33
+ import {useAutofetcher, useTypedSelector} from '../../utils/hooks';
34
+ import {AdditionalNodesInfo, NodesUptimeFilterValues} from '../../utils/nodes';
35
+ import {DEFAULT_TABLE_SETTINGS} from '../../utils/constants';
36
+
37
+ import {StorageGroups} from './StorageGroups/StorageGroups';
38
+ import {StorageNodes} from './StorageNodes/StorageNodes';
39
+ import {StorageTypeFilter} from './StorageTypeFilter/StorageTypeFilter';
40
+ import {StorageVisibleEntityFilter} from './StorageVisibleEntityFilter/StorageVisibleEntityFilter';
41
+ import {UsageFilter} from './UsageFilter';
42
+
43
+ import './Storage.scss';
44
+
45
+ const b = cn('global-storage');
46
+
47
+ const tableSettings: Settings = {
48
+ ...DEFAULT_TABLE_SETTINGS,
49
+ defaultOrder: DataTable.DESCENDING,
50
+ };
51
+
52
+ interface StorageProps {
53
+ additionalNodesInfo?: AdditionalNodesInfo;
54
+ tenant?: string;
55
+ nodeId?: string;
56
+ }
57
+
58
+ export const Storage = ({additionalNodesInfo, tenant, nodeId}: StorageProps) => {
59
+ const dispatch = useDispatch();
60
+
61
+ const {autorefresh} = useTypedSelector((state) => state.schema);
62
+ const {
63
+ loading,
64
+ wasLoaded,
65
+ error,
66
+ type: storageType,
67
+ visible: visibleEntities,
68
+ filter,
69
+ usageFilter,
70
+ nodesUptimeFilter,
71
+ } = useTypedSelector((state) => state.storage);
72
+ const storageNodes = useTypedSelector(selectFilteredNodes);
73
+ const storageGroups = useTypedSelector(selectFilteredGroups);
74
+ const nodesCount = useTypedSelector(selectStorageNodesCount);
75
+ const groupsCount = useTypedSelector(selectStorageGroupsCount);
76
+ const nodesMap = useTypedSelector(selectNodesMap);
77
+ const usageFilterOptions = useTypedSelector(selectUsageFilterOptions);
78
+
79
+ useEffect(() => {
80
+ dispatch(getNodesList());
81
+
82
+ return () => {
83
+ // Clean data on component unmount
84
+ dispatch(setInitialState());
85
+ };
86
+ }, [dispatch]);
87
+
88
+ const fetchData = useCallback(
89
+ (isBackground: boolean) => {
90
+ if (!isBackground) {
91
+ dispatch(setDataWasNotLoaded());
92
+ }
93
+
94
+ dispatch(
95
+ getStorageInfo(
96
+ {
97
+ tenant,
98
+ nodeId,
99
+ visibleEntities,
100
+ type: storageType,
101
+ },
102
+ {
103
+ concurrentId: 'getStorageInfo',
104
+ },
105
+ ),
106
+ );
107
+ },
108
+ [dispatch, tenant, nodeId, visibleEntities, storageType],
109
+ );
110
+
111
+ const autorefreshEnabled = tenant ? autorefresh : true;
112
+
113
+ useAutofetcher(fetchData, [fetchData], autorefreshEnabled);
114
+
115
+ const handleUsageFilterChange = (value: string[]) => {
116
+ dispatch(setUsageFilter(value));
117
+ };
118
+
119
+ const handleTextFilterChange = (value: string) => {
120
+ dispatch(setStorageTextFilter(value));
121
+ };
122
+
123
+ const handleGroupVisibilityChange = (value: string) => {
124
+ dispatch(setVisibleEntities(value as VisibleEntities));
125
+ };
126
+
127
+ const handleStorageTypeChange = (value: string) => {
128
+ dispatch(setStorageType(value as StorageType));
129
+ };
130
+
131
+ const handleUptimeFilterChange = (value: string) => {
132
+ dispatch(setNodesUptimeFilter(value as NodesUptimeFilterValues));
133
+ };
134
+
135
+ const handleShowAllNodes = () => {
136
+ handleGroupVisibilityChange(VISIBLE_ENTITIES.all);
137
+ handleUptimeFilterChange(NodesUptimeFilterValues.All);
138
+ };
139
+
140
+ const renderLoader = () => {
141
+ return <TableSkeleton className={b('loader')} />;
142
+ };
143
+
144
+ const renderDataTable = () => {
145
+ return (
146
+ <div className={b('table-wrapper')}>
147
+ {storageType === STORAGE_TYPES.groups && (
148
+ <StorageGroups
149
+ visibleEntities={visibleEntities}
150
+ data={storageGroups}
151
+ tableSettings={tableSettings}
152
+ nodes={nodesMap}
153
+ onShowAll={() => handleGroupVisibilityChange(VISIBLE_ENTITIES.all)}
154
+ />
155
+ )}
156
+ {storageType === STORAGE_TYPES.nodes && (
157
+ <StorageNodes
158
+ visibleEntities={visibleEntities}
159
+ nodesUptimeFilter={nodesUptimeFilter}
160
+ data={storageNodes}
161
+ tableSettings={tableSettings}
162
+ onShowAll={handleShowAllNodes}
163
+ additionalNodesInfo={additionalNodesInfo}
164
+ />
165
+ )}
166
+ </div>
167
+ );
168
+ };
169
+
170
+ const renderEntitiesCount = () => {
171
+ const entityName = storageType === STORAGE_TYPES.groups ? 'Groups' : 'Nodes';
172
+ const count = storageType === STORAGE_TYPES.groups ? groupsCount : nodesCount;
173
+ const current =
174
+ storageType === STORAGE_TYPES.groups ? storageGroups.length : storageNodes.length;
175
+
176
+ return (
177
+ <EntitiesCount
178
+ label={entityName}
179
+ loading={loading && !wasLoaded}
180
+ total={count.total}
181
+ current={current}
182
+ />
183
+ );
184
+ };
185
+
186
+ const renderControls = () => {
187
+ return (
188
+ <div className={b('controls')}>
189
+ <div className={b('search')}>
190
+ <Search
191
+ placeholder={
192
+ storageType === STORAGE_TYPES.groups
193
+ ? 'Group ID, Pool name'
194
+ : 'Node ID, FQDN'
195
+ }
196
+ onChange={handleTextFilterChange}
197
+ value={filter}
198
+ />
199
+ </div>
200
+
201
+ <StorageTypeFilter value={storageType} onChange={handleStorageTypeChange} />
202
+ <StorageVisibleEntityFilter
203
+ value={visibleEntities}
204
+ onChange={handleGroupVisibilityChange}
205
+ />
206
+
207
+ {storageType === STORAGE_TYPES.nodes && (
208
+ <UptimeFilter value={nodesUptimeFilter} onChange={handleUptimeFilterChange} />
209
+ )}
210
+
211
+ {storageType === STORAGE_TYPES.groups && (
212
+ <UsageFilter
213
+ value={usageFilter}
214
+ onChange={handleUsageFilterChange}
215
+ groups={usageFilterOptions}
216
+ disabled={usageFilterOptions.length === 0}
217
+ />
218
+ )}
219
+ {renderEntitiesCount()}
220
+ </div>
221
+ );
222
+ };
223
+
224
+ const showLoader = loading && !wasLoaded;
225
+
226
+ if (error) {
227
+ if (error.status === 403) {
228
+ return <AccessDenied />;
229
+ }
230
+
231
+ return <div className={b()}>{error.statusText}</div>;
232
+ }
233
+
234
+ return (
235
+ <div className={b()}>
236
+ {renderControls()}
237
+ {showLoader ? renderLoader() : renderDataTable()}
238
+ </div>
239
+ );
240
+ };
@@ -1,25 +1,20 @@
1
- import _ from 'lodash';
2
1
  import cn from 'bem-cn-lite';
2
+
3
3
  import DataTable, {Column, Settings, SortOrder} from '@gravity-ui/react-data-table';
4
4
  import {Icon, Label, Popover, PopoverBehavior} from '@gravity-ui/uikit';
5
5
 
6
6
  import type {NodesMap} from '../../../types/store/nodesList';
7
+ import type {PreparedStorageGroup, VisibleEntities} from '../../../store/reducers/storage/types';
7
8
 
8
- import shieldIcon from '../../../assets/icons/shield.svg';
9
-
10
- import {Stack} from '../../../components/Stack/Stack';
11
- //@ts-ignore
12
- import EntityStatus from '../../../components/EntityStatus/EntityStatus';
13
-
14
- import {TVDiskStateInfo} from '../../../types/api/vdisk';
15
- //@ts-ignore
16
- import {VisibleEntities} from '../../../store/reducers/storage';
17
- //@ts-ignore
9
+ import {VISIBLE_ENTITIES} from '../../../store/reducers/storage/constants';
18
10
  import {bytesToGB, bytesToSpeed} from '../../../utils/utils';
19
- //@ts-ignore
20
11
  import {stringifyVdiskId} from '../../../utils';
21
12
  import {getUsage, isFullVDiskData} from '../../../utils/storage';
22
13
 
14
+ import shieldIcon from '../../../assets/icons/shield.svg';
15
+ import {Stack} from '../../../components/Stack/Stack';
16
+ import EntityStatus from '../../../components/EntityStatus/EntityStatus';
17
+
23
18
  import {EmptyFilter} from '../EmptyFilter/EmptyFilter';
24
19
  import {VDisk} from '../VDisk';
25
20
  import {getDegradedSeverity, getUsageSeverityForStorageGroup} from '../utils';
@@ -46,10 +41,10 @@ type TableColumnsIdsKeys = keyof typeof TableColumnsIds;
46
41
  type TableColumnsIdsValues = typeof TableColumnsIds[TableColumnsIdsKeys];
47
42
 
48
43
  interface StorageGroupsProps {
49
- data: any;
50
- nodes: NodesMap;
44
+ data: PreparedStorageGroup[];
45
+ nodes?: NodesMap;
51
46
  tableSettings: Settings;
52
- visibleEntities: keyof typeof VisibleEntities;
47
+ visibleEntities: VisibleEntities;
53
48
  onShowAll?: VoidFunction;
54
49
  }
55
50
 
@@ -70,21 +65,21 @@ const tableColumnsNames: Record<TableColumnsIdsValues, string> = {
70
65
 
71
66
  const b = cn('global-storage-groups');
72
67
 
73
- function setSortOrder(visibleEntities: keyof typeof VisibleEntities): SortOrder | undefined {
68
+ function setSortOrder(visibleEntities: VisibleEntities): SortOrder | undefined {
74
69
  switch (visibleEntities) {
75
- case VisibleEntities.All: {
70
+ case VISIBLE_ENTITIES.all: {
76
71
  return {
77
72
  columnId: TableColumnsIds.PoolName,
78
73
  order: DataTable.ASCENDING,
79
74
  };
80
75
  }
81
- case VisibleEntities.Missing: {
76
+ case VISIBLE_ENTITIES.missing: {
82
77
  return {
83
78
  columnId: TableColumnsIds.Missing,
84
79
  order: DataTable.DESCENDING,
85
80
  };
86
81
  }
87
- case VisibleEntities.Space: {
82
+ case VISIBLE_ENTITIES.space: {
88
83
  return {
89
84
  columnId: TableColumnsIds.UsedSpaceFlag,
90
85
  order: DataTable.DESCENDING,
@@ -96,25 +91,25 @@ function setSortOrder(visibleEntities: keyof typeof VisibleEntities): SortOrder
96
91
  }
97
92
  }
98
93
 
99
- function StorageGroups({
94
+ export function StorageGroups({
100
95
  data,
101
96
  tableSettings,
102
97
  visibleEntities,
103
98
  nodes,
104
99
  onShowAll,
105
100
  }: StorageGroupsProps) {
106
- const allColumns: Column<any>[] = [
101
+ const allColumns: Column<PreparedStorageGroup>[] = [
107
102
  {
108
103
  name: TableColumnsIds.PoolName,
109
104
  header: tableColumnsNames[TableColumnsIds.PoolName],
110
105
  width: 250,
111
- render: ({value}) => {
112
- const splitted = (value as string)?.split('/');
106
+ render: ({row}) => {
107
+ const splitted = row.PoolName?.split('/');
113
108
  return (
114
109
  <div className={b('pool-name-wrapper')}>
115
110
  {splitted && (
116
111
  <Popover
117
- content={value as string}
112
+ content={row.PoolName}
118
113
  placement={['right']}
119
114
  behavior={PopoverBehavior.Immediate}
120
115
  >
@@ -132,9 +127,9 @@ function StorageGroups({
132
127
  name: TableColumnsIds.Type,
133
128
  header: tableColumnsNames[TableColumnsIds.Type],
134
129
  // prettier-ignore
135
- render: ({value, row}) => (
130
+ render: ({row}) => (
136
131
  <>
137
- <Label>{(value as string) || '—'}</Label>
132
+ <Label>{row.Type || '—'}</Label>
138
133
  {' '}
139
134
  {row.Encryption && (
140
135
  <Popover
@@ -160,8 +155,12 @@ function StorageGroups({
160
155
  name: TableColumnsIds.Missing,
161
156
  header: tableColumnsNames[TableColumnsIds.Missing],
162
157
  width: 100,
163
- render: ({value, row}) =>
164
- value ? <Label theme={getDegradedSeverity(row)}>Degraded: {value}</Label> : '-',
158
+ render: ({row}) =>
159
+ row.Missing ? (
160
+ <Label theme={getDegradedSeverity(row)}>Degraded: {row.Missing}</Label>
161
+ ) : (
162
+ '-'
163
+ ),
165
164
  align: DataTable.LEFT,
166
165
  defaultOrder: DataTable.DESCENDING,
167
166
  },
@@ -192,8 +191,8 @@ function StorageGroups({
192
191
  name: TableColumnsIds.GroupID,
193
192
  header: tableColumnsNames[TableColumnsIds.GroupID],
194
193
  width: 130,
195
- render: ({value}) => {
196
- return <span className={b('group-id')}>{value as number}</span>;
194
+ render: ({row}) => {
195
+ return <span className={b('group-id')}>{row.GroupID}</span>;
197
196
  },
198
197
  align: DataTable.RIGHT,
199
198
  },
@@ -201,8 +200,8 @@ function StorageGroups({
201
200
  name: TableColumnsIds.Used,
202
201
  header: tableColumnsNames[TableColumnsIds.Used],
203
202
  width: 100,
204
- render: ({value}) => {
205
- return bytesToGB(value, true);
203
+ render: ({row}) => {
204
+ return bytesToGB(row.Used, true);
206
205
  },
207
206
  align: DataTable.RIGHT,
208
207
  },
@@ -210,8 +209,8 @@ function StorageGroups({
210
209
  name: TableColumnsIds.Limit,
211
210
  header: tableColumnsNames[TableColumnsIds.Limit],
212
211
  width: 100,
213
- render: ({value}) => {
214
- return bytesToGB(value);
212
+ render: ({row}) => {
213
+ return bytesToGB(row.Limit);
215
214
  },
216
215
  align: DataTable.RIGHT,
217
216
  },
@@ -219,15 +218,17 @@ function StorageGroups({
219
218
  name: TableColumnsIds.UsedSpaceFlag,
220
219
  header: tableColumnsNames[TableColumnsIds.UsedSpaceFlag],
221
220
  width: 110,
222
- render: ({value}) => {
223
- const val = value as number;
221
+ render: ({row}) => {
222
+ const value = row.UsedSpaceFlag;
223
+
224
224
  let color = 'Red';
225
- if (val < 100) {
225
+
226
+ if (value < 100) {
226
227
  color = 'Green';
227
- } else if (val < 10000) {
228
+ } else if (value < 10000) {
228
229
  color = 'Yellow';
229
- } else if (val < 1000000) {
230
- value = 'Orange';
230
+ } else if (value < 1000000) {
231
+ color = 'Orange';
231
232
  }
232
233
  return <EntityStatus status={color} />;
233
234
  },
@@ -238,8 +239,8 @@ function StorageGroups({
238
239
  name: TableColumnsIds.Read,
239
240
  header: tableColumnsNames[TableColumnsIds.Read],
240
241
  width: 100,
241
- render: ({value}) => {
242
- return value ? bytesToSpeed(value) : '-';
242
+ render: ({row}) => {
243
+ return row.Read ? bytesToSpeed(row.Read) : '-';
243
244
  },
244
245
  align: DataTable.RIGHT,
245
246
  },
@@ -247,8 +248,8 @@ function StorageGroups({
247
248
  name: TableColumnsIds.Write,
248
249
  header: tableColumnsNames[TableColumnsIds.Write],
249
250
  width: 100,
250
- render: ({value}) => {
251
- return value ? bytesToSpeed(value) : '-';
251
+ render: ({row}) => {
252
+ return row.Write ? bytesToSpeed(row.Write) : '-';
252
253
  },
253
254
  align: DataTable.RIGHT,
254
255
  },
@@ -256,14 +257,17 @@ function StorageGroups({
256
257
  name: TableColumnsIds.VDisks,
257
258
  className: b('vdisks-column'),
258
259
  header: tableColumnsNames[TableColumnsIds.VDisks],
259
- render: ({value}) => (
260
+ render: ({row}) => (
260
261
  <div className={b('vdisks-wrapper')}>
261
- {_.map(value as TVDiskStateInfo[], (el) => {
262
- const donors = el.Donors;
262
+ {row.VDisks?.map((vDisk) => {
263
+ const donors = vDisk.Donors;
263
264
 
264
265
  return donors && donors.length > 0 ? (
265
- <Stack className={b('vdisks-item')} key={stringifyVdiskId(el.VDiskId)}>
266
- <VDisk data={el} nodes={nodes} />
266
+ <Stack
267
+ className={b('vdisks-item')}
268
+ key={stringifyVdiskId(vDisk.VDiskId)}
269
+ >
270
+ <VDisk data={vDisk} nodes={nodes} />
267
271
  {donors.map((donor) => {
268
272
  const isFullData = isFullVDiskData(donor);
269
273
 
@@ -280,8 +284,8 @@ function StorageGroups({
280
284
  })}
281
285
  </Stack>
282
286
  ) : (
283
- <div className={b('vdisks-item')} key={stringifyVdiskId(el.VDiskId)}>
284
- <VDisk data={el} nodes={nodes} />
287
+ <div className={b('vdisks-item')} key={stringifyVdiskId(vDisk.VDiskId)}>
288
+ <VDisk data={vDisk} nodes={nodes} />
285
289
  </div>
286
290
  );
287
291
  })}
@@ -295,7 +299,7 @@ function StorageGroups({
295
299
 
296
300
  let columns = allColumns;
297
301
 
298
- if (visibleEntities === VisibleEntities.All) {
302
+ if (visibleEntities === VISIBLE_ENTITIES.all) {
299
303
  columns = allColumns.filter((col) => {
300
304
  return (
301
305
  col.name !== TableColumnsIds.Missing && col.name !== TableColumnsIds.UsedSpaceFlag
@@ -303,7 +307,7 @@ function StorageGroups({
303
307
  });
304
308
  }
305
309
 
306
- if (visibleEntities === VisibleEntities.Space) {
310
+ if (visibleEntities === VISIBLE_ENTITIES.space) {
307
311
  columns = allColumns.filter((col) => col.name !== TableColumnsIds.Missing);
308
312
 
309
313
  if (!data.length) {
@@ -317,7 +321,7 @@ function StorageGroups({
317
321
  }
318
322
  }
319
323
 
320
- if (visibleEntities === VisibleEntities.Missing) {
324
+ if (visibleEntities === VISIBLE_ENTITIES.missing) {
321
325
  columns = allColumns.filter((col) => col.name !== TableColumnsIds.UsedSpaceFlag);
322
326
 
323
327
  if (!data.length) {
@@ -333,7 +337,7 @@ function StorageGroups({
333
337
 
334
338
  return data ? (
335
339
  <DataTable
336
- key={visibleEntities as string}
340
+ key={visibleEntities}
337
341
  theme="yandex-cloud"
338
342
  data={data}
339
343
  columns={columns}
@@ -343,5 +347,3 @@ function StorageGroups({
343
347
  />
344
348
  ) : null;
345
349
  }
346
-
347
- export default StorageGroups;
@@ -1,9 +1,10 @@
1
- import _ from 'lodash';
2
1
  import cn from 'bem-cn-lite';
3
2
 
4
3
  import DataTable, {Column, Settings, SortOrder} from '@gravity-ui/react-data-table';
5
4
 
6
- import {VisibleEntities} from '../../../store/reducers/storage';
5
+ import type {PreparedStorageNode, VisibleEntities} from '../../../store/reducers/storage/types';
6
+
7
+ import {VISIBLE_ENTITIES} from '../../../store/reducers/storage/constants';
7
8
  import {
8
9
  AdditionalNodesInfo,
9
10
  isUnavailableNode,
@@ -23,7 +24,7 @@ enum TableColumnsIds {
23
24
  FQDN = 'FQDN',
24
25
  DataCenter = 'DataCenter',
25
26
  Rack = 'Rack',
26
- uptime = 'uptime',
27
+ Uptime = 'Uptime',
27
28
  PDisks = 'PDisks',
28
29
  Missing = 'Missing',
29
30
  }
@@ -32,10 +33,9 @@ type TableColumnsIdsKeys = keyof typeof TableColumnsIds;
32
33
  type TableColumnsIdsValues = typeof TableColumnsIds[TableColumnsIdsKeys];
33
34
 
34
35
  interface StorageNodesProps {
35
- data: any;
36
- nodes: any;
36
+ data: PreparedStorageNode[];
37
37
  tableSettings: Settings;
38
- visibleEntities: keyof typeof VisibleEntities;
38
+ visibleEntities: VisibleEntities;
39
39
  nodesUptimeFilter: keyof typeof NodesUptimeFilterValues;
40
40
  onShowAll?: VoidFunction;
41
41
  additionalNodesInfo?: AdditionalNodesInfo;
@@ -46,22 +46,22 @@ const tableColumnsNames: Record<TableColumnsIdsValues, string> = {
46
46
  FQDN: 'FQDN',
47
47
  DataCenter: 'DC',
48
48
  Rack: 'Rack',
49
- uptime: 'Uptime',
49
+ Uptime: 'Uptime',
50
50
  PDisks: 'PDisks',
51
51
  Missing: 'Missing',
52
52
  };
53
53
 
54
54
  const b = cn('global-storage-nodes');
55
55
 
56
- function setSortOrder(visibleEntities: keyof typeof VisibleEntities): SortOrder | undefined {
56
+ function setSortOrder(visibleEntities: VisibleEntities): SortOrder | undefined {
57
57
  switch (visibleEntities) {
58
- case VisibleEntities.All: {
58
+ case VISIBLE_ENTITIES.all: {
59
59
  return {
60
60
  columnId: TableColumnsIds.NodeId,
61
61
  order: DataTable.ASCENDING,
62
62
  };
63
63
  }
64
- case VisibleEntities.Missing: {
64
+ case VISIBLE_ENTITIES.missing: {
65
65
  return {
66
66
  columnId: TableColumnsIds.Missing,
67
67
  order: DataTable.DESCENDING,
@@ -73,7 +73,7 @@ function setSortOrder(visibleEntities: keyof typeof VisibleEntities): SortOrder
73
73
  }
74
74
  }
75
75
 
76
- function StorageNodes({
76
+ export function StorageNodes({
77
77
  data,
78
78
  tableSettings,
79
79
  visibleEntities,
@@ -83,7 +83,7 @@ function StorageNodes({
83
83
  }: StorageNodesProps) {
84
84
  const getNodeRef = additionalNodesInfo?.getNodeRef;
85
85
 
86
- const allColumns: Column<any>[] = [
86
+ const allColumns: Column<PreparedStorageNode>[] = [
87
87
  {
88
88
  name: TableColumnsIds.NodeId,
89
89
  header: tableColumnsNames[TableColumnsIds.NodeId],
@@ -112,10 +112,10 @@ function StorageNodes({
112
112
  align: DataTable.LEFT,
113
113
  },
114
114
  {
115
- name: TableColumnsIds.uptime,
116
- header: tableColumnsNames[TableColumnsIds.uptime],
115
+ name: TableColumnsIds.Uptime,
116
+ header: tableColumnsNames[TableColumnsIds.Uptime],
117
117
  width: 130,
118
- sortAccessor: ({StartTime}) => -StartTime,
118
+ sortAccessor: ({StartTime}) => (StartTime ? -StartTime : 0),
119
119
  align: DataTable.RIGHT,
120
120
  },
121
121
  {
@@ -129,11 +129,11 @@ function StorageNodes({
129
129
  name: TableColumnsIds.PDisks,
130
130
  className: b('pdisks-column'),
131
131
  header: tableColumnsNames[TableColumnsIds.PDisks],
132
- render: ({value, row}) => (
132
+ render: ({row}) => (
133
133
  <div className={b('pdisks-wrapper')}>
134
- {_.map(value as any, (el) => (
135
- <div className={b('pdisks-item')} key={el.PDiskId}>
136
- <PDisk data={el} nodeId={row.NodeId} />
134
+ {row.PDisks?.map((pDisk) => (
135
+ <div className={b('pdisks-item')} key={pDisk.PDiskId}>
136
+ <PDisk data={pDisk} nodeId={row.NodeId} />
137
137
  </div>
138
138
  ))}
139
139
  </div>
@@ -146,18 +146,18 @@ function StorageNodes({
146
146
 
147
147
  let columns = allColumns;
148
148
 
149
- if (visibleEntities === VisibleEntities.Space) {
149
+ if (visibleEntities === VISIBLE_ENTITIES.space) {
150
150
  columns = allColumns.filter((col) => col.name !== TableColumnsIds.Missing);
151
151
  }
152
152
 
153
153
  if (!data.length) {
154
154
  let message;
155
155
 
156
- if (visibleEntities === VisibleEntities.Space) {
156
+ if (visibleEntities === VISIBLE_ENTITIES.space) {
157
157
  message = i18n('empty.out_of_space');
158
158
  }
159
159
 
160
- if (visibleEntities === VisibleEntities.Missing) {
160
+ if (visibleEntities === VISIBLE_ENTITIES.missing) {
161
161
  message = i18n('empty.degraded');
162
162
  }
163
163
 
@@ -166,7 +166,7 @@ function StorageNodes({
166
166
  }
167
167
 
168
168
  if (
169
- visibleEntities !== VisibleEntities.All &&
169
+ visibleEntities !== VISIBLE_ENTITIES.all &&
170
170
  nodesUptimeFilter !== NodesUptimeFilterValues.All
171
171
  ) {
172
172
  message = i18n('empty.several_filters');
@@ -193,5 +193,3 @@ function StorageNodes({
193
193
  />
194
194
  ) : null;
195
195
  }
196
-
197
- export default StorageNodes;