1
- import { type ReactElement , useMemo , useRef } from 'react' ;
1
+ import { type ReactElement , useCallback , useMemo , useRef } from 'react' ;
2
2
import { type Theme , useTheme } from '@emotion/react' ;
3
3
import type {
4
4
CustomSeriesOption ,
@@ -10,10 +10,12 @@ import type {
10
10
} from 'echarts' ;
11
11
import type { EChartsInstance } from 'echarts-for-react' ;
12
12
import debounce from 'lodash/debounce' ;
13
+ import omit from 'lodash/omit' ;
13
14
import moment from 'moment-timezone' ;
14
15
15
16
import { closeModal } from 'sentry/actionCreators/modal' ;
16
17
import { isChartHovered } from 'sentry/components/charts/utils' ;
18
+ import useDrawer from 'sentry/components/globalDrawer' ;
17
19
import type { normalizeDateTimeParams } from 'sentry/components/organizations/pageFilters/parse' ;
18
20
import { t , tn } from 'sentry/locale' ;
19
21
import type {
@@ -27,18 +29,36 @@ import type {ReleaseMetaBasic} from 'sentry/types/release';
27
29
import { defined } from 'sentry/utils' ;
28
30
import { trackAnalytics } from 'sentry/utils/analytics' ;
29
31
import { getFormat } from 'sentry/utils/dates' ;
32
+ import { decodeList , decodeScalar } from 'sentry/utils/queryString' ;
30
33
import { useLocation } from 'sentry/utils/useLocation' ;
31
34
import { useNavigate } from 'sentry/utils/useNavigate' ;
32
35
import useOrganization from 'sentry/utils/useOrganization' ;
33
36
import usePageFilters from 'sentry/utils/usePageFilters' ;
34
37
import { useUser } from 'sentry/utils/useUser' ;
38
+ import { ReleasesDrawerList } from 'sentry/views/releases/drawer/releasesDrawerList' ;
35
39
import {
36
40
BUBBLE_AREA_SERIES_ID ,
37
41
BUBBLE_SERIES_ID ,
38
42
} from 'sentry/views/releases/releaseBubbles/constants' ;
39
- import type { Bucket } from 'sentry/views/releases/releaseBubbles/types' ;
43
+ import type {
44
+ Bucket ,
45
+ ChartRendererProps ,
46
+ } from 'sentry/views/releases/releaseBubbles/types' ;
40
47
import { createReleaseBuckets } from 'sentry/views/releases/releaseBubbles/utils/createReleaseBuckets' ;
41
48
49
+ interface ReleaseBubbleSeriesProps {
50
+ alignInMiddle : boolean ;
51
+ bubblePadding : number ;
52
+ bubbleSize : number ;
53
+ buckets : Bucket [ ] ;
54
+ chartRef : React . RefObject < ReactEchartsRef | null > ;
55
+ dateFormatOptions : {
56
+ timezone : string ;
57
+ } ;
58
+ releases : ReleaseMetaBasic [ ] ;
59
+ theme : Theme ;
60
+ }
61
+
42
62
interface LegendSelectChangedParams {
43
63
name : string ;
44
64
selected : Record < string , boolean > ;
@@ -53,18 +73,19 @@ const trackLegend = debounce((params: LegendSelectChangedParams) => {
53
73
selected : Boolean ( params . selected . Releases ) ,
54
74
} ) ;
55
75
} ) ;
56
-
57
- interface ReleaseBubbleSeriesProps {
58
- alignInMiddle : boolean ;
59
- bubblePadding : number ;
60
- bubbleSize : number ;
61
- buckets : Bucket [ ] ;
62
- chartRef : React . RefObject < ReactEchartsRef | null > ;
63
- dateFormatOptions : {
64
- timezone : string ;
65
- } ;
66
- releases : ReleaseMetaBasic [ ] ;
67
- theme : Theme ;
76
+ const RELEASES_DRAWER_FIELD_MAP = {
77
+ showReleasesDrawer : decodeScalar ,
78
+ rdEnd : decodeScalar ,
79
+ rdStart : decodeScalar ,
80
+ rdEnv : decodeList ,
81
+ rdProject : decodeList ,
82
+ release : decodeScalar ,
83
+ releaseProjectId : decodeScalar ,
84
+ } ;
85
+ const RELEASES_DRAWER_FIELDS = Object . keys ( RELEASES_DRAWER_FIELD_MAP ) ;
86
+
87
+ function cleanLocationQuery ( query : Record < string , string [ ] | string | null | undefined > ) {
88
+ return omit ( query , RELEASES_DRAWER_FIELDS ) ;
68
89
}
69
90
70
91
/**
@@ -303,6 +324,7 @@ export function useReleaseBubbles({
303
324
const location = useLocation ( ) ;
304
325
const theme = useTheme ( ) ;
305
326
const { options} = useUser ( ) ;
327
+ const { openDrawer} = useDrawer ( ) ;
306
328
const { selection} = usePageFilters ( ) ;
307
329
// `maxTime` refers to the max time on x-axis for charts.
308
330
// There may be the need to include releases that are > maxTime (e.g. in the
@@ -437,10 +459,35 @@ export function useReleaseBubbles({
437
459
// drawer.
438
460
closeModal ( ) ;
439
461
462
+ openDrawer (
463
+ ( ) => (
464
+ < ReleasesDrawerList
465
+ chartRenderer = { chartRenderer }
466
+ environments = { environments ?? selection . environments }
467
+ projects = { projects ?? selection . projects }
468
+ startTs = { data . start }
469
+ endTs = { data . end }
470
+ />
471
+ ) ,
472
+ {
473
+ shouldCloseOnLocationChange : ( ) => {
474
+ return false ;
475
+ } ,
476
+ ariaLabel : t ( 'Releases drawer' ) ,
477
+ transitionProps : { stiffness : 1000 } ,
478
+ onClose : ( ) => {
479
+ navigate ( {
480
+ query : cleanLocationQuery ( location . query ) ,
481
+ } ) ;
482
+ } ,
483
+ }
484
+ ) ;
485
+
440
486
navigate ( {
441
487
query : {
442
488
...location . query ,
443
489
showReleasesDrawer : 1 ,
490
+ rdChart : 1 ,
444
491
rdStart : data . start ,
445
492
rdEnd : data . end ,
446
493
rdProject : projects ?? selection . projects ,
@@ -569,6 +616,8 @@ export function useReleaseBubbles({
569
616
} ;
570
617
} ,
571
618
[
619
+ chartRenderer ,
620
+ openDrawer ,
572
621
location . query ,
573
622
navigate ,
574
623
alignInMiddle ,
@@ -598,9 +647,9 @@ export function useReleaseBubbles({
598
647
return {
599
648
connectReleaseBubbleChartRef : handleChartRef ,
600
649
601
- //
602
- // Series to append to a chart's existing `series`
603
- / /
650
+ /**
651
+ * Series to append to a chart's existing `series`
652
+ * /
604
653
releaseBubbleSeries : ReleaseBubbleSeries ( {
605
654
alignInMiddle,
606
655
buckets,
0 commit comments