woocommerce/plugins/woocommerce-admin/client/core-profiler/index.tsx

1156 lines
27 KiB
TypeScript
Raw Normal View History

/* eslint-disable xstate/no-inline-implementation */
/**
* External dependencies
*/
import { createMachine, assign, DoneInvokeEvent, actions, spawn } from 'xstate';
import { useMachine } from '@xstate/react';
Add core profiler "Welcome to Woo!" page (#37952) * Add core profiler - welcome to woo page * Add changelog * Update checkbox styles * Update copies * Add test * Add enable prop to window.wcTracks type * Add tracks * Add explat changelog * Fix import * Update default tracking value * Update copies * Fix test * using invoked promise instead of useState - take advantage of xstate's built ins for side effects instead of useEffect/hooks - discovered that error result wasn't really handled in original useEffect - use text labels instead of inline functions so that we can decouple the implementation from the machine model - todo: can move the invoked function out elsewhere and also tests if needed (not necessary here because it's a simple call) * use actions.choose instead of branching inside action - https://stately.ai/docs/xstate/transitions-and-choices/guarded-actions#the-choose-action - makes it so that the machine model is serializeable - todo: in the distant future i wonder if it might be tidier to have tracks be its own actor that just receives the same events that this machine does, that way it's just standalone instead of mixing up tracks with the implementation * use dispatch instead of useDispatch - decouples the implementation of the handler from the react component - makes the handler testable on its own if needed - makes the state machine testable without relying on external dependencies * decoupled remaining function calls * Fix lint error * Fix style lint * address xstate console warnings - .withConfig() is a function call that returns a new object every invocation so we need to wrap it in useMemo to keep it stable * Add optInDataSharing is false test * Fix lint --------- Co-authored-by: rjchow <me@rjchow.com>
2023-05-03 07:54:28 +00:00
import { useEffect, useMemo } from '@wordpress/element';
import { resolveSelect, dispatch } from '@wordpress/data';
Add Business Location page to the core profiler (#38019) * Add core profiler - welcome to woo page * Update checkbox styles * Add tracks * Update default tracking value * Update copies * using invoked promise instead of useState - take advantage of xstate's built ins for side effects instead of useEffect/hooks - discovered that error result wasn't really handled in original useEffect - use text labels instead of inline functions so that we can decouple the implementation from the machine model - todo: can move the invoked function out elsewhere and also tests if needed (not necessary here because it's a simple call) * add: core profiler scaffolding using xstate * Add navigation and progress-bar components * fix css lint error * Update plugins/woocommerce-admin/client/core-profiler/components/navigation/woologo.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/components/progress-bar/progress-bar.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/components/navigation/navigation.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Remove var from __ function * Use woocommerce prefix for classnames * Fix css lint error * Fix broken tests * Add business location page * Remove unwanted changes from rebase * Remove unwanted changes from rebase * Redirect to Woo Home on exit * Add tracks * Fix js lint error * Add loader page * Support meta value from nested states * Use navigateTo * Add tests for getCountryStateOptions * Use Country type from navigation package * Rename useStages to getLoaderStageMeta * Add changelog * Move progress from 20 to 80 * Fix xstate warning * Fix broken pnpm lock * Fix eslint errors * Update plugins/woocommerce-admin/client/core-profiler/services/country.ts Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com> * Update plugins/woocommerce-admin/client/core-profiler/index.tsx Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com> * Save country to option * Fix jslint error * Update plugins/woocommerce-admin/client/core-profiler/services/country.ts Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/style.scss Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Fix eslint error * Use decodeEntities directly * Update comment for artificial 3 seconds wait * Disable Go to my store button when country is empty * Style for mobile devices * Style updates for the country dropdown * Fix js lint error * Update country dropdown border color * Style the loader * Fix css lint --------- Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> Co-authored-by: rjchow <me@rjchow.com> Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com>
2023-05-14 20:56:47 +00:00
import {
ExtensionList,
OPTIONS_STORE_NAME,
COUNTRIES_STORE_NAME,
Country,
ONBOARDING_STORE_NAME,
Extension,
GeolocationResponse,
Add Business Location page to the core profiler (#38019) * Add core profiler - welcome to woo page * Update checkbox styles * Add tracks * Update default tracking value * Update copies * using invoked promise instead of useState - take advantage of xstate's built ins for side effects instead of useEffect/hooks - discovered that error result wasn't really handled in original useEffect - use text labels instead of inline functions so that we can decouple the implementation from the machine model - todo: can move the invoked function out elsewhere and also tests if needed (not necessary here because it's a simple call) * add: core profiler scaffolding using xstate * Add navigation and progress-bar components * fix css lint error * Update plugins/woocommerce-admin/client/core-profiler/components/navigation/woologo.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/components/progress-bar/progress-bar.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/components/navigation/navigation.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Remove var from __ function * Use woocommerce prefix for classnames * Fix css lint error * Fix broken tests * Add business location page * Remove unwanted changes from rebase * Remove unwanted changes from rebase * Redirect to Woo Home on exit * Add tracks * Fix js lint error * Add loader page * Support meta value from nested states * Use navigateTo * Add tests for getCountryStateOptions * Use Country type from navigation package * Rename useStages to getLoaderStageMeta * Add changelog * Move progress from 20 to 80 * Fix xstate warning * Fix broken pnpm lock * Fix eslint errors * Update plugins/woocommerce-admin/client/core-profiler/services/country.ts Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com> * Update plugins/woocommerce-admin/client/core-profiler/index.tsx Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com> * Save country to option * Fix jslint error * Update plugins/woocommerce-admin/client/core-profiler/services/country.ts Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/style.scss Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Fix eslint error * Use decodeEntities directly * Update comment for artificial 3 seconds wait * Disable Go to my store button when country is empty * Style for mobile devices * Style updates for the country dropdown * Fix js lint error * Update country dropdown border color * Style the loader * Fix css lint --------- Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> Co-authored-by: rjchow <me@rjchow.com> Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com>
2023-05-14 20:56:47 +00:00
} from '@woocommerce/data';
Add core profiler "Welcome to Woo!" page (#37952) * Add core profiler - welcome to woo page * Add changelog * Update checkbox styles * Update copies * Add test * Add enable prop to window.wcTracks type * Add tracks * Add explat changelog * Fix import * Update default tracking value * Update copies * Fix test * using invoked promise instead of useState - take advantage of xstate's built ins for side effects instead of useEffect/hooks - discovered that error result wasn't really handled in original useEffect - use text labels instead of inline functions so that we can decouple the implementation from the machine model - todo: can move the invoked function out elsewhere and also tests if needed (not necessary here because it's a simple call) * use actions.choose instead of branching inside action - https://stately.ai/docs/xstate/transitions-and-choices/guarded-actions#the-choose-action - makes it so that the machine model is serializeable - todo: in the distant future i wonder if it might be tidier to have tracks be its own actor that just receives the same events that this machine does, that way it's just standalone instead of mixing up tracks with the implementation * use dispatch instead of useDispatch - decouples the implementation of the handler from the react component - makes the handler testable on its own if needed - makes the state machine testable without relying on external dependencies * decoupled remaining function calls * Fix lint error * Fix style lint * address xstate console warnings - .withConfig() is a function call that returns a new object every invocation so we need to wrap it in useMemo to keep it stable * Add optInDataSharing is false test * Fix lint --------- Co-authored-by: rjchow <me@rjchow.com>
2023-05-03 07:54:28 +00:00
import { recordEvent } from '@woocommerce/tracks';
import { initializeExPlat } from '@woocommerce/explat';
import { CountryStateOption } from '@woocommerce/onboarding';
/**
* Internal dependencies
*/
import { IntroOptIn } from './pages/IntroOptIn';
import {
UserProfile,
BusinessChoice,
SellingOnlineAnswer,
SellingPlatform,
} from './pages/UserProfile';
import {
BusinessInfo,
IndustryChoice,
POSSIBLY_DEFAULT_STORE_NAMES,
} from './pages/BusinessInfo';
import { BusinessLocation } from './pages/BusinessLocation';
Add Business Location page to the core profiler (#38019) * Add core profiler - welcome to woo page * Update checkbox styles * Add tracks * Update default tracking value * Update copies * using invoked promise instead of useState - take advantage of xstate's built ins for side effects instead of useEffect/hooks - discovered that error result wasn't really handled in original useEffect - use text labels instead of inline functions so that we can decouple the implementation from the machine model - todo: can move the invoked function out elsewhere and also tests if needed (not necessary here because it's a simple call) * add: core profiler scaffolding using xstate * Add navigation and progress-bar components * fix css lint error * Update plugins/woocommerce-admin/client/core-profiler/components/navigation/woologo.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/components/progress-bar/progress-bar.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/components/navigation/navigation.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Remove var from __ function * Use woocommerce prefix for classnames * Fix css lint error * Fix broken tests * Add business location page * Remove unwanted changes from rebase * Remove unwanted changes from rebase * Redirect to Woo Home on exit * Add tracks * Fix js lint error * Add loader page * Support meta value from nested states * Use navigateTo * Add tests for getCountryStateOptions * Use Country type from navigation package * Rename useStages to getLoaderStageMeta * Add changelog * Move progress from 20 to 80 * Fix xstate warning * Fix broken pnpm lock * Fix eslint errors * Update plugins/woocommerce-admin/client/core-profiler/services/country.ts Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com> * Update plugins/woocommerce-admin/client/core-profiler/index.tsx Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com> * Save country to option * Fix jslint error * Update plugins/woocommerce-admin/client/core-profiler/services/country.ts Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/style.scss Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Fix eslint error * Use decodeEntities directly * Update comment for artificial 3 seconds wait * Disable Go to my store button when country is empty * Style for mobile devices * Style updates for the country dropdown * Fix js lint error * Update country dropdown border color * Style the loader * Fix css lint --------- Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> Co-authored-by: rjchow <me@rjchow.com> Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com>
2023-05-14 20:56:47 +00:00
import { getCountryStateOptions } from './services/country';
import { Loader } from './pages/Loader';
import { Plugins } from './pages/Plugins';
import { getPluginTrackKey, getTimeFrame } from '~/utils';
Add core profiler "Welcome to Woo!" page (#37952) * Add core profiler - welcome to woo page * Add changelog * Update checkbox styles * Update copies * Add test * Add enable prop to window.wcTracks type * Add tracks * Add explat changelog * Fix import * Update default tracking value * Update copies * Fix test * using invoked promise instead of useState - take advantage of xstate's built ins for side effects instead of useEffect/hooks - discovered that error result wasn't really handled in original useEffect - use text labels instead of inline functions so that we can decouple the implementation from the machine model - todo: can move the invoked function out elsewhere and also tests if needed (not necessary here because it's a simple call) * use actions.choose instead of branching inside action - https://stately.ai/docs/xstate/transitions-and-choices/guarded-actions#the-choose-action - makes it so that the machine model is serializeable - todo: in the distant future i wonder if it might be tidier to have tracks be its own actor that just receives the same events that this machine does, that way it's just standalone instead of mixing up tracks with the implementation * use dispatch instead of useDispatch - decouples the implementation of the handler from the react component - makes the handler testable on its own if needed - makes the state machine testable without relying on external dependencies * decoupled remaining function calls * Fix lint error * Fix style lint * address xstate console warnings - .withConfig() is a function call that returns a new object every invocation so we need to wrap it in useMemo to keep it stable * Add optInDataSharing is false test * Fix lint --------- Co-authored-by: rjchow <me@rjchow.com>
2023-05-03 07:54:28 +00:00
import './style.scss';
import {
InstallationCompletedResult,
InstallAndActivatePlugins,
InstalledPlugin,
PluginInstallError,
} from './services/installAndActivatePlugins';
import { ProfileSpinner } from './components/profile-spinner/profile-spinner';
import recordTracksActions from './actions/tracks';
Add core profiler "Welcome to Woo!" page (#37952) * Add core profiler - welcome to woo page * Add changelog * Update checkbox styles * Update copies * Add test * Add enable prop to window.wcTracks type * Add tracks * Add explat changelog * Fix import * Update default tracking value * Update copies * Fix test * using invoked promise instead of useState - take advantage of xstate's built ins for side effects instead of useEffect/hooks - discovered that error result wasn't really handled in original useEffect - use text labels instead of inline functions so that we can decouple the implementation from the machine model - todo: can move the invoked function out elsewhere and also tests if needed (not necessary here because it's a simple call) * use actions.choose instead of branching inside action - https://stately.ai/docs/xstate/transitions-and-choices/guarded-actions#the-choose-action - makes it so that the machine model is serializeable - todo: in the distant future i wonder if it might be tidier to have tracks be its own actor that just receives the same events that this machine does, that way it's just standalone instead of mixing up tracks with the implementation * use dispatch instead of useDispatch - decouples the implementation of the handler from the react component - makes the handler testable on its own if needed - makes the state machine testable without relying on external dependencies * decoupled remaining function calls * Fix lint error * Fix style lint * address xstate console warnings - .withConfig() is a function call that returns a new object every invocation so we need to wrap it in useMemo to keep it stable * Add optInDataSharing is false test * Fix lint --------- Co-authored-by: rjchow <me@rjchow.com>
2023-05-03 07:54:28 +00:00
export type InitializationCompleteEvent = {
type: 'INITIALIZATION_COMPLETE';
payload: { optInDataSharing: boolean };
};
export type IntroOptInEvent =
| { type: 'INTRO_COMPLETED'; payload: { optInDataSharing: boolean } } // can be true or false depending on whether the user opted in or not
| { type: 'INTRO_SKIPPED'; payload: { optInDataSharing: false } }; // always false for now
export type UserProfileEvent =
| {
type: 'USER_PROFILE_COMPLETED';
payload: {
userProfile: CoreProfilerStateMachineContext[ 'userProfile' ];
}; // TODO: fill in the types for this when developing this page
}
| {
type: 'USER_PROFILE_SKIPPED';
payload: { userProfile: { skipped: true } };
};
export type BusinessInfoEvent = {
type: 'BUSINESS_INFO_COMPLETED';
payload: {
storeName?: string;
industry?: IndustryChoice;
storeLocation: CountryStateOption[ 'key' ];
geolocationOverruled: boolean;
};
};
export type BusinessLocationEvent = {
type: 'BUSINESS_LOCATION_COMPLETED';
payload: {
storeLocation: CountryStateOption[ 'key' ];
};
};
export type PluginsInstallationRequestedEvent = {
type: 'PLUGINS_INSTALLATION_REQUESTED';
payload: {
plugins: CoreProfilerStateMachineContext[ 'pluginsSelected' ];
};
};
// TODO: add types as we develop the pages
export type OnboardingProfile = {
business_choice: BusinessChoice;
industry: Array< IndustryChoice >;
selling_online_answer: SellingOnlineAnswer | null;
selling_platforms: SellingPlatform[] | null;
skip?: boolean;
is_store_country_set: boolean | null;
};
export type PluginsPageSkippedEvent = {
type: 'PLUGINS_PAGE_SKIPPED';
};
export type PluginInstalledAndActivatedEvent = {
type: 'PLUGIN_INSTALLED_AND_ACTIVATED';
payload: {
pluginsCount: number;
installedPluginIndex: number;
};
};
export type PluginsInstallationCompletedEvent = {
type: 'PLUGINS_INSTALLATION_COMPLETED';
payload: {
installationCompletedResult: InstallationCompletedResult;
};
};
export type PluginsInstallationCompletedWithErrorsEvent = {
type: 'PLUGINS_INSTALLATION_COMPLETED_WITH_ERRORS';
payload: {
errors: PluginInstallError[];
};
};
export type CoreProfilerStateMachineContext = {
optInDataSharing: boolean;
userProfile: {
businessChoice?: BusinessChoice;
sellingOnlineAnswer?: SellingOnlineAnswer | null;
sellingPlatforms?: SellingPlatform[] | null;
skipped?: boolean;
};
pluginsAvailable: ExtensionList[ 'plugins' ] | [];
pluginsSelected: string[]; // extension slugs
pluginsInstallationErrors: PluginInstallError[];
geolocatedLocation: GeolocationResponse | undefined;
businessInfo: {
storeName?: string | undefined;
industry?: string | undefined;
location?: string;
};
countries: CountryStateOption[];
Add Business Location page to the core profiler (#38019) * Add core profiler - welcome to woo page * Update checkbox styles * Add tracks * Update default tracking value * Update copies * using invoked promise instead of useState - take advantage of xstate's built ins for side effects instead of useEffect/hooks - discovered that error result wasn't really handled in original useEffect - use text labels instead of inline functions so that we can decouple the implementation from the machine model - todo: can move the invoked function out elsewhere and also tests if needed (not necessary here because it's a simple call) * add: core profiler scaffolding using xstate * Add navigation and progress-bar components * fix css lint error * Update plugins/woocommerce-admin/client/core-profiler/components/navigation/woologo.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/components/progress-bar/progress-bar.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/components/navigation/navigation.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Remove var from __ function * Use woocommerce prefix for classnames * Fix css lint error * Fix broken tests * Add business location page * Remove unwanted changes from rebase * Remove unwanted changes from rebase * Redirect to Woo Home on exit * Add tracks * Fix js lint error * Add loader page * Support meta value from nested states * Use navigateTo * Add tests for getCountryStateOptions * Use Country type from navigation package * Rename useStages to getLoaderStageMeta * Add changelog * Move progress from 20 to 80 * Fix xstate warning * Fix broken pnpm lock * Fix eslint errors * Update plugins/woocommerce-admin/client/core-profiler/services/country.ts Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com> * Update plugins/woocommerce-admin/client/core-profiler/index.tsx Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com> * Save country to option * Fix jslint error * Update plugins/woocommerce-admin/client/core-profiler/services/country.ts Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/style.scss Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Fix eslint error * Use decodeEntities directly * Update comment for artificial 3 seconds wait * Disable Go to my store button when country is empty * Style for mobile devices * Style updates for the country dropdown * Fix js lint error * Update country dropdown border color * Style the loader * Fix css lint --------- Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> Co-authored-by: rjchow <me@rjchow.com> Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com>
2023-05-14 20:56:47 +00:00
loader: {
progress?: number;
className?: string;
useStages?: string;
stageIndex?: number;
};
onboardingProfile: OnboardingProfile;
};
Add core profiler "Welcome to Woo!" page (#37952) * Add core profiler - welcome to woo page * Add changelog * Update checkbox styles * Update copies * Add test * Add enable prop to window.wcTracks type * Add tracks * Add explat changelog * Fix import * Update default tracking value * Update copies * Fix test * using invoked promise instead of useState - take advantage of xstate's built ins for side effects instead of useEffect/hooks - discovered that error result wasn't really handled in original useEffect - use text labels instead of inline functions so that we can decouple the implementation from the machine model - todo: can move the invoked function out elsewhere and also tests if needed (not necessary here because it's a simple call) * use actions.choose instead of branching inside action - https://stately.ai/docs/xstate/transitions-and-choices/guarded-actions#the-choose-action - makes it so that the machine model is serializeable - todo: in the distant future i wonder if it might be tidier to have tracks be its own actor that just receives the same events that this machine does, that way it's just standalone instead of mixing up tracks with the implementation * use dispatch instead of useDispatch - decouples the implementation of the handler from the react component - makes the handler testable on its own if needed - makes the state machine testable without relying on external dependencies * decoupled remaining function calls * Fix lint error * Fix style lint * address xstate console warnings - .withConfig() is a function call that returns a new object every invocation so we need to wrap it in useMemo to keep it stable * Add optInDataSharing is false test * Fix lint --------- Co-authored-by: rjchow <me@rjchow.com>
2023-05-03 07:54:28 +00:00
const getAllowTrackingOption = async () =>
resolveSelect( OPTIONS_STORE_NAME ).getOption(
'woocommerce_allow_tracking'
);
const handleTrackingOption = assign( {
optInDataSharing: (
_context,
event: DoneInvokeEvent< 'no' | 'yes' | undefined >
) => event.data !== 'no',
} );
const getStoreNameOption = async () =>
resolveSelect( OPTIONS_STORE_NAME ).getOption( 'blogname' );
const handleStoreNameOption = assign( {
businessInfo: (
context: CoreProfilerStateMachineContext,
event: DoneInvokeEvent< string | undefined >
) => {
return {
...context.businessInfo,
storeName: POSSIBLY_DEFAULT_STORE_NAMES.includes( event.data ) // if its empty or the default, show empty to the user
? undefined
: event.data,
};
},
} );
const getStoreCountryOption = async () =>
resolveSelect( OPTIONS_STORE_NAME ).getOption(
'woocommerce_default_country'
);
const handleStoreCountryOption = assign( {
businessInfo: (
context: CoreProfilerStateMachineContext,
event: DoneInvokeEvent< string | undefined >
) => {
return {
...context.businessInfo,
location: event.data,
};
},
} );
/**
* Prefetch it so that @wp/data caches it and there won't be a loading delay when its used
*/
const preFetchGetCountries = assign( {
spawnGetCountriesRef: () =>
spawn(
() => resolveSelect( COUNTRIES_STORE_NAME ).getCountries(),
'core-profiler-prefetch-countries'
),
} );
const preFetchOptions = assign( {
spawnPrefetchOptionsRef: ( _context, _event, { action } ) => {
spawn(
() =>
Promise.all( [
// @ts-expect-error -- not sure its possible to type this yet, maybe in xstate v5
action.options.map( ( optionName: string ) =>
resolveSelect( OPTIONS_STORE_NAME ).getOption(
optionName
)
),
] ),
'core-profiler-prefetch-options'
);
},
} );
Add Business Location page to the core profiler (#38019) * Add core profiler - welcome to woo page * Update checkbox styles * Add tracks * Update default tracking value * Update copies * using invoked promise instead of useState - take advantage of xstate's built ins for side effects instead of useEffect/hooks - discovered that error result wasn't really handled in original useEffect - use text labels instead of inline functions so that we can decouple the implementation from the machine model - todo: can move the invoked function out elsewhere and also tests if needed (not necessary here because it's a simple call) * add: core profiler scaffolding using xstate * Add navigation and progress-bar components * fix css lint error * Update plugins/woocommerce-admin/client/core-profiler/components/navigation/woologo.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/components/progress-bar/progress-bar.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/components/navigation/navigation.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Remove var from __ function * Use woocommerce prefix for classnames * Fix css lint error * Fix broken tests * Add business location page * Remove unwanted changes from rebase * Remove unwanted changes from rebase * Redirect to Woo Home on exit * Add tracks * Fix js lint error * Add loader page * Support meta value from nested states * Use navigateTo * Add tests for getCountryStateOptions * Use Country type from navigation package * Rename useStages to getLoaderStageMeta * Add changelog * Move progress from 20 to 80 * Fix xstate warning * Fix broken pnpm lock * Fix eslint errors * Update plugins/woocommerce-admin/client/core-profiler/services/country.ts Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com> * Update plugins/woocommerce-admin/client/core-profiler/index.tsx Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com> * Save country to option * Fix jslint error * Update plugins/woocommerce-admin/client/core-profiler/services/country.ts Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/style.scss Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Fix eslint error * Use decodeEntities directly * Update comment for artificial 3 seconds wait * Disable Go to my store button when country is empty * Style for mobile devices * Style updates for the country dropdown * Fix js lint error * Update country dropdown border color * Style the loader * Fix css lint --------- Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> Co-authored-by: rjchow <me@rjchow.com> Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com>
2023-05-14 20:56:47 +00:00
const getCountries = async () =>
resolveSelect( COUNTRIES_STORE_NAME ).getCountries();
const handleCountries = assign( {
countries: ( _context, event: DoneInvokeEvent< Country[] > ) => {
return getCountryStateOptions( event.data );
},
} );
const getOnboardingProfileOption = async () =>
resolveSelect( OPTIONS_STORE_NAME ).getOption(
'woocommerce_onboarding_profile'
);
const handleOnboardingProfileOption = assign( {
userProfile: (
_context,
event: DoneInvokeEvent< OnboardingProfile | undefined >
) => {
if ( ! event.data ) {
return {};
}
const {
business_choice: businessChoice,
selling_online_answer: sellingOnlineAnswer,
selling_platforms: sellingPlatforms,
...rest
} = event.data;
return {
...rest,
businessChoice,
sellingOnlineAnswer,
sellingPlatforms,
};
},
} );
const assignOnboardingProfile = assign( {
onboardingProfile: (
_context,
event: DoneInvokeEvent< OnboardingProfile | undefined >
) => event.data,
} );
const getGeolocation = async ( context: CoreProfilerStateMachineContext ) => {
if ( context.optInDataSharing ) {
return resolveSelect( COUNTRIES_STORE_NAME ).geolocate();
}
return undefined;
};
const preFetchGeolocation = assign( {
spawnGeolocationRef: ( context: CoreProfilerStateMachineContext ) =>
spawn(
() => getGeolocation( context ),
'core-profiler-prefetch-geolocation'
),
} );
const handleGeolocation = assign( {
geolocatedLocation: (
_context,
event: DoneInvokeEvent< GeolocationResponse >
) => {
return event.data;
},
} );
Add Business Location page to the core profiler (#38019) * Add core profiler - welcome to woo page * Update checkbox styles * Add tracks * Update default tracking value * Update copies * using invoked promise instead of useState - take advantage of xstate's built ins for side effects instead of useEffect/hooks - discovered that error result wasn't really handled in original useEffect - use text labels instead of inline functions so that we can decouple the implementation from the machine model - todo: can move the invoked function out elsewhere and also tests if needed (not necessary here because it's a simple call) * add: core profiler scaffolding using xstate * Add navigation and progress-bar components * fix css lint error * Update plugins/woocommerce-admin/client/core-profiler/components/navigation/woologo.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/components/progress-bar/progress-bar.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/components/navigation/navigation.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Remove var from __ function * Use woocommerce prefix for classnames * Fix css lint error * Fix broken tests * Add business location page * Remove unwanted changes from rebase * Remove unwanted changes from rebase * Redirect to Woo Home on exit * Add tracks * Fix js lint error * Add loader page * Support meta value from nested states * Use navigateTo * Add tests for getCountryStateOptions * Use Country type from navigation package * Rename useStages to getLoaderStageMeta * Add changelog * Move progress from 20 to 80 * Fix xstate warning * Fix broken pnpm lock * Fix eslint errors * Update plugins/woocommerce-admin/client/core-profiler/services/country.ts Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com> * Update plugins/woocommerce-admin/client/core-profiler/index.tsx Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com> * Save country to option * Fix jslint error * Update plugins/woocommerce-admin/client/core-profiler/services/country.ts Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/style.scss Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Fix eslint error * Use decodeEntities directly * Update comment for artificial 3 seconds wait * Disable Go to my store button when country is empty * Style for mobile devices * Style updates for the country dropdown * Fix js lint error * Update country dropdown border color * Style the loader * Fix css lint --------- Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> Co-authored-by: rjchow <me@rjchow.com> Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com>
2023-05-14 20:56:47 +00:00
const redirectToWooHome = () => {
/**
* @todo replace with navigateTo
*/
window.location.href = '/wp-admin/admin.php?page=wc-admin';
Add Business Location page to the core profiler (#38019) * Add core profiler - welcome to woo page * Update checkbox styles * Add tracks * Update default tracking value * Update copies * using invoked promise instead of useState - take advantage of xstate's built ins for side effects instead of useEffect/hooks - discovered that error result wasn't really handled in original useEffect - use text labels instead of inline functions so that we can decouple the implementation from the machine model - todo: can move the invoked function out elsewhere and also tests if needed (not necessary here because it's a simple call) * add: core profiler scaffolding using xstate * Add navigation and progress-bar components * fix css lint error * Update plugins/woocommerce-admin/client/core-profiler/components/navigation/woologo.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/components/progress-bar/progress-bar.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/components/navigation/navigation.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Remove var from __ function * Use woocommerce prefix for classnames * Fix css lint error * Fix broken tests * Add business location page * Remove unwanted changes from rebase * Remove unwanted changes from rebase * Redirect to Woo Home on exit * Add tracks * Fix js lint error * Add loader page * Support meta value from nested states * Use navigateTo * Add tests for getCountryStateOptions * Use Country type from navigation package * Rename useStages to getLoaderStageMeta * Add changelog * Move progress from 20 to 80 * Fix xstate warning * Fix broken pnpm lock * Fix eslint errors * Update plugins/woocommerce-admin/client/core-profiler/services/country.ts Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com> * Update plugins/woocommerce-admin/client/core-profiler/index.tsx Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com> * Save country to option * Fix jslint error * Update plugins/woocommerce-admin/client/core-profiler/services/country.ts Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/style.scss Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Fix eslint error * Use decodeEntities directly * Update comment for artificial 3 seconds wait * Disable Go to my store button when country is empty * Style for mobile devices * Style updates for the country dropdown * Fix js lint error * Update country dropdown border color * Style the loader * Fix css lint --------- Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> Co-authored-by: rjchow <me@rjchow.com> Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com>
2023-05-14 20:56:47 +00:00
};
Add core profiler "Welcome to Woo!" page (#37952) * Add core profiler - welcome to woo page * Add changelog * Update checkbox styles * Update copies * Add test * Add enable prop to window.wcTracks type * Add tracks * Add explat changelog * Fix import * Update default tracking value * Update copies * Fix test * using invoked promise instead of useState - take advantage of xstate's built ins for side effects instead of useEffect/hooks - discovered that error result wasn't really handled in original useEffect - use text labels instead of inline functions so that we can decouple the implementation from the machine model - todo: can move the invoked function out elsewhere and also tests if needed (not necessary here because it's a simple call) * use actions.choose instead of branching inside action - https://stately.ai/docs/xstate/transitions-and-choices/guarded-actions#the-choose-action - makes it so that the machine model is serializeable - todo: in the distant future i wonder if it might be tidier to have tracks be its own actor that just receives the same events that this machine does, that way it's just standalone instead of mixing up tracks with the implementation * use dispatch instead of useDispatch - decouples the implementation of the handler from the react component - makes the handler testable on its own if needed - makes the state machine testable without relying on external dependencies * decoupled remaining function calls * Fix lint error * Fix style lint * address xstate console warnings - .withConfig() is a function call that returns a new object every invocation so we need to wrap it in useMemo to keep it stable * Add optInDataSharing is false test * Fix lint --------- Co-authored-by: rjchow <me@rjchow.com>
2023-05-03 07:54:28 +00:00
const updateTrackingOption = (
_context: CoreProfilerStateMachineContext,
event: IntroOptInEvent
) => {
if (
event.payload.optInDataSharing &&
typeof window.wcTracks.enable === 'function'
) {
window.wcTracks.enable( () => {
initializeExPlat();
} );
} else if ( ! event.payload.optInDataSharing ) {
window.wcTracks.isEnabled = false;
}
const trackingValue = event.payload.optInDataSharing ? 'yes' : 'no';
dispatch( OPTIONS_STORE_NAME ).updateOptions( {
woocommerce_allow_tracking: trackingValue,
} );
};
// TODO: move the data references over to the context.onboardingProfile object which stores the entire woocommerce_onboarding_profile contents
const updateOnboardingProfileOption = (
context: CoreProfilerStateMachineContext
) => {
const { businessChoice, sellingOnlineAnswer, sellingPlatforms } =
context.userProfile;
return dispatch( OPTIONS_STORE_NAME ).updateOptions( {
woocommerce_onboarding_profile: {
...context.onboardingProfile,
business_choice: businessChoice,
selling_online_answer: sellingOnlineAnswer,
selling_platforms: sellingPlatforms,
},
} );
};
Add Business Location page to the core profiler (#38019) * Add core profiler - welcome to woo page * Update checkbox styles * Add tracks * Update default tracking value * Update copies * using invoked promise instead of useState - take advantage of xstate's built ins for side effects instead of useEffect/hooks - discovered that error result wasn't really handled in original useEffect - use text labels instead of inline functions so that we can decouple the implementation from the machine model - todo: can move the invoked function out elsewhere and also tests if needed (not necessary here because it's a simple call) * add: core profiler scaffolding using xstate * Add navigation and progress-bar components * fix css lint error * Update plugins/woocommerce-admin/client/core-profiler/components/navigation/woologo.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/components/progress-bar/progress-bar.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/components/navigation/navigation.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Remove var from __ function * Use woocommerce prefix for classnames * Fix css lint error * Fix broken tests * Add business location page * Remove unwanted changes from rebase * Remove unwanted changes from rebase * Redirect to Woo Home on exit * Add tracks * Fix js lint error * Add loader page * Support meta value from nested states * Use navigateTo * Add tests for getCountryStateOptions * Use Country type from navigation package * Rename useStages to getLoaderStageMeta * Add changelog * Move progress from 20 to 80 * Fix xstate warning * Fix broken pnpm lock * Fix eslint errors * Update plugins/woocommerce-admin/client/core-profiler/services/country.ts Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com> * Update plugins/woocommerce-admin/client/core-profiler/index.tsx Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com> * Save country to option * Fix jslint error * Update plugins/woocommerce-admin/client/core-profiler/services/country.ts Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/style.scss Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Fix eslint error * Use decodeEntities directly * Update comment for artificial 3 seconds wait * Disable Go to my store button when country is empty * Style for mobile devices * Style updates for the country dropdown * Fix js lint error * Update country dropdown border color * Style the loader * Fix css lint --------- Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> Co-authored-by: rjchow <me@rjchow.com> Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com>
2023-05-14 20:56:47 +00:00
const updateBusinessLocation = ( countryAndState: string ) => {
return dispatch( OPTIONS_STORE_NAME ).updateOptions( {
woocommerce_default_country: countryAndState,
} );
};
const updateBusinessInfo = async (
_context: CoreProfilerStateMachineContext,
event: BusinessInfoEvent
) => {
const refreshedOnboardingProfile = ( await resolveSelect(
OPTIONS_STORE_NAME
).getOption( 'woocommerce_onboarding_profile' ) ) as OnboardingProfile;
return dispatch( OPTIONS_STORE_NAME ).updateOptions( {
blogname: event.payload.storeName,
woocommerce_default_country: event.payload.storeLocation,
woocommerce_onboarding_profile: {
...refreshedOnboardingProfile,
is_store_country_set: true,
industry: [ event.payload.industry ],
},
} );
};
const persistBusinessInfo = assign( {
persistBusinessInfoRef: (
context: CoreProfilerStateMachineContext,
event: BusinessInfoEvent
) =>
spawn(
() => updateBusinessInfo( context, event ),
'core-profiler-update-business-info'
),
} );
Add Business Location page to the core profiler (#38019) * Add core profiler - welcome to woo page * Update checkbox styles * Add tracks * Update default tracking value * Update copies * using invoked promise instead of useState - take advantage of xstate's built ins for side effects instead of useEffect/hooks - discovered that error result wasn't really handled in original useEffect - use text labels instead of inline functions so that we can decouple the implementation from the machine model - todo: can move the invoked function out elsewhere and also tests if needed (not necessary here because it's a simple call) * add: core profiler scaffolding using xstate * Add navigation and progress-bar components * fix css lint error * Update plugins/woocommerce-admin/client/core-profiler/components/navigation/woologo.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/components/progress-bar/progress-bar.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/components/navigation/navigation.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Remove var from __ function * Use woocommerce prefix for classnames * Fix css lint error * Fix broken tests * Add business location page * Remove unwanted changes from rebase * Remove unwanted changes from rebase * Redirect to Woo Home on exit * Add tracks * Fix js lint error * Add loader page * Support meta value from nested states * Use navigateTo * Add tests for getCountryStateOptions * Use Country type from navigation package * Rename useStages to getLoaderStageMeta * Add changelog * Move progress from 20 to 80 * Fix xstate warning * Fix broken pnpm lock * Fix eslint errors * Update plugins/woocommerce-admin/client/core-profiler/services/country.ts Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com> * Update plugins/woocommerce-admin/client/core-profiler/index.tsx Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com> * Save country to option * Fix jslint error * Update plugins/woocommerce-admin/client/core-profiler/services/country.ts Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/style.scss Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Fix eslint error * Use decodeEntities directly * Update comment for artificial 3 seconds wait * Disable Go to my store button when country is empty * Style for mobile devices * Style updates for the country dropdown * Fix js lint error * Update country dropdown border color * Style the loader * Fix css lint --------- Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> Co-authored-by: rjchow <me@rjchow.com> Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com>
2023-05-14 20:56:47 +00:00
const promiseDelay = ( milliseconds: number ) => {
return new Promise( ( resolve ) => {
setTimeout( resolve, milliseconds );
} );
};
Add core profiler "Welcome to Woo!" page (#37952) * Add core profiler - welcome to woo page * Add changelog * Update checkbox styles * Update copies * Add test * Add enable prop to window.wcTracks type * Add tracks * Add explat changelog * Fix import * Update default tracking value * Update copies * Fix test * using invoked promise instead of useState - take advantage of xstate's built ins for side effects instead of useEffect/hooks - discovered that error result wasn't really handled in original useEffect - use text labels instead of inline functions so that we can decouple the implementation from the machine model - todo: can move the invoked function out elsewhere and also tests if needed (not necessary here because it's a simple call) * use actions.choose instead of branching inside action - https://stately.ai/docs/xstate/transitions-and-choices/guarded-actions#the-choose-action - makes it so that the machine model is serializeable - todo: in the distant future i wonder if it might be tidier to have tracks be its own actor that just receives the same events that this machine does, that way it's just standalone instead of mixing up tracks with the implementation * use dispatch instead of useDispatch - decouples the implementation of the handler from the react component - makes the handler testable on its own if needed - makes the state machine testable without relying on external dependencies * decoupled remaining function calls * Fix lint error * Fix style lint * address xstate console warnings - .withConfig() is a function call that returns a new object every invocation so we need to wrap it in useMemo to keep it stable * Add optInDataSharing is false test * Fix lint --------- Co-authored-by: rjchow <me@rjchow.com>
2023-05-03 07:54:28 +00:00
/**
* Assigns the optInDataSharing value from the event payload to the context
*/
const assignOptInDataSharing = assign( {
optInDataSharing: ( _context, event: IntroOptInEvent ) =>
event.payload.optInDataSharing,
} );
/**
* Prefetch it so that @wp/data caches it and there won't be a loading delay when its used
*/
const preFetchGetPlugins = assign( {
extensionsRef: () =>
spawn(
() => resolveSelect( ONBOARDING_STORE_NAME ).getFreeExtensions(),
'core-profiler-prefetch-extensions'
),
} );
const getPlugins = async () => {
dispatch( ONBOARDING_STORE_NAME ).invalidateResolution(
'getFreeExtensions'
);
const extensionsBundles = await resolveSelect(
ONBOARDING_STORE_NAME
).getFreeExtensions();
return (
extensionsBundles.find(
( bundle ) => bundle.key === 'obw/core-profiler'
)?.plugins || []
);
};
const handlePlugins = assign( {
pluginsAvailable: ( _context, event: DoneInvokeEvent< Extension[] > ) =>
event.data,
} );
export const preFetchActions = {
preFetchGetPlugins,
preFetchGetCountries,
preFetchGeolocation,
preFetchOptions,
};
const coreProfilerMachineActions = {
...preFetchActions,
...recordTracksActions,
handlePlugins,
updateTrackingOption,
handleTrackingOption,
handleGeolocation,
handleStoreNameOption,
handleStoreCountryOption,
assignOptInDataSharing,
handleCountries,
handleOnboardingProfileOption,
assignOnboardingProfile,
persistBusinessInfo,
redirectToWooHome,
};
const coreProfilerMachineServices = {
getAllowTrackingOption,
getStoreNameOption,
getStoreCountryOption,
getCountries,
getGeolocation,
getOnboardingProfileOption,
getPlugins,
};
export const coreProfilerStateMachineDefinition = createMachine( {
id: 'coreProfiler',
initial: 'initializing',
Add core profiler "Welcome to Woo!" page (#37952) * Add core profiler - welcome to woo page * Add changelog * Update checkbox styles * Update copies * Add test * Add enable prop to window.wcTracks type * Add tracks * Add explat changelog * Fix import * Update default tracking value * Update copies * Fix test * using invoked promise instead of useState - take advantage of xstate's built ins for side effects instead of useEffect/hooks - discovered that error result wasn't really handled in original useEffect - use text labels instead of inline functions so that we can decouple the implementation from the machine model - todo: can move the invoked function out elsewhere and also tests if needed (not necessary here because it's a simple call) * use actions.choose instead of branching inside action - https://stately.ai/docs/xstate/transitions-and-choices/guarded-actions#the-choose-action - makes it so that the machine model is serializeable - todo: in the distant future i wonder if it might be tidier to have tracks be its own actor that just receives the same events that this machine does, that way it's just standalone instead of mixing up tracks with the implementation * use dispatch instead of useDispatch - decouples the implementation of the handler from the react component - makes the handler testable on its own if needed - makes the state machine testable without relying on external dependencies * decoupled remaining function calls * Fix lint error * Fix style lint * address xstate console warnings - .withConfig() is a function call that returns a new object every invocation so we need to wrap it in useMemo to keep it stable * Add optInDataSharing is false test * Fix lint --------- Co-authored-by: rjchow <me@rjchow.com>
2023-05-03 07:54:28 +00:00
predictableActionArguments: true, // recommended setting: https://xstate.js.org/docs/guides/actions.html
context: {
// these are safe default values if for some reason the steps fail to complete correctly
// actual defaults displayed to the user should be handled in the steps themselves
optInDataSharing: false,
userProfile: { skipped: true },
geolocatedLocation: undefined,
businessInfo: {
storeName: undefined,
industry: undefined,
storeCountryPreviouslySet: false,
location: 'US:CA',
},
countries: [] as CountryStateOption[],
pluginsAvailable: [],
pluginsInstallationErrors: [],
pluginsSelected: [],
Add Business Location page to the core profiler (#38019) * Add core profiler - welcome to woo page * Update checkbox styles * Add tracks * Update default tracking value * Update copies * using invoked promise instead of useState - take advantage of xstate's built ins for side effects instead of useEffect/hooks - discovered that error result wasn't really handled in original useEffect - use text labels instead of inline functions so that we can decouple the implementation from the machine model - todo: can move the invoked function out elsewhere and also tests if needed (not necessary here because it's a simple call) * add: core profiler scaffolding using xstate * Add navigation and progress-bar components * fix css lint error * Update plugins/woocommerce-admin/client/core-profiler/components/navigation/woologo.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/components/progress-bar/progress-bar.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/components/navigation/navigation.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Remove var from __ function * Use woocommerce prefix for classnames * Fix css lint error * Fix broken tests * Add business location page * Remove unwanted changes from rebase * Remove unwanted changes from rebase * Redirect to Woo Home on exit * Add tracks * Fix js lint error * Add loader page * Support meta value from nested states * Use navigateTo * Add tests for getCountryStateOptions * Use Country type from navigation package * Rename useStages to getLoaderStageMeta * Add changelog * Move progress from 20 to 80 * Fix xstate warning * Fix broken pnpm lock * Fix eslint errors * Update plugins/woocommerce-admin/client/core-profiler/services/country.ts Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com> * Update plugins/woocommerce-admin/client/core-profiler/index.tsx Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com> * Save country to option * Fix jslint error * Update plugins/woocommerce-admin/client/core-profiler/services/country.ts Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/style.scss Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Fix eslint error * Use decodeEntities directly * Update comment for artificial 3 seconds wait * Disable Go to my store button when country is empty * Style for mobile devices * Style updates for the country dropdown * Fix js lint error * Update country dropdown border color * Style the loader * Fix css lint --------- Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> Co-authored-by: rjchow <me@rjchow.com> Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com>
2023-05-14 20:56:47 +00:00
loader: {},
onboardingProfile: {} as OnboardingProfile,
} as CoreProfilerStateMachineContext,
states: {
initializing: {
entry: [
// these prefetch tasks are spawned actors in the background and do not block progression of the state machine
'preFetchGetPlugins',
'preFetchGetCountries',
{
type: 'preFetchOptions',
options: [
'blogname',
'woocommerce_onboarding_profile',
'woocommerce_default_country',
Add core profiler "Welcome to Woo!" page (#37952) * Add core profiler - welcome to woo page * Add changelog * Update checkbox styles * Update copies * Add test * Add enable prop to window.wcTracks type * Add tracks * Add explat changelog * Fix import * Update default tracking value * Update copies * Fix test * using invoked promise instead of useState - take advantage of xstate's built ins for side effects instead of useEffect/hooks - discovered that error result wasn't really handled in original useEffect - use text labels instead of inline functions so that we can decouple the implementation from the machine model - todo: can move the invoked function out elsewhere and also tests if needed (not necessary here because it's a simple call) * use actions.choose instead of branching inside action - https://stately.ai/docs/xstate/transitions-and-choices/guarded-actions#the-choose-action - makes it so that the machine model is serializeable - todo: in the distant future i wonder if it might be tidier to have tracks be its own actor that just receives the same events that this machine does, that way it's just standalone instead of mixing up tracks with the implementation * use dispatch instead of useDispatch - decouples the implementation of the handler from the react component - makes the handler testable on its own if needed - makes the state machine testable without relying on external dependencies * decoupled remaining function calls * Fix lint error * Fix style lint * address xstate console warnings - .withConfig() is a function call that returns a new object every invocation so we need to wrap it in useMemo to keep it stable * Add optInDataSharing is false test * Fix lint --------- Co-authored-by: rjchow <me@rjchow.com>
2023-05-03 07:54:28 +00:00
],
},
],
type: 'parallel',
states: {
// if we have any other init tasks to do in parallel, add them as a parallel state here.
// this blocks the introOptIn UI from loading keep that in mind when adding new tasks here
trackingOption: {
initial: 'fetching',
states: {
fetching: {
invoke: {
src: 'getAllowTrackingOption',
onDone: [
{
actions: [ 'handleTrackingOption' ],
target: 'done',
},
],
onError: {
target: 'done', // leave it as initialised default on error
},
},
},
done: {
type: 'final',
},
},
},
},
onDone: {
target: 'introOptIn',
// TODO: at this point, we can handle the URL path param if any and jump to the correct page
},
meta: {
progress: 0,
},
},
introOptIn: {
on: {
INTRO_COMPLETED: {
target: 'preUserProfile',
actions: [
Add core profiler "Welcome to Woo!" page (#37952) * Add core profiler - welcome to woo page * Add changelog * Update checkbox styles * Update copies * Add test * Add enable prop to window.wcTracks type * Add tracks * Add explat changelog * Fix import * Update default tracking value * Update copies * Fix test * using invoked promise instead of useState - take advantage of xstate's built ins for side effects instead of useEffect/hooks - discovered that error result wasn't really handled in original useEffect - use text labels instead of inline functions so that we can decouple the implementation from the machine model - todo: can move the invoked function out elsewhere and also tests if needed (not necessary here because it's a simple call) * use actions.choose instead of branching inside action - https://stately.ai/docs/xstate/transitions-and-choices/guarded-actions#the-choose-action - makes it so that the machine model is serializeable - todo: in the distant future i wonder if it might be tidier to have tracks be its own actor that just receives the same events that this machine does, that way it's just standalone instead of mixing up tracks with the implementation * use dispatch instead of useDispatch - decouples the implementation of the handler from the react component - makes the handler testable on its own if needed - makes the state machine testable without relying on external dependencies * decoupled remaining function calls * Fix lint error * Fix style lint * address xstate console warnings - .withConfig() is a function call that returns a new object every invocation so we need to wrap it in useMemo to keep it stable * Add optInDataSharing is false test * Fix lint --------- Co-authored-by: rjchow <me@rjchow.com>
2023-05-03 07:54:28 +00:00
'assignOptInDataSharing',
'updateTrackingOption',
],
},
INTRO_SKIPPED: {
// if the user skips the intro, we set the optInDataSharing to false and go to the Business Location page
Add Business Location page to the core profiler (#38019) * Add core profiler - welcome to woo page * Update checkbox styles * Add tracks * Update default tracking value * Update copies * using invoked promise instead of useState - take advantage of xstate's built ins for side effects instead of useEffect/hooks - discovered that error result wasn't really handled in original useEffect - use text labels instead of inline functions so that we can decouple the implementation from the machine model - todo: can move the invoked function out elsewhere and also tests if needed (not necessary here because it's a simple call) * add: core profiler scaffolding using xstate * Add navigation and progress-bar components * fix css lint error * Update plugins/woocommerce-admin/client/core-profiler/components/navigation/woologo.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/components/progress-bar/progress-bar.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/components/navigation/navigation.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Remove var from __ function * Use woocommerce prefix for classnames * Fix css lint error * Fix broken tests * Add business location page * Remove unwanted changes from rebase * Remove unwanted changes from rebase * Redirect to Woo Home on exit * Add tracks * Fix js lint error * Add loader page * Support meta value from nested states * Use navigateTo * Add tests for getCountryStateOptions * Use Country type from navigation package * Rename useStages to getLoaderStageMeta * Add changelog * Move progress from 20 to 80 * Fix xstate warning * Fix broken pnpm lock * Fix eslint errors * Update plugins/woocommerce-admin/client/core-profiler/services/country.ts Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com> * Update plugins/woocommerce-admin/client/core-profiler/index.tsx Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com> * Save country to option * Fix jslint error * Update plugins/woocommerce-admin/client/core-profiler/services/country.ts Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/style.scss Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Fix eslint error * Use decodeEntities directly * Update comment for artificial 3 seconds wait * Disable Go to my store button when country is empty * Style for mobile devices * Style updates for the country dropdown * Fix js lint error * Update country dropdown border color * Style the loader * Fix css lint --------- Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> Co-authored-by: rjchow <me@rjchow.com> Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com>
2023-05-14 20:56:47 +00:00
target: 'preSkipFlowBusinessLocation',
actions: [
Add core profiler "Welcome to Woo!" page (#37952) * Add core profiler - welcome to woo page * Add changelog * Update checkbox styles * Update copies * Add test * Add enable prop to window.wcTracks type * Add tracks * Add explat changelog * Fix import * Update default tracking value * Update copies * Fix test * using invoked promise instead of useState - take advantage of xstate's built ins for side effects instead of useEffect/hooks - discovered that error result wasn't really handled in original useEffect - use text labels instead of inline functions so that we can decouple the implementation from the machine model - todo: can move the invoked function out elsewhere and also tests if needed (not necessary here because it's a simple call) * use actions.choose instead of branching inside action - https://stately.ai/docs/xstate/transitions-and-choices/guarded-actions#the-choose-action - makes it so that the machine model is serializeable - todo: in the distant future i wonder if it might be tidier to have tracks be its own actor that just receives the same events that this machine does, that way it's just standalone instead of mixing up tracks with the implementation * use dispatch instead of useDispatch - decouples the implementation of the handler from the react component - makes the handler testable on its own if needed - makes the state machine testable without relying on external dependencies * decoupled remaining function calls * Fix lint error * Fix style lint * address xstate console warnings - .withConfig() is a function call that returns a new object every invocation so we need to wrap it in useMemo to keep it stable * Add optInDataSharing is false test * Fix lint --------- Co-authored-by: rjchow <me@rjchow.com>
2023-05-03 07:54:28 +00:00
'assignOptInDataSharing',
'updateTrackingOption',
],
},
},
entry: [
{ type: 'recordTracksStepViewed', step: 'store_details' },
],
Add core profiler "Welcome to Woo!" page (#37952) * Add core profiler - welcome to woo page * Add changelog * Update checkbox styles * Update copies * Add test * Add enable prop to window.wcTracks type * Add tracks * Add explat changelog * Fix import * Update default tracking value * Update copies * Fix test * using invoked promise instead of useState - take advantage of xstate's built ins for side effects instead of useEffect/hooks - discovered that error result wasn't really handled in original useEffect - use text labels instead of inline functions so that we can decouple the implementation from the machine model - todo: can move the invoked function out elsewhere and also tests if needed (not necessary here because it's a simple call) * use actions.choose instead of branching inside action - https://stately.ai/docs/xstate/transitions-and-choices/guarded-actions#the-choose-action - makes it so that the machine model is serializeable - todo: in the distant future i wonder if it might be tidier to have tracks be its own actor that just receives the same events that this machine does, that way it's just standalone instead of mixing up tracks with the implementation * use dispatch instead of useDispatch - decouples the implementation of the handler from the react component - makes the handler testable on its own if needed - makes the state machine testable without relying on external dependencies * decoupled remaining function calls * Fix lint error * Fix style lint * address xstate console warnings - .withConfig() is a function call that returns a new object every invocation so we need to wrap it in useMemo to keep it stable * Add optInDataSharing is false test * Fix lint --------- Co-authored-by: rjchow <me@rjchow.com>
2023-05-03 07:54:28 +00:00
exit: actions.choose( [
{
cond: ( _context, event ) =>
event.type === 'INTRO_COMPLETED',
actions: 'recordTracksIntroCompleted',
},
{
cond: ( _context, event ) => event.type === 'INTRO_SKIPPED',
actions: [
{
type: 'recordTracksStepSkipped',
step: 'store_details',
},
],
Add core profiler "Welcome to Woo!" page (#37952) * Add core profiler - welcome to woo page * Add changelog * Update checkbox styles * Update copies * Add test * Add enable prop to window.wcTracks type * Add tracks * Add explat changelog * Fix import * Update default tracking value * Update copies * Fix test * using invoked promise instead of useState - take advantage of xstate's built ins for side effects instead of useEffect/hooks - discovered that error result wasn't really handled in original useEffect - use text labels instead of inline functions so that we can decouple the implementation from the machine model - todo: can move the invoked function out elsewhere and also tests if needed (not necessary here because it's a simple call) * use actions.choose instead of branching inside action - https://stately.ai/docs/xstate/transitions-and-choices/guarded-actions#the-choose-action - makes it so that the machine model is serializeable - todo: in the distant future i wonder if it might be tidier to have tracks be its own actor that just receives the same events that this machine does, that way it's just standalone instead of mixing up tracks with the implementation * use dispatch instead of useDispatch - decouples the implementation of the handler from the react component - makes the handler testable on its own if needed - makes the state machine testable without relying on external dependencies * decoupled remaining function calls * Fix lint error * Fix style lint * address xstate console warnings - .withConfig() is a function call that returns a new object every invocation so we need to wrap it in useMemo to keep it stable * Add optInDataSharing is false test * Fix lint --------- Co-authored-by: rjchow <me@rjchow.com>
2023-05-03 07:54:28 +00:00
},
] ),
meta: {
progress: 20,
component: IntroOptIn,
},
},
preUserProfile: {
invoke: {
src: 'getOnboardingProfileOption',
onDone: [
{
actions: [
'handleOnboardingProfileOption',
'assignOnboardingProfile',
],
target: 'userProfile',
},
],
onError: {
target: 'userProfile',
},
},
},
userProfile: {
entry: [
{ type: 'recordTracksStepViewed', step: 'user_profile' },
'preFetchGeolocation',
],
on: {
USER_PROFILE_COMPLETED: {
target: 'postUserProfile',
actions: [
assign( {
userProfile: ( context, event: UserProfileEvent ) =>
event.payload.userProfile, // sets context.userProfile to the payload of the event
} ),
],
},
USER_PROFILE_SKIPPED: {
target: 'postUserProfile',
actions: [
assign( {
userProfile: ( context, event: UserProfileEvent ) =>
event.payload.userProfile, // assign context.userProfile to the payload of the event
} ),
],
},
},
exit: actions.choose( [
{
cond: ( _context, event ) =>
event.type === 'USER_PROFILE_COMPLETED',
actions: 'recordTracksUserProfileCompleted',
},
{
cond: ( _context, event ) =>
event.type === 'USER_PROFILE_SKIPPED',
actions: [
{
type: 'recordTracksStepSkipped',
step: 'user_profile',
},
],
},
] ),
meta: {
progress: 40,
component: UserProfile,
},
},
postUserProfile: {
invoke: {
src: ( context ) => {
return updateOnboardingProfileOption( context );
},
onDone: {
target: 'preBusinessInfo',
},
onError: {
target: 'preBusinessInfo',
},
},
},
preBusinessInfo: {
type: 'parallel',
states: {
geolocation: {
initial: 'checkDataOptIn',
states: {
checkDataOptIn: {
// if the user has opted out of data sharing, we skip the geolocation step
always: [
{
cond: ( context ) =>
context.optInDataSharing,
target: 'fetching',
},
{
target: 'done',
},
],
},
fetching: {
invoke: {
src: 'getGeolocation',
onDone: {
target: 'done',
actions: 'handleGeolocation',
},
// onError TODO: handle error
},
},
done: {
type: 'final',
},
},
},
storeCountryOption: {
initial: 'fetching',
states: {
fetching: {
invoke: {
src: 'getStoreCountryOption',
onDone: [
{
actions: [ 'handleStoreCountryOption' ],
target: 'done',
},
],
onError: {
target: 'done',
},
},
},
done: {
type: 'final',
},
},
},
storeNameOption: {
initial: 'fetching',
states: {
fetching: {
invoke: {
src: 'getStoreNameOption',
onDone: [
{
actions: [ 'handleStoreNameOption' ],
target: 'done',
},
],
onError: {
target: 'done', // leave it as initialised default on error
},
},
},
done: {
type: 'final',
},
},
},
countries: {
initial: 'fetching',
states: {
fetching: {
invoke: {
src: 'getCountries',
onDone: {
target: 'done',
actions: 'handleCountries',
},
},
},
done: {
type: 'final',
},
},
},
},
// onDone is reached when child parallel states are all at their final states
onDone: {
target: 'businessInfo',
},
meta: {
progress: 50,
},
},
businessInfo: {
entry: [
{ type: 'recordTracksStepViewed', step: 'business_info' },
],
on: {
BUSINESS_INFO_COMPLETED: {
target: 'prePlugins',
actions: [
'persistBusinessInfo',
'recordTracksBusinessInfoCompleted',
],
},
},
meta: {
progress: 60,
component: BusinessInfo,
},
},
Add Business Location page to the core profiler (#38019) * Add core profiler - welcome to woo page * Update checkbox styles * Add tracks * Update default tracking value * Update copies * using invoked promise instead of useState - take advantage of xstate's built ins for side effects instead of useEffect/hooks - discovered that error result wasn't really handled in original useEffect - use text labels instead of inline functions so that we can decouple the implementation from the machine model - todo: can move the invoked function out elsewhere and also tests if needed (not necessary here because it's a simple call) * add: core profiler scaffolding using xstate * Add navigation and progress-bar components * fix css lint error * Update plugins/woocommerce-admin/client/core-profiler/components/navigation/woologo.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/components/progress-bar/progress-bar.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/components/navigation/navigation.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Remove var from __ function * Use woocommerce prefix for classnames * Fix css lint error * Fix broken tests * Add business location page * Remove unwanted changes from rebase * Remove unwanted changes from rebase * Redirect to Woo Home on exit * Add tracks * Fix js lint error * Add loader page * Support meta value from nested states * Use navigateTo * Add tests for getCountryStateOptions * Use Country type from navigation package * Rename useStages to getLoaderStageMeta * Add changelog * Move progress from 20 to 80 * Fix xstate warning * Fix broken pnpm lock * Fix eslint errors * Update plugins/woocommerce-admin/client/core-profiler/services/country.ts Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com> * Update plugins/woocommerce-admin/client/core-profiler/index.tsx Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com> * Save country to option * Fix jslint error * Update plugins/woocommerce-admin/client/core-profiler/services/country.ts Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/style.scss Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Fix eslint error * Use decodeEntities directly * Update comment for artificial 3 seconds wait * Disable Go to my store button when country is empty * Style for mobile devices * Style updates for the country dropdown * Fix js lint error * Update country dropdown border color * Style the loader * Fix css lint --------- Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> Co-authored-by: rjchow <me@rjchow.com> Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com>
2023-05-14 20:56:47 +00:00
preSkipFlowBusinessLocation: {
invoke: {
src: 'getCountries',
onDone: [
{
actions: [ 'handleCountries' ],
target: 'skipFlowBusinessLocation',
},
],
onError: {
target: 'skipFlowBusinessLocation',
},
},
},
skipFlowBusinessLocation: {
on: {
BUSINESS_LOCATION_COMPLETED: {
Add Business Location page to the core profiler (#38019) * Add core profiler - welcome to woo page * Update checkbox styles * Add tracks * Update default tracking value * Update copies * using invoked promise instead of useState - take advantage of xstate's built ins for side effects instead of useEffect/hooks - discovered that error result wasn't really handled in original useEffect - use text labels instead of inline functions so that we can decouple the implementation from the machine model - todo: can move the invoked function out elsewhere and also tests if needed (not necessary here because it's a simple call) * add: core profiler scaffolding using xstate * Add navigation and progress-bar components * fix css lint error * Update plugins/woocommerce-admin/client/core-profiler/components/navigation/woologo.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/components/progress-bar/progress-bar.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/components/navigation/navigation.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Remove var from __ function * Use woocommerce prefix for classnames * Fix css lint error * Fix broken tests * Add business location page * Remove unwanted changes from rebase * Remove unwanted changes from rebase * Redirect to Woo Home on exit * Add tracks * Fix js lint error * Add loader page * Support meta value from nested states * Use navigateTo * Add tests for getCountryStateOptions * Use Country type from navigation package * Rename useStages to getLoaderStageMeta * Add changelog * Move progress from 20 to 80 * Fix xstate warning * Fix broken pnpm lock * Fix eslint errors * Update plugins/woocommerce-admin/client/core-profiler/services/country.ts Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com> * Update plugins/woocommerce-admin/client/core-profiler/index.tsx Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com> * Save country to option * Fix jslint error * Update plugins/woocommerce-admin/client/core-profiler/services/country.ts Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/style.scss Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Fix eslint error * Use decodeEntities directly * Update comment for artificial 3 seconds wait * Disable Go to my store button when country is empty * Style for mobile devices * Style updates for the country dropdown * Fix js lint error * Update country dropdown border color * Style the loader * Fix css lint --------- Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> Co-authored-by: rjchow <me@rjchow.com> Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com>
2023-05-14 20:56:47 +00:00
target: 'postSkipFlowBusinessLocation',
actions: [
assign( {
businessInfo: (
context,
event: BusinessLocationEvent
) => {
return {
...context.businessInfo,
location: event.payload.storeLocation,
};
},
} ),
Add Business Location page to the core profiler (#38019) * Add core profiler - welcome to woo page * Update checkbox styles * Add tracks * Update default tracking value * Update copies * using invoked promise instead of useState - take advantage of xstate's built ins for side effects instead of useEffect/hooks - discovered that error result wasn't really handled in original useEffect - use text labels instead of inline functions so that we can decouple the implementation from the machine model - todo: can move the invoked function out elsewhere and also tests if needed (not necessary here because it's a simple call) * add: core profiler scaffolding using xstate * Add navigation and progress-bar components * fix css lint error * Update plugins/woocommerce-admin/client/core-profiler/components/navigation/woologo.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/components/progress-bar/progress-bar.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/components/navigation/navigation.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Remove var from __ function * Use woocommerce prefix for classnames * Fix css lint error * Fix broken tests * Add business location page * Remove unwanted changes from rebase * Remove unwanted changes from rebase * Redirect to Woo Home on exit * Add tracks * Fix js lint error * Add loader page * Support meta value from nested states * Use navigateTo * Add tests for getCountryStateOptions * Use Country type from navigation package * Rename useStages to getLoaderStageMeta * Add changelog * Move progress from 20 to 80 * Fix xstate warning * Fix broken pnpm lock * Fix eslint errors * Update plugins/woocommerce-admin/client/core-profiler/services/country.ts Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com> * Update plugins/woocommerce-admin/client/core-profiler/index.tsx Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com> * Save country to option * Fix jslint error * Update plugins/woocommerce-admin/client/core-profiler/services/country.ts Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/style.scss Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Fix eslint error * Use decodeEntities directly * Update comment for artificial 3 seconds wait * Disable Go to my store button when country is empty * Style for mobile devices * Style updates for the country dropdown * Fix js lint error * Update country dropdown border color * Style the loader * Fix css lint --------- Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> Co-authored-by: rjchow <me@rjchow.com> Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com>
2023-05-14 20:56:47 +00:00
'recordTracksSkipBusinessLocationCompleted',
],
},
},
entry: [
{
type: 'recordTracksStepViewed',
step: 'skip_business_location',
},
],
meta: {
progress: 80,
component: BusinessLocation,
},
},
Add Business Location page to the core profiler (#38019) * Add core profiler - welcome to woo page * Update checkbox styles * Add tracks * Update default tracking value * Update copies * using invoked promise instead of useState - take advantage of xstate's built ins for side effects instead of useEffect/hooks - discovered that error result wasn't really handled in original useEffect - use text labels instead of inline functions so that we can decouple the implementation from the machine model - todo: can move the invoked function out elsewhere and also tests if needed (not necessary here because it's a simple call) * add: core profiler scaffolding using xstate * Add navigation and progress-bar components * fix css lint error * Update plugins/woocommerce-admin/client/core-profiler/components/navigation/woologo.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/components/progress-bar/progress-bar.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/components/navigation/navigation.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Remove var from __ function * Use woocommerce prefix for classnames * Fix css lint error * Fix broken tests * Add business location page * Remove unwanted changes from rebase * Remove unwanted changes from rebase * Redirect to Woo Home on exit * Add tracks * Fix js lint error * Add loader page * Support meta value from nested states * Use navigateTo * Add tests for getCountryStateOptions * Use Country type from navigation package * Rename useStages to getLoaderStageMeta * Add changelog * Move progress from 20 to 80 * Fix xstate warning * Fix broken pnpm lock * Fix eslint errors * Update plugins/woocommerce-admin/client/core-profiler/services/country.ts Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com> * Update plugins/woocommerce-admin/client/core-profiler/index.tsx Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com> * Save country to option * Fix jslint error * Update plugins/woocommerce-admin/client/core-profiler/services/country.ts Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/style.scss Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Fix eslint error * Use decodeEntities directly * Update comment for artificial 3 seconds wait * Disable Go to my store button when country is empty * Style for mobile devices * Style updates for the country dropdown * Fix js lint error * Update country dropdown border color * Style the loader * Fix css lint --------- Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> Co-authored-by: rjchow <me@rjchow.com> Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com>
2023-05-14 20:56:47 +00:00
postSkipFlowBusinessLocation: {
initial: 'updateBusinessLocation',
states: {
updateBusinessLocation: {
entry: assign( {
loader: {
progress: 10,
},
} ),
invoke: {
src: ( context ) => {
return updateBusinessLocation(
context.businessInfo.location as string
Add Business Location page to the core profiler (#38019) * Add core profiler - welcome to woo page * Update checkbox styles * Add tracks * Update default tracking value * Update copies * using invoked promise instead of useState - take advantage of xstate's built ins for side effects instead of useEffect/hooks - discovered that error result wasn't really handled in original useEffect - use text labels instead of inline functions so that we can decouple the implementation from the machine model - todo: can move the invoked function out elsewhere and also tests if needed (not necessary here because it's a simple call) * add: core profiler scaffolding using xstate * Add navigation and progress-bar components * fix css lint error * Update plugins/woocommerce-admin/client/core-profiler/components/navigation/woologo.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/components/progress-bar/progress-bar.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/components/navigation/navigation.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Remove var from __ function * Use woocommerce prefix for classnames * Fix css lint error * Fix broken tests * Add business location page * Remove unwanted changes from rebase * Remove unwanted changes from rebase * Redirect to Woo Home on exit * Add tracks * Fix js lint error * Add loader page * Support meta value from nested states * Use navigateTo * Add tests for getCountryStateOptions * Use Country type from navigation package * Rename useStages to getLoaderStageMeta * Add changelog * Move progress from 20 to 80 * Fix xstate warning * Fix broken pnpm lock * Fix eslint errors * Update plugins/woocommerce-admin/client/core-profiler/services/country.ts Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com> * Update plugins/woocommerce-admin/client/core-profiler/index.tsx Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com> * Save country to option * Fix jslint error * Update plugins/woocommerce-admin/client/core-profiler/services/country.ts Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/style.scss Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Fix eslint error * Use decodeEntities directly * Update comment for artificial 3 seconds wait * Disable Go to my store button when country is empty * Style for mobile devices * Style updates for the country dropdown * Fix js lint error * Update country dropdown border color * Style the loader * Fix css lint --------- Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> Co-authored-by: rjchow <me@rjchow.com> Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com>
2023-05-14 20:56:47 +00:00
);
},
onDone: {
target: 'progress20',
},
},
},
// Although we don't need to wait 3 seconds for the following states
// We will dispaly 20% and 80% progress for 1.5 seconds each
// for the sake of user experience.
progress20: {
entry: assign( {
loader: {
progress: 20,
},
} ),
invoke: {
src: () => {
return promiseDelay( 1500 );
},
onDone: {
target: 'progress80',
},
},
},
progress80: {
entry: assign( {
loader: {
progress: 80,
},
} ),
invoke: {
src: () => {
return promiseDelay( 1500 );
},
onDone: {
actions: [ 'redirectToWooHome' ],
},
},
},
},
meta: {
component: Loader,
},
},
prePlugins: {
invoke: {
src: 'getPlugins',
onDone: [
{
target: 'pluginsSkipped',
cond: ( context, event ) => event.data.length === 0,
},
{ target: 'plugins', actions: 'handlePlugins' },
],
},
// add exit action to filter the extensions using a custom function here and assign it to context.extensionsAvailable
exit: assign( {
pluginsAvailable: ( context ) => {
return context.pluginsAvailable.filter( () => true );
}, // TODO : define an extensible filter function here
} ),
meta: {
progress: 70,
},
},
pluginsSkipped: {
entry: assign( {
loader: {
progress: 80,
},
} ),
invoke: {
src: () => {
dispatch( ONBOARDING_STORE_NAME ).updateProfileItems( {
plugins_page_skipped: true,
completed: true,
} );
return promiseDelay( 3000 );
},
onDone: {
actions: [ 'redirectToWooHome' ],
},
},
meta: {
component: Loader,
},
},
plugins: {
entry: [ { type: 'recordTracksStepViewed', step: 'plugins' } ],
on: {
PLUGINS_PAGE_SKIPPED: {
actions: [
{
type: 'recordTracksStepSkipped',
step: 'plugins',
},
],
target: 'pluginsSkipped',
},
PLUGINS_INSTALLATION_REQUESTED: {
target: 'installPlugins',
actions: [
assign( {
pluginsSelected: (
_context,
event: PluginsInstallationRequestedEvent
) => event.payload.plugins,
} ),
],
},
},
meta: {
progress: 80,
component: Plugins,
},
},
postPluginInstallation: {
invoke: {
src: async ( _context, event ) => {
return await dispatch(
ONBOARDING_STORE_NAME
).updateProfileItems( {
business_extensions:
event.payload.installationCompletedResult.installedPlugins.map(
( extension: InstalledPlugin ) =>
extension.plugin
),
completed: true,
} );
},
onDone: {
actions: 'redirectToWooHome',
},
},
meta: {
component: Loader,
progress: 100,
},
},
installPlugins: {
on: {
PLUGIN_INSTALLED_AND_ACTIVATED: {
actions: [
assign( {
loader: (
_context,
event: PluginInstalledAndActivatedEvent
) => {
const progress = Math.round(
( event.payload.installedPluginIndex /
event.payload.pluginsCount ) *
100
);
let stageIndex = 0;
if ( progress > 30 ) {
stageIndex = 1;
} else if ( progress > 60 ) {
stageIndex = 2;
}
return {
useStages: 'plugins',
progress,
stageIndex,
};
},
} ),
],
},
PLUGINS_INSTALLATION_COMPLETED_WITH_ERRORS: {
target: 'prePlugins',
actions: [
assign( {
pluginsInstallationErrors: ( _context, event ) =>
event.payload.errors,
} ),
( _context, event ) => {
recordEvent(
'storeprofiler_store_extensions_installed_and_activated',
{
success: false,
failed_extensions: event.payload.errors.map(
( error: PluginInstallError ) =>
getPluginTrackKey( error.plugin )
),
}
);
},
],
},
PLUGINS_INSTALLATION_COMPLETED: {
target: 'postPluginInstallation',
actions: [
( _context, event ) => {
const installationCompletedResult =
event.payload.installationCompletedResult;
const trackData: {
success: boolean;
installed_extensions: string[];
total_time: string;
[ key: string ]:
| number
| boolean
| string
| string[];
} = {
success: true,
installed_extensions:
installationCompletedResult.installedPlugins.map(
( installedPlugin: InstalledPlugin ) =>
getPluginTrackKey(
installedPlugin.plugin
)
),
total_time: getTimeFrame(
installationCompletedResult.totalTime
),
};
for ( const installedPlugin of installationCompletedResult.installedPlugins ) {
trackData[
'install_time_' +
getPluginTrackKey(
installedPlugin.plugin
)
] = getTimeFrame( installedPlugin.installTime );
}
recordEvent(
'storeprofiler_store_extensions_installed_and_activated',
trackData
);
},
],
},
},
entry: [
assign( {
loader: {
progress: 10,
useStages: 'plugins',
},
} ),
],
invoke: {
src: InstallAndActivatePlugins,
},
meta: {
component: Loader,
},
},
settingUpStore: {},
},
} );
export const CoreProfilerController = ( {
actionOverrides,
servicesOverrides,
}: {
actionOverrides: Partial< typeof coreProfilerMachineActions >;
servicesOverrides: Partial< typeof coreProfilerMachineServices >;
} ) => {
Add core profiler "Welcome to Woo!" page (#37952) * Add core profiler - welcome to woo page * Add changelog * Update checkbox styles * Update copies * Add test * Add enable prop to window.wcTracks type * Add tracks * Add explat changelog * Fix import * Update default tracking value * Update copies * Fix test * using invoked promise instead of useState - take advantage of xstate's built ins for side effects instead of useEffect/hooks - discovered that error result wasn't really handled in original useEffect - use text labels instead of inline functions so that we can decouple the implementation from the machine model - todo: can move the invoked function out elsewhere and also tests if needed (not necessary here because it's a simple call) * use actions.choose instead of branching inside action - https://stately.ai/docs/xstate/transitions-and-choices/guarded-actions#the-choose-action - makes it so that the machine model is serializeable - todo: in the distant future i wonder if it might be tidier to have tracks be its own actor that just receives the same events that this machine does, that way it's just standalone instead of mixing up tracks with the implementation * use dispatch instead of useDispatch - decouples the implementation of the handler from the react component - makes the handler testable on its own if needed - makes the state machine testable without relying on external dependencies * decoupled remaining function calls * Fix lint error * Fix style lint * address xstate console warnings - .withConfig() is a function call that returns a new object every invocation so we need to wrap it in useMemo to keep it stable * Add optInDataSharing is false test * Fix lint --------- Co-authored-by: rjchow <me@rjchow.com>
2023-05-03 07:54:28 +00:00
const augmentedStateMachine = useMemo( () => {
// When adding extensibility, this is the place to manipulate the state machine definition.
return coreProfilerStateMachineDefinition.withConfig( {
actions: {
...coreProfilerMachineActions,
...actionOverrides,
Add core profiler "Welcome to Woo!" page (#37952) * Add core profiler - welcome to woo page * Add changelog * Update checkbox styles * Update copies * Add test * Add enable prop to window.wcTracks type * Add tracks * Add explat changelog * Fix import * Update default tracking value * Update copies * Fix test * using invoked promise instead of useState - take advantage of xstate's built ins for side effects instead of useEffect/hooks - discovered that error result wasn't really handled in original useEffect - use text labels instead of inline functions so that we can decouple the implementation from the machine model - todo: can move the invoked function out elsewhere and also tests if needed (not necessary here because it's a simple call) * use actions.choose instead of branching inside action - https://stately.ai/docs/xstate/transitions-and-choices/guarded-actions#the-choose-action - makes it so that the machine model is serializeable - todo: in the distant future i wonder if it might be tidier to have tracks be its own actor that just receives the same events that this machine does, that way it's just standalone instead of mixing up tracks with the implementation * use dispatch instead of useDispatch - decouples the implementation of the handler from the react component - makes the handler testable on its own if needed - makes the state machine testable without relying on external dependencies * decoupled remaining function calls * Fix lint error * Fix style lint * address xstate console warnings - .withConfig() is a function call that returns a new object every invocation so we need to wrap it in useMemo to keep it stable * Add optInDataSharing is false test * Fix lint --------- Co-authored-by: rjchow <me@rjchow.com>
2023-05-03 07:54:28 +00:00
},
services: {
...coreProfilerMachineServices,
...servicesOverrides,
},
Add core profiler "Welcome to Woo!" page (#37952) * Add core profiler - welcome to woo page * Add changelog * Update checkbox styles * Update copies * Add test * Add enable prop to window.wcTracks type * Add tracks * Add explat changelog * Fix import * Update default tracking value * Update copies * Fix test * using invoked promise instead of useState - take advantage of xstate's built ins for side effects instead of useEffect/hooks - discovered that error result wasn't really handled in original useEffect - use text labels instead of inline functions so that we can decouple the implementation from the machine model - todo: can move the invoked function out elsewhere and also tests if needed (not necessary here because it's a simple call) * use actions.choose instead of branching inside action - https://stately.ai/docs/xstate/transitions-and-choices/guarded-actions#the-choose-action - makes it so that the machine model is serializeable - todo: in the distant future i wonder if it might be tidier to have tracks be its own actor that just receives the same events that this machine does, that way it's just standalone instead of mixing up tracks with the implementation * use dispatch instead of useDispatch - decouples the implementation of the handler from the react component - makes the handler testable on its own if needed - makes the state machine testable without relying on external dependencies * decoupled remaining function calls * Fix lint error * Fix style lint * address xstate console warnings - .withConfig() is a function call that returns a new object every invocation so we need to wrap it in useMemo to keep it stable * Add optInDataSharing is false test * Fix lint --------- Co-authored-by: rjchow <me@rjchow.com>
2023-05-03 07:54:28 +00:00
} );
}, [ actionOverrides, servicesOverrides ] );
Add core profiler "Welcome to Woo!" page (#37952) * Add core profiler - welcome to woo page * Add changelog * Update checkbox styles * Update copies * Add test * Add enable prop to window.wcTracks type * Add tracks * Add explat changelog * Fix import * Update default tracking value * Update copies * Fix test * using invoked promise instead of useState - take advantage of xstate's built ins for side effects instead of useEffect/hooks - discovered that error result wasn't really handled in original useEffect - use text labels instead of inline functions so that we can decouple the implementation from the machine model - todo: can move the invoked function out elsewhere and also tests if needed (not necessary here because it's a simple call) * use actions.choose instead of branching inside action - https://stately.ai/docs/xstate/transitions-and-choices/guarded-actions#the-choose-action - makes it so that the machine model is serializeable - todo: in the distant future i wonder if it might be tidier to have tracks be its own actor that just receives the same events that this machine does, that way it's just standalone instead of mixing up tracks with the implementation * use dispatch instead of useDispatch - decouples the implementation of the handler from the react component - makes the handler testable on its own if needed - makes the state machine testable without relying on external dependencies * decoupled remaining function calls * Fix lint error * Fix style lint * address xstate console warnings - .withConfig() is a function call that returns a new object every invocation so we need to wrap it in useMemo to keep it stable * Add optInDataSharing is false test * Fix lint --------- Co-authored-by: rjchow <me@rjchow.com>
2023-05-03 07:54:28 +00:00
const [ state, send ] = useMachine( augmentedStateMachine, {
devTools: process.env.NODE_ENV === 'development',
} );
Add Business Location page to the core profiler (#38019) * Add core profiler - welcome to woo page * Update checkbox styles * Add tracks * Update default tracking value * Update copies * using invoked promise instead of useState - take advantage of xstate's built ins for side effects instead of useEffect/hooks - discovered that error result wasn't really handled in original useEffect - use text labels instead of inline functions so that we can decouple the implementation from the machine model - todo: can move the invoked function out elsewhere and also tests if needed (not necessary here because it's a simple call) * add: core profiler scaffolding using xstate * Add navigation and progress-bar components * fix css lint error * Update plugins/woocommerce-admin/client/core-profiler/components/navigation/woologo.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/components/progress-bar/progress-bar.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/components/navigation/navigation.tsx Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Remove var from __ function * Use woocommerce prefix for classnames * Fix css lint error * Fix broken tests * Add business location page * Remove unwanted changes from rebase * Remove unwanted changes from rebase * Redirect to Woo Home on exit * Add tracks * Fix js lint error * Add loader page * Support meta value from nested states * Use navigateTo * Add tests for getCountryStateOptions * Use Country type from navigation package * Rename useStages to getLoaderStageMeta * Add changelog * Move progress from 20 to 80 * Fix xstate warning * Fix broken pnpm lock * Fix eslint errors * Update plugins/woocommerce-admin/client/core-profiler/services/country.ts Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com> * Update plugins/woocommerce-admin/client/core-profiler/index.tsx Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com> * Save country to option * Fix jslint error * Update plugins/woocommerce-admin/client/core-profiler/services/country.ts Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Update plugins/woocommerce-admin/client/core-profiler/style.scss Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> * Fix eslint error * Use decodeEntities directly * Update comment for artificial 3 seconds wait * Disable Go to my store button when country is empty * Style for mobile devices * Style updates for the country dropdown * Fix js lint error * Update country dropdown border color * Style the loader * Fix css lint --------- Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com> Co-authored-by: rjchow <me@rjchow.com> Co-authored-by: RJ <27843274+rjchow@users.noreply.github.com>
2023-05-14 20:56:47 +00:00
const stateValue =
typeof state.value === 'object'
? Object.keys( state.value )[ 0 ]
: state.value;
const currentNodeMeta = state.meta[ `coreProfiler.${ stateValue }` ]
? state.meta[ `coreProfiler.${ stateValue }` ]
: undefined;
const navigationProgress = currentNodeMeta?.progress; // This value is defined in each state node's meta tag, we can assume it is 0-100
const CurrentComponent =
2023-06-03 01:08:33 +00:00
currentNodeMeta?.component ?? ( () => <ProfileSpinner /> ); // If no component is defined for the state then its a loading state
useEffect( () => {
document.body.classList.remove( 'woocommerce-admin-is-loading' );
document.body.classList.add( 'woocommerce-profile-wizard__body' );
document.body.classList.add( 'woocommerce-admin-full-screen' );
document.body.classList.add( 'is-wp-toolbar-disabled' );
return () => {
document.body.classList.remove(
'woocommerce-profile-wizard__body'
);
document.body.classList.remove( 'woocommerce-admin-full-screen' );
document.body.classList.remove( 'is-wp-toolbar-disabled' );
};
} );
return (
<>
<div
className={ `woocommerce-profile-wizard__container woocommerce-profile-wizard__step-${ state.value }` }
>
Add core profiler "Welcome to Woo!" page (#37952) * Add core profiler - welcome to woo page * Add changelog * Update checkbox styles * Update copies * Add test * Add enable prop to window.wcTracks type * Add tracks * Add explat changelog * Fix import * Update default tracking value * Update copies * Fix test * using invoked promise instead of useState - take advantage of xstate's built ins for side effects instead of useEffect/hooks - discovered that error result wasn't really handled in original useEffect - use text labels instead of inline functions so that we can decouple the implementation from the machine model - todo: can move the invoked function out elsewhere and also tests if needed (not necessary here because it's a simple call) * use actions.choose instead of branching inside action - https://stately.ai/docs/xstate/transitions-and-choices/guarded-actions#the-choose-action - makes it so that the machine model is serializeable - todo: in the distant future i wonder if it might be tidier to have tracks be its own actor that just receives the same events that this machine does, that way it's just standalone instead of mixing up tracks with the implementation * use dispatch instead of useDispatch - decouples the implementation of the handler from the react component - makes the handler testable on its own if needed - makes the state machine testable without relying on external dependencies * decoupled remaining function calls * Fix lint error * Fix style lint * address xstate console warnings - .withConfig() is a function call that returns a new object every invocation so we need to wrap it in useMemo to keep it stable * Add optInDataSharing is false test * Fix lint --------- Co-authored-by: rjchow <me@rjchow.com>
2023-05-03 07:54:28 +00:00
{
<CurrentComponent
navigationProgress={ navigationProgress }
sendEvent={ send }
context={ state.context }
/>
}
</div>
</>
);
};
export default CoreProfilerController;