ydb-embedded-ui 4.4.2 → 4.5.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.
Files changed (36) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dist/components/ContentWithPopup/ContentWithPopup.tsx +51 -0
  3. package/dist/components/ExternalLinkWithIcon/ExternalLinkWithIcon.scss +7 -0
  4. package/dist/components/ExternalLinkWithIcon/ExternalLinkWithIcon.tsx +24 -0
  5. package/dist/components/NodeHostWrapper/NodeHostWrapper.tsx +2 -2
  6. package/dist/components/PoolBar/PoolBar.scss +6 -1
  7. package/dist/components/PoolBar/PoolBar.tsx +39 -0
  8. package/dist/components/PoolsGraph/PoolsGraph.scss +1 -1
  9. package/dist/components/PoolsGraph/PoolsGraph.tsx +23 -0
  10. package/dist/components/Tablet/Tablet.scss +4 -1
  11. package/dist/components/Tablet/Tablet.tsx +11 -35
  12. package/dist/components/{Tooltips/NodeEndpointsTooltip/NodeEndpointsTooltip.scss → TooltipsContent/NodeEndpointsTooltipContent/NodeEndpointsTooltipContent.scss} +1 -1
  13. package/dist/components/{Tooltips/NodeEndpointsTooltip/NodeEndpointsTooltip.tsx → TooltipsContent/NodeEndpointsTooltipContent/NodeEndpointsTooltipContent.tsx} +3 -3
  14. package/dist/components/TooltipsContent/PoolTooltipContent/PoolTooltipContent.tsx +24 -0
  15. package/dist/components/TooltipsContent/TabletTooltipContent/TabletTooltipContent.tsx +34 -0
  16. package/dist/components/TooltipsContent/index.ts +3 -0
  17. package/dist/containers/Cluster/Cluster.tsx +14 -10
  18. package/dist/containers/{ClusterInfo → Cluster/ClusterInfo}/ClusterInfo.scss +8 -40
  19. package/dist/containers/Cluster/ClusterInfo/ClusterInfo.tsx +223 -0
  20. package/dist/containers/{ClusterInfo → Cluster/ClusterInfo}/utils.ts +1 -1
  21. package/dist/containers/Cluster/VersionsBar/VersionsBar.scss +27 -0
  22. package/dist/containers/Cluster/VersionsBar/VersionsBar.tsx +33 -0
  23. package/dist/containers/Header/Header.tsx +3 -6
  24. package/dist/containers/Nodes/Nodes.tsx +0 -11
  25. package/dist/containers/Nodes/getNodesColumns.tsx +3 -20
  26. package/dist/containers/Tablets/Tablets.tsx +1 -17
  27. package/dist/containers/TabletsFilters/TabletsFilters.js +2 -14
  28. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.js +2 -12
  29. package/dist/containers/Tenants/Tenants.js +3 -17
  30. package/dist/containers/Versions/NodesTable/NodesTable.tsx +4 -34
  31. package/dist/types/additionalProps.ts +11 -0
  32. package/dist/utils/tooltip.js +8 -80
  33. package/package.json +1 -1
  34. package/dist/components/PoolBar/PoolBar.js +0 -52
  35. package/dist/components/PoolsGraph/PoolsGraph.js +0 -33
  36. package/dist/containers/ClusterInfo/ClusterInfo.tsx +0 -207
