ydb-embedded-ui 4.5.1 → 4.6.0
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +20 -0
- package/dist/components/FullNodeViewer/FullNodeViewer.js +1 -1
- package/dist/components/NodeHostWrapper/NodeHostWrapper.tsx +1 -1
- package/dist/components/PoolUsage/PoolUsage.scss +1 -1
- package/dist/components/PoolUsage/PoolUsage.tsx +50 -0
- package/dist/containers/App/Content.js +3 -2
- package/dist/containers/AsideNavigation/AsideNavigation.tsx +4 -50
- package/dist/containers/Cluster/Cluster.scss +7 -48
- package/dist/containers/Cluster/Cluster.tsx +136 -20
- package/dist/containers/Cluster/ClusterInfo/ClusterInfo.scss +34 -17
- package/dist/containers/Cluster/ClusterInfo/ClusterInfo.tsx +57 -91
- package/dist/containers/Cluster/ClusterInfoSkeleton/ClusterInfoSkeleton.scss +48 -0
- package/dist/containers/Cluster/ClusterInfoSkeleton/ClusterInfoSkeleton.tsx +34 -0
- package/dist/containers/Cluster/utils.ts +34 -0
- package/dist/containers/Header/Header.scss +0 -24
- package/dist/containers/Header/Header.tsx +14 -44
- package/dist/containers/Node/Node.tsx +23 -21
- package/dist/containers/Node/NodeStructure/NodeStructure.tsx +19 -17
- package/dist/containers/Nodes/Nodes.tsx +0 -16
- package/dist/containers/Nodes/getNodesColumns.tsx +1 -1
- package/dist/containers/Storage/Storage.js +1 -11
- package/dist/containers/Tablet/Tablet.tsx +28 -0
- package/dist/containers/TabletsFilters/TabletsFilters.js +16 -1
- package/dist/containers/Tenant/Diagnostics/Describe/Describe.tsx +1 -1
- package/dist/containers/Tenant/Diagnostics/DetailedOverview/DetailedOverview.scss +3 -0
- package/dist/containers/Tenant/Diagnostics/Diagnostics.tsx +3 -3
- package/dist/containers/Tenant/Diagnostics/Network/Network.js +2 -2
- package/dist/containers/Tenant/Diagnostics/Overview/ChangefeedInfo/ChangefeedInfo.tsx +4 -6
- package/dist/containers/Tenant/Diagnostics/Overview/Overview.tsx +56 -53
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.js +1 -1
- package/dist/containers/Tenant/Diagnostics/TopShards/TopShards.tsx +1 -1
- package/dist/containers/Tenant/ObjectSummary/ObjectSummary.tsx +1 -1
- package/dist/containers/Tenant/Preview/Preview.js +1 -1
- package/dist/containers/Tenant/QueryEditor/QueryEditor.js +26 -22
- package/dist/containers/Tenant/QueryEditor/QueryEditorControls/OldQueryEditorControls.tsx +10 -3
- package/dist/containers/Tenant/QueryEditor/QueryEditorControls/QueryEditorControls.tsx +8 -1
- package/dist/containers/Tenant/QueryEditor/QueryEditorControls/shared.ts +1 -6
- package/dist/containers/Tenant/Schema/SchemaTree/SchemaTree.tsx +1 -1
- package/dist/containers/Tenant/Tenant.tsx +8 -13
- package/dist/containers/Tenant/utils/schemaActions.ts +1 -1
- package/dist/containers/Tenants/Tenants.js +18 -28
- package/dist/containers/Tenants/Tenants.scss +2 -4
- 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/containers/Versions/GroupedNodesTree/GroupedNodesTree.scss +1 -0
- package/dist/containers/Versions/NodesTable/NodesTable.tsx +2 -3
- package/dist/containers/Versions/Versions.scss +0 -4
- package/dist/containers/Versions/Versions.tsx +74 -66
- package/dist/routes.ts +0 -7
- package/dist/services/api.ts +8 -4
- package/dist/store/reducers/clusterNodes/clusterNodes.tsx +4 -0
- package/dist/store/reducers/index.ts +6 -4
- package/dist/store/reducers/{network.js → network/network.ts} +11 -8
- package/dist/store/reducers/network/types.ts +16 -0
- package/dist/store/reducers/node/node.ts +102 -0
- package/dist/store/reducers/node/selectors.ts +59 -0
- package/dist/store/reducers/node/types.ts +44 -0
- package/dist/store/reducers/overview/overview.ts +109 -0
- package/dist/store/reducers/overview/types.ts +24 -0
- package/dist/store/reducers/{schema.ts → schema/schema.ts} +24 -50
- package/dist/{types/store/schema.ts → store/reducers/schema/types.ts} +16 -15
- package/dist/store/reducers/{schemaAcl.js → schemaAcl/schemaAcl.ts} +20 -9
- package/dist/store/reducers/schemaAcl/types.ts +15 -0
- package/dist/store/reducers/settings/settings.ts +5 -3
- package/dist/types/api/acl.ts +1 -1
- package/dist/types/api/query.ts +78 -44
- package/dist/types/store/explainQuery.ts +2 -2
- package/dist/types/store/query.ts +4 -2
- package/dist/utils/constants.ts +3 -1
- package/dist/utils/nodes.ts +1 -1
- package/dist/utils/query.ts +3 -3
- package/package.json +1 -1
- package/dist/components/PoolUsage/PoolUsage.js +0 -54
- package/dist/store/reducers/node.js +0 -141
package/CHANGELOG.md
CHANGED
@@ -1,5 +1,25 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [4.6.0](https://github.com/ydb-platform/ydb-embedded-ui/compare/v4.5.2...v4.6.0) (2023-06-13)
|
4
|
+
|
5
|
+
|
6
|
+
### Features
|
7
|
+
|
8
|
+
* **QueryEditor:** add data and query modes ([#422](https://github.com/ydb-platform/ydb-embedded-ui/issues/422)) ([c142f03](https://github.com/ydb-platform/ydb-embedded-ui/commit/c142f03e9caeab4dcf1d34b3988e949a94213932))
|
9
|
+
* rework navigation, update breadcrumbs ([#418](https://github.com/ydb-platform/ydb-embedded-ui/issues/418)) ([2d807d6](https://github.com/ydb-platform/ydb-embedded-ui/commit/2d807d6a52e13edcf2a7e1591672224339d91949))
|
10
|
+
|
11
|
+
|
12
|
+
### Bug Fixes
|
13
|
+
|
14
|
+
* **Diagnostics:** remove unneded tenantInfo fetch ([#420](https://github.com/ydb-platform/ydb-embedded-ui/issues/420)) ([ccaafe4](https://github.com/ydb-platform/ydb-embedded-ui/commit/ccaafe4ec9346ee1ec2ebd2a62600274f2175bfb))
|
15
|
+
|
16
|
+
## [4.5.2](https://github.com/ydb-platform/ydb-embedded-ui/compare/v4.5.1...v4.5.2) (2023-06-06)
|
17
|
+
|
18
|
+
|
19
|
+
### Bug Fixes
|
20
|
+
|
21
|
+
* **Versions:** enable table dynamic render ([#416](https://github.com/ydb-platform/ydb-embedded-ui/issues/416)) ([3c877ea](https://github.com/ydb-platform/ydb-embedded-ui/commit/3c877ea88a0c4036213b38099676f473cf3ac2d6))
|
22
|
+
|
3
23
|
## [4.5.1](https://github.com/ydb-platform/ydb-embedded-ui/compare/v4.5.0...v4.5.1) (2023-06-02)
|
4
24
|
|
5
25
|
|
@@ -4,7 +4,7 @@ import PropTypes from 'prop-types';
|
|
4
4
|
|
5
5
|
import InfoViewer from '../InfoViewer/InfoViewer';
|
6
6
|
import ProgressViewer from '../ProgressViewer/ProgressViewer';
|
7
|
-
import PoolUsage from '../PoolUsage/PoolUsage';
|
7
|
+
import {PoolUsage} from '../PoolUsage/PoolUsage';
|
8
8
|
|
9
9
|
import {LOAD_AVERAGE_TIME_INTERVALS} from '../../utils/constants';
|
10
10
|
import {calcUptime} from '../../utils';
|
@@ -16,7 +16,7 @@ const b = block('ydb-node-host-wrapper');
|
|
16
16
|
|
17
17
|
interface NodeHostWrapperProps {
|
18
18
|
node: INodesPreparedEntity;
|
19
|
-
getNodeRef?: (node?: NodeAddress) => string;
|
19
|
+
getNodeRef?: (node?: NodeAddress) => string | null;
|
20
20
|
}
|
21
21
|
|
22
22
|
export const NodeHostWrapper = ({node, getNodeRef}: NodeHostWrapperProps) => {
|
@@ -0,0 +1,50 @@
|
|
1
|
+
import block from 'bem-cn-lite';
|
2
|
+
|
3
|
+
import type {TPoolStats} from '../../types/api/nodes';
|
4
|
+
|
5
|
+
import './PoolUsage.scss';
|
6
|
+
|
7
|
+
const b = block('ydb-pool-usage');
|
8
|
+
|
9
|
+
const getLineType = (fillWidth: number) => {
|
10
|
+
let fillColor = 'green';
|
11
|
+
if (fillWidth > 60 && fillWidth <= 80) {
|
12
|
+
fillColor = 'yellow';
|
13
|
+
} else if (fillWidth > 80) {
|
14
|
+
fillColor = 'red';
|
15
|
+
}
|
16
|
+
|
17
|
+
return fillColor;
|
18
|
+
};
|
19
|
+
|
20
|
+
interface PoolUsageProps {
|
21
|
+
data?: TPoolStats;
|
22
|
+
}
|
23
|
+
|
24
|
+
export const PoolUsage = ({data: pool = {}}: PoolUsageProps) => {
|
25
|
+
const {Threads, Name = 'Unknown', Usage = 0} = pool;
|
26
|
+
const dataExist = Usage && Threads;
|
27
|
+
|
28
|
+
const value = Math.floor(Usage * 100);
|
29
|
+
const fillWidth = value > 100 ? 100 : value;
|
30
|
+
|
31
|
+
return (
|
32
|
+
<div className={b()}>
|
33
|
+
<div className={b('info')}>
|
34
|
+
<div className={b('pool-name')}>{Name}</div>
|
35
|
+
{dataExist && (
|
36
|
+
<div className={b('value')}>
|
37
|
+
<div className={b('percents')}>{value < 1 ? '<1' : value}%</div>
|
38
|
+
<div className={b('threads')}>(×{Threads})</div>
|
39
|
+
</div>
|
40
|
+
)}
|
41
|
+
</div>
|
42
|
+
<div className={b('visual')}>
|
43
|
+
<div
|
44
|
+
className={b('usage-line', {type: getLineType(fillWidth)})}
|
45
|
+
style={{width: `${fillWidth}%`}}
|
46
|
+
/>
|
47
|
+
</div>
|
48
|
+
</div>
|
49
|
+
);
|
50
|
+
};
|
@@ -5,7 +5,7 @@ import {connect} from 'react-redux';
|
|
5
5
|
|
6
6
|
import {ThemeProvider} from '@gravity-ui/uikit';
|
7
7
|
|
8
|
-
import routes, {createHref
|
8
|
+
import routes, {createHref} from '../../routes';
|
9
9
|
|
10
10
|
import Cluster from '../Cluster/Cluster';
|
11
11
|
import Tenant from '../Tenant/Tenant';
|
@@ -23,6 +23,7 @@ import './App.scss';
|
|
23
23
|
import PropTypes from 'prop-types';
|
24
24
|
import HistoryContext from '../../contexts/HistoryContext';
|
25
25
|
import Authentication from '../Authentication/Authentication';
|
26
|
+
import {clusterTabsIds} from '../Cluster/utils';
|
26
27
|
|
27
28
|
const b = cn('app');
|
28
29
|
|
@@ -44,7 +45,7 @@ export function Content(props) {
|
|
44
45
|
<Route path={routes.tabletsFilters} component={TabletsFilters} />
|
45
46
|
<Redirect
|
46
47
|
to={createHref(routes.cluster, {
|
47
|
-
activeTab:
|
48
|
+
activeTab: clusterTabsIds.tenants,
|
48
49
|
})}
|
49
50
|
/>
|
50
51
|
</Switch>
|
@@ -9,11 +9,7 @@ import {AsideHeader, MenuItem as AsideHeaderMenuItem, FooterItem} from '@gravity
|
|
9
9
|
|
10
10
|
import signOutIcon from '../../assets/icons/signOut.svg';
|
11
11
|
import signInIcon from '../../assets/icons/signIn.svg';
|
12
|
-
import databaseIcon from '../../assets/icons/server.svg';
|
13
|
-
import storageIcon from '../../assets/icons/storage.svg';
|
14
|
-
import clusterIcon from '../../assets/icons/cluster.svg';
|
15
12
|
import ydbLogoIcon from '../../assets/icons/ydb.svg';
|
16
|
-
import databasesIcon from '../../assets/icons/databases.svg';
|
17
13
|
import userSecret from '../../assets/icons/user-secret.svg';
|
18
14
|
import userChecked from '../../assets/icons/user-check.svg';
|
19
15
|
import settingsIcon from '../../assets/icons/settings.svg';
|
@@ -21,7 +17,7 @@ import supportIcon from '../../assets/icons/support.svg';
|
|
21
17
|
|
22
18
|
import {UserSettings} from '../UserSettings/UserSettings';
|
23
19
|
|
24
|
-
import routes, {createHref
|
20
|
+
import routes, {createHref} from '../../routes';
|
25
21
|
|
26
22
|
import {logout} from '../../store/reducers/authentication';
|
27
23
|
import {getParsedSettingValue, setSettingValue} from '../../store/reducers/settings/settings';
|
@@ -115,46 +111,8 @@ interface AsideNavigationProps {
|
|
115
111
|
setSettingValue: (name: string, value: string) => void;
|
116
112
|
}
|
117
113
|
|
118
|
-
|
119
|
-
|
120
|
-
id: CLUSTER_PAGES.tenants.id,
|
121
|
-
title: 'Databases',
|
122
|
-
icon: databasesIcon,
|
123
|
-
iconSize: 20,
|
124
|
-
location: createHref(routes.cluster, {
|
125
|
-
activeTab: CLUSTER_PAGES.tenants.id,
|
126
|
-
}),
|
127
|
-
locationKeys: ['/tenant'],
|
128
|
-
},
|
129
|
-
{
|
130
|
-
id: CLUSTER_PAGES.nodes.id,
|
131
|
-
title: 'Nodes',
|
132
|
-
icon: databaseIcon,
|
133
|
-
iconSize: 20,
|
134
|
-
location: createHref(routes.cluster, {activeTab: CLUSTER_PAGES.nodes.id}),
|
135
|
-
locationKeys: ['/node'],
|
136
|
-
},
|
137
|
-
{
|
138
|
-
id: CLUSTER_PAGES.storage.id,
|
139
|
-
title: 'Storage',
|
140
|
-
icon: storageIcon,
|
141
|
-
iconSize: 20,
|
142
|
-
location: createHref(routes.cluster, {
|
143
|
-
activeTab: CLUSTER_PAGES.storage.id,
|
144
|
-
}),
|
145
|
-
locationKeys: ['/storage'],
|
146
|
-
},
|
147
|
-
{
|
148
|
-
id: CLUSTER_PAGES.cluster.id,
|
149
|
-
title: 'Cluster',
|
150
|
-
icon: clusterIcon,
|
151
|
-
iconSize: 20,
|
152
|
-
location: createHref(routes.cluster, {
|
153
|
-
activeTab: CLUSTER_PAGES.cluster.id,
|
154
|
-
}),
|
155
|
-
locationKeys: ['/cluster/cluster'],
|
156
|
-
},
|
157
|
-
];
|
114
|
+
// FIXME: add items or delete
|
115
|
+
const items: MenuItem[] = [];
|
158
116
|
|
159
117
|
enum Panel {
|
160
118
|
UserSettings = 'UserSettings',
|
@@ -172,17 +130,13 @@ function AsideNavigation(props: AsideNavigationProps) {
|
|
172
130
|
|
173
131
|
const menuItems: AsideHeaderMenuItem[] = React.useMemo(() => {
|
174
132
|
const {pathname} = location;
|
175
|
-
const isClusterPage = pathname === '/cluster';
|
176
133
|
const menuItems: AsideHeaderMenuItem[] = items.map((item) => {
|
177
134
|
const locationKeysCoincidence = item.locationKeys?.filter((key) =>
|
178
135
|
pathname.startsWith(key),
|
179
136
|
);
|
180
|
-
|
137
|
+
const current =
|
181
138
|
(locationKeysCoincidence && locationKeysCoincidence.length > 0) ||
|
182
139
|
item.location.startsWith(pathname);
|
183
|
-
if (isClusterPage && item.id !== CLUSTER_PAGES.tenants.id) {
|
184
|
-
current = false;
|
185
|
-
}
|
186
140
|
return {
|
187
141
|
id: item.id,
|
188
142
|
title: item.title,
|
@@ -2,57 +2,16 @@
|
|
2
2
|
|
3
3
|
.cluster {
|
4
4
|
overflow: auto;
|
5
|
+
flex-grow: 1;
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
&_tab_cluster {
|
10
|
-
padding: 0px;
|
11
|
-
}
|
12
|
-
|
13
|
-
&__tab {
|
14
|
-
text-decoration: none;
|
15
|
-
|
16
|
-
&:first-letter {
|
17
|
-
text-transform: uppercase;
|
18
|
-
}
|
19
|
-
}
|
20
|
-
|
21
|
-
&__format-label {
|
22
|
-
margin-right: 15px;
|
23
|
-
}
|
24
|
-
|
25
|
-
&__title {
|
26
|
-
text-align: center;
|
27
|
-
}
|
7
|
+
height: 100%;
|
8
|
+
padding: 20px 20px 0px;
|
28
9
|
|
29
|
-
|
30
|
-
animation: none !important;
|
31
|
-
}
|
32
|
-
|
33
|
-
&__search {
|
34
|
-
width: 255px;
|
35
|
-
margin: 0 15px 0 0;
|
36
|
-
}
|
37
|
-
|
38
|
-
&__tablets {
|
39
|
-
padding: 0 !important;
|
40
|
-
|
41
|
-
.tablets-viewer__grid {
|
42
|
-
grid-template-columns: 125px;
|
43
|
-
}
|
44
|
-
}
|
45
|
-
|
46
|
-
&__controls {
|
47
|
-
display: flex;
|
48
|
-
justify-content: space-between;
|
10
|
+
@include flex-container();
|
49
11
|
|
50
|
-
|
51
|
-
|
12
|
+
&__content {
|
13
|
+
overflow: auto;
|
52
14
|
|
53
|
-
|
54
|
-
display: flex;
|
55
|
-
flex: 1 1 auto;
|
56
|
-
flex-direction: column;
|
15
|
+
height: 100%;
|
57
16
|
}
|
58
17
|
}
|
@@ -1,51 +1,133 @@
|
|
1
|
-
import {
|
1
|
+
import {useEffect, useMemo} from 'react';
|
2
|
+
import {useLocation, useRouteMatch} from 'react-router';
|
3
|
+
import {useDispatch} from 'react-redux';
|
2
4
|
import cn from 'bem-cn-lite';
|
5
|
+
import qs from 'qs';
|
6
|
+
|
7
|
+
import {Tabs} from '@gravity-ui/uikit';
|
3
8
|
|
4
9
|
import type {AdditionalClusterProps, AdditionalVersionsProps} from '../../types/additionalProps';
|
5
|
-
import
|
10
|
+
import type {AdditionalNodesInfo} from '../../utils/nodes';
|
11
|
+
import routes from '../../routes';
|
6
12
|
|
7
|
-
import {
|
13
|
+
import {setHeader} from '../../store/reducers/header';
|
14
|
+
import {getClusterInfo} from '../../store/reducers/cluster/cluster';
|
15
|
+
import {getClusterNodes} from '../../store/reducers/clusterNodes/clusterNodes';
|
16
|
+
import {parseNodesToVersionsValues, parseVersionsToVersionToColorMap} from '../../utils/versions';
|
17
|
+
import {useAutofetcher, useTypedSelector} from '../../utils/hooks';
|
18
|
+
|
19
|
+
import {InternalLink} from '../../components/InternalLink';
|
8
20
|
import Tenants from '../Tenants/Tenants';
|
9
21
|
import {Nodes} from '../Nodes/Nodes';
|
10
22
|
import Storage from '../Storage/Storage';
|
23
|
+
import {Versions} from '../Versions/Versions';
|
24
|
+
|
25
|
+
import {ClusterInfo} from './ClusterInfo/ClusterInfo';
|
26
|
+
import {ClusterTab, clusterTabs, clusterTabsIds, getClusterPath} from './utils';
|
11
27
|
|
12
28
|
import './Cluster.scss';
|
13
29
|
|
14
30
|
const b = cn('cluster');
|
15
31
|
|
16
32
|
interface ClusterProps {
|
17
|
-
additionalTenantsInfo?:
|
18
|
-
additionalNodesInfo?:
|
33
|
+
additionalTenantsInfo?: unknown;
|
34
|
+
additionalNodesInfo?: AdditionalNodesInfo;
|
19
35
|
additionalClusterProps?: AdditionalClusterProps;
|
20
36
|
additionalVersionsProps?: AdditionalVersionsProps;
|
21
37
|
}
|
22
38
|
|
23
39
|
function Cluster({
|
40
|
+
additionalClusterProps,
|
24
41
|
additionalTenantsInfo,
|
25
42
|
additionalNodesInfo,
|
26
|
-
additionalClusterProps,
|
27
43
|
additionalVersionsProps,
|
28
44
|
}: ClusterProps) {
|
29
|
-
const
|
30
|
-
|
31
|
-
const
|
45
|
+
const dispatch = useDispatch();
|
46
|
+
|
47
|
+
const match = useRouteMatch<{activeTab: string}>(routes.cluster);
|
48
|
+
const {activeTab = clusterTabsIds.tenants} = match?.params || {};
|
49
|
+
|
50
|
+
const location = useLocation();
|
51
|
+
const queryParams = qs.parse(location.search, {
|
52
|
+
ignoreQueryPrefix: true,
|
53
|
+
});
|
54
|
+
const {clusterName} = queryParams;
|
55
|
+
|
56
|
+
const {
|
57
|
+
data: cluster = {},
|
58
|
+
loading: clusterLoading,
|
59
|
+
wasLoaded: clusterWasLoaded,
|
60
|
+
error: clusterError,
|
61
|
+
} = useTypedSelector((state) => state.cluster);
|
62
|
+
const {
|
63
|
+
nodes,
|
64
|
+
loading: nodesLoading,
|
65
|
+
wasLoaded: nodesWasLoaded,
|
66
|
+
} = useTypedSelector((state) => state.clusterNodes);
|
67
|
+
|
68
|
+
const {Name} = cluster;
|
69
|
+
|
70
|
+
const infoLoading = (clusterLoading && !clusterWasLoaded) || (nodesLoading && !nodesWasLoaded);
|
71
|
+
|
72
|
+
useEffect(() => {
|
73
|
+
dispatch(getClusterNodes());
|
74
|
+
}, [dispatch]);
|
75
|
+
|
76
|
+
useAutofetcher(
|
77
|
+
() => dispatch(getClusterInfo(clusterName ? String(clusterName) : undefined)),
|
78
|
+
[dispatch, clusterName],
|
79
|
+
true,
|
80
|
+
);
|
81
|
+
|
82
|
+
useEffect(() => {
|
83
|
+
dispatch(
|
84
|
+
setHeader([
|
85
|
+
{
|
86
|
+
text: Name || 'Cluster',
|
87
|
+
link: getClusterPath(),
|
88
|
+
},
|
89
|
+
]),
|
90
|
+
);
|
91
|
+
}, [dispatch, Name]);
|
92
|
+
|
93
|
+
const versionToColor = useMemo(() => {
|
94
|
+
if (additionalVersionsProps?.getVersionToColorMap) {
|
95
|
+
return additionalVersionsProps?.getVersionToColorMap();
|
96
|
+
}
|
97
|
+
return parseVersionsToVersionToColorMap(cluster?.Versions);
|
98
|
+
}, [additionalVersionsProps, cluster]);
|
99
|
+
|
100
|
+
const versionsValues = useMemo(() => {
|
101
|
+
return parseNodesToVersionsValues(nodes, versionToColor);
|
102
|
+
}, [nodes, versionToColor]);
|
103
|
+
|
104
|
+
const renderTab = () => {
|
32
105
|
switch (activeTab) {
|
33
|
-
case
|
106
|
+
case clusterTabsIds.tenants: {
|
34
107
|
return <Tenants additionalTenantsInfo={additionalTenantsInfo} />;
|
35
108
|
}
|
36
|
-
case
|
109
|
+
case clusterTabsIds.nodes: {
|
37
110
|
return <Nodes additionalNodesInfo={additionalNodesInfo} />;
|
38
111
|
}
|
39
|
-
case
|
112
|
+
case clusterTabsIds.storage: {
|
40
113
|
return <Storage additionalNodesInfo={additionalNodesInfo} />;
|
41
114
|
}
|
42
|
-
case
|
43
|
-
return
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
115
|
+
case clusterTabsIds.versions: {
|
116
|
+
return <Versions versionToColor={versionToColor} />;
|
117
|
+
}
|
118
|
+
default: {
|
119
|
+
return null;
|
120
|
+
}
|
121
|
+
}
|
122
|
+
};
|
123
|
+
|
124
|
+
const getTabEntityCount = (tabId: ClusterTab) => {
|
125
|
+
switch (tabId) {
|
126
|
+
case clusterTabsIds.tenants: {
|
127
|
+
return cluster?.Tenants;
|
128
|
+
}
|
129
|
+
case clusterTabsIds.nodes: {
|
130
|
+
return cluster?.NodesTotal;
|
49
131
|
}
|
50
132
|
default: {
|
51
133
|
return null;
|
@@ -53,7 +135,41 @@ function Cluster({
|
|
53
135
|
}
|
54
136
|
};
|
55
137
|
|
56
|
-
return
|
138
|
+
return (
|
139
|
+
<div className={b()}>
|
140
|
+
<ClusterInfo
|
141
|
+
cluster={cluster}
|
142
|
+
versionsValues={versionsValues}
|
143
|
+
loading={infoLoading}
|
144
|
+
error={clusterError}
|
145
|
+
additionalClusterProps={additionalClusterProps}
|
146
|
+
/>
|
147
|
+
|
148
|
+
<div>
|
149
|
+
<Tabs
|
150
|
+
size="l"
|
151
|
+
allowNotSelected={true}
|
152
|
+
activeTab={activeTab as string}
|
153
|
+
items={clusterTabs.map((item) => {
|
154
|
+
return {
|
155
|
+
...item,
|
156
|
+
title: `${item.title} ${getTabEntityCount(item.id) || ''}`,
|
157
|
+
};
|
158
|
+
})}
|
159
|
+
wrapTo={({id}, node) => {
|
160
|
+
const path = getClusterPath(id as ClusterTab, queryParams);
|
161
|
+
return (
|
162
|
+
<InternalLink to={path} key={id}>
|
163
|
+
{node}
|
164
|
+
</InternalLink>
|
165
|
+
);
|
166
|
+
}}
|
167
|
+
/>
|
168
|
+
</div>
|
169
|
+
|
170
|
+
<div className={b('content')}>{renderTab()}</div>
|
171
|
+
</div>
|
172
|
+
);
|
57
173
|
}
|
58
174
|
|
59
175
|
export default Cluster;
|
@@ -1,31 +1,48 @@
|
|
1
1
|
@import '../../../styles/mixins';
|
2
2
|
|
3
3
|
.cluster-info {
|
4
|
-
|
5
|
-
$progress_width: 100%;
|
4
|
+
width: 100%;
|
6
5
|
|
7
|
-
|
8
|
-
|
9
|
-
flex-direction: column;
|
6
|
+
&__header {
|
7
|
+
display: flex;
|
10
8
|
|
11
|
-
|
9
|
+
width: fit-content;
|
10
|
+
margin-bottom: 20px;
|
12
11
|
|
13
|
-
|
14
|
-
line-height: var(--yc-text-body-2-line-height);
|
12
|
+
cursor: pointer;
|
15
13
|
|
16
|
-
|
17
|
-
|
14
|
+
&__expand-button {
|
15
|
+
margin-left: 6px;
|
18
16
|
|
19
|
-
|
20
|
-
|
17
|
+
&_rotate {
|
18
|
+
transform: rotate(180deg);
|
19
|
+
}
|
20
|
+
}
|
21
21
|
}
|
22
22
|
|
23
|
-
&__title {
|
24
|
-
|
25
|
-
|
23
|
+
&__title .entity-status__name {
|
24
|
+
font-size: var(--yc-text-header-1-font-size);
|
25
|
+
font-weight: var(--yc-text-header-font-weight);
|
26
|
+
line-height: var(--yc-text-header-1-line-height);
|
27
|
+
}
|
28
|
+
|
29
|
+
&__title-skeleton {
|
30
|
+
width: 20%;
|
31
|
+
min-width: 200px;
|
32
|
+
height: var(--yc-text-header-1-line-height);
|
33
|
+
}
|
26
34
|
|
27
|
-
|
35
|
+
&__error {
|
36
|
+
font-size: var(--yc-text-body-2-font-size);
|
37
|
+
line-height: var(--yc-text-body-2-line-height);
|
38
|
+
}
|
39
|
+
|
40
|
+
&__info {
|
28
41
|
margin-bottom: 20px;
|
42
|
+
|
43
|
+
&_hidden {
|
44
|
+
display: none;
|
45
|
+
}
|
29
46
|
}
|
30
47
|
|
31
48
|
&__metric-field {
|
@@ -38,7 +55,7 @@
|
|
38
55
|
align-items: center;
|
39
56
|
|
40
57
|
& .tablet {
|
41
|
-
margin-
|
58
|
+
margin-top: 2px;
|
42
59
|
}
|
43
60
|
}
|
44
61
|
|