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.
- package/CHANGELOG.md +25 -0
- package/dist/components/Tablet/Tablet.scss +1 -16
- package/dist/components/Tablet/Tablet.tsx +5 -5
- package/dist/components/TabletIcon/TabletIcon.scss +17 -0
- package/dist/components/TabletIcon/TabletIcon.tsx +18 -0
- package/dist/containers/App/App.js +1 -1
- package/dist/containers/AsideNavigation/AsideNavigation.tsx +1 -1
- package/dist/containers/Authentication/Authentication.tsx +1 -1
- package/dist/containers/Header/Header.scss +2 -0
- package/dist/containers/Header/Header.tsx +2 -7
- package/dist/containers/Header/{breadcrumbs.ts → breadcrumbs.tsx} +19 -8
- package/dist/containers/Nodes/Nodes.tsx +53 -16
- package/dist/containers/Nodes/getNodesColumns.tsx +31 -13
- package/dist/containers/Storage/Storage.tsx +64 -32
- package/dist/containers/Storage/StorageGroups/StorageGroups.tsx +56 -73
- package/dist/containers/Storage/StorageNodes/StorageNodes.tsx +33 -43
- package/dist/containers/Storage/utils/index.ts +3 -3
- package/dist/containers/Tablet/Tablet.tsx +9 -3
- package/dist/containers/Tenant/Query/QueryDuration/QueryDuration.scss +8 -0
- package/dist/containers/Tenant/Query/QueryDuration/QueryDuration.tsx +13 -1
- package/dist/containers/Tenant/Query/QueryEditorControls/QueryEditorControls.scss +3 -1
- package/dist/containers/Tenant/Query/i18n/en.json +6 -4
- package/dist/containers/Tenant/Query/i18n/ru.json +6 -4
- package/dist/containers/Tenant/Schema/SchemaTree/SchemaTree.tsx +4 -0
- package/dist/containers/Tenant/i18n/en.json +3 -0
- package/dist/containers/Tenant/i18n/ru.json +3 -0
- package/dist/containers/Tenant/utils/queryTemplates.ts +89 -0
- package/dist/containers/Tenant/utils/schema.ts +1 -1
- package/dist/containers/Tenant/utils/schemaActions.ts +30 -54
- package/dist/containers/Tenant/utils/schemaControls.tsx +69 -0
- package/dist/containers/UserSettings/i18n/en.json +3 -0
- package/dist/containers/UserSettings/i18n/ru.json +3 -0
- package/dist/containers/UserSettings/settings.ts +12 -1
- package/dist/{reportWebVitals.js → reportWebVitals.ts} +3 -1
- package/dist/services/api.ts +30 -16
- package/dist/store/reducers/{authentication.js → authentication/authentication.ts} +14 -7
- package/dist/store/reducers/authentication/types.ts +15 -0
- package/dist/store/reducers/describe.ts +1 -16
- package/dist/store/reducers/header/types.ts +2 -0
- package/dist/store/reducers/index.ts +1 -1
- package/dist/store/reducers/nodes/nodes.ts +23 -6
- package/dist/store/reducers/nodes/selectors.ts +2 -2
- package/dist/store/reducers/nodes/types.ts +15 -5
- package/dist/store/reducers/settings/settings.ts +5 -0
- package/dist/store/reducers/storage/selectors.ts +50 -150
- package/dist/store/reducers/storage/storage.ts +73 -25
- package/dist/store/reducers/storage/types.ts +49 -17
- package/dist/store/reducers/storage/utils.ts +207 -0
- package/dist/store/utils.ts +1 -1
- package/dist/types/api/compute.ts +0 -12
- package/dist/types/api/error.ts +4 -0
- package/dist/types/api/nodes.ts +0 -12
- package/dist/types/api/storage.ts +32 -4
- package/dist/types/window.d.ts +1 -0
- package/dist/utils/constants.ts +3 -0
- package/dist/utils/filters.ts +23 -0
- package/dist/utils/hooks/index.ts +4 -0
- package/dist/utils/hooks/useNodesRequestParams.ts +46 -0
- package/dist/utils/hooks/useStorageRequestParams.ts +28 -0
- package/dist/utils/hooks/useTableSort.ts +37 -0
- package/dist/utils/nodes.ts +25 -0
- package/dist/utils/storage.ts +31 -3
- package/package.json +2 -6
- package/dist/HOCS/WithSearch/WithSearch.js +0 -26
- package/dist/HOCS/index.js +0 -1
- package/dist/components/Hotkey/Hotkey.js +0 -102
- package/dist/components/Pagination/Pagination.js +0 -63
- package/dist/components/Pagination/Pagination.scss +0 -28
- package/dist/types/store/storage.ts +0 -12
- /package/dist/{index.js → index.tsx} +0 -0
- /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 =
|
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
|
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
|
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
|
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 {
|
5
|
-
import {
|
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 {
|
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 =
|
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
|
174
|
-
|
175
|
-
|
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
|
-
// ====
|
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
|
194
|
-
|
195
|
-
if (!storageNodes) {
|
196
|
-
return [];
|
197
|
-
}
|
91
|
+
export const selectGroupsSortParams = (state: StorageStateSlice) => {
|
92
|
+
const visibleEntities = state.storage.visible;
|
198
93
|
|
199
|
-
|
200
|
-
|
94
|
+
let defaultSortValue: StorageSortValue = STORAGE_SORT_VALUES.PoolName;
|
95
|
+
let defaultSortOrder: OrderType = ASCENDING;
|
201
96
|
|
202
|
-
|
203
|
-
|
204
|
-
|
97
|
+
if (visibleEntities === VISIBLE_ENTITIES.missing) {
|
98
|
+
defaultSortValue = STORAGE_SORT_VALUES.Degraded;
|
99
|
+
defaultSortOrder = DESCENDING;
|
100
|
+
}
|
205
101
|
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
});
|
102
|
+
if (visibleEntities === VISIBLE_ENTITIES.space) {
|
103
|
+
defaultSortValue = STORAGE_SORT_VALUES.Usage;
|
104
|
+
defaultSortOrder = DESCENDING;
|
105
|
+
}
|
211
106
|
|
212
|
-
|
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
|
-
|
134
|
+
selectStorageGroups,
|
236
135
|
(groups) => {
|
237
136
|
const items: Record<number, number> = {};
|
238
137
|
|
239
|
-
groups
|
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
|
-
[
|
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
|
-
[
|
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 {
|
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
|
-
|
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.
|
152
|
+
request: window.api.getNodes(
|
153
|
+
{tenant, visibleEntities, type: 'static', ...params},
|
154
|
+
{concurrentId},
|
155
|
+
),
|
139
156
|
actions: FETCH_STORAGE,
|
140
|
-
dataHandler:
|
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;
|