33 * License: MS-RSL – see LICENSE.md for details
44 */
55
6+ // cspell:ignore Questionmark
7+
68declare let DEBUG ;
79
8- import { InfoCircleOutlined , ScheduleOutlined } from "@ant-design/icons" ;
910import { 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" ;
1014import { Col , Row } from "@cocalc/frontend/antd-bootstrap" ;
1115import { CSS , ProjectActions , redux } from "@cocalc/frontend/app-framework" ;
1216import { A , Loading , Tip } from "@cocalc/frontend/components" ;
1317import { SiteName } from "@cocalc/frontend/customize" ;
18+ import { field_cmp , seconds2hms } from "@cocalc/util/misc" ;
19+ import { COLORS } from "@cocalc/util/theme" ;
1420import {
1521 Process ,
1622 ProjectInfo as ProjectInfoType ,
1723} 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 " ;
2026import { RestartProject } from "../settings/restart-project" ;
2127import {
2228 AboutContent ,
@@ -28,7 +34,6 @@ import {
2834} from "./components" ;
2935import { CGroupInfo , DUState , PTStats , ProcessRow } from "./types" ;
3036import { DETAILS_BTN_TEXT , SSH_KEYS_DOC } from "./utils" ;
31- import { ROOT_STYLE } from "../servers/consts" ;
3237
3338interface Props {
3439 any_alerts : ( ) => boolean ;
@@ -89,6 +94,53 @@ export function Full(props: Readonly<Props>): React.JSX.Element {
8994 onCellProps,
9095 } = props ;
9196
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+
92144 function render_help ( ) {
93145 return (
94146 < Form . Item label = "Help:" >
@@ -295,11 +347,16 @@ export function Full(props: Readonly<Props>): React.JSX.Element {
295347 </ Tip >
296348 ) ;
297349
298- const table_style : CSS = { marginBottom : "2rem" } ;
350+ const table_style : CSS = {
351+ marginBottom : "2rem" ,
352+ } ;
299353
300354 return (
301355 < >
302- < Row style = { { marginBottom : "10px" , marginTop : "20px" } } >
356+ < Row
357+ ref = { headerRef }
358+ style = { { marginBottom : "10px" , marginTop : "20px" } }
359+ >
303360 < Col md = { 9 } >
304361 < Form layout = "inline" >
305362 < Form . Item label = "Table of Processes" />
@@ -314,13 +371,14 @@ export function Full(props: Readonly<Props>): React.JSX.Element {
314371 </ Form >
315372 </ Col >
316373 </ Row >
317- < Row > { render_explanation ( ) } </ Row >
374+ < Row ref = { explanationRef } > { render_explanation ( ) } </ Row >
318375 < Row >
319376 < Table < ProcessRow >
377+ key = { `table-${ contentSize . width } -${ contentSize . height } ` }
320378 dataSource = { ptree }
321379 size = { "small" }
322380 pagination = { false }
323- scroll = { { y : "65vh" } }
381+ scroll = { { y : tableHeight } }
324382 style = { table_style }
325383 expandable = { expandable }
326384 rowSelection = { rowSelection }
@@ -439,7 +497,7 @@ export function Full(props: Readonly<Props>): React.JSX.Element {
439497 </ div >
440498 ) ;
441499 return (
442- < Col lg = { 8 } lgOffset = { 2 } md = { 12 } mdOffset = { 0 } >
500+ < Col md = { 12 } mdOffset = { 0 } >
443501 < Alert
444502 message = { msg }
445503 style = { { margin : "10px 0" } }
@@ -457,30 +515,36 @@ export function Full(props: Readonly<Props>): React.JSX.Element {
457515
458516 function render_general_status ( ) {
459517 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 >
468528 </ Col >
469529 ) ;
470530 }
471531
472532 function render_body ( ) {
473533 return (
474534 < >
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 >
484548 { render_top ( ) }
485549 { render_modals ( ) }
486550 { DEBUG && render_general_status ( ) }
0 commit comments