ydb-embedded-ui 1.8.7 → 1.10.0
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +56 -0
- package/dist/components/BasicNodeViewer/BasicNodeViewer.scss +43 -0
- package/dist/components/BasicNodeViewer/BasicNodeViewer.tsx +53 -0
- package/dist/components/BasicNodeViewer/index.ts +1 -0
- package/dist/components/EntityStatus/EntityStatus.js +15 -3
- package/dist/components/FullNodeViewer/FullNodeViewer.js +29 -48
- package/dist/components/FullNodeViewer/FullNodeViewer.scss +0 -45
- package/dist/components/IndexInfoViewer/IndexInfoViewer.tsx +52 -0
- package/dist/components/InfoViewer/index.ts +4 -0
- package/dist/components/InfoViewer/utils.ts +32 -0
- package/dist/components/ProgressViewer/ProgressViewer.js +1 -1
- package/dist/components/TabletsOverall/TabletsOverall.tsx +1 -1
- package/dist/containers/Node/Node.scss +5 -1
- package/dist/containers/Node/Node.tsx +7 -1
- package/dist/containers/Node/NodeOverview/NodeOverview.tsx +1 -3
- package/dist/containers/Node/NodeStructure/NodeStructure.scss +30 -1
- package/dist/containers/Node/NodeStructure/PDiskTitleBadge.tsx +25 -0
- package/dist/containers/Node/NodeStructure/Pdisk.tsx +24 -2
- package/dist/containers/Nodes/Nodes.js +1 -0
- package/dist/containers/ReduxTooltip/ReduxTooltip.js +1 -1
- package/dist/containers/Storage/Pdisk/Pdisk.tsx +25 -33
- package/dist/containers/Storage/Vdisk/Vdisk.js +2 -0
- package/dist/containers/Tablet/Tablet.js +2 -2
- package/dist/containers/Tablets/Tablets.js +1 -1
- package/dist/containers/Tablets/Tablets.scss +0 -6
- package/dist/containers/TabletsFilters/TabletsFilters.scss +0 -7
- package/dist/containers/Tenant/Diagnostics/DetailedOverview/DetailedOverview.scss +6 -2
- package/dist/containers/Tenant/Diagnostics/DiagnosticsPages.ts +24 -14
- package/dist/containers/Tenant/Diagnostics/Healthcheck/Healthcheck.js +6 -2
- package/dist/containers/Tenant/Diagnostics/Healthcheck/Healthcheck.scss +6 -2
- package/dist/containers/Tenant/Diagnostics/HotKeys/HotKeys.js +3 -3
- package/dist/containers/Tenant/Diagnostics/Overview/Overview.tsx +24 -3
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.js +15 -13
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.scss +22 -6
- package/dist/containers/Tenant/Diagnostics/TopShards/TopShards.js +80 -10
- package/dist/containers/Tenant/Schema/SchemaInfoViewer/SchemaInfoViewer.js +20 -16
- package/dist/containers/Tenant/Schema/SchemaTree/SchemaTree.tsx +1 -0
- package/dist/containers/Tenant/utils/schema.ts +73 -28
- package/dist/containers/Tenant/utils/schemaActions.ts +42 -32
- package/dist/services/api.js +13 -8
- package/dist/store/reducers/executeQuery.js +1 -1
- package/dist/store/reducers/executeTopQueries.js +1 -1
- package/dist/store/reducers/olapStats.js +5 -1
- package/dist/store/reducers/preview.js +1 -1
- package/dist/store/reducers/shardsWorkload.js +32 -4
- package/dist/types/api/schema.ts +43 -1
- package/dist/types/api/storage.ts +54 -0
- package/dist/utils/getNodesColumns.js +2 -0
- package/dist/utils/pdisk.ts +74 -0
- package/dist/utils/tooltip.js +27 -0
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
@@ -1,5 +1,61 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [1.10.0](https://github.com/ydb-platform/ydb-embedded-ui/compare/v1.9.0...v1.10.0) (2022-08-10)
|
4
|
+
|
5
|
+
|
6
|
+
### Features
|
7
|
+
|
8
|
+
* **TopShards:** add DataSize column ([cbcd047](https://github.com/ydb-platform/ydb-embedded-ui/commit/cbcd047d277f699a67bc002a5542f3b9f6a0c942))
|
9
|
+
* **TopShards:** sort table data on backend ([dc28c5c](https://github.com/ydb-platform/ydb-embedded-ui/commit/dc28c5c75b0036480bf804d49f82fc54eac98c8e))
|
10
|
+
|
11
|
+
|
12
|
+
### Bug Fixes
|
13
|
+
|
14
|
+
* add concurrentId for sendQuery request ([dc6b32a](https://github.com/ydb-platform/ydb-embedded-ui/commit/dc6b32a8fd51064ddeca2fc60a0f08a725216334))
|
15
|
+
* **Storage:** display pdisk type in tooltip ([2b03a35](https://github.com/ydb-platform/ydb-embedded-ui/commit/2b03a35fc11ddeae3bdd30a0690b324ae917f5c3))
|
16
|
+
* **Tablet:** change Kill to Restart ([dd585b1](https://github.com/ydb-platform/ydb-embedded-ui/commit/dd585b1d1a6a5ddb484a702523773b169900f582))
|
17
|
+
* **Tenant:** add missing schema node types ([62a0ecb](https://github.com/ydb-platform/ydb-embedded-ui/commit/62a0ecb848dbcee53e18535cbf7c03a731d0cfeb))
|
18
|
+
* **Tenant:** ensure correct behavior for new schema node types ([f80c381](https://github.com/ydb-platform/ydb-embedded-ui/commit/f80c38152656e8bbbe51ec38b29fc0d954c361cc))
|
19
|
+
* **Tenant:** use new schema icons ([389a921](https://github.com/ydb-platform/ydb-embedded-ui/commit/389a9214c64b1adb183fa0c6caa6f2ec536dbef3))
|
20
|
+
* **TopShards:** disable virtualization for table ([006d3d9](https://github.com/ydb-platform/ydb-embedded-ui/commit/006d3d9fb9a4744b8bb4ad03e53693199213f80e))
|
21
|
+
* **TopShards:** format DataSize value ([c51ce66](https://github.com/ydb-platform/ydb-embedded-ui/commit/c51ce66286f6454f7252d1194628ee5a50aafba2))
|
22
|
+
* **TopShards:** only allow DESC sort ([6aa326f](https://github.com/ydb-platform/ydb-embedded-ui/commit/6aa326fc4b8165f00f8b3ecf5becdb0943ed57af))
|
23
|
+
* **TopShards:** substring tenant name out of shards path ([9e57672](https://github.com/ydb-platform/ydb-embedded-ui/commit/9e5767222c7dac7734c68abd08067cea507b1e15))
|
24
|
+
|
25
|
+
## [1.9.0](https://github.com/ydb-platform/ydb-embedded-ui/compare/v1.8.8...v1.9.0) (2022-07-29)
|
26
|
+
|
27
|
+
|
28
|
+
### Features
|
29
|
+
|
30
|
+
* **Node:** display endpoints in overview ([89e9e47](https://github.com/ydb-platform/ydb-embedded-ui/commit/89e9e470499b6f458e8949211d97293c0b7d9b97))
|
31
|
+
* **Node:** display node basic info above tabs ([aafb15b](https://github.com/ydb-platform/ydb-embedded-ui/commit/aafb15b399bf116026eff36f3c4ac817e2c40e18))
|
32
|
+
* **Node:** more informative pdisks panels ([342712b](https://github.com/ydb-platform/ydb-embedded-ui/commit/342712bcaa793971e1ca354da57fb962639ef90c))
|
33
|
+
* **Nodes:** show node endpoints in tooltip ([34be559](https://github.com/ydb-platform/ydb-embedded-ui/commit/34be55957e02f947ede30b43f22fde82d21df308))
|
34
|
+
* **Tenant:** table index overview ([2aed714](https://github.com/ydb-platform/ydb-embedded-ui/commit/2aed71488cde1175e6569c236ab609bb126f9cf3))
|
35
|
+
* **Tenant:** virtualized tree in schema ([815f558](https://github.com/ydb-platform/ydb-embedded-ui/commit/815f5588e5fed6fb86f69653c4937e975465372f))
|
36
|
+
* utils for parsing bitfields in pdisk data ([da22b4a](https://github.com/ydb-platform/ydb-embedded-ui/commit/da22b4afde9efe4d9605cefb69ddd51aed989722))
|
37
|
+
|
38
|
+
|
39
|
+
### Bug Fixes
|
40
|
+
|
41
|
+
* **Node:** fix pdisk title items width ([ca5fec6](https://github.com/ydb-platform/ydb-embedded-ui/commit/ca5fec6388364b7d1d6362f1bda36431d9c29749))
|
42
|
+
* **Nodes:** hide tooltip on unmount ([54e4fdc](https://github.com/ydb-platform/ydb-embedded-ui/commit/54e4fdc8045c555338e79d89a93faf58e888fa0e))
|
43
|
+
* **ProgressViewer:** apply provided custom class name ([aa60e9d](https://github.com/ydb-platform/ydb-embedded-ui/commit/aa60e9d1b9c0752853f4323d3bcfd220bedd272d))
|
44
|
+
* **Tenant:** display all table props in overview ([d70e311](https://github.com/ydb-platform/ydb-embedded-ui/commit/d70e311296f6a4d1781f6e72929c70e0db7c3226))
|
45
|
+
* **Tenant:** display PartCount first in table overview ([8c09746](https://github.com/ydb-platform/ydb-embedded-ui/commit/8c09746b026a23a36fe31be94057cc92535aceaa))
|
46
|
+
|
47
|
+
## [1.8.8](https://github.com/ydb-platform/ydb-embedded-ui/compare/v1.8.7...v1.8.8) (2022-07-21)
|
48
|
+
|
49
|
+
|
50
|
+
### Bug Fixes
|
51
|
+
|
52
|
+
* **TabletsFilters:** display tablets grid full-height ([0dde809](https://github.com/ydb-platform/ydb-embedded-ui/commit/0dde8097fe026248aade97f034fa35c56b28e903))
|
53
|
+
* **TabletsOverall:** properly hide tooltip on mouseleave ([df36eba](https://github.com/ydb-platform/ydb-embedded-ui/commit/df36ebaf44d8966bc419f3720d51390dfd767a87))
|
54
|
+
* **Tablets:** properly display tablets in grid ([f3b64fa](https://github.com/ydb-platform/ydb-embedded-ui/commit/f3b64fae3a1e1a46ababd2d2f04ddff488698676))
|
55
|
+
* **Tenant:** align info in overview ([acb39fa](https://github.com/ydb-platform/ydb-embedded-ui/commit/acb39fab70b7b4e0e78124fd887b2f1b76815221))
|
56
|
+
* **Tenant:** display tenant name in single line ([301e391](https://github.com/ydb-platform/ydb-embedded-ui/commit/301e3911330024f80ebfda6d1a16823b64d94b36))
|
57
|
+
* **Tenant:** move tablets under tenant name ([b7e4b8f](https://github.com/ydb-platform/ydb-embedded-ui/commit/b7e4b8f7027f1481a7c1baff77bf8ad5e2ed467c))
|
58
|
+
|
3
59
|
## [1.8.7](https://github.com/ydb-platform/ydb-embedded-ui/compare/v1.8.6...v1.8.7) (2022-07-18)
|
4
60
|
|
5
61
|
|
@@ -0,0 +1,43 @@
|
|
1
|
+
@import '../../styles/mixins.scss';
|
2
|
+
|
3
|
+
.basic-node-viewer {
|
4
|
+
font-size: var(--yc-text-body-2-font-size);
|
5
|
+
line-height: var(--yc-text-body-2-line-height);
|
6
|
+
|
7
|
+
display: flex;
|
8
|
+
align-items: center;
|
9
|
+
|
10
|
+
margin: 15px 0;
|
11
|
+
|
12
|
+
&__title {
|
13
|
+
margin: 0 20px 0 0;
|
14
|
+
|
15
|
+
font-size: var(--yc-text-body-2-font-size);
|
16
|
+
font-weight: 600;
|
17
|
+
line-height: var(--yc-text-body-2-line-height);
|
18
|
+
text-transform: uppercase;
|
19
|
+
}
|
20
|
+
|
21
|
+
&__id {
|
22
|
+
margin: 0 15px 0 24px;
|
23
|
+
}
|
24
|
+
|
25
|
+
&__label {
|
26
|
+
margin-right: 10px;
|
27
|
+
|
28
|
+
font-size: var(--yc-text-body-2-font-size);
|
29
|
+
line-height: 18px;
|
30
|
+
white-space: nowrap;
|
31
|
+
|
32
|
+
color: var(--yc-color-text-hint);
|
33
|
+
|
34
|
+
.yc-root_theme_dark & {
|
35
|
+
color: var(--yc-color-text-hint);
|
36
|
+
}
|
37
|
+
}
|
38
|
+
|
39
|
+
&__link {
|
40
|
+
margin-left: 5px;
|
41
|
+
@extend .link;
|
42
|
+
}
|
43
|
+
}
|
@@ -0,0 +1,53 @@
|
|
1
|
+
import cn from 'bem-cn-lite';
|
2
|
+
|
3
|
+
import EntityStatus from '../EntityStatus/EntityStatus';
|
4
|
+
import Tags from '../Tags/Tags';
|
5
|
+
import Icon from '../Icon/Icon';
|
6
|
+
|
7
|
+
import './BasicNodeViewer.scss';
|
8
|
+
|
9
|
+
const b = cn('basic-node-viewer');
|
10
|
+
|
11
|
+
interface BasicNodeViewerProps {
|
12
|
+
node: any;
|
13
|
+
additionalNodesInfo?: any;
|
14
|
+
className?: string;
|
15
|
+
}
|
16
|
+
|
17
|
+
export const BasicNodeViewer = ({node, additionalNodesInfo, className}: BasicNodeViewerProps) => {
|
18
|
+
const nodeHref = additionalNodesInfo?.getNodeRef
|
19
|
+
? additionalNodesInfo.getNodeRef(node) + 'internal'
|
20
|
+
: undefined;
|
21
|
+
|
22
|
+
return (
|
23
|
+
<div className={b(null, className)}>
|
24
|
+
{node ? (
|
25
|
+
<>
|
26
|
+
<div className={b('title')}>Node</div>
|
27
|
+
<EntityStatus status={node.SystemState} name={node.Host} />
|
28
|
+
{nodeHref && (
|
29
|
+
<a
|
30
|
+
rel="noopener noreferrer"
|
31
|
+
className={b('link', {external: true})}
|
32
|
+
href={nodeHref}
|
33
|
+
target="_blank"
|
34
|
+
>
|
35
|
+
<Icon name="external" />
|
36
|
+
</a>
|
37
|
+
)}
|
38
|
+
|
39
|
+
<div className={b('id')}>
|
40
|
+
<label className={b('label')}>NodeID</label>
|
41
|
+
<label>{node.NodeId}</label>
|
42
|
+
</div>
|
43
|
+
|
44
|
+
<Tags tags={[node.DataCenter]} />
|
45
|
+
<Tags tags={node.Roles} tagsType="blue" />
|
46
|
+
</>
|
47
|
+
) : (
|
48
|
+
<div className="error">no data</div>
|
49
|
+
)}
|
50
|
+
|
51
|
+
</div>
|
52
|
+
);
|
53
|
+
};
|
@@ -0,0 +1 @@
|
|
1
|
+
export * from './BasicNodeViewer';
|
@@ -12,6 +12,8 @@ class EntityStatus extends React.Component {
|
|
12
12
|
static propTypes = {
|
13
13
|
status: PropTypes.string,
|
14
14
|
name: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
15
|
+
onNameMouseEnter: PropTypes.func,
|
16
|
+
onNameMouseLeave: PropTypes.func,
|
15
17
|
path: PropTypes.string,
|
16
18
|
size: PropTypes.string,
|
17
19
|
label: PropTypes.string,
|
@@ -49,19 +51,29 @@ class EntityStatus extends React.Component {
|
|
49
51
|
);
|
50
52
|
}
|
51
53
|
renderLink() {
|
52
|
-
const {externalLink, name, path} = this.props;
|
54
|
+
const {externalLink, name, path, onNameMouseEnter, onNameMouseLeave} = this.props;
|
53
55
|
|
54
56
|
if (externalLink) {
|
55
57
|
return <ExternalLink href={path}>{name}</ExternalLink>;
|
56
58
|
}
|
57
59
|
|
58
60
|
return path ? (
|
59
|
-
<Link
|
61
|
+
<Link
|
62
|
+
title={name}
|
63
|
+
to={path}
|
64
|
+
onMouseEnter={onNameMouseEnter}
|
65
|
+
onMouseLeave={onNameMouseLeave}
|
66
|
+
>
|
60
67
|
{name}
|
61
68
|
</Link>
|
62
69
|
) : (
|
63
70
|
name && (
|
64
|
-
<span
|
71
|
+
<span
|
72
|
+
className={b('name')}
|
73
|
+
title={name}
|
74
|
+
onMouseEnter={onNameMouseEnter}
|
75
|
+
onMouseLeave={onNameMouseLeave}
|
76
|
+
>
|
65
77
|
{name}
|
66
78
|
</span>
|
67
79
|
)
|
@@ -3,11 +3,8 @@ import cn from 'bem-cn-lite';
|
|
3
3
|
import PropTypes from 'prop-types';
|
4
4
|
|
5
5
|
import InfoViewer from '../InfoViewer/InfoViewer';
|
6
|
-
import EntityStatus from '../EntityStatus/EntityStatus';
|
7
6
|
import ProgressViewer from '../ProgressViewer/ProgressViewer';
|
8
7
|
import PoolUsage from '../PoolUsage/PoolUsage';
|
9
|
-
import Tags from '../Tags/Tags';
|
10
|
-
import Icon from '../Icon/Icon';
|
11
8
|
|
12
9
|
import {LOAD_AVERAGE_TIME_INTERVALS} from '../../utils/constants';
|
13
10
|
import {calcUptime} from '../../utils';
|
@@ -22,7 +19,6 @@ class FullNodeViewer extends React.Component {
|
|
22
19
|
node: PropTypes.object.isRequired,
|
23
20
|
backend: PropTypes.string,
|
24
21
|
singleClusterMode: PropTypes.bool,
|
25
|
-
additionalNodesInfo: PropTypes.object,
|
26
22
|
};
|
27
23
|
|
28
24
|
static defaultProps = {
|
@@ -30,10 +26,12 @@ class FullNodeViewer extends React.Component {
|
|
30
26
|
};
|
31
27
|
|
32
28
|
render() {
|
33
|
-
const {node, className
|
34
|
-
|
35
|
-
|
36
|
-
:
|
29
|
+
const {node, className} = this.props;
|
30
|
+
|
31
|
+
const endpointsInfo = node.Endpoints?.map(({Name, Address}) => ({
|
32
|
+
label: Name,
|
33
|
+
value: Address,
|
34
|
+
}));
|
37
35
|
|
38
36
|
const commonInfo = [
|
39
37
|
{label: 'Version', value: node.Version},
|
@@ -50,52 +48,35 @@ class FullNodeViewer extends React.Component {
|
|
50
48
|
return (
|
51
49
|
<div className={`${b()} ${className}`}>
|
52
50
|
{node ? (
|
53
|
-
<div>
|
54
|
-
<div
|
55
|
-
<div className={b('title')}>
|
56
|
-
<
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
className={b('link', {external: true})}
|
61
|
-
href={nodeHref}
|
62
|
-
target="_blank"
|
63
|
-
>
|
64
|
-
<Icon name="external" />
|
65
|
-
</a>
|
66
|
-
)}
|
67
|
-
|
68
|
-
<div className={b('row', {id: true})}>
|
69
|
-
<label className={b('label', {id: true})}>NodeID</label>
|
70
|
-
<label>{node.NodeId}</label>
|
51
|
+
<div className={b('common-info')}>
|
52
|
+
<div>
|
53
|
+
<div className={b('section-title')}>Pools</div>
|
54
|
+
<div className={b('section', {pools: true})}>
|
55
|
+
{node.PoolStats.map((pool, poolIndex) => (
|
56
|
+
<PoolUsage key={poolIndex} data={pool} />
|
57
|
+
))}
|
71
58
|
</div>
|
72
|
-
|
73
|
-
<Tags tags={[node.DataCenter]} />
|
74
|
-
<Tags tags={node.Roles} tagsType="blue" />
|
75
59
|
</div>
|
76
60
|
|
77
|
-
|
78
|
-
<div>
|
79
|
-
<div className={b('section-title')}>Pools</div>
|
80
|
-
<div className={b('section', {pools: true})}>
|
81
|
-
{node.PoolStats.map((pool, poolIndex) => (
|
82
|
-
<PoolUsage key={poolIndex} data={pool} />
|
83
|
-
))}
|
84
|
-
</div>
|
85
|
-
</div>
|
86
|
-
|
61
|
+
{endpointsInfo && endpointsInfo.length && (
|
87
62
|
<InfoViewer
|
88
|
-
title="
|
63
|
+
title="Endpoints"
|
89
64
|
className={b('section')}
|
90
|
-
info={
|
65
|
+
info={endpointsInfo}
|
91
66
|
/>
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
67
|
+
)}
|
68
|
+
|
69
|
+
<InfoViewer
|
70
|
+
title="Common info"
|
71
|
+
className={b('section')}
|
72
|
+
info={commonInfo}
|
73
|
+
/>
|
74
|
+
|
75
|
+
<InfoViewer
|
76
|
+
title="Load average"
|
77
|
+
className={b('section', {average: true})}
|
78
|
+
info={averageInfo}
|
79
|
+
/>
|
99
80
|
</div>
|
100
81
|
) : (
|
101
82
|
<div className="error">no data</div>
|
@@ -4,26 +4,6 @@
|
|
4
4
|
font-size: var(--yc-text-body-2-font-size);
|
5
5
|
line-height: var(--yc-text-body-2-line-height);
|
6
6
|
|
7
|
-
&__title {
|
8
|
-
margin: 0 20px 0 0;
|
9
|
-
|
10
|
-
font-size: var(--yc-text-body-2-font-size);
|
11
|
-
font-weight: 600;
|
12
|
-
line-height: var(--yc-text-body-2-line-height);
|
13
|
-
text-transform: uppercase;
|
14
|
-
}
|
15
|
-
|
16
|
-
&__row {
|
17
|
-
display: flex;
|
18
|
-
align-items: center;
|
19
|
-
|
20
|
-
margin: 15px 0;
|
21
|
-
|
22
|
-
&_id {
|
23
|
-
margin: 0 15px 0 24px;
|
24
|
-
}
|
25
|
-
}
|
26
|
-
|
27
7
|
&__common-info {
|
28
8
|
display: flex;
|
29
9
|
flex-direction: column;
|
@@ -46,26 +26,6 @@
|
|
46
26
|
min-width: 60px;
|
47
27
|
}
|
48
28
|
|
49
|
-
&__label {
|
50
|
-
min-width: 100px;
|
51
|
-
margin-right: 25px;
|
52
|
-
|
53
|
-
font-size: var(--yc-text-body-2-font-size);
|
54
|
-
line-height: 18px;
|
55
|
-
white-space: nowrap;
|
56
|
-
|
57
|
-
color: var(--yc-color-text-hint);
|
58
|
-
|
59
|
-
.yc-root_theme_dark & {
|
60
|
-
color: var(--yc-color-text-hint);
|
61
|
-
}
|
62
|
-
|
63
|
-
&_id {
|
64
|
-
min-width: auto;
|
65
|
-
margin-right: 10px;
|
66
|
-
}
|
67
|
-
}
|
68
|
-
|
69
29
|
&__section-title {
|
70
30
|
margin: 15px 0 10px;
|
71
31
|
|
@@ -73,9 +33,4 @@
|
|
73
33
|
font-weight: 600;
|
74
34
|
line-height: var(--yc-text-body-2-line-height);
|
75
35
|
}
|
76
|
-
|
77
|
-
&__link {
|
78
|
-
margin-left: 5px;
|
79
|
-
@extend .link;
|
80
|
-
}
|
81
36
|
}
|
@@ -0,0 +1,52 @@
|
|
1
|
+
import type {TEvDescribeSchemeResult, TIndexDescription} from '../../types/api/schema';
|
2
|
+
import {InfoViewer, createInfoFormatter} from '../InfoViewer';
|
3
|
+
|
4
|
+
const DISPLAYED_FIELDS: Set<keyof TIndexDescription> = new Set([
|
5
|
+
'Type',
|
6
|
+
'State',
|
7
|
+
'DataSize',
|
8
|
+
'KeyColumnNames',
|
9
|
+
'DataColumnNames',
|
10
|
+
]);
|
11
|
+
|
12
|
+
const formatItem = createInfoFormatter<TIndexDescription>({
|
13
|
+
Type: (value) => value?.substring(10), // trims EIndexType prefix
|
14
|
+
State: (value) => value?.substring(11), // trims EIndexState prefix
|
15
|
+
KeyColumnNames: (value) => value?.join(', '),
|
16
|
+
DataColumnNames: (value) => value?.join(', '),
|
17
|
+
}, {
|
18
|
+
KeyColumnNames: 'Columns',
|
19
|
+
DataColumnNames: 'Includes',
|
20
|
+
});
|
21
|
+
|
22
|
+
interface IndexInfoViewerProps {
|
23
|
+
data?: TEvDescribeSchemeResult;
|
24
|
+
}
|
25
|
+
|
26
|
+
export const IndexInfoViewer = ({data}: IndexInfoViewerProps) => {
|
27
|
+
if (!data) {
|
28
|
+
return (
|
29
|
+
<div className="error">no index data</div>
|
30
|
+
);
|
31
|
+
}
|
32
|
+
|
33
|
+
const TableIndex = data.PathDescription?.TableIndex;
|
34
|
+
const info: Array<{label?: string, value?: unknown}> = [];
|
35
|
+
|
36
|
+
let key: keyof TIndexDescription;
|
37
|
+
for (key in TableIndex) {
|
38
|
+
if (DISPLAYED_FIELDS.has(key)) {
|
39
|
+
info.push(formatItem(key, TableIndex?.[key]));
|
40
|
+
}
|
41
|
+
}
|
42
|
+
|
43
|
+
return (
|
44
|
+
<>
|
45
|
+
{info.length ? (
|
46
|
+
<InfoViewer info={info}></InfoViewer>
|
47
|
+
) : (
|
48
|
+
<>Empty</>
|
49
|
+
)}
|
50
|
+
</>
|
51
|
+
);
|
52
|
+
};
|
@@ -0,0 +1,32 @@
|
|
1
|
+
type LabelMap<T> = {
|
2
|
+
[label in keyof T]?: string;
|
3
|
+
}
|
4
|
+
|
5
|
+
type FieldMappers<T> = {
|
6
|
+
[label in keyof T]?: (value: T[label]) => string | undefined;
|
7
|
+
}
|
8
|
+
|
9
|
+
function formatLabel<Shape>(label: keyof Shape, map: LabelMap<Shape>) {
|
10
|
+
return map[label] ?? label;
|
11
|
+
}
|
12
|
+
|
13
|
+
function formatValue<Shape, Key extends keyof Shape>(
|
14
|
+
label: Key,
|
15
|
+
value: Shape[Key],
|
16
|
+
mappers: FieldMappers<Shape>,
|
17
|
+
) {
|
18
|
+
const mapper = mappers[label];
|
19
|
+
const mappedValue = mapper ? mapper(value) : value;
|
20
|
+
|
21
|
+
return String(mappedValue ?? '');
|
22
|
+
}
|
23
|
+
|
24
|
+
export function createInfoFormatter<Shape extends Record<string, any>>(
|
25
|
+
fieldMappers?: FieldMappers<Shape>,
|
26
|
+
labelMap?: LabelMap<Shape>,
|
27
|
+
) {
|
28
|
+
return <Key extends keyof Shape>(label: Key, value: Shape[Key]) => ({
|
29
|
+
label: formatLabel(label, labelMap || {}),
|
30
|
+
value: formatValue(label, value, fieldMappers || {}),
|
31
|
+
});
|
32
|
+
}
|
@@ -76,7 +76,7 @@ export class ProgressViewer extends React.Component {
|
|
76
76
|
|
77
77
|
if (!isNaN(fillWidth)) {
|
78
78
|
return (
|
79
|
-
<div className={b({size})}>
|
79
|
+
<div className={b({size}, className)}>
|
80
80
|
<div className={b('line', {bg})} style={lineStyle}></div>
|
81
81
|
<span className={b('text', {text})}>
|
82
82
|
{`${valueText} ${divider} ${capacityText}`}
|
@@ -93,7 +93,7 @@ function TabletsOverall({tablets}: TabletsOverallProps) {
|
|
93
93
|
<div className={b('row', {overall: true})}>
|
94
94
|
<span className={b('label', {overall: true})}>Overall:</span>
|
95
95
|
<div
|
96
|
-
onMouseLeave={dispatch(hideTooltip)}
|
96
|
+
onMouseLeave={() => dispatch(hideTooltip())}
|
97
97
|
onMouseEnter={(e) => dispatch(showTooltip(e.target, tooltipData, 'tabletsOverall'))}
|
98
98
|
>
|
99
99
|
<Progress value={memoryProgress} stack={stack} />
|
@@ -13,6 +13,7 @@ import Storage from '../Storage/Storage';
|
|
13
13
|
import NodeOverview from './NodeOverview/NodeOverview';
|
14
14
|
import NodeStructure from './NodeStructure/NodeStructure';
|
15
15
|
import Loader from '../../components/Loader/Loader';
|
16
|
+
import {BasicNodeViewer} from '../../components/BasicNodeViewer';
|
16
17
|
|
17
18
|
import {getNodeInfo, resetNode} from '../../store/reducers/node';
|
18
19
|
import routes, {CLUSTER_PAGES, createHref} from '../../routes';
|
@@ -133,7 +134,6 @@ function Node(props: NodeProps) {
|
|
133
134
|
case OVERVIEW: {
|
134
135
|
return (
|
135
136
|
<NodeOverview
|
136
|
-
additionalNodesInfo={additionalNodesInfo}
|
137
137
|
node={node}
|
138
138
|
className={b('overview-wrapper')}
|
139
139
|
/>
|
@@ -162,6 +162,12 @@ function Node(props: NodeProps) {
|
|
162
162
|
if (node) {
|
163
163
|
return (
|
164
164
|
<div className={b(null, props.className)}>
|
165
|
+
<BasicNodeViewer
|
166
|
+
node={node}
|
167
|
+
additionalNodesInfo={props.additionalNodesInfo}
|
168
|
+
className={b('header')}
|
169
|
+
/>
|
170
|
+
|
165
171
|
{renderTabs()}
|
166
172
|
|
167
173
|
<div className={b('content')}>{renderTabContent()}</div>
|
@@ -5,16 +5,14 @@ import {backend} from '../../../store';
|
|
5
5
|
|
6
6
|
interface NodeOverviewProps {
|
7
7
|
node: any;
|
8
|
-
additionalNodesInfo: any;
|
9
8
|
className?: string;
|
10
9
|
}
|
11
10
|
|
12
|
-
function NodeOverview({node,
|
11
|
+
function NodeOverview({node, className}: NodeOverviewProps) {
|
13
12
|
return (
|
14
13
|
<FullNodeViewer
|
15
14
|
node={node}
|
16
15
|
backend={backend}
|
17
|
-
additionalNodesInfo={additionalNodesInfo}
|
18
16
|
className={className}
|
19
17
|
/>
|
20
18
|
);
|
@@ -44,9 +44,38 @@
|
|
44
44
|
&__pdisk-title-wrapper {
|
45
45
|
display: flex;
|
46
46
|
align-items: center;
|
47
|
-
gap:
|
47
|
+
gap: 16px;
|
48
48
|
|
49
49
|
font-weight: 600;
|
50
|
+
|
51
|
+
.entity-status__status-icon {
|
52
|
+
margin-right: 0;
|
53
|
+
}
|
54
|
+
}
|
55
|
+
|
56
|
+
&__pdisk-title-item {
|
57
|
+
display: flex;
|
58
|
+
gap: 4px;
|
59
|
+
|
60
|
+
&-label {
|
61
|
+
font-weight: 400;
|
62
|
+
|
63
|
+
color: var(--yc-color-text-secondary);
|
64
|
+
}
|
65
|
+
}
|
66
|
+
|
67
|
+
&__pdisk-title-id {
|
68
|
+
min-width: 110px;
|
69
|
+
}
|
70
|
+
|
71
|
+
&__pdisk-title-type {
|
72
|
+
justify-content: flex-end;
|
73
|
+
|
74
|
+
min-width: 50px;
|
75
|
+
}
|
76
|
+
|
77
|
+
&__pdisk-title-size {
|
78
|
+
min-width: 150px;
|
50
79
|
}
|
51
80
|
|
52
81
|
&__pdisk-details {
|
@@ -0,0 +1,25 @@
|
|
1
|
+
import {ReactNode} from 'react';
|
2
|
+
import cn from 'bem-cn-lite';
|
3
|
+
|
4
|
+
const b = cn('kv-node-structure');
|
5
|
+
|
6
|
+
interface PDiskTitleBadgeProps {
|
7
|
+
label?: string;
|
8
|
+
value: ReactNode;
|
9
|
+
className?: string;
|
10
|
+
}
|
11
|
+
|
12
|
+
export function PDiskTitleBadge({label, value, className}: PDiskTitleBadgeProps) {
|
13
|
+
return (
|
14
|
+
<span className={b('pdisk-title-item', className)}>
|
15
|
+
{label && (
|
16
|
+
<span className={b('pdisk-title-item-label')}>
|
17
|
+
{label}:
|
18
|
+
</span>
|
19
|
+
)}
|
20
|
+
<span className={b('pdisk-title-item-value')}>
|
21
|
+
{value}
|
22
|
+
</span>
|
23
|
+
</span>
|
24
|
+
);
|
25
|
+
}
|