CYS - Core: install font when user clicks opt-in (#45580)

* CYS - Core: install font when user clicks opt-in

* remove debugger

* CYS - Core: fix wp-admin page visible when click on start designing

* Add changefile(s) from automation for the following project(s): woocommerce

* use sendEvent instead of redirect

* Add changefile(s) from automation for the following project(s): woocommerce

* not show wp-admin after the click on the dialog button

* use sendEventToIntroMachine

* fix font installation

* fix eslint error

* fix install font phase when the iframe is not loaded

* remove not necessary async

---------

Co-authored-by: github-actions <github-actions@github.com>
This commit is contained in:
Luigi Teschio 2024-03-18 16:49:41 +01:00 committed by GitHub
parent d69ceaa0a1
commit f9c0d406ae
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 166 additions and 55 deletions

View File

@ -9,7 +9,7 @@ import {
useContext,
useState,
} from '@wordpress/element';
import { dispatch, useSelect } from '@wordpress/data';
import { useSelect } from '@wordpress/data';
import { Link } from '@woocommerce/components';
import { OPTIONS_STORE_NAME } from '@woocommerce/data';
import { recordEvent } from '@woocommerce/tracks';
@ -24,8 +24,9 @@ import { ADMIN_URL } from '~/utils/admin-settings';
import { FontPairing } from './global-styles';
import { CustomizeStoreContext } from '..';
import { FlowType } from '~/customize-store/types';
import { isIframe, sendMessageToParent } from '~/customize-store/utils';
export const SidebarNavigationScreenTypography = () => {
const { context } = useContext( CustomizeStoreContext );
const { context, sendEvent } = useContext( CustomizeStoreContext );
const aiOnline = context.flowType === FlowType.AIOnline;
const isFontLibraryAvailable = context.isFontLibraryAvailable;
@ -67,7 +68,7 @@ export const SidebarNavigationScreenTypography = () => {
upgradeNotice = '';
}
const OptIn = () => {
const optIn = () => {
recordEvent(
'customize_your_store_assembler_hub_opt_in_usage_tracking'
);
@ -200,19 +201,17 @@ export const SidebarNavigationScreenTypography = () => {
{ __( 'Cancel', 'woocommerce' ) }
</Button>
<Button
onClick={ async () => {
await dispatch(
OPTIONS_STORE_NAME
).updateOptions( {
woocommerce_allow_tracking:
OptInDataSharing
? 'yes'
: 'no',
} );
OptIn();
closeModal();
window.location.href = `${ ADMIN_URL }admin.php?page=wc-admin&path=%2Fcustomize-store%2Fassembler-hub`;
onClick={ () => {
optIn();
if ( isIframe( window ) ) {
sendMessageToParent( {
type: 'INSTALL_FONTS',
} );
} else {
sendEvent(
'INSTALL_FONTS'
);
}
} }
variant="primary"
disabled={ ! OptInDataSharing }

View File

@ -15,7 +15,7 @@ import {
} from '../types';
import { designWithNoAiStateMachineDefinition } from './state-machine';
import { findComponentMeta } from '~/utils/xstate/find-component';
import { AssembleHubLoader } from '../design-with-ai/pages';
import { AssembleHubLoader } from './pages/ApiCallLoader';
export type DesignWithoutAiComponent = typeof AssembleHubLoader;
export type DesignWithoutAiComponentMeta = {
@ -30,15 +30,18 @@ export const DesignWithNoAiController = ( {
sendEventToParent?: Sender< customizeStoreStateMachineEvents >;
parentContext?: customizeStoreStateMachineContext;
} ) => {
const [ , , service ] = useMachine( designWithNoAiStateMachineDefinition, {
devTools: process.env.NODE_ENV === 'development',
parent: parentMachine,
context: {
...designWithNoAiStateMachineDefinition.context,
isFontLibraryAvailable:
parentContext?.isFontLibraryAvailable ?? false,
},
} );
const [ , send, service ] = useMachine(
designWithNoAiStateMachineDefinition,
{
devTools: process.env.NODE_ENV === 'development',
parent: parentMachine,
context: {
...designWithNoAiStateMachineDefinition.context,
isFontLibraryAvailable:
parentContext?.isFontLibraryAvailable ?? false,
},
}
);
// eslint-disable-next-line react-hooks/exhaustive-deps -- false positive due to function name match, this isn't from react std lib
const currentNodeMeta = useSelector( service, ( currentState ) =>
@ -59,7 +62,11 @@ export const DesignWithNoAiController = ( {
return (
<>
<div className={ `woocommerce-design-without-ai__container` }>
{ CurrentComponent ? <CurrentComponent /> : <div /> }
{ CurrentComponent ? (
<CurrentComponent sendEvent={ send } />
) : (
<div />
) }
</div>
</>
);

View File

@ -17,6 +17,7 @@ import {
createAugmentedSteps,
onIframeLoad,
} from '~/customize-store/utils';
import { DesignWithoutAIStateMachineEvents } from '../state-machine';
const loaderSteps = [
{
@ -103,11 +104,21 @@ export const ApiCallLoader = () => {
);
};
const AssemblerHub = () => {
type SendEventFn = ( event: DesignWithoutAIStateMachineEvents ) => void;
const AssemblerHub = ( { sendEvent }: { sendEvent: SendEventFn } ) => {
const assemblerUrl = getNewPath( {}, '/customize-store/assembler-hub', {} );
const iframe = useRef< HTMLIFrameElement >( null );
const [ isVisible, setIsVisible ] = useState( false );
useEffect( () => {
window.addEventListener( 'message', ( event ) => {
if ( event.data?.type === 'INSTALL_FONTS' ) {
sendEvent( { type: 'INSTALL_FONTS' } );
}
} );
}, [ sendEvent ] );
return (
<iframe
ref={ iframe }
@ -127,7 +138,11 @@ const AssemblerHub = () => {
);
};
export const AssembleHubLoader = () => {
export const AssembleHubLoader = ( {
sendEvent,
}: {
sendEvent: SendEventFn;
} ) => {
// Show the last two steps of the loader so that the last frame is the shortest time possible
const augmentedSteps = createAugmentedSteps( loaderSteps.slice( -2 ), 10 );
@ -160,7 +175,7 @@ export const AssembleHubLoader = () => {
progress={ progress || 0 }
/>
</Loader>
<AssemblerHub />
<AssemblerHub sendEvent={ sendEvent } />
</>
);
};

View File

@ -235,6 +235,17 @@ const createProducts = async () => {
}
};
export const enableTracking = async () => {
try {
await dispatch( OPTIONS_STORE_NAME ).updateOptions( {
woocommerce_allow_tracking: 'yes',
} );
window.wcTracks.isEnabled = true;
} catch ( error ) {
throw error;
}
};
export const services = {
assembleSite,
browserPopstateHandler,
@ -242,4 +253,5 @@ export const services = {
createProducts,
installFontFamilies,
updateGlobalStylesWithDefaultValues,
enableTracking,
};

View File

@ -29,8 +29,49 @@ export const hasStepInUrl = (
);
};
export const hasFontInstallInUrl = () => {
const { path = '' } = getQuery() as { path: string };
const pathFragments = path.split( '/' );
return (
pathFragments[ 2 ] === 'design' &&
pathFragments[ 3 ] === 'install-fonts'
);
};
const installFontFamiliesState = {
initial: 'checkFontLibrary',
states: {
checkFontLibrary: {
always: [
{
cond: {
type: 'isFontLibraryAvailable',
},
target: 'pending',
},
{ target: 'success' },
],
},
pending: {
invoke: {
src: 'installFontFamilies',
onDone: {
target: 'success',
},
onError: {
actions: 'redirectToIntroWithError',
},
},
},
success: {
type: 'final',
},
},
};
export type DesignWithoutAIStateMachineEvents =
| { type: 'EXTERNAL_URL_UPDATE' }
| { type: 'INSTALL_FONTS' }
| { type: 'NO_AI_FLOW_ERROR'; payload: { hasError: boolean } };
export const designWithNoAiStateMachineDefinition = createMachine(
@ -49,6 +90,9 @@ export const designWithNoAiStateMachineDefinition = createMachine(
EXTERNAL_URL_UPDATE: {
target: 'navigate',
},
INSTALL_FONTS: {
target: 'installFontFamilies',
},
},
context: {
startLoadingTime: null,
@ -62,6 +106,13 @@ export const designWithNoAiStateMachineDefinition = createMachine(
states: {
navigate: {
always: [
{
cond: {
type: 'hasFontInstallInUrl',
step: 'design',
},
target: 'installFontFamilies',
},
{
cond: {
type: 'hasStepInUrl',
@ -71,6 +122,31 @@ export const designWithNoAiStateMachineDefinition = createMachine(
},
],
},
installFontFamilies: {
meta: {
component: ApiCallLoader,
},
initial: 'enableTracking',
states: {
enableTracking: {
invoke: {
src: 'enableTracking',
onDone: {
target: 'checkFontLibrary',
},
},
},
checkFontLibrary:
installFontFamiliesState.states.checkFontLibrary,
pending: installFontFamiliesState.states.pending,
success: {
type: 'final',
},
},
onDone: {
target: '#designWithoutAI.showAssembleHub',
},
},
preAssembleSite: {
initial: 'preApiCallLoader',
id: 'preAssembleSite',
@ -141,31 +217,13 @@ export const designWithNoAiStateMachineDefinition = createMachine(
},
},
installFontFamilies: {
initial: 'checkFontLibrary',
initial: installFontFamiliesState.initial,
states: {
checkFontLibrary: {
always: [
{
cond: {
type: 'isFontLibraryAvailable',
},
target: 'pending',
},
{ target: 'success' },
],
},
pending: {
invoke: {
src: 'installFontFamilies',
onDone: {
target: 'success',
},
onError: {
actions:
'redirectToIntroWithError',
},
},
},
checkFontLibrary:
installFontFamiliesState.states
.checkFontLibrary,
pending:
installFontFamiliesState.states.pending,
success: {
type: 'final',
},
@ -184,7 +242,6 @@ export const designWithNoAiStateMachineDefinition = createMachine(
component: AssembleHubLoader,
},
entry: [ 'redirectToAssemblerHub' ],
type: 'final',
},
},
},
@ -194,6 +251,7 @@ export const designWithNoAiStateMachineDefinition = createMachine(
guards: {
hasStepInUrl,
isFontLibraryAvailable,
hasFontInstallInUrl,
},
}
);

View File

@ -57,6 +57,7 @@ export type customizeStoreStateMachineEvents =
| transitionalEvents
| { type: 'AI_WIZARD_CLOSED_BEFORE_COMPLETION'; payload: { step: string } }
| { type: 'EXTERNAL_URL_UPDATE' }
| { type: 'INSTALL_FONTS' }
| { type: 'NO_AI_FLOW_ERROR'; payload: { hasError: boolean } }
| { type: 'IS_FONT_LIBRARY_AVAILABLE'; payload: boolean };
@ -202,6 +203,9 @@ export const customizeStoreStateMachineDefinition = createMachine( {
{ type: 'updateQueryStep', step: 'intro' },
],
},
INSTALL_FONTS: {
target: 'designWithoutAi.installFonts',
},
},
states: {
setFlags: {
@ -365,6 +369,18 @@ export const customizeStoreStateMachineDefinition = createMachine( {
component: DesignWithoutAi,
},
},
// This state is used to install fonts and then redirect to the assembler hub.
installFonts: {
entry: [
{
type: 'updateQueryStep',
step: 'design/install-fonts',
},
],
meta: {
component: DesignWithoutAi,
},
},
},
},
designWithAi: {

View File

@ -0,0 +1,4 @@
Significance: minor
Type: fix
CYS - Core: install font when user clicks opt-in