ydb-embedded-ui 4.14.0 → 4.15.0
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +9 -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/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/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 +27 -44
- package/dist/containers/UserSettings/i18n/en.json +1 -1
- package/dist/containers/UserSettings/i18n/ru.json +1 -1
- package/dist/{reportWebVitals.js → reportWebVitals.ts} +3 -1
- package/dist/services/api.ts +6 -4
- 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/index.ts +1 -1
- 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/error.ts +4 -0
- package/dist/types/api/storage.ts +32 -4
- package/dist/types/window.d.ts +1 -0
- package/dist/utils/hooks/index.ts +1 -0
- package/dist/utils/hooks/useStorageRequestParams.ts +28 -0
- package/dist/utils/hooks/useTableSort.ts +1 -1
- package/dist/utils/storage.ts +31 -3
- package/package.json +1 -5
- 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
package/CHANGELOG.md
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [4.15.0](https://github.com/ydb-platform/ydb-embedded-ui/compare/v4.14.0...v4.15.0) (2023-08-17)
|
4
|
+
|
5
|
+
|
6
|
+
### Features
|
7
|
+
|
8
|
+
* **SchemaTree:** add actions for topic ([#507](https://github.com/ydb-platform/ydb-embedded-ui/issues/507)) ([6700136](https://github.com/ydb-platform/ydb-embedded-ui/commit/670013629cb68425e670969323a2ef466ef7c018))
|
9
|
+
* **Storage:** sort on backend ([#510](https://github.com/ydb-platform/ydb-embedded-ui/issues/510)) ([034a89a](https://github.com/ydb-platform/ydb-embedded-ui/commit/034a89a9844021c5ea3a73c8f6456e35128078c0))
|
10
|
+
* **Storage:** v2 api and backend filters ([#506](https://github.com/ydb-platform/ydb-embedded-ui/issues/506)) ([ce4bf6d](https://github.com/ydb-platform/ydb-embedded-ui/commit/ce4bf6d0ef154b87a7b3a44d56281230b2b5b554))
|
11
|
+
|
3
12
|
## [4.14.0](https://github.com/ydb-platform/ydb-embedded-ui/compare/v4.13.0...v4.14.0) (2023-08-11)
|
4
13
|
|
5
14
|
|
@@ -5,7 +5,7 @@ import PropTypes from 'prop-types';
|
|
5
5
|
import ContentWrapper, {Content} from './Content';
|
6
6
|
import AsideNavigation from '../AsideNavigation/AsideNavigation';
|
7
7
|
|
8
|
-
import {getUser} from '../../store/reducers/authentication';
|
8
|
+
import {getUser} from '../../store/reducers/authentication/authentication';
|
9
9
|
import {registerLanguages} from '../../utils/monaco';
|
10
10
|
|
11
11
|
import './App.scss';
|
@@ -18,7 +18,7 @@ import userChecked from '../../assets/icons/user-check.svg';
|
|
18
18
|
import settingsIcon from '../../assets/icons/settings.svg';
|
19
19
|
import supportIcon from '../../assets/icons/support.svg';
|
20
20
|
|
21
|
-
import {logout} from '../../store/reducers/authentication';
|
21
|
+
import {logout} from '../../store/reducers/authentication/authentication';
|
22
22
|
import {getParsedSettingValue, setSettingValue} from '../../store/reducers/settings/settings';
|
23
23
|
import {TENANT_PAGE, TENANT_PAGES_IDS} from '../../store/reducers/tenant/constants';
|
24
24
|
import routes, {TENANT, createHref, parseQuery} from '../../routes';
|
@@ -5,7 +5,7 @@ import cn from 'bem-cn-lite';
|
|
5
5
|
|
6
6
|
import {Button, TextInput, Icon, Link as ExternalLink} from '@gravity-ui/uikit';
|
7
7
|
|
8
|
-
import {authenticate} from '../../store/reducers/authentication';
|
8
|
+
import {authenticate} from '../../store/reducers/authentication/authentication';
|
9
9
|
import {useTypedSelector} from '../../utils/hooks';
|
10
10
|
|
11
11
|
import ydbLogoIcon from '../../assets/icons/ydb.svg';
|
@@ -2,8 +2,6 @@ import {useCallback, useEffect} from 'react';
|
|
2
2
|
import {useDispatch} from 'react-redux';
|
3
3
|
import cn from 'bem-cn-lite';
|
4
4
|
|
5
|
-
import DataTable, {Settings} from '@gravity-ui/react-data-table';
|
6
|
-
|
7
5
|
import {Search} from '../../components/Search';
|
8
6
|
import {UptimeFilter} from '../../components/UptimeFIlter';
|
9
7
|
import {AccessDenied} from '../../components/Errors/403';
|
@@ -11,9 +9,13 @@ import {EntitiesCount} from '../../components/EntitiesCount';
|
|
11
9
|
import {TableWithControlsLayout} from '../../components/TableWithControlsLayout/TableWithControlsLayout';
|
12
10
|
import {ResponseError} from '../../components/Errors/ResponseError';
|
13
11
|
|
14
|
-
import type {
|
12
|
+
import type {
|
13
|
+
StorageSortParams,
|
14
|
+
StorageType,
|
15
|
+
VisibleEntities,
|
16
|
+
} from '../../store/reducers/storage/types';
|
17
|
+
import type {NodesSortParams} from '../../store/reducers/nodes/types';
|
15
18
|
import {
|
16
|
-
getStorageInfo,
|
17
19
|
setInitialState,
|
18
20
|
setVisibleEntities,
|
19
21
|
setStorageTextFilter,
|
@@ -21,17 +23,28 @@ import {
|
|
21
23
|
setStorageType,
|
22
24
|
setNodesUptimeFilter,
|
23
25
|
setDataWasNotLoaded,
|
26
|
+
getStorageNodesInfo,
|
27
|
+
getStorageGroupsInfo,
|
28
|
+
setNodesSortParams,
|
29
|
+
setGroupsSortParams,
|
24
30
|
} from '../../store/reducers/storage/storage';
|
25
31
|
import {
|
26
32
|
selectFilteredGroups,
|
27
33
|
selectFilteredNodes,
|
28
|
-
|
29
|
-
selectStorageGroupsCount,
|
34
|
+
selectEntitiesCount,
|
30
35
|
selectUsageFilterOptions,
|
36
|
+
selectNodesSortParams,
|
37
|
+
selectGroupsSortParams,
|
31
38
|
} from '../../store/reducers/storage/selectors';
|
32
39
|
import {VISIBLE_ENTITIES, STORAGE_TYPES} from '../../store/reducers/storage/constants';
|
33
40
|
import {getNodesList, selectNodesMap} from '../../store/reducers/nodesList';
|
34
|
-
import {
|
41
|
+
import {
|
42
|
+
useAutofetcher,
|
43
|
+
useNodesRequestParams,
|
44
|
+
useStorageRequestParams,
|
45
|
+
useTableSort,
|
46
|
+
useTypedSelector,
|
47
|
+
} from '../../utils/hooks';
|
35
48
|
import {AdditionalNodesInfo, NodesUptimeFilterValues} from '../../utils/nodes';
|
36
49
|
import {DEFAULT_TABLE_SETTINGS} from '../../utils/constants';
|
37
50
|
|
@@ -45,11 +58,6 @@ import './Storage.scss';
|
|
45
58
|
|
46
59
|
const b = cn('global-storage');
|
47
60
|
|
48
|
-
const tableSettings: Settings = {
|
49
|
-
...DEFAULT_TABLE_SETTINGS,
|
50
|
-
defaultOrder: DataTable.DESCENDING,
|
51
|
-
};
|
52
|
-
|
53
61
|
interface StorageProps {
|
54
62
|
additionalNodesInfo?: AdditionalNodesInfo;
|
55
63
|
tenant?: string;
|
@@ -72,10 +80,11 @@ export const Storage = ({additionalNodesInfo, tenant, nodeId}: StorageProps) =>
|
|
72
80
|
} = useTypedSelector((state) => state.storage);
|
73
81
|
const storageNodes = useTypedSelector(selectFilteredNodes);
|
74
82
|
const storageGroups = useTypedSelector(selectFilteredGroups);
|
75
|
-
const
|
76
|
-
const groupsCount = useTypedSelector(selectStorageGroupsCount);
|
83
|
+
const entitiesCount = useTypedSelector(selectEntitiesCount);
|
77
84
|
const nodesMap = useTypedSelector(selectNodesMap);
|
78
85
|
const usageFilterOptions = useTypedSelector(selectUsageFilterOptions);
|
86
|
+
const nodesSortParams = useTypedSelector(selectNodesSortParams);
|
87
|
+
const groupsSortParams = useTypedSelector(selectGroupsSortParams);
|
79
88
|
|
80
89
|
useEffect(() => {
|
81
90
|
dispatch(getNodesList());
|
@@ -86,27 +95,47 @@ export const Storage = ({additionalNodesInfo, tenant, nodeId}: StorageProps) =>
|
|
86
95
|
};
|
87
96
|
}, [dispatch]);
|
88
97
|
|
98
|
+
const nodesRequestParams = useNodesRequestParams({
|
99
|
+
filter,
|
100
|
+
nodesUptimeFilter,
|
101
|
+
...nodesSortParams,
|
102
|
+
});
|
103
|
+
const storageRequestParams = useStorageRequestParams({
|
104
|
+
filter,
|
105
|
+
...groupsSortParams,
|
106
|
+
});
|
107
|
+
|
108
|
+
const [nodesSort, handleNodesSort] = useTableSort(nodesSortParams, (params) =>
|
109
|
+
dispatch(setNodesSortParams(params as NodesSortParams)),
|
110
|
+
);
|
111
|
+
const [groupsSort, handleGroupsSort] = useTableSort(groupsSortParams, (params) =>
|
112
|
+
dispatch(setGroupsSortParams(params as StorageSortParams)),
|
113
|
+
);
|
114
|
+
|
89
115
|
const fetchData = useCallback(
|
90
116
|
(isBackground: boolean) => {
|
91
117
|
if (!isBackground) {
|
92
118
|
dispatch(setDataWasNotLoaded());
|
93
119
|
}
|
94
120
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
{
|
104
|
-
concurrentId: 'getStorageInfo',
|
105
|
-
},
|
106
|
-
),
|
107
|
-
);
|
121
|
+
const nodesParams = nodesRequestParams || {};
|
122
|
+
const storageParams = storageRequestParams || {};
|
123
|
+
|
124
|
+
if (storageType === STORAGE_TYPES.nodes) {
|
125
|
+
dispatch(getStorageNodesInfo({tenant, visibleEntities, ...nodesParams}));
|
126
|
+
} else {
|
127
|
+
dispatch(getStorageGroupsInfo({tenant, visibleEntities, nodeId, ...storageParams}));
|
128
|
+
}
|
108
129
|
},
|
109
|
-
[
|
130
|
+
[
|
131
|
+
dispatch,
|
132
|
+
tenant,
|
133
|
+
nodeId,
|
134
|
+
visibleEntities,
|
135
|
+
storageType,
|
136
|
+
storageRequestParams,
|
137
|
+
nodesRequestParams,
|
138
|
+
],
|
110
139
|
);
|
111
140
|
|
112
141
|
const autorefreshEnabled = tenant ? autorefresh : true;
|
@@ -145,9 +174,11 @@ export const Storage = ({additionalNodesInfo, tenant, nodeId}: StorageProps) =>
|
|
145
174
|
<StorageGroups
|
146
175
|
visibleEntities={visibleEntities}
|
147
176
|
data={storageGroups}
|
148
|
-
tableSettings={
|
177
|
+
tableSettings={DEFAULT_TABLE_SETTINGS}
|
149
178
|
nodes={nodesMap}
|
150
179
|
onShowAll={() => handleGroupVisibilityChange(VISIBLE_ENTITIES.all)}
|
180
|
+
sort={groupsSort}
|
181
|
+
handleSort={handleGroupsSort}
|
151
182
|
/>
|
152
183
|
)}
|
153
184
|
{storageType === STORAGE_TYPES.nodes && (
|
@@ -155,9 +186,11 @@ export const Storage = ({additionalNodesInfo, tenant, nodeId}: StorageProps) =>
|
|
155
186
|
visibleEntities={visibleEntities}
|
156
187
|
nodesUptimeFilter={nodesUptimeFilter}
|
157
188
|
data={storageNodes}
|
158
|
-
tableSettings={
|
189
|
+
tableSettings={DEFAULT_TABLE_SETTINGS}
|
159
190
|
onShowAll={handleShowAllNodes}
|
160
191
|
additionalNodesInfo={additionalNodesInfo}
|
192
|
+
sort={nodesSort}
|
193
|
+
handleSort={handleNodesSort}
|
161
194
|
/>
|
162
195
|
)}
|
163
196
|
</>
|
@@ -166,7 +199,6 @@ export const Storage = ({additionalNodesInfo, tenant, nodeId}: StorageProps) =>
|
|
166
199
|
|
167
200
|
const renderEntitiesCount = () => {
|
168
201
|
const entityName = storageType === STORAGE_TYPES.groups ? 'Groups' : 'Nodes';
|
169
|
-
const count = storageType === STORAGE_TYPES.groups ? groupsCount : nodesCount;
|
170
202
|
const current =
|
171
203
|
storageType === STORAGE_TYPES.groups ? storageGroups.length : storageNodes.length;
|
172
204
|
|
@@ -174,7 +206,7 @@ export const Storage = ({additionalNodesInfo, tenant, nodeId}: StorageProps) =>
|
|
174
206
|
<EntitiesCount
|
175
207
|
label={entityName}
|
176
208
|
loading={loading && !wasLoaded}
|
177
|
-
total={
|
209
|
+
total={entitiesCount.total}
|
178
210
|
current={current}
|
179
211
|
/>
|
180
212
|
);
|
@@ -3,13 +3,15 @@ import cn from 'bem-cn-lite';
|
|
3
3
|
import DataTable, {Column, Settings, SortOrder} from '@gravity-ui/react-data-table';
|
4
4
|
import {Icon, Label, Popover, PopoverBehavior} from '@gravity-ui/uikit';
|
5
5
|
|
6
|
+
import type {ValueOf} from '../../../types/common';
|
6
7
|
import type {NodesMap} from '../../../types/store/nodesList';
|
7
8
|
import type {PreparedStorageGroup, VisibleEntities} from '../../../store/reducers/storage/types';
|
9
|
+
import type {HandleSort} from '../../../utils/hooks/useTableSort';
|
8
10
|
|
9
11
|
import {VISIBLE_ENTITIES} from '../../../store/reducers/storage/constants';
|
10
12
|
import {bytesToGB, bytesToSpeed} from '../../../utils/utils';
|
11
13
|
import {stringifyVdiskId} from '../../../utils';
|
12
|
-
import {getUsage, isFullVDiskData} from '../../../utils/storage';
|
14
|
+
import {getUsage, isFullVDiskData, isSortableStorageProperty} from '../../../utils/storage';
|
13
15
|
|
14
16
|
import shieldIcon from '../../../assets/icons/shield.svg';
|
15
17
|
import {Stack} from '../../../components/Stack/Stack';
|
@@ -22,23 +24,22 @@ import {getDegradedSeverity, getUsageSeverityForStorageGroup} from '../utils';
|
|
22
24
|
import i18n from './i18n';
|
23
25
|
import './StorageGroups.scss';
|
24
26
|
|
25
|
-
|
26
|
-
PoolName
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
Used
|
31
|
-
Limit
|
32
|
-
|
33
|
-
UsedSpaceFlag
|
34
|
-
Read
|
35
|
-
Write
|
36
|
-
VDisks
|
37
|
-
|
38
|
-
}
|
27
|
+
const TableColumnsIds = {
|
28
|
+
PoolName: 'PoolName',
|
29
|
+
Kind: 'Kind',
|
30
|
+
Erasure: 'Erasure',
|
31
|
+
GroupId: 'GroupId',
|
32
|
+
Used: 'Used',
|
33
|
+
Limit: 'Limit',
|
34
|
+
Usage: 'Usage',
|
35
|
+
UsedSpaceFlag: 'UsedSpaceFlag',
|
36
|
+
Read: 'Read',
|
37
|
+
Write: 'Write',
|
38
|
+
VDisks: 'VDisks',
|
39
|
+
Degraded: 'Degraded',
|
40
|
+
} as const;
|
39
41
|
|
40
|
-
type
|
41
|
-
type TableColumnsIdsValues = typeof TableColumnsIds[TableColumnsIdsKeys];
|
42
|
+
type TableColumnId = ValueOf<typeof TableColumnsIds>;
|
42
43
|
|
43
44
|
interface StorageGroupsProps {
|
44
45
|
data: PreparedStorageGroup[];
|
@@ -46,59 +47,37 @@ interface StorageGroupsProps {
|
|
46
47
|
tableSettings: Settings;
|
47
48
|
visibleEntities: VisibleEntities;
|
48
49
|
onShowAll?: VoidFunction;
|
50
|
+
sort?: SortOrder;
|
51
|
+
handleSort?: HandleSort;
|
49
52
|
}
|
50
53
|
|
51
|
-
const tableColumnsNames: Record<
|
54
|
+
const tableColumnsNames: Record<TableColumnId, string> = {
|
52
55
|
PoolName: 'Pool Name',
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
+
Kind: 'Type',
|
57
|
+
Erasure: 'Erasure',
|
58
|
+
GroupId: 'Group ID',
|
56
59
|
Used: 'Used',
|
57
60
|
Limit: 'Limit',
|
58
61
|
UsedSpaceFlag: 'Space',
|
59
|
-
|
62
|
+
Usage: 'Usage',
|
60
63
|
Read: 'Read',
|
61
64
|
Write: 'Write',
|
62
65
|
VDisks: 'VDisks',
|
63
|
-
|
66
|
+
Degraded: 'Degraded',
|
64
67
|
};
|
65
68
|
|
66
69
|
const b = cn('global-storage-groups');
|
67
70
|
|
68
|
-
function setSortOrder(visibleEntities: VisibleEntities): SortOrder | undefined {
|
69
|
-
switch (visibleEntities) {
|
70
|
-
case VISIBLE_ENTITIES.all: {
|
71
|
-
return {
|
72
|
-
columnId: TableColumnsIds.PoolName,
|
73
|
-
order: DataTable.ASCENDING,
|
74
|
-
};
|
75
|
-
}
|
76
|
-
case VISIBLE_ENTITIES.missing: {
|
77
|
-
return {
|
78
|
-
columnId: TableColumnsIds.Missing,
|
79
|
-
order: DataTable.DESCENDING,
|
80
|
-
};
|
81
|
-
}
|
82
|
-
case VISIBLE_ENTITIES.space: {
|
83
|
-
return {
|
84
|
-
columnId: TableColumnsIds.UsedSpaceFlag,
|
85
|
-
order: DataTable.DESCENDING,
|
86
|
-
};
|
87
|
-
}
|
88
|
-
default: {
|
89
|
-
return undefined;
|
90
|
-
}
|
91
|
-
}
|
92
|
-
}
|
93
|
-
|
94
71
|
export function StorageGroups({
|
95
72
|
data,
|
96
73
|
tableSettings,
|
97
74
|
visibleEntities,
|
98
75
|
nodes,
|
99
76
|
onShowAll,
|
77
|
+
sort,
|
78
|
+
handleSort,
|
100
79
|
}: StorageGroupsProps) {
|
101
|
-
const
|
80
|
+
const rawColumns: Column<PreparedStorageGroup>[] = [
|
102
81
|
{
|
103
82
|
name: TableColumnsIds.PoolName,
|
104
83
|
header: tableColumnsNames[TableColumnsIds.PoolName],
|
@@ -124,12 +103,12 @@ export function StorageGroups({
|
|
124
103
|
align: DataTable.LEFT,
|
125
104
|
},
|
126
105
|
{
|
127
|
-
name: TableColumnsIds.
|
128
|
-
header: tableColumnsNames[TableColumnsIds.
|
106
|
+
name: TableColumnsIds.Kind,
|
107
|
+
header: tableColumnsNames[TableColumnsIds.Kind],
|
129
108
|
// prettier-ignore
|
130
109
|
render: ({row}) => (
|
131
110
|
<>
|
132
|
-
<Label>{row.
|
111
|
+
<Label>{row.Kind || '—'}</Label>
|
133
112
|
{' '}
|
134
113
|
{row.Encryption && (
|
135
114
|
<Popover
|
@@ -146,18 +125,18 @@ export function StorageGroups({
|
|
146
125
|
),
|
147
126
|
},
|
148
127
|
{
|
149
|
-
name: TableColumnsIds.
|
150
|
-
header: tableColumnsNames[TableColumnsIds.
|
128
|
+
name: TableColumnsIds.Erasure,
|
129
|
+
header: tableColumnsNames[TableColumnsIds.Erasure],
|
151
130
|
render: ({row}) => (row.ErasureSpecies ? row.ErasureSpecies : '-'),
|
152
131
|
align: DataTable.LEFT,
|
153
132
|
},
|
154
133
|
{
|
155
|
-
name: TableColumnsIds.
|
156
|
-
header: tableColumnsNames[TableColumnsIds.
|
134
|
+
name: TableColumnsIds.Degraded,
|
135
|
+
header: tableColumnsNames[TableColumnsIds.Degraded],
|
157
136
|
width: 100,
|
158
137
|
render: ({row}) =>
|
159
|
-
row.
|
160
|
-
<Label theme={getDegradedSeverity(row)}>Degraded: {row.
|
138
|
+
row.Degraded ? (
|
139
|
+
<Label theme={getDegradedSeverity(row)}>Degraded: {row.Degraded}</Label>
|
161
140
|
) : (
|
162
141
|
'-'
|
163
142
|
),
|
@@ -165,19 +144,18 @@ export function StorageGroups({
|
|
165
144
|
defaultOrder: DataTable.DESCENDING,
|
166
145
|
},
|
167
146
|
{
|
168
|
-
name: TableColumnsIds.
|
169
|
-
header: tableColumnsNames[TableColumnsIds.
|
147
|
+
name: TableColumnsIds.Usage,
|
148
|
+
header: tableColumnsNames[TableColumnsIds.Usage],
|
170
149
|
width: 100,
|
171
150
|
render: ({row}) => {
|
172
|
-
const usage = getUsage(row, 5);
|
173
151
|
// without a limit the usage can be evaluated as 0,
|
174
152
|
// but the absence of a value is more clear
|
175
153
|
return row.Limit ? (
|
176
154
|
<Label
|
177
|
-
theme={getUsageSeverityForStorageGroup(
|
178
|
-
className={b('usage-label', {overload:
|
155
|
+
theme={getUsageSeverityForStorageGroup(row.Usage)}
|
156
|
+
className={b('usage-label', {overload: row.Usage >= 90})}
|
179
157
|
>
|
180
|
-
{
|
158
|
+
{row.Usage}%
|
181
159
|
</Label>
|
182
160
|
) : (
|
183
161
|
'-'
|
@@ -188,12 +166,13 @@ export function StorageGroups({
|
|
188
166
|
align: DataTable.LEFT,
|
189
167
|
},
|
190
168
|
{
|
191
|
-
name: TableColumnsIds.
|
192
|
-
header: tableColumnsNames[TableColumnsIds.
|
169
|
+
name: TableColumnsIds.GroupId,
|
170
|
+
header: tableColumnsNames[TableColumnsIds.GroupId],
|
193
171
|
width: 130,
|
194
172
|
render: ({row}) => {
|
195
173
|
return <span className={b('group-id')}>{row.GroupID}</span>;
|
196
174
|
},
|
175
|
+
sortAccessor: (row) => Number(row.GroupID),
|
197
176
|
align: DataTable.RIGHT,
|
198
177
|
},
|
199
178
|
{
|
@@ -297,18 +276,21 @@ export function StorageGroups({
|
|
297
276
|
},
|
298
277
|
];
|
299
278
|
|
300
|
-
let columns =
|
279
|
+
let columns = rawColumns.map((column) => ({
|
280
|
+
...column,
|
281
|
+
sortable: isSortableStorageProperty(column.name),
|
282
|
+
}));
|
301
283
|
|
302
284
|
if (visibleEntities === VISIBLE_ENTITIES.all) {
|
303
|
-
columns =
|
285
|
+
columns = columns.filter((col) => {
|
304
286
|
return (
|
305
|
-
col.name !== TableColumnsIds.
|
287
|
+
col.name !== TableColumnsIds.Degraded && col.name !== TableColumnsIds.UsedSpaceFlag
|
306
288
|
);
|
307
289
|
});
|
308
290
|
}
|
309
291
|
|
310
292
|
if (visibleEntities === VISIBLE_ENTITIES.space) {
|
311
|
-
columns =
|
293
|
+
columns = columns.filter((col) => col.name !== TableColumnsIds.Degraded);
|
312
294
|
|
313
295
|
if (!data.length) {
|
314
296
|
return (
|
@@ -322,7 +304,7 @@ export function StorageGroups({
|
|
322
304
|
}
|
323
305
|
|
324
306
|
if (visibleEntities === VISIBLE_ENTITIES.missing) {
|
325
|
-
columns =
|
307
|
+
columns = columns.filter((col) => col.name !== TableColumnsIds.UsedSpaceFlag);
|
326
308
|
|
327
309
|
if (!data.length) {
|
328
310
|
return (
|
@@ -342,8 +324,9 @@ export function StorageGroups({
|
|
342
324
|
data={data}
|
343
325
|
columns={columns}
|
344
326
|
settings={tableSettings}
|
345
|
-
initialSortOrder={setSortOrder(visibleEntities)}
|
346
327
|
emptyDataMessage={i18n('empty.default')}
|
328
|
+
sortOrder={sort}
|
329
|
+
onSort={handleSort}
|
347
330
|
/>
|
348
331
|
) : null;
|
349
332
|
}
|
@@ -2,11 +2,14 @@ import cn from 'bem-cn-lite';
|
|
2
2
|
|
3
3
|
import DataTable, {Column, Settings, SortOrder} from '@gravity-ui/react-data-table';
|
4
4
|
|
5
|
+
import type {ValueOf} from '../../../types/common';
|
5
6
|
import type {PreparedStorageNode, VisibleEntities} from '../../../store/reducers/storage/types';
|
7
|
+
import type {HandleSort} from '../../../utils/hooks/useTableSort';
|
6
8
|
|
7
9
|
import {VISIBLE_ENTITIES} from '../../../store/reducers/storage/constants';
|
8
10
|
import {
|
9
11
|
AdditionalNodesInfo,
|
12
|
+
isSortableNodesProperty,
|
10
13
|
isUnavailableNode,
|
11
14
|
NodesUptimeFilterValues,
|
12
15
|
} from '../../../utils/nodes';
|
@@ -19,18 +22,17 @@ import {PDisk} from '../PDisk';
|
|
19
22
|
import i18n from './i18n';
|
20
23
|
import './StorageNodes.scss';
|
21
24
|
|
22
|
-
|
23
|
-
NodeId
|
24
|
-
|
25
|
-
|
26
|
-
Rack
|
27
|
-
Uptime
|
28
|
-
PDisks
|
29
|
-
Missing
|
30
|
-
}
|
25
|
+
const TableColumnsIds = {
|
26
|
+
NodeId: 'NodeId',
|
27
|
+
Host: 'Host',
|
28
|
+
DC: 'DC',
|
29
|
+
Rack: 'Rack',
|
30
|
+
Uptime: 'Uptime',
|
31
|
+
PDisks: 'PDisks',
|
32
|
+
Missing: 'Missing',
|
33
|
+
} as const;
|
31
34
|
|
32
|
-
type
|
33
|
-
type TableColumnsIdsValues = typeof TableColumnsIds[TableColumnsIdsKeys];
|
35
|
+
type TableColumnId = ValueOf<typeof TableColumnsIds>;
|
34
36
|
|
35
37
|
interface StorageNodesProps {
|
36
38
|
data: PreparedStorageNode[];
|
@@ -39,12 +41,14 @@ interface StorageNodesProps {
|
|
39
41
|
nodesUptimeFilter: keyof typeof NodesUptimeFilterValues;
|
40
42
|
onShowAll?: VoidFunction;
|
41
43
|
additionalNodesInfo?: AdditionalNodesInfo;
|
44
|
+
sort?: SortOrder;
|
45
|
+
handleSort?: HandleSort;
|
42
46
|
}
|
43
47
|
|
44
|
-
const tableColumnsNames: Record<
|
48
|
+
const tableColumnsNames: Record<TableColumnId, string> = {
|
45
49
|
NodeId: 'Node ID',
|
46
|
-
|
47
|
-
|
50
|
+
Host: 'Host',
|
51
|
+
DC: 'DC',
|
48
52
|
Rack: 'Rack',
|
49
53
|
Uptime: 'Uptime',
|
50
54
|
PDisks: 'PDisks',
|
@@ -53,26 +57,6 @@ const tableColumnsNames: Record<TableColumnsIdsValues, string> = {
|
|
53
57
|
|
54
58
|
const b = cn('global-storage-nodes');
|
55
59
|
|
56
|
-
function setSortOrder(visibleEntities: VisibleEntities): SortOrder | undefined {
|
57
|
-
switch (visibleEntities) {
|
58
|
-
case VISIBLE_ENTITIES.all: {
|
59
|
-
return {
|
60
|
-
columnId: TableColumnsIds.NodeId,
|
61
|
-
order: DataTable.ASCENDING,
|
62
|
-
};
|
63
|
-
}
|
64
|
-
case VISIBLE_ENTITIES.missing: {
|
65
|
-
return {
|
66
|
-
columnId: TableColumnsIds.Missing,
|
67
|
-
order: DataTable.DESCENDING,
|
68
|
-
};
|
69
|
-
}
|
70
|
-
default: {
|
71
|
-
return undefined;
|
72
|
-
}
|
73
|
-
}
|
74
|
-
}
|
75
|
-
|
76
60
|
export function StorageNodes({
|
77
61
|
data,
|
78
62
|
tableSettings,
|
@@ -80,10 +64,12 @@ export function StorageNodes({
|
|
80
64
|
onShowAll,
|
81
65
|
nodesUptimeFilter,
|
82
66
|
additionalNodesInfo,
|
67
|
+
sort,
|
68
|
+
handleSort,
|
83
69
|
}: StorageNodesProps) {
|
84
70
|
const getNodeRef = additionalNodesInfo?.getNodeRef;
|
85
71
|
|
86
|
-
const
|
72
|
+
const rawColumns: Column<PreparedStorageNode>[] = [
|
87
73
|
{
|
88
74
|
name: TableColumnsIds.NodeId,
|
89
75
|
header: tableColumnsNames[TableColumnsIds.NodeId],
|
@@ -91,8 +77,8 @@ export function StorageNodes({
|
|
91
77
|
align: DataTable.RIGHT,
|
92
78
|
},
|
93
79
|
{
|
94
|
-
name: TableColumnsIds.
|
95
|
-
header: tableColumnsNames[TableColumnsIds.
|
80
|
+
name: TableColumnsIds.Host,
|
81
|
+
header: tableColumnsNames[TableColumnsIds.Host],
|
96
82
|
width: 350,
|
97
83
|
render: ({row}) => {
|
98
84
|
return <NodeHostWrapper node={row} getNodeRef={getNodeRef} />;
|
@@ -100,8 +86,8 @@ export function StorageNodes({
|
|
100
86
|
align: DataTable.LEFT,
|
101
87
|
},
|
102
88
|
{
|
103
|
-
name: TableColumnsIds.
|
104
|
-
header: tableColumnsNames[TableColumnsIds.
|
89
|
+
name: TableColumnsIds.DC,
|
90
|
+
header: tableColumnsNames[TableColumnsIds.DC],
|
105
91
|
render: ({row}) => row.DataCenter || '—',
|
106
92
|
align: DataTable.LEFT,
|
107
93
|
},
|
@@ -144,10 +130,13 @@ export function StorageNodes({
|
|
144
130
|
},
|
145
131
|
];
|
146
132
|
|
147
|
-
let columns =
|
133
|
+
let columns = rawColumns.map((column) => ({
|
134
|
+
...column,
|
135
|
+
sortable: isSortableNodesProperty(column.name),
|
136
|
+
}));
|
148
137
|
|
149
|
-
if (visibleEntities
|
150
|
-
columns =
|
138
|
+
if (visibleEntities !== VISIBLE_ENTITIES.missing) {
|
139
|
+
columns = columns.filter((col) => col.name !== TableColumnsIds.Missing);
|
151
140
|
}
|
152
141
|
|
153
142
|
if (!data.length) {
|
@@ -187,9 +176,10 @@ export function StorageNodes({
|
|
187
176
|
...tableSettings,
|
188
177
|
dynamicRenderType: 'variable',
|
189
178
|
}}
|
190
|
-
initialSortOrder={setSortOrder(visibleEntities)}
|
191
179
|
emptyDataMessage={i18n('empty.default')}
|
192
180
|
rowClassName={(row) => b('node', {unavailable: isUnavailableNode(row)})}
|
181
|
+
sortOrder={sort}
|
182
|
+
onSort={handleSort}
|
193
183
|
/>
|
194
184
|
) : null;
|
195
185
|
}
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import type {
|
1
|
+
import type {PreparedStorageGroup} from '../../../store/reducers/storage/types';
|
2
2
|
import {EFlag} from '../../../types/api/enums';
|
3
3
|
|
4
4
|
export * from './constants';
|
@@ -35,12 +35,12 @@ const degradationEvaluators = {
|
|
35
35
|
const canEvaluateErasureSpecies = (value?: string): value is keyof typeof degradationEvaluators =>
|
36
36
|
value !== undefined && value in degradationEvaluators;
|
37
37
|
|
38
|
-
export const getDegradedSeverity = (group:
|
38
|
+
export const getDegradedSeverity = (group: PreparedStorageGroup) => {
|
39
39
|
const evaluate = canEvaluateErasureSpecies(group.ErasureSpecies)
|
40
40
|
? degradationEvaluators[group.ErasureSpecies]
|
41
41
|
: defaultDegradationEvaluator;
|
42
42
|
|
43
|
-
return evaluate(group.
|
43
|
+
return evaluate(group.Degraded);
|
44
44
|
};
|
45
45
|
|
46
46
|
export const getUsageSeverityForStorageGroup = generateEvaluator(80, 85, [
|
@@ -14,8 +14,11 @@
|
|
14
14
|
"actions.openPreview": "Open preview",
|
15
15
|
"actions.createTable": "Create table...",
|
16
16
|
"actions.createExternalTable": "Create external table...",
|
17
|
+
"actions.createTopic": "Create topic...",
|
17
18
|
"actions.dropTable": "Drop table...",
|
19
|
+
"actions.dropTopic": "Drop topic...",
|
18
20
|
"actions.alterTable": "Alter table...",
|
21
|
+
"actions.alterTopic": "Alter topic...",
|
19
22
|
"actions.selectQuery": "Select query...",
|
20
23
|
"actions.upsertQuery": "Upsert query..."
|
21
24
|
}
|