11import React from 'react' ;
22
3- import { Flex } from '@gravity-ui/uikit' ;
3+ import { Flex , Label } from '@gravity-ui/uikit' ;
4+ import { isNil } from 'lodash' ;
45
56import { selectNodesMap } from '../../store/reducers/nodesList' ;
67import { EFlag } from '../../types/api/enums' ;
7- import { valueIsDefined } from '../../utils' ;
88import { EMPTY_DATA_PLACEHOLDER } from '../../utils/constants' ;
99import { createPDiskDeveloperUILink } from '../../utils/developerUI/developerUI' ;
10+ import { getStateSeverity } from '../../utils/disks/calculatePDiskSeverity' ;
11+ import { NUMERIC_SEVERITY_TO_LABEL_VIEW } from '../../utils/disks/constants' ;
1012import type { PreparedPDisk } from '../../utils/disks/types' ;
1113import { useTypedSelector } from '../../utils/hooks' ;
1214import { useDatabaseFromQuery } from '../../utils/hooks/useDatabaseFromQuery' ;
1315import { useIsUserAllowedToMakeChanges } from '../../utils/hooks/useIsUserAllowedToMakeChanges' ;
1416import { bytesToGB , isNumeric } from '../../utils/utils' ;
15- import { InfoViewer } from '../InfoViewer' ;
16- import type { InfoViewerItem } from '../InfoViewer' ;
1717import { LinkWithIcon } from '../LinkWithIcon/LinkWithIcon' ;
1818import { pDiskInfoKeyset } from '../PDiskInfo/i18n' ;
1919import { PDiskPageLink } from '../PDiskPageLink/PDiskPageLink' ;
20+ import { StatusIcon } from '../StatusIcon/StatusIcon' ;
21+ import type {
22+ YDBDefinitionListHeaderLabel ,
23+ YDBDefinitionListItem ,
24+ } from '../YDBDefinitionList/YDBDefinitionList' ;
25+ import { YDBDefinitionList } from '../YDBDefinitionList/YDBDefinitionList' ;
26+
27+ import { pDiskPopupKeyset } from './i18n' ;
2028
2129const errorColors = [ EFlag . Orange , EFlag . Red , EFlag . Yellow ] ;
2230
23- export const preparePDiskData = (
24- data : PreparedPDisk ,
25- nodeData ?: { Host ?: string ; DC ?: string } ,
26- withDeveloperUILink ?: boolean ,
27- ) => {
28- const {
29- AvailableSize,
30- TotalSize,
31- State,
32- PDiskId,
33- NodeId,
34- StringifiedId,
35- Path,
36- Realtime,
37- Type,
38- Device,
39- } = data ;
40-
41- const pdiskData : InfoViewerItem [ ] = [
42- {
43- label : 'PDisk' ,
44- value : StringifiedId ?? EMPTY_DATA_PLACEHOLDER ,
45- } ,
46- { label : 'State' , value : State || 'not available' } ,
47- { label : 'Type' , value : Type || 'unknown' } ,
31+ export const preparePDiskData = ( data : PreparedPDisk , nodeData ?: { Host ?: string ; DC ?: string } ) => {
32+ const { AvailableSize, TotalSize, NodeId, Path, Realtime, Type, Device} = data ;
33+
34+ const pdiskData : YDBDefinitionListItem [ ] = [
35+ { name : pDiskPopupKeyset ( 'label_type' ) , content : Type || pDiskPopupKeyset ( 'value_unknown' ) } ,
4836 ] ;
4937
5038 if ( NodeId ) {
51- pdiskData . push ( { label : 'Node Id' , value : NodeId } ) ;
39+ pdiskData . push ( { name : pDiskPopupKeyset ( 'label_node-id' ) , content : NodeId } ) ;
5240 }
5341
5442 if ( nodeData ?. Host ) {
55- pdiskData . push ( { label : 'Host' , value : nodeData . Host } ) ;
43+ pdiskData . push ( { name : pDiskPopupKeyset ( 'label_host' ) , content : nodeData . Host } ) ;
5644 }
45+
5746 if ( nodeData ?. DC ) {
58- pdiskData . push ( { label : 'DC' , value : nodeData . DC } ) ;
47+ pdiskData . push ( { name : pDiskPopupKeyset ( 'label_dc' ) , content : < Label > { nodeData . DC } </ Label > } ) ;
5948 }
6049
6150 if ( Path ) {
62- pdiskData . push ( { label : 'Path' , value : Path } ) ;
51+ pdiskData . push ( { name : pDiskPopupKeyset ( 'label_path' ) , content : Path } ) ;
6352 }
6453
65- if ( isNumeric ( TotalSize ) ) {
54+ if ( isNumeric ( TotalSize ) && isNumeric ( AvailableSize ) ) {
6655 pdiskData . push ( {
67- label : 'Available' ,
68- value : `${ bytesToGB ( AvailableSize ) } of ${ bytesToGB ( TotalSize ) } ` ,
56+ name : pDiskPopupKeyset ( 'label_available' ) ,
57+ content : `${ bytesToGB ( AvailableSize ) } ${ pDiskPopupKeyset ( 'value_of' ) } ${ bytesToGB ( TotalSize ) } ` ,
6958 } ) ;
7059 }
7160
7261 if ( Realtime && errorColors . includes ( Realtime ) ) {
73- pdiskData . push ( { label : 'Realtime' , value : Realtime } ) ;
62+ pdiskData . push ( {
63+ name : pDiskPopupKeyset ( 'label_realtime' ) ,
64+ content : < StatusIcon mode = "icons" status = { Realtime } /> ,
65+ } ) ;
7466 }
7567
7668 if ( Device && errorColors . includes ( Device ) ) {
77- pdiskData . push ( { label : 'Device' , value : Device } ) ;
69+ pdiskData . push ( {
70+ name : pDiskPopupKeyset ( 'label_device' ) ,
71+ content : < StatusIcon mode = "icons" status = { Device } /> ,
72+ } ) ;
7873 }
7974
80- if ( withDeveloperUILink && valueIsDefined ( NodeId ) && valueIsDefined ( PDiskId ) ) {
81- const pDiskInternalViewerPath = createPDiskDeveloperUILink ( {
82- nodeId : NodeId ,
83- pDiskId : PDiskId ,
75+ return pdiskData ;
76+ } ;
77+
78+ export const preparePDiskHeaderLabels = ( data : PreparedPDisk ) : YDBDefinitionListHeaderLabel [ ] => {
79+ const labels : YDBDefinitionListHeaderLabel [ ] = [ ] ;
80+ const { State} = data ;
81+
82+ if ( ! State ) {
83+ labels . push ( {
84+ id : 'state' ,
85+ value : pDiskPopupKeyset ( 'context_not-available' ) ,
8486 } ) ;
8587
86- pdiskData . push ( {
87- label : 'Links' ,
88- value : (
89- < Flex gap = { 2 } wrap = "wrap" >
90- < PDiskPageLink pDiskId = { PDiskId } nodeId = { NodeId } />
91- < LinkWithIcon
92- title = { pDiskInfoKeyset ( 'developer-ui' ) }
93- url = { pDiskInternalViewerPath }
94- />
95- </ Flex >
96- ) ,
88+ return labels ;
89+ }
90+
91+ if ( State ) {
92+ const severity = getStateSeverity ( State ) ;
93+ const { theme, icon} = NUMERIC_SEVERITY_TO_LABEL_VIEW [ severity ] ;
94+
95+ labels . push ( {
96+ id : 'state' ,
97+ value : State ,
98+ theme : theme ,
99+ icon : icon ,
97100 } ) ;
98101 }
99102
100- return pdiskData ;
103+ return labels ;
104+ } ;
105+
106+ export const buildPDiskFooter = (
107+ data : PreparedPDisk ,
108+ withDeveloperUILink ?: boolean ,
109+ ) : React . ReactNode | null => {
110+ const { NodeId, PDiskId} = data ;
111+
112+ if ( ! withDeveloperUILink || isNil ( NodeId ) || isNil ( PDiskId ) ) {
113+ return null ;
114+ }
115+
116+ const pDiskInternalViewerPath = createPDiskDeveloperUILink ( {
117+ nodeId : NodeId ,
118+ pDiskId : PDiskId ,
119+ } ) ;
120+
121+ return (
122+ < Flex gap = { 2 } wrap = "wrap" >
123+ < PDiskPageLink pDiskId = { PDiskId } nodeId = { NodeId } />
124+ < LinkWithIcon title = { pDiskInfoKeyset ( 'developer-ui' ) } url = { pDiskInternalViewerPath } />
125+ </ Flex >
126+ ) ;
101127} ;
102128
103129interface PDiskPopupProps {
@@ -108,11 +134,31 @@ export const PDiskPopup = ({data}: PDiskPopupProps) => {
108134 const database = useDatabaseFromQuery ( ) ;
109135 const isUserAllowedToMakeChanges = useIsUserAllowedToMakeChanges ( ) ;
110136 const nodesMap = useTypedSelector ( ( state ) => selectNodesMap ( state , database ) ) ;
111- const nodeData = valueIsDefined ( data . NodeId ) ? nodesMap ?. get ( data . NodeId ) : undefined ;
112- const info = React . useMemo (
113- ( ) => preparePDiskData ( data , nodeData , isUserAllowedToMakeChanges ) ,
114- [ data , nodeData , isUserAllowedToMakeChanges ] ,
137+ const nodeData = isNil ( data . NodeId ) ? undefined : nodesMap ?. get ( data . NodeId ) ;
138+
139+ const info = React . useMemo ( ( ) => preparePDiskData ( data , nodeData ) , [ data , nodeData ] ) ;
140+
141+ const headerLabels = React . useMemo < YDBDefinitionListHeaderLabel [ ] > (
142+ ( ) => preparePDiskHeaderLabels ( data ) ,
143+ [ data ] ,
144+ ) ;
145+
146+ const footer = React . useMemo (
147+ ( ) => buildPDiskFooter ( data , isUserAllowedToMakeChanges ) ,
148+ [ data , isUserAllowedToMakeChanges ] ,
115149 ) ;
116150
117- return < InfoViewer title = "PDisk" info = { info } size = "s" /> ;
151+ const pdiskId = data . StringifiedId ;
152+
153+ return (
154+ < YDBDefinitionList
155+ compact
156+ title = "PDisk"
157+ titleSuffix = { pdiskId ?? EMPTY_DATA_PLACEHOLDER }
158+ items = { info }
159+ headerLabels = { headerLabels }
160+ footer = { footer }
161+ nameMaxWidth = { 100 }
162+ />
163+ ) ;
118164} ;
0 commit comments