ydb-embedded-ui 1.8.6 → 1.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/dist/components/BasicNodeViewer/BasicNodeViewer.scss +43 -0
  3. package/dist/components/BasicNodeViewer/BasicNodeViewer.tsx +53 -0
  4. package/dist/components/BasicNodeViewer/index.ts +1 -0
  5. package/dist/components/EntityStatus/EntityStatus.js +15 -3
  6. package/dist/components/FullNodeViewer/FullNodeViewer.js +29 -48
  7. package/dist/components/FullNodeViewer/FullNodeViewer.scss +0 -45
  8. package/dist/components/IndexInfoViewer/IndexInfoViewer.tsx +52 -0
  9. package/dist/components/InfoViewer/index.ts +4 -0
  10. package/dist/components/InfoViewer/utils.ts +32 -0
  11. package/dist/components/ProgressViewer/ProgressViewer.js +1 -1
  12. package/dist/components/TabletsOverall/TabletsOverall.tsx +1 -1
  13. package/dist/containers/App/App.js +3 -5
  14. package/dist/containers/Node/Node.scss +5 -1
  15. package/dist/containers/Node/Node.tsx +7 -1
  16. package/dist/containers/Node/NodeOverview/NodeOverview.tsx +1 -3
  17. package/dist/containers/Node/NodeStructure/NodeStructure.scss +30 -1
  18. package/dist/containers/Node/NodeStructure/PDiskTitleBadge.tsx +25 -0
  19. package/dist/containers/Node/NodeStructure/Pdisk.tsx +24 -2
  20. package/dist/containers/Nodes/Nodes.js +1 -0
  21. package/dist/containers/ReduxTooltip/ReduxTooltip.js +1 -1
  22. package/dist/containers/Tablets/Tablets.js +1 -1
  23. package/dist/containers/Tablets/Tablets.scss +0 -6
  24. package/dist/containers/TabletsFilters/TabletsFilters.scss +0 -7
  25. package/dist/containers/Tenant/Diagnostics/DetailedOverview/DetailedOverview.scss +6 -2
  26. package/dist/containers/Tenant/Diagnostics/Healthcheck/Healthcheck.js +6 -2
  27. package/dist/containers/Tenant/Diagnostics/Healthcheck/Healthcheck.scss +6 -2
  28. package/dist/containers/Tenant/Diagnostics/Overview/Overview.tsx +16 -2
  29. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.js +15 -13
  30. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.scss +22 -6
  31. package/dist/containers/Tenant/Preview/Preview.js +3 -0
  32. package/dist/containers/Tenant/Schema/SchemaInfoViewer/SchemaInfoViewer.js +20 -16
  33. package/dist/containers/Tenant/Schema/SchemaTree/SchemaTree.tsx +1 -0
  34. package/dist/types/api/schema.ts +36 -0
  35. package/dist/types/api/storage.ts +54 -0
  36. package/dist/utils/getNodesColumns.js +2 -0
  37. package/dist/utils/pdisk.ts +74 -0
  38. package/dist/utils/tooltip.js +27 -0
  39. package/dist/utils/utils.js +8 -1
  40. package/package.json +2 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,46 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.9.0](https://github.com/ydb-platform/ydb-embedded-ui/compare/v1.8.8...v1.9.0) (2022-07-29)
4
+
5
+
6
+ ### Features
7
+
8
+ * **Node:** display endpoints in overview ([89e9e47](https://github.com/ydb-platform/ydb-embedded-ui/commit/89e9e470499b6f458e8949211d97293c0b7d9b97))
9
+ * **Node:** display node basic info above tabs ([aafb15b](https://github.com/ydb-platform/ydb-embedded-ui/commit/aafb15b399bf116026eff36f3c4ac817e2c40e18))
10
+ * **Node:** more informative pdisks panels ([342712b](https://github.com/ydb-platform/ydb-embedded-ui/commit/342712bcaa793971e1ca354da57fb962639ef90c))
11
+ * **Nodes:** show node endpoints in tooltip ([34be559](https://github.com/ydb-platform/ydb-embedded-ui/commit/34be55957e02f947ede30b43f22fde82d21df308))
12
+ * **Tenant:** table index overview ([2aed714](https://github.com/ydb-platform/ydb-embedded-ui/commit/2aed71488cde1175e6569c236ab609bb126f9cf3))
13
+ * **Tenant:** virtualized tree in schema ([815f558](https://github.com/ydb-platform/ydb-embedded-ui/commit/815f5588e5fed6fb86f69653c4937e975465372f))
14
+ * utils for parsing bitfields in pdisk data ([da22b4a](https://github.com/ydb-platform/ydb-embedded-ui/commit/da22b4afde9efe4d9605cefb69ddd51aed989722))
15
+
16
+
17
+ ### Bug Fixes
18
+
19
+ * **Node:** fix pdisk title items width ([ca5fec6](https://github.com/ydb-platform/ydb-embedded-ui/commit/ca5fec6388364b7d1d6362f1bda36431d9c29749))
20
+ * **Nodes:** hide tooltip on unmount ([54e4fdc](https://github.com/ydb-platform/ydb-embedded-ui/commit/54e4fdc8045c555338e79d89a93faf58e888fa0e))
21
+ * **ProgressViewer:** apply provided custom class name ([aa60e9d](https://github.com/ydb-platform/ydb-embedded-ui/commit/aa60e9d1b9c0752853f4323d3bcfd220bedd272d))
22
+ * **Tenant:** display all table props in overview ([d70e311](https://github.com/ydb-platform/ydb-embedded-ui/commit/d70e311296f6a4d1781f6e72929c70e0db7c3226))
23
+ * **Tenant:** display PartCount first in table overview ([8c09746](https://github.com/ydb-platform/ydb-embedded-ui/commit/8c09746b026a23a36fe31be94057cc92535aceaa))
24
+
25
+ ## [1.8.8](https://github.com/ydb-platform/ydb-embedded-ui/compare/v1.8.7...v1.8.8) (2022-07-21)
26
+
27
+
28
+ ### Bug Fixes
29
+
30
+ * **TabletsFilters:** display tablets grid full-height ([0dde809](https://github.com/ydb-platform/ydb-embedded-ui/commit/0dde8097fe026248aade97f034fa35c56b28e903))
31
+ * **TabletsOverall:** properly hide tooltip on mouseleave ([df36eba](https://github.com/ydb-platform/ydb-embedded-ui/commit/df36ebaf44d8966bc419f3720d51390dfd767a87))
32
+ * **Tablets:** properly display tablets in grid ([f3b64fa](https://github.com/ydb-platform/ydb-embedded-ui/commit/f3b64fae3a1e1a46ababd2d2f04ddff488698676))
33
+ * **Tenant:** align info in overview ([acb39fa](https://github.com/ydb-platform/ydb-embedded-ui/commit/acb39fab70b7b4e0e78124fd887b2f1b76815221))
34
+ * **Tenant:** display tenant name in single line ([301e391](https://github.com/ydb-platform/ydb-embedded-ui/commit/301e3911330024f80ebfda6d1a16823b64d94b36))
35
+ * **Tenant:** move tablets under tenant name ([b7e4b8f](https://github.com/ydb-platform/ydb-embedded-ui/commit/b7e4b8f7027f1481a7c1baff77bf8ad5e2ed467c))
36
+
37
+ ## [1.8.7](https://github.com/ydb-platform/ydb-embedded-ui/compare/v1.8.6...v1.8.7) (2022-07-18)
38
+
39
+
40
+ ### Bug Fixes
41
+
42
+ * **Preview:** sort numbers as numbers, not string ([6c42a62](https://github.com/ydb-platform/ydb-embedded-ui/commit/6c42a62d077fcb9419ceb680906d4cef78a0134f))
43
+
3
44
  ## [1.8.6](https://github.com/ydb-platform/ydb-embedded-ui/compare/v1.8.5...v1.8.6) (2022-07-14)
4
45
 
5
46
 
@@ -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 title={name} to={path}>
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 className={b('name')} title={name}>
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, additionalNodesInfo={}} = this.props;
34
- const nodeHref = additionalNodesInfo.getNodeRef
35
- ? additionalNodesInfo.getNodeRef(node) + 'internal'
36
- : undefined;
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 className={b('row')}>
55
- <div className={b('title')}>Node</div>
56
- <EntityStatus status={node.SystemState} name={node.Host} />
57
- {nodeHref && (
58
- <a
59
- rel="noopener noreferrer"
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
- <div className={b('common-info')}>
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="Common info"
63
+ title="Endpoints"
89
64
  className={b('section')}
90
- info={commonInfo}
65
+ info={endpointsInfo}
91
66
  />
92
-
93
- <InfoViewer
94
- title="Load average"
95
- className={b('section', {average: true})}
96
- info={averageInfo}
97
- />
98
- </div>
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,4 @@
1
+ import InfoViewer from './InfoViewer';
2
+
3
+ export {InfoViewer};
4
+ export * from './utils';
@@ -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} />
@@ -3,7 +3,7 @@ import {connect} from 'react-redux';
3
3
  import PropTypes from 'prop-types';
4
4
 
5
5
  import {configure as configureUiKit} from '@yandex-cloud/uikit';
6
- import {i18n as YDBComponentsI18N} from 'ydb-ui-components';
6
+ import {configure as configureYdbUiComponents} from 'ydb-ui-components';
7
7
  import {i18n, Lang} from '../../utils/i18n';
8
8
 
9
9
  import ContentWrapper, {Content} from './Content';
@@ -27,10 +27,8 @@ class App extends React.Component {
27
27
  constructor(props) {
28
28
  super(props);
29
29
  i18n.setLang(Lang.En);
30
- YDBComponentsI18N.setLang(Lang.En);
31
- configureUiKit({
32
- lang: Lang.En,
33
- });
30
+ configureYdbUiComponents({lang: Lang.En});
31
+ configureUiKit({lang: Lang.En});
34
32
  }
35
33
 
36
34
  componentDidMount() {
@@ -4,6 +4,10 @@
4
4
  overflow: auto;
5
5
  @include flex-container();
6
6
 
7
+ &__header {
8
+ margin: 16px 20px;
9
+ }
10
+
7
11
  &__content {
8
12
  position: relative;
9
13
 
@@ -19,7 +23,7 @@
19
23
  }
20
24
 
21
25
  &__tabs {
22
- padding: 16px 20px 0;
26
+ padding: 0 20px;
23
27
  }
24
28
 
25
29
  &__tab {
@@ -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, additionalNodesInfo, className}: NodeOverviewProps) {
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: 8px;
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
+ }