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

Add Single Product Details block #8225

Merged
merged 25 commits into from
Feb 16, 2023
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
d46e480
Add minimum structure for Single Product Details block
thealexandrelara Jan 17, 2023
e743ebe
Add tests for Single Product Details block
thealexandrelara Jan 20, 2023
f87de21
wip: create block structure and add initial styles
thealexandrelara Jan 25, 2023
561f6f8
Add block details to the SingleProductDetails.php file
thealexandrelara Jan 26, 2023
d07b9b5
Render tabs title with empty content
thealexandrelara Jan 27, 2023
9c90f71
Use woocommerce_output_product_data_tabs function to retrieve tabs data
thealexandrelara Jan 27, 2023
eb0ce4a
Remove customizations for the Single Product Details block
thealexandrelara Jan 30, 2023
22be4e9
Merge branch 'trunk' into feat/add-single-product-details-block
thealexandrelara Jan 30, 2023
2a4baad
Remove unnecessary console.log from the Edit.tsx file
thealexandrelara Jan 31, 2023
8e05b71
Remove block classname from block wrapper
thealexandrelara Jan 31, 2023
f70ab0c
Remove unnecessary WooCommerce tabs filter from the BlockTemplatesCon…
thealexandrelara Jan 31, 2023
4ea37cb
Merge branch 'trunk' into feat/add-single-product-details-block
thealexandrelara Jan 31, 2023
ad70695
Remove attributes property from the block registration
thealexandrelara Jan 31, 2023
fd83c09
Remove isExperimental flag for the Single Product Details block
thealexandrelara Jan 31, 2023
3661133
Remove get_classes_and_styles_by_attributes method from SingleProduct…
thealexandrelara Jan 31, 2023
8a9196e
Prevent Single Product Details block from apppearing in Pages or Posts
thealexandrelara Jan 31, 2023
edcac21
Fix PHP Coding Standards warnings
thealexandrelara Feb 1, 2023
528b9ce
Merge branch 'trunk' into feat/add-single-product-details-block
gigitux Feb 13, 2023
0ba35e1
update block name
gigitux Feb 13, 2023
af09b77
Merge branch 'feat/add-single-product-details-block' of https://githu…
gigitux Feb 13, 2023
93bcb28
fix SCSS linter error
gigitux Feb 13, 2023
7742ffe
Merge branch 'trunk' of https://github.com/woocommerce/woocommerce-bl…
gigitux Feb 14, 2023
96fab80
move blocks into product-elements folder and rename to product-details
gigitux Feb 14, 2023
43dd558
avoid 404 error
gigitux Feb 15, 2023
85e6247
disable js asset enqueue
gigitux Feb 15, 2023
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
1 change: 1 addition & 0 deletions assets/js/atomic/blocks/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ import './product-elements/tag-list';
import './product-elements/stock-indicator';
import './product-elements/add-to-cart';
import './product-elements/product-image-gallery';
import './product-elements/product-details';
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "woocommerce/product-details",
"version": "1.0.0",
"icon": "info",
"title": "Product Details",
"description": "A block that allows your customers to see details and reviews about the product.",
"category": "woocommerce",
"keywords": [ "WooCommerce" ],
"supports": {},
"attributes": {},
"textdomain": "woo-gutenberg-products-block",
"apiVersion": 2,
"$schema": "https://schemas.wp.org/trunk/block.json"
}
95 changes: 95 additions & 0 deletions assets/js/atomic/blocks/product-elements/product-details/block.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/**
* External dependencies
*/
import classnames from 'classnames';
import { __ } from '@wordpress/i18n';
import { useBlockProps } from '@wordpress/block-editor';

/**
* Internal dependencies
*/

interface SingleProductTab {
id: string;
title: string;
active: boolean;
content: string | undefined;
}

