From c94114ffcbac3a6ca54f4b72d9418b37affdcc81 Mon Sep 17 00:00:00 2001 From: Luis Felipe Zaguini <26530524+zaguiini@users.noreply.github.com> Date: Tue, 24 Dec 2024 15:07:30 -0300 Subject: [PATCH] Goals and DP first: Move DIFM intro before account (#97749) * Goals and DP first: Move DIFM intro before account * Goals First: Support backUrl and preselected choice for the DIFM steps * Goals First: Support Use an existing site for logged-in users on the DIFM screen * Fix tests * Don't show site choice if there is a selected site * Display back button on the DIFM for the site-setup flow * Fix styles * Fix types * Add back_to to the loginUrl --------- Co-authored-by: arthur --- .../declarative-flow/internals/global.scss | 1 + .../difm-starting-point/index.tsx | 20 +++++-- .../stepper/declarative-flow/onboarding.ts | 59 +++++++++++++------ .../declarative-flow/site-setup-flow.ts | 7 ++- .../declarative-flow/test/onboarding-flow.tsx | 4 +- client/signup/config/flows-pure.js | 7 ++- .../signup/steps/difm-site-picker/index.tsx | 6 +- .../steps/new-or-existing-site/index.tsx | 24 +++++++- client/signup/steps/site-options/index.tsx | 4 +- 9 files changed, 97 insertions(+), 35 deletions(-) diff --git a/client/landing/stepper/declarative-flow/internals/global.scss b/client/landing/stepper/declarative-flow/internals/global.scss index ddf1920f6edbc..be07373955ac9 100644 --- a/client/landing/stepper/declarative-flow/internals/global.scss +++ b/client/landing/stepper/declarative-flow/internals/global.scss @@ -75,6 +75,7 @@ button { .site-setup, .onboarding.goals, .onboarding.design-setup, +.onboarding.difm-starting-point, .site-migration, .migration, .migration-signup, diff --git a/client/landing/stepper/declarative-flow/internals/steps-repository/difm-starting-point/index.tsx b/client/landing/stepper/declarative-flow/internals/steps-repository/difm-starting-point/index.tsx index f7fdf8094cff8..76f038e8f901d 100644 --- a/client/landing/stepper/declarative-flow/internals/steps-repository/difm-starting-point/index.tsx +++ b/client/landing/stepper/declarative-flow/internals/steps-repository/difm-starting-point/index.tsx @@ -1,21 +1,28 @@ import { StepContainer } from '@automattic/onboarding'; import { useTranslate } from 'i18n-calypso'; +import { useSelector } from 'react-redux'; import DocumentHead from 'calypso/components/data/document-head'; import { useSite } from 'calypso/landing/stepper/hooks/use-site'; import { recordTracksEvent } from 'calypso/lib/analytics/tracks'; import DIFMLanding from 'calypso/my-sites/marketing/do-it-for-me/difm-landing'; +import { getCurrentUserSiteCount } from 'calypso/state/current-user/selectors'; import type { Step } from '../../types'; +import type { AppState } from 'calypso/types'; const STEP_NAME = 'difmStartingPoint'; const DIFMStartingPoint: Step = function ( { navigation } ) { const { goNext, goBack, submit } = navigation; const translate = useTranslate(); + const existingSiteCount = useSelector( ( state: AppState ) => getCurrentUserSiteCount( state ) ); + const siteId = useSite()?.ID; + const showNewOrExistingSiteChoice = ! siteId && !! existingSiteCount && existingSiteCount > 0; - const onSubmit = () => { - submit?.(); + const onSubmit = ( value: string ) => { + submit?.( { + newOrExistingSiteChoice: value, + } ); }; - const siteId = useSite()?.ID; return ( <> @@ -29,8 +36,11 @@ const DIFMStartingPoint: Step = function ( { navigation } ) { skipLabelText={ translate( 'No Thanks, I’ll Build It' ) } stepContent={ + showNewOrExistingSiteChoice ? onSubmit( 'existing-site' ) : onSubmit( 'new-site' ) + } + onSecondarySubmit={ () => onSubmit( 'new-site' ) } + showNewOrExistingSiteChoice={ showNewOrExistingSiteChoice } siteId={ siteId } isStoreFlow={ false } /> diff --git a/client/landing/stepper/declarative-flow/onboarding.ts b/client/landing/stepper/declarative-flow/onboarding.ts index 48dc78a1e4d04..985e90673577d 100644 --- a/client/landing/stepper/declarative-flow/onboarding.ts +++ b/client/landing/stepper/declarative-flow/onboarding.ts @@ -1,4 +1,4 @@ -import { OnboardSelect, Onboard } from '@automattic/data-stores'; +import { OnboardSelect, Onboard, UserSelect } from '@automattic/data-stores'; import { ONBOARDING_FLOW } from '@automattic/onboarding'; import { useDispatch, useSelect } from '@wordpress/data'; import { addQueryArgs, getQueryArg, getQueryArgs, removeQueryArgs } from '@wordpress/url'; @@ -16,7 +16,8 @@ import { } from '../constants'; import { useFlowLocale } from '../hooks/use-flow-locale'; import { useQuery } from '../hooks/use-query'; -import { ONBOARD_STORE } from '../stores'; +import { ONBOARD_STORE, USER_STORE } from '../stores'; +import { getLoginUrl } from '../utils/path'; import { stepsWithRequiredLogin } from '../utils/steps-with-required-login'; import { useGoalsFirstExperiment } from './helpers/use-goals-first-experiment'; import { recordStepNavigation } from './internals/analytics/record-step-navigation'; @@ -83,7 +84,7 @@ const onboarding: Flow = { if ( isGoalsAtFrontExperiment ) { // Note: these steps are not wrapped in `stepsWithRequiredLogin` - steps.unshift( STEPS.GOALS, STEPS.DESIGN_SETUP ); + steps.unshift( STEPS.GOALS, STEPS.DESIGN_SETUP, STEPS.DIFM_STARTING_POINT ); } return steps; @@ -101,11 +102,12 @@ const onboarding: Flow = { } = useDispatch( ONBOARD_STORE ); const locale = useFlowLocale(); - const { planCartItem, signupDomainOrigin } = useSelect( - ( select: ( key: string ) => OnboardSelect ) => ( { - domainCartItem: select( ONBOARD_STORE ).getDomainCartItem(), - planCartItem: select( ONBOARD_STORE ).getPlanCartItem(), + const { planCartItem, signupDomainOrigin, isUserLoggedIn } = useSelect( + ( select ) => ( { + domainCartItem: ( select( ONBOARD_STORE ) as OnboardSelect ).getDomainCartItem(), + planCartItem: ( select( ONBOARD_STORE ) as OnboardSelect ).getPlanCartItem(), signupDomainOrigin: ( select( ONBOARD_STORE ) as OnboardSelect ).getSignupDomainOrigin(), + isUserLoggedIn: ( select( USER_STORE ) as UserSelect ).isCurrentUserLoggedIn(), } ), [] ); @@ -142,18 +144,8 @@ const onboarding: Flow = { ); } - case SiteIntent.DIFM: { - const difmFlowLink = - locale && locale !== 'en' - ? `/start/do-it-for-me/${ locale }` - : '/start/do-it-for-me'; - - return window.location.assign( - addQueryArgs( difmFlowLink, { - back_to: goalsUrl, - } ) - ); - } + case SiteIntent.DIFM: + return navigate( 'difmStartingPoint' ); default: { return navigate( 'designSetup' ); @@ -165,6 +157,32 @@ const onboarding: Flow = { return navigate( 'domains' ); } + case 'difmStartingPoint': { + const { newOrExistingSiteChoice } = providedDependencies; + const difmFlowLink = addQueryArgs( + locale && locale !== 'en' ? `/start/do-it-for-me/${ locale }` : '/start/do-it-for-me', + { + back_to: window.location.href.replace( window.location.origin, '' ), + newOrExistingSiteChoice, + } + ); + + if ( isUserLoggedIn ) { + return window.location.assign( difmFlowLink ); + } + + const loginUrl = getLoginUrl( { + variationName: flowName, + redirectTo: difmFlowLink, + locale, + extra: { + back_to: window.location.href.replace( window.location.origin, '' ), + }, + } ); + + return window.location.assign( loginUrl ); + } + case 'domains': setSiteUrl( providedDependencies.siteUrl ); setDomain( providedDependencies.suggestion ); @@ -249,6 +267,7 @@ const onboarding: Flow = { siteSlug: providedDependencies.siteSlug, ...( isGoalsAtFrontExperiment && { 'goals-at-front-experiment': true } ), } ); + persistSignupDestination( destination ); setSignupCompleteFlowName( flowName ); setSignupCompleteSlug( providedDependencies.siteSlug ); @@ -309,6 +328,8 @@ const onboarding: Flow = { if ( isGoalsAtFrontExperiment ) { return navigate( 'goals' ); } + case 'difmStartingPoint': + return navigate( 'goals' ); default: return; } diff --git a/client/landing/stepper/declarative-flow/site-setup-flow.ts b/client/landing/stepper/declarative-flow/site-setup-flow.ts index 1de834ca78abf..4106c42350c8b 100644 --- a/client/landing/stepper/declarative-flow/site-setup-flow.ts +++ b/client/landing/stepper/declarative-flow/site-setup-flow.ts @@ -491,7 +491,12 @@ const siteSetupFlow: Flow = { return navigate( `importerWordpress?${ urlQueryParams.toString() }` ); case 'difmStartingPoint': { - return exitFlow( `/start/website-design-services/?siteSlug=${ siteSlug }` ); + const backUrl = window.location.href.replace( window.location.origin, '' ); + return exitFlow( + `/start/website-design-services/?siteSlug=${ siteSlug }&back_to=${ encodeURIComponent( + backUrl + ) }` + ); } } } diff --git a/client/landing/stepper/declarative-flow/test/onboarding-flow.tsx b/client/landing/stepper/declarative-flow/test/onboarding-flow.tsx index cd0dd41643cd7..8a2d7414e1bff 100644 --- a/client/landing/stepper/declarative-flow/test/onboarding-flow.tsx +++ b/client/landing/stepper/declarative-flow/test/onboarding-flow.tsx @@ -64,9 +64,7 @@ describe( 'Onboarding Flow', () => { }, } ); - expect( window.location.assign ).toHaveBeenCalledWith( - '/start/do-it-for-me?back_to=%2Fsetup%2Fonboarding%2Fgoals' - ); + expect( getFlowLocation().path ).toBe( '/difmStartingPoint' ); } ); it( 'should navigate to designSetup step for other intents', async () => { diff --git a/client/signup/config/flows-pure.js b/client/signup/config/flows-pure.js index 8d325aaa813f7..9b938574484e7 100644 --- a/client/signup/config/flows-pure.js +++ b/client/signup/config/flows-pure.js @@ -463,8 +463,8 @@ export function generateFlows( { enableBranchSteps: true, hideProgressIndicator: true, enablePresales: false, - providesDependenciesInQuery: [ 'coupon' ], - optionalDependenciesInQuery: [ 'coupon' ], + providesDependenciesInQuery: [ 'coupon', 'back_to', 'newOrExistingSiteChoice' ], + optionalDependenciesInQuery: [ 'coupon', 'back_to', 'newOrExistingSiteChoice' ], }, { name: 'do-it-for-me-store', @@ -493,7 +493,8 @@ export function generateFlows( { destination: getDIFMSignupDestination, description: 'A flow for DIFM onboarding', excludeFromManageSiteFlows: true, - providesDependenciesInQuery: [ 'siteSlug' ], + providesDependenciesInQuery: [ 'siteSlug', 'back_to' ], + optionalDependenciesInQuery: [ 'back_to' ], lastModified: '2024-06-14', enablePresales: false, }, diff --git a/client/signup/steps/difm-site-picker/index.tsx b/client/signup/steps/difm-site-picker/index.tsx index c5cabc82ab35b..0392404517a07 100644 --- a/client/signup/steps/difm-site-picker/index.tsx +++ b/client/signup/steps/difm-site-picker/index.tsx @@ -15,6 +15,7 @@ interface Props { stepSectionName: string | null; stepName: string; flowName: string; + signupDependencies: any; goToStep: () => void; goToNextStep: () => void; } @@ -36,7 +37,8 @@ const DIFMSitePicker = ( { export default function DIFMSitePickerStep( props: Props ) { const translate = useTranslate(); const dispatch = useDispatch(); - const { goToNextStep } = props; + const { signupDependencies, goToNextStep } = props; + const { back_to: backUrl } = signupDependencies; const store = useStore(); const headerText = translate( 'Choose where you want us to build your site.' ); @@ -108,6 +110,8 @@ export default function DIFMSitePickerStep( props: Props ) { fallbackSubHeaderText={ subHeaderText } stepContent={ } hideSkip + backUrl={ backUrl } + allowBackFirstStep={ !! backUrl } { ...props } /> ); diff --git a/client/signup/steps/new-or-existing-site/index.tsx b/client/signup/steps/new-or-existing-site/index.tsx index 40eda449e886c..eccadb676f9a3 100644 --- a/client/signup/steps/new-or-existing-site/index.tsx +++ b/client/signup/steps/new-or-existing-site/index.tsx @@ -18,19 +18,26 @@ interface Props { flowName: string; stepName: string; existingSiteCount: number; + signupDependencies: { + back_to?: string; + newOrExistingSiteChoice?: ChoiceType; + }; } export default function NewOrExistingSiteStep( props: Props ) { const dispatch = useDispatch(); - const { stepName, goToNextStep, existingSiteCount, flowName } = props; + const { stepName, goToNextStep, existingSiteCount, flowName, signupDependencies } = props; + const { back_to: backUrl, newOrExistingSiteChoice: preselectedChoice } = signupDependencies; useEffect( () => { dispatch( saveSignupStep( { stepName } ) ); triggerGuidesForStep( flowName, stepName ); }, [ dispatch, flowName, stepName ] ); - const branchSteps = useBranchSteps( stepName, () => [ 'difm-site-picker' ] ); + const branchSteps = useBranchSteps( stepName, () => + preselectedChoice ? [ 'new-or-existing-site', 'difm-site-picker' ] : [ 'difm-site-picker' ] + ); const newOrExistingSiteSelected = ( value: ChoiceType ) => { // If 'new-site' is selected, skip the `difm-site-picker` step. @@ -52,6 +59,17 @@ export default function NewOrExistingSiteStep( props: Props ) { const showNewOrExistingSiteChoice = existingSiteCount > 0; + // Support pre-selected choice. + useEffect( () => { + if ( preselectedChoice ) { + newOrExistingSiteSelected( preselectedChoice ); + } + }, [ preselectedChoice ] ); + + if ( preselectedChoice ) { + return null; + } + return ( ( siteId ? getSite( state, siteId ) : null ) ); @@ -127,6 +127,8 @@ export default function SiteOptionsStep( props: Props ) { skipButtonAlign="top" skipLabelText={ translate( 'Skip this step' ) } isHorizontalLayout + backUrl={ backUrl } + allowBackFirstStep={ !! backUrl } defaultDependencies={ { siteTitle: '', tagline: '',