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.
- package/CHANGELOG.md +7 -0
- package/dist/components/ContentWithPopup/ContentWithPopup.tsx +51 -0
- package/dist/components/ExternalLinkWithIcon/ExternalLinkWithIcon.scss +7 -0
- package/dist/components/ExternalLinkWithIcon/ExternalLinkWithIcon.tsx +24 -0
- package/dist/components/NodeHostWrapper/NodeHostWrapper.tsx +2 -2
- package/dist/components/PoolBar/PoolBar.scss +6 -1
- package/dist/components/PoolBar/PoolBar.tsx +39 -0
- package/dist/components/PoolsGraph/PoolsGraph.scss +1 -1
- package/dist/components/PoolsGraph/PoolsGraph.tsx +23 -0
- package/dist/components/Tablet/Tablet.scss +4 -1
- package/dist/components/Tablet/Tablet.tsx +11 -35
- package/dist/components/{Tooltips/NodeEndpointsTooltip/NodeEndpointsTooltip.scss → TooltipsContent/NodeEndpointsTooltipContent/NodeEndpointsTooltipContent.scss} +1 -1
- package/dist/components/{Tooltips/NodeEndpointsTooltip/NodeEndpointsTooltip.tsx → TooltipsContent/NodeEndpointsTooltipContent/NodeEndpointsTooltipContent.tsx} +3 -3
- package/dist/components/TooltipsContent/PoolTooltipContent/PoolTooltipContent.tsx +24 -0
- package/dist/components/TooltipsContent/TabletTooltipContent/TabletTooltipContent.tsx +34 -0
- package/dist/components/TooltipsContent/index.ts +3 -0
- package/dist/containers/Cluster/Cluster.tsx +14 -10
- package/dist/containers/{ClusterInfo → Cluster/ClusterInfo}/ClusterInfo.scss +8 -40
- package/dist/containers/Cluster/ClusterInfo/ClusterInfo.tsx +223 -0
- package/dist/containers/{ClusterInfo → Cluster/ClusterInfo}/utils.ts +1 -1
- package/dist/containers/Cluster/VersionsBar/VersionsBar.scss +27 -0
- package/dist/containers/Cluster/VersionsBar/VersionsBar.tsx +33 -0
- package/dist/containers/Header/Header.tsx +3 -6
- package/dist/containers/Nodes/Nodes.tsx +0 -11
- package/dist/containers/Nodes/getNodesColumns.tsx +3 -20
- package/dist/containers/Tablets/Tablets.tsx +1 -17
- package/dist/containers/TabletsFilters/TabletsFilters.js +2 -14
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.js +2 -12
- package/dist/containers/Tenants/Tenants.js +3 -17
- package/dist/containers/Versions/NodesTable/NodesTable.tsx +4 -34
- package/dist/types/additionalProps.ts +11 -0
- package/dist/utils/tooltip.js +8 -80
- package/package.json +1 -1
- package/dist/components/PoolBar/PoolBar.js +0 -52
- package/dist/components/PoolsGraph/PoolsGraph.js +0 -33
- 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
|
+
};
|
@@ -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
|
5
|
+
import {Breadcrumbs, BreadcrumbsItem} from '@gravity-ui/uikit';
|
6
6
|
|
7
7
|
import Divider from '../../components/Divider/Divider';
|
8
|
-
import {
|
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
|
-
<
|
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,
|
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,
|
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.
|
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
|
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={
|
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
|
+
}
|