ydb-embedded-ui 3.2.3 → 3.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (116) hide show
  1. package/CHANGELOG.md +20 -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.tsx +18 -10
  70. package/dist/services/api.d.ts +8 -1
  71. package/dist/services/api.js +27 -8
  72. package/dist/store/reducers/index.ts +3 -1
  73. package/dist/store/reducers/nodes.ts +148 -14
  74. package/dist/store/reducers/{clusterNodes.js → nodesList.js} +0 -41
  75. package/dist/store/reducers/settings.js +10 -4
  76. package/dist/store/reducers/storage.js +24 -13
  77. package/dist/store/reducers/tenant.js +5 -4
  78. package/dist/store/reducers/tooltip.ts +1 -1
  79. package/dist/store/reducers/topic.ts +52 -0
  80. package/dist/styles/mixins.scss +19 -11
  81. package/dist/types/api/common.ts +5 -0
  82. package/dist/types/api/compute.ts +1 -1
  83. package/dist/types/api/consumer.ts +12 -10
  84. package/dist/types/api/nodes.ts +2 -0
  85. package/dist/types/api/pdisk.ts +1 -0
  86. package/dist/types/api/schema.ts +3 -3
  87. package/dist/types/api/topic.ts +5 -4
  88. package/dist/types/api/vdisk.ts +2 -1
  89. package/dist/types/store/nodes.ts +56 -6
  90. package/dist/types/store/tooltip.ts +1 -1
  91. package/dist/types/store/topic.ts +21 -0
  92. package/dist/utils/constants.ts +5 -1
  93. package/dist/utils/i18n/i18n.ts +10 -2
  94. package/dist/utils/index.js +1 -1
  95. package/dist/utils/timeParsers/__test__/formatDuration.test.ts +50 -0
  96. package/dist/utils/timeParsers/__test__/protobuf.test.ts +74 -0
  97. package/dist/utils/timeParsers/formatDuration.ts +46 -0
  98. package/dist/utils/timeParsers/i18n/en.json +7 -0
  99. package/dist/utils/timeParsers/i18n/index.ts +11 -0
  100. package/dist/utils/timeParsers/i18n/ru.json +7 -0
  101. package/dist/utils/timeParsers/index.ts +2 -0
  102. package/dist/utils/timeParsers/protobuf.ts +36 -0
  103. package/package.json +1 -1
  104. package/dist/components/InfoViewer/schemaInfo/CDCStreamInfo.tsx +0 -48
  105. package/dist/components/InfoViewer/schemaInfo/PersQueueGroupInfo.tsx +0 -30
  106. package/dist/components/InternalLink/InternalLink.js +0 -23
  107. package/dist/containers/Nodes/Nodes.js +0 -214
  108. package/dist/containers/NodesViewer/NodesViewer.js +0 -163
  109. package/dist/containers/NodesViewer/NodesViewer.scss +0 -66
  110. package/dist/containers/Storage/Pdisk/Pdisk.tsx +0 -153
  111. package/dist/containers/Storage/Pdisk/__tests__/colors.tsx +0 -41
  112. package/dist/containers/Storage/Vdisk/Vdisk.js +0 -275
  113. package/dist/containers/Storage/Vdisk/Vdisk.scss +0 -22
  114. package/dist/containers/Storage/Vdisk/__tests__/colors.tsx +0 -163
  115. package/dist/containers/Tenant/Diagnostics/Compute/Compute.js +0 -139
  116. package/dist/containers/Tenant/Diagnostics/Compute/Compute.scss +0 -14
@@ -1,21 +1,35 @@
1
1
  import type {Reducer} from 'redux';
2
+ import {createSelector, Selector} from 'reselect';
3
+ import {escapeRegExp} from 'lodash/fp';
2
4
 
3
5
  import '../../services/api';
6
+ import {ALL, HOUR_IN_SECONDS, IProblemFilterValues} from '../../utils/constants';
7
+ import {calcUptime, calcUptimeInSeconds} from '../../utils';
4
8
  import {NodesUptimeFilterValues} from '../../utils/nodes';
