ydb-embedded-ui 1.8.7 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/CHANGELOG.md +56 -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/Node/Node.scss +5 -1
  14. package/dist/containers/Node/Node.tsx +7 -1
  15. package/dist/containers/Node/NodeOverview/NodeOverview.tsx +1 -3
  16. package/dist/containers/Node/NodeStructure/NodeStructure.scss +30 -1
  17. package/dist/containers/Node/NodeStructure/PDiskTitleBadge.tsx +25 -0
  18. package/dist/containers/Node/NodeStructure/Pdisk.tsx +24 -2
  19. package/dist/containers/Nodes/Nodes.js +1 -0
  20. package/dist/containers/ReduxTooltip/ReduxTooltip.js +1 -1
  21. package/dist/containers/Storage/Pdisk/Pdisk.tsx +25 -33
  22. package/dist/containers/Storage/Vdisk/Vdisk.js +2 -0
  23. package/dist/containers/Tablet/Tablet.js +2 -2
  24. package/dist/containers/Tablets/Tablets.js +1 -1
  25. package/dist/containers/Tablets/Tablets.scss +0 -6
  26. package/dist/containers/TabletsFilters/TabletsFilters.scss +0 -7
  27. package/dist/containers/Tenant/Diagnostics/DetailedOverview/DetailedOverview.scss +6 -2
  28. package/dist/containers/Tenant/Diagnostics/DiagnosticsPages.ts +24 -14
  29. package/dist/containers/Tenant/Diagnostics/Healthcheck/Healthcheck.js +6 -2
  30. package/dist/containers/Tenant/Diagnostics/Healthcheck/Healthcheck.scss +6 -2
  31. package/dist/containers/Tenant/Diagnostics/HotKeys/HotKeys.js +3 -3
  32. package/dist/containers/Tenant/Diagnostics/Overview/Overview.tsx +24 -3
  33. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.js +15 -13
  34. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.scss +22 -6
  35. package/dist/containers/Tenant/Diagnostics/TopShards/TopShards.js +80 -10
  36. package/dist/containers/Tenant/Schema/SchemaInfoViewer/SchemaInfoViewer.js +20 -16
  37. package/dist/containers/Tenant/Schema/SchemaTree/SchemaTree.tsx +1 -0
  38. package/dist/containers/Tenant/utils/schema.ts +73 -28
  39. package/dist/containers/Tenant/utils/schemaActions.ts +42 -32
  40. package/dist/services/api.js +13 -8
  41. package/dist/store/reducers/executeQuery.js +1 -1
  42. package/dist/store/reducers/executeTopQueries.js +1 -1
  43. package/dist/store/reducers/olapStats.js +5 -1
  44. package/dist/store/reducers/preview.js +1 -1
  45. package/dist/store/reducers/shardsWorkload.js +32 -4
  46. package/dist/types/api/schema.ts +43 -1
  47. package/dist/types/api/storage.ts +54 -0
  48. package/dist/utils/getNodesColumns.js +2 -0
  49. package/dist/utils/pdisk.ts +74 -0
  50. package/dist/utils/tooltip.js +27 -0
  51. 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 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} />
@@ -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
+ }