From 4437b775513ba0dd0615a4a0cbb02f43c415be30 Mon Sep 17 00:00:00 2001 From: Priscila Oliveira Date: Fri, 23 May 2025 09:54:29 +0200 Subject: [PATCH 1/9] ref(project-creation): Introduce useCreateProjectRules hook --- .../onboarding/useCreateProjectRules.tsx | 35 +++++++++++++++++++ .../views/projectInstall/createProject.tsx | 25 ++++++------- .../issueAlertNotificationOptions.tsx | 22 ++++++------ 3 files changed, 56 insertions(+), 26 deletions(-) create mode 100644 static/app/components/onboarding/useCreateProjectRules.tsx diff --git a/static/app/components/onboarding/useCreateProjectRules.tsx b/static/app/components/onboarding/useCreateProjectRules.tsx new file mode 100644 index 00000000000000..bb13ab70715980 --- /dev/null +++ b/static/app/components/onboarding/useCreateProjectRules.tsx @@ -0,0 +1,35 @@ +import {useMutation} from 'sentry/utils/queryClient'; +import type RequestError from 'sentry/utils/requestError/requestError'; +import useApi from 'sentry/utils/useApi'; +import useOrganization from 'sentry/utils/useOrganization'; +import type {RequestDataFragment} from 'sentry/views/projectInstall/issueAlertOptions'; + +interface Variables + extends Partial< + Pick< + RequestDataFragment, + 'conditions' | 'actions' | 'actionMatch' | 'frequency' | 'name' + > + > { + projectSlug: string; +} + +export function useCreateProjectRules() { + const api = useApi(); + const organization = useOrganization(); + // TODO(priscila): Introduce better response types + return useMutation<{id: string}, RequestError, Variables>({ + mutationFn: ({projectSlug, name, conditions, actions, actionMatch, frequency}) => { + return api.requestPromise(`/projects/${organization.slug}/${projectSlug}/rules/`, { + method: 'POST', + data: { + name, + conditions, + actions, + actionMatch, + frequency, + }, + }); + }, + }); +} diff --git a/static/app/views/projectInstall/createProject.tsx b/static/app/views/projectInstall/createProject.tsx index dcb8871b5c2db8..aae8b8b9b51b34 100644 --- a/static/app/views/projectInstall/createProject.tsx +++ b/static/app/views/projectInstall/createProject.tsx @@ -19,6 +19,7 @@ import List from 'sentry/components/list'; import ListItem from 'sentry/components/list/listItem'; import {SupportedLanguages} from 'sentry/components/onboarding/frameworkSuggestionModal'; import {useCreateProject} from 'sentry/components/onboarding/useCreateProject'; +import {useCreateProjectRules} from 'sentry/components/onboarding/useCreateProjectRules'; import type {Platform} from 'sentry/components/platformPicker'; import PlatformPicker from 'sentry/components/platformPicker'; import TeamSelector from 'sentry/components/teamSelector'; @@ -140,6 +141,7 @@ export function CreateProject() { const {createNotificationAction, notificationProps} = useCreateNotificationAction(); const canUserCreateProject = useCanCreateProject(); const createProject = useCreateProject(); + const createProjectRules = useCreateProjectRules(); const {teams} = useTeams(); const accessTeams = teams.filter((team: Team) => team.access.includes('team:admin')); const referrer = decodeScalar(location.query.referrer); @@ -157,19 +159,14 @@ export function CreateProject() { const ruleIds = []; if (alertRuleConfig?.shouldCreateCustomRule) { - const ruleData = await api.requestPromise( - `/projects/${organization.slug}/${project.slug}/rules/`, - { - method: 'POST', - data: { - name: project.name, - conditions: alertRuleConfig?.conditions, - actions: alertRuleConfig?.actions, - actionMatch: alertRuleConfig?.actionMatch, - frequency: alertRuleConfig?.frequency, - }, - } - ); + const ruleData = await createProjectRules.mutateAsync({ + projectSlug: project.slug, + name: project.name, + conditions: alertRuleConfig?.conditions, + actions: alertRuleConfig?.actions, + actionMatch: alertRuleConfig?.actionMatch, + frequency: alertRuleConfig?.frequency, + }); ruleIds.push(ruleData.id); } @@ -189,7 +186,7 @@ export function CreateProject() { return ruleIds; }, - [organization, api, createNotificationAction] + [createNotificationAction, createProjectRules] ); const autoFill = useMemo(() => { diff --git a/static/app/views/projectInstall/issueAlertNotificationOptions.tsx b/static/app/views/projectInstall/issueAlertNotificationOptions.tsx index 3f2518a572f142..724da75ac2f7dd 100644 --- a/static/app/views/projectInstall/issueAlertNotificationOptions.tsx +++ b/static/app/views/projectInstall/issueAlertNotificationOptions.tsx @@ -2,13 +2,13 @@ import {Fragment, useCallback, useEffect, useMemo, useState} from 'react'; import styled from '@emotion/styled'; import MultipleCheckbox from 'sentry/components/forms/controls/multipleCheckbox'; +import {useCreateProjectRules} from 'sentry/components/onboarding/useCreateProjectRules'; import {t, tct} from 'sentry/locale'; import {space} from 'sentry/styles/space'; import {type IntegrationAction, IssueAlertActionType} from 'sentry/types/alerts'; import type {OrganizationIntegration} from 'sentry/types/integrations'; import {useApiQuery} from 'sentry/utils/queryClient'; import useRouteAnalyticsParams from 'sentry/utils/routeAnalytics/useRouteAnalyticsParams'; -import useApi from 'sentry/utils/useApi'; import useOrganization from 'sentry/utils/useOrganization'; import SetupMessagingIntegrationButton, { MessagingIntegrationAnalyticsView, @@ -77,8 +77,8 @@ export type IssueAlertNotificationProps = { }; export function useCreateNotificationAction() { - const api = useApi(); const organization = useOrganization(); + const createProjectRules = useCreateProjectRules(); const messagingIntegrationsQuery = useApiQuery( [`/organizations/${organization.slug}/integrations/?integrationType=messaging`], @@ -174,18 +174,16 @@ export function useCreateNotificationAction() { return undefined; } - return api.requestPromise(`/projects/${organization.slug}/${projectSlug}/rules/`, { - method: 'POST', - data: { - name, - conditions, - actions: [integrationAction], - actionMatch, - frequency, - }, + return createProjectRules.mutateAsync({ + projectSlug, + name, + conditions, + actions: [integrationAction], + actionMatch, + frequency, }); }, - [actions, api, provider, integration, channel, organization.slug] + [actions, provider, integration, channel, createProjectRules] ); return { From ccd66cb6011e316548dbcbeba9e73ea7544fc666 Mon Sep 17 00:00:00 2001 From: Priscila Oliveira Date: Fri, 23 May 2025 09:18:53 +0200 Subject: [PATCH 2/9] fix(project-creation): Button should be busy until all mutations are complete --- .../onboarding/frameworkSuggestionModal.tsx | 11 ++- .../onboarding/useCreateProject.tsx | 9 +-- .../onboarding/useCreateProjectAndRules.tsx | 72 +++++++++++++++++ .../views/projectInstall/createProject.tsx | 81 ++++++------------- 4 files changed, 107 insertions(+), 66 deletions(-) create mode 100644 static/app/components/onboarding/useCreateProjectAndRules.tsx diff --git a/static/app/components/onboarding/frameworkSuggestionModal.tsx b/static/app/components/onboarding/frameworkSuggestionModal.tsx index c105ff24133658..00f717ff7c2d31 100644 --- a/static/app/components/onboarding/frameworkSuggestionModal.tsx +++ b/static/app/components/onboarding/frameworkSuggestionModal.tsx @@ -12,7 +12,7 @@ import {Radio} from 'sentry/components/core/radio'; import {RadioLineItem} from 'sentry/components/forms/controls/radioGroup'; import List from 'sentry/components/list'; import ListItem from 'sentry/components/list/listItem'; -import {useIsCreatingProject} from 'sentry/components/onboarding/useCreateProject'; +import {useIsCreatingProjectAndRules} from 'sentry/components/onboarding/useCreateProjectAndRules'; import Panel from 'sentry/components/panels/panel'; import PanelBody from 'sentry/components/panels/panelBody'; import categoryList, {createablePlatforms} from 'sentry/data/platformPickerCategories'; @@ -133,7 +133,8 @@ export function FrameworkSuggestionModal({ organization, newOrg, }: FrameworkSuggestionModalProps) { - const isCreatingProject = useIsCreatingProject(); + const isCreatingProjectAndRules = useIsCreatingProjectAndRules(); + const [selectedFramework, setSelectedFramework] = useState< OnboardingSelectedSDK | undefined >(selectedPlatform); @@ -306,7 +307,11 @@ export function FrameworkSuggestionModal({
-
diff --git a/static/app/components/onboarding/useCreateProject.tsx b/static/app/components/onboarding/useCreateProject.tsx index 178541f0255eb0..02b75ca679e628 100644 --- a/static/app/components/onboarding/useCreateProject.tsx +++ b/static/app/components/onboarding/useCreateProject.tsx @@ -1,13 +1,11 @@ import ProjectsStore from 'sentry/stores/projectsStore'; import type {OnboardingSelectedSDK} from 'sentry/types/onboarding'; import type {Project} from 'sentry/types/project'; -import {useIsMutating, useMutation} from 'sentry/utils/queryClient'; +import {useMutation} from 'sentry/utils/queryClient'; import type RequestError from 'sentry/utils/requestError/requestError'; import useApi from 'sentry/utils/useApi'; import useOrganization from 'sentry/utils/useOrganization'; -const MUTATION_KEY = 'create-project'; - interface Variables { platform: OnboardingSelectedSDK; default_rules?: boolean; @@ -20,7 +18,6 @@ export function useCreateProject() { const organization = useOrganization(); return useMutation({ - mutationKey: [MUTATION_KEY], mutationFn: ({firstTeamSlug, name, platform, default_rules}) => { return api.requestPromise( firstTeamSlug @@ -42,7 +39,3 @@ export function useCreateProject() { }, }); } - -export function useIsCreatingProject() { - return Boolean(useIsMutating({mutationKey: [MUTATION_KEY]})); -} diff --git a/static/app/components/onboarding/useCreateProjectAndRules.tsx b/static/app/components/onboarding/useCreateProjectAndRules.tsx new file mode 100644 index 00000000000000..0b5c850928f088 --- /dev/null +++ b/static/app/components/onboarding/useCreateProjectAndRules.tsx @@ -0,0 +1,72 @@ +import {useCreateProject} from 'sentry/components/onboarding/useCreateProject'; +import {useCreateProjectRules} from 'sentry/components/onboarding/useCreateProjectRules'; +import type {OnboardingSelectedSDK} from 'sentry/types/onboarding'; +import {defined} from 'sentry/utils'; +import {useIsMutating, useMutation} from 'sentry/utils/queryClient'; +import type {useCreateNotificationAction} from 'sentry/views/projectInstall/issueAlertNotificationOptions'; +import type {RequestDataFragment} from 'sentry/views/projectInstall/issueAlertOptions'; + +const MUTATION_KEY = 'create-project-and-rules'; + +export function useCreateProjectAndRules() { + const createProject = useCreateProject(); + const createProjectRules = useCreateProjectRules(); + + return useMutation({ + mutationKey: [MUTATION_KEY], + mutationFn: async ({ + projectName, + platform, + alertRuleConfig, + team, + createNotificationAction, + }: { + alertRuleConfig: Partial; + createNotificationAction: ReturnType< + typeof useCreateNotificationAction + >['createNotificationAction']; + platform: OnboardingSelectedSDK; + projectName: string; + team?: string; + }) => { + const project = await createProject.mutateAsync({ + name: projectName, + platform, + default_rules: alertRuleConfig?.defaultRules ?? true, + firstTeamSlug: team, + }); + + const ruleIds = []; + + if (alertRuleConfig?.shouldCreateCustomRule) { + const ruleData = await createProjectRules.mutateAsync({ + projectSlug: project.slug, + name: project.name, + conditions: alertRuleConfig?.conditions, + actions: alertRuleConfig?.actions, + actionMatch: alertRuleConfig?.actionMatch, + frequency: alertRuleConfig?.frequency, + }); + + ruleIds.push(ruleData.id); + } + + const notificationRule = await createNotificationAction({ + shouldCreateRule: alertRuleConfig?.shouldCreateRule, + name: project.name, + projectSlug: project.slug, + conditions: alertRuleConfig?.conditions, + actionMatch: alertRuleConfig?.actionMatch, + frequency: alertRuleConfig?.frequency, + }); + + ruleIds.push(notificationRule?.id); + + return {project, ruleIds: ruleIds.filter(defined)}; + }, + }); +} + +export function useIsCreatingProjectAndRules() { + return Boolean(useIsMutating({mutationKey: [MUTATION_KEY]})); +} diff --git a/static/app/views/projectInstall/createProject.tsx b/static/app/views/projectInstall/createProject.tsx index aae8b8b9b51b34..aa4033e94710c4 100644 --- a/static/app/views/projectInstall/createProject.tsx +++ b/static/app/views/projectInstall/createProject.tsx @@ -1,6 +1,7 @@ import {useCallback, useEffect, useMemo, useState} from 'react'; import styled from '@emotion/styled'; import * as Sentry from '@sentry/react'; +import debounce from 'lodash/debounce'; import omit from 'lodash/omit'; import startCase from 'lodash/startCase'; import {PlatformIcon} from 'platformicons'; @@ -18,8 +19,7 @@ import ExternalLink from 'sentry/components/links/externalLink'; import List from 'sentry/components/list'; import ListItem from 'sentry/components/list/listItem'; import {SupportedLanguages} from 'sentry/components/onboarding/frameworkSuggestionModal'; -import {useCreateProject} from 'sentry/components/onboarding/useCreateProject'; -import {useCreateProjectRules} from 'sentry/components/onboarding/useCreateProjectRules'; +import {useCreateProjectAndRules} from 'sentry/components/onboarding/useCreateProjectAndRules'; import type {Platform} from 'sentry/components/platformPicker'; import PlatformPicker from 'sentry/components/platformPicker'; import TeamSelector from 'sentry/components/teamSelector'; @@ -140,8 +140,7 @@ export function CreateProject() { const location = useLocation(); const {createNotificationAction, notificationProps} = useCreateNotificationAction(); const canUserCreateProject = useCanCreateProject(); - const createProject = useCreateProject(); - const createProjectRules = useCreateProjectRules(); + const createProjectAndRules = useCreateProjectAndRules(); const {teams} = useTeams(); const accessTeams = teams.filter((team: Team) => team.access.includes('team:admin')); const referrer = decodeScalar(location.query.referrer); @@ -151,44 +150,6 @@ export function CreateProject() { null ); - const createRules = useCallback( - async ({ - project, - alertRuleConfig, - }: {project: Project} & Pick) => { - const ruleIds = []; - - if (alertRuleConfig?.shouldCreateCustomRule) { - const ruleData = await createProjectRules.mutateAsync({ - projectSlug: project.slug, - name: project.name, - conditions: alertRuleConfig?.conditions, - actions: alertRuleConfig?.actions, - actionMatch: alertRuleConfig?.actionMatch, - frequency: alertRuleConfig?.frequency, - }); - - ruleIds.push(ruleData.id); - } - - const notificationRule = await createNotificationAction({ - shouldCreateRule: alertRuleConfig?.shouldCreateRule, - name: project.name, - projectSlug: project.slug, - conditions: alertRuleConfig?.conditions, - actionMatch: alertRuleConfig?.actionMatch, - frequency: alertRuleConfig?.frequency, - }); - - if (notificationRule) { - ruleIds.push(notificationRule.id); - } - - return ruleIds; - }, - [createNotificationAction, createProjectRules] - ); - const autoFill = useMemo(() => { return referrer === 'getting-started' && projectId === createdProject?.id; }, [referrer, projectId, createdProject?.id]); @@ -235,9 +196,6 @@ export function CreateProject() { missingValues.isMissingMessagingIntegrationChannel, ].filter(value => value).length; - const canSubmitForm = - !createProject.isPending && canUserCreateProject && formErrorCount === 0; - const submitTooltipText = getSubmitTooltipText({ ...missingValues, formErrorCount, @@ -284,17 +242,15 @@ export function CreateProject() { let projectToRollback: Project | undefined; try { - const project = await createProject.mutateAsync({ - name: projectName, + const {project, ruleIds} = await createProjectAndRules.mutateAsync({ + projectName, platform: selectedPlatform, - default_rules: alertRuleConfig?.defaultRules ?? true, - firstTeamSlug: team, + team, + alertRuleConfig, + createNotificationAction, }); - projectToRollback = project; - const ruleIds = await createRules({project, alertRuleConfig}); - trackAnalytics('project_creation_page.created', { organization, issue_alert: alertRuleConfig?.defaultRules @@ -373,11 +329,20 @@ export function CreateProject() { } } }, - [createRules, organization, createProject, setCreatedProject, navigate, api] + [ + organization, + setCreatedProject, + navigate, + api, + createProjectAndRules, + createNotificationAction, + ] ); const handleProjectCreation = useCallback( async (data: FormData) => { + setErrors(undefined); + const selectedPlatform = data.platform; if (!isNotPartialPlatform(selectedPlatform)) { @@ -428,6 +393,11 @@ export function CreateProject() { [configurePlatform, organization] ); + const debounceHandleProjectCreation = useMemo( + () => debounce(handleProjectCreation, 2000, {leading: true, trailing: false}), + [handleProjectCreation] + ); + const handlePlatformChange = useCallback( (value: Platform | null) => { if (!value) { @@ -549,8 +519,9 @@ export function CreateProject() { From a7170ef560be3fb4594b4277ad4b4907c360272b Mon Sep 17 00:00:00 2001 From: Priscila Oliveira Date: Fri, 23 May 2025 14:00:49 +0200 Subject: [PATCH 3/9] feedback --- .../onboarding/useCreateProjectAndRules.tsx | 27 ++++++++++++------- .../views/projectInstall/createProject.tsx | 10 +++---- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/static/app/components/onboarding/useCreateProjectAndRules.tsx b/static/app/components/onboarding/useCreateProjectAndRules.tsx index 0b5c850928f088..0b96cfca7912a9 100644 --- a/static/app/components/onboarding/useCreateProjectAndRules.tsx +++ b/static/app/components/onboarding/useCreateProjectAndRules.tsx @@ -1,18 +1,35 @@ import {useCreateProject} from 'sentry/components/onboarding/useCreateProject'; import {useCreateProjectRules} from 'sentry/components/onboarding/useCreateProjectRules'; import type {OnboardingSelectedSDK} from 'sentry/types/onboarding'; +import type {Project} from 'sentry/types/project'; import {defined} from 'sentry/utils'; import {useIsMutating, useMutation} from 'sentry/utils/queryClient'; +import type RequestError from 'sentry/utils/requestError/requestError'; import type {useCreateNotificationAction} from 'sentry/views/projectInstall/issueAlertNotificationOptions'; import type {RequestDataFragment} from 'sentry/views/projectInstall/issueAlertOptions'; const MUTATION_KEY = 'create-project-and-rules'; +type Variables = { + alertRuleConfig: Partial; + createNotificationAction: ReturnType< + typeof useCreateNotificationAction + >['createNotificationAction']; + platform: OnboardingSelectedSDK; + projectName: string; + team?: string; +}; + +type Response = { + project: Project; + ruleIds: string[]; +}; + export function useCreateProjectAndRules() { const createProject = useCreateProject(); const createProjectRules = useCreateProjectRules(); - return useMutation({ + return useMutation({ mutationKey: [MUTATION_KEY], mutationFn: async ({ projectName, @@ -20,14 +37,6 @@ export function useCreateProjectAndRules() { alertRuleConfig, team, createNotificationAction, - }: { - alertRuleConfig: Partial; - createNotificationAction: ReturnType< - typeof useCreateNotificationAction - >['createNotificationAction']; - platform: OnboardingSelectedSDK; - projectName: string; - team?: string; }) => { const project = await createProject.mutateAsync({ name: projectName, diff --git a/static/app/views/projectInstall/createProject.tsx b/static/app/views/projectInstall/createProject.tsx index aa4033e94710c4..8c01c49e211f4f 100644 --- a/static/app/views/projectInstall/createProject.tsx +++ b/static/app/views/projectInstall/createProject.tsx @@ -135,7 +135,6 @@ const keyToErrorText: Record = { export function CreateProject() { const api = useApi(); const navigate = useNavigate(); - const [errors, setErrors] = useState(); const organization = useOrganization(); const location = useLocation(); const {createNotificationAction, notificationProps} = useCreateNotificationAction(); @@ -297,7 +296,6 @@ export function CreateProject() { ) ); } catch (error) { - setErrors(error.responseJSON); addErrorMessage(t('Failed to create project %s', `${projectName}`)); // Only log this if the error is something other than: @@ -341,8 +339,6 @@ export function CreateProject() { const handleProjectCreation = useCallback( async (data: FormData) => { - setErrors(undefined); - const selectedPlatform = data.platform; if (!isNotPartialPlatform(selectedPlatform)) { @@ -528,13 +524,13 @@ export function CreateProject() { - {errors && ( + {createProjectAndRules.isError && createProjectAndRules.error.responseJSON && ( - {Object.keys(errors).map(key => ( + {Object.keys(createProjectAndRules.error.responseJSON).map(key => (
{keyToErrorText[key] ?? startCase(key)}:{' '} - {(errors as any)[key]} + {(createProjectAndRules.error.responseJSON as any)[key]}
))}
From c5dfc7a0b738ecb9aa0df831e2ee999bd787e3f2 Mon Sep 17 00:00:00 2001 From: Priscila Oliveira Date: Fri, 23 May 2025 14:06:58 +0200 Subject: [PATCH 4/9] feedback 2 --- .../onboarding/useCreateProjectAndRules.tsx | 31 +++++++++---------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/static/app/components/onboarding/useCreateProjectAndRules.tsx b/static/app/components/onboarding/useCreateProjectAndRules.tsx index 0b96cfca7912a9..6a45c4a0325b7a 100644 --- a/static/app/components/onboarding/useCreateProjectAndRules.tsx +++ b/static/app/components/onboarding/useCreateProjectAndRules.tsx @@ -45,22 +45,18 @@ export function useCreateProjectAndRules() { firstTeamSlug: team, }); - const ruleIds = []; + const customRulePromise = alertRuleConfig?.shouldCreateCustomRule + ? createProjectRules.mutateAsync({ + projectSlug: project.slug, + name: project.name, + conditions: alertRuleConfig?.conditions, + actions: alertRuleConfig?.actions, + actionMatch: alertRuleConfig?.actionMatch, + frequency: alertRuleConfig?.frequency, + }) + : undefined; - if (alertRuleConfig?.shouldCreateCustomRule) { - const ruleData = await createProjectRules.mutateAsync({ - projectSlug: project.slug, - name: project.name, - conditions: alertRuleConfig?.conditions, - actions: alertRuleConfig?.actions, - actionMatch: alertRuleConfig?.actionMatch, - frequency: alertRuleConfig?.frequency, - }); - - ruleIds.push(ruleData.id); - } - - const notificationRule = await createNotificationAction({ + const notificationRulePromise = createNotificationAction({ shouldCreateRule: alertRuleConfig?.shouldCreateRule, name: project.name, projectSlug: project.slug, @@ -69,9 +65,10 @@ export function useCreateProjectAndRules() { frequency: alertRuleConfig?.frequency, }); - ruleIds.push(notificationRule?.id); + const rules = await Promise.all([customRulePromise, notificationRulePromise]); + const ruleIds = rules.filter(defined).map(rule => rule.id); - return {project, ruleIds: ruleIds.filter(defined)}; + return {project, ruleIds}; }, }); } From 7f0ae304193acbc5addb63111e83c5824db3017f Mon Sep 17 00:00:00 2001 From: Priscila Oliveira Date: Tue, 27 May 2025 09:21:01 +0200 Subject: [PATCH 5/9] it does not need to be tsx --- .../{useCreateProjectRules.tsx => useCreateProjectRules.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename static/app/components/onboarding/{useCreateProjectRules.tsx => useCreateProjectRules.ts} (100%) diff --git a/static/app/components/onboarding/useCreateProjectRules.tsx b/static/app/components/onboarding/useCreateProjectRules.ts similarity index 100% rename from static/app/components/onboarding/useCreateProjectRules.tsx rename to static/app/components/onboarding/useCreateProjectRules.ts From 3c6c200fe54e39e7ffbc305fd66505085cb1a7f0 Mon Sep 17 00:00:00 2001 From: Priscila Oliveira Date: Tue, 27 May 2025 09:41:40 +0200 Subject: [PATCH 6/9] it does not need to be tsx --- .../{useCreateProjectAndRules.tsx => useCreateProjectAndRules.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename static/app/components/onboarding/{useCreateProjectAndRules.tsx => useCreateProjectAndRules.ts} (100%) diff --git a/static/app/components/onboarding/useCreateProjectAndRules.tsx b/static/app/components/onboarding/useCreateProjectAndRules.ts similarity index 100% rename from static/app/components/onboarding/useCreateProjectAndRules.tsx rename to static/app/components/onboarding/useCreateProjectAndRules.ts From 6a9963c942670346166b007fac1212a3da8f2c61 Mon Sep 17 00:00:00 2001 From: Priscila Oliveira Date: Tue, 3 Jun 2025 08:08:57 +0200 Subject: [PATCH 7/9] fix conflict --- .../views/projectInstall/createProject.tsx | 51 ------------------- 1 file changed, 51 deletions(-) diff --git a/static/app/views/projectInstall/createProject.tsx b/static/app/views/projectInstall/createProject.tsx index b36e2cca2d2586..8c01c49e211f4f 100644 --- a/static/app/views/projectInstall/createProject.tsx +++ b/static/app/views/projectInstall/createProject.tsx @@ -19,12 +19,7 @@ import ExternalLink from 'sentry/components/links/externalLink'; import List from 'sentry/components/list'; import ListItem from 'sentry/components/list/listItem'; import {SupportedLanguages} from 'sentry/components/onboarding/frameworkSuggestionModal'; -<<<<<<< HEAD import {useCreateProjectAndRules} from 'sentry/components/onboarding/useCreateProjectAndRules'; -======= -import {useCreateProject} from 'sentry/components/onboarding/useCreateProject'; -import {useCreateProjectRules} from 'sentry/components/onboarding/useCreateProjectRules'; ->>>>>>> master import type {Platform} from 'sentry/components/platformPicker'; import PlatformPicker from 'sentry/components/platformPicker'; import TeamSelector from 'sentry/components/teamSelector'; @@ -144,12 +139,7 @@ export function CreateProject() { const location = useLocation(); const {createNotificationAction, notificationProps} = useCreateNotificationAction(); const canUserCreateProject = useCanCreateProject(); -<<<<<<< HEAD const createProjectAndRules = useCreateProjectAndRules(); -======= - const createProject = useCreateProject(); - const createProjectRules = useCreateProjectRules(); ->>>>>>> master const {teams} = useTeams(); const accessTeams = teams.filter((team: Team) => team.access.includes('team:admin')); const referrer = decodeScalar(location.query.referrer); @@ -159,47 +149,6 @@ export function CreateProject() { null ); -<<<<<<< HEAD -======= - const createRules = useCallback( - async ({ - project, - alertRuleConfig, - }: {project: Project} & Pick) => { - const ruleIds = []; - - if (alertRuleConfig?.shouldCreateCustomRule) { - const ruleData = await createProjectRules.mutateAsync({ - projectSlug: project.slug, - name: project.name, - conditions: alertRuleConfig?.conditions, - actions: alertRuleConfig?.actions, - actionMatch: alertRuleConfig?.actionMatch, - frequency: alertRuleConfig?.frequency, - }); - - ruleIds.push(ruleData.id); - } - - const notificationRule = await createNotificationAction({ - shouldCreateRule: alertRuleConfig?.shouldCreateRule, - name: project.name, - projectSlug: project.slug, - conditions: alertRuleConfig?.conditions, - actionMatch: alertRuleConfig?.actionMatch, - frequency: alertRuleConfig?.frequency, - }); - - if (notificationRule) { - ruleIds.push(notificationRule.id); - } - - return ruleIds; - }, - [createNotificationAction, createProjectRules] - ); - ->>>>>>> master const autoFill = useMemo(() => { return referrer === 'getting-started' && projectId === createdProject?.id; }, [referrer, projectId, createdProject?.id]); From eeed64d7136967d4becbf06c56aabf6dd74ec0c6 Mon Sep 17 00:00:00 2001 From: Priscila Oliveira Date: Tue, 3 Jun 2025 08:17:13 +0200 Subject: [PATCH 8/9] ref(onboarding): Add persistInFlight to all mutations --- static/app/components/onboarding/useMutateOnboardingTasks.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static/app/components/onboarding/useMutateOnboardingTasks.tsx b/static/app/components/onboarding/useMutateOnboardingTasks.tsx index 0d70e816a6739a..9ff5ece5608e0c 100644 --- a/static/app/components/onboarding/useMutateOnboardingTasks.tsx +++ b/static/app/components/onboarding/useMutateOnboardingTasks.tsx @@ -8,7 +8,7 @@ import useOrganization from 'sentry/utils/useOrganization'; * Custom hook to update multiple onboarding tasks in parallel. */ export function useMutateOnboardingTasks() { - const api = useApi(); + const api = useApi({persistInFlight: true}); const organization = useOrganization(); return useMutation({ From 59a73fae5977510f2970b0a95433a0b4c20b791c Mon Sep 17 00:00:00 2001 From: Priscila Oliveira Date: Tue, 3 Jun 2025 08:17:13 +0200 Subject: [PATCH 9/9] ref(onboarding): Add persistInFlight to all mutations --- static/app/components/onboarding/useCreateProject.tsx | 2 +- static/app/components/onboarding/useMutateOnboardingTasks.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/static/app/components/onboarding/useCreateProject.tsx b/static/app/components/onboarding/useCreateProject.tsx index 02b75ca679e628..73df713f5238bb 100644 --- a/static/app/components/onboarding/useCreateProject.tsx +++ b/static/app/components/onboarding/useCreateProject.tsx @@ -14,7 +14,7 @@ interface Variables { } export function useCreateProject() { - const api = useApi(); + const api = useApi({persistInFlight: true}); const organization = useOrganization(); return useMutation({ diff --git a/static/app/components/onboarding/useMutateOnboardingTasks.tsx b/static/app/components/onboarding/useMutateOnboardingTasks.tsx index 0d70e816a6739a..9ff5ece5608e0c 100644 --- a/static/app/components/onboarding/useMutateOnboardingTasks.tsx +++ b/static/app/components/onboarding/useMutateOnboardingTasks.tsx @@ -8,7 +8,7 @@ import useOrganization from 'sentry/utils/useOrganization'; * Custom hook to update multiple onboarding tasks in parallel. */ export function useMutateOnboardingTasks() { - const api = useApi(); + const api = useApi({persistInFlight: true}); const organization = useOrganization(); return useMutation({