2023-08-29 06:00:54 +00:00
|
|
|
/**
|
|
|
|
* External dependencies
|
|
|
|
*/
|
2023-09-06 06:21:09 +00:00
|
|
|
import { createMachine, sendParent } from 'xstate';
|
2023-09-12 06:32:50 +00:00
|
|
|
import { getQuery } from '@woocommerce/navigation';
|
2023-08-29 06:00:54 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Internal dependencies
|
|
|
|
*/
|
|
|
|
import {
|
|
|
|
designWithAiStateMachineContext,
|
|
|
|
designWithAiStateMachineEvents,
|
2023-09-20 04:26:15 +00:00
|
|
|
FontPairing,
|
2023-09-20 07:27:08 +00:00
|
|
|
ColorPaletteResponse,
|
2023-09-25 10:30:31 +00:00
|
|
|
HomepageTemplate,
|
2023-08-29 06:00:54 +00:00
|
|
|
} from './types';
|
|
|
|
import {
|
|
|
|
BusinessInfoDescription,
|
|
|
|
LookAndFeel,
|
|
|
|
ToneOfVoice,
|
|
|
|
ApiCallLoader,
|
2023-10-31 13:09:21 +00:00
|
|
|
AssembleHubLoader,
|
2023-08-29 06:00:54 +00:00
|
|
|
} from './pages';
|
|
|
|
import { actions } from './actions';
|
2023-09-06 06:21:09 +00:00
|
|
|
import { services } from './services';
|
2023-10-12 06:35:46 +00:00
|
|
|
import { defaultColorPalette } from './prompts';
|
2023-09-12 06:32:50 +00:00
|
|
|
|
|
|
|
export const hasStepInUrl = (
|
|
|
|
_ctx: unknown,
|
|
|
|
_evt: unknown,
|
|
|
|
{ cond }: { cond: unknown }
|
|
|
|
) => {
|
|
|
|
const { path = '' } = getQuery() as { path: string };
|
|
|
|
const pathFragments = path.split( '/' );
|
|
|
|
return (
|
|
|
|
pathFragments[ 3 ] === // [0] '', [1] 'customize-store', [2] cys step slug [3] design-with-ai step slug
|
|
|
|
( cond as { step: string | undefined } ).step
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2023-12-06 12:49:28 +00:00
|
|
|
export const isAiOnline = ( _ctx: designWithAiStateMachineContext ) => {
|
|
|
|
return _ctx.aiOnline;
|
|
|
|
};
|
|
|
|
|
2023-08-29 06:00:54 +00:00
|
|
|
export const designWithAiStateMachineDefinition = createMachine(
|
|
|
|
{
|
|
|
|
id: 'designWithAi',
|
|
|
|
predictableActionArguments: true,
|
|
|
|
preserveActionOrder: true,
|
|
|
|
schema: {
|
|
|
|
context: {} as designWithAiStateMachineContext,
|
|
|
|
events: {} as designWithAiStateMachineEvents,
|
|
|
|
},
|
2023-09-12 06:32:50 +00:00
|
|
|
invoke: {
|
|
|
|
src: 'browserPopstateHandler',
|
|
|
|
},
|
|
|
|
on: {
|
|
|
|
EXTERNAL_URL_UPDATE: {
|
|
|
|
target: 'navigate',
|
|
|
|
},
|
|
|
|
AI_WIZARD_CLOSED_BEFORE_COMPLETION: {
|
2023-09-15 04:48:12 +00:00
|
|
|
actions: [
|
|
|
|
sendParent( ( _context, event ) => event ),
|
|
|
|
'recordTracksStepClosed',
|
|
|
|
],
|
2023-09-12 06:32:50 +00:00
|
|
|
},
|
|
|
|
},
|
2023-08-29 06:00:54 +00:00
|
|
|
context: {
|
2023-11-09 01:32:47 +00:00
|
|
|
startLoadingTime: null,
|
2023-08-29 06:00:54 +00:00
|
|
|
businessInfoDescription: {
|
|
|
|
descriptionText: '',
|
|
|
|
},
|
|
|
|
lookAndFeel: {
|
|
|
|
choice: '',
|
|
|
|
},
|
|
|
|
toneOfVoice: {
|
|
|
|
choice: '',
|
|
|
|
},
|
2023-09-19 08:41:52 +00:00
|
|
|
aiSuggestions: {
|
2023-09-28 03:15:38 +00:00
|
|
|
// Default color palette, font pairing are used as fallbacks when the AI endpoint fails.
|
|
|
|
defaultColorPalette: {
|
|
|
|
default: 'Ancient Bronze',
|
|
|
|
} as ColorPaletteResponse,
|
|
|
|
fontPairing: 'Rubik + Inter' as FontPairing[ 'pair_name' ],
|
2023-09-30 02:39:34 +00:00
|
|
|
homepageTemplate:
|
|
|
|
'template1' as HomepageTemplate[ 'homepage_template' ],
|
2023-09-19 08:41:52 +00:00
|
|
|
},
|
2023-09-28 03:15:38 +00:00
|
|
|
apiCallLoader: {
|
|
|
|
hasErrors: false,
|
|
|
|
},
|
2023-12-06 12:49:28 +00:00
|
|
|
aiOnline: true,
|
2024-06-05 14:54:29 +00:00
|
|
|
isBlockTheme: false,
|
2023-08-29 06:00:54 +00:00
|
|
|
},
|
2023-09-12 06:32:50 +00:00
|
|
|
initial: 'navigate',
|
2023-08-29 06:00:54 +00:00
|
|
|
states: {
|
2023-09-12 06:32:50 +00:00
|
|
|
navigate: {
|
|
|
|
always: [
|
|
|
|
{
|
|
|
|
target: 'businessInfoDescription',
|
|
|
|
cond: {
|
|
|
|
type: 'hasStepInUrl',
|
|
|
|
step: 'business-info-description',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
target: 'lookAndFeel',
|
|
|
|
cond: {
|
|
|
|
type: 'hasStepInUrl',
|
|
|
|
step: 'look-and-feel',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
target: 'toneOfVoice',
|
|
|
|
cond: {
|
|
|
|
type: 'hasStepInUrl',
|
|
|
|
step: 'tone-of-voice',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
target: 'apiCallLoader',
|
|
|
|
cond: {
|
|
|
|
type: 'hasStepInUrl',
|
|
|
|
step: 'api-call-loader',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
target: 'businessInfoDescription',
|
|
|
|
},
|
|
|
|
],
|
|
|
|
},
|
2023-08-29 06:00:54 +00:00
|
|
|
businessInfoDescription: {
|
|
|
|
id: 'businessInfoDescription',
|
|
|
|
initial: 'preBusinessInfoDescription',
|
|
|
|
states: {
|
|
|
|
preBusinessInfoDescription: {
|
|
|
|
// if we need to prefetch options, other settings previously populated from core profiler, do it here
|
|
|
|
always: {
|
|
|
|
target: 'businessInfoDescription',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
businessInfoDescription: {
|
|
|
|
meta: {
|
|
|
|
component: BusinessInfoDescription,
|
|
|
|
},
|
2023-09-15 04:48:12 +00:00
|
|
|
entry: [
|
|
|
|
{
|
|
|
|
type: 'recordTracksStepViewed',
|
|
|
|
step: 'business_info_description',
|
|
|
|
},
|
|
|
|
],
|
2023-08-29 06:00:54 +00:00
|
|
|
on: {
|
|
|
|
BUSINESS_INFO_DESCRIPTION_COMPLETE: {
|
2023-09-22 12:43:42 +00:00
|
|
|
actions: [
|
|
|
|
'assignBusinessInfoDescription',
|
|
|
|
'spawnSaveDescriptionToOption',
|
2023-09-15 04:48:12 +00:00
|
|
|
{
|
|
|
|
type: 'recordTracksStepCompleted',
|
|
|
|
step: 'business_info_description',
|
|
|
|
},
|
|
|
|
],
|
2023-11-17 11:40:43 +00:00
|
|
|
target: 'postBusinessInfoDescription',
|
2023-09-06 06:21:09 +00:00
|
|
|
},
|
2023-08-29 06:00:54 +00:00
|
|
|
},
|
|
|
|
},
|
2023-11-17 11:40:43 +00:00
|
|
|
postBusinessInfoDescription: {
|
|
|
|
always: {
|
|
|
|
target: '#lookAndFeel',
|
|
|
|
},
|
|
|
|
},
|
2023-08-29 06:00:54 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
lookAndFeel: {
|
|
|
|
id: 'lookAndFeel',
|
|
|
|
initial: 'preLookAndFeel',
|
|
|
|
states: {
|
|
|
|
preLookAndFeel: {
|
|
|
|
always: {
|
|
|
|
target: 'lookAndFeel',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
lookAndFeel: {
|
|
|
|
meta: {
|
|
|
|
component: LookAndFeel,
|
|
|
|
},
|
2023-09-12 06:32:50 +00:00
|
|
|
entry: [
|
|
|
|
{
|
|
|
|
type: 'updateQueryStep',
|
|
|
|
step: 'look-and-feel',
|
|
|
|
},
|
2023-09-15 04:48:12 +00:00
|
|
|
{
|
|
|
|
type: 'recordTracksStepViewed',
|
|
|
|
step: 'look_and_feel',
|
|
|
|
},
|
2023-09-12 06:32:50 +00:00
|
|
|
],
|
2023-08-29 06:00:54 +00:00
|
|
|
on: {
|
|
|
|
LOOK_AND_FEEL_COMPLETE: {
|
2023-09-15 04:48:12 +00:00
|
|
|
actions: [
|
|
|
|
{
|
|
|
|
type: 'recordTracksStepCompleted',
|
|
|
|
step: 'look_and_feel',
|
|
|
|
},
|
|
|
|
'assignLookAndFeel',
|
|
|
|
],
|
2023-08-29 06:00:54 +00:00
|
|
|
target: 'postLookAndFeel',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
postLookAndFeel: {
|
|
|
|
always: {
|
|
|
|
target: '#toneOfVoice',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
toneOfVoice: {
|
|
|
|
id: 'toneOfVoice',
|
|
|
|
initial: 'preToneOfVoice',
|
|
|
|
states: {
|
|
|
|
preToneOfVoice: {
|
|
|
|
always: {
|
|
|
|
target: 'toneOfVoice',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
toneOfVoice: {
|
|
|
|
meta: {
|
|
|
|
component: ToneOfVoice,
|
|
|
|
},
|
2023-09-12 06:32:50 +00:00
|
|
|
entry: [
|
|
|
|
{
|
|
|
|
type: 'updateQueryStep',
|
|
|
|
step: 'tone-of-voice',
|
|
|
|
},
|
2023-09-15 04:48:12 +00:00
|
|
|
{
|
|
|
|
type: 'recordTracksStepViewed',
|
|
|
|
step: 'tone_of_voice',
|
|
|
|
},
|
2023-09-12 06:32:50 +00:00
|
|
|
],
|
2023-08-29 06:00:54 +00:00
|
|
|
on: {
|
|
|
|
TONE_OF_VOICE_COMPLETE: {
|
2023-09-15 04:48:12 +00:00
|
|
|
actions: [
|
|
|
|
'assignToneOfVoice',
|
|
|
|
{
|
|
|
|
type: 'recordTracksStepCompleted',
|
|
|
|
step: 'tone_of_voice',
|
|
|
|
},
|
|
|
|
],
|
2023-08-29 06:00:54 +00:00
|
|
|
target: 'postToneOfVoice',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
postToneOfVoice: {
|
|
|
|
always: {
|
|
|
|
target: '#apiCallLoader',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
apiCallLoader: {
|
|
|
|
id: 'apiCallLoader',
|
|
|
|
initial: 'preApiCallLoader',
|
|
|
|
states: {
|
|
|
|
preApiCallLoader: {
|
|
|
|
always: {
|
|
|
|
target: 'apiCallLoader',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
apiCallLoader: {
|
|
|
|
meta: {
|
|
|
|
component: ApiCallLoader,
|
|
|
|
},
|
2023-09-12 06:32:50 +00:00
|
|
|
entry: [
|
|
|
|
{
|
|
|
|
type: 'updateQueryStep',
|
|
|
|
step: 'api-call-loader',
|
|
|
|
},
|
2023-11-09 01:32:47 +00:00
|
|
|
'assignStartLoadingTime',
|
2023-09-12 06:32:50 +00:00
|
|
|
],
|
2023-09-19 08:41:52 +00:00
|
|
|
type: 'parallel',
|
|
|
|
states: {
|
|
|
|
chooseColorPairing: {
|
2023-12-06 12:49:28 +00:00
|
|
|
initial: 'executeOrSkip',
|
2023-09-21 05:30:57 +00:00
|
|
|
states: {
|
2023-12-06 12:49:28 +00:00
|
|
|
executeOrSkip: {
|
|
|
|
always: [
|
|
|
|
{
|
|
|
|
target: 'pending',
|
|
|
|
cond: 'isAiOnline',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
target: 'success',
|
|
|
|
},
|
|
|
|
],
|
|
|
|
},
|
2023-09-21 05:30:57 +00:00
|
|
|
pending: {
|
|
|
|
invoke: {
|
|
|
|
src: 'queryAiEndpoint',
|
|
|
|
data: ( context ) => {
|
|
|
|
return {
|
|
|
|
...defaultColorPalette,
|
|
|
|
prompt: defaultColorPalette.prompt(
|
|
|
|
context
|
|
|
|
.businessInfoDescription
|
|
|
|
.descriptionText,
|
|
|
|
context.lookAndFeel
|
|
|
|
.choice,
|
|
|
|
context.toneOfVoice
|
|
|
|
.choice
|
|
|
|
),
|
|
|
|
};
|
|
|
|
},
|
|
|
|
onDone: {
|
|
|
|
actions: [
|
|
|
|
'assignDefaultColorPalette',
|
|
|
|
],
|
|
|
|
target: 'success',
|
|
|
|
},
|
2023-09-28 03:15:38 +00:00
|
|
|
// If there's an error we don't want to block the user from proceeding.
|
|
|
|
onError: {
|
|
|
|
target: 'success',
|
|
|
|
},
|
2023-09-21 05:30:57 +00:00
|
|
|
},
|
2023-09-19 08:41:52 +00:00
|
|
|
},
|
2023-09-21 05:30:57 +00:00
|
|
|
success: { type: 'final' },
|
2023-09-19 08:41:52 +00:00
|
|
|
},
|
|
|
|
},
|
2023-09-20 04:26:15 +00:00
|
|
|
chooseFontPairing: {
|
2023-12-20 14:41:19 +00:00
|
|
|
initial: 'pending',
|
2023-10-13 01:53:20 +00:00
|
|
|
states: {
|
|
|
|
pending: {
|
|
|
|
entry: [ 'assignFontPairing' ],
|
|
|
|
always: {
|
|
|
|
target: 'success',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
success: { type: 'final' },
|
|
|
|
},
|
2023-09-20 04:26:15 +00:00
|
|
|
},
|
2023-09-21 05:30:57 +00:00
|
|
|
updateStorePatterns: {
|
2023-12-06 12:49:28 +00:00
|
|
|
initial: 'executeOrSkip',
|
2023-09-21 05:30:57 +00:00
|
|
|
states: {
|
2023-12-06 12:49:28 +00:00
|
|
|
executeOrSkip: {
|
|
|
|
always: [
|
|
|
|
{
|
|
|
|
target: 'pending',
|
|
|
|
cond: 'isAiOnline',
|
|
|
|
},
|
|
|
|
{
|
2023-12-07 08:42:16 +00:00
|
|
|
target: 'resetPatternsAndProducts',
|
2023-12-06 12:49:28 +00:00
|
|
|
},
|
|
|
|
],
|
|
|
|
},
|
2023-09-21 05:30:57 +00:00
|
|
|
pending: {
|
|
|
|
invoke: {
|
|
|
|
src: 'updateStorePatterns',
|
|
|
|
onDone: {
|
|
|
|
target: 'success',
|
|
|
|
},
|
|
|
|
onError: {
|
2023-09-28 03:15:38 +00:00
|
|
|
actions: [
|
|
|
|
'assignAPICallLoaderError',
|
|
|
|
],
|
|
|
|
target: '#toneOfVoice',
|
2023-09-21 05:30:57 +00:00
|
|
|
},
|
|
|
|
},
|
2023-09-21 01:49:00 +00:00
|
|
|
},
|
2023-12-07 08:42:16 +00:00
|
|
|
resetPatternsAndProducts: {
|
2023-12-06 12:49:28 +00:00
|
|
|
invoke: {
|
2023-12-07 08:42:16 +00:00
|
|
|
src: 'resetPatternsAndProducts',
|
2023-12-06 12:49:28 +00:00
|
|
|
onDone: {
|
|
|
|
target: 'success',
|
|
|
|
},
|
|
|
|
onError: {
|
|
|
|
actions: [
|
|
|
|
'assignAPICallLoaderError',
|
|
|
|
],
|
|
|
|
target: '#toneOfVoice',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2023-09-21 05:30:57 +00:00
|
|
|
success: { type: 'final' },
|
2023-09-21 01:49:00 +00:00
|
|
|
},
|
|
|
|
},
|
2023-10-03 07:41:48 +00:00
|
|
|
installAndActivateTheme: {
|
|
|
|
initial: 'pending',
|
|
|
|
states: {
|
|
|
|
pending: {
|
|
|
|
invoke: {
|
|
|
|
src: 'installAndActivateTheme',
|
|
|
|
onDone: {
|
|
|
|
target: 'success',
|
|
|
|
},
|
|
|
|
onError: {
|
|
|
|
actions: [
|
|
|
|
'assignAPICallLoaderError',
|
|
|
|
],
|
|
|
|
target: '#toneOfVoice',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
success: { type: 'final' },
|
|
|
|
},
|
|
|
|
},
|
2023-09-19 08:41:52 +00:00
|
|
|
},
|
2023-09-21 05:30:57 +00:00
|
|
|
onDone: 'postApiCallLoader',
|
|
|
|
},
|
|
|
|
postApiCallLoader: {
|
2023-09-22 12:43:42 +00:00
|
|
|
type: 'parallel',
|
|
|
|
states: {
|
|
|
|
assembleSite: {
|
|
|
|
initial: 'pending',
|
|
|
|
states: {
|
|
|
|
pending: {
|
|
|
|
invoke: {
|
|
|
|
src: 'assembleSite',
|
|
|
|
onDone: {
|
|
|
|
target: 'done',
|
|
|
|
},
|
|
|
|
onError: {
|
2023-09-28 03:15:38 +00:00
|
|
|
actions: [
|
|
|
|
'assignAPICallLoaderError',
|
|
|
|
],
|
|
|
|
target: '#toneOfVoice',
|
2023-09-22 12:43:42 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
done: {
|
|
|
|
type: 'final',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
saveAiResponse: {
|
|
|
|
initial: 'pending',
|
|
|
|
states: {
|
|
|
|
pending: {
|
|
|
|
invoke: {
|
|
|
|
src: 'saveAiResponseToOption',
|
|
|
|
onDone: {
|
|
|
|
target: 'done',
|
|
|
|
},
|
|
|
|
onError: {
|
|
|
|
target: 'failed',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
done: {
|
|
|
|
type: 'final',
|
|
|
|
},
|
|
|
|
failed: {
|
|
|
|
type: 'final',
|
|
|
|
},
|
|
|
|
},
|
2023-09-21 05:30:57 +00:00
|
|
|
},
|
2024-06-10 13:00:33 +00:00
|
|
|
installPatterns: {
|
|
|
|
initial: 'pending',
|
|
|
|
states: {
|
|
|
|
pending: {
|
|
|
|
invoke: {
|
|
|
|
src: 'installPatterns',
|
|
|
|
onDone: {
|
|
|
|
target: 'success',
|
|
|
|
},
|
|
|
|
onError: {
|
|
|
|
target: 'success',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
success: {
|
|
|
|
type: 'final',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2023-09-21 05:30:57 +00:00
|
|
|
},
|
2023-09-22 12:43:42 +00:00
|
|
|
onDone: {
|
2023-10-31 13:09:21 +00:00
|
|
|
target: '#designWithAi.showAssembleHub',
|
2023-09-22 12:43:42 +00:00
|
|
|
},
|
2023-08-29 06:00:54 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2023-10-31 13:09:21 +00:00
|
|
|
showAssembleHub: {
|
|
|
|
meta: {
|
|
|
|
component: AssembleHubLoader,
|
|
|
|
},
|
|
|
|
entry: [ 'redirectToAssemblerHub' ],
|
|
|
|
type: 'final',
|
|
|
|
},
|
2023-08-29 06:00:54 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
actions,
|
2023-09-06 06:21:09 +00:00
|
|
|
services,
|
2023-09-12 06:32:50 +00:00
|
|
|
guards: {
|
|
|
|
hasStepInUrl,
|
2023-12-06 12:49:28 +00:00
|
|
|
isAiOnline,
|
2023-09-12 06:32:50 +00:00
|
|
|
},
|
2023-08-29 06:00:54 +00:00
|
|
|
}
|
|
|
|
);
|