Skip to content
This repository was archived by the owner on Feb 23, 2024. It is now read-only.

Commit ca4bad3

Browse files
authored
Add product query support for Sale badge block (#7709)
* Add product query support for Sale badge block On the client side, when the Sale badge block is used within the product query block, the markup will be rendered on the server side - No javascript related to Sale badge block will be rendered. * Add support for additional CSS class(es) ADDITIONAL CSS CLASS(ES)(available in advanced toggle in sidebar) should be added to the container div * Convert preset to css variable for padding We are getting padding value in preset format like this: "var:preset|spacing|50" Therefore I added a function to convert it to CSS variable like this: "var(--wp--preset--spacing--50)" i.e. "var:preset|spacing|50" -> "var(--wp--preset--spacing--50)" * Add reference for preset to css variable conversion logic
1 parent 410bf87 commit ca4bad3

File tree

7 files changed

+4334
-13
lines changed

7 files changed

+4334
-13
lines changed

assets/js/atomic/blocks/product-elements/sale-badge/attributes.ts

+4
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ export const blockAttributes: Record< string, Record< string, unknown > > = {
33
type: 'number',
44
default: 0,
55
},
6+
isDescendentOfQueryLoop: {
7+
type: 'boolean',
8+
default: false,
9+
},
610
};
711

812
export default blockAttributes;

assets/js/atomic/blocks/product-elements/sale-badge/edit.tsx

+21-6
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
* External dependencies
33
*/
44
import { useBlockProps } from '@wordpress/block-editor';
5+
import type { BlockEditProps } from '@wordpress/blocks';
6+
import { ProductQueryContext as Context } from '@woocommerce/blocks/product-query/types';
7+
import { useEffect } from 'react';
58

69
/**
710
* Internal dependencies
@@ -15,15 +18,27 @@ import {
1518
} from './constants';
1619
import type { BlockAttributes } from './types';
1720

18-
interface Props {
19-
attributes: BlockAttributes;
20-
}
21-
22-
const Edit = ( { attributes }: Props ): JSX.Element => {
21+
const Edit = ( {
22+
attributes,
23+
setAttributes,
24+
context,
25+
}: BlockEditProps< BlockAttributes > & { context: Context } ): JSX.Element => {
2326
const blockProps = useBlockProps();
27+
28+
const blockAttrs = {
29+
...attributes,
30+
...context,
31+
};
32+
const isDescendentOfQueryLoop = Number.isFinite( context.queryId );
33+
34+
useEffect(
35+
() => setAttributes( { isDescendentOfQueryLoop } ),
36+
[ setAttributes, isDescendentOfQueryLoop ]
37+
);
38+
2439
return (
2540
<div { ...blockProps }>
26-
<Block { ...attributes } />
41+
<Block { ...blockAttrs } />
2742
</div>
2843
);
2944
};

assets/js/atomic/blocks/product-elements/sale-badge/index.ts

+6-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import {
1515
BLOCK_ICON as icon,
1616
BLOCK_DESCRIPTION as description,
1717
} from './constants';
18-
import { Save } from './save';
1918
import { supports } from './support';
2019

2120
const blockConfig: BlockConfiguration = {
@@ -27,7 +26,12 @@ const blockConfig: BlockConfiguration = {
2726
supports,
2827
attributes,
2928
edit,
30-
save: Save,
29+
usesContext: [ 'query', 'queryId', 'postId' ],
30+
ancestor: [
31+
'@woocommerce/all-products',
32+
'@woocommerce/single-product',
33+
'core/post-template',
34+
],
3135
};
3236

3337
registerBlockType( 'woocommerce/product-sale-badge', { ...blockConfig } );
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export interface BlockAttributes {
22
productId: number;
33
align: 'left' | 'center' | 'right';
4+
isDescendentOfQueryLoop: boolean;
45
}

checkstyle.xml

+4,215
Large diffs are not rendered by default.

src/BlockTypes/ProductSaleBadge.php

+51-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
<?php
22
namespace Automattic\WooCommerce\Blocks\BlockTypes;
33

4+
use Automattic\WooCommerce\Blocks\Utils\StyleAttributesUtils;
5+
46
/**
57
* ProductSaleBadge class.
68
*/
@@ -54,12 +56,57 @@ protected function get_block_type_supports() {
5456
}
5557

