ydb-embedded-ui 4.13.0 → 4.15.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/components/Tablet/Tablet.scss +1 -16
  3. package/dist/components/Tablet/Tablet.tsx +5 -5
  4. package/dist/components/TabletIcon/TabletIcon.scss +17 -0
  5. package/dist/components/TabletIcon/TabletIcon.tsx +18 -0
  6. package/dist/containers/App/App.js +1 -1
  7. package/dist/containers/AsideNavigation/AsideNavigation.tsx +1 -1
  8. package/dist/containers/Authentication/Authentication.tsx +1 -1
  9. package/dist/containers/Header/Header.scss +2 -0
  10. package/dist/containers/Header/Header.tsx +2 -7
  11. package/dist/containers/Header/{breadcrumbs.ts → breadcrumbs.tsx} +19 -8
  12. package/dist/containers/Nodes/Nodes.tsx +53 -16
  13. package/dist/containers/Nodes/getNodesColumns.tsx +31 -13
  14. package/dist/containers/Storage/Storage.tsx +64 -32
  15. package/dist/containers/Storage/StorageGroups/StorageGroups.tsx +56 -73
  16. package/dist/containers/Storage/StorageNodes/StorageNodes.tsx +33 -43
  17. package/dist/containers/Storage/utils/index.ts +3 -3
  18. package/dist/containers/Tablet/Tablet.tsx +9 -3
  19. package/dist/containers/Tenant/Query/QueryDuration/QueryDuration.scss +8 -0
  20. package/dist/containers/Tenant/Query/QueryDuration/QueryDuration.tsx +13 -1
  21. package/dist/containers/Tenant/Query/QueryEditorControls/QueryEditorControls.scss +3 -1
  22. package/dist/containers/Tenant/Query/i18n/en.json +6 -4
  23. package/dist/containers/Tenant/Query/i18n/ru.json +6 -4
  24. package/dist/containers/Tenant/Schema/SchemaTree/SchemaTree.tsx +4 -0
  25. package/dist/containers/Tenant/i18n/en.json +3 -0
  26. package/dist/containers/Tenant/i18n/ru.json +3 -0
  27. package/dist/containers/Tenant/utils/queryTemplates.ts +89 -0
  28. package/dist/containers/Tenant/utils/schema.ts +1 -1
  29. package/dist/containers/Tenant/utils/schemaActions.ts +30 -54
  30. package/dist/containers/Tenant/utils/schemaControls.tsx +69 -0
  31. package/dist/containers/UserSettings/i18n/en.json +3 -0
  32. package/dist/containers/UserSettings/i18n/ru.json +3 -0
  33. package/dist/containers/UserSettings/settings.ts +12 -1
  34. package/dist/{reportWebVitals.js → reportWebVitals.ts} +3 -1
  35. package/dist/services/api.ts +30 -16
  36. package/dist/store/reducers/{authentication.js → authentication/authentication.ts} +14 -7
  37. package/dist/store/reducers/authentication/types.ts +15 -0
  38. package/dist/store/reducers/describe.ts +1 -16
  39. package/dist/store/reducers/header/types.ts +2 -0
  40. package/dist/store/reducers/index.ts +1 -1
  41. package/dist/store/reducers/nodes/nodes.ts +23 -6
  42. package/dist/store/reducers/nodes/selectors.ts +2 -2
  43. package/dist/store/reducers/nodes/types.ts +15 -5
  44. package/dist/store/reducers/settings/settings.ts +5 -0
  45. package/dist/store/reducers/storage/selectors.ts +50 -150
  46. package/dist/store/reducers/storage/storage.ts +73 -25
  47. package/dist/store/reducers/storage/types.ts +49 -17
  48. package/dist/store/reducers/storage/utils.ts +207 -0
  49. package/dist/store/utils.ts +1 -1
  50. package/dist/types/api/compute.ts +0 -12
  51. package/dist/types/api/error.ts +4 -0
  52. package/dist/types/api/nodes.ts +0 -12
  53. package/dist/types/api/storage.ts +32 -4
  54. package/dist/types/window.d.ts +1 -0
  55. package/dist/utils/constants.ts +3 -0
  56. package/dist/utils/filters.ts +23 -0
  57. package/dist/utils/hooks/index.ts +4 -0
  58. package/dist/utils/hooks/useNodesRequestParams.ts +46 -0
  59. package/dist/utils/hooks/useStorageRequestParams.ts +28 -0
  60. package/dist/utils/hooks/useTableSort.ts +37 -0
  61. package/dist/utils/nodes.ts +25 -0
  62. package/dist/utils/storage.ts +31 -3
  63. package/package.json +2 -6
  64. package/dist/HOCS/WithSearch/WithSearch.js +0 -26
  65. package/dist/HOCS/index.js +0 -1
  66. package/dist/components/Hotkey/Hotkey.js +0 -102
  67. package/dist/components/Pagination/Pagination.js +0 -63
  68. package/dist/components/Pagination/Pagination.scss +0 -28
  69. package/dist/types/store/storage.ts +0 -12
  70. /package/dist/{index.js → index.tsx} +0 -0
  71. /package/dist/utils/{monaco.js → monaco.ts} +0 -0
