-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
MetaBoxes: Remove dirty-checking metaboxes state (#4184)
* MetaBoxes: Remove dirty-checking metaboxes state * MetaBoxes: compare meta boxes HTML while leaving the editor to warn about unsaved changes * Meta Boxes: Changing the way we save metaboxes Hidden metaboxes (side) were not saved before
- Loading branch information
1 parent
036f60a
commit 6dd01de
Showing
15 changed files
with
327 additions
and
523 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,153 +1,89 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import { isEqual } from 'lodash'; | ||
import classnames from 'classnames'; | ||
import { connect } from 'react-redux'; | ||
import jQuery from 'jquery'; | ||
|
||
/** | ||
* WordPress dependencies | ||
*/ | ||
import { addQueryArgs } from '@wordpress/url'; | ||
import { Component } from '@wordpress/element'; | ||
import { Spinner } from '@wordpress/components'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import './style.scss'; | ||
import { handleMetaBoxReload, metaBoxStateChanged, metaBoxLoaded } from '../../../store/actions'; | ||
import { getMetaBox, isSavingPost } from '../../../store/selectors'; | ||
import { isSavingMetaBoxes } from '../../../store/selectors'; | ||
|
||
class MetaBoxesArea extends Component { | ||
/** | ||
* @inheritdoc | ||
*/ | ||
constructor() { | ||
super( ...arguments ); | ||
|
||
this.state = { | ||
loading: false, | ||
}; | ||
this.originalFormData = ''; | ||
this.bindNode = this.bindNode.bind( this ); | ||
this.checkState = this.checkState.bind( this ); | ||
} | ||
|
||
bindNode( node ) { | ||
this.node = node; | ||
this.bindContainerNode = this.bindContainerNode.bind( this ); | ||
} | ||
|
||
/** | ||
* @inheritdoc | ||
*/ | ||
componentDidMount() { | ||
this.mounted = true; | ||
this.fetchMetaboxes(); | ||
} | ||
|
||
componentWillUnmount() { | ||
this.mounted = false; | ||
this.unbindFormEvents(); | ||
document.querySelector( '#metaboxes' ).appendChild( this.form ); | ||
} | ||
|
||
unbindFormEvents() { | ||
this.form = document.querySelector( '.metabox-location-' + this.props.location ); | ||
if ( this.form ) { | ||
this.form.removeEventListener( 'change', this.checkState ); | ||
this.form.removeEventListener( 'input', this.checkState ); | ||
this.container.appendChild( this.form ); | ||
} | ||
} | ||
|
||
componentWillReceiveProps( nextProps ) { | ||
if ( nextProps.isUpdating && ! this.props.isUpdating ) { | ||
this.setState( { loading: true } ); | ||
const { location } = nextProps; | ||
const headers = new window.Headers(); | ||
const fetchOptions = { | ||
method: 'POST', | ||
headers, | ||
body: new window.FormData( this.form ), | ||
credentials: 'include', | ||
}; | ||
|
||
// Save the metaboxes | ||
window.fetch( addQueryArgs( window._wpMetaBoxUrl, { meta_box: location } ), fetchOptions ) | ||
.then( () => { | ||
if ( ! this.mounted ) { | ||
return false; | ||
} | ||
this.setState( { loading: false } ); | ||
this.props.metaBoxReloaded( location ); | ||
} ); | ||
/** | ||
* Get the meta box location form from the original location. | ||
*/ | ||
componentWillUnmount() { | ||
if ( this.form ) { | ||
document.querySelector( '#metaboxes' ).appendChild( this.form ); | ||
} | ||
} | ||
|
||
fetchMetaboxes() { | ||
const { location } = this.props; | ||
this.form = document.querySelector( '.metabox-location-' + location ); | ||
this.node.appendChild( this.form ); | ||
this.form.onSubmit = ( event ) => event.preventDefault(); | ||
this.originalFormData = this.getFormData(); | ||
this.form.addEventListener( 'change', this.checkState ); | ||
this.form.addEventListener( 'input', this.checkState ); | ||
this.props.metaBoxLoaded( location ); | ||
} | ||
|
||
getFormData() { | ||
return jQuery( this.form ).serialize(); | ||
} | ||
|
||
checkState() { | ||
const { loading } = this.state; | ||
const { isDirty, changedMetaBoxState, location } = this.props; | ||
|
||
const newIsDirty = ! isEqual( this.originalFormData, this.getFormData() ); | ||
|
||
/** | ||
* If we are not updating, then if dirty and equal to original, then set not dirty. | ||
* If we are not updating, then if not dirty and not equal to original, set as dirty. | ||
*/ | ||
if ( ! loading && isDirty !== newIsDirty ) { | ||
changedMetaBoxState( location, newIsDirty ); | ||
} | ||
/** | ||
* Binds the metabox area container node. | ||
* | ||
* @param {Element} node DOM Node. | ||
*/ | ||
bindContainerNode( node ) { | ||
this.container = node; | ||
} | ||
|
||
/** | ||
* @inheritdoc | ||
*/ | ||
render() { | ||
const { location } = this.props; | ||
const { loading } = this.state; | ||
const { location, isSaving } = this.props; | ||
|
||
const classes = classnames( | ||
'editor-meta-boxes-area', | ||
`is-${ location }`, | ||
{ | ||
'is-loading': loading, | ||
'is-loading': isSaving, | ||
} | ||
); | ||
|
||
return ( | ||
<div className={ classes }> | ||
{ loading && <Spinner /> } | ||
<div ref={ this.bindNode } /> | ||
{ isSaving && <Spinner /> } | ||
<div className="editor-meta-boxes-area__container" ref={ this.bindContainerNode } /> | ||
<div className="editor-meta-boxes-area__clear" /> | ||
</div> | ||
); | ||
} | ||
} | ||
|
||
function mapStateToProps( state, ownProps ) { | ||
const metaBox = getMetaBox( state, ownProps.location ); | ||
const { isDirty, isUpdating } = metaBox; | ||
|
||
return { | ||
isDirty, | ||
isUpdating, | ||
isPostSaving: isSavingPost( state ) ? true : false, | ||
}; | ||
} | ||
|
||
function mapDispatchToProps( dispatch ) { | ||
/** | ||
* @inheritdoc | ||
*/ | ||
function mapStateToProps( state ) { | ||
return { | ||
// Used to set the reference to the MetaBox in redux, fired when the component mounts. | ||
metaBoxReloaded: ( location ) => dispatch( handleMetaBoxReload( location ) ), | ||
changedMetaBoxState: ( location, hasChanged ) => dispatch( metaBoxStateChanged( location, hasChanged ) ), | ||
metaBoxLoaded: ( location ) => dispatch( metaBoxLoaded( location ) ), | ||
isSaving: isSavingMetaBoxes( state ), | ||
}; | ||
} | ||
|
||
export default connect( mapStateToProps, mapDispatchToProps )( MetaBoxesArea ); | ||
export default connect( mapStateToProps )( MetaBoxesArea ); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
/** | ||
* Function returning the current Meta Boxes DOM Node in the editor | ||
* whether the meta box area is opened or not. | ||
* If the MetaBox Area is visible returns it, and returns the original container instead. | ||
* | ||
* @param {string} location Meta Box location. | ||
* @returns {string} HTML content. | ||
*/ | ||
export const getMetaBoxContainer = ( location ) => { | ||
const area = document.querySelector( `.editor-meta-boxes-area.is-${ location } .metabox-location-${ location }` ); | ||
if ( area ) { | ||
return area; | ||
} | ||
|
||
return document.querySelector( '#metaboxes .metabox-location-' + location ); | ||
}; |
Oops, something went wrong.