ydb-embedded-ui 2.4.4 → 2.6.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 (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
+ }