ydb-embedded-ui 4.3.0 → 4.4.1

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 (79) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/containers/App/Content.js +2 -8
  3. package/dist/containers/AsideNavigation/AsideNavigation.tsx +1 -1
  4. package/dist/containers/Cluster/Cluster.scss +4 -0
  5. package/dist/containers/Cluster/Cluster.tsx +14 -8
  6. package/dist/{components → containers}/ClusterInfo/ClusterInfo.scss +39 -0
  7. package/dist/containers/ClusterInfo/ClusterInfo.tsx +207 -0
  8. package/dist/containers/ClusterInfo/utils.ts +13 -0
  9. package/dist/containers/Header/Header.tsx +9 -16
  10. package/dist/containers/Nodes/Nodes.tsx +4 -6
  11. package/dist/containers/Storage/DiskStateProgressBar/DiskStateProgressBar.tsx +2 -3
  12. package/dist/containers/Tenant/Diagnostics/Partitions/Headers/Headers.tsx +4 -4
  13. package/dist/containers/Tenant/Diagnostics/Partitions/Partitions.scss +4 -0
  14. package/dist/containers/Tenant/Diagnostics/Partitions/Partitions.tsx +2 -2
  15. package/dist/containers/Tenant/Diagnostics/Partitions/PartitionsControls/PartitionsControls.tsx +20 -26
  16. package/dist/containers/Tenant/Diagnostics/Partitions/i18n/en.json +1 -1
  17. package/dist/containers/Tenant/Diagnostics/Partitions/i18n/ru.json +1 -1
  18. package/dist/containers/UserSettings/Setting.tsx +82 -0
  19. package/dist/containers/UserSettings/UserSettings.tsx +61 -102
  20. package/dist/containers/UserSettings/i18n/en.json +20 -0
  21. package/dist/containers/UserSettings/i18n/index.ts +11 -0
  22. package/dist/containers/UserSettings/i18n/ru.json +20 -0
  23. package/dist/containers/Versions/GroupedNodesTree/GroupedNodesTree.scss +59 -0
  24. package/dist/containers/Versions/GroupedNodesTree/GroupedNodesTree.tsx +98 -0
  25. package/dist/containers/Versions/NodesTable/NodesTable.tsx +150 -0
  26. package/dist/containers/Versions/NodesTreeTitle/NodesTreeTitle.scss +55 -0
  27. package/dist/containers/Versions/NodesTreeTitle/NodesTreeTitle.tsx +62 -0
  28. package/dist/containers/Versions/Versions.scss +32 -0
  29. package/dist/containers/Versions/Versions.tsx +121 -0
  30. package/dist/containers/Versions/groupNodes.ts +124 -0
  31. package/dist/containers/Versions/types.ts +16 -0
  32. package/dist/routes.ts +0 -6
  33. package/dist/services/api.ts +3 -0
  34. package/dist/store/reducers/cluster/cluster.ts +4 -0
  35. package/dist/store/reducers/cluster/types.ts +3 -2
  36. package/dist/store/reducers/clusterNodes/clusterNodes.tsx +64 -0
  37. package/dist/store/reducers/clusterNodes/types.ts +22 -0
  38. package/dist/store/reducers/index.ts +2 -8
  39. package/dist/store/reducers/partitions/partitions.ts +2 -2
  40. package/dist/store/reducers/partitions/types.ts +1 -1
  41. package/dist/types/additionalProps.ts +5 -0
  42. package/dist/types/versions.ts +9 -0
  43. package/dist/utils/constants.ts +0 -11
  44. package/dist/utils/hooks/useSetting.ts +5 -3
  45. package/dist/utils/versions/getVersionsColors.ts +98 -0
  46. package/dist/utils/versions/index.ts +3 -0
  47. package/dist/utils/versions/parseNodesToVersionsValues.ts +28 -0
  48. package/dist/utils/versions/parseVersion.ts +23 -0
  49. package/package.json +1 -1
  50. package/dist/components/ClusterInfo/ClusterInfo.tsx +0 -239
  51. package/dist/components/FullGroupViewer/FullGroupViewer.js +0 -147
  52. package/dist/components/FullGroupViewer/FullGroupViewer.scss +0 -35
  53. package/dist/components/GroupTreeViewer/GroupTreeViewer.js +0 -87
  54. package/dist/components/GroupTreeViewer/GroupTreeViewer.scss +0 -16
  55. package/dist/components/GroupViewer/GroupViewer.js +0 -100
  56. package/dist/components/GroupViewer/GroupViewer.scss +0 -45
  57. package/dist/components/PDiskViewer/PDiskViewer.js +0 -79
  58. package/dist/components/PDiskViewer/PDiskViewer.scss +0 -46
  59. package/dist/components/TabletsViewer/TabletsViewer.js +0 -44
  60. package/dist/components/TabletsViewer/TabletsViewer.scss +0 -40
  61. package/dist/components/VerticalBars/VerticalBars.scss +0 -15
  62. package/dist/components/VerticalBars/VerticalBars.tsx +0 -38
  63. package/dist/components/VerticalBars/index.ts +0 -1
  64. package/dist/containers/Group/Group.js +0 -97
  65. package/dist/containers/Group/Group.scss +0 -6
  66. package/dist/containers/Header/Host/Host.js +0 -66
  67. package/dist/containers/Header/Host/Host.scss +0 -50
  68. package/dist/containers/Pdisk/Pdisk.js +0 -156
  69. package/dist/containers/Pdisk/Pdisk.scss +0 -42
  70. package/dist/containers/Pool/Pool.js +0 -170
  71. package/dist/containers/Pool/Pool.scss +0 -35
  72. package/dist/containers/Vdisk/Vdisk.js +0 -158
  73. package/dist/containers/Vdisk/Vdisk.scss +0 -42
  74. package/dist/containers/VdiskPdiskNode/VdiskPdiskNode.js +0 -526
  75. package/dist/containers/VdiskPdiskNode/VdiskPdiskNode.scss +0 -60
  76. package/dist/store/reducers/group.js +0 -49
  77. package/dist/store/reducers/pdisk.js +0 -51
  78. package/dist/store/reducers/pool.js +0 -42
  79. package/dist/store/reducers/vdisk.js +0 -49
