Skip to content

Commit

Permalink
Try refactoring the reusable blocks to use a separate block editor
Browse files Browse the repository at this point in the history
  • Loading branch information
youknowriad committed Mar 12, 2019
1 parent 3edaae7 commit e0e10f7
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 136 deletions.
33 changes: 31 additions & 2 deletions packages/block-editor/src/store/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
orderBy,
reduce,
some,
find,
} from 'lodash';
import createSelector from 'rememo';

Expand All @@ -25,6 +26,7 @@ import {
getBlockTypes,
hasBlockSupport,
hasChildBlocksWithInserterSupport,
parse,
} from '@wordpress/blocks';

/***
Expand Down Expand Up @@ -1129,7 +1131,8 @@ const canIncludeReusableBlockInInserter = ( state, reusableBlock, rootClientId )
return false;
}

const referencedBlockName = getBlockName( state, reusableBlock.clientId );
const referencedBlocks = __experimentalGetParsedReusableBlock( state, reusableBlock.id );
const referencedBlockName = referencedBlocks ? referencedBlocks[ 0 ].name : null;
if ( ! referencedBlockName ) {
return false;
}
Expand Down Expand Up @@ -1251,7 +1254,8 @@ export const getInserterItems = createSelector(
const buildReusableBlockInserterItem = ( reusableBlock ) => {
const id = `core/block/${ reusableBlock.id }`;

const referencedBlockName = getBlockName( state, reusableBlock.clientId );
const referencedBlocks = __experimentalGetParsedReusableBlock( state, reusableBlock.id );
const referencedBlockName = referencedBlocks[ 0 ].name;
const referencedBlockType = getBlockType( referencedBlockName );

const { time, count = 0 } = getInsertUsage( state, id ) || {};
Expand Down Expand Up @@ -1367,6 +1371,31 @@ export function isLastBlockChangePersistent( state ) {
return state.blocks.isPersistentChange;
}

/**
* Returns the parsed block saved as shared block with the given ID.
*
* @param {Object} state Global application state.
* @param {number|string} ref The shared block's ID.
*
* @return {Object} The parsed block.
*/
export const __experimentalGetParsedReusableBlock = createSelector(
( state, ref ) => {
const reusableBlock = find(
getReusableBlocks( state ),
( block ) => block.id === ref
);
if ( ! reusableBlock ) {
return null;
}

return parse( reusableBlock.content );
},
( state ) => [
getReusableBlocks( state ),
],
);

/**
* Returns the value of a post meta from the editor settings.
*
Expand Down
71 changes: 31 additions & 40 deletions packages/block-library/src/block/edit.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { noop, partial } from 'lodash';
import { partial } from 'lodash';

/**
* WordPress dependencies
Expand All @@ -10,22 +10,23 @@ import { Component, Fragment } from '@wordpress/element';
import { Placeholder, Spinner, Disabled } from '@wordpress/components';
import { withSelect, withDispatch } from '@wordpress/data';
import { __ } from '@wordpress/i18n';
import { BlockEdit } from '@wordpress/block-editor';
import { BlockEditorProvider } from '@wordpress/block-editor';
import { compose } from '@wordpress/compose';

/**
* Internal dependencies
*/
import ReusableBlockEditPanel from './edit-panel';
import ReusableBlockIndicator from './indicator';
import { parse, serialize } from 'path';

