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 all 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
63 changes: 63 additions & 0 deletions src/BlockTypes/ProductDetails.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php

namespace Automattic\WooCommerce\Blocks\BlockTypes;

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

/**
* It isn't necessary register block assets because it is a server side block.
*/
protected function register_block_type_assets() {
return null;
}

/**
* 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-product-details %1$s">
%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;
}
}
7 changes: 7 additions & 0 deletions src/BlockTypes/ProductImageGallery.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ protected function get_block_type_uses_context() {
return [ 'query', 'queryId', 'postId' ];
}

/**
* It isn't necessary register block assets because it is a server side block.
*/
protected function register_block_type_assets() {
return null;
}


/**
* Include and render the block.
Expand Down
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 );
} );
} );