Skip to content
This repository was archived by the owner on Feb 23, 2024. It is now read-only.

Commit a52be40

Browse files
authored
[Blockifying Product Archive Templates]: Implement the blockified template conversion for the Classic Template Block. (#8248)
* Extract a blockified Product Archive Template to the templates * Add templates to tsconfig.json so the files are resolved as part of the core code * Add a encouragement note to use blockified version IF migration is available * Add a Row block wrapping Product Results Count and Catalog Sorting blocks * Move blockified product-archive from templates/ to assets/ directory * Remove unnecessary margin from Product Results Count block When used in a Row block in a blockified Archive Product template, Product Results Count had additional unnecessary margin which caused misalignment with the Catalog Sorting block * Update the description of the Classic Template Editor placeholder * Remove unnecessary entry in tsconfig.json to include templates directory It was added couple of commits earlier, since the template was kept there, but it was decided to move it to assets directory, so entry is no longer necessary * Differentiate the Classic Template placeholder description depending on the availability to convert to Products block * Set margin for Catalog Sorting to 0, so it aligns properly when used in blockified Archive Product template * Make the blockification config, so it covers the Product Archive as well as Single Product templates * Move the product-archive specific functions from classic-template/index.tsx to the product-archive.ts * Add alignment option to the Store Notices block and make the blockified template blocks aligned wide That is required, so the Classic Template layout is preserved * Create single-product.ts file which is a placeholder for the blockified Single Product template * Make Blockified Product Archive template inherit the align attibute * Simplify the interface of blockified templates Expose function instead of two functions for allowing and disallowing conversion * Add a BlockifiedTemplate type * Rename and simplify the function checking if conversion of classic template to block version is possible * Align the variable naming to use instead of * Pass the Classic Template attributes to the blockified template instead of getting it from data store * Include Breadcrumbs block in the Blockified Product Archive Template * Consume alignment attributes of Catalog Sorting in the PHP render function * Consume alignment attributes of Breadcrumbs in the PHP render function * Remove align support from Catalog Sorting and add to Store Notices block * Extend the get_classes_and_styles_by_attributes method with align and text_align attributes * Add Archive Title block to the Blockified Classic Template * Minor getRowBlock function refactor * Add property to the classic templates and base the config on it instead of placeholder * Add separate blockified template for a Product Search Results * Pass attribute from classic template to No Results block in Product Search Results * Extract the common functions between blockified archive-template and product-search-results to utils * Enable 'Inherit query from template' in Products block by default when converting the Classic Template to blockified one * Improve the naming of BlockifiedTemplateConfig type * Differentiate Product Catalog and Products By * templates. The latter include Term Description block * Change unclear ProductsBy to ProductTaxonomy in regards to classic template conversion * Revert the margin fix which was added already on trunk * Move the surrounding blocks as inner blocks of Products * Hide the conversion behind the experimental build flag (as it was before)
1 parent 8032d39 commit a52be40

File tree

11 files changed

+476
-47
lines changed

11 files changed

+476
-47
lines changed
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
/**
2+
* External dependencies
3+
*/
4+
import {
5+
createBlock,
6+
createBlocksFromInnerBlocksTemplate,
7+
type BlockInstance,
8+
} from '@wordpress/blocks';
9+
import { isWpVersion } from '@woocommerce/settings';
10+
import { __, sprintf } from '@wordpress/i18n';
11+
12+
/**
13+
* Internal dependencies
14+
*/
15+
import {
16+
INNER_BLOCKS_TEMPLATE as productsInnerBlocksTemplate,
17+
QUERY_DEFAULT_ATTRIBUTES as productsQueryDefaultAttributes,
18+
} from '../product-query/constants';
19+
import { VARIATION_NAME as productsVariationName } from '../product-query/variations/product-query';
20+
import { createArchiveTitleBlock, createRowBlock } from './utils';
21+
import { type InheritedAttributes } from './types';
22+
23+
const createProductsBlock = (
24+
inheritedAttributes: InheritedAttributes,
25+
templateInnerBlocks: BlockInstance[]
26+
) => {
27+
const innerBlocks = [
28+
...templateInnerBlocks,
29+
...createBlocksFromInnerBlocksTemplate( productsInnerBlocksTemplate ),
30+
];
31+
32+
return createBlock(
33+
'core/query',
34+
{
35+
...productsQueryDefaultAttributes,
36+
...inheritedAttributes,
37+
namespace: productsVariationName,
38+
query: {
39+
...productsQueryDefaultAttributes.query,
40+
inherit: true,
41+
},
42+
},
43+
innerBlocks
44+
);
45+
};
46+
47+
const getBlockifiedTemplate = (
48+
inheritedAttributes: InheritedAttributes,
49+
withTermDescription = false
50+
) => {
51+
const templateInnerBlocks = [
52+
createBlock( 'woocommerce/breadcrumbs', inheritedAttributes ),
53+
createArchiveTitleBlock( 'archive-title', inheritedAttributes ),
54+
withTermDescription
55+
? createBlock( 'core/term-description', inheritedAttributes )
56+
: null,
57+
createBlock( 'woocommerce/store-notices', inheritedAttributes ),
58+
createRowBlock(
59+
[
60+
createBlock( 'woocommerce/product-results-count' ),
61+
createBlock( 'woocommerce/catalog-sorting' ),
62+
],
63+
inheritedAttributes
64+
),
65+
].filter( Boolean ) as BlockInstance[];
66+
67+
return createProductsBlock( inheritedAttributes, templateInnerBlocks );
68+
};
69+
70+
const getBlockifiedTemplateWithTermDescription = (
71+
inheritedAttributes: InheritedAttributes
72+
) => getBlockifiedTemplate( inheritedAttributes, true );
73+
74+
const isConversionPossible = () => {
75+
// Blockification is possible for the WP version 6.1 and above,
76+
// which are the versions the Products block supports.
77+
return isWpVersion( '6.1', '>=' );
78+
};
79+
80+
const getDescriptionAllowingConversion = ( templateTitle: string ) =>
81+
sprintf(
82+
/* translators: %s is the template title */
83+
__(
84+
"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.",
85+
'woo-gutenberg-products-block'
86+
),
87+
templateTitle
88+
);
89+
90+
const getDescriptionDisallowingConversion = ( templateTitle: string ) =>
91+
sprintf(
92+
/* translators: %s is the template title */
93+
__(
94+
'This block serves as a placeholder for your %s. It will display the actual product image, title, price in your store. You can move this placeholder around and add more blocks around to customize the template.',
95+
'woo-gutenberg-products-block'
96+
),
97+
templateTitle
98+
);
99+
100+
const getDescription = ( templateTitle: string, canConvert: boolean ) => {
101+
if ( canConvert ) {
102+
return getDescriptionAllowingConversion( templateTitle );
103+
}
104+
105+
return getDescriptionDisallowingConversion( templateTitle );
106+
};
107+
108+
const getButtonLabel = () =>
109+
__( 'Upgrade to Products block', 'woo-gutenberg-products-block' );
110+
111+
export const blockifiedProductCatalogConfig = {
112+
getBlockifiedTemplate,
113+
isConversionPossible,
114+
getDescription,
115+
getButtonLabel,
116+
};
117+
118+
export const blockifiedProductTaxonomyConfig = {
119+
getBlockifiedTemplate: getBlockifiedTemplateWithTermDescription,
120+
isConversionPossible,
121+
getDescription,
122+
getButtonLabel,
123+
};

assets/js/blocks/classic-template/constants.ts

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,54 +2,71 @@
22
* External dependencies
33
*/
44
import { __ } from '@wordpress/i18n';
5-
export const BLOCK_SLUG = 'woocommerce/legacy-template';
65

76
/**
87
* Internal dependencies
98
*/
109
import { TemplateDetails } from './types';
1110

11+
export const BLOCK_SLUG = 'woocommerce/legacy-template';
12+
export const TYPES = {
13+
singleProduct: 'single-product',
14+
productCatalog: 'product-catalog',
15+
productTaxonomy: 'product-taxonomy',
16+
productSearchResults: 'product-search-results',
17+
};
18+
export const PLACEHOLDERS = {
19+
singleProduct: 'single-product',
20+
archiveProduct: 'archive-product',
21+
};
22+
1223
export const TEMPLATES: TemplateDetails = {
1324
'single-product': {
25+
type: TYPES.singleProduct,
1426
title: __(
1527
'WooCommerce Single Product Block',
1628
'woo-gutenberg-products-block'
1729
),
18-
placeholder: 'single-product',
30+
placeholder: PLACEHOLDERS.singleProduct,
1931
},
2032
'archive-product': {
33+
type: TYPES.productCatalog,
2134
title: __(
2235
'WooCommerce Product Grid Block',
2336
'woo-gutenberg-products-block'
2437
),
25-
placeholder: 'archive-product',
38+
placeholder: PLACEHOLDERS.archiveProduct,
2639
},
2740
'taxonomy-product_cat': {
41+
type: TYPES.productTaxonomy,
2842
title: __(
2943
'WooCommerce Product Taxonomy Block',
3044
'woo-gutenberg-products-block'
3145
),
32-
placeholder: 'archive-product',
46+
placeholder: PLACEHOLDERS.archiveProduct,
3347
},
3448
'taxonomy-product_tag': {
49+
type: TYPES.productTaxonomy,
3550
title: __(
3651
'WooCommerce Product Tag Block',
3752
'woo-gutenberg-products-block'
3853
),
39-
placeholder: 'archive-product',
54+
placeholder: PLACEHOLDERS.archiveProduct,
4055
},
4156
'taxonomy-product_attribute': {
57+
type: TYPES.productTaxonomy,
4258
title: __(
4359
'WooCommerce Product Attribute Block',
4460
'woo-gutenberg-products-block'
4561
),
46-
placeholder: 'archive-product',
62+
placeholder: PLACEHOLDERS.archiveProduct,
4763
},
4864
'product-search-results': {
65+
type: TYPES.productSearchResults,
4966
title: __(
5067
'WooCommerce Product Search Results Block',
5168
'woo-gutenberg-products-block'
5269
),
53-
placeholder: 'archive-product',
70+
placeholder: PLACEHOLDERS.archiveProduct,
5471
},
5572
};

assets/js/blocks/classic-template/index.tsx

Lines changed: 39 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
* External dependencies
33
*/
44
import {
5-
createBlock,
65
getBlockType,
76
registerBlockType,
87
unregisterBlockType,
@@ -14,7 +13,7 @@ import {
1413
} from '@woocommerce/block-settings';
1514
import { useBlockProps } from '@wordpress/block-editor';
1615
import { Button, Placeholder } from '@wordpress/components';
17-
import { __, sprintf } from '@wordpress/i18n';
16+
import { __ } from '@wordpress/i18n';
1817
import { box, Icon } from '@wordpress/icons';
1918
import { select, useDispatch, subscribe } from '@wordpress/data';
2019
import { useEffect } from '@wordpress/element';
@@ -24,18 +23,40 @@ import { useEffect } from '@wordpress/element';
2423
*/
2524
import './editor.scss';
2625
import './style.scss';
27-
import { BLOCK_SLUG, TEMPLATES } from './constants';
26+
import { BLOCK_SLUG, TEMPLATES, TYPES } from './constants';
2827
import {
2928
isClassicTemplateBlockRegisteredWithAnotherTitle,
3029
hasTemplateSupportForClassicTemplateBlock,
3130
getTemplateDetailsBySlug,
3231
} from './utils';
32+
import {
33+
blockifiedProductCatalogConfig,
34+
blockifiedProductTaxonomyConfig,
35+
} from './archive-product';
36+
import * as blockifiedSingleProduct from './single-product';
37+
import * as blockifiedProductSearchResults from './product-search-results';
38+
import type { BlockifiedTemplateConfig } from './types';
3339

3440
type Attributes = {
3541
template: string;
3642
align: string;
3743
};
3844

45+
const blockifiedFallbackConfig = {
46+
isConversionPossible: () => false,
47+
getBlockifiedTemplate: () => [],
48+
getDescription: () => '',
49+
getButtonLabel: () => '',
50+
};
51+
52+
const conversionConfig: { [ key: string ]: BlockifiedTemplateConfig } = {
53+
[ TYPES.productCatalog ]: blockifiedProductCatalogConfig,
54+
[ TYPES.productTaxonomy ]: blockifiedProductTaxonomyConfig,
55+
[ TYPES.singleProduct ]: blockifiedSingleProduct,
56+
[ TYPES.productSearchResults ]: blockifiedProductSearchResults,
57+
fallback: blockifiedFallbackConfig,
58+
};
59+
3960
const Edit = ( {
4061
clientId,
4162
attributes,
@@ -50,6 +71,7 @@ const Edit = ( {
5071
);
5172
const templateTitle = templateDetails?.title ?? attributes.template;
5273
const templatePlaceholder = templateDetails?.placeholder ?? 'fallback';
74+
const templateType = templateDetails?.type ?? 'fallback';
5375

5476
useEffect(
5577
() =>
@@ -60,6 +82,16 @@ const Edit = ( {
6082
[ attributes.align, attributes.template, setAttributes ]
6183
);
6284

85+
const {
86+
getBlockifiedTemplate,
87+
isConversionPossible,
88+
getDescription,
89+
getButtonLabel,
90+
} = conversionConfig[ templateType ];
91+
92+
const canConvert = isExperimentalBuild() && isConversionPossible();
93+
const placeholderDescription = getDescription( templateTitle, canConvert );
94+
6395
return (
6496
<div { ...blockProps }>
6597
<Placeholder
@@ -68,48 +100,20 @@ const Edit = ( {
68100
className="wp-block-woocommerce-classic-template__placeholder"
69101
>
70102
<div className="wp-block-woocommerce-classic-template__placeholder-copy">
71-
<p className="wp-block-woocommerce-classic-template__placeholder-warning">
72-
<strong>
73-
{ __(
74-
'Do not remove this block!',
75-
'woo-gutenberg-products-block'
76-
) }
77-
</strong>{ ' ' }
78-
{ __(
79-
'Removing this will cause unintended effects on your store.',
80-
'woo-gutenberg-products-block'
81-
) }
82-
</p>
83-
<p>
84-
{ sprintf(
85-
/* translators: %s is the template title */
86-
__(
87-
'This is a placeholder for the %s. In your store it will display the actual product image, title, price, etc. You can move this placeholder around and add more blocks around it to customize the template.',
88-
'woo-gutenberg-products-block'
89-
),
90-
templateTitle
91-
) }
92-
</p>
103+
<p>{ placeholderDescription }</p>
93104
</div>
94105
<div className="wp-block-woocommerce-classic-template__placeholder-wireframe">
95-
{ isExperimentalBuild() && (
106+
{ canConvert && (
96107
<div className="wp-block-woocommerce-classic-template__placeholder-migration-button-container">
97108
<Button
98109
isPrimary
99110
onClick={ () => {
100111
replaceBlock(
101112
clientId,
102-
// TODO: Replace with the blockified version of the Product Grid Block when it will be available.
103-
createBlock( 'core/paragraph', {
104-
content:
105-
'Instead of this block, the new Product Grid Block will be rendered',
106-
} )
113+
getBlockifiedTemplate( attributes )
107114
);
108115
} }
109-
text={ __(
110-
'Use the blockified Product Grid Block',
111-
'woo-gutenberg-products-block'
112-
) }
116+
text={ getButtonLabel() }
113117
/>
114118
</div>
115119
) }

0 commit comments

Comments
 (0)