Converted product-tag and removed its proptypes (https://github.com/woocommerce/woocommerce-blocks/pull/9758)
* Converted product-tag and removed its proptypes * addressed review comments --------- Co-authored-by: Niels Lange <info@nielslange.de>
This commit is contained in:
parent
74e39331fb
commit
c1f2949a5d
|
@ -1,9 +1,11 @@
|
|||
// @ts-expect-error: `ServerSideRender ` currently does not have a type definition in WordPress core
|
||||
// eslint-disable-next-line @woocommerce/dependency-group
|
||||
import ServerSideRender from '@wordpress/server-side-render';
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { BlockControls, InspectorControls } from '@wordpress/block-editor';
|
||||
import ServerSideRender from '@wordpress/server-side-render';
|
||||
import {
|
||||
Button,
|
||||
Disabled,
|
||||
|
@ -12,8 +14,7 @@ import {
|
|||
ToolbarGroup,
|
||||
withSpokenMessages,
|
||||
} from '@wordpress/components';
|
||||
import { Component } from '@wordpress/element';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useEffect, useState } from '@wordpress/element';
|
||||
import GridContentControl from '@woocommerce/editor-components/grid-content-control';
|
||||
import GridLayoutControl from '@woocommerce/editor-components/grid-layout-control';
|
||||
import ProductTagControl from '@woocommerce/editor-components/product-tag-control';
|
||||
|
@ -21,70 +22,50 @@ import ProductOrderbyControl from '@woocommerce/editor-components/product-orderb
|
|||
import ProductStockControl from '@woocommerce/editor-components/product-stock-control';
|
||||
import { Icon, tag } from '@wordpress/icons';
|
||||
import { gridBlockPreview } from '@woocommerce/resource-previews';
|
||||
import { getSetting } from '@woocommerce/settings';
|
||||
import { getSetting, getSettingWithCoercion } from '@woocommerce/settings';
|
||||
import { isNumber } from '@woocommerce/types';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import type { ProductsByTagBlockProps } from './types';
|
||||
/**
|
||||
* Component to handle edit mode of "Products by Tag".
|
||||
*/
|
||||
class ProductsByTagBlock extends Component {
|
||||
constructor() {
|
||||
super( ...arguments );
|
||||
this.state = {
|
||||
changedAttributes: {},
|
||||
isEditing: false,
|
||||
};
|
||||
|
||||
this.startEditing = this.startEditing.bind( this );
|
||||
this.stopEditing = this.stopEditing.bind( this );
|
||||
this.setChangedAttributes = this.setChangedAttributes.bind( this );
|
||||
this.save = this.save.bind( this );
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { attributes } = this.props;
|
||||
const ProductsByTagBlock = ( {
|
||||
attributes,
|
||||
name,
|
||||
setAttributes,
|
||||
debouncedSpeak,
|
||||
}: ProductsByTagBlockProps ) => {
|
||||
const [ changedAttributes, setChangedAttributes ] = useState<
|
||||
Partial< ProductsByTagBlockProps[ 'attributes' ] >
|
||||
>( {} );
|
||||
const [ isEditing, setIsEditing ] = useState( false );
|
||||
|
||||
useEffect( () => {
|
||||
if ( ! attributes.tags.length ) {
|
||||
// We've removed all selected categories, or no categories have been selected yet.
|
||||
this.setState( { isEditing: true } );
|
||||
setIsEditing( true );
|
||||
}
|
||||
}
|
||||
}, [ attributes.tags.length ] );
|
||||
|
||||
startEditing() {
|
||||
this.setState( {
|
||||
isEditing: true,
|
||||
changedAttributes: {},
|
||||
} );
|
||||
}
|
||||
const startEditing = () => {
|
||||
setIsEditing( true );
|
||||
setChangedAttributes( {} );
|
||||
};
|
||||
|
||||
stopEditing() {
|
||||
this.setState( {
|
||||
isEditing: false,
|
||||
changedAttributes: {},
|
||||
} );
|
||||
}
|
||||
|
||||
setChangedAttributes( attributes ) {
|
||||
this.setState( ( prevState ) => {
|
||||
return {
|
||||
changedAttributes: {
|
||||
...prevState.changedAttributes,
|
||||
...attributes,
|
||||
},
|
||||
};
|
||||
} );
|
||||
}
|
||||
|
||||
save() {
|
||||
const { changedAttributes } = this.state;
|
||||
const { setAttributes } = this.props;
|
||||
const stopEditing = () => {
|
||||
setIsEditing( false );
|
||||
setChangedAttributes( {} );
|
||||
};
|
||||
|
||||
const save = () => {
|
||||
setAttributes( changedAttributes );
|
||||
this.stopEditing();
|
||||
}
|
||||
stopEditing();
|
||||
};
|
||||
|
||||
getInspectorControls() {
|
||||
const { attributes, setAttributes } = this.props;
|
||||
const { isEditing } = this.state;
|
||||
const getInspectorControls = () => {
|
||||
const {
|
||||
columns,
|
||||
tagOperator,
|
||||
|
@ -104,6 +85,7 @@ class ProductsByTagBlock extends Component {
|
|||
) }
|
||||
initialOpen={ ! attributes.tags.length && ! isEditing }
|
||||
>
|
||||
{ /* @ts-expect-error ProductTagControl is yet to be converted to tsx*/ }
|
||||
<ProductTagControl
|
||||
selected={ attributes.tags }
|
||||
onChange={ ( value = [] ) => {
|
||||
|
@ -126,10 +108,26 @@ class ProductsByTagBlock extends Component {
|
|||
rows={ rows }
|
||||
alignButtons={ alignButtons }
|
||||
setAttributes={ setAttributes }
|
||||
minColumns={ getSetting( 'min_columns', 1 ) }
|
||||
maxColumns={ getSetting( 'max_columns', 6 ) }
|
||||
minRows={ getSetting( 'min_rows', 1 ) }
|
||||
maxRows={ getSetting( 'max_rows', 6 ) }
|
||||
minColumns={ getSettingWithCoercion(
|
||||
'min_columns',
|
||||
1,
|
||||
isNumber
|
||||
) }
|
||||
maxColumns={ getSettingWithCoercion(
|
||||
'max_columns',
|
||||
6,
|
||||
isNumber
|
||||
) }
|
||||
minRows={ getSettingWithCoercion(
|
||||
'min_rows',
|
||||
6,
|
||||
isNumber
|
||||
) }
|
||||
maxRows={ getSettingWithCoercion(
|
||||
'max_rows',
|
||||
6,
|
||||
isNumber
|
||||
) }
|
||||
/>
|
||||
</PanelBody>
|
||||
<PanelBody
|
||||
|
@ -166,14 +164,12 @@ class ProductsByTagBlock extends Component {
|
|||
</PanelBody>
|
||||
</InspectorControls>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
renderEditMode() {
|
||||
const { attributes, debouncedSpeak } = this.props;
|
||||
const { changedAttributes } = this.state;
|
||||
const renderEditMode = () => {
|
||||
const currentAttributes = { ...attributes, ...changedAttributes };
|
||||
const onDone = () => {
|
||||
this.save();
|
||||
save();
|
||||
debouncedSpeak(
|
||||
__(
|
||||
'Showing Products by Tag block preview.',
|
||||
|
@ -182,7 +178,7 @@ class ProductsByTagBlock extends Component {
|
|||
);
|
||||
};
|
||||
const onCancel = () => {
|
||||
this.stopEditing();
|
||||
stopEditing();
|
||||
debouncedSpeak(
|
||||
__(
|
||||
'Showing Products by Tag block preview.',
|
||||
|
@ -207,15 +203,16 @@ class ProductsByTagBlock extends Component {
|
|||
'woo-gutenberg-products-block'
|
||||
) }
|
||||
<div className="wc-block-product-tag__selection">
|
||||
{ /* @ts-expect-error ProductTagControl is yet to be converted to tsx*/ }
|
||||
<ProductTagControl
|
||||
selected={ currentAttributes.tags }
|
||||
onChange={ ( value = [] ) => {
|
||||
const ids = value.map( ( { id } ) => id );
|
||||
this.setChangedAttributes( { tags: ids } );
|
||||
setChangedAttributes( { tags: ids } );
|
||||
} }
|
||||
operator={ currentAttributes.tagOperator }
|
||||
onOperatorChange={ ( value = 'any' ) =>
|
||||
this.setChangedAttributes( { tagOperator: value } )
|
||||
setChangedAttributes( { tagOperator: value } )
|
||||
}
|
||||
/>
|
||||
<Button isPrimary onClick={ onDone }>
|
||||
|
@ -231,10 +228,8 @@ class ProductsByTagBlock extends Component {
|
|||
</div>
|
||||
</Placeholder>
|
||||
);
|
||||
}
|
||||
|
||||
renderViewMode() {
|
||||
const { attributes, name } = this.props;
|
||||
};
|
||||
const renderViewMode = () => {
|
||||
const selectedTags = attributes.tags.length;
|
||||
|
||||
return (
|
||||
|
@ -266,76 +261,44 @@ class ProductsByTagBlock extends Component {
|
|||
) }
|
||||
</Disabled>
|
||||
);
|
||||
};
|
||||
|
||||
if ( attributes.isPreview ) {
|
||||
return gridBlockPreview;
|
||||
}
|
||||
|
||||
render() {
|
||||
const { isEditing } = this.state;
|
||||
const { attributes } = this.props;
|
||||
|
||||
if ( attributes.isPreview ) {
|
||||
return gridBlockPreview;
|
||||
}
|
||||
|
||||
return getSetting( 'hasTags', true ) ? (
|
||||
<>
|
||||
<BlockControls>
|
||||
<ToolbarGroup
|
||||
controls={ [
|
||||
{
|
||||
icon: 'edit',
|
||||
title: __(
|
||||
'Edit selected tags',
|
||||
'woo-gutenberg-products-block'
|
||||
),
|
||||
onClick: () =>
|
||||
isEditing
|
||||
? this.stopEditing()
|
||||
: this.startEditing(),
|
||||
isActive: isEditing,
|
||||
},
|
||||
] }
|
||||
/>
|
||||
</BlockControls>
|
||||
{ this.getInspectorControls() }
|
||||
{ isEditing ? this.renderEditMode() : this.renderViewMode() }
|
||||
</>
|
||||
) : (
|
||||
<Placeholder
|
||||
icon={
|
||||
<Icon icon={ tag } className="block-editor-block-icon" />
|
||||
}
|
||||
label={ __(
|
||||
'Products by Tag',
|
||||
'woo-gutenberg-products-block'
|
||||
) }
|
||||
className="wc-block-products-grid wc-block-product-tag"
|
||||
>
|
||||
{ __(
|
||||
'This block displays products from selected tags. To use it you first need to create products and assign tags to them.',
|
||||
'woo-gutenberg-products-block'
|
||||
) }
|
||||
</Placeholder>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ProductsByTagBlock.propTypes = {
|
||||
/**
|
||||
* The attributes for this block
|
||||
*/
|
||||
attributes: PropTypes.object.isRequired,
|
||||
/**
|
||||
* The register block name.
|
||||
*/
|
||||
name: PropTypes.string.isRequired,
|
||||
/**
|
||||
* A callback to update attributes
|
||||
*/
|
||||
setAttributes: PropTypes.func.isRequired,
|
||||
/**
|
||||
* From withSpokenMessages
|
||||
*/
|
||||
debouncedSpeak: PropTypes.func.isRequired,
|
||||
return getSetting( 'hasTags', true ) ? (
|
||||
<>
|
||||
<BlockControls>
|
||||
<ToolbarGroup
|
||||
controls={ [
|
||||
{
|
||||
icon: 'edit',
|
||||
title: __(
|
||||
'Edit selected tags',
|
||||
'woo-gutenberg-products-block'
|
||||
),
|
||||
onClick: () =>
|
||||
isEditing ? stopEditing() : startEditing(),
|
||||
isActive: isEditing,
|
||||
},
|
||||
] }
|
||||
/>
|
||||
</BlockControls>
|
||||
{ getInspectorControls() }
|
||||
{ isEditing ? renderEditMode() : renderViewMode() }
|
||||
</>
|
||||
) : (
|
||||
<Placeholder
|
||||
icon={ <Icon icon={ tag } className="block-editor-block-icon" /> }
|
||||
label={ __( 'Products by Tag', 'woo-gutenberg-products-block' ) }
|
||||
className="wc-block-products-grid wc-block-product-tag"
|
||||
>
|
||||
{ __(
|
||||
'This block displays products from selected tags. To use it you first need to create products and assign tags to them.',
|
||||
'woo-gutenberg-products-block'
|
||||
) }
|
||||
</Placeholder>
|
||||
);
|
||||
};
|
||||
|
||||
export default withSpokenMessages( ProductsByTagBlock );
|
|
@ -8,8 +8,9 @@ import { useBlockProps } from '@wordpress/block-editor';
|
|||
*/
|
||||
import Block from './block';
|
||||
import './editor.scss';
|
||||
import type { ProductsByTagBlockProps } from './types';
|
||||
|
||||
export const Edit = ( props: unknown ): JSX.Element => {
|
||||
export const Edit = ( props: ProductsByTagBlockProps ): JSX.Element => {
|
||||
const blockProps = useBlockProps();
|
||||
|
||||
return (
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
export interface ProductsByTagBlockProps {
|
||||
attributes: {
|
||||
tags: number[];
|
||||
tagOperator: string;
|
||||
columns: number;
|
||||
rows: number;
|
||||
alignButtons: boolean;
|
||||
contentVisibility: {
|
||||
title: boolean;
|
||||
price: boolean;
|
||||
rating: boolean;
|
||||
button: boolean;
|
||||
quantity?: boolean;
|
||||
description?: boolean;
|
||||
category?: boolean;
|
||||
image: boolean;
|
||||
};
|
||||
orderby: string;
|
||||
stockStatus: string[];
|
||||
isPreview: boolean;
|
||||
};
|
||||
name: string;
|
||||
setAttributes: (
|
||||
attributes: Partial< ProductsByTagBlockProps[ 'attributes' ] >
|
||||
) => void;
|
||||
debouncedSpeak: ( message: string ) => void;
|
||||
}
|
Loading…
Reference in New Issue