const ProductTabTitle = ( {
id,
title,
active,
}: Pick< SingleProductTab, 'id' | 'title' | 'active' > ) => {
return (
<li
className={ classnames( `${ id }_tab`, {
active,
} ) }
id={ `tab-title-${ id }` }
role="tab"
aria-controls={ `tab-${ id }` }
>
<a href={ `#tab-${ id }` }>{ title }</a>
</li>
);
};

const ProductTabContent = ( {
id,
content,
}: Pick< SingleProductTab, 'id' | 'content' > ) => {
return (
<div
className={ `${ id }_tab` }
id={ `tab-title-${ id }` }
role="tab"
aria-controls={ `tab-${ id }` }
>
{ content }
</div>
);
};

export const SingleProductDetails = () => {
const blockProps = useBlockProps();
const productTabs = [
{
id: 'description',
title: 'Description',
active: true,
content: __(
'This block lists description, attributes and reviews for a single product.',
'woo-gutenberg-products-block'
),
},
{
id: 'additional_information',
title: 'Additional Information',
active: false,
},
{ id: 'reviews', title: 'Reviews', active: false },
];
const tabsTitle = productTabs.map( ( { id, title, active } ) => (
<ProductTabTitle
key={ id }
id={ id }
title={ title }
active={ active }
/>
) );
const tabsContent = productTabs.map( ( { id, content } ) => (
<ProductTabContent key={ id } id={ id } content={ content } />
) );

return (
<div { ...blockProps }>
<ul className="tabs" role="tablist">
{ tabsTitle }
</ul>
{ tabsContent }
</div>
);
};

export default SingleProductDetails;
31 changes: 31 additions & 0 deletions assets/js/atomic/blocks/product-elements/product-details/edit.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* External dependencies
*/
import { useBlockProps } from '@wordpress/block-editor';
import { Disabled } from '@wordpress/components';
import type { BlockEditProps } from '@wordpress/blocks';

/**
* Internal dependencies
*/
import Block from './block';
import { Attributes } from './types';

const Edit = ( { attributes }: BlockEditProps< Attributes > ) => {
const { className } = attributes;
const blockProps = useBlockProps( {
className,
} );

return (
<>
<div { ...blockProps }>
<Disabled>
<Block />
</Disabled>
</div>
</>
);
};

export default Edit;
24 changes: 24 additions & 0 deletions assets/js/atomic/blocks/product-elements/product-details/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* External dependencies
*/
import { registerBlockSingleProductTemplate } from '@woocommerce/atomic-utils';
import { registerBlockType, unregisterBlockType } from '@wordpress/blocks';

/**
* Internal dependencies
*/
import metadata from './block.json';
import edit from './edit';

