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

Commit

Permalink
Add Product Image Gallery (#8235)
Browse files Browse the repository at this point in the history
* Add Product Image Gallery #8233

Add Product Image Gallery

* Add Product Image Gallery block

* remove support global styles

* remove support global styles

* address CSS feedback

* add support for the custom classname

* remove save function

* add second parameter to the subscribe function

* update @types/wordpress__data package

* update placeholder, icon and description

* update tsconfig
  • Loading branch information
gigitux authored Feb 14, 2023
1 parent cffafeb commit 7a4006a
Show file tree
Hide file tree
Showing 15 changed files with 278 additions and 5 deletions.
1 change: 1 addition & 0 deletions assets/js/atomic/blocks/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ import './product-elements/category-list';
import './product-elements/tag-list';
import './product-elements/stock-indicator';
import './product-elements/add-to-cart';
import './product-elements/product-image-gallery';
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "woocommerce/product-image-gallery",
"version": "1.0.0",
"title": "Product Image Gallery",
"icon": "gallery",
"description": "Display a product's images.",
"category": "woocommerce",
"supports": {
"align": true,
"reusable": false
},
"keywords": [ "WooCommerce" ],
"usesContext": [ "postId", "postType", "queryId" ],
"textdomain": "woo-gutenberg-products-block",
"apiVersion": 2,
"$schema": "https://schemas.wp.org/trunk/block.json"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/**
* External dependencies
*/
import { WC_BLOCKS_IMAGE_URL } from '@woocommerce/block-settings';
import { isEmptyObject } from '@woocommerce/types';
import { useBlockProps } from '@wordpress/block-editor';
import { BlockAttributes } from '@wordpress/blocks';
import { Disabled } from '@wordpress/components';

/**
* Internal dependencies
*/
import './editor.scss';

const Placeholder = () => {
return (
<div className="wc-block-editor-product-gallery">
<img
src={ `${ WC_BLOCKS_IMAGE_URL }block-placeholders/product-image-gallery.svg` }
alt="Placeholder"
/>
<div className="wc-block-editor-product-gallery__other-images">
{ [ ...Array( 4 ).keys() ].map( ( index ) => {
return (
<img
key={ index }
src={ `${ WC_BLOCKS_IMAGE_URL }block-placeholders/product-image-gallery.svg` }
alt="Placeholder"
/>
);
} ) }
</div>
</div>
);
};

type Context = {
postId: string;
postType: string;
queryId: string;
};

interface Props {
attributes: BlockAttributes;
context: Context;
}

const Edit = ( { context }: Props ) => {
const blockProps = useBlockProps();

if ( isEmptyObject( context ) ) {
return (
<div { ...blockProps }>
<Disabled>
<Placeholder />
</Disabled>
</div>
);
}
// We have work on this case when we will work on the Single Product block.
return '';
};

export default Edit;
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.wc-block-editor-product-gallery {
img {
width: 500px;
height: 500px;
}
.wc-block-editor-product-gallery__other-images {
img {
width: 100px;
height: 100px;
margin: 5px;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/**
* External dependencies
*/
import { gallery as icon } from '@wordpress/icons';
import { registerBlockType, unregisterBlockType } from '@wordpress/blocks';
import { registerBlockSingleProductTemplate } from '@woocommerce/atomic-utils';

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

registerBlockSingleProductTemplate( {
registerBlockFn: () => {
// @ts-expect-error: `registerBlockType` is a function that is typed in WordPress core.
registerBlockType( metadata, {
icon,
edit,
} );
},
unregisterBlockFn: () => {
unregisterBlockType( metadata.name );
},
blockName: metadata.name,
} );
1 change: 1 addition & 0 deletions assets/js/atomic/utils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export * from './get-block-map';
export * from './create-blocks-from-template';
export * from './render-parent-block';
export * from './render-standalone-blocks';
export * from './register-block-single-product-template';
46 changes: 46 additions & 0 deletions assets/js/atomic/utils/register-block-single-product-template.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/**
* External dependencies
*/
import { getBlockType } from '@wordpress/blocks';
import { subscribe, select } from '@wordpress/data';

export const registerBlockSingleProductTemplate = ( {
registerBlockFn,
unregisterBlockFn,
blockName,
}: {
registerBlockFn: () => void;
unregisterBlockFn: () => void;
blockName: string;
} ) => {
let currentTemplateId: string | undefined;

subscribe( () => {
const previousTemplateId = currentTemplateId;
const store = select( 'core/edit-site' );
currentTemplateId = store?.getEditedPostId() as string | undefined;

if ( previousTemplateId === currentTemplateId ) {
return;
}

const parsedTemplate = currentTemplateId?.split( '//' )[ 1 ];

if ( parsedTemplate === null || parsedTemplate === undefined ) {
return;
}

const block = getBlockType( blockName );

if (
block === undefined &&
parsedTemplate.includes( 'single-product' )
) {
registerBlockFn();
}

if ( block !== undefined ) {
unregisterBlockFn();
}
}, 'core/edit-site' );
};
6 changes: 6 additions & 0 deletions assets/js/types/type-guards/object.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,9 @@ export function objectHasProp< P extends PropertyKey >(
// The `in` operator throws a `TypeError` for non-object values.
return isObject( target ) && property in target;
}

export const isEmptyObject = < T extends { [ key: string ]: unknown } >(
object: T
) => {
return Object.keys( object ).length === 0;
};
25 changes: 25 additions & 0 deletions assets/js/types/type-guards/test/object.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* External dependencies
*/
import { isEmptyObject, isObject } from '@woocommerce/types';

describe( 'Object type-guards', () => {
describe( 'Testing isObject()', () => {
it( 'Correctly identifies an object', () => {
expect( isObject( {} ) ).toBe( true );
expect( isObject( { test: 'object' } ) ).toBe( true );
} );
it( 'Correctly rejects object-like things', () => {
expect( isObject( [] ) ).toBe( false );
expect( isObject( null ) ).toBe( false );
} );
} );
describe( 'Testing isEmptyObject()', () => {
it( 'Correctly identifies an empty object', () => {
expect( isEmptyObject( {} ) ).toBe( true );
} );
it( 'Correctly identifies an not empty object', () => {
expect( isEmptyObject( { name: 'Woo' } ) ).toBe( false );
} );
} );
} );
9 changes: 9 additions & 0 deletions images/block-placeholders/product-image-gallery.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 7 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@
"@types/wordpress__blocks": "11.0.7",
"@types/wordpress__components": "^23.0.0",
"@types/wordpress__core-data": "^2.4.5",
"@types/wordpress__data": "^6.0.1",
"@types/wordpress__data": "^6.0.2",
"@types/wordpress__data-controls": "2.2.0",
"@types/wordpress__editor": "^11.0.0",
"@types/wordpress__notices": "^3.5.0",
Expand Down
60 changes: 60 additions & 0 deletions src/BlockTypes/ProductImageGallery.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php
namespace Automattic\WooCommerce\Blocks\BlockTypes;

use Automattic\WooCommerce\Blocks\Utils\StyleAttributesUtils;


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

/**
* Register the context
*
* @var string
*/
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 ) {

$post_id = $block->context['postId'];
global $product;
$product = wc_get_product( $post_id );

if ( class_exists( 'WC_Frontend_Scripts' ) ) {
$frontend_scripts = new \WC_Frontend_Scripts();
$frontend_scripts::load_scripts();
}

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

ob_start();
woocommerce_show_product_images();
$product_image_gallery_html = ob_get_clean();

return sprintf(
'<div class="wp-block-woocommerce-product-image-gallery %1$s">%2$s</div>',
esc_attr( $classname ),
$product_image_gallery_html
);

}
}
1 change: 1 addition & 0 deletions src/BlockTypesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ protected function get_block_types() {
'ProductCategory',
'ProductCategoryList',
'ProductImage',
'ProductImageGallery',
'ProductNew',
'ProductOnSale',
'ProductPrice',
Expand Down
1 change: 1 addition & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"./assets/js/**/*",
"./packages/checkout/**/*",
"./assets/js/blocks/**/block.json",
"./assets/js/atomic/blocks/**/block.json",
"./assets/js/blocks/mini-cart/mini-cart-contents/inner-blocks/**/block.json",
"./storybook/**/*",
"./tests/js/setup-after-env.ts"
Expand Down

0 comments on commit 7a4006a

Please sign in to comment.