From a7026d88328250acfaf5ce79e3a6eb9d5162083b Mon Sep 17 00:00:00 2001 From: Billy Vong Date: Tue, 15 Apr 2025 16:44:50 -0500 Subject: [PATCH 1/2] feat(releases): Refactor to support deep-linked Issues Chart Part of https://github.com/getsentry/sentry/issues/88560 --- .../components/charts/chartWidgetLoader.tsx | 9 ++- .../issueDetails/streamline/eventGraph.tsx | 43 +++++++++----- .../streamline/eventGraphWidget.tsx | 58 +++++++++++++++++++ .../hooks/useIssueDetailsDiscoverQuery.tsx | 19 +++--- 4 files changed, 106 insertions(+), 23 deletions(-) create mode 100644 static/app/views/issueDetails/streamline/eventGraphWidget.tsx diff --git a/static/app/components/charts/chartWidgetLoader.tsx b/static/app/components/charts/chartWidgetLoader.tsx index e459ab8a9acf47..52c2614f11abc8 100644 --- a/static/app/components/charts/chartWidgetLoader.tsx +++ b/static/app/components/charts/chartWidgetLoader.tsx @@ -4,6 +4,7 @@ import {useQuery} from '@tanstack/react-query'; import Placeholder from 'sentry/components/placeholder'; import {t} from 'sentry/locale'; import type {LoadableChartWidgetProps} from 'sentry/views/insights/common/components/widgets/types'; +import {EVENT_GRAPH_WIDGET_ID} from 'sentry/views/issueDetails/streamline/eventGraphWidget'; interface Props extends LoadableChartWidgetProps { /** @@ -26,7 +27,13 @@ interface Props extends LoadableChartWidgetProps { export function ChartWidgetLoader(props: Props) { const query = useQuery<{default: React.FC}>({ queryKey: [`widget-${props.id}`], - queryFn: () => import(`sentry/views/insights/common/components/widgets/${props.id}`), + queryFn: () => { + if (props.id === EVENT_GRAPH_WIDGET_ID) { + return import('sentry/views/issueDetails/streamline/eventGraphWidget'); + } + + return import(`sentry/views/insights/common/components/widgets/${props.id}`); + }, }); if (query.isPending) { diff --git a/static/app/views/issueDetails/streamline/eventGraph.tsx b/static/app/views/issueDetails/streamline/eventGraph.tsx index 1ed934caebdb8d..a95667d9bd1818 100644 --- a/static/app/views/issueDetails/streamline/eventGraph.tsx +++ b/static/app/views/issueDetails/streamline/eventGraph.tsx @@ -26,6 +26,7 @@ import type {ReactEchartsRef, SeriesDataUnit} from 'sentry/types/echarts'; import type {Event} from 'sentry/types/event'; import type {Group} from 'sentry/types/group'; import type {EventsStats, MultiSeriesEventsStats} from 'sentry/types/organization'; +import type EventView from 'sentry/utils/discover/eventView'; import {DiscoverDatasets} from 'sentry/utils/discover/types'; import {formatAbbreviatedNumber} from 'sentry/utils/formatters'; import {getConfigForIssueType} from 'sentry/utils/issueTypeConfig'; @@ -37,6 +38,7 @@ import useOrganization from 'sentry/utils/useOrganization'; import {useReleaseStats} from 'sentry/utils/useReleaseStats'; import {getBucketSize} from 'sentry/views/dashboards/utils/getBucketSize'; import {useIssueDetails} from 'sentry/views/issueDetails/streamline/context'; +import {EVENT_GRAPH_WIDGET_ID} from 'sentry/views/issueDetails/streamline/eventGraphWidget'; import useFlagSeries from 'sentry/views/issueDetails/streamline/hooks/featureFlags/useFlagSeries'; import {useCurrentEventMarklineSeries} from 'sentry/views/issueDetails/streamline/hooks/useEventMarkLineSeries'; import { @@ -48,7 +50,7 @@ import {Tab} from 'sentry/views/issueDetails/types'; import {useGroupDetailsRoute} from 'sentry/views/issueDetails/useGroupDetailsRoute'; import {useReleaseBubbles} from 'sentry/views/releases/releaseBubbles/useReleaseBubbles'; -const enum EventGraphSeries { +enum EventGraphSeries { EVENT = 'event', USER = 'user', } @@ -64,6 +66,7 @@ interface EventGraphProps { * chart). */ disableZoomNavigation?: boolean; + eventView?: EventView; ref?: React.Ref; /** * Configures showing releases on the chart as bubbles or lines. This is used @@ -100,6 +103,7 @@ function createSeriesAndCount(stats: EventsStats) { export function EventGraph({ group, event, + eventView: eventViewProps, disableZoomNavigation = false, showReleasesAs, showSummary = true, @@ -131,7 +135,8 @@ export function EventGraph({ ref: chartContainerRef, onResize, }); - const eventView = useIssueDetailsEventView({group, isSmallContainer}); + const eventViewHook = useIssueDetailsEventView({group, isSmallContainer}); + const eventView = eventViewProps || eventViewHook; const { data: groupStats = {}, @@ -447,18 +452,22 @@ export function EventGraph({ if (isLoadingStats || isPendingUniqueUsersCount) { return ( - - - - + {showSummary ? ( + + + + + ) : ( +
+ )} @@ -561,7 +570,11 @@ function GraphButton({ label, count, ...props -}: {isActive: boolean; label: string; count?: string} & Partial) { +}: { + isActive: boolean; + label: string; + count?: string; +} & Partial) { return ( + + + ); + } + + if (isGroupError) { + return ( + + + + ); + } + + return ( + + ); +} + +const Container = styled('div')` + height: 100%; +`; + +export const EVENT_GRAPH_WIDGET_ID = 'event-graph-widget'; diff --git a/static/app/views/issueDetails/streamline/hooks/useIssueDetailsDiscoverQuery.tsx b/static/app/views/issueDetails/streamline/hooks/useIssueDetailsDiscoverQuery.tsx index 6f34ef62971e2b..1b1993b8626846 100644 --- a/static/app/views/issueDetails/streamline/hooks/useIssueDetailsDiscoverQuery.tsx +++ b/static/app/views/issueDetails/streamline/hooks/useIssueDetailsDiscoverQuery.tsx @@ -1,4 +1,5 @@ import {getInterval} from 'sentry/components/charts/utils'; +import type {PageFilters} from 'sentry/types/core'; import type {Group} from 'sentry/types/group'; import type {NewQuery, SavedQuery} from 'sentry/types/organization'; import EventView from 'sentry/utils/discover/eventView'; @@ -16,11 +17,13 @@ import {useGroupDefaultStatsPeriod} from 'sentry/views/issueDetails/useGroupDefa export function useIssueDetailsEventView({ group, + pageFilters, queryProps, isSmallContainer = false, }: { group: Group; isSmallContainer?: boolean; + pageFilters?: PageFilters; queryProps?: Partial; }) { const searchQuery = useEventQuery({groupId: group.id}); @@ -29,13 +32,15 @@ export function useIssueDetailsEventView({ const hasSetStatsPeriod = location.query.statsPeriod || location.query.start || location.query.end; const defaultStatsPeriod = useGroupDefaultStatsPeriod(group, group.project); - const periodQuery = hasSetStatsPeriod - ? getPeriod({ - start: location.query.start as string, - end: location.query.end as string, - period: location.query.statsPeriod as string, - }) - : defaultStatsPeriod; + const periodQuery = pageFilters + ? getPeriod(pageFilters.datetime) + : hasSetStatsPeriod + ? getPeriod({ + start: location.query.start as string, + end: location.query.end as string, + period: location.query.statsPeriod as string, + }) + : defaultStatsPeriod; const interval = getInterval( { From 04b70cebe870bcb3261dd231ca23e8a7a4d3dae7 Mon Sep 17 00:00:00 2001 From: Billy Vong Date: Wed, 23 Apr 2025 11:43:40 -0400 Subject: [PATCH 2/2] lint --- static/app/views/issueDetails/streamline/eventGraph.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/static/app/views/issueDetails/streamline/eventGraph.tsx b/static/app/views/issueDetails/streamline/eventGraph.tsx index a95667d9bd1818..611331288f2bca 100644 --- a/static/app/views/issueDetails/streamline/eventGraph.tsx +++ b/static/app/views/issueDetails/streamline/eventGraph.tsx @@ -38,7 +38,6 @@ import useOrganization from 'sentry/utils/useOrganization'; import {useReleaseStats} from 'sentry/utils/useReleaseStats'; import {getBucketSize} from 'sentry/views/dashboards/utils/getBucketSize'; import {useIssueDetails} from 'sentry/views/issueDetails/streamline/context'; -import {EVENT_GRAPH_WIDGET_ID} from 'sentry/views/issueDetails/streamline/eventGraphWidget'; import useFlagSeries from 'sentry/views/issueDetails/streamline/hooks/featureFlags/useFlagSeries'; import {useCurrentEventMarklineSeries} from 'sentry/views/issueDetails/streamline/hooks/useEventMarkLineSeries'; import {