@@ -15,6 +15,7 @@ import React, {useEffect, useMemo, useRef, useState} from 'react';
15
15
16
16
import { Switch } from '@headlessui/react' ;
17
17
import { RpcError } from '@protobuf-ts/runtime-rpc' ;
18
+ import cx from 'classnames' ;
18
19
import Select , { type SelectInstance } from 'react-select' ;
19
20
20
21
import { Label , ProfileTypesResponse , QueryServiceClient } from '@parca/client' ;
@@ -63,6 +64,9 @@ interface ProfileSelectorProps {
63
64
comparing : boolean ;
64
65
navigateTo : NavigateFunction ;
65
66
suffix ?: string ;
67
+ showMetricsGraph : boolean ;
68
+ displayHideMetricsGraphButton : boolean ;
69
+ setDisplayHideMetricsGraphButton : Dispatch < SetStateAction < boolean > > ;
66
70
}
67
71
68
72
export interface IProfileTypesResult {
@@ -101,6 +105,9 @@ const ProfileSelector = ({
101
105
profileSelection,
102
106
comparing,
103
107
navigateTo,
108
+ showMetricsGraph,
109
+ displayHideMetricsGraphButton,
110
+ setDisplayHideMetricsGraphButton,
104
111
} : ProfileSelectorProps ) : JSX . Element => {
105
112
const {
106
113
loading : profileTypesLoading ,
@@ -427,75 +434,91 @@ const ProfileSelector = ({
427
434
</ div >
428
435
< div > { comparing && < IconButton onClick = { ( ) => closeProfile ( ) } icon = { < CloseIcon /> } /> } </ div >
429
436
</ div >
430
- < div >
431
- < div style = { { height : heightStyle } } >
432
- { querySelection . expression !== undefined &&
433
- querySelection . expression . length > 0 &&
434
- querySelection . from !== undefined &&
435
- querySelection . to !== undefined ? (
436
- < div >
437
- < ProfileMetricsGraph
438
- queryClient = { queryClient }
439
- queryExpression = { querySelection . expression }
440
- from = { querySelection . from }
441
- to = { querySelection . to }
442
- profile = { profileSelection }
443
- comparing = { comparing }
444
- sumBy = { querySelection . sumBy ?? defaultSumBy ?? [ ] }
445
- sumByLoading = { defaultSumByLoading }
446
- setTimeRange = { ( range : DateTimeRange ) => {
447
- const from = range . getFromMs ( ) ;
448
- const to = range . getToMs ( ) ;
449
- let mergedProfileParams = { } ;
450
- if ( query . profileType ( ) . delta ) {
451
- mergedProfileParams = { mergeFrom : from , mergeTo : to } ;
452
- }
453
- setTimeRangeSelection ( range ) ;
454
- selectQuery ( {
455
- expression : queryExpressionString ,
456
- from,
457
- to,
458
- timeSelection : range . getRangeKey ( ) ,
459
- ...mergedProfileParams ,
460
- } ) ;
461
- } }
462
- addLabelMatcher = { addLabelMatcher }
463
- onPointClick = { (
464
- timestamp : number ,
465
- labels : Label [ ] ,
466
- queryExpression : string ,
467
- duration : number
468
- ) => {
469
- // TODO: Pass the query object via click rather than queryExpression
470
- let query = Query . parse ( queryExpression ) ;
471
- labels . forEach ( l => {
472
- const [ newQuery , updated ] = query . setMatcher ( l . name , l . value ) ;
473
- if ( updated ) {
474
- query = newQuery ;
475
- }
476
- } ) ;
477
-
478
- const durationInMilliseconds = duration / 1000000 ; // duration is in nanoseconds
479
- const mergeFrom = timestamp ;
480
- const mergeTo = query . profileType ( ) . delta
481
- ? mergeFrom + durationInMilliseconds
482
- : mergeFrom ;
483
- selectProfile ( new MergedProfileSelection ( mergeFrom , mergeTo , query ) ) ;
484
- } }
485
- />
486
- </ div >
487
- ) : (
488
- < >
489
- { profileSelection == null ? (
490
- < div className = "p-2" >
491
- < ProfileMetricsEmptyState
492
- message = { `Please select a profile type and click "Search" to begin.` }
493
- />
494
- </ div >
495
- ) : null }
496
- </ >
437
+ < div
438
+ className = { cx ( 'relative' , {
439
+ 'py-4' : ! showMetricsGraph ,
440
+ } ) }
441
+ >
442
+ < button
443
+ onClick = { ( ) => setDisplayHideMetricsGraphButton ( ! showMetricsGraph ) }
444
+ className = { cx (
445
+ 'hidden z-10 px-3 py-1 text-sm font-medium text-gray-700 dark:text-gray-200 bg-gray-100 rounded-md hover:bg-gray-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:bg-gray-900' ,
446
+ displayHideMetricsGraphButton && showMetricsGraph && 'absolute right-0 bottom-3 !flex' ,
447
+ ! showMetricsGraph && 'relative !flex ml-auto'
497
448
) }
498
- </ div >
449
+ >
450
+ { showMetricsGraph ? 'Hide' : 'Show' } Metrics Graph
451
+ </ button >
452
+ { showMetricsGraph ? (
453
+ < div style = { { height : heightStyle } } >
454
+ { querySelection . expression !== undefined &&
455
+ querySelection . expression . length > 0 &&
456
+ querySelection . from !== undefined &&
457
+ querySelection . to !== undefined ? (
458
+ < div >
459
+ < ProfileMetricsGraph
460
+ queryClient = { queryClient }
461
+ queryExpression = { querySelection . expression }
462
+ from = { querySelection . from }
463
+ to = { querySelection . to }
464
+ profile = { profileSelection }
465
+ comparing = { comparing }
466
+ sumBy = { querySelection . sumBy ?? defaultSumBy ?? [ ] }
467
+ sumByLoading = { defaultSumByLoading }
468
+ setTimeRange = { ( range : DateTimeRange ) => {
469
+ const from = range . getFromMs ( ) ;
470
+ const to = range . getToMs ( ) ;
471
+ let mergedProfileParams = { } ;
472
+ if ( query . profileType ( ) . delta ) {
473
+ mergedProfileParams = { mergeFrom : from , mergeTo : to } ;
474
+ }
475
+ setTimeRangeSelection ( range ) ;
476
+ selectQuery ( {
477
+ expression : queryExpressionString ,
478
+ from,
479
+ to,
480
+ timeSelection : range . getRangeKey ( ) ,
481
+ ...mergedProfileParams ,
482
+ } ) ;
483
+ } }
484
+ addLabelMatcher = { addLabelMatcher }
485
+ onPointClick = { (
486
+ timestamp : number ,
487
+ labels : Label [ ] ,
488
+ queryExpression : string ,
489
+ duration : number
490
+ ) => {
491
+ // TODO: Pass the query object via click rather than queryExpression
492
+ let query = Query . parse ( queryExpression ) ;
493
+ labels . forEach ( l => {
494
+ const [ newQuery , updated ] = query . setMatcher ( l . name , l . value ) ;
495
+ if ( updated ) {
496
+ query = newQuery ;
497
+ }
498
+ } ) ;
499
+
500
+ const durationInMilliseconds = duration / 1000000 ; // duration is in nanoseconds
501
+ const mergeFrom = timestamp ;
502
+ const mergeTo = query . profileType ( ) . delta
503
+ ? mergeFrom + durationInMilliseconds
504
+ : mergeFrom ;
505
+ selectProfile ( new MergedProfileSelection ( mergeFrom , mergeTo , query ) ) ;
506
+ } }
507
+ />
508
+ </ div >
509
+ ) : (
510
+ < >
511
+ { profileSelection == null ? (
512
+ < div className = "p-2" >
513
+ < ProfileMetricsEmptyState
514
+ message = { `Please select a profile type and click "Search" to begin.` }
515
+ />
516
+ </ div >
517
+ ) : null }
518
+ </ >
519
+ ) }
520
+ </ div >
521
+ ) : null }
499
522
</ div >
500
523
</ >
501
524
) ;
0 commit comments