ydb-embedded-ui 2.4.4 → 2.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/dist/components/InfoViewer/InfoViewer.scss +3 -3
  3. package/dist/components/InfoViewer/formatters/schema.ts +2 -1
  4. package/dist/components/InfoViewer/schemaInfo/CDCStreamInfo.tsx +23 -22
  5. package/dist/components/InfoViewer/schemaInfo/PersQueueGroupInfo.tsx +8 -13
  6. package/dist/components/InfoViewer/schemaInfo/TableIndexInfo.tsx +2 -12
  7. package/dist/components/InfoViewer/schemaOverview/CDCStreamOverview.tsx +3 -16
  8. package/dist/components/InfoViewer/schemaOverview/PersQueueGroupOverview.tsx +8 -13
  9. package/dist/components/InfoViewer/utils.ts +6 -6
  10. package/dist/components/Loader/Loader.scss +6 -3
  11. package/dist/components/Loader/Loader.tsx +7 -5
  12. package/dist/components/Loader/index.ts +1 -0
  13. package/dist/components/UptimeFIlter/UptimeFilter.tsx +21 -0
  14. package/dist/components/UptimeFIlter/index.ts +1 -0
  15. package/dist/containers/Node/Node.scss +1 -0
  16. package/dist/containers/Node/Node.tsx +3 -8
  17. package/dist/containers/Node/NodeStructure/NodeStructure.scss +0 -6
  18. package/dist/containers/Node/NodeStructure/NodeStructure.tsx +1 -1
  19. package/dist/containers/Nodes/Nodes.js +22 -10
  20. package/dist/{components → containers}/NodesViewer/NodesViewer.js +49 -62
  21. package/dist/{components → containers}/NodesViewer/NodesViewer.scss +0 -0
  22. package/dist/containers/Storage/Pdisk/Pdisk.scss +1 -1
  23. package/dist/containers/Storage/Pdisk/Pdisk.tsx +3 -9
  24. package/dist/containers/Storage/Pdisk/__tests__/colors.tsx +1 -1
  25. package/dist/containers/Storage/Storage.js +46 -11
  26. package/dist/containers/Storage/StorageGroups/StorageGroups.tsx +39 -32
  27. package/dist/containers/Storage/StorageNodes/StorageNodes.scss +2 -2
  28. package/dist/containers/Storage/StorageNodes/StorageNodes.tsx +35 -17
  29. package/dist/containers/Storage/StorageNodes/i18n/en.json +6 -4
  30. package/dist/containers/Storage/StorageNodes/i18n/ru.json +6 -4
  31. package/dist/containers/Storage/UsageFilter/UsageFilter.scss +10 -5
  32. package/dist/containers/Tenant/Acl/Acl.js +1 -7
  33. package/dist/containers/Tenant/Diagnostics/Compute/Compute.js +22 -14
  34. package/dist/containers/Tenant/Diagnostics/Consumers/Consumers.tsx +52 -10
  35. package/dist/containers/Tenant/Diagnostics/Describe/Describe.scss +0 -8
  36. package/dist/containers/Tenant/Diagnostics/Describe/Describe.tsx +42 -15
  37. package/dist/containers/Tenant/Diagnostics/Diagnostics.scss +0 -7
  38. package/dist/containers/Tenant/Diagnostics/Diagnostics.tsx +19 -15
  39. package/dist/containers/Tenant/Diagnostics/DiagnosticsPages.ts +1 -1
  40. package/dist/containers/Tenant/Diagnostics/Healthcheck/Healthcheck.tsx +13 -5
  41. package/dist/containers/Tenant/Diagnostics/Network/Network.js +17 -4
  42. package/dist/containers/Tenant/Diagnostics/Overview/Overview.tsx +50 -16
  43. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.js +16 -2
  44. package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.js +1 -0
  45. package/dist/containers/Tenant/Diagnostics/TopShards/TopShards.js +21 -13
  46. package/dist/containers/Tenant/ObjectGeneral/ObjectGeneral.tsx +1 -5
  47. package/dist/containers/Tenant/QueryEditor/QueryExplain/QueryExplain.js +4 -4
  48. package/dist/containers/Tenant/QueryEditor/SaveQuery/SaveQuery.js +1 -4
  49. package/dist/containers/Tenant/Schema/SchemaInfoViewer/SchemaInfoViewer.js +23 -28
  50. package/dist/containers/Tenant/Schema/SchemaTree/SchemaTree.tsx +2 -2
  51. package/dist/containers/Tenant/TenantPages.tsx +1 -1
  52. package/dist/containers/Tenant/utils/schema.ts +84 -0
  53. package/dist/containers/Tenant/utils/schemaActions.ts +9 -20
  54. package/dist/services/api.d.ts +17 -11
  55. package/dist/store/reducers/clusterNodes.js +29 -10
  56. package/dist/store/reducers/describe.ts +56 -14
  57. package/dist/store/reducers/healthcheckInfo.ts +23 -8
  58. package/dist/store/reducers/network.js +22 -1
  59. package/dist/store/reducers/nodes.js +37 -3
  60. package/dist/store/reducers/schema.ts +229 -0
  61. package/dist/store/reducers/storage.js +59 -5
  62. package/dist/types/api/enums.ts +10 -0
  63. package/dist/types/api/nodes.ts +96 -0
  64. package/dist/types/api/pdisk.ts +48 -0
  65. package/dist/types/api/schema.ts +148 -9
  66. package/dist/types/api/storage.ts +3 -173
  67. package/dist/types/api/tablet.ts +97 -0
  68. package/dist/types/api/vdisk.ts +120 -0
  69. package/dist/types/store/describe.ts +8 -2
  70. package/dist/types/store/healthcheck.ts +12 -0
  71. package/dist/types/store/schema.ts +52 -0
  72. package/dist/utils/index.js +6 -2
  73. package/dist/utils/nodes.ts +9 -0
  74. package/dist/utils/pdisk.ts +1 -1
  75. package/dist/utils/storage.ts +1 -1
  76. package/package.json +1 -1
  77. package/dist/store/reducers/schema.js +0 -148