@@ -0,0 +1,223 @@
1
+ import {useCallback, useEffect, useMemo} from 'react';
2
+ import {useDispatch} from 'react-redux';
3
+ import {useLocation} from 'react-router';
4
+ import block from 'bem-cn-lite';
5
+ import qs from 'qs';
6
+
7
+ import EntityStatus from '../../../components/EntityStatus/EntityStatus';
8
+ import ProgressViewer from '../../../components/ProgressViewer/ProgressViewer';
9
+ import InfoViewer, {InfoViewerItem} from '../../../components/InfoViewer/InfoViewer';
10
+ import {Tags} from '../../../components/Tags';
11
+ import {Tablet} from '../../../components/Tablet';
12
+ import {Loader} from '../../../components/Loader';
13
+ import {ResponseError} from '../../../components/Errors/ResponseError';
14
+ import {ExternalLinkWithIcon} from '../../../components/ExternalLinkWithIcon/ExternalLinkWithIcon';
15
+
16
+ import type {
17
+ AdditionalClusterProps,
18
+ AdditionalVersionsProps,
19
+ ClusterLink,
20
+ } from '../../../types/additionalProps';
21
+ import type {VersionValue} from '../../../types/versions';
22
+ import type {TClusterInfo} from '../../../types/api/cluster';
23
+ import {getClusterNodes} from '../../../store/reducers/clusterNodes/clusterNodes';
24
+ import {getClusterInfo} from '../../../store/reducers/cluster/cluster';
25
+ import {backend, customBackend} from '../../../store';
26
+ import {setHeader} from '../../../store/reducers/header';
27
+ import {formatStorageValues} from '../../../utils';
28
+ import {useAutofetcher, useTypedSelector} from '../../../utils/hooks';
29
+ import {
30
+ parseVersionsToVersionToColorMap,
31
+ parseNodesToVersionsValues,
32
+ } from '../../../utils/versions';
33
+ import routes, {CLUSTER_PAGES, createHref} from '../../../routes';
34
+
35
+ import {Versions} from '../../Versions/Versions';
36
+ import {VersionsBar} from '../VersionsBar/VersionsBar';
37
+
38
+ import {compareTablets} from './utils';
39
+
40
+ import './ClusterInfo.scss';
41
+
42
+ const b = block('cluster-info');
43
+
44
+ const getInfo = (
45
+ cluster: TClusterInfo,
46
+ versionsValues: VersionValue[],
47
+ additionalInfo: InfoViewerItem[],
48
+ links: ClusterLink[],
49
+ ) => {
50
+ const info: InfoViewerItem[] = [];
51
+
52
+ if (cluster.DataCenters) {
53
+ info.push({
54
+ label: 'DC',
55
+ value: <Tags tags={cluster.DataCenters} />,
56
+ });
57
+ }
58
+
59
+ if (cluster.SystemTablets) {
60
+ info.push({
61
+ label: 'Tablets',
62
+ value: (
63
+ <div className={b('system-tablets')}>
64
+ {cluster.SystemTablets.sort(compareTablets).map((tablet, tabletIndex) => (
65
+ <Tablet key={tabletIndex} tablet={tablet} />
66
+ ))}
67
+ </div>
68
+ ),
69
+ });
70
+ }
71
+
72
+ info.push(
73
+ {
74
+ label: 'Nodes',
75
+ value: (
76
+ <ProgressViewer
77
+ className={b('metric-field')}
78
+ value={cluster?.NodesAlive}
79
+ capacity={cluster?.NodesTotal}
80
+ />
81
+ ),
82
+ },
83
+ {
84
+ label: 'Load',
85
+ value: (
86
+ <ProgressViewer
87
+ className={b('metric-field')}
88
+ value={cluster?.LoadAverage}
89
+ capacity={cluster?.NumberOfCpus}
90
+ />
91
+ ),
92
+ },
93
+ {
94
+ label: 'Storage',
95
+ value: (
96
+ <ProgressViewer
97
+ className={b('metric-field')}
98
+ value={cluster?.StorageUsed}
99
+ capacity={cluster?.StorageTotal}
100
+ formatValues={formatStorageValues}
101
+ />
102
+ ),
103
+ },
104
+ ...additionalInfo,
105
+ {
106
+ label: 'Links',
107
+ value: (
108
+ <div className={b('links')}>
109
+ {links.map(({title, url}) => (
110
+ <ExternalLinkWithIcon key={title} title={title} url={url} />
111
+ ))}
112
+ </div>
113
+ ),
114
+ },
115
+ {
116
+ label: 'Versions',
117
+ value: <VersionsBar versionsValues={versionsValues} />,
118
+ },
119
+ );
120
+
121
+ return info;
122
+ };
123
+
124
+ interface ClusterInfoProps {
125
+ clusterTitle?: string;
126
+ additionalClusterProps?: AdditionalClusterProps;
127
+ additionalVersionsProps?: AdditionalVersionsProps;
128
+ }
129
+
130
+ export const ClusterInfo = ({
131
+ clusterTitle,
132
+ additionalClusterProps = {},
133
+ additionalVersionsProps = {},
134
+ }: ClusterInfoProps) => {
135
+ const dispatch = useDispatch();
136
+ const location = useLocation();
137
+
138
+ const queryParams = qs.parse(location.search, {
139
+ ignoreQueryPrefix: true,
140
+ });
141
+ const {clusterName} = queryParams;
142
+
143
+ const {
144
+ data: cluster = {},
145
+ loading,
146
+ wasLoaded,
147
+ error,
148
+ } = useTypedSelector((state) => state.cluster);
149
+ const {
150
+ nodes,
151
+ loading: nodesLoading,
152
+ wasLoaded: nodesWasLoaded,
153
+ error: nodesError,
154
+ } = useTypedSelector((state) => state.clusterNodes);
155
+ const singleClusterMode = useTypedSelector((state) => state.singleClusterMode);
156
+
157
+ useEffect(() => {
158
+ dispatch(
159
+ setHeader([
160
+ {
161
+ text: CLUSTER_PAGES.cluster.title,
162
+ link: createHref(routes.cluster, {activeTab: CLUSTER_PAGES.cluster.id}),
163
+ },
164
+ ]),
165
+ );
166
+ }, [dispatch]);
167
+
168
+ const fetchData = useCallback(() => {
169
+ dispatch(getClusterInfo(clusterName ? String(clusterName) : undefined));
170
+ dispatch(getClusterNodes());
171
+ }, [dispatch, clusterName]);
172
+
173
+ useAutofetcher(fetchData, [fetchData], true);
174
+
175
+ const versionToColor = useMemo(() => {
176
+ if (additionalVersionsProps?.getVersionToColorMap) {
177
+ return additionalVersionsProps.getVersionToColorMap();
178
+ }
179
+ return parseVersionsToVersionToColorMap(cluster.Versions);
180
+ }, [additionalVersionsProps, cluster]);
181
+
182
+ const versionsValues = useMemo(() => {
183
+ return parseNodesToVersionsValues(nodes, versionToColor);
184
+ }, [nodes, versionToColor]);
185
+
186
+ if ((loading && !wasLoaded) || (nodesLoading && !nodesWasLoaded)) {
187
+ return <Loader size="l" />;
188
+ }
189
+
190
+ if (error || nodesError) {
191
+ return <ResponseError error={error || nodesError} />;
192
+ }
193
+
194
+ let internalLink = backend + '/internal';
195
+
196
+ if (singleClusterMode && !customBackend) {
197
+ internalLink = `/internal`;
198
+ }
199
+
200
+ const {info = [], links = []} = additionalClusterProps;
201
+
202
+ const clusterInfo = getInfo(cluster, versionsValues, info, [
203
+ {title: 'Internal Viewer', url: internalLink},
204
+ ...links,
205
+ ]);
206
+
207
+ return (
208
+ <div className={b()}>
209
+ <div className={b('header')}>
210
+ <div className={b('title')}>
211
+ <EntityStatus
212
+ size="m"
213
+ status={cluster.Overall}
214
+ name={clusterTitle ?? cluster.Name ?? 'Unknown cluster'}
215
+ />
216
+ </div>
217
+ <InfoViewer dots={true} info={clusterInfo} />
218
+ </div>
219
+
220
+ <Versions nodes={nodes} versionToColor={versionToColor} />
221
+ </div>
222
+ );
223
+ };
@@ -1,4 +1,4 @@
1
- import {TTabletStateInfo, EType} from '../../types/api/tablet';
1
+ import {TTabletStateInfo, EType} from '../../../types/api/tablet';
2
2
 