5
- import {INodesAction, INodesRootStateSlice, INodesState} from '../../types/store/nodes';
9
+ import type {
10
+ INodesAction,
11
+ INodesApiRequestParams,
12
+ INodesHandledResponse,
13
+ INodesPreparedEntity,
14
+ INodesRootStateSlice,
15
+ INodesState,
16
+ } from '../../types/store/nodes';
17
+ import {EFlag} from '../../types/api/enums';
6
18
 
7
19
  import {createRequestActionTypes, createApiRequest} from '../utils';
8
20
 
9
21
  export const FETCH_NODES = createRequestActionTypes('nodes', 'FETCH_NODES');
10
22
 
11
- const CLEAR_NODES = 'nodes/CLEAR_NODES';
23
+ const RESET_NODES_STATE = 'nodes/RESET_NODES_STATE';
12
24
  const SET_NODES_UPTIME_FILTER = 'nodes/SET_NODES_UPTIME_FILTER';
13
25
  const SET_DATA_WAS_NOT_LOADED = 'nodes/SET_DATA_WAS_NOT_LOADED';
26
+ const SET_SEARCH_VALUE = 'nodes/SET_SEARCH_VALUE';
14
27
 
15
28
  const initialState = {
16
- loading: true,
29
+ loading: false,
17
30
  wasLoaded: false,
18
31
  nodesUptimeFilter: NodesUptimeFilterValues.All,
32
+ searchValue: '',
19
33
  };
20
34
 
