From 70eea018febfb4e88495c8688ff73f8849ef4b00 Mon Sep 17 00:00:00 2001 From: Robert Anderson Date: Wed, 31 Oct 2018 02:11:25 +1100 Subject: [PATCH] Reusable blocks: Mark API as experimental (#11230) * Reusable blocks: Mark API as experimental The reusable block selectors and actions will need to change in the future. Give ourselves some breathing room to make these changes after Gutenberg 4.2 by marking them as experimental. * Add notes about deprecations added for Reusable Blocks Data API --- docs/data/data-core-editor.md | 26 +++--- docs/reference/deprecated.md | 1 + packages/block-library/src/block/edit.js | 12 +-- packages/editor/CHANGELOG.md | 6 ++ .../reusable-block-convert-button.js | 10 +- .../reusable-block-delete-button.js | 7 +- .../editor/src/components/inserter/menu.js | 2 +- .../src/hooks/default-autocompleters.js | 2 +- packages/editor/src/store/actions.js | 91 +++++++++++++++++-- .../src/store/effects/reusable-blocks.js | 6 +- .../src/store/effects/test/reusable-blocks.js | 12 +-- packages/editor/src/store/selectors.js | 56 ++++++++++-- packages/editor/src/store/test/actions.js | 10 +- packages/editor/src/store/test/selectors.js | 8 +- 14 files changed, 193 insertions(+), 56 deletions(-) diff --git a/docs/data/data-core-editor.md b/docs/data/data-core-editor.md index a4fe2f576da271..4ce76d80ea62a8 100644 --- a/docs/data/data-core-editor.md +++ b/docs/data/data-core-editor.md @@ -1120,7 +1120,7 @@ Items are returned ordered descendingly by their 'utility' and 'frecency'. Items that appear in inserter. -### getReusableBlock +### __experimentalGetReusableBlock Returns the reusable block with the given ID. @@ -1133,7 +1133,7 @@ Returns the reusable block with the given ID. The reusable block, or null if none exists. -### isSavingReusableBlock +### __experimentalIsSavingReusableBlock Returns whether or not the reusable block with the given ID is being saved. @@ -1146,7 +1146,7 @@ Returns whether or not the reusable block with the given ID is being saved. Whether or not the reusable block is being saved. -### isFetchingReusableBlock +### __experimentalIsFetchingReusableBlock Returns true if the reusable block with the given ID is being fetched, or false otherwise. @@ -1160,7 +1160,7 @@ false otherwise. Whether the reusable block is being fetched. -### getReusableBlocks +### __experimentalGetReusableBlocks Returns an array of all reusable blocks. @@ -1649,7 +1649,7 @@ Returns an action object used to lock the editor. * lock: Details about the post lock status, user, and nonce. -### fetchReusableBlocks +### __experimentalFetchReusableBlocks Returns an action object used to fetch a single reusable block or all reusable blocks from the REST API into the store. @@ -1659,7 +1659,7 @@ reusable blocks from the REST API into the store. * id: If given, only a single reusable block with this ID will be fetched. -### receiveReusableBlocks +### __experimentalReceiveReusableBlocks Returns an action object used in signalling that reusable blocks have been received. `results` is an array of objects containing: @@ -1670,7 +1670,7 @@ received. `results` is an array of objects containing: * results: Reusable blocks received. -### saveReusableBlock +### __experimentalSaveReusableBlock Returns an action object used to save a reusable block that's in the store to the REST API. @@ -1679,7 +1679,7 @@ the REST API. * id: The ID of the reusable block to save. -### deleteReusableBlock +### __experimentalDeleteReusableBlock Returns an action object used to delete a reusable block via the REST API. @@ -1687,7 +1687,7 @@ Returns an action object used to delete a reusable block via the REST API. * id: The ID of the reusable block to delete. -### updateReusableBlockTitle +### __experimentalUpdateReusableBlockTitle Returns an action object used in signalling that a reusable block's title is to be updated. @@ -1697,7 +1697,7 @@ to be updated. * id: The ID of the reusable block to update. * title: The new title. -### convertBlockToStatic +### __experimentalConvertBlockToStatic Returns an action object used to convert a reusable block into a static block. @@ -1705,7 +1705,7 @@ Returns an action object used to convert a reusable block into a static block. * clientId: The client ID of the block to attach. -### convertBlockToReusable +### __experimentalConvertBlockToReusable Returns an action object used to convert a static block into a reusable block. @@ -1776,4 +1776,6 @@ Returns an action object signaling that a new term is added to the edited post. * slug: Taxonomy slug. * term: Term object. -### createNotice \ No newline at end of file +### createNotice + +### fetchReusableBlocks \ No newline at end of file diff --git a/docs/reference/deprecated.md b/docs/reference/deprecated.md index bae63e3d84877e..252b56c2ef809d 100644 --- a/docs/reference/deprecated.md +++ b/docs/reference/deprecated.md @@ -31,6 +31,7 @@ Gutenberg's deprecation policy is intended to support backwards-compatibility fo - `wp.components.CodeEditor` has been removed. Used `wp.codeEditor` directly instead. - `wp.blocks.setUnknownTypeHandlerName` has been removed. Please use `setFreeformContentHandlerName` and `setUnregisteredTypeHandlerName` instead. - `wp.blocks.getUnknownTypeHandlerName` has been removed. Please use `getFreeformContentHandlerName` and `getUnregisteredTypeHandlerName` instead. +- The Reusable Blocks Data API was marked as experimental as it's subject to change in the future. ## 4.1.0 diff --git a/packages/block-library/src/block/edit.js b/packages/block-library/src/block/edit.js index fb523cd5c95373..d95b07aedb9150 100644 --- a/packages/block-library/src/block/edit.js +++ b/packages/block-library/src/block/edit.js @@ -146,9 +146,9 @@ class ReusableBlockEdit extends Component { export default compose( [ withSelect( ( select, ownProps ) => { const { - getReusableBlock, - isFetchingReusableBlock, - isSavingReusableBlock, + __experimentalGetReusableBlock: getReusableBlock, + __experimentalIsFetchingReusableBlock: isFetchingReusableBlock, + __experimentalIsSavingReusableBlock: isSavingReusableBlock, getBlock, } = select( 'core/editor' ); const { ref } = ownProps.attributes; @@ -163,10 +163,10 @@ export default compose( [ } ), withDispatch( ( dispatch, ownProps ) => { const { - fetchReusableBlocks, + __experimentalFetchReusableBlocks: fetchReusableBlocks, updateBlockAttributes, - updateReusableBlockTitle, - saveReusableBlock, + __experimentalUpdateReusableBlockTitle: updateReusableBlockTitle, + __experimentalSaveReusableBlock: saveReusableBlock, } = dispatch( 'core/editor' ); const { ref } = ownProps.attributes; diff --git a/packages/editor/CHANGELOG.md b/packages/editor/CHANGELOG.md index 70cb95e06f342a..8ef9c5cce31eaf 100644 --- a/packages/editor/CHANGELOG.md +++ b/packages/editor/CHANGELOG.md @@ -1,3 +1,9 @@ +## 6.1.0 (Unreleased) + +### Deprecations + +- The Reusable Blocks Data API is marked as experimental as it's subject to change in the future ([#11230](https://github.com/WordPress/gutenberg/pull/11230)). + ## 6.0.1 (2018-10-30) ### Bug Fixes diff --git a/packages/editor/src/components/block-settings-menu/reusable-block-convert-button.js b/packages/editor/src/components/block-settings-menu/reusable-block-convert-button.js index b30569720edfb4..84530fb22bbef3 100644 --- a/packages/editor/src/components/block-settings-menu/reusable-block-convert-button.js +++ b/packages/editor/src/components/block-settings-menu/reusable-block-convert-button.js @@ -49,7 +49,11 @@ export function ReusableBlockConvertButton( { export default compose( [ withSelect( ( select, { clientIds } ) => { - const { getBlock, canInsertBlockType, getReusableBlock } = select( 'core/editor' ); + const { + getBlock, + canInsertBlockType, + __experimentalGetReusableBlock: getReusableBlock, + } = select( 'core/editor' ); const { getFreeformFallbackBlockName, getUnregisteredFallbackBlockName, @@ -85,8 +89,8 @@ export default compose( [ } ), withDispatch( ( dispatch, { clientIds, onToggle = noop } ) => { const { - convertBlockToReusable, - convertBlockToStatic, + __experimentalConvertBlockToReusable: convertBlockToReusable, + __experimentalConvertBlockToStatic: convertBlockToStatic, } = dispatch( 'core/editor' ); return { diff --git a/packages/editor/src/components/block-settings-menu/reusable-block-delete-button.js b/packages/editor/src/components/block-settings-menu/reusable-block-delete-button.js index 537af329a9d3aa..52f2ad08108f93 100644 --- a/packages/editor/src/components/block-settings-menu/reusable-block-delete-button.js +++ b/packages/editor/src/components/block-settings-menu/reusable-block-delete-button.js @@ -31,7 +31,10 @@ export function ReusableBlockDeleteButton( { reusableBlock, onDelete } ) { export default compose( [ withSelect( ( select, { clientId } ) => { - const { getBlock, getReusableBlock } = select( 'core/editor' ); + const { + getBlock, + __experimentalGetReusableBlock: getReusableBlock, + } = select( 'core/editor' ); const block = getBlock( clientId ); return { reusableBlock: block && isReusableBlock( block ) ? getReusableBlock( block.attributes.ref ) : null, @@ -39,7 +42,7 @@ export default compose( [ } ), withDispatch( ( dispatch, { onToggle = noop } ) => { const { - deleteReusableBlock, + __experimentalDeleteReusableBlock: deleteReusableBlock, } = dispatch( 'core/editor' ); return { diff --git a/packages/editor/src/components/inserter/menu.js b/packages/editor/src/components/inserter/menu.js index 7af57b6af6adda..4bb2362377c390 100644 --- a/packages/editor/src/components/inserter/menu.js +++ b/packages/editor/src/components/inserter/menu.js @@ -351,7 +351,7 @@ export default compose( }; } ), withDispatch( ( dispatch ) => ( { - fetchReusableBlocks: dispatch( 'core/editor' ).fetchReusableBlocks, + fetchReusableBlocks: dispatch( 'core/editor' ).__experimentalFetchReusableBlocks, showInsertionPoint: dispatch( 'core/editor' ).showInsertionPoint, hideInsertionPoint: dispatch( 'core/editor' ).hideInsertionPoint, } ) ), diff --git a/packages/editor/src/hooks/default-autocompleters.js b/packages/editor/src/hooks/default-autocompleters.js index e1615b41334668..6ab43ed47d6abc 100644 --- a/packages/editor/src/hooks/default-autocompleters.js +++ b/packages/editor/src/hooks/default-autocompleters.js @@ -17,7 +17,7 @@ import { blockAutocompleter, userAutocompleter } from '../components'; const defaultAutocompleters = [ userAutocompleter ]; -const fetchReusableBlocks = once( () => dispatch( 'core/editor' ).fetchReusableBlocks() ); +const fetchReusableBlocks = once( () => dispatch( 'core/editor' ).__experimentalFetchReusableBlocks() ); function setDefaultCompleters( completers, blockName ) { if ( ! completers ) { diff --git a/packages/editor/src/store/actions.js b/packages/editor/src/store/actions.js index bf2fd1f7a73408..2935b833270f0e 100644 --- a/packages/editor/src/store/actions.js +++ b/packages/editor/src/store/actions.js @@ -578,7 +578,7 @@ export function updatePostLock( lock ) { * * @return {Object} Action object. */ -export function fetchReusableBlocks( id ) { +export function __experimentalFetchReusableBlocks( id ) { return { type: 'FETCH_REUSABLE_BLOCKS', id, @@ -595,7 +595,7 @@ export function fetchReusableBlocks( id ) { * * @return {Object} Action object. */ -export function receiveReusableBlocks( results ) { +export function __experimentalReceiveReusableBlocks( results ) { return { type: 'RECEIVE_REUSABLE_BLOCKS', results, @@ -610,7 +610,7 @@ export function receiveReusableBlocks( results ) { * * @return {Object} Action object. */ -export function saveReusableBlock( id ) { +export function __experimentalSaveReusableBlock( id ) { return { type: 'SAVE_REUSABLE_BLOCK', id, @@ -624,7 +624,7 @@ export function saveReusableBlock( id ) { * * @return {Object} Action object. */ -export function deleteReusableBlock( id ) { +export function __experimentalDeleteReusableBlock( id ) { return { type: 'DELETE_REUSABLE_BLOCK', id, @@ -640,7 +640,7 @@ export function deleteReusableBlock( id ) { * * @return {Object} Action object. */ -export function updateReusableBlockTitle( id, title ) { +export function __experimentalUpdateReusableBlockTitle( id, title ) { return { type: 'UPDATE_REUSABLE_BLOCK_TITLE', id, @@ -655,7 +655,7 @@ export function updateReusableBlockTitle( id, title ) { * * @return {Object} Action object. */ -export function convertBlockToStatic( clientId ) { +export function __experimentalConvertBlockToStatic( clientId ) { return { type: 'CONVERT_BLOCK_TO_STATIC', clientId, @@ -669,7 +669,7 @@ export function convertBlockToStatic( clientId ) { * * @return {Object} Action object. */ -export function convertBlockToReusable( clientIds ) { +export function __experimentalConvertBlockToReusable( clientIds ) { return { type: 'CONVERT_BLOCK_TO_REUSABLE', clientIds: castArray( clientIds ), @@ -821,3 +821,80 @@ export const createSuccessNotice = partial( createNotice, 'success' ); export const createInfoNotice = partial( createNotice, 'info' ); export const createErrorNotice = partial( createNotice, 'error' ); export const createWarningNotice = partial( createNotice, 'warning' ); + +// +// Deprecated +// + +export function fetchReusableBlocks( id ) { + deprecated( "wp.data.dispatch( 'core/editor' ).fetchReusableBlocks( id )", { + alternative: "wp.data.select( 'core' ).getEntityRecords( 'postType', 'wp_block' )", + plugin: 'Gutenberg', + version: '4.4.0', + } ); + + return __experimentalFetchReusableBlocks( id ); +} + +export function receiveReusableBlocks( results ) { + deprecated( "wp.data.dispatch( 'core/editor' ).receiveReusableBlocks( results )", { + alternative: "wp.data.select( 'core' ).getEntityRecords( 'postType', 'wp_block' )", + plugin: 'Gutenberg', + version: '4.4.0', + } ); + + return __experimentalReceiveReusableBlocks( results ); +} + +export function saveReusableBlock( id ) { + deprecated( "wp.data.dispatch( 'core/editor' ).saveReusableBlock( id )", { + alternative: "wp.data.dispatch( 'core' ).saveEntityRecord( 'postType', 'wp_block', reusableBlock )", + plugin: 'Gutenberg', + version: '4.4.0', + } ); + + return __experimentalSaveReusableBlock( id ); +} + +export function deleteReusableBlock( id ) { + deprecated( 'deleteReusableBlock action (`core/editor` store)', { + alternative: '__experimentalDeleteReusableBlock action (`core/edtior` store)', + plugin: 'Gutenberg', + version: '4.4.0', + hint: 'Using experimental APIs is strongly discouraged as they are subject to removal without notice.', + } ); + + return __experimentalDeleteReusableBlock( id ); +} + +export function updateReusableBlockTitle( id, title ) { + deprecated( "wp.data.dispatch( 'core/editor' ).updateReusableBlockTitle( id, title )", { + alternative: "wp.data.dispatch( 'core' ).saveEntityRecord( 'postType', 'wp_block', reusableBlock )", + plugin: 'Gutenberg', + version: '4.4.0', + } ); + + return __experimentalUpdateReusableBlockTitle( id, title ); +} + +export function convertBlockToStatic( id ) { + deprecated( 'convertBlockToStatic action (`core/editor` store)', { + alternative: '__experimentalConvertBlockToStatic action (`core/edtior` store)', + plugin: 'Gutenberg', + version: '4.4.0', + hint: 'Using experimental APIs is strongly discouraged as they are subject to removal without notice.', + } ); + + return __experimentalConvertBlockToStatic( id ); +} + +export function convertBlockToReusable( id ) { + deprecated( 'convertBlockToReusable action (`core/editor` store)', { + alternative: '__experimentalConvertBlockToReusable action (`core/edtior` store)', + plugin: 'Gutenberg', + version: '4.4.0', + hint: 'Using experimental APIs is strongly discouraged as they are subject to removal without notice.', + } ); + + return __experimentalConvertBlockToReusable( id ); +} diff --git a/packages/editor/src/store/effects/reusable-blocks.js b/packages/editor/src/store/effects/reusable-blocks.js index 7d9795d64d34d6..0c569728b6a39d 100644 --- a/packages/editor/src/store/effects/reusable-blocks.js +++ b/packages/editor/src/store/effects/reusable-blocks.js @@ -26,14 +26,14 @@ import { dispatch as dataDispatch } from '@wordpress/data'; */ import { resolveSelector } from './utils'; import { - receiveReusableBlocks as receiveReusableBlocksAction, + __experimentalReceiveReusableBlocks as receiveReusableBlocksAction, removeBlocks, replaceBlocks, receiveBlocks, - saveReusableBlock, + __experimentalSaveReusableBlock as saveReusableBlock, } from '../actions'; import { - getReusableBlock, + __experimentalGetReusableBlock as getReusableBlock, getBlock, getBlocks, getBlocksByClientId, diff --git a/packages/editor/src/store/effects/test/reusable-blocks.js b/packages/editor/src/store/effects/test/reusable-blocks.js index 4aca3995d165a9..2cc3b83e4f36f7 100644 --- a/packages/editor/src/store/effects/test/reusable-blocks.js +++ b/packages/editor/src/store/effects/test/reusable-blocks.js @@ -27,13 +27,13 @@ import { import { resetBlocks, receiveBlocks, - saveReusableBlock, - deleteReusableBlock, + __experimentalSaveReusableBlock as saveReusableBlock, + __experimentalDeleteReusableBlock as deleteReusableBlock, removeBlocks, - convertBlockToReusable as convertBlockToReusableAction, - convertBlockToStatic as convertBlockToStaticAction, - receiveReusableBlocks as receiveReusableBlocksAction, - fetchReusableBlocks as fetchReusableBlocksAction, + __experimentalConvertBlockToReusable as convertBlockToReusableAction, + __experimentalConvertBlockToStatic as convertBlockToStaticAction, + __experimentalReceiveReusableBlocks as receiveReusableBlocksAction, + __experimentalFetchReusableBlocks as fetchReusableBlocksAction, } from '../../actions'; import reducer from '../../reducer'; import '../../..'; // Ensure store dependencies are imported via root. diff --git a/packages/editor/src/store/selectors.js b/packages/editor/src/store/selectors.js index 1c5036e3d73ccb..ed734f7e5dcbfd 100644 --- a/packages/editor/src/store/selectors.js +++ b/packages/editor/src/store/selectors.js @@ -1738,7 +1738,7 @@ export const getInserterItems = createSelector( .filter( shouldIncludeBlockType ) .map( buildBlockTypeInserterItem ); - const reusableBlockInserterItems = getReusableBlocks( state ) + const reusableBlockInserterItems = __experimentalGetReusableBlocks( state ) .filter( shouldIncludeReusableBlock ) .map( buildReusableBlockInserterItem ); @@ -1768,7 +1768,7 @@ export const getInserterItems = createSelector( * * @return {Object} The reusable block, or null if none exists. */ -export const getReusableBlock = createSelector( +export const __experimentalGetReusableBlock = createSelector( ( state, ref ) => { const block = state.reusableBlocks.data[ ref ]; if ( ! block ) { @@ -1796,7 +1796,7 @@ export const getReusableBlock = createSelector( * * @return {boolean} Whether or not the reusable block is being saved. */ -export function isSavingReusableBlock( state, ref ) { +export function __experimentalIsSavingReusableBlock( state, ref ) { return state.reusableBlocks.isSaving[ ref ] || false; } @@ -1809,7 +1809,7 @@ export function isSavingReusableBlock( state, ref ) { * * @return {boolean} Whether the reusable block is being fetched. */ -export function isFetchingReusableBlock( state, ref ) { +export function __experimentalIsFetchingReusableBlock( state, ref ) { return !! state.reusableBlocks.isFetching[ ref ]; } @@ -1820,8 +1820,11 @@ export function isFetchingReusableBlock( state, ref ) { * * @return {Array} An array of all reusable blocks. */ -export function getReusableBlocks( state ) { - return map( state.reusableBlocks.data, ( value, ref ) => getReusableBlock( state, ref ) ); +export function __experimentalGetReusableBlocks( state ) { + return map( + state.reusableBlocks.data, + ( value, ref ) => __experimentalGetReusableBlock( state, ref ) + ); } /** @@ -2077,3 +2080,44 @@ export function getNotices() { return select( 'core/notices' ).getNotices(); } + +export function getReusableBlock( state, ref ) { + deprecated( "wp.data.select( 'core/editor' ).getReusableBlock( ref )", { + alternative: "wp.data.select( 'core' ).getEntityRecord( 'postType', 'wp_block', ref )", + plugin: 'Gutenberg', + version: '4.4.0', + } ); + + return __experimentalGetReusableBlock( state, ref ); +} + +export function isSavingReusableBlock( state, ref ) { + deprecated( 'isSavingReusableBlock selector (`core/editor` store)', { + alternative: '__experimentalIsSavingReusableBlock selector (`core/edtior` store)', + plugin: 'Gutenberg', + version: '4.4.0', + hint: 'Using experimental APIs is strongly discouraged as they are subject to removal without notice.', + } ); + + return __experimentalIsSavingReusableBlock( state, ref ); +} + +export function isFetchingReusableBlock( state, ref ) { + deprecated( "wp.data.select( 'core/editor' ).isFetchingReusableBlock( ref )", { + alternative: "wp.data.select( 'core' ).isResolving( 'getEntityRecord', 'wp_block', ref )", + plugin: 'Gutenberg', + version: '4.4.0', + } ); + + return __experimentalIsFetchingReusableBlock( state, ref ); +} + +export function getReusableBlocks( state ) { + deprecated( "wp.data.select( 'core/editor' ).getReusableBlocks( ref )", { + alternative: "wp.data.select( 'core' ).getEntityRecords( 'postType', 'wp_block' )", + plugin: 'Gutenberg', + version: '4.4.0', + } ); + + return __experimentalGetReusableBlocks( state ); +} diff --git a/packages/editor/src/store/test/actions.js b/packages/editor/src/store/test/actions.js index 9c776f0cc47e80..4358054f8573b4 100644 --- a/packages/editor/src/store/test/actions.js +++ b/packages/editor/src/store/test/actions.js @@ -7,11 +7,11 @@ import { stopTyping, enterFormattedText, exitFormattedText, - fetchReusableBlocks, - saveReusableBlock, - deleteReusableBlock, - convertBlockToStatic, - convertBlockToReusable, + __experimentalFetchReusableBlocks as fetchReusableBlocks, + __experimentalSaveReusableBlock as saveReusableBlock, + __experimentalDeleteReusableBlock as deleteReusableBlock, + __experimentalConvertBlockToStatic as convertBlockToStatic, + __experimentalConvertBlockToReusable as convertBlockToReusable, toggleSelection, setupEditor, resetPost, diff --git a/packages/editor/src/store/test/selectors.js b/packages/editor/src/store/test/selectors.js index f94b4c407e3454..dcfb2016d369ba 100644 --- a/packages/editor/src/store/test/selectors.js +++ b/packages/editor/src/store/test/selectors.js @@ -90,11 +90,11 @@ const { didPostSaveRequestFail, getSuggestedPostFormat, getEditedPostContent, - getReusableBlock, - isSavingReusableBlock, - isFetchingReusableBlock, + __experimentalGetReusableBlock: getReusableBlock, + __experimentalIsSavingReusableBlock: isSavingReusableBlock, + __experimentalIsFetchingReusableBlock: isFetchingReusableBlock, isSelectionEnabled, - getReusableBlocks, + __experimentalGetReusableBlocks: getReusableBlocks, getStateBeforeOptimisticTransaction, isPublishingPost, isPublishSidebarEnabled,