From 222c97775d49420b52ead22e9a55776f3b483350 Mon Sep 17 00:00:00 2001 From: Manish Menaria Date: Mon, 28 Nov 2022 11:47:27 +0530 Subject: [PATCH] Adds product query support for Category list block (#7675) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Adds product query support for Category list block On the client side, when the Category list block is used within the product query bloc, the markup will be rendered on the server side - No javascript related to Category list block will be rendered. * bot: update checkstyle.xml * Fix extra space after the category link I used the solution from following link: https://css-tricks.com/fighting-the-space-between-inline-block-elements/#aa-remove-the-spaces Here is the content from the above link: The reason you get the spaces is because, well, you have spaces between the elements (a line break and a few tabs counts as a space, just to be clear). Minimized HTML will solve this problem, or one of these tricks: ```CSS ``` or ```CSS ``` or with comments… ```CSS ``` They’re all pretty funky, but it does the trick. * Fix custom style doesn't work on the frontend side For more info, check this comment on the PR: https://github.com/woocommerce/woocommerce-blocks/pull/7675#pullrequestreview-1179267957 In summary, user can set the custom styles like text color, link color, font size, font weight, line height using the editor sidebar. These styles weren't showing on the frontend side. * Add support for additional CSS class(es) * Fix "custom style -> link color" not working To understand the issue in more details please check following comment: https://github.com/woocommerce/woocommerce-blocks/pull/7675#issuecomment-1319822535 * Fix classname undefined issue Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .../category-list/attributes.ts | 4 ++ .../product-elements/category-list/edit.tsx | 26 ++++++-- .../product-elements/category-list/index.ts | 9 ++- .../product-elements/category-list/save.tsx | 21 ------ .../product-elements/category-list/types.ts | 1 + checkstyle.xml | 9 +-- src/BlockTypes/ProductCategoryList.php | 64 ++++++++++++++++--- 7 files changed, 88 insertions(+), 46 deletions(-) delete mode 100644 assets/js/atomic/blocks/product-elements/category-list/save.tsx diff --git a/assets/js/atomic/blocks/product-elements/category-list/attributes.ts b/assets/js/atomic/blocks/product-elements/category-list/attributes.ts index caed2652df1..372f22f2568 100644 --- a/assets/js/atomic/blocks/product-elements/category-list/attributes.ts +++ b/assets/js/atomic/blocks/product-elements/category-list/attributes.ts @@ -3,6 +3,10 @@ export const blockAttributes: Record< string, Record< string, unknown > > = { type: 'number', default: 0, }, + isDescendentOfQueryLoop: { + type: 'boolean', + default: false, + }, }; export default blockAttributes; diff --git a/assets/js/atomic/blocks/product-elements/category-list/edit.tsx b/assets/js/atomic/blocks/product-elements/category-list/edit.tsx index eae09bc5581..38c46049f3b 100644 --- a/assets/js/atomic/blocks/product-elements/category-list/edit.tsx +++ b/assets/js/atomic/blocks/product-elements/category-list/edit.tsx @@ -2,9 +2,12 @@ * External dependencies */ import { __ } from '@wordpress/i18n'; +import type { BlockEditProps } from '@wordpress/blocks'; +import { ProductQueryContext as Context } from '@woocommerce/blocks/product-query/types'; import { Disabled } from '@wordpress/components'; import EditProductLink from '@woocommerce/editor-components/edit-product-link'; import { useBlockProps } from '@wordpress/block-editor'; +import { useEffect } from 'react'; /** * Internal dependencies @@ -14,18 +17,29 @@ import withProductSelector from '../shared/with-product-selector'; import { BLOCK_TITLE, BLOCK_ICON } from './constants'; import { Attributes } from './types'; -interface Props { - attributes: Attributes; -} - -const Edit = ( { attributes }: Props ): JSX.Element => { +const Edit = ( { + attributes, + setAttributes, + context, +}: BlockEditProps< Attributes > & { context: Context } ): JSX.Element => { const blockProps = useBlockProps(); + const blockAttrs = { + ...attributes, + ...context, + }; + const isDescendentOfQueryLoop = Number.isFinite( context.queryId ); + + useEffect( + () => setAttributes( { isDescendentOfQueryLoop } ), + [ setAttributes, isDescendentOfQueryLoop ] + ); + return (
- +
); diff --git a/assets/js/atomic/blocks/product-elements/category-list/index.ts b/assets/js/atomic/blocks/product-elements/category-list/index.ts index 15fd0ec92bb..369eb89bb91 100644 --- a/assets/js/atomic/blocks/product-elements/category-list/index.ts +++ b/assets/js/atomic/blocks/product-elements/category-list/index.ts @@ -18,7 +18,6 @@ import { BLOCK_ICON as icon, BLOCK_DESCRIPTION as description, } from './constants'; -import { Save } from './save'; const blockConfig: BlockConfiguration = { ...sharedConfig, @@ -27,13 +26,18 @@ const blockConfig: BlockConfiguration = { description, icon: { src: icon }, attributes, + usesContext: [ 'query', 'queryId', 'postId' ], + ancestor: [ + '@woocommerce/all-products', + '@woocommerce/single-product', + 'core/post-template', + ], supports: { ...( isFeaturePluginBuild() && { color: { text: true, link: true, background: false, - __experimentalSkipSerialization: true, }, typography: { fontSize: true, @@ -46,7 +50,6 @@ const blockConfig: BlockConfiguration = { '.wc-block-components-product-category-list', } ), }, - save: Save, edit, }; diff --git a/assets/js/atomic/blocks/product-elements/category-list/save.tsx b/assets/js/atomic/blocks/product-elements/category-list/save.tsx deleted file mode 100644 index 11135ed1bb2..00000000000 --- a/assets/js/atomic/blocks/product-elements/category-list/save.tsx +++ /dev/null @@ -1,21 +0,0 @@ -/** - * External dependencies - */ -import classnames from 'classnames'; -import { useBlockProps } from '@wordpress/block-editor'; - -type Props = { - attributes: Record< string, unknown > & { - className: string; - }; -}; - -export const Save = ( { attributes }: Props ): JSX.Element => { - return ( -
- ); -}; diff --git a/assets/js/atomic/blocks/product-elements/category-list/types.ts b/assets/js/atomic/blocks/product-elements/category-list/types.ts index 104d6e55f30..a7d3a20b916 100644 --- a/assets/js/atomic/blocks/product-elements/category-list/types.ts +++ b/assets/js/atomic/blocks/product-elements/category-list/types.ts @@ -1,3 +1,4 @@ export interface Attributes { productId: number; + isDescendentOfQueryLoop: boolean; } diff --git a/checkstyle.xml b/checkstyle.xml index 6613e296fd1..80283d8dbd9 100644 --- a/checkstyle.xml +++ b/checkstyle.xml @@ -1405,17 +1405,10 @@ Object literal may only specify known properties, and 'ancestor' does not exist in type 'BlockConfiguration<{}>'." source="TS2322" /> - - diff --git a/src/BlockTypes/ProductCategoryList.php b/src/BlockTypes/ProductCategoryList.php index cd0f10b3d5f..81e96aaaa13 100644 --- a/src/BlockTypes/ProductCategoryList.php +++ b/src/BlockTypes/ProductCategoryList.php @@ -1,6 +1,8 @@ array( - 'text' => true, - 'link' => true, - 'background' => false, - '__experimentalSkipSerialization' => true, + 'text' => true, + 'link' => true, + 'background' => false, ), 'typography' => array( @@ -48,12 +49,59 @@ protected function get_block_type_supports() { } /** - * Register script and style assets for the block type before it is registered. + * Overwrite parent method to prevent script registration. * - * This registers the scripts; it does not enqueue them. + * It is necessary to register and enqueues assets during the render + * phase because we want to load assets only if the block has the content. */ protected function register_block_type_assets() { - parent::register_block_type_assets(); - $this->register_chunk_translations( [ $this->block_name ] ); + return null; + } + + /** + * Register the context. + */ + protected function get_block_type_uses_context() { + return [ 'query', 'queryId', 'postId' ]; + } + + /** + * Include and render the block. + * + * @param array $attributes Block attributes. Default empty array. + * @param string $content Block content. Default empty string. + * @param WP_Block $block Block instance. + * @return string Rendered block type output. + */ + protected function render( $attributes, $content, $block ) { + if ( ! empty( $content ) ) { + parent::register_block_type_assets(); + $this->register_chunk_translations( [ $this->block_name ] ); + return $content; + } + + $post_id = $block->context['postId']; + $product = wc_get_product( $post_id ); + $product_categories_terms = get_the_terms( $product->get_id(), 'product_cat' ); + + $classes_and_styles = StyleAttributesUtils::get_classes_and_styles_by_attributes( $attributes ); + $classname = isset( $attributes['className'] ) ? $attributes['className'] : ''; + + $output = ''; + $output .= ' +
+ ' . __( 'Categories:', 'woo-gutenberg-products-block' ) + . '
'; + + return $output; } }