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,20 +1,22 @@
|
|
1
|
+
import type {OrderType} from '@gravity-ui/react-data-table';
|
2
|
+
|
1
3
|
import type {IResponseError} from '../../../types/api/error';
|
2
|
-
import type {
|
4
|
+
import type {TSystemStateInfo} from '../../../types/api/nodes';
|
3
5
|
import type {TPDiskStateInfo} from '../../../types/api/pdisk';
|
4
|
-
import type {
|
5
|
-
|
6
|
-
THiveStorageGroupStats,
|
7
|
-
TStorageInfo,
|
8
|
-
} from '../../../types/api/storage';
|
6
|
+
import type {EVersion, TStorageGroupInfo} from '../../../types/api/storage';
|
7
|
+
import type {TVDiskStateInfo} from '../../../types/api/vdisk';
|
9
8
|
import type {ValueOf} from '../../../types/common';
|
10
|
-
import type {NodesUptimeFilterValues} from '../../../utils/nodes';
|
9
|
+
import type {NodesSortValue, NodesUptimeFilterValues} from '../../../utils/nodes';
|
10
|
+
import type {StorageSortValue} from '../../../utils/storage';
|
11
11
|
import type {ApiRequestAction} from '../../utils';
|
12
12
|
|
13
13
|
import {STORAGE_TYPES, VISIBLE_ENTITIES} from './constants';
|
14
14
|
import {
|
15
15
|
FETCH_STORAGE,
|
16
16
|
setDataWasNotLoaded,
|
17
|
+
setGroupsSortParams,
|
17
18
|
setInitialState,
|
19
|
+
setNodesSortParams,
|
18
20
|
setNodesUptimeFilter,
|
19
21
|
setStorageTextFilter,
|
20
22
|
setStorageType,
|
@@ -28,23 +30,24 @@ export type StorageType = ValueOf<typeof STORAGE_TYPES>;
|
|
28
30
|
export interface PreparedStorageNode extends TSystemStateInfo {
|
29
31
|
NodeId: number;
|
30
32
|
PDisks: TPDiskStateInfo[] | undefined;
|
33
|
+
VDisks: TVDiskStateInfo[] | undefined;
|
31
34
|
|
32
35
|
Missing: number;
|
33
36
|
Uptime: string;
|
34
37
|
}
|
35
38
|
|
36
|
-
export
|
37
|
-
|
38
|
-
export interface PreparedStorageGroup extends RawStorageGroup {
|
39
|
+
export interface PreparedStorageGroup extends TStorageGroupInfo {
|
39
40
|
PoolName: string | undefined;
|
40
41
|
|
42
|
+
Usage: number;
|
41
43
|
Read: number;
|
42
44
|
Write: number;
|
43
45
|
Used: number;
|
44
46
|
Limit: number;
|
45
|
-
|
47
|
+
Degraded: number;
|
48
|
+
Kind: string | undefined;
|
49
|
+
|
46
50
|
UsedSpaceFlag: number;
|
47
|
-
Type: string | null;
|
48
51
|
}
|
49
52
|
|
50
53
|
export interface UsageFilter {
|
@@ -52,10 +55,24 @@ export interface UsageFilter {
|
|
52
55
|
count: number;
|
53
56
|
}
|
54
57
|
|
55
|
-
export interface
|
58
|
+
export interface StorageSortParams {
|
59
|
+
sortOrder?: OrderType;
|
60
|
+
sortValue?: StorageSortValue;
|
61
|
+
}
|
62
|
+
|
63
|
+
export interface StorageSortAndFilterParams extends StorageSortParams {
|
64
|
+
filter?: string; // PoolName or GroupId
|
65
|
+
|
66
|
+
offser?: number;
|
67
|
+
limit?: number;
|
68
|
+
}
|
69
|
+
|
70
|
+
export interface StorageApiRequestParams extends StorageSortAndFilterParams {
|
56
71
|
tenant?: string;
|
57
72
|
nodeId?: string;
|
58
73
|
visibleEntities?: VisibleEntities;
|
74
|
+
|
75
|
+
version?: EVersion;
|
59
76
|
}
|
60
77
|
|
61
78
|
export interface StorageState {
|
@@ -65,15 +82,28 @@ export interface StorageState {
|
|
65
82
|
usageFilter: string[];
|
66
83
|
visible: VisibleEntities;
|
67
84
|
nodesUptimeFilter: NodesUptimeFilterValues;
|
85
|
+
groupsSortValue?: StorageSortValue;
|
86
|
+
groupsSortOrder?: OrderType;
|
87
|
+
nodesSortValue?: NodesSortValue;
|
88
|
+
nodesSortOrder?: OrderType;
|
68
89
|
type: StorageType;
|
69
|
-
nodes?:
|
70
|
-
groups?:
|
90
|
+
nodes?: PreparedStorageNode[];
|
91
|
+
groups?: PreparedStorageGroup[];
|
92
|
+
found?: number;
|
93
|
+
total?: number;
|
71
94
|
error?: IResponseError;
|
72
95
|
}
|
73
96
|
|
97
|
+
export interface PreparedStorageResponse {
|
98
|
+
nodes?: PreparedStorageNode[];
|
99
|
+
groups?: PreparedStorageGroup[];
|
100
|
+
found: number | undefined;
|
101
|
+
total: number | undefined;
|
102
|
+
}
|
103
|
+
|
74
104
|
type GetStorageInfoApiRequestAction = ApiRequestAction<
|
75
105
|
typeof FETCH_STORAGE,
|
76
|
-
|
106
|
+
PreparedStorageResponse,
|
77
107
|
IResponseError
|
78
108
|
>;
|
79
109
|
|
@@ -85,7 +115,9 @@ export type StorageAction =
|
|
85
115
|
| ReturnType<typeof setUsageFilter>
|
86
116
|
| ReturnType<typeof setVisibleEntities>
|
87
117
|
| ReturnType<typeof setNodesUptimeFilter>
|
88
|
-
| ReturnType<typeof setDataWasNotLoaded
|
118
|
+
| ReturnType<typeof setDataWasNotLoaded>
|
119
|
+
| ReturnType<typeof setNodesSortParams>
|
120
|
+
| ReturnType<typeof setGroupsSortParams>;
|
89
121
|
|
90
122
|
export interface StorageStateSlice {
|
91
123
|
storage: StorageState;
|
@@ -0,0 +1,207 @@
|
|
1
|
+
import type {TNodeInfo, TNodesInfo} from '../../../types/api/nodes';
|
2
|
+
import type {
|
3
|
+
TStorageGroupInfo,
|
4
|
+
TStorageGroupInfoV2,
|
5
|
+
TStorageInfo,
|
6
|
+
} from '../../../types/api/storage';
|
7
|
+
import {EVDiskState, type TVDiskStateInfo} from '../../../types/api/vdisk';
|
8
|
+
import {TPDiskState} from '../../../types/api/pdisk';
|
9
|
+
import {EFlag} from '../../../types/api/enums';
|
10
|
+
import {getPDiskType} from '../../../utils/pdisk';
|
11
|
+
import {getUsage} from '../../../utils/storage';
|
12
|
+
import {calcUptime} from '../../../utils';
|
13
|
+
|
14
|
+
import type {PreparedStorageGroup, PreparedStorageNode, PreparedStorageResponse} from './types';
|
15
|
+
|
16
|
+
// ==== Constants ====
|
17
|
+
|
18
|
+
const FLAGS_POINTS = {
|
19
|
+
[EFlag.Green]: 1,
|
20
|
+
[EFlag.Yellow]: 100,
|
21
|
+
[EFlag.Orange]: 10_000,
|
22
|
+
[EFlag.Red]: 1_000_000,
|
23
|
+
};
|
24
|
+
|
25
|
+
// ==== Prepare groups ====
|
26
|
+
|
27
|
+
const prepareVDisk = (vDisk: TVDiskStateInfo, poolName: string | undefined) => {
|
28
|
+
// VDisk doesn't have its own StoragePoolName when located inside StoragePool data
|
29
|
+
return {
|
30
|
+
...vDisk,
|
31
|
+
StoragePoolName: poolName,
|
32
|
+
Donors: vDisk.Donors?.map((donor) => ({
|
33
|
+
...donor,
|
34
|
+
StoragePoolName: poolName,
|
35
|
+
})),
|
36
|
+
};
|
37
|
+
};
|
38
|
+
|
39
|
+
const prepareStorageGroupData = (
|
40
|
+
group: TStorageGroupInfo,
|
41
|
+
poolName?: string,
|
42
|
+
): PreparedStorageGroup => {
|
43
|
+
let missing = 0;
|
44
|
+
let usedSpaceFlag = 0;
|
45
|
+
let usedSpaceBytes = 0;
|
46
|
+
let limitSizeBytes = 0;
|
47
|
+
let readSpeedBytesPerSec = 0;
|
48
|
+
let writeSpeedBytesPerSec = 0;
|
49
|
+
let mediaType = '';
|
50
|
+
|
51
|
+
if (group.VDisks) {
|
52
|
+
for (const vDisk of group.VDisks) {
|
53
|
+
const {
|
54
|
+
Replicated,
|
55
|
+
VDiskState,
|
56
|
+
AvailableSize,
|
57
|
+
AllocatedSize,
|
58
|
+
PDisk,
|
59
|
+
DiskSpace,
|
60
|
+
ReadThroughput,
|
61
|
+
WriteThroughput,
|
62
|
+
} = vDisk;
|
63
|
+
|
64
|
+
if (
|
65
|
+
!Replicated ||
|
66
|
+
PDisk?.State !== TPDiskState.Normal ||
|
67
|
+
VDiskState !== EVDiskState.OK
|
68
|
+
) {
|
69
|
+
missing += 1;
|
70
|
+
}
|
71
|
+
|
72
|
+
if (DiskSpace && DiskSpace !== EFlag.Grey) {
|
73
|
+
usedSpaceFlag += FLAGS_POINTS[DiskSpace];
|
74
|
+
}
|
75
|
+
|
76
|
+
const available = Number(AvailableSize ?? PDisk?.AvailableSize) || 0;
|
77
|
+
const allocated = Number(AllocatedSize) || 0;
|
78
|
+
|
79
|
+
usedSpaceBytes += allocated;
|
80
|
+
limitSizeBytes += available + allocated;
|
81
|
+
|
82
|
+
readSpeedBytesPerSec += Number(ReadThroughput) || 0;
|
83
|
+
writeSpeedBytesPerSec += Number(WriteThroughput) || 0;
|
84
|
+
|
85
|
+
const currentType = getPDiskType(PDisk || {});
|
86
|
+
mediaType =
|
87
|
+
currentType && (currentType === mediaType || mediaType === '')
|
88
|
+
? currentType
|
89
|
+
: 'Mixed';
|
90
|
+
}
|
91
|
+
}
|
92
|
+
|
93
|
+
const vDisks = group.VDisks?.map((vdisk) => prepareVDisk(vdisk, poolName));
|
94
|
+
const usage = getUsage({Used: usedSpaceBytes, Limit: limitSizeBytes}, 5);
|
95
|
+
|
96
|
+
return {
|
97
|
+
...group,
|
98
|
+
VDisks: vDisks,
|
99
|
+
Usage: usage,
|
100
|
+
Read: readSpeedBytesPerSec,
|
101
|
+
Write: writeSpeedBytesPerSec,
|
102
|
+
PoolName: poolName,
|
103
|
+
Used: usedSpaceBytes,
|
104
|
+
Limit: limitSizeBytes,
|
105
|
+
Degraded: missing,
|
106
|
+
UsedSpaceFlag: usedSpaceFlag,
|
107
|
+
Kind: mediaType || undefined,
|
108
|
+
};
|
109
|
+
};
|
110
|
+
|
111
|
+
const prepareStorageGroupDataV2 = (group: TStorageGroupInfoV2): PreparedStorageGroup => {
|
112
|
+
const {
|
113
|
+
VDisks = [],
|
114
|
+
PoolName,
|
115
|
+
Usage = 0,
|
116
|
+
Read = 0,
|
117
|
+
Write = 0,
|
118
|
+
Used = 0,
|
119
|
+
Limit = 0,
|
120
|
+
Degraded = 0,
|
121
|
+
Kind,
|
122
|
+
} = group;
|
123
|
+
|
124
|
+
const UsedSpaceFlag = VDisks.reduce((acc, {DiskSpace}) => {
|
125
|
+
if (DiskSpace && DiskSpace !== EFlag.Grey) {
|
126
|
+
return acc + FLAGS_POINTS[DiskSpace];
|
127
|
+
}
|
128
|
+
return acc;
|
129
|
+
}, 0);
|
130
|
+
|
131
|
+
const vDisks = VDisks.map((vdisk) => prepareVDisk(vdisk, PoolName));
|
132
|
+
const usage = Math.floor(Number(Usage) * 100);
|
133
|
+
|
134
|
+
return {
|
135
|
+
...group,
|
136
|
+
UsedSpaceFlag,
|
137
|
+
PoolName,
|
138
|
+
Kind,
|
139
|
+
VDisks: vDisks,
|
140
|
+
Usage: usage,
|
141
|
+
Read: Number(Read),
|
142
|
+
Write: Number(Write),
|
143
|
+
Used: Number(Used),
|
144
|
+
Limit: Number(Limit),
|
145
|
+
Degraded: Number(Degraded),
|
146
|
+
};
|
147
|
+
};
|
148
|
+
|
149
|
+
// ==== Prepare nodes ====
|
150
|
+
|
151
|
+
const prepareStorageNodeData = (node: TNodeInfo): PreparedStorageNode => {
|
152
|
+
const systemState = node.SystemState ?? {};
|
153
|
+
const missing =
|
154
|
+
node.PDisks?.filter((pDisk) => {
|
155
|
+
return pDisk.State !== TPDiskState.Normal;
|
156
|
+
}).length || 0;
|
157
|
+
|
158
|
+
return {
|
159
|
+
NodeId: node.NodeId,
|
160
|
+
SystemState: systemState.SystemState,
|
161
|
+
DataCenter: systemState.DataCenter,
|
162
|
+
Rack: systemState.Rack,
|
163
|
+
Host: systemState.Host,
|
164
|
+
Endpoints: systemState.Endpoints,
|
165
|
+
Uptime: calcUptime(systemState.StartTime),
|
166
|
+
StartTime: systemState.StartTime,
|
167
|
+
PDisks: node.PDisks,
|
168
|
+
VDisks: node.VDisks,
|
169
|
+
Missing: missing,
|
170
|
+
};
|
171
|
+
};
|
172
|
+
|
173
|
+
// ==== Prepare responses ====
|
174
|
+
|
175
|
+
export const prepareStorageNodesResponse = (data: TNodesInfo): PreparedStorageResponse => {
|
176
|
+
const {Nodes, TotalNodes, FoundNodes} = data;
|
177
|
+
|
178
|
+
const preparedNodes = Nodes?.map(prepareStorageNodeData);
|
179
|
+
|
180
|
+
return {
|
181
|
+
nodes: preparedNodes,
|
182
|
+
total: Number(TotalNodes) || preparedNodes?.length,
|
183
|
+
found: Number(FoundNodes),
|
184
|
+
};
|
185
|
+
};
|
186
|
+
|
187
|
+
export const prepareStorageGroupsResponse = (data: TStorageInfo): PreparedStorageResponse => {
|
188
|
+
const {StoragePools, StorageGroups, TotalGroups, FoundGroups} = data;
|
189
|
+
|
190
|
+
let preparedGroups: PreparedStorageGroup[] = [];
|
191
|
+
|
192
|
+
if (StorageGroups) {
|
193
|
+
preparedGroups = StorageGroups.map(prepareStorageGroupDataV2);
|
194
|
+
} else {
|
195
|
+
StoragePools?.forEach((pool) => {
|
196
|
+
pool.Groups?.forEach((group) => {
|
197
|
+
preparedGroups.push(prepareStorageGroupData(group, pool.Name));
|
198
|
+
});
|
199
|
+
});
|
200
|
+
}
|
201
|
+
|
202
|
+
return {
|
203
|
+
groups: preparedGroups,
|
204
|
+
total: Number(TotalGroups) || preparedGroups.length,
|
205
|
+
found: Number(FoundGroups),
|
206
|
+
};
|
207
|
+
};
|
package/dist/store/utils.ts
CHANGED
@@ -3,7 +3,7 @@ import {AxiosResponse} from 'axios';
|
|
3
3
|
|
4
4
|
import createToast from '../utils/createToast';
|
5
5
|
|
6
|
-
import {SET_UNAUTHENTICATED} from './reducers/authentication';
|
6
|
+
import {SET_UNAUTHENTICATED} from './reducers/authentication/authentication';
|
7
7
|
import type {GetState} from './reducers';
|
8
8
|
|
9
9
|
export const nop = (result: any) => result;
|
@@ -65,15 +65,3 @@ export enum EVersion {
|
|
65
65
|
v1 = 'v1',
|
66
66
|
v2 = 'v2', // only this versions works with sorting
|
67
67
|
}
|
68
|
-
|
69
|
-
export enum ESort {
|
70
|
-
NodeId = 'NodeId',
|
71
|
-
Host = 'Host',
|
72
|
-
DC = 'DC',
|
73
|
-
Rack = 'Rack',
|
74
|
-
Version = 'Version',
|
75
|
-
Uptime = 'Uptime',
|
76
|
-
Memory = 'Memory',
|
77
|
-
CPU = 'CPU',
|
78
|
-
LoadAverage = 'LoadAverage',
|
79
|
-
}
|
package/dist/types/api/error.ts
CHANGED
package/dist/types/api/nodes.ts
CHANGED
@@ -101,15 +101,3 @@ enum EConfigState {
|
|
101
101
|
'Consistent' = 'Consistent',
|
102
102
|
'Outdated' = 'Outdated',
|
103
103
|
}
|
104
|
-
|
105
|
-
export enum ESort {
|
106
|
-
NodeId = 'NodeId',
|
107
|
-
Host = 'Host',
|
108
|
-
DC = 'DC',
|
109
|
-
Rack = 'Rack',
|
110
|
-
Version = 'Version',
|
111
|
-
Uptime = 'Uptime',
|
112
|
-
Memory = 'Memory',
|
113
|
-
CPU = 'CPU',
|
114
|
-
LoadAverage = 'LoadAverage',
|
115
|
-
}
|
@@ -8,7 +8,8 @@ import {TVDiskStateInfo} from './vdisk';
|
|
8
8
|
*/
|
9
9
|
export interface TStorageInfo {
|
10
10
|
Overall?: EFlag;
|
11
|
-
StoragePools?: TStoragePoolInfo[];
|
11
|
+
StoragePools?: TStoragePoolInfo[]; // v1
|
12
|
+
StorageGroups?: TStorageGroupInfoV2[]; // v2
|
12
13
|
/** uint64 */
|
13
14
|
TotalGroups?: string;
|
14
15
|
/** uint64 */
|
@@ -19,7 +20,7 @@ interface TStoragePoolInfo {
|
|
19
20
|
Overall?: EFlag;
|
20
21
|
Name?: string;
|
21
22
|
Kind?: string;
|
22
|
-
Groups?:
|
23
|
+
Groups?: TStorageGroupInfo[];
|
23
24
|
/** uint64 */
|
24
25
|
AcquiredUnits?: string;
|
25
26
|
AcquiredIOPS?: number;
|
@@ -34,7 +35,29 @@ interface TStoragePoolInfo {
|
|
34
35
|
MaximumSize?: string;
|
35
36
|
}
|
36
37
|
|
37
|
-
export interface
|
38
|
+
export interface TStorageGroupInfoV2 extends TStorageGroupInfo {
|
39
|
+
PoolName?: string;
|
40
|
+
Kind?: string;
|
41
|
+
|
42
|
+
/** uint64 */
|
43
|
+
Degraded?: string;
|
44
|
+
|
45
|
+
/** uint64 */
|
46
|
+
Used: string;
|
47
|
+
/** uint64 */
|
48
|
+
Limit: string;
|
49
|
+
/** uint64 */
|
50
|
+
Read: string;
|
51
|
+
/** uint64 */
|
52
|
+
Write: string;
|
53
|
+
|
54
|
+
/** uint64 */
|
55
|
+
Usage?: string;
|
56
|
+
}
|
57
|
+
|
58
|
+
export type TStorageGroupInfo = TBSGroupStateInfo & THiveStorageGroupStats;
|
59
|
+
|
60
|
+
interface TBSGroupStateInfo {
|
38
61
|
GroupID?: number;
|
39
62
|
ErasureSpecies?: string;
|
40
63
|
VDisks?: TVDiskStateInfo[];
|
@@ -57,7 +80,7 @@ export interface TBSGroupStateInfo {
|
|
57
80
|
Encryption?: boolean;
|
58
81
|
}
|
59
82
|
|
60
|
-
|
83
|
+
interface THiveStorageGroupStats {
|
61
84
|
GroupID?: number;
|
62
85
|
/** uint64 */
|
63
86
|
AcquiredUnits?: string;
|
@@ -76,3 +99,8 @@ export interface THiveStorageGroupStats {
|
|
76
99
|
/** uint64 */
|
77
100
|
AvailableSize?: string;
|
78
101
|
}
|
102
|
+
|
103
|
+
export enum EVersion {
|
104
|
+
v1 = 'v1',
|
105
|
+
v2 = 'v2', // only this versions works with sorting
|
106
|
+
}
|
package/dist/types/window.d.ts
CHANGED
@@ -37,6 +37,7 @@ interface Window {
|
|
37
37
|
custom_backend?: string;
|
38
38
|
|
39
39
|
__REDUX_DEVTOOLS_EXTENSION_COMPOSE__?: typeof import('redux').compose;
|
40
|
+
store?: import('redux').Store;
|
40
41
|
|
41
42
|
userSettings?: Record<string, string | undefined>;
|
42
43
|
systemSettings?: Record<string, string | undefined>;
|
package/dist/utils/constants.ts
CHANGED
@@ -119,3 +119,6 @@ export const CLUSTER_INFO_HIDDEN_KEY = 'clusterInfoHidden';
|
|
119
119
|
|
120
120
|
// Remain "tab" in key name for backward compatibility
|
121
121
|
export const TENANT_INITIAL_PAGE_KEY = 'saved_tenant_initial_tab';
|
122
|
+
|
123
|
+
// Send filters and sort params to backend for Nodes and Storage tables
|
124
|
+
export const USE_BACKEND_PARAMS_FOR_TABLES_KEY = 'useBackendParamsForTables';
|
@@ -0,0 +1,23 @@
|
|
1
|
+
import {escapeRegExp} from 'lodash';
|
2
|
+
|
3
|
+
import type {OrderType} from '@gravity-ui/react-data-table';
|
4
|
+
import {DESCENDING} from '@gravity-ui/react-data-table/build/esm/lib/constants';
|
5
|
+
|
6
|
+
export const prepareSortValue = (
|
7
|
+
sortValue: string | undefined,
|
8
|
+
sortOrder: OrderType = DESCENDING,
|
9
|
+
) => {
|
10
|
+
if (!sortValue) {
|
11
|
+
return '';
|
12
|
+
}
|
13
|
+
|
14
|
+
if (sortOrder === DESCENDING) {
|
15
|
+
return '-' + sortValue;
|
16
|
+
}
|
17
|
+
|
18
|
+
return sortValue;
|
19
|
+
};
|
20
|
+
|
21
|
+
export const prepareSearchValue = (searchValue = '') => {
|
22
|
+
return new RegExp(escapeRegExp(searchValue), 'i');
|
23
|
+
};
|
@@ -0,0 +1,46 @@
|
|
1
|
+
import {useMemo} from 'react';
|
2
|
+
|
3
|
+
import type {NodesGeneralRequestParams} from '../../store/reducers/nodes/types';
|
4
|
+
import type {ProblemFilterValue} from '../../store/reducers/settings/types';
|
5
|
+
import {ProblemFilterValues} from '../../store/reducers/settings/settings';
|
6
|
+
|
7
|
+
import {HOUR_IN_SECONDS, USE_BACKEND_PARAMS_FOR_TABLES_KEY} from '../constants';
|
8
|
+
import {NodesUptimeFilterValues} from '../nodes';
|
9
|
+
import {useSetting} from './useSetting';
|
10
|
+
|
11
|
+
interface NodesRawRequestParams
|
12
|
+
extends Omit<NodesGeneralRequestParams, 'problems_only' | 'uptime'> {
|
13
|
+
problemFilter?: ProblemFilterValue;
|
14
|
+
nodesUptimeFilter?: NodesUptimeFilterValues;
|
15
|
+
}
|
16
|
+
|
17
|
+
export const useNodesRequestParams = ({
|
18
|
+
filter,
|
19
|
+
problemFilter,
|
20
|
+
nodesUptimeFilter,
|
21
|
+
sortOrder,
|
22
|
+
sortValue,
|
23
|
+
}: NodesRawRequestParams) => {
|
24
|
+
const [useBackendParamsForTables] = useSetting<boolean>(USE_BACKEND_PARAMS_FOR_TABLES_KEY);
|
25
|
+
|
26
|
+
// If backend params are enabled, update params value to use them in fetch request
|
27
|
+
// Otherwise no params will be updated, no hooks that depend on requestParams will be triggered
|
28
|
+
return useMemo(() => {
|
29
|
+
if (useBackendParamsForTables) {
|
30
|
+
const problemsOnly = problemFilter === ProblemFilterValues.PROBLEMS;
|
31
|
+
const uptime =
|
32
|
+
nodesUptimeFilter === NodesUptimeFilterValues.SmallUptime
|
33
|
+
? HOUR_IN_SECONDS
|
34
|
+
: undefined;
|
35
|
+
|
36
|
+
return {
|
37
|
+
filter,
|
38
|
+
problems_only: problemsOnly,
|
39
|
+
uptime,
|
40
|
+
sortOrder,
|
41
|
+
sortValue,
|
42
|
+
};
|
43
|
+
}
|
44
|
+
return undefined;
|
45
|
+
}, [useBackendParamsForTables, filter, problemFilter, nodesUptimeFilter, sortOrder, sortValue]);
|
46
|
+
};
|
@@ -0,0 +1,28 @@
|
|
1
|
+
import {useMemo} from 'react';
|
2
|
+
|
3
|
+
import type {StorageSortAndFilterParams} from '../../store/reducers/storage/types';
|
4
|
+
import {EVersion} from '../../types/api/storage';
|
5
|
+
import {USE_BACKEND_PARAMS_FOR_TABLES_KEY} from '../constants';
|
6
|
+
import {useSetting} from './useSetting';
|
7
|
+
|
8
|
+
export const useStorageRequestParams = ({
|
9
|
+
filter,
|
10
|
+
sortOrder,
|
11
|
+
sortValue,
|
12
|
+
}: StorageSortAndFilterParams) => {
|
13
|
+
const [useBackendParamsForTables] = useSetting<boolean>(USE_BACKEND_PARAMS_FOR_TABLES_KEY);
|
14
|
+
|
15
|
+
// If backend params are enabled, update params value to use them in fetch request
|
16
|
+
// Otherwise no params will be updated, no hooks that depend on requestParams will be triggered
|
17
|
+
return useMemo(() => {
|
18
|
+
if (useBackendParamsForTables) {
|
19
|
+
return {
|
20
|
+
version: EVersion.v2,
|
21
|
+
filter,
|
22
|
+
sortOrder,
|
23
|
+
sortValue,
|
24
|
+
};
|
25
|
+
}
|
26
|
+
return undefined;
|
27
|
+
}, [useBackendParamsForTables, filter, sortOrder, sortValue]);
|
28
|
+
};
|
@@ -0,0 +1,37 @@
|
|
1
|
+
import {useMemo} from 'react';
|
2
|
+
|
3
|
+
import {OrderType, SortOrder} from '@gravity-ui/react-data-table';
|
4
|
+
import {DESCENDING} from '@gravity-ui/react-data-table/build/esm/lib/constants';
|
5
|
+
|
6
|
+
interface SortParams {
|
7
|
+
sortValue: string | undefined;
|
8
|
+
sortOrder: OrderType | undefined;
|
9
|
+
}
|
10
|
+
|
11
|
+
export type HandleSort = (rawValue: SortOrder | SortOrder[] | undefined) => void;
|
12
|
+
|
13
|
+
export const useTableSort = (
|
14
|
+
{sortValue, sortOrder = DESCENDING}: SortParams,
|
15
|
+
onSort: (params: SortParams) => void,
|
16
|
+
): [SortOrder | undefined, HandleSort] => {
|
17
|
+
const sort: SortOrder | undefined = useMemo(() => {
|
18
|
+
if (!sortValue) {
|
19
|
+
return undefined;
|
20
|
+
}
|
21
|
+
|
22
|
+
return {
|
23
|
+
columnId: sortValue,
|
24
|
+
order: sortOrder,
|
25
|
+
};
|
26
|
+
}, [sortValue, sortOrder]);
|
27
|
+
|
28
|
+
const handleSort: HandleSort = (rawValue) => {
|
29
|
+
const value = Array.isArray(rawValue) ? rawValue[0] : rawValue;
|
30
|
+
onSort({
|
31
|
+
sortValue: value?.columnId,
|
32
|
+
sortOrder: value?.order,
|
33
|
+
});
|
34
|
+
};
|
35
|
+
|
36
|
+
return [sort, handleSort];
|
37
|
+
};
|
package/dist/utils/nodes.ts
CHANGED
@@ -2,6 +2,7 @@ import type {TSystemStateInfo} from '../types/api/nodes';
|
|
2
2
|
import type {TNodeInfo} from '../types/api/nodesList';
|
3
3
|
import type {NodesPreparedEntity} from '../store/reducers/nodes/types';
|
4
4
|
import type {NodesMap} from '../types/store/nodesList';
|
5
|
+
import type {ValueOf} from '../types/common';
|
5
6
|
import {EFlag} from '../types/api/enums';
|
6
7
|
|
7
8
|
export enum NodesUptimeFilterValues {
|
@@ -31,3 +32,27 @@ export const prepareNodesMap = (nodesList?: TNodeInfo[]) => {
|
|
31
32
|
return nodesMap;
|
32
33
|
}, new Map());
|
33
34
|
};
|
35
|
+
|
36
|
+
/**
|
37
|
+
* Values to sort /compute v2 and /nodes responses
|
38
|
+
*
|
39
|
+
* For actual values go to:\
|
40
|
+
* /nodes: https://github.com/ydb-platform/ydb/blob/main/ydb/core/viewer/json_nodes.h\
|
41
|
+
* /compute: https://github.com/ydb-platform/ydb/blob/main/ydb/core/viewer/json_compute.h
|
42
|
+
*/
|
43
|
+
export const NODES_SORT_VALUES = {
|
44
|
+
NodeId: 'NodeId',
|
45
|
+
Host: 'Host',
|
46
|
+
DC: 'DC',
|
47
|
+
Rack: 'Rack',
|
48
|
+
Version: 'Version',
|
49
|
+
Uptime: 'Uptime',
|
50
|
+
Memory: 'Memory',
|
51
|
+
CPU: 'CPU',
|
52
|
+
LoadAverage: 'LoadAverage',
|
53
|
+
} as const;
|
54
|
+
|
55
|
+
export type NodesSortValue = ValueOf<typeof NODES_SORT_VALUES>;
|
56
|
+
|
57
|
+
export const isSortableNodesProperty = (value: string): value is NodesSortValue =>
|
58
|
+
Object.values(NODES_SORT_VALUES).includes(value as NodesSortValue);
|