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

Add product query support for Sale badge block #7709

Merged
merged 5 commits into from
Nov 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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