Create the `Products by Attribute` template (https://github.com/woocommerce/woocommerce-blocks/pull/7660)
* Create the `Products by Attribute` template * bot: update checkstyle.xml * Fix typo * Rename template to `taxonomy-product_attribute` * Rename test template file * bot: update checkstyle.xml * Fix test enabling archives for shade attribute Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This commit is contained in:
parent
ddd0cc2300
commit
87510929b5
|
@ -18,7 +18,7 @@ This block does not have any customizable options available, so any style or cus
|
|||
### Props
|
||||
|
||||
- `attributes`
|
||||
- `template`: `single-product` | `archive-product` | `taxonomy-product_cat` | `taxonomy-product_tag`
|
||||
- `template`: `single-product` | `archive-product` | `taxonomy-product_cat` | `taxonomy-product_tag` | `taxonomy-product_attribute`
|
||||
- `align`: `wide` | `full`
|
||||
|
||||
```html
|
||||
|
|
|
@ -38,6 +38,13 @@ export const TEMPLATES: TemplateDetails = {
|
|||
),
|
||||
placeholder: 'archive-product',
|
||||
},
|
||||
'taxonomy-product_attribute': {
|
||||
title: __(
|
||||
'WooCommerce Product Attribute Block',
|
||||
'woo-gutenberg-products-block'
|
||||
),
|
||||
placeholder: 'archive-product',
|
||||
},
|
||||
'product-search-results': {
|
||||
title: __(
|
||||
'WooCommerce Product Search Results Block',
|
||||
|
|
|
@ -20,6 +20,10 @@ const TEMPLATES = {
|
|||
title: 'Product Taxonomy Title',
|
||||
placeholder: 'Product Taxonomy Placeholder',
|
||||
},
|
||||
'taxonomy-product_attribute': {
|
||||
title: 'Product Attribute Title',
|
||||
placeholder: 'Product Attribute Placeholder',
|
||||
},
|
||||
};
|
||||
|
||||
describe( 'getTemplateDetailsBySlug', function () {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
namespace Automattic\WooCommerce\Blocks;
|
||||
|
||||
use Automattic\WooCommerce\Blocks\Domain\Package;
|
||||
use Automattic\WooCommerce\Blocks\Templates\ProductAttributeTemplate;
|
||||
use Automattic\WooCommerce\Blocks\Utils\BlockTemplateUtils;
|
||||
|
||||
/**
|
||||
|
@ -110,7 +111,7 @@ class BlockTemplatesController {
|
|||
|
||||
list( $template_id, $template_slug ) = $template_name_parts;
|
||||
|
||||
// If the theme has an archive-product.html template, but not a taxonomy-product_cat/tag.html template let's use the themes archive-product.html template.
|
||||
// If the theme has an archive-product.html template, but not a taxonomy-product_cat/tag/attribute.html template let's use the themes archive-product.html template.
|
||||
if ( BlockTemplateUtils::template_is_eligible_for_product_archive_fallback( $template_slug ) ) {
|
||||
$template_path = BlockTemplateUtils::get_theme_template_path( 'archive-product' );
|
||||
$template_object = BlockTemplateUtils::create_new_block_template_object( $template_path, $template_type, $template_slug, true );
|
||||
|
@ -330,7 +331,7 @@ class BlockTemplatesController {
|
|||
continue;
|
||||
}
|
||||
|
||||
// If the theme has an archive-product.html template, but not a taxonomy-product_cat.html template let's use the themes archive-product.html template.
|
||||
// If the theme has an archive-product.html template, but not a taxonomy-product_cat/tag/attribute.html template let's use the themes archive-product.html template.
|
||||
if ( BlockTemplateUtils::template_is_eligible_for_product_archive_fallback( $template_slug ) ) {
|
||||
$template_file = BlockTemplateUtils::get_theme_template_path( 'archive-product' );
|
||||
$templates[] = BlockTemplateUtils::create_new_block_template_object( $template_file, $template_type, $template_slug, true );
|
||||
|
@ -439,8 +440,8 @@ class BlockTemplatesController {
|
|||
}
|
||||
|
||||
if ( isset( $queried_object->taxonomy ) && taxonomy_is_product_attribute( $queried_object->taxonomy ) &&
|
||||
! BlockTemplateUtils::theme_has_template( 'archive-product' ) &&
|
||||
$this->block_template_is_available( 'archive-product' )
|
||||
! BlockTemplateUtils::theme_has_template( ProductAttributeTemplate::SLUG ) &&
|
||||
$this->block_template_is_available( ProductAttributeTemplate::SLUG )
|
||||
) {
|
||||
add_filter( 'woocommerce_has_block_template', '__return_true', 10, 0 );
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<?php
|
||||
namespace Automattic\WooCommerce\Blocks\BlockTypes;
|
||||
|
||||
use Automattic\WooCommerce\Blocks\Templates\ProductAttributeTemplate;
|
||||
use Automattic\WooCommerce\Blocks\Templates\ProductSearchResultsTemplate;
|
||||
use Automattic\WooCommerce\Blocks\Utils\StyleAttributesUtils;
|
||||
use WC_Query;
|
||||
|
@ -61,7 +62,7 @@ class ClassicTemplate extends AbstractDynamicBlock {
|
|||
$frontend_scripts::load_scripts();
|
||||
}
|
||||
|
||||
$archive_templates = array( 'archive-product', 'taxonomy-product_cat', 'taxonomy-product_tag', ProductSearchResultsTemplate::SLUG );
|
||||
$archive_templates = array( 'archive-product', 'taxonomy-product_cat', 'taxonomy-product_tag', ProductAttributeTemplate::SLUG, ProductSearchResultsTemplate::SLUG );
|
||||
|
||||
if ( 'single-product' === $attributes['template'] ) {
|
||||
return $this->render_single_product();
|
||||
|
|
|
@ -8,7 +8,7 @@ namespace Automattic\WooCommerce\Blocks\Templates;
|
|||
* @internal
|
||||
*/
|
||||
class ProductAttributeTemplate {
|
||||
const SLUG = 'archive-product';
|
||||
const SLUG = 'taxonomy-product_attribute';
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
|
@ -25,14 +25,14 @@ class ProductAttributeTemplate {
|
|||
}
|
||||
|
||||
/**
|
||||
* Render the Archive Product Template for product attributes.
|
||||
* Renders the Product by Attribute template for product attributes taxonomy pages.
|
||||
*
|
||||
* @param array $templates Templates that match the product attributes taxonomy.
|
||||
*/
|
||||
public function update_taxonomy_template_hierarchy( $templates ) {
|
||||
$queried_object = get_queried_object();
|
||||
if ( taxonomy_is_product_attribute( $queried_object->taxonomy ) && wc_current_theme_is_fse_theme() ) {
|
||||
array_unshift( $templates, self::SLUG );
|
||||
array_splice( $templates, count( $templates ) - 1, 0, self::SLUG );
|
||||
}
|
||||
|
||||
return $templates;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<?php
|
||||
namespace Automattic\WooCommerce\Blocks\Utils;
|
||||
|
||||
use Automattic\WooCommerce\Blocks\Templates\ProductAttributeTemplate;
|
||||
use Automattic\WooCommerce\Blocks\Templates\ProductSearchResultsTemplate;
|
||||
use Automattic\WooCommerce\Blocks\Domain\Services\FeatureGating;
|
||||
use Automattic\WooCommerce\Blocks\Options;
|
||||
|
@ -312,6 +313,10 @@ class BlockTemplateUtils {
|
|||
'title' => _x( 'Products by Tag', 'Template name', 'woo-gutenberg-products-block' ),
|
||||
'description' => __( 'Displays products filtered by a tag.', 'woo-gutenberg-products-block' ),
|
||||
),
|
||||
ProductAttributeTemplate::SLUG => array(
|
||||
'title' => _x( 'Products by Attribute', 'Template name', 'woo-gutenberg-products-block' ),
|
||||
'description' => __( 'Displays products filtered by an attribute.', 'woo-gutenberg-products-block' ),
|
||||
),
|
||||
ProductSearchResultsTemplate::SLUG => array(
|
||||
'title' => _x( 'Product Search Results', 'Template name', 'woo-gutenberg-products-block' ),
|
||||
'description' => __( 'Displays search results for your store.', 'woo-gutenberg-products-block' ),
|
||||
|
@ -449,14 +454,14 @@ class BlockTemplateUtils {
|
|||
/**
|
||||
* Checks if we can fallback to the `archive-product` template for a given slug
|
||||
*
|
||||
* `taxonomy-product_cat` and `taxonomy-product_tag` templates can generally use the
|
||||
* `archive-product` as a fallback if there are no specific overrides.
|
||||
* `taxonomy-product_cat`, `taxonomy-product_tag`, `taxonomy-attribute` templates can
|
||||
* generally use the `archive-product` as a fallback if there are no specific overrides.
|
||||
*
|
||||
* @param string $template_slug Slug to check for fallbacks.
|
||||
* @return boolean
|
||||
*/
|
||||
public static function template_is_eligible_for_product_archive_fallback( $template_slug ) {
|
||||
$eligible_for_fallbacks = array( 'taxonomy-product_cat', 'taxonomy-product_tag' );
|
||||
$eligible_for_fallbacks = array( 'taxonomy-product_cat', 'taxonomy-product_tag', ProductAttributeTemplate::SLUG );
|
||||
|
||||
return in_array( $template_slug, $eligible_for_fallbacks, true )
|
||||
&& ! self::theme_has_template( $template_slug )
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
<!-- wp:template-part {"slug":"header","tagName":"header"} /-->
|
||||
<!-- wp:group {"layout":{"inherit":true}} -->
|
||||
<div class="wp-block-group"><!-- wp:woocommerce/legacy-template {"template":"taxonomy-product_attribute"} /--></div>
|
||||
<!-- /wp:group -->
|
||||
<!-- wp:template-part {"slug":"footer","tagName":"footer"} /-->
|
|
@ -26,7 +26,10 @@ const Attributes = () => [
|
|||
],
|
||||
},
|
||||
{
|
||||
attribute: { name: 'Shade' },
|
||||
attribute: {
|
||||
name: 'Shade',
|
||||
has_archives: true,
|
||||
},
|
||||
terms: [
|
||||
{
|
||||
name: 'Red',
|
||||
|
|
|
@ -93,6 +93,14 @@ const BLOCK_DATA = {
|
|||
},
|
||||
name: 'woocommerce/legacy-template',
|
||||
},
|
||||
'taxonomy-product_attribute': {
|
||||
attributes: {
|
||||
placeholder: 'archive-product',
|
||||
template: 'taxonomy-product_attribute',
|
||||
title: 'WooCommerce Product Attribute Block',
|
||||
},
|
||||
name: 'woocommerce/legacy-template',
|
||||
},
|
||||
'product-search-results': {
|
||||
attributes: {
|
||||
title: 'WooCommerce Product Search Results Block',
|
||||
|
@ -516,6 +524,100 @@ describe( 'Store Editing Templates', () => {
|
|||
} );
|
||||
} );
|
||||
|
||||
describe( 'Products by Attribute template', () => {
|
||||
it( 'default template from WooCommerce Blocks is available on an FSE theme', async () => {
|
||||
const EXPECTED_TEMPLATE = defaultTemplateProps(
|
||||
'Products by Attribute'
|
||||
);
|
||||
|
||||
await goToTemplatesList();
|
||||
|
||||
const templates = await getAllTemplates();
|
||||
|
||||
try {
|
||||
expect( templates ).toContainEqual( EXPECTED_TEMPLATE );
|
||||
} catch ( ok ) {
|
||||
// Depending on the speed of the execution and whether Chrome is headless or not
|
||||
// the id might be parsed or not
|
||||
|
||||
expect( templates ).toContainEqual( {
|
||||
...EXPECTED_TEMPLATE,
|
||||
addedBy: WOOCOMMERCE_PARSED_ID,
|
||||
} );
|
||||
}
|
||||
} );
|
||||
|
||||
runOnlyWhenGutenbergIsDisabled( () =>
|
||||
it( 'should contain the "WooCommerce Product Taxonomy Block" classic template', async () => {
|
||||
await goToTemplateEditor( {
|
||||
postId: 'woocommerce/woocommerce//taxonomy-product_attribute',
|
||||
} );
|
||||
|
||||
const [ classicBlock ] = await filterCurrentBlocks(
|
||||
( block ) =>
|
||||
block.name ===
|
||||
BLOCK_DATA[ 'taxonomy-product_attribute' ].name
|
||||
);
|
||||
|
||||
expect( classicBlock.attributes.template ).toBe(
|
||||
BLOCK_DATA[ 'taxonomy-product_attribute' ].attributes
|
||||
.template
|
||||
);
|
||||
expect( await getCurrentSiteEditorContent() ).toMatchSnapshot();
|
||||
} )
|
||||
);
|
||||
|
||||
it( 'should show the action menu if the template has been customized by the user', async () => {
|
||||
const EXPECTED_TEMPLATE = {
|
||||
...defaultTemplateProps( 'Products by Attribute' ),
|
||||
hasActions: true,
|
||||
};
|
||||
|
||||
await visitTemplateAndAddCustomParagraph(
|
||||
'taxonomy-product_attribute'
|
||||
);
|
||||
|
||||
await goToTemplatesList( { waitFor: 'actions' } );
|
||||
|
||||
const templates = await getAllTemplates();
|
||||
|
||||
try {
|
||||
expect( templates ).toContainEqual( EXPECTED_TEMPLATE );
|
||||
} catch ( ok ) {
|
||||
// Depending on the speed of the execution and whether Chrome is headless or not
|
||||
// the id might be parsed or not
|
||||
|
||||
expect( templates ).toContainEqual( {
|
||||
...EXPECTED_TEMPLATE,
|
||||
addedBy: WOOCOMMERCE_PARSED_ID,
|
||||
} );
|
||||
}
|
||||
} );
|
||||
|
||||
it( 'should preserve and correctly show the user customization on the back-end', async () => {
|
||||
await goToTemplateEditor( {
|
||||
postId: 'woocommerce/woocommerce//taxonomy-product_attribute',
|
||||
} );
|
||||
|
||||
await expect( canvas() ).toMatchElement(
|
||||
SELECTORS.blocks.paragraph,
|
||||
{
|
||||
text: CUSTOMIZED_STRING,
|
||||
timeout: DEFAULT_TIMEOUT,
|
||||
}
|
||||
);
|
||||
} );
|
||||
|
||||
it( 'should show the user customization on the front-end', async () => {
|
||||
await page.goto( new URL( '/shade/red', BASE_URL ) );
|
||||
|
||||
await expect( page ).toMatchElement( 'p', {
|
||||
text: CUSTOMIZED_STRING,
|
||||
timeout: DEFAULT_TIMEOUT,
|
||||
} );
|
||||
} );
|
||||
} );
|
||||
|
||||
describe( 'Product Search Results block template', () => {
|
||||
it( 'default template from WooCommerce Blocks is available on an FSE theme', async () => {
|
||||
const EXPECTED_TEMPLATE = defaultTemplateProps(
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
<!-- wp:template-part {"slug":"header"} /-->
|
||||
<!-- wp:group {"layout":{"inherit":true}} -->
|
||||
<h2 class="theme-template-title">Template loaded from theme</h2>
|
||||
<div class="wp-block-group">
|
||||
<!-- wp:woocommerce/legacy-template {"template":"taxonomy-product_attribute"} /-->
|
||||
</div>
|
||||
<!-- /wp:group -->
|
||||
<!-- wp:template-part {"slug":"footer"} /-->
|
Loading…
Reference in New Issue