5658
/**
57-
* Register script and style assets for the block type before it is registered.
59+
* Overwrite parent method to prevent script registration.
5860
*
59-
* This registers the scripts; it does not enqueue them.
61+
* It is necessary to register and enqueues assets during the render
62+
* phase because we want to load assets only if the block has the content.
6063
*/
6164
protected function register_block_type_assets() {
62-
parent::register_block_type_assets();
63-
$this->register_chunk_translations( [ $this->block_name ] );
65+
return null;
66+
}
67+
68+
/**
69+
* Register the context.
70+
*/
71+
protected function get_block_type_uses_context() {
72+
return [ 'query', 'queryId', 'postId' ];
73+
}
74+
75+
/**
76+
* Include and render the block.
77+
*
78+
* @param array $attributes Block attributes. Default empty array.
79+
* @param string $content Block content. Default empty string.
80+
* @param WP_Block $block Block instance.
81+
* @return string Rendered block type output.
82+
*/
83+
protected function render( $attributes, $content, $block ) {
84+
if ( ! empty( $content ) ) {
85+
parent::register_block_type_assets();
86+
$this->register_chunk_translations( [ $this->block_name ] );
87+
return $content;
88+
}
89+
90+
$post_id = $block->context['postId'];
91+
$product = wc_get_product( $post_id );
92+
$is_on_sale = $product->is_on_sale();
93+
94+
if ( ! $is_on_sale ) {
95+
return null;
96+
}
97+
98+
$classes_and_styles = StyleAttributesUtils::get_classes_and_styles_by_attributes( $attributes );
99+
$classname = isset( $attributes['className'] ) ? $attributes['className'] : '';
100+
101+
$output = '';
102+
$output .= '<div class="wc-block-components-product-sale-badge ' . $classes_and_styles['classes'] . ' ' . $classname . '" style="' . $classes_and_styles['styles'] . '"">';
103+
$output .= '<span class="wc-block-components-product-sale-badge__text" aria-hidden="true">' . __( 'Sale', 'woo-gutenberg-products-block' ) . '</span>';
104+
$output .= '<span class="screen-reader-text">' . __(
105+
'Product on sale',
106+
'woo-gutenberg-products-block'
107+
) . '</span>';
108+
$output .= '</div>';
109+
110+
return $output;
64111
}
65112
}

src/Utils/StyleAttributesUtils.php

+36-1
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,27 @@ public static function get_align_class_and_style( $attributes ) {
327327
return null;
328328
}
329329

330+
331+
/**
332+
* If spacing value is in preset format, convert it to a CSS var. Else return same value
333+
* For example:
334+
* "var:preset|spacing|50" -> "var(--wp--preset--spacing--50)"
335+
* "50px" -> "50px"
336+
*
337+
* @param string $spacing_value value to be processed.
338+
*
339+
* @return (string)
340+
*/
341+
public static function get_spacing_value( $spacing_value ) {
342+
// Used following code as reference: https://github.com/WordPress/gutenberg/blob/cff6d70d6ff5a26e212958623dc3130569f95685/lib/block-supports/layout.php/#L219-L225.
343+
if ( is_string( $spacing_value ) && str_contains( $spacing_value, 'var:preset|spacing|' ) ) {
344+
$spacing_value = str_replace( 'var:preset|spacing|', '', 'var:preset|spacing|50' );
345+
return sprintf( 'var(--wp--preset--spacing--%s)', $spacing_value );
346+
}
347+
348+
return $spacing_value;
349+
}
350+
330351
/**
331352
* Get class and style for padding from attributes.
332353
*
@@ -341,9 +362,23 @@ public static function get_padding_class_and_style( $attributes ) {
341362
return null;
342363
}
343364

365+
$padding_top = $padding['top'] ? self::get_spacing_value( $padding['top'] ) : null;
366+
$padding_right = $padding['right'] ? self::get_spacing_value( $padding['right'] ) : null;
367+
$padding_bottom = $padding['bottom'] ? self::get_spacing_value( $padding['bottom'] ) : null;
368+
$padding_left = $padding['left'] ? self::get_spacing_value( $padding['left'] ) : null;
369+
344370
return array(
345371
'class' => null,
346-
'style' => sprintf( 'padding: %s;', implode( ' ', $padding ) ),
372+
'style' => sprintf(
373+
'padding-top:%s;
374+
padding-right:%s;
375+
padding-bottom:%s;
376+
padding-left:%s;',
377+
$padding_top,
378+
$padding_right,
379+
$padding_bottom,
380+
$padding_left
381+
),
347382
);
348383
}
349384

0 commit comments

Comments
 (0)