@@ -3,7 +3,13 @@ import {Reducer} from 'redux';
3
3
 
4
4
  import '../../services/api';
5
5
  import {IConsumer} from '../../types/api/consumers';
6
- import {IDescribeRootStateSlice, IDescribeState, IDescribeAction} from '../../types/store/describe';
6
+ import {
7
+ IDescribeRootStateSlice,
8
+ IDescribeState,
9
+ IDescribeAction,
10
+ IDescribeHandledResponse,
11
+ IDescribeData,
12
+ } from '../../types/store/describe';
7
13
  import {createRequestActionTypes, createApiRequest} from '../utils';
8
14
 
9
15
  export const FETCH_DESCRIBE = createRequestActionTypes('describe', 'FETCH_DESCRIBE');
@@ -27,16 +33,8 @@ const describe: Reducer<IDescribeState, IDescribeAction> = (state = initialState
27
33
  };
28
34
  }
29
35
  case FETCH_DESCRIBE.SUCCESS: {
30
- const data = action.data;
31
-
32
- const isCurrentDescribePath = data.Path === state.currentDescribePath;
33
-
34
- let newData = state.data;
35
-
36
- if (data.Path) {
37
- newData = JSON.parse(JSON.stringify(state.data));
38
- newData[data.Path] = data;
39
- }
36
+ const isCurrentDescribePath = action.data.path === state.currentDescribePath;
37
+ const newData = {...state.data, ...action.data.data};
40
38
 
41
39
  if (!isCurrentDescribePath) {
42
40
  return {
@@ -48,7 +46,7 @@ const describe: Reducer<IDescribeState, IDescribeAction> = (state = initialState
48
46
  return {
49
47
  ...state,
50
48
  data: newData,
51
- currentDescribe: data,
49
+ currentDescribe: action.data.currentDescribe,
52
50
  loading: false,
53
51
  wasLoaded: true,
54
52
  error: undefined,
@@ -97,7 +95,7 @@ export const setDataWasNotLoaded = () => {
97
95
  };
98
96
 
99
97
  // Consumers selectors
100
- const selectConsumersNames = (state: IDescribeRootStateSlice, path: string | undefined) =>
98
+ const selectConsumersNames = (state: IDescribeRootStateSlice, path?: string) =>
101
99
  path
102
100
  ? state.describe.data[path]?.PathDescription?.PersQueueGroup?.PQTabletConfig?.ReadRules
103
101
  : undefined;
@@ -106,9 +104,53 @@ export const selectConsumers: Selector<IDescribeRootStateSlice, IConsumer[], [st
106
104
  createSelector(selectConsumersNames, (names = []) => names.map((name) => ({name})));
107
105
 
108
106
  export function getDescribe({path}: {path: string}) {
107
+ const request = window.api.getDescribe({path});
108
+ return createApiRequest({
109
+ request,
110
+ actions: FETCH_DESCRIBE,
111
+ dataHandler: (data): IDescribeHandledResponse => {
112
+ const dataPath = data.Path;
113
+ const currentDescribe: IDescribeData = {};
114
+ const newData: IDescribeData = {};
115
+
116
+ if (dataPath) {
117
+ currentDescribe[dataPath] = data;
118
+ newData[dataPath] = data;
119
+ }
120
+
121
+ return {
122
+ path: dataPath,
123
+ currentDescribe,
124
+ data: newData,
125
+ };
126
+ },
127
+ });
128
+ }
129
+
130
+ export function getDescribeBatched(paths: string[]) {
131
+ const requestsArray = paths.map((p) => window.api.getDescribe({path: p}));
132
+
133
+ const request = Promise.all(requestsArray);
109
134
  return createApiRequest({
110
- request: window.api.getDescribe({path}),
135
+ request,
111
136
  actions: FETCH_DESCRIBE,
137
+ dataHandler: (data): IDescribeHandledResponse => {
138
+ const currentDescribe: IDescribeData = {};
139
+ const newData: IDescribeData = {};
140
+
141
+ data.forEach((dataItem) => {
142
+ if (dataItem.Path) {
143
+ newData[dataItem.Path] = dataItem;
144
+ currentDescribe[dataItem.Path] = dataItem;
145
+ }
146
+ });
147
+
148
+ return {
149
+ path: data[0].Path,
150
+ currentDescribe,
151
+ data: newData,
152
+ };
153
+ },
112
154
  });
113
155
  }
114
156
 
@@ -9,21 +9,23 @@ import {
9
9
  IHealthcheckInfoState,
10
10
  IHealthcheckInfoRootStateSlice,
11
11
  IIssuesTree,
12
+ IHealthCheckInfoAction,
12
13
  } from '../../types/store/healthcheck';
13
- import {HealthCheckAPIResponse, IssueLog, StatusFlag} from '../../types/api/healthcheck';
14
- import {IResponseError} from '../../types/api/error';
14
+ import {IssueLog, StatusFlag} from '../../types/api/healthcheck';
15
15
 
16
16
  import '../../services/api';
17
- import {createRequestActionTypes, createApiRequest, ApiRequestAction} from '../utils';
17
+ import {createRequestActionTypes, createApiRequest} from '../utils';
18
18
 
19
- const FETCH_HEALTHCHECK = createRequestActionTypes('cluster', 'FETCH_HEALTHCHECK');
19
+ export const FETCH_HEALTHCHECK = createRequestActionTypes('cluster', 'FETCH_HEALTHCHECK');
20
+
21
+ const SET_DATA_WAS_NOT_LOADED = 'healthcheckInfo/SET_DATA_WAS_NOT_LOADED';
20
22
 
21
23
  const initialState = {loading: false, wasLoaded: false};
22
24
 
23
- const healthcheckInfo: Reducer<
24
- IHealthcheckInfoState,
25
- ApiRequestAction<typeof FETCH_HEALTHCHECK, HealthCheckAPIResponse, IResponseError>
26
- > = function (state = initialState, action) {
25
+ const healthcheckInfo: Reducer<IHealthcheckInfoState, IHealthCheckInfoAction> = function (
26
+ state = initialState,
27
+ action,
28
+ ) {
27
29
  switch (action.type) {
28
30
  case FETCH_HEALTHCHECK.REQUEST: {
29
31
  return {
@@ -49,6 +51,13 @@ const healthcheckInfo: Reducer<
49
51
  loading: false,
50
52
  };
51
53
  }
54
+
55
+ case SET_DATA_WAS_NOT_LOADED: {
56
+ return {
57
+ ...state,
58
+ wasLoaded: false,
59
+ };
60
+ }
52
61
  default:
53
62
  return state;
54
63
  }
@@ -127,4 +136,10 @@ export function getHealthcheckInfo(database: string) {
127
136
  });
128
137
  }
129
138
 
139
+ export const setDataWasNotLoaded = () => {
140
+ return {
141
+ type: SET_DATA_WAS_NOT_LOADED,
142
+ } as const;
143
+ };
144
+
130
145
  export default healthcheckInfo;
@@ -6,7 +6,15 @@ const FETCH_ALL_NODES_NETWORK = createRequestActionTypes(
6
6
  'FETCH_ALL_NODES_NETWORK',
7
7
  );
8
8
 
9
- const network = (state = {data: {}, loading: true, wasLoaded: false}, action) => {
9
+ const SET_DATA_WAS_NOT_LOADED = 'network/SET_DATA_WAS_NOT_LOADED';
10
+
11
+ const initialState = {
12
+ data: {},
13
+ loading: false,
14
+ wasLoaded: false,
15
+ };
16
+
17
+ const network = (state = initialState, action) => {
10
18
  switch (action.type) {
11
19
  case FETCH_ALL_NODES_NETWORK.REQUEST: {
12
20
  return {
@@ -30,11 +38,24 @@ const network = (state = {data: {}, loading: true, wasLoaded: false}, action) =>
30
38
  loading: false,
31
39
  };
32
40
  }
41
+
42
+ case SET_DATA_WAS_NOT_LOADED: {
43
+ return {
44
+ ...state,
45
+ wasLoaded: false,
46
+ };
47
+ }
33
48
  default:
34
49
  return state;
35
50
  }
36
51
  };
37
52
 
53
+ export const setDataWasNotLoaded = () => {
54
+ return {
55
+ type: SET_DATA_WAS_NOT_LOADED,
56
+ };
57
+ };
58
+
38
59
  export const getNetworkInfo = (tenant) => {
39
60
  return createApiRequest({
40
61
  request: window.api.getNetwork(tenant),
@@ -1,9 +1,20 @@
1
1
  import {createRequestActionTypes, createApiRequest} from '../utils';
2
2
  import '../../services/api';
3
+ import {NodesUptimeFilterValues} from '../../utils/nodes';
3
4
 
4
5
  const FETCH_NODES = createRequestActionTypes('nodes', 'FETCH_NODES');
5
6
 
6
- const nodes = function z(state = {loading: true, wasLoaded: false}, action) {
7
+ const CLEAR_NODES = 'nodes/CLEAR_NODES';
8
+ const SET_NODES_UPTIME_FILTER = 'nodes/SET_NODES_UPTIME_FILTER';
9
+ const SET_DATA_WAS_NOT_LOADED = 'nodes/SET_DATA_WAS_NOT_LOADED';
10
+
11
+ const initialState = {
12
+ loading: true,
13
+ wasLoaded: false,
14
+ nodesUptimeFilter: NodesUptimeFilterValues.All,
15
+ };
16
+
17
+ const nodes = (state = initialState, action) => {
7
18
  switch (action.type) {
8
19
  case FETCH_NODES.REQUEST: {
9
20
  return {
@@ -28,7 +39,7 @@ const nodes = function z(state = {loading: true, wasLoaded: false}, action) {
28
39
  loading: false,
29
40
  };
30
41
  }
31
- case 'CLEAR_NODES': {
42
+ case CLEAR_NODES: {
32
43
  return {
33
44
  ...state,
34
45
  loading: true,
@@ -38,6 +49,16 @@ const nodes = function z(state = {loading: true, wasLoaded: false}, action) {
38
49
  error: undefined,
39
50
  };
40
51
  }
52
+
53
+ case SET_NODES_UPTIME_FILTER: {
54
+ return {...state, nodesUptimeFilter: action.data};
55
+ }
56
+ case SET_DATA_WAS_NOT_LOADED: {
57
+ return {
58
+ ...state,
59
+ wasLoaded: false,
60
+ };
61
+ }
41
62
  default:
42
63
  return state;
43
64
  }
@@ -50,6 +71,19 @@ export function getNodes(path) {
50
71
  });
51
72
  }
52
73
 
53
- export const clearNodes = () => ({type: 'CLEAR_NODES'});
74
+ export const clearNodes = () => ({type: CLEAR_NODES});
75
+
76
+ export const setNodesUptimeFilter = (value) => ({
77
+ type: SET_NODES_UPTIME_FILTER,
78
+ data: value,
79
+ });
80
+
81
+ export const setDataWasNotLoaded = () => {
82
+ return {
83
+ type: SET_DATA_WAS_NOT_LOADED,
84
+ };
85
+ };
86
+
87
+ export const getNodesUptimeFilter = (state) => state.nodes.nodesUptimeFilter;
54
88
 
55
89
  export default nodes;
@@ -0,0 +1,229 @@
1
+ import {Reducer} from 'redux';
2
+ import {createSelector, Selector} from 'reselect';
3
+
4
+ import {
5
+ ISchemaAction,
6
+ ISchemaData,
7
+ ISchemaHandledResponse,
8
+ ISchemaRootStateSlice,
9
+ ISchemaState,
10
+ } from '../../types/store/schema';
11
+ import {EPathType} from '../../types/api/schema';
12
+ import '../../services/api';
13
+ import {isEntityWithMergedImplementation} from '../../containers/Tenant/utils/schema';
14
+
15
+ import {createRequestActionTypes, createApiRequest} from '../utils';
16
+
17
+ export const FETCH_SCHEMA = createRequestActionTypes('schema', 'FETCH_SCHEMA');
18
+ const PRELOAD_SCHEMAS = 'schema/PRELOAD_SCHEMAS';
19
+ const SET_SCHEMA = 'schema/SET_SCHEMA';
20
+ const SET_SHOW_PREVIEW = 'schema/SET_SHOW_PREVIEW';
21
+ const ENABLE_AUTOREFRESH = 'schema/ENABLE_AUTOREFRESH';
22
+ const DISABLE_AUTOREFRESH = 'schema/DISABLE_AUTOREFRESH';
23
+ const RESET_LOADING_STATE = 'schema/RESET_LOADING_STATE';
24
+
25
+ export const initialState = {
26
+ loading: true,
27
+ wasLoaded: false,
28
+ data: {},
29
+ currentSchemaPath: undefined,
30
+ autorefresh: false,
31
+ showPreview: false,
32
+ };
33
+
34
+ const schema: Reducer<ISchemaState, ISchemaAction> = (state = initialState, action) => {
35
+ switch (action.type) {
36
+ case FETCH_SCHEMA.REQUEST: {
37
+ return {
38
+ ...state,
39
+ loading: true,
40
+ };
41
+ }
42
+ case FETCH_SCHEMA.SUCCESS: {
43
+ const isCurrentSchema =
44
+ !state.currentSchemaPath || state.currentSchemaPath === action.data.path;
45
+
46
+ const newData = {...state.data, ...action.data.data};
47
+
48
+ if (!isCurrentSchema) {
49
+ return {
50
+ ...state,
51
+ data: newData,
52
+ };
53
+ }
54
+
55
+ return {
56
+ ...state,
57
+ error: undefined,
58
+ data: newData,
59
+ currentSchema: action.data.currentSchema,
60
+ currentSchemaPath: action.data.path,
61
+ loading: false,
62
+ wasLoaded: true,
63
+ };
64
+ }
65
+ case FETCH_SCHEMA.FAILURE: {
66
+ if (action.error?.isCancelled) {
67
+ return state;
68
+ }
69
+
70
+ return {
71
+ ...state,
72
+ error: action.error,
73
+ loading: false,
74
+ };
75
+ }
76
+ case PRELOAD_SCHEMAS: {
77
+ return {
78
+ ...state,
79
+ data: {
80
+ // we don't want to overwrite existing paths
81
+ ...action.data,
82
+ ...state.data,
83
+ },
84
+ };
85
+ }
86
+ case SET_SCHEMA: {
87
+ return {
88
+ ...state,
89
+ currentSchemaPath: action.data,
90
+ wasLoaded: false,
91
+ };
92
+ }
93
+ case ENABLE_AUTOREFRESH: {
94
+ return {
95
+ ...state,
96
+ autorefresh: true,
97
+ };
98
+ }
99
+ case DISABLE_AUTOREFRESH: {
100
+ return {
101
+ ...state,
102
+ autorefresh: false,
103
+ };
104
+ }
105
+ case SET_SHOW_PREVIEW: {
106
+ return {
107
+ ...state,
108
+ showPreview: action.data,
109
+ };
110
+ }
111
+ case RESET_LOADING_STATE: {
112
+ return {
113
+ ...state,
114
+ wasLoaded: initialState.wasLoaded,
115
+ };
116
+ }
117
+ default:
118
+ return state;
119
+ }
120
+ };
121
+
122
+ export function getSchema({path}: {path: string}) {
123
+ const request = window.api.getSchema({path});
124
+ return createApiRequest({
125
+ request,
126
+ actions: FETCH_SCHEMA,
127
+ dataHandler: (data): ISchemaHandledResponse => {
128
+ const newData: ISchemaData = {};
129
+ if (data.Path) {
130
+ newData[data.Path] = data;
131
+ }
132
+ return {
133
+ path: data.Path,
134
+ currentSchema: data,
135
+ data: newData,
136
+ };
137
+ },
138
+ });
139
+ }
140
+
141
+ export function getSchemaBatched(paths: string[]) {
142
+ const requestArray = paths.map((p) =>
143
+ window.api.getSchema({path: p}, {concurrentId: `getSchemaBatched|${p}`}),
144
+ );
145
+ const request = Promise.all(requestArray);
146
+
147
+ return createApiRequest({
148
+ request,
149
+ actions: FETCH_SCHEMA,
150
+ dataHandler: (data): ISchemaHandledResponse => {
151
+ const newData: ISchemaData = {};
152
+
153
+ data.forEach((dataItem) => {
154
+ if (dataItem.Path) {
155
+ newData[dataItem.Path] = dataItem;
156
+ }
157
+ });
158
+
159
+ return {
160
+ path: data[0].Path,
161
+ currentSchema: data[0],
162
+ data: newData,
163
+ };
164
+ },
165
+ });
166
+ }
167
+
168
+ export function setCurrentSchemaPath(currentSchemaPath: string) {
169
+ return {
170
+ type: SET_SCHEMA,
171
+ data: currentSchemaPath,
172
+ } as const;
173
+ }
174
+ export function enableAutorefresh() {
175
+ return {
176
+ type: ENABLE_AUTOREFRESH,
177
+ } as const;
178
+ }
179
+ export function disableAutorefresh() {
180
+ return {
181
+ type: DISABLE_AUTOREFRESH,
182
+ } as const;
183
+ }
184
+ export function setShowPreview(value: boolean) {
185
+ return {
186
+ type: SET_SHOW_PREVIEW,
187
+ data: value,
188
+ } as const;
189
+ }
190
+
191
+ // only stores data for paths that are not in the store yet
192
+ // existing paths are ignored
193
+ export function preloadSchemas(data: ISchemaData) {
194
+ return {
195
+ type: PRELOAD_SCHEMAS,
196
+ data,
197
+ } as const;
198
+ }
199
+
200
+ export function resetLoadingState() {
201
+ return {
202
+ type: RESET_LOADING_STATE,
203
+ } as const;
204
+ }
205
+
206
+ export const selectSchemaChildren = (state: ISchemaRootStateSlice, path?: string) =>
207
+ path ? state.schema.data[path]?.PathDescription?.Children : undefined;
208
+
209
+ export const selectSchemaData = (state: ISchemaRootStateSlice, path?: string) =>
210
+ path ? state.schema.data[path] : undefined;
211
+
212
+ export const selectSchemaMergedChildrenPaths: Selector<
213
+ ISchemaRootStateSlice,
214
+ string[] | undefined,
215
+ [string | undefined, EPathType | undefined]
216
+ > = createSelector(
217
+ [
218
+ (_, path?: string) => path,
219
+ (_, _path, type: EPathType | undefined) => type,
220
+ selectSchemaChildren,
221
+ ],
222
+ (path, type, children) => {
223
+ return isEntityWithMergedImplementation(type)
224
+ ? children?.map(({Name}) => path + '/' + Name)
225
+ : undefined;
226
+ },
227
+ );
228
+
229
+ export default schema;
@@ -1,10 +1,14 @@
1
- import {createRequestActionTypes, createApiRequest} from '../utils';
2
- import '../../services/api';
3
1
  import _ from 'lodash';
4
2
  import {createSelector} from 'reselect';
5
- import {calcUptime} from '../../utils';
3
+
4
+ import {calcUptime, calcUptimeInSeconds} from '../../utils';
6
5
  import {getUsage} from '../../utils/storage';
6
+ import {NodesUptimeFilterValues} from '../../utils/nodes';
7
7
  import {getPDiskType} from '../../utils/pdisk';
8
+ import {HOUR_IN_SECONDS} from '../../utils/constants';
9
+ import '../../services/api';
10
+
11
+ import {createRequestActionTypes, createApiRequest} from '../utils';
8
12
 
9
13
  export const VisibleEntities = {
10
14
  All: 'All',
@@ -29,6 +33,8 @@ const SET_FILTER = 'storage/SET_FILTER';
29
33
  const SET_USAGE_FILTER = 'storage/SET_USAGE_FILTER';
30
34
  const SET_VISIBLE_GROUPS = 'storage/SET_VISIBLE_GROUPS';
31
35
  const SET_STORAGE_TYPE = 'storage/SET_STORAGE_TYPE';
36
+ const SET_NODES_UPTIME_FILTER = 'storage/SET_NODES_UPTIME_FILTER';
37
+ const SET_DATA_WAS_NOT_LOADED = 'storage/SET_DATA_WAS_NOT_LOADED';
32
38
 
33
39
  const initialState = {
34
40
  loading: true,
@@ -36,6 +42,7 @@ const initialState = {
36
42
  filter: '',
37
43
  usageFilter: [],
38
44
  visible: VisibleEntities.Missing,
45
+ nodesUptimeFilter: NodesUptimeFilterValues.All,
39
46
  type: StorageTypes.groups,
40
47
  };
41
48
 
@@ -93,6 +100,13 @@ const storage = (state = initialState, action) => {
93
100
  error: undefined,
94
101
  };
95
102
  }
103
+
104
+ case SET_NODES_UPTIME_FILTER: {
105
+ return {
106
+ ...state,
107
+ nodesUptimeFilter: action.data,
108
+ };
109
+ }
96
110
  case SET_STORAGE_TYPE: {
97
111
  return {
98
112
  ...state,
@@ -103,6 +117,12 @@ const storage = (state = initialState, action) => {
103
117
  error: undefined,
104
118
  };
105
119
  }
120
+ case SET_DATA_WAS_NOT_LOADED: {
121
+ return {
122
+ ...state,
123
+ wasLoaded: false,
124
+ };
125
+ }
106
126
  default:
107
127
  return state;
108
128
  }
@@ -149,6 +169,19 @@ export function setVisibleEntities(value) {
149
169
  };
150
170
  }
151
171
 
172
+ export function setNodesUptimeFilter(value) {
173
+ return {
174
+ type: SET_NODES_UPTIME_FILTER,
175
+ data: value,
176
+ };
177
+ }
178
+
179
+ export const setDataWasNotLoaded = () => {
180
+ return {
181
+ type: SET_DATA_WAS_NOT_LOADED,
182
+ };
183
+ };
184
+
152
185
  export const getStoragePools = (state) => state.storage.data?.StoragePools;
153
186
  export const getStoragePoolsGroupsCount = (state) => ({
154
187
  total: state.storage.data?.TotalGroups || 0,
@@ -162,6 +195,7 @@ export const getStorageNodesCount = (state) => ({
162
195
  export const getStorageFilter = (state) => state.storage.filter;
163
196
  export const getUsageFilter = (state) => state.storage.usageFilter;
164
197
  export const getVisibleEntities = (state) => state.storage.visible;
198
+ export const getNodesUptimeFilter = (state) => state.storage.nodesUptimeFilter;
165
199
  export const getStorageType = (state) => state.storage.type;
166
200
  export const getNodesObject = (state) =>
167
201
  _.reduce(
@@ -337,12 +371,32 @@ const filterByUsage = (entities, usage) => {
337
371
  });
338
372
  };
339
373
 
374
+ export const filterByUptime = (nodes = [], nodesUptimeFilter) => {
375
+ if (nodesUptimeFilter === NodesUptimeFilterValues.All) {
376
+ return nodes;
377
+ }
378
+ return nodes.filter(({StartTime}) => {
379
+ return !StartTime || calcUptimeInSeconds(StartTime) < HOUR_IN_SECONDS;
380
+ });
381
+ };
382
+
340
383
  export const getFilteredEntities = createSelector(
341
- [getStorageFilter, getUsageFilter, getStorageType, getVisibleEntitiesList],
342
- (textFilter, usageFilter, type, entities) => {
384
+ [
385
+ getStorageFilter,
386
+ getUsageFilter,
387
+ getStorageType,
388
+ getNodesUptimeFilter,
389
+ getVisibleEntitiesList,
390
+ ],
391
+ (textFilter, usageFilter, type, nodesUptimeFilter, entities) => {
343
392
  let result = entities;
344
393
  result = filterByText(result, type, textFilter);
345
394
  result = filterByUsage(result, usageFilter);
395
+
396
+ if (type === StorageTypes.nodes) {
397
+ result = filterByUptime(result, nodesUptimeFilter);
398
+ }
399
+
346
400
  return result;
347
401
  },
348
402
  );
@@ -0,0 +1,10 @@
1
+ // Shows system status
2
+ // Currently is used in response types of viewer/json/nodes and viewer/json/storage
3
+ // Probably will appear in /viewer/json/tenantinfo /viewer/json/cluster /viewer/json/tabletinfo /viewer/json/compute
4
+ export enum EFlag {
5
+ Grey = 'Grey',
6
+ Green = 'Green',
7
+ Yellow = 'Yellow',
8
+ Orange = 'Orange',
9
+ Red = 'Red',
10
+ }