Skip to content

Commit 3e08f31

Browse files
committed
ref(ui): Change useReleaseMarkLineSeries to use useReleaseStats hook
1 parent 293547d commit 3e08f31

File tree

9 files changed

+545
-363
lines changed

9 files changed

+545
-363
lines changed

static/app/components/charts/baseChart.tsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {css, Global, useTheme} from '@emotion/react';
1010
import styled from '@emotion/styled';
1111
import type {
1212
AxisPointerComponentOption,
13+
CustomSeriesOption,
1314
ECharts,
1415
EChartsOption,
1516
GridComponentOption,
@@ -137,7 +138,7 @@ export interface BaseChartProps {
137138
* Additional Chart Series
138139
* This is to pass series to BaseChart bypassing the wrappers like LineChart, AreaChart etc.
139140
*/
140-
additionalSeries?: LineSeriesOption[];
141+
additionalSeries?: Array<CustomSeriesOption | SeriesOption>;
141142
/**
142143
* If true, ignores height value and auto-scales chart to fit container height.
143144
*/
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,31 @@
1+
import type {MutableRefObject} from 'react';
2+
3+
import type {ReactEchartsRef} from 'sentry/types/echarts';
14
import type {ReleaseMetaBasic} from 'sentry/types/release';
25

3-
export type Bucket = {
6+
export interface ChartRendererProps {
7+
/**
8+
* This needs to be passed as a `ref` to the chart being rendered. The chart
9+
* needs to forward the ref to ECharts component.
10+
*/
11+
chartRef:
12+
| MutableRefObject<ReactEchartsRef | null>
13+
| ((e: ReactEchartsRef | null) => void);
14+
/**
15+
* The ending Date object of the release group to render
16+
*/
17+
end: Date;
18+
/**
19+
* The list of releases in the current release group to render
20+
*/
21+
releases: ReleaseMetaBasic[];
22+
/**
23+
* The starting Date object of the release group to render
24+
*/
25+
start: Date;
26+
}
27+
28+
export interface Bucket {
429
end: number;
530
releases: ReleaseMetaBasic[];
631
start: number;
@@ -9,4 +34,4 @@ export type Bucket = {
934
// e.g. the max timestamp we show on the x-axis is 3:30, but data at that
1035
// point represents data from [3:30, now (final)]
1136
final?: number;
12-
};
37+
}

static/app/views/dashboards/widgets/timeSeriesWidget/releaseBubbles/useReleaseBubbles.tsx

+48-16
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type {ReactElement} from 'react';
1+
import {type ReactElement, useCallback, useRef} from 'react';
22
import {type Theme, useTheme} from '@emotion/react';
33
import type {
44
CustomSeriesOption,
@@ -31,7 +31,10 @@ import {
3131
BUBBLE_SERIES_ID,
3232
} from 'sentry/views/dashboards/widgets/timeSeriesWidget/releaseBubbles/constants';
3333
import {createReleaseBubbleHighlighter} from 'sentry/views/dashboards/widgets/timeSeriesWidget/releaseBubbles/createReleaseBubbleHighlighter';
34-
import type {Bucket} from 'sentry/views/dashboards/widgets/timeSeriesWidget/releaseBubbles/types';
34+
import type {
35+
Bucket,
36+
ChartRendererProps,
37+
} from 'sentry/views/dashboards/widgets/timeSeriesWidget/releaseBubbles/types';
3538
import {createReleaseBuckets} from 'sentry/views/dashboards/widgets/timeSeriesWidget/releaseBubbles/utils/createReleaseBuckets';
3639
import {ReleasesDrawer} from 'sentry/views/releases/drawer/releasesDrawer';
3740

@@ -42,11 +45,7 @@ interface CreateReleaseBubbleMouseListenersParams {
4245
renderer: DrawerConfig['renderer'],
4346
options: DrawerConfig['options']
4447
) => void;
45-
chartRenderer?: (rendererProps: {
46-
end: Date;
47-
releases: ReleaseMetaBasic[];
48-
start: Date;
49-
}) => ReactElement;
48+
chartRenderer?: (rendererProps: ChartRendererProps) => ReactElement;
5049
}
5150

5251
/**
@@ -322,26 +321,44 @@ ${t('Click to expand')}
322321
}
323322

324323
interface UseReleaseBubblesParams {
325-
chartRef: React.RefObject<ReactEchartsRef | null>;
324+
/**
325+
* The whitespace around the bubbles.
326+
*/
326327
bubblePadding?: number;
328+
/**
329+
* The size (height) of the bubble
330+
*/
327331
bubbleSize?: number;
328-
chartRenderer?: (rendererProps: {
329-
end: Date;
330-
releases: ReleaseMetaBasic[];
331-
start: Date;
332-
}) => ReactElement;
332+
/**
333+
* This is a callback function that is used in ReleasesDrawer when rendering
334+
* the chart inside of the drawer.
335+
*/
336+
chartRenderer?: (rendererProps: ChartRendererProps) => ReactElement;
337+
/**
338+
* Number of desired bubbles/buckets to create
339+
*/
340+
desiredBuckets?: number;
341+
/**
342+
* The maximum/latest timestamp of the chart's timeseries
343+
*/
333344
maxTime?: number;
345+
/**
346+
* The minimum/earliest timestamp of the chart's timeseries
347+
*/
334348
minTime?: number;
349+
/**
350+
* List of releases that will be grouped
351+
*/
335352
releases?: ReleaseMetaBasic[];
336353
}
337354
export function useReleaseBubbles({
338-
chartRef,
339355
chartRenderer,
340356
releases,
341357
minTime,
342358
maxTime,
343359
bubbleSize = 4,
344360
bubblePadding = 2,
361+
desiredBuckets = 10,
345362
}: UseReleaseBubblesParams) {
346363
const organization = useOrganization();
347364
const {openDrawer} = useDrawer();
@@ -355,13 +372,28 @@ export function useReleaseBubbles({
355372
const releasesMaxTime = defined(selection.datetime.end)
356373
? new Date(selection.datetime.end).getTime()
357374
: Date.now();
375+
const chartRef = useRef<ReactEchartsRef | null>(null);
358376
const hasReleaseBubbles = organization.features.includes('release-bubbles-ui');
377+
const handleChartRef = useCallback((e: ReactEchartsRef | null) => {
378+
chartRef.current = e;
379+
380+
if (e?.getEchartsInstance) {
381+
createReleaseBubbleHighlighter(e.getEchartsInstance());
382+
}
383+
}, []);
384+
359385
const buckets =
360386
(hasReleaseBubbles &&
361387
releases?.length &&
362388
minTime &&
363389
maxTime &&
364-
createReleaseBuckets(minTime, maxTime, releasesMaxTime, releases)) ||
390+
createReleaseBuckets({
391+
minTime,
392+
maxTime,
393+
finalTime: releasesMaxTime,
394+
releases,
395+
desiredBuckets,
396+
})) ||
365397
[];
366398

367399
if (!releases || !buckets.length) {
@@ -377,7 +409,7 @@ export function useReleaseBubbles({
377409
const totalBubblePaddingY = bubblePadding * 2;
378410

379411
return {
380-
createReleaseBubbleHighlighter,
412+
createReleaseBubbleHighlighter: handleChartRef,
381413

382414
/**
383415
* An object map of ECharts event handlers. These should be spread onto a Chart component

static/app/views/dashboards/widgets/timeSeriesWidget/releaseBubbles/utils/createReleaseBuckets.spec.tsx

+7-7
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ describe('createReleaseBuckets', () => {
1111
])(
1212
'creates correct # of buckets for timeSeries with [min, max] of [%d, %d] and %d desired buckets',
1313
(minTime, maxTime, desiredBuckets, expectedBuckets) => {
14-
const buckets = createReleaseBuckets(
14+
const buckets = createReleaseBuckets({
1515
minTime,
1616
maxTime,
17-
Date.now() + 120391, // Shouldn't affect buckets
18-
[],
19-
desiredBuckets
20-
);
17+
finalTime: Date.now() + 120391, // Shouldn't affect buckets
18+
releases: [],
19+
desiredBuckets,
20+
});
2121
expect(buckets).toHaveLength(expectedBuckets);
2222
}
2323
);
@@ -27,7 +27,7 @@ describe('createReleaseBuckets', () => {
2727
const maxTime = Date.now() + 12 * 1000 + 2235;
2828
const finalTime = maxTime + 9999;
2929

30-
const buckets = createReleaseBuckets(minTime, maxTime, finalTime, []);
30+
const buckets = createReleaseBuckets({minTime, maxTime, finalTime, releases: []});
3131
expect(buckets).toEqual([
3232
{start: 1508208080000, end: 1508208081424, releases: []},
3333
{start: 1508208081424, end: 1508208082848, releases: []},
@@ -102,7 +102,7 @@ describe('createReleaseBuckets', () => {
102102
},
103103
];
104104

105-
const buckets = createReleaseBuckets(minTime, maxTime, finalTime, releases);
105+
const buckets = createReleaseBuckets({minTime, maxTime, finalTime, releases});
106106

107107
expect(buckets).toEqual([
108108
{

static/app/views/dashboards/widgets/timeSeriesWidget/releaseBubbles/utils/createReleaseBuckets.tsx

+15-7
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,21 @@ import type {Bucket} from 'sentry/views/dashboards/widgets/timeSeriesWidget/rele
1919
//
2020
// where only the first bucket's starting timestamp is inclusive.
2121
//
22-
export function createReleaseBuckets(
23-
minTime: number | undefined,
24-
maxTime: number | undefined,
25-
finalTime: number,
26-
releases: ReleaseMetaBasic[],
27-
desiredBuckets = 10
28-
): Bucket[] {
22+
interface CreateReleaseBucketsParams {
23+
finalTime: number;
24+
maxTime: number | undefined;
25+
minTime: number | undefined;
26+
releases: ReleaseMetaBasic[];
27+
desiredBuckets?: number;
28+
}
29+
30+
export function createReleaseBuckets({
31+
minTime,
32+
maxTime,
33+
finalTime,
34+
releases,
35+
desiredBuckets = 10,
36+
}: CreateReleaseBucketsParams): Bucket[] {
2937
const buckets: Bucket[] = [];
3038

3139
if (!minTime || !maxTime) {

static/app/views/dashboards/widgets/timeSeriesWidget/timeSeriesWidgetVisualization.tsx

+1-2
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,6 @@ export function TimeSeriesWidgetVisualization(props: TimeSeriesWidgetVisualizati
112112
releaseBubbleXAxis,
113113
releaseBubbleGrid,
114114
} = useReleaseBubbles({
115-
chartRef,
116115
chartRenderer: ({start: trimStart, end: trimEnd}) => {
117116
return (
118117
<TimeSeriesWidgetVisualization
@@ -167,7 +166,7 @@ export function TimeSeriesWidgetVisualization(props: TimeSeriesWidgetVisualizati
167166
registerWithWidgetSyncContext(echartsInstance);
168167

169168
if (hasReleaseBubblesSeries) {
170-
createReleaseBubbleHighlighter(echartsInstance);
169+
createReleaseBubbleHighlighter(e);
171170
}
172171
},
173172
[

0 commit comments

Comments
 (0)