1
- import { useEffect , useRef , useState , useMemo } from 'react' ;
1
+ import { useEffect , useRef , useMemo } from 'react' ;
2
2
import { useDispatch , useSelector } from 'react-redux' ;
3
3
import url from 'url' ;
4
4
import _ from 'lodash' ;
5
5
6
6
import cn from 'bem-cn-lite' ;
7
7
8
- import { ArrowToggle , Button , Loader , Tooltip } from '@yandex-cloud/uikit' ;
9
- import DataTable , { Column , Settings } from '@yandex-cloud/react-data-table' ;
8
+ import { Loader } from '@yandex-cloud/uikit' ;
10
9
11
- import EntityStatus from '../../../components/EntityStatus/EntityStatus' ;
12
- import InfoViewer from '../../../components/InfoViewer/InfoViewer' ;
13
- import ProgressViewer from '../../../components/ProgressViewer/ProgressViewer' ;
14
- import Icon from '../../../components/Icon/Icon' ;
15
- //@ts -ignore
16
- import { Vdisk } from '../../VdiskPdiskNode/VdiskPdiskNode' ;
17
-
18
- import { bytesToGB , pad9 } from '../../../utils/utils' ;
19
- import { formatStorageValuesToGb } from '../../../utils' ;
10
+ import { PDisk } from './Pdisk' ;
20
11
21
12
import { getNodeStructure , selectNodeStructure } from '../../../store/reducers/node' ;
22
13
@@ -26,284 +17,14 @@ import './NodeStructure.scss';
26
17
27
18
const b = cn ( 'kv-node-structure' ) ;
28
19
29
- function valueIsDefined ( value : any ) {
20
+ export function valueIsDefined ( value : any ) {
30
21
return value !== null && value !== undefined ;
31
22
}
32
23
33
24
function generateId ( { type, id} : { type : 'pdisk' | 'vdisk' ; id : string } ) {
34
25
return `${ type } -${ id } ` ;
35
26
}
36
27
37
- interface PDiskProps {
38
- data : Record < string , any > ;
39
- unfolded ?: boolean ;
40
- id : string ;
41
- selectedVdiskId ?: string ;
42
- nodeHref ?: string ;
43
- }
44
-
45
- enum VDiskTableColumnsIds {
46
- slotId = 'VDiskSlotId' ,
47
- VDiskState = 'VDiskState' ,
48
- Size = 'Size' ,
49
- Info = 'Info' ,
50
- }
51
-
52
- type VDiskTableColumnsIdsKeys = keyof typeof VDiskTableColumnsIds ;
53
- type VDiskTableColumnsIdsValues = typeof VDiskTableColumnsIds [ VDiskTableColumnsIdsKeys ] ;
54
-
55
- const vDiskTableColumnsNames : Record < VDiskTableColumnsIdsValues , string > = {
56
- VDiskSlotId : 'Slot id' ,
57
- VDiskState : 'Status' ,
58
- Size : 'Size' ,
59
- Info : '' ,
60
- } ;
61
-
62
- function getColumns ( {
63
- pDiskId,
64
- selectedVdiskId,
65
- nodeHref,
66
- } : {
67
- pDiskId : number ;
68
- selectedVdiskId ?: string ;
69
- nodeHref ?: string ;
70
- } ) {
71
- const columns : Column < any > [ ] = [
72
- {
73
- name : VDiskTableColumnsIds . slotId as string ,
74
- header : vDiskTableColumnsNames [ VDiskTableColumnsIds . slotId ] ,
75
- width : 100 ,
76
- render : ( { value, row} ) => {
77
- let vdiskInternalViewerLink : string | undefined ;
78
-
79
- if ( nodeHref && value !== undefined ) {
80
- vdiskInternalViewerLink +=
81
- nodeHref + '/actors/vdisks/vdisk' + pad9 ( pDiskId ) + '_' + pad9 ( value ) ;
82
- }
83
-
84
- return (
85
- < div className = { b ( 'vdisk-id' , { selected : row . id === selectedVdiskId } ) } >
86
- < span > { value as any } </ span >
87
- { vdiskInternalViewerLink && (
88
- < Button
89
- size = "s"
90
- className = { b ( 'external-button' , { hidden : true } ) }
91
- href = { vdiskInternalViewerLink }
92
- target = "_blank"
93
- >
94
- < Icon name = "external" />
95
- </ Button >
96
- ) }
97
- </ div >
98
- ) ;
99
- } ,
100
- align : DataTable . LEFT ,
101
- } ,
102
- {
103
- name : VDiskTableColumnsIds . VDiskState as string ,
104
- header : vDiskTableColumnsNames [ VDiskTableColumnsIds . VDiskState ] ,
105
- width : 70 ,
106
- render : ( { value} ) => {
107
- return < EntityStatus status = { value === 'OK' ? 'green' : 'red' } /> ;
108
- } ,
109
- sortAccessor : ( row ) => ( row [ VDiskTableColumnsIds . VDiskState ] === 'OK' ? 1 : 0 ) ,
110
- align : DataTable . CENTER ,
111
- } ,
112
- {
113
- name : VDiskTableColumnsIds . Size as string ,
114
- header : vDiskTableColumnsNames [ VDiskTableColumnsIds . Size ] ,
115
- width : 100 ,
116
- render : ( { row} ) => {
117
- return (
118
- < ProgressViewer
119
- value = { row . AllocatedSize }
120
- capacity = { Number ( row . AllocatedSize ) + Number ( row . AvailableSize ) }
121
- formatValues = { formatStorageValuesToGb }
122
- colorizeProgress = { true }
123
- />
124
- ) ;
125
- } ,
126
- sortAccessor : ( row ) => Number ( row . AllocatedSize ) ,
127
- align : DataTable . CENTER ,
128
- } ,
129
- {
130
- name : VDiskTableColumnsIds . Info as string ,
131
- header : vDiskTableColumnsNames [ VDiskTableColumnsIds . Info ] ,
132
- width : 70 ,
133
- render : ( { row} ) => {
134
- return (
135
- < Tooltip
136
- placement = { [ 'right' ] }
137
- content = { < Vdisk { ...row } /> }
138
- contentClassName = { b ( 'vdisk-details' ) }
139
- >
140
- < Button
141
- view = "clear"
142
- className = { b ( 'vdisk-details-button' , {
143
- selected : row . id === selectedVdiskId ,
144
- } ) }
145
- >
146
- < Icon name = "information" viewBox = "0 0 512 512" height = { 16 } width = { 16 } />
147
- </ Button >
148
- </ Tooltip >
149
- ) ;
150
- } ,
151
- sortable : false ,
152
- } ,
153
- ] ;
154
- return columns ;
155
- }
156
-
157
- function PDisk ( props : PDiskProps ) {
158
- const [ unfolded , setUnfolded ] = useState ( props . unfolded ?? false ) ;
159
-
160
- const data = props . data ?? { } ;
161
-
162
- const onOpenPDiskDetails = ( ) => {
163
- setUnfolded ( true ) ;
164
- } ;
165
- const onClosePDiskDetails = ( ) => {
166
- setUnfolded ( false ) ;
167
- } ;
168
-
169
- const renderVDisks = ( ) => {
170
- const { selectedVdiskId, data, nodeHref} = props ;
171
- const { vDisks} = data ;
172
-
173
- return (
174
- < DataTable
175
- theme = "yandex-cloud"
176
- data = { vDisks }
177
- columns = { getColumns ( { nodeHref, pDiskId : data . PDiskId , selectedVdiskId} ) }
178
- settings = { { ...DEFAULT_TABLE_SETTINGS , dynamicRender : false } as Settings }
179
- rowClassName = { ( row ) => {
180
- return row . id === selectedVdiskId ? b ( 'selected-vdisk' ) : '' ;
181
- } }
182
- />
183
- ) ;
184
- } ;
185
-
186
- const renderPDiskDetails = ( ) => {
187
- if ( _ . isEmpty ( data ) ) {
188
- return < div > No information about PDisk</ div > ;
189
- }
190
- const { nodeHref} = props ;
191
- const {
192
- TotalSize,
193
- AvailableSize,
194
- Device,
195
- Guid,
196
- PDiskId,
197
- Path,
198
- Realtime,
199
- State,
200
- Category,
201
- SerialNumber,
202
- } = data ;
203
-
204
- let pDiskInternalViewerLink : string | undefined ;
205
-
206
- if ( nodeHref ) {
207
- pDiskInternalViewerLink += nodeHref + '/actors/pdisks/pdisk' + pad9 ( PDiskId ) ;
208
- }
209
-
210
- const pdiskInfo : any = [
211
- {
212
- label : 'PDisk Id' ,
213
- value : (
214
- < div className = { b ( 'pdisk-id' ) } >
215
- { PDiskId }
216
- { pDiskInternalViewerLink && (
217
- < Button
218
- size = "s"
219
- className = { b ( 'external-button' ) }
220
- href = { pDiskInternalViewerLink }
221
- target = "_blank"
222
- view = "clear"
223
- >
224
- < Icon name = "external" />
225
- </ Button >
226
- ) }
227
- </ div >
228
- ) ,
229
- } ,
230
- ] ;
231
- if ( valueIsDefined ( Path ) ) {
232
- pdiskInfo . push ( { label : 'Path' , value : Path } ) ;
233
- }
234
- if ( valueIsDefined ( Guid ) ) {
235
- pdiskInfo . push ( { label : 'GUID' , value : Guid } ) ;
236
- }
237
- if ( valueIsDefined ( Category ) ) {
238
- pdiskInfo . push ( { label : 'Category' , value : Category } ) ;
239
- }
240
- pdiskInfo . push ( {
241
- label : 'Allocated Size' ,
242
- value : bytesToGB ( TotalSize - AvailableSize ) ,
243
- } ) ;
244
- pdiskInfo . push ( {
245
- label : 'Available Size' ,
246
- value : bytesToGB ( AvailableSize ) ,
247
- } ) ;
248
- if ( Number ( TotalSize ) >= 0 && Number ( AvailableSize ) >= 0 ) {
249
- pdiskInfo . push ( {
250
- label : 'Size' ,
251
- value : (
252
- < ProgressViewer
253
- value = { TotalSize - AvailableSize }
254
- capacity = { TotalSize }
255
- formatValues = { formatStorageValuesToGb }
256
- colorizeProgress = { true }
257
- className = { b ( 'size' ) }
258
- />
259
- ) ,
260
- } ) ;
261
- }
262
- if ( valueIsDefined ( State ) ) {
263
- pdiskInfo . push ( { label : 'State' , value : State } ) ;
264
- }
265
- if ( valueIsDefined ( Device ) ) {
266
- pdiskInfo . push ( {
267
- label : 'Device' ,
268
- value : < EntityStatus status = { Device } /> ,
269
- } ) ;
270
- }
271
- if ( valueIsDefined ( Realtime ) ) {
272
- pdiskInfo . push ( {
273
- label : 'Realtime' ,
274
- value : < EntityStatus status = { Realtime } /> ,
275
- } ) ;
276
- }
277
- if ( valueIsDefined ( SerialNumber ) ) {
278
- pdiskInfo . push ( { label : 'SerialNumber' , value : SerialNumber } ) ;
279
- }
280
- return (
281
- < div >
282
- < InfoViewer className = { b ( 'pdisk-details' ) } info = { pdiskInfo } />
283
- < div className = { b ( 'vdisks-container' ) } >
284
- < div className = { b ( 'vdisks-header' ) } > VDisks</ div >
285
- { renderVDisks ( ) }
286
- </ div >
287
- </ div >
288
- ) ;
289
- } ;
290
-
291
- return (
292
- < div className = { b ( 'pdisk' ) } id = { props . id } >
293
- < div className = { b ( 'pdisk-header' ) } >
294
- < div className = { b ( 'pdisk-title-wrapper' ) } >
295
- < span > { data . Path } </ span >
296
- < EntityStatus status = { data . Device } name = { `${ data . NodeId } -${ data . PDiskId } ` } />
297
- </ div >
298
- < Button onClick = { unfolded ? onClosePDiskDetails : onOpenPDiskDetails } view = "clear" >
299
- < ArrowToggle direction = { unfolded ? 'top' : 'bottom' } />
300
- </ Button >
301
- </ div >
302
- { unfolded && renderPDiskDetails ( ) }
303
- </ div >
304
- ) ;
305
- }
306
-
307
28
interface NodeStructureProps {
308
29
nodeId : string ;
309
30
className ?: string ;
0 commit comments