Skip to content

Commit

Permalink
Fix metabox reordering (WordPress#30617)
Browse files Browse the repository at this point in the history
  • Loading branch information
ribaricplusplus authored Aug 30, 2021
1 parent b2c4a00 commit 893b2b8
Show file tree
Hide file tree
Showing 7 changed files with 155 additions and 71 deletions.
16 changes: 16 additions & 0 deletions docs/reference-guides/data/data-core-edit-post.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,18 @@ Namespace: `core/edit-post`.

<!-- START TOKEN(Autogenerated selectors|../../../packages/edit-post/src/store/selectors.js) -->

### areMetaBoxesInitialized

Returns true if meta boxes are initialized.

_Parameters_

- _state_ `Object`: Global application state.

_Returns_

- `boolean`: Whether meta boxes are initialized.

### getActiveGeneralSidebarName

Returns the current active general sidebar name, or null if there is no
Expand Down Expand Up @@ -351,6 +363,10 @@ _Returns_

- `Object`: Action object.

### initializeMetaBoxes

Initializes WordPress `postboxes` script and the logic for saving meta boxes.

### metaBoxUpdatesFailure

Returns an action object used to signal a failed meta box update.
Expand Down
5 changes: 1 addition & 4 deletions packages/edit-post/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,10 @@ They can be found in the global variable `wp.editPost` when defining `wp-edit-po

Initializes and returns an instance of Editor.

The return value of this function is not necessary if we change where we
call initializeEditor(). This is due to metaBox timing.

_Parameters_

- _id_ `string`: Unique identifier for editor instance.
- _postType_ `Object`: Post type of the post to edit.
- _postType_ `string`: Post type of the post to edit.
- _postId_ `Object`: ID of the post to edit.
- _settings_ `?Object`: Editor settings object.
- _initialEdits_ `Object`: Programmatic edits to apply initially, to be considered as non-user-initiated (bypass for unsaved changes prompt).
Expand Down
54 changes: 41 additions & 13 deletions packages/edit-post/src/components/meta-boxes/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import { map } from 'lodash';
/**
* WordPress dependencies
*/
import { withSelect } from '@wordpress/data';
import { useSelect, useRegistry } from '@wordpress/data';
import { useEffect } from '@wordpress/element';
import { store as editorStore } from '@wordpress/editor';

/**
* Internal dependencies
Expand All @@ -15,7 +17,44 @@ import MetaBoxesArea from './meta-boxes-area';
import MetaBoxVisibility from './meta-box-visibility';
import { store as editPostStore } from '../../store';

function MetaBoxes( { location, isVisible, metaBoxes } ) {
export default function MetaBoxes( { location } ) {
const registry = useRegistry();
const {
metaBoxes,
isVisible,
areMetaBoxesInitialized,
isEditorReady,
} = useSelect(
( select ) => {
const { __unstableIsEditorReady } = select( editorStore );
const {
isMetaBoxLocationVisible,
getMetaBoxesPerLocation,
areMetaBoxesInitialized: _areMetaBoxesInitialized,
} = select( editPostStore );
return {
metaBoxes: getMetaBoxesPerLocation( location ),
isVisible: isMetaBoxLocationVisible( location ),
areMetaBoxesInitialized: _areMetaBoxesInitialized(),
isEditorReady: __unstableIsEditorReady(),
};
},
[ location ]
);

// When editor is ready, initialize postboxes (wp core script) and metabox
// saving. This initializes all meta box locations, not just this specific
// one.
useEffect( () => {
if ( isEditorReady && ! areMetaBoxesInitialized ) {
registry.dispatch( editPostStore ).initializeMetaBoxes();
}
}, [ isEditorReady, areMetaBoxesInitialized ] );

if ( ! areMetaBoxesInitialized ) {
return null;
}

return (
<>
{ map( metaBoxes, ( { id } ) => (
Expand All @@ -25,14 +64,3 @@ function MetaBoxes( { location, isVisible, metaBoxes } ) {
</>
);
}

export default withSelect( ( select, { location } ) => {
const { isMetaBoxLocationVisible, getMetaBoxesPerLocation } = select(
editPostStore
);

return {
metaBoxes: getMetaBoxesPerLocation( location ),
isVisible: isMetaBoxLocationVisible( location ),
};
} )( MetaBoxes );
7 changes: 2 additions & 5 deletions packages/edit-post/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import { store as interfaceStore } from '@wordpress/interface';
*/
import './hooks';
import './plugins';
export { store } from './store';
import Editor from './editor';

/**
Expand Down Expand Up @@ -63,11 +62,8 @@ export function reinitializeEditor(
/**
* Initializes and returns an instance of Editor.
*
* The return value of this function is not necessary if we change where we
* call initializeEditor(). This is due to metaBox timing.
*
* @param {string} id Unique identifier for editor instance.
* @param {Object} postType Post type of the post to edit.
* @param {string} postType Post type of the post to edit.
* @param {Object} postId ID of the post to edit.
* @param {?Object} settings Editor settings object.
* @param {Object} initialEdits Programmatic edits to apply initially, to be
Expand Down Expand Up @@ -170,3 +166,4 @@ export { default as PluginSidebar } from './components/sidebar/plugin-sidebar';
export { default as PluginSidebarMoreMenuItem } from './components/header/plugin-sidebar-more-menu-item';
export { default as __experimentalFullscreenModeClose } from './components/header/fullscreen-mode-close';
export { default as __experimentalMainDashboardButton } from './components/header/main-dashboard-button';
export { store } from './store';
116 changes: 67 additions & 49 deletions packages/edit-post/src/store/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { castArray, reduce } from 'lodash';
import { __ } from '@wordpress/i18n';
import { apiFetch } from '@wordpress/data-controls';
import { store as interfaceStore } from '@wordpress/interface';
import { controls, dispatch, select, subscribe } from '@wordpress/data';
import { controls, select, subscribe, dispatch } from '@wordpress/data';
import { speak } from '@wordpress/a11y';
import { store as noticesStore } from '@wordpress/notices';
import { store as coreStore } from '@wordpress/core-data';
Expand Down Expand Up @@ -265,8 +265,6 @@ export function showBlockTypes( blockNames ) {
};
}

let saveMetaboxUnsubscribe;

/**
* Returns an action object used in signaling
* what Meta boxes are available in which location.
Expand All @@ -280,52 +278,6 @@ export function* setAvailableMetaBoxesPerLocation( metaBoxesPerLocation ) {
type: 'SET_META_BOXES_PER_LOCATIONS',
metaBoxesPerLocation,
};

const postType = yield controls.select( editorStore, 'getCurrentPostType' );
if ( window.postboxes.page !== postType ) {
window.postboxes.add_postbox_toggles( postType );
}

let wasSavingPost = yield controls.select( editorStore, 'isSavingPost' );
let wasAutosavingPost = yield controls.select(
editorStore,
'isAutosavingPost'
);

// Meta boxes are initialized once at page load. It is not necessary to
// account for updates on each state change.
//
// See: https://github.com/WordPress/WordPress/blob/5.1.1/wp-admin/includes/post.php#L2307-L2309
const hasActiveMetaBoxes = yield controls.select(
editPostStore,
'hasMetaBoxes'
);

// First remove any existing subscription in order to prevent multiple saves
if ( !! saveMetaboxUnsubscribe ) {
saveMetaboxUnsubscribe();
}

// Save metaboxes when performing a full save on the post.
saveMetaboxUnsubscribe = subscribe( () => {
const isSavingPost = select( editorStore ).isSavingPost();
const isAutosavingPost = select( editorStore ).isAutosavingPost();

// Save metaboxes on save completion, except for autosaves that are not a post preview.
const shouldTriggerMetaboxesSave =
hasActiveMetaBoxes &&
wasSavingPost &&
! isSavingPost &&
! wasAutosavingPost;

// Save current state for next inspection.
wasSavingPost = isSavingPost;
wasAutosavingPost = isAutosavingPost;

if ( shouldTriggerMetaboxesSave ) {
dispatch( editPostStore ).requestMetaBoxUpdates();
}
} );
}

/**
Expand Down Expand Up @@ -531,3 +483,69 @@ export function* __unstableCreateTemplate( template ) {
}
);
}

let metaBoxesInitialized = false;

/**
* Initializes WordPress `postboxes` script and the logic for saving meta boxes.
*/
export function* initializeMetaBoxes() {
const isEditorReady = yield controls.select(
editorStore,
'__unstableIsEditorReady'
);

if ( ! isEditorReady ) {
return;
}

const postType = yield controls.select( editorStore, 'getCurrentPostType' );

// Only initialize once.
if ( metaBoxesInitialized ) {
return;
}

if ( window.postboxes.page !== postType ) {
window.postboxes.add_postbox_toggles( postType );
}

metaBoxesInitialized = true;

let wasSavingPost = yield controls.select( editorStore, 'isSavingPost' );
let wasAutosavingPost = yield controls.select(
editorStore,
'isAutosavingPost'
);
const hasMetaBoxes = yield controls.select( editPostStore, 'hasMetaBoxes' );

// Save metaboxes when performing a full save on the post.
subscribe( () => {
const isSavingPost = select( editorStore ).isSavingPost();
const isAutosavingPost = select( editorStore ).isAutosavingPost();

// Save metaboxes on save completion, except for autosaves that are not a post preview.
//
// Meta boxes are initialized once at page load. It is not necessary to
// account for updates on each state change.
//
// See: https://github.com/WordPress/WordPress/blob/5.1.1/wp-admin/includes/post.php#L2307-L2309
const shouldTriggerMetaboxesSave =
hasMetaBoxes &&
wasSavingPost &&
! isSavingPost &&
! wasAutosavingPost;

// Save current state for next inspection.
wasSavingPost = isSavingPost;
wasAutosavingPost = isAutosavingPost;

if ( shouldTriggerMetaboxesSave ) {
dispatch( editPostStore ).requestMetaBoxUpdates();
}
} );

return {
type: 'META_BOXES_INITIALIZED',
};
}
17 changes: 17 additions & 0 deletions packages/edit-post/src/store/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -281,9 +281,26 @@ function isEditingTemplate( state = false, action ) {
return state;
}

/**
* Reducer tracking whether meta boxes are initialized.
*
* @param {boolean} state
* @param {Object} action
*
* @return {boolean} Updated state.
*/
function metaBoxesInitialized( state = false, action ) {
switch ( action.type ) {
case 'META_BOXES_INITIALIZED':
return true;
}
return state;
}

const metaBoxes = combineReducers( {
isSaving: isSavingMetaBoxes,
locations: metaBoxLocations,
initialized: metaBoxesInitialized,
} );

export default combineReducers( {
Expand Down
11 changes: 11 additions & 0 deletions packages/edit-post/src/store/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,17 @@ export function isEditingTemplate( state ) {
return state.isEditingTemplate;
}

/**
* Returns true if meta boxes are initialized.
*
* @param {Object} state Global application state.
*
* @return {boolean} Whether meta boxes are initialized.
*/
export function areMetaBoxesInitialized( state ) {
return state.metaBoxes.initialized;
}

/**
* Retrieves the template of the currently edited post.
*
Expand Down

0 comments on commit 893b2b8

Please sign in to comment.