initial commit

This commit is contained in:
2021-12-10 12:03:04 +00:00
commit c46c7ddbf0
3643 changed files with 582794 additions and 0 deletions

View File

@ -0,0 +1,23 @@
/**
* External dependencies
*/
import ErrorPlaceholder from '@woocommerce/editor-components/error-placeholder';
/**
* Shown when there is an API error getting a product.
*
* @param {Object} props Incoming props for the component.
* @param {string} props.error
* @param {boolean} props.isLoading
* @param {function(any):any} props.getProduct
*/
const ApiError = ( { error, isLoading, getProduct } ) => (
<ErrorPlaceholder
className="wc-block-single-product-error"
error={ error }
isLoading={ isLoading }
onRetry={ getProduct }
/>
);
export default ApiError;

View File

@ -0,0 +1,32 @@
/**
* External dependencies
*/
import { __ } from '@wordpress/i18n';
import { BlockControls } from '@wordpress/block-editor';
import { ToolbarGroup } from '@wordpress/components';
/**
* Adds controls to the editor toolbar.
*
* @param {Object} props Incoming props for the component.
* @param {boolean} props.isEditing
* @param {function(boolean):any} props.setIsEditing
*/
const EditorBlockControls = ( { isEditing, setIsEditing } ) => {
return (
<BlockControls>
<ToolbarGroup
controls={ [
{
icon: 'edit',
title: __( 'Edit', 'woocommerce' ),
onClick: () => setIsEditing( ! isEditing ),
isActive: isEditing,
},
] }
/>
</BlockControls>
);
};
export default EditorBlockControls;

View File

@ -0,0 +1,18 @@
.wc-block-single-product__selection {
width: 100%;
}
.wc-block-single-product__reset-layout {
padding: 0;
svg {
margin-right: 4px;
}
}
.wc-block-single-product__edit-card {
padding: 16px;
border-top: 1px solid $gray-200;
.wc-block-single-product__edit-card-title {
margin: 0 0 $gap;
}
}

View File

@ -0,0 +1,126 @@
/**
* External dependencies
*/
import { __ } from '@wordpress/i18n';
import { useState } from '@wordpress/element';
import { Placeholder, Button, PanelBody } from '@wordpress/components';
import { withProduct } from '@woocommerce/block-hocs';
import BlockErrorBoundary from '@woocommerce/base-components/block-error-boundary';
import EditProductLink from '@woocommerce/editor-components/edit-product-link';
import { singleProductBlockPreview } from '@woocommerce/resource-previews';
import { InspectorControls } from '@wordpress/block-editor';
/**
* Internal dependencies
*/
import './editor.scss';
import ApiError from './api-error';
import SharedProductControl from './shared-product-control';
import EditorBlockControls from './editor-block-controls';
import LayoutEditor from './layout-editor';
import { BLOCK_TITLE, BLOCK_ICON, BLOCK_DESCRIPTION } from '../constants';
/**
* Component to handle edit mode of the "Single Product Block".
*
* @param {Object} props Incoming props for the component.
* @param {string} props.className
* @param {Object} props.attributes Incoming block attributes.
* @param {function(any):any} props.setAttributes Setter for block attributes.
* @param {string} props.error
* @param {function(any):any} props.getProduct
* @param {Object} props.product
* @param {boolean} props.isLoading
* @param {string} props.clientId
*/
const Editor = ( {
className,
attributes,
setAttributes,
error,
getProduct,
product,
isLoading,
clientId,
} ) => {
const { productId, isPreview } = attributes;
const [ isEditing, setIsEditing ] = useState( ! productId );
if ( isPreview ) {
return singleProductBlockPreview;
}
if ( error ) {
return (
<ApiError
error={ error }
isLoading={ isLoading }
getProduct={ getProduct }
/>
);
}
return (
<div className={ className }>
<BlockErrorBoundary
header={ __(
'Single Product Block Error',
'woocommerce'
) }
>
<EditorBlockControls
setIsEditing={ setIsEditing }
isEditing={ isEditing }
/>
{ isEditing ? (
<Placeholder
icon={ BLOCK_ICON }
label={ BLOCK_TITLE }
className="wc-block-single-product"
>
{ BLOCK_DESCRIPTION }
<div className="wc-block-single-product__selection">
<SharedProductControl
attributes={ attributes }
setAttributes={ setAttributes }
/>
<Button
isSecondary
onClick={ () => {
setIsEditing( false );
} }
>
{ __( 'Done', 'woocommerce' ) }
</Button>
</div>
</Placeholder>
) : (
<>
<InspectorControls>
<PanelBody
title={ __(
'Product',
'woocommerce'
) }
initialOpen={ false }
>
<SharedProductControl
attributes={ attributes }
setAttributes={ setAttributes }
/>
</PanelBody>
</InspectorControls>
<EditProductLink productId={ productId } />
<LayoutEditor
clientId={ clientId }
product={ product }
isLoading={ isLoading }
/>
</>
) }
</BlockErrorBoundary>
</div>
);
};
export default withProduct( Editor );

