Skip to content

Commit e4ff029

Browse files
committed
ref(onboarding): Report project-details completion through one callback
The project-details hook fired onProjectCreated, onProjectDetailsFormChange, and onComplete in sequence at the end of a successful submit, an artifact of extracting the inline step logic. The single-view project-creation host needs the created project (id and slug) and the submitted form at the same moment to snapshot its wizard session and navigate, so replace the three callbacks with one onComplete carrying both, and widen the payload from the project slug to the project itself. The onboarding step forwards the same values to its existing context setters, so its behavior is unchanged. The reuse path now reports the reused project and form state, which match what the host already has stored.
1 parent 3f0aa69 commit e4ff029

2 files changed

Lines changed: 32 additions & 24 deletions

File tree

static/app/views/onboarding/components/useScmProjectDetails.ts

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {t} from 'sentry/locale';
88
import type {Repository} from 'sentry/types/integrations';
99
import type {OnboardingSelectedSDK} from 'sentry/types/onboarding';
1010
import type {Team} from 'sentry/types/organization';
11+
import type {Project} from 'sentry/types/project';
1112
import {trackAnalytics} from 'sentry/utils/analytics';
1213
import {fetchMutation} from 'sentry/utils/queryClient';
1314
import type {RequestError} from 'sentry/utils/requestError/requestError';
@@ -52,12 +53,22 @@ const CREATE_FAILED_EVENT = {
5253
'project-creation': 'project_creation.scm_project_details_create_failed',
5354
} as const;
5455

56+
export interface ScmProjectDetailsCompletion {
57+
/** The created project, or the reused one on the unchanged back-nav path. */
58+
project: Project;
59+
/** The form state the project was created with. */
60+
projectDetailsForm: ProjectDetailsFormState;
61+
}
62+
5563
interface UseScmProjectDetailsOptions {
5664
analyticsFlow: ScmAnalyticsFlow;
57-
/** Called after a project is created (or an unchanged one reused). */
58-
onComplete: () => void;
59-
onProjectCreated: (slug: string | undefined) => void;
60-
onProjectDetailsFormChange: (form: ProjectDetailsFormState) => void;
65+
/**
66+
* Called once the step is done: a project was created (or an unchanged one
67+
* reused on the back-nav path) and the repo link attempted. Receives the
68+
* project and the submitted form state together so the host can persist
69+
* both and advance in one place.
70+
*/
71+
onComplete: (completion: ScmProjectDetailsCompletion) => void;
6172
selectedPlatform: OnboardingSelectedSDK | undefined;
6273
selectedRepository: Repository | undefined;
6374
/**
@@ -106,8 +117,6 @@ interface ScmProjectDetailsForm {
106117
export function useScmProjectDetails({
107118
analyticsFlow,
108119
onComplete,
109-
onProjectCreated,
110-
onProjectDetailsFormChange,
111120
selectedPlatform,
112121
selectedRepository,
113122
createdProjectSlug,
@@ -216,6 +225,12 @@ export function useScmProjectDetails({
216225

217226
trackAnalytics(CREATE_CLICKED_EVENT[analyticsFlow], {organization});
218227

228+
const submittedForm = {
229+
projectName: projectNameResolved,
230+
teamSlug: teamSlugResolved,
231+
alertRuleConfig,
232+
};
233+
219234
// User navigated back and clicked Create without changing anything; skip
220235
// to completion without creating a duplicate. Any actual change abandons
221236
// the previous project and creates a new one, matching legacy onboarding.
@@ -224,7 +239,7 @@ export function useScmProjectDetails({
224239
organization,
225240
project_slug: existingProject.slug,
226241
});
227-
onComplete();
242+
onComplete({project: existingProject, projectDetailsForm: submittedForm});
228243
return;
229244
}
230245

@@ -237,10 +252,6 @@ export function useScmProjectDetails({
237252
createNotificationAction: () => {},
238253
});
239254

240-
// Store the project slug separately so the host can find the project
241-
// without corrupting selectedPlatform.key.
242-
onProjectCreated(project.slug);
243-
244255
if (selectedRepository?.id) {
245256
try {
246257
await fetchMutation({
@@ -253,18 +264,12 @@ export function useScmProjectDetails({
253264
}
254265
}
255266

256-
onProjectDetailsFormChange({
257-
projectName: projectNameResolved,
258-
teamSlug: teamSlugResolved,
259-
alertRuleConfig,
260-
});
261-
262267
trackAnalytics(CREATE_SUCCEEDED_EVENT[analyticsFlow], {
263268
organization,
264269
project_slug: project.slug,
265270
});
266271

267-
onComplete();
272+
onComplete({project, projectDetailsForm: submittedForm});
268273
} catch (error) {
269274
trackAnalytics(CREATE_FAILED_EVENT[analyticsFlow], {organization});
270275
addErrorMessage(t('Failed to create project'));
@@ -279,8 +284,6 @@ export function useScmProjectDetails({
279284
isOrgMemberWithNoAccess,
280285
nothingChanged,
281286
onComplete,
282-
onProjectCreated,
283-
onProjectDetailsFormChange,
284287
organization,
285288
projectNameResolved,
286289
selectedPlatform,

static/app/views/onboarding/scmProjectDetails.tsx

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,15 @@ export function ScmProjectDetails({
4444
selectedRepository,
4545
createdProjectSlug,
4646
projectDetailsForm,
47-
onProjectCreated,
48-
onProjectDetailsFormChange,
49-
onComplete: () =>
50-
onComplete(undefined, selectedFeatures ? {product: selectedFeatures} : undefined),
47+
onComplete: ({project, projectDetailsForm: submittedForm}) => {
48+
// Store the slug separately so onboarding.tsx can find the project via
49+
// useRecentCreatedProject without corrupting selectedPlatform.key (which
50+
// the platform features step needs), and persist the form so navigating
51+
// back from setup-docs restores it. Both land before the step advances.
52+
onProjectCreated(project.slug);
53+
onProjectDetailsFormChange(submittedForm);
54+
onComplete(undefined, selectedFeatures ? {product: selectedFeatures} : undefined);
55+
},
5156
});
5257

5358
return (

0 commit comments

Comments
 (0)