diff --git a/plugins/woocommerce-blocks/assets/js/blocks/classic-template/archive-product.ts b/plugins/woocommerce-blocks/assets/js/blocks/classic-template/archive-product.ts
index e9a6b4bb30f..f38439ae12a 100644
--- a/plugins/woocommerce-blocks/assets/js/blocks/classic-template/archive-product.ts
+++ b/plugins/woocommerce-blocks/assets/js/blocks/classic-template/archive-product.ts
@@ -19,7 +19,7 @@ import {
} from '../product-query/constants';
import { VARIATION_NAME as productsVariationName } from '../product-query/variations/product-query';
import { createArchiveTitleBlock, createRowBlock } from './utils';
-import { type InheritedAttributes } from './types';
+import { OnClickCallbackParameter, type InheritedAttributes } from './types';
const createProductsBlock = ( inheritedAttributes: InheritedAttributes ) =>
createBlock(
@@ -71,7 +71,7 @@ const getDescriptionAllowingConversion = ( templateTitle: string ) =>
sprintf(
/* translators: %s is the template title */
__(
- "This block serves as a placeholder for your %s. We recommend upgrading to the Products block for more features to edit your products visually. Don't worry, you can always revert back.",
+ 'Transform this template into multiple blocks so you can add, remove, reorder, and customize your %s template.',
'woo-gutenberg-products-block'
),
templateTitle
@@ -96,17 +96,69 @@ const getDescription = ( templateTitle: string, canConvert: boolean ) => {
};
const getButtonLabel = () =>
- __( 'Upgrade to Products block', 'woo-gutenberg-products-block' );
+ __( 'Transform into blocks', 'woo-gutenberg-products-block' );
+
+const onClickCallback = ( {
+ clientId,
+ attributes,
+ getBlocks,
+ replaceBlock,
+ selectBlock,
+}: OnClickCallbackParameter ) => {
+ replaceBlock( clientId, getBlockifiedTemplate( attributes ) );
+
+ const blocks = getBlocks();
+
+ const groupBlock = blocks.find(
+ ( block ) =>
+ block.name === 'core/group' &&
+ block.innerBlocks.some(
+ ( innerBlock ) =>
+ innerBlock.name === 'woocommerce/store-notices'
+ )
+ );
+
+ if ( groupBlock ) {
+ selectBlock( groupBlock.clientId );
+ }
+};
+
+const onClickCallbackWithTermDescription = ( {
+ clientId,
+ attributes,
+ getBlocks,
+ replaceBlock,
+ selectBlock,
+}: OnClickCallbackParameter ) => {
+ replaceBlock( clientId, getBlockifiedTemplate( attributes, true ) );
+
+ const blocks = getBlocks();
+
+ const groupBlock = blocks.find(
+ ( block ) =>
+ block.name === 'core/group' &&
+ block.innerBlocks.some(
+ ( innerBlock ) =>
+ innerBlock.name === 'woocommerce/store-notices'
+ )
+ );
+
+ if ( groupBlock ) {
+ selectBlock( groupBlock.clientId );
+ }
+};
export const blockifiedProductCatalogConfig = {
getBlockifiedTemplate,
isConversionPossible,
getDescription,
getButtonLabel,
+ onClickCallback,
};
export const blockifiedProductTaxonomyConfig = {
getBlockifiedTemplate: getBlockifiedTemplateWithTermDescription,
+ onClickCallback: onClickCallbackWithTermDescription,
isConversionPossible,
getDescription,
getButtonLabel,
diff --git a/plugins/woocommerce-blocks/assets/js/blocks/classic-template/editor.scss b/plugins/woocommerce-blocks/assets/js/blocks/classic-template/editor.scss
index 9ff1b017c70..c2997f22d81 100644
--- a/plugins/woocommerce-blocks/assets/js/blocks/classic-template/editor.scss
+++ b/plugins/woocommerce-blocks/assets/js/blocks/classic-template/editor.scss
@@ -1,12 +1,14 @@
:where(.wp-block-woocommerce-legacy-template) {
margin-left: auto;
margin-right: auto;
- max-width: 1000px;
}
.wp-block-woocommerce-classic-template__placeholder-copy {
+ display: flex;
+ flex-direction: column;
max-width: 900px;
- margin-bottom: 30px;
+ width: 400px;
+ margin: auto;
}
.wp-block-woocommerce-classic-template__placeholder-warning {
@@ -15,9 +17,12 @@
}
.wp-block-woocommerce-classic-template__placeholder-wireframe {
- width: 100%;
height: 250px;
background: #e5e5e5;
+ display: flex;
+ flex-wrap: wrap;
+ gap: $gap-large;
+ margin: auto;
@media only screen and (min-width: 768px) {
height: auto;
@@ -27,7 +32,7 @@
.wp-block-woocommerce-classic-template__placeholder .wp-block-woocommerce-classic-template__placeholder-image {
display: none;
- width: 100%;
+ width: 400px;
height: auto;
@media only screen and (min-width: 768px) {
@@ -35,14 +40,18 @@
}
}
-
-.wp-block-woocommerce-classic-template__placeholder-wireframe {
- display: flex;
- flex-direction: column;
-}
-
.wp-block-woocommerce-classic-template__placeholder-migration-button-container {
justify-content: center;
align-items: center;
margin: 0 auto;
}
+
+.wp-block-woocommerce-classic-template__placeholder-copy__icon-container {
+ display: flex;
+ align-items: center;
+ gap: $gap-small;
+
+ span {
+ @include font-size(larger);
+ }
+}
diff --git a/plugins/woocommerce-blocks/assets/js/blocks/classic-template/index.tsx b/plugins/woocommerce-blocks/assets/js/blocks/classic-template/index.tsx
index 2df71d93f5e..9271db20e14 100644
--- a/plugins/woocommerce-blocks/assets/js/blocks/classic-template/index.tsx
+++ b/plugins/woocommerce-blocks/assets/js/blocks/classic-template/index.tsx
@@ -2,6 +2,8 @@
* External dependencies
*/
import {
+ BlockInstance,
+ createBlock,
getBlockType,
registerBlockType,
unregisterBlockType,
@@ -11,12 +13,18 @@ import {
isExperimentalBuild,
WC_BLOCKS_IMAGE_URL,
} from '@woocommerce/block-settings';
-import { useBlockProps } from '@wordpress/block-editor';
-import { Button, Placeholder } from '@wordpress/components';
+import {
+ useBlockProps,
+ BlockPreview,
+ store as blockEditorStore,
+} from '@wordpress/block-editor';
+import { Button, Placeholder, Popover } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import { box, Icon } from '@wordpress/icons';
-import { select, useDispatch, subscribe } from '@wordpress/data';
-import { useEffect } from '@wordpress/element';
+import { useDispatch, subscribe, useSelect, select } from '@wordpress/data';
+import { useEffect, useMemo, useState } from '@wordpress/element';
+import { store as noticesStore } from '@wordpress/notices';
+import { useEntityRecord } from '@wordpress/core-data';
/**
* Internal dependencies
@@ -47,6 +55,7 @@ const blockifiedFallbackConfig = {
getBlockifiedTemplate: () => [],
getDescription: () => '',
getButtonLabel: () => '',
+ onClickCallback: () => void 0,
};
const conversionConfig: { [ key: string ]: BlockifiedTemplateConfig } = {
@@ -57,19 +66,53 @@ const conversionConfig: { [ key: string ]: BlockifiedTemplateConfig } = {
fallback: blockifiedFallbackConfig,
};
+const pickBlockClientIds = ( blocks: Array< BlockInstance > ) =>
+ blocks.reduce< Array< string > >( ( acc, block ) => {
+ if ( block.name === 'core/template-part' ) {
+ return acc;
+ }
+
+ return [ ...acc, block.clientId ];
+ }, [] );
+
const Edit = ( {
clientId,
attributes,
setAttributes,
}: BlockEditProps< Attributes > ) => {
- const { replaceBlock } = useDispatch( 'core/block-editor' );
+ const { replaceBlock, selectBlock, replaceBlocks } =
+ useDispatch( blockEditorStore );
+
+ const { getBlocks, editedPostId } = useSelect( ( sel ) => {
+ return {
+ getBlocks: sel( blockEditorStore ).getBlocks,
+ editedPostId: sel( 'core/edit-site' ).getEditedPostId(),
+ };
+ }, [] );
+
+ const template = useEntityRecord< {
+ slug: string;
+ title: {
+ rendered?: string;
+ row: string;
+ };
+ } >( 'postType', 'wp_template', editedPostId );
+
+ const { createInfoNotice } = useDispatch( noticesStore );
+
+ const blocks = getBlocks();
+
+ const clientIds = useMemo( () => {
+ pickBlockClientIds( blocks );
+ }, [ blocks ] );
const blockProps = useBlockProps();
const templateDetails = getTemplateDetailsBySlug(
attributes.template,
TEMPLATES
);
- const templateTitle = templateDetails?.title ?? attributes.template;
+ const templateTitle =
+ template.record?.title.rendered?.toLowerCase() ?? attributes.template;
const templatePlaceholder = templateDetails?.placeholder ?? 'fallback';
const templateType = templateDetails?.type ?? 'fallback';
@@ -83,40 +126,128 @@ const Edit = ( {
);
const {
- getBlockifiedTemplate,
isConversionPossible,
getDescription,
getButtonLabel,
+ onClickCallback,
+ getBlockifiedTemplate,
} = conversionConfig[ templateType ];
const canConvert = isConversionPossible();
const placeholderDescription = getDescription( templateTitle, canConvert );
+ const [ isPopoverOpen, setIsPopoverOpen ] = useState( false );
return (
-
-
-
{ placeholderDescription }
-
+
- { canConvert && (
-
-