Skip to content

Commit

Permalink
add: fetch extensions from API for core profiler
Browse files Browse the repository at this point in the history
- prefetch it once in the machine init so that it's instant when used later
- fetch it again in preExtensions state and store it to context
  • Loading branch information
rjchow committed May 12, 2023
1 parent 29520cd commit 0adba7f
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 37 deletions.
78 changes: 41 additions & 37 deletions plugins/woocommerce-admin/client/core-profiler/index.tsx
@@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { createMachine, assign, DoneInvokeEvent, actions } from 'xstate';
import { createMachine, assign, DoneInvokeEvent, actions, spawn } from 'xstate';
import { useMachine } from '@xstate/react';
import { useEffect, useMemo } from '@wordpress/element';
import { resolveSelect, dispatch } from '@wordpress/data';
Expand All @@ -11,6 +11,8 @@ import {
OPTIONS_STORE_NAME,
COUNTRIES_STORE_NAME,
Country,
ONBOARDING_STORE_NAME,
Extension,
} from '@woocommerce/data';
import { recordEvent } from '@woocommerce/tracks';
import { getSetting } from '@woocommerce/settings';
Expand All @@ -25,6 +27,7 @@ import { BusinessInfo } from './pages/BusinessInfo';
import { BusinessLocation } from './pages/BusinessLocation';
import { getCountryStateOptions } from './services/country';
import { Loader } from './pages/Loader';
import { Extensions } from './pages/Extensions';

import './style.scss';

Expand Down Expand Up @@ -79,7 +82,7 @@ export type CoreProfilerStateMachineContext = {
geolocatedLocation: {
location: string;
};
extensionsAvailable: ExtensionList[ 'plugins' ] | [];
extensionsAvailable: ExtensionList[ 'plugins' ] | [ ];
extensionsSelected: string[]; // extension slugs
businessInfo: { foo?: { bar: 'qux' }; location: string };
countries: { [ key: string ]: string };
Expand All @@ -91,34 +94,6 @@ export type CoreProfilerStateMachineContext = {
};
};

const Extensions = ( {
context,
sendEvent,
}: {
context: CoreProfilerStateMachineContext;
sendEvent: ( payload: ExtensionsEvent ) => void;
} ) => {
return (
// TOOD: we need to fetch the extensions list from the API as part of initializing the profiler
<>
<div>Extensions</div>
<div>{ context.extensionsAvailable }</div>
<button
onClick={ () =>
sendEvent( {
type: 'EXTENSIONS_COMPLETED',
payload: {
extensionsSelected: [ 'woocommerce-payments' ],
},
} )
}
>
Next
</button>
</>
);
};

const getAllowTrackingOption = async () =>
resolveSelect( OPTIONS_STORE_NAME ).getOption(
'woocommerce_allow_tracking'
Expand Down Expand Up @@ -217,9 +192,37 @@ const assignOptInDataSharing = assign( {
event.payload.optInDataSharing,
} );

/**
* Prefetch it so that @wp/data caches it and there won't be a loading delay when its used
*/
const preFetchGetExtensions = assign( {
extensionsRef: () =>
spawn(
resolveSelect( ONBOARDING_STORE_NAME ).getFreeExtensions(),
'core-profiler-prefetch-extensions'
),
} );

const getExtensions = async () => {
const extensionsBundles = await resolveSelect(
ONBOARDING_STORE_NAME
).getFreeExtensions();
return (
extensionsBundles.find( ( bundle ) => bundle.key === 'obw/grow' )
?.plugins || []
);
};

const handleExtensions = assign( {
extensionsAvailable: ( _context, event: DoneInvokeEvent< Extension[] > ) =>
event.data,
} );

const coreProfilerMachineActions = {
updateTrackingOption,
preFetchGetExtensions,
handleTrackingOption,
handleExtensions,
recordTracksIntroCompleted,
recordTracksIntroSkipped,
recordTracksIntroViewed,
Expand All @@ -233,6 +236,7 @@ const coreProfilerMachineActions = {
const coreProfilerMachineServices = {
getAllowTrackingOption,
getCountries,
getExtensions,
};
export const coreProfilerStateMachineDefinition = createMachine( {
id: 'coreProfiler',
Expand All @@ -257,6 +261,7 @@ export const coreProfilerStateMachineDefinition = createMachine( {
target: 'introOptIn',
},
},
entry: [ 'preFetchGetExtensions' ],
invoke: [
{
src: 'getAllowTrackingOption',
Expand Down Expand Up @@ -462,13 +467,12 @@ export const coreProfilerStateMachineDefinition = createMachine( {
},
},
preExtensions: {
always: [
// immediately transition to extensions without any events as long as extensions fetching parallel has completed
{
target: 'extensions',
cond: () => true, // TODO: use a custom function to check on the parallel state using meta when we implement that. https://xstate.js.org/docs/guides/guards.html#guards-condition-functions
},
],
invoke: {
src: 'getExtensions',
onDone: [
{ target: 'extensions', actions: 'handleExtensions' },
],
},
// add exit action to filter the extensions using a custom function here and assign it to context.extensionsAvailable
exit: assign( {
extensionsAvailable: ( context ) => {
Expand Down
@@ -0,0 +1,31 @@
/**
* Internal dependencies
*/
import { CoreProfilerStateMachineContext, ExtensionsEvent } from '../index';

export const Extensions = ( {
context,
sendEvent,
}: {
context: CoreProfilerStateMachineContext;
sendEvent: ( payload: ExtensionsEvent ) => void;
} ) => {
return (
<>
<div>Extensions</div>
<div>{ JSON.stringify( context.extensionsAvailable ) }</div>
<button
onClick={ () =>
sendEvent( {
type: 'EXTENSIONS_COMPLETED',
payload: {
extensionsSelected: [ 'woocommerce-payments' ],
},
} )
}
>
Next
</button>
</>
);
};

0 comments on commit 0adba7f

Please sign in to comment.