2024-01-11 14:32:16 +00:00
|
|
|
/**
|
|
|
|
* External dependencies
|
|
|
|
*/
|
|
|
|
import { Sender } from 'xstate';
|
2024-01-18 14:52:49 +00:00
|
|
|
import apiFetch from '@wordpress/api-fetch';
|
2024-02-08 15:08:38 +00:00
|
|
|
import { resolveSelect, dispatch } from '@wordpress/data';
|
2024-02-28 14:47:31 +00:00
|
|
|
import { OPTIONS_STORE_NAME } from '@woocommerce/data';
|
2024-02-08 15:08:38 +00:00
|
|
|
// @ts-expect-error -- No types for this exist yet.
|
|
|
|
// eslint-disable-next-line @woocommerce/dependency-group
|
|
|
|
import { mergeBaseAndUserConfigs } from '@wordpress/edit-site/build-module/components/global-styles/global-styles-provider';
|
|
|
|
// @ts-expect-error -- No types for this exist yet.
|
|
|
|
// eslint-disable-next-line @woocommerce/dependency-group
|
|
|
|
import { store as coreStore } from '@wordpress/core-data';
|
2024-01-17 14:09:12 +00:00
|
|
|
|
2024-01-11 14:32:16 +00:00
|
|
|
/**
|
|
|
|
* Internal dependencies
|
|
|
|
*/
|
|
|
|
import { updateTemplate } from '../data/actions';
|
|
|
|
import { HOMEPAGE_TEMPLATES } from '../data/homepageTemplates';
|
2024-01-17 14:09:12 +00:00
|
|
|
import { installAndActivateTheme as setTheme } from '../data/service';
|
|
|
|
import { THEME_SLUG } from '../data/constants';
|
2024-02-01 17:16:12 +00:00
|
|
|
import { FontFace, FontFamily } from '../types/font';
|
|
|
|
import {
|
|
|
|
FontCollectionResponse,
|
|
|
|
installFontFace,
|
|
|
|
installFontFamily,
|
|
|
|
getFontFamiliesAndFontFaceToInstall,
|
|
|
|
} from './fonts';
|
2024-02-08 15:08:38 +00:00
|
|
|
import { COLOR_PALETTES } from '../assembler-hub/sidebar/global-styles/color-palette-variations/constants';
|
2024-02-28 14:47:31 +00:00
|
|
|
import {
|
|
|
|
FONT_PAIRINGS_WHEN_AI_IS_OFFLINE,
|
|
|
|
FONT_PAIRINGS_WHEN_USER_DID_NOT_ALLOW_TRACKING,
|
|
|
|
} from '../assembler-hub/sidebar/global-styles/font-pairing-variations/constants';
|
2024-03-15 10:09:31 +00:00
|
|
|
import { DesignWithoutAIStateMachineContext, Theme } from './types';
|
2024-04-23 17:38:06 +00:00
|
|
|
import { trackEvent } from '../tracking';
|
2024-01-11 14:32:16 +00:00
|
|
|
|
|
|
|
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 );
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2024-03-15 10:09:31 +00:00
|
|
|
const getActiveThemeWithRetries = async (): Promise< Theme[] | null > => {
|
|
|
|
let retries = 3;
|
|
|
|
|
|
|
|
while ( retries > 0 ) {
|
|
|
|
const activeThemes = ( await resolveSelect( 'core' ).getEntityRecords(
|
|
|
|
'root',
|
|
|
|
'theme',
|
|
|
|
{ status: 'active' },
|
|
|
|
true
|
|
|
|
) ) as Theme[];
|
|
|
|
if ( activeThemes ) {
|
|
|
|
return activeThemes;
|
|
|
|
}
|
|
|
|
|
|
|
|
retries--;
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
};
|
|
|
|
|
|
|
|
const getCurrentGlobalStylesId = async (): Promise< number | null > => {
|
|
|
|
const activeThemes = await getActiveThemeWithRetries();
|
|
|
|
if ( ! activeThemes ) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
const currentThemeLinks = activeThemes[ 0 ]?._links;
|
|
|
|
const url = currentThemeLinks?.[ 'wp:user-global-styles' ]?.[ 0 ]?.href;
|
|
|
|
const globalStylesObject = ( await apiFetch( { url } ) ) as { id: number };
|
|
|
|
|
|
|
|
return globalStylesObject.id;
|
|
|
|
};
|
|
|
|
|
|
|
|
const updateGlobalStylesWithDefaultValues = async (
|
|
|
|
context: DesignWithoutAIStateMachineContext
|
|
|
|
) => {
|
|
|
|
// We are using the first color palette and font pairing that are displayed on the color/font picker on the sidebar.
|
|
|
|
const colorPalette = COLOR_PALETTES[ 0 ];
|
|
|
|
|
|
|
|
const allowTracking =
|
|
|
|
( await resolveSelect( OPTIONS_STORE_NAME ).getOption(
|
|
|
|
'woocommerce_allow_tracking'
|
|
|
|
) ) === 'yes';
|
|
|
|
|
|
|
|
const fontPairing =
|
|
|
|
context.isFontLibraryAvailable && allowTracking
|
|
|
|
? FONT_PAIRINGS_WHEN_AI_IS_OFFLINE[ 0 ]
|
|
|
|
: FONT_PAIRINGS_WHEN_USER_DID_NOT_ALLOW_TRACKING[ 0 ];
|
|
|
|
|
|
|
|
const globalStylesId = await getCurrentGlobalStylesId();
|
|
|
|
if ( ! globalStylesId ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// @ts-expect-error 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,
|
|
|
|
}
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
const installAndActivateTheme = async (
|
|
|
|
context: DesignWithoutAIStateMachineContext
|
|
|
|
) => {
|
2024-01-17 14:09:12 +00:00
|
|
|
try {
|
|
|
|
await setTheme( THEME_SLUG );
|
2024-03-15 10:09:31 +00:00
|
|
|
await updateGlobalStylesWithDefaultValues( context );
|
2024-01-17 14:09:12 +00:00
|
|
|
} catch ( error ) {
|
2024-04-23 17:38:06 +00:00
|
|
|
trackEvent(
|
2024-01-17 14:09:12 +00:00
|
|
|
'customize_your_store__no_ai_install_and_activate_theme_error',
|
|
|
|
{
|
|
|
|
theme: THEME_SLUG,
|
|
|
|
error: error instanceof Error ? error.message : 'unknown',
|
|
|
|
}
|
|
|
|
);
|
|
|
|
throw error;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2024-06-10 13:00:33 +00:00
|
|
|
export const installPatterns = async () => {
|
|
|
|
if ( ! window.wcAdminFeatures[ 'pattern-toolkit-full-composability' ] ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-06-05 13:09:35 +00:00
|
|
|
const isTrackingEnabled = window.wcTracks?.isEnabled || false;
|
|
|
|
if ( ! isTrackingEnabled ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
const { success } = await apiFetch< {
|
|
|
|
success: boolean;
|
|
|
|
} >( {
|
|
|
|
path: '/wc/private/patterns',
|
|
|
|
method: 'POST',
|
|
|
|
} );
|
|
|
|
|
|
|
|
if ( ! success ) {
|
|
|
|
throw new Error( 'Fetching patterns failed' );
|
|
|
|
}
|
|
|
|
} catch ( error ) {
|
|
|
|
throw error;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2024-02-01 17:16:12 +00:00
|
|
|
const installFontFamilies = async () => {
|
2024-02-13 13:03:06 +00:00
|
|
|
const isTrackingEnabled = window.wcTracks?.isEnabled || false;
|
|
|
|
if ( ! isTrackingEnabled ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-02-01 17:16:12 +00:00
|
|
|
try {
|
|
|
|
const installedFontFamily = ( await resolveSelect(
|
|
|
|
'core'
|
|
|
|
).getEntityRecords( 'postType', 'wp_font_family', {
|
|
|
|
per_page: -1,
|
|
|
|
} ) ) as Array< {
|
|
|
|
id: number;
|
|
|
|
font_faces: Array< number >;
|
|
|
|
font_family_settings: FontFamily;
|
|
|
|
} >;
|
|
|
|
|
|
|
|
const installedFontFamiliesWithFontFaces = await Promise.all(
|
|
|
|
installedFontFamily.map( async ( fontFamily ) => {
|
|
|
|
const fontFaces = await apiFetch< Array< FontFace > >( {
|
|
|
|
path: `/wp/v2/font-families/${ fontFamily.id }/font-faces`,
|
|
|
|
method: 'GET',
|
|
|
|
} );
|
|
|
|
|
|
|
|
return {
|
|
|
|
...fontFamily,
|
|
|
|
font_face: fontFaces,
|
|
|
|
};
|
|
|
|
} )
|
|
|
|
);
|
|
|
|
|
|
|
|
const fontCollection = await apiFetch< FontCollectionResponse >( {
|
2024-02-13 13:15:52 +00:00
|
|
|
path: `/wp/v2/font-collections/google-fonts`,
|
2024-02-01 17:16:12 +00:00
|
|
|
method: 'GET',
|
|
|
|
} );
|
|
|
|
|
|
|
|
const { fontFacesToInstall, fontFamiliesWithFontFacesToInstall } =
|
|
|
|
getFontFamiliesAndFontFaceToInstall(
|
|
|
|
fontCollection,
|
|
|
|
installedFontFamiliesWithFontFaces
|
|
|
|
);
|
|
|
|
|
|
|
|
const fontFamiliesWithFontFaceToInstallPromises =
|
|
|
|
fontFamiliesWithFontFacesToInstall.map( async ( fontFamily ) => {
|
|
|
|
const fontFamilyResponse = await installFontFamily(
|
|
|
|
fontFamily
|
|
|
|
);
|
|
|
|
return Promise.all(
|
|
|
|
fontFamily.fontFace.map( async ( fontFace, index ) => {
|
|
|
|
installFontFace(
|
|
|
|
{
|
|
|
|
...fontFace,
|
|
|
|
fontFamilyId: fontFamilyResponse.id,
|
|
|
|
},
|
|
|
|
index
|
|
|
|
);
|
|
|
|
} )
|
|
|
|
);
|
|
|
|
} );
|
|
|
|
|
|
|
|
const fontFacesToInstallPromises =
|
|
|
|
fontFacesToInstall.map( installFontFace );
|
|
|
|
|
|
|
|
await Promise.all( [
|
|
|
|
...fontFamiliesWithFontFaceToInstallPromises,
|
|
|
|
...fontFacesToInstallPromises,
|
|
|
|
] );
|
|
|
|
} catch ( error ) {
|
|
|
|
throw error;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2024-01-18 14:52:49 +00:00
|
|
|
const createProducts = async () => {
|
|
|
|
try {
|
|
|
|
const { success } = await apiFetch< {
|
|
|
|
success: boolean;
|
|
|
|
} >( {
|
|
|
|
path: `/wc-admin/onboarding/products`,
|
|
|
|
method: 'POST',
|
|
|
|
} );
|
|
|
|
|
|
|
|
if ( ! success ) {
|
|
|
|
throw new Error( 'Product creation failed' );
|
|
|
|
}
|
|
|
|
} catch ( error ) {
|
|
|
|
throw error;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2024-03-18 15:49:41 +00:00
|
|
|
export const enableTracking = async () => {
|
|
|
|
try {
|
|
|
|
await dispatch( OPTIONS_STORE_NAME ).updateOptions( {
|
|
|
|
woocommerce_allow_tracking: 'yes',
|
|
|
|
} );
|
|
|
|
window.wcTracks.isEnabled = true;
|
|
|
|
} catch ( error ) {
|
|
|
|
throw error;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2024-01-11 14:32:16 +00:00
|
|
|
export const services = {
|
|
|
|
assembleSite,
|
|
|
|
browserPopstateHandler,
|
2024-01-17 14:09:12 +00:00
|
|
|
installAndActivateTheme,
|
2024-01-18 14:52:49 +00:00
|
|
|
createProducts,
|
2024-02-01 17:16:12 +00:00
|
|
|
installFontFamilies,
|
2024-06-05 13:09:35 +00:00
|
|
|
installPatterns,
|
2024-02-08 15:08:38 +00:00
|
|
|
updateGlobalStylesWithDefaultValues,
|
2024-03-18 15:49:41 +00:00
|
|
|
enableTracking,
|
2024-01-11 14:32:16 +00:00
|
|
|
};
|