diff --git a/components/spinner/index.js b/components/spinner/index.js new file mode 100644 index 0000000000000..4e3c00b7845c1 --- /dev/null +++ b/components/spinner/index.js @@ -0,0 +1,3 @@ +const spinner = ; + +export default () => spinner; diff --git a/editor/sidebar/featured-image/index.js b/editor/sidebar/featured-image/index.js new file mode 100644 index 0000000000000..288de6a6d6094 --- /dev/null +++ b/editor/sidebar/featured-image/index.js @@ -0,0 +1,146 @@ +/** + * External dependencies + */ +import { connect } from 'react-redux'; + +/** + * WordPress dependencies + */ +import { Component } from 'element'; +import { __ } from 'i18n'; +import Button from 'components/button'; +import PanelBody from 'components/panel/body'; +import MediaUploadButton from 'blocks/media-upload-button'; +import Spinner from 'components/spinner'; + +/** + * Internal dependencies + */ +import './style.scss'; +import { getEditedPostAttribute } from '../../selectors'; +import { editPost } from '../../actions'; + +class FeaturedImage extends Component { + constructor() { + super( ...arguments ); + this.state = { + media: null, + loading: false, + }; + + // This boolean should be removed when we provide QueryComponents + this.mounted = true; + } + + componentDidMount() { + this.fetchMedia(); + } + + componentDidUpdate( prevProps ) { + if ( prevProps.featuredImageId !== this.props.featuredImageId ) { + this.fetchMedia(); + } + } + + componentWillUnmount() { + this.mounted = false; + } + + fetchMedia() { + if ( ! this.props.featuredImageId ) { + this.setState( { + media: null, + loading: false, + } ); + return; + } + this.setState( { + media: null, + loading: true, + } ); + const mediaIdToLoad = this.props.featuredImageId; + new wp.api.models.Media( { id: mediaIdToLoad } ).fetch() + .done( ( media ) => { + if ( ! this.mounted || this.props.featuredImageId !== mediaIdToLoad ) { + return; + } + this.setState( { + loading: false, + media, + } ); + } ) + .fail( () => { + if ( ! this.mounted || this.props.featuredImageId !== mediaIdToLoad ) { + return; + } + this.setState( { + loading: false, + } ); + } ); + } + + render() { + const { featuredImageId, onUpdateImage, onRemoveImage } = this.props; + const { media, loading } = this.state; + + return ( + +
+ { !! featuredImageId && + + { media && + { + } + { loading && } + + } + { !! featuredImageId && media && +

+ { __( 'Click the image to edit or update' ) } +

+ } + { ! featuredImageId && + + { wp.i18n.__( 'Set featured image' ) } + + } + { !! featuredImageId && + + } +
+
+ ); + } +} + +export default connect( + ( state ) => { + return { + featuredImageId: getEditedPostAttribute( state, 'featured_media' ), + }; + }, + ( dispatch ) => { + return { + onUpdateImage( image ) { + dispatch( editPost( { featured_media: image.id } ) ); + }, + onRemoveImage() { + dispatch( editPost( { featured_media: null } ) ); + }, + }; + } +)( FeaturedImage ); diff --git a/editor/sidebar/featured-image/style.scss b/editor/sidebar/featured-image/style.scss new file mode 100644 index 0000000000000..9f28c4f6ee305 --- /dev/null +++ b/editor/sidebar/featured-image/style.scss @@ -0,0 +1,32 @@ +.editor-featured-image__content { + padding: 10px 0 0; + + .spinner { + margin: 0; + } +} + +.editor-featured-image__toggle { + text-decoration: underline; + color: $blue-wordpress; + + &:focus { + box-shadow: none; + outline: none; + } + + &:hover { + color: $blue-medium; + } +} + +.editor-featured-image__preview { + display: block; + max-width: 100%; +} + +.editor-featured-image__howto { + color: $dark-gray-300; + font-style: italic; + margin: 10px 0; +} diff --git a/editor/sidebar/post-settings/index.js b/editor/sidebar/post-settings/index.js index ce23efe639559..5f53e92928ec4 100644 --- a/editor/sidebar/post-settings/index.js +++ b/editor/sidebar/post-settings/index.js @@ -17,6 +17,7 @@ import IconButton from 'components/icon-button'; import './style.scss'; import PostStatus from '../post-status'; import PostExcerpt from '../post-excerpt'; +import FeaturedImage from '../featured-image'; const PostSettings = ( { toggleSidebar } ) => { return ( @@ -32,6 +33,7 @@ const PostSettings = ( { toggleSidebar } ) => { + ); };