Product Categories List: Add show child categories only toggle (https://github.com/woocommerce/woocommerce-blocks/pull/9550)

* Add show child categories only toggle to Product Categories block

* Check if current page is a template editor before adding the toggle

* Show current category if show_children is enabled and its the last category in the hierarchy

* Update comment

* Fix typo

* Remove forward slash

* Add is-widget-editor utility and enable feature for block usage in widget editor

* Don't render anything if the child only option is enabled and there are no children
This commit is contained in:
Tom Cafferkey 2023-05-31 12:49:31 +01:00 committed by GitHub
parent c6e0ca1d8b
commit 801b7846e7
5 changed files with 104 additions and 33 deletions

View File

@ -6,6 +6,8 @@ import { InspectorControls, useBlockProps } from '@wordpress/block-editor';
import ServerSideRender from '@wordpress/server-side-render';
import PropTypes from 'prop-types';
import { Icon, listView } from '@wordpress/icons';
import { isSiteEditorPage, isWidgetEditorPage } from '@woocommerce/utils';
import { useSelect } from '@wordpress/data';
import {
Disabled,
PanelBody,
@ -42,9 +44,19 @@ const EmptyPlaceholder = () => (
* @param {string} props.name Name for block.
*/
const ProductCategoriesBlock = ( { attributes, setAttributes, name } ) => {
const editSiteStore = useSelect( 'core/edit-site' );
const editWidgetStore = useSelect( 'core/edit-widgets' );
const isSiteEditor = isSiteEditorPage( editSiteStore );
const isWidgetEditor = isWidgetEditorPage( editWidgetStore );
const getInspectorControls = () => {
const { hasCount, hasImage, hasEmpty, isDropdown, isHierarchical } =
attributes;
const {
hasCount,
hasImage,
hasEmpty,
isDropdown,
isHierarchical,
showChildrenOnly,
} = attributes;
return (
<InspectorControls key="inspector">
@ -142,6 +154,24 @@ const ProductCategoriesBlock = ( { attributes, setAttributes, name } ) => {
setAttributes( { hasEmpty: ! hasEmpty } )
}
/>
{ ( isSiteEditor || isWidgetEditor ) && (
<ToggleControl
label={ __(
'Only show children of current category',
'woo-gutenberg-products-block'
) }
help={ __(
'This will affect product category pages',
'woo-gutenberg-products-block'
) }
checked={ showChildrenOnly }
onChange={ () =>
setAttributes( {
showChildrenOnly: ! showChildrenOnly,
} )
}
/>
) }
</PanelBody>
</InspectorControls>
);

View File

@ -39,7 +39,11 @@
"isHierarchical": {
"type": "boolean",
"default": true
}
},
"showChildrenOnly": {
"type": "boolean",
"default": false
}
},
"example": {
"attributes": {

View File

@ -8,3 +8,4 @@ export * from './products';
export * from './shared-attributes';
export * from './sanitize-html';
export * from './is-site-editor-page';
export * from './is-widget-editor-page';

View File

@ -0,0 +1,18 @@
/**
* Internal dependencies
*/
import { isObject } from '../types/type-guards';
export const isWidgetEditorPage = ( store: unknown ): boolean => {
if ( isObject( store ) ) {
const widgetAreas = (
store as {
getWidgetAreas: () => string;
}
).getWidgetAreas();
return Array.isArray( widgetAreas ) && widgetAreas.length > 0;
}
return false;
};

View File

@ -22,11 +22,12 @@ class ProductCategories extends AbstractDynamicBlock {
* @var array
*/
protected $defaults = array(
'hasCount' => true,
'hasImage' => false,
'hasEmpty' => false,
'isDropdown' => false,
'isHierarchical' => true,
'hasCount' => true,
'hasImage' => false,
'hasEmpty' => false,
'isDropdown' => false,
'isHierarchical' => true,
'showChildrenOnly' => false,
);
/**
@ -38,17 +39,18 @@ class ProductCategories extends AbstractDynamicBlock {
return array_merge(
parent::get_block_type_attributes(),
array(
'align' => $this->get_schema_align(),
'className' => $this->get_schema_string(),
'hasCount' => $this->get_schema_boolean( true ),
'hasImage' => $this->get_schema_boolean( false ),
'hasEmpty' => $this->get_schema_boolean( false ),
'isDropdown' => $this->get_schema_boolean( false ),
'isHierarchical' => $this->get_schema_boolean( true ),
'textColor' => $this->get_schema_string(),
'fontSize' => $this->get_schema_string(),
'lineHeight' => $this->get_schema_string(),
'style' => array( 'type' => 'object' ),
'align' => $this->get_schema_align(),
'className' => $this->get_schema_string(),
'hasCount' => $this->get_schema_boolean( true ),
'hasImage' => $this->get_schema_boolean( false ),
'hasEmpty' => $this->get_schema_boolean( false ),
'isDropdown' => $this->get_schema_boolean( false ),
'isHierarchical' => $this->get_schema_boolean( true ),
'showChildrenOnly' => $this->get_schema_boolean( false ),
'textColor' => $this->get_schema_string(),
'fontSize' => $this->get_schema_string(),
'lineHeight' => $this->get_schema_string(),
'style' => array( 'type' => 'object' ),
)
);
}
@ -134,15 +136,30 @@ class ProductCategories extends AbstractDynamicBlock {
* @return array
*/
protected function get_categories( $attributes ) {
$hierarchical = wc_string_to_bool( $attributes['isHierarchical'] );
$categories = get_terms(
'product_cat',
[
'hide_empty' => ! $attributes['hasEmpty'],
'pad_counts' => true,
'hierarchical' => true,
]
);
$hierarchical = wc_string_to_bool( $attributes['isHierarchical'] );
$children_only = wc_string_to_bool( $attributes['showChildrenOnly'] ) && is_product_category();
if ( $children_only ) {
$term_id = get_queried_object_id();
$categories = get_terms(
'product_cat',
[
'hide_empty' => ! $attributes['hasEmpty'],
'pad_counts' => true,
'hierarchical' => true,
'child_of' => $term_id,
]
);
} else {
$categories = get_terms(
'product_cat',
[
'hide_empty' => ! $attributes['hasEmpty'],
'pad_counts' => true,
'hierarchical' => true,
]
);
}
if ( ! is_array( $categories ) || empty( $categories ) ) {
return [];
@ -157,17 +174,17 @@ class ProductCategories extends AbstractDynamicBlock {
}
);
}
return $hierarchical ? $this->build_category_tree( $categories ) : $categories;
return $hierarchical ? $this->build_category_tree( $categories, $children_only ) : $categories;
}
/**
* Build hierarchical tree of categories.
*
* @param array $categories List of terms.
* @param bool $children_only Is the block rendering only the children of the current category.
* @return array
*/
protected function build_category_tree( $categories ) {
protected function build_category_tree( $categories, $children_only ) {
$categories_by_parent = [];
foreach ( $categories as $category ) {
@ -177,8 +194,9 @@ class ProductCategories extends AbstractDynamicBlock {
$categories_by_parent[ 'cat-' . $category->parent ][] = $category;
}
$tree = $categories_by_parent['cat-0'];
unset( $categories_by_parent['cat-0'] );
$parent_id = $children_only ? get_queried_object_id() : 0;
$tree = $categories_by_parent[ 'cat-' . $parent_id ]; // these are top level categories. So all parents.
unset( $categories_by_parent[ 'cat-' . $parent_id ] );
foreach ( $tree as $category ) {
if ( ! empty( $categories_by_parent[ 'cat-' . $category->term_id ] ) ) {