Skip to content

Commit

Permalink
Blocks: Reimplement shared block as embedded editor
Browse files Browse the repository at this point in the history
  • Loading branch information
aduth committed Jun 21, 2018
1 parent 64a7c83 commit 58c5103
Show file tree
Hide file tree
Showing 24 changed files with 383 additions and 1,145 deletions.
39 changes: 37 additions & 2 deletions core-blocks/block/edit-panel/index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
/**
* External dependencies
*/
import { over, compact } from 'lodash';

/**
* WordPress dependencies
*/
import { Button, withInstanceId } from '@wordpress/components';
import { Component, Fragment, createRef } from '@wordpress/element';
import { Component, Fragment, createRef, compose } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import { keycodes } from '@wordpress/utils';
import { withSelect, withDispatch } from '@wordpress/data';

/**
* Internal dependencies
Expand Down Expand Up @@ -117,4 +123,33 @@ class SharedBlockEditPanel extends Component {
}
}

export default withInstanceId( SharedBlockEditPanel );
export default compose( [
withInstanceId,
withSelect( ( select ) => {
const { getEditedPostAttribute } = select( 'core/editor' );

return {
title: getEditedPostAttribute( 'title' ),
};
} ),
withDispatch( ( dispatch, ownProps ) => {
const {
editPost,
undoAll,
savePost,
clearSelectedBlock,
} = dispatch( 'core/editor' );

const withClearAndFinish = ( fn ) => over( compact( [
clearSelectedBlock,
ownProps.onFinishedEditing,
fn,
] ) );

return {
onChangeTitle: ( title ) => editPost( { title } ),
onSave: withClearAndFinish( savePost ),
onCancel: withClearAndFinish( undoAll ),
};
} ),
] )( SharedBlockEditPanel );
174 changes: 58 additions & 116 deletions core-blocks/block/edit.js
Original file line number Diff line number Diff line change
@@ -1,169 +1,111 @@
/**
* External dependencies
*/
import { noop, partial } from 'lodash';

/**
* WordPress dependencies
*/
import { Component, Fragment, compose } from '@wordpress/element';
import { Component, compose } from '@wordpress/element';
import { Placeholder, Spinner, Disabled } from '@wordpress/components';
import { withSelect, withDispatch } from '@wordpress/data';
import { __ } from '@wordpress/i18n';
import { BlockEdit } from '@wordpress/editor';
import { EditorProvider, BlockList } from '@wordpress/editor';
import isShallowEqual from '@wordpress/is-shallow-equal';

/**
* Internal dependencies
*/
import SharedBlockEditPanel from './edit-panel';
import SharedBlockIndicator from './indicator';
import SharedBlockSelection from './selection';

