-
Notifications
You must be signed in to change notification settings - Fork 4.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Chrome: Adding the featured image panel #894
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
const spinner = <span className="spinner is-active" />; | ||
|
||
export default () => spinner; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
/** | ||
* 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, | ||
}; | ||
} | ||
|
||
componentDidMount() { | ||
this.fetchMedia(); | ||
} | ||
|
||
componentDidUpdate( prevProps ) { | ||
if ( prevProps.featuredImageId !== this.props.featuredImageId ) { | ||
this.fetchMedia(); | ||
} | ||
} | ||
|
||
componentWillUnmount() { | ||
if ( this.fetchMediaRequest ) { | ||
this.fetchMediaRequest.abort(); | ||
} | ||
} | ||
|
||
fetchMedia() { | ||
this.setState( { media: null } ); | ||
if ( ! this.props.featuredImageId ) { | ||
this.setState( { loading: false } ); | ||
return; | ||
} | ||
this.setState( { loading: true } ); | ||
const mediaIdToLoad = this.props.featuredImageId; | ||
this.fetchMediaRequest = new wp.api.models.Media( { id: mediaIdToLoad } ).fetch() | ||
.done( ( media ) => { | ||
if ( this.props.featuredImageId !== mediaIdToLoad ) { | ||
return; | ||
} | ||
this.setState( { | ||
loading: false, | ||
media, | ||
} ); | ||
} ) | ||
.fail( () => { | ||
if ( this.props.featuredImageId !== mediaIdToLoad ) { | ||
return; | ||
} | ||
this.setState( { | ||
loading: false, | ||
} ); | ||
} ); | ||
} | ||
|
||
render() { | ||
const { featuredImageId, onUpdateImage, onRemoveImage } = this.props; | ||
const { media, loading } = this.state; | ||
|
||
return ( | ||
<PanelBody title={ __( 'Featured image' ) } initialOpen={ false }> | ||
<div className="editor-featured-image__content"> | ||
{ !! featuredImageId && | ||
<MediaUploadButton | ||
buttonProps={ { className: 'button-link' } } | ||
onSelect={ onUpdateImage } | ||
type="image" | ||
> | ||
{ media && | ||
<img | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. One minor thing we might consider is using the media's dimensions to assign a height to the space that the image will occupy, to avoid the jarring appearance of content being pushed down only after the image has loaded. Height is difficult to calculate unless we know the width of the container, which we probably don't want to assume. We could use a technique for proportionally scaled responsive containers though, using padding to dynamically fill height. See: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure I understand. The height depends on the loaded image. So even if we know the width container, we don't know the ratio of the loaded image, how can we compute the height in this case? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To your point, more accurately there's two resources that need to be loaded:
The idea is that after the first of these finishes loading, we know the dimensions of the image and the space we expect it to consume, even before the image itself has finished loading. Practically speaking this is probably not very noticeable though, since either we've loaded a post with a featured image already assigned and Settings -> Featured Image is likely collapsed, or we've just assigned the image from the media library and the image is already cached by the browser. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here's maybe a clearer demonstration of the issue/solution and its particular relevance when we don't know the containing width: |
||
className="editor-featured-image__preview" | ||
src={ media.source_url } | ||
alt={ __( 'Featured image' ) } | ||
/> | ||
} | ||
{ loading && <Spinner /> } | ||
</MediaUploadButton> | ||
} | ||
{ !! featuredImageId && media && | ||
<p className="editor-featured-image__howto"> | ||
{ __( 'Click the image to edit or update' ) } | ||
</p> | ||
} | ||
{ ! featuredImageId && | ||
<MediaUploadButton | ||
buttonProps={ { className: 'editor-featured-image__toggle button-link' } } | ||
onSelect={ onUpdateImage } | ||
type="image" | ||
> | ||
{ wp.i18n.__( 'Set featured image' ) } | ||
</MediaUploadButton> | ||
} | ||
{ !! featuredImageId && | ||
<Button className="editor-featured-image__toggle button-link" onClick={ onRemoveImage }> | ||
{ wp.i18n.__( 'Remove featured image' ) } | ||
</Button> | ||
} | ||
</div> | ||
</PanelBody> | ||
); | ||
} | ||
} | ||
|
||
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 ); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice optimization 👍 (related)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have a good teacher :)