From 03e9fd38a9140c03c53d8db777dbb0f0c5f4185f Mon Sep 17 00:00:00 2001 From: Anthony Grullon Date: Thu, 12 Sep 2024 12:47:04 -0400 Subject: [PATCH 01/11] Update use-step-route-tracking to include flow name in page view params --- .../step-route/hooks/use-step-route-tracking/index.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/client/landing/stepper/declarative-flow/internals/components/step-route/hooks/use-step-route-tracking/index.tsx b/client/landing/stepper/declarative-flow/internals/components/step-route/hooks/use-step-route-tracking/index.tsx index 57113946241ea..55f53cc9f731d 100644 --- a/client/landing/stepper/declarative-flow/internals/components/step-route/hooks/use-step-route-tracking/index.tsx +++ b/client/landing/stepper/declarative-flow/internals/components/step-route/hooks/use-step-route-tracking/index.tsx @@ -82,7 +82,10 @@ export const useStepRouteTracking = ( { // Also record page view for data and analytics const pathname = window.location.pathname; const pageTitle = `Setup > ${ flowName } > ${ stepSlug }`; - recordPageView( pathname, pageTitle ); + const params = { + flow: flowName, + }; + recordPageView( pathname, pageTitle, params ); // We leave out intent and design from the dependency list, due to the ONBOARD_STORE being reset in the exit flow. // The store reset causes these values to become empty, and may trigger this event again. From 706b8e548c56ad17a4c8bba5e140e8c0bbbd4476 Mon Sep 17 00:00:00 2001 From: Anthony Grullon Date: Fri, 13 Sep 2024 08:43:13 -0400 Subject: [PATCH 02/11] Fix domains stepper step submit tracks --- .../unified-domains/index.tsx | 91 +++++++++++-------- 1 file changed, 54 insertions(+), 37 deletions(-) diff --git a/client/landing/stepper/declarative-flow/internals/steps-repository/unified-domains/index.tsx b/client/landing/stepper/declarative-flow/internals/steps-repository/unified-domains/index.tsx index c0870a8f583fd..d170e581230b1 100644 --- a/client/landing/stepper/declarative-flow/internals/steps-repository/unified-domains/index.tsx +++ b/client/landing/stepper/declarative-flow/internals/steps-repository/unified-domains/index.tsx @@ -26,58 +26,75 @@ import { import { getAvailableProductsList } from 'calypso/state/products-list/selectors'; import getSitesItems from 'calypso/state/selectors/get-sites-items'; import { fetchUsernameSuggestion } from 'calypso/state/signup/optional-dependencies/actions'; -import { removeStep } from 'calypso/state/signup/progress/actions'; +import { + removeStep, + saveSignupStep, + submitSignupStep, +} from 'calypso/state/signup/progress/actions'; import { setDesignType } from 'calypso/state/signup/steps/design-type/actions'; import { getDesignType } from 'calypso/state/signup/steps/design-type/selectors'; import { getSelectedSite } from 'calypso/state/ui/selectors'; import { ProvidedDependencies, StepProps } from '../../types'; -const RenderDomainsStepConnect = connect( - ( state, { flow }: StepProps ) => { - const productsList = getAvailableProductsList( state ); - const productsLoaded = ! isEmpty( productsList ); - const selectedSite = getSelectedSite( state ); - const multiDomainDefaultPlan = planItem( PLAN_PERSONAL ); - const userLoggedIn = isUserLoggedIn( state as object ); - const currentUserSiteCount = getCurrentUserSiteCount( state as object ); - const stepSectionName = window.location.pathname.includes( 'use-your-domain' ) - ? 'use-your-domain' - : undefined; - - return { - designType: getDesignType( state ), - currentUser: getCurrentUser( state as object ), - productsList, - productsLoaded, - selectedSite, - isDomainOnly: false, - sites: getSitesItems( state ), - userSiteCount: currentUserSiteCount, - previousStepName: 'user', - isPlanSelectionAvailableLaterInFlow: true, - userLoggedIn, - multiDomainDefaultPlan, - domainsWithPlansOnly: currentUserHasFlag( state as object, DOMAINS_WITH_PLANS_ONLY ), - flowName: flow, - path: window.location.pathname, - positionInFlow: 1, - isReskinned: true, - stepSectionName, - }; - }, - { +const mapDispatchToProps = ( dispatch: any, props: any ) => { + return { recordAddDomainButtonClick, recordAddDomainButtonClickInMapDomain, recordAddDomainButtonClickInTransferDomain, recordAddDomainButtonClickInUseYourDomain, recordUseYourDomainButtonClick, removeStep, + saveSignupStep: ( step: Record< string, unknown > ) => { + props.saveSignupStep?.( step ); + dispatch( saveSignupStep( step ) ); + }, + submitSignupStep: ( + step: Record< string, unknown >, + providedDependencies: Record< string, unknown >, + optionalProps: Record< string, unknown > + ) => { + props.submitSignupStep?.( step ); + dispatch( submitSignupStep( step, providedDependencies, optionalProps ) ); + }, submitDomainStepSelection, setDesignType, recordTracksEvent, fetchUsernameSuggestion, - } -)( withCartKey( withShoppingCart( localize( RenderDomainsStep ) ) ) ); + }; +}; + +const RenderDomainsStepConnect = connect( ( state, { flow }: StepProps ) => { + const productsList = getAvailableProductsList( state ); + const productsLoaded = ! isEmpty( productsList ); + const selectedSite = getSelectedSite( state ); + const multiDomainDefaultPlan = planItem( PLAN_PERSONAL ); + const userLoggedIn = isUserLoggedIn( state as object ); + const currentUserSiteCount = getCurrentUserSiteCount( state as object ); + const stepSectionName = window.location.pathname.includes( 'use-your-domain' ) + ? 'use-your-domain' + : undefined; + + return { + designType: getDesignType( state ), + currentUser: getCurrentUser( state as object ), + productsList, + productsLoaded, + selectedSite, + isDomainOnly: false, + sites: getSitesItems( state ), + userSiteCount: currentUserSiteCount, + previousStepName: 'user', + isPlanSelectionAvailableLaterInFlow: true, + userLoggedIn, + multiDomainDefaultPlan, + domainsWithPlansOnly: currentUserHasFlag( state as object, DOMAINS_WITH_PLANS_ONLY ), + flowName: flow, + path: window.location.pathname, + positionInFlow: 1, + isReskinned: true, + stepSectionName, + }; +}, mapDispatchToProps )( withCartKey( withShoppingCart( localize( RenderDomainsStep ) ) ) ); export default function DomainsStep( props: StepProps ) { const [ stepState, setStepState ] = From 3007385793e16a4cc02899c9661475fe427a3ba8 Mon Sep 17 00:00:00 2001 From: Anthony Grullon Date: Fri, 13 Sep 2024 13:40:07 -0400 Subject: [PATCH 03/11] Fix Plans submit step and tracks events --- .../steps-repository/unified-plans/index.tsx | 36 +++++++++++++------ 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/client/landing/stepper/declarative-flow/internals/steps-repository/unified-plans/index.tsx b/client/landing/stepper/declarative-flow/internals/steps-repository/unified-plans/index.tsx index d4d37af777a7c..cbd7671ecf7fa 100644 --- a/client/landing/stepper/declarative-flow/internals/steps-repository/unified-plans/index.tsx +++ b/client/landing/stepper/declarative-flow/internals/steps-repository/unified-plans/index.tsx @@ -5,6 +5,7 @@ import { useSelect, useDispatch as useWPDispatch } from '@wordpress/data'; import { localize } from 'i18n-calypso'; import { useState } from 'react'; import { useDispatch } from 'react-redux'; +import { AnyAction } from 'redux'; import { useQuery } from 'calypso/landing/stepper/hooks/use-query'; import { useSite } from 'calypso/landing/stepper/hooks/use-site'; import { useSiteSlug } from 'calypso/landing/stepper/hooks/use-site-slug'; @@ -15,6 +16,7 @@ import { useSelector } from 'calypso/state'; import { recordTracksEvent } from 'calypso/state/analytics/actions'; import { getCurrentUserName } from 'calypso/state/current-user/selectors'; import { errorNotice } from 'calypso/state/notices/actions'; +import { submitSignupStep } from 'calypso/state/signup/progress/actions'; import { ProvidedDependencies, StepProps } from '../../types'; import './style.scss'; @@ -73,20 +75,29 @@ export default function PlansStepAdaptor( props: StepProps ) { saveSignupStep={ ( state: ProvidedDependencies ) => { setStepState( ( mostRecentState = { ...stepState, ...state } ) ); } } - submitSignupStep={ ( state: ProvidedDependencies ) => { - /* The plans step removes paid domains when the user picks a free plan - after picking a paid domain */ - if ( state.stepName === 'domains' ) { - if ( state.isPurchasingItem === false ) { + submitSignupStep={ ( + step: Record< string, unknown >, + providedDependencies: Record< string, unknown >, + optionalProps: Record< string, unknown > + ) => { + if ( step.stepName === 'domains' ) { + if ( step.isPurchasingItem === false ) { setDomainCartItem( undefined ); setDomainCartItems( undefined ); - } else if ( state.siteUrl ) { - setSiteUrl( state.siteUrl ); + } else if ( step.siteUrl ) { + setSiteUrl( step.siteUrl ); } } else { - setStepState( ( mostRecentState = { ...stepState, ...state } ) ); + setStepState( ( mostRecentState = { ...stepState, ...step } ) ); + dispatch( + submitSignupStep( + mostRecentState, + providedDependencies, + optionalProps + ) as unknown as AnyAction + ); props.navigation.submit?.( - ( mostRecentState = { ...stepState, ...state, ...mostRecentState } ) + ( mostRecentState = { ...stepState, ...step, ...mostRecentState } ) ); } } } @@ -97,13 +108,16 @@ export default function PlansStepAdaptor( props: StepProps ) { signupDependencies={ signupDependencies } stepName="plans" flowName={ props.flow } - recordTracksEvent={ ( event: unknown ) => dispatch( recordTracksEvent( event ) ) } + recordTracksEvent={ ( name: string, props: unknown ) => { + dispatch( recordTracksEvent( name, props ) ); + } } onPlanIntervalUpdate={ onPlanIntervalUpdate } intervalType={ planInterval } wrapperProps={ { hideBack: isMobile, goBack: props.navigation.goBack, - recordTracksEvent: ( event: unknown ) => dispatch( recordTracksEvent( event ) ), + recordTracksEvent: ( name: string, props: unknown ) => + dispatch( recordTracksEvent( name, props ) ), isFullLayout: true, isExtraWideLayout: false, } } From 4d1f97e8b7bb0fcbf985493a31d6967fd803564b Mon Sep 17 00:00:00 2001 From: Anthony Grullon Date: Fri, 13 Sep 2024 14:51:48 -0400 Subject: [PATCH 04/11] Refactor PlansStepAdaptor to streamline submitSignupStep handling and improve state management --- .../steps-repository/unified-plans/index.tsx | 64 ++++++++++--------- 1 file changed, 33 insertions(+), 31 deletions(-) diff --git a/client/landing/stepper/declarative-flow/internals/steps-repository/unified-plans/index.tsx b/client/landing/stepper/declarative-flow/internals/steps-repository/unified-plans/index.tsx index cbd7671ecf7fa..9600b6ee96742 100644 --- a/client/landing/stepper/declarative-flow/internals/steps-repository/unified-plans/index.tsx +++ b/client/landing/stepper/declarative-flow/internals/steps-repository/unified-plans/index.tsx @@ -58,49 +58,51 @@ export default function PlansStepAdaptor( props: StepProps ) { const [ planInterval, setPlanInterval ] = useState< string | undefined >( undefined ); - const onPlanIntervalUpdate = ( path: string ) => { - const intervalType = getIntervalType( path ); - setPlanInterval( intervalType ); - }; - /** * The plans step has a quirk where it calls `submitSignupStep` then synchronously calls `goToNextStep` after it. * This doesn't give `setStepState` a chance to update and the data is not passed to `submit`. */ let mostRecentState: ProvidedDependencies; + const onPlanIntervalUpdate = ( path: string ) => { + const intervalType = getIntervalType( path ); + setPlanInterval( intervalType ); + }; + + const handleSubmitSignupStep = ( + step: Record< string, unknown >, + providedDependencies: Record< string, unknown >, + optionalProps: Record< string, unknown > + ) => { + if ( step.stepName === 'domains' ) { + if ( step.isPurchasingItem === false ) { + setDomainCartItem( undefined ); + setDomainCartItems( undefined ); + } else if ( step.siteUrl ) { + setSiteUrl( step.siteUrl ); + } + } else { + setStepState( ( mostRecentState = { ...stepState, ...step } ) ); + dispatch( + submitSignupStep( + mostRecentState, + providedDependencies, + optionalProps + ) as unknown as AnyAction + ); + props.navigation.submit?.( + ( mostRecentState = { ...stepState, ...step, ...mostRecentState } ) + ); + } + }; + return ( { setStepState( ( mostRecentState = { ...stepState, ...state } ) ); } } - submitSignupStep={ ( - step: Record< string, unknown >, - providedDependencies: Record< string, unknown >, - optionalProps: Record< string, unknown > - ) => { - if ( step.stepName === 'domains' ) { - if ( step.isPurchasingItem === false ) { - setDomainCartItem( undefined ); - setDomainCartItems( undefined ); - } else if ( step.siteUrl ) { - setSiteUrl( step.siteUrl ); - } - } else { - setStepState( ( mostRecentState = { ...stepState, ...step } ) ); - dispatch( - submitSignupStep( - mostRecentState, - providedDependencies, - optionalProps - ) as unknown as AnyAction - ); - props.navigation.submit?.( - ( mostRecentState = { ...stepState, ...step, ...mostRecentState } ) - ); - } - } } + submitSignupStep={ handleSubmitSignupStep } goToNextStep={ () => props.navigation.submit?.( { ...stepState, ...mostRecentState } ) } step={ stepState } customerType={ customerType } From b6ebe46fd125c82ce13cab8daf482e28056e4d04 Mon Sep 17 00:00:00 2001 From: Anthony Grullon Date: Fri, 13 Sep 2024 16:51:21 -0400 Subject: [PATCH 05/11] Remove unused saveSignupStep action from unified-domains step repository --- .../steps-repository/unified-domains/index.tsx | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/client/landing/stepper/declarative-flow/internals/steps-repository/unified-domains/index.tsx b/client/landing/stepper/declarative-flow/internals/steps-repository/unified-domains/index.tsx index d170e581230b1..2b49decb10c05 100644 --- a/client/landing/stepper/declarative-flow/internals/steps-repository/unified-domains/index.tsx +++ b/client/landing/stepper/declarative-flow/internals/steps-repository/unified-domains/index.tsx @@ -26,11 +26,7 @@ import { import { getAvailableProductsList } from 'calypso/state/products-list/selectors'; import getSitesItems from 'calypso/state/selectors/get-sites-items'; import { fetchUsernameSuggestion } from 'calypso/state/signup/optional-dependencies/actions'; -import { - removeStep, - saveSignupStep, - submitSignupStep, -} from 'calypso/state/signup/progress/actions'; +import { removeStep, submitSignupStep } from 'calypso/state/signup/progress/actions'; import { setDesignType } from 'calypso/state/signup/steps/design-type/actions'; import { getDesignType } from 'calypso/state/signup/steps/design-type/selectors'; import { getSelectedSite } from 'calypso/state/ui/selectors'; @@ -44,10 +40,6 @@ const mapDispatchToProps = ( dispatch: any, props: any ) => { recordAddDomainButtonClickInUseYourDomain, recordUseYourDomainButtonClick, removeStep, - saveSignupStep: ( step: Record< string, unknown > ) => { - props.saveSignupStep?.( step ); - dispatch( saveSignupStep( step ) ); - }, submitSignupStep: ( step: Record< string, unknown >, providedDependencies: Record< string, unknown >, From f97f28fc72b41ce963ffd81c0136704eb856bba0 Mon Sep 17 00:00:00 2001 From: Anthony Grullon Date: Mon, 16 Sep 2024 12:46:43 -0400 Subject: [PATCH 06/11] Replace submitSignupStep with dispatchRecordSubmitStep in unified-domains and unified-plans steps for improved tracking --- .../steps-repository/unified-domains/index.tsx | 4 ++-- .../steps-repository/unified-plans/index.tsx | 6 +++--- client/state/signup/progress/actions.js | 16 ++++++++++++++++ 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/client/landing/stepper/declarative-flow/internals/steps-repository/unified-domains/index.tsx b/client/landing/stepper/declarative-flow/internals/steps-repository/unified-domains/index.tsx index 2b49decb10c05..d652fa0b4f4b8 100644 --- a/client/landing/stepper/declarative-flow/internals/steps-repository/unified-domains/index.tsx +++ b/client/landing/stepper/declarative-flow/internals/steps-repository/unified-domains/index.tsx @@ -26,7 +26,7 @@ import { import { getAvailableProductsList } from 'calypso/state/products-list/selectors'; import getSitesItems from 'calypso/state/selectors/get-sites-items'; import { fetchUsernameSuggestion } from 'calypso/state/signup/optional-dependencies/actions'; -import { removeStep, submitSignupStep } from 'calypso/state/signup/progress/actions'; +import { removeStep, dispatchRecordSubmitStep } from 'calypso/state/signup/progress/actions'; import { setDesignType } from 'calypso/state/signup/steps/design-type/actions'; import { getDesignType } from 'calypso/state/signup/steps/design-type/selectors'; import { getSelectedSite } from 'calypso/state/ui/selectors'; @@ -45,8 +45,8 @@ const mapDispatchToProps = ( dispatch: any, props: any ) => { providedDependencies: Record< string, unknown >, optionalProps: Record< string, unknown > ) => { + dispatch( dispatchRecordSubmitStep( step, providedDependencies, optionalProps ) ); props.submitSignupStep?.( step ); - dispatch( submitSignupStep( step, providedDependencies, optionalProps ) ); }, submitDomainStepSelection, setDesignType, diff --git a/client/landing/stepper/declarative-flow/internals/steps-repository/unified-plans/index.tsx b/client/landing/stepper/declarative-flow/internals/steps-repository/unified-plans/index.tsx index 9600b6ee96742..5e3f37cff6dc3 100644 --- a/client/landing/stepper/declarative-flow/internals/steps-repository/unified-plans/index.tsx +++ b/client/landing/stepper/declarative-flow/internals/steps-repository/unified-plans/index.tsx @@ -16,7 +16,7 @@ import { useSelector } from 'calypso/state'; import { recordTracksEvent } from 'calypso/state/analytics/actions'; import { getCurrentUserName } from 'calypso/state/current-user/selectors'; import { errorNotice } from 'calypso/state/notices/actions'; -import { submitSignupStep } from 'calypso/state/signup/progress/actions'; +import { dispatchRecordSubmitStep } from 'calypso/state/signup/progress/actions'; import { ProvidedDependencies, StepProps } from '../../types'; import './style.scss'; @@ -84,8 +84,8 @@ export default function PlansStepAdaptor( props: StepProps ) { } else { setStepState( ( mostRecentState = { ...stepState, ...step } ) ); dispatch( - submitSignupStep( - mostRecentState, + dispatchRecordSubmitStep( + { ...stepState, ...step }, providedDependencies, optionalProps ) as unknown as AnyAction diff --git a/client/state/signup/progress/actions.js b/client/state/signup/progress/actions.js index 841b4b6ec1974..967eb1d11d186 100644 --- a/client/state/signup/progress/actions.js +++ b/client/state/signup/progress/actions.js @@ -129,6 +129,22 @@ export function saveSignupStep( step ) { }; } +export function dispatchRecordSubmitStep( step, providedDependencies, optionalProps ) { + assertValidDependencies( step.stepName, providedDependencies ); + return ( dispatch, getState ) => { + const lastKnownFlow = getCurrentFlowName( getState() ); + const { intent } = getSignupDependencyStore( getState() ); + + dispatch( + recordSubmitStep( lastKnownFlow, step.stepName, providedDependencies, { + intent, + ...optionalProps, + ...( step.wasSkipped && { was_skipped: step.wasSkipped } ), + } ) + ); + }; +} + export function submitSignupStep( step, providedDependencies, optionalProps ) { assertValidDependencies( step.stepName, providedDependencies ); return ( dispatch, getState ) => { From 6158912e926b1be59895ef231f7e4be5ae238dca Mon Sep 17 00:00:00 2001 From: escapemanuele Date: Wed, 18 Sep 2024 16:30:18 +0200 Subject: [PATCH 07/11] Fix domainForm and suggestion for domain step tracking --- .../analytics/record-step-navigation.ts | 21 ++++++++++ .../unified-domains/index.tsx | 21 ++++------ client/signup/steps/domains/index.jsx | 39 +++++++++---------- 3 files changed, 48 insertions(+), 33 deletions(-) diff --git a/client/landing/stepper/declarative-flow/internals/analytics/record-step-navigation.ts b/client/landing/stepper/declarative-flow/internals/analytics/record-step-navigation.ts index e362b07dd8ad7..f9d7f957f4ab3 100644 --- a/client/landing/stepper/declarative-flow/internals/analytics/record-step-navigation.ts +++ b/client/landing/stepper/declarative-flow/internals/analytics/record-step-navigation.ts @@ -15,6 +15,15 @@ export interface RecordStepNavigationParams { additionalProps?: ProvidedDependencies; } +// These properties are never recorded in the tracks event for security reasons. +const EXCLUDED_DEPENDENCIES = [ + 'bearer_token', + 'token', + 'password', + 'password_confirm', + 'domainCart', +]; + export function recordStepNavigation( { event, intent, @@ -28,6 +37,9 @@ export function recordStepNavigation( { const inputs = reduce( providedDependencies, ( props, propValue, propName: string ) => { + if ( EXCLUDED_DEPENDENCIES.includes( propName ) ) { + return props; + } propName = snakeCase( propName ); // Ensure we don't capture identifiable user data we don't need. @@ -49,6 +61,15 @@ export function recordStepNavigation( { propValue = ( propValue as { product_slug: string } | null )?.product_slug; } + if ( + [ 'cart_items', 'domain_item', 'email_item', 'domain_cart' ].includes( propName ) && + typeof propValue !== 'string' + ) { + propValue = Object.entries( propValue || {} ) + .map( ( pair ) => pair.join( ':' ) ) + .join( ',' ); + } + return { ...props, [ propName ]: propValue, diff --git a/client/landing/stepper/declarative-flow/internals/steps-repository/unified-domains/index.tsx b/client/landing/stepper/declarative-flow/internals/steps-repository/unified-domains/index.tsx index 1b174a7ed1a7d..e433e00dd18a5 100644 --- a/client/landing/stepper/declarative-flow/internals/steps-repository/unified-domains/index.tsx +++ b/client/landing/stepper/declarative-flow/internals/steps-repository/unified-domains/index.tsx @@ -27,13 +27,13 @@ import { import { getAvailableProductsList } from 'calypso/state/products-list/selectors'; import getSitesItems from 'calypso/state/selectors/get-sites-items'; import { fetchUsernameSuggestion } from 'calypso/state/signup/optional-dependencies/actions'; -import { removeStep, dispatchRecordSubmitStep } from 'calypso/state/signup/progress/actions'; +import { removeStep } from 'calypso/state/signup/progress/actions'; import { setDesignType } from 'calypso/state/signup/steps/design-type/actions'; import { getDesignType } from 'calypso/state/signup/steps/design-type/selectors'; import { ProvidedDependencies, StepProps } from '../../types'; import { useIsManagedSiteFlowProps } from './use-is-managed-site-flow'; -const mapDispatchToProps = ( dispatch: any, props: any ) => { +const mapDispatchToProps = () => { return { recordAddDomainButtonClick, recordAddDomainButtonClickInMapDomain, @@ -41,14 +41,6 @@ const mapDispatchToProps = ( dispatch: any, props: any ) => { recordAddDomainButtonClickInUseYourDomain, recordUseYourDomainButtonClick, removeStep, - submitSignupStep: ( - step: Record< string, unknown >, - providedDependencies: Record< string, unknown >, - optionalProps: Record< string, unknown > - ) => { - dispatch( dispatchRecordSubmitStep( step, providedDependencies, optionalProps ) ); - props.submitSignupStep?.( step ); - }, submitDomainStepSelection, setDesignType, recordTracksEvent, @@ -95,8 +87,10 @@ export default function DomainsStep( props: StepProps ) { const mostRecentStateRef = useRef< ProvidedDependencies | undefined >( undefined ); const updateSignupStepState = useCallback( - ( state: ProvidedDependencies ) => { - setStepState( ( mostRecentStateRef.current = { ...stepState, ...state } ) ); + ( state: ProvidedDependencies, providedDependencies: ProvidedDependencies ) => { + setStepState( + ( mostRecentStateRef.current = { ...stepState, ...providedDependencies, ...state } ) + ); }, [ stepState, setStepState ] ); @@ -110,7 +104,8 @@ export default function DomainsStep( props: StepProps ) { saveSignupStep={ updateSignupStepState } submitSignupStep={ updateSignupStepState } goToNextStep={ ( state: ProvidedDependencies ) => { - props.navigation.submit?.( { ...mostRecentStateRef.current, ...state } ); + const { domainForm, suggestion, ...rest } = mostRecentStateRef.current ?? {}; + props.navigation.submit?.( { ...rest, ...state } ); } } step={ stepState } flowName={ props.flow } diff --git a/client/signup/steps/domains/index.jsx b/client/signup/steps/domains/index.jsx index 2f257e7ac7777..8e4579d098dc4 100644 --- a/client/signup/steps/domains/index.jsx +++ b/client/signup/steps/domains/index.jsx @@ -855,27 +855,26 @@ export class RenderDomainsStep extends Component { ? SIGNUP_DOMAIN_ORIGIN.CUSTOM : SIGNUP_DOMAIN_ORIGIN.FREE; - this.props.submitSignupStep( - Object.assign( - { - stepName: this.props.stepName, - domainItem, - isPurchasingItem, - siteUrl, - stepSectionName: this.props.stepSectionName, - domainCart, - }, - this.getThemeArgs() - ), - Object.assign( - { domainItem, domainCart }, - useThemeHeadstartItem, - signupDomainOrigin ? { signupDomainOrigin } : {}, - { siteUrl: suggestion?.domain_name }, - lastDomainSearched ? { lastDomainSearched } : {}, - { domainCart } - ) + const stepDependencies = Object.assign( + { + stepName: this.props.stepName, + domainItem, + isPurchasingItem, + siteUrl, + stepSectionName: this.props.stepSectionName, + domainCart, + }, + this.getThemeArgs() + ); + const providedDependencies = Object.assign( + { domainItem, domainCart }, + useThemeHeadstartItem, + signupDomainOrigin ? { signupDomainOrigin } : {}, + { siteUrl: suggestion?.domain_name }, + lastDomainSearched ? { lastDomainSearched } : {}, + { domainCart } ); + this.props.submitSignupStep( stepDependencies, providedDependencies ); const productToRemove = cart.products.find( ( product ) => product.product_slug === multiDomainDefaultPlan.product_slug From 3bd5d84d2f90c7c8dfadc17289f97bfbce2170ba Mon Sep 17 00:00:00 2001 From: escapemanuele Date: Wed, 18 Sep 2024 16:43:21 +0200 Subject: [PATCH 08/11] Remove triple plan tracking --- .../steps-repository/unified-plans/index.tsx | 47 +++++++------------ client/state/signup/progress/actions.js | 16 ------- 2 files changed, 17 insertions(+), 46 deletions(-) diff --git a/client/landing/stepper/declarative-flow/internals/steps-repository/unified-plans/index.tsx b/client/landing/stepper/declarative-flow/internals/steps-repository/unified-plans/index.tsx index 5e3f37cff6dc3..423bda3d31b18 100644 --- a/client/landing/stepper/declarative-flow/internals/steps-repository/unified-plans/index.tsx +++ b/client/landing/stepper/declarative-flow/internals/steps-repository/unified-plans/index.tsx @@ -5,7 +5,6 @@ import { useSelect, useDispatch as useWPDispatch } from '@wordpress/data'; import { localize } from 'i18n-calypso'; import { useState } from 'react'; import { useDispatch } from 'react-redux'; -import { AnyAction } from 'redux'; import { useQuery } from 'calypso/landing/stepper/hooks/use-query'; import { useSite } from 'calypso/landing/stepper/hooks/use-site'; import { useSiteSlug } from 'calypso/landing/stepper/hooks/use-site-slug'; @@ -16,7 +15,6 @@ import { useSelector } from 'calypso/state'; import { recordTracksEvent } from 'calypso/state/analytics/actions'; import { getCurrentUserName } from 'calypso/state/current-user/selectors'; import { errorNotice } from 'calypso/state/notices/actions'; -import { dispatchRecordSubmitStep } from 'calypso/state/signup/progress/actions'; import { ProvidedDependencies, StepProps } from '../../types'; import './style.scss'; @@ -69,40 +67,29 @@ export default function PlansStepAdaptor( props: StepProps ) { setPlanInterval( intervalType ); }; - const handleSubmitSignupStep = ( - step: Record< string, unknown >, - providedDependencies: Record< string, unknown >, - optionalProps: Record< string, unknown > - ) => { - if ( step.stepName === 'domains' ) { - if ( step.isPurchasingItem === false ) { - setDomainCartItem( undefined ); - setDomainCartItems( undefined ); - } else if ( step.siteUrl ) { - setSiteUrl( step.siteUrl ); - } - } else { - setStepState( ( mostRecentState = { ...stepState, ...step } ) ); - dispatch( - dispatchRecordSubmitStep( - { ...stepState, ...step }, - providedDependencies, - optionalProps - ) as unknown as AnyAction - ); - props.navigation.submit?.( - ( mostRecentState = { ...stepState, ...step, ...mostRecentState } ) - ); - } - }; - return ( { setStepState( ( mostRecentState = { ...stepState, ...state } ) ); } } - submitSignupStep={ handleSubmitSignupStep } + submitSignupStep={ ( state: ProvidedDependencies ) => { + /* The plans step removes paid domains when the user picks a free plan + after picking a paid domain */ + if ( state.stepName === 'domains' ) { + if ( state.isPurchasingItem === false ) { + setDomainCartItem( undefined ); + setDomainCartItems( undefined ); + } else if ( state.siteUrl ) { + setSiteUrl( state.siteUrl ); + } + } else { + setStepState( ( mostRecentState = { ...stepState, ...state } ) ); + props.navigation.submit?.( + ( mostRecentState = { ...stepState, ...state, ...mostRecentState } ) + ); + } + } } goToNextStep={ () => props.navigation.submit?.( { ...stepState, ...mostRecentState } ) } step={ stepState } customerType={ customerType } diff --git a/client/state/signup/progress/actions.js b/client/state/signup/progress/actions.js index 967eb1d11d186..841b4b6ec1974 100644 --- a/client/state/signup/progress/actions.js +++ b/client/state/signup/progress/actions.js @@ -129,22 +129,6 @@ export function saveSignupStep( step ) { }; } -export function dispatchRecordSubmitStep( step, providedDependencies, optionalProps ) { - assertValidDependencies( step.stepName, providedDependencies ); - return ( dispatch, getState ) => { - const lastKnownFlow = getCurrentFlowName( getState() ); - const { intent } = getSignupDependencyStore( getState() ); - - dispatch( - recordSubmitStep( lastKnownFlow, step.stepName, providedDependencies, { - intent, - ...optionalProps, - ...( step.wasSkipped && { was_skipped: step.wasSkipped } ), - } ) - ); - }; -} - export function submitSignupStep( step, providedDependencies, optionalProps ) { assertValidDependencies( step.stepName, providedDependencies ); return ( dispatch, getState ) => { From 668192bf5e29e33965198186439ffa8e4f969a0f Mon Sep 17 00:00:00 2001 From: escapemanuele Date: Wed, 18 Sep 2024 19:51:26 +0200 Subject: [PATCH 09/11] Remove double event fire plans --- .../internals/steps-repository/unified-plans/index.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/client/landing/stepper/declarative-flow/internals/steps-repository/unified-plans/index.tsx b/client/landing/stepper/declarative-flow/internals/steps-repository/unified-plans/index.tsx index 423bda3d31b18..27c239e6849a8 100644 --- a/client/landing/stepper/declarative-flow/internals/steps-repository/unified-plans/index.tsx +++ b/client/landing/stepper/declarative-flow/internals/steps-repository/unified-plans/index.tsx @@ -85,12 +85,11 @@ export default function PlansStepAdaptor( props: StepProps ) { } } else { setStepState( ( mostRecentState = { ...stepState, ...state } ) ); - props.navigation.submit?.( - ( mostRecentState = { ...stepState, ...state, ...mostRecentState } ) - ); } } } - goToNextStep={ () => props.navigation.submit?.( { ...stepState, ...mostRecentState } ) } + goToNextStep={ () => { + props.navigation.submit?.( { ...stepState, ...mostRecentState } ); + } } step={ stepState } customerType={ customerType } errorNotice={ ( message: string ) => dispatch( errorNotice( message ) ) } From 06d7991e7d23befc8a5a785f4abb03a77ab3e72c Mon Sep 17 00:00:00 2001 From: escapemanuele Date: Thu, 19 Sep 2024 11:59:15 +0200 Subject: [PATCH 10/11] fix test --- .../internals/components/step-route/test/index.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/client/landing/stepper/declarative-flow/internals/components/step-route/test/index.tsx b/client/landing/stepper/declarative-flow/internals/components/step-route/test/index.tsx index 7c87be2d84c20..7861be0e0f05e 100644 --- a/client/landing/stepper/declarative-flow/internals/components/step-route/test/index.tsx +++ b/client/landing/stepper/declarative-flow/internals/components/step-route/test/index.tsx @@ -153,7 +153,9 @@ describe( 'StepRoute', () => { it( 'records a page view when the step is rendered', async () => { render( { step: regularStep } ); - expect( recordPageView ).toHaveBeenCalledWith( '/', 'Setup > some-flow > some-step-slug' ); + expect( recordPageView ).toHaveBeenCalledWith( '/', 'Setup > some-flow > some-step-slug', { + flow: 'some-flow', + } ); } ); it( 'records recordStepStart when the step is rendered', async () => { From 031e92573a3bc5b6083613b1df81079f507ad93d Mon Sep 17 00:00:00 2001 From: escapemanuele Date: Thu, 19 Sep 2024 12:30:02 +0200 Subject: [PATCH 11/11] Remove mapDispatchToProps --- .../unified-domains/index.tsx | 69 +++++++++---------- 1 file changed, 34 insertions(+), 35 deletions(-) diff --git a/client/landing/stepper/declarative-flow/internals/steps-repository/unified-domains/index.tsx b/client/landing/stepper/declarative-flow/internals/steps-repository/unified-domains/index.tsx index e433e00dd18a5..74dbb955e9f76 100644 --- a/client/landing/stepper/declarative-flow/internals/steps-repository/unified-domains/index.tsx +++ b/client/landing/stepper/declarative-flow/internals/steps-repository/unified-domains/index.tsx @@ -33,8 +33,38 @@ import { getDesignType } from 'calypso/state/signup/steps/design-type/selectors' import { ProvidedDependencies, StepProps } from '../../types'; import { useIsManagedSiteFlowProps } from './use-is-managed-site-flow'; -const mapDispatchToProps = () => { - return { +const RenderDomainsStepConnect = connect( + ( state, { flow }: StepProps ) => { + const productsList = getAvailableProductsList( state ); + const productsLoaded = ! isEmpty( productsList ); + const multiDomainDefaultPlan = planItem( PLAN_PERSONAL ); + const userLoggedIn = isUserLoggedIn( state as object ); + const currentUserSiteCount = getCurrentUserSiteCount( state as object ); + const stepSectionName = window.location.pathname.includes( 'use-your-domain' ) + ? 'use-your-domain' + : undefined; + + return { + designType: getDesignType( state ), + currentUser: getCurrentUser( state as object ), + productsList, + productsLoaded, + isDomainOnly: false, + sites: getSitesItems( state ), + userSiteCount: currentUserSiteCount, + previousStepName: 'user', + isPlanSelectionAvailableLaterInFlow: true, + userLoggedIn, + multiDomainDefaultPlan, + domainsWithPlansOnly: currentUserHasFlag( state as object, DOMAINS_WITH_PLANS_ONLY ), + flowName: flow, + path: window.location.pathname, + positionInFlow: 1, + isReskinned: true, + stepSectionName, + }; + }, + { recordAddDomainButtonClick, recordAddDomainButtonClickInMapDomain, recordAddDomainButtonClickInTransferDomain, @@ -45,39 +75,8 @@ const mapDispatchToProps = () => { setDesignType, recordTracksEvent, fetchUsernameSuggestion, - }; -}; - -const RenderDomainsStepConnect = connect( ( state, { flow }: StepProps ) => { - const productsList = getAvailableProductsList( state ); - const productsLoaded = ! isEmpty( productsList ); - const multiDomainDefaultPlan = planItem( PLAN_PERSONAL ); - const userLoggedIn = isUserLoggedIn( state as object ); - const currentUserSiteCount = getCurrentUserSiteCount( state as object ); - const stepSectionName = window.location.pathname.includes( 'use-your-domain' ) - ? 'use-your-domain' - : undefined; - - return { - designType: getDesignType( state ), - currentUser: getCurrentUser( state as object ), - productsList, - productsLoaded, - isDomainOnly: false, - sites: getSitesItems( state ), - userSiteCount: currentUserSiteCount, - previousStepName: 'user', - isPlanSelectionAvailableLaterInFlow: true, - userLoggedIn, - multiDomainDefaultPlan, - domainsWithPlansOnly: currentUserHasFlag( state as object, DOMAINS_WITH_PLANS_ONLY ), - flowName: flow, - path: window.location.pathname, - positionInFlow: 1, - isReskinned: true, - stepSectionName, - }; -}, mapDispatchToProps )( withCartKey( withShoppingCart( localize( RenderDomainsStep ) ) ) ); + } +)( withCartKey( withShoppingCart( localize( RenderDomainsStep ) ) ) ); export default function DomainsStep( props: StepProps ) { const [ stepState, setStepState ] =