21
35
  const nodes: Reducer<INodesState, INodesAction> = (state = initialState, action) => {
@@ -29,7 +43,8 @@ const nodes: Reducer<INodesState, INodesAction> = (state = initialState, action)
29
43
  case FETCH_NODES.SUCCESS: {
30
44
  return {
31
45
  ...state,
32
- data: action.data,
46
+ data: action.data?.Nodes,
47
+ totalNodes: action.data?.TotalNodes,
33
48
  loading: false,
34
49
  wasLoaded: true,
35
50
  error: undefined,
@@ -42,22 +57,28 @@ const nodes: Reducer<INodesState, INodesAction> = (state = initialState, action)
42
57
  loading: false,
43
58
  };
44
59
  }
45
- case CLEAR_NODES: {
60
+ case RESET_NODES_STATE: {
46
61
  return {
47
62
  ...state,
48
- loading: true,
49
- data: undefined,
50
- wasLoaded: false,
51
- error: undefined,
63
+ loading: initialState.loading,
64
+ wasLoaded: initialState.wasLoaded,
65
+ nodesUptimeFilter: initialState.nodesUptimeFilter,
66
+ searchValue: initialState.searchValue,
52
67
  };
53
68
  }
54
-
55
69
  case SET_NODES_UPTIME_FILTER: {
56
70
  return {
57
71
  ...state,
58
72
  nodesUptimeFilter: action.data,
59
73
  };
60
74
  }
75
+ case SET_SEARCH_VALUE: {
76
+ return {
77
+ ...state,
78
+ searchValue: action.data,
79
+ };
80
+ }
81
+
61
82
  case SET_DATA_WAS_NOT_LOADED: {
62
83
  return {
63
84
  ...state,
@@ -69,14 +90,68 @@ const nodes: Reducer<INodesState, INodesAction> = (state = initialState, action)
69
90
  }
70
91
  };
71
92
 
72
- export function getNodes(path: string) {
93
+ export function getNodes({tenant, filter, type = 'any'}: INodesApiRequestParams) {
73
94
  return createApiRequest({
74
- request: window.api.getNodes(path),
95
+ request: window.api.getNodes({tenant, filter, type}),
75
96
  actions: FETCH_NODES,
97
+ dataHandler: (data): INodesHandledResponse => {
98
+ const rawNodes = data.Nodes || [];
99
+
100
+ const preparedNodes = rawNodes.map((node) => {
101
+ return {
102
+ ...node?.SystemState,
103
+ Tablets: node?.Tablets,
104
+ NodeId: node?.NodeId,
105
+ Uptime: calcUptime(node?.SystemState?.StartTime),
106
+ TenantName: node?.SystemState?.Tenants?.[0],
107
+ };
108
+ });
109
+
110
+ return {
111
+ Nodes: preparedNodes,
112
+ TotalNodes: Number(data.TotalNodes) || preparedNodes.length,
113
+ };
114
+ },
76
115
  });
77
116
  }
78
117
 
79
- export const clearNodes = () => ({type: CLEAR_NODES} as const);
118
+ export function getComputeNodes(path: string) {
119
+ return createApiRequest({
120
+ request: window.api.getCompute(path),
121
+ actions: FETCH_NODES,
122
+ dataHandler: (data): INodesHandledResponse => {
123
+ const preparedNodes: INodesPreparedEntity[] = [];
124
+
125
+ if (data.Tenants) {
126
+ for (const tenant of data.Tenants) {
127
+ if (tenant && tenant.Nodes) {
128
+ const tenantNodes = tenant.Nodes.map((node) => {
129
+ return {
130
+ ...node,
131
+ TenantName: tenant.Name,
132
+ SystemState: node?.Overall,
133
+ Uptime: calcUptime(node?.StartTime),
134
+ };
135
+ });
136
+
137
+ preparedNodes.push(...tenantNodes);
138
+ }
139
+ }
140
+ }
141
+
142
+ return {
143
+ Nodes: preparedNodes,
144
+ TotalNodes: preparedNodes.length,
145
+ };
146
+ },
147
+ });
148
+ }
149
+
150
+ export const resetNodesState = () => {
151
+ return {
152
+ type: RESET_NODES_STATE,
153
+ } as const;
154
+ };
80
155
 
81
156
  export const setNodesUptimeFilter = (value: NodesUptimeFilterValues) =>
82
157
  ({
@@ -90,6 +165,65 @@ export const setDataWasNotLoaded = () => {
90
165
  } as const;
91
166
  };
92
167
 
93
- export const getNodesUptimeFilter = (state: INodesRootStateSlice) => state.nodes.nodesUptimeFilter;
168
+ export const setSearchValue = (value: string) => {
169
+ return {
170
+ type: SET_SEARCH_VALUE,
171
+ data: value,
172
+ } as const;
173
+ };
174
+
175
+ const getNodesUptimeFilter = (state: INodesRootStateSlice) => state.nodes.nodesUptimeFilter;
176
+ const getSearchValue = (state: INodesRootStateSlice) => state.nodes.searchValue;
177
+ const getNodesList = (state: INodesRootStateSlice) => state.nodes.data;
178
+
179
+ const filterNodesByProblemsStatus = (
180
+ nodesList: INodesPreparedEntity[] = [],
181
+ problemFilter: IProblemFilterValues,
182
+ ) => {
183
+ if (problemFilter === ALL) {
184
+ return nodesList;
185
+ }
186
+
187
+ return nodesList.filter(({SystemState}) => {
188
+ return SystemState && SystemState !== EFlag.Green;
189
+ });
190
+ };
191
+
192
+ export const filterNodesByUptime = (
193
+ nodesList: INodesPreparedEntity[] = [],
194
+ nodesUptimeFilter: NodesUptimeFilterValues,
195
+ ) => {
196
+ if (nodesUptimeFilter === NodesUptimeFilterValues.All) {
197
+ return nodesList;
198
+ }
199
+ return nodesList.filter(({StartTime}) => {
200
+ return !StartTime || calcUptimeInSeconds(StartTime) < HOUR_IN_SECONDS;
201
+ });
202
+ };
203
+
204
+ const filterNodesBySearchValue = (nodesList: INodesPreparedEntity[] = [], searchValue: string) => {
205
+ if (!searchValue) {
206
+ return nodesList;
207
+ }
208
+ const re = new RegExp(escapeRegExp(searchValue), 'i');
209
+
210
+ return nodesList.filter((node) => {
211
+ return node.Host ? re.test(node.Host) || re.test(String(node.NodeId)) : true;
212
+ });
213
+ };
214
+
215
+ export const getFilteredPreparedNodesList: Selector<
216
+ INodesRootStateSlice,
217
+ INodesPreparedEntity[] | undefined
218
+ > = createSelector(
219
+ [getNodesList, getNodesUptimeFilter, getSearchValue, (state) => state.settings.problemFilter],
220
+ (nodesList, uptimeFilter, searchValue, problemFilter) => {
221
+ let result = filterNodesByUptime(nodesList, uptimeFilter);
222
+ result = filterNodesByProblemsStatus(result, problemFilter);
223
+ result = filterNodesBySearchValue(result, searchValue);
224
+
225
+ return result;
226
+ },
227
+ );
94
228
 
95
229
  export default nodes;
@@ -1,12 +1,6 @@
1
- import {createSelector} from 'reselect';
2
-
3
1
  import '../../services/api';
4
- import {ALL} from '../../utils/constants';
5
2
  import {createRequestActionTypes, createApiRequest} from '../utils';
6
3
 
7
- import {filterByUptime} from './storage';
8
- import {getNodesUptimeFilter} from './nodes';
9
-
10
4
  const FETCH_NODES_LIST = createRequestActionTypes('tenants', 'FETCH_NODES_LIST');
11
5
 
12
6
  const initialState = {loading: true, wasLoaded: false, data: []};
@@ -51,39 +45,4 @@ export function getNodesList() {
51
45
  });
52
46
  }
53
47
 
54
- const filterByProblemsStatus = (nodes = [], problemFilter) => {
55
- if (problemFilter === ALL) {
56
- return nodes;
57
- }
58
-
59
- return nodes.filter(({Overall}) => {
60
- return Overall && Overall !== 'Green';
61
- });
62
- };
63
-
64
- export const filterNodesByStatusAndUptime = (nodes = [], problemFilter, uptimeFilter) => {
65
- let result = filterByProblemsStatus(nodes, problemFilter);
66
- result = filterByUptime(result, uptimeFilter);
67
-
68
- return result;
69
- };
70
-
71
- export const getFilteredNodes = createSelector(
72
- [
73
- (state) => state.nodes.data?.Tenants,
74
- (state) => state.settings.problemFilter,
75
- getNodesUptimeFilter,
76
- ],
77
- (tenants, problemFilter, uptimeFilter) => {
78
- const nodes = tenants?.reduce((acc, item) => {
79
- if (Array.isArray(item.Nodes)) {
80
- return [...acc, ...item.Nodes.map((node) => ({...node, TenantName: item.Name}))];
81
- }
82
- return acc;
83
- }, []);
84
-
85
- return filterNodesByStatusAndUptime(nodes, problemFilter, uptimeFilter);
86
- },
87
- );
88
-
89
48
  export default nodesList;
@@ -6,6 +6,7 @@ import {
6
6
  QUERY_INITIAL_RUN_ACTION_KEY,
7
7
  INVERTED_DISKS_KEY,
8
8
  ASIDE_HEADER_COMPACT_KEY,
9
+ USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY,
9
10
  } from '../../utils/constants';
10
11
  import '../../services/api';
11
12
  import {getValueFromLS} from '../../utils/utils';
@@ -17,9 +18,7 @@ const userSettings = window.userSettings || {};
17
18
  const systemSettings = window.systemSettings || {};
18
19
 
19
20
  export function readSavedSettingsValue(key, defaultValue) {
20
- const savedValue = window.web_version
21
- ? userSettings[key]
22
- : getValueFromLS(key);
21
+ const savedValue = window.web_version ? userSettings[key] : getValueFromLS(key);
23
22
 
24
23
  return savedValue ?? defaultValue;
25
24
  }
@@ -40,10 +39,17 @@ export const initialState = {
40
39
  ...userSettings,
41
40
  [THEME_KEY]: readSavedSettingsValue(THEME_KEY, 'light'),
42
41
  [INVERTED_DISKS_KEY]: readSavedSettingsValue(INVERTED_DISKS_KEY, 'false'),
42
+ [USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY]: readSavedSettingsValue(
43
+ USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY,
44
+ 'false',
45
+ ),
43
46
  [SAVED_QUERIES_KEY]: readSavedSettingsValue(SAVED_QUERIES_KEY, '[]'),
44
47
  [TENANT_INITIAL_TAB_KEY]: readSavedSettingsValue(TENANT_INITIAL_TAB_KEY),
45
48
  [QUERY_INITIAL_RUN_ACTION_KEY]: readSavedSettingsValue(QUERY_INITIAL_RUN_ACTION_KEY),
46
- [ASIDE_HEADER_COMPACT_KEY]: readSavedSettingsValue(ASIDE_HEADER_COMPACT_KEY, legacyAsideNavCompactState || 'true'),
49
+ [ASIDE_HEADER_COMPACT_KEY]: readSavedSettingsValue(
50
+ ASIDE_HEADER_COMPACT_KEY,
51
+ legacyAsideNavCompactState || 'true',
52
+ ),
47
53
  },
48
54
  systemSettings,
49
55
  };
@@ -1,14 +1,14 @@
1
1
  import _ from 'lodash';
2
2
  import {createSelector} from 'reselect';
3
3
 
4
- import {calcUptime, calcUptimeInSeconds} from '../../utils';
4
+ import {calcUptime} from '../../utils';
5
5
  import {getUsage} from '../../utils/storage';
6
6
  import {NodesUptimeFilterValues} from '../../utils/nodes';
7
7
  import {getPDiskType} from '../../utils/pdisk';
8
- import {HOUR_IN_SECONDS} from '../../utils/constants';
9
8
  import '../../services/api';
10
9
 
11
10
  import {createRequestActionTypes, createApiRequest} from '../utils';
11
+ import {filterNodesByUptime} from './nodes';
12
12
 
13
13
  export const VisibleEntities = {
14
14
  All: 'All',
@@ -135,8 +135,15 @@ export function setInitialState() {
135
135
  }
136
136
 
137
137
  export function getStorageInfo({tenant, filter, nodeId, type}, {concurrentId}) {
138
+ if (type === StorageTypes.nodes) {
139
+ return createApiRequest({
140
+ request: window.api.getNodes({tenant, filter, type: 'static'}, {concurrentId}),
141
+ actions: FETCH_STORAGE,
142
+ });
143
+ }
144
+
138
145
  return createApiRequest({
139
- request: window.api.getStorageInfo({tenant, filter, nodeId, type}, {concurrentId}),
146
+ request: window.api.getStorageInfo({tenant, filter, nodeId}, {concurrentId}),
140
147
  actions: FETCH_STORAGE,
141
148
  });
142
149
  }
@@ -317,6 +324,19 @@ export const getFlatListStorageNodes = createSelector([getStorageNodes], (storag
317
324
  });
318
325
  });
