From 1ba9520205f524ddd6fa5a4aa21ce2c54a49799e Mon Sep 17 00:00:00 2001 From: Saad Tarhi Date: Thu, 11 Aug 2022 09:14:00 +0100 Subject: [PATCH 1/3] Show "Feedback prompt" for all inner blocks --- .../feedback-prompt/index.js | 48 +++++++++++-------- 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/assets/js/editor-components/feedback-prompt/index.js b/assets/js/editor-components/feedback-prompt/index.js index 1ced9034a66..471a0bdabac 100644 --- a/assets/js/editor-components/feedback-prompt/index.js +++ b/assets/js/editor-components/feedback-prompt/index.js @@ -4,6 +4,7 @@ import { __ } from '@wordpress/i18n'; import PropTypes from 'prop-types'; import { Icon, commentContent, external } from '@wordpress/icons'; +import { useEffect, useState } from '@wordpress/element'; /** * Internal dependencies @@ -21,26 +22,35 @@ const FeedbackPrompt = ( { text, url = 'https://ideas.woocommerce.com/forums/133476-woocommerce?category_id=384565', } ) => { + const [ isVisible, setIsVisible ] = useState( false ); + + // This is a hack to render the feedback prompt last in the sidebar. + useEffect( () => { + setIsVisible( true ); + }, [] ); + return ( -
- -

- { __( 'Feedback?', 'woo-gutenberg-products-block' ) } -

-

{ text }

- - { __( - 'Give us your feedback.', - 'woo-gutenberg-products-block' - ) } - - -
+ isVisible && ( +
+ +

+ { __( 'Feedback?', 'woo-gutenberg-products-block' ) } +

+

{ text }

+ + { __( + 'Give us your feedback.', + 'woo-gutenberg-products-block' + ) } + + +
+ ) ); }; From 7d5f9a57b7e0f2a1a99bc86cfc109d3821087920 Mon Sep 17 00:00:00 2001 From: Saad Tarhi Date: Thu, 11 Aug 2022 16:38:16 +0100 Subject: [PATCH 2/3] Fix the "feedback" notice position for these blocks The "checkout fields", "checkout billing address" and "checkout shipping address" have the addressFields option which gets rerendered and placed at the bottom of the inspector controls. --- .../address-fields/index.tsx | 153 ++++++++++++++++++ .../js/blocks/cart-checkout-shared/index.js | 1 + assets/js/blocks/checkout/context.ts | 11 +- assets/js/blocks/checkout/edit.tsx | 71 +------- .../checkout-billing-address-block/edit.tsx | 8 +- .../checkout-fields-block/edit.tsx | 5 - .../checkout-shipping-address-block/edit.tsx | 9 +- .../feedback-prompt/index.js | 6 +- 8 files changed, 166 insertions(+), 98 deletions(-) create mode 100644 assets/js/blocks/cart-checkout-shared/address-fields/index.tsx diff --git a/assets/js/blocks/cart-checkout-shared/address-fields/index.tsx b/assets/js/blocks/cart-checkout-shared/address-fields/index.tsx new file mode 100644 index 00000000000..8819cff02b3 --- /dev/null +++ b/assets/js/blocks/cart-checkout-shared/address-fields/index.tsx @@ -0,0 +1,153 @@ +/** + * External dependencies + */ +import { __ } from '@wordpress/i18n'; +import { createHigherOrderComponent } from '@wordpress/compose'; +import { InspectorControls } from '@wordpress/block-editor'; +import { + PanelBody, + ToggleControl, + CheckboxControl, +} from '@wordpress/components'; +import { addFilter, hasFilter } from '@wordpress/hooks'; +import { useSelect } from '@wordpress/data'; +import { isString } from '@woocommerce/types'; + +interface Attributes extends Record< string, boolean | number > { + allowCreateAccount: boolean; + hasDarkControls: boolean; + showCompanyField: boolean; + showApartmentField: boolean; + showPhoneField: boolean; + requireCompanyField: boolean; + requirePhoneField: boolean; + // Deprecated. + showOrderNotes: boolean; + showPolicyLinks: boolean; + showReturnToCart: boolean; + showRateAfterTaxName: boolean; + cartPageId: number; +} + +const withAddressFields = createHigherOrderComponent( + ( BlockEdit ) => ( props ) => { + const { clientId } = props; + const blockName = useSelect( ( select ) => { + return select( 'core/block-editor' ).getBlockName( clientId ); + } ); + const blocksWithAddressFields = [ + 'woocommerce/checkout-shipping-address', + 'woocommerce/checkout-billing-address', + 'woocommerce/checkout-fields-block', + ]; + + if ( + isString( blockName ) && + ! blocksWithAddressFields.includes( blockName ) + ) { + return ; + } + + const { attributes, setAttributes } = props; + const { + showCompanyField, + requireCompanyField, + showApartmentField, + showPhoneField, + requirePhoneField, + } = attributes; + + const toggleAttribute = ( key: keyof Attributes ): void => { + const newAttributes = {} as Partial< Attributes >; + newAttributes[ key ] = ! ( attributes[ key ] as boolean ); + setAttributes( newAttributes ); + }; + + const AddressFields = (): JSX.Element => ( + + +

+ { __( + 'Show or hide fields in the checkout address forms.', + 'woo-gutenberg-products-block' + ) } +

+ toggleAttribute( 'showCompanyField' ) } + /> + { showCompanyField && ( + + toggleAttribute( 'requireCompanyField' ) + } + className="components-base-control--nested" + /> + ) } + + toggleAttribute( 'showApartmentField' ) + } + /> + toggleAttribute( 'showPhoneField' ) } + /> + { showPhoneField && ( + + toggleAttribute( 'requirePhoneField' ) + } + className="components-base-control--nested" + /> + ) } +
+
+ ); + + return ( + <> + + + + + + + ); + }, + 'withAddressFields' +); + +if ( ! hasFilter( 'editor.BlockEdit', 'woocommerce/add/address-fields' ) ) { + addFilter( + 'editor.BlockEdit', + 'woocommerce/add/address-fields', + withAddressFields, + 9 + ); +} diff --git a/assets/js/blocks/cart-checkout-shared/index.js b/assets/js/blocks/cart-checkout-shared/index.js index 36a16f5804b..eb401bc3bc5 100644 --- a/assets/js/blocks/cart-checkout-shared/index.js +++ b/assets/js/blocks/cart-checkout-shared/index.js @@ -5,3 +5,4 @@ export * from './use-view-switcher'; export * from './default-notice'; export * from './sidebar-notices'; export * from './block-settings'; +export * from './address-fields'; diff --git a/assets/js/blocks/checkout/context.ts b/assets/js/blocks/checkout/context.ts index 7293a909e3a..07a87e5f306 100644 --- a/assets/js/blocks/checkout/context.ts +++ b/assets/js/blocks/checkout/context.ts @@ -21,12 +21,11 @@ export type CheckoutBlockContextProps = { }; export type CheckoutBlockControlsContextProps = { - addressFieldControls: () => JSX.Element | null; accountControls: () => JSX.Element | null; }; -export const CheckoutBlockContext = createContext< CheckoutBlockContextProps >( - { +export const CheckoutBlockContext: React.Context< CheckoutBlockContextProps > = + createContext< CheckoutBlockContextProps >( { allowCreateAccount: false, showCompanyField: false, showApartmentField: false, @@ -38,12 +37,10 @@ export const CheckoutBlockContext = createContext< CheckoutBlockContextProps >( showReturnToCart: true, cartPageId: 0, showRateAfterTaxName: false, - } -); + } ); -export const CheckoutBlockControlsContext = +export const CheckoutBlockControlsContext: React.Context< CheckoutBlockControlsContextProps > = createContext< CheckoutBlockControlsContextProps >( { - addressFieldControls: () => null, accountControls: () => null, } ); diff --git a/assets/js/blocks/checkout/edit.tsx b/assets/js/blocks/checkout/edit.tsx index 7c4f4a48649..00fea76f944 100644 --- a/assets/js/blocks/checkout/edit.tsx +++ b/assets/js/blocks/checkout/edit.tsx @@ -14,11 +14,7 @@ import { previewCart, previewSavedPaymentMethods, } from '@woocommerce/resource-previews'; -import { - PanelBody, - ToggleControl, - CheckboxControl, -} from '@wordpress/components'; +import { PanelBody, ToggleControl } from '@wordpress/components'; import type { TemplateArray } from '@wordpress/blocks'; /** * Internal dependencies @@ -68,12 +64,6 @@ export const Edit = ( { [ 'woocommerce/checkout-totals-block', {}, [] ], ] as TemplateArray; - const toggleAttribute = ( key: keyof Attributes ): void => { - const newAttributes = {} as Partial< Attributes >; - newAttributes[ key ] = ! ( attributes[ key ] as boolean ); - setAttributes( newAttributes ); - }; - const accountControls = (): JSX.Element => ( ); - const addressFieldControls = (): JSX.Element => ( - - -

- { __( - 'Show or hide fields in the checkout address forms.', - 'woo-gutenberg-products-block' - ) } -

- toggleAttribute( 'showCompanyField' ) } - /> - { showCompanyField && ( - - toggleAttribute( 'requireCompanyField' ) - } - className="components-base-control--nested" - /> - ) } - toggleAttribute( 'showApartmentField' ) } - /> - toggleAttribute( 'showPhoneField' ) } - /> - { showPhoneField && ( - - toggleAttribute( 'requirePhoneField' ) - } - className="components-base-control--nested" - /> - ) } -
-
- ); const blockProps = useBlockPropsWithLocking(); return (
@@ -176,7 +108,6 @@ export const Edit = ( { > diff --git a/assets/js/blocks/checkout/inner-blocks/checkout-billing-address-block/edit.tsx b/assets/js/blocks/checkout/inner-blocks/checkout-billing-address-block/edit.tsx index 692b9c4f20c..c3b15122b10 100644 --- a/assets/js/blocks/checkout/inner-blocks/checkout-billing-address-block/edit.tsx +++ b/assets/js/blocks/checkout/inner-blocks/checkout-billing-address-block/edit.tsx @@ -14,10 +14,7 @@ import { AdditionalFields, AdditionalFieldsContent, } from '../../form-step'; -import { - useCheckoutBlockContext, - useCheckoutBlockControlsContext, -} from '../../context'; +import { useCheckoutBlockContext } from '../../context'; import Block from './block'; export const Edit = ( { @@ -39,8 +36,6 @@ export const Edit = ( { showPhoneField, requirePhoneField, } = useCheckoutBlockContext(); - const { addressFieldControls: Controls } = - useCheckoutBlockControlsContext(); const { showBillingFields } = useCheckoutAddress(); if ( ! showBillingFields ) { @@ -56,7 +51,6 @@ export const Edit = ( { attributes?.className ) } > - -
- { + // By returning false we ensure that this component is not entered into the InspectorControls + // (which is a slot fill), children array on first render, on the second render when the state + // gets updated this component does get put into the InspectorControls children array but as the + // last item, ensuring it shows last in the sidebar. const [ isVisible, setIsVisible ] = useState( false ); - - // This is a hack to render the feedback prompt last in the sidebar. useEffect( () => { setIsVisible( true ); }, [] ); From 51e92ae883121361ef1c8d75b89182b5b314afcc Mon Sep 17 00:00:00 2001 From: Saad Tarhi Date: Thu, 11 Aug 2022 17:00:48 +0100 Subject: [PATCH 3/3] Tidy up the address-fields hoc --- .../address-fields/index.tsx | 113 +++++++++--------- 1 file changed, 57 insertions(+), 56 deletions(-) diff --git a/assets/js/blocks/cart-checkout-shared/address-fields/index.tsx b/assets/js/blocks/cart-checkout-shared/address-fields/index.tsx index 8819cff02b3..114e7b08c69 100644 --- a/assets/js/blocks/cart-checkout-shared/address-fields/index.tsx +++ b/assets/js/blocks/cart-checkout-shared/address-fields/index.tsx @@ -63,77 +63,78 @@ const withAddressFields = createHigherOrderComponent( setAttributes( newAttributes ); }; - const AddressFields = (): JSX.Element => ( - - -

- { __( - 'Show or hide fields in the checkout address forms.', - 'woo-gutenberg-products-block' - ) } -

- + + toggleAttribute( 'showCompanyField' ) } - /> - { showCompanyField && ( - +

+ { __( + 'Show or hide fields in the checkout address forms.', + 'woo-gutenberg-products-block' + ) } +

+ - toggleAttribute( 'requireCompanyField' ) + toggleAttribute( 'showCompanyField' ) } - className="components-base-control--nested" /> - ) } - + toggleAttribute( 'requireCompanyField' ) + } + className="components-base-control--nested" + /> ) } - checked={ showApartmentField } - onChange={ () => - toggleAttribute( 'showApartmentField' ) - } - /> - toggleAttribute( 'showPhoneField' ) } - /> - { showPhoneField && ( - - toggleAttribute( 'requirePhoneField' ) + toggleAttribute( 'showApartmentField' ) } - className="components-base-control--nested" /> - ) } -
-
- ); - - return ( - <> - - + + toggleAttribute( 'showPhoneField' ) + } + /> + { showPhoneField && ( + + toggleAttribute( 'requirePhoneField' ) + } + className="components-base-control--nested" + /> + ) } +