ydb-embedded-ui 4.27.0 → 4.28.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/components/EmptyState/EmptyState.scss +5 -2
  3. package/dist/components/EmptyState/EmptyState.tsx +11 -3
  4. package/dist/components/Errors/403/AccessDenied.tsx +4 -3
  5. package/dist/components/ProblemFilter/ProblemFilter.tsx +1 -1
  6. package/dist/components/UptimeFIlter/UptimeFilter.tsx +1 -1
  7. package/dist/components/VirtualTable/VirtualTable.scss +1 -1
  8. package/dist/containers/Cluster/Cluster.tsx +11 -12
  9. package/dist/containers/Nodes/Nodes.tsx +4 -4
  10. package/dist/containers/Nodes/NodesWrapper.tsx +21 -0
  11. package/dist/containers/Nodes/VirtualNodes.tsx +4 -14
  12. package/dist/containers/Storage/DiskStateProgressBar/DiskStateProgressBar.scss +1 -0
  13. package/dist/containers/Storage/EmptyFilter/EmptyFilter.tsx +1 -0
  14. package/dist/containers/Storage/PDisk/PDisk.tsx +5 -7
  15. package/dist/containers/Storage/Storage.tsx +30 -67
  16. package/dist/containers/Storage/StorageControls/StorageControls.tsx +104 -0
  17. package/dist/containers/Storage/StorageGroups/StorageGroups.tsx +18 -62
  18. package/dist/containers/Storage/StorageGroups/StorageGroupsEmptyDataMessage.tsx +30 -0
  19. package/dist/containers/Storage/StorageGroups/VirtualStorageGroups.tsx +94 -0
  20. package/dist/containers/Storage/StorageGroups/getGroups.ts +21 -0
  21. package/dist/containers/Storage/StorageGroups/getStorageGroupsColumns.tsx +73 -50
  22. package/dist/containers/Storage/StorageNodes/StorageNodes.tsx +23 -138
  23. package/dist/containers/Storage/StorageNodes/StorageNodesEmptyDataMessage.tsx +44 -0
  24. package/dist/containers/Storage/StorageNodes/VirtualStorageNodes.tsx +105 -0
  25. package/dist/containers/Storage/StorageNodes/getNodes.ts +26 -0
  26. package/dist/containers/Storage/StorageNodes/getStorageNodesColumns.tsx +125 -0
  27. package/dist/containers/Storage/StorageNodes/shared.ts +9 -0
  28. package/dist/containers/Storage/StorageTypeFilter/StorageTypeFilter.tsx +1 -1
  29. package/dist/containers/Storage/StorageVisibleEntitiesFilter/StorageVisibleEntitiesFilter.tsx +1 -1
  30. package/dist/containers/Storage/StorageWrapper.tsx +23 -0
  31. package/dist/containers/Storage/UsageFilter/UsageFilter.tsx +3 -4
  32. package/dist/containers/Storage/VirtualStorage.tsx +112 -0
  33. package/dist/containers/Storage/i18n/en.json +7 -0
  34. package/dist/containers/Storage/i18n/index.ts +11 -0
  35. package/dist/containers/Storage/i18n/ru.json +7 -0
  36. package/dist/containers/Storage/shared.ts +3 -0
  37. package/dist/containers/Tenants/Tenants.tsx +2 -2
  38. package/dist/containers/UserSettings/i18n/en.json +2 -2
  39. package/dist/containers/UserSettings/i18n/ru.json +2 -2
  40. package/dist/containers/UserSettings/settings.ts +4 -4
  41. package/dist/services/settings.ts +7 -11
  42. package/dist/store/reducers/settings/settings.ts +16 -3
  43. package/dist/store/reducers/settings/types.ts +5 -2
  44. package/dist/store/reducers/storage/selectors.ts +0 -20
  45. package/package.json +6 -6
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
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
+
10
+ ## [4.27.1](https://github.com/ydb-platform/ydb-embedded-ui/compare/v4.27.0...v4.27.1) (2024-01-10)
11
+
12
+
13
+ ### Bug Fixes
14
+
15
+ * enable extract and set user settings manually ([#629](https://github.com/ydb-platform/ydb-embedded-ui/issues/629)) ([5eecd58](https://github.com/ydb-platform/ydb-embedded-ui/commit/5eecd58249688b4a8b3ecad766564f7b404e839c))
16
+
3
17
  ## [4.27.0](https://github.com/ydb-platform/ydb-embedded-ui/compare/v4.26.0...v4.27.0) (2023-12-28)
4
18
 
5
19
 
@@ -19,10 +19,13 @@
19
19
  }
20
20
 
21
21
  &_size_m {
22
- position: relative;
23
-
24
22
  width: 800px;
25
23
  height: 240px;
24
+ }
25
+
26
+ &_position_center {
27
+ position: relative;
28
+
26
29
  margin: 0 auto;
27
30
  }
28
31
  }
