diff --git a/apis/api-users/src/schema/user/findOrFetchUser.ts b/apis/api-users/src/schema/user/findOrFetchUser.ts index 38d5d656395..1dce0a2a72e 100644 --- a/apis/api-users/src/schema/user/findOrFetchUser.ts +++ b/apis/api-users/src/schema/user/findOrFetchUser.ts @@ -85,8 +85,8 @@ export async function findOrFetchUser( if (user == null) { try { user = await prisma.user.create({ - data - }) + data + }) userCreated = true } catch { user = await prisma.user.findUnique({ diff --git a/apps/journeys-admin/__generated__/GetAdminJourneys.ts b/apps/journeys-admin/__generated__/GetAdminJourneys.ts index 014c09aa5b4..3f904fb27b0 100644 --- a/apps/journeys-admin/__generated__/GetAdminJourneys.ts +++ b/apps/journeys-admin/__generated__/GetAdminJourneys.ts @@ -103,12 +103,6 @@ export interface GetAdminJourneys_journeys { } export interface GetAdminJourneys { - /** - * returns all journeys that match the provided filters - * If no team id is provided and template is not true then only returns journeys - * where the user is not a member of a team but is an editor or owner of the - * journey - */ journeys: GetAdminJourneys_journeys[]; } diff --git a/apps/journeys-admin/__generated__/JourneyDuplicate.ts b/apps/journeys-admin/__generated__/JourneyDuplicate.ts index 7724c5a5900..0f6479f1bec 100644 --- a/apps/journeys-admin/__generated__/JourneyDuplicate.ts +++ b/apps/journeys-admin/__generated__/JourneyDuplicate.ts @@ -21,4 +21,5 @@ export interface JourneyDuplicateVariables { id: string; teamId: string; forceNonTemplate?: boolean | null; + duplicateAsDraft?: boolean | null; } diff --git a/apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/LanguageScreen/LanguageScreen.tsx b/apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/LanguageScreen/LanguageScreen.tsx index 18cee381add..53bef70f5e9 100644 --- a/apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/LanguageScreen/LanguageScreen.tsx +++ b/apps/journeys-admin/src/components/TemplateCustomization/MultiStepForm/Screens/LanguageScreen/LanguageScreen.tsx @@ -9,7 +9,7 @@ import { useRouter } from 'next/router' import { useUser } from 'next-firebase-auth' import { useTranslation } from 'next-i18next' import { useSnackbar } from 'notistack' -import { ReactElement, useEffect, useState } from 'react' +import { ReactElement, useState } from 'react' import { object } from 'yup' import { useJourney } from '@core/journeys/ui/JourneyProvider' @@ -19,27 +19,14 @@ import { useJourneyDuplicateMutation } from '@core/journeys/ui/useJourneyDuplica import { LanguageAutocomplete } from '@core/shared/ui/LanguageAutocomplete' import { JourneyProfileCreate } from '../../../../../../__generated__/JourneyProfileCreate' +import { JourneyStatus } from '../../../../../../__generated__/globalTypes' import { useCurrentUserLazyQuery } from '../../../../../libs/useCurrentUserLazyQuery' import { useGetChildTemplateJourneyLanguages } from '../../../../../libs/useGetChildTemplateJourneyLanguages' import { useGetParentTemplateJourneyLanguages } from '../../../../../libs/useGetParentTemplateJourneyLanguages' -import { - useTeamCreateMutation, - useTeamCreateMutationGuest -} from '../../../../../libs/useTeamCreateMutation' +import { useTeamCreateMutation } from '../../../../../libs/useTeamCreateMutation' import { CustomizationScreen } from '../../../utils/getCustomizeFlowConfig' import { CustomizeFlowNextButton } from '../../CustomizeFlowNextButton' - -// const JOURNEY_PROFILE_CREATE = gql` -// mutation JourneyProfileCreate { -// journeyProfileCreate { -// id -// userId -// acceptedTermsAt -// } -// } -// ` - interface LanguageScreenProps { handleNext: () => void handleScreenNavigation: (screen: CustomizationScreen) => void @@ -60,14 +47,6 @@ export function LanguageScreen({ const isSignedIn = user?.email != null && user?.id != null const { query } = useTeam() - useEffect(() => { - //TODO: delete this effect - const firebaseUserId = user?.id ?? null - const isAnonymous = user?.firebaseUser?.isAnonymous ?? false - console.log('[LanguageScreen] Firebase user id:', firebaseUserId) - console.log('[LanguageScreen] Is anonymous user:', isAnonymous) - }, [user?.id, user?.firebaseUser?.isAnonymous]) - const isParentTemplate = journey?.fromTemplateId == null const { @@ -131,121 +110,45 @@ export function LanguageScreen({ const [journeyDuplicate] = useJourneyDuplicateMutation() const { loadUser } = useCurrentUserLazyQuery() - // const [journeyProfileCreate] = useMutation( - // JOURNEY_PROFILE_CREATE - // ) const [teamCreate] = useTeamCreateMutation() - const [teamCreateGuest] = useTeamCreateMutationGuest() const FORM_SM_BREAKPOINT_WIDTH = '390px' - async function createGuestUser(): Promise<{ teamId: string } | null> { - try { - console.log('[createGuestUser] 1. start', { - isAnonymous: user?.firebaseUser?.isAnonymous ?? false - }) - const isAnonymous = user?.firebaseUser?.isAnonymous ?? false - if (!isAnonymous) { - console.log('[createGuestUser] 2. calling signInAnonymously') - await signInAnonymously(getAuth(getApp())) - console.log('[createGuestUser] 3. signInAnonymously done') - } else { - console.log('[createGuestUser] 2. already anonymous, skip signInAnonymously') - } - - const teamName = t('My Team') - - let meResult: Awaited> | null = null - try { - console.log('[createGuestUser] 4. calling loadUser') - meResult = await loadUser() - console.log('[createGuestUser] 5. loadUser done', { - hasMe: meResult?.data?.me != null, - __typename: meResult?.data?.me?.__typename - }) - } catch (e) { - console.error('[createGuestUser] loadUser failed:', e) + async function createGuestUser(): Promise<{ teamId: string }> { + const teamName = t('My Team') + const isAnonymous = user?.firebaseUser?.isAnonymous ?? false + if (!isAnonymous) { + await signInAnonymously(getAuth(getApp())) } - // let profileResult: Awaited> | null = - // null - // try { - // profileResult = await journeyProfileCreate() - // } catch (e) { - // console.error('[createGuestUser] journeyProfileCreate failed:', e) - // } - - let teamResult: Awaited> | null = null - try { - console.log('[createGuestUser] 6. calling teamCreate', { teamName }) - teamResult = await teamCreateGuest({ + const [, teamResult] = await Promise.all([ + loadUser().catch(() => null), + teamCreate({ variables: { input: { title: teamName, publicTitle: teamName } } }) - console.log('[createGuestUser] 7. teamCreate done', { - teamId: teamResult?.data?.teamCreate?.id - }) - } catch (e) { - const err = e as { - graphQLErrors?: Array<{ message: string; extensions?: unknown }> - networkError?: unknown - message?: string - cause?: unknown - } - console.error('[createGuestUser] teamCreate failed:', err?.message ?? e) - if (err?.graphQLErrors?.length) { - err.graphQLErrors.forEach((g, i) => { - console.error( - `[createGuestUser] graphQLErrors[${i}]:`, - g.message, - g.extensions - ) - }) - } - if (err?.networkError) { - console.error('[createGuestUser] networkError:', err.networkError) - } - if (err?.cause != null) { - console.error('[createGuestUser] cause:', err.cause) - } - return null - } + ]) if (teamResult?.data?.teamCreate == null) { - console.log('[createGuestUser] 8. returning null (team missing)', { - hasMe: meResult?.data?.me != null, - hasTeam: false - }) - return null + throw new Error('Guest team creation returned no team') } - // Refetch me after teamCreate (user was created in resolveReference); optional for guest flow - if (meResult?.data?.me == null) { - try { - await loadUser() - } catch { - // ignore - } - } - - // Guest flow success: we have a team (user exists in api-users via resolveReference) - console.log('[createGuestUser] 9. success', { - teamId: teamResult.data.teamCreate.id - }) - return { teamId: teamResult.data.teamCreate.id } - } catch (e) { - console.error('[createGuestUser] unexpected error:', e) - return null - } + return { teamId: teamResult.data.teamCreate.id } } async function duplicateJourneyAndRedirect( journeyId: string, - teamId: string + teamId: string, + duplicateAsDraft?: boolean ): Promise { const { data } = await journeyDuplicate({ - variables: { id: journeyId, teamId, forceNonTemplate: true } + variables: { + id: journeyId, + teamId, + forceNonTemplate: true, + duplicateAsDraft + } }) if (data?.journeyDuplicate == null) return false @@ -276,16 +179,14 @@ export function LanguageScreen({ } if (isSignedIn) { + // Duplicates journey for a signed in user const teams = query?.data?.teams ?? [] const teamId = query?.data?.getJourneyProfile?.lastActiveTeamId ?? teams[0]?.id if (teamId == null) { - enqueueSnackbar( - t( - 'No team available. Please create a team first.' - ), - { variant: 'error' } - ) + enqueueSnackbar(t('No team available. Please create a team first.'), { + variant: 'error' + }) setLoading(false) return } @@ -303,43 +204,25 @@ export function LanguageScreen({ setLoading(false) return } else { + // Creates a guest user and duplicates the journey for them try { const guestResult = await createGuestUser() - if (guestResult == null) { - enqueueSnackbar( - t('Unable to continue as guest. Please try again or sign in.'), - { variant: 'error' } - ) - setLoading(false) - return - } - - try { - const success = await duplicateJourneyAndRedirect( - journeyId, - guestResult.teamId - ) - if (!success) { - enqueueSnackbar( - t( - 'Failed to duplicate journey to team, please refresh the page and try again' - ), - { variant: 'error' } - ) - } else { - handleNext() - } - } catch (e) { - console.error('[LanguageScreen] duplicateJourneyAndRedirect error:', e) + const journeyDuplicateSuccess = await duplicateJourneyAndRedirect( + journeyId, + guestResult.teamId, + true + ) + if (!journeyDuplicateSuccess) { enqueueSnackbar( t( 'Failed to duplicate journey to team, please refresh the page and try again' ), { variant: 'error' } ) + } else { + handleNext() } - } catch (e) { - console.error('[LanguageScreen] createGuestUser error:', e) + } catch { enqueueSnackbar( t('Unable to continue as guest. Please try again or sign in.'), { variant: 'error' } diff --git a/apps/journeys-admin/src/libs/useTeamCreateMutation/index.ts b/apps/journeys-admin/src/libs/useTeamCreateMutation/index.ts index 01b7632c399..38ddb0db05b 100644 --- a/apps/journeys-admin/src/libs/useTeamCreateMutation/index.ts +++ b/apps/journeys-admin/src/libs/useTeamCreateMutation/index.ts @@ -1,4 +1 @@ -export { - useTeamCreateMutation, - useTeamCreateMutationGuest -} from './useTeamCreateMutation' +export { useTeamCreateMutation } from './useTeamCreateMutation' diff --git a/apps/journeys-admin/src/libs/useTeamCreateMutation/useTeamCreateMutation.tsx b/apps/journeys-admin/src/libs/useTeamCreateMutation/useTeamCreateMutation.tsx index 8a27f4257fa..fb2e66796ec 100644 --- a/apps/journeys-admin/src/libs/useTeamCreateMutation/useTeamCreateMutation.tsx +++ b/apps/journeys-admin/src/libs/useTeamCreateMutation/useTeamCreateMutation.tsx @@ -42,33 +42,6 @@ export const TEAM_CREATE = gql` } ` -/** Minimal selection for guest flow: only user.id to avoid User entity field resolution errors in federation. */ -export const TEAM_CREATE_GUEST = gql` - mutation TeamCreateGuest($input: TeamCreateInput!) { - teamCreate(input: $input) { - id - title - publicTitle - userTeams { - id - user { - ... on AuthenticatedUser { - id - } - ... on AnonymousUser { - id - } - } - role - } - customDomains { - id - name - } - } - } -` - export function useTeamCreateMutation( options?: MutationHookOptions ): MutationTuple { @@ -103,37 +76,3 @@ export function useTeamCreateMutation( return mutation } - -/** Use for guest flow: only requests user.id to avoid federation User field resolution errors. */ -export function useTeamCreateMutationGuest( - options?: MutationHookOptions -): MutationTuple { - const { setActiveTeam } = useTeam() - return useMutation(TEAM_CREATE_GUEST, { - update(cache, { data }) { - if (data?.teamCreate != null) { - cache.modify({ - fields: { - teams(existingTeams = []) { - const newTeamRef = cache.writeFragment({ - data: data.teamCreate, - fragment: gql` - fragment NewTeam on Team { - id - } - ` - }) - return [...existingTeams, newTeamRef] - } - } - }) - } - }, - onCompleted(data) { - if (data?.teamCreate != null) { - setActiveTeam(data.teamCreate) - } - }, - ...options - }) -} diff --git a/libs/journeys/ui/src/components/TemplateView/UseThisTemplateButton/UseThisTemplateButton.tsx b/libs/journeys/ui/src/components/TemplateView/UseThisTemplateButton/UseThisTemplateButton.tsx index 9f2d29d3c23..7b16534ee41 100644 --- a/libs/journeys/ui/src/components/TemplateView/UseThisTemplateButton/UseThisTemplateButton.tsx +++ b/libs/journeys/ui/src/components/TemplateView/UseThisTemplateButton/UseThisTemplateButton.tsx @@ -36,12 +36,12 @@ export function UseThisTemplateButton({ const handleCheckSignIn = async (): Promise => { // For menu-item variant, assume user is signed in - // if (variant === 'menu-item' || signedIn) { - setLoading(true) - await handleCustomizeNavigation() - // } else { - // setOpenAccountDialog(true) - // } + if (variant === 'menu-item' || signedIn) { + setLoading(true) + await handleCustomizeNavigation() + } else { + setOpenAccountDialog(true) + } } const handleSignIn = (login: boolean): void => { diff --git a/libs/journeys/ui/src/libs/useJourneyDuplicateMutation/__generated__/JourneyDuplicate.ts b/libs/journeys/ui/src/libs/useJourneyDuplicateMutation/__generated__/JourneyDuplicate.ts index 7724c5a5900..0f6479f1bec 100644 --- a/libs/journeys/ui/src/libs/useJourneyDuplicateMutation/__generated__/JourneyDuplicate.ts +++ b/libs/journeys/ui/src/libs/useJourneyDuplicateMutation/__generated__/JourneyDuplicate.ts @@ -21,4 +21,5 @@ export interface JourneyDuplicateVariables { id: string; teamId: string; forceNonTemplate?: boolean | null; + duplicateAsDraft?: boolean | null; } diff --git a/libs/journeys/ui/src/libs/useJourneyDuplicateMutation/useJourneyDuplicateMutation.ts b/libs/journeys/ui/src/libs/useJourneyDuplicateMutation/useJourneyDuplicateMutation.ts index de4bc675056..40b3bb5b446 100644 --- a/libs/journeys/ui/src/libs/useJourneyDuplicateMutation/useJourneyDuplicateMutation.ts +++ b/libs/journeys/ui/src/libs/useJourneyDuplicateMutation/useJourneyDuplicateMutation.ts @@ -15,11 +15,13 @@ export const JOURNEY_DUPLICATE = gql` $id: ID! $teamId: ID! $forceNonTemplate: Boolean + $duplicateAsDraft: Boolean ) { journeyDuplicate( id: $id teamId: $teamId forceNonTemplate: $forceNonTemplate + duplicateAsDraft: $duplicateAsDraft ) { id template diff --git a/libs/locales/en/journeys-ui.json b/libs/locales/en/journeys-ui.json index b059ab4592a..efc32e3c7b4 100644 --- a/libs/locales/en/journeys-ui.json +++ b/libs/locales/en/journeys-ui.json @@ -1,4 +1,6 @@ { + "My Team": "My Team", + "Unable to continue as guest. Please try again or sign in.": "Unable to continue as guest. Please try again or sign in.", "Failed to duplicate journey to team, please refresh the page and try again": "Failed to duplicate journey to team, please refresh the page and try again", "Let's get started!": "Let's get started!", "A few quick edits and your template will be ready to share.": "A few quick edits and your template will be ready to share.",