From 4a037ed84107e107fa720fcb29349a384bdb5905 Mon Sep 17 00:00:00 2001 From: Jorge Date: Tue, 27 Nov 2018 15:37:42 +0000 Subject: [PATCH 1/6] Gallery Block: Add Media Library buttons to the upload new image area; Media Upload: Allow galleries to open in the library frame. --- .../src/components/media-placeholder/index.js | 127 +++++++++++++----- .../components/media-placeholder/style.scss | 20 +++ .../src/components/media-upload/README.md | 19 +++ packages/block-library/src/gallery/edit.js | 88 ++++-------- .../block-library/src/gallery/editor.scss | 36 ----- packages/block-library/src/gallery/style.scss | 8 -- .../hooks/components/media-upload/index.js | 12 +- 7 files changed, 169 insertions(+), 141 deletions(-) diff --git a/packages/block-editor/src/components/media-placeholder/index.js b/packages/block-editor/src/components/media-placeholder/index.js index d972aeca06bd7..bdfdb7a45dc4d 100644 --- a/packages/block-editor/src/components/media-placeholder/index.js +++ b/packages/block-editor/src/components/media-placeholder/index.js @@ -1,7 +1,14 @@ /** * External dependencies */ -import { every, get, noop, startsWith, defaultTo } from 'lodash'; +import { + defaultTo, + every, + get, + isArray, + noop, + startsWith, +} from 'lodash'; import classnames from 'classnames'; /** @@ -103,8 +110,28 @@ export class MediaPlaceholder extends Component { } onFilesUpload( files ) { - const { onSelect, multiple, onError, allowedTypes, mediaUpload } = this.props; - const setMedia = multiple ? onSelect : ( [ media ] ) => onSelect( media ); + const { + addToGallery, + allowedTypes, + mediaUpload, + multiple, + onError, + onSelect, + value = [], + } = this.props; + let setMedia; + if ( multiple ) { + if ( addToGallery ) { + const currentValue = value; + setMedia = ( newMedia ) => { + onSelect( currentValue.concat( newMedia ) ); + }; + } else { + setMedia = onSelect; + } + } else { + setMedia = ( [ media ] ) => onSelect( media ); + } mediaUpload( { allowedTypes, filesList: files, @@ -124,18 +151,21 @@ export class MediaPlaceholder extends Component { render() { const { accept, - icon, + addToGallery, + allowedTypes = [], className, + dropZoneUIOnly, + hasUploadPermissions, + icon, + isAppender, labels = {}, - onSelect, - value = {}, - onSelectURL, - onHTMLDrop = noop, + mediaUpload, multiple = false, notices, - allowedTypes = [], - hasUploadPermissions, - mediaUpload, + onHTMLDrop = noop, + onSelect, + onSelectURL, + value = {}, } = this.props; const { @@ -143,20 +173,20 @@ export class MediaPlaceholder extends Component { src, } = this.state; - let instructions = labels.instructions || ''; - let title = labels.title || ''; + let instructions = labels.instructions; + let title = labels.title; if ( ! hasUploadPermissions && ! onSelectURL ) { instructions = __( 'To edit this block, you need permission to upload media.' ); } - if ( ! instructions || ! title ) { + if ( instructions === undefined || title === undefined ) { const isOneType = 1 === allowedTypes.length; const isAudio = isOneType && 'audio' === allowedTypes[ 0 ]; const isImage = isOneType && 'image' === allowedTypes[ 0 ]; const isVideo = isOneType && 'video' === allowedTypes[ 0 ]; - if ( ! instructions ) { + if ( instructions === undefined ) { if ( hasUploadPermissions ) { instructions = __( 'Drag a media file, upload a new one or select a file from your library.' ); @@ -180,7 +210,7 @@ export class MediaPlaceholder extends Component { } } - if ( ! title ) { + if ( title === undefined ) { title = __( 'Media' ); if ( isAudio ) { @@ -193,24 +223,47 @@ export class MediaPlaceholder extends Component { } } + const dropZone = ( + + ); + + if ( dropZoneUIOnly ) { + return ( + + { dropZone } + + ); + } + return ( { !! mediaUpload && ( - + { dropZone } ) } ( - - ) } + value={ + isArray( value ) ? + value.map( ( { id } ) => id ) : + value.id + } + render={ ( { open } ) => { + return ( + + ); + } } /> { onSelectURL && ( diff --git a/packages/block-editor/src/components/media-placeholder/style.scss b/packages/block-editor/src/components/media-placeholder/style.scss index 7cc50c523885a..15ee92a684e6d 100644 --- a/packages/block-editor/src/components/media-placeholder/style.scss +++ b/packages/block-editor/src/components/media-placeholder/style.scss @@ -45,3 +45,23 @@ .components-form-file-upload .block-editor-media-placeholder__button { margin-right: $grid-size-small; } + +.block-editor-media-placeholder.is-appender { + min-height: 100px; + background-color: unset; + outline: $border-width dashed $dark-gray-150; + + &:hover { + outline: $border-width dashed $dark-gray-500; + } + + .block-editor-media-placeholder__upload-button { + margin-right: $grid-size-small; + &.components-button:hover, + &.components-button:focus { + box-shadow: none; + border: $border-width solid $dark-gray-500; + } + } + +} diff --git a/packages/block-editor/src/components/media-upload/README.md b/packages/block-editor/src/components/media-upload/README.md index eb2f75cbdd8af..6e0a67d9f187c 100644 --- a/packages/block-editor/src/components/media-upload/README.md +++ b/packages/block-editor/src/components/media-upload/README.md @@ -101,6 +101,25 @@ CSS class added to the media modal frame. - Type: `String` - Required: No + +### addToGallery + +If true, the gallery media modal opens directly in the media library where the user can add additional images. +If false the gallery media modal opens in the edit mode where the user can edit existing images, by reordering them, remove them, or change their attributes. +Only applies if `gallery === true`. + +- Type: `Boolean` +- Required: No +- Default: `false` + +### gallery + +If true, the component will initiate all the states required to represent a gallery. By default, the media modal opens in the gallery edit frame, but that can be changed using the `addToGallery`flag. + +- Type: `Boolean` +- Required: No +- Default: `false` + ## render A callback invoked to render the Button opening the media library. diff --git a/packages/block-library/src/gallery/edit.js b/packages/block-library/src/gallery/edit.js index ade7ba978264b..a42e86fa94037 100644 --- a/packages/block-library/src/gallery/edit.js +++ b/packages/block-library/src/gallery/edit.js @@ -8,8 +8,6 @@ import { filter, pick, map, get } from 'lodash'; * WordPress dependencies */ import { - DropZone, - FormFileUpload, IconButton, PanelBody, RangeControl, @@ -25,7 +23,6 @@ import { MediaUpload, InspectorControls, } from '@wordpress/block-editor'; -import { mediaUpload } from '@wordpress/editor'; import { Component, Fragment } from '@wordpress/element'; import { __, sprintf } from '@wordpress/i18n'; @@ -64,8 +61,6 @@ class GalleryEdit extends Component { this.toggleImageCrop = this.toggleImageCrop.bind( this ); this.onRemoveImage = this.onRemoveImage.bind( this ); this.setImageAttributes = this.setImageAttributes.bind( this ); - this.addFiles = this.addFiles.bind( this ); - this.uploadFromFiles = this.uploadFromFiles.bind( this ); this.setAttributes = this.setAttributes.bind( this ); this.state = { @@ -152,27 +147,6 @@ class GalleryEdit extends Component { } ); } - uploadFromFiles( event ) { - this.addFiles( event.target.files ); - } - - addFiles( files ) { - const currentImages = this.props.attributes.images || []; - const { noticeOperations } = this.props; - const { setAttributes } = this; - mediaUpload( { - allowedTypes: ALLOWED_MEDIA_TYPES, - filesList: files, - onFileChange: ( images ) => { - const imagesNormalized = images.map( ( image ) => pickRelevantMediaFiles( image ) ); - setAttributes( { - images: currentImages.concat( imagesNormalized ), - } ); - }, - onError: noticeOperations.createErrorNotice, - } ); - } - componentDidUpdate( prevProps ) { // Deselect images when deselecting the block if ( ! this.props.isSelected && prevProps.isSelected ) { @@ -187,15 +161,11 @@ class GalleryEdit extends Component { const { attributes, isSelected, className, noticeOperations, noticeUI } = this.props; const { images, columns = defaultColumnsNumber( attributes ), align, imageCrop, linkTo } = attributes; - const dropZone = ( - - ); + const hasImages = !! images.length; const controls = ( - { !! images.length && ( + { hasImages && ( ); - if ( images.length === 0 ) { + const mediaPlaceholder = ( + } + labels={ { + title: ! hasImages && __( 'Gallery' ), + instructions: ! hasImages && __( 'Drag images, upload new ones or select files from your library.' ), + } } + onSelect={ this.onSelectImages } + accept="image/*" + allowedTypes={ ALLOWED_MEDIA_TYPES } + multiple + value={ hasImages ? images : undefined } + onError={ noticeOperations.createErrorNotice } + notices={ hasImages ? undefined : noticeUI } + /> + ); + + if ( ! hasImages ) { return ( { controls } - } - className={ className } - labels={ { - title: __( 'Gallery' ), - instructions: __( 'Drag images, upload new ones or select files from your library.' ), - } } - onSelect={ this.onSelectImages } - accept="image/*" - allowedTypes={ ALLOWED_MEDIA_TYPES } - multiple - notices={ noticeUI } - onError={ noticeOperations.createErrorNotice } - /> + { mediaPlaceholder } ); } @@ -277,7 +255,6 @@ class GalleryEdit extends Component { } ) } > - { dropZone } { images.map( ( img, index ) => { /* translators: %1$d is the order number of the image, %2$d is the total number of images. */ const ariaLabel = sprintf( __( 'image %1$d of %2$d in gallery' ), ( index + 1 ), images.length ); @@ -298,21 +275,8 @@ class GalleryEdit extends Component { ); } ) } - { isSelected && -
  • - - { __( 'Upload an image' ) } - -
  • - } + { mediaPlaceholder } ); } diff --git a/packages/block-library/src/gallery/editor.scss b/packages/block-library/src/gallery/editor.scss index 34b08797e2e55..4136018059e49 100644 --- a/packages/block-library/src/gallery/editor.scss +++ b/packages/block-library/src/gallery/editor.scss @@ -53,31 +53,6 @@ ul.wp-block-gallery li { } } - .components-form-file-upload, - .components-button.block-library-gallery-add-item-button { - width: 100%; - height: 100%; - } - - .components-button.block-library-gallery-add-item-button { - display: flex; - flex-direction: column; - justify-content: center; - box-shadow: none; - border: none; - border-radius: 0; - min-height: 100px; - - & .dashicon { - margin-top: 10px; - } - - &:hover, - &:focus { - border: $border-width solid $dark-gray-500; - } - } - .block-editor-rich-text figcaption { a { color: $white; @@ -118,14 +93,3 @@ ul.wp-block-gallery li { margin-top: -9px; margin-left: -9px; } - -// Last item always needs margins reset. -// When block is selected, only reset the right margin of the 2nd to last item. -.wp-block-gallery { - .is-selected & .blocks-gallery-image:nth-last-child(2), - .is-selected & .blocks-gallery-item:nth-last-child(2), - .is-typing & .blocks-gallery-image:nth-last-child(2), - .is-typing & .blocks-gallery-item:nth-last-child(2) { - margin-right: 0; - } -} diff --git a/packages/block-library/src/gallery/style.scss b/packages/block-library/src/gallery/style.scss index 2557f727c5c0e..df60d6fd1fc9b 100644 --- a/packages/block-library/src/gallery/style.scss +++ b/packages/block-library/src/gallery/style.scss @@ -126,14 +126,6 @@ margin-right: 0; } - // Make the "Add new Gallery item" button full-width (so it always appears - // below other items). - .blocks-gallery-item { - &.has-add-item-button { - width: 100%; - } - } - // Apply max-width to floated items that have no intrinsic width. &.alignleft, &.alignright { diff --git a/packages/edit-post/src/hooks/components/media-upload/index.js b/packages/edit-post/src/hooks/components/media-upload/index.js index df65411e1c305..eefb3450a6e1c 100644 --- a/packages/edit-post/src/hooks/components/media-upload/index.js +++ b/packages/edit-post/src/hooks/components/media-upload/index.js @@ -78,10 +78,10 @@ const getAttachmentsCollection = ( ids ) => { class MediaUpload extends Component { constructor( { allowedTypes, - multiple = false, gallery = false, - title = __( 'Select or Upload Media' ), modalClass, + multiple = false, + title = __( 'Select or Upload Media' ), } ) { super( ...arguments ); this.openModal = this.openModal.bind( this ); @@ -124,6 +124,7 @@ class MediaUpload extends Component { buildAndSetGalleryFrame() { const { + addToGallery = false, allowedTypes, multiple = false, value = null, @@ -140,7 +141,12 @@ class MediaUpload extends Component { if ( this.frame ) { this.frame.remove(); } - const currentState = value ? 'gallery-edit' : 'gallery'; + let currentState; + if ( addToGallery ) { + currentState = 'gallery-library'; + } else { + currentState = value ? 'gallery-edit' : 'gallery'; + } if ( ! this.GalleryDetailsMediaFrame ) { this.GalleryDetailsMediaFrame = getGalleryDetailsMediaFrame(); } From b90fbbdc41293ba562ebc51e41eb09bcb6757841 Mon Sep 17 00:00:00 2001 From: Jorge Date: Thu, 21 Mar 2019 10:18:19 +0000 Subject: [PATCH 2/6] Allow clicking all placeholder appender area to upload files. --- .../src/components/media-placeholder/index.js | 267 +++++++++++------- .../components/src/form-file-upload/index.js | 10 +- 2 files changed, 178 insertions(+), 99 deletions(-) diff --git a/packages/block-editor/src/components/media-placeholder/index.js b/packages/block-editor/src/components/media-placeholder/index.js index bdfdb7a45dc4d..42fa7e7d8fbe7 100644 --- a/packages/block-editor/src/components/media-placeholder/index.js +++ b/packages/block-editor/src/components/media-placeholder/index.js @@ -148,31 +148,18 @@ export class MediaPlaceholder extends Component { this.setState( { isURLInputVisible: false } ); } - render() { + renderPlaceholder( content, onClick ) { const { - accept, - addToGallery, allowedTypes = [], className, - dropZoneUIOnly, hasUploadPermissions, icon, isAppender, labels = {}, - mediaUpload, - multiple = false, notices, - onHTMLDrop = noop, - onSelect, onSelectURL, - value = {}, } = this.props; - const { - isURLInputVisible, - src, - } = this.state; - let instructions = labels.instructions; let title = labels.title; @@ -223,103 +210,191 @@ export class MediaPlaceholder extends Component { } } - const dropZone = ( - + const placeholderClassName = classnames( + 'block-editor-media-placeholder', + 'editor-media-placeholder', + className, + { 'is-appender': isAppender } ); - if ( dropZoneUIOnly ) { - return ( - - { dropZone } - - ); - } - return ( - - { !! mediaUpload && ( - - { dropZone } - - { __( 'Upload' ) } - - - ) } - id ) : - value.id - } - render={ ( { open } ) => { - return ( - - ); - } } + { content } + + ); + } + + renderDropZone() { + const { onHTMLDrop = noop } = this.props; + return ( + + ); + } + + renderUrlSelectionUI() { + const { + onSelectURL, + } = this.props; + if ( ! onSelectURL ) { + return null; + } + const { + isURLInputVisible, + src, + } = this.state; + return ( +
    + + { isURLInputVisible && ( + - - { onSelectURL && ( -
    + ) } +
    + ); + } + + renderMediaUploadChecked() { + const { + accept, + addToGallery, + allowedTypes = [], + isAppender, + mediaUpload, + multiple = false, + onSelect, + value = {}, + } = this.props; + + const mediaLibraryButton = ( + id ) : + value.id + } + render={ ( { open } ) => { + return ( - { isURLInputVisible && ( - + ); + } } + /> + ); + + if ( mediaUpload && isAppender ) { + return ( + + { this.renderDropZone() } + { + const content = ( + + + { __( 'Upload' ) } + + { mediaLibraryButton } + { this.renderUrlSelectionUI() } + + ); + return this.renderPlaceholder( content, openFileDialog ); + } } + /> + + ); + } + if ( mediaUpload ) { + const content = ( + + { this.renderDropZone() } + - ) } - + onChange={ this.onUpload } + accept={ accept } + multiple={ multiple } + > + { __( 'Upload' ) } + + { mediaLibraryButton } + { this.renderUrlSelectionUI() } + + ); + return this.renderPlaceholder( content ); + } + return this.renderPlaceholder( mediaLibraryButton ); + } + + render() { + const { + dropZoneUIOnly, + } = this.props; + + if ( dropZoneUIOnly ) { + return ( + + { this.renderDropZone() } + + ); + } + + return ( + + { this.renderMediaUploadChecked() } + ); } } diff --git a/packages/components/src/form-file-upload/index.js b/packages/components/src/form-file-upload/index.js index 461f83c263888..7a45a075ddfd8 100644 --- a/packages/components/src/form-file-upload/index.js +++ b/packages/components/src/form-file-upload/index.js @@ -24,10 +24,10 @@ class FormFileUpload extends Component { } render() { - const { children, multiple = false, accept, onChange, icon = 'upload', ...props } = this.props; + const { children, multiple = false, accept, onChange, icon = 'upload', render, ...props } = this.props; - return ( -
    + const ui = render ? + render( { openFileDialog: this.openFileDialog } ) : ( { children } + ); + return ( +
    + { ui } Date: Mon, 25 Mar 2019 08:29:17 -0400 Subject: [PATCH 3/6] Switch to a "pointer" cursor on the appender on hover. To reinforce that this area is clickable. --- .../block-editor/src/components/media-placeholder/style.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/block-editor/src/components/media-placeholder/style.scss b/packages/block-editor/src/components/media-placeholder/style.scss index 15ee92a684e6d..db04917a21078 100644 --- a/packages/block-editor/src/components/media-placeholder/style.scss +++ b/packages/block-editor/src/components/media-placeholder/style.scss @@ -53,6 +53,7 @@ &:hover { outline: $border-width dashed $dark-gray-500; + cursor: pointer; } .block-editor-media-placeholder__upload-button { From 792eecd7ba04797ff91225e4f816f8f0cef38579 Mon Sep 17 00:00:00 2001 From: Kjell Reigstad Date: Mon, 25 Mar 2019 08:42:03 -0400 Subject: [PATCH 4/6] Reinstate the gray background. --- .../block-editor/src/components/media-placeholder/style.scss | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/block-editor/src/components/media-placeholder/style.scss b/packages/block-editor/src/components/media-placeholder/style.scss index db04917a21078..4ce7e8a0e6942 100644 --- a/packages/block-editor/src/components/media-placeholder/style.scss +++ b/packages/block-editor/src/components/media-placeholder/style.scss @@ -48,7 +48,6 @@ .block-editor-media-placeholder.is-appender { min-height: 100px; - background-color: unset; outline: $border-width dashed $dark-gray-150; &:hover { From 5756a0577d2e917a84f720764a01d89470efdae0 Mon Sep 17 00:00:00 2001 From: Kjell Reigstad Date: Mon, 25 Mar 2019 09:05:41 -0400 Subject: [PATCH 5/6] Switch to a white dashed outline on dark backgrounds. --- .../src/components/media-placeholder/style.scss | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/block-editor/src/components/media-placeholder/style.scss b/packages/block-editor/src/components/media-placeholder/style.scss index 4ce7e8a0e6942..d18b42ce5e57a 100644 --- a/packages/block-editor/src/components/media-placeholder/style.scss +++ b/packages/block-editor/src/components/media-placeholder/style.scss @@ -55,6 +55,13 @@ cursor: pointer; } + .is-dark-theme & { + + &:hover { + outline: $border-width dashed $white; + } + } + .block-editor-media-placeholder__upload-button { margin-right: $grid-size-small; &.components-button:hover, From 3eb3261ea53393974d0cb59f09108279c8dceac0 Mon Sep 17 00:00:00 2001 From: Jorge Date: Mon, 25 Mar 2019 15:34:27 +0000 Subject: [PATCH 6/6] Updated the changelogs. --- packages/block-editor/CHANGELOG.md | 7 +++++++ packages/components/CHANGELOG.md | 4 ++++ packages/edit-post/CHANGELOG.md | 9 ++++++++- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/CHANGELOG.md b/packages/block-editor/CHANGELOG.md index 4306b855955f5..e8e873c3719d2 100644 --- a/packages/block-editor/CHANGELOG.md +++ b/packages/block-editor/CHANGELOG.md @@ -1,5 +1,12 @@ ## 2.0.0 (Unreleased) +### New Features + +- Added the `addToGallery` property to the `MediaUpload` interface. The property allows users to open the media modal in the `gallery-library`instead of `gallery-edit` state. +- Added the `addToGallery` property to the `MediaPlaceholder` component. The component passes the property to the `MediaUpload` component used inside the placeholder. +- Added the `isAppender` property to the `MediaPlaceholder` component. The property changes the look of the placeholder to be adequate to scenarios where new files are added to an already existing set of files, e.g., adding files to a gallery. +- Added the `dropZoneUIOnly` property to the `MediaPlaceholder` component. The property makes the `MediaPlaceholder` only render a dropzone without any other additional UI. + ### Breaking Changes - `CopyHandler` will now only catch cut/copy events coming from its `props.children`, instead of from anywhere in the `document`. diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 2035d92dd9be9..c76f5a75ac8d7 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -1,5 +1,9 @@ ## 7.2.1 (Unreleased) +### New Features + +- Added a new `render` property to `FormFileUpload` component. Allowing users of the component to custom the UI for their needs. + ### Bug fixes - Fix `instanceId` prop passed through to `Button` component via `MenuItems` producing React console error. Fixed by removing the unnecessary use of `withInstanceId` on the `MenuItems` component [#14599](https://github.com/WordPress/gutenberg/pull/14599) diff --git a/packages/edit-post/CHANGELOG.md b/packages/edit-post/CHANGELOG.md index 4e58838aade5e..c01997e5377e0 100644 --- a/packages/edit-post/CHANGELOG.md +++ b/packages/edit-post/CHANGELOG.md @@ -1,4 +1,11 @@ -## 3.2.0 (Next) +## V.V.V (Unreleased) + +### New Features + +- Implement the `addToGallery` option in the `MediaUpload` hook. The option allows users to open the media modal in the `gallery-library`instead of `gallery-edit` state. + + +## 3.2.0 (2019-03-06) ### Polish