ydb-embedded-ui 4.27.1 → 4.28.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 +7 -0
- package/dist/components/EmptyState/EmptyState.scss +5 -2
- package/dist/components/EmptyState/EmptyState.tsx +11 -3
- package/dist/components/Errors/403/AccessDenied.tsx +4 -3
- package/dist/components/ProblemFilter/ProblemFilter.tsx +1 -1
- package/dist/components/UptimeFIlter/UptimeFilter.tsx +1 -1
- package/dist/components/VirtualTable/VirtualTable.scss +1 -1
- package/dist/containers/Cluster/Cluster.tsx +11 -12
- package/dist/containers/Nodes/Nodes.tsx +4 -4
- package/dist/containers/Nodes/NodesWrapper.tsx +21 -0
- package/dist/containers/Nodes/VirtualNodes.tsx +4 -14
- package/dist/containers/Storage/DiskStateProgressBar/DiskStateProgressBar.scss +1 -0
- package/dist/containers/Storage/EmptyFilter/EmptyFilter.tsx +1 -0
- package/dist/containers/Storage/PDisk/PDisk.tsx +5 -7
- package/dist/containers/Storage/Storage.tsx +30 -67
- package/dist/containers/Storage/StorageControls/StorageControls.tsx +104 -0
- package/dist/containers/Storage/StorageGroups/StorageGroups.tsx +18 -62
- package/dist/containers/Storage/StorageGroups/StorageGroupsEmptyDataMessage.tsx +30 -0
- package/dist/containers/Storage/StorageGroups/VirtualStorageGroups.tsx +94 -0
- package/dist/containers/Storage/StorageGroups/getGroups.ts +21 -0
- package/dist/containers/Storage/StorageGroups/getStorageGroupsColumns.tsx +73 -50
- package/dist/containers/Storage/StorageNodes/StorageNodes.tsx +23 -138
- package/dist/containers/Storage/StorageNodes/StorageNodesEmptyDataMessage.tsx +44 -0
- package/dist/containers/Storage/StorageNodes/VirtualStorageNodes.tsx +105 -0
- package/dist/containers/Storage/StorageNodes/getNodes.ts +26 -0
- package/dist/containers/Storage/StorageNodes/getStorageNodesColumns.tsx +125 -0
- package/dist/containers/Storage/StorageNodes/shared.ts +9 -0
- package/dist/containers/Storage/StorageTypeFilter/StorageTypeFilter.tsx +1 -1
- package/dist/containers/Storage/StorageVisibleEntitiesFilter/StorageVisibleEntitiesFilter.tsx +1 -1
- package/dist/containers/Storage/StorageWrapper.tsx +23 -0
- package/dist/containers/Storage/UsageFilter/UsageFilter.tsx +3 -4
- package/dist/containers/Storage/VirtualStorage.tsx +112 -0
- package/dist/containers/Storage/i18n/en.json +7 -0
- package/dist/containers/Storage/i18n/index.ts +11 -0
- package/dist/containers/Storage/i18n/ru.json +7 -0
- package/dist/containers/Storage/shared.ts +3 -0
- package/dist/containers/Tenants/Tenants.tsx +2 -2
- package/dist/containers/UserSettings/i18n/en.json +2 -2
- package/dist/containers/UserSettings/i18n/ru.json +2 -2
- package/dist/containers/UserSettings/settings.ts +4 -4
- package/dist/store/reducers/storage/selectors.ts +0 -20
- package/package.json +6 -6
package/CHANGELOG.md
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [4.28.0](https://github.com/ydb-platform/ydb-embedded-ui/compare/v4.27.1...v4.28.0) (2024-01-10)
|
4
|
+
|
5
|
+
|
6
|
+
### Features
|
7
|
+
|
8
|
+
* **Storage:** use VirtualTable ([#628](https://github.com/ydb-platform/ydb-embedded-ui/issues/628)) ([67fd9b0](https://github.com/ydb-platform/ydb-embedded-ui/commit/67fd9b03653dd28be650094c987451b09fcce858))
|
9
|
+
|
3
10
|
## [4.27.1](https://github.com/ydb-platform/ydb-embedded-ui/compare/v4.27.0...v4.27.1) (2024-01-10)
|
4
11
|
|
5
12
|
|
@@ -13,18 +13,26 @@ const sizes = {
|
|
13
13
|
l: 350,
|
14
14
|
};
|
15
15
|
|
16
|
-
interface EmptyStateProps {
|
16
|
+
export interface EmptyStateProps {
|
17
17
|
title: string;
|
18
18
|
image?: ReactNode;
|
19
19
|
description?: ReactNode;
|
20
20
|
actions?: ReactNode[];
|
21
21
|
size?: keyof typeof sizes;
|
22
|
+
position?: 'left' | 'center';
|
22
23
|
}
|
23
24
|
|
24
|
-
export const EmptyState = ({
|
25
|
+
export const EmptyState = ({
|
26
|
+
image,
|
27
|
+
title,
|
28
|
+
description,
|
29
|
+
actions,
|
30
|
+
size = 'm',
|
31
|
+
position = 'center',
|
32
|
+
}: EmptyStateProps) => {
|
25
33
|
return (
|
26
34
|
<div className={block({size})}>
|
27
|
-
<div className={block('wrapper', {size})}>
|
35
|
+
<div className={block('wrapper', {size, position})}>
|
28
36
|
<div className={block('image')}>
|
29
37
|
{image ? (
|
30
38
|
image
|
@@ -1,19 +1,20 @@
|
|
1
|
-
import {EmptyState} from '../../EmptyState';
|
1
|
+
import {EmptyState, type EmptyStateProps} from '../../EmptyState';
|
2
2
|
import {Illustration} from '../../Illustration';
|
3
3
|
|
4
4
|
import i18n from '../i18n';
|
5
5
|
|
6
|
-
interface AccessDeniedProps {
|
6
|
+
interface AccessDeniedProps extends Omit<EmptyStateProps, 'image' | 'title' | 'description'> {
|
7
7
|
title?: string;
|
8
8
|
description?: string;
|
9
9
|
}
|
10
10
|
|
11
|
-
export const AccessDenied = ({title, description}: AccessDeniedProps) => {
|
11
|
+
export const AccessDenied = ({title, description, ...restProps}: AccessDeniedProps) => {
|
12
12
|
return (
|
13
13
|
<EmptyState
|
14
14
|
image={<Illustration name="403" />}
|
15
15
|
title={title || i18n('403.title')}
|
16
16
|
description={description || i18n('403.description')}
|
17
|
+
{...restProps}
|
17
18
|
/>
|
18
19
|
);
|
19
20
|
};
|
@@ -4,7 +4,7 @@ import {NodesUptimeFilterValues, NodesUptimeFilterTitles} from '../../utils/node
|
|
4
4
|
|
5
5
|
interface UptimeFilterProps {
|
6
6
|
value: NodesUptimeFilterValues;
|
7
|
-
onChange: (value:
|
7
|
+
onChange: (value: NodesUptimeFilterValues) => void;
|
8
8
|
className?: string;
|
9
9
|
}
|
10
10
|
|
@@ -18,14 +18,12 @@ import {setHeaderBreadcrumbs} from '../../store/reducers/header/header';
|
|
18
18
|
import {getClusterInfo} from '../../store/reducers/cluster/cluster';
|
19
19
|
import {getClusterNodes} from '../../store/reducers/clusterNodes/clusterNodes';
|
20
20
|
import {parseNodesToVersionsValues, parseVersionsToVersionToColorMap} from '../../utils/versions';
|
21
|
-
import {useAutofetcher,
|
22
|
-
import {USE_BACKEND_PARAMS_FOR_TABLES_KEY} from '../../utils/constants';
|
21
|
+
import {useAutofetcher, useTypedSelector} from '../../utils/hooks';
|
23
22
|
|
24
23
|
import {InternalLink} from '../../components/InternalLink';
|
25
24
|
import {Tenants} from '../Tenants/Tenants';
|
26
|
-
import {
|
27
|
-
import {
|
28
|
-
import {Storage} from '../Storage/Storage';
|
25
|
+
import {StorageWrapper} from '../Storage/StorageWrapper';
|
26
|
+
import {NodesWrapper} from '../Nodes/NodesWrapper';
|
29
27
|
import {Versions} from '../Versions/Versions';
|
30
28
|
|
31
29
|
import {ClusterInfo} from './ClusterInfo/ClusterInfo';
|
@@ -55,8 +53,6 @@ function Cluster({
|
|
55
53
|
const match = useRouteMatch<{activeTab: string}>(routes.cluster);
|
56
54
|
const {activeTab = clusterTabsIds.tenants} = match?.params || {};
|
57
55
|
|
58
|
-
const [useVirtualNodes] = useSetting<boolean>(USE_BACKEND_PARAMS_FOR_TABLES_KEY);
|
59
|
-
|
60
56
|
const location = useLocation();
|
61
57
|
const queryParams = qs.parse(location.search, {
|
62
58
|
ignoreQueryPrefix: true,
|
@@ -111,17 +107,20 @@ function Cluster({
|
|
111
107
|
return <Tenants additionalTenantsProps={additionalTenantsProps} />;
|
112
108
|
}
|
113
109
|
case clusterTabsIds.nodes: {
|
114
|
-
return
|
115
|
-
<
|
110
|
+
return (
|
111
|
+
<NodesWrapper
|
116
112
|
parentContainer={container.current}
|
117
113
|
additionalNodesProps={additionalNodesProps}
|
118
114
|
/>
|
119
|
-
) : (
|
120
|
-
<Nodes additionalNodesProps={additionalNodesProps} />
|
121
115
|
);
|
122
116
|
}
|
123
117
|
case clusterTabsIds.storage: {
|
124
|
-
return
|
118
|
+
return (
|
119
|
+
<StorageWrapper
|
120
|
+
parentContainer={container.current}
|
121
|
+
additionalNodesProps={additionalNodesProps}
|
122
|
+
/>
|
123
|
+
);
|
125
124
|
}
|
126
125
|
case clusterTabsIds.versions: {
|
127
126
|
return <Versions versionToColor={versionToColor} />;
|
@@ -106,12 +106,12 @@ export const Nodes = ({path, additionalNodesProps = {}}: NodesProps) => {
|
|
106
106
|
dispatch(setSearchValue(value));
|
107
107
|
};
|
108
108
|
|
109
|
-
const handleProblemFilterChange = (value:
|
110
|
-
dispatch(changeFilter(value
|
109
|
+
const handleProblemFilterChange = (value: ProblemFilterValue) => {
|
110
|
+
dispatch(changeFilter(value));
|
111
111
|
};
|
112
112
|
|
113
|
-
const handleUptimeFilterChange = (value:
|
114
|
-
dispatch(setNodesUptimeFilter(value
|
113
|
+
const handleUptimeFilterChange = (value: NodesUptimeFilterValues) => {
|
114
|
+
dispatch(setNodesUptimeFilter(value));
|
115
115
|
};
|
116
116
|
|
117
117
|
const renderControls = () => {
|
@@ -0,0 +1,21 @@
|
|
1
|
+
import type {AdditionalNodesProps} from '../../types/additionalProps';
|
2
|
+
import {USE_BACKEND_PARAMS_FOR_TABLES_KEY} from '../../utils/constants';
|
3
|
+
import {useSetting} from '../../utils/hooks';
|
4
|
+
|
5
|
+
import {VirtualNodes} from './VirtualNodes';
|
6
|
+
import {Nodes} from './Nodes';
|
7
|
+
|
8
|
+
interface NodesWrapperProps {
|
9
|
+
parentContainer?: Element | null;
|
10
|
+
additionalNodesProps?: AdditionalNodesProps;
|
11
|
+
}
|
12
|
+
|
13
|
+
export const NodesWrapper = ({parentContainer, ...props}: NodesWrapperProps) => {
|
14
|
+
const [useVirtualTable] = useSetting<boolean>(USE_BACKEND_PARAMS_FOR_TABLES_KEY);
|
15
|
+
|
16
|
+
if (useVirtualTable) {
|
17
|
+
return <VirtualNodes parentContainer={parentContainer} {...props} />;
|
18
|
+
}
|
19
|
+
|
20
|
+
return <Nodes {...props} />;
|
21
|
+
};
|
@@ -72,27 +72,17 @@ export const VirtualNodes = ({parentContainer, additionalNodesProps}: NodesProps
|
|
72
72
|
return b('node', {unavailable: isUnavailableNode(row)});
|
73
73
|
};
|
74
74
|
|
75
|
-
const handleSearchQueryChange = (value: string) => {
|
76
|
-
setSearchValue(value);
|
77
|
-
};
|
78
|
-
const handleProblemFilterChange = (value: string) => {
|
79
|
-
setProblemFilter(value as ProblemFilterValue);
|
80
|
-
};
|
81
|
-
const handleUptimeFilterChange = (value: string) => {
|
82
|
-
setUptimeFilter(value as NodesUptimeFilterValues);
|
83
|
-
};
|
84
|
-
|
85
75
|
const renderControls: RenderControls = ({totalEntities, foundEntities, inited}) => {
|
86
76
|
return (
|
87
77
|
<>
|
88
78
|
<Search
|
89
|
-
onChange={
|
79
|
+
onChange={setSearchValue}
|
90
80
|
placeholder="Host name"
|
91
81
|
className={b('search')}
|
92
82
|
value={searchValue}
|
93
83
|
/>
|
94
|
-
<ProblemFilter value={problemFilter} onChange={
|
95
|
-
<UptimeFilter value={uptimeFilter} onChange={
|
84
|
+
<ProblemFilter value={problemFilter} onChange={setProblemFilter} />
|
85
|
+
<UptimeFilter value={uptimeFilter} onChange={setUptimeFilter} />
|
96
86
|
<EntitiesCount
|
97
87
|
total={totalEntities}
|
98
88
|
current={foundEntities}
|
@@ -116,7 +106,7 @@ export const VirtualNodes = ({parentContainer, additionalNodesProps}: NodesProps
|
|
116
106
|
|
117
107
|
const renderErrorMessage: RenderErrorMessage = (error) => {
|
118
108
|
if (error && error.status === 403) {
|
119
|
-
return <AccessDenied />;
|
109
|
+
return <AccessDenied position="left" />;
|
120
110
|
}
|
121
111
|
|
122
112
|
return <ResponseError error={error} />;
|
@@ -1,14 +1,13 @@
|
|
1
1
|
import React, {useEffect, useState, useRef, useMemo} from 'react';
|
2
2
|
import cn from 'bem-cn-lite';
|
3
3
|
|
4
|
+
import type {TVDiskStateInfo} from '../../../types/api/vdisk';
|
4
5
|
import {InternalLink} from '../../../components/InternalLink';
|
5
6
|
import {Stack} from '../../../components/Stack/Stack';
|
6
7
|
|
7
8
|
import routes, {createHref} from '../../../routes';
|
8
|
-
import {selectVDisksForPDisk} from '../../../store/reducers/storage/selectors';
|
9
9
|
import {TPDiskStateInfo, TPDiskState} from '../../../types/api/pdisk';
|
10
10
|
import {stringifyVdiskId} from '../../../utils/dataFormatters/dataFormatters';
|
11
|
-
import {useTypedSelector} from '../../../utils/hooks';
|
12
11
|
import {getPDiskType} from '../../../utils/pdisk';
|
13
12
|
import {isFullVDiskData} from '../../../utils/storage';
|
14
13
|
|
@@ -44,6 +43,7 @@ const stateSeverity = {
|
|
44
43
|
interface PDiskProps {
|
45
44
|
nodeId: number;
|
46
45
|
data?: TPDiskStateInfo;
|
46
|
+
vDisks?: TVDiskStateInfo[];
|
47
47
|
}
|
48
48
|
|
49
49
|
const isSeverityKey = (key?: TPDiskState): key is keyof typeof stateSeverity =>
|
@@ -53,12 +53,10 @@ const getStateSeverity = (pDiskState?: TPDiskState) => {
|
|
53
53
|
return isSeverityKey(pDiskState) ? stateSeverity[pDiskState] : NOT_AVAILABLE_SEVERITY;
|
54
54
|
};
|
55
55
|
|
56
|
-
export const PDisk = ({nodeId, data: rawData = {}}: PDiskProps) => {
|
56
|
+
export const PDisk = ({nodeId, data: rawData = {}, vDisks}: PDiskProps) => {
|
57
57
|
// NodeId in data is required for the popup
|
58
58
|
const data = useMemo(() => ({...rawData, NodeId: nodeId}), [rawData, nodeId]);
|
59
59
|
|
60
|
-
const vdisks = useTypedSelector((state) => selectVDisksForPDisk(state, nodeId, data.PDiskId));
|
61
|
-
|
62
60
|
const [severity, setSeverity] = useState(getStateSeverity(data.State));
|
63
61
|
const [isPopupVisible, setIsPopupVisible] = useState(false);
|
64
62
|
|
@@ -100,13 +98,13 @@ export const PDisk = ({nodeId, data: rawData = {}}: PDiskProps) => {
|
|
100
98
|
};
|
101
99
|
|
102
100
|
const renderVDisks = () => {
|
103
|
-
if (!
|
101
|
+
if (!vDisks?.length) {
|
104
102
|
return null;
|
105
103
|
}
|
106
104
|
|
107
105
|
return (
|
108
106
|
<div className={b('vdisks')}>
|
109
|
-
{
|
107
|
+
{vDisks.map((vdisk) => {
|
110
108
|
const donors = vdisk.Donors;
|
111
109
|
|
112
110
|
return (
|
@@ -1,11 +1,7 @@
|
|
1
1
|
import {useCallback, useEffect} from 'react';
|
2
2
|
import {useDispatch} from 'react-redux';
|
3
|
-
import cn from 'bem-cn-lite';
|
4
3
|
|
5
|
-
import {Search} from '../../components/Search';
|
6
|
-
import {UptimeFilter} from '../../components/UptimeFIlter';
|
7
4
|
import {AccessDenied} from '../../components/Errors/403';
|
8
|
-
import {EntitiesCount} from '../../components/EntitiesCount';
|
9
5
|
import {TableWithControlsLayout} from '../../components/TableWithControlsLayout/TableWithControlsLayout';
|
10
6
|
import {ResponseError} from '../../components/Errors/ResponseError';
|
11
7
|
|
@@ -51,14 +47,11 @@ import {DEFAULT_TABLE_SETTINGS} from '../../utils/constants';
|
|
51
47
|
|
52
48
|
import {StorageGroups} from './StorageGroups/StorageGroups';
|
53
49
|
import {StorageNodes} from './StorageNodes/StorageNodes';
|
54
|
-
import {
|
55
|
-
import {
|
56
|
-
import {UsageFilter} from './UsageFilter';
|
50
|
+
import {StorageControls} from './StorageControls/StorageControls';
|
51
|
+
import {b} from './shared';
|
57
52
|
|
58
53
|
import './Storage.scss';
|
59
54
|
|
60
|
-
const b = cn('global-storage');
|
61
|
-
|
62
55
|
interface StorageProps {
|
63
56
|
additionalNodesProps?: AdditionalNodesProps;
|
64
57
|
tenant?: string;
|
@@ -155,16 +148,16 @@ export const Storage = ({additionalNodesProps, tenant, nodeId}: StorageProps) =>
|
|
155
148
|
dispatch(setStorageTextFilter(value));
|
156
149
|
};
|
157
150
|
|
158
|
-
const handleGroupVisibilityChange = (value:
|
159
|
-
dispatch(setVisibleEntities(value
|
151
|
+
const handleGroupVisibilityChange = (value: VisibleEntities) => {
|
152
|
+
dispatch(setVisibleEntities(value));
|
160
153
|
};
|
161
154
|
|
162
|
-
const handleStorageTypeChange = (value:
|
163
|
-
dispatch(setStorageType(value
|
155
|
+
const handleStorageTypeChange = (value: StorageType) => {
|
156
|
+
dispatch(setStorageType(value));
|
164
157
|
};
|
165
158
|
|
166
|
-
const handleUptimeFilterChange = (value:
|
167
|
-
dispatch(setNodesUptimeFilter(value
|
159
|
+
const handleUptimeFilterChange = (value: NodesUptimeFilterValues) => {
|
160
|
+
dispatch(setNodesUptimeFilter(value));
|
168
161
|
};
|
169
162
|
|
170
163
|
const handleShowAllNodes = () => {
|
@@ -202,65 +195,35 @@ export const Storage = ({additionalNodesProps, tenant, nodeId}: StorageProps) =>
|
|
202
195
|
);
|
203
196
|
};
|
204
197
|
|
205
|
-
const renderEntitiesCount = () => {
|
206
|
-
const entityName = storageType === STORAGE_TYPES.groups ? 'Groups' : 'Nodes';
|
207
|
-
const current =
|
208
|
-
storageType === STORAGE_TYPES.groups ? storageGroups.length : storageNodes.length;
|
209
|
-
|
210
|
-
return (
|
211
|
-
<EntitiesCount
|
212
|
-
label={entityName}
|
213
|
-
loading={loading && !wasLoaded}
|
214
|
-
total={entitiesCount.total}
|
215
|
-
current={current}
|
216
|
-
/>
|
217
|
-
);
|
218
|
-
};
|
219
|
-
|
220
198
|
const renderControls = () => {
|
221
199
|
return (
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
{
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
{storageType === STORAGE_TYPES.nodes && (
|
245
|
-
<UptimeFilter value={nodesUptimeFilter} onChange={handleUptimeFilterChange} />
|
246
|
-
)}
|
247
|
-
|
248
|
-
{storageType === STORAGE_TYPES.groups && (
|
249
|
-
<UsageFilter
|
250
|
-
value={usageFilter}
|
251
|
-
onChange={handleUsageFilterChange}
|
252
|
-
groups={usageFilterOptions}
|
253
|
-
disabled={usageFilterOptions.length === 0}
|
254
|
-
/>
|
255
|
-
)}
|
256
|
-
{renderEntitiesCount()}
|
257
|
-
</>
|
200
|
+
<StorageControls
|
201
|
+
searchValue={filter}
|
202
|
+
handleSearchValueChange={handleTextFilterChange}
|
203
|
+
withTypeSelector={!isNodePage}
|
204
|
+
storageType={storageType}
|
205
|
+
handleStorageTypeChange={handleStorageTypeChange}
|
206
|
+
visibleEntities={visibleEntities}
|
207
|
+
handleVisibleEntitiesChange={handleGroupVisibilityChange}
|
208
|
+
nodesUptimeFilter={nodesUptimeFilter}
|
209
|
+
handleNodesUptimeFilterChange={handleUptimeFilterChange}
|
210
|
+
groupsUsageFilter={usageFilter}
|
211
|
+
groupsUsageFilterOptions={usageFilterOptions}
|
212
|
+
handleGroupsUsageFilterChange={handleUsageFilterChange}
|
213
|
+
entitiesCountCurrent={
|
214
|
+
storageType === STORAGE_TYPES.groups
|
215
|
+
? storageGroups.length
|
216
|
+
: storageNodes.length
|
217
|
+
}
|
218
|
+
entitiesCountTotal={entitiesCount.total}
|
219
|
+
entitiesLoading={loading && !wasLoaded}
|
220
|
+
/>
|
258
221
|
);
|
259
222
|
};
|
260
223
|
|
261
224
|
if (error) {
|
262
225
|
if (error.status === 403) {
|
263
|
-
return <AccessDenied />;
|
226
|
+
return <AccessDenied position="left" />;
|
264
227
|
}
|
265
228
|
|
266
229
|
return <ResponseError error={error} />;
|
@@ -0,0 +1,104 @@
|
|
1
|
+
import {EntitiesCount} from '../../../components/EntitiesCount/EntitiesCount';
|
2
|
+
import {Search} from '../../../components/Search/Search';
|
3
|
+
import {UptimeFilter} from '../../../components/UptimeFIlter';
|
4
|
+
|
5
|
+
import type {StorageType, VisibleEntities} from '../../../store/reducers/storage/types';
|
6
|
+
import {STORAGE_TYPES} from '../../../store/reducers/storage/constants';
|
7
|
+
import {NodesUptimeFilterValues} from '../../../utils/nodes';
|
8
|
+
|
9
|
+
import {UsageFilter, type UsageFilterItem} from '../UsageFilter/UsageFilter';
|
10
|
+
import {StorageTypeFilter} from '../StorageTypeFilter/StorageTypeFilter';
|
11
|
+
import {StorageVisibleEntitiesFilter} from '../StorageVisibleEntitiesFilter/StorageVisibleEntitiesFilter';
|
12
|
+
import i18n from '../i18n';
|
13
|
+
import {b} from '../shared';
|
14
|
+
|
15
|
+
interface StorageControlsProps {
|
16
|
+
searchValue?: string;
|
17
|
+
handleSearchValueChange: (value: string) => void;
|
18
|
+
|
19
|
+
withTypeSelector?: boolean;
|
20
|
+
storageType: StorageType;
|
21
|
+
handleStorageTypeChange: (value: StorageType) => void;
|
22
|
+
|
23
|
+
visibleEntities: VisibleEntities;
|
24
|
+
handleVisibleEntitiesChange: (value: VisibleEntities) => void;
|
25
|
+
|
26
|
+
nodesUptimeFilter: NodesUptimeFilterValues;
|
27
|
+
handleNodesUptimeFilterChange: (value: NodesUptimeFilterValues) => void;
|
28
|
+
|
29
|
+
withGroupsUsageFilter?: boolean;
|
30
|
+
groupsUsageFilter?: string[];
|
31
|
+
groupsUsageFilterOptions?: UsageFilterItem[];
|
32
|
+
handleGroupsUsageFilterChange?: (value: string[]) => void;
|
33
|
+
|
34
|
+
entitiesCountCurrent: number;
|
35
|
+
entitiesCountTotal?: number;
|
36
|
+
entitiesLoading: boolean;
|
37
|
+
}
|
38
|
+
|
39
|
+
export const StorageControls = ({
|
40
|
+
searchValue,
|
41
|
+
handleSearchValueChange,
|
42
|
+
|
43
|
+
withTypeSelector,
|
44
|
+
storageType,
|
45
|
+
handleStorageTypeChange,
|
46
|
+
|
47
|
+
visibleEntities,
|
48
|
+
handleVisibleEntitiesChange,
|
49
|
+
|
50
|
+
nodesUptimeFilter,
|
51
|
+
handleNodesUptimeFilterChange,
|
52
|
+
|
53
|
+
withGroupsUsageFilter,
|
54
|
+
groupsUsageFilter,
|
55
|
+
groupsUsageFilterOptions,
|
56
|
+
handleGroupsUsageFilterChange,
|
57
|
+
|
58
|
+
entitiesCountCurrent,
|
59
|
+
entitiesCountTotal,
|
60
|
+
entitiesLoading,
|
61
|
+
}: StorageControlsProps) => {
|
62
|
+
const isNodes = storageType === STORAGE_TYPES.nodes;
|
63
|
+
const entityName = isNodes ? i18n('nodes') : i18n('groups');
|
64
|
+
|
65
|
+
return (
|
66
|
+
<>
|
67
|
+
<Search
|
68
|
+
value={searchValue}
|
69
|
+
onChange={handleSearchValueChange}
|
70
|
+
placeholder={
|
71
|
+
isNodes
|
72
|
+
? i18n('controls_nodes-search-placeholder')
|
73
|
+
: i18n('controls_groups-search-placeholder')
|
74
|
+
}
|
75
|
+
className={b('search')}
|
76
|
+
/>
|
77
|
+
{withTypeSelector && (
|
78
|
+
<StorageTypeFilter value={storageType} onChange={handleStorageTypeChange} />
|
79
|
+
)}
|
80
|
+
<StorageVisibleEntitiesFilter
|
81
|
+
value={visibleEntities}
|
82
|
+
onChange={handleVisibleEntitiesChange}
|
83
|
+
/>
|
84
|
+
|
85
|
+
{isNodes && (
|
86
|
+
<UptimeFilter value={nodesUptimeFilter} onChange={handleNodesUptimeFilterChange} />
|
87
|
+
)}
|
88
|
+
{!isNodes && withGroupsUsageFilter && (
|
89
|
+
<UsageFilter
|
90
|
+
value={groupsUsageFilter}
|
91
|
+
onChange={handleGroupsUsageFilterChange}
|
92
|
+
groups={groupsUsageFilterOptions}
|
93
|
+
/>
|
94
|
+
)}
|
95
|
+
|
96
|
+
<EntitiesCount
|
97
|
+
label={entityName}
|
98
|
+
loading={entitiesLoading}
|
99
|
+
total={entitiesCountTotal}
|
100
|
+
current={entitiesCountCurrent}
|
101
|
+
/>
|
102
|
+
</>
|
103
|
+
);
|
104
|
+
};
|