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

Commit

Permalink
Change default rows for product grid blocks to 3 (#1613)
Browse files Browse the repository at this point in the history
* Change default rows to 3

* Handle all products rows change via deprecation

* Prevent errors if object is undefined

* HOC to set default attribute values

* Separate default attributes from attribute definitions

* Filters to set defaults

* Fix deprecation so attributes are not reordered

* Move flters to index file and limit which blocks are affected

* Fix object assign

* Use typeof for undefined checks

* Move hoc to filter file so it has context

* Fix up comment

* Avoid mutating props

* Prevent multiple `attributes` by cloning props

* Force attributes to be saved to HTML in a specific order, and handle migration

* useEffect to set attributes and avoid prop mutation

* Switch to class component
  • Loading branch information
mikejolley authored Jan 22, 2020
1 parent f4d9f7d commit bd8d9a1
Show file tree
Hide file tree
Showing 13 changed files with 198 additions and 42 deletions.
53 changes: 41 additions & 12 deletions assets/js/blocks/products/all-products/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,11 @@ import Gridicon from 'gridicons';
* Internal dependencies
*/
import Editor from './edit';
import sharedAttributes from '../attributes';
import { attributes as sharedAttributes, defaults } from '../attributes';
import { getBlockClassName } from '../utils.js';
import '../../../atomic/blocks/product';

/**
* Register and run the "All Products" block.
*/
registerBlockType( 'woocommerce/all-products', {
const blockSettings = {
title: __( 'All Products', 'woo-gutenberg-products-block' ),
icon: {
src: <Gridicon icon="grid" />,
Expand All @@ -39,10 +36,8 @@ registerBlockType( 'woocommerce/all-products', {
isPreview: true,
},
},
attributes: {
...sharedAttributes,
},

attributes: sharedAttributes,
defaults,
/**
* Renders and manages the block.
*
Expand All @@ -51,17 +46,18 @@ registerBlockType( 'woocommerce/all-products', {
edit( props ) {
return <Editor { ...props } />;
},

/**
* Save the props to post content.
*
* @param {Object} attributes Attributes to save.
*/
save( { attributes } ) {
const data = {
'data-attributes': JSON.stringify( attributes ),
'data-attributes': JSON.stringify(
attributes,
Object.keys( attributes ).sort()
),
};

return (
<div
className={ getBlockClassName(
Expand All @@ -74,4 +70,37 @@ registerBlockType( 'woocommerce/all-products', {
</div>
);
},
};

/**
* Register and run the "All Products" block.
*/
registerBlockType( 'woocommerce/all-products', {
...blockSettings,
/**
* Deprecation rule to handle the previous default rows which was 1 instead of 3.
*/
deprecated: [
{
attributes: Object.assign( {}, blockSettings.attributes, {
rows: { type: 'number', default: 1 },
} ),
save( { attributes } ) {
const data = {
'data-attributes': JSON.stringify( attributes ),
};
return (
<div
className={ getBlockClassName(
'wc-block-all-products',
attributes
) }
{ ...data }
>
<InnerBlocks.Content />
</div>
);
},
},
],
} );
28 changes: 13 additions & 15 deletions assets/js/blocks/products/attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,57 +8,55 @@ import { DEFAULT_COLUMNS, DEFAULT_ROWS } from '@woocommerce/block-settings';
*/
import { DEFAULT_PRODUCT_LIST_LAYOUT } from './base-utils';

export default {
export const defaults = {
columns: DEFAULT_COLUMNS,
rows: DEFAULT_ROWS,
alignButtons: false,
contentVisibility: {
orderBy: true,
},
orderby: 'date',
layoutConfig: DEFAULT_PRODUCT_LIST_LAYOUT,
isPreview: false,
};

export const attributes = {
/**
* Number of columns.
*/
columns: {
type: 'number',
default: DEFAULT_COLUMNS,
},

/**
* Number of rows.
*/
rows: {
type: 'number',
default: DEFAULT_ROWS,
},

/**
* How to align cart buttons.
*/
alignButtons: {
type: 'boolean',
default: false,
},

/**
* Content visibility setting
*/
contentVisibility: {
type: 'object',
default: {
orderBy: true,
},
},

/**
* Order to use for the products listing.
*/
orderby: {
type: 'string',
default: 'date',
},

/**
* Layout config.
*/
layoutConfig: {
type: 'array',
default: DEFAULT_PRODUCT_LIST_LAYOUT,
},

/**
* Are we previewing?
*/
Expand Down
10 changes: 5 additions & 5 deletions assets/js/blocks/products/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ export const getBlockClassName = ( blockClassName, attributes ) => {
const { className, contentVisibility } = attributes;

return classNames( blockClassName, className, {
'has-image': contentVisibility.image,
'has-title': contentVisibility.title,
'has-rating': contentVisibility.rating,
'has-price': contentVisibility.price,
'has-button': contentVisibility.button,
'has-image': contentVisibility && contentVisibility.image,
'has-title': contentVisibility && contentVisibility.title,
'has-rating': contentVisibility && contentVisibility.rating,
'has-price': contentVisibility && contentVisibility.price,
'has-button': contentVisibility && contentVisibility.button,
} );
};

Expand Down
84 changes: 84 additions & 0 deletions assets/js/filters/block-list-block.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/**
* External dependencies
*/
import { Component } from '@wordpress/element';
import { createHigherOrderComponent } from '@wordpress/compose';
const { getBlockType } = wp.blocks;
const { addFilter } = wp.hooks;

/**
* withDefaultAttributes HOC for editor.BlockListBlock.
*
* @param object BlockListBlock The BlockListBlock element.
*/
const withDefaultAttributes = createHigherOrderComponent(
( BlockListBlock ) => {
class WrappedComponent extends Component {
constructor() {
super( ...arguments );

const blockType = getBlockType( this.props.block.name );
const attributes = Object.assign(
{},
this.props.attributes || {}
);

if (
this.props.block.name.startsWith( 'woocommerce/' ) &&
typeof blockType.attributes !== 'undefined' &&
typeof blockType.defaults !== 'undefined'
) {
Object.keys( blockType.attributes ).map( ( key ) => {
if (
typeof attributes[ key ] === 'undefined' &&
typeof blockType.defaults[ key ] !== 'undefined'
) {
attributes[ key ] = blockType.defaults[ key ];
}
return key;
} );
}

this.attributesWithDefaults = attributes;
}

componentDidMount() {
const { block, setAttributes } = this.props;

if ( block.name.startsWith( 'woocommerce/' ) ) {
setAttributes( this.attributesWithDefaults );
}
}

render() {
return (
<BlockListBlock
{ ...this.props }
attributes={ this.attributesWithDefaults }
/>
);
}
}
return WrappedComponent;
},
'withDefaultAttributes'
);

/**
* Hook into `editor.BlockListBlock` to set default attributes (if blocks
* define them separately) when a block is inserted.
*
* This is a workaround for Gutenberg which does not save "default" attributes
* to the post, which means if defaults change, all existing blocks change too.
*
* See https://github.com/WordPress/gutenberg/issues/7342
*
* To use this, the block name needs a `woocommerce/` prefix, and as well
* as defining `attributes` during block registration, you must also declare an
* array called `defaults`. Defaults should be omitted from `attributes`.
*/
addFilter(
'editor.BlockListBlock',
'woocommerce-blocks/block-list-block',
withDefaultAttributes
);
44 changes: 44 additions & 0 deletions assets/js/filters/get-block-attributes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
const { addFilter } = wp.hooks;

/**
* Adjust attributes on load to set defaults so default attributes get saved.
*
* @param {Object} blockAttributes Original block attributes.
* @param {Object} blockType Block type settings.
*
* @return {Object} Filtered block attributes.
*/
const setBlockAttributeDefaults = ( blockAttributes, blockType ) => {
if ( blockType.name.startsWith( 'woocommerce/' ) ) {
Object.keys( blockType.attributes ).map( ( key ) => {
if (
typeof blockAttributes[ key ] === 'undefined' &&
typeof blockType.defaults !== 'undefined' &&
typeof blockType.defaults[ key ] !== 'undefined'
) {
blockAttributes[ key ] = blockType.defaults[ key ];
}
return key;
} );
}
return blockAttributes;
};

/**
* Hook into `blocks.getBlockAttributes` to set default attributes (if blocks
* define them separately) when a block is loaded.
*
* This is a workaround for Gutenberg which does not save "default" attributes
* to the post, which means if defaults change, all existing blocks change too.
*
* See https://github.com/WordPress/gutenberg/issues/7342
*
* To use this, the block name needs a `woocommerce/` prefix, and as well
* as defining `attributes` during block registration, you must also declare an
* array called `defaults`. Defaults should be omitted from `attributes`.
*/
addFilter(
'blocks.getBlockAttributes',
'woocommerce-blocks/get-block-attributes',
setBlockAttributeDefaults
);
4 changes: 1 addition & 3 deletions assets/js/hocs/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,5 @@ export { default as withFeedbackPrompt } from './with-feedback-prompt';
export { default as withProduct } from './with-product';
export { default as withProductVariations } from './with-product-variations';
export { default as withSearchedProducts } from './with-searched-products';
export {
default as withTransformSingleSelectToMultipleSelect,
} from './with-transform-single-select-to-multiple-select';
export { default as withTransformSingleSelectToMultipleSelect } from './with-transform-single-select-to-multiple-select';
export { default as withRestApiHydration } from './with-rest-api-hydration';
2 changes: 2 additions & 0 deletions assets/js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import { __ } from '@wordpress/i18n';
*/
import '../css/editor.scss';
import '../css/style.scss';
import './filters/block-list-block';
import './filters/get-block-attributes';
import { IconWoo } from './components/icons';

setCategories( [
Expand Down
2 changes: 1 addition & 1 deletion assets/js/settings/blocks/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export const MIN_COLUMNS = getSetting( 'min_columns', 1 );
export const DEFAULT_COLUMNS = getSetting( 'default_columns', 3 );
export const MAX_ROWS = getSetting( 'max_rows', 6 );
export const MIN_ROWS = getSetting( 'min_rows', 1 );
export const DEFAULT_ROWS = getSetting( 'default_rows', 2 );
export const DEFAULT_ROWS = getSetting( 'default_rows', 3 );
export const MIN_HEIGHT = getSetting( 'min_height', 500 );
export const DEFAULT_HEIGHT = getSetting( 'default_height', 500 );
export const PLACEHOLDER_IMG_SRC = getSetting( 'placeholderImgSrc', '' );
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
"sideEffects": [
"*.css",
"*.scss",
"./assets/js/atomic/blocks/product/**"
"./assets/js/atomic/blocks/product/**",
"./assets/js/filters/**"
],
"repository": {
"type": "git",
Expand Down
2 changes: 1 addition & 1 deletion src/Assets.php
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ public static function get_wc_block_data( $settings ) {
'default_columns' => wc_get_theme_support( 'product_blocks::default_columns', 3 ),
'min_rows' => wc_get_theme_support( 'product_blocks::min_rows', 1 ),
'max_rows' => wc_get_theme_support( 'product_blocks::max_rows', 6 ),
'default_rows' => wc_get_theme_support( 'product_blocks::default_rows', 1 ),
'default_rows' => wc_get_theme_support( 'product_blocks::default_rows', 3 ),
'thumbnail_size' => wc_get_theme_support( 'thumbnail_image_width', 300 ),
'placeholderImgSrc' => wc_placeholder_img_src(),
'min_height' => wc_get_theme_support( 'featured_block::min_height', 500 ),
Expand Down
4 changes: 2 additions & 2 deletions src/BlockTypes/AbstractProductGrid.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ protected function get_attributes() {
return array(
'className' => $this->get_schema_string(),
'columns' => $this->get_schema_number( wc_get_theme_support( 'product_blocks::default_columns', 3 ) ),
'rows' => $this->get_schema_number( wc_get_theme_support( 'product_blocks::default_rows', 1 ) ),
'rows' => $this->get_schema_number( wc_get_theme_support( 'product_blocks::default_rows', 3 ) ),
'categories' => $this->get_schema_list_ids(),
'catOperator' => array(
'type' => 'string',
Expand Down Expand Up @@ -122,7 +122,7 @@ protected function parse_attributes( $attributes ) {
// These should match what's set in JS `registerBlockType`.
$defaults = array(
'columns' => wc_get_theme_support( 'product_blocks::default_columns', 3 ),
'rows' => wc_get_theme_support( 'product_blocks::default_rows', 1 ),
'rows' => wc_get_theme_support( 'product_blocks::default_rows', 3 ),
'alignButtons' => false,
'categories' => array(),
'catOperator' => 'any',
Expand Down
2 changes: 1 addition & 1 deletion src/BlockTypes/ProductTag.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ protected function get_attributes() {
return array(
'className' => $this->get_schema_string(),
'columns' => $this->get_schema_number( wc_get_theme_support( 'product_blocks::default_columns', 3 ) ),
'rows' => $this->get_schema_number( wc_get_theme_support( 'product_blocks::default_rows', 1 ) ),
'rows' => $this->get_schema_number( wc_get_theme_support( 'product_blocks::default_rows', 3 ) ),
'contentVisibility' => $this->get_schema_content_visibility(),
'align' => $this->get_schema_align(),
'alignButtons' => $this->get_schema_boolean( false ),
Expand Down
2 changes: 1 addition & 1 deletion src/BlockTypes/ProductsByAttribute.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ protected function get_attributes() {
'contentVisibility' => $this->get_schema_content_visibility(),
'editMode' => $this->get_schema_boolean( true ),
'orderby' => $this->get_schema_orderby(),
'rows' => $this->get_schema_number( wc_get_theme_support( 'product_blocks::default_rows', 1 ) ),
'rows' => $this->get_schema_number( wc_get_theme_support( 'product_blocks::default_rows', 3 ) ),
'isPreview' => $this->get_schema_boolean( false ),
);
}
Expand Down

0 comments on commit bd8d9a1

Please sign in to comment.