From e81ad0c5e8f680ce081fcbedf2e9affff8c083a4 Mon Sep 17 00:00:00 2001 From: Siddharth Thevaril Date: Sat, 17 Jun 2023 00:43:58 +0530 Subject: [PATCH] move from class to functional component --- .../js/blocks/products/all-products/edit.tsx | 204 ++++++++---------- .../js/blocks/products/all-products/index.js | 8 +- .../js/blocks/products/all-products/save.js | 2 +- 3 files changed, 91 insertions(+), 123 deletions(-) diff --git a/assets/js/blocks/products/all-products/edit.tsx b/assets/js/blocks/products/all-products/edit.tsx index cce7e399606..58b19301e76 100644 --- a/assets/js/blocks/products/all-products/edit.tsx +++ b/assets/js/blocks/products/all-products/edit.tsx @@ -8,18 +8,17 @@ import { InnerBlocks, InspectorControls, } from '@wordpress/block-editor'; -import { withDispatch, withSelect } from '@wordpress/data'; +import { useSelect, useDispatch } from '@wordpress/data'; import { PanelBody, - withSpokenMessages, Placeholder, Button, ToolbarGroup, Disabled, Tip, } from '@wordpress/components'; -import { Component } from '@wordpress/element'; -import { compose } from '@wordpress/compose'; +import { useState, useEffect } from '@wordpress/element'; +import { useDebounce } from '@wordpress/compose'; import { Icon, grid } from '@wordpress/icons'; import GridLayoutControl from '@woocommerce/editor-components/grid-layout-control'; import { @@ -30,6 +29,7 @@ import { getBlockMap } from '@woocommerce/atomic-utils'; import { previewProducts } from '@woocommerce/resource-previews'; import { getSetting } from '@woocommerce/settings'; import { blocksConfig } from '@woocommerce/block-settings'; +import { speak } from '@wordpress/a11y'; /** * Internal dependencies @@ -47,63 +47,58 @@ import { getSharedContentControls, getSharedListControls } from '../edit'; import Block from './block'; import './editor.scss'; -type EditorAttributes = { +type Attributes = { columns: number; rows: number; alignButtons: boolean; - contentVisibility: object; - orderby: string; - layoutConfig: Array< object >; - isPreview: boolean; + layoutConfig: [ string, object? ][]; }; -interface EditorProps { - block: BlockInstance; - attributes: EditorAttributes; - debouncedSpeak: ( label: string ) => void; +type Props = { + contentVisibility: number; + orderby: number; + isPreview: number; + clientId: string; + attributes: Attributes; setAttributes: ( attributes: Record< string, unknown > ) => void; - replaceInnerBlocks: ( - rootClientId: string, - blocks: BlockInstance[], - updateSelection?: boolean - ) => void; -} +}; -interface EditorState { - isEditing: boolean; - innerBlocks: BlockInstance[]; -} +export const Edit = ( props: Props ): JSX.Element => { + const [ isEditing, setIsEditing ] = useState< boolean >( false ); + const [ , setInnerBlocks ] = useState< BlockInstance[] | boolean >( false ); + const blockMap = getBlockMap( 'woocommerce/all-products' ); -/** - * Component to handle edit mode of "All Products". - */ -class Editor extends Component< EditorProps, EditorState > { - state = { - isEditing: false, - innerBlocks: [], - }; + const { clientId, attributes, setAttributes } = props; - blockMap = getBlockMap( 'woocommerce/all-products' ); + const { columns, rows, alignButtons, layoutConfig } = attributes; - componentDidMount = (): void => { - const { block } = this.props; - this.setState( { innerBlocks: block.innerBlocks } ); - }; + const { innerBlocks } = useSelect( ( select ) => { + const { getBlock } = select( 'core/block-editor' ); + const block = getBlock( clientId ); + return { + innerBlocks: block ? block.innerBlocks : [], + }; + } ); + + useEffect( () => { + setInnerBlocks( innerBlocks ); + }, [] ); + + const { replaceInnerBlocks } = useDispatch( 'core/block-editor' ); + const debouncedSpeak = useDebounce( speak ); - getTitle = (): string => { + const getTitle = (): string => { return __( 'All Products', 'woo-gutenberg-products-block' ); }; - getIcon = (): JSX.Element => { + const getIcon = (): JSX.Element => { return ; }; - togglePreview = (): void => { - const { debouncedSpeak } = this.props; + const togglePreview = (): void => { + setIsEditing( ! isEditing ); - this.setState( { isEditing: ! this.state.isEditing } ); - - if ( ! this.state.isEditing ) { + if ( ! isEditing ) { debouncedSpeak( __( 'Showing All Products block preview.', @@ -113,10 +108,7 @@ class Editor extends Component< EditorProps, EditorState > { } }; - getInspectorControls = (): JSX.Element => { - const { attributes, setAttributes } = this.props; - const { columns, rows, alignButtons } = attributes; - + const getInspectorControls = (): JSX.Element => { return ( { 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={ getSetting( 'min_columns', 1 ) as number } + maxColumns={ getSetting( 'max_columns', 6 ) as number } + minRows={ getSetting( 'min_rows', 1 ) as number } + maxRows={ getSetting( 'max_rows', 6 ) as number } /> { ); }; - getBlockControls = (): JSX.Element => { - const { isEditing } = this.state; - + const getBlockControls = (): JSX.Element => { return ( { 'Edit the layout of each product', 'woo-gutenberg-products-block' ), - onClick: () => this.togglePreview(), + onClick: () => togglePreview(), isActive: isEditing, }, ] } @@ -172,47 +162,47 @@ class Editor extends Component< EditorProps, EditorState > { ); }; - renderEditMode = () => { + const renderEditMode = () => { const onDone = () => { - const { block, setAttributes } = this.props; setAttributes( { - layoutConfig: getProductLayoutConfig( block.innerBlocks ), + layoutConfig: getProductLayoutConfig( innerBlocks ), } ); - this.setState( { innerBlocks: block.innerBlocks } ); - this.togglePreview(); + setInnerBlocks( innerBlocks ); + togglePreview(); }; const onCancel = () => { - const { block, replaceInnerBlocks } = this.props; - const { innerBlocks } = this.state; - replaceInnerBlocks( block.clientId, innerBlocks, false ); - this.togglePreview(); + replaceInnerBlocks( clientId, innerBlocks, false ); + togglePreview(); }; const onReset = () => { - const { block, replaceInnerBlocks } = this.props; const newBlocks: BlockInstance[] = []; - DEFAULT_PRODUCT_LIST_LAYOUT.map( ( [ name, attributes ] ) => { - newBlocks.push( createBlock( name, attributes ) ); + DEFAULT_PRODUCT_LIST_LAYOUT.map( ( [ name, blockAttributes ] ) => { + newBlocks.push( createBlock( name, blockAttributes ) ); return true; } ); - replaceInnerBlocks( block.clientId, newBlocks, false ); - this.setState( { innerBlocks: block.innerBlocks } ); + replaceInnerBlocks( clientId, newBlocks, false ); + setInnerBlocks( innerBlocks ); }; - const InnerBlockProps = { - template: this.props.attributes.layoutConfig, + const InnerBlockProps: { + template: [ string, object? ][]; + templateLock: boolean; + allowedBlocks: Array< string >; + renderAppender?: undefined | boolean; + } = { + template: layoutConfig, templateLock: false, - allowedBlocks: Object.keys( this.blockMap ), - renderAppender: true, + allowedBlocks: Object.keys( blockMap ), }; - if ( this.props.attributes.layoutConfig.length !== 0 ) { + if ( layoutConfig.length !== 0 ) { InnerBlockProps.renderAppender = false; } return ( - + { __( 'Display all products from your store as a grid.', 'woo-gutenberg-products-block' @@ -277,12 +267,10 @@ class Editor extends Component< EditorProps, EditorState > { ); }; - renderViewMode = () => { - const { attributes } = this.props; - const { layoutConfig } = attributes; + const renderViewMode = () => { const hasContent = layoutConfig && layoutConfig.length !== 0; - const blockTitle = this.getTitle(); - const blockIcon = this.getIcon(); + const blockTitle = getTitle(); + const blockIcon = getIcon(); if ( ! hasContent ) { return renderHiddenContentPlaceholder( blockTitle, blockIcon ); @@ -296,43 +284,23 @@ class Editor extends Component< EditorProps, EditorState > { ); }; - render = () => { - const { attributes } = this.props; - const { isEditing } = this.state; - const blockTitle = this.getTitle(); - const blockIcon = this.getIcon(); + const blockTitle = getTitle(); + const blockIcon = getIcon(); - if ( blocksConfig.productCount === 0 ) { - return renderNoProductsPlaceholder( blockTitle, blockIcon ); - } - - return ( -
- { this.getBlockControls() } - { this.getInspectorControls() } - { isEditing ? this.renderEditMode() : this.renderViewMode() } -
- ); - }; -} + if ( blocksConfig.productCount === 0 ) { + return renderNoProductsPlaceholder( blockTitle, blockIcon ); + } -export default compose( - withSpokenMessages, - withSelect( ( select, { clientId } ) => { - const { getBlock } = select( 'core/block-editor' ); - return { - block: getBlock( clientId ), - }; - } ), - withDispatch( ( dispatch ) => { - const { replaceInnerBlocks } = dispatch( 'core/block-editor' ); - return { - replaceInnerBlocks, - }; - } ) -)( Editor ); + return ( +
+ { getBlockControls() } + { getInspectorControls() } + { isEditing ? renderEditMode() : renderViewMode() } +
+ ); +}; diff --git a/assets/js/blocks/products/all-products/index.js b/assets/js/blocks/products/all-products/index.js index 659c21724a9..3636e7baf7b 100644 --- a/assets/js/blocks/products/all-products/index.js +++ b/assets/js/blocks/products/all-products/index.js @@ -10,8 +10,8 @@ import '@woocommerce/atomic-blocks'; */ import metadata from './block.json'; import deprecated from './deprecated'; -import edit from './edit'; -import save from './save'; +import { Edit } from './edit'; +import Save from './save'; import defaults from './defaults'; const { name } = metadata; @@ -26,9 +26,9 @@ const settings = { /> ), }, - edit, + edit: Edit, // Save the props to post content. - save, + save: Save, deprecated, defaults, }; diff --git a/assets/js/blocks/products/all-products/save.js b/assets/js/blocks/products/all-products/save.js index 108ae322d63..e9683b910ae 100644 --- a/assets/js/blocks/products/all-products/save.js +++ b/assets/js/blocks/products/all-products/save.js @@ -8,7 +8,7 @@ import { InnerBlocks } from '@wordpress/block-editor'; */ import { getBlockClassName } from '../utils.js'; -export default function save( { attributes } ) { +export default function Save( { attributes } ) { const dataAttributes = {}; Object.keys( attributes ) .sort()