@@ -4,13 +4,18 @@ import cn from 'bem-cn-lite';
44import { InternalLink } from '../../../components/InternalLink' ;
55
66import routes , { createHref } from '../../../routes' ;
7+ import { getVDisksForPDisk } from '../../../store/reducers/storage' ;
78import { TPDiskStateInfo , TPDiskState } from '../../../types/api/pdisk' ;
9+ import { TVDiskStateInfo } from '../../../types/api/vdisk' ;
10+ import { stringifyVdiskId } from '../../../utils' ;
11+ import { useTypedSelector } from '../../../utils/hooks' ;
812import { getPDiskType } from '../../../utils/pdisk' ;
913
1014import { STRUCTURE } from '../../Node/NodePages' ;
1115
1216import { DiskStateProgressBar , EDiskStateSeverity } from '../DiskStateProgressBar' ;
1317import { PDiskPopup } from '../PDiskPopup' ;
18+ import { VDisk } from '../VDisk' ;
1419
1520import { NOT_AVAILABLE_SEVERITY } from '../utils' ;
1621
@@ -51,6 +56,12 @@ export const PDisk = ({nodeId, data: rawData = {}}: PDiskProps) => {
5156 // NodeId in data is required for the popup
5257 const data = useMemo ( ( ) => ( { ...rawData , NodeId : nodeId } ) , [ rawData , nodeId ] ) ;
5358
59+ const vdisks : TVDiskStateInfo [ ] | undefined = useTypedSelector ( ( state ) =>
60+ // @ts -expect-error selector is correct, but js infers broken type
61+ // unignore after rewriting reducer in ts
62+ getVDisksForPDisk ( state , nodeId , data . PDiskId ) ,
63+ ) ;
64+
5465 const [ severity , setSeverity ] = useState ( getStateSeverity ( data . State ) ) ;
5566 const [ isPopupVisible , setIsPopupVisible ] = useState ( false ) ;
5667
@@ -83,17 +94,44 @@ export const PDisk = ({nodeId, data: rawData = {}}: PDiskProps) => {
8394 : undefined ;
8495 } , [ data ] ) ;
8596
97+ const renderVDisks = ( ) => {
98+ if ( ! vdisks ?. length ) {
99+ return null ;
100+ }
101+
102+ return (
103+ < div className = { b ( 'vdisks' ) } >
104+ { vdisks . map ( ( vdisk ) => (
105+ < div
106+ key = { stringifyVdiskId ( vdisk . VDiskId ) }
107+ className = { b ( 'vdisks-item' ) }
108+ style = { {
109+ // 1 is small enough for empty disks to be of the minimum width
110+ // but if all of them are empty, `flex-grow: 1` would size them evenly
111+ flexGrow : ( Number ( vdisk . AllocatedSize ) || 1 ) ,
112+ } }
113+ >
114+ < VDisk data = { vdisk } compact />
115+ </ div >
116+ ) ) }
117+ </ div >
118+ ) ;
119+ } ;
120+
86121 return (
87122 < React . Fragment >
88123 < PDiskPopup data = { data } anchorRef = { anchor } open = { isPopupVisible } />
89- < div className = { b ( ) } ref = { anchor } onMouseEnter = { showPopup } onMouseLeave = { hidePopup } >
124+ < div className = { b ( ) } ref = { anchor } >
125+ { renderVDisks ( ) }
90126 < InternalLink
91127 to = { createHref (
92128 routes . node ,
93129 { id : nodeId , activeTab : STRUCTURE } ,
94130 { pdiskId : data . PDiskId || '' } ,
95131 ) }
96132 className = { b ( 'content' ) }
133+ onMouseEnter = { showPopup }
134+ onMouseLeave = { hidePopup }
97135 >
98136 < DiskStateProgressBar
99137 diskAllocatedPercent = { pdiskAllocatedPercent }
0 commit comments