From cbde25b5cd84444774df0f8f5b6f3bfd403fc1c0 Mon Sep 17 00:00:00 2001 From: Darren Ethier Date: Mon, 19 Jun 2023 18:53:02 -0400 Subject: [PATCH] Implement discount as inner blocks This allows for being able to edit the text portion of the discount rendering as its own entity. --- .../price-v2/inner-blocks/discount/block.json | 9 +++ .../price-v2/inner-blocks/discount/edit.tsx | 56 +++++++++---------- .../price-v2/inner-blocks/discount/index.ts | 10 ++-- .../inner-blocks/discount-amount/block.json | 14 +++++ .../discount-amount}/block.tsx | 0 .../inner-blocks/discount-amount/edit.tsx | 51 +++++++++++++++++ .../inner-blocks/discount-amount/index.ts | 27 +++++++++ .../discount/inner-blocks/index.tsx | 6 ++ .../inner-blocks/discount/template.ts | 34 +++++++++++ 9 files changed, 174 insertions(+), 33 deletions(-) create mode 100644 assets/js/atomic/blocks/product-elements/price-v2/inner-blocks/discount/inner-blocks/discount-amount/block.json rename assets/js/atomic/blocks/product-elements/price-v2/inner-blocks/discount/{ => inner-blocks/discount-amount}/block.tsx (100%) create mode 100644 assets/js/atomic/blocks/product-elements/price-v2/inner-blocks/discount/inner-blocks/discount-amount/edit.tsx create mode 100644 assets/js/atomic/blocks/product-elements/price-v2/inner-blocks/discount/inner-blocks/discount-amount/index.ts create mode 100644 assets/js/atomic/blocks/product-elements/price-v2/inner-blocks/discount/inner-blocks/index.tsx create mode 100644 assets/js/atomic/blocks/product-elements/price-v2/inner-blocks/discount/template.ts diff --git a/assets/js/atomic/blocks/product-elements/price-v2/inner-blocks/discount/block.json b/assets/js/atomic/blocks/product-elements/price-v2/inner-blocks/discount/block.json index dedfd2d970c..480e13efa02 100644 --- a/assets/js/atomic/blocks/product-elements/price-v2/inner-blocks/discount/block.json +++ b/assets/js/atomic/blocks/product-elements/price-v2/inner-blocks/discount/block.json @@ -7,6 +7,15 @@ "category": "woocommerce", "keywords": [ "WooCommerce" ], "textdomain": "woo-gutenberg-products-block", + "supports": { + "__experimentalLayout": { + "allowSwitching": false, + "allowInheriting": false, + "default": { "type": "flex" } + }, + "html": false + + }, "apiVersion": 2, "$schema": "https://schemas.wp.org/trunk/block.json" } diff --git a/assets/js/atomic/blocks/product-elements/price-v2/inner-blocks/discount/edit.tsx b/assets/js/atomic/blocks/product-elements/price-v2/inner-blocks/discount/edit.tsx index 4e1894030df..87fae2a6fc1 100644 --- a/assets/js/atomic/blocks/product-elements/price-v2/inner-blocks/discount/edit.tsx +++ b/assets/js/atomic/blocks/product-elements/price-v2/inner-blocks/discount/edit.tsx @@ -1,51 +1,49 @@ /** * External dependencies */ -import { useBlockProps } from '@wordpress/block-editor'; -import type { HTMLAttributes, CSSProperties } from 'react'; +import { useBlockProps, InnerBlocks } from '@wordpress/block-editor'; import { useProductDataContext } from '@woocommerce/shared-context'; -import { getCurrencyFromPriceResponse } from '@woocommerce/price-format'; +import { useStyleProps } from '@woocommerce/base-hooks'; +import { useEffect } from '@wordpress/element'; /** * Internal dependencies */ -import DiscountBlock from './block'; +import { discountAmountName } from './inner-blocks'; +import { TEMPLATE } from './template'; -interface Attributes { - style: CSSProperties; -} - -type Props = { - attributes: Attributes; - context?: { isDescendentOfSingleProductTemplate: boolean }; -} & HTMLAttributes< HTMLDivElement >; - -const DiscountEdit = ( { attributes, context }: Props ): JSX.Element => { - const blockProps = useBlockProps(); +export const Edit = ( { attributes, setAttributes } ): JSX.Element => { + const { style, className } = useStyleProps( attributes ); const { product } = useProductDataContext(); - const { isDescendentOfSingleProductTemplate = false } = context || {}; const originalPrice = product?.prices?.regular_price; const currentPrice = product?.prices?.price; const showPrice = originalPrice && currentPrice !== originalPrice; - const currency = isDescendentOfSingleProductTemplate - ? getCurrencyFromPriceResponse() - : getCurrencyFromPriceResponse( product?.prices ); - const blockAttrs = { - attributes, - currency, - context, - originalPrice, - currentPrice, - }; + useEffect( () => { + if ( ! attributes?.style ) { + setAttributes( { style: { spacing: { blockGap: '0' } } } ); + } + }, [ attributes, setAttributes ] ); return ( <> { showPrice && ( -
- +
+
) } ); }; -export default DiscountEdit; +export const Save = (): JSX.Element => { + return ( +
+ +
+ ); +}; diff --git a/assets/js/atomic/blocks/product-elements/price-v2/inner-blocks/discount/index.ts b/assets/js/atomic/blocks/product-elements/price-v2/inner-blocks/discount/index.ts index 5cbea61364e..40171006b72 100644 --- a/assets/js/atomic/blocks/product-elements/price-v2/inner-blocks/discount/index.ts +++ b/assets/js/atomic/blocks/product-elements/price-v2/inner-blocks/discount/index.ts @@ -6,8 +6,9 @@ import { registerBlockType } from '@wordpress/blocks'; /** * Internal dependencies */ -import edit from './edit'; +import { Edit as edit, Save as save } from './edit'; import sharedConfig from '../../../shared/config'; +import { supports } from '../../supports'; import metadata from './block.json'; const { ancestor, ...configuration } = sharedConfig; @@ -15,11 +16,12 @@ const { ancestor, ...configuration } = sharedConfig; const blockConfig = { ...configuration, ...metadata, - edit, supports: { - ...configuration.supports, - context: '', + ...supports, + ...metadata.supports, }, + edit, + save, }; registerBlockType( metadata.name, blockConfig ); diff --git a/assets/js/atomic/blocks/product-elements/price-v2/inner-blocks/discount/inner-blocks/discount-amount/block.json b/assets/js/atomic/blocks/product-elements/price-v2/inner-blocks/discount/inner-blocks/discount-amount/block.json new file mode 100644 index 00000000000..536c10795fc --- /dev/null +++ b/assets/js/atomic/blocks/product-elements/price-v2/inner-blocks/discount/inner-blocks/discount-amount/block.json @@ -0,0 +1,14 @@ +{ + "name": "woocommerce/discount-amount", + "version": "1.0.0", + "icon": "info", + "title": "Discount Amount", + "description": "Display the discounted amount value.", + "category": "woocommerce", + "usesContext": ["woocommerce/isDescendantOfSingleProductTemplate"], + "keywords": [ "WooCommerce" ], + "textdomain": "woo-gutenberg-products-block", + "ancestor": "woocommerce/discount", + "apiVersion": 2, + "$schema": "https://schemas.wp.org/trunk/block.json" +} diff --git a/assets/js/atomic/blocks/product-elements/price-v2/inner-blocks/discount/block.tsx b/assets/js/atomic/blocks/product-elements/price-v2/inner-blocks/discount/inner-blocks/discount-amount/block.tsx similarity index 100% rename from assets/js/atomic/blocks/product-elements/price-v2/inner-blocks/discount/block.tsx rename to assets/js/atomic/blocks/product-elements/price-v2/inner-blocks/discount/inner-blocks/discount-amount/block.tsx diff --git a/assets/js/atomic/blocks/product-elements/price-v2/inner-blocks/discount/inner-blocks/discount-amount/edit.tsx b/assets/js/atomic/blocks/product-elements/price-v2/inner-blocks/discount/inner-blocks/discount-amount/edit.tsx new file mode 100644 index 00000000000..4e1894030df --- /dev/null +++ b/assets/js/atomic/blocks/product-elements/price-v2/inner-blocks/discount/inner-blocks/discount-amount/edit.tsx @@ -0,0 +1,51 @@ +/** + * External dependencies + */ +import { useBlockProps } from '@wordpress/block-editor'; +import type { HTMLAttributes, CSSProperties } from 'react'; +import { useProductDataContext } from '@woocommerce/shared-context'; +import { getCurrencyFromPriceResponse } from '@woocommerce/price-format'; + +/** + * Internal dependencies + */ +import DiscountBlock from './block'; + +interface Attributes { + style: CSSProperties; +} + +type Props = { + attributes: Attributes; + context?: { isDescendentOfSingleProductTemplate: boolean }; +} & HTMLAttributes< HTMLDivElement >; + +const DiscountEdit = ( { attributes, context }: Props ): JSX.Element => { + const blockProps = useBlockProps(); + const { product } = useProductDataContext(); + const { isDescendentOfSingleProductTemplate = false } = context || {}; + const originalPrice = product?.prices?.regular_price; + const currentPrice = product?.prices?.price; + const showPrice = originalPrice && currentPrice !== originalPrice; + const currency = isDescendentOfSingleProductTemplate + ? getCurrencyFromPriceResponse() + : getCurrencyFromPriceResponse( product?.prices ); + const blockAttrs = { + attributes, + currency, + context, + originalPrice, + currentPrice, + }; + return ( + <> + { showPrice && ( +
+ +
+ ) } + + ); +}; + +export default DiscountEdit; diff --git a/assets/js/atomic/blocks/product-elements/price-v2/inner-blocks/discount/inner-blocks/discount-amount/index.ts b/assets/js/atomic/blocks/product-elements/price-v2/inner-blocks/discount/inner-blocks/discount-amount/index.ts new file mode 100644 index 00000000000..be7063e7eb1 --- /dev/null +++ b/assets/js/atomic/blocks/product-elements/price-v2/inner-blocks/discount/inner-blocks/discount-amount/index.ts @@ -0,0 +1,27 @@ +/** + * External dependencies + */ +import { registerBlockType } from '@wordpress/blocks'; + +/** + * Internal dependencies + */ +import edit from './edit'; +import sharedConfig from '../../../../../shared/config'; +import metadata from './block.json'; + +const { ancestor, ...configuration } = sharedConfig; + +const blockConfig = { + ...configuration, + ...metadata, + edit, + supports: { + ...configuration.supports, + context: '', + }, +}; + +registerBlockType( metadata.name, blockConfig ); + +export const BLOCK_NAME = metadata.name; diff --git a/assets/js/atomic/blocks/product-elements/price-v2/inner-blocks/discount/inner-blocks/index.tsx b/assets/js/atomic/blocks/product-elements/price-v2/inner-blocks/discount/inner-blocks/index.tsx new file mode 100644 index 00000000000..9f20e96872f --- /dev/null +++ b/assets/js/atomic/blocks/product-elements/price-v2/inner-blocks/discount/inner-blocks/index.tsx @@ -0,0 +1,6 @@ +/** + * Internal dependencies + */ +import './discount-amount/index.ts'; + +export { BLOCK_NAME as discountAmountName } from './discount-amount/index'; diff --git a/assets/js/atomic/blocks/product-elements/price-v2/inner-blocks/discount/template.ts b/assets/js/atomic/blocks/product-elements/price-v2/inner-blocks/discount/template.ts new file mode 100644 index 00000000000..58153b03b92 --- /dev/null +++ b/assets/js/atomic/blocks/product-elements/price-v2/inner-blocks/discount/template.ts @@ -0,0 +1,34 @@ +/** + * External dependencies + */ +import { InnerBlockTemplate } from '@wordpress/blocks'; +import { _x, sprintf } from '@wordpress/i18n'; + +// Some hackery to both make translation clearer and to allow for RTL languages +// in default template layout. +const translatedContent = sprintf( + // translators: %s: discount amount. The rendered value will only allow for placeholder at beginning or end of string. + _x( + '%s off', + 'post text next to discount amount', + 'woo-gutenberg-products-block' + ), + ':placeholder:' +); + +const templateContent = translatedContent.replace( ':placeholder:', '' ); + +const RTLtemplate: InnerBlockTemplate[] = [ + [ 'core/paragraph', { content: templateContent }, [] ], + [ 'woocommerce/discount-amount', {}, [] ], +]; + +const LTRtemplate: InnerBlockTemplate[] = [ + [ 'woocommerce/discount-amount', {}, [] ], + [ 'core/paragraph', { content: templateContent }, [] ], +]; + +export const TEMPLATE: InnerBlockTemplate[] = + translatedContent.indexOf( ':placeholder:' ) === 0 + ? LTRtemplate + : RTLtemplate;