Skip to content

Commit

Permalink
Adding migrationHandler step to the importer-flow to handle redirects (
Browse files Browse the repository at this point in the history
…#73214)

* Modify font size

* Moving API into the helper function file

* Modify addTempSiteToSourceOption function to use id instead of site slug

* Refactor data layer to using React Query hooks

* Remove unused functions
  • Loading branch information
ouikhuan authored Feb 13, 2023
1 parent 3130f4d commit 7db4a17
Show file tree
Hide file tree
Showing 10 changed files with 218 additions and 27 deletions.
37 changes: 37 additions & 0 deletions client/data/site-migration/use-add-temp-site-mutation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { useCallback } from 'react';
import { useMutation, useQueryClient } from 'react-query';
import wp from 'calypso/lib/wp';

interface TempSiteToSourceOption {
targetBlogId: number;
sourceBlogId: number;
}

function useAddTempSiteToSourceOptionMutation() {
const queryClient = useQueryClient();
const mutation = useMutation(
( { targetBlogId, sourceBlogId }: TempSiteToSourceOption ) =>
wp.req.post(
`/migrations/from-source/${ sourceBlogId }`,
{
apiNamespace: 'wpcom/v2',
},
{ target_blog_id: targetBlogId }
),
{
onSuccess( data, { sourceBlogId } ) {
queryClient.setQueryData( [ 'temp-target-site', sourceBlogId ], data );
},
}
);

const { mutate } = mutation;
const addTempSiteToSourceOption = useCallback(
( targetBlogId: number, sourceBlogId: number ) => mutate( { targetBlogId, sourceBlogId } ),
[ mutate ]
);

return { addTempSiteToSourceOption, ...mutation };
}

export default useAddTempSiteToSourceOptionMutation;
21 changes: 21 additions & 0 deletions client/data/site-migration/use-source-migration-status-query.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { SourceSiteMigrationDetails } from '@automattic/data-stores/src/site';
import { useQuery } from 'react-query';
import wp from 'calypso/lib/wp';
import type { SiteId } from 'calypso/types';

export const useSourceMigrationStatusQuery = ( sourceId: SiteId | undefined ) => {
return useQuery(
[ 'source-migration-status', sourceId ],
(): Promise< SourceSiteMigrationDetails > =>
wp.req.get( {
path: '/migrations/from-source/' + encodeURIComponent( sourceId as number ),
apiNamespace: 'wpcom/v2',
} ),
{
meta: {
persist: false,
},
enabled: !! sourceId,
}
);
};
19 changes: 19 additions & 0 deletions client/data/sites/use-site-query.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { SiteDetails } from '@automattic/data-stores/src/site';
import { useQuery } from 'react-query';
import wp from 'calypso/lib/wp';

export const useSiteQuery = ( sourceSiteSlug: string, enabled = true ) => {
return useQuery(
[ 'site-details', sourceSiteSlug ],
(): Promise< SiteDetails > =>
wp.req.get( {
path: '/sites/' + encodeURIComponent( sourceSiteSlug as string ),
} ),
{
meta: {
persist: false,
},
enabled,
}
);
};
4 changes: 3 additions & 1 deletion client/jetpack-connect/authorize.js
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,8 @@ export class JetpackAuthorize extends Component {
return this.redirect();
} else if ( nextProps.isAlreadyOnSitesList && alreadyAuthorized ) {
return this.redirect();
} else if ( this.isFromJetpackMigration() && nextProps.isAlreadyOnSitesList ) {
return this.redirect();
}
if (
authorizeError &&
Expand Down Expand Up @@ -292,7 +294,7 @@ export class JetpackAuthorize extends Component {
debug( `Redirecting directly to cart with ${ PRODUCT_JETPACK_BACKUP_T1_YEARLY } in cart.` );
navigate( `/checkout/${ urlToSlug( homeUrl ) }/${ PRODUCT_JETPACK_BACKUP_T1_YEARLY }` );
} else if ( this.isFromJetpackMigration() ) {
navigate( `/setup/import-focused/siteCreationStep?from=${ urlToSlug( homeUrl ) }` );
navigate( `/setup/import-focused/migrationHandler?from=${ urlToSlug( homeUrl ) }` );
} else {
const redirectionTarget = this.getRedirectionTarget();
debug( `Redirecting to: ${ redirectionTarget }` );
Expand Down
27 changes: 27 additions & 0 deletions client/landing/stepper/declarative-flow/import-flow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import ImporterMedium from './internals/steps-repository/importer-medium';
import ImporterSquarespace from './internals/steps-repository/importer-squarespace';
import ImporterWix from './internals/steps-repository/importer-wix';
import ImporterWordpress from './internals/steps-repository/importer-wordpress';
import MigrationHandler from './internals/steps-repository/migration-handler';
import PatternAssembler from './internals/steps-repository/pattern-assembler';
import ProcessingStep from './internals/steps-repository/processing-step';
import SiteCreationStep from './internals/steps-repository/site-creation-step';
Expand All @@ -43,6 +44,7 @@ const importFlow: Flow = {
{ slug: 'patternAssembler', component: PatternAssembler },
{ slug: 'processing', component: ProcessingStep },
{ slug: 'siteCreationStep', component: SiteCreationStep },
{ slug: 'migrationHandler', component: MigrationHandler },
];
},

Expand Down Expand Up @@ -72,6 +74,28 @@ const importFlow: Flow = {
return navigate( 'processing' );
};

const handleMigrationRedirects = ( providedDependencies: ProvidedDependencies = {} ) => {
const from = urlQueryParams.get( 'from' );
// If there's any errors, we redirct them to the siteCreationStep for a clean start
if ( providedDependencies?.hasError ) {
return navigate( 'siteCreationStep' );
}
if ( providedDependencies?.status === 'inactive' ) {
// This means they haven't kick off the migration before, so we send them to create a new site
if ( ! providedDependencies?.targetBlogId ) {
return navigate( 'siteCreationStep' );
}
// For some reason, the admin role is mismatch, we want to create a new site for them as well
if ( providedDependencies?.isAdminOnTarget === false ) {
return navigate( 'siteCreationStep' );
}
}
// For those who hasn't paid or in the middle of the migration process, we sent them to the importerWordPress step
return navigate(
`importerWordpress?siteSlug=${ providedDependencies?.targetBlogSlug }&from=${ from }&option=everything`
);
};

const submit = ( providedDependencies: ProvidedDependencies = {} ) => {
switch ( _currentStep ) {
case 'importReady': {
Expand Down Expand Up @@ -131,6 +155,9 @@ const importFlow: Flow = {

return exitFlow( `/home/${ siteSlugParam }` );
}
case 'migrationHandler': {
return handleMigrationRedirects( providedDependencies );
}
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
getWpOrgImporterUrl,
} from 'calypso/blocks/import/util';
import { WPImportOption } from 'calypso/blocks/importer/wordpress/types';
import wpcom from 'calypso/lib/wp';
import { BASE_ROUTE } from './config';

export function getFinalImporterUrl(
Expand Down Expand Up @@ -63,18 +62,3 @@ export function generateStepPath( stepName: string, stepSectionName?: string ) {

return camelCase( path ) as string;
}

export async function addTempSiteToSourceOption( targetBlogId: number, sourceSiteSlug: string ) {
return wpcom.req
.post( {
path: `/migrations/from-source/${ sourceSiteSlug }`,
apiNamespace: 'wpcom/v2',
body: {
target_blog_id: targetBlogId,
},
} )
.catch( ( error: Error ) => {
// eslint-disable-next-line no-console
console.error( 'Unable to store option in source site', error );
} );
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { StepContainer, Title } from '@automattic/onboarding';
import { useDispatch, useSelect } from '@wordpress/data';
import { useI18n } from '@wordpress/react-i18n';
import { useEffect } from 'react';
import DocumentHead from 'calypso/components/data/document-head';
import { LoadingEllipsis } from 'calypso/components/loading-ellipsis';
import { useSourceMigrationStatusQuery } from 'calypso/data/site-migration/use-source-migration-status-query';
import { useSiteQuery } from 'calypso/data/sites/use-site-query';
import { ONBOARD_STORE } from 'calypso/landing/stepper/stores';
import { recordTracksEvent } from 'calypso/lib/analytics/tracks';
import type { Step } from '../../types';
import './styles.scss';

const MigrationHandler: Step = function MigrationHandler( { navigation } ) {
const { submit } = navigation;
const { __ } = useI18n();
const stepProgress = useSelect( ( select ) => select( ONBOARD_STORE ).getStepProgress() );
const { setIsMigrateFromWp } = useDispatch( ONBOARD_STORE );
const search = window.location.search;
const sourceSiteSlug = new URLSearchParams( search ).get( 'from' ) || '';
const { data: sourceSite, isError: isErrorSourcSite } = useSiteQuery( sourceSiteSlug );
const { data: sourceSiteMigrationStatus, isError: isErrorSourceSiteMigrationStatus } =
useSourceMigrationStatusQuery( sourceSite?.ID );
const errorDependency = {
isFromMigrationPlugin: true,
hasError: true,
};

useEffect( () => {
setIsMigrateFromWp( true );
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [] );

useEffect( () => {
if ( submit ) {
if ( isErrorSourcSite || isErrorSourceSiteMigrationStatus ) {
return submit( errorDependency );
}
if ( sourceSiteMigrationStatus ) {
submit( {
isFromMigrationPlugin: true,
status: sourceSiteMigrationStatus?.status,
targetBlogId: sourceSiteMigrationStatus?.target_blog_id,
isAdminOnTarget: sourceSiteMigrationStatus?.is_target_blog_admin,
isTargetBlogUpgraded: sourceSiteMigrationStatus?.is_target_blog_upgraded,
targetBlogSlug: sourceSiteMigrationStatus?.target_blog_slug,
} );
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ isErrorSourcSite, isErrorSourceSiteMigrationStatus, sourceSiteMigrationStatus ] );

const getCurrentMessage = () => {
return __( 'Scanning your site' );
};

return (
<>
<DocumentHead title={ getCurrentMessage() } />
<StepContainer
shouldHideNavButtons={ true }
hideFormattedHeader={ true }
stepName="migration-handler"
isHorizontalLayout={ true }
recordTracksEvent={ recordTracksEvent }
stepContent={
<>
<Title>{ getCurrentMessage() }</Title>
<LoadingEllipsis />
</>
}
stepProgress={ stepProgress }
showFooterWooCommercePowered={ false }
/>
</>
);
};

export default MigrationHandler;
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
@import "../style";

.migration-handler {
max-width: 540px;
text-align: center;
margin: 16vh auto 0;

.step-container__content {
.onboarding-title {
font-size: 1.625rem; /* stylelint-disable-line scales/font-sizes */
/* stylelint-disable-next-line declaration-property-unit-allowed-list */
line-height: 1em;
margin-bottom: 1.5rem;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import { useSelector } from 'react-redux';
import DocumentHead from 'calypso/components/data/document-head';
import { LoadingBar } from 'calypso/components/loading-bar';
import { LoadingEllipsis } from 'calypso/components/loading-ellipsis';
import useAddTempSiteToSourceOptionMutation from 'calypso/data/site-migration/use-add-temp-site-mutation';
import { useSiteQuery } from 'calypso/data/sites/use-site-query';
import { ONBOARD_STORE } from 'calypso/landing/stepper/stores';
import { recordTracksEvent } from 'calypso/lib/analytics/tracks';
import {
Expand All @@ -28,7 +30,6 @@ import {
getSignupCompleteSlug,
} from 'calypso/signup/storageUtils';
import { getCurrentUserName } from 'calypso/state/current-user/selectors';
import { addTempSiteToSourceOption } from '../import/helper';
import type { Step } from '../../types';

import './styles.scss';
Expand All @@ -54,7 +55,7 @@ const SiteCreationStep: Step = function SiteCreationStep( { navigation, flow, da

const username = useSelector( ( state ) => getCurrentUserName( state ) );

const { setPendingAction, setIsMigrateFromWp } = useDispatch( ONBOARD_STORE );
const { setPendingAction } = useDispatch( ONBOARD_STORE );

let theme: string;
if ( isMigrationFlow( flow ) || isCopySiteFlow( flow ) ) {
Expand Down Expand Up @@ -92,6 +93,10 @@ const SiteCreationStep: Step = function SiteCreationStep( { navigation, flow, da
wasSignupCheckoutPageUnloaded() && signupDestinationCookieExists && isReEnteringFlow
);
const blogTitle = isFreeFlow( 'free' ) ? getSelectedSiteTitle : '';
const { addTempSiteToSourceOption } = useAddTempSiteToSourceOptionMutation();
const search = window.location.search;
const sourceSiteSlug = new URLSearchParams( search ).get( 'from' ) || '';
const { data: siteData } = useSiteQuery( sourceSiteSlug, isCopySiteFlow( flow ) );

async function createSite() {
if ( isManageSiteFlow ) {
Expand Down Expand Up @@ -124,10 +129,8 @@ const SiteCreationStep: Step = function SiteCreationStep( { navigation, flow, da
}

if ( isMigrationFlow( flow ) ) {
const search = window.location.search;
const sourceSiteSlug = new URLSearchParams( search ).get( 'from' );
// Store temporary target blog id to source site option
await addTempSiteToSourceOption( site?.siteId as number, sourceSiteSlug as string );
addTempSiteToSourceOption( site?.siteId as number, siteData?.ID as number );
}

return {
Expand All @@ -138,11 +141,6 @@ const SiteCreationStep: Step = function SiteCreationStep( { navigation, flow, da

useEffect( () => {
setProgress( 0.1 );

if ( isMigrationFlow( flow ) ) {
setIsMigrateFromWp( true );
}

if ( submit ) {
setPendingAction( createSite );
submit();
Expand Down
8 changes: 8 additions & 0 deletions packages/data-stores/src/site/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -481,3 +481,11 @@ export interface ActiveTheme {
'wp:user-global-styles': { href: string }[];
};
}

export interface SourceSiteMigrationDetails {
status: string;
target_blog_id?: number;
is_target_blog_admin?: boolean;
is_target_blog_upgraded?: boolean;
target_blog_slug?: string;
}

0 comments on commit 7db4a17

Please sign in to comment.