class SharedBlockEdit extends Component {
constructor( { sharedBlock } ) {
constructor( props ) {
super( ...arguments );

this.startEditing = this.startEditing.bind( this );
this.stopEditing = this.stopEditing.bind( this );
this.setAttributes = this.setAttributes.bind( this );
this.setTitle = this.setTitle.bind( this );
this.save = this.save.bind( this );
this.startEditing = this.toggleEditing.bind( this, true );
this.stopEditing = this.toggleEditing.bind( this, false );

const { sharedBlock, settings } = props;
this.state = {
isEditing: !! ( sharedBlock && sharedBlock.isTemporary ),
title: null,
changedAttributes: null,
settingsWithLock: { ...settings, templateLock: true },
};
}

componentDidMount() {
if ( ! this.props.sharedBlock ) {
this.props.fetchSharedBlock();
static getDerivedStateFromProps( props, prevState ) {
if ( isShallowEqual( props.settings, prevState.settings ) ) {
return null;
}
}

startEditing() {
const { sharedBlock } = this.props;

this.setState( {
isEditing: true,
title: sharedBlock.title,
changedAttributes: {},
} );
}

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

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

setTitle( title ) {
this.setState( { title } );
return {
settings: props.settings,
settingsWithLock: {
...props.settings,
templateLock: true,
},
};
}

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

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

updateAttributes( block.uid, changedAttributes );
onSave();

this.stopEditing();
toggleEditing( isEditing ) {
this.setState( { isEditing } );
}

render() {
const { isSelected, sharedBlock, block, isFetching, isSaving } = this.props;
const { isEditing, title, changedAttributes } = this.state;
const { setIsSelected, sharedBlock, isSelected, isSaving } = this.props;
const { settingsWithLock, isEditing } = this.state;

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

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

let element = (
<BlockEdit
{ ...this.props }
isSelected={ isEditing && isSelected }
id={ block.uid }
name={ block.name }
attributes={ { ...block.attributes, ...changedAttributes } }
setAttributes={ isEditing ? this.setAttributes : noop }
/>
);

let list = <BlockList />;
if ( ! isEditing ) {
element = <Disabled>{ element }</Disabled>;
list = <Disabled>{ list }</Disabled>;
}

return (
<Fragment>
{ element }
{ ( isSelected || isEditing ) && (
<SharedBlockEditPanel
isEditing={ isEditing }
title={ title !== null ? title : sharedBlock.title }
isSaving={ isSaving && ! sharedBlock.isTemporary }
onEdit={ this.startEditing }
onChangeTitle={ this.setTitle }
onSave={ this.save }
onCancel={ this.stopEditing }
/>
) }
{ ! isSelected && ! isEditing && <SharedBlockIndicator title={ sharedBlock.title } /> }
</Fragment>
<EditorProvider
reducerKey={ 'core/editor-shared-' + sharedBlock.id }
postType="wp_block"
inheritContext
settings={ settingsWithLock }
post={ sharedBlock }
>
<SharedBlockSelection
isSharedBlockSelected={ isSelected }
onBlockSelection={ setIsSelected }
>
{ list }
{ ( isSelected || isEditing ) && (
<SharedBlockEditPanel
isEditing={ isEditing }
isSaving={ isSaving && ! sharedBlock.isTemporary }
onEdit={ this.startEditing }
onFinishedEditing={ this.stopEditing }
/>
) }
{ ! isSelected && ! isEditing && <SharedBlockIndicator /> }
</SharedBlockSelection>
</EditorProvider>
);
}
}

export default compose( [
withSelect( ( select, ownProps ) => {
const {
getSharedBlock,
isFetchingSharedBlock,
isSavingSharedBlock,
getBlock,
} = select( 'core/editor' );
const { ref } = ownProps.attributes;
const sharedBlock = getSharedBlock( ref );
if ( ! Number.isFinite( ref ) ) {
return;
}

const { getEntityRecord } = select( 'core' );
return {
sharedBlock,
isFetching: isFetchingSharedBlock( ref ),
isSaving: isSavingSharedBlock( ref ),
block: sharedBlock ? getBlock( sharedBlock.uid ) : null,
sharedBlock: getEntityRecord( 'postType', 'wp_block', ref ),
settings: select( 'core/editor' ).getEditorSettings(),
};
} ),
withDispatch( ( dispatch, ownProps ) => {
const {
fetchSharedBlocks,
updateBlockAttributes,
updateSharedBlockTitle,
saveSharedBlock,
} = dispatch( 'core/editor' );
const { ref } = ownProps.attributes;
const { selectBlock } = dispatch( 'core/editor' );
const { id } = ownProps;

return {
fetchSharedBlock: partial( fetchSharedBlocks, ref ),
updateAttributes: updateBlockAttributes,
onUpdateTitle: partial( updateSharedBlockTitle, ref ),
onSave: partial( saveSharedBlock, ref ),
setIsSelected: () => selectBlock( id ),
};
} ),
] )( SharedBlockEdit );
9 changes: 8 additions & 1 deletion core-blocks/block/indicator/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*/
import { Tooltip, Dashicon } from '@wordpress/components';
import { __, sprintf } from '@wordpress/i18n';
import { withSelect } from '@wordpress/data';

/**
* Internal dependencies
Expand All @@ -21,4 +22,10 @@ function SharedBlockIndicator( { title } ) {
);
}

export default SharedBlockIndicator;
export default withSelect( ( select ) => {
const { getEditedPostAttribute } = select( 'core/editor' );

return {
title: getEditedPostAttribute( 'title' ),
};
} )( SharedBlockIndicator );
42 changes: 42 additions & 0 deletions core-blocks/block/selection.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/**
* WordPress dependencies
*/
import { Component, compose } from '@wordpress/element';
import { withSelect, withDispatch } from '@wordpress/data';

class SharedBlockSelection extends Component {
componentDidUpdate( prevProps ) {
const {
isSharedBlockSelected,
hasSelection,
clearSelectedBlock,
onBlockSelection,
} = this.props;

if ( ! isSharedBlockSelected && prevProps.isSharedBlockSelected ) {
clearSelectedBlock();
}

if ( hasSelection && ! prevProps.hasSelection ) {
onBlockSelection();
}
}

render() {
return this.props.children;
}
}

export default compose( [
withSelect( ( select ) => {
const { getBlockSelectionStart } = select( 'core/editor' );

return {
hasSelection: !! getBlockSelectionStart(),
};
} ),
withDispatch( ( dispatch ) => {
const { clearSelectedBlock } = dispatch( 'core/editor' );
return { clearSelectedBlock };
} ),
] )( SharedBlockSelection );
9 changes: 8 additions & 1 deletion edit-post/editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import { StrictMode } from '@wordpress/element';
* Internal dependencies
*/
import Layout from './components/layout';
import store from './store';

const initializeStore = () => store.dispatch( { type: 'INIT' } );

function Editor( { settings, hasFixedToolbar, post, overridePost, onError, ...props } ) {
if ( ! post ) {
Expand All @@ -22,7 +25,11 @@ function Editor( { settings, hasFixedToolbar, post, overridePost, onError, ...pr

return (
<StrictMode>
<EditorProvider settings={ editorSettings } post={ { ...post, ...overridePost } } { ...props }>
<EditorProvider
settings={ editorSettings }
post={ { ...post, ...overridePost } }
onStoreCreated={ initializeStore }
{ ...props }>
<ErrorBoundary onError={ onError }>
<Layout />
</ErrorBoundary>
Expand Down
1 change: 0 additions & 1 deletion edit-post/store/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,5 @@ const store = registerStore( 'core/edit-post', {

applyMiddlewares( store );
loadAndPersist( store, reducer, 'preferences', STORAGE_KEY );
store.dispatch( { type: 'INIT' } );

export default store;
Loading

0 comments on commit 58c5103

Please sign in to comment.