class ReusableBlockEdit extends Component {
constructor( { reusableBlock } ) {
super( ...arguments );

this.startEditing = this.startEditing.bind( this );
this.stopEditing = this.stopEditing.bind( this );
this.setAttributes = this.setAttributes.bind( this );
this.setBlocks = this.setBlocks.bind( this );
this.setTitle = this.setTitle.bind( this );
this.save = this.save.bind( this );

Expand All @@ -34,14 +35,14 @@ class ReusableBlockEdit extends Component {
this.state = {
isEditing: true,
title: reusableBlock.title,
changedAttributes: {},
blocks: [],
};
} else {
// Start in preview mode when we're working with an existing reusable block
this.state = {
isEditing: false,
title: null,
changedAttributes: null,
blocks: [],
};
}
}
Expand All @@ -58,65 +59,57 @@ class ReusableBlockEdit extends Component {
this.setState( {
isEditing: true,
title: reusableBlock.title,
changedAttributes: {},
blocks: parse( reusableBlock.content ),
} );
}

stopEditing() {
this.setState( {
isEditing: false,
title: null,
changedAttributes: null,
blocks: [],
} );
}

setAttributes( attributes ) {
this.setState( ( prevState ) => {
if ( prevState.changedAttributes !== null ) {
return { changedAttributes: { ...prevState.changedAttributes, ...attributes } };
}
} );
setBlocks( blocks ) {
this.setState( { blocks } );
}

setTitle( title ) {
this.setState( { title } );
}

save() {
const { reusableBlock, onUpdateTitle, updateAttributes, block, onSave } = this.props;
const { title, changedAttributes } = this.state;

if ( title !== reusableBlock.title ) {
onUpdateTitle( title );
}

updateAttributes( block.clientId, changedAttributes );
const { onChange, onSave } = this.props;
const { blocks, title } = this.state;
const content = serialize( blocks );
onChange( { title, content } );
onSave();

this.stopEditing();
}

render() {
const { isSelected, reusableBlock, block, isFetching, isSaving, canUpdateBlock } = this.props;
const { isEditing, title, changedAttributes } = this.state;
const { isSelected, reusableBlock, isFetching, isSaving, canUpdateBlock, settings } = this.props;
const { isEditing, title, blocks } = this.state;

if ( ! reusableBlock && isFetching ) {
return <Placeholder><Spinner /></Placeholder>;
}

if ( ! reusableBlock || ! block ) {
if ( ! reusableBlock ) {
return <Placeholder>{ __( 'Block has been deleted or is unavailable.' ) }</Placeholder>;
}

let element = (
<BlockEdit
{ ...this.props }
isSelected={ isEditing && isSelected }
clientId={ block.clientId }
name={ block.name }
attributes={ { ...block.attributes, ...changedAttributes } }
setAttributes={ isEditing ? this.setAttributes : noop }
/>
<BlockEditorProvider
settings={ settings }
value={ blocks }
onChange={ this.setBlocks }
onInput={ this.setBlocks }
>
<div>test sdfsdf sdf sdf</div>
</BlockEditorProvider>
);

if ( ! isEditing ) {
Expand Down Expand Up @@ -153,7 +146,8 @@ export default compose( [
} = select( 'core/editor' );
const { canUser } = select( 'core' );
const {
getBlock,
__experimentalGetParsedReusableBlock,
getSettings,
} = select( 'core/block-editor' );
const { ref } = ownProps.attributes;
const reusableBlock = getReusableBlock( ref );
Expand All @@ -162,25 +156,22 @@ export default compose( [
reusableBlock,
isFetching: isFetchingReusableBlock( ref ),
isSaving: isSavingReusableBlock( ref ),
block: reusableBlock ? getBlock( reusableBlock.clientId ) : null,
blocks: reusableBlock ? __experimentalGetParsedReusableBlock( reusableBlock.id ) : null,
canUpdateBlock: !! reusableBlock && ! reusableBlock.isTemporary && !! canUser( 'update', 'blocks', ref ),
settings: getSettings(),
};
} ),
withDispatch( ( dispatch, ownProps ) => {
const {
__experimentalFetchReusableBlocks: fetchReusableBlocks,
__experimentalUpdateReusableBlockTitle: updateReusableBlockTitle,
__experimentalUpdateReusableBlock: updateReusableBlock,
__experimentalSaveReusableBlock: saveReusableBlock,
} = dispatch( 'core/editor' );
const {
updateBlockAttributes,
} = dispatch( 'core/block-editor' );
const { ref } = ownProps.attributes;

return {
fetchReusableBlock: partial( fetchReusableBlocks, ref ),
updateAttributes: updateBlockAttributes,
onUpdateTitle: partial( updateReusableBlockTitle, ref ),
onChange: partial( updateReusableBlock, ref ),
onSave: partial( saveReusableBlock, ref ),
};
} ),
Expand Down
12 changes: 6 additions & 6 deletions packages/editor/src/store/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -585,19 +585,19 @@ export function __experimentalDeleteReusableBlock( id ) {
}

/**
* Returns an action object used in signalling that a reusable block's title is
* Returns an action object used in signalling that a reusable block is
* to be updated.
*
* @param {number} id The ID of the reusable block to update.
* @param {string} title The new title.
* @param {number} id The ID of the reusable block to update.
* @param {Object} changes The changes to apply.
*
* @return {Object} Action object.
*/
export function __experimentalUpdateReusableBlockTitle( id, title ) {
export function __experimentalUpdateReusableBlock( id, changes ) {
return {
type: 'UPDATE_REUSABLE_BLOCK_TITLE',
type: 'UPDATE_REUSABLE_BLOCK',
id,
title,
changes,
};
}

Expand Down
2 changes: 0 additions & 2 deletions packages/editor/src/store/effects.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import {
deleteReusableBlocks,
convertBlockToReusable,
convertBlockToStatic,
receiveReusableBlocks,
} from './effects/reusable-blocks';

export default {
Expand Down Expand Up @@ -63,7 +62,6 @@ export default {
DELETE_REUSABLE_BLOCK: ( action, store ) => {
deleteReusableBlocks( action, store );
},
RECEIVE_REUSABLE_BLOCKS: receiveReusableBlocks,
CONVERT_BLOCK_TO_STATIC: convertBlockToStatic,
CONVERT_BLOCK_TO_REUSABLE: convertBlockToReusable,
};
Loading

0 comments on commit e0e10f7

Please sign in to comment.