ydb-embedded-ui 4.8.1 → 4.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -0
- package/dist/components/NodeHostWrapper/NodeHostWrapper.tsx +2 -2
- package/dist/components/Tablet/Tablet.tsx +2 -13
- package/dist/containers/Header/breadcrumbs.ts +22 -6
- package/dist/containers/Nodes/Nodes.tsx +1 -1
- package/dist/containers/Nodes/getNodesColumns.tsx +2 -2
- package/dist/containers/Storage/PDisk/PDisk.tsx +1 -1
- package/dist/containers/Storage/Storage.js +26 -48
- package/dist/containers/Storage/StorageGroups/StorageGroups.tsx +16 -19
- package/dist/containers/Storage/StorageNodes/StorageNodes.tsx +12 -10
- package/dist/containers/Storage/StorageTypeFilter/StorageTypeFilter.tsx +27 -0
- package/dist/containers/Storage/StorageVisibleEntityFilter/StorageVisibleEntityFilter.tsx +31 -0
- package/dist/containers/Tablet/Tablet.tsx +2 -11
- package/dist/containers/TabletsFilters/TabletsFilters.js +8 -3
- package/dist/containers/Tenant/Query/QueryEditor/QueryEditor.js +17 -43
- package/dist/containers/Tenant/Query/QueryEditorControls/QueryEditorControls.scss +20 -15
- package/dist/containers/Tenant/Query/QueryEditorControls/QueryEditorControls.tsx +74 -27
- package/dist/containers/Tenant/Query/i18n/en.json +1 -1
- package/dist/containers/Tenant/Query/i18n/ru.json +1 -1
- package/dist/containers/UserSettings/i18n/en.json +1 -1
- package/dist/containers/UserSettings/i18n/ru.json +1 -1
- package/dist/services/api.ts +6 -13
- package/dist/store/reducers/executeQuery.ts +2 -3
- package/dist/store/reducers/explainQuery.ts +2 -2
- package/dist/store/reducers/header/types.ts +0 -2
- package/dist/store/reducers/index.ts +2 -2
- package/dist/store/reducers/{nodes.ts → nodes/nodes.ts} +31 -30
- package/dist/{types/store/nodes.ts → store/reducers/nodes/types.ts} +24 -27
- package/dist/store/reducers/settings/settings.ts +10 -2
- package/dist/store/reducers/storage/constants.ts +10 -0
- package/dist/store/reducers/{storage.js → storage/storage.js} +19 -53
- package/dist/store/reducers/storage/types.ts +12 -0
- package/dist/types/store/query.ts +5 -6
- package/dist/utils/constants.ts +1 -0
- package/dist/utils/nodes.ts +2 -2
- package/dist/utils/query.ts +12 -0
- package/package.json +1 -1
- package/dist/containers/Tenant/Query/QueryEditorControls/OldQueryEditorControls.tsx +0 -90
- package/dist/containers/Tenant/Query/QueryEditorControls/shared.ts +0 -18
package/CHANGELOG.md
CHANGED
@@ -1,5 +1,27 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [4.9.0](https://github.com/ydb-platform/ydb-embedded-ui/compare/v4.8.2...v4.9.0) (2023-06-30)
|
4
|
+
|
5
|
+
|
6
|
+
### Features
|
7
|
+
|
8
|
+
* **QueryEditor:** remove old controls, update setting ([#445](https://github.com/ydb-platform/ydb-embedded-ui/issues/445)) ([75efd44](https://github.com/ydb-platform/ydb-embedded-ui/commit/75efd444c8b8ba5213117ec9c33f6b9664855a2c))
|
9
|
+
|
10
|
+
|
11
|
+
### Bug Fixes
|
12
|
+
|
13
|
+
* **QueryEditor:** color last used query action, run on command ([#436](https://github.com/ydb-platform/ydb-embedded-ui/issues/436)) ([c4d3bb8](https://github.com/ydb-platform/ydb-embedded-ui/commit/c4d3bb81bc1cea8ec3fe2e5e7e18c997d94f5714))
|
14
|
+
* **QueryEditor:** rename query modes ([#449](https://github.com/ydb-platform/ydb-embedded-ui/issues/449)) ([c93c9c1](https://github.com/ydb-platform/ydb-embedded-ui/commit/c93c9c17ba26e01c596009657cac02ecc9cc9ab0))
|
15
|
+
* **StorageNodes:** sort by uptime ([#447](https://github.com/ydb-platform/ydb-embedded-ui/issues/447)) ([283cb81](https://github.com/ydb-platform/ydb-embedded-ui/commit/283cb81b3f4711ddc2bb991615729a9bda7e893c))
|
16
|
+
* **Storage:** remove visible entities filter ([#448](https://github.com/ydb-platform/ydb-embedded-ui/issues/448)) ([b4d9489](https://github.com/ydb-platform/ydb-embedded-ui/commit/b4d948965cd349a54fe833a6b81ea3b087782735))
|
17
|
+
|
18
|
+
## [4.8.2](https://github.com/ydb-platform/ydb-embedded-ui/compare/v4.8.1...v4.8.2) (2023-06-27)
|
19
|
+
|
20
|
+
|
21
|
+
### Bug Fixes
|
22
|
+
|
23
|
+
* **breadcrumbs:** update tenant and tablet params ([#443](https://github.com/ydb-platform/ydb-embedded-ui/issues/443)) ([b0d31ac](https://github.com/ydb-platform/ydb-embedded-ui/commit/b0d31acce6d6e97d759180c885e6aea3b762a91c))
|
24
|
+
|
3
25
|
## [4.8.1](https://github.com/ydb-platform/ydb-embedded-ui/compare/v4.8.0...v4.8.1) (2023-06-26)
|
4
26
|
|
5
27
|
|
@@ -2,7 +2,7 @@ import block from 'bem-cn-lite';
|
|
2
2
|
|
3
3
|
import {Button, Popover, PopoverBehavior} from '@gravity-ui/uikit';
|
4
4
|
|
5
|
-
import type {
|
5
|
+
import type {NodesPreparedEntity} from '../../store/reducers/nodes/types';
|
6
6
|
import {getDefaultNodePath} from '../../containers/Node/NodePages';
|
7
7
|
import {isUnavailableNode, NodeAddress} from '../../utils/nodes';
|
8
8
|
|
@@ -15,7 +15,7 @@ import './NodeHostWrapper.scss';
|
|
15
15
|
const b = block('ydb-node-host-wrapper');
|
16
16
|
|
17
17
|
interface NodeHostWrapperProps {
|
18
|
-
node:
|
18
|
+
node: NodesPreparedEntity;
|
19
19
|
getNodeRef?: (node?: NodeAddress) => string | null;
|
20
20
|
}
|
21
21
|
|
@@ -18,21 +18,10 @@ interface TabletProps {
|
|
18
18
|
}
|
19
19
|
|
20
20
|
export const Tablet = ({tablet = {}, tenantName}: TabletProps) => {
|
21
|
-
const {TabletId: id, NodeId
|
21
|
+
const {TabletId: id, NodeId} = tablet;
|
22
22
|
const status = tablet.Overall?.toLowerCase();
|
23
23
|
|
24
|
-
const tabletPath =
|
25
|
-
id &&
|
26
|
-
createHref(
|
27
|
-
routes.tablet,
|
28
|
-
{id},
|
29
|
-
{
|
30
|
-
nodeId: NodeId,
|
31
|
-
type: Type,
|
32
|
-
state: State,
|
33
|
-
tenantName,
|
34
|
-
},
|
35
|
-
);
|
24
|
+
const tabletPath = id && createHref(routes.tablet, {id}, {nodeId: NodeId, tenantName});
|
36
25
|
|
37
26
|
return (
|
38
27
|
<ContentWithPopup
|
@@ -10,10 +10,15 @@ import type {
|
|
10
10
|
TabletsBreadcrumbsOptions,
|
11
11
|
TenantBreadcrumbsOptions,
|
12
12
|
} from '../../store/reducers/header/types';
|
13
|
+
import {
|
14
|
+
TENANT_DIAGNOSTICS_TABS_IDS,
|
15
|
+
TENANT_PAGE,
|
16
|
+
TENANT_PAGES_IDS,
|
17
|
+
} from '../../store/reducers/tenant/constants';
|
13
18
|
import routes, {createHref} from '../../routes';
|
14
19
|
|
15
20
|
import {getClusterPath} from '../Cluster/utils';
|
16
|
-
import {getTenantPath} from '../Tenant/TenantPages';
|
21
|
+
import {TenantTabsGroups, getTenantPath} from '../Tenant/TenantPages';
|
17
22
|
import {getDefaultNodePath} from '../Node/NodePages';
|
18
23
|
|
19
24
|
const prepareTenantName = (tenantName: string) => {
|
@@ -61,10 +66,16 @@ const getNodeBreadcrumbs = (options: NodeBreadcrumbsOptions, query = {}): RawBre
|
|
61
66
|
// Compute nodes have tenantName, storage nodes doesn't
|
62
67
|
const isStorageNode = !tenantName;
|
63
68
|
|
69
|
+
const newQuery = {
|
70
|
+
...query,
|
71
|
+
[TENANT_PAGE]: TENANT_PAGES_IDS.diagnostics,
|
72
|
+
[TenantTabsGroups.diagnosticsTab]: TENANT_DIAGNOSTICS_TABS_IDS.nodes,
|
73
|
+
};
|
74
|
+
|
64
75
|
if (isStorageNode) {
|
65
76
|
breadcrumbs = getClusterBreadcrumbs(options, query);
|
66
77
|
} else {
|
67
|
-
breadcrumbs = getTenantBreadcrumbs(options,
|
78
|
+
breadcrumbs = getTenantBreadcrumbs(options, newQuery);
|
68
79
|
}
|
69
80
|
|
70
81
|
const text = nodeId ? `Node ${nodeId}` : 'Node';
|
@@ -79,21 +90,26 @@ const getTabletsBreadcrubms = (
|
|
79
90
|
options: TabletsBreadcrumbsOptions,
|
80
91
|
query = {},
|
81
92
|
): RawBreadcrumbItem[] => {
|
82
|
-
const {tenantName, nodeIds
|
93
|
+
const {tenantName, nodeIds} = options;
|
94
|
+
|
95
|
+
const newQuery = {
|
96
|
+
...query,
|
97
|
+
[TENANT_PAGE]: TENANT_PAGES_IDS.diagnostics,
|
98
|
+
[TenantTabsGroups.diagnosticsTab]: TENANT_DIAGNOSTICS_TABS_IDS.tablets,
|
99
|
+
};
|
83
100
|
|
84
101
|
let breadcrumbs: RawBreadcrumbItem[];
|
85
102
|
|
86
103
|
// Cluster system tablets don't have tenantName
|
87
104
|
if (tenantName) {
|
88
|
-
breadcrumbs = getTenantBreadcrumbs(options,
|
105
|
+
breadcrumbs = getTenantBreadcrumbs(options, newQuery);
|
89
106
|
} else {
|
90
107
|
breadcrumbs = getClusterBreadcrumbs(options, query);
|
91
108
|
}
|
92
109
|
|
93
110
|
const link = createHref(routes.tabletsFilters, undefined, {
|
111
|
+
...query,
|
94
112
|
nodeIds,
|
95
|
-
state,
|
96
|
-
type,
|
97
113
|
path: tenantName,
|
98
114
|
});
|
99
115
|
|
@@ -26,7 +26,7 @@ import {
|
|
26
26
|
setSearchValue,
|
27
27
|
resetNodesState,
|
28
28
|
getComputeNodes,
|
29
|
-
} from '../../store/reducers/nodes';
|
29
|
+
} from '../../store/reducers/nodes/nodes';
|
30
30
|
import {changeFilter, ProblemFilterValues} from '../../store/reducers/settings/settings';
|
31
31
|
|
32
32
|
import {isDatabaseEntityType} from '../Tenant/utils/schema';
|
@@ -9,7 +9,7 @@ import {NodeHostWrapper} from '../../components/NodeHostWrapper/NodeHostWrapper'
|
|
9
9
|
import type {NodeAddress} from '../../utils/nodes';
|
10
10
|
import {formatBytesToGigabyte} from '../../utils/index';
|
11
11
|
|
12
|
-
import type {
|
12
|
+
import type {NodesPreparedEntity} from '../../store/reducers/nodes/types';
|
13
13
|
|
14
14
|
interface GetNodesColumnsProps {
|
15
15
|
tabletsPath?: string;
|
@@ -17,7 +17,7 @@ interface GetNodesColumnsProps {
|
|
17
17
|
}
|
18
18
|
|
19
19
|
export function getNodesColumns({tabletsPath, getNodeRef}: GetNodesColumnsProps) {
|
20
|
-
const columns: Column<
|
20
|
+
const columns: Column<NodesPreparedEntity>[] = [
|
21
21
|
{
|
22
22
|
name: 'NodeId',
|
23
23
|
header: '#',
|
@@ -5,7 +5,7 @@ import {InternalLink} from '../../../components/InternalLink';
|
|
5
5
|
import {Stack} from '../../../components/Stack/Stack';
|
6
6
|
|
7
7
|
import routes, {createHref} from '../../../routes';
|
8
|
-
import {getVDisksForPDisk} from '../../../store/reducers/storage';
|
8
|
+
import {getVDisksForPDisk} from '../../../store/reducers/storage/storage';
|
9
9
|
import {TPDiskStateInfo, TPDiskState} from '../../../types/api/pdisk';
|
10
10
|
import {TVDiskStateInfo} from '../../../types/api/vdisk';
|
11
11
|
import {stringifyVdiskId} from '../../../utils';
|
@@ -3,7 +3,6 @@ import PropTypes from 'prop-types';
|
|
3
3
|
import {connect} from 'react-redux';
|
4
4
|
import cn from 'bem-cn-lite';
|
5
5
|
import DataTable from '@gravity-ui/react-data-table';
|
6
|
-
import {RadioButton} from '@gravity-ui/uikit';
|
7
6
|
|
8
7
|
import {Search} from '../../components/Search';
|
9
8
|
import {UsageFilter} from './UsageFilter';
|
@@ -18,33 +17,29 @@ import {
|
|
18
17
|
getStorageInfo,
|
19
18
|
setInitialState,
|
20
19
|
getFilteredEntities,
|
21
|
-
VisibleEntities,
|
22
20
|
setVisibleEntities,
|
23
21
|
setStorageFilter,
|
24
22
|
setUsageFilter,
|
25
|
-
StorageTypes,
|
26
23
|
setStorageType,
|
27
24
|
setNodesUptimeFilter,
|
28
25
|
setDataWasNotLoaded,
|
29
|
-
VisibleEntitiesTitles,
|
30
26
|
getStoragePoolsGroupsCount,
|
31
27
|
getStorageNodesCount,
|
32
28
|
getUsageFilterOptions,
|
33
|
-
} from '../../store/reducers/storage';
|
29
|
+
} from '../../store/reducers/storage/storage';
|
30
|
+
import {VISIBLE_ENTITIES, STORAGE_TYPES} from '../../store/reducers/storage/constants';
|
34
31
|
import {getNodesList, selectNodesMap} from '../../store/reducers/nodesList';
|
35
32
|
import StorageGroups from './StorageGroups/StorageGroups';
|
36
33
|
import StorageNodes from './StorageNodes/StorageNodes';
|
37
34
|
import {DEFAULT_TABLE_SETTINGS} from '../../utils/constants';
|
38
35
|
|
36
|
+
import {StorageTypeFilter} from './StorageTypeFilter/StorageTypeFilter';
|
37
|
+
import {StorageVisibleEntityFilter} from './StorageVisibleEntityFilter/StorageVisibleEntityFilter';
|
38
|
+
|
39
39
|
import './Storage.scss';
|
40
40
|
|
41
41
|
const b = cn('global-storage');
|
42
42
|
|
43
|
-
const FILTER_OPTIONS = {
|
44
|
-
Missing: 'missing',
|
45
|
-
Space: 'space',
|
46
|
-
};
|
47
|
-
|
48
43
|
const tableSettings = {
|
49
44
|
...DEFAULT_TABLE_SETTINGS,
|
50
45
|
defaultOrder: DataTable.DESCENDING,
|
@@ -74,25 +69,23 @@ class Storage extends React.Component {
|
|
74
69
|
};
|
75
70
|
|
76
71
|
componentDidMount() {
|
77
|
-
const {tenant, nodeId, setVisibleEntities, storageType, getNodesList} =
|
78
|
-
this.props;
|
72
|
+
const {tenant, nodeId, setVisibleEntities, storageType, getNodesList} = this.props;
|
79
73
|
|
80
74
|
this.autofetcher = new AutoFetcher();
|
81
75
|
getNodesList();
|
82
76
|
if (tenant || nodeId) {
|
83
|
-
setVisibleEntities(
|
77
|
+
setVisibleEntities(VISIBLE_ENTITIES.all);
|
84
78
|
this.getStorageInfo({
|
85
|
-
filter: FILTER_OPTIONS.All,
|
86
79
|
type: storageType,
|
87
80
|
});
|
88
81
|
} else {
|
89
82
|
this.getStorageInfo({
|
90
|
-
|
83
|
+
visibleEntities: VISIBLE_ENTITIES.missing,
|
91
84
|
type: storageType,
|
92
85
|
});
|
93
86
|
this.autofetcher.fetch(() =>
|
94
87
|
this.getStorageInfo({
|
95
|
-
|
88
|
+
visibleEntities: VISIBLE_ENTITIES.missing,
|
96
89
|
type: storageType,
|
97
90
|
}),
|
98
91
|
);
|
@@ -105,7 +98,7 @@ class Storage extends React.Component {
|
|
105
98
|
|
106
99
|
const startFetch = () => {
|
107
100
|
this.getStorageInfo({
|
108
|
-
|
101
|
+
visibleEntities,
|
109
102
|
type: storageType,
|
110
103
|
});
|
111
104
|
};
|
@@ -115,7 +108,7 @@ class Storage extends React.Component {
|
|
115
108
|
this.autofetcher.start();
|
116
109
|
this.autofetcher.fetch(() =>
|
117
110
|
this.getStorageInfo({
|
118
|
-
|
111
|
+
visibleEntities,
|
119
112
|
type: storageType,
|
120
113
|
}),
|
121
114
|
);
|
@@ -183,16 +176,16 @@ class Storage extends React.Component {
|
|
183
176
|
|
184
177
|
return (
|
185
178
|
<div className={b('table-wrapper')}>
|
186
|
-
{storageType ===
|
179
|
+
{storageType === STORAGE_TYPES.groups && (
|
187
180
|
<StorageGroups
|
188
181
|
visibleEntities={visibleEntities}
|
189
182
|
data={flatListStorageEntities}
|
190
183
|
tableSettings={tableSettings}
|
191
184
|
nodes={nodes}
|
192
|
-
onShowAll={() => this.onGroupVisibilityChange(
|
185
|
+
onShowAll={() => this.onGroupVisibilityChange(VISIBLE_ENTITIES.all)}
|
193
186
|
/>
|
194
187
|
)}
|
195
|
-
{storageType ===
|
188
|
+
{storageType === STORAGE_TYPES.nodes && (
|
196
189
|
<StorageNodes
|
197
190
|
visibleEntities={visibleEntities}
|
198
191
|
nodesUptimeFilter={nodesUptimeFilter}
|
@@ -221,7 +214,7 @@ class Storage extends React.Component {
|
|
221
214
|
};
|
222
215
|
|
223
216
|
onShowAllNodes = () => {
|
224
|
-
this.onGroupVisibilityChange(
|
217
|
+
this.onGroupVisibilityChange(VISIBLE_ENTITIES.all);
|
225
218
|
this.onUptimeFilterChange(NodesUptimeFilterValues.All);
|
226
219
|
};
|
227
220
|
|
@@ -229,8 +222,8 @@ class Storage extends React.Component {
|
|
229
222
|
const {storageType, groupsCount, nodesCount, flatListStorageEntities, loading, wasLoaded} =
|
230
223
|
this.props;
|
231
224
|
|
232
|
-
const entityName = storageType ===
|
233
|
-
const count = storageType ===
|
225
|
+
const entityName = storageType === STORAGE_TYPES.groups ? 'Groups' : 'Nodes';
|
226
|
+
const count = storageType === STORAGE_TYPES.groups ? groupsCount : nodesCount;
|
234
227
|
|
235
228
|
return (
|
236
229
|
<EntitiesCount
|
@@ -259,7 +252,7 @@ class Storage extends React.Component {
|
|
259
252
|
<div className={b('search')}>
|
260
253
|
<Search
|
261
254
|
placeholder={
|
262
|
-
storageType ===
|
255
|
+
storageType === STORAGE_TYPES.groups
|
263
256
|
? 'Group ID, Pool name'
|
264
257
|
: 'Node ID, FQDN'
|
265
258
|
}
|
@@ -268,32 +261,17 @@ class Storage extends React.Component {
|
|
268
261
|
/>
|
269
262
|
</div>
|
270
263
|
|
271
|
-
<
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
</RadioButton>
|
279
|
-
|
280
|
-
<RadioButton value={visibleEntities} onUpdate={this.onGroupVisibilityChange}>
|
281
|
-
<RadioButton.Option value={VisibleEntities.Missing}>
|
282
|
-
{VisibleEntitiesTitles[VisibleEntities.Missing]}
|
283
|
-
</RadioButton.Option>
|
284
|
-
<RadioButton.Option value={VisibleEntities.Space}>
|
285
|
-
{VisibleEntitiesTitles[VisibleEntities.Space]}
|
286
|
-
</RadioButton.Option>
|
287
|
-
<RadioButton.Option value={VisibleEntities.All}>
|
288
|
-
{VisibleEntitiesTitles[VisibleEntities.All]}
|
289
|
-
</RadioButton.Option>
|
290
|
-
</RadioButton>
|
291
|
-
|
292
|
-
{storageType === StorageTypes.nodes && (
|
264
|
+
<StorageTypeFilter value={storageType} onChange={this.onStorageTypeChange} />
|
265
|
+
<StorageVisibleEntityFilter
|
266
|
+
value={visibleEntities}
|
267
|
+
onChange={this.onGroupVisibilityChange}
|
268
|
+
/>
|
269
|
+
|
270
|
+
{storageType === STORAGE_TYPES.nodes && (
|
293
271
|
<UptimeFilter value={nodesUptimeFilter} onChange={this.onUptimeFilterChange} />
|
294
272
|
)}
|
295
273
|
|
296
|
-
{storageType ===
|
274
|
+
{storageType === STORAGE_TYPES.groups && (
|
297
275
|
<UsageFilter
|
298
276
|
value={usageFilter}
|
299
277
|
onChange={setUsageFilter}
|
@@ -1,25 +1,22 @@
|
|
1
1
|
import _ from 'lodash';
|
2
2
|
import cn from 'bem-cn-lite';
|
3
|
+
|
3
4
|
import DataTable, {Column, Settings, SortOrder} from '@gravity-ui/react-data-table';
|
4
5
|
import {Icon, Label, Popover, PopoverBehavior} from '@gravity-ui/uikit';
|
5
6
|
|
6
7
|
import type {NodesMap} from '../../../types/store/nodesList';
|
8
|
+
import type {TVDiskStateInfo} from '../../../types/api/vdisk';
|
9
|
+
import type {VisibleEntities} from '../../../store/reducers/storage/types';
|
7
10
|
|
8
|
-
import
|
9
|
-
|
10
|
-
import {Stack} from '../../../components/Stack/Stack';
|
11
|
-
//@ts-ignore
|
12
|
-
import EntityStatus from '../../../components/EntityStatus/EntityStatus';
|
13
|
-
|
14
|
-
import {TVDiskStateInfo} from '../../../types/api/vdisk';
|
15
|
-
//@ts-ignore
|
16
|
-
import {VisibleEntities} from '../../../store/reducers/storage';
|
17
|
-
//@ts-ignore
|
11
|
+
import {VISIBLE_ENTITIES} from '../../../store/reducers/storage/constants';
|
18
12
|
import {bytesToGB, bytesToSpeed} from '../../../utils/utils';
|
19
|
-
//@ts-ignore
|
20
13
|
import {stringifyVdiskId} from '../../../utils';
|
21
14
|
import {getUsage, isFullVDiskData} from '../../../utils/storage';
|
22
15
|
|
16
|
+
import shieldIcon from '../../../assets/icons/shield.svg';
|
17
|
+
import {Stack} from '../../../components/Stack/Stack';
|
18
|
+
import EntityStatus from '../../../components/EntityStatus/EntityStatus';
|
19
|
+
|
23
20
|
import {EmptyFilter} from '../EmptyFilter/EmptyFilter';
|
24
21
|
import {VDisk} from '../VDisk';
|
25
22
|
import {getDegradedSeverity, getUsageSeverityForStorageGroup} from '../utils';
|
@@ -49,7 +46,7 @@ interface StorageGroupsProps {
|
|
49
46
|
data: any;
|
50
47
|
nodes: NodesMap;
|
51
48
|
tableSettings: Settings;
|
52
|
-
visibleEntities:
|
49
|
+
visibleEntities: VisibleEntities;
|
53
50
|
onShowAll?: VoidFunction;
|
54
51
|
}
|
55
52
|
|
@@ -70,21 +67,21 @@ const tableColumnsNames: Record<TableColumnsIdsValues, string> = {
|
|
70
67
|
|
71
68
|
const b = cn('global-storage-groups');
|
72
69
|
|
73
|
-
function setSortOrder(visibleEntities:
|
70
|
+
function setSortOrder(visibleEntities: VisibleEntities): SortOrder | undefined {
|
74
71
|
switch (visibleEntities) {
|
75
|
-
case
|
72
|
+
case VISIBLE_ENTITIES.all: {
|
76
73
|
return {
|
77
74
|
columnId: TableColumnsIds.PoolName,
|
78
75
|
order: DataTable.ASCENDING,
|
79
76
|
};
|
80
77
|
}
|
81
|
-
case
|
78
|
+
case VISIBLE_ENTITIES.missing: {
|
82
79
|
return {
|
83
80
|
columnId: TableColumnsIds.Missing,
|
84
81
|
order: DataTable.DESCENDING,
|
85
82
|
};
|
86
83
|
}
|
87
|
-
case
|
84
|
+
case VISIBLE_ENTITIES.space: {
|
88
85
|
return {
|
89
86
|
columnId: TableColumnsIds.UsedSpaceFlag,
|
90
87
|
order: DataTable.DESCENDING,
|
@@ -295,7 +292,7 @@ function StorageGroups({
|
|
295
292
|
|
296
293
|
let columns = allColumns;
|
297
294
|
|
298
|
-
if (visibleEntities ===
|
295
|
+
if (visibleEntities === VISIBLE_ENTITIES.all) {
|
299
296
|
columns = allColumns.filter((col) => {
|
300
297
|
return (
|
301
298
|
col.name !== TableColumnsIds.Missing && col.name !== TableColumnsIds.UsedSpaceFlag
|
@@ -303,7 +300,7 @@ function StorageGroups({
|
|
303
300
|
});
|
304
301
|
}
|
305
302
|
|
306
|
-
if (visibleEntities ===
|
303
|
+
if (visibleEntities === VISIBLE_ENTITIES.space) {
|
307
304
|
columns = allColumns.filter((col) => col.name !== TableColumnsIds.Missing);
|
308
305
|
|
309
306
|
if (!data.length) {
|
@@ -317,7 +314,7 @@ function StorageGroups({
|
|
317
314
|
}
|
318
315
|
}
|
319
316
|
|
320
|
-
if (visibleEntities ===
|
317
|
+
if (visibleEntities === VISIBLE_ENTITIES.missing) {
|
321
318
|
columns = allColumns.filter((col) => col.name !== TableColumnsIds.UsedSpaceFlag);
|
322
319
|
|
323
320
|
if (!data.length) {
|
@@ -3,7 +3,9 @@ import cn from 'bem-cn-lite';
|
|
3
3
|
|
4
4
|
import DataTable, {Column, Settings, SortOrder} from '@gravity-ui/react-data-table';
|
5
5
|
|
6
|
-
import {VisibleEntities} from '../../../store/reducers/storage';
|
6
|
+
import type {VisibleEntities} from '../../../store/reducers/storage/types';
|
7
|
+
|
8
|
+
import {VISIBLE_ENTITIES} from '../../../store/reducers/storage/constants';
|
7
9
|
import {
|
8
10
|
AdditionalNodesInfo,
|
9
11
|
isUnavailableNode,
|
@@ -35,7 +37,7 @@ interface StorageNodesProps {
|
|
35
37
|
data: any;
|
36
38
|
nodes: any;
|
37
39
|
tableSettings: Settings;
|
38
|
-
visibleEntities:
|
40
|
+
visibleEntities: VisibleEntities;
|
39
41
|
nodesUptimeFilter: keyof typeof NodesUptimeFilterValues;
|
40
42
|
onShowAll?: VoidFunction;
|
41
43
|
additionalNodesInfo?: AdditionalNodesInfo;
|
@@ -53,15 +55,15 @@ const tableColumnsNames: Record<TableColumnsIdsValues, string> = {
|
|
53
55
|
|
54
56
|
const b = cn('global-storage-nodes');
|
55
57
|
|
56
|
-
function setSortOrder(visibleEntities:
|
58
|
+
function setSortOrder(visibleEntities: VisibleEntities): SortOrder | undefined {
|
57
59
|
switch (visibleEntities) {
|
58
|
-
case
|
60
|
+
case VISIBLE_ENTITIES.all: {
|
59
61
|
return {
|
60
62
|
columnId: TableColumnsIds.NodeId,
|
61
63
|
order: DataTable.ASCENDING,
|
62
64
|
};
|
63
65
|
}
|
64
|
-
case
|
66
|
+
case VISIBLE_ENTITIES.missing: {
|
65
67
|
return {
|
66
68
|
columnId: TableColumnsIds.Missing,
|
67
69
|
order: DataTable.DESCENDING,
|
@@ -115,7 +117,7 @@ function StorageNodes({
|
|
115
117
|
name: TableColumnsIds.uptime,
|
116
118
|
header: tableColumnsNames[TableColumnsIds.uptime],
|
117
119
|
width: 130,
|
118
|
-
sortAccessor: ({StartTime}) => -StartTime,
|
120
|
+
sortAccessor: ({StartTime}) => (StartTime ? -StartTime : 0),
|
119
121
|
align: DataTable.RIGHT,
|
120
122
|
},
|
121
123
|
{
|
@@ -146,18 +148,18 @@ function StorageNodes({
|
|
146
148
|
|
147
149
|
let columns = allColumns;
|
148
150
|
|
149
|
-
if (visibleEntities ===
|
151
|
+
if (visibleEntities === VISIBLE_ENTITIES.space) {
|
150
152
|
columns = allColumns.filter((col) => col.name !== TableColumnsIds.Missing);
|
151
153
|
}
|
152
154
|
|
153
155
|
if (!data.length) {
|
154
156
|
let message;
|
155
157
|
|
156
|
-
if (visibleEntities ===
|
158
|
+
if (visibleEntities === VISIBLE_ENTITIES.space) {
|
157
159
|
message = i18n('empty.out_of_space');
|
158
160
|
}
|
159
161
|
|
160
|
-
if (visibleEntities ===
|
162
|
+
if (visibleEntities === VISIBLE_ENTITIES.missing) {
|
161
163
|
message = i18n('empty.degraded');
|
162
164
|
}
|
163
165
|
|
@@ -166,7 +168,7 @@ function StorageNodes({
|
|
166
168
|
}
|
167
169
|
|
168
170
|
if (
|
169
|
-
visibleEntities !==
|
171
|
+
visibleEntities !== VISIBLE_ENTITIES.all &&
|
170
172
|
nodesUptimeFilter !== NodesUptimeFilterValues.All
|
171
173
|
) {
|
172
174
|
message = i18n('empty.several_filters');
|
@@ -0,0 +1,27 @@
|
|
1
|
+
import {RadioButton} from '@gravity-ui/uikit';
|
2
|
+
|
3
|
+
import type {StorageType} from '../../../store/reducers/storage/types';
|
4
|
+
import {STORAGE_TYPES} from '../../../store/reducers/storage/constants';
|
5
|
+
|
6
|
+
const StorageTypesTitles = {
|
7
|
+
[STORAGE_TYPES.groups]: 'Groups',
|
8
|
+
[STORAGE_TYPES.nodes]: 'Nodes',
|
9
|
+
};
|
10
|
+
|
11
|
+
interface StorageTypeFilterProps {
|
12
|
+
value: StorageType;
|
13
|
+
onChange: (value: string) => void;
|
14
|
+
}
|
15
|
+
|
16
|
+
export const StorageTypeFilter = ({value, onChange}: StorageTypeFilterProps) => {
|
17
|
+
return (
|
18
|
+
<RadioButton value={value} onUpdate={onChange}>
|
19
|
+
<RadioButton.Option value={STORAGE_TYPES.groups}>
|
20
|
+
{StorageTypesTitles[STORAGE_TYPES.groups]}
|
21
|
+
</RadioButton.Option>
|
22
|
+
<RadioButton.Option value={STORAGE_TYPES.nodes}>
|
23
|
+
{StorageTypesTitles[STORAGE_TYPES.nodes]}
|
24
|
+
</RadioButton.Option>
|
25
|
+
</RadioButton>
|
26
|
+
);
|
27
|
+
};
|
@@ -0,0 +1,31 @@
|
|
1
|
+
import {RadioButton} from '@gravity-ui/uikit';
|
2
|
+
|
3
|
+
import type {VisibleEntities} from '../../../store/reducers/storage/types';
|
4
|
+
import {VISIBLE_ENTITIES} from '../../../store/reducers/storage/constants';
|
5
|
+
|
6
|
+
export const VisibleEntitiesTitles = {
|
7
|
+
[VISIBLE_ENTITIES.all]: 'All',
|
8
|
+
[VISIBLE_ENTITIES.missing]: 'Degraded',
|
9
|
+
[VISIBLE_ENTITIES.space]: 'Out of Space',
|
10
|
+
};
|
11
|
+
|
12
|
+
interface StorageProblemFilterProps {
|
13
|
+
value: VisibleEntities;
|
14
|
+
onChange: (value: string) => void;
|
15
|
+
}
|
16
|
+
|
17
|
+
export const StorageVisibleEntityFilter = ({value, onChange}: StorageProblemFilterProps) => {
|
18
|
+
return (
|
19
|
+
<RadioButton value={value} onUpdate={onChange}>
|
20
|
+
<RadioButton.Option value={VISIBLE_ENTITIES.missing}>
|
21
|
+
{VisibleEntitiesTitles[VISIBLE_ENTITIES.missing]}
|
22
|
+
</RadioButton.Option>
|
23
|
+
<RadioButton.Option value={VISIBLE_ENTITIES.space}>
|
24
|
+
{VisibleEntitiesTitles[VISIBLE_ENTITIES.space]}
|
25
|
+
</RadioButton.Option>
|
26
|
+
<RadioButton.Option value={VISIBLE_ENTITIES.all}>
|
27
|
+
{VisibleEntitiesTitles[VISIBLE_ENTITIES.all]}
|
28
|
+
</RadioButton.Option>
|
29
|
+
</RadioButton>
|
30
|
+
);
|
31
|
+
};
|
@@ -48,16 +48,9 @@ export const Tablet = () => {
|
|
48
48
|
error,
|
49
49
|
} = useTypedSelector((state) => state.tablet);
|
50
50
|
|
51
|
-
const {
|
52
|
-
nodeId: queryNodeId,
|
53
|
-
type: queryType,
|
54
|
-
state: queryState,
|
55
|
-
tenantName: queryTenantName,
|
56
|
-
} = parseQuery(location);
|
51
|
+
const {nodeId: queryNodeId, tenantName: queryTenantName} = parseQuery(location);
|
57
52
|
|
58
53
|
const nodeId = tablet.NodeId?.toString() || queryNodeId?.toString();
|
59
|
-
const tabletState = tablet.State || queryState?.toString();
|
60
|
-
const tabletType = tablet.Type || queryType?.toString();
|
61
54
|
const tenantName = tenantPath || queryTenantName?.toString();
|
62
55
|
|
63
56
|
// NOTE: should be reviewed when migrating to React 18
|
@@ -84,13 +77,11 @@ export const Tablet = () => {
|
|
84
77
|
dispatch(
|
85
78
|
setHeaderBreadcrumbs('tablet', {
|
86
79
|
nodeIds: nodeId ? [nodeId] : [],
|
87
|
-
state: tabletState,
|
88
|
-
type: tabletType,
|
89
80
|
tenantName,
|
90
81
|
tabletId: id,
|
91
82
|
}),
|
92
83
|
);
|
93
|
-
}, [dispatch, tenantName, id, nodeId
|
84
|
+
}, [dispatch, tenantName, id, nodeId]);
|
94
85
|
|
95
86
|
const renderExternalLinks = (link: {name: string; path: string}, index: number) => {
|
96
87
|
return (
|
@@ -81,10 +81,15 @@ class TabletsFilters extends React.Component {
|
|
81
81
|
});
|
82
82
|
const {nodeIds, type, path, state} = queryParams;
|
83
83
|
const nodes = TabletsFilters.parseNodes(nodeIds);
|
84
|
-
const stateFilter = TabletsFilters.getStateFiltersFromColor(state);
|
85
84
|
|
86
|
-
|
87
|
-
|
85
|
+
if (state) {
|
86
|
+
const stateFilter = TabletsFilters.getStateFiltersFromColor(state);
|
87
|
+
setStateFilter(stateFilter);
|
88
|
+
}
|
89
|
+
|
90
|
+
if (type) {
|
91
|
+
setTypeFilter([type]);
|
92
|
+
}
|
88
93
|
|
89
94
|
this.setState({nodeFilter: nodes, tenantPath: path}, () => {
|
90
95
|
this.makeRequest();
|