ydb-embedded-ui 3.2.2 → 3.3.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 (118) 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/Consumers/Consumers.tsx +2 -1
  53. package/dist/containers/Tenant/Diagnostics/Diagnostics.scss +2 -2
  54. package/dist/containers/Tenant/Diagnostics/Diagnostics.tsx +3 -4
  55. package/dist/containers/Tenant/Diagnostics/OverloadedShards/OverloadedShards.tsx +1 -1
  56. package/dist/containers/Tenant/Diagnostics/Overview/ChangefeedInfo/ChangefeedInfo.tsx +69 -0
  57. package/dist/containers/Tenant/Diagnostics/Overview/ChangefeedInfo/index.ts +1 -0
  58. package/dist/containers/Tenant/Diagnostics/Overview/Overview.tsx +18 -16
  59. package/dist/containers/Tenant/Diagnostics/Overview/TopicInfo/TopicInfo.tsx +37 -0
  60. package/dist/containers/Tenant/Diagnostics/Overview/TopicInfo/index.ts +1 -0
  61. package/dist/containers/Tenant/Diagnostics/Overview/TopicStats/TopicStats.scss +30 -0
  62. package/dist/containers/Tenant/Diagnostics/Overview/TopicStats/TopicStats.tsx +94 -0
  63. package/dist/containers/Tenant/Diagnostics/Overview/TopicStats/i18n/en.json +3 -0
  64. package/dist/containers/Tenant/Diagnostics/Overview/TopicStats/i18n/index.ts +11 -0
  65. package/dist/containers/Tenant/Diagnostics/Overview/TopicStats/i18n/ru.json +3 -0
  66. package/dist/containers/Tenant/Diagnostics/Overview/TopicStats/index.ts +1 -0
  67. package/dist/containers/Tenant/Diagnostics/Overview/utils/index.ts +1 -0
  68. package/dist/containers/Tenant/Diagnostics/Overview/utils/prepareTopicSchemaInfo.ts +42 -0
  69. package/dist/containers/Tenant/utils/schema.ts +19 -0
  70. package/dist/containers/Tenants/Tenants.js +2 -1
  71. package/dist/containers/UserSettings/UserSettings.tsx +18 -10
  72. package/dist/services/api.d.ts +8 -1
  73. package/dist/services/api.js +27 -8
  74. package/dist/store/reducers/index.ts +3 -1
  75. package/dist/store/reducers/nodes.ts +148 -14
  76. package/dist/store/reducers/{clusterNodes.js → nodesList.js} +0 -41
  77. package/dist/store/reducers/settings.js +10 -4
  78. package/dist/store/reducers/storage.js +24 -13
  79. package/dist/store/reducers/tenant.js +5 -4
  80. package/dist/store/reducers/tooltip.ts +1 -1
  81. package/dist/store/reducers/topic.ts +52 -0
  82. package/dist/styles/mixins.scss +19 -11
  83. package/dist/types/api/common.ts +5 -0
  84. package/dist/types/api/compute.ts +1 -1
  85. package/dist/types/api/consumer.ts +12 -10
  86. package/dist/types/api/nodes.ts +2 -0
  87. package/dist/types/api/pdisk.ts +1 -0
  88. package/dist/types/api/schema.ts +3 -3
  89. package/dist/types/api/topic.ts +5 -4
  90. package/dist/types/api/vdisk.ts +2 -1
  91. package/dist/types/store/nodes.ts +56 -6
  92. package/dist/types/store/tooltip.ts +1 -1
  93. package/dist/types/store/topic.ts +21 -0
  94. package/dist/utils/constants.ts +5 -1
  95. package/dist/utils/i18n/i18n.ts +10 -2
  96. package/dist/utils/index.js +1 -1
  97. package/dist/utils/timeParsers/__test__/formatDuration.test.ts +50 -0
  98. package/dist/utils/timeParsers/__test__/protobuf.test.ts +74 -0
  99. package/dist/utils/timeParsers/formatDuration.ts +46 -0
  100. package/dist/utils/timeParsers/i18n/en.json +7 -0
  101. package/dist/utils/timeParsers/i18n/index.ts +11 -0
  102. package/dist/utils/timeParsers/i18n/ru.json +7 -0
  103. package/dist/utils/timeParsers/index.ts +2 -0
  104. package/dist/utils/timeParsers/protobuf.ts +36 -0
  105. package/package.json +1 -1
  106. package/dist/components/InfoViewer/schemaInfo/CDCStreamInfo.tsx +0 -48
  107. package/dist/components/InfoViewer/schemaInfo/PersQueueGroupInfo.tsx +0 -30
  108. package/dist/components/InternalLink/InternalLink.js +0 -23
  109. package/dist/containers/Nodes/Nodes.js +0 -213
  110. package/dist/containers/NodesViewer/NodesViewer.js +0 -163
  111. package/dist/containers/NodesViewer/NodesViewer.scss +0 -66
  112. package/dist/containers/Storage/Pdisk/Pdisk.tsx +0 -153
  113. package/dist/containers/Storage/Pdisk/__tests__/colors.tsx +0 -41
  114. package/dist/containers/Storage/Vdisk/Vdisk.js +0 -275
  115. package/dist/containers/Storage/Vdisk/Vdisk.scss +0 -22
  116. package/dist/containers/Storage/Vdisk/__tests__/colors.tsx +0 -163
  117. package/dist/containers/Tenant/Diagnostics/Compute/Compute.js +0 -139
  118. 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',