@@ -1,4 +1,5 @@
1
1
  import type {ClusterTab} from '../../../containers/Cluster/utils';
2
+ import type {EType} from '../../../types/api/tablet';
2
3
 
3
4
  import {setHeaderBreadcrumbs} from './header';
4
5
 
@@ -23,6 +24,7 @@ export interface TabletsBreadcrumbsOptions extends TenantBreadcrumbsOptions {
23
24
 
24
25
  export interface TabletBreadcrumbsOptions extends TabletsBreadcrumbsOptions {
25
26
  tabletId?: string;
27
+ tabletType?: EType;
26
28
  }
27
29
 
28
30
  export type BreadcrumbsOptions =
@@ -30,7 +30,7 @@ import healthcheckInfo from './healthcheckInfo';
30
30
  import shardsWorkload from './shardsWorkload';
31
31
  import hotKeys from './hotKeys';
32
32
  import olapStats from './olapStats';
33
- import authentication from './authentication';
33
+ import authentication from './authentication/authentication';
34
34
  import header from './header/header';
35
35
  import saveQuery from './saveQuery';
36
36
  import fullscreen from './fullscreen';
@@ -10,6 +10,7 @@ import type {
10
10
  ComputeApiRequestParams,
11
11
  NodesAction,
12
12
  NodesApiRequestParams,
13
+ NodesSortParams,
13
14
  NodesState,
14
15
  } from './types';
15
16
  import {prepareComputeNodesData, prepareNodesData} from './utils';
@@ -20,6 +21,7 @@ const RESET_NODES_STATE = 'nodes/RESET_NODES_STATE';
20
21
  const SET_NODES_UPTIME_FILTER = 'nodes/SET_NODES_UPTIME_FILTER';
21
22
  const SET_DATA_WAS_NOT_LOADED = 'nodes/SET_DATA_WAS_NOT_LOADED';
22
23
  const SET_SEARCH_VALUE = 'nodes/SET_SEARCH_VALUE';
24
+ const SET_SORT = 'nodes/SET_SORT';
23
25
 
24
26
  const initialState = {
25
27
  loading: false,
@@ -47,6 +49,10 @@ const nodes: Reducer<NodesState, NodesAction> = (state = initialState, action) =
47
49
  };
48
50
  }
49
51
  case FETCH_NODES.FAILURE: {
52
+ if (action.error?.isCancelled) {
53
+ return state;
54
+ }
55
+
50
56
  return {
51
57
  ...state,
52
58
  error: action.error,
@@ -74,7 +80,13 @@ const nodes: Reducer<NodesState, NodesAction> = (state = initialState, action) =
74
80
  searchValue: action.data,
75
81
  };
76
82
  }
77
-
83
+ case SET_SORT: {
84
+ return {
85
+ ...state,
86
+ sortValue: action.data.sortValue,
87
+ sortOrder: action.data.sortOrder,
88
+ };
89
+ }
78
90
  case SET_DATA_WAS_NOT_LOADED: {
79
91
  return {
80
92
  ...state,
@@ -85,13 +97,11 @@ const nodes: Reducer<NodesState, NodesAction> = (state = initialState, action) =
85
97
  return state;
86
98
  }
87
99
  };
100
+ const concurrentId = 'getNodes';
88
101
 
