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

Commit

Permalink
Add product query support for Sale badge block (#7709)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
imanish003 authored and Tarun Vijwani committed Nov 24, 2022
1 parent 74a1719 commit 9b3f5c2
Show file tree
Hide file tree
Showing 7 changed files with 4,334 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ export const blockAttributes: Record< string, Record< string, unknown > > = {
type: 'number',
default: 0,
},
isDescendentOfQueryLoop: {
type: 'boolean',
default: false,
},
};

export default blockAttributes;
27 changes: 21 additions & 6 deletions assets/js/atomic/blocks/product-elements/sale-badge/edit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
* External dependencies
*/
import { useBlockProps } from '@wordpress/block-editor';
import type { BlockEditProps } from '@wordpress/blocks';
import { ProductQueryContext as Context } from '@woocommerce/blocks/product-query/types';
import { useEffect } from 'react';

/**
* Internal dependencies
Expand All @@ -15,15 +18,27 @@ import {
} from './constants';
import type { BlockAttributes } from './types';

interface Props {
attributes: BlockAttributes;
}

const Edit = ( { attributes }: Props ): JSX.Element => {
const Edit = ( {
attributes,
setAttributes,
context,
}: BlockEditProps< BlockAttributes > & { context: Context } ): JSX.Element => {
const blockProps = useBlockProps();

const blockAttrs = {
...attributes,
...context,
};
const isDescendentOfQueryLoop = Number.isFinite( context.queryId );

useEffect(
() => setAttributes( { isDescendentOfQueryLoop } ),
[ setAttributes, isDescendentOfQueryLoop ]
);

return (
<div { ...blockProps }>
<Block { ...attributes } />
<Block { ...blockAttrs } />
</div>
);
};
Expand Down
8 changes: 6 additions & 2 deletions assets/js/atomic/blocks/product-elements/sale-badge/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import {
BLOCK_ICON as icon,
BLOCK_DESCRIPTION as description,
} from './constants';
import { Save } from './save';
import { supports } from './support';

const blockConfig: BlockConfiguration = {
Expand All @@ -27,7 +26,12 @@ const blockConfig: BlockConfiguration = {
supports,
attributes,
edit,
save: Save,
usesContext: [ 'query', 'queryId', 'postId' ],
ancestor: [
'@woocommerce/all-products',
'@woocommerce/single-product',
'core/post-template',
],
};

registerBlockType( 'woocommerce/product-sale-badge', { ...blockConfig } );
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export interface BlockAttributes {
productId: number;
align: 'left' | 'center' | 'right';
isDescendentOfQueryLoop: boolean;
}
4,215 changes: 4,215 additions & 0 deletions checkstyle.xml

Large diffs are not rendered by default.

55 changes: 51 additions & 4 deletions src/BlockTypes/ProductSaleBadge.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
<?php
namespace Automattic\WooCommerce\Blocks\BlockTypes;

use Automattic\WooCommerce\Blocks\Utils\StyleAttributesUtils;

/**
* ProductSaleBadge class.
*/
Expand Down Expand Up @@ -54,12 +56,57 @@ 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 );
$is_on_sale = $product->is_on_sale();

if ( ! $is_on_sale ) {
return null;
}

$classes_and_styles = StyleAttributesUtils::get_classes_and_styles_by_attributes( $attributes );
$classname = isset( $attributes['className'] ) ? $attributes['className'] : '';

$output = '';
$output .= '<div class="wc-block-components-product-sale-badge ' . $classes_and_styles['classes'] . ' ' . $classname . '" style="' . $classes_and_styles['styles'] . '"">';
$output .= '<span class="wc-block-components-product-sale-badge__text" aria-hidden="true">' . __( 'Sale', 'woo-gutenberg-products-block' ) . '</span>';
$output .= '<span class="screen-reader-text">' . __(
'Product on sale',
'woo-gutenberg-products-block'
) . '</span>';
$output .= '</div>';

return $output;
}
}
37 changes: 36 additions & 1 deletion src/Utils/StyleAttributesUtils.php
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,27 @@ public static function get_align_class_and_style( $attributes ) {
return null;
}


/**
* If spacing value is in preset format, convert it to a CSS var. Else return same value
* For example:
* "var:preset|spacing|50" -> "var(--wp--preset--spacing--50)"
* "50px" -> "50px"
*
* @param string $spacing_value value to be processed.
*
* @return (string)
*/
public static function get_spacing_value( $spacing_value ) {
// Used following code as reference: https://github.com/WordPress/gutenberg/blob/cff6d70d6ff5a26e212958623dc3130569f95685/lib/block-supports/layout.php/#L219-L225.
if ( is_string( $spacing_value ) && str_contains( $spacing_value, 'var:preset|spacing|' ) ) {
$spacing_value = str_replace( 'var:preset|spacing|', '', 'var:preset|spacing|50' );
return sprintf( 'var(--wp--preset--spacing--%s)', $spacing_value );
}

return $spacing_value;
}

/**
* Get class and style for padding from attributes.
*
Expand All @@ -341,9 +362,23 @@ public static function get_padding_class_and_style( $attributes ) {
return null;
}

$padding_top = $padding['top'] ? self::get_spacing_value( $padding['top'] ) : null;
$padding_right = $padding['right'] ? self::get_spacing_value( $padding['right'] ) : null;
$padding_bottom = $padding['bottom'] ? self::get_spacing_value( $padding['bottom'] ) : null;
$padding_left = $padding['left'] ? self::get_spacing_value( $padding['left'] ) : null;

return array(
'class' => null,
'style' => sprintf( 'padding: %s;', implode( ' ', $padding ) ),
'style' => sprintf(
'padding-top:%s;
padding-right:%s;
padding-bottom:%s;
padding-left:%s;',
$padding_top,
$padding_right,
$padding_bottom,
$padding_left
),
);
}

Expand Down

0 comments on commit 9b3f5c2

Please sign in to comment.