@@ -68,7 +68,7 @@ type Props = {
6868 /** Scale up the grid? [default: 1] */
6969 scale ?: number
7070
71- grids : GridSpec [ ]
71+ grids : ( null | GridSpec ) [ ]
7272}
7373
7474type State = {
@@ -95,9 +95,12 @@ type State = {
9595}
9696
9797type GridProps = {
98+ /** Position of legend w.r.t. the grid UI [default: "below"] */
99+ legendPosition ?: "right" | "below"
100+
98101 scale : Props [ "scale" ]
99- title : Props [ "grids" ] [ number ] [ "title" ]
100- states : Props [ "grids" ] [ number ] [ "states" ]
102+ title : NonNullable < Props [ "grids" ] [ number ] > [ "title" ]
103+ states : NonNullable < Props [ "grids" ] [ number ] > [ "states" ]
101104 workers : State [ "workers" ] [ number ]
102105}
103106
@@ -136,6 +139,8 @@ class Grid extends React.PureComponent<GridProps> {
136139 }
137140
138141 private get emptyCell ( ) : TextProps {
142+ // TODO in light terminal themes, white-dim is a better choice
143+ // than gray-dim
139144 return this . cellFor ( { color : "gray" , dimColor : true } )
140145 }
141146
@@ -199,16 +204,20 @@ class Grid extends React.PureComponent<GridProps> {
199204 return (
200205 < Box flexDirection = "column" >
201206 { A . filter ( Boolean ) . map ( ( AA , ridx ) => (
207+ /* legend row */
202208 < Box key = { ridx } flexDirection = "row" justifyContent = "space-around" >
203209 { AA . filter ( Boolean ) . map ( ( _ , cidx ) => (
210+ /* legend entry (i.e. legend column) */
204211 < Box key = { _ . state } { ...outerBoxProps } >
205212 < Box { ...innerBoxProps } marginLeft = { 1 } >
213+ { /* legend entry label */ }
206214 < Box >
207215 < Text { ..._ . style } bold >
208216 { _ . state }
209217 </ Text >
210218 </ Box >
211219
220+ { /* legend entry value */ }
212221 < Box { ...valueProps } >
213222 < Text { ..._ . style } > { C [ ridx ] [ cidx ] /*.toString().padStart(maxLen)*/ } </ Text >
214223 </ Box >
@@ -250,22 +259,45 @@ class Grid extends React.PureComponent<GridProps> {
250259 return < Text > { this . props . title } </ Text >
251260 }
252261
262+ private get legendPosition ( ) {
263+ return this . props . legendPosition
264+ }
265+
253266 public render ( ) {
267+ const flexDirection = this . legendPosition === "below" ? "column" : "row"
268+ const alignItems = this . legendPosition === "below" ? "center" : "center"
269+ const legendBoxProps = this . legendPosition === "below" ? { marginTop : 1 } : { marginLeft : 2 }
270+
254271 return (
255- < Box flexDirection = "column" alignItems = "center" justifyContent = "center" paddingTop = { 1 } paddingBottom = { 1 } >
256- { this . title ( ) }
257- { this . grid ( ) }
258- < Box marginTop = { 1 } > { this . legend ( ) } </ Box >
272+ < Box
273+ flexDirection = { flexDirection }
274+ alignItems = { alignItems }
275+ justifyContent = "center"
276+ paddingTop = { 1 }
277+ paddingBottom = { 1 }
278+ >
279+ { /* title and grid */ }
280+ < Box flexDirection = "column" alignItems = "center" >
281+ { this . title ( ) }
282+ { this . grid ( ) }
283+ </ Box >
284+
285+ { /* legend */ }
286+ < Box { ...legendBoxProps } > { this . legend ( ) } </ Box >
259287 </ Box >
260288 )
261289 }
262290}
263291
264292export default class Dashboard extends React . PureComponent < Props , State > {
293+ private get grids ( ) : GridSpec [ ] {
294+ return this . props . grids . filter ( ( _ ) => _ !== null ) as GridSpec [ ]
295+ }
296+
265297 public componentDidMount ( ) {
266298 this . setState ( {
267299 workers : [ ] ,
268- watchers : this . props . grids . map ( ( props , gridIdx ) =>
300+ watchers : this . grids . map ( ( props , gridIdx ) =>
269301 props . initWatcher ( ( model : UpdatePayload ) => this . onUpdate ( gridIdx , model ) )
270302 ) ,
271303 agoInterval : setInterval ( ( ) => this . setState ( ( curState ) => ( { iter : ( curState ?. iter || 0 ) + 1 } ) ) , 5 * 1000 ) ,
@@ -388,26 +420,47 @@ export default class Dashboard extends React.PureComponent<Props, State> {
388420 // eslint-disable-next-line no-control-regex
389421 rows . push ( < Text key = { line + "-" + n } > { line . replace ( / \x1b \x5B \[ 2 J / g, "" ) } </ Text > )
390422 }
391- return < React . Fragment > { rows } </ React . Fragment >
423+ return (
424+ < Box marginTop = { 1 } flexDirection = "column" >
425+ { rows }
426+ </ Box >
427+ )
428+ }
429+ }
430+
431+ private gridRows ( ) {
432+ const rows : { widx : number ; grid : NonNullable < Props [ "grids" ] [ number ] > } [ ] [ ] = [ ]
433+ for ( let idx = 0 , ridx = 0 , widx = 0 ; idx < this . props . grids . length ; idx ++ ) {
434+ const grid = this . props . grids [ idx ]
435+ if ( grid === null ) {
436+ ridx ++
437+ } else {
438+ if ( ! rows [ ridx ] ) {
439+ rows [ ridx ] = [ ]
440+ }
441+ rows [ ridx ] . push ( { grid, widx : widx ++ } )
442+ }
392443 }
444+ return rows
393445 }
394446
395447 private body ( ) {
396- return (
397- < Box justifyContent = "space-around" >
398- { this . props . grids . map ( ( props , idx ) => (
399- < Box key = { props . title } marginLeft = { 2 } >
448+ return this . gridRows ( ) . map ( ( row , ridx ) => (
449+ < Box key = { ridx } justifyContent = "space-around" >
450+ { row . map ( ( { grid , widx } ) => (
451+ < Box key = { grid . title } marginLeft = { 2 } >
400452 < Grid
401- key = { props . title }
402- title = { props . title }
453+ key = { grid . title }
454+ title = { grid . title }
403455 scale = { this . props . scale }
404- states = { props . states }
405- workers = { this . state ?. workers [ idx ] || [ ] }
456+ states = { grid . states }
457+ workers = { this . state ?. workers [ widx ] || [ ] }
458+ legendPosition = { row . length === 1 ? "right" : "below" }
406459 />
407460 </ Box >
408461 ) ) }
409462 </ Box >
410- )
463+ ) )
411464 }
412465
413466 public render ( ) {
0 commit comments