@@ -0,0 +1,22 @@
1
+ import type {IResponseError} from '../../../types/api/error';
2
+ import type {TSystemStateInfo} from '../../../types/api/nodes';
3
+ import type {ApiRequestAction} from '../../utils';
4
+
5
+ import {FETCH_CLUSTER_NODES} from './clusterNodes';
6
+
7
+ export interface PreparedClusterNode extends TSystemStateInfo {
8
+ uptime: string;
9
+ }
10
+
11
+ export interface ClusterNodesState {
12
+ loading: boolean;
13
+ wasLoaded: boolean;
14
+ nodes?: PreparedClusterNode[];
15
+ error?: IResponseError;
16
+ }
17
+
18
+ export type ClusterNodesAction = ApiRequestAction<
19
+ typeof FETCH_CLUSTER_NODES,
20
+ PreparedClusterNode[],
21
+ IResponseError
22
+ >;
@@ -2,19 +2,16 @@ import {combineReducers} from 'redux';
2
2
 
3
3
  import nodes from './nodes';
4
4
  import cluster from './cluster/cluster';
5
+ import clusterNodes from './clusterNodes/clusterNodes';
5
6
  import tenant from './tenant';
6
7
  import storage from './storage';
7
8
  import node from './node';
8
- import pdisk from './pdisk';
9
- import vdisk from './vdisk';
10
- import group from './group';
11
9
  import tooltip from './tooltip';
12
10
  import tablets from './tablets';
13
11
  import heatmap from './heatmap';
14
12
  import schema from './schema';
15
13
  import host from './host';
16
14
  import network from './network';
17
- import pool from './pool';
18
15
  import tenants from './tenants/tenants';
19
16
  import tablet from './tablet';
20
17
  import topic from './topic';
