From c686f605e6813333920cd2cafe302c53b985a16f Mon Sep 17 00:00:00 2001
From: Luigi Teschio
Date: Thu, 11 Jan 2024 15:32:16 +0100
Subject: [PATCH] [CYS - Core] Update the homepage with default patterns when
the assembler is loaded (#43457)
CYS - Core: Setup the site with a default homepage when the assembler is loaded
---
.../customize-store/assembler-hub/layout.tsx | 4 +-
.../assembler-hub/onboarding-tour/index.tsx | 48 ++++++--
.../onboarding-tour/test/index.tsx | 15 ++-
.../client/customize-store/data/actions.ts | 71 +++++++++++
.../design-with-ai/services.ts | 58 +--------
.../design-without-ai/actions.ts | 47 ++++++++
.../design-without-ai/index.tsx | 74 ++++++++++++
.../design-without-ai/services.ts | 31 +++++
.../design-without-ai/state-machine.tsx | 111 ++++++++++++++++++
.../design-without-ai/types.ts | 12 ++
.../client/customize-store/index.tsx | 108 ++++++++++-------
.../client/customize-store/intro/index.tsx | 7 +-
.../customize-store/intro/intro-banners.tsx | 58 ++++++---
...ault-patterns-when-the-assembler-is-loaded | 4 +
14 files changed, 515 insertions(+), 133 deletions(-)
create mode 100644 plugins/woocommerce-admin/client/customize-store/data/actions.ts
create mode 100644 plugins/woocommerce-admin/client/customize-store/design-without-ai/actions.ts
create mode 100644 plugins/woocommerce-admin/client/customize-store/design-without-ai/index.tsx
create mode 100644 plugins/woocommerce-admin/client/customize-store/design-without-ai/services.ts
create mode 100644 plugins/woocommerce-admin/client/customize-store/design-without-ai/state-machine.tsx
create mode 100644 plugins/woocommerce-admin/client/customize-store/design-without-ai/types.ts
create mode 100644 plugins/woocommerce/changelog/43457-43420-cys-core-update-homepage-with-default-patterns-when-the-assembler-is-loaded
diff --git a/plugins/woocommerce-admin/client/customize-store/assembler-hub/layout.tsx b/plugins/woocommerce-admin/client/customize-store/assembler-hub/layout.tsx
index 97e6350af7a..eef96c5b31b 100644
--- a/plugins/woocommerce-admin/client/customize-store/assembler-hub/layout.tsx
+++ b/plugins/woocommerce-admin/client/customize-store/assembler-hub/layout.tsx
@@ -243,11 +243,13 @@ export const Layout = () => {
{ ! isEditorLoading &&
shouldTourBeShown &&
- ! showAiOfflineModal && (
+ ( FlowType.AIOnline === context.flowType ||
+ FlowType.noAI === context.flowType ) && (
) }
diff --git a/plugins/woocommerce-admin/client/customize-store/assembler-hub/onboarding-tour/index.tsx b/plugins/woocommerce-admin/client/customize-store/assembler-hub/onboarding-tour/index.tsx
index b07d4db41b9..6a426ea4c77 100644
--- a/plugins/woocommerce-admin/client/customize-store/assembler-hub/onboarding-tour/index.tsx
+++ b/plugins/woocommerce-admin/client/customize-store/assembler-hub/onboarding-tour/index.tsx
@@ -10,6 +10,7 @@ import { recordEvent } from '@woocommerce/tracks';
* Internal dependencies
*/
export * from './use-onboarding-tour';
+import { FlowType } from '~/customize-store/types';
type OnboardingTourProps = {
onClose: () => void;
@@ -17,18 +18,53 @@ type OnboardingTourProps = {
takeTour: () => void;
showWelcomeTour: boolean;
setIsResizeHandleVisible: ( isVisible: boolean ) => void;
+ flowType: FlowType.AIOnline | FlowType.noAI;
+};
+
+const getLabels = ( flowType: FlowType.AIOnline | FlowType.noAI ) => {
+ switch ( flowType ) {
+ case FlowType.AIOnline:
+ return {
+ heading: __(
+ 'Welcome to your AI-generated store!',
+ 'woocommerce'
+ ),
+ descriptions: {
+ desktop: __(
+ 'This is where you can start customizing the look and feel of your store, including adding your logo, and changing colors and layouts. Take a quick tour to discover what’s possible.',
+ 'woocommerce'
+ ),
+ },
+ };
+ case FlowType.noAI:
+ return {
+ heading: __(
+ "Discover what's possible with the store designer",
+ 'woocommerce'
+ ),
+ descriptions: {
+ desktop: __(
+ "Start designing your store, including adding your logo, changing color schemes, and choosing layouts. Take a quick tour to discover what's possible.",
+ 'woocommerce'
+ ),
+ },
+ };
+ }
};
export const OnboardingTour = ( {
onClose,
skipTour,
takeTour,
+ flowType,
showWelcomeTour,
setIsResizeHandleVisible,
}: OnboardingTourProps ) => {
const [ placement, setPlacement ] =
useState< TourKitTypes.WooConfig[ 'placement' ] >( 'left' );
+ const { heading, descriptions } = getLabels( flowType );
+
if ( showWelcomeTour ) {
return (
( { recordEvent: jest.fn() } ) );
jest.mock( '../../', () => ( {
@@ -26,6 +27,7 @@ describe( 'OnboardingTour', () => {
takeTour: jest.Mock;
setShowWelcomeTour: jest.Mock;
showWelcomeTour: boolean;
+ flowType: FlowType.AIOnline | FlowType.noAI;
setIsResizeHandleVisible: ( isVisible: boolean ) => void;
};
@@ -37,10 +39,11 @@ describe( 'OnboardingTour', () => {
setShowWelcomeTour: jest.fn(),
showWelcomeTour: true,
setIsResizeHandleVisible: jest.fn(),
+ flowType: FlowType.AIOnline,
};
} );
- it( 'should render welcome tour', () => {
+ it( 'should render welcome tour mentioning the AI when the flowType is AIOnline', () => {
render( );
expect(
@@ -48,6 +51,16 @@ describe( 'OnboardingTour', () => {
).toBeInTheDocument();
} );
+ it( 'should render welcome tour not mentioning the AI when the flowType is AIOnline', () => {
+ render( );
+
+ expect(
+ screen.getByText(
+ /Discover what's possible with the store designer/i
+ )
+ ).toBeInTheDocument();
+ } );
+
it( 'should render step 1', () => {
render( );
diff --git a/plugins/woocommerce-admin/client/customize-store/data/actions.ts b/plugins/woocommerce-admin/client/customize-store/data/actions.ts
new file mode 100644
index 00000000000..a4b839f9883
--- /dev/null
+++ b/plugins/woocommerce-admin/client/customize-store/data/actions.ts
@@ -0,0 +1,71 @@
+/* eslint-disable @woocommerce/dependency-group */
+/* eslint-disable @typescript-eslint/ban-ts-comment */
+/**
+ * External dependencies
+ */
+import { resolveSelect, dispatch } from '@wordpress/data';
+// @ts-ignore No types for this exist yet.
+import { store as coreStore } from '@wordpress/core-data';
+// @ts-ignore No types for this exist yet.
+
+/**
+ * Internal dependencies
+ */
+import {
+ patternsToNameMap,
+ getTemplatePatterns,
+} from '../assembler-hub/hooks/use-home-templates';
+import { setLogoWidth } from '../utils';
+import { HOMEPAGE_TEMPLATES } from './homepageTemplates';
+
+// Update the current theme template
+export const updateTemplate = async ( {
+ homepageTemplateId,
+}: {
+ homepageTemplateId: keyof typeof HOMEPAGE_TEMPLATES;
+} ) => {
+ // @ts-ignore No types for this exist yet.
+ const { invalidateResolutionForStoreSelector } = dispatch( coreStore );
+
+ // Ensure that the patterns are up to date because we populate images and content in previous step.
+ invalidateResolutionForStoreSelector( 'getBlockPatterns' );
+ invalidateResolutionForStoreSelector( '__experimentalGetTemplateForLink' );
+
+ const patterns = ( await resolveSelect(
+ coreStore
+ // @ts-ignore No types for this exist yet.
+ ).getBlockPatterns() ) as Pattern[];
+ const patternsByName = patternsToNameMap( patterns );
+ const homepageTemplate = getTemplatePatterns(
+ HOMEPAGE_TEMPLATES[ homepageTemplateId ].blocks,
+ patternsByName
+ );
+
+ let content = [ ...homepageTemplate ]
+ .filter( Boolean )
+ .map( ( pattern ) => pattern.content )
+ .join( '\n\n' );
+
+ // Replace the logo width with the default width.
+ content = setLogoWidth( content );
+
+ const currentTemplate = await resolveSelect(
+ coreStore
+ // @ts-ignore No types for this exist yet.
+ ).__experimentalGetTemplateForLink( '/' );
+
+ // @ts-ignore No types for this exist yet.
+ const { saveEntityRecord } = dispatch( coreStore );
+
+ await saveEntityRecord(
+ 'postType',
+ currentTemplate.type,
+ {
+ id: currentTemplate.id,
+ content,
+ },
+ {
+ throwOnError: true,
+ }
+ );
+};
diff --git a/plugins/woocommerce-admin/client/customize-store/design-with-ai/services.ts b/plugins/woocommerce-admin/client/customize-store/design-with-ai/services.ts
index b5c2f72cdba..e947c20d54d 100644
--- a/plugins/woocommerce-admin/client/customize-store/design-with-ai/services.ts
+++ b/plugins/woocommerce-admin/client/customize-store/design-with-ai/services.ts
@@ -19,12 +19,8 @@ import { mergeBaseAndUserConfigs } from '@wordpress/edit-site/build-module/compo
import { designWithAiStateMachineContext } from './types';
import { FONT_PAIRINGS } from '../assembler-hub/sidebar/global-styles/font-pairing-variations/constants';
import { COLOR_PALETTES } from '../assembler-hub/sidebar/global-styles/color-palette-variations/constants';
-import {
- patternsToNameMap,
- getTemplatePatterns,
-} from '../assembler-hub/hooks/use-home-templates';
import { HOMEPAGE_TEMPLATES } from '../data/homepageTemplates';
-import { setLogoWidth } from '../utils';
+import { updateTemplate } from '../data/actions';
const { escalate } = actions;
@@ -396,58 +392,6 @@ const updateGlobalStyles = async ( {
);
};
-// Update the current theme template
-const updateTemplate = async ( {
- homepageTemplateId,
-}: {
- homepageTemplateId: keyof typeof HOMEPAGE_TEMPLATES;
-} ) => {
- // @ts-ignore No types for this exist yet.
- const { invalidateResolutionForStoreSelector } = dispatch( coreStore );
-
- // Ensure that the patterns are up to date because we populate images and content in previous step.
- invalidateResolutionForStoreSelector( 'getBlockPatterns' );
- invalidateResolutionForStoreSelector( '__experimentalGetTemplateForLink' );
-
- const patterns = ( await resolveSelect(
- coreStore
- // @ts-ignore No types for this exist yet.
- ).getBlockPatterns() ) as Pattern[];
- const patternsByName = patternsToNameMap( patterns );
- const homepageTemplate = getTemplatePatterns(
- HOMEPAGE_TEMPLATES[ homepageTemplateId ].blocks,
- patternsByName
- );
-
- let content = [ ...homepageTemplate ]
- .filter( Boolean )
- .map( ( pattern ) => pattern.content )
- .join( '\n\n' );
-
- // Replace the logo width with the default width.
- content = setLogoWidth( content );
-
- const currentTemplate = await resolveSelect(
- coreStore
- // @ts-ignore No types for this exist yet.
- ).__experimentalGetTemplateForLink( '/' );
-
- // @ts-ignore No types for this exist yet.
- const { saveEntityRecord } = dispatch( coreStore );
-
- await saveEntityRecord(
- 'postType',
- currentTemplate.type,
- {
- id: currentTemplate.id,
- content,
- },
- {
- throwOnError: true,
- }
- );
-};
-
export const assembleSite = async (
context: designWithAiStateMachineContext
) => {
diff --git a/plugins/woocommerce-admin/client/customize-store/design-without-ai/actions.ts b/plugins/woocommerce-admin/client/customize-store/design-without-ai/actions.ts
new file mode 100644
index 00000000000..08a42f356b3
--- /dev/null
+++ b/plugins/woocommerce-admin/client/customize-store/design-without-ai/actions.ts
@@ -0,0 +1,47 @@
+/**
+ * External dependencies
+ */
+import { getNewPath } from '@woocommerce/navigation';
+/**
+ * Internal dependencies
+ */
+import { attachIframeListeners, onIframeLoad } from '../utils';
+
+const redirectToAssemblerHub = async () => {
+ const assemblerUrl = getNewPath( {}, '/customize-store/assembler-hub', {} );
+ const iframe = document.createElement( 'iframe' );
+ iframe.classList.add( 'cys-fullscreen-iframe' );
+ iframe.src = assemblerUrl;
+
+ const showIframe = () => {
+ if ( iframe.style.opacity === '1' ) {
+ // iframe is already visible
+ return;
+ }
+
+ const loader = document.getElementsByClassName(
+ 'woocommerce-onboarding-loader'
+ );
+ if ( loader[ 0 ] ) {
+ ( loader[ 0 ] as HTMLElement ).style.display = 'none';
+ }
+
+ iframe.style.opacity = '1';
+ };
+
+ iframe.onload = () => {
+ // Hide loading UI
+ attachIframeListeners( iframe );
+ onIframeLoad( showIframe );
+
+ // Ceiling wait time set to 60 seconds
+ setTimeout( showIframe, 60 * 1000 );
+ window.history?.pushState( {}, '', assemblerUrl );
+ };
+
+ document.body.appendChild( iframe );
+};
+
+export const actions = {
+ redirectToAssemblerHub,
+};
diff --git a/plugins/woocommerce-admin/client/customize-store/design-without-ai/index.tsx b/plugins/woocommerce-admin/client/customize-store/design-without-ai/index.tsx
new file mode 100644
index 00000000000..5a913343c37
--- /dev/null
+++ b/plugins/woocommerce-admin/client/customize-store/design-without-ai/index.tsx
@@ -0,0 +1,74 @@
+/**
+ * External dependencies
+ */
+import { useMachine, useSelector } from '@xstate/react';
+import { AnyInterpreter, Sender } from 'xstate';
+import { useEffect, useState } from '@wordpress/element';
+
+/**
+ * Internal dependencies
+ */
+import { customizeStoreStateMachineEvents } from '..';
+import {
+ CustomizeStoreComponent,
+ customizeStoreStateMachineContext,
+} from '../types';
+import { designWithNoAiStateMachineDefinition } from './state-machine';
+import { findComponentMeta } from '~/utils/xstate/find-component';
+import { AssembleHubLoader } from '../design-with-ai/pages';
+
+export type DesignWithoutAiComponent = typeof AssembleHubLoader;
+export type DesignWithoutAiComponentMeta = {
+ component: DesignWithoutAiComponent;
+};
+
+export const DesignWithNoAiController = ( {
+ parentMachine,
+}: {
+ parentMachine?: AnyInterpreter;
+ sendEventToParent?: Sender< customizeStoreStateMachineEvents >;
+ parentContext?: customizeStoreStateMachineContext;
+} ) => {
+ const [ , , service ] = useMachine( designWithNoAiStateMachineDefinition, {
+ devTools: process.env.NODE_ENV === 'development',
+ parent: parentMachine,
+ } );
+
+ // 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 ) =>
+ findComponentMeta< DesignWithoutAiComponentMeta >(
+ currentState?.meta ?? undefined
+ )
+ );
+
+ const [ CurrentComponent, setCurrentComponent ] =
+ useState< DesignWithoutAiComponent | null >( null );
+ useEffect( () => {
+ if ( currentNodeMeta?.component ) {
+ setCurrentComponent( () => currentNodeMeta?.component );
+ }
+ }, [ CurrentComponent, currentNodeMeta?.component ] );
+
+ return (
+ <>
+
+ { CurrentComponent ?
:
}
+
+ >
+ );
+};
+
+//loader should send event 'THEME_SUGGESTED' when it's done
+export const DesignWithoutAi: CustomizeStoreComponent = ( {
+ parentMachine,
+ context,
+} ) => {
+ return (
+ <>
+
+ >
+ );
+};
diff --git a/plugins/woocommerce-admin/client/customize-store/design-without-ai/services.ts b/plugins/woocommerce-admin/client/customize-store/design-without-ai/services.ts
new file mode 100644
index 00000000000..ff5d5121009
--- /dev/null
+++ b/plugins/woocommerce-admin/client/customize-store/design-without-ai/services.ts
@@ -0,0 +1,31 @@
+/**
+ * External dependencies
+ */
+import { Sender } from 'xstate';
+/**
+ * Internal dependencies
+ */
+import { updateTemplate } from '../data/actions';
+import { HOMEPAGE_TEMPLATES } from '../data/homepageTemplates';
+
+const assembleSite = async () => {
+ await updateTemplate( {
+ homepageTemplateId: 'template1' as keyof typeof HOMEPAGE_TEMPLATES,
+ } );
+};
+
+const browserPopstateHandler =
+ () => ( sendBack: Sender< { type: 'EXTERNAL_URL_UPDATE' } > ) => {
+ const popstateHandler = () => {
+ sendBack( { type: 'EXTERNAL_URL_UPDATE' } );
+ };
+ window.addEventListener( 'popstate', popstateHandler );
+ return () => {
+ window.removeEventListener( 'popstate', popstateHandler );
+ };
+ };
+
+export const services = {
+ assembleSite,
+ browserPopstateHandler,
+};
diff --git a/plugins/woocommerce-admin/client/customize-store/design-without-ai/state-machine.tsx b/plugins/woocommerce-admin/client/customize-store/design-without-ai/state-machine.tsx
new file mode 100644
index 00000000000..d497d7e0b14
--- /dev/null
+++ b/plugins/woocommerce-admin/client/customize-store/design-without-ai/state-machine.tsx
@@ -0,0 +1,111 @@
+/**
+ * External dependencies
+ */
+import { EventObject, createMachine } from 'xstate';
+import { getQuery } from '@woocommerce/navigation';
+
+/**
+ * Internal dependencies
+ */
+
+import { AssembleHubLoader } from '../design-with-ai/pages';
+
+import { FlowType } from '../types';
+import { DesignWithoutAIStateMachineContext } from './types';
+import { services } from './services';
+import { actions } from './actions';
+
+export const hasStepInUrl = (
+ _ctx: unknown,
+ _evt: unknown,
+ { cond }: { cond: unknown }
+) => {
+ const { path = '' } = getQuery() as { path: string };
+ const pathFragments = path.split( '/' );
+ return (
+ pathFragments[ 2 ] === // [0] '', [1] 'customize-store', [2] design step slug
+ ( cond as { step: string | undefined } ).step
+ );
+};
+
+export const designWithNoAiStateMachineDefinition = createMachine(
+ {
+ id: 'designWithoutAI',
+ predictableActionArguments: true,
+ preserveActionOrder: true,
+ schema: {
+ context: {} as DesignWithoutAIStateMachineContext,
+ events: {} as EventObject,
+ },
+ invoke: {
+ src: 'browserPopstateHandler',
+ },
+ on: {
+ EXTERNAL_URL_UPDATE: {
+ target: 'navigate',
+ },
+ },
+ context: {
+ startLoadingTime: null,
+ flowType: FlowType.noAI,
+ apiCallLoader: {
+ hasErrors: false,
+ },
+ },
+ initial: 'navigate',
+ states: {
+ navigate: {
+ always: [
+ {
+ cond: {
+ type: 'hasStepInUrl',
+ step: 'design',
+ },
+ target: 'preAssembleSite',
+ },
+ ],
+ },
+ preAssembleSite: {
+ type: 'parallel',
+ states: {
+ assembleSite: {
+ initial: 'pending',
+ states: {
+ pending: {
+ invoke: {
+ src: 'assembleSite',
+ onDone: {
+ target: 'done',
+ },
+ onError: {
+ actions: [ 'assignAPICallLoaderError' ],
+ },
+ },
+ },
+ done: {
+ type: 'final',
+ },
+ },
+ onDone: {
+ target: '#designWithoutAI.showAssembleHub',
+ },
+ },
+ },
+ },
+ showAssembleHub: {
+ meta: {
+ component: AssembleHubLoader,
+ },
+ entry: [ 'redirectToAssemblerHub' ],
+ type: 'final',
+ },
+ },
+ },
+ {
+ actions,
+ services,
+ guards: {
+ hasStepInUrl,
+ },
+ }
+);
diff --git a/plugins/woocommerce-admin/client/customize-store/design-without-ai/types.ts b/plugins/woocommerce-admin/client/customize-store/design-without-ai/types.ts
new file mode 100644
index 00000000000..1fc8e5863e5
--- /dev/null
+++ b/plugins/woocommerce-admin/client/customize-store/design-without-ai/types.ts
@@ -0,0 +1,12 @@
+/**
+ * Internal dependencies
+ */
+import { FlowType } from '../types';
+
+export type DesignWithoutAIStateMachineContext = {
+ startLoadingTime: number | null;
+ apiCallLoader: {
+ hasErrors: boolean;
+ };
+ flowType: FlowType.noAI;
+};
diff --git a/plugins/woocommerce-admin/client/customize-store/index.tsx b/plugins/woocommerce-admin/client/customize-store/index.tsx
index 8bafb258128..ddad8b381bf 100644
--- a/plugins/woocommerce-admin/client/customize-store/index.tsx
+++ b/plugins/woocommerce-admin/client/customize-store/index.tsx
@@ -28,6 +28,8 @@ import {
actions as introActions,
} from './intro';
import { DesignWithAi, events as designWithAiEvents } from './design-with-ai';
+import { DesignWithoutAi } from './design-without-ai';
+
import { AssemblerHub, events as assemblerHubEvents } from './assembler-hub';
import {
events as transitionalEvents,
@@ -193,6 +195,13 @@ export const customizeStoreStateMachineDefinition = createMachine( {
step: 'design-with-ai',
},
},
+ {
+ target: 'designWithoutAi',
+ cond: {
+ type: 'hasStepInUrl',
+ step: 'design',
+ },
+ },
{
target: 'assemblerHub',
cond: {
@@ -222,64 +231,59 @@ export const customizeStoreStateMachineDefinition = createMachine( {
// eslint-disable-next-line xstate/prefer-always
'': [
{
- target: 'intro',
+ target: 'fetchIntroData',
cond: 'isNotWooExpress',
actions: 'assignNoAI',
},
{
- target: 'preIntro',
+ target: 'checkAiStatus',
cond: 'isWooExpress',
},
],
},
},
- preIntro: {
- type: 'parallel',
+ checkAiStatus: {
+ initial: 'pending',
states: {
- checkAiStatus: {
- initial: 'pending',
- states: {
- pending: {
- invoke: {
- src: 'fetchAiStatus',
- onDone: {
- actions: 'assignAiStatus',
- target: 'success',
- },
- onError: {
- actions: 'assignAiOffline',
- target: 'success',
- },
- },
+ pending: {
+ invoke: {
+ src: 'fetchAiStatus',
+ onDone: {
+ actions: 'assignAiStatus',
+ target: 'success',
+ },
+ onError: {
+ actions: 'assignAiOffline',
+ target: 'success',
},
- success: { type: 'final' },
},
},
- fetchIntroData: {
- initial: 'pending',
- states: {
- pending: {
- invoke: {
- src: 'fetchIntroData',
- onError: {
- actions:
- 'assignFetchIntroDataError',
- target: 'success',
- },
- onDone: {
- target: 'success',
- actions: [
- 'assignThemeData',
- 'assignActiveThemeHasMods',
- 'assignCustomizeStoreCompleted',
- 'assignCurrentThemeIsAiGenerated',
- ],
- },
- },
+ success: { type: 'final' },
+ },
+ onDone: 'fetchIntroData',
+ },
+ fetchIntroData: {
+ initial: 'pending',
+ states: {
+ pending: {
+ invoke: {
+ src: 'fetchIntroData',
+ onError: {
+ actions: 'assignFetchIntroDataError',
+ target: 'success',
+ },
+ onDone: {
+ target: 'success',
+ actions: [
+ 'assignThemeData',
+ 'assignActiveThemeHasMods',
+ 'assignCustomizeStoreCompleted',
+ 'assignCurrentThemeIsAiGenerated',
+ ],
},
- success: { type: 'final' },
},
},
+ success: { type: 'final' },
},
onDone: 'intro',
},
@@ -297,6 +301,10 @@ export const customizeStoreStateMachineDefinition = createMachine( {
actions: [ 'recordTracksDesignWithAIClicked' ],
target: 'designWithAi',
},
+ DESIGN_WITHOUT_AI: {
+ actions: [ 'recordTracksDesignWithAIClicked' ],
+ target: 'designWithoutAi',
+ },
SELECTED_NEW_THEME: {
actions: [ 'recordTracksThemeSelected' ],
target: 'appearanceTask',
@@ -313,6 +321,22 @@ export const customizeStoreStateMachineDefinition = createMachine( {
},
},
},
+ designWithoutAi: {
+ initial: 'preDesignWithoutAi',
+ states: {
+ preDesignWithoutAi: {
+ always: {
+ target: 'designWithoutAi',
+ },
+ },
+ designWithoutAi: {
+ entry: [ { type: 'updateQueryStep', step: 'design' } ],
+ meta: {
+ component: DesignWithoutAi,
+ },
+ },
+ },
+ },
designWithAi: {
initial: 'preDesignWithAi',
states: {
diff --git a/plugins/woocommerce-admin/client/customize-store/intro/index.tsx b/plugins/woocommerce-admin/client/customize-store/intro/index.tsx
index 50609e6cf8f..1eb358cdbd7 100644
--- a/plugins/woocommerce-admin/client/customize-store/intro/index.tsx
+++ b/plugins/woocommerce-admin/client/customize-store/intro/index.tsx
@@ -30,7 +30,7 @@ import {
DefaultBanner,
ExistingAiThemeBanner,
ExistingThemeBanner,
- CoreBanner,
+ NoAIBanner,
} from './intro-banners';
export type events =
@@ -39,7 +39,8 @@ export type events =
| { type: 'CLICKED_ON_BREADCRUMB' }
| { type: 'SELECTED_BROWSE_ALL_THEMES' }
| { type: 'SELECTED_ACTIVE_THEME'; payload: { theme: string } }
- | { type: 'SELECTED_NEW_THEME'; payload: { theme: string } };
+ | { type: 'SELECTED_NEW_THEME'; payload: { theme: string } }
+ | { type: 'DESIGN_WITHOUT_AI' };
export * as actions from './actions';
export * as services from './services';
@@ -52,7 +53,7 @@ const BANNER_COMPONENTS = {
'jetpack-offline': JetpackOfflineBanner,
'existing-ai-theme': ExistingAiThemeBanner,
'existing-theme': ExistingThemeBanner,
- [ FlowType.noAI ]: CoreBanner,
+ [ FlowType.noAI ]: NoAIBanner,
default: DefaultBanner,
};
diff --git a/plugins/woocommerce-admin/client/customize-store/intro/intro-banners.tsx b/plugins/woocommerce-admin/client/customize-store/intro/intro-banners.tsx
index 56385f87180..498986906c9 100644
--- a/plugins/woocommerce-admin/client/customize-store/intro/intro-banners.tsx
+++ b/plugins/woocommerce-admin/client/customize-store/intro/intro-banners.tsx
@@ -21,6 +21,7 @@ export const BaseIntroBanner = ( {
bannerTitle,
bannerText,
bannerClass,
+ showAIDisclaimer,
buttonIsLink,
bannerButtonOnClick,
bannerButtonText,
@@ -30,6 +31,7 @@ export const BaseIntroBanner = ( {
bannerTitle: string;
bannerText: string;
bannerClass: string;
+ showAIDisclaimer: boolean;
buttonIsLink?: boolean;
bannerButtonOnClick?: () => void;
bannerButtonText?: string;
@@ -58,23 +60,25 @@ export const BaseIntroBanner = ( {
) }
{ secondaryButton }
-
- { interpolateComponents( {
- mixedString: __(
- 'Powered by experimental AI. {{link}}Learn more{{/link}}',
- 'woocommerce'
- ),
- components: {
- link: (
-
+ { showAIDisclaimer && (
+
+ { interpolateComponents( {
+ mixedString: __(
+ 'Powered by experimental AI. {{link}}Learn more{{/link}}',
+ 'woocommerce'
),
- },
- } ) }
-
+ components: {
+ link: (
+
+ ),
+ },
+ } ) }
+
+ ) }
{ children }
@@ -95,6 +99,7 @@ export const NetworkOfflineBanner = () => {
) }
bannerClass="offline-banner"
bannerButtonOnClick={ () => {} }
+ showAIDisclaimer={ true }
/>
);
};
@@ -122,6 +127,7 @@ export const JetpackOfflineBanner = ( {
} );
} }
bannerButtonText={ __( 'Find out how', 'woocommerce' ) }
+ showAIDisclaimer={ true }
/>
);
};
@@ -147,6 +153,7 @@ export const ExistingThemeBanner = ( {
setOpenDesignChangeWarningModal( true );
} }
bannerButtonText={ __( 'Design with AI', 'woocommerce' ) }
+ showAIDisclaimer={ true }
/>
);
};
@@ -174,6 +181,7 @@ export const DefaultBanner = ( {
} );
} }
bannerButtonText={ __( 'Design with AI', 'woocommerce' ) }
+ showAIDisclaimer={ true }
/>
);
};
@@ -199,11 +207,16 @@ export const ThemeHasModsBanner = ( {
setOpenDesignChangeWarningModal( true );
} }
bannerButtonText={ __( 'Design with AI', 'woocommerce' ) }
+ showAIDisclaimer={ true }
/>
);
};
-export const CoreBanner = () => {
+export const NoAIBanner = ( {
+ sendEvent,
+}: {
+ sendEvent: React.ComponentProps< typeof Intro >[ 'sendEvent' ];
+} ) => {
return (
{
'Quickly create a beautiful store using our built-in store designer. Choose your layout, select a style, and much more.',
'woocommerce'
) }
- bannerClass="core-banner"
- bannerButtonOnClick={ () => {} }
+ bannerClass="no-ai-banner"
+ bannerButtonText={ __( 'Start designing', 'woocommerce' ) }
+ bannerButtonOnClick={ () => {
+ sendEvent( {
+ type: 'DESIGN_WITHOUT_AI',
+ } );
+ } }
+ showAIDisclaimer={ false }
/>
);
};
@@ -260,6 +279,7 @@ export const ExistingAiThemeBanner = ( {
} }
bannerButtonText={ __( 'Customize', 'woocommerce' ) }
secondaryButton={ secondaryButton }
+ showAIDisclaimer={ true }
>
diff --git a/plugins/woocommerce/changelog/43457-43420-cys-core-update-homepage-with-default-patterns-when-the-assembler-is-loaded b/plugins/woocommerce/changelog/43457-43420-cys-core-update-homepage-with-default-patterns-when-the-assembler-is-loaded
new file mode 100644
index 00000000000..747a6030baf
--- /dev/null
+++ b/plugins/woocommerce/changelog/43457-43420-cys-core-update-homepage-with-default-patterns-when-the-assembler-is-loaded
@@ -0,0 +1,4 @@
+Significance: minor
+Type: add
+
+[CYS - Core] Update the homepage with default patterns when the assembler is loaded.
\ No newline at end of file