@@ -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 = ({image, title, description, actions, size = 'm'}: EmptyStateProps) => {
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
  };
@@ -5,7 +5,7 @@ import {ProblemFilterValues} from '../../store/reducers/settings/settings';
5
5
 
6
6
  interface ProblemFilterProps {
7
7
  value: ProblemFilterValue;
8
- onChange: (value: string) => void;
8
+ onChange: (value: ProblemFilterValue) => void;
9
9
  className?: string;
10
10
  }
11
11
 
@@ -4,7 +4,7 @@ import {NodesUptimeFilterValues, NodesUptimeFilterTitles} from '../../utils/node
4
4
 
5
5
  interface UptimeFilterProps {
6
6
  value: NodesUptimeFilterValues;
7
- onChange: (value: string) => void;
7
+ onChange: (value: NodesUptimeFilterValues) => void;
8
8
  className?: string;
9
9
  }
10
10
 
@@ -15,7 +15,7 @@
15
15
  @include body-2-typography();
16
16
 
17
17
  &__table {
18
- width: 100%;
18
+ width: max-content;
19
19
  max-width: 100%;
20
20
 
21
21
  table-layout: fixed;
@@ -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, useSetting, useTypedSelector} from '../../utils/hooks';
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 {Nodes} from '../Nodes/Nodes';
27
- import {VirtualNodes} from '../Nodes/VirtualNodes';
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 useVirtualNodes ? (
115
- <VirtualNodes
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 <Storage additionalNodesProps={additionalNodesProps} />;
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: string) => {
110
- dispatch(changeFilter(value as ProblemFilterValue));
109
+ const handleProblemFilterChange = (value: ProblemFilterValue) => {
110
+ dispatch(changeFilter(value));
111
111
  };
112
112
 
113
- const handleUptimeFilterChange = (value: string) => {
114
- dispatch(setNodesUptimeFilter(value as NodesUptimeFilterValues));
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={handleSearchQueryChange}
79
+ onChange={setSearchValue}
90
80
  placeholder="Host name"
91
81
  className={b('search')}
92
82
  value={searchValue}
93
83
  />
94
- <ProblemFilter value={problemFilter} onChange={handleProblemFilterChange} />
95
- <UptimeFilter value={uptimeFilter} onChange={handleUptimeFilterChange} />
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} />;
@@ -6,6 +6,7 @@
6
6
  $inner-border-radius: $outer-border-radius - $border-width;
7
7
 
8
8
  position: relative;
9
+ z-index: 0;
9
10
 
10
11
  display: block;
11
12
 
@@ -20,6 +20,7 @@ export const EmptyFilter = ({
20
20
  }: EmptyFilterProps) => (
21
21
  <EmptyState
22
22
  image={<Illustration name="thumbsUp" />}
23
+ position="left"
23
24
  title={title}
24
25
  description={message}
25
26
  actions={
@@ -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 (!vdisks?.length) {
101
+ if (!vDisks?.length) {
104
102
  return null;
105
103
  }
106
104
 
107
105
  return (
108
106
  <div className={b('vdisks')}>
109
- {vdisks.map((vdisk) => {
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 {StorageTypeFilter} from './StorageTypeFilter/StorageTypeFilter';
55
- import {StorageVisibleEntitiesFilter} from './StorageVisibleEntitiesFilter/StorageVisibleEntitiesFilter';
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: string) => {
159
- dispatch(setVisibleEntities(value as VisibleEntities));
151
+ const handleGroupVisibilityChange = (value: VisibleEntities) => {
152
+ dispatch(setVisibleEntities(value));
160
153
  };
161
154
 
162
- const handleStorageTypeChange = (value: string) => {
163
- dispatch(setStorageType(value as StorageType));
155
+ const handleStorageTypeChange = (value: StorageType) => {
156
+ dispatch(setStorageType(value));
164
157
  };
165
158
 
166
- const handleUptimeFilterChange = (value: string) => {
167
- dispatch(setNodesUptimeFilter(value as NodesUptimeFilterValues));
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
- <div className={b('search')}>
224
- <Search
225
- placeholder={
226
- storageType === STORAGE_TYPES.groups
227
- ? 'Group ID, Pool name'
228
- : 'Node ID, FQDN'
229
- }
230
- onChange={handleTextFilterChange}
231
- value={filter}
232
- />
233
- </div>
234
-
235
- {!isNodePage && (
236
- <StorageTypeFilter value={storageType} onChange={handleStorageTypeChange} />
237
- )}
238
-
239
- <StorageVisibleEntitiesFilter
240
- value={visibleEntities}
241
- onChange={handleGroupVisibilityChange}
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
+ };