From 6685fc00e6570268e738e630c0135404144d74a7 Mon Sep 17 00:00:00 2001 From: Luigi Date: Fri, 3 Mar 2023 15:00:19 +0100 Subject: [PATCH] Add Product Meta block --- assets/js/atomic/blocks/index.js | 1 + .../product-elements/product-meta/block.json | 17 +++++ .../product-elements/product-meta/edit.tsx | 50 +++++++++++++ .../product-elements/product-meta/editor.scss | 4 + .../product-elements/product-meta/index.tsx | 28 +++++++ .../product-elements/product-meta/save.tsx | 17 +++++ .../blocks/product-elements/sku/edit.tsx | 75 +++---------------- .../blocks/product-elements/sku/index.tsx | 6 ++ .../SingleProductTemplateCompatibility.php | 56 +++----------- templates/parts/product-meta.html | 3 - 10 files changed, 143 insertions(+), 114 deletions(-) create mode 100644 assets/js/atomic/blocks/product-elements/product-meta/block.json create mode 100644 assets/js/atomic/blocks/product-elements/product-meta/edit.tsx create mode 100644 assets/js/atomic/blocks/product-elements/product-meta/editor.scss create mode 100644 assets/js/atomic/blocks/product-elements/product-meta/index.tsx create mode 100644 assets/js/atomic/blocks/product-elements/product-meta/save.tsx delete mode 100644 templates/parts/product-meta.html diff --git a/assets/js/atomic/blocks/index.js b/assets/js/atomic/blocks/index.js index ab691403fc8..8b66f58247a 100644 --- a/assets/js/atomic/blocks/index.js +++ b/assets/js/atomic/blocks/index.js @@ -17,3 +17,4 @@ import './product-elements/add-to-cart-form'; import './product-elements/product-image-gallery'; import './product-elements/product-details'; import './product-elements/related-products'; +import './product-elements/product-meta'; diff --git a/assets/js/atomic/blocks/product-elements/product-meta/block.json b/assets/js/atomic/blocks/product-elements/product-meta/block.json new file mode 100644 index 00000000000..f2d22b4f6b2 --- /dev/null +++ b/assets/js/atomic/blocks/product-elements/product-meta/block.json @@ -0,0 +1,17 @@ +{ + "name": "woocommerce/product-meta", + "version": "1.0.0", + "title": "Product Meta", + "icon": "product", + "description": "Display Product Meta", + "category": "woocommerce", + "supports": { + "align": true, + "reusable": false + }, + "keywords": [ "WooCommerce" ], + "usesContext": [ "postId", "postType", "queryId" ], + "textdomain": "woo-gutenberg-products-block", + "apiVersion": 2, + "$schema": "https://schemas.wp.org/trunk/block.json" +} diff --git a/assets/js/atomic/blocks/product-elements/product-meta/edit.tsx b/assets/js/atomic/blocks/product-elements/product-meta/edit.tsx new file mode 100644 index 00000000000..1058d11faa6 --- /dev/null +++ b/assets/js/atomic/blocks/product-elements/product-meta/edit.tsx @@ -0,0 +1,50 @@ +/** + * External dependencies + */ +import { InnerBlocks, useBlockProps } from '@wordpress/block-editor'; +import { InnerBlockTemplate } from '@wordpress/blocks'; + +/** + * Internal dependencies + */ +import './editor.scss'; + +const Edit = () => { + const TEMPLATE: InnerBlockTemplate[] = [ + [ + 'core/group', + { layout: { type: 'flex', flexWrap: 'nowrap' } }, + [ + [ + 'woocommerce/product-sku', + { + isDescendentOfSingleProductTemplate: true, + }, + ], + [ + 'core/post-terms', + { + prefix: 'Category: ', + term: 'product_cat', + }, + ], + [ + 'core/post-terms', + { + prefix: 'Tags: ', + term: 'product_tag', + }, + ], + ], + ], + ]; + const blockProps = useBlockProps(); + + return ( +
+ +
+ ); +}; + +export default Edit; diff --git a/assets/js/atomic/blocks/product-elements/product-meta/editor.scss b/assets/js/atomic/blocks/product-elements/product-meta/editor.scss new file mode 100644 index 00000000000..b3872daea3a --- /dev/null +++ b/assets/js/atomic/blocks/product-elements/product-meta/editor.scss @@ -0,0 +1,4 @@ +.wc-block-editor-related-products__notice { + margin: 10px auto; + max-width: max-content; +} diff --git a/assets/js/atomic/blocks/product-elements/product-meta/index.tsx b/assets/js/atomic/blocks/product-elements/product-meta/index.tsx new file mode 100644 index 00000000000..1db84adc949 --- /dev/null +++ b/assets/js/atomic/blocks/product-elements/product-meta/index.tsx @@ -0,0 +1,28 @@ +/** + * External dependencies + */ +import { box as icon } from '@wordpress/icons'; +import { registerBlockType, unregisterBlockType } from '@wordpress/blocks'; +import { registerBlockSingleProductTemplate } from '@woocommerce/atomic-utils'; + +/** + * Internal dependencies + */ +import edit from './edit'; +import save from './save'; +import metadata from './block.json'; + +registerBlockSingleProductTemplate( { + registerBlockFn: () => { + // @ts-expect-error: `registerBlockType` is a function that is typed in WordPress core. + registerBlockType( metadata, { + icon, + edit, + save, + } ); + }, + unregisterBlockFn: () => { + unregisterBlockType( metadata.name ); + }, + blockName: metadata.name, +} ); diff --git a/assets/js/atomic/blocks/product-elements/product-meta/save.tsx b/assets/js/atomic/blocks/product-elements/product-meta/save.tsx new file mode 100644 index 00000000000..0feb6d8f950 --- /dev/null +++ b/assets/js/atomic/blocks/product-elements/product-meta/save.tsx @@ -0,0 +1,17 @@ +/** + * External dependencies + */ +import { InnerBlocks, useBlockProps } from '@wordpress/block-editor'; + +const Save = () => { + const blockProps = useBlockProps.save(); + + return ( +
+ { /* @ts-expect-error: `InnerBlocks.Content` is a component that is typed in WordPress core*/ } + +
+ ); +}; + +export default Save; diff --git a/assets/js/atomic/blocks/product-elements/sku/edit.tsx b/assets/js/atomic/blocks/product-elements/sku/edit.tsx index 401489c4ed1..afa0ac94dba 100644 --- a/assets/js/atomic/blocks/product-elements/sku/edit.tsx +++ b/assets/js/atomic/blocks/product-elements/sku/edit.tsx @@ -11,13 +11,9 @@ import { useEffect } from '@wordpress/element'; * Internal dependencies */ import Block from './block'; -import { BLOCK_TITLE, BLOCK_ICON } from './constants'; import type { Attributes } from './types'; -import { ProductSelector } from '../shared/product-selector'; -import { useBlockProps } from '@wordpress/block-editor'; -import { useSelect } from '@wordpress/data'; -export default ( { +const Edit = ( { attributes, setAttributes, context, @@ -28,70 +24,17 @@ export default ( { }; const isDescendentOfQueryLoop = Number.isFinite( context.queryId ); - const { showProductSelector, isDescendentOfSingleProductTemplate } = - useSelect( - ( select ) => { - const store = select( 'core/edit-site' ); - const postId = store?.getEditedPostId(); - - const descendentOfSingleProductTemplate = - ( postId === 'woocommerce/woocommerce//product-meta' || - postId === - 'woocommerce/woocommerce//single-product' ) && - ! isDescendentOfQueryLoop; - - return { - isDescendentOfSingleProductTemplate: - descendentOfSingleProductTemplate, - showProductSelector: - ! isDescendentOfQueryLoop && - ! descendentOfSingleProductTemplate, - }; - }, - [ isDescendentOfQueryLoop ] - ); - - const blockProps = useBlockProps(); - useEffect( - () => - setAttributes( { - isDescendentOfQueryLoop, - isDescendentOfSingleProductTemplate, - showProductSelector, - } ), - [ - isDescendentOfQueryLoop, - isDescendentOfSingleProductTemplate, - setAttributes, - showProductSelector, - ] + () => setAttributes( { isDescendentOfQueryLoop } ), + [ setAttributes, isDescendentOfQueryLoop ] ); - if ( ! showProductSelector ) { - return ( -
- - -
- ); - } - return ( -
- - - - -
+ <> + + + ); }; + +export default Edit; diff --git a/assets/js/atomic/blocks/product-elements/sku/index.tsx b/assets/js/atomic/blocks/product-elements/sku/index.tsx index 56148fbcd3e..4774bdc03bd 100644 --- a/assets/js/atomic/blocks/product-elements/sku/index.tsx +++ b/assets/js/atomic/blocks/product-elements/sku/index.tsx @@ -27,6 +27,12 @@ const blockConfig: BlockConfiguration = { icon: { src: icon }, usesContext: [ 'query', 'queryId', 'postId' ], attributes, + ancestor: [ + 'woocommerce/all-products', + 'woocommerce/single-product', + 'core/post-template', + 'woocommerce/product-meta', + ], edit, save: () => { if ( diff --git a/src/Templates/SingleProductTemplateCompatibility.php b/src/Templates/SingleProductTemplateCompatibility.php index 07603ff24a8..7ba8f89ed4c 100644 --- a/src/Templates/SingleProductTemplateCompatibility.php +++ b/src/Templates/SingleProductTemplateCompatibility.php @@ -85,21 +85,6 @@ private function inject_hook_to_first_and_last_blocks( $block_content, $block ) ), ); - if ( 'core/template-part' === $block['blockName'] && isset( $block['attrs']['slug'] ) && 'product-meta' === $block['attrs']['slug'] ) { - return sprintf( - '%1$s%2$s%3$s', - $this->get_hooks_buffer( - $this->hook_data['woocommerce_product_meta_start'], - 'before' - ), - $block_content, - $this->get_hooks_buffer( - $this->hook_data['woocommerce_product_meta_end'], - 'after' - ) - ); - } - if ( isset( $block['attrs'][ self::IS_FIRST_BLOCK ] ) && isset( $block['attrs'][ self::IS_LAST_BLOCK ] ) ) { return sprintf( '%1$s%2$s%3$s', @@ -218,18 +203,18 @@ protected function set_hook_data() { 'woocommerce_template_single_sharing' => 50, ), ), - 'woocommerce_product_meta_start' => array( + 'woocommerce_after_single_product' => array( 'block_name' => '', - 'position' => 'before', + 'position' => 'after', 'hooked' => array(), ), - 'woocommerce_product_meta_end' => array( - 'block_name' => '', - 'position' => 'after', + 'woocommerce_product_meta_start' => array( + 'block_name' => 'woocommerce/product-meta', + 'position' => 'before', 'hooked' => array(), ), - 'woocommerce_after_single_product' => array( - 'block_name' => '', + 'woocommerce_product_meta_end' => array( + 'block_name' => 'woocommerce/product-meta', 'position' => 'after', 'hooked' => array(), ), @@ -289,7 +274,7 @@ private static function wrap_single_product_template( $template_content ) { $wrapped_blocks = array_map( function( $blocks ) use ( $single_product_template_blocks ) { - if ( self::is_template_part( $blocks[0] ) ) { + if ( 'core/template-part' === $blocks[0]['blockName'] ) { return $blocks; } @@ -321,7 +306,7 @@ function( $carry, $item ) { $carry['index'] = $carry['index'] + 1; $block = $item[0]; - if ( self::is_template_part( $block ) ) { + if ( 'core/template-part' === $block['blockName'] ) { $carry['template'][] = $block; return $carry; } @@ -429,7 +414,7 @@ private static function group_blocks( $parsed_blocks ) { return array_reduce( $parsed_blocks, function( $carry, $block ) { - if ( self::is_template_part( $block ) ) { + if ( 'core/template-part' === $block['blockName'] ) { $carry[] = array( $block ); return $carry; } @@ -437,7 +422,7 @@ function( $carry, $block ) { return $carry; } $last_element_index = count( $carry ) - 1; - if ( isset( $carry[ $last_element_index ][0]['blockName'] ) && ! self::is_template_part( $carry[ $last_element_index ][0] ) ) { + if ( isset( $carry[ $last_element_index ][0]['blockName'] ) && 'core/template-part' !== $carry[ $last_element_index ][0]['blockName'] ) { $carry[ $last_element_index ][] = $block; return $carry; } @@ -447,23 +432,4 @@ function( $carry, $block ) { array() ); } - - /** - * Check if the block is a template part except for the product meta template part. - * - * @param array $block Block object. - * @return bool True if the block is a template part, false otherwise. - */ - private static function is_template_part( $block ) { - if ( 'core/template-part' === $block['blockName'] && isset( $block['attrs']['slug'] ) && 'product-meta' === $block['attrs']['slug'] ) { - return false; - } - - if ( 'core/template-part' === $block['blockName'] ) { - return true; - } - - return false; - - } } diff --git a/templates/parts/product-meta.html b/templates/parts/product-meta.html deleted file mode 100644 index d5fc82f4086..00000000000 --- a/templates/parts/product-meta.html +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file