View File

@ -0,0 +1,89 @@
/**
* External dependencies
*/
import { __ } from '@wordpress/i18n';
import { useCallback } from '@wordpress/element';
import { useDispatch } from '@wordpress/data';
import { InnerBlocks, InspectorControls } from '@wordpress/block-editor';
import {
InnerBlockLayoutContextProvider,
ProductDataContextProvider,
} from '@woocommerce/shared-context';
import { createBlocksFromTemplate } from '@woocommerce/atomic-utils';
import { PanelBody, Button } from '@wordpress/components';
import { Icon, restore } from '@woocommerce/icons';
/**
* Internal dependencies
*/
import {
BLOCK_NAME,
DEFAULT_INNER_BLOCKS,
ALLOWED_INNER_BLOCKS,
} from '../constants';
/**
* Component to handle edit mode of the "Single Product Block".
*
* @param {Object} props Incoming props for the component.
* @param {boolean} props.isLoading
* @param {Object} props.product
* @param {string} props.clientId
*/
const LayoutEditor = ( { isLoading, product, clientId } ) => {
const baseClassName = 'wc-block-single-product wc-block-layout';
const { replaceInnerBlocks } = useDispatch( 'core/block-editor' );
const resetInnerBlocks = useCallback( () => {
replaceInnerBlocks(
clientId,
createBlocksFromTemplate( DEFAULT_INNER_BLOCKS ),
false
);
}, [ clientId, replaceInnerBlocks ] );
return (
<InnerBlockLayoutContextProvider
parentName={ BLOCK_NAME }
parentClassName={ baseClassName }
>
<ProductDataContextProvider
product={ product }
isLoading={ isLoading }
>
<InspectorControls>
<PanelBody
title={ __( 'Layout', 'woocommerce' ) }
initialOpen={ true }
>
<Button
label={ __(
'Reset layout to default',
'woocommerce'
) }
onClick={ resetInnerBlocks }
isTertiary
className="wc-block-single-product__reset-layout"
>
<Icon srcElement={ restore } />{ ' ' }
{ __(
'Reset layout',
'woocommerce'
) }
</Button>
</PanelBody>
</InspectorControls>
<div className={ baseClassName }>
<InnerBlocks
template={ DEFAULT_INNER_BLOCKS }
allowedBlocks={ ALLOWED_INNER_BLOCKS }
templateLock={ false }
renderAppender={ false }
/>
</div>
</ProductDataContextProvider>
</InnerBlockLayoutContextProvider>
);
};
export default LayoutEditor;

View File

@ -0,0 +1,26 @@
/**
* External dependencies
*/
import ProductControl from '@woocommerce/editor-components/product-control';
/**
* Allows a product to be selected for display.
*
* @param {Object} props Incoming props for the component.
* @param {Object} props.attributes Incoming block attributes.
* @param {function(any):any} props.setAttributes Setter for block attributes.
*/
const SharedProductControl = ( { attributes, setAttributes } ) => (
<ProductControl
selected={ attributes.productId || 0 }
showVariations
onChange={ ( value = [] ) => {
const id = value[ 0 ] ? value[ 0 ].id : 0;
setAttributes( {
productId: id,
} );
} }
/>
);
export default SharedProductControl;