89
102
  export function getNodes({type = 'any', ...params}: NodesApiRequestParams) {
90
103
  return createApiRequest({
91
- request: window.api.getNodes({
92
- type,
93
- ...params,
94
- }),
104
+ request: window.api.getNodes({type, ...params}, {concurrentId}),
95
105
  actions: FETCH_NODES,
96
106
  dataHandler: prepareNodesData,
97
107
  });
@@ -99,7 +109,7 @@ export function getNodes({type = 'any', ...params}: NodesApiRequestParams) {
99
109
 
100
110
  export function getComputeNodes({version = EVersion.v2, ...params}: ComputeApiRequestParams) {
101
111
  return createApiRequest({
102
- request: window.api.getCompute({version, ...params}),
112
+ request: window.api.getCompute({version, ...params}, {concurrentId}),
103
113
  actions: FETCH_NODES,
104
114
  dataHandler: prepareComputeNodesData,
105
115
  });
@@ -130,4 +140,11 @@ export const setSearchValue = (value: string) => {
130
140
  } as const;
131
141
  };
132
142
 
143
+ export const setSort = (sortParams: NodesSortParams) => {
144
+ return {
145
+ type: SET_SORT,
146
+ data: sortParams,
147
+ } as const;
148
+ };
149
+
133
150
  export default nodes;
@@ -1,10 +1,10 @@
1
1
  import {Selector, createSelector} from 'reselect';
2
- import {escapeRegExp} from 'lodash';
3
2
 
4
3
  import {EFlag} from '../../../types/api/enums';
5
4
  import {calcUptimeInSeconds} from '../../../utils';
6
5
  import {HOUR_IN_SECONDS} from '../../../utils/constants';
7
6
  import {NodesUptimeFilterValues} from '../../../utils/nodes';
7
+ import {prepareSearchValue} from '../../../utils/filters';
8
8
 
9
9
  import type {ProblemFilterValue} from '../settings/types';
10
10
  import type {NodesPreparedEntity, NodesStateSlice} from './types';
@@ -41,7 +41,7 @@ const filterNodesBySearchValue = (nodesList: NodesPreparedEntity[] = [], searchV
41
41
  if (!searchValue) {
42
42
  return nodesList;
43
43
  }
44
- const re = new RegExp(escapeRegExp(searchValue), 'i');
44
+ const re = prepareSearchValue(searchValue);
45
45
 
46
46
  return nodesList.filter((node) => {
47
47
  return node.Host ? re.test(node.Host) || re.test(String(node.NodeId)) : true;
@@ -1,3 +1,5 @@
1
+ import type {OrderType} from '@gravity-ui/react-data-table';
2
+
1
3
  import type {IResponseError} from '../../../types/api/error';
2
4
  import type {TEndpoint, TPoolStats} from '../../../types/api/nodes';
3
5
  import type {
@@ -9,13 +11,14 @@ import type {EFlag} from '../../../types/api/enums';
9
11
  import type {ApiRequestAction} from '../../utils';
10
12
  import type {VisibleEntities} from '../storage/types';
11
13
 
12
- import {NodesUptimeFilterValues} from '../../../utils/nodes';
14
+ import type {NodesSortValue, NodesUptimeFilterValues} from '../../../utils/nodes';
13
15
  import {
14
16
  FETCH_NODES,
15
17
  resetNodesState,
16
18
  setDataWasNotLoaded,
17
19
  setNodesUptimeFilter,
18
20
  setSearchValue,
21
+ setSort,
19
22
  } from './nodes';
20
23
 
21
24
  // Since nodes from different endpoints can have different types,
@@ -42,6 +45,8 @@ export interface NodesState {
42
45
  wasLoaded: boolean;
43
46
  nodesUptimeFilter: NodesUptimeFilterValues;
44
47
  searchValue: string;
48
+ sortValue?: NodesSortValue;
49
+ sortOrder?: OrderType;
45
50
  data?: NodesPreparedEntity[];
46
51
  totalNodes?: number;
47
52
  error?: IResponseError;
@@ -49,17 +54,21 @@ export interface NodesState {
49
54
 
50
55
  export type NodeType = 'static' | 'dynamic' | 'any';
51
56
 
52
- interface RequestParams {
57
+ export interface NodesSortParams {
58
+ sortOrder?: OrderType;
59
+ sortValue?: NodesSortValue;
60
+ }
61
+
62
+ export interface NodesGeneralRequestParams extends NodesSortParams {
53
63
  filter?: string; // NodeId or Host
54
64
  uptime?: number; // return nodes with less uptime in seconds
55
65
  problems_only?: boolean; // return nodes with SystemState !== EFlag.Green
56
- sort?: string; // Sort by one of ESort params (may differ for /nodes and /compute)
57
66
 
58
67
  offser?: number;
59
68
  limit?: number;
60
69
  }
61
70
 
62
- export interface NodesApiRequestParams extends RequestParams {
71
+ export interface NodesApiRequestParams extends NodesGeneralRequestParams {
63
72
  tenant?: string;
64
73
  type?: NodeType;
65
74
  visibleEntities?: VisibleEntities; // "with" param
@@ -67,7 +76,7 @@ export interface NodesApiRequestParams extends RequestParams {
67
76
  tablets?: boolean;
68
77
  }
69
78
 
70
- export interface ComputeApiRequestParams extends RequestParams {
79
+ export interface ComputeApiRequestParams extends NodesGeneralRequestParams {
71
80
  path: string;
72
81
  version?: EVersion; // only v2 works with filters
73
82
  }
@@ -90,6 +99,7 @@ export type NodesAction =
90
99
  | ReturnType<typeof setDataWasNotLoaded>
91
100
  | ReturnType<typeof setNodesUptimeFilter>
92
101
  | ReturnType<typeof setSearchValue>
102
+ | ReturnType<typeof setSort>
93
103
  | ReturnType<typeof resetNodesState>
94
104
  );
95
105
 
@@ -13,6 +13,7 @@ import {
13
13
  ENABLE_ADDITIONAL_QUERY_MODES,
14
14
  CLUSTER_INFO_HIDDEN_KEY,
15
15
  LAST_USED_QUERY_ACTION_KEY,
16
+ USE_BACKEND_PARAMS_FOR_TABLES_KEY,
16
17
  } from '../../../utils/constants';
17
18
  import '../../../services/api';
18
19
  import {getValueFromLS, parseJson} from '../../../utils/utils';
@@ -76,6 +77,10 @@ export const initialState = {
76
77
  [ASIDE_HEADER_COMPACT_KEY]: readSavedSettingsValue(ASIDE_HEADER_COMPACT_KEY, 'true'),
77
78
  [PARTITIONS_HIDDEN_COLUMNS_KEY]: readSavedSettingsValue(PARTITIONS_HIDDEN_COLUMNS_KEY),
78
79
  [CLUSTER_INFO_HIDDEN_KEY]: readSavedSettingsValue(CLUSTER_INFO_HIDDEN_KEY, 'true'),
80
+ [USE_BACKEND_PARAMS_FOR_TABLES_KEY]: readSavedSettingsValue(
81
+ USE_BACKEND_PARAMS_FOR_TABLES_KEY,
82
+ 'false',
83
+ ),
79
84
  },
80
85
  systemSettings,
81
86
  };
@@ -1,128 +1,20 @@
1
1
  import {Selector, createSelector} from 'reselect';
2
- import {getUsage} from '../../../utils/storage';
3
2
 
4
- import type {TNodeInfo} from '../../../types/api/nodes';
5
- import {TPDiskState} from '../../../types/api/pdisk';
6
- import {EVDiskState, TVDiskStateInfo} from '../../../types/api/vdisk';
7
- import {EFlag} from '../../../types/api/enums';
8
- import {getPDiskType} from '../../../utils/pdisk';
9
- import {calcUptime} from '../../../utils';
3
+ import type {OrderType} from '@gravity-ui/react-data-table';
4
+ import {ASCENDING, DESCENDING} from '@gravity-ui/react-data-table/build/esm/lib/constants';
10
5
 
6
+ import type {TVDiskStateInfo} from '../../../types/api/vdisk';
7
+ import {NODES_SORT_VALUES, type NodesSortValue} from '../../../utils/nodes';
8
+ import {STORAGE_SORT_VALUES, type StorageSortValue, getUsage} from '../../../utils/storage';
9
+
10
+ import {filterNodesByUptime} from '../nodes/selectors';
11
11
  import type {
12
12
  PreparedStorageGroup,
13
13
  PreparedStorageNode,
14
- RawStorageGroup,
15
14
  StorageStateSlice,
16
15
  UsageFilter,
17
16
  } from './types';
18
- import {filterNodesByUptime} from '../nodes/selectors';
19
-
20
- // ==== Prepare data ====
21
- const FLAGS_POINTS = {
22
- [EFlag.Green]: 1,
23
- [EFlag.Yellow]: 100,
24
- [EFlag.Orange]: 10_000,
25
- [EFlag.Red]: 1_000_000,
26
- };
27
-
28
- const prepareStorageGroupData = (
29
- group: RawStorageGroup,
30
- poolName?: string,
31
- ): PreparedStorageGroup => {
32
- let missing = 0;
33
- let usedSpaceFlag = 0;
34
- let usedSpaceBytes = 0;
35
- let limitSizeBytes = 0;
36
- let readSpeedBytesPerSec = 0;
37
- let writeSpeedBytesPerSec = 0;
38
- let mediaType = '';
39
-
40
- if (group.VDisks) {
41
- for (const vDisk of group.VDisks) {
42
- const {
43
- Replicated,
44
- VDiskState,
45
- AvailableSize,
46
- AllocatedSize,
47
- PDisk,
48
- DiskSpace,
49
- ReadThroughput,
50
- WriteThroughput,
51
- } = vDisk;
52
-
53
- if (
54
- !Replicated ||
55
- PDisk?.State !== TPDiskState.Normal ||
56
- VDiskState !== EVDiskState.OK
57
- ) {
58
- missing += 1;
59
- }
60
-
61
- if (DiskSpace && DiskSpace !== EFlag.Grey) {
62
- usedSpaceFlag += FLAGS_POINTS[DiskSpace];
63
- }
64
-
65
- const available = Number(AvailableSize ?? PDisk?.AvailableSize) || 0;
66
- const allocated = Number(AllocatedSize) || 0;
67
-
68
- usedSpaceBytes += allocated;
69
- limitSizeBytes += available + allocated;
70
-
71
- readSpeedBytesPerSec += Number(ReadThroughput) || 0;
72
- writeSpeedBytesPerSec += Number(WriteThroughput) || 0;
73
-
74
- const currentType = getPDiskType(PDisk || {});
75
- mediaType =
76
- currentType && (currentType === mediaType || mediaType === '')
77
- ? currentType
78
- : 'Mixed';
79
- }
80
- }
81
-
82
- // VDisk doesn't have its own StoragePoolName when located inside StoragePool data
83
- const vDisks = group.VDisks?.map((vdisk) => ({
84
- ...vdisk,
85
- StoragePoolName: poolName,
86
- Donors: vdisk.Donors?.map((donor) => ({
87
- ...donor,
88
- StoragePoolName: poolName,
89
- })),
90
- }));
91
-
92
- return {
93
- ...group,
94
- VDisks: vDisks,
95
- Read: readSpeedBytesPerSec,
96
- Write: writeSpeedBytesPerSec,
97
- PoolName: poolName,
98
- Used: usedSpaceBytes,
99
- Limit: limitSizeBytes,
100
- Missing: missing,
101
- UsedSpaceFlag: usedSpaceFlag,
102
- Type: mediaType || null,
103
- };
104
- };
105
-
106
- const prepareStorageNodeData = (node: TNodeInfo): PreparedStorageNode => {
107
- const systemState = node.SystemState ?? {};
108
- const missing =
109
- node.PDisks?.filter((pDisk) => {
110
- return pDisk.State !== TPDiskState.Normal;
111
- }).length || 0;
112
-
113
- return {
114
- NodeId: node.NodeId,
115
- SystemState: systemState.SystemState,
116
- DataCenter: systemState.DataCenter,
117
- Rack: systemState.Rack,
118
- Host: systemState.Host,
119
- Endpoints: systemState.Endpoints,
120
- Uptime: calcUptime(systemState.StartTime),
121
- StartTime: systemState.StartTime,
122
- PDisks: node.PDisks,
123
- Missing: missing,
124
- };
125
- };
17
+ import {VISIBLE_ENTITIES} from './constants';
126
18
 
127
19
  // ==== Filters ====
128
20
 
@@ -163,24 +55,21 @@ const filterGroupsByUsage = (entities: PreparedStorageGroup[], usage?: string[])
163
55
  }
164
56
 
165
57
  return entities.filter((entity) => {
166
- const entityUsage = getUsage(entity, 5);
58
+ const entityUsage = entity.Usage;
167
59
  return usage.some((val) => Number(val) <= entityUsage && entityUsage < Number(val) + 5);
168
60
  });
169
61
  };
170
62
 
171
63
  // ==== Simple selectors ====
172
64
 
173
- export const selectStoragePools = (state: StorageStateSlice) => state.storage.groups?.StoragePools;
174
- export const selectStorageGroupsCount = (state: StorageStateSlice) => ({
175
- total: state.storage.groups?.TotalGroups || 0,
176
- found: state.storage.groups?.FoundGroups || 0,
177
- });
178
- export const selectStorageNodes = (state: StorageStateSlice) => state.storage.nodes?.Nodes;
179
- export const selectStorageNodesCount = (state: StorageStateSlice) => ({
180
- total: state.storage.nodes?.TotalNodes || 0,
181
- found: state.storage.nodes?.FoundNodes || 0,
65
+ export const selectEntitiesCount = (state: StorageStateSlice) => ({
66
+ total: state.storage.total,
67
+ found: state.storage.found,
182
68
  });
183
69
 
70
+ export const selectStorageGroups = (state: StorageStateSlice) => state.storage.groups;
71
+ export const selectStorageNodes = (state: StorageStateSlice) => state.storage.nodes;
72
+
184
73
  export const selectStorageFilter = (state: StorageStateSlice) => state.storage.filter;
185
74
  export const selectUsageFilter = (state: StorageStateSlice) => state.storage.usageFilter;
186
75
  export const selectVisibleEntities = (state: StorageStateSlice) => state.storage.visible;
@@ -188,29 +77,39 @@ export const selectNodesUptimeFilter = (state: StorageStateSlice) =>
188
77
  state.storage.nodesUptimeFilter;
189
78
  export const selectStorageType = (state: StorageStateSlice) => state.storage.type;
190
79
 
191
- // ==== Complex selectors ====
80
+ // ==== Sort params selectors ====
81
+ export const selectNodesSortParams = (state: StorageStateSlice) => {
82
+ const defaultSortValue: NodesSortValue = NODES_SORT_VALUES.NodeId;
83
+ const defaultSortOrder: OrderType = ASCENDING;
84
+
85
+ return {
86
+ sortValue: state.storage.nodesSortValue || defaultSortValue,
87
+ sortOrder: state.storage.nodesSortOrder || defaultSortOrder,
88
+ };
89
+ };
192
90
 
193
- const selectPreparedStorageNodes: Selector<StorageStateSlice, PreparedStorageNode[]> =
194
- createSelector(selectStorageNodes, (storageNodes) => {
195
- if (!storageNodes) {
196
- return [];
197
- }
91
+ export const selectGroupsSortParams = (state: StorageStateSlice) => {
92
+ const visibleEntities = state.storage.visible;
198
93
 
199
- return storageNodes.map(prepareStorageNodeData);
200
- });
94
+ let defaultSortValue: StorageSortValue = STORAGE_SORT_VALUES.PoolName;
95
+ let defaultSortOrder: OrderType = ASCENDING;
201
96
 
202
- export const selectPreparedStorageGroups: Selector<StorageStateSlice, PreparedStorageGroup[]> =
203
- createSelector(selectStoragePools, (storagePools) => {
204
- const preparedGroups: PreparedStorageGroup[] = [];
97
+ if (visibleEntities === VISIBLE_ENTITIES.missing) {
98
+ defaultSortValue = STORAGE_SORT_VALUES.Degraded;
99
+ defaultSortOrder = DESCENDING;
100
+ }
205
101
 
206
- storagePools?.forEach((pool) => {
207
- pool.Groups?.forEach((group) => {
208
- preparedGroups.push(prepareStorageGroupData(group, pool.Name));
209
- });
210
- });
102
+ if (visibleEntities === VISIBLE_ENTITIES.space) {
103
+ defaultSortValue = STORAGE_SORT_VALUES.Usage;
104
+ defaultSortOrder = DESCENDING;
105
+ }
211
106
 
212
- return preparedGroups;
213
- });
107
+ return {
108
+ sortValue: state.storage.groupsSortValue || defaultSortValue,
109
+ sortOrder: state.storage.groupsSortOrder || defaultSortOrder,
110
+ };
111
+ };
112
+ // ==== Complex selectors ====
214
113
 
215
114
  export const selectVDisksForPDisk: Selector<
216
115
  StorageStateSlice,
@@ -232,11 +131,12 @@ export const selectVDisksForPDisk: Selector<
232
131
  );
233
132
 
234
133
  export const selectUsageFilterOptions: Selector<StorageStateSlice, UsageFilter[]> = createSelector(
235
- selectPreparedStorageGroups,
134
+ selectStorageGroups,
236
135
  (groups) => {
237
136
  const items: Record<number, number> = {};
238
137
 
239
- groups.forEach((group) => {
138
+ groups?.forEach((group) => {
139
+ // Get groups usage with step 5
240
140
  const usage = getUsage(group, 5);
241
141
 
242
142
  if (!Object.prototype.hasOwnProperty.call(items, usage)) {
@@ -256,9 +156,9 @@ export const selectUsageFilterOptions: Selector<StorageStateSlice, UsageFilter[]
256
156
 
257
157
  export const selectFilteredNodes: Selector<StorageStateSlice, PreparedStorageNode[]> =
258
158
  createSelector(
259
- [selectPreparedStorageNodes, selectStorageFilter, selectNodesUptimeFilter],
159
+ [selectStorageNodes, selectStorageFilter, selectNodesUptimeFilter],
260
160
  (storageNodes, textFilter, uptimeFilter) => {
261
- let result = storageNodes;
161
+ let result = storageNodes || [];
262
162
  result = filterNodesByText(result, textFilter);
263
163
  result = filterNodesByUptime(result, uptimeFilter);
264
164
 
@@ -268,9 +168,9 @@ export const selectFilteredNodes: Selector<StorageStateSlice, PreparedStorageNod
268
168
 
269
169
  export const selectFilteredGroups: Selector<StorageStateSlice, PreparedStorageGroup[]> =
270
170
  createSelector(
271
- [selectPreparedStorageGroups, selectStorageFilter, selectUsageFilter],
171
+ [selectStorageGroups, selectStorageFilter, selectUsageFilter],
272
172
  (storageGroups, textFilter, usageFilter) => {
273
- let result = storageGroups;
173
+ let result = storageGroups || [];
274
174
  result = filterGroupsByText(result, textFilter);
275
175
  result = filterGroupsByUsage(result, usageFilter);
276
176
 
@@ -1,13 +1,23 @@
1
1
  import type {Reducer} from 'redux';
2
2
  import _ from 'lodash';
3
3
 
4
+ import {EVersion} from '../../../types/api/storage';
4
5
  import {NodesUptimeFilterValues} from '../../../utils/nodes';
5
6
  import '../../../services/api';
6
7
 
7
8
  import {createRequestActionTypes, createApiRequest} from '../../utils';
8
9
 
9
- import type {StorageAction, StorageState, StorageType, VisibleEntities} from './types';
10
+ import type {NodesApiRequestParams, NodesSortParams} from '../nodes/types';
11
+ import type {
12
+ StorageAction,
13
+ StorageApiRequestParams,
14
+ StorageSortParams,
15
+ StorageState,
16
+ StorageType,
17
+ VisibleEntities,
18
+ } from './types';
10
19
  import {VISIBLE_ENTITIES, STORAGE_TYPES} from './constants';
20
+ import {prepareStorageGroupsResponse, prepareStorageNodesResponse} from './utils';
11
21
 
12
22
  export const FETCH_STORAGE = createRequestActionTypes('storage', 'FETCH_STORAGE');
13
23
 
@@ -18,6 +28,8 @@ const SET_VISIBLE_GROUPS = 'storage/SET_VISIBLE_GROUPS';
18
28
  const SET_STORAGE_TYPE = 'storage/SET_STORAGE_TYPE';
19
29
  const SET_NODES_UPTIME_FILTER = 'storage/SET_NODES_UPTIME_FILTER';
20
30
  const SET_DATA_WAS_NOT_LOADED = 'storage/SET_DATA_WAS_NOT_LOADED';
31
+ const SET_NODES_SORT_PARAMS = 'storage/SET_NODES_SORT_PARAMS';
32
+ const SET_GROUPS_SORT_PARAMS = 'storage/SET_GROUPS_SORT_PARAMS';
21
33
 
22
34
  const initialState = {
23
35
  loading: true,
@@ -42,6 +54,8 @@ const storage: Reducer<StorageState, StorageAction> = (state = initialState, act
42
54
  ...state,
43
55
  nodes: action.data.nodes,
44
56
  groups: action.data.groups,
57
+ total: action.data.total,
58
+ found: action.data.found,
45
59
  loading: false,
46
60
  wasLoaded: true,
47
61
  error: undefined,
@@ -80,6 +94,7 @@ const storage: Reducer<StorageState, StorageAction> = (state = initialState, act
80
94
  return {
81
95
  ...state,
82
96
  visible: action.data,
97
+ usageFilter: [],
83
98
  wasLoaded: false,
84
99
  error: undefined,
85
100
  };
@@ -107,39 +122,58 @@ const storage: Reducer<StorageState, StorageAction> = (state = initialState, act
107
122
  wasLoaded: false,
108
123
  };
109
124
  }
125
+ case SET_NODES_SORT_PARAMS: {
126
+ return {
127
+ ...state,
128
+ nodesSortValue: action.data.sortValue,
129
+ nodesSortOrder: action.data.sortOrder,
130
+ };
131
+ }
132
+ case SET_GROUPS_SORT_PARAMS: {
133
+ return {
134
+ ...state,
135
+ groupsSortValue: action.data.sortValue,
136
+ groupsSortOrder: action.data.sortOrder,
137
+ };
138
+ }
110
139
  default:
111
140
  return state;
112
141
  }
113
142
  };
114
143
 
115
- export function getStorageInfo(
116
- {
117
- tenant,
118
- visibleEntities,
119
- nodeId,
120
- type,
121
- }: {
122
- tenant?: string;
123
- visibleEntities?: VisibleEntities;
124
- nodeId?: string;
125
- type?: StorageType;
126
- },
127
- {concurrentId}: {concurrentId?: string} = {},
128
- ) {
129
- if (type === STORAGE_TYPES.nodes) {
130
- return createApiRequest({
131
- request: window.api.getNodes({tenant, visibleEntities, type: 'static'}, {concurrentId}),
132
- actions: FETCH_STORAGE,
133
- dataHandler: (data) => ({nodes: data}),
134
- });
135
- }
144
+ const concurrentId = 'getStorageInfo';
136
145
 
146
+ export const getStorageNodesInfo = ({
147
+ tenant,
148
+ visibleEntities,
149
+ ...params
150
+ }: Omit<NodesApiRequestParams, 'type'>) => {
137
151
  return createApiRequest({
138
- request: window.api.getStorageInfo({tenant, visibleEntities, nodeId}, {concurrentId}),
152
+ request: window.api.getNodes(
153
+ {tenant, visibleEntities, type: 'static', ...params},
154
+ {concurrentId},
155
+ ),
139
156
  actions: FETCH_STORAGE,
140
- dataHandler: (data) => ({groups: data}),
157
+ dataHandler: prepareStorageNodesResponse,
141
158
  });
142
- }
159
+ };
160
+
161
+ export const getStorageGroupsInfo = ({
162
+ tenant,
163
+ visibleEntities,
164
+ nodeId,
165
+ version = EVersion.v1,
166
+ ...params
167
+ }: StorageApiRequestParams) => {
168
+ return createApiRequest({
169
+ request: window.api.getStorageInfo(
170
+ {tenant, visibleEntities, nodeId, version, ...params},
171
+ {concurrentId},
172
+ ),
173
+ actions: FETCH_STORAGE,
174
+ dataHandler: prepareStorageGroupsResponse,
175
+ });
176
+ };
143
177
 
144
178
  export function setInitialState() {
145
179
  return {
@@ -188,4 +222,18 @@ export const setDataWasNotLoaded = () => {
188
222
  } as const;
189
223
  };
190
224
 
225
+ export const setNodesSortParams = (sortParams: NodesSortParams) => {
226
+ return {
227
+ type: SET_NODES_SORT_PARAMS,
228
+ data: sortParams,
229
+ } as const;
230
+ };
231
+
232
+ export const setGroupsSortParams = (sortParams: StorageSortParams) => {
233
+ return {
234
+ type: SET_GROUPS_SORT_PARAMS,
235
+ data: sortParams,
236
+ } as const;
237
+ };
238
+
191
239
  export default storage;