3
3
  export const compareTablets = (tablet1: TTabletStateInfo, tablet2: TTabletStateInfo) => {
4
4
  if (tablet1.Type === EType.TxAllocator) {
@@ -0,0 +1,27 @@
1
+ .ydb-cluster-versions-bar {
2
+ display: flex;
3
+ flex-direction: column;
4
+
5
+ width: 600px;
6
+
7
+ & .yc-progress {
8
+ width: 100%;
9
+ }
10
+
11
+ &__versions {
12
+ display: flex;
13
+ flex-flow: row wrap;
14
+
15
+ margin-top: 6px;
16
+ }
17
+
18
+ &__version-title {
19
+ margin-left: 3px;
20
+
21
+ white-space: nowrap;
22
+ }
23
+
24
+ & .yc-progress__stack {
25
+ cursor: pointer;
26
+ }
27
+ }
@@ -0,0 +1,33 @@
1
+ import block from 'bem-cn-lite';
2
+
3
+ import {Progress} from '@gravity-ui/uikit';
4
+
5
+ import type {VersionValue} from '../../../types/versions';
6
+
7
+ import './VersionsBar.scss';
8
+
9
+ const b = block('ydb-cluster-versions-bar');
10
+
11
+ interface VersionsBarProps {
12
+ versionsValues?: VersionValue[];
13
+ }
14
+
15
+ export const VersionsBar = ({versionsValues = []}: VersionsBarProps) => {
16
+ return (
17
+ <div className={b()}>
18
+ <Progress value={100} stack={versionsValues} view="thin" />
19
+ <div className={b('versions')}>
20
+ {versionsValues.map((item, index) => (
21
+ <div
22
+ className={b('version-title')}
23
+ style={{color: item.color}}
24
+ key={item.version}
25
+ title={item.version}
26
+ >
27
+ {`${item.version}${index === versionsValues.length - 1 ? '' : ','}`}
28
+ </div>
29
+ ))}
30
+ </div>
31
+ </div>
32
+ );
33
+ };
@@ -2,10 +2,10 @@ import React, {useEffect} from 'react';
2
2
  import {useDispatch} from 'react-redux';
3
3
  import cn from 'bem-cn-lite';
4
4
  import {useHistory} from 'react-router';
5
- import {Breadcrumbs, BreadcrumbsItem, Link} from '@gravity-ui/uikit';
5
+ import {Breadcrumbs, BreadcrumbsItem} from '@gravity-ui/uikit';
6
6
 
7
7
  import Divider from '../../components/Divider/Divider';
8
- import {Icon} from '../../components/Icon';
8
+ import {ExternalLinkWithIcon} from '../../components/ExternalLinkWithIcon/ExternalLinkWithIcon';
9
9
 
10
10
  import {backend, customBackend} from '../../store';
11
11
  import {getHostInfo} from '../../store/reducers/host';
@@ -72,10 +72,7 @@ function Header({clusterName}: HeaderProps) {
72
72
  </div>
73
73
 
74
74
  <div className={b('cluster-name-wrapper')}>
75
- <Link href={link} target="_blank">
76
- Internal viewer{' '}
77
- <Icon name="external" viewBox={'0 0 16 16'} width={16} height={16} />
78
- </Link>
75
+ <ExternalLinkWithIcon title={'Internal Viewer'} url={link} />
79
76
  {clusterNameFinal && (
80
77
  <React.Fragment>
81
78
  <div className={b('divider')}>
@@ -31,7 +31,6 @@ import {
31
31
  getComputeNodes,
32
32
  } from '../../store/reducers/nodes';
33
33
  import {changeFilter, ProblemFilterValues} from '../../store/reducers/settings/settings';
34
- import {hideTooltip, showTooltip} from '../../store/reducers/tooltip';
35
34
 
36
35
  import {isDatabaseEntityType} from '../Tenant/utils/schema';
37
36
 
@@ -129,18 +128,8 @@ export const Nodes = ({path, type, className, additionalNodesInfo = {}}: NodesPr
129
128
  );
130
129
  };
131
130
 
132
- const onShowTooltip = (...args: Parameters<typeof showTooltip>) => {
133
- dispatch(showTooltip(...args));
134
- };
135
-
136
- const onHideTooltip = () => {
137
- dispatch(hideTooltip());
138
- };
139
-
140
131
  const renderTable = () => {
141
132
  const columns = getNodesColumns({
142
- showTooltip: onShowTooltip,
143
- hideTooltip: onHideTooltip,
144
133
  getNodeRef: additionalNodesInfo.getNodeRef,
145
134
  });
146
135
 
@@ -1,7 +1,7 @@
1
1
  import DataTable, {Column} from '@gravity-ui/react-data-table';
2
2
  import {Popover} from '@gravity-ui/uikit';
3
3
 
4
- import PoolsGraph from '../../components/PoolsGraph/PoolsGraph';
4
+ import {PoolsGraph} from '../../components/PoolsGraph/PoolsGraph';
5
5
  import ProgressViewer from '../../components/ProgressViewer/ProgressViewer';
6
6
  import {TabletsStatistic} from '../../components/TabletsStatistic';
7
7
  import {NodeHostWrapper} from '../../components/NodeHostWrapper/NodeHostWrapper';
@@ -10,21 +10,13 @@ import type {NodeAddress} from '../../utils/nodes';
10
10
  import {formatBytesToGigabyte} from '../../utils/index';
11
11
 
12
12
  import type {INodesPreparedEntity} from '../../types/store/nodes';
13
- import {showTooltip as externalShowTooltip} from '../../store/reducers/tooltip';
14
13
 
15
14
  interface GetNodesColumnsProps {
16
- showTooltip: (...args: Parameters<typeof externalShowTooltip>) => void;
17
- hideTooltip: VoidFunction;
18
15
  tabletsPath?: string;
19
16
  getNodeRef?: (node?: NodeAddress) => string;
20
17
  }
21
18
 
22
- export function getNodesColumns({
23
- showTooltip,
24
- hideTooltip,
25
- tabletsPath,
26
- getNodeRef,
27
- }: GetNodesColumnsProps) {
19
+ export function getNodesColumns({tabletsPath, getNodeRef}: GetNodesColumnsProps) {
28
20
  const columns: Column<INodesPreparedEntity>[] = [
29
21
  {
30
22
  name: 'NodeId',
@@ -96,16 +88,7 @@ export function getNodesColumns({
96
88
  }
97
89
  }, 0),
98
90
  defaultOrder: DataTable.DESCENDING,
99
- render: ({row}) =>
100
- row.PoolStats ? (
101
- <PoolsGraph
102
- onMouseEnter={showTooltip}
103
- onMouseLeave={hideTooltip}
104
- pools={row.PoolStats}
105
- />
106
- ) : (
107
- '—'
108
- ),
91
+ render: ({row}) => (row.PoolStats ? <PoolsGraph pools={row.PoolStats} /> : '—'),
109
92
  align: DataTable.LEFT,
110
93
  width: '120px',
111
94
  },
@@ -12,7 +12,6 @@ import {Loader} from '../../components/Loader';
12
12
  import {useAutofetcher, useTypedSelector} from '../../utils/hooks';
13
13
  import {ETabletState, EType, TTabletStateInfo} from '../../types/api/tablet';
14
14
 
15
- import {showTooltip, hideTooltip} from '../../store/reducers/tooltip';
16
15
  import {
17
16
  getTabletsInfo,
18
17
  clearWasLoadingFlag,
@@ -89,23 +88,8 @@ export const Tablets = ({path, nodeId, className}: TabletsProps) => {
89
88
  dispatch(setTypeFilter(value as EType[]));
90
89
  };
91
90
 
92
- const onShowTooltip = (...args: Parameters<typeof showTooltip>) => {
93
- dispatch(showTooltip(...args));
94
- };
95
-
96
- const onHideTooltip = () => {
97
- dispatch(hideTooltip());
98
- };
99
-
100
91
  const renderTablet = (tabletIndex: number) => {
101
- return (
102
- <Tablet
103
- onMouseLeave={onHideTooltip}
104
- onMouseEnter={onShowTooltip}
105
- tablet={tabletsToRender[tabletIndex]}
106
- key={tabletIndex}
107
- />
108
- );
92
+ return <Tablet tablet={tabletsToRender[tabletIndex]} key={tabletIndex} />;
109
93
  };
110
94
 
111
95
  const renderContent = () => {
@@ -12,7 +12,6 @@ import {Tablet} from '../../components/Tablet';
12
12
  import {AccessDenied} from '../../components/Errors/403';
13
13
 
14
14
  import {tabletColorToTabletState, tabletStates} from '../../utils/tablet';
15
- import {showTooltip, hideTooltip} from '../../store/reducers/tooltip';
16
15
  import {
17
16
  getTabletsInfo,
18
17
  clearWasLoadingFlag,
@@ -30,8 +29,6 @@ class TabletsFilters extends React.Component {
30
29
  static propTypes = {
31
30
  wasLoaded: PropTypes.bool,
32
31
  loading: PropTypes.bool,
33
- showTooltip: PropTypes.func,
34
- hideTooltip: PropTypes.func,
35
32
  getTabletsInfo: PropTypes.func,
36
33
  timeoutForRequest: PropTypes.number,
37
34
  path: PropTypes.string,
@@ -141,17 +138,10 @@ class TabletsFilters extends React.Component {
141
138
  };
142
139
 
143
140
  renderTablet = (index, key) => {
144
- const {filteredTablets, hideTooltip, showTooltip, size} = this.props;
141
+ const {filteredTablets, size} = this.props;
145
142
 
146
143
  return (
147
- <Tablet
148
- onMouseLeave={hideTooltip}
149
- onMouseEnter={showTooltip}
150
- tablet={filteredTablets[index]}
151
- key={key}
152
- size={size}
153
- className={b('tablet')}
154
- />
144
+ <Tablet tablet={filteredTablets[index]} key={key} size={size} className={b('tablet')} />
155
145
  );
156
146
  };
157
147
 
@@ -333,8 +323,6 @@ const mapStateToProps = (state) => {
333
323
 
334
324
  const mapDispatchToProps = {
335
325
  getTabletsInfo,
336
- hideTooltip,
337
- showTooltip,
338
326
  clearWasLoadingFlag,
339
327
  setStateFilter,
340
328
  setTypeFilter,
@@ -9,7 +9,6 @@ import InfoViewer from '../../../../components/InfoViewer/InfoViewer';
9
9
  import PoolUsage from '../../../../components/PoolUsage/PoolUsage';
10
10
  import {Tablet} from '../../../../components/Tablet';
11
11
 
12
- import {hideTooltip, showTooltip} from '../../../../store/reducers/tooltip';
13
12
  import {getTenantInfo} from '../../../../store/reducers/tenant';
14
13
 
15
14
  import {formatCPU} from '../../../../utils';
@@ -44,8 +43,6 @@ class TenantOverview extends React.Component {
44
43
  loading: PropTypes.bool,
45
44
  autorefresh: PropTypes.bool,
46
45
  tenant: PropTypes.object,
47
- hideTooltip: PropTypes.func,
48
- showTooltip: PropTypes.func,
49
46
  systemTablets: PropTypes.array,
50
47
  additionalTenantInfo: PropTypes.func,
51
48
  tenantName: PropTypes.string,
@@ -102,7 +99,7 @@ class TenantOverview extends React.Component {
102
99
  };
103
100
 
104
101
  render() {
105
- const {tenant, hideTooltip, showTooltip, loading} = this.props;
102
+ const {tenant, loading} = this.props;
106
103
  const {
107
104
  Metrics = {},
108
105
  PoolStats,
@@ -162,12 +159,7 @@ class TenantOverview extends React.Component {
162
159
  <div className={b('system-tablets')}>
163
160
  {SystemTablets &&
164
161
  SystemTablets.map((tablet, tabletIndex) => (
165
- <Tablet
166
- onMouseEnter={showTooltip}
167
- onMouseLeave={hideTooltip}
168
- key={tabletIndex}
169
- tablet={tablet}
170
- />
162
+ <Tablet key={tabletIndex} tablet={tablet} />
171
163
  ))}
172
164
  </div>
173
165
  <div className={b('common-info')}>
@@ -211,8 +203,6 @@ function mapStateToProps(state) {
211
203
  }
212
204
 
213
205
  const mapDispatchToProps = {
214
- hideTooltip,
215
- showTooltip,
216
206
  getTenantInfo,
217
207
  };
218
208
 
@@ -9,7 +9,7 @@ import DataTable from '@gravity-ui/react-data-table';
9
9
  import {Loader, TextInput, Button} from '@gravity-ui/uikit';
10
10
 
11
11
  import EntityStatus from '../../components/EntityStatus/EntityStatus';
12
- import PoolsGraph from '../../components/PoolsGraph/PoolsGraph';
12
+ import {PoolsGraph} from '../../components/PoolsGraph/PoolsGraph';
13
13
  import {TabletsStatistic} from '../../components/TabletsStatistic';
14
14
  import {ProblemFilter} from '../../components/ProblemFilter';
15
15
  import {Illustration} from '../../components/Illustration';
@@ -17,7 +17,6 @@ import {AutoFetcher} from '../../utils/autofetcher';
17
17
 
18
18
  import routes, {CLUSTER_PAGES, createHref} from '../../routes';
19
19
  import {formatCPU, formatBytesToGigabyte, formatNumber} from '../../utils';
20
- import {hideTooltip, showTooltip} from '../../store/reducers/tooltip';
21
20
  import {withSearch} from '../../HOCS';
22
21
  import {DEFAULT_TABLE_SETTINGS, TENANT_INITIAL_TAB_KEY} from '../../utils/constants';
23
22
  import {getTenantsInfo} from '../../store/reducers/tenants/tenants';
@@ -50,8 +49,6 @@ class Tenants extends React.Component {
50
49
  error: PropTypes.bool,
51
50
  getTenantsInfo: PropTypes.func,
52
51
  tenants: PropTypes.array,
53
- showTooltip: PropTypes.func,
54
- hideTooltip: PropTypes.func,
55
52
  searchQuery: PropTypes.string,
56
53
  handleSearchQuery: PropTypes.func,
57
54
  setHeader: PropTypes.func,
@@ -121,8 +118,6 @@ class Tenants extends React.Component {
121
118
  const {
122
119
  tenants = [],
123
120
  searchQuery,
124
- showTooltip,
125
- hideTooltip,
126
121
  filter,
127
122
  handleSearchQuery,
128
123
  additionalTenantsInfo = {},
@@ -291,15 +286,8 @@ class Tenants extends React.Component {
291
286
  sortAccessor: ({PoolStats = []}) =>
292
287
  PoolStats.reduce((acc, item) => acc + item.Usage, 0),
293
288
  defaultOrder: DataTable.DESCENDING,
294
- align: DataTable.CENTER,
295
- render: ({value}) => (
296
- <PoolsGraph
297
- onMouseEnter={showTooltip}
298
- onMouseLeave={hideTooltip}
299
- rowInfo={value}
300
- pools={value}
301
- />
302
- ),
289
+ align: DataTable.LEFT,
290
+ render: ({value}) => <PoolsGraph rowInfo={value} pools={value} />,
303
291
  },
304
292
  {
305
293
  name: 'Tablets',
@@ -374,8 +362,6 @@ const mapStateToProps = (state) => {
374
362
 
375
363
  const mapDispatchToProps = {
376
364
  getTenantsInfo,
377
- hideTooltip,
378
- showTooltip,
379
365
  changeFilter,
380
366
  setHeader,
381
367
  };
@@ -1,26 +1,15 @@
1
- import {useDispatch} from 'react-redux';
2
-
3
1
  import DataTable, {Column} from '@gravity-ui/react-data-table';
4
2
 
5
3
  import type {PreparedClusterNode} from '../../../store/reducers/clusterNodes/types';
6
- import type {ShowTooltipFunction} from '../../../types/store/tooltip';
7
-
8
- import {hideTooltip, showTooltip} from '../../../store/reducers/tooltip';
9
4
  import {isUnavailableNode} from '../../../utils/nodes';
10
5
  import {formatBytes} from '../../../utils';
11
6
  import {getDefaultNodePath} from '../../Node/NodePages';
12
7
 
13
8
  import ProgressViewer from '../../../components/ProgressViewer/ProgressViewer';
14
- import PoolsGraph from '../../../components/PoolsGraph/PoolsGraph';
9
+ import {PoolsGraph} from '../../../components/PoolsGraph/PoolsGraph';
15
10
  import EntityStatus from '../../../components/EntityStatus/EntityStatus';
16
11
 
17
- const getColumns = ({
18
- onShowTooltip,
19
- onHideTooltip,
20
- }: {
21
- onShowTooltip: (...args: Parameters<ShowTooltipFunction>) => void;
22
- onHideTooltip: VoidFunction;
23
- }): Column<PreparedClusterNode>[] => [
12
+ const columns: Column<PreparedClusterNode>[] = [
24
13
  {
25
14
  name: 'NodeId',
26
15
  header: '#',
@@ -89,16 +78,7 @@ const getColumns = ({
89
78
  PoolStats.reduce((acc, item) => acc + (item.Usage || 0), 0),
90
79
  defaultOrder: DataTable.DESCENDING,
91
80
  width: '120px',
92
- render: ({row}) =>
93
- row.PoolStats ? (
94
- <PoolsGraph
95
- onMouseEnter={onShowTooltip}
96
- onMouseLeave={onHideTooltip}
97
- pools={row.PoolStats}
98
- />
99
- ) : (
100
- '—'
101
- ),
81
+ render: ({row}) => (row.PoolStats ? <PoolsGraph pools={row.PoolStats} /> : '—'),
102
82
  align: DataTable.LEFT,
103
83
  },
104
84
  {
@@ -127,21 +107,11 @@ interface NodesTableProps {
127
107
  }
128
108
 
129
109
  export const NodesTable = ({nodes}: NodesTableProps) => {
130
- const dispatch = useDispatch();
131
-
132
- const onShowTooltip = (...args: Parameters<ShowTooltipFunction>) => {
133
- dispatch(showTooltip(...args));
134
- };
135
-
136
- const onHideTooltip = () => {
137
- dispatch(hideTooltip());
138
- };
139
-
140
110
  return (
141
111
  <DataTable
142
112
  theme="yandex-cloud"
143
113
  data={nodes}
144
- columns={getColumns({onShowTooltip, onHideTooltip})}
114
+ columns={columns}
145
115
  settings={{
146
116
  displayIndices: false,
147
117
  }}
@@ -1,5 +1,16 @@
1
+ import type {InfoViewerItem} from '../components/InfoViewer';
1
2
  import type {VersionToColorMap} from './versions';
2
3
 
3
4
  export interface AdditionalVersionsProps {
4
5
  getVersionToColorMap?: () => VersionToColorMap;
5
6
  }
7
+
8
+ export interface ClusterLink {
9
+ title: string;
10
+ url: string;
11
+ }
12
+
13
+ export interface AdditionalClusterProps {
14
+ info?: InfoViewerItem[];
15
+ links?: ClusterLink[];
16
+ }