@@ -41,6 +41,7 @@ type MainGraphResponse = {
4141 ( ResultItem & { change : [ number | null ] | null } ) | null
4242 >
4343 meta : {
44+ partial_time_labels : string [ ] | null
4445 time_labels : string [ ]
4546 time_label_result_indices : ( number | null ) [ ]
4647 comparison_time_labels ?: string [ ]
@@ -56,6 +57,7 @@ type MainGraphResponse = {
5657}
5758type GraphDatum = {
5859 value : number | null
60+ isPartial : boolean | null
5961 timeLabel : string | null
6062 comparisonValue ?: number | null
6163 comparisonTimeLabel ?: string | null
@@ -149,7 +151,9 @@ export const MainGraph = ({
149151 ? getXLabel ( datum . timeLabel , {
150152 shouldShowYear : hasMultipleYears ,
151153 period,
152- interval
154+ interval,
155+ bucketIndex : bucketIndex . valueOf ( ) ,
156+ totalBuckets : remappedData . length
153157 } )
154158 : ''
155159 : ''
@@ -354,6 +358,8 @@ export const MainGraph = ({
354358 x = { tooltip . x }
355359 y = { tooltip . y }
356360 datum = { remappedData [ selectedIndex ] }
361+ bucketIndex = { selectedIndex }
362+ totalBuckets = { remappedData . length }
357363 />
358364 ) }
359365 </ div >
@@ -369,7 +375,9 @@ const GraphTooltip = ({
369375 x,
370376 y,
371377 datum,
372- showZoomToPeriod
378+ showZoomToPeriod,
379+ bucketIndex,
380+ totalBuckets
373381} : {
374382 metric : FormattableMetric
375383 interval : string
@@ -379,6 +387,8 @@ const GraphTooltip = ({
379387 y : number
380388 datum : GraphDatum
381389 showZoomToPeriod ?: boolean
390+ bucketIndex : number
391+ totalBuckets : number
382392 width : number
383393} ) => {
384394 const formatter = MetricFormatterShort [ metric ]
@@ -420,10 +430,13 @@ const GraphTooltip = ({
420430 < span className = "flex items-center mr-4" >
421431 < div className = "size-2 mr-2 rounded-full bg-indigo-400" > </ div >
422432 < span >
423- { getXLabel ( datum . timeLabel , {
433+ { getFullBucketLabel ( datum . timeLabel , {
424434 period,
425435 interval,
426- shouldShowYear
436+ shouldShowYear,
437+ bucketIndex,
438+ totalBuckets,
439+ isPartial : datum . isPartial !
427440 } ) }
428441 </ span >
429442 </ span >
@@ -436,10 +449,13 @@ const GraphTooltip = ({
436449 < span className = "flex items-center mr-4" >
437450 < div className = "size-2 mr-2 rounded-full bg-gray-500" > </ div >
438451 < span >
439- { getXLabel ( datum . comparisonTimeLabel , {
452+ { getFullBucketLabel ( datum . comparisonTimeLabel , {
440453 period,
441454 interval,
442- shouldShowYear
455+ shouldShowYear,
456+ bucketIndex,
457+ totalBuckets,
458+ isPartial : false
443459 } ) }
444460 </ span >
445461 </ span >
@@ -480,12 +496,16 @@ const getXLabel = (
480496 {
481497 shouldShowYear,
482498 period,
483- interval
499+ interval,
500+ bucketIndex,
501+ totalBuckets
484502 } : {
485503 shouldShowYear : boolean
486504 /* "month" | "week" | "day" | "hour" | "minute" */
487505 interval : string
488506 period : DashboardPeriod
507+ bucketIndex : number
508+ totalBuckets : number
489509 }
490510) => {
491511 const parsedDate = parseNaiveDate ( xValue )
@@ -507,7 +527,76 @@ const getXLabel = (
507527 return `${ formatDayShort ( parsedDate , shouldShowYear ) } , ${ time } `
508528 }
509529 case 'minute' :
510- if ( period === 'realtime' ) return `${ xValue } m`
530+ if ( period === DashboardPeriod . realtime ) {
531+ const minutesAgo = totalBuckets - bucketIndex
532+ return `-${ minutesAgo } m`
533+ }
534+ return formatTime ( parsedDate , {
535+ use12HourClock : is12HourClock ( ) ,
536+ includeMinutes : true
537+ } )
538+ default :
539+ return ''
540+ }
541+ }
542+
543+ const getFullBucketLabel = (
544+ // in the format "YYYY-MM-DD" or "YYYY-MM-DD HH:MM:SS"
545+ xValue : string ,
546+ {
547+ shouldShowYear,
548+ period,
549+ interval,
550+ bucketIndex,
551+ totalBuckets,
552+ isPartial
553+ } : {
554+ isPartial : boolean
555+ shouldShowYear : boolean
556+ /* "month" | "week" | "day" | "hour" | "minute" */
557+ interval : string
558+ period : DashboardPeriod
559+ bucketIndex : number
560+ totalBuckets : number
561+ }
562+ ) => {
563+ const parsedDate = parseNaiveDate ( xValue )
564+ switch ( interval ) {
565+ case 'month' : {
566+ const month = getXLabel ( xValue , {
567+ shouldShowYear,
568+ interval,
569+ period,
570+ bucketIndex,
571+ totalBuckets
572+ } )
573+ return isPartial ? `Partial of ${ month } ` : month
574+ }
575+ case 'week' : {
576+ const date = getXLabel ( xValue , {
577+ shouldShowYear,
578+ interval,
579+ period,
580+ bucketIndex,
581+ totalBuckets
582+ } )
583+ return isPartial ? `Partial week of ${ date } ` : `Week of ${ date } `
584+ }
585+ case 'day' :
586+ return parsedDate . format ( 'ddd, D MMM' )
587+ case 'hour' :
588+ return getXLabel ( xValue , {
589+ shouldShowYear,
590+ interval,
591+ period,
592+ bucketIndex,
593+ totalBuckets
594+ } )
595+ case 'minute' :
596+ if ( period === DashboardPeriod . realtime ) {
597+ const minutesAgo = totalBuckets - bucketIndex
598+ return minutesAgo === 1 ? `1 minute ago` : `${ minutesAgo } minutes ago`
599+ }
511600 return formatTime ( parsedDate , {
512601 use12HourClock : is12HourClock ( ) ,
513602 includeMinutes : true
@@ -558,8 +647,14 @@ const remapToGraphData = (
558647 const mainResultDefined = typeof timeLabel === 'string'
559648 const comparisonResultDefined = typeof comparisonTimeLabel === 'string'
560649
650+ let isPartial : boolean | null = null
561651 let value : number | null = null
562652 if ( mainResultDefined ) {
653+ isPartial = ( data . meta . partial_time_labels ?? [ ] ) . find (
654+ ( l ) => l === timeLabel
655+ )
656+ ? true
657+ : false
563658 if ( firstTimeLabel === null ) {
564659 firstTimeLabel = timeLabel
565660 }
@@ -608,7 +703,14 @@ const remapToGraphData = (
608703 yMax = comparisonValue
609704 }
610705
611- return { value, comparisonValue, timeLabel, comparisonTimeLabel, change }
706+ return {
707+ value,
708+ comparisonValue,
709+ timeLabel,
710+ comparisonTimeLabel,
711+ change,
712+ isPartial
713+ }
612714 } )
613715
614716 const hasMultipleYears =
0 commit comments