);
}
);
/**
* One option from the list of all available ways to display products.
*/
class ProductsBlockSettingsEditorDisplayOption extends React.Component {
render() {
return (
);
}
}
/**
* One product in the product block preview.
*/
class ProductPreview extends React.Component {
render() {
const { attributes, product } = this.props;
let image = null;
if ( product.images.length ) {
image =
}
let title = null;
if ( attributes.display_title ) {
title =
{ product.name }
}
let price = null;
if ( attributes.display_price ) {
price =
{ product.price }
}
let add_to_cart = null;
if ( attributes.display_add_to_cart ) {
add_to_cart = { __( 'Add to cart' ) }
}
return (
{ image }
{ title }
{ price }
{ add_to_cart }
);
}
}
/**
* Renders a preview of what the block will look like with current settings.
*/
const ProductsBlockPreview = withAPIData( ( { attributes } ) => {
const { columns, rows, order, display, display_setting, layout } = attributes;
let query = {
per_page: ( 'list' === layout ) ? rows : rows * columns,
orderby: order
};
// @todo These will likely need to be modified to work with the final version of the category/product picker attributes.
if ( 'specific' === display ) {
query.include = JSON.stringify( display_setting );
query.orderby = 'include';
} else if ( 'category' === display ) {
query.category = display_setting.join( ',' );
}
let query_string = '?';
for ( const key of Object.keys( query ) ) {
query_string += key + '=' + query[ key ] + '&';
}
return {
products: '/wc/v2/products' + query_string
};
} )( ( { products, attributes } ) => {
if ( ! products.data ) {
return __( 'Loading' );
}
if ( 0 === products.data.length ) {
return __( 'No products found' );
}
const classes = "wc-products-block-preview " + attributes.layout + " cols-" + attributes.columns;
return (
{ products.data.map( ( product ) => (
) ) }
);
} );
/**
* Register and run the products block.
*/
registerBlockType( 'woocommerce/products', {
title: __( 'Products' ),
icon: 'universal-access-alt', // @todo Needs a good icon.
category: 'widgets',
attributes: {
/**
* Layout to use. 'grid' or 'list'.
*/
layout: {
type: 'string',
default: 'grid',
},
/**
* Number of columns.
*/
columns: {
type: 'number',
default: 3,
},
/**
* Number of rows.
*/
rows: {
type: 'number',
default: 1,
},
/**
* Whether to display product titles.
*/
display_title: {
type: 'boolean',
default: true,
},
/**
* Whether to display prices.
*/
display_price: {
type: 'boolean',
default: true,
},
/**
* Whether to display Add to Cart buttons.
*/
display_add_to_cart: {
type: 'boolean',
default: false,
},
/**
* Order to use for products. 'date', or 'title'.
*/
order: {
type: 'string',
default: 'date',
},
/**
* What types of products to display. 'all', 'specific', or 'category'.
*/
display: {
type: 'string',
default: '',
},
/**
* Which products to display if 'display' is 'specific' or 'category'. Array of product ids or category slugs depending on setting.
*/
display_setting: {
type: 'array',
default: [],
},
/**
* Whether the block is in edit or preview mode.
*/
edit_mode: {
type: 'boolean',
default: true,
},
},
/**
* Renders and manages the block.
*/
edit( props ) {
const { attributes, className, focus, setAttributes, setFocus } = props;
const { layout, rows, columns, display_title, display_price, display_add_to_cart, order, display, display_setting, edit_mode } = attributes;
/**
* Get the components for the sidebar settings area that is rendered while focused on a Products block.
*
* @return Component
*/
function getInspectorControls() {
return (
{ __( 'Layout' ) }
setAttributes( { columns: value } ) }
min={ 1 }
max={ 6 }
/>
setAttributes( { rows: value } ) }
min={ 1 }
max={ 6 }
/>
setAttributes( { display_title: ! display_title } ) }
/>
setAttributes( { display_price: ! display_price } ) }
/>
setAttributes( { display_add_to_cart: ! display_add_to_cart } ) }
/>
setAttributes( { order: value } ) }
/>
);
};
/**
* Get the components for the toolbar area that appears on top of the block when focused.
*
* @return Component
*/
function getToolbarControls() {
const layoutControls = [
{
icon: 'list-view',
title: __( 'List View' ),
onClick: () => setAttributes( { layout: 'list' } ),
isActive: layout === 'list',
},
{
icon: 'grid-view',
title: __( 'Grid View' ),
onClick: () => setAttributes( { layout: 'grid' } ),
isActive: layout === 'grid',
},
];
const editButton = [
{
icon: 'edit',
title: __( 'Edit' ),
onClick: () => setAttributes( { edit_mode: ! edit_mode } ),
isActive: edit_mode,
},
];
return (
);
}
/**
* Get the block preview component for preview mode.
*
* @return Component
*/
function getPreview() {
return ;
}
/**
* Get the block edit component for edit mode.
*
* @return Component
*/
function getSettingsEditor() {
return (
setAttributes( { display: value } ) }
update_display_setting_callback={ ( value ) => setAttributes( { display_setting: value } ) }
done_callback={ () => setAttributes( { edit_mode: false } ) }
/>
);
}
return [
( !! focus ) ? getInspectorControls() : null,
( !! focus ) ? getToolbarControls() : null,
edit_mode ? getSettingsEditor() : getPreview(),
];
},
/**
* Save the block content in the post content. Block content is saved as a products shortcode.
*
* @return string
*/
save( props ) {
const { layout, rows, columns, display_title, display_price, display_add_to_cart, order, display, display_setting, className } = props.attributes;
let shortcode_atts = new Map();
shortcode_atts.set( 'orderby', order );
shortcode_atts.set( 'limit', 'grid' === layout ? rows * columns : rows );
shortcode_atts.set( 'class', 'list' === layout ? className + ' list-layout' : className );
if ( 'grid' === layout ) {
shortcode_atts.set( 'columns', columns );
}
if ( ! display_title ) {
shortcode_atts.set( 'show_title', 0 );
}
if ( ! display_price ) {
shortcode_atts.set( 'show_price', 0 );
}
if ( ! display_add_to_cart ) {
shortcode_atts.set( 'show_add_to_cart', 0 );
}
if ( 'specific' === display ) {
shortcode_atts.set( 'include', display_setting.join( ',' ) );
}
if ( 'category' === display ) {
shortcode_atts.set( 'category', display_setting.join( ',' ) );
}
// Build the shortcode string out of the set shortcode attributes.
let shortcode = '[products';
for ( let [key, value] of shortcode_atts ) {
shortcode += ' ' + key + '="' + value + '"';
}
shortcode += ']';
return shortcode;
},
} );