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

Commit

Permalink
Add media controls to the Featured Product block (#6348)
Browse files Browse the repository at this point in the history
This PR adds image editing controls to the Featured Product block. In particular, user can now:

* Rotate the image
* Crop the image
* Change the aspect ratio of the image
* Zoom the image

Each edit gets saved in the database as a new image.
  • Loading branch information
sunyatasattva authored May 3, 2022
1 parent f548e11 commit c72993d
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 10 deletions.
85 changes: 75 additions & 10 deletions assets/js/blocks/featured-product/block.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
/**
* External dependencies
*/
import { useCallback, useState } from 'react';
import { useCallback, useEffect, useState } from 'react';
import { __ } from '@wordpress/i18n';
import {
AlignmentToolbar,
Expand All @@ -13,6 +13,8 @@ import {
MediaReplaceFlow,
RichText,
__experimentalGetSpacingClassesAndStyles as getSpacingClassesAndStyles,
__experimentalImageEditingProvider as ImageEditingProvider,
__experimentalImageEditor as ImageEditor,
__experimentalPanelColorGradientSettings as PanelColorGradientSettings,
__experimentalUseGradient as useGradient,
} from '@wordpress/block-editor';
Expand All @@ -28,6 +30,7 @@ import {
Spinner,
TextareaControl,
ToggleControl,
ToolbarButton,
ToolbarGroup,
withSpokenMessages,
__experimentalToggleGroupControl as ToggleGroupControl,
Expand All @@ -42,7 +45,7 @@ import ProductControl from '@woocommerce/editor-components/product-control';
import ErrorPlaceholder from '@woocommerce/editor-components/error-placeholder';
import TextToolbarButton from '@woocommerce/editor-components/text-toolbar-button';
import { withProduct } from '@woocommerce/block-hocs';
import { Icon, starEmpty } from '@wordpress/icons';
import { crop, Icon, starEmpty } from '@wordpress/icons';

/**
* Internal dependencies
Expand All @@ -54,6 +57,11 @@ import {
} from '../../utils/products';
import { useThrottle } from '../../utils/useThrottle';

const DEFAULT_EDITOR_SIZE = {
height: 500,
width: 500,
};

export const ConstrainedResizable = ( {
className = '',
onResize,
Expand Down Expand Up @@ -112,10 +120,18 @@ const FeaturedProduct = ( {
setAttributes,
triggerUrlUpdate = () => void null,
} ) => {
const { mediaId, mediaSrc } = attributes;

const [ isEditingImage, setIsEditingImage ] = useState( false );
const [ backgroundImageSize, setBackgroundImageSize ] = useState( {} );
const { setGradient } = useGradient( {
gradientAttribute: 'overlayGradient',
customGradientAttribute: 'overlayGradient',
} );

const backgroundImageSrc = mediaSrc || getImageSrcFromProduct( product );
const backgroundImageId = mediaId || getImageIdFromProduct( product );

const onResize = useCallback(
( _event, _direction, elt ) => {
setAttributes( { minHeight: parseInt( elt.style.height, 10 ) } );
Expand All @@ -132,6 +148,10 @@ const FeaturedProduct = ( {
/>
);

useEffect( () => {
setIsEditingImage( false );
}, [ isSelected ] );

const renderEditMode = () => {
const onDone = () => {
setAttributes( { editMode: false } );
Expand Down Expand Up @@ -182,8 +202,7 @@ const FeaturedProduct = ( {
};

const getBlockControls = () => {
const { contentAlign, editMode, mediaSrc } = attributes;
const mediaId = attributes.mediaId || getImageIdFromProduct( product );
const { contentAlign, editMode } = attributes;

return (
<BlockControls>
Expand All @@ -194,8 +213,18 @@ const FeaturedProduct = ( {
} }
/>
<ToolbarGroup>
{ ! isEditingImage && (
<ToolbarButton
onClick={ () => setIsEditingImage( true ) }
icon={ crop }
label={ __(
'Edit product image',
'woo-gutenberg-products-block'
) }
/>
) }
<MediaReplaceFlow
mediaId={ mediaId }
mediaId={ backgroundImageId }
mediaURL={ mediaSrc }
accept="image/*"
onSelect={ ( media ) => {
Expand All @@ -206,7 +235,7 @@ const FeaturedProduct = ( {
} }
allowedTypes={ [ 'image' ] }
/>
{ mediaId && mediaSrc ? (
{ backgroundImageId && mediaSrc ? (
<TextToolbarButton
onClick={ () =>
setAttributes( { mediaId: 0, mediaSrc: '' } )
Expand Down Expand Up @@ -426,7 +455,6 @@ const FeaturedProduct = ( {
dimRatio,
focalPoint,
imageFit,
mediaSrc,
minHeight,
overlayColor,
overlayGradient,
Expand Down Expand Up @@ -456,9 +484,6 @@ const FeaturedProduct = ( {
minHeight,
};

const backgroundImageSrc =
mediaSrc || getImageSrcFromProduct( product );

const backgroundImageStyle = {
...calculateBackgroundImagePosition( focalPoint ),
objectFit: imageFit,
Expand Down Expand Up @@ -491,6 +516,12 @@ const FeaturedProduct = ( {
className="wc-block-featured-product__background-image"
src={ backgroundImageSrc }
style={ backgroundImageStyle }
onLoad={ ( e ) => {
setBackgroundImageSize( {
height: e.target?.naturalHeight,
width: e.target?.naturalWidth,
} );
} }
/>
<h2
className="wc-block-featured-product__title"
Expand Down Expand Up @@ -606,6 +637,40 @@ const FeaturedProduct = ( {
return renderEditMode();
}

if ( isEditingImage ) {
return (
<>
<ImageEditingProvider
id={ backgroundImageId }
url={ backgroundImageSrc }
naturalHeight={
backgroundImageSize.height || DEFAULT_EDITOR_SIZE.height
}
naturalWidth={
backgroundImageSize.width || DEFAULT_EDITOR_SIZE.width
}
onSaveImage={ ( { id, url } ) => {
setAttributes( { mediaId: id, mediaSrc: url } );
} }
isEditing={ isEditingImage }
onFinishEditing={ () => setIsEditingImage( false ) }
>
<ImageEditor
url={ backgroundImageSrc }
height={
backgroundImageSize.height ||
DEFAULT_EDITOR_SIZE.height
}
width={
backgroundImageSize.width ||
DEFAULT_EDITOR_SIZE.width
}
/>
</ImageEditingProvider>
</>
);
}

return (
<>
{ getBlockControls() }
Expand Down
15 changes: 15 additions & 0 deletions assets/js/blocks/featured-product/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,21 @@
height: auto !important;
}
}

// Applying image edits
.is-applying {
.components-spinner {
position: absolute;
top: 50%;
left: 50%;
margin-top: -9px;
margin-left: -9px;
}

img {
opacity: 0.3;
}
}
}

.wc-block-featured-product {
Expand Down

0 comments on commit c72993d

Please sign in to comment.