Skip to content

Commit

Permalink
Slideshow Block: refactor Edit component to function (#36805)
Browse files Browse the repository at this point in the history
  • Loading branch information
monsieur-z authored Apr 10, 2024
1 parent 5ce0120 commit 5b892af
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 120 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: other

Slideshow Block: refactor Edit component to function
220 changes: 100 additions & 120 deletions projects/plugins/jetpack/extensions/blocks/slideshow/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,16 @@ import { DropZone, FormFileUpload, withNotices } from '@wordpress/components';
import { compose } from '@wordpress/compose';
import { withDispatch, withSelect } from '@wordpress/data';
import { mediaUpload } from '@wordpress/editor';
import { Component, Fragment } from '@wordpress/element';
import { useEffect } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import { filter, get, map, pick } from 'lodash';
import { get, map, pick } from 'lodash';
import metadata from './block.json';
import { PanelControls, ToolbarControls } from './controls';
import Slideshow from './slideshow';

import './editor.scss';

const ALLOWED_MEDIA_TYPES = [ 'image' ];
const icon = getBlockIconComponent( metadata );

export const pickRelevantMediaFiles = ( image, sizeSlug ) => {
const imageProps = pick( image, [ 'alt', 'id', 'link', 'caption' ] );
Expand All @@ -26,148 +25,107 @@ export const pickRelevantMediaFiles = ( image, sizeSlug ) => {
return imageProps;
};

export class SlideshowEdit extends Component {
constructor() {
super( ...arguments );
this.state = {
selectedImage: null,
};
}
componentDidMount() {
const { ids, sizeSlug } = this.props.attributes;
if ( ! sizeSlug ) {
// To improve the performance, we use large size images by default except for blocks inserted before the
// image size attribute was added, since they were loading full size images. The presence or lack of images
// in a block determines when it has been inserted (before or after we added the image size attribute),
// given that now it is not possible to have a block with images and no size.
this.setAttributes( { sizeSlug: ids.length ? 'full' : 'large' } );
}
}
setAttributes( attributes ) {
if ( attributes.ids ) {
throw new Error(
'The "ids" attribute should not be changed directly. It is managed automatically when "images" attribute changes'
);
}
export const SlideshowEdit = ( {
attributes,
setAttributes,
className,
isSelected,
noticeOperations,
noticeUI,
lockPostSaving,
unlockPostSaving,
imageSizes,
resizedImages,
} ) => {
const { align, autoplay, delay, effect, images, sizeSlug, ids } = attributes;

if ( attributes.images ) {
attributes = {
...attributes,
ids: attributes.images.map( ( { id } ) => parseInt( id, 10 ) ),
};
}

this.props.setAttributes( attributes );
}
onSelectImages = images => {
const { sizeSlug } = this.props.attributes;
const mapped = images.map( image => pickRelevantMediaFiles( image, sizeSlug ) );
this.setAttributes( {
images: mapped,
const setImages = imgs => {
setAttributes( {
images: imgs,
ids: imgs.map( ( { id } ) => parseInt( id, 10 ) ),
} );
};
onRemoveImage = index => {
return () => {
const images = filter( this.props.attributes.images, ( img, i ) => index !== i );
this.setState( { selectedImage: null } );
this.setAttributes( { images } );
};
};
addFiles = files => {
const currentImages = this.props.attributes.images || [];
const sizeSlug = this.props.attributes.sizeSlug;
const { lockPostSaving, unlockPostSaving, noticeOperations } = this.props;

const onSelectImages = imgs =>
setImages( imgs.map( image => pickRelevantMediaFiles( image, sizeSlug ) ) );

const addFiles = files => {
const lockName = 'slideshowBlockLock';

lockPostSaving( lockName );
mediaUpload( {
allowedTypes: ALLOWED_MEDIA_TYPES,
filesList: files,
onFileChange: images => {
const imagesNormalized = images.map( image => pickRelevantMediaFiles( image, sizeSlug ) );
this.setAttributes( {
images: [ ...currentImages, ...imagesNormalized ],
} );
onFileChange: imgs => {
const imagesNormalized = imgs.map( image => pickRelevantMediaFiles( image, sizeSlug ) );

setImages( [ ...( images || [] ), ...imagesNormalized ] );

if ( ! imagesNormalized.every( image => isBlobURL( image.url ) ) ) {
unlockPostSaving( lockName );
}
},
onError: noticeOperations.createErrorNotice,
} );
};
uploadFromFiles = event => this.addFiles( event.target.files );
getImageSizeOptions() {
const { imageSizes } = this.props;
return map( imageSizes, ( { name, slug } ) => ( { value: slug, label: name } ) );
}
updateImagesSize = sizeSlug => {
const { images } = this.props.attributes;
const { resizedImages } = this.props;

const uploadFromFiles = event => addFiles( event.target.files );

const getImageSizeOptions = () =>
map( imageSizes, ( { name, slug } ) => ( { value: slug, label: name } ) );

const updateImagesSize = slug => {
const updatedImages = images.map( image => {
const resizedImage = resizedImages.find(
( { id } ) => parseInt( id, 10 ) === parseInt( image.id, 10 )
);
const url = get( resizedImage, [ 'sizes', sizeSlug, 'source_url' ] );
const url = get( resizedImage, [ 'sizes', slug, 'source_url' ] );
return {
...image,
...( url && { url } ),
};
} );

this.setAttributes( { images: updatedImages, sizeSlug } );
setImages( updatedImages );
setAttributes( { sizeSlug: slug } );
};
render() {
const { attributes, className, isSelected, noticeOperations, noticeUI } = this.props;
const { align, autoplay, delay, effect, images } = attributes;

const imageSizeOptions = this.getImageSizeOptions();
const controls = (
<>
<InspectorControls>
<PanelControls
attributes={ attributes }
imageSizeOptions={ imageSizeOptions }
onChangeImageSize={ this.updateImagesSize }
setAttributes={ attrs => this.setAttributes( attrs ) }
/>
</InspectorControls>
<BlockControls>
<ToolbarControls
allowedMediaTypes={ ALLOWED_MEDIA_TYPES }
attributes={ attributes }
onSelectImages={ this.onSelectImages }
/>
</BlockControls>
</>
);

if ( images.length === 0 ) {
return (
<Fragment>
{ controls }
<MediaPlaceholder
icon={ icon }
className={ className }
labels={ {
title: __( 'Slideshow', 'jetpack' ),
instructions: __(
'Drag images, upload new ones or select files from your library.',
'jetpack'
),
} }
onSelect={ this.onSelectImages }
accept="image/*"
allowedTypes={ ALLOWED_MEDIA_TYPES }
multiple
notices={ noticeUI }
onError={ noticeOperations.createErrorNotice }
/>
</Fragment>
);
useEffect( () => {
if ( ! sizeSlug ) {
// To improve the performance, we use large size images by default except for blocks inserted before the
// image size attribute was added, since they were loading full size images. The presence or lack of images
// in a block determines when it has been inserted (before or after we added the image size attribute),
// given that now it is not possible to have a block with images and no size.
setAttributes( { sizeSlug: ids.length ? 'full' : 'large' } );
}
return (
<Fragment>
{ controls }
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [] );

let content;

if ( images.length === 0 ) {
content = (
<MediaPlaceholder
icon={ getBlockIconComponent( metadata ) }
className={ className }
labels={ {
title: __( 'Slideshow', 'jetpack' ),
instructions: __(
'Drag images, upload new ones or select files from your library.',
'jetpack'
),
} }
onSelect={ onSelectImages }
accept="image/*"
allowedTypes={ ALLOWED_MEDIA_TYPES }
multiple
notices={ noticeUI }
onError={ noticeOperations.createErrorNotice }
/>
);
} else {
content = (
<>
{ noticeUI }
<Slideshow
align={ align }
Expand All @@ -178,24 +136,46 @@ export class SlideshowEdit extends Component {
images={ images }
onError={ noticeOperations.createErrorNotice }
/>
<DropZone onFilesDrop={ this.addFiles } />
<DropZone onFilesDrop={ addFiles } />
{ isSelected && (
<div className="wp-block-jetpack-slideshow__add-item">
<FormFileUpload
multiple
className="wp-block-jetpack-slideshow__add-item-button"
onChange={ this.uploadFromFiles }
onChange={ uploadFromFiles }
accept="image/*"
icon="insert"
>
{ __( 'Upload an image', 'jetpack' ) }
</FormFileUpload>
</div>
) }
</Fragment>
</>
);
}
}

return (
<>
<InspectorControls>
<PanelControls
attributes={ attributes }
imageSizeOptions={ getImageSizeOptions() }
onChangeImageSize={ updateImagesSize }
setAttributes={ setAttributes }
/>
</InspectorControls>
<BlockControls>
<ToolbarControls
allowedMediaTypes={ ALLOWED_MEDIA_TYPES }
attributes={ attributes }
onSelectImages={ onSelectImages }
/>
</BlockControls>
{ content }
</>
);
};

export default compose(
withSelect( ( select, props ) => {
const imageSizes = select( 'core/editor' ).getEditorSettings().imageSizes;
Expand Down

0 comments on commit 5b892af

Please sign in to comment.