Handle CYS ai wizard API failures (#40430)
* Add error notice * Handle api call loader errors * Add docs * Add changelog * Fix untranslated text
This commit is contained in:
parent
508b2d1615
commit
6d52afa5e9
|
@ -196,6 +196,17 @@ const spawnSaveDescriptionToOption = assign<
|
|||
),
|
||||
} );
|
||||
|
||||
const assignAPICallLoaderError = assign<
|
||||
designWithAiStateMachineContext,
|
||||
designWithAiStateMachineEvents
|
||||
>( {
|
||||
apiCallLoader: () => {
|
||||
return {
|
||||
hasErrors: true,
|
||||
};
|
||||
},
|
||||
} );
|
||||
|
||||
const logAIAPIRequestError = () => {
|
||||
// log AI API request error
|
||||
// eslint-disable-next-line no-console
|
||||
|
@ -275,6 +286,7 @@ export const actions = {
|
|||
assignHeader,
|
||||
assignFooter,
|
||||
assignHomepageTemplate,
|
||||
assignAPICallLoaderError,
|
||||
logAIAPIRequestError,
|
||||
updateQueryStep,
|
||||
recordTracksStepViewed,
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { Button } from '@wordpress/components';
|
||||
import { Button, Notice } from '@wordpress/components';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { ProgressBar } from '@woocommerce/components';
|
||||
import { useState } from '@wordpress/element';
|
||||
import { useState, createInterpolateElement } from '@wordpress/element';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
|
@ -59,6 +59,14 @@ export const ToneOfVoice = ( {
|
|||
? choices[ 0 ].key
|
||||
: context.toneOfVoice.choice
|
||||
);
|
||||
|
||||
const onContinue = () => {
|
||||
sendEvent( {
|
||||
type: 'TONE_OF_VOICE_COMPLETE',
|
||||
payload: sound,
|
||||
} );
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<ProgressBar
|
||||
|
@ -82,6 +90,33 @@ export const ToneOfVoice = ( {
|
|||
'woocommerce'
|
||||
) }
|
||||
</h1>
|
||||
{ context.apiCallLoader.hasErrors && (
|
||||
<Notice
|
||||
className="woocommerce-cys-design-with-ai__error-notice"
|
||||
isDismissible={ false }
|
||||
status="error"
|
||||
>
|
||||
{ createInterpolateElement(
|
||||
__(
|
||||
'Oops! We encountered a problem while generating your store. <retryButton/>',
|
||||
'woocommerce'
|
||||
),
|
||||
{
|
||||
retryButton: (
|
||||
<Button
|
||||
onClick={ onContinue }
|
||||
variant="tertiary"
|
||||
>
|
||||
{ __(
|
||||
'Please try again',
|
||||
'woocommerce'
|
||||
) }
|
||||
</Button>
|
||||
),
|
||||
}
|
||||
) }
|
||||
</Notice>
|
||||
) }
|
||||
<div className="choices">
|
||||
{ choices.map( ( { title, subtitle, key } ) => {
|
||||
return (
|
||||
|
@ -99,16 +134,7 @@ export const ToneOfVoice = ( {
|
|||
);
|
||||
} ) }
|
||||
</div>
|
||||
|
||||
<Button
|
||||
variant="primary"
|
||||
onClick={ () => {
|
||||
sendEvent( {
|
||||
type: 'TONE_OF_VOICE_COMPLETE',
|
||||
payload: sound,
|
||||
} );
|
||||
} }
|
||||
>
|
||||
<Button variant="primary" onClick={ onContinue }>
|
||||
{ __( 'Continue', 'woocommerce' ) }
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
@ -7,7 +7,7 @@ import { __experimentalRequestJetpackToken as requestJetpackToken } from '@wooco
|
|||
import apiFetch from '@wordpress/api-fetch';
|
||||
import { recordEvent } from '@woocommerce/tracks';
|
||||
import { OPTIONS_STORE_NAME } from '@woocommerce/data';
|
||||
import { Sender, assign, createMachine } from 'xstate';
|
||||
import { Sender, assign, createMachine, actions } from 'xstate';
|
||||
import { dispatch, resolveSelect } from '@wordpress/data';
|
||||
// @ts-ignore No types for this exist yet.
|
||||
import { store as coreStore } from '@wordpress/core-data';
|
||||
|
@ -26,6 +26,8 @@ import {
|
|||
} from '../assembler-hub/hooks/use-home-templates';
|
||||
import { HOMEPAGE_TEMPLATES } from '../data/homepageTemplates';
|
||||
|
||||
const { escalate } = actions;
|
||||
|
||||
const browserPopstateHandler =
|
||||
() => ( sendBack: Sender< { type: 'EXTERNAL_URL_UPDATE' } > ) => {
|
||||
const popstateHandler = () => {
|
||||
|
@ -163,7 +165,13 @@ export const queryAiEndpoint = createMachine(
|
|||
always: [
|
||||
{
|
||||
cond: ( context ) => context.retryCount >= 3,
|
||||
target: 'failed',
|
||||
target: 'querying',
|
||||
actions: [
|
||||
// Throw an error to be caught by the parent machine.
|
||||
escalate( () => ( {
|
||||
data: 'Max retries exceeded',
|
||||
} ) ),
|
||||
],
|
||||
},
|
||||
{
|
||||
target: 'querying',
|
||||
|
@ -173,12 +181,6 @@ export const queryAiEndpoint = createMachine(
|
|||
},
|
||||
],
|
||||
},
|
||||
failed: {
|
||||
type: 'final',
|
||||
data: {
|
||||
result: 'failed',
|
||||
},
|
||||
},
|
||||
success: {
|
||||
type: 'final',
|
||||
data: ( context ) => {
|
||||
|
|
|
@ -75,10 +75,16 @@ export const designWithAiStateMachineDefinition = createMachine(
|
|||
choice: '',
|
||||
},
|
||||
aiSuggestions: {
|
||||
defaultColorPalette: {} as ColorPaletteResponse,
|
||||
fontPairing: '' as FontPairing[ 'pair_name' ],
|
||||
// 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' ],
|
||||
homepageTemplate: '' as HomepageTemplate[ 'homepage_template' ],
|
||||
},
|
||||
apiCallLoader: {
|
||||
hasErrors: false,
|
||||
},
|
||||
},
|
||||
initial: 'navigate',
|
||||
states: {
|
||||
|
@ -307,6 +313,10 @@ export const designWithAiStateMachineDefinition = createMachine(
|
|||
],
|
||||
target: 'success',
|
||||
},
|
||||
// If there's an error we don't want to block the user from proceeding.
|
||||
onError: {
|
||||
target: 'success',
|
||||
},
|
||||
},
|
||||
},
|
||||
success: { type: 'final' },
|
||||
|
@ -338,6 +348,10 @@ export const designWithAiStateMachineDefinition = createMachine(
|
|||
],
|
||||
target: 'success',
|
||||
},
|
||||
// If there's an error we don't want to block the user from proceeding.
|
||||
onError: {
|
||||
target: 'success',
|
||||
},
|
||||
},
|
||||
},
|
||||
success: { type: 'final' },
|
||||
|
@ -369,6 +383,12 @@ export const designWithAiStateMachineDefinition = createMachine(
|
|||
],
|
||||
target: 'success',
|
||||
},
|
||||
onError: {
|
||||
actions: [
|
||||
'assignAPICallLoaderError',
|
||||
],
|
||||
target: '#toneOfVoice',
|
||||
},
|
||||
},
|
||||
},
|
||||
success: { type: 'final' },
|
||||
|
@ -384,8 +404,10 @@ export const designWithAiStateMachineDefinition = createMachine(
|
|||
target: 'success',
|
||||
},
|
||||
onError: {
|
||||
// TODO: handle error
|
||||
target: 'success',
|
||||
actions: [
|
||||
'assignAPICallLoaderError',
|
||||
],
|
||||
target: '#toneOfVoice',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -408,16 +430,16 @@ export const designWithAiStateMachineDefinition = createMachine(
|
|||
target: 'done',
|
||||
},
|
||||
onError: {
|
||||
target: 'failed',
|
||||
actions: [
|
||||
'assignAPICallLoaderError',
|
||||
],
|
||||
target: '#toneOfVoice',
|
||||
},
|
||||
},
|
||||
},
|
||||
done: {
|
||||
type: 'final',
|
||||
},
|
||||
failed: {
|
||||
type: 'final', // If there's an error we should not block the user from proceeding. They'll just not see the AI suggestions, but that's better than being stuck
|
||||
},
|
||||
},
|
||||
},
|
||||
saveAiResponse: {
|
||||
|
|
|
@ -30,6 +30,9 @@ export type designWithAiStateMachineContext = {
|
|||
fontPairing: FontPairing[ 'pair_name' ];
|
||||
homepageTemplate: HomepageTemplate[ 'homepage_template' ];
|
||||
};
|
||||
apiCallLoader: {
|
||||
hasErrors: boolean;
|
||||
};
|
||||
// If we require more data from options, previously provided core profiler details,
|
||||
// we can retrieve them in preBusinessInfoDescription and then assign them here
|
||||
spawnSaveDescriptionToOptionRef?: ReturnType< typeof spawn >;
|
||||
|
|
|
@ -116,3 +116,25 @@ body.woocommerce-customize-store.js.is-fullscreen-mode {
|
|||
gap: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.woocommerce-cys-design-with-ai__error-notice.is-error {
|
||||
background: #fce2e4;
|
||||
padding: $gap-small;
|
||||
// gap: 12px;
|
||||
font-size: 13px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 24px;
|
||||
color: $gray-900;
|
||||
margin: 0 0 60px;
|
||||
width: 615px;
|
||||
|
||||
.components-notice__content {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.components-button {
|
||||
padding: 0;
|
||||
height: initial;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Significance: minor
|
||||
Type: update
|
||||
|
||||
Handle CYS ai wizard API failures
|
Loading…
Reference in New Issue