@@ -42,19 +39,16 @@ export const rootReducer = {
42
39
  singleClusterMode,
43
40
  nodes,
44
41
  cluster,
42
+ clusterNodes,
45
43
  tenant,
46
44
  storage,
47
45
  node,
48
- pdisk,
49
- vdisk,
50
- group,
51
46
  tooltip,
52
47
  tablets,
53
48
  schema,
54
49
  olapStats,
55
50
  host,
56
51
  network,
57
- pool,
58
52
  tenants,
59
53
  tablet,
60
54
  topic,
@@ -15,7 +15,7 @@ const SET_DATA_WAS_NOT_LOADED = 'partitions/SET_DATA_WAS_NOT_LOADED';
15
15
  const initialState = {
16
16
  loading: false,
17
17
  wasLoaded: false,
18
- selectedConsumer: undefined,
18
+ selectedConsumer: '',
19
19
  };
20
20
 
21
21
  const partitions: Reducer<PartitionsState, PartitionsAction> = (state = initialState, action) => {
@@ -63,7 +63,7 @@ const partitions: Reducer<PartitionsState, PartitionsAction> = (state = initialS
63
63
  }
64
64
  };
65
65
 
66
- export const setSelectedConsumer = (value?: string) => {
66
+ export const setSelectedConsumer = (value: string) => {
67
67
  return {
68
68
  type: SET_SELECTED_CONSUMER,
69
69
  data: value,
@@ -36,7 +36,7 @@ export interface PreparedPartitionData {
36
36
  export interface PartitionsState {
37
37
  loading: boolean;
38
38
  wasLoaded: boolean;
39
- selectedConsumer: string | undefined;
39
+ selectedConsumer: string;
40
40
  partitions?: PreparedPartitionData[];
41
41
  error?: IResponseError;
42
42
  }
@@ -0,0 +1,5 @@
1
+ import type {VersionToColorMap} from './versions';
2
+
3
+ export interface AdditionalVersionsProps {
4
+ getVersionToColorMap?: () => VersionToColorMap;
5
+ }
@@ -0,0 +1,9 @@
1
+ export type VersionsMap = Map<string, Set<string>>;
2
+ export type VersionToColorMap = Map<string, string>;
3
+
4
+ export interface VersionValue {
5
+ value: number;
6
+ color: string | undefined;
7
+ version: string;
8
+ title: string;
9
+ }
@@ -2,9 +2,6 @@ import DataTable from '@gravity-ui/react-data-table';
2
2
 
3
3
  const SECOND = 1000;
4
4
 
5
- export const GROUP_AUTO_RELOAD_INTERVAL = 10 * SECOND;
6
- export const PDISK_AUTO_RELOAD_INTERVAL = 10 * SECOND;
7
- export const VDISK_AUTO_RELOAD_INTERVAL = 10 * SECOND;
8
5
  export const AUTO_RELOAD_INTERVAL = 10 * SECOND;
9
6
  // by agreement, display all byte values in decimal scale
10
7
  // values in data are always in bytes, never in higher units,
@@ -13,7 +10,6 @@ export const KILOBYTE = 1_000;
13
10
  export const MEGABYTE = 1_000_000;
14
11
  export const GIGABYTE = 1_000_000_000;
15
12
  export const TERABYTE = 1_000_000_000_000;
16
- export const GROUP = 'group';
17
13
 
18
14
  export const MINUTE_IN_SECONDS = 60;
19
15
  export const HOUR_IN_SECONDS = 60 * MINUTE_IN_SECONDS;
@@ -43,8 +39,6 @@ export const TABLET_COLORS = {
43
39
  Active: 'lightgreen',
44
40
  };
45
41
 
46
- export const TxAllocator = 'TxAllocator';
47
-
48
42
  export const TABLET_SYMBOLS = {
49
43
  OldTxProxy: 'P',
50
44
  TxProxy: 'P',
@@ -72,11 +66,6 @@ export const getTabletLabel = (type?: string) => {
72
66
 
73
67
  export const LOAD_AVERAGE_TIME_INTERVALS = ['1 min', '5 min', '15 min'];
74
68
 
75
- export const PDISK_CATEGORIES = {
76
- 0: 'HDD',
77
- 1: 'SSD',
78
- };
79
-
80
69
  export const COLORS_PRIORITY = {
81
70
  green: 5,
82
71
  yellow: 4,
@@ -5,16 +5,18 @@ import {getParsedSettingValue, setSettingValue} from '../../store/reducers/setti
5
5
 
6
6
  import {useTypedSelector} from './useTypedSelector';
7
7
 
8
- export const useSetting = <T>(key: string, defaultValue: T): [T, (value: T) => void] => {
8
+ export const useSetting = <T>(key: string, defaultValue?: T): [T, (value: T) => void] => {
9
9
  const dispatch = useDispatch();
10
10
 
11
11
  const settingValue: T = useTypedSelector(
12
- (state) => getParsedSettingValue(state, key) || defaultValue,
12
+ (state) => getParsedSettingValue(state, key) ?? defaultValue,
13
13
  );
14
14
 
15
15
  const setValue = useCallback(
16
16
  (value: T) => {
17
- dispatch(setSettingValue(key, JSON.stringify(value)));
17
+ const preparedValue = typeof value === 'string' ? value : JSON.stringify(value);
18
+
19
+ dispatch(setSettingValue(key, preparedValue));
18
20
  },
19
21
  [dispatch, key],
20
22
  );
@@ -0,0 +1,98 @@
1
+ import type {VersionToColorMap, VersionsMap} from '../../types/versions';
2
+
3
+ import {getMajorVersion, getMinorVersion} from './parseVersion';
4
+
5
+ export const hashCode = (s: string) => {
6
+ return s.split('').reduce((a, b) => {
7
+ const num = (a << 5) - a + b.charCodeAt(0); // eslint-disable-line
8
+ return num & num; // eslint-disable-line
9
+ }, 0);
10
+ };
11
+
12
+ // 11 distinct colors from https://mokole.com/palette.html
13
+ export const COLORS = [
14
+ '#008000', // green
15
+ '#4169e1', // royalblue
16
+ '#ffd700', // gold
17
+ '#ff8c00', // darkorange
18
+ '#808000', // olive
19
+ '#e9967a', // darksalmon
20
+ '#ff1493', // deeppink
21
+ '#00bfff', // deepskyblue
22
+ '#da70d6', // orchid
23
+ '#3cb371', // mediumseagreen
24
+ '#b22222', // firebrick
25
+ ];
26
+
27
+ export const GRAY_COLOR = '#bfbfbf'; // --yc-color-base-neutral-hover
28
+
29
+ export const getVersionsMap = (versions: string[], initialMap: VersionsMap = new Map()) => {
30
+ versions.forEach((version) => {
31
+ const majorVersion = getMajorVersion(version);
32
+ const minorVersion = getMinorVersion(version);
33
+ if (!initialMap.has(majorVersion)) {
34
+ initialMap.set(majorVersion, new Set());
35
+ }
36
+ initialMap.get(majorVersion)?.add(minorVersion);
37
+ });
38
+ return initialMap;
39
+ };
40
+
41
+ export const getVersionToColorMap = (versionsMap: VersionsMap) => {
42
+ const clustersVersions = Array.from(versionsMap.keys()).map((version) => {
43
+ return {
44
+ version,
45
+ hash: hashCode(version),
46
+ };
47
+ });
48
+
49
+ const versionToColor: VersionToColorMap = new Map();
50
+ // not every version is colored, therefore iteration index can't be used consistently
51
+ // init with the colors length to put increment right after condition for better readability
52
+ let currentColorIndex = COLORS.length - 1;
53
+
54
+ clustersVersions
55
+ // ascending by version name, just for consistency
56
+ // sorting only impacts color choose for a version
57
+ .sort((a, b) => a.hash - b.hash)
58
+ .forEach((item) => {
59
+ if (/^(\w+-)?stable/.test(item.version)) {
60
+ currentColorIndex = (currentColorIndex + 1) % COLORS.length;
61
+
62
+ versionToColor.set(item.version, COLORS[currentColorIndex]);
63
+
64
+ const minors = Array.from(versionsMap.get(item.version) || [])
65
+ .filter((v) => v !== item.version)
66
+ .map((v) => {
67
+ return {
68
+ version: v,
69
+ hash: hashCode(v),
70
+ };
71
+ });
72
+
73
+ const minorQuantity = minors.length;
74
+
75
+ minors
76
+ // descending by version name: newer versions come first,
77
+ // so the newer version gets the brighter color
78
+ .sort((a, b) => b.hash - a.hash)
79
+ .forEach((minor, minorIndex) => {
80
+ const majorColor = COLORS[currentColorIndex];
81
+ const opacityPercent = Math.max(
82
+ 100 - minorIndex * (100 / minorQuantity),
83
+ 20,
84
+ );
85
+ const hexOpacity = Math.round((opacityPercent * 255) / 100).toString(16);
86
+ const versionColor = `${majorColor}${hexOpacity}`;
87
+ versionToColor.set(minor.version, versionColor);
88
+ });
89
+ } else {
90
+ versionToColor.set(item.version, GRAY_COLOR);
91
+ }
92
+ });
93
+ return versionToColor;
94
+ };
95
+
96
+ export const parseVersionsToVersionToColorMap = (versions: string[] = []) => {
97
+ return getVersionToColorMap(getVersionsMap(versions));
98
+ };
@@ -0,0 +1,3 @@
1
+ export * from './getVersionsColors';
2
+ export * from './parseVersion';
3
+ export * from './parseNodesToVersionsValues';
@@ -0,0 +1,28 @@
1
+ import type {TSystemStateInfo} from '../../types/api/nodes';
2
+ import type {VersionToColorMap, VersionValue} from '../../types/versions';
3
+ import {getMinorVersion} from './parseVersion';
4
+
5
+ export const parseNodesToVersionsValues = (
6
+ nodes: TSystemStateInfo[] = [],
7
+ versionsToColor?: VersionToColorMap,
8
+ ): VersionValue[] => {
9
+ const versionsCount = nodes.reduce<Record<string, number>>((acc, node) => {
10
+ if (node.Version) {
11
+ if (acc[node.Version]) {
12
+ acc[node.Version] = acc[node.Version] + 1;
13
+ } else {
14
+ acc[node.Version] = 1;
15
+ }
16
+ }
17
+ return acc;
18
+ }, {});
19
+
20
+ return Object.keys(versionsCount).map((version) => {
21
+ return {
22
+ title: version,
23
+ version: version,
24
+ color: versionsToColor?.get(getMinorVersion(version)),
25
+ value: (versionsCount[version] / nodes.length) * 100,
26
+ };
27
+ });
28
+ };
@@ -0,0 +1,23 @@
1
+ export const getMinorVersion = (version: string) => {
2
+ const regexp = /\d{1,}-\d{1,}(-\d){0,}(-hotfix-\d{1,}(-\d{1,})?)?\.[0-9a-zA-Z]+$/;
3
+
4
+ let result = version;
5
+
6
+ if (regexp.test(version)) {
7
+ result = result.replace(/(-hotfix-\d{1,}(-\d{1,})?)?\.[0-9a-zA-Z]+$/, ''); // stable-19-2-18.bfa368f -> stable-19-2-18
8
+ }
9
+
10
+ const buildVersionRegexp = /\d{1,}-\d{1,}-\d{1,}-\d{1,}$/;
11
+ if (buildVersionRegexp.test(version)) {
12
+ result = result.replace(/-\d{1,}$/, ''); // stable-19-2-18-1 -> stable-19-2-18
13
+ }
14
+
15
+ return result;
16
+ };
17
+
18
+ export const getMajorVersion = (version: string) => {
19
+ const minorVersion = getMinorVersion(version);
20
+ const regexp = /\d{1,}-\d{1,}-\d{1,}/; // to check versions that have minor part
21
+
22
+ return regexp.test(minorVersion) ? minorVersion.replace(/-\d{1,}$/, '') : minorVersion;
23
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ydb-embedded-ui",
3
- "version": "4.3.0",
3
+ "version": "4.4.1",
4
4
  "files": [
5
5
  "dist"
6
6
  ],
@@ -1,239 +0,0 @@
1
- import React, {ReactNode} from 'react';
2
- import cn from 'bem-cn-lite';
3
- import {connect} from 'react-redux';
4
- import {Link, Loader} from '@gravity-ui/uikit';
5
-
6
- //@ts-ignore
7
- import EntityStatus from '../EntityStatus/EntityStatus';
8
- //@ts-ignore
9
- import ProgressViewer from '../ProgressViewer/ProgressViewer';
10
- //@ts-ignore
11
- import InfoViewer from '../InfoViewer/InfoViewer';
12
- import {Tags} from '../Tags';
13
- import {Tablet} from '../Tablet';
14
-
15
- //@ts-ignore
16
- import {hideTooltip, showTooltip} from '../../store/reducers/tooltip';
17
- //@ts-ignore
18
- import {getClusterInfo} from '../../store/reducers/cluster/cluster';
19
- //@ts-ignore
20
- import {clusterName, backend, customBackend} from '../../store';
21
-
22
- //@ts-ignore
23
- import {formatStorageValues} from '../../utils';
24
- //@ts-ignore
25
- import {TxAllocator} from '../../utils/constants';
26
- import {AutoFetcher} from '../../utils/autofetcher';
27
- import {Icon} from '../Icon';
28
- import {setHeader} from '../../store/reducers/header';
29
- import routes, {CLUSTER_PAGES, createHref} from '../../routes';
30
-
31
- import type {TClusterInfo} from '../../types/api/cluster';
32
- import type {TTabletStateInfo} from '../../types/api/tablet';
33
-
34
- import './ClusterInfo.scss';
35
-
36
- const b = cn('cluster-info');
37
-
38
- export interface IClusterInfoItem {
39
- label: string;
40
- value: ReactNode;
41
- }
42
-
43
- interface ClusterInfoProps {
44
- className?: string;
45
- cluster?: TClusterInfo;
46
- hideTooltip: VoidFunction;
47
- showTooltip: (...args: Parameters<typeof showTooltip>) => void;
48
- setHeader: any;
49
- getClusterInfo: (clusterName: string) => void;
50
- clusterTitle?: string;
51
- additionalClusterInfo?: IClusterInfoItem[];
52
- loading: boolean;
53
- singleClusterMode: boolean;
54
- wasLoaded: boolean;
55
- error?: {statusText: string};
56
- }
57
-
58
- class ClusterInfo extends React.Component<ClusterInfoProps> {
59
- static compareTablets(tablet1: TTabletStateInfo, tablet2: TTabletStateInfo) {
60
- if (tablet1.Type === TxAllocator) {
61
- return 1;
62
- }
63
-
64
- if (tablet2.Type === TxAllocator) {
65
- return -1;
66
- }
67
-
68
- return 0;
69
- }
70
-
71
- private autofetcher: any;
72
-
73
- componentDidMount() {
74
- const {setHeader} = this.props;
75
- setHeader([
76
- {
77
- text: CLUSTER_PAGES.cluster.title,
78
- link: createHref(routes.cluster, {activeTab: CLUSTER_PAGES.cluster.id}),
79
- },
80
- ]);
81
- this.props.getClusterInfo(clusterName);
82
- this.autofetcher = new AutoFetcher();
83
- this.autofetcher.fetch(() => this.props.getClusterInfo(clusterName));
84
- }
85
-
86
- shouldComponentUpdate(nextProps: ClusterInfoProps) {
87
- const {cluster = {}} = nextProps;
88
- return !(Object.keys(cluster).length === 0);
89
- }
90
-
91
- componentWillUnmount() {
92
- this.autofetcher.stop();
93
- }
94
-
95
- renderLoader() {
96
- return (
97
- <div className={b('loader')}>
98
- <Loader size="l" />
99
- </div>
100
- );
101
- }
102
-
103
- render() {
104
- const {className, error} = this.props;
105
- let helper;
106
- if (error) {
107
- helper = error.statusText;
108
- }
109
- return <div className={b(null, className)}>{helper || this.renderContent()}</div>;
110
- }
111
-
112
- private getInfo() {
113
- const {cluster = {}, additionalClusterInfo = [], singleClusterMode} = this.props;
114
- const {StorageTotal, StorageUsed} = cluster;
115
-
116
- let link = backend + '/internal';
117
-
118
- if (singleClusterMode && !customBackend) {
119
- link = `/internal`;
120
- }
121
-
122
- const info: IClusterInfoItem[] = [
123
- {
124
- label: 'Nodes',
125
- value: (
126
- <ProgressViewer
127
- className={b('metric-field')}
128
- value={cluster.NodesAlive}
129
- capacity={cluster.NodesTotal}
130
- />
131
- ),
132
- },
133
- {
134
- label: 'Load',
135
- value: (
136
- <ProgressViewer
137
- className={b('metric-field')}
138
- value={cluster.LoadAverage}
139
- capacity={cluster.NumberOfCpus}
140
- />
141
- ),
142
- },
143
- {
144
- label: 'Storage',
145
- value: (
146
- <ProgressViewer
147
- className={b('metric-field')}
148
- value={StorageUsed}
149
- capacity={StorageTotal}
150
- formatValues={formatStorageValues}
151
- />
152
- ),
153
- },
154
- {
155
- label: 'Versions',
156
- value: <div>{cluster.Versions?.join(', ')}</div>,
157
- },
158
- ...additionalClusterInfo,
159
- {
160
- label: 'Internal viewer',
161
- value: (
162
- <Link href={link} target="_blank">
163
- <Icon name="external" viewBox={'0 0 16 16'} width={16} height={16} />
164
- </Link>
165
- ),
166
- },
167
- ];
168
-
169
- return info;
170
- }
171
-
172
- private renderContent = () => {
173
- const {
174
- cluster = {},
175
- showTooltip,
176
- hideTooltip,
177
- clusterTitle,
178
- loading,
179
- wasLoaded,
180
- } = this.props;
181
- const {Name: clusterName = 'Unknown cluster'} = cluster;
182
-
183
- const info = this.getInfo();
184
-
185
- return loading && !wasLoaded ? (
186
- this.renderLoader()
187
- ) : (
188
- <React.Fragment>
189
- <div className={b('common')}>
190
- <div className={b('url')}>
191
- <EntityStatus
192
- size="m"
193
- status={cluster.Overall}
194
- name={clusterTitle ?? clusterName}
195
- />
196
- </div>
197
-
198
- {cluster.DataCenters && <Tags tags={cluster.DataCenters} />}
199
-
200
- <div className={b('system-tablets')}>
201
- {cluster.SystemTablets &&
202
- cluster.SystemTablets.sort(ClusterInfo.compareTablets).map(
203
- (tablet, tabletIndex) => (
204
- <Tablet
205
- onMouseEnter={showTooltip}
206
- onMouseLeave={hideTooltip}
207
- key={tabletIndex}
208
- tablet={tablet}
209
- />
210
- ),
211
- )}
212
- </div>
213
- </div>
214
- <InfoViewer dots={true} info={info} />
215
- </React.Fragment>
216
- );
217
- };
218
- }
219
-
220
- const mapStateToProps = (state: any) => {
221
- const {data: cluster, loading, error, wasLoaded} = state.cluster;
222
-
223
- return {
224
- cluster,
225
- loading,
226
- wasLoaded,
227
- error,
228
- singleClusterMode: state.singleClusterMode,
229
- };
230
- };
231
-
232
- const mapDispatchToProps = {
233
- getClusterInfo,
234
- hideTooltip,
235
- showTooltip,
236
- setHeader,
237
- };
238
-
239
- export default connect(mapStateToProps, mapDispatchToProps)(ClusterInfo);