3
3
* License: MS-RSL – see LICENSE.md for details
4
4
*/
5
5
6
+ // cspell:ignore Questionmark
7
+
6
8
declare let DEBUG ;
7
9
8
- import { InfoCircleOutlined , ScheduleOutlined } from "@ant-design/icons" ;
9
10
import { Alert , Button , Form , Modal , Popconfirm , Switch , Table } from "antd" ;
11
+ import { useEffect , useRef , useState } from "react" ;
12
+
13
+ import { InfoCircleOutlined , ScheduleOutlined } from "@ant-design/icons" ;
10
14
import { Col , Row } from "@cocalc/frontend/antd-bootstrap" ;
11
15
import { CSS , ProjectActions , redux } from "@cocalc/frontend/app-framework" ;
12
16
import { A , Loading , Tip } from "@cocalc/frontend/components" ;
13
17
import { SiteName } from "@cocalc/frontend/customize" ;
18
+ import { field_cmp , seconds2hms } from "@cocalc/util/misc" ;
19
+ import { COLORS } from "@cocalc/util/theme" ;
14
20
import {
15
21
Process ,
16
22
ProjectInfo as ProjectInfoType ,
17
23
} from "@cocalc/util/types/project-info/types" ;
18
- import { field_cmp , seconds2hms } from "@cocalc/util/misc " ;
19
- import { COLORS } from "@cocalc/util/theme " ;
24
+ import { useProjectContext } from "../context " ;
25
+ import { ROOT_STYLE } from "../servers/consts " ;
20
26
import { RestartProject } from "../settings/restart-project" ;
21
27
import {
22
28
AboutContent ,
@@ -28,7 +34,6 @@ import {
28
34
} from "./components" ;
29
35
import { CGroupInfo , DUState , PTStats , ProcessRow } from "./types" ;
30
36
import { DETAILS_BTN_TEXT , SSH_KEYS_DOC } from "./utils" ;
31
- import { ROOT_STYLE } from "../servers/consts" ;
32
37
33
38
interface Props {
34
39
any_alerts : ( ) => boolean ;
@@ -89,6 +94,53 @@ export function Full(props: Readonly<Props>): React.JSX.Element {
89
94
onCellProps,
90
95
} = props ;
91
96
97
+ const { contentSize } = useProjectContext ( ) ;
98
+
99
+ const problemsRef = useRef < HTMLDivElement > ( null ) ;
100
+ const cgroupRef = useRef < HTMLDivElement > ( null ) ;
101
+ const headerRef = useRef < HTMLDivElement > ( null ) ;
102
+ const explanationRef = useRef < HTMLDivElement > ( null ) ;
103
+ const generalStatusRef = useRef < HTMLDivElement > ( null ) ;
104
+ const [ tableHeight , setTableHeight ] = useState < number > ( 400 ) ;
105
+
106
+ useEffect ( ( ) => {
107
+ const calculateTableHeight = ( ) => {
108
+ const parentHeight = contentSize . height ;
109
+ if ( parentHeight === 0 ) return ; // Wait until contentSize is measured
110
+
111
+ let usedHeight = 0 ;
112
+
113
+ // Add height of ProjectProblems component
114
+ usedHeight += problemsRef . current ?. offsetHeight ?? 0 ;
115
+
116
+ // Add height of CGroup component
117
+ usedHeight += cgroupRef . current ?. offsetHeight ?? 0 ;
118
+
119
+ // Add height of header row
120
+ usedHeight += headerRef . current ?. offsetHeight ?? 0 ;
121
+
122
+ // Add height of explanation row if visible
123
+ usedHeight += explanationRef . current ?. offsetHeight ?? 0 ;
124
+
125
+ // Add height of general status row if DEBUG is enabled
126
+ if ( DEBUG ) {
127
+ usedHeight += generalStatusRef . current ?. offsetHeight ?? 0 ;
128
+ }
129
+
130
+ // Add more buffer for table header, margins, and other spacing
131
+ usedHeight += 100 ;
132
+
133
+ const availableHeight = Math . max ( 300 , parentHeight - usedHeight ) ;
134
+ setTableHeight ( availableHeight ) ;
135
+ } ;
136
+
137
+ calculateTableHeight ( ) ;
138
+
139
+ // Recalculate on window resize
140
+ window . addEventListener ( "resize" , calculateTableHeight ) ;
141
+ return ( ) => window . removeEventListener ( "resize" , calculateTableHeight ) ;
142
+ } , [ show_explanation , ptree , contentSize . height , contentSize . width ] ) ;
143
+
92
144
function render_help ( ) {
93
145
return (
94
146
< Form . Item label = "Help:" >
@@ -295,11 +347,16 @@ export function Full(props: Readonly<Props>): React.JSX.Element {
295
347
</ Tip >
296
348
) ;
297
349
298
- const table_style : CSS = { marginBottom : "2rem" } ;
350
+ const table_style : CSS = {
351
+ marginBottom : "2rem" ,
352
+ } ;
299
353
300
354
return (
301
355
< >
302
- < Row style = { { marginBottom : "10px" , marginTop : "20px" } } >
356
+ < Row
357
+ ref = { headerRef }
358
+ style = { { marginBottom : "10px" , marginTop : "20px" } }
359
+ >
303
360
< Col md = { 9 } >
304
361
< Form layout = "inline" >
305
362
< Form . Item label = "Table of Processes" />
@@ -314,13 +371,14 @@ export function Full(props: Readonly<Props>): React.JSX.Element {
314
371
</ Form >
315
372
</ Col >
316
373
</ Row >
317
- < Row > { render_explanation ( ) } </ Row >
374
+ < Row ref = { explanationRef } > { render_explanation ( ) } </ Row >
318
375
< Row >
319
376
< Table < ProcessRow >
377
+ key = { `table-${ contentSize . width } -${ contentSize . height } ` }
320
378
dataSource = { ptree }
321
379
size = { "small" }
322
380
pagination = { false }
323
- scroll = { { y : "65vh" } }
381
+ scroll = { { y : tableHeight } }
324
382
style = { table_style }
325
383
expandable = { expandable }
326
384
rowSelection = { rowSelection }
@@ -439,7 +497,7 @@ export function Full(props: Readonly<Props>): React.JSX.Element {
439
497
</ div >
440
498
) ;
441
499
return (
442
- < Col lg = { 8 } lgOffset = { 2 } md = { 12 } mdOffset = { 0 } >
500
+ < Col md = { 12 } mdOffset = { 0 } >
443
501
< Alert
444
502
message = { msg }
445
503
style = { { margin : "10px 0" } }
@@ -457,30 +515,36 @@ export function Full(props: Readonly<Props>): React.JSX.Element {
457
515
458
516
function render_general_status ( ) {
459
517
return (
460
- < Col md = { 12 } style = { { color : COLORS . GRAY } } >
461
- Timestamp:{ " " }
462
- { info ?. timestamp != null ? (
463
- < code > { new Date ( info . timestamp ) . toISOString ( ) } </ code >
464
- ) : (
465
- "no timestamp"
466
- ) } { " " }
467
- | Status: < code > { status } </ code >
518
+ < Col md = { 12 } >
519
+ < div ref = { generalStatusRef } style = { { color : COLORS . GRAY } } >
520
+ Timestamp:{ " " }
521
+ { info ?. timestamp != null ? (
522
+ < code > { new Date ( info . timestamp ) . toISOString ( ) } </ code >
523
+ ) : (
524
+ "no timestamp"
525
+ ) } { " " }
526
+ | Status: < code > { status } </ code >
527
+ </ div >
468
528
</ Col >
469
529
) ;
470
530
}
471
531
472
532
function render_body ( ) {
473
533
return (
474
534
< >
475
- < ProjectProblems project_status = { project_status } />
476
- < CGroup
477
- have_cgroup = { info ?. cgroup != null }
478
- cg_info = { cg_info }
479
- disk_usage = { disk_usage }
480
- pt_stats = { pt_stats }
481
- start_ts = { start_ts }
482
- project_status = { project_status }
483
- />
535
+ < div ref = { problemsRef } >
536
+ < ProjectProblems project_status = { project_status } />
537
+ </ div >
538
+ < div ref = { cgroupRef } >
539
+ < CGroup
540
+ have_cgroup = { info ?. cgroup != null }
541
+ cg_info = { cg_info }
542
+ disk_usage = { disk_usage }
543
+ pt_stats = { pt_stats }
544
+ start_ts = { start_ts }
545
+ project_status = { project_status }
546
+ />
547
+ </ div >
484
548
{ render_top ( ) }
485
549
{ render_modals ( ) }
486
550
{ DEBUG && render_general_status ( ) }
0 commit comments