From d2636f55f8644fde10002f0556f2e7128146b1aa Mon Sep 17 00:00:00 2001 From: Nathan Silveira Date: Fri, 5 Jan 2024 15:01:12 -0300 Subject: [PATCH] Add HOC to hide inventory collapsible block when nothing is inside it (#43228) * Add expression-evaluation package * Export useEvaluationContext * Add HOC to hide collapsible block when nothing is inside it * Add changelog * Create a separate place for WP hooks and move existing hook to it * Reintroduce line deleted automatically * Refactor to useSelect --- .../changelog/add-hide-advanced-section | 4 + packages/js/product-editor/package.json | 4 + packages/js/product-editor/src/index.ts | 3 + .../register-product-editor-block-type.ts | 2 +- .../hide-inventory-advanced-collapsible.tsx | 91 +++++++++++++++++++ .../js/product-editor/src/wp-hooks/index.ts | 8 ++ pnpm-lock.yaml | 3 + 7 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 packages/js/product-editor/changelog/add-hide-advanced-section create mode 100644 packages/js/product-editor/src/wp-hooks/hide-inventory-advanced-collapsible.tsx create mode 100644 packages/js/product-editor/src/wp-hooks/index.ts diff --git a/packages/js/product-editor/changelog/add-hide-advanced-section b/packages/js/product-editor/changelog/add-hide-advanced-section new file mode 100644 index 00000000000..349b6e2833f --- /dev/null +++ b/packages/js/product-editor/changelog/add-hide-advanced-section @@ -0,0 +1,4 @@ +Significance: minor +Type: add + +Add HOC to hide inventory collapsible block when nothing is inside it diff --git a/packages/js/product-editor/package.json b/packages/js/product-editor/package.json index 629f1dbb09d..7f4f20936e5 100644 --- a/packages/js/product-editor/package.json +++ b/packages/js/product-editor/package.json @@ -44,6 +44,7 @@ "@woocommerce/customer-effort-score": "workspace:*", "@woocommerce/data": "workspace:*", "@woocommerce/experimental": "workspace:*", + "@woocommerce/expression-evaluation": "workspace:*", "@woocommerce/navigation": "workspace:^", "@woocommerce/number": "workspace:*", "@woocommerce/settings": "^1.0.0", @@ -236,6 +237,9 @@ "node_modules/@woocommerce/navigation/build", "node_modules/@woocommerce/navigation/build-module", "node_modules/@woocommerce/navigation/build-types", + "node_modules/@woocommerce/expression-evaluation/build", + "node_modules/@woocommerce/expression-evaluation/build-module", + "node_modules/@woocommerce/expression-evaluation/build-types", "node_modules/@woocommerce/experimental/build", "node_modules/@woocommerce/experimental/build-module", "node_modules/@woocommerce/experimental/build-style", diff --git a/packages/js/product-editor/src/index.ts b/packages/js/product-editor/src/index.ts index 55964e55a03..ec36de52af7 100644 --- a/packages/js/product-editor/src/index.ts +++ b/packages/js/product-editor/src/index.ts @@ -2,6 +2,7 @@ * Internal dependencies */ import registerProductEditorUiStore from './store/product-editor-ui'; +import registerProductEditorHooks from './wp-hooks'; export * from './components'; export { @@ -36,3 +37,5 @@ export * from './contexts/validation-context/types'; // Init the store registerProductEditorUiStore(); + +registerProductEditorHooks(); diff --git a/packages/js/product-editor/src/utils/register-product-editor-block-type.ts b/packages/js/product-editor/src/utils/register-product-editor-block-type.ts index 29c5415c935..d1f7fe915e9 100644 --- a/packages/js/product-editor/src/utils/register-product-editor-block-type.ts +++ b/packages/js/product-editor/src/utils/register-product-editor-block-type.ts @@ -15,7 +15,7 @@ interface BlockRepresentation< T extends Record< string, object > > { settings: Partial< BlockConfiguration< T > >; } -function useEvaluationContext( context: Record< string, unknown > ) { +export function useEvaluationContext( context: Record< string, unknown > ) { const { postType } = context; const productId = useEntityId( 'postType', postType ); diff --git a/packages/js/product-editor/src/wp-hooks/hide-inventory-advanced-collapsible.tsx b/packages/js/product-editor/src/wp-hooks/hide-inventory-advanced-collapsible.tsx new file mode 100644 index 00000000000..9d79e4222b9 --- /dev/null +++ b/packages/js/product-editor/src/wp-hooks/hide-inventory-advanced-collapsible.tsx @@ -0,0 +1,91 @@ +/** + * External dependencies + */ +import type { BlockInstance } from '@wordpress/blocks'; +import { createElement } from '@wordpress/element'; +import { addFilter } from '@wordpress/hooks'; +import { createHigherOrderComponent } from '@wordpress/compose'; +import { useSelect } from '@wordpress/data'; +import { evaluate } from '@woocommerce/expression-evaluation'; + +/** + * Internal dependencies + */ +import { useEvaluationContext } from '../utils'; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const areAllBlocksInvisible = ( blocks: BlockInstance[], context: any ) => { + return blocks.every( ( block ) => { + if ( + ! block.attributes?._templateBlockHideConditions || + ! Array.isArray( block.attributes?._templateBlockHideConditions ) + ) { + return false; + } + return block.attributes._templateBlockHideConditions.some( + ( condition ) => evaluate( condition.expression, context ) + ); + } ); +}; + +const maybeHideInventoryAdvancedCollapsible = createHigherOrderComponent< + Record< string, unknown > +>( ( BlockEdit ) => { + return ( props ) => { + const { hasInnerBlocks, allBlocksInvisible: blocksInvisible } = + useSelect( ( select ) => { + // bail early if not the product-inventory-advanced block + if ( + ( props?.attributes as Record< string, string > ) + ?._templateBlockId !== 'product-inventory-advanced' + ) { + return { + hasInnerBlocks: true, + allBlocksInvisible: false, + }; + } + const evalContext = useEvaluationContext( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + props.context as any + ); + const advancedCollapsibleBlock = select( + 'core/block-editor' + ).getBlock( props?.clientId as string ); + + let allBlocksInvisible = false; + if ( advancedCollapsibleBlock?.innerBlocks?.length ) { + const advancedSectionBlock = + advancedCollapsibleBlock?.innerBlocks[ 0 ]; + allBlocksInvisible = areAllBlocksInvisible( + advancedSectionBlock?.innerBlocks, + evalContext.getEvaluationContext( select ) + ); + } + + return { + hasInnerBlocks: + !! advancedCollapsibleBlock?.innerBlocks?.length, + allBlocksInvisible, + }; + } ); + + // No inner blocks, so we can render the default block edit. + if ( ! hasInnerBlocks ) { + return ; + } + + if ( blocksInvisible ) { + return null; + } + + return ; + }; +}, 'maybeHideInventoryAdvancedCollapsible' ); + +export default function () { + addFilter( + 'editor.BlockEdit', + 'woocommerce/handle-hide-inventory-advanced-collapsible', + maybeHideInventoryAdvancedCollapsible + ); +} diff --git a/packages/js/product-editor/src/wp-hooks/index.ts b/packages/js/product-editor/src/wp-hooks/index.ts new file mode 100644 index 00000000000..21389da4826 --- /dev/null +++ b/packages/js/product-editor/src/wp-hooks/index.ts @@ -0,0 +1,8 @@ +/** + * Internal dependencies + */ +import registerHideInventoryAdvancedCollapsible from './hide-inventory-advanced-collapsible'; + +export default function registerProductEditorHooks() { + registerHideInventoryAdvancedCollapsible(); +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 35b127eb868..9e6bab9c27e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2549,6 +2549,9 @@ importers: '@woocommerce/experimental': specifier: workspace:* version: link:../experimental + '@woocommerce/expression-evaluation': + specifier: workspace:* + version: link:../expression-evaluation '@woocommerce/navigation': specifier: workspace:^ version: link:../navigation