woocommerce/main/plugins/woocommerce-admin/client/customize-store/assembler-hub/index.tsx

197 lines
6.5 KiB
TypeScript
Raw Permalink Normal View History

// Reference: https://github.com/WordPress/gutenberg/tree/v16.4.0/packages/edit-site/src/index.js
/* eslint-disable @woocommerce/dependency-group */
/* eslint-disable @typescript-eslint/ban-ts-comment */
/**
* External dependencies
*/
import { createContext, useEffect, useRef, useState } from '@wordpress/element';
import { dispatch } from '@wordpress/data';
import {
__experimentalFetchLinkSuggestions as fetchLinkSuggestions,
__experimentalFetchUrlData as fetchUrlData,
// @ts-ignore No types for this exist yet.
} from '@wordpress/core-data';
// eslint-disable-next-line @woocommerce/dependency-group
import {
registerCoreBlocks,
__experimentalGetCoreBlocks,
// @ts-ignore No types for this exist yet.
} from '@wordpress/block-library';
import {
getBlockType,
// @ts-ignore No types for this exist yet.
store as blocksStore,
} from '@wordpress/blocks';
// @ts-ignore No types for this exist yet.
import { privateApis as routerPrivateApis } from '@wordpress/router';
// @ts-ignore No types for this exist yet.
import { unlock } from '@wordpress/edit-site/build-module/lock-unlock';
// @ts-ignore No types for this exist yet.
import { ShortcutProvider } from '@wordpress/keyboard-shortcuts';
// @ts-ignore No types for this exist yet.
import { store as preferencesStore } from '@wordpress/preferences';
// @ts-ignore No types for this exist yet.
import { store as editorStore } from '@wordpress/editor';
// @ts-ignore No types for this exist yet.
import { store as editSiteStore } from '@wordpress/edit-site/build-module/store';
// @ts-ignore No types for this exist yet.
import { GlobalStylesProvider } from '@wordpress/edit-site/build-module/components/global-styles/global-styles-provider';
import { MediaUpload } from '@wordpress/media-utils';
import { addFilter } from '@wordpress/hooks';
/**
* Internal dependencies
*/
import { CustomizeStoreComponent } from '../types';
import { Layout } from './layout';
import './style.scss';
import { GoBackWarningModal } from './go-back-warning-modal';
import { onBackButtonClicked } from '../utils';
import { getNewPath } from '@woocommerce/navigation';
import useBodyClass from '../hooks/use-body-class';
import { OptInSubscribe } from './opt-in/opt-in';
import { OptInContextProvider } from './opt-in/context';
import './tracking';
const { RouterProvider } = unlock( routerPrivateApis );
addFilter(
'editor.MediaUpload',
'woo/customize-store/assembler-hub',
() => MediaUpload
);
type CustomizeStoreComponentProps = Parameters< CustomizeStoreComponent >[ 0 ];
export const CustomizeStoreContext = createContext< {
sendEvent: CustomizeStoreComponentProps[ 'sendEvent' ];
context: CustomizeStoreComponentProps[ 'context' ];
currentState: CustomizeStoreComponentProps[ 'currentState' ];
} >( {
sendEvent: () => {},
context: {} as CustomizeStoreComponentProps[ 'context' ],
currentState: 'assemblerHub',
} );
export type events =
| { type: 'FINISH_CUSTOMIZATION' }
| { type: 'GO_BACK_TO_DESIGN_WITH_AI' }
| { type: 'GO_BACK_TO_DESIGN_WITHOUT_AI' };
const initializeAssembleHub = () => {
if ( ! window.wcBlockSettings ) {
// eslint-disable-next-line no-console
console.warn(
'window.blockSettings not found. Skipping initialization.'
);
return;
}
// Set up the block editor settings.
const settings = window.wcBlockSettings;
settings.__experimentalFetchLinkSuggestions = (
search: string,
searchOptions: {
isInitialSuggestions: boolean;
type: 'attachment' | 'post' | 'term' | 'post-format';
subtype: string;
page: number;
perPage: number;
}
) => fetchLinkSuggestions( search, searchOptions, settings );
settings.__experimentalFetchRichUrlData = fetchUrlData;
const reapplyBlockTypeFilters =
// @ts-ignore No types for this exist yet.
dispatch( blocksStore ).__experimentalReapplyBlockTypeFilters || // GB < 16.6
// @ts-ignore No types for this exist yet.
dispatch( blocksStore ).reapplyBlockTypeFilters; // GB >= 16.6
reapplyBlockTypeFilters();
const coreBlocks = __experimentalGetCoreBlocks().filter(
( { name }: { name: string } ) =>
name !== 'core/freeform' && ! getBlockType( name )
);
registerCoreBlocks( coreBlocks );
// @ts-ignore No types for this exist yet.
dispatch( blocksStore ).setFreeformFallbackBlockName( 'core/html' );
// @ts-ignore No types for this exist yet.
dispatch( preferencesStore ).setDefaults( 'core/edit-site', {
editorMode: 'visual',
fixedToolbar: false,
focusMode: false,
distractionFree: false,
keepCaretInsideBlock: false,
welcomeGuide: false,
welcomeGuideStyles: false,
welcomeGuidePage: false,
welcomeGuideTemplate: false,
showListViewByDefault: false,
showBlockBreadcrumbs: true,
} );
// @ts-ignore No types for this exist yet.
dispatch( editSiteStore ).updateSettings( settings );
// @ts-ignore No types for this exist yet.
dispatch( editorStore ).updateEditorSettings( {
defaultTemplateTypes: settings.defaultTemplateTypes,
defaultTemplatePartAreas: settings.defaultTemplatePartAreas,
} );
// Prevent the default browser action for files dropped outside of dropzones.
window.addEventListener( 'dragover', ( e ) => e.preventDefault(), false );
window.addEventListener( 'drop', ( e ) => e.preventDefault(), false );
unlock( dispatch( editSiteStore ) ).setCanvasMode( 'view' );
};
export const AssemblerHub: CustomizeStoreComponent = ( props ) => {
const isInitializedRef = useRef( false );
useBodyClass( 'woocommerce-assembler' );
if ( ! isInitializedRef.current ) {
initializeAssembleHub();
isInitializedRef.current = true;
}
const [ showExitModal, setShowExitModal ] = useState( false );
useEffect( () => {
onBackButtonClicked( () => setShowExitModal( true ) );
}, [] );
// @ts-expect-error temp fix
// Since we load the assember hub in an iframe, we don't have access to
// xstate's context values.
// This is the best workaround I can think of for now.
// Set the aiOnline value from the parent window so that any child components
// can access it.
props.context.aiOnline = window.parent?.window.cys_aiOnline;
return (
<>
{ showExitModal && (
<GoBackWarningModal
setOpenWarningModal={ setShowExitModal }
onExitClicked={ () => {
window.location.href = getNewPath( {}, '/', {} );
} }
/>
) }
<CustomizeStoreContext.Provider value={ props }>
<ShortcutProvider style={ { height: '100%' } }>
<OptInContextProvider>
<GlobalStylesProvider>
<RouterProvider>
<Layout />
</RouterProvider>
<OptInSubscribe />
</GlobalStylesProvider>
</OptInContextProvider>
</ShortcutProvider>
</CustomizeStoreContext.Provider>
</>
);
};