Skip to content

Commit 927a142

Browse files
ref(onboarding): fix initial project state (#75094)
Fixes an onboarding sidebar bug where multiple projects or no projects being selected leads the wrong platform to be displayed in the sidebar. Specifically on issues, if you have multiple projects selected and click into a specific event details, the global project selection will persist, and there's a chance the wrong platform will be displayed when you jump into the replay onboarding side. This PR sets the URL `project` param so that it's always the platform of the event being showed. Before: sidebar displays instructions for bun when the platform is go, since bun is the first project in the global selection: https://github.com/user-attachments/assets/0b98ff2f-04fc-4bc5-929d-fe4c69669a19 After: sidebar displays correct instructions for the platform even though there are many projects in the global selection: https://github.com/user-attachments/assets/f4c9155c-1448-4626-b1bc-2dc8d5769705
1 parent dee65bc commit 927a142

File tree

3 files changed

+20
-12
lines changed

3 files changed

+20
-12
lines changed

static/app/components/events/eventReplay/index.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {lazy} from 'react';
1+
import {lazy, useEffect} from 'react';
22

33
import ErrorBoundary from 'sentry/components/errorBoundary';
44
import {ReplayClipSection} from 'sentry/components/events/eventReplay/replayClipSection';
@@ -8,6 +8,7 @@ import type {Group} from 'sentry/types/group';
88
import useEventCanShowReplayUpsell from 'sentry/utils/event/useEventCanShowReplayUpsell';
99
import {getReplayIdFromEvent} from 'sentry/utils/replays/getReplayIdFromEvent';
1010
import {useHaveSelectedProjectsSentAnyReplayEvents} from 'sentry/utils/replays/hooks/useReplayOnboarding';
11+
import useUrlParams from 'sentry/utils/useUrlParams';
1112

1213
interface Props {
1314
event: Event;
@@ -26,6 +27,14 @@ export default function EventReplay({event, group, projectSlug}: Props) {
2627
projectSlug,
2728
});
2829

30+
const {setParamValue: setProjectId} = useUrlParams('project');
31+
32+
useEffect(() => {
33+
if (canShowUpsell) {
34+
setProjectId(upsellProjectId);
35+
}
36+
}, [upsellProjectId, setProjectId, canShowUpsell]);
37+
2938
if (replayId) {
3039
return <ReplayClipSection event={event} replayId={replayId} group={group} />;
3140
}

static/app/components/onboarding/gettingStartedDoc/utils/useCurrentProjectState.spec.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ describe('useCurrentProjectState', () => {
8989
expect(result.current.currentProject).toBe(undefined);
9090
});
9191

92-
it('should return currentProject=undefined whenproject url param is present and currentPanel != targetPanel', () => {
92+
it('should return currentProject=undefined when project url param is present and currentPanel != targetPanel', () => {
9393
ProjectsStore.loadInitialData([javascript, angular]);
9494
mockPageFilterStore([javascript, angular]);
9595
const {result} = renderHook(useCurrentProjectState, {
@@ -99,7 +99,7 @@ describe('useCurrentProjectState', () => {
9999
onboardingPlatforms: customMetricOnboardingPlatforms,
100100
allPlatforms: customMetricPlatforms,
101101
},
102-
wrapper: createWrapper(angular.slug),
102+
wrapper: createWrapper(angular.id),
103103
});
104104
expect(result.current.currentProject).toBe(undefined);
105105
});
@@ -129,9 +129,9 @@ describe('useCurrentProjectState', () => {
129129
onboardingPlatforms: customMetricOnboardingPlatforms,
130130
allPlatforms: customMetricPlatforms,
131131
},
132-
wrapper: createWrapper(angular.slug),
132+
wrapper: createWrapper(javascript.id),
133133
});
134-
expect(result.current.currentProject).toBe(angular);
134+
expect(result.current.currentProject).toBe(javascript);
135135
});
136136

137137
it('should return the first project if global selection does not have onboarding', () => {

static/app/components/onboarding/gettingStartedDoc/utils/useCurrentProjectState.tsx

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import type {SidebarPanelKey} from 'sentry/components/sidebar/types';
55
import PageFiltersStore from 'sentry/stores/pageFiltersStore';
66
import {useLegacyStore} from 'sentry/stores/useLegacyStore';
77
import type {PlatformKey, Project} from 'sentry/types/project';
8-
import {useParams} from 'sentry/utils/useParams';
98
import useProjects from 'sentry/utils/useProjects';
9+
import useUrlParams from 'sentry/utils/useUrlParams';
1010

1111
type Props = {
1212
allPlatforms: readonly PlatformKey[];
@@ -21,12 +21,11 @@ function useCurrentProjectState({
2121
onboardingPlatforms,
2222
allPlatforms,
2323
}: Props) {
24-
const params = useParams<{projectId?: string}>();
25-
const projectSlug = params.projectId;
2624
const {projects, initiallyLoaded: projectsLoaded} = useProjects();
2725
const {selection, isReady} = useLegacyStore(PageFiltersStore);
2826
const [currentProject, setCurrentProject] = useState<Project | undefined>(undefined);
29-
27+
const {getParamValue: projectIds} = useUrlParams('project');
28+
const projectId = projectIds()?.split('&').at(0);
3029
const isActive = currentPanel === targetPanel;
3130

3231
// Projects with onboarding instructions
@@ -55,8 +54,8 @@ function useCurrentProjectState({
5554
return;
5655
}
5756

58-
if (projectSlug) {
59-
setCurrentProject(projects.find(p => p.slug === projectSlug) ?? undefined);
57+
if (projectId) {
58+
setCurrentProject(projects.find(p => p.id === projectId) ?? undefined);
6059
return;
6160
}
6261

@@ -100,7 +99,7 @@ function useCurrentProjectState({
10099
selection.projects,
101100
projectsWithOnboarding,
102101
supportedProjects,
103-
projectSlug,
102+
projectId,
104103
]);
105104

106105
return {

0 commit comments

Comments
 (0)