registerBlockSingleProductTemplate( {
registerBlockFn: () => {
// @ts-expect-error: `registerBlockType` is a function that is typed in WordPress core.
registerBlockType( metadata, {
edit,
} );
},
unregisterBlockFn: () => {
unregisterBlockType( metadata.name );
},
blockName: metadata.name,
} );
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
.wp-block-woocommerce-product-details {
nefeline marked this conversation as resolved.
Show resolved Hide resolved
ul.tabs {
list-style: none;
padding: 0 0 0 1em;
margin: 0 0 1.618em;
overflow: hidden;
position: relative;
border-bottom: 1px solid $gray-200;

li {
border: 1px solid $gray-200;
background-color: $white;
display: inline-block;
position: relative;
z-index: 0;
border-radius: 4px 4px 0 0;
margin: 0;
padding: 0.5em 1em;
opacity: 0.5;

a {
display: inline-block;
font-weight: 700;
color: $black;
text-decoration: none;

&:hover {
text-decoration: none;
color: color.adjust($black, $lightness: 10%);
}
}

&.active {
background: $gray-100;
z-index: 2;
border-bottom-color: $gray-200;
opacity: 1;

a {
color: inherit;
text-shadow: inherit;
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface Attributes {
className?: string;
}
1 change: 0 additions & 1 deletion src/BlockTemplatesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ protected function init() {
add_filter( 'get_block_templates', array( $this, 'add_block_templates' ), 10, 3 );
add_filter( 'current_theme_supports-block-templates', array( $this, 'remove_block_template_support_for_shop_page' ) );
add_filter( 'taxonomy_template_hierarchy', array( $this, 'add_archive_product_to_eligible_for_fallback_templates' ), 10, 1 );

if ( $this->package->is_experimental_build() ) {
add_action( 'after_switch_theme', array( $this, 'check_should_use_blockified_product_grid_templates' ), 10, 2 );
}
Expand Down
56 changes: 56 additions & 0 deletions src/BlockTypes/ProductDetails.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php

namespace Automattic\WooCommerce\Blocks\BlockTypes;

/**
* ProductDetails class.
*/
class ProductDetails extends AbstractBlock {
/**
* Block name.
*
* @var string
*/
protected $block_name = 'product-details';

/**
* Render the block.
*
* @param array $attributes Block attributes.
* @param string $content Block content.
* @param WP_Block $block Block instance.
*
* @return string Rendered block output.
*/
protected function render( $attributes, $content, $block ) {
$tabs = $this->render_tabs();

$classname = $attributes['className'] ?? '';

return sprintf(
'<div class="wp-block-woocommerce-single-product-details %1$s">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The styles are now broken due to the latest changes to rename the block from single-product-details to product-details. The following should do the trick:

Suggested change
'<div class="wp-block-woocommerce-single-product-details %1$s">
'<div class="wc-block-woocommerce-product-details %1$s">

I also suggest renaming the class prefix from wp-block to wc-block so it is aligned with the standards we are using in other blocks.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We decided to avoid adding a custom class. We should use WP generated class (more context: p1675160559571929-slack-C02UBB1EPEF)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We decided to avoid adding a custom class. We should use WP generated class (more context: p1675160559571929-slack-C02UBB1EPEF)

Oh cool, I missed that convo, thanks for sharing! I'll also go ahead and update #8284 with this prefix.

In case someone else comes across this convo: the reason for this decision was that for new blocks, it's a good idea not to introduce new classes, as block themes interact with blocks via theme.json.

%2$s
</div>',
esc_attr( $classname ),
$tabs
);
}

/**
* Gets the tabs with their content to be rendered by the block.
*
* @return string The tabs html to be rendered by the block
*/
protected function render_tabs() {
ob_start();

while ( have_posts() ) {
the_post();
woocommerce_output_product_data_tabs();
}

$tabs = ob_get_clean();

return $tabs;
}
}
2 changes: 2 additions & 0 deletions src/BlockTypesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ protected function get_block_types() {
'RatingFilter',
'ReviewsByCategory',
'ReviewsByProduct',
'ProductDetails',
'StockFilter',
];

Expand Down Expand Up @@ -255,6 +256,7 @@ protected function get_block_types() {
'CatalogSorting',
'ClassicTemplate',
'ProductResultsCount',
'ProductDetails',
'StoreNotices',
]
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"title":"Product Details Block","pageContent":"<!-- wp:woocommerce/single-product-details /-->"}
32 changes: 32 additions & 0 deletions tests/e2e/specs/backend/single-produt-details.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* External dependencies
*/
import { getAllBlocks, switchUserToAdmin } from '@wordpress/e2e-test-utils';
import { visitBlockPage } from '@woocommerce/blocks-test-utils';

/**
* Internal dependencies
*/
import { insertBlockDontWaitForInsertClose } from '../../utils.js';

const block = {
name: 'Product Details',
slug: 'woocommerce/single-product-details',
class: '.wc-block-single-product-details',
};

describe( `${ block.name } Block`, () => {
beforeAll( async () => {
await switchUserToAdmin();
await visitBlockPage( `${ block.name } Block` );
} );

it( 'can be inserted more than once', async () => {
await insertBlockDontWaitForInsertClose( block.name );
expect( await getAllBlocks() ).toHaveLength( 2 );
} );

it( 'renders without crashing', async () => {
await expect( page ).toRenderBlock( block );
} );
} );