Add Product Query Support for Atomic SKU Block (https://github.com/woocommerce/woocommerce-blocks/pull/7385)

* Add attributes, settings, and editor PQ settings.

- Adds isDescendentOfQueryLoop attribute and sets up usage in editor.
- Connects Context (via useContext) in editor.
- Sets up necessary hierarchy in block index file settings.

* Update parent inner blocks config.

Reassign parent array to ancestor array which allows for blocks to be
included with more flexibility - i.e., added within groups that are
children of the ancestor block.

* Add dynamic render function for PQ support.

* Update to use correct classnames on PHP side.

SSR markup was accidentally using rating classname instead of sku so it
was not applying the proper text transform seen in the editor.

* Rename BlockAttributes type to Attributes

This keeps things consistent with the type naming on the other blocks.

* Remove redundant spread of sharedConfig object.

We don't need to spread the `sharedConfig` object into the `blockConfig`
object when defining `blockConfig` since we spread/merge these two
objects when registering the block via `registerExperimentalBlockType`.

* bot: update checkstyle.xml

* bot: update checkstyle.xml

* Empty commit to trigger checks.

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This commit is contained in:
Daniel W. Robert 2022-11-10 13:32:07 -05:00 committed by GitHub
parent 9fa34effce
commit 37a6b2ef63
7 changed files with 79 additions and 15 deletions

View File

@ -3,6 +3,10 @@ export const blockAttributes: Record< string, Record< string, unknown > > = {
type: 'number',
default: 0,
},
isDescendentOfQueryLoop: {
type: 'boolean',
default: false,
},
};
export default blockAttributes;

View File

@ -14,9 +14,9 @@ import type { HTMLAttributes } from 'react';
* Internal dependencies
*/
import './style.scss';
import type { BlockAttributes } from './types';
import type { Attributes } from './types';
type Props = BlockAttributes & HTMLAttributes< HTMLDivElement >;
type Props = Attributes & HTMLAttributes< HTMLDivElement >;
const Block = ( props: Props ): JSX.Element | null => {
const { className } = props;

View File

@ -2,7 +2,10 @@
* External dependencies
*/
import { __ } from '@wordpress/i18n';
import type { BlockEditProps } from '@wordpress/blocks';
import EditProductLink from '@woocommerce/editor-components/edit-product-link';
import { ProductQueryContext as Context } from '@woocommerce/blocks/product-query/types';
import { useEffect } from 'react';
/**
* Internal dependencies
@ -10,17 +13,28 @@ import EditProductLink from '@woocommerce/editor-components/edit-product-link';
import Block from './block';
import withProductSelector from '../shared/with-product-selector';
import { BLOCK_TITLE, BLOCK_ICON } from './constants';
import type { BlockAttributes } from './types';
import type { Attributes } from './types';
interface Props {
attributes: BlockAttributes;
}
const Edit = ( {
attributes,
setAttributes,
context,
}: BlockEditProps< Attributes > & { context: Context } ): JSX.Element => {
const blockAttrs = {
...attributes,
...context,
};
const isDescendentOfQueryLoop = Number.isFinite( context.queryId );
useEffect(
() => setAttributes( { isDescendentOfQueryLoop } ),
[ setAttributes, isDescendentOfQueryLoop ]
);
const Edit = ( { attributes }: Props ): JSX.Element => {
return (
<>
<EditProductLink />
<Block { ...attributes } />
<Block { ...blockAttrs } />
</>
);
};

View File

@ -17,11 +17,16 @@ import {
} from './constants';
const blockConfig: BlockConfiguration = {
...sharedConfig,
apiVersion: 2,
title,
description,
icon: { src: icon },
usesContext: [ 'query', 'queryId', 'postId' ],
ancestor: [
'@woocommerce/all-products',
'@woocommerce/single-product',
'core/post-template',
],
attributes,
edit,
};

View File

@ -1,3 +1,4 @@
export interface BlockAttributes {
className: string;
export interface Attributes {
productId: number;
isDescendentOfQueryLoop: boolean;
}

View File

@ -1425,6 +1425,10 @@
<file name="assets/js/editor-components/edit-product-link/index.js">
<error line="18" column="40" severity="error" message="Property &apos;productId&apos; does not exist on type &apos;Object&apos;." source="TS2339" />
</file>
<file name="assets/js/atomic/blocks/product-elements/sku/index.ts">
<error line="25" column="2" severity="error" message="Type &apos;{ apiVersion: number; title: string; description: string; icon: { src: JSX.Element; }; usesContext: string[]; ancestor: string[]; attributes: Record&lt;string, Record&lt;string, unknown&gt;&gt;; edit: (props: any) =&gt; JSX.Element; }&apos; is not assignable to type &apos;BlockConfiguration&lt;{}&gt;&apos;.
Object literal may only specify known properties, and &apos;ancestor&apos; does not exist in type &apos;BlockConfiguration&lt;{}&gt;&apos;." source="TS2322" />
</file>
<file name="assets/js/atomic/blocks/product-elements/category-list/index.ts">
<error line="36" column="5" severity="error" message="Type &apos;{ color?: { text: true; link: true; background: false; __experimentalSkipSerialization: true; }; typography?: { fontSize: true; lineHeight: true; __experimentalFontStyle: true; __experimentalFontWeight: true; __experimentalSkipSerialization: true; }; __experimentalSelector?: string; }&apos; is not assignable to type &apos;BlockSupports&apos;.
Types of property &apos;color&apos; are incompatible.

View File

@ -21,12 +21,48 @@ class ProductSKU extends AbstractBlock {
protected $api_version = '2';
/**
* 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 );
if ( $product ) {
return sprintf(
'<div class="wc-block-components-product-sku wc-block-grid__product-sku">
SKU:
<strong>%s</strong>
</div>',
$product->get_sku()
);
}
}
}