* Block scaffolding

* Rename to store notices

* Register only in the site editor

* Update description

* Add woocommerce class

* Add tests

* Delete old test file

* Update notices message in the editor

* Remove customization

* Disable the block server side

* Fix TS error

* Add custom classes

* Reprashed test description

* Escape notices

* Remove unnecessary disabled component

* Only allow to insert the block once

* Improve class name

* Merge edit and block files

* Fix copy

* Simplify test case

* Remove align support

* Remove attributes

* Change editor markup

* Use the Notice component to display the notice placeholder on the editor

* Use sprintf to improve readability

* Inline component

* Remove styles and unregister scripts

* Use ordered placeholders

Co-authored-by: Tung Du <dinhtungdu@gmail.com>

* Use info as the notices status

Co-authored-by: Tung Du <dinhtungdu@gmail.com>

* Fix php lint error

Co-authored-by: Tung Du <dinhtungdu@gmail.com>
This commit is contained in:
Alba Rincón 2023-01-18 13:40:30 +01:00 committed by GitHub
parent 34c7fa95e1
commit fbd86f8762
7 changed files with 188 additions and 0 deletions

View File

@ -0,0 +1,14 @@
{
"name": "woocommerce/store-notices",
"version": "1.0.0",
"title": "Store Notices",
"description": "Display shopper-facing notifications generated by WooCommerce or extensions.",
"category": "woocommerce",
"keywords": [ "WooCommerce" ],
"supports": {
"multiple": false
},
"textdomain": "woo-gutenberg-products-block",
"apiVersion": 2,
"$schema": "https://schemas.wp.org/trunk/block.json"
}

View File

@ -0,0 +1,25 @@
/**
* External dependencies
*/
import { useBlockProps } from '@wordpress/block-editor';
import { __ } from '@wordpress/i18n';
import { Notice } from '@wordpress/components';
const Edit = (): JSX.Element => {
const blockProps = useBlockProps( {
className: 'wc-block-store-notices',
} );
return (
<div { ...blockProps }>
<Notice status="info" isDismissible={ false }>
{ __(
'Notices added by WooCommerce or extensions will show up here.',
'woo-gutenberg-products-block'
) }
</Notice>
</div>
);
};
export default Edit;

View File

@ -0,0 +1,30 @@
/**
* External dependencies
*/
import { registerBlockType } from '@wordpress/blocks';
import { Icon } from '@wordpress/icons';
import { totals } from '@woocommerce/icons';
/**
* Internal dependencies
*/
import metadata from './block.json';
import edit from './edit';
registerBlockType( metadata, {
icon: {
src: (
<Icon
icon={ totals }
className="wc-block-editor-components-block-icon"
/>
),
},
attributes: {
...metadata.attributes,
},
edit,
save() {
return null;
},
} );

View File

@ -40,6 +40,7 @@ const blocks = {
'mini-cart-contents': {
customDir: 'mini-cart/mini-cart-contents',
},
'store-notices': {},
'price-filter': {},
'product-best-sellers': {},
'product-category': {},

View File

@ -0,0 +1,54 @@
<?php
namespace Automattic\WooCommerce\Blocks\BlockTypes;
use Automattic\WooCommerce\Blocks\Utils\StyleAttributesUtils;
/**
* StoreNotices class.
*/
class StoreNotices extends AbstractBlock {
/**
* Block name.
*
* @var string
*/
protected $block_name = 'store-notices';
/**
* Render the block.
*
* @param array $attributes Block attributes.
* @param string $content Block content.
* @param WP_Block $block Block instance.
*
* @return string | void Rendered block output.
*/
protected function render( $attributes, $content, $block ) {
ob_start();
woocommerce_output_all_notices();
$notices = ob_get_clean();
if ( ! $notices ) {
return;
}
$classname = isset( $attributes['className'] ) ? $attributes['className'] : '';
return sprintf(
'<div class="woocommerce wc-block-store-notices %1$s">%2$s</div>',
esc_attr( $classname ),
wc_kses_notice( $notices )
);
}
/**
* Get the frontend script handle for this block type.
*
* @param string $key Data to get, or default to everything.
*/
protected function get_block_type_script( $key = null ) {
return null;
}
}

View File

@ -177,6 +177,7 @@ final class BlockTypesController {
'HandpickedProducts',
'MiniCart',
'MiniCartContents',
'StoreNotices',
'PriceFilter',
'ProductAddToCart',
'ProductBestSellers',
@ -251,6 +252,7 @@ final class BlockTypesController {
'CatalogSorting',
'ClassicTemplate',
'ProductResultsCount',
'StoreNotices',
]
);
}

View File

@ -0,0 +1,62 @@
/**
* External dependencies
*/
import {
canvas,
createNewPost,
insertBlock,
switchUserToAdmin,
} from '@wordpress/e2e-test-utils';
import { searchForBlock } from '@wordpress/e2e-test-utils/build/inserter';
/**
* Internal dependencies
*/
import { goToSiteEditor, useTheme, waitForCanvas } from '../../utils.js';
const block = {
name: 'Store Notices',
slug: 'woocommerce/store-notices',
class: '.wc-block-store-notices',
selectors: {
insertButton: "//button//span[text()='Store Notices']",
insertButtonDisabled:
"//button[@aria-disabled]//span[text()='Store Notices']",
},
};
describe( `${ block.name } Block`, () => {
it( 'can not be inserted in the Post Editor', async () => {
await switchUserToAdmin();
await createNewPost( {
postType: 'post',
title: block.name,
} );
await searchForBlock( block.name );
expect( page ).toMatch( 'No results found.' );
} );
describe( 'in FSE editor', () => {
useTheme( 'emptytheme' );
beforeEach( async () => {
await goToSiteEditor();
await waitForCanvas();
} );
it( 'can be inserted in FSE area', async () => {
await insertBlock( block.name );
await expect( canvas() ).toMatchElement( block.class );
} );
it( 'can only be inserted once', async () => {
await insertBlock( block.name );
await searchForBlock( block.name );
const storeNoticesButton = await page.$x(
block.selectors.insertButtonDisabled
);
expect( storeNoticesButton ).toHaveLength( 1 );
} );
} );
} );