319
326
 
327
+ export const getVDisksForPDisk = createSelector(
328
+ getStorageNodes,
329
+ (_state, nodeId) => nodeId,
330
+ (_state, _nodeId, pdiskId) => pdiskId,
331
+ (storageNodes, nodeId, pdiskId) => {
332
+ const targetNode = storageNodes?.find((node) => node.NodeId === nodeId);
333
+ return targetNode?.VDisks?.filter((vdisk) => vdisk.PDiskId === pdiskId).map((data) => ({
334
+ ...data,
335
+ NodeId: nodeId,
336
+ }));
337
+ },
338
+ );
339
+
320
340
  export const getFlatListStorage = createSelector(
321
341
  [getStorageType, getFlatListStorageGroups, getFlatListStorageNodes],
322
342
  (storageType, groupsList, nodesList) => {
@@ -373,15 +393,6 @@ const filterByUsage = (entities, usage) => {
373
393
  });
374
394
  };
375
395
 
376
- export const filterByUptime = (nodes = [], nodesUptimeFilter) => {
377
- if (nodesUptimeFilter === NodesUptimeFilterValues.All) {
378
- return nodes;
379
- }
380
- return nodes.filter(({StartTime}) => {
381
- return !StartTime || calcUptimeInSeconds(StartTime) < HOUR_IN_SECONDS;
382
- });
383
- };
384
-
385
396
  export const getFilteredEntities = createSelector(
386
397
  [
387
398
  getStorageFilter,
@@ -396,7 +407,7 @@ export const getFilteredEntities = createSelector(
396
407
  result = filterByUsage(result, usageFilter);
397
408
 
398
409
  if (type === StorageTypes.nodes) {
399
- result = filterByUptime(result, nodesUptimeFilter);
410
+ result = filterNodesByUptime(result, nodesUptimeFilter);
400
411
  }
401
412
 
402
413
  return result;
@@ -5,6 +5,7 @@ import _ from 'lodash';
5
5
  const FETCH_TENANT = createRequestActionTypes('tenant', 'FETCH_TENANT');
6
6
  const SET_TOP_LEVEL_TAB = 'tenant/SET_TOP_LEVEL_TAB';
7
7
  const SET_DIAGNOSTICS_TAB = 'tenant/SET_DIAGNOSTICS_TAB';
8
+ const CLEAR_TENANT = 'tenant/CLEAR_TENANT';
8
9
 
9
10
  const tenantReducer = (state = {loading: false, wasLoaded: false, tenant: {}}, action) => {
10
11
  switch (action.type) {
@@ -37,7 +38,7 @@ const tenantReducer = (state = {loading: false, wasLoaded: false, tenant: {}}, a
37
38
  };
38
39
  }
39
40
 
40
- case 'CLEAR_TENANT': {
41
+ case CLEAR_TENANT: {
41
42
  return {
42
43
  ...state,
43
44
  tenant: {},
@@ -65,12 +66,12 @@ const tenantReducer = (state = {loading: false, wasLoaded: false, tenant: {}}, a
65
66
  };
66
67
 
67
68
  export const clearTenant = () => {
68
- return {type: 'CLEAR_TENANT'};
69
+ return {type: CLEAR_TENANT};
69
70
  };
70
71
 
71
72
  export const getTenantInfo = ({path}) => {
72
73
  return createApiRequest({
73
- request: Promise.all([window.api.getTenantInfo({path}), window.api.getNodes(path)]),
74
+ request: Promise.all([window.api.getTenantInfo({path}), window.api.getCompute(path)]),
74
75
  actions: FETCH_TENANT,
75
76
  dataHandler: ([tenantData, nodesData]) => {
76
77
  const tenant = tenantData.TenantInfo[0];
@@ -83,7 +84,7 @@ export const getTenantInfo = ({path}) => {
83
84
  };
84
85
  }
85
86
 
86
- return;
87
+ return undefined;
87
88
  }).filter(Boolean);
88
89
 
89
90
  return {tenant, tenantNodes};
@@ -62,7 +62,7 @@ export const hideTooltip = () => {
62
62
  };
63
63
 
64
64
  export const showTooltip = (
65
- node: EventTarget,
65
+ node: EventTarget | null,
66
66
  data: any,
67
67
  templateType: ITooltipTemplateType,
68
68
  additionalData?: any,
@@ -0,0 +1,52 @@
1
+ import type {Reducer} from 'redux';
2
+
3
+ import type {ITopicAction, ITopicState} from '../../types/store/topic';
4
+ import '../../services/api';
5
+
6
+ import {createRequestActionTypes, createApiRequest} from '../utils';
7
+
8
+ export const FETCH_TOPIC = createRequestActionTypes('topic', 'FETCH_TOPIC');
9
+
10
+ const initialState = {
11
+ loading: true,
12
+ wasLoaded: false,
13
+ data: {},
14
+ };
15
+
16
+ const topic: Reducer<ITopicState, ITopicAction> = (state = initialState, action) => {
17
+ switch (action.type) {
18
+ case FETCH_TOPIC.REQUEST: {
19
+ return {
20
+ ...state,
21
+ loading: true,
22
+ };
23
+ }
24
+ case FETCH_TOPIC.SUCCESS: {
25
+ return {
26
+ ...state,
27
+ data: action.data,
28
+ loading: false,
29
+ wasLoaded: true,
30
+ error: undefined,
31
+ };
32
+ }
33
+ case FETCH_TOPIC.FAILURE: {
34
+ return {
35
+ ...state,
36
+ error: action.error,
37
+ loading: false,
38
+ };
39
+ }
40
+ default:
41
+ return state;
42
+ }
43
+ };
44
+
45
+ export function getTopic(path?: string) {
46
+ return createApiRequest({
47
+ request: window.api.getTopic({path}),
48
+ actions: FETCH_TOPIC,
49
+ });
50
+ }
51
+
52
+ export default topic;
@@ -79,6 +79,14 @@
79
79
  width: 238px;
80
80
  }
81
81
 
82
+ @mixin info-viewer-title {
83
+ margin: 15px 0 10px;
84
+
85
+ font-size: var(--yc-text-body-2-font-size);
86
+ font-weight: 600;
87
+ line-height: var(--yc-text-body-2-line-height);
88
+ }
89
+
82
90
  @mixin query-data-table() {
83
91
  & .data-table {
84
92
  $_: &;
@@ -128,17 +136,6 @@
128
136
  $border-width: 1px;
129
137
  $clearance-width: 1px; /* Delete clearance and cancel column shadow for previous columns */
130
138
 
131
- @for $i from 0 through $nth {
132
- & .data-table__td:nth-child(#{$i}),
133
- & .data-table__head-row:first-child .data-table__th:nth-child(#{$i}) {
134
- box-shadow: unset;
135
-
136
- @if $i < $nth {
137
- border-right: unset;
138
- }
139
- }
140
- }
141
-
142
139
  /* Freeze td */
143
140
  & .data-table__td:nth-child(#{$nth}),
144
141
  & .data-table__head-row:first-child .data-table__th:nth-child(#{$nth}) {
@@ -152,6 +149,17 @@
152
149
  .data-table__row:hover .data-table__td:nth-child(#{$nth}) {
153
150
  background-color: var(--ydb-data-table-color-hover) !important;
154
151
  }
152
+
153
+ @for $i from 0 through $nth {
154
+ & .data-table__td:nth-child(#{$i}),
155
+ & .data-table__head-row:first-child .data-table__th:nth-child(#{$i}) {
156
+ box-shadow: unset;
157
+
158
+ @if $i < $nth {
159
+ border-right: unset;
160
+ }
161
+ }
162
+ }
155
163
  }
156
164
 
157
165
  @mixin table-styles {
@@ -0,0 +1,5 @@
1
+ export interface IProtobufTimeObject {
2
+ /** int64 */
3
+ seconds?: string;
4
+ nanos?: number;
5
+ }
@@ -17,7 +17,7 @@ interface TComputeTenantInfo {
17
17
  Nodes?: TComputeNodeInfo[];
18
18
  }
19
19
 
20
- interface TComputeNodeInfo {
20
+ export interface TComputeNodeInfo {
21
21
  /** uint64 */
22
22
  StartTime: string;
23
23
  /** uint64 */
@@ -1,5 +1,7 @@
1
1
  /* eslint-disable camelcase */
2
2
 
3
+ import {IProtobufTimeObject} from './common';
4
+
3
5
  /**
4
6
  * endpoint: /json/describe_consumer
5
7
  *
@@ -65,27 +67,27 @@ interface PartitionConsumerStats {
65
67
  *
66
68
  * Timestamp of providing this partition to this session by server.
67
69
  */
68
- partition_read_session_create_time?: string;
70
+ partition_read_session_create_time?: string | IProtobufTimeObject;
69
71
 
70
72
  /**
71
73
  * google.protobuf.Timestamp
72
74
  *
73
75
  * Timestamp of last read from this partition. */
74
- last_read_time?: string;
76
+ last_read_time?: string | IProtobufTimeObject;
75
77
 
76
78
  /**
77
79
  * google.protobuf.Duration
78
80
  *
79
81
  * Maximum of differences between timestamp of read and write timestamp for all messages, read during last minute.
80
82
  */
81
- max_read_time_lag?: string;
83
+ max_read_time_lag?: string | IProtobufTimeObject;
82
84
 
83
85
  /**
84
86
  * google.protobuf.Duration
85
87
  *
86
88
  * Maximum of differences between write timestamp and create timestamp for all messages, read during last minute.
87
89
  */
88
- max_write_time_lag?: string;
90
+ max_write_time_lag?: string | IProtobufTimeObject;
89
91
 
90
92
  /** How much bytes were read during several windows statistics from this partiton. */
91
93
  bytes_read?: MultipleWindowsStat;
@@ -113,14 +115,14 @@ export interface PartitionStats {
113
115
  *
114
116
  * Timestamp of last write.
115
117
  */
116
- last_write_time?: string;
118
+ last_write_time?: string | IProtobufTimeObject;
117
119
 
118
120
  /**
119
121
  * google.protobuf.Duration
120
122
  *
121
123
  * Maximum of differences between write timestamp and create timestamp for all messages, written during last minute.
122
124
  */
123
- max_write_time_lag?: string;
125
+ max_write_time_lag?: string | IProtobufTimeObject;
124
126
 
125
127
  /** How much bytes were written during several windows in this partition. */
126
128
  bytes_written?: MultipleWindowsStat;
@@ -148,7 +150,7 @@ export interface Consumer {
148
150
  *
149
151
  * All messages with smaller server written_at timestamp will be skipped.
150
152
  */
151
- read_from?: string;
153
+ read_from?: string | IProtobufTimeObject;
152
154
 
153
155
  /**
154
156
  * List of supported codecs by this consumer.
@@ -170,21 +172,21 @@ interface ConsumerStats {
170
172
  *
171
173
  * Minimal timestamp of last read from partitions.
172
174
  */
173
- min_partitions_last_read_time?: string;
175
+ min_partitions_last_read_time?: string | IProtobufTimeObject;
174
176
 
175
177
  /**
176
178
  * google.protobuf.Duration
177
179
  *
178
180
  * Maximum of differences between timestamp of read and write timestamp for all messages, read during last minute.
179
181
  */
180
- max_read_time_lag?: string;
182
+ max_read_time_lag?: string | IProtobufTimeObject;
181
183
 
182
184
  /**
183
185
  * google.protobuf.Duration
184
186
  *
185
187
  * Maximum of differences between write timestamp and create timestamp for all messages, read during last minute.
186
188
  */
187
- max_write_time_lag?: string;
189
+ max_write_time_lag?: string | IProtobufTimeObject;
188
190
 
189
191
  /** Bytes read stastics. */
190
192
  bytes_read?: MultipleWindowsStat;
@@ -1,6 +1,7 @@
1
1
  import {EFlag} from './enums';
2
2
  import {TPDiskStateInfo} from './pdisk';
3
3
  import {TTabletStateInfo} from './tablet';
4
+ import {TVDiskStateInfo} from './vdisk';
4
5
 
5
6
  // endpoint: /viewer/json/nodes
6
7
  // source: https://github.com/ydb-platform/ydb/blob/main/ydb/core/viewer/protos/viewer.proto
@@ -19,6 +20,7 @@ export interface TNodeInfo {
19
20
  NodeId: number;
20
21
  SystemState: TSystemStateInfo;
21
22
  PDisks?: TPDiskStateInfo[];
23
+ VDisks?: TVDiskStateInfo[];
22
24
  Tablets?: TTabletStateInfo[];
23
25
  }
24
26
 
@@ -44,6 +44,7 @@ export enum TPDiskState {
44
44
  ChunkQuotaError = 'ChunkQuotaError',
45
45
  DeviceIoError = 'DeviceIoError',
46
46
 
47
+ // these can't be sent to UI
47
48
  Missing = 'Missing',
48
49
  Timeout = 'Timeout',
49
50
  NodeDisconnected = 'NodeDisconnected',