diff --git a/docs/designers-developers/developers/data/data-core-editor.md b/docs/designers-developers/developers/data/data-core-editor.md index cd251dc92d678..34016e7153662 100644 --- a/docs/designers-developers/developers/data/data-core-editor.md +++ b/docs/designers-developers/developers/data/data-core-editor.md @@ -734,7 +734,7 @@ The editor settings object. ### setupEditor -Returns an action object used in signalling that editor has initialized with +Returns an action generator used in signalling that editor has initialized with the specified post object and editor settings. *Parameters* diff --git a/package-lock.json b/package-lock.json index d8bc6f6abec6f..44e9965126ee6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2829,7 +2829,6 @@ "lodash": "^4.17.11", "memize": "^1.0.5", "react-autosize-textarea": "^3.0.2", - "redux-multi": "^0.1.12", "redux-optimist": "^1.0.0", "refx": "^3.0.0", "rememo": "^3.0.0", diff --git a/packages/editor/CHANGELOG.md b/packages/editor/CHANGELOG.md index ce396bfa582ec..cefab057402b6 100644 --- a/packages/editor/CHANGELOG.md +++ b/packages/editor/CHANGELOG.md @@ -1,3 +1,10 @@ +## 9.1.1 (Unreleased) + +### Internal + +- Refactor setupEditor effects to action-generator using controls ([#14513](https://github.com/WordPress/gutenberg/pull/14513)) +- Remove redux-multi dependency (no longer needed/used with above refactor) + ## 9.1.0 (2019-03-06) ### New Features diff --git a/packages/editor/package.json b/packages/editor/package.json index f2132eb5c6e67..844cf5fcd58fe 100644 --- a/packages/editor/package.json +++ b/packages/editor/package.json @@ -47,7 +47,6 @@ "lodash": "^4.17.11", "memize": "^1.0.5", "react-autosize-textarea": "^3.0.2", - "redux-multi": "^0.1.12", "redux-optimist": "^1.0.0", "refx": "^3.0.0", "rememo": "^3.0.0", diff --git a/packages/editor/src/store/actions.js b/packages/editor/src/store/actions.js index c0c88d1072fe9..32f3bed210e10 100644 --- a/packages/editor/src/store/actions.js +++ b/packages/editor/src/store/actions.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import { castArray, pick } from 'lodash'; +import { castArray, pick, has } from 'lodash'; import { BEGIN, COMMIT, REVERT } from 'redux-optimist'; /** @@ -26,22 +26,49 @@ import { } from './utils/notice-builder'; /** - * Returns an action object used in signalling that editor has initialized with + * WordPress dependencies + */ +import { + parse, + synchronizeBlocksWithTemplate, +} from '@wordpress/blocks'; + +/** + * Returns an action generator used in signalling that editor has initialized with * the specified post object and editor settings. * * @param {Object} post Post object. * @param {Object} edits Initial edited attributes object. * @param {Array?} template Block Template. - * - * @return {Object} Action object. */ -export function setupEditor( post, edits, template ) { - return { +export function* setupEditor( post, edits, template ) { + yield { type: 'SETUP_EDITOR', post, edits, template, }; + + // In order to ensure maximum of a single parse during setup, edits are + // included as part of editor setup action. Assume edited content as + // canonical if provided, falling back to post. + let content; + if ( has( edits, [ 'content' ] ) ) { + content = edits.content; + } else { + content = post.content.raw; + } + + let blocks = parse( content ); + + // Apply a template for new posts only, if exists. + const isNewPost = post.status === 'auto-draft'; + if ( isNewPost && template ) { + blocks = synchronizeBlocksWithTemplate( blocks, template ); + } + + yield resetEditorBlocks( blocks ); + yield setupEditorState( post ); } /** diff --git a/packages/editor/src/store/effects.js b/packages/editor/src/store/effects.js index 84f5115113766..0893f8315cbf1 100644 --- a/packages/editor/src/store/effects.js +++ b/packages/editor/src/store/effects.js @@ -1,23 +1,6 @@ -/** - * External dependencies - */ -import { has } from 'lodash'; - -/** - * WordPress dependencies - */ -import { - parse, - synchronizeBlocksWithTemplate, -} from '@wordpress/blocks'; - /** * Internal dependencies */ -import { - setupEditorState, - resetEditorBlocks, -} from './actions'; import { fetchReusableBlocks, saveReusableBlocks, @@ -28,32 +11,6 @@ import { } from './effects/reusable-blocks'; export default { - SETUP_EDITOR( action ) { - const { post, edits, template } = action; - - // In order to ensure maximum of a single parse during setup, edits are - // included as part of editor setup action. Assume edited content as - // canonical if provided, falling back to post. - let content; - if ( has( edits, [ 'content' ] ) ) { - content = edits.content; - } else { - content = post.content.raw; - } - - let blocks = parse( content ); - - // Apply a template for new posts only, if exists. - const isNewPost = post.status === 'auto-draft'; - if ( isNewPost && template ) { - blocks = synchronizeBlocksWithTemplate( blocks, template ); - } - - return [ - resetEditorBlocks( blocks ), - setupEditorState( post ), - ]; - }, FETCH_REUSABLE_BLOCKS: ( action, store ) => { fetchReusableBlocks( action, store ); }, diff --git a/packages/editor/src/store/middlewares.js b/packages/editor/src/store/middlewares.js index 6381132bb81e0..b19b1b9bb5817 100644 --- a/packages/editor/src/store/middlewares.js +++ b/packages/editor/src/store/middlewares.js @@ -2,8 +2,6 @@ * External dependencies */ import refx from 'refx'; -import multi from 'redux-multi'; -import { flowRight } from 'lodash'; /** * Internal dependencies @@ -18,25 +16,19 @@ import effects from './effects'; * @return {Object} Update Store Object. */ function applyMiddlewares( store ) { - const middlewares = [ - refx( effects ), - multi, - ]; - let enhancedDispatch = () => { throw new Error( 'Dispatching while constructing your middleware is not allowed. ' + 'Other middleware would not be applied to this dispatch.' ); }; - let chain = []; const middlewareAPI = { getState: store.getState, dispatch: ( ...args ) => enhancedDispatch( ...args ), }; - chain = middlewares.map( ( middleware ) => middleware( middlewareAPI ) ); - enhancedDispatch = flowRight( ...chain )( store.dispatch ); + + enhancedDispatch = refx( effects )( middlewareAPI )( store.dispatch ); store.dispatch = enhancedDispatch; return store; diff --git a/packages/editor/src/store/test/actions.js b/packages/editor/src/store/test/actions.js index 296a365fe4c49..3f0e453b384eb 100644 --- a/packages/editor/src/store/test/actions.js +++ b/packages/editor/src/store/test/actions.js @@ -625,16 +625,35 @@ describe( 'Post generator actions', () => { } ); } ); -describe( 'actions', () => { - describe( 'setupEditor', () => { - it( 'should return the SETUP_EDITOR action', () => { - const post = {}; - const result = actions.setupEditor( post ); - expect( result ).toEqual( { - type: 'SETUP_EDITOR', +describe( 'Editor actions', () => { + describe( 'setupEditor()', () => { + let fulfillment; + const reset = ( post, edits, template ) => fulfillment = actions + .setupEditor( post, + edits, + template, + ); + it( 'should yield the SETUP_EDITOR action', () => { + reset( { content: { raw: '' }, status: 'publish' } ); + const { value } = fulfillment.next(); + expect( value ).toEqual( { + type: 'SETUP_EDITOR', + post: { content: { raw: '' }, status: 'publish' }, } ); } ); + it( 'should yield action object for resetEditorBlocks', () => { + const { value } = fulfillment.next(); + expect( value ).toEqual( actions.resetEditorBlocks( [] ) ); + } ); + it( 'should yield action object for setupEditorState', () => { + const { value } = fulfillment.next(); + expect( value ).toEqual( + actions.setupEditorState( + { content: { raw: '' }, status: 'publish' } + ) + ); + } ); } ); describe( 'resetPost', () => { diff --git a/packages/editor/src/store/test/effects.js b/packages/editor/src/store/test/effects.js deleted file mode 100644 index cdc7223858e0f..0000000000000 --- a/packages/editor/src/store/test/effects.js +++ /dev/null @@ -1,88 +0,0 @@ -/** - * WordPress dependencies - */ -import { - getBlockTypes, - unregisterBlockType, - registerBlockType, -} from '@wordpress/blocks'; - -/** - * Internal dependencies - */ -import { setupEditorState, resetEditorBlocks } from '../actions'; -import effects from '../effects'; -import '../../'; - -describe( 'effects', () => { - const defaultBlockSettings = { save: () => 'Saved', category: 'common', title: 'block title' }; - - describe( '.SETUP_EDITOR', () => { - const handler = effects.SETUP_EDITOR; - - afterEach( () => { - getBlockTypes().forEach( ( block ) => { - unregisterBlockType( block.name ); - } ); - } ); - - it( 'should return post reset action', () => { - const post = { - id: 1, - title: { - raw: 'A History of Pork', - }, - content: { - raw: '', - }, - status: 'draft', - }; - - const result = handler( { post, settings: {} } ); - - expect( result ).toEqual( [ - resetEditorBlocks( [] ), - setupEditorState( post, [], {} ), - ] ); - } ); - - it( 'should return block reset with non-empty content', () => { - registerBlockType( 'core/test-block', defaultBlockSettings ); - const post = { - id: 1, - title: { - raw: 'A History of Pork', - }, - content: { - raw: 'Saved', - }, - status: 'draft', - }; - - const result = handler( { post } ); - - expect( result[ 0 ].blocks ).toHaveLength( 1 ); - expect( result[ 1 ] ).toEqual( setupEditorState( post, result[ 0 ].blocks, {} ) ); - } ); - - it( 'should return post setup action only if auto-draft', () => { - const post = { - id: 1, - title: { - raw: 'A History of Pork', - }, - content: { - raw: '', - }, - status: 'auto-draft', - }; - - const result = handler( { post } ); - - expect( result ).toEqual( [ - resetEditorBlocks( [] ), - setupEditorState( post, [], { title: 'A History of Pork' } ), - ] ); - } ); - } ); -} );