@@ -10,6 +10,7 @@ import {Tablet} from '../../../components/Tablet';
1010import { ResponseError } from '../../../components/Errors/ResponseError' ;
1111import { ExternalLinkWithIcon } from '../../../components/ExternalLinkWithIcon/ExternalLinkWithIcon' ;
1212import { IconWrapper as Icon } from '../../../components/Icon/Icon' ;
13+ import { ContentWithPopup } from '../../../components/ContentWithPopup/ContentWithPopup' ;
1314
1415import type { IResponseError } from '../../../types/api/error' ;
1516import type { AdditionalClusterProps , ClusterLink } from '../../../types/additionalProps' ;
@@ -18,39 +19,122 @@ import type {TClusterInfo} from '../../../types/api/cluster';
1819import { backend , customBackend } from '../../../store' ;
1920import { formatStorageValues } from '../../../utils/dataFormatters/dataFormatters' ;
2021import { useSetting , useTypedSelector } from '../../../utils/hooks' ;
22+ import { formatBytes , getSizeWithSignificantDigits } from '../../../utils/bytesParsers' ;
2123import {
2224 CLUSTER_DEFAULT_TITLE ,
2325 CLUSTER_INFO_HIDDEN_KEY ,
2426 DEVELOPER_UI_TITLE ,
2527} from '../../../utils/constants' ;
28+ import type {
29+ ClusterGroupsStats ,
30+ DiskErasureGroupsStats ,
31+ DiskGroupsStats ,
32+ } from '../../../store/reducers/cluster/types' ;
2633
2734import { VersionsBar } from '../VersionsBar/VersionsBar' ;
2835import { ClusterInfoSkeleton } from '../ClusterInfoSkeleton/ClusterInfoSkeleton' ;
36+ import i18n from '../i18n' ;
2937
3038import { compareTablets } from './utils' ;
3139
3240import './ClusterInfo.scss' ;
3341
3442const b = block ( 'cluster-info' ) ;
3543
44+ interface GroupsStatsPopupContentProps {
45+ stats : DiskErasureGroupsStats ;
46+ }
47+
48+ const GroupsStatsPopupContent = ( { stats} : GroupsStatsPopupContentProps ) => {
49+ const { diskType, erasure, allocatedSize, availableSize} = stats ;
50+
51+ const sizeToConvert = getSizeWithSignificantDigits ( Math . max ( allocatedSize , availableSize ) , 2 ) ;
52+
53+ const convertedAllocatedSize = formatBytes ( { value : allocatedSize , size : sizeToConvert } ) ;
54+ const convertedAvailableSize = formatBytes ( { value : availableSize , size : sizeToConvert } ) ;
55+
56+ const usage = Math . round ( ( allocatedSize / ( allocatedSize + availableSize ) ) * 100 ) ;
57+
58+ const info = [
59+ {
60+ label : i18n ( 'disk-type' ) ,
61+ value : diskType ,
62+ } ,
63+ {
64+ label : i18n ( 'erasure' ) ,
65+ value : erasure ,
66+ } ,
67+ {
68+ label : i18n ( 'allocated' ) ,
69+ value : convertedAllocatedSize ,
70+ } ,
71+ {
72+ label : i18n ( 'available' ) ,
73+ value : convertedAvailableSize ,
74+ } ,
75+ {
76+ label : i18n ( 'usage' ) ,
77+ value : usage + '%' ,
78+ } ,
79+ ] ;
80+
81+ return (
82+ < InfoViewer dots = { true } info = { info } className = { b ( 'groups-stats-popup-content' ) } size = "s" />
83+ ) ;
84+ } ;
85+
86+ interface DiskGroupsStatsProps {
87+ stats : DiskGroupsStats ;
88+ }
89+
90+ const DiskGroupsStatsBars = ( { stats} : DiskGroupsStatsProps ) => {
91+ return (
92+ < div className = { b ( 'storage-groups-stats' ) } >
93+ { Object . values ( stats ) . map ( ( erasureStats ) => (
94+ < ContentWithPopup
95+ placement = { [ 'right' ] }
96+ key = { erasureStats . erasure }
97+ content = { < GroupsStatsPopupContent stats = { erasureStats } /> }
98+ >
99+ < ProgressViewer
100+ className = { b ( 'groups-stats-bar' ) }
101+ value = { erasureStats . createdGroups }
102+ capacity = { erasureStats . totalGroups }
103+ />
104+ </ ContentWithPopup >
105+ ) ) }
106+ </ div >
107+ ) ;
108+ } ;
109+
110+ const getGroupsStatsFields = ( groupsStats : ClusterGroupsStats ) => {
111+ return Object . keys ( groupsStats ) . map ( ( diskType ) => {
112+ return {
113+ label : i18n ( 'storage-groups' , { diskType} ) ,
114+ value : < DiskGroupsStatsBars stats = { groupsStats [ diskType ] } /> ,
115+ } ;
116+ } ) ;
117+ } ;
118+
36119const getInfo = (
37120 cluster : TClusterInfo ,
38121 versionsValues : VersionValue [ ] ,
122+ groupsStats : ClusterGroupsStats ,
39123 additionalInfo : InfoViewerItem [ ] ,
40124 links : ClusterLink [ ] ,
41125) => {
42126 const info : InfoViewerItem [ ] = [ ] ;
43127
44128 if ( cluster . DataCenters ) {
45129 info . push ( {
46- label : 'DC' ,
130+ label : i18n ( 'dc' ) ,
47131 value : < Tags tags = { cluster . DataCenters } /> ,
48132 } ) ;
49133 }
50134
51135 if ( cluster . SystemTablets ) {
52136 info . push ( {
53- label : 'Tablets' ,
137+ label : i18n ( 'tablets' ) ,
54138 value : (
55139 < div className = { b ( 'system-tablets' ) } >
56140 { cluster . SystemTablets . sort ( compareTablets ) . map ( ( tablet , tabletIndex ) => (
@@ -63,46 +147,40 @@ const getInfo = (
63147
64148 if ( cluster . Tenants ) {
65149 info . push ( {
66- label : 'Databases' ,
150+ label : i18n ( 'databases' ) ,
67151 value : cluster . Tenants ,
68152 } ) ;
69153 }
70154
71155 info . push (
72156 {
73- label : 'Nodes' ,
74- value : (
75- < ProgressViewer
76- className = { b ( 'metric-field' ) }
77- value = { cluster ?. NodesAlive }
78- capacity = { cluster ?. NodesTotal }
79- />
80- ) ,
157+ label : i18n ( 'nodes' ) ,
158+ value : < ProgressViewer value = { cluster ?. NodesAlive } capacity = { cluster ?. NodesTotal } /> ,
81159 } ,
82160 {
83- label : 'Load' ,
84- value : (
85- < ProgressViewer
86- className = { b ( 'metric-field' ) }
87- value = { cluster ?. LoadAverage }
88- capacity = { cluster ?. NumberOfCpus }
89- />
90- ) ,
161+ label : i18n ( 'load' ) ,
162+ value : < ProgressViewer value = { cluster ?. LoadAverage } capacity = { cluster ?. NumberOfCpus } /> ,
91163 } ,
92164 {
93- label : 'Storage' ,
165+ label : i18n ( 'storage-size' ) ,
94166 value : (
95167 < ProgressViewer
96- className = { b ( 'metric-field' ) }
97168 value = { cluster ?. StorageUsed }
98169 capacity = { cluster ?. StorageTotal }
99170 formatValues = { formatStorageValues }
100171 />
101172 ) ,
102173 } ,
174+ ) ;
175+
176+ if ( Object . keys ( groupsStats ) . length ) {
177+ info . push ( ...getGroupsStatsFields ( groupsStats ) ) ;
178+ }
179+
180+ info . push (
103181 ...additionalInfo ,
104182 {
105- label : 'Links' ,
183+ label : i18n ( 'links' ) ,
106184 value : (
107185 < div className = { b ( 'links' ) } >
108186 { links . map ( ( { title, url} ) => (
@@ -112,7 +190,7 @@ const getInfo = (
112190 ) ,
113191 } ,
114192 {
115- label : 'Versions' ,
193+ label : i18n ( 'versions' ) ,
116194 value : < VersionsBar versionsValues = { versionsValues } /> ,
117195 } ,
118196 ) ;
@@ -123,6 +201,7 @@ const getInfo = (
123201interface ClusterInfoProps {
124202 cluster ?: TClusterInfo ;
125203 versionsValues ?: VersionValue [ ] ;
204+ groupsStats ?: ClusterGroupsStats ;
126205 loading ?: boolean ;
127206 error ?: IResponseError ;
128207 additionalClusterProps ?: AdditionalClusterProps ;
@@ -131,6 +210,7 @@ interface ClusterInfoProps {
131210export const ClusterInfo = ( {
132211 cluster = { } ,
133212 versionsValues = [ ] ,
213+ groupsStats = { } ,
134214 loading,
135215 error,
136216 additionalClusterProps = { } ,
@@ -151,7 +231,7 @@ export const ClusterInfo = ({
151231
152232 const { info = [ ] , links = [ ] } = additionalClusterProps ;
153233
154- const clusterInfo = getInfo ( cluster , versionsValues , info , [
234+ const clusterInfo = getInfo ( cluster , versionsValues , groupsStats , info , [
155235 { title : DEVELOPER_UI_TITLE , url : internalLink } ,
156236 ...links ,
157237 ] ) ;
0 commit comments