Merge branch 'trunk' into e2e/remove-obw-tests
This commit is contained in:
commit
20c5be1235
|
@ -1,5 +1,12 @@
|
||||||
== Changelog ==
|
== Changelog ==
|
||||||
|
|
||||||
|
= 8.1.1 2023-09-18 =
|
||||||
|
|
||||||
|
**WooCommerce**
|
||||||
|
|
||||||
|
* Fix - Do not send user meta data back in `woocommerce_get_customer_details` response. [#40221](https://github.com/woocommerce/woocommerce/pull/40221)
|
||||||
|
* Fix - Fix possible metadata duplication when HPOS is enabled. [#40148](https://github.com/woocommerce/woocommerce/pull/40148)
|
||||||
|
|
||||||
= 8.1.0 2023-09-12 =
|
= 8.1.0 2023-09-12 =
|
||||||
|
|
||||||
**WooCommerce**
|
**WooCommerce**
|
||||||
|
|
|
@ -12,7 +12,7 @@ import { parse } from '@wordpress/blocks';
|
||||||
import { usePatterns, Pattern, PatternWithBlocks } from './use-patterns';
|
import { usePatterns, Pattern, PatternWithBlocks } from './use-patterns';
|
||||||
|
|
||||||
// TODO: It might be better to create an API endpoint to get the templates.
|
// TODO: It might be better to create an API endpoint to get the templates.
|
||||||
const LARGE_BUSINESS_TEMPLATES = {
|
export const LARGE_BUSINESS_TEMPLATES = {
|
||||||
template1: [
|
template1: [
|
||||||
'a8c/cover-image-with-left-aligned-call-to-action',
|
'a8c/cover-image-with-left-aligned-call-to-action',
|
||||||
'woocommerce-blocks/featured-products-5-item-grid',
|
'woocommerce-blocks/featured-products-5-item-grid',
|
||||||
|
@ -42,7 +42,7 @@ const LARGE_BUSINESS_TEMPLATES = {
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
const SMALL_MEDIUM_BUSINESS_TEMPLATES = {
|
export const SMALL_MEDIUM_BUSINESS_TEMPLATES = {
|
||||||
template1: [
|
template1: [
|
||||||
'woocommerce-blocks/featured-products-fresh-and-tasty',
|
'woocommerce-blocks/featured-products-fresh-and-tasty',
|
||||||
'woocommerce-blocks/testimonials-single',
|
'woocommerce-blocks/testimonials-single',
|
||||||
|
@ -68,7 +68,16 @@ const SMALL_MEDIUM_BUSINESS_TEMPLATES = {
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
const getTemplatePatterns = (
|
const TEMPLATES = {
|
||||||
|
template1: LARGE_BUSINESS_TEMPLATES.template1,
|
||||||
|
template2: LARGE_BUSINESS_TEMPLATES.template2,
|
||||||
|
template3: LARGE_BUSINESS_TEMPLATES.template3,
|
||||||
|
template4: SMALL_MEDIUM_BUSINESS_TEMPLATES.template1,
|
||||||
|
template5: SMALL_MEDIUM_BUSINESS_TEMPLATES.template2,
|
||||||
|
template6: SMALL_MEDIUM_BUSINESS_TEMPLATES.template3,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getTemplatePatterns = (
|
||||||
template: string[],
|
template: string[],
|
||||||
patternsByName: Record< string, Pattern >
|
patternsByName: Record< string, Pattern >
|
||||||
) =>
|
) =>
|
||||||
|
@ -88,27 +97,26 @@ const getTemplatePatterns = (
|
||||||
} )
|
} )
|
||||||
.filter( ( pattern ) => pattern !== null ) as PatternWithBlocks[];
|
.filter( ( pattern ) => pattern !== null ) as PatternWithBlocks[];
|
||||||
|
|
||||||
|
export const patternsToNameMap = ( blockPatterns: Pattern[] ) =>
|
||||||
|
blockPatterns.reduce(
|
||||||
|
( acc: Record< string, Pattern >, pattern: Pattern ) => {
|
||||||
|
acc[ pattern.name ] = pattern;
|
||||||
|
return acc;
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
|
||||||
export const useHomeTemplates = () => {
|
export const useHomeTemplates = () => {
|
||||||
// TODO: Get businessType from option
|
|
||||||
const businessType = 'SMB' as string;
|
|
||||||
const { blockPatterns, isLoading } = usePatterns();
|
const { blockPatterns, isLoading } = usePatterns();
|
||||||
|
|
||||||
const patternsByName = useMemo( () => {
|
const patternsByName = useMemo(
|
||||||
return blockPatterns.reduce(
|
() => patternsToNameMap( blockPatterns ),
|
||||||
( acc: Record< string, Pattern >, pattern: Pattern ) => {
|
[ blockPatterns ]
|
||||||
acc[ pattern.name ] = pattern;
|
);
|
||||||
return acc;
|
|
||||||
},
|
|
||||||
{}
|
|
||||||
);
|
|
||||||
}, [ blockPatterns ] );
|
|
||||||
|
|
||||||
const homeTemplates = useMemo( () => {
|
const homeTemplates = useMemo( () => {
|
||||||
if ( isLoading ) return {};
|
if ( isLoading ) return {};
|
||||||
const recommendedTemplates =
|
const recommendedTemplates = TEMPLATES;
|
||||||
businessType === 'SMB'
|
|
||||||
? SMALL_MEDIUM_BUSINESS_TEMPLATES
|
|
||||||
: LARGE_BUSINESS_TEMPLATES;
|
|
||||||
|
|
||||||
return Object.entries( recommendedTemplates ).reduce(
|
return Object.entries( recommendedTemplates ).reduce(
|
||||||
(
|
(
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -21,7 +21,8 @@ export const ColorPalette = () => {
|
||||||
gap={ 4 }
|
gap={ 4 }
|
||||||
className="woocommerce-customize-store_color-palette-container"
|
className="woocommerce-customize-store_color-palette-container"
|
||||||
>
|
>
|
||||||
{ COLOR_PALETTES.map( ( variation, index ) => (
|
{ /* TODO: Show 9 colors based on the AI recommendation */ }
|
||||||
|
{ COLOR_PALETTES.slice( 0, 9 ).map( ( variation, index ) => (
|
||||||
<VariationContainer key={ index } variation={ variation }>
|
<VariationContainer key={ index } variation={ variation }>
|
||||||
<ColorPaletteVariationPreview title={ variation?.title } />
|
<ColorPaletteVariationPreview title={ variation?.title } />
|
||||||
</VariationContainer>
|
</VariationContainer>
|
||||||
|
|
|
@ -14,6 +14,8 @@ import {
|
||||||
designWithAiStateMachineEvents,
|
designWithAiStateMachineEvents,
|
||||||
FontPairing,
|
FontPairing,
|
||||||
LookAndToneCompletionResponse,
|
LookAndToneCompletionResponse,
|
||||||
|
Header,
|
||||||
|
Footer,
|
||||||
} from './types';
|
} from './types';
|
||||||
import { aiWizardClosedBeforeCompletionEvent } from './events';
|
import { aiWizardClosedBeforeCompletionEvent } from './events';
|
||||||
import {
|
import {
|
||||||
|
@ -110,6 +112,42 @@ const assignFontPairing = assign<
|
||||||
},
|
},
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
const assignHeader = assign<
|
||||||
|
designWithAiStateMachineContext,
|
||||||
|
designWithAiStateMachineEvents
|
||||||
|
>( {
|
||||||
|
aiSuggestions: ( context, event: unknown ) => {
|
||||||
|
return {
|
||||||
|
...context.aiSuggestions,
|
||||||
|
header: (
|
||||||
|
event as {
|
||||||
|
data: {
|
||||||
|
response: Header;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
).data.response.slug,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
} );
|
||||||
|
|
||||||
|
const assignFooter = assign<
|
||||||
|
designWithAiStateMachineContext,
|
||||||
|
designWithAiStateMachineEvents
|
||||||
|
>( {
|
||||||
|
aiSuggestions: ( context, event: unknown ) => {
|
||||||
|
return {
|
||||||
|
...context.aiSuggestions,
|
||||||
|
footer: (
|
||||||
|
event as {
|
||||||
|
data: {
|
||||||
|
response: Footer;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
).data.response.slug,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
} );
|
||||||
|
|
||||||
const logAIAPIRequestError = () => {
|
const logAIAPIRequestError = () => {
|
||||||
// log AI API request error
|
// log AI API request error
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
|
@ -178,6 +216,8 @@ export const actions = {
|
||||||
assignLookAndTone,
|
assignLookAndTone,
|
||||||
assignDefaultColorPalette,
|
assignDefaultColorPalette,
|
||||||
assignFontPairing,
|
assignFontPairing,
|
||||||
|
assignHeader,
|
||||||
|
assignFooter,
|
||||||
logAIAPIRequestError,
|
logAIAPIRequestError,
|
||||||
updateQueryStep,
|
updateQueryStep,
|
||||||
recordTracksStepViewed,
|
recordTracksStepViewed,
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
/**
|
||||||
|
* External dependencies
|
||||||
|
*/
|
||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
|
const footerChoices = [
|
||||||
|
{
|
||||||
|
slug: 'woocommerce-blocks/footer-simple-menu-and-cart',
|
||||||
|
label: 'Footer with Simple Menu and Cart',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: 'woocommerce-blocks/footer-with-3-menus',
|
||||||
|
label: 'Footer with 3 Menus',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: 'woocommerce-blocks/footer-large',
|
||||||
|
label: 'Large Footer',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const allowedFooter: string[] = footerChoices.map( ( footer ) => footer.slug );
|
||||||
|
|
||||||
|
export const footerValidator = z.object( {
|
||||||
|
slug: z.string().refine( ( slug ) => allowedFooter.includes( slug ), {
|
||||||
|
message: 'Footer not part of allowed list',
|
||||||
|
} ),
|
||||||
|
} );
|
||||||
|
|
||||||
|
export const defaultFooter = {
|
||||||
|
queryId: 'default_footer',
|
||||||
|
|
||||||
|
// make sure version is updated every time the prompt is changed
|
||||||
|
version: '2023-09-19',
|
||||||
|
prompt: ( businessDescription: string, look: string, tone: string ) => {
|
||||||
|
return `
|
||||||
|
You are a WordPress theme expert. Analyse the following store description, merchant's chosen look and tone, and determine the most appropriate footer.
|
||||||
|
Respond only with one footer and only its JSON.
|
||||||
|
|
||||||
|
Chosen look and tone: ${ look } look, ${ tone } tone.
|
||||||
|
Business description: ${ businessDescription }
|
||||||
|
|
||||||
|
Footer to choose from:
|
||||||
|
${ JSON.stringify( footerChoices ) }
|
||||||
|
`;
|
||||||
|
},
|
||||||
|
responseValidation: footerValidator.parse,
|
||||||
|
};
|
|
@ -0,0 +1,51 @@
|
||||||
|
/**
|
||||||
|
* External dependencies
|
||||||
|
*/
|
||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
|
const headerChoices = [
|
||||||
|
{
|
||||||
|
slug: 'woocommerce-blocks/header-essential',
|
||||||
|
label: 'Essential Header',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: 'woocommerce-blocks/header-centered-menu-with-search',
|
||||||
|
label: 'Centered Menu with search Header',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: 'woocommerce-blocks/header-minimal',
|
||||||
|
label: 'Minimal Header',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: 'woocommerce-blocks/header-large',
|
||||||
|
label: 'Large Header',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const allowedHeaders: string[] = headerChoices.map( ( header ) => header.slug );
|
||||||
|
|
||||||
|
export const headerValidator = z.object( {
|
||||||
|
slug: z.string().refine( ( slug ) => allowedHeaders.includes( slug ), {
|
||||||
|
message: 'Header not part of allowed list',
|
||||||
|
} ),
|
||||||
|
} );
|
||||||
|
|
||||||
|
export const defaultHeader = {
|
||||||
|
queryId: 'default_header',
|
||||||
|
|
||||||
|
// make sure version is updated every time the prompt is changed
|
||||||
|
version: '2023-09-19',
|
||||||
|
prompt: ( businessDescription: string, look: string, tone: string ) => {
|
||||||
|
return `
|
||||||
|
You are a WordPress theme expert. Analyse the following store description, merchant's chosen look and tone, and determine the most appropriate header.
|
||||||
|
Respond only with one header and only its JSON.
|
||||||
|
|
||||||
|
Chosen look and tone: ${ look } look, ${ tone } tone.
|
||||||
|
Business description: ${ businessDescription }
|
||||||
|
|
||||||
|
Headers to choose from:
|
||||||
|
${ JSON.stringify( headerChoices ) }
|
||||||
|
`;
|
||||||
|
},
|
||||||
|
responseValidation: headerValidator.parse,
|
||||||
|
};
|
|
@ -1,3 +1,5 @@
|
||||||
export * from './colorChoices';
|
export * from './colorChoices';
|
||||||
export * from './lookAndTone';
|
export * from './lookAndTone';
|
||||||
export * from './fontPairings';
|
export * from './fontPairings';
|
||||||
|
export * from './header';
|
||||||
|
export * from './footer';
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
/**
|
||||||
|
* Internal dependencies
|
||||||
|
*/
|
||||||
|
import { footerValidator } from '..';
|
||||||
|
|
||||||
|
describe( 'footerValidator', () => {
|
||||||
|
it( 'should validate when footer is part of the allowed list', () => {
|
||||||
|
const validFooter = { slug: 'woocommerce-blocks/footer-large' };
|
||||||
|
expect( () => footerValidator.parse( validFooter ) ).not.toThrow();
|
||||||
|
} );
|
||||||
|
|
||||||
|
it( 'should not validate when footer is not part of the allowed list', () => {
|
||||||
|
const invalidFooter = {
|
||||||
|
slug: 'woocommerce-blocks/footer-large-invalid',
|
||||||
|
};
|
||||||
|
expect( () => footerValidator.parse( invalidFooter ) )
|
||||||
|
.toThrowErrorMatchingInlineSnapshot( `
|
||||||
|
"[
|
||||||
|
{
|
||||||
|
\\"code\\": \\"custom\\",
|
||||||
|
\\"message\\": \\"Footer not part of allowed list\\",
|
||||||
|
\\"path\\": [
|
||||||
|
\\"slug\\"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]"
|
||||||
|
` );
|
||||||
|
} );
|
||||||
|
|
||||||
|
it( 'should not validate when slug is not a string', () => {
|
||||||
|
const invalidType = { slug: 123 };
|
||||||
|
expect( () => footerValidator.parse( invalidType ) )
|
||||||
|
.toThrowErrorMatchingInlineSnapshot( `
|
||||||
|
"[
|
||||||
|
{
|
||||||
|
\\"code\\": \\"invalid_type\\",
|
||||||
|
\\"expected\\": \\"string\\",
|
||||||
|
\\"received\\": \\"number\\",
|
||||||
|
\\"path\\": [
|
||||||
|
\\"slug\\"
|
||||||
|
],
|
||||||
|
\\"message\\": \\"Expected string, received number\\"
|
||||||
|
}
|
||||||
|
]"
|
||||||
|
` );
|
||||||
|
} );
|
||||||
|
} );
|
|
@ -0,0 +1,47 @@
|
||||||
|
/**
|
||||||
|
* Internal dependencies
|
||||||
|
*/
|
||||||
|
import { headerValidator } from '..';
|
||||||
|
|
||||||
|
describe( 'headerValidator', () => {
|
||||||
|
it( 'should validate when header is part of the allowed list', () => {
|
||||||
|
const validHeader = { slug: 'woocommerce-blocks/header-large' };
|
||||||
|
expect( () => headerValidator.parse( validHeader ) ).not.toThrow();
|
||||||
|
} );
|
||||||
|
|
||||||
|
it( 'should not validate when header is not part of the allowed list', () => {
|
||||||
|
const invalidHeader = {
|
||||||
|
slug: 'woocommerce-blocks/header-large-invalid',
|
||||||
|
};
|
||||||
|
expect( () => headerValidator.parse( invalidHeader ) )
|
||||||
|
.toThrowErrorMatchingInlineSnapshot( `
|
||||||
|
"[
|
||||||
|
{
|
||||||
|
\\"code\\": \\"custom\\",
|
||||||
|
\\"message\\": \\"Header not part of allowed list\\",
|
||||||
|
\\"path\\": [
|
||||||
|
\\"slug\\"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]"
|
||||||
|
` );
|
||||||
|
} );
|
||||||
|
|
||||||
|
it( 'should not validate when slug is not a string', () => {
|
||||||
|
const invalidType = { slug: 123 };
|
||||||
|
expect( () => headerValidator.parse( invalidType ) )
|
||||||
|
.toThrowErrorMatchingInlineSnapshot( `
|
||||||
|
"[
|
||||||
|
{
|
||||||
|
\\"code\\": \\"invalid_type\\",
|
||||||
|
\\"expected\\": \\"string\\",
|
||||||
|
\\"received\\": \\"number\\",
|
||||||
|
\\"path\\": [
|
||||||
|
\\"slug\\"
|
||||||
|
],
|
||||||
|
\\"message\\": \\"Expected string, received number\\"
|
||||||
|
}
|
||||||
|
]"
|
||||||
|
` );
|
||||||
|
} );
|
||||||
|
} );
|
|
@ -1,16 +1,32 @@
|
||||||
|
/* eslint-disable @woocommerce/dependency-group */
|
||||||
|
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
||||||
/**
|
/**
|
||||||
* External dependencies
|
* External dependencies
|
||||||
*/
|
*/
|
||||||
import { __experimentalRequestJetpackToken as requestJetpackToken } from '@woocommerce/ai';
|
import { __experimentalRequestJetpackToken as requestJetpackToken } from '@woocommerce/ai';
|
||||||
import apiFetch from '@wordpress/api-fetch';
|
import apiFetch from '@wordpress/api-fetch';
|
||||||
import { recordEvent } from '@woocommerce/tracks';
|
import { recordEvent } from '@woocommerce/tracks';
|
||||||
|
import { OPTIONS_STORE_NAME } from '@woocommerce/data';
|
||||||
import { Sender, assign, createMachine } from 'xstate';
|
import { Sender, assign, createMachine } from 'xstate';
|
||||||
|
import { dispatch, resolveSelect } 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.
|
||||||
|
import { mergeBaseAndUserConfigs } from '@wordpress/edit-site/build-module/components/global-styles/global-styles-provider';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal dependencies
|
* Internal dependencies
|
||||||
*/
|
*/
|
||||||
import { designWithAiStateMachineContext } from './types';
|
import { designWithAiStateMachineContext } from './types';
|
||||||
import { lookAndTone } from './prompts';
|
import { lookAndTone } from './prompts';
|
||||||
|
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,
|
||||||
|
LARGE_BUSINESS_TEMPLATES,
|
||||||
|
SMALL_MEDIUM_BUSINESS_TEMPLATES,
|
||||||
|
} from '../assembler-hub/hooks/use-home-templates';
|
||||||
|
|
||||||
const browserPopstateHandler =
|
const browserPopstateHandler =
|
||||||
() => ( sendBack: Sender< { type: 'EXTERNAL_URL_UPDATE' } > ) => {
|
() => ( sendBack: Sender< { type: 'EXTERNAL_URL_UPDATE' } > ) => {
|
||||||
|
@ -192,8 +208,185 @@ export const queryAiEndpoint = createMachine(
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const updateStorePatterns = async (
|
||||||
|
context: designWithAiStateMachineContext
|
||||||
|
) => {
|
||||||
|
try {
|
||||||
|
// TODO: Probably move this to a more appropriate place with a check. We should set this when the user granted permissions during the onboarding phase.
|
||||||
|
await dispatch( OPTIONS_STORE_NAME ).updateOptions( {
|
||||||
|
woocommerce_blocks_allow_ai_connection: true,
|
||||||
|
} );
|
||||||
|
|
||||||
|
await apiFetch( {
|
||||||
|
path: '/wc/store/patterns',
|
||||||
|
method: 'POST',
|
||||||
|
data: {
|
||||||
|
business_description:
|
||||||
|
context.businessInfoDescription.descriptionText,
|
||||||
|
},
|
||||||
|
} );
|
||||||
|
} catch ( error ) {
|
||||||
|
recordEvent( 'customize_your_store_update_store_pattern_api_error', {
|
||||||
|
error: error instanceof Error ? error.message : 'unknown',
|
||||||
|
} );
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Update the current global styles of theme
|
||||||
|
const updateGlobalStyles = async ( {
|
||||||
|
colorPaletteName = COLOR_PALETTES[ 0 ].title,
|
||||||
|
fontPairingName = FONT_PAIRINGS[ 0 ].title,
|
||||||
|
}: {
|
||||||
|
colorPaletteName: string;
|
||||||
|
fontPairingName: string;
|
||||||
|
} ) => {
|
||||||
|
const colorPalette = COLOR_PALETTES.find(
|
||||||
|
( palette ) => palette.title === colorPaletteName
|
||||||
|
);
|
||||||
|
const fontPairing = FONT_PAIRINGS.find(
|
||||||
|
( pairing ) => pairing.title === fontPairingName
|
||||||
|
);
|
||||||
|
|
||||||
|
const globalStylesId = await resolveSelect(
|
||||||
|
coreStore
|
||||||
|
// @ts-ignore No types for this exist yet.
|
||||||
|
).__experimentalGetCurrentGlobalStylesId();
|
||||||
|
|
||||||
|
// @ts-ignore No types for this exist yet.
|
||||||
|
const { saveEntityRecord } = dispatch( coreStore );
|
||||||
|
|
||||||
|
await saveEntityRecord(
|
||||||
|
'root',
|
||||||
|
'globalStyles',
|
||||||
|
{
|
||||||
|
id: globalStylesId,
|
||||||
|
styles: mergeBaseAndUserConfigs(
|
||||||
|
colorPalette?.styles || {},
|
||||||
|
fontPairing?.styles || {}
|
||||||
|
),
|
||||||
|
settings: mergeBaseAndUserConfigs(
|
||||||
|
colorPalette?.settings || {},
|
||||||
|
fontPairing?.settings || {}
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
throwOnError: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Update the current theme template
|
||||||
|
const updateTemplate = async ( {
|
||||||
|
headerSlug,
|
||||||
|
businessSize,
|
||||||
|
homepageTemplateId,
|
||||||
|
footerSlug,
|
||||||
|
}: {
|
||||||
|
headerSlug: string;
|
||||||
|
businessSize: 'SMB' | 'LB';
|
||||||
|
homepageTemplateId:
|
||||||
|
| keyof typeof SMALL_MEDIUM_BUSINESS_TEMPLATES
|
||||||
|
| keyof typeof LARGE_BUSINESS_TEMPLATES;
|
||||||
|
footerSlug: string;
|
||||||
|
} ) => {
|
||||||
|
const patterns = ( await resolveSelect(
|
||||||
|
coreStore
|
||||||
|
// @ts-ignore No types for this exist yet.
|
||||||
|
).getBlockPatterns() ) as Pattern[];
|
||||||
|
|
||||||
|
const patternsByName = patternsToNameMap( patterns );
|
||||||
|
|
||||||
|
const headerPattern = patternsByName[ headerSlug ];
|
||||||
|
const footerPattern = patternsByName[ footerSlug ];
|
||||||
|
|
||||||
|
const homepageTemplate = getTemplatePatterns(
|
||||||
|
businessSize === 'SMB'
|
||||||
|
? SMALL_MEDIUM_BUSINESS_TEMPLATES[ homepageTemplateId ]
|
||||||
|
: LARGE_BUSINESS_TEMPLATES[ homepageTemplateId ],
|
||||||
|
patternsByName
|
||||||
|
);
|
||||||
|
|
||||||
|
const content = [ headerPattern, ...homepageTemplate, footerPattern ]
|
||||||
|
.filter( Boolean )
|
||||||
|
.map( ( pattern ) => pattern.content )
|
||||||
|
.join( '\n\n' );
|
||||||
|
|
||||||
|
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
|
||||||
|
) => {
|
||||||
|
try {
|
||||||
|
await updateGlobalStyles( {
|
||||||
|
colorPaletteName: context.aiSuggestions.defaultColorPalette.default,
|
||||||
|
fontPairingName: context.aiSuggestions.fontPairing,
|
||||||
|
} );
|
||||||
|
recordEvent( 'customize_your_store_ai_update_global_styles_success' );
|
||||||
|
} catch ( error ) {
|
||||||
|
// TODO handle error
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.error( error );
|
||||||
|
recordEvent(
|
||||||
|
'customize_your_store_ai_update_global_styles_response_error',
|
||||||
|
{
|
||||||
|
error: error instanceof Error ? error.message : 'unknown',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await updateTemplate( {
|
||||||
|
headerSlug: context.aiSuggestions.header,
|
||||||
|
// TODO: Get from context
|
||||||
|
businessSize: 'SMB',
|
||||||
|
homepageTemplateId: 'template1',
|
||||||
|
footerSlug: context.aiSuggestions.footer,
|
||||||
|
} );
|
||||||
|
recordEvent( 'customize_your_store_ai_update_template_success' );
|
||||||
|
} catch ( error ) {
|
||||||
|
// TODO handle error
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.error( error );
|
||||||
|
recordEvent( 'customize_your_store_ai_update_template_response_error', {
|
||||||
|
error: error instanceof Error ? error.message : 'unknown',
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
// @ts-ignore No types for this exist yet.
|
||||||
|
const { invalidateResolutionForStoreSelector } = dispatch( coreStore );
|
||||||
|
|
||||||
|
// Invalid the selectors so that the new template/style are used in assembler hub.
|
||||||
|
invalidateResolutionForStoreSelector( 'getEntityRecord' );
|
||||||
|
invalidateResolutionForStoreSelector(
|
||||||
|
'__experimentalGetCurrentGlobalStylesId'
|
||||||
|
);
|
||||||
|
invalidateResolutionForStoreSelector( '__experimentalGetTemplateForLink' );
|
||||||
|
};
|
||||||
|
|
||||||
export const services = {
|
export const services = {
|
||||||
getLookAndTone,
|
getLookAndTone,
|
||||||
browserPopstateHandler,
|
browserPopstateHandler,
|
||||||
queryAiEndpoint,
|
queryAiEndpoint,
|
||||||
|
assembleSite,
|
||||||
|
updateStorePatterns,
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,6 +11,8 @@ import {
|
||||||
designWithAiStateMachineContext,
|
designWithAiStateMachineContext,
|
||||||
designWithAiStateMachineEvents,
|
designWithAiStateMachineEvents,
|
||||||
FontPairing,
|
FontPairing,
|
||||||
|
Header,
|
||||||
|
Footer,
|
||||||
ColorPaletteResponse,
|
ColorPaletteResponse,
|
||||||
} from './types';
|
} from './types';
|
||||||
import {
|
import {
|
||||||
|
@ -21,7 +23,12 @@ import {
|
||||||
} from './pages';
|
} from './pages';
|
||||||
import { actions } from './actions';
|
import { actions } from './actions';
|
||||||
import { services } from './services';
|
import { services } from './services';
|
||||||
import { defaultColorPalette, fontPairings } from './prompts';
|
import {
|
||||||
|
defaultColorPalette,
|
||||||
|
fontPairings,
|
||||||
|
defaultHeader,
|
||||||
|
defaultFooter,
|
||||||
|
} from './prompts';
|
||||||
|
|
||||||
export const hasStepInUrl = (
|
export const hasStepInUrl = (
|
||||||
_ctx: unknown,
|
_ctx: unknown,
|
||||||
|
@ -72,6 +79,8 @@ export const designWithAiStateMachineDefinition = createMachine(
|
||||||
aiSuggestions: {
|
aiSuggestions: {
|
||||||
defaultColorPalette: {} as ColorPaletteResponse,
|
defaultColorPalette: {} as ColorPaletteResponse,
|
||||||
fontPairing: '' as FontPairing[ 'pair_name' ],
|
fontPairing: '' as FontPairing[ 'pair_name' ],
|
||||||
|
header: '' as Header[ 'slug' ],
|
||||||
|
footer: '' as Footer[ 'slug' ],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
initial: 'navigate',
|
initial: 'navigate',
|
||||||
|
@ -273,48 +282,158 @@ export const designWithAiStateMachineDefinition = createMachine(
|
||||||
type: 'parallel',
|
type: 'parallel',
|
||||||
states: {
|
states: {
|
||||||
chooseColorPairing: {
|
chooseColorPairing: {
|
||||||
invoke: {
|
initial: 'pending',
|
||||||
src: 'queryAiEndpoint',
|
states: {
|
||||||
data: ( context ) => {
|
pending: {
|
||||||
return {
|
invoke: {
|
||||||
...defaultColorPalette,
|
src: 'queryAiEndpoint',
|
||||||
prompt: defaultColorPalette.prompt(
|
data: ( context ) => {
|
||||||
context.businessInfoDescription
|
return {
|
||||||
.descriptionText,
|
...defaultColorPalette,
|
||||||
context.lookAndFeel.choice,
|
prompt: defaultColorPalette.prompt(
|
||||||
context.toneOfVoice.choice
|
context
|
||||||
),
|
.businessInfoDescription
|
||||||
};
|
.descriptionText,
|
||||||
},
|
context.lookAndFeel
|
||||||
onDone: {
|
.choice,
|
||||||
actions: [
|
context.toneOfVoice
|
||||||
'assignDefaultColorPalette',
|
.choice
|
||||||
],
|
),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
onDone: {
|
||||||
|
actions: [
|
||||||
|
'assignDefaultColorPalette',
|
||||||
|
],
|
||||||
|
target: 'success',
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
success: { type: 'final' },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
chooseFontPairing: {
|
chooseFontPairing: {
|
||||||
invoke: {
|
initial: 'pending',
|
||||||
src: 'queryAiEndpoint',
|
states: {
|
||||||
data: ( context ) => {
|
pending: {
|
||||||
return {
|
invoke: {
|
||||||
...fontPairings,
|
src: 'queryAiEndpoint',
|
||||||
prompt: fontPairings.prompt(
|
data: ( context ) => {
|
||||||
context.businessInfoDescription
|
return {
|
||||||
.descriptionText,
|
...fontPairings,
|
||||||
context.lookAndFeel.choice,
|
prompt: fontPairings.prompt(
|
||||||
context.toneOfVoice.choice
|
context
|
||||||
),
|
.businessInfoDescription
|
||||||
};
|
.descriptionText,
|
||||||
|
context.lookAndFeel
|
||||||
|
.choice,
|
||||||
|
context.toneOfVoice
|
||||||
|
.choice
|
||||||
|
),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
onDone: {
|
||||||
|
actions: [
|
||||||
|
'assignFontPairing',
|
||||||
|
],
|
||||||
|
target: 'success',
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
onDone: {
|
success: { type: 'final' },
|
||||||
actions: [ 'assignFontPairing' ],
|
},
|
||||||
|
},
|
||||||
|
chooseHeader: {
|
||||||
|
initial: 'pending',
|
||||||
|
states: {
|
||||||
|
pending: {
|
||||||
|
invoke: {
|
||||||
|
src: 'queryAiEndpoint',
|
||||||
|
data: ( context ) => {
|
||||||
|
return {
|
||||||
|
...defaultHeader,
|
||||||
|
prompt: defaultHeader.prompt(
|
||||||
|
context
|
||||||
|
.businessInfoDescription
|
||||||
|
.descriptionText,
|
||||||
|
context.lookAndFeel
|
||||||
|
.choice,
|
||||||
|
context.toneOfVoice
|
||||||
|
.choice
|
||||||
|
),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
onDone: {
|
||||||
|
actions: [ 'assignHeader' ],
|
||||||
|
target: 'success',
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
success: { type: 'final' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
chooseFooter: {
|
||||||
|
initial: 'pending',
|
||||||
|
states: {
|
||||||
|
pending: {
|
||||||
|
invoke: {
|
||||||
|
src: 'queryAiEndpoint',
|
||||||
|
data: ( context ) => {
|
||||||
|
return {
|
||||||
|
...defaultFooter,
|
||||||
|
prompt: defaultFooter.prompt(
|
||||||
|
context
|
||||||
|
.businessInfoDescription
|
||||||
|
.descriptionText,
|
||||||
|
context.lookAndFeel
|
||||||
|
.choice,
|
||||||
|
context.toneOfVoice
|
||||||
|
.choice
|
||||||
|
),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
onDone: {
|
||||||
|
actions: [ 'assignFooter' ],
|
||||||
|
target: 'success',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
success: { type: 'final' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
updateStorePatterns: {
|
||||||
|
initial: 'pending',
|
||||||
|
states: {
|
||||||
|
pending: {
|
||||||
|
invoke: {
|
||||||
|
src: 'updateStorePatterns',
|
||||||
|
onDone: {
|
||||||
|
target: 'success',
|
||||||
|
},
|
||||||
|
onError: {
|
||||||
|
// TODO: handle error
|
||||||
|
target: 'success',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
success: { type: 'final' },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
onDone: 'postApiCallLoader',
|
||||||
|
},
|
||||||
|
postApiCallLoader: {
|
||||||
|
invoke: {
|
||||||
|
src: 'assembleSite',
|
||||||
|
onDone: {
|
||||||
|
actions: [
|
||||||
|
sendParent( () => ( {
|
||||||
|
type: 'THEME_SUGGESTED',
|
||||||
|
} ) ),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
postApiCallLoader: {},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -19,6 +19,13 @@ jest.mock( '@woocommerce/ai', () => ( {
|
||||||
|
|
||||||
jest.mock( '@wordpress/api-fetch', () => jest.fn() );
|
jest.mock( '@wordpress/api-fetch', () => jest.fn() );
|
||||||
|
|
||||||
|
jest.mock(
|
||||||
|
'@wordpress/edit-site/build-module/components/global-styles/global-styles-provider',
|
||||||
|
() => ( {
|
||||||
|
mergeBaseAndUserConfigs: jest.fn(),
|
||||||
|
} )
|
||||||
|
);
|
||||||
|
|
||||||
describe( 'getCompletion', () => {
|
describe( 'getCompletion', () => {
|
||||||
beforeEach( () => {
|
beforeEach( () => {
|
||||||
jest.clearAllMocks();
|
jest.clearAllMocks();
|
||||||
|
|
|
@ -7,8 +7,10 @@ import { z } from 'zod';
|
||||||
*/
|
*/
|
||||||
import {
|
import {
|
||||||
colorPaletteValidator,
|
colorPaletteValidator,
|
||||||
colorPaletteResponseValidator,
|
|
||||||
fontChoiceValidator,
|
fontChoiceValidator,
|
||||||
|
headerValidator,
|
||||||
|
footerValidator,
|
||||||
|
colorPaletteResponseValidator,
|
||||||
} from './prompts';
|
} from './prompts';
|
||||||
|
|
||||||
export type designWithAiStateMachineContext = {
|
export type designWithAiStateMachineContext = {
|
||||||
|
@ -24,6 +26,8 @@ export type designWithAiStateMachineContext = {
|
||||||
aiSuggestions: {
|
aiSuggestions: {
|
||||||
defaultColorPalette: ColorPaletteResponse;
|
defaultColorPalette: ColorPaletteResponse;
|
||||||
fontPairing: FontPairing[ 'pair_name' ];
|
fontPairing: FontPairing[ 'pair_name' ];
|
||||||
|
header: Header[ 'slug' ];
|
||||||
|
footer: Footer[ 'slug' ];
|
||||||
};
|
};
|
||||||
// If we require more data from options, previously provided core profiler details,
|
// If we require more data from options, previously provided core profiler details,
|
||||||
// we can retrieve them in preBusinessInfoDescription and then assign them here
|
// we can retrieve them in preBusinessInfoDescription and then assign them here
|
||||||
|
@ -60,3 +64,7 @@ export type ColorPaletteResponse = z.infer<
|
||||||
>;
|
>;
|
||||||
|
|
||||||
export type FontPairing = z.infer< typeof fontChoiceValidator >;
|
export type FontPairing = z.infer< typeof fontChoiceValidator >;
|
||||||
|
|
||||||
|
export type Header = z.infer< typeof headerValidator >;
|
||||||
|
|
||||||
|
export type Footer = z.infer< typeof footerValidator >;
|
||||||
|
|
|
@ -4,7 +4,11 @@
|
||||||
import { Sender, createMachine } from 'xstate';
|
import { Sender, createMachine } from 'xstate';
|
||||||
import { useEffect, useMemo, useState } from '@wordpress/element';
|
import { useEffect, useMemo, useState } from '@wordpress/element';
|
||||||
import { useMachine, useSelector } from '@xstate/react';
|
import { useMachine, useSelector } from '@xstate/react';
|
||||||
import { getQuery, updateQueryString } from '@woocommerce/navigation';
|
import {
|
||||||
|
getNewPath,
|
||||||
|
getQuery,
|
||||||
|
updateQueryString,
|
||||||
|
} from '@woocommerce/navigation';
|
||||||
import { OPTIONS_STORE_NAME } from '@woocommerce/data';
|
import { OPTIONS_STORE_NAME } from '@woocommerce/data';
|
||||||
import { dispatch } from '@wordpress/data';
|
import { dispatch } from '@wordpress/data';
|
||||||
|
|
||||||
|
@ -59,6 +63,10 @@ const updateQueryStep = (
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const redirectToWooHome = () => {
|
||||||
|
window.location.href = getNewPath( {}, '/', {} );
|
||||||
|
};
|
||||||
|
|
||||||
const markTaskComplete = async () => {
|
const markTaskComplete = async () => {
|
||||||
return dispatch( OPTIONS_STORE_NAME ).updateOptions( {
|
return dispatch( OPTIONS_STORE_NAME ).updateOptions( {
|
||||||
woocommerce_admin_customize_store_completed: 'yes',
|
woocommerce_admin_customize_store_completed: 'yes',
|
||||||
|
@ -78,6 +86,7 @@ const browserPopstateHandler =
|
||||||
|
|
||||||
export const machineActions = {
|
export const machineActions = {
|
||||||
updateQueryStep,
|
updateQueryStep,
|
||||||
|
redirectToWooHome,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const customizeStoreStateMachineActions = {
|
export const customizeStoreStateMachineActions = {
|
||||||
|
@ -184,7 +193,7 @@ export const customizeStoreStateMachineDefinition = createMachine( {
|
||||||
target: 'assemblerHub',
|
target: 'assemblerHub',
|
||||||
},
|
},
|
||||||
CLICKED_ON_BREADCRUMB: {
|
CLICKED_ON_BREADCRUMB: {
|
||||||
target: 'backToHomescreen',
|
actions: 'redirectToWooHome',
|
||||||
},
|
},
|
||||||
SELECTED_NEW_THEME: {
|
SELECTED_NEW_THEME: {
|
||||||
target: 'appearanceTask',
|
target: 'appearanceTask',
|
||||||
|
@ -263,11 +272,10 @@ export const customizeStoreStateMachineDefinition = createMachine( {
|
||||||
},
|
},
|
||||||
on: {
|
on: {
|
||||||
GO_BACK_TO_HOME: {
|
GO_BACK_TO_HOME: {
|
||||||
target: 'backToHomescreen',
|
actions: 'redirectToWooHome',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
backToHomescreen: {},
|
|
||||||
appearanceTask: {},
|
appearanceTask: {},
|
||||||
},
|
},
|
||||||
} );
|
} );
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: minor
|
|
||||||
Type: fix
|
|
||||||
|
|
||||||
Avoid a fatal error on the order received page if the order ID is not for a valid order.
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: minor
|
|
||||||
Type: add
|
|
||||||
|
|
||||||
Add tags (or general taxonomy ) block
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: major
|
|
||||||
Type: update
|
|
||||||
|
|
||||||
Update the simple product template implementation to use the product form template API.
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: minor
|
|
||||||
Type: add
|
|
||||||
|
|
||||||
Add support for slug auto generation to the create attribute endpoint
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: minor
|
|
||||||
Type: update
|
|
||||||
|
|
||||||
Update intro screen for the new Customize Your Store task
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: minor
|
|
||||||
Type: add
|
|
||||||
|
|
||||||
Add AI wizard business info step for Customize Your Store task
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: minor
|
|
||||||
Type: add
|
|
||||||
|
|
||||||
Add sidebar to customize your store task.
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: minor
|
|
||||||
Type: add
|
|
||||||
|
|
||||||
Add component to Customize Your Store task.
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: minor
|
|
||||||
Type: fix
|
|
||||||
|
|
||||||
Add Variation options section back to the product blocks template
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: minor
|
|
||||||
Type: add
|
|
||||||
|
|
||||||
Create a plugin to enable Variations feature #40027
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: minor
|
|
||||||
Type: add
|
|
||||||
|
|
||||||
Add has_price param to the variations REST API query.
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: minor
|
|
||||||
Type: add
|
|
||||||
|
|
||||||
Add variable product experiment
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: minor
|
|
||||||
Type: update
|
|
||||||
|
|
||||||
Update Remote Inbox Notifications to add in and !in comparison operators for comparing values against arrays
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: minor
|
|
||||||
Type: add
|
|
||||||
|
|
||||||
Add Tracks events to Appearance > Themes screen
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
Significance: minor
|
||||||
|
Type: add
|
||||||
|
|
||||||
|
Persist CYS AI assembled site
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: minor
|
|
||||||
Type: add
|
|
||||||
|
|
||||||
Add after_add_block and after_remove block hooks to the block template API.
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: minor
|
|
||||||
Type: add
|
|
||||||
|
|
||||||
Add woocommerce_block_template_register action.
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
Significance: minor
|
||||||
|
Type: add
|
||||||
|
|
||||||
|
Call wc store patterns API to update patterns for CYS
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: minor
|
|
||||||
Type: add
|
|
||||||
|
|
||||||
Add customize store assembler hub
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: minor
|
|
||||||
Type: add
|
|
||||||
|
|
||||||
Implement customize store assembler hub - logo feature
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: minor
|
|
||||||
Type: add
|
|
||||||
|
|
||||||
Add customize store assembler hub onboarding tour
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: minor
|
|
||||||
Type: add
|
|
||||||
|
|
||||||
Add customize store AI wizard call for best colour palette suggestions.
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: minor
|
|
||||||
Type: add
|
|
||||||
|
|
||||||
Add customize store AI wizard call for color palette suggestion
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: minor
|
|
||||||
Type: add
|
|
||||||
|
|
||||||
Implemented loader design for Customize your store - Design with AI
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: minor
|
|
||||||
Type: add
|
|
||||||
|
|
||||||
Add customize store AI wizard call for font pairing suggestion
|
|
|
@ -1,4 +1,4 @@
|
||||||
Significance: minor
|
Significance: minor
|
||||||
Type: add
|
Type: add
|
||||||
|
|
||||||
Add customize store - fonts
|
Add cys ai header/footer
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: patch
|
|
||||||
Type: add
|
|
||||||
|
|
||||||
Add track events to customize store AI wizard
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: minor
|
|
||||||
Type: update
|
|
||||||
|
|
||||||
Added xstate scaffolding for AI Wizard in customize your store feature
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: patch
|
|
||||||
Type: add
|
|
||||||
|
|
||||||
Add tracks to CYS assembler-hub and hide pages sidebar screen
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: minor
|
|
||||||
Type: add
|
|
||||||
|
|
||||||
Add customize store color palettes
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: minor
|
|
||||||
Type: add
|
|
||||||
|
|
||||||
Add customize store transitional screen
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: patch
|
|
||||||
Type: add
|
|
||||||
|
|
||||||
Add track events to customize store transitional page
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: minor
|
|
||||||
Type: add
|
|
||||||
|
|
||||||
Added URL navigation support to customize-store feature
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: minor
|
|
||||||
Type: add
|
|
||||||
|
|
||||||
Add a filter to OrdersTableQuery to allow overriding of HPOS queries.
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: patch
|
|
||||||
Type: add
|
|
||||||
|
|
||||||
Add filter woocommerce_hpos_enable_sync_on_read to disable sync on read with HPOS sync enabled.
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: major
|
|
||||||
Type: enhancement
|
|
||||||
|
|
||||||
Enable HPOS by default for new installs.
|
|
|
@ -1,5 +0,0 @@
|
||||||
Significance: patch
|
|
||||||
Type: dev
|
|
||||||
Comment: Update CONTRIBUTING.md file to include instructions on how adding unit, API and E2E tests when applicable.
|
|
||||||
|
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: minor
|
|
||||||
Type: add
|
|
||||||
|
|
||||||
Made ai completion for look and tone more robust and added tracks
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: patch
|
|
||||||
Type: add
|
|
||||||
|
|
||||||
Add new e2e test to cover My Account Addresses section
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: patch
|
|
||||||
Type: add
|
|
||||||
|
|
||||||
Add new e2e test for Shopper My Account Downloads section
|
|
|
@ -1,5 +0,0 @@
|
||||||
Significance: patch
|
|
||||||
Type: dev
|
|
||||||
Comment: Adds regression test for https://github.com/woocommerce/woocommerce/pull/40221.
|
|
||||||
|
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: minor
|
|
||||||
Type: tweak
|
|
||||||
|
|
||||||
Add order property to every block in SimpleProductTemplate
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: minor
|
|
||||||
Type: add
|
|
||||||
|
|
||||||
Add ability to remove blocks from templates.
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: minor
|
|
||||||
Type: add
|
|
||||||
|
|
||||||
Adds new action hook `woocommerce_pay_order_before_payment` to the `checkout/form-pay.php` template.
|
|
|
@ -1,5 +0,0 @@
|
||||||
Significance: patch
|
|
||||||
Type: add
|
|
||||||
Comment: Updated perf test and workflow for extra site
|
|
||||||
|
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: patch
|
|
||||||
Type: dev
|
|
||||||
|
|
||||||
Fix for a couple of flaky API tests on daily runs
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: patch
|
|
||||||
Type: dev
|
|
||||||
|
|
||||||
Run a full reset on API daily test site
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: patch
|
|
||||||
Type: dev
|
|
||||||
|
|
||||||
Fixes and enables API test suite to run on daily CI run against alternate host
|
|
|
@ -1,5 +0,0 @@
|
||||||
Significance: patch
|
|
||||||
Type: dev
|
|
||||||
Comment: Bump PHP version where it was missed in #39820.
|
|
||||||
|
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: patch
|
|
||||||
Type: dev
|
|
||||||
|
|
||||||
Bump required PHP version to 7.4
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: minor
|
|
||||||
Type: dev
|
|
||||||
|
|
||||||
Add notice to "track inventory" toggle #40011
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: minor
|
|
||||||
Type: dev
|
|
||||||
|
|
||||||
Add some basic E2E tests for Assembler Hub
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: minor
|
|
||||||
Type: add
|
|
||||||
|
|
||||||
Add header customization to the Assembler Hub
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: patch
|
|
||||||
Type: dev
|
|
||||||
|
|
||||||
Added documentation for the Core Profiler
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: minor
|
|
||||||
Type: dev
|
|
||||||
|
|
||||||
Refactored core profiler loader to be more generalizable and moved to @woocommerce/onboarding
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: minor
|
|
||||||
Type: dev
|
|
||||||
|
|
||||||
Cleanup: remove the unused is_feature_visible and show_feature methods.
|
|
|
@ -1,5 +0,0 @@
|
||||||
Significance: patch
|
|
||||||
Type: tweak
|
|
||||||
Comment: This change only tweaks a few comments.
|
|
||||||
|
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: patch
|
|
||||||
Type: dev
|
|
||||||
|
|
||||||
Add new E2E test covering shopper product page and make Product-related tests granular (separated test files)
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: patch
|
|
||||||
Type: dev
|
|
||||||
|
|
||||||
Add job to post Slack summary of plugin test results in "Smoke test daily" workflow.
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: patch
|
|
||||||
Type: dev
|
|
||||||
|
|
||||||
Fix flakiness around the `Turn off the new product form` menu item.
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: patch
|
|
||||||
Type: dev
|
|
||||||
|
|
||||||
Remove "WP Latest-2" from release tests.
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: patch
|
|
||||||
Type: dev
|
|
||||||
|
|
||||||
Adds test to check required fields on checkout
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: patch
|
|
||||||
Type: dev
|
|
||||||
|
|
||||||
Updates Playwright from 1.33 to 1.37.1
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: major
|
|
||||||
Type: update
|
|
||||||
|
|
||||||
We have completely redesigned the In-app Marketplace.
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: patch
|
|
||||||
Type: fix
|
|
||||||
|
|
||||||
Eliminate an unnecessary redirect when the geo hash isalready set to the correct value.
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: patch
|
|
||||||
Type: fix
|
|
||||||
|
|
||||||
Display search results subtitle in HPOS list table view.
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: patch
|
|
||||||
Type: fix
|
|
||||||
|
|
||||||
[HPOS] Modify query to have less characters before the `FROM` keyword.
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: patch
|
|
||||||
Type: fix
|
|
||||||
|
|
||||||
Fix minor layout shift in the core profiler.
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: major
|
|
||||||
Type: fix
|
|
||||||
|
|
||||||
Remove use of woocommerce-page class within WooCommerce Admin pages, replaced with woocommerce-admin-page.
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: patch
|
|
||||||
Type: fix
|
|
||||||
|
|
||||||
Properly convert local time date queries to UTC in the HPOS datastore.
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: patch
|
|
||||||
Type: fix
|
|
||||||
|
|
||||||
Fix a bug where updating store location doesn't update store currency.
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: patch
|
|
||||||
Type: update
|
|
||||||
|
|
||||||
Update use of preventLeavingProductForm with new function changes.
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: patch
|
|
||||||
Type: fix
|
|
||||||
|
|
||||||
FIx WC Admin pages are empty for WP 6.2 and below.
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: patch
|
|
||||||
Type: tweak
|
|
||||||
|
|
||||||
Adds an informative tooltip to the Account Details section of the Direct Bank Transfer settings.
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: patch
|
|
||||||
Type: fix
|
|
||||||
|
|
||||||
Fix cached refund not deleted when the refund is deleted with HPOS active
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: patch
|
|
||||||
Type: enhancement
|
|
||||||
|
|
||||||
Add CLI commands to enable or disable HPOS.
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: patch
|
|
||||||
Type: fix
|
|
||||||
|
|
||||||
Remove COT enable requirement from sync and verify command.
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: patch
|
|
||||||
Type: fix
|
|
||||||
|
|
||||||
Avoid string<>int comparison in products bought query to avoid results with customer_id = 0.
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: patch
|
|
||||||
Type: fix
|
|
||||||
|
|
||||||
Fix CYS `__experimentalReapplyBlockTypeFilters` is not a function
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: patch
|
|
||||||
Type: fix
|
|
||||||
|
|
||||||
Fix customize your store task header button
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: patch
|
|
||||||
Type: fix
|
|
||||||
|
|
||||||
Addressed visual tweaks for CYS in response to feedback from 12th Sept
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: patch
|
|
||||||
Type: fix
|
|
||||||
|
|
||||||
Fix customize store white screen bug in WP 6.3
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: patch
|
|
||||||
Type: fix
|
|
||||||
|
|
||||||
[HPOS] Support deleting metadata just by meta id.
|
|
|
@ -1,5 +0,0 @@
|
||||||
Significance: patch
|
|
||||||
Type: tweak
|
|
||||||
Comment: Just a typo fix.
|
|
||||||
|
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
Significance: patch
|
|
||||||
Type: fix
|
|
||||||
|
|
||||||
[HPOS]Fix duplicate meta handling by passing meta_value|unique in post calls
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue