From cc476e6b483c2a4d6281e4248e3b05b4481fceaa Mon Sep 17 00:00:00 2001 From: Carlos Bravo Date: Thu, 4 Aug 2022 15:40:48 +0200 Subject: [PATCH 01/14] Add hydration experiment to summary coupon, not working due to PHP error at pre-commit --- .../cart-order-summary-coupon-form/block.tsx | 6 +++++ .../cart/inner-blocks/register-components.ts | 26 ++++++++++++------- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/assets/js/blocks/cart/inner-blocks/cart-order-summary-coupon-form/block.tsx b/assets/js/blocks/cart/inner-blocks/cart-order-summary-coupon-form/block.tsx index 7983eae49..10d5f0b53 100644 --- a/assets/js/blocks/cart/inner-blocks/cart-order-summary-coupon-form/block.tsx +++ b/assets/js/blocks/cart/inner-blocks/cart-order-summary-coupon-form/block.tsx @@ -5,10 +5,13 @@ import { TotalsCoupon } from '@woocommerce/base-components/cart-checkout'; import { useStoreCartCoupons } from '@woocommerce/base-context/hooks'; import { getSetting } from '@woocommerce/settings'; import { TotalsWrapper } from '@woocommerce/blocks-checkout'; +import { useState } from '@wordpress/element'; const Block = ( { className }: { className: string } ): JSX.Element | null => { const couponsEnabled = getSetting( 'couponsEnabled', true ); + const [ count, setCount ] = useState( 0 ); + const { applyCoupon, isApplyingCoupon } = useStoreCartCoupons( 'wc/cart' ); if ( ! couponsEnabled ) { @@ -21,6 +24,9 @@ const Block = ( { className }: { className: string } ): JSX.Element | null => { onSubmit={ applyCoupon } isLoading={ isApplyingCoupon } /> + ); }; diff --git a/assets/js/blocks/cart/inner-blocks/register-components.ts b/assets/js/blocks/cart/inner-blocks/register-components.ts index bf4ac082f..3cea36833 100644 --- a/assets/js/blocks/cart/inner-blocks/register-components.ts +++ b/assets/js/blocks/cart/inner-blocks/register-components.ts @@ -9,6 +9,8 @@ import { registerCheckoutBlock } from '@woocommerce/blocks-checkout'; * Internal dependencies */ import metadata from './component-metadata'; +import { registerBlockType } from '../../../base/utils/bhe-frontend'; +import CouponBlock from '../../cart/inner-blocks/cart-order-summary-coupon-form/frontend'; // Modify webpack publicPath at runtime based on location of WordPress Plugin. // eslint-disable-next-line no-undef,camelcase @@ -157,16 +159,20 @@ registerCheckoutBlock( { ), } ); -registerCheckoutBlock( { - metadata: metadata.CART_ORDER_SUMMARY_COUPON_FORM, - component: lazy( - () => - import( - /* webpackChunkName: "cart-blocks/order-summary-coupon-form" */ - './cart-order-summary-coupon-form/frontend' - ) - ), -} ); +registerBlockType( + 'woocommerce/cart-order-summary-coupon-form-block', + CouponBlock +); +// registerCheckoutBlock( { +// metadata: metadata.CART_ORDER_SUMMARY_COUPON_FORM, +// component: lazy( +// () => +// import( +// /* webpackChunkName: "cart-blocks/order-summary-coupon-form" */ +// './cart-order-summary-coupon-form/frontend' +// ) +// ), +// } ); registerCheckoutBlock( { metadata: metadata.CART_ORDER_SUMMARY_SHIPPING, From 9c0f8a1af8aeab7c25f3e2e18f52a1a449679250 Mon Sep 17 00:00:00 2001 From: Carlos Bravo Date: Fri, 5 Aug 2022 10:57:39 +0200 Subject: [PATCH 02/14] Add php block loader --- src/BlockTypesController.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/BlockTypesController.php b/src/BlockTypesController.php index 79c0fe272..dab774d21 100644 --- a/src/BlockTypesController.php +++ b/src/BlockTypesController.php @@ -104,6 +104,10 @@ public function add_data_attributes( $content, $block ) { return $content; } + if ( 'woocommerce/cart-order-summary-coupon-form-block' === $block_name ) { + return $content; + } + $attributes = (array) $block['attrs']; $exclude_attributes = [ 'className', 'align' ]; $escaped_data_attributes = [ @@ -143,6 +147,7 @@ public function block_hydration_wrapper( $block_content, $block, $instance ) { $block['blockName'], array( 'woocommerce/all-products', + 'woocommerce/cart-order-summary-coupon-form-block', ), true ) ) { From 6d504d44cd36a1fd3825e378fda4355e717e99e1 Mon Sep 17 00:00:00 2001 From: Carlos Bravo Date: Fri, 5 Aug 2022 11:16:27 +0200 Subject: [PATCH 03/14] Fix notices if blockType is null --- src/BlockTypesController.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/BlockTypesController.php b/src/BlockTypesController.php index dab774d21..196ec51c1 100644 --- a/src/BlockTypesController.php +++ b/src/BlockTypesController.php @@ -155,7 +155,7 @@ public function block_hydration_wrapper( $block_content, $block, $instance ) { } $block_type = $instance->block_type; - $attr_definitions = $block_type->attributes; + $attr_definitions = isset( $block_type ) ? $block_type->attributes : []; $attributes = array(); $sourced_attributes = array(); @@ -193,8 +193,8 @@ public function block_hydration_wrapper( $block_content, $block, $instance ) { 'data-wp-block-props="%6$s" ' . 'data-wp-block-hydration="idle">', esc_attr( $block['blockName'] ), - esc_attr( wp_json_encode( $block_type->uses_context ) ), - esc_attr( wp_json_encode( $block_type->provides_context ) ), + esc_attr( wp_json_encode( isset( $block_type ) ? $block_type->uses_context : [] ) ), + esc_attr( wp_json_encode( isset( $block_type ) ? $block_type->provides_context : [] ) ), esc_attr( wp_json_encode( $attributes ) ), esc_attr( wp_json_encode( $sourced_attributes ) ), esc_attr( wp_json_encode( $block_supports_attributes ) ) From 0186e3283efe91f89b175645a9a12cb73d3cbac2 Mon Sep 17 00:00:00 2001 From: Carlos Bravo Date: Fri, 5 Aug 2022 12:49:14 +0200 Subject: [PATCH 04/14] Added explanatory comments --- .../cart/inner-blocks/cart-order-summary-coupon-form/block.tsx | 2 ++ assets/js/blocks/cart/inner-blocks/register-components.ts | 2 ++ 2 files changed, 4 insertions(+) diff --git a/assets/js/blocks/cart/inner-blocks/cart-order-summary-coupon-form/block.tsx b/assets/js/blocks/cart/inner-blocks/cart-order-summary-coupon-form/block.tsx index 10d5f0b53..0be98ffe4 100644 --- a/assets/js/blocks/cart/inner-blocks/cart-order-summary-coupon-form/block.tsx +++ b/assets/js/blocks/cart/inner-blocks/cart-order-summary-coupon-form/block.tsx @@ -10,6 +10,7 @@ import { useState } from '@wordpress/element'; const Block = ( { className }: { className: string } ): JSX.Element | null => { const couponsEnabled = getSetting( 'couponsEnabled', true ); + /* Added a temporary setState to easily check hydration */ const [ count, setCount ] = useState( 0 ); const { applyCoupon, isApplyingCoupon } = useStoreCartCoupons( 'wc/cart' ); @@ -24,6 +25,7 @@ const Block = ( { className }: { className: string } ): JSX.Element | null => { onSubmit={ applyCoupon } isLoading={ isApplyingCoupon } /> + { /* Added a temporary button to easily check hydration */ } diff --git a/assets/js/blocks/cart/inner-blocks/register-components.ts b/assets/js/blocks/cart/inner-blocks/register-components.ts index 3cea36833..ebc54cc10 100644 --- a/assets/js/blocks/cart/inner-blocks/register-components.ts +++ b/assets/js/blocks/cart/inner-blocks/register-components.ts @@ -159,10 +159,12 @@ registerCheckoutBlock( { ), } ); +// Hide registering the block the default way, using instead bhe-frontend. registerBlockType( 'woocommerce/cart-order-summary-coupon-form-block', CouponBlock ); + // registerCheckoutBlock( { // metadata: metadata.CART_ORDER_SUMMARY_COUPON_FORM, // component: lazy( From 1e0dba798d8c7af32592097c57bc275954105a0c Mon Sep 17 00:00:00 2001 From: Carlos Bravo Date: Tue, 9 Aug 2022 11:49:48 +0200 Subject: [PATCH 05/14] Fix duplication elements on block parsing --- assets/js/atomic/utils/render-parent-block.tsx | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/assets/js/atomic/utils/render-parent-block.tsx b/assets/js/atomic/utils/render-parent-block.tsx index bb6b2ecdf..72582e9bd 100644 --- a/assets/js/atomic/utils/render-parent-block.tsx +++ b/assets/js/atomic/utils/render-parent-block.tsx @@ -142,6 +142,18 @@ const renderInnerBlocks = ( { return null; } return Array.from( children ).map( ( node: Node, index: number ) => { + /** + * Do not process the node if its a `` element. + */ + if ( + node instanceof HTMLElement && + node instanceof window.customElements.get( 'wp-block' ) + ) { + const reactElement = parse( node.outerHTML ); + + if ( isValidElement( reactElement ) ) + return cloneElement( reactElement ); + } /** * This will grab the blockName from the data- attributes stored in block markup. Without a blockName, we cannot * convert the HTMLElement to a React component. From 1d422eff955be2569cf3f56637f711a95c494b7b Mon Sep 17 00:00:00 2001 From: Carlos Bravo Date: Wed, 10 Aug 2022 13:30:33 +0200 Subject: [PATCH 06/14] Server register inner coupon block --- .../cart-order-summary-heading/block.tsx | 5 +++++ src/BlockTypesController.php | 15 +++++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/assets/js/blocks/cart/inner-blocks/cart-order-summary-heading/block.tsx b/assets/js/blocks/cart/inner-blocks/cart-order-summary-heading/block.tsx index 015c29f8f..96a7a43b5 100644 --- a/assets/js/blocks/cart/inner-blocks/cart-order-summary-heading/block.tsx +++ b/assets/js/blocks/cart/inner-blocks/cart-order-summary-heading/block.tsx @@ -3,6 +3,7 @@ */ import Title from '@woocommerce/base-components/title'; import classnames from 'classnames'; +import { useState } from '@wordpress/element'; const Block = ( { className, @@ -11,12 +12,16 @@ const Block = ( { className: string; content: string; } ): JSX.Element => { + const [ count, setCount ] = useState( 0 ); return ( { content } + <button + onClick={ () => setCount( count + 1 ) } + >{ `Counter: ${ count }` }</button> ); }; diff --git a/src/BlockTypesController.php b/src/BlockTypesController.php index 196ec51c1..b60483004 100644 --- a/src/BlockTypesController.php +++ b/src/BlockTypesController.php @@ -8,6 +8,7 @@ use Automattic\WooCommerce\Blocks\Integrations\IntegrationRegistry; use Automattic\WooCommerce\Blocks\BlockTypes\Cart; use Automattic\WooCommerce\Blocks\BlockTypes\Checkout; +use Automattic\WooCommerce\StoreApi\Utilities\NoticeHandler; /** * BlockTypesController class. @@ -154,8 +155,12 @@ public function block_hydration_wrapper( $block_content, $block, $instance ) { return $block_content; } - $block_type = $instance->block_type; - $attr_definitions = isset( $block_type ) ? $block_type->attributes : []; + $block_type = $instance->block_type; + if ( ! $block_type ) { + // We might use a better way to flag it here. + wc_add_notice( 'You need to make a server registration of ' . $block['blockName'], 'error' ); + } + $attr_definitions = $block_type->attributes; $attributes = array(); $sourced_attributes = array(); @@ -193,8 +198,8 @@ public function block_hydration_wrapper( $block_content, $block, $instance ) { 'data-wp-block-props="%6$s" ' . 'data-wp-block-hydration="idle">', esc_attr( $block['blockName'] ), - esc_attr( wp_json_encode( isset( $block_type ) ? $block_type->uses_context : [] ) ), - esc_attr( wp_json_encode( isset( $block_type ) ? $block_type->provides_context : [] ) ), + esc_attr( wp_json_encode( $block_type->uses_context ) ), + esc_attr( wp_json_encode( $block_type->provides_context ) ), esc_attr( wp_json_encode( $attributes ) ), esc_attr( wp_json_encode( $sourced_attributes ) ), esc_attr( wp_json_encode( $block_supports_attributes ) ) @@ -301,6 +306,7 @@ protected function get_block_types() { [ 'AllProducts', 'Cart', + 'CartOrderSummaryCouponFormBlock', 'Checkout', ] ); @@ -315,6 +321,7 @@ protected function get_block_types() { [ 'AllProducts', 'Cart', + 'CartOrderSummaryCouponFormBlock', 'Checkout', ] ); From d48d81aa638db7cc9fcb5d390d41be4f3cefa6a9 Mon Sep 17 00:00:00 2001 From: Carlos Bravo Date: Fri, 12 Aug 2022 15:21:47 +0200 Subject: [PATCH 07/14] Code cleaning --- assets/js/atomic/utils/render-parent-block.tsx | 2 -- .../cart-order-summary-coupon-form/block.tsx | 8 -------- .../inner-blocks/cart-order-summary-heading/block.tsx | 5 ----- src/BlockTypesController.php | 9 +-------- 4 files changed, 1 insertion(+), 23 deletions(-) diff --git a/assets/js/atomic/utils/render-parent-block.tsx b/assets/js/atomic/utils/render-parent-block.tsx index 72582e9bd..e1739e1a5 100644 --- a/assets/js/atomic/utils/render-parent-block.tsx +++ b/assets/js/atomic/utils/render-parent-block.tsx @@ -163,7 +163,6 @@ const renderInnerBlocks = ( { ...( node instanceof HTMLElement ? node.dataset : {} ), className: node instanceof Element ? node?.className : '', }; - const InnerBlockComponent = getBlockComponentFromMap( blockName, blockMap @@ -181,7 +180,6 @@ const renderInnerBlocks = ( { node?.textContent || '' ); - // Returns text nodes without manipulation. if ( typeof parsedElement === 'string' && !! parsedElement ) { return parsedElement; diff --git a/assets/js/blocks/cart/inner-blocks/cart-order-summary-coupon-form/block.tsx b/assets/js/blocks/cart/inner-blocks/cart-order-summary-coupon-form/block.tsx index 0be98ffe4..7983eae49 100644 --- a/assets/js/blocks/cart/inner-blocks/cart-order-summary-coupon-form/block.tsx +++ b/assets/js/blocks/cart/inner-blocks/cart-order-summary-coupon-form/block.tsx @@ -5,14 +5,10 @@ import { TotalsCoupon } from '@woocommerce/base-components/cart-checkout'; import { useStoreCartCoupons } from '@woocommerce/base-context/hooks'; import { getSetting } from '@woocommerce/settings'; import { TotalsWrapper } from '@woocommerce/blocks-checkout'; -import { useState } from '@wordpress/element'; const Block = ( { className }: { className: string } ): JSX.Element | null => { const couponsEnabled = getSetting( 'couponsEnabled', true ); - /* Added a temporary setState to easily check hydration */ - const [ count, setCount ] = useState( 0 ); - const { applyCoupon, isApplyingCoupon } = useStoreCartCoupons( 'wc/cart' ); if ( ! couponsEnabled ) { @@ -25,10 +21,6 @@ const Block = ( { className }: { className: string } ): JSX.Element | null => { onSubmit={ applyCoupon } isLoading={ isApplyingCoupon } /> - { /* Added a temporary button to easily check hydration */ } - ); }; diff --git a/assets/js/blocks/cart/inner-blocks/cart-order-summary-heading/block.tsx b/assets/js/blocks/cart/inner-blocks/cart-order-summary-heading/block.tsx index 96a7a43b5..015c29f8f 100644 --- a/assets/js/blocks/cart/inner-blocks/cart-order-summary-heading/block.tsx +++ b/assets/js/blocks/cart/inner-blocks/cart-order-summary-heading/block.tsx @@ -3,7 +3,6 @@ */ import Title from '@woocommerce/base-components/title'; import classnames from 'classnames'; -import { useState } from '@wordpress/element'; const Block = ( { className, @@ -12,16 +11,12 @@ const Block = ( { className: string; content: string; } ): JSX.Element => { - const [ count, setCount ] = useState( 0 ); return ( { content } - <button - onClick={ () => setCount( count + 1 ) } - >{ `Counter: ${ count }` }</button> ); }; diff --git a/src/BlockTypesController.php b/src/BlockTypesController.php index b60483004..dab774d21 100644 --- a/src/BlockTypesController.php +++ b/src/BlockTypesController.php @@ -8,7 +8,6 @@ use Automattic\WooCommerce\Blocks\Integrations\IntegrationRegistry; use Automattic\WooCommerce\Blocks\BlockTypes\Cart; use Automattic\WooCommerce\Blocks\BlockTypes\Checkout; -use Automattic\WooCommerce\StoreApi\Utilities\NoticeHandler; /** * BlockTypesController class. @@ -155,11 +154,7 @@ public function block_hydration_wrapper( $block_content, $block, $instance ) { return $block_content; } - $block_type = $instance->block_type; - if ( ! $block_type ) { - // We might use a better way to flag it here. - wc_add_notice( 'You need to make a server registration of ' . $block['blockName'], 'error' ); - } + $block_type = $instance->block_type; $attr_definitions = $block_type->attributes; $attributes = array(); @@ -306,7 +301,6 @@ protected function get_block_types() { [ 'AllProducts', 'Cart', - 'CartOrderSummaryCouponFormBlock', 'Checkout', ] ); @@ -321,7 +315,6 @@ protected function get_block_types() { [ 'AllProducts', 'Cart', - 'CartOrderSummaryCouponFormBlock', 'Checkout', ] ); From 29df37cb76f985015d2b777e73725522f3789728 Mon Sep 17 00:00:00 2001 From: Carlos Bravo Date: Fri, 12 Aug 2022 16:01:48 +0200 Subject: [PATCH 08/14] Some more small refactors --- src/BlockTypesController.php | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/BlockTypesController.php b/src/BlockTypesController.php index dab774d21..b7dbead04 100644 --- a/src/BlockTypesController.php +++ b/src/BlockTypesController.php @@ -100,11 +100,14 @@ public function add_data_attributes( $content, $block ) { return $content; } - if ( 'woocommerce/all-products' === $block_name ) { - return $content; - } - - if ( 'woocommerce/cart-order-summary-coupon-form-block' === $block_name ) { + if ( in_array( + $block_name, + array( + 'woocommerce/all-products', + 'woocommerce/cart-order-summary-coupon-form-block', + ), + true + ) ) { return $content; } From 895c21a3dec1f55241f73412e3429e9b340a66cc Mon Sep 17 00:00:00 2001 From: Carlos Bravo Date: Tue, 16 Aug 2022 13:43:15 +0200 Subject: [PATCH 09/14] Update with frontend bhe registration --- assets/js/base/utils/bhe-blocks.tsx | 35 +++++++++++++++++++ .../cart-order-summary-coupon-form/edit.tsx | 4 --- .../frontend.tsx | 1 + .../cart-order-summary-coupon-form/index.tsx | 32 ++++++++--------- 4 files changed, 51 insertions(+), 21 deletions(-) create mode 100644 assets/js/base/utils/bhe-blocks.tsx diff --git a/assets/js/base/utils/bhe-blocks.tsx b/assets/js/base/utils/bhe-blocks.tsx new file mode 100644 index 000000000..50c00b57a --- /dev/null +++ b/assets/js/base/utils/bhe-blocks.tsx @@ -0,0 +1,35 @@ +/** + * External dependencies + */ +import { useBlockProps, useInnerBlocksProps } from '@wordpress/block-editor'; +import { registerBlockType as gutenbergRegisterBlockType } from '@wordpress/blocks'; +import { Fragment } from '@wordpress/element'; + +const save = + ( name, Comp ) => + ( { attributes } ) => { + const blockProps = useBlockProps.save(); + const innerBlocksProps = useInnerBlocksProps.save(); + + return ( + + + + + { /* Render InnerBlocks inside a template, to avoid losing them + if Comp doesn't render them. */ } +