Skip to content

Commit 4479b64

Browse files
committed
hack to render ReleasesDrawerList with chartRenderer on click only
1 parent febae53 commit 4479b64

File tree

3 files changed

+120
-30
lines changed

3 files changed

+120
-30
lines changed

static/app/views/releases/drawer/releasesDrawerList.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import {
1616
import {t, tn} from 'sentry/locale';
1717
import {space} from 'sentry/styles/space';
1818
import type {ReactEchartsRef, SeriesDataUnit} from 'sentry/types/echarts';
19-
import type {ReleaseMetaBasic} from 'sentry/types/release';
2019
import {useLocation} from 'sentry/utils/useLocation';
2120
import {useNavigate} from 'sentry/utils/useNavigate';
2221
import usePageFilters from 'sentry/utils/usePageFilters';
@@ -114,6 +113,7 @@ export function ReleasesDrawerList({
114113
end: endTs ? new Date(endTs).toISOString() : null,
115114
},
116115
});
116+
117117
const handleSelectRelease = useCallback(
118118
(nextSelectedRelease: string, projectId: string) => {
119119
navigate({

static/app/views/releases/drawer/useReleasesDrawer.tsx

Lines changed: 53 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {useEffect} from 'react';
1+
import {useEffect, useRef} from 'react';
22
import omit from 'lodash/omit';
33

44
import useDrawer from 'sentry/components/globalDrawer';
@@ -12,6 +12,7 @@ import {ReleasesDrawerList} from 'sentry/views/releases/drawer/releasesDrawerLis
1212

1313
const RELEASES_DRAWER_FIELD_MAP = {
1414
showReleasesDrawer: decodeScalar,
15+
rdChart: decodeScalar,
1516
rdEnd: decodeScalar,
1617
rdStart: decodeScalar,
1718
rdEnv: decodeList,
@@ -29,6 +30,7 @@ export function useReleasesDrawer() {
2930
const {
3031
releaseProjectId,
3132
showReleasesDrawer,
33+
rdChart,
3234
rdEnd,
3335
rdEnv,
3436
rdProject,
@@ -40,11 +42,17 @@ export function useReleasesDrawer() {
4042
const navigate = useNavigate();
4143
const location = useLocation();
4244
const {closeDrawer, openDrawer} = useDrawer();
45+
const isRenderedFromClick = useRef(false);
46+
const {rdChart: _rdChart, ...queryWithoutChart} = location.query;
4347

4448
useEffect(() => {
4549
if (showReleasesDrawer !== '1') {
4650
closeDrawer();
47-
} else if (release) {
51+
}
52+
}, [closeDrawer, showReleasesDrawer]);
53+
54+
useEffect(() => {
55+
if (showReleasesDrawer === '1' && release) {
4856
openDrawer(
4957
() => <ReleasesDrawerDetails release={release} projectId={releaseProjectId} />,
5058
{
@@ -60,7 +68,46 @@ export function useReleasesDrawer() {
6068
},
6169
}
6270
);
63-
} else if (rdStart && rdEnd) {
71+
}
72+
}, [
73+
location.query,
74+
navigate,
75+
openDrawer,
76+
release,
77+
releaseProjectId,
78+
showReleasesDrawer,
79+
]);
80+
81+
useEffect(() => {
82+
if (rdChart) {
83+
isRenderedFromClick.current = true;
84+
85+
// `rdChart` is a temp hack so that we can render the charts onClick by
86+
// passing the render function to openDrawer, while at the same time
87+
// writing a URL entry that gets ignored by `useReleasesDrawer` due to
88+
// `rdChart` being present in the URL params. This hook then removes
89+
// `rdChart` so that on reload, this hook will render the drawer (without
90+
// chart) due to the URL params. Note that it might be possible (but
91+
// unprobable?) that this `rdChart` clearing call gets interrupted and
92+
// the user copies a URL with the param, in which case, the drawer won't
93+
// open on next load.
94+
navigate(
95+
{
96+
query: queryWithoutChart,
97+
},
98+
{replace: true}
99+
);
100+
}
101+
}, [navigate, queryWithoutChart, rdChart]);
102+
103+
useEffect(() => {
104+
if (
105+
showReleasesDrawer === '1' &&
106+
!rdChart &&
107+
rdStart &&
108+
rdEnd &&
109+
!isRenderedFromClick.current
110+
) {
64111
openDrawer(
65112
() => (
66113
<ReleasesDrawerList
@@ -84,21 +131,15 @@ export function useReleasesDrawer() {
84131
}
85132
);
86133
}
87-
88-
return () => {
89-
closeDrawer();
90-
};
91134
}, [
92-
closeDrawer,
93-
openDrawer,
94135
location.query,
95136
navigate,
137+
openDrawer,
138+
showReleasesDrawer,
139+
rdChart,
96140
rdEnd,
97141
rdEnv,
98142
rdProject,
99143
rdStart,
100-
release,
101-
releaseProjectId,
102-
showReleasesDrawer,
103144
]);
104145
}

static/app/views/releases/releaseBubbles/useReleaseBubbles.tsx

Lines changed: 66 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {type ReactElement, useMemo, useRef} from 'react';
1+
import {type ReactElement, useCallback, useMemo, useRef} from 'react';
22
import {type Theme, useTheme} from '@emotion/react';
33
import type {
44
CustomSeriesOption,
@@ -10,10 +10,12 @@ import type {
1010
} from 'echarts';
1111
import type {EChartsInstance} from 'echarts-for-react';
1212
import debounce from 'lodash/debounce';
13+
import omit from 'lodash/omit';
1314
import moment from 'moment-timezone';
1415

1516
import {closeModal} from 'sentry/actionCreators/modal';
1617
import {isChartHovered} from 'sentry/components/charts/utils';
18+
import useDrawer from 'sentry/components/globalDrawer';
1719
import type {normalizeDateTimeParams} from 'sentry/components/organizations/pageFilters/parse';
1820
import {t, tn} from 'sentry/locale';
1921
import type {
@@ -27,18 +29,36 @@ import type {ReleaseMetaBasic} from 'sentry/types/release';
2729
import {defined} from 'sentry/utils';
2830
import {trackAnalytics} from 'sentry/utils/analytics';
2931
import {getFormat} from 'sentry/utils/dates';
32+
import {decodeList, decodeScalar} from 'sentry/utils/queryString';
3033
import {useLocation} from 'sentry/utils/useLocation';
3134
import {useNavigate} from 'sentry/utils/useNavigate';
3235
import useOrganization from 'sentry/utils/useOrganization';
3336
import usePageFilters from 'sentry/utils/usePageFilters';
3437
import {useUser} from 'sentry/utils/useUser';
38+
import {ReleasesDrawerList} from 'sentry/views/releases/drawer/releasesDrawerList';
3539
import {
3640
BUBBLE_AREA_SERIES_ID,
3741
BUBBLE_SERIES_ID,
3842
} 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';
4047
import {createReleaseBuckets} from 'sentry/views/releases/releaseBubbles/utils/createReleaseBuckets';
4148

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+
4262
interface LegendSelectChangedParams {
4363
name: string;
4464
selected: Record<string, boolean>;
@@ -53,18 +73,19 @@ const trackLegend = debounce((params: LegendSelectChangedParams) => {
5373
selected: Boolean(params.selected.Releases),
5474
});
5575
});
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);
6889
}
6990

7091
/**
@@ -303,6 +324,7 @@ export function useReleaseBubbles({
303324
const location = useLocation();
304325
const theme = useTheme();
305326
const {options} = useUser();
327+
const {openDrawer} = useDrawer();
306328
const {selection} = usePageFilters();
307329
// `maxTime` refers to the max time on x-axis for charts.
308330
// There may be the need to include releases that are > maxTime (e.g. in the
@@ -437,10 +459,35 @@ export function useReleaseBubbles({
437459
// drawer.
438460
closeModal();
439461

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+
440486
navigate({
441487
query: {
442488
...location.query,
443489
showReleasesDrawer: 1,
490+
rdChart: 1,
444491
rdStart: data.start,
445492
rdEnd: data.end,
446493
rdProject: projects ?? selection.projects,
@@ -569,6 +616,8 @@ export function useReleaseBubbles({
569616
};
570617
},
571618
[
619+
chartRenderer,
620+
openDrawer,
572621
location.query,
573622
navigate,
574623
alignInMiddle,
@@ -598,9 +647,9 @@ export function useReleaseBubbles({
598647
return {
599648
connectReleaseBubbleChartRef: handleChartRef,
600649

601-
//
602-
// Series to append to a chart's existing `series`
603-
//
650+
/**
651+
* Series to append to a chart's existing `series`
652+
*/
604653
releaseBubbleSeries: ReleaseBubbleSeries({
605654
alignInMiddle,
606655
buckets,

0 commit comments

Comments
 (0)