336 lines
8.2 KiB
TypeScript
336 lines
8.2 KiB
TypeScript
|
/**
|
|||
|
* External dependencies
|
|||
|
*/
|
|||
|
import { useEffect, useState } from '@wordpress/element';
|
|||
|
import { __ } from '@wordpress/i18n';
|
|||
|
import { TourKit, TourKitTypes } from '@woocommerce/components';
|
|||
|
import { recordEvent } from '@woocommerce/tracks';
|
|||
|
import qs from 'qs';
|
|||
|
|
|||
|
/**
|
|||
|
* Internal dependencies
|
|||
|
*/
|
|||
|
import { useTmceIframeFocusStyle } from './use-tmce-iframe-focus-style';
|
|||
|
import { useActiveEditorType } from './use-active-editor-type';
|
|||
|
import {
|
|||
|
bindEnableGuideModeClickEvent,
|
|||
|
waitUntilElementTopNotChange,
|
|||
|
} from './utils';
|
|||
|
import {
|
|||
|
ProductTourStepName,
|
|||
|
useProductStepChange,
|
|||
|
} from './use-product-step-change';
|
|||
|
import { useTrackPublishButton } from './use-track-publish-button';
|
|||
|
|
|||
|
const getTourConfig = ( {
|
|||
|
isExcerptEditorTmceActive,
|
|||
|
isContentEditorTmceActive,
|
|||
|
closeHandler,
|
|||
|
onNextStepHandler,
|
|||
|
}: {
|
|||
|
isExcerptEditorTmceActive: boolean;
|
|||
|
isContentEditorTmceActive: boolean;
|
|||
|
closeHandler: TourKitTypes.CloseHandler;
|
|||
|
onNextStepHandler: ( currentStepIndex: number ) => void;
|
|||
|
} ): TourKitTypes.WooConfig => {
|
|||
|
return {
|
|||
|
placement: 'bottom-start',
|
|||
|
options: {
|
|||
|
effects: {
|
|||
|
spotlight: {
|
|||
|
interactivity: {
|
|||
|
enabled: true,
|
|||
|
rootElementSelector: '#wpwrap',
|
|||
|
},
|
|||
|
},
|
|||
|
arrowIndicator: true,
|
|||
|
autoScroll: {
|
|||
|
behavior: 'auto',
|
|||
|
block: 'center',
|
|||
|
},
|
|||
|
liveResize: {
|
|||
|
mutation: true,
|
|||
|
resize: true,
|
|||
|
rootElementSelector: '#wpwrap',
|
|||
|
},
|
|||
|
},
|
|||
|
popperModifiers: [
|
|||
|
{
|
|||
|
name: 'arrow',
|
|||
|
options: {
|
|||
|
padding: ( {
|
|||
|
popper,
|
|||
|
}: {
|
|||
|
popper: { width: number };
|
|||
|
} ) => {
|
|||
|
return {
|
|||
|
// Align the arrow to the left of the popper.
|
|||
|
right: popper.width - 34,
|
|||
|
};
|
|||
|
},
|
|||
|
},
|
|||
|
},
|
|||
|
],
|
|||
|
callbacks: {
|
|||
|
onNextStep: onNextStepHandler,
|
|||
|
},
|
|||
|
},
|
|||
|
steps: [
|
|||
|
{
|
|||
|
referenceElements: {
|
|||
|
desktop: '#title',
|
|||
|
},
|
|||
|
focusElement: {
|
|||
|
desktop: '#title',
|
|||
|
},
|
|||
|
meta: {
|
|||
|
name: 'product-name',
|
|||
|
heading: __( 'Product name', 'woocommerce' ),
|
|||
|
descriptions: {
|
|||
|
desktop: __(
|
|||
|
'Start typing your new product name here. This will be what your customers will see in your store.',
|
|||
|
'woocommerce'
|
|||
|
),
|
|||
|
},
|
|||
|
},
|
|||
|
},
|
|||
|
{
|
|||
|
referenceElements: {
|
|||
|
desktop: '#postdivrich',
|
|||
|
},
|
|||
|
focusElement: {
|
|||
|
iframe: isContentEditorTmceActive
|
|||
|
? '#content_ifr'
|
|||
|
: undefined,
|
|||
|
desktop: isContentEditorTmceActive
|
|||
|
? '#tinymce'
|
|||
|
: '#wp-content-editor-container > .wp-editor-area',
|
|||
|
},
|
|||
|
meta: {
|
|||
|
name: 'product-description',
|
|||
|
heading: __(
|
|||
|
'Add your product description',
|
|||
|
'woocommerce'
|
|||
|
),
|
|||
|
descriptions: {
|
|||
|
desktop: __(
|
|||
|
'Start typing your new product name here. Add your full product description here. Describe your product in detail.',
|
|||
|
'woocommerce'
|
|||
|
),
|
|||
|
},
|
|||
|
},
|
|||
|
},
|
|||
|
{
|
|||
|
referenceElements: {
|
|||
|
desktop: '#woocommerce-product-data',
|
|||
|
},
|
|||
|
focusElement: {
|
|||
|
desktop: '#_regular_price',
|
|||
|
},
|
|||
|
meta: {
|
|||
|
name: 'product-data',
|
|||
|
heading: __( 'Add your product data', 'woocommerce' ),
|
|||
|
descriptions: {
|
|||
|
desktop: __(
|
|||
|
'Use the tabs to switch between sections and insert product details. Start by adding your product price.',
|
|||
|
'woocommerce'
|
|||
|
),
|
|||
|
},
|
|||
|
},
|
|||
|
},
|
|||
|
{
|
|||
|
referenceElements: {
|
|||
|
desktop: '#postexcerpt',
|
|||
|
},
|
|||
|
focusElement: {
|
|||
|
iframe: isExcerptEditorTmceActive
|
|||
|
? '#excerpt_ifr'
|
|||
|
: undefined,
|
|||
|
desktop: isExcerptEditorTmceActive
|
|||
|
? '#tinymce'
|
|||
|
: '#wp-excerpt-editor-container > .wp-editor-area',
|
|||
|
},
|
|||
|
meta: {
|
|||
|
name: 'product-short-description',
|
|||
|
heading: __(
|
|||
|
'Add your short product description',
|
|||
|
'woocommerce'
|
|||
|
),
|
|||
|
descriptions: {
|
|||
|
desktop: __(
|
|||
|
'Type a quick summary for your product here. This will appear on the product page right under the product name.',
|
|||
|
'woocommerce'
|
|||
|
),
|
|||
|
},
|
|||
|
},
|
|||
|
},
|
|||
|
{
|
|||
|
referenceElements: {
|
|||
|
desktop: '#postimagediv',
|
|||
|
},
|
|||
|
focusElement: {
|
|||
|
desktop: '#set-post-thumbnail',
|
|||
|
},
|
|||
|
meta: {
|
|||
|
name: 'product-image',
|
|||
|
heading: __( 'Add your product image', 'woocommerce' ),
|
|||
|
descriptions: {
|
|||
|
desktop: __(
|
|||
|
'Upload an image to your product here. Ideally a JPEG or PNG about 600 px wide or bigger. This image will be shown in your store’s catalog.',
|
|||
|
'woocommerce'
|
|||
|
),
|
|||
|
},
|
|||
|
},
|
|||
|
},
|
|||
|
{
|
|||
|
referenceElements: {
|
|||
|
desktop: '#tagsdiv-product_tag',
|
|||
|
},
|
|||
|
focusElement: {
|
|||
|
desktop: '#new-tag-product_tag',
|
|||
|
},
|
|||
|
meta: {
|
|||
|
name: 'product-tags',
|
|||
|
heading: __( 'Add your product tags', 'woocommerce' ),
|
|||
|
descriptions: {
|
|||
|
desktop: __(
|
|||
|
'Add your product tags here. Tags are a method of labeling your products to make them easier for customers to find. For example, if you sell clothing, and you have a lot of cat prints, you could make a tag for “cat.”',
|
|||
|
'woocommerce'
|
|||
|
),
|
|||
|
},
|
|||
|
},
|
|||
|
},
|
|||
|
{
|
|||
|
referenceElements: {
|
|||
|
desktop: '#product_catdiv',
|
|||
|
},
|
|||
|
meta: {
|
|||
|
name: 'product-categories',
|
|||
|
heading: __( 'Add your product categories', 'woocommerce' ),
|
|||
|
descriptions: {
|
|||
|
desktop: __(
|
|||
|
'Add your product categories here. Assign categories to your products to make them easier to browse through and find in your store.',
|
|||
|
'woocommerce'
|
|||
|
),
|
|||
|
},
|
|||
|
},
|
|||
|
},
|
|||
|
{
|
|||
|
referenceElements: {
|
|||
|
desktop: '#submitdiv',
|
|||
|
},
|
|||
|
focusElement: {
|
|||
|
desktop: '#submitdiv',
|
|||
|
},
|
|||
|
meta: {
|
|||
|
name: 'publish',
|
|||
|
heading: __( 'Publish your product 🎉', 'woocommerce' ),
|
|||
|
descriptions: {
|
|||
|
desktop: __(
|
|||
|
'Good work! Now you can publish your product to your store by hitting the “Publish” button or keep editing it.',
|
|||
|
'woocommerce'
|
|||
|
),
|
|||
|
},
|
|||
|
primaryButton: {
|
|||
|
text: __( 'Keep editing', 'woocommerce' ),
|
|||
|
},
|
|||
|
},
|
|||
|
},
|
|||
|
],
|
|||
|
closeHandler,
|
|||
|
};
|
|||
|
};
|
|||
|
|
|||
|
export const ProductTour = () => {
|
|||
|
const [ showTour, setShowTour ] = useState< boolean >( false );
|
|||
|
const { setIsLoaded, hasUpdatedInfo } = useProductStepChange();
|
|||
|
|
|||
|
const { isTmce: isContentEditorTmceActive } = useActiveEditorType( {
|
|||
|
editorWrapSelector: '#wp-content-wrap',
|
|||
|
} );
|
|||
|
const { isTmce: isExcerptEditorTmceActive } = useActiveEditorType( {
|
|||
|
editorWrapSelector: '#wp-excerpt-wrap',
|
|||
|
} );
|
|||
|
|
|||
|
const { style: contentTmceIframeFocusStyle } = useTmceIframeFocusStyle( {
|
|||
|
isActive: showTour && isContentEditorTmceActive,
|
|||
|
iframeSelector: '#content_ifr',
|
|||
|
} );
|
|||
|
const { style: excerptTmceIframeFocusStyle } = useTmceIframeFocusStyle( {
|
|||
|
isActive: showTour && isExcerptEditorTmceActive,
|
|||
|
iframeSelector: '#excerpt_ifr',
|
|||
|
} );
|
|||
|
|
|||
|
const tourConfig = getTourConfig( {
|
|||
|
isContentEditorTmceActive,
|
|||
|
isExcerptEditorTmceActive,
|
|||
|
closeHandler: ( steps, stepIndex ) => {
|
|||
|
setShowTour( false );
|
|||
|
if ( steps.length - 1 === stepIndex ) {
|
|||
|
recordEvent( 'walkthrough_product_completed' );
|
|||
|
} else {
|
|||
|
recordEvent( 'walkthrough_product_dismissed', {
|
|||
|
step_name: steps[ stepIndex ].meta.name,
|
|||
|
} );
|
|||
|
}
|
|||
|
},
|
|||
|
onNextStepHandler: ( stepIndex ) => {
|
|||
|
const stepName = tourConfig.steps[ stepIndex ].meta.name;
|
|||
|
|
|||
|
// This records all "next" steps and ignores the final "publish" step.
|
|||
|
recordEvent( 'walkthrough_product_step_completed', {
|
|||
|
step_name: stepName,
|
|||
|
added_info: hasUpdatedInfo( stepName as ProductTourStepName )
|
|||
|
? 'yes'
|
|||
|
: 'no',
|
|||
|
} );
|
|||
|
},
|
|||
|
} );
|
|||
|
|
|||
|
useEffect( () => {
|
|||
|
bindEnableGuideModeClickEvent( ( e ) => {
|
|||
|
e.preventDefault();
|
|||
|
setShowTour( true );
|
|||
|
recordEvent( 'walkthrough_product_enable_button_click' );
|
|||
|
} );
|
|||
|
|
|||
|
const query = qs.parse( window.location.search.slice( 1 ) );
|
|||
|
if ( query && query.tutorial === 'true' ) {
|
|||
|
const intervalId = waitUntilElementTopNotChange(
|
|||
|
tourConfig.steps[ 0 ].referenceElements?.desktop || '',
|
|||
|
() => {
|
|||
|
setShowTour( true );
|
|||
|
recordEvent( 'walkthrough_product_view', {
|
|||
|
spotlight: 'yes',
|
|||
|
product_template: 'physical',
|
|||
|
} );
|
|||
|
setIsLoaded( true );
|
|||
|
},
|
|||
|
500
|
|||
|
);
|
|||
|
return () => clearInterval( intervalId );
|
|||
|
}
|
|||
|
// only run once
|
|||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|||
|
}, [] );
|
|||
|
|
|||
|
useTrackPublishButton( showTour );
|
|||
|
|
|||
|
if ( ! showTour ) {
|
|||
|
return null;
|
|||
|
}
|
|||
|
|
|||
|
return (
|
|||
|
<>
|
|||
|
<style>
|
|||
|
{ contentTmceIframeFocusStyle }
|
|||
|
{ excerptTmceIframeFocusStyle }
|
|||
|
{ `.wp-editor-area:focus {
|
|||
|
border: 1.5px solid #007CBA;
|
|||
|
}` }
|
|||
|
</style>
|
|||
|
<TourKit config={ tourConfig } />
|
|||
|
</>
|
|||
|
);
|
|||
|
};
|