Skip to content
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

Fix metabox reordering #30617

Merged
merged 22 commits into from
Aug 30, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 ]
);
ribaricplusplus marked this conversation as resolved.
Show resolved Hide resolved

// 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