From bf424fc7a5377e4e8f49fe909b9a2338bdc8f989 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Mon, 25 Mar 2019 23:01:27 +0100 Subject: [PATCH 01/23] Start adding template inserter. --- assets/css/amp-editor-story-blocks.css | 31 ++++ assets/src/components/index.js | 1 + assets/src/components/story-controls.js | 20 +- .../template-inserter/block-preview.js | 46 +++++ .../src/components/template-inserter/index.js | 172 ++++++++++++++++++ assets/src/constants.js | 1 + 6 files changed, 254 insertions(+), 17 deletions(-) create mode 100644 assets/src/components/template-inserter/block-preview.js create mode 100644 assets/src/components/template-inserter/index.js diff --git a/assets/css/amp-editor-story-blocks.css b/assets/css/amp-editor-story-blocks.css index c671b28f6d0..3b3b3ca3230 100644 --- a/assets/css/amp-editor-story-blocks.css +++ b/assets/css/amp-editor-story-blocks.css @@ -690,6 +690,37 @@ div[data-type="amp/amp-story-page"] .wp-block-image { * 10. Custom Components */ +/* + * Template Inserter Component. + */ +.amp-stories__template-inserter__popover.components-popover .components-popover__content:not(.is-mobile) { + width: 386px; + max-height: 600px; + left: -100px; + padding: 2px; +} + +.amp-stories__template-inserter__popover.components-popover.is-top .components-popover__content { + bottom: initial; +} + +.amp-stories__editor-inserter__results li { + display: block; + list-style-type: none; + width: 160px; + height: 268px; + float: left; + margin: 15px; +} + +.amp-stories__editor-inserter__results li amp-story-page, +.amp-stories__editor-inserter__results li amp-story-grid-layer { + display: block; + width: 100%; + height: 100%; +} + + /* * Preview Picker component * diff --git a/assets/src/components/index.js b/assets/src/components/index.js index 332e53fe98f..8a0f7310e67 100644 --- a/assets/src/components/index.js +++ b/assets/src/components/index.js @@ -6,6 +6,7 @@ export { default as StoryControls } from './story-controls'; export { default as Shortcuts } from './shortcuts'; export { default as StoryBlockDropZone } from './story-block-drop-zone'; export { default as StoryBlockMover } from './block-mover'; +export { default as TemplateInserter } from './template-inserter'; export { default as FontFamilyPicker } from './font-family-picker'; export { default as withAmpStorySettings } from './with-amp-story-settings'; export { default as withAnimationControls } from './with-animation-controls'; diff --git a/assets/src/components/story-controls.js b/assets/src/components/story-controls.js index 6b37c8e71d7..f097baa99c4 100644 --- a/assets/src/components/story-controls.js +++ b/assets/src/components/story-controls.js @@ -3,6 +3,8 @@ * to add new pages and start/stop reordering pages. */ +import { TemplateInserter } from './'; + /** * WordPress dependencies */ @@ -38,25 +40,9 @@ function StoryControls( { isReordering, startReordering, saveOrder, resetOrder } return ( - ( - - ) } /> + + + ); +} + +export function BlockPreviewContent( { name, attributes } ) { + const blocks = wp.blocks.parse( attributes.content ); + if ( ! blocks.length ) { + return null; + } + const block = createBlock( 'core/template', {}, blocks ); + return ( + + + + ); +} + +export default BlockPreview; diff --git a/assets/src/components/template-inserter/index.js b/assets/src/components/template-inserter/index.js new file mode 100644 index 00000000000..4fa784d649d --- /dev/null +++ b/assets/src/components/template-inserter/index.js @@ -0,0 +1,172 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; +import { Dropdown, IconButton } from '@wordpress/components'; +import { Component, RawHTML } from '@wordpress/element'; +import { dispatch } from '@wordpress/data'; +import uuid from 'uuid/v4'; +const { apiFetch } = wp; + +const blocksRestBase = 'blocks'; + +/** + * Internal dependencies + */ +import BlockPreview from './block-preview'; + +const renderToggle = ( { onToggle, disabled, isOpen } ) => ( + +); + +/** + * Temporary static function for displaying template contents. + * + * @param {number} templateId Template ID. + */ +const getTemplateBlocks = ( templateId ) => { + switch ( templateId ) { + case 0: + return `

`; + case 1: + return `

Hello, this is a sample.

`; + default: + return ''; + } +}; + +class TemplateInserter extends Component { + constructor() { + super( ...arguments ); + + this.onToggle = this.onToggle.bind( this ); + this.renderToggle = this.renderToggle.bind( this ); + + this.state = { + reusableBlocks: null, + }; + } + + componentDidMount() { + debugger; + this.getReusableBlocks(); + // Only debounce once the initial fetch occurs to ensure that the first + // renders show data as soon as possible. + // this.getReusableBlocks = debounce( this.getReusableBlocks(), 500 ); + } + + onToggle( isOpen ) { + const { onToggle } = this.props; + + // Surface toggle callback to parent component + if ( onToggle ) { + onToggle( isOpen ); + } + } + + /** + * Render callback to display Dropdown toggle element. + * + * @param {Function} options.onToggle Callback to invoke when toggle is + * pressed. + * @param {boolean} options.isOpen Whether dropdown is currently open. + * + * @return {WPElement} Dropdown toggle element. + */ + renderToggle( { onToggle, isOpen } ) { + const { + disabled, + } = this.props; + + return renderToggle( { onToggle, isOpen, disabled } ); + } + + getReusableBlocks() { + return apiFetch( { + path: `/wp/v2/${ blocksRestBase }`, + } ) + .then( ( response ) => { + if ( response ) { + this.setState( { reusableBlocks: response } ); + } + } ) + .catch( ( error ) => { + debugger; + } ); + } + + render() { + const { insertBlocks } = dispatch('core/block-editor'); + return ( + ( + + { __( 'Insert Template', 'amp' ) } + + ) } + renderContent={ ( { onClose } ) => { + const onSelect = ( templateId ) => { + const templateHTML = getTemplateBlocks( templateId ); + + const blocks = wp.blocks.parse( templateHTML ); + insertBlocks( blocks ); + onClose(); + }; + + const reusableBlocks = this.state.reusableBlocks; + if ( ! reusableBlocks ) { + return ( +
DmmDmm
+ ); + } else { + debugger; + return ( +
+
+
    + { reusableBlocks && reusableBlocks.map( ( item ) => + { + onSelect( item ); + } } + /> + ) } +
+
+
+ ); + } + } } + /> + ); + } +} + +export default TemplateInserter; diff --git a/assets/src/constants.js b/assets/src/constants.js index 80614666729..58f2f3feb92 100644 --- a/assets/src/constants.js +++ b/assets/src/constants.js @@ -50,6 +50,7 @@ export const ALLOWED_CHILD_BLOCKS = [ 'core/verse', 'core/video', 'amp/amp-story-text', + 'core/template', // Reusable blocks. ]; export const ALLOWED_BLOCKS = [ From 7e0b6823f3bf9b1989576bef81198eb6861c2756 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Tue, 26 Mar 2019 13:22:35 +0100 Subject: [PATCH 02/23] Make template inserter (kind of) functional. --- assets/css/amp-editor-story-blocks.css | 31 +++- assets/src/components/story-controls.js | 3 + .../template-inserter/block-preview.js | 14 +- .../src/components/template-inserter/index.js | 135 +++++++----------- assets/src/constants.js | 2 +- 5 files changed, 89 insertions(+), 96 deletions(-) diff --git a/assets/css/amp-editor-story-blocks.css b/assets/css/amp-editor-story-blocks.css index 3b3b3ca3230..5299d8c6622 100644 --- a/assets/css/amp-editor-story-blocks.css +++ b/assets/css/amp-editor-story-blocks.css @@ -695,11 +695,16 @@ div[data-type="amp/amp-story-page"] .wp-block-image { */ .amp-stories__template-inserter__popover.components-popover .components-popover__content:not(.is-mobile) { width: 386px; - max-height: 600px; + height: 500px; left: -100px; padding: 2px; } +.amp-stories__template-inserter__popover.block-editor-inserter__popover .block-editor-block-types-list { + margin: 0; + padding: 5px; +} + .amp-stories__template-inserter__popover.components-popover.is-top .components-popover__content { bottom: initial; } @@ -720,6 +725,30 @@ div[data-type="amp/amp-story-page"] .wp-block-image { height: 100%; } +.amp-stories__editor-inserter__results .block-editor-block-preview { + width: 160px; + height: 268px; + margin: 10px; + padding: 0; +} + +.amp-stories__editor-inserter__results .block-editor-block-preview .block-editor-block-preview__content { + padding: 0; +} + +.amp-stories__blank-page-inserter { + height: 100%; + width: 100%; +} + +.amp-stories__blank-page-inserter svg { + margin: 0 auto; +} + +.amp-stories__editor-inserter__results .block-editor-block-preview { + pointer-events: initial; +} + /* * Preview Picker component diff --git a/assets/src/components/story-controls.js b/assets/src/components/story-controls.js index f097baa99c4..8319d0d0934 100644 --- a/assets/src/components/story-controls.js +++ b/assets/src/components/story-controls.js @@ -3,6 +3,9 @@ * to add new pages and start/stop reordering pages. */ +/** + * Internal dependencies + */ import { TemplateInserter } from './'; /** diff --git a/assets/src/components/template-inserter/block-preview.js b/assets/src/components/template-inserter/block-preview.js index 137b344af7f..85d5d21577b 100644 --- a/assets/src/components/template-inserter/block-preview.js +++ b/assets/src/components/template-inserter/block-preview.js @@ -8,7 +8,7 @@ import { noop } from 'lodash'; */ import { createBlock } from '@wordpress/blocks'; import { Disabled } from '@wordpress/components'; -import { BlockEdit } from '@wordpress/block-editor'; +// import { BlockEdit } from '@wordpress/block-editor'; /** * Block Preview Component: It renders a preview given a block name and attributes. @@ -19,22 +19,20 @@ import { BlockEdit } from '@wordpress/block-editor'; */ function BlockPreview( props ) { return ( -
+
); } export function BlockPreviewContent( { name, attributes } ) { - const blocks = wp.blocks.parse( attributes.content ); - if ( ! blocks.length ) { - return null; - } - const block = createBlock( 'core/template', {}, blocks ); + // @todo Importing this outside of the function causes error for some reason. + const BlockEdit = wp.blockEditor.BlockEdit; + const block = createBlock( name, attributes ); return ( ( - -); - -/** - * Temporary static function for displaying template contents. - * - * @param {number} templateId Template ID. - */ -const getTemplateBlocks = ( templateId ) => { - switch ( templateId ) { - case 0: - return `

`; - case 1: - return `

Hello, this is a sample.

`; - default: - return ''; - } -}; - class TemplateInserter extends Component { constructor() { super( ...arguments ); this.onToggle = this.onToggle.bind( this ); - this.renderToggle = this.renderToggle.bind( this ); this.state = { reusableBlocks: null, @@ -57,11 +27,7 @@ class TemplateInserter extends Component { } componentDidMount() { - debugger; this.getReusableBlocks(); - // Only debounce once the initial fetch occurs to ensure that the first - // renders show data as soon as possible. - // this.getReusableBlocks = debounce( this.getReusableBlocks(), 500 ); } onToggle( isOpen ) { @@ -73,24 +39,8 @@ class TemplateInserter extends Component { } } - /** - * Render callback to display Dropdown toggle element. - * - * @param {Function} options.onToggle Callback to invoke when toggle is - * pressed. - * @param {boolean} options.isOpen Whether dropdown is currently open. - * - * @return {WPElement} Dropdown toggle element. - */ - renderToggle( { onToggle, isOpen } ) { - const { - disabled, - } = this.props; - - return renderToggle( { onToggle, isOpen, disabled } ); - } - getReusableBlocks() { + // @todo We only need reusable blocks that can be used by AMP Stories. return apiFetch( { path: `/wp/v2/${ blocksRestBase }`, } ) @@ -105,7 +55,7 @@ class TemplateInserter extends Component { } render() { - const { insertBlocks } = dispatch('core/block-editor'); + const { insertBlocks, insertBlock } = dispatch( 'core/block-editor' ); return ( - { __( 'Insert Template', 'amp' ) } -
+ /> ) } renderContent={ ( { onClose } ) => { - const onSelect = ( templateId ) => { - const templateHTML = getTemplateBlocks( templateId ); - - const blocks = wp.blocks.parse( templateHTML ); - insertBlocks( blocks ); + const onSelect = ( name, content ) => { + if ( 'core/block' === name ) { + const blocks = parse( content ); + insertBlocks( blocks ); + } else { + const block = createBlock( name ); + insertBlock( block ); + } onClose(); }; const reusableBlocks = this.state.reusableBlocks; + const pageIcon = ; if ( ! reusableBlocks ) { + // @todo Add spinner. return ( -
DmmDmm
+
Loading
); - } else { - debugger; - return ( -
-
-
    - { reusableBlocks && reusableBlocks.map( ( item ) => - { - onSelect( item ); - } } - /> - ) } -
+ } + + return ( +
+
+
+
+ { + onSelect( 'amp/amp-story-page' ); + } } + className="amp-stories__blank-page-inserter editor-block-preview__content block-editor-block-preview__content editor-styles-wrapper" + /> +
+ { reusableBlocks && reusableBlocks.map( ( item ) => + { + onSelect( 'core/block', item.content.raw ); + } } + /> + ) }
- ); - } +
+ ); } } /> ); diff --git a/assets/src/constants.js b/assets/src/constants.js index 58f2f3feb92..09ae8eeac5a 100644 --- a/assets/src/constants.js +++ b/assets/src/constants.js @@ -50,7 +50,7 @@ export const ALLOWED_CHILD_BLOCKS = [ 'core/verse', 'core/video', 'amp/amp-story-text', - 'core/template', // Reusable blocks. + 'core/block', // Reusable blocks. ]; export const ALLOWED_BLOCKS = [ From 738d975b3bc2f105fbb99df31b2607e02c60c4b9 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Tue, 26 Mar 2019 15:36:18 +0100 Subject: [PATCH 03/23] Improve style. --- assets/css/amp-editor-story-blocks.css | 20 ++++++++++++++++--- .../template-inserter/block-preview.js | 4 ++-- .../src/components/template-inserter/icon.js | 20 +++++++++++++++++++ .../src/components/template-inserter/index.js | 12 ++++++----- 4 files changed, 46 insertions(+), 10 deletions(-) create mode 100644 assets/src/components/template-inserter/icon.js diff --git a/assets/css/amp-editor-story-blocks.css b/assets/css/amp-editor-story-blocks.css index 5299d8c6622..5bd79fbafd1 100644 --- a/assets/css/amp-editor-story-blocks.css +++ b/assets/css/amp-editor-story-blocks.css @@ -695,9 +695,20 @@ div[data-type="amp/amp-story-page"] .wp-block-image { */ .amp-stories__template-inserter__popover.components-popover .components-popover__content:not(.is-mobile) { width: 386px; - height: 500px; - left: -100px; + height: 400px; padding: 2px; + transform: translateX(-90%); +} + +@media (min-width: 782px) { + .amp-stories__template-inserter__popover.block-editor-inserter__popover:not(.is-mobile) > .components-popover__content { + overflow-y: scroll; + } +} + +.edit-post-layout:not(.is-sidebar-opened) .amp-stories__template-inserter__popover.components-popover .components-popover__content:not(.is-mobile) { + left: initial; + transform: none; } .amp-stories__template-inserter__popover.block-editor-inserter__popover .block-editor-block-types-list { @@ -732,8 +743,11 @@ div[data-type="amp/amp-story-page"] .wp-block-image { padding: 0; } -.amp-stories__editor-inserter__results .block-editor-block-preview .block-editor-block-preview__content { +.amp-stories__editor-inserter__results .block-editor-block-preview .block-editor-block-preview__content, +.amo-stories__editor-inserter__results .components-placeholder { padding: 0; + width: 100%; + height: 100%; } .amp-stories__blank-page-inserter { diff --git a/assets/src/components/template-inserter/block-preview.js b/assets/src/components/template-inserter/block-preview.js index 85d5d21577b..31786198230 100644 --- a/assets/src/components/template-inserter/block-preview.js +++ b/assets/src/components/template-inserter/block-preview.js @@ -19,9 +19,9 @@ import { Disabled } from '@wordpress/components'; */ function BlockPreview( props ) { return ( -
+
+ ); } diff --git a/assets/src/components/template-inserter/icon.js b/assets/src/components/template-inserter/icon.js new file mode 100644 index 00000000000..8f26ebdd034 --- /dev/null +++ b/assets/src/components/template-inserter/icon.js @@ -0,0 +1,20 @@ +const pageIcon = ( + + + + + + + + + + + + + + + + +); + +export default pageIcon; diff --git a/assets/src/components/template-inserter/index.js b/assets/src/components/template-inserter/index.js index eb93285d9e7..9cc0713d91c 100644 --- a/assets/src/components/template-inserter/index.js +++ b/assets/src/components/template-inserter/index.js @@ -2,7 +2,7 @@ * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { Dropdown, IconButton } from '@wordpress/components'; +import { Dropdown, IconButton, Spinner } from '@wordpress/components'; import { Component } from '@wordpress/element'; import { dispatch } from '@wordpress/data'; import { parse, createBlock } from '@wordpress/blocks'; @@ -14,6 +14,7 @@ const blocksRestBase = 'blocks'; * Internal dependencies */ import BlockPreview from './block-preview'; +import pageIcon from './icon'; class TemplateInserter extends Component { constructor() { @@ -27,7 +28,10 @@ class TemplateInserter extends Component { } componentDidMount() { - this.getReusableBlocks(); + // @todo Improve handling the requests. + if ( ! this.state.reusableBlocks ) { + this.getReusableBlocks(); + } } onToggle( isOpen ) { @@ -85,11 +89,9 @@ class TemplateInserter extends Component { }; const reusableBlocks = this.state.reusableBlocks; - const pageIcon = ; if ( ! reusableBlocks ) { - // @todo Add spinner. return ( -
Loading
+ ); } From 1932e3f05b473e836cf6334ce219c51f8c155837 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Tue, 26 Mar 2019 20:01:45 +0100 Subject: [PATCH 04/23] Improve API request. --- .../src/components/template-inserter/index.js | 44 +++++++++++++++---- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/assets/src/components/template-inserter/index.js b/assets/src/components/template-inserter/index.js index 9cc0713d91c..5a395cacd54 100644 --- a/assets/src/components/template-inserter/index.js +++ b/assets/src/components/template-inserter/index.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { __ } from '@wordpress/i18n'; +import { __, sprintf } from '@wordpress/i18n'; import { Dropdown, IconButton, Spinner } from '@wordpress/components'; import { Component } from '@wordpress/element'; import { dispatch } from '@wordpress/data'; @@ -28,10 +28,13 @@ class TemplateInserter extends Component { } componentDidMount() { - // @todo Improve handling the requests. - if ( ! this.state.reusableBlocks ) { - this.getReusableBlocks(); - } + // This is used for making sure that once the response finishes the component actually still exists. + this.isComponentMounted = true; + this.getReusableBlocks(); + } + + componentWillUnmount() { + this.isComponentMounted = false; } onToggle( isOpen ) { @@ -44,17 +47,31 @@ class TemplateInserter extends Component { } getReusableBlocks() { + if ( ! this.isComponentMounted ) { + return; + } + + if ( null !== this.state.reusableBlocks ) { + this.setState( { reusableBlocks: null } ); + } + // @todo We only need reusable blocks that can be used by AMP Stories. - return apiFetch( { - path: `/wp/v2/${ blocksRestBase }`, + const blocksRequest = this.lastRequest = apiFetch( { + path: `/wp/v2/${ blocksRestBase }?search=amp-story-page`, } ) .then( ( response ) => { - if ( response ) { + // Check if it's the result of the last request. + if ( this.isComponentMounted && blocksRequest === this.lastRequest && response ) { this.setState( { reusableBlocks: response } ); } } ) .catch( ( error ) => { - debugger; + if ( this.isComponentMounted && blocksRequest === this.lastRequest ) { + this.setState( { reusableBlocks: { + error: true, + message: error.message, + } } ); + } } ); } @@ -95,6 +112,15 @@ class TemplateInserter extends Component { ); } + if ( reusableBlocks.error ) { + const errorMessage = sprintf( __( 'Loading templates failed: %s', 'amp' ), reusableBlocks.error.message ); + return ( +
+ { errorMessage } +
+ ); + } + return (
Date: Tue, 26 Mar 2019 20:13:00 +0100 Subject: [PATCH 05/23] Remove unused params. --- assets/src/components/story-controls.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/assets/src/components/story-controls.js b/assets/src/components/story-controls.js index 8319d0d0934..8d51ef756d3 100644 --- a/assets/src/components/story-controls.js +++ b/assets/src/components/story-controls.js @@ -14,7 +14,6 @@ import { TemplateInserter } from './'; import { __ } from '@wordpress/i18n'; import { IconButton, Button } from '@wordpress/components'; import { Fragment } from '@wordpress/element'; -import { Inserter } from '@wordpress/editor'; import { withDispatch, withSelect } from '@wordpress/data'; import { compose } from '@wordpress/compose'; @@ -43,10 +42,7 @@ function StoryControls( { isReordering, startReordering, saveOrder, resetOrder } return ( - + Date: Wed, 27 Mar 2019 17:39:47 +0100 Subject: [PATCH 06/23] Rework getting reusable blocks. --- assets/src/blocks/amp-story-text/index.js | 1 + assets/src/blocks/amp-story/index.js | 4 + .../src/components/template-inserter/index.js | 123 +++++++++--------- assets/src/constants.js | 3 + assets/src/stores/amp-story/actions.js | 6 + assets/src/stores/amp-story/index.js | 1 + assets/src/stores/amp-story/selectors.js | 4 + 7 files changed, 77 insertions(+), 65 deletions(-) diff --git a/assets/src/blocks/amp-story-text/index.js b/assets/src/blocks/amp-story-text/index.js index 6ea420cd0bf..4c00716607d 100644 --- a/assets/src/blocks/amp-story-text/index.js +++ b/assets/src/blocks/amp-story-text/index.js @@ -25,6 +25,7 @@ export const name = 'amp/amp-story-text'; const supports = { className: false, anchor: true, + reusable: true, }; const schema = { diff --git a/assets/src/blocks/amp-story/index.js b/assets/src/blocks/amp-story/index.js index 17eef1ca1b0..a2aefea0e75 100644 --- a/assets/src/blocks/amp-story/index.js +++ b/assets/src/blocks/amp-story/index.js @@ -57,6 +57,10 @@ export const settings = { icon: BLOCK_ICONS[ 'amp/amp-story-page' ], attributes: schema, + supports: { + reusable: true, + }, + /* * : * mandatory_parent: "AMP-STORY" diff --git a/assets/src/components/template-inserter/index.js b/assets/src/components/template-inserter/index.js index 5a395cacd54..4a7e77f7fcd 100644 --- a/assets/src/components/template-inserter/index.js +++ b/assets/src/components/template-inserter/index.js @@ -1,14 +1,12 @@ /** * WordPress dependencies */ -import { __, sprintf } from '@wordpress/i18n'; +import { __ } from '@wordpress/i18n'; import { Dropdown, IconButton, Spinner } from '@wordpress/components'; import { Component } from '@wordpress/element'; -import { dispatch } from '@wordpress/data'; -import { parse, createBlock } from '@wordpress/blocks'; -const { apiFetch } = wp; - -const blocksRestBase = 'blocks'; +import { withSelect, withDispatch } from '@wordpress/data'; +import { createBlock, cloneBlock } from '@wordpress/blocks'; +import { compose } from '@wordpress/compose'; /** * Internal dependencies @@ -16,6 +14,8 @@ const blocksRestBase = 'blocks'; import BlockPreview from './block-preview'; import pageIcon from './icon'; +const storyPageBlockName = 'amp/amp-story-page'; + class TemplateInserter extends Component { constructor() { super( ...arguments ); @@ -28,13 +28,15 @@ class TemplateInserter extends Component { } componentDidMount() { - // This is used for making sure that once the response finishes the component actually still exists. - this.isComponentMounted = true; - this.getReusableBlocks(); + this.props.fetchReusableBlocks(); } - componentWillUnmount() { - this.isComponentMounted = false; + componentDidUpdate( prevProps ) { + if ( prevProps.reusableBlocks !== this.props.reusableBlocks || prevProps.allBlocks !== this.props.allBlocks ) { + this.setState( { + reusableBlocks: this.props.reusableBlocks + } ); + } } onToggle( isOpen ) { @@ -46,37 +48,8 @@ class TemplateInserter extends Component { } } - getReusableBlocks() { - if ( ! this.isComponentMounted ) { - return; - } - - if ( null !== this.state.reusableBlocks ) { - this.setState( { reusableBlocks: null } ); - } - - // @todo We only need reusable blocks that can be used by AMP Stories. - const blocksRequest = this.lastRequest = apiFetch( { - path: `/wp/v2/${ blocksRestBase }?search=amp-story-page`, - } ) - .then( ( response ) => { - // Check if it's the result of the last request. - if ( this.isComponentMounted && blocksRequest === this.lastRequest && response ) { - this.setState( { reusableBlocks: response } ); - } - } ) - .catch( ( error ) => { - if ( this.isComponentMounted && blocksRequest === this.lastRequest ) { - this.setState( { reusableBlocks: { - error: true, - message: error.message, - } } ); - } - } ); - } - render() { - const { insertBlocks, insertBlock } = dispatch( 'core/block-editor' ); + const { insertBlock, getBlock } = this.props; return ( ) } renderContent={ ( { onClose } ) => { - const onSelect = ( name, content ) => { - if ( 'core/block' === name ) { - const blocks = parse( content ); - insertBlocks( blocks ); - } else { - const block = createBlock( name ); - insertBlock( block ); - } - onClose(); + const isStoryBlock = ( clientId ) => { + const block = getBlock( clientId ); + return block && storyPageBlockName === block.name; }; - const reusableBlocks = this.state.reusableBlocks; - if ( ! reusableBlocks ) { + const onSelect = ( item ) => { + const block = ! item ? createBlock( storyPageBlockName ) : getBlock( item.clientId ); + onClose(); + // Clone block to avoid duplicate ID-s. + insertBlock( cloneBlock( block ) ); + }; + if ( ! this.state.reusableBlocks ) { return ( ); } - - if ( reusableBlocks.error ) { - const errorMessage = sprintf( __( 'Loading templates failed: %s', 'amp' ), reusableBlocks.error.message ); - return ( -
- { errorMessage } -
- ); - } + const storyTemplates = this.state.reusableBlocks.filter( ( { clientId } ) => isStoryBlock( clientId ) ); return (
@@ -135,18 +99,18 @@ class TemplateInserter extends Component { icon={ pageIcon } label={ __( 'Blank Page', 'amp' ) } onClick={ () => { - onSelect( 'amp/amp-story-page' ); + onSelect( null ); } } className="amp-stories__blank-page-inserter editor-block-preview__content block-editor-block-preview__content editor-styles-wrapper" />
- { reusableBlocks && reusableBlocks.map( ( item ) => + { storyTemplates && storyTemplates.map( ( item ) => { - onSelect( 'core/block', item.content.raw ); + onSelect( item ); } } /> ) } @@ -160,4 +124,33 @@ class TemplateInserter extends Component { } } -export default TemplateInserter; +export default compose( + withSelect( ( select ) => { + const { + __experimentalGetReusableBlocks: getReusableBlocks, + } = select( 'core/editor' ); + + const { + getBlock, + getBlocks, + } = select( 'core/block-editor' ); + + return { + reusableBlocks: getReusableBlocks(), + getBlock, + allBlocks: getBlocks(), + }; + } ), + withDispatch( ( dispatch ) => { + const { + __experimentalFetchReusableBlocks: fetchReusableBlocks, + } = dispatch( 'core/editor' ); + + const { insertBlock } = dispatch( 'core/block-editor' ); + + return { + fetchReusableBlocks, + insertBlock, + }; + } ) +)( TemplateInserter ); diff --git a/assets/src/constants.js b/assets/src/constants.js index 09ae8eeac5a..b388349843e 100644 --- a/assets/src/constants.js +++ b/assets/src/constants.js @@ -35,6 +35,8 @@ export const STORY_PAGE_WIDTH = STORY_PAGE_INNER_WIDTH + storyPageBorderWidth; export const ALLOWED_TOP_LEVEL_BLOCKS = [ 'amp/amp-story-page', + 'core/block', // Reusable blocks. + 'core/template', // Reusable blocks. ]; export const ALLOWED_CHILD_BLOCKS = [ @@ -51,6 +53,7 @@ export const ALLOWED_CHILD_BLOCKS = [ 'core/video', 'amp/amp-story-text', 'core/block', // Reusable blocks. + 'core/template', // Reusable blocks. ]; export const ALLOWED_BLOCKS = [ diff --git a/assets/src/stores/amp-story/actions.js b/assets/src/stores/amp-story/actions.js index ae7b7df5093..b85333fdf38 100644 --- a/assets/src/stores/amp-story/actions.js +++ b/assets/src/stores/amp-story/actions.js @@ -134,3 +134,9 @@ export function resetOrder() { type: 'RESET_ORDER', }; } + +export function getReusableBlocks() { + return { + type: 'GET_REUSABLE_BLOCKS', + } +} diff --git a/assets/src/stores/amp-story/index.js b/assets/src/stores/amp-story/index.js index 0fefd279a41..5979509b1e9 100644 --- a/assets/src/stores/amp-story/index.js +++ b/assets/src/stores/amp-story/index.js @@ -27,6 +27,7 @@ export default registerStore( order: [], isReordering: false, }, + reusableBlocks: [], }, } ); diff --git a/assets/src/stores/amp-story/selectors.js b/assets/src/stores/amp-story/selectors.js index bd67e57d405..4d35cc4026c 100644 --- a/assets/src/stores/amp-story/selectors.js +++ b/assets/src/stores/amp-story/selectors.js @@ -91,3 +91,7 @@ export function getBlockIndex( state, page ) { export function isReordering( state ) { return state.blocks.isReordering || false; } + +export function getReusableBlocks( state ) { + return state.reusableBlocks || []; +} From 1306f9cb09a4f3d2a6797c832fd058933172e461 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Wed, 27 Mar 2019 19:20:01 +0100 Subject: [PATCH 07/23] Remove unused code. --- assets/src/components/template-inserter/index.js | 3 ++- assets/src/stores/amp-story/actions.js | 6 ------ assets/src/stores/amp-story/index.js | 1 - assets/src/stores/amp-story/selectors.js | 4 ---- 4 files changed, 2 insertions(+), 12 deletions(-) diff --git a/assets/src/components/template-inserter/index.js b/assets/src/components/template-inserter/index.js index 4a7e77f7fcd..d195057b4e7 100644 --- a/assets/src/components/template-inserter/index.js +++ b/assets/src/components/template-inserter/index.js @@ -32,9 +32,10 @@ class TemplateInserter extends Component { } componentDidUpdate( prevProps ) { + // This check is needed to make sure that the blocks are loaded in time. if ( prevProps.reusableBlocks !== this.props.reusableBlocks || prevProps.allBlocks !== this.props.allBlocks ) { this.setState( { - reusableBlocks: this.props.reusableBlocks + reusableBlocks: this.props.reusableBlocks, } ); } } diff --git a/assets/src/stores/amp-story/actions.js b/assets/src/stores/amp-story/actions.js index b85333fdf38..ae7b7df5093 100644 --- a/assets/src/stores/amp-story/actions.js +++ b/assets/src/stores/amp-story/actions.js @@ -134,9 +134,3 @@ export function resetOrder() { type: 'RESET_ORDER', }; } - -export function getReusableBlocks() { - return { - type: 'GET_REUSABLE_BLOCKS', - } -} diff --git a/assets/src/stores/amp-story/index.js b/assets/src/stores/amp-story/index.js index 5979509b1e9..0fefd279a41 100644 --- a/assets/src/stores/amp-story/index.js +++ b/assets/src/stores/amp-story/index.js @@ -27,7 +27,6 @@ export default registerStore( order: [], isReordering: false, }, - reusableBlocks: [], }, } ); diff --git a/assets/src/stores/amp-story/selectors.js b/assets/src/stores/amp-story/selectors.js index 4d35cc4026c..bd67e57d405 100644 --- a/assets/src/stores/amp-story/selectors.js +++ b/assets/src/stores/amp-story/selectors.js @@ -91,7 +91,3 @@ export function getBlockIndex( state, page ) { export function isReordering( state ) { return state.blocks.isReordering || false; } - -export function getReusableBlocks( state ) { - return state.reusableBlocks || []; -} From 8ae5c64bfc52dbef797eada99a4e9927fae24eb0 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Wed, 27 Mar 2019 23:57:22 +0100 Subject: [PATCH 08/23] Style adjustments. --- assets/css/amp-editor-story-blocks.css | 48 +++++++++++++++++++ .../template-inserter/block-preview.js | 4 +- .../src/components/template-inserter/index.js | 2 +- 3 files changed, 51 insertions(+), 3 deletions(-) diff --git a/assets/css/amp-editor-story-blocks.css b/assets/css/amp-editor-story-blocks.css index 5bd79fbafd1..6fbda66ff00 100644 --- a/assets/css/amp-editor-story-blocks.css +++ b/assets/css/amp-editor-story-blocks.css @@ -699,6 +699,20 @@ div[data-type="amp/amp-story-page"] .wp-block-image { padding: 2px; transform: translateX(-90%); } +.components-popover:not(.is-without-arrow):not(.is-mobile).is-top::before { + border: 8px solid #e2e4e7; +} +.components-popover:not(.is-without-arrow):not(.is-mobile).is-top::after { + border: 8px solid #fff; +} +.components-popover:not(.is-without-arrow):not(.is-mobile).is-top::before, +.components-popover:not(.is-without-arrow):not(.is-mobile).is-top::after { + border-bottom-style: solid; + border-left-color: transparent; + border-right-color: transparent; + border-top: none; + margin-left: -10px; +} @media (min-width: 782px) { .amp-stories__template-inserter__popover.block-editor-inserter__popover:not(.is-mobile) > .components-popover__content { @@ -706,6 +720,12 @@ div[data-type="amp/amp-story-page"] .wp-block-image { } } +@media (min-width: 600px) { + .amp-stories__template-inserter__popover .block-editor-block-list__block .block-editor-block-list__block-edit { + margin: 0; + } +} + .edit-post-layout:not(.is-sidebar-opened) .amp-stories__template-inserter__popover.components-popover .components-popover__content:not(.is-mobile) { left: initial; transform: none; @@ -719,6 +739,9 @@ div[data-type="amp/amp-story-page"] .wp-block-image { .amp-stories__template-inserter__popover.components-popover.is-top .components-popover__content { bottom: initial; } +.amp-stories__template-inserter__popover.components-popover:not(.is-without-arrow):not(.is-mobile).is-top { + margin-top: 44px; +} .amp-stories__editor-inserter__results li { display: block; @@ -763,6 +786,31 @@ div[data-type="amp/amp-story-page"] .wp-block-image { pointer-events: initial; } +.amp-stories__editor-inserter__results .block-list-appender, +.amo-stories__editor-inserter__results .editor-block-list__insertion-point { + display: none; +} + +.amp-stories__editor-inserter__results .block-editor-block-preview .block-editor-block-preview__content .components-disabled { + transform: initial; + text-align: initial; +} +.amp-stories__editor-inserter__results .components-disabled, +.amp-stories__editor-inserter__results .components-disabled div:first-of-type, +.amp-stories__editor-inserter__results .components-disabled .editor-inner-blocks { + padding: 0; + height: 100%; + width: 100%; +} + +.amp-stories__editor-inserter__results .block-editor-block-preview .wp-block { + transform: scale(0.48) translateX(-40%) translateY(-40%); +} + +.amp-stories__editor-inserter__results .block-editor-block-types-list { + padding: 10px; +} + /* * Preview Picker component diff --git a/assets/src/components/template-inserter/block-preview.js b/assets/src/components/template-inserter/block-preview.js index 31786198230..025c3571217 100644 --- a/assets/src/components/template-inserter/block-preview.js +++ b/assets/src/components/template-inserter/block-preview.js @@ -19,9 +19,9 @@ import { Disabled } from '@wordpress/components'; */ function BlockPreview( props ) { return ( - + ); } diff --git a/assets/src/components/template-inserter/index.js b/assets/src/components/template-inserter/index.js index d195057b4e7..59a2179737a 100644 --- a/assets/src/components/template-inserter/index.js +++ b/assets/src/components/template-inserter/index.js @@ -54,7 +54,7 @@ class TemplateInserter extends Component { return ( ( From 3c43aebf61df5e23b4eb666182441e36c9b44f82 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Thu, 28 Mar 2019 10:49:30 +0100 Subject: [PATCH 09/23] Add icons for the template inserter and reordering. --- assets/css/amp-editor-story-blocks.css | 37 +++++++++++++++++-- assets/src/components/story-controls.js | 3 +- .../template-inserter/block-preview.js | 8 +++- .../src/components/template-inserter/index.js | 3 +- assets/src/constants.js | 25 +++++++++++++ assets/src/helpers.js | 4 +- 6 files changed, 70 insertions(+), 10 deletions(-) diff --git a/assets/css/amp-editor-story-blocks.css b/assets/css/amp-editor-story-blocks.css index 6fbda66ff00..cf01c9001eb 100644 --- a/assets/css/amp-editor-story-blocks.css +++ b/assets/css/amp-editor-story-blocks.css @@ -352,6 +352,7 @@ div[data-type="amp/amp-story-page"] .editor-inner-blocks .editor-block-list__lay #amp-story-controls { text-align: right; + padding-right: 20px; } #amp-story-controls .amp-story-controls-reorder { @@ -693,6 +694,33 @@ div[data-type="amp/amp-story-page"] .wp-block-image { /* * Template Inserter Component. */ + +#amp-story-controls .editor-inserter__amp-inserter { + height: 48px; + width: 48px; + background-color: #0085BA; + border-radius: 50%; + margin-right: 10px; +} + +#amp-story-controls .editor-inserter__amp-inserter span:first-of-type, +.amp-story-controls-reorder span:first-of-type { + display: none; +} + +#amp-story-controls .editor-inserter__amp-inserter svg { + margin: 0 auto; +} + +.amp-story-controls-reorder { + box-sizing: border-box; + height: 49px; + width: 49px; + border: 1px solid #AAAEB3; + border-radius: 50%; + margin-right: 10px; +} + .amp-stories__template-inserter__popover.components-popover .components-popover__content:not(.is-mobile) { width: 386px; height: 400px; @@ -706,12 +734,14 @@ div[data-type="amp/amp-story-page"] .wp-block-image { border: 8px solid #fff; } .components-popover:not(.is-without-arrow):not(.is-mobile).is-top::before, -.components-popover:not(.is-without-arrow):not(.is-mobile).is-top::after { +.components-popover:not(.is-without-arrow):not(.is-mobile).is-bottom::before, +.components-popover:not(.is-without-arrow):not(.is-mobile).is-top::after, +.components-popover:not(.is-without-arrow):not(.is-mobile).is-bottom::after { border-bottom-style: solid; border-left-color: transparent; border-right-color: transparent; border-top: none; - margin-left: -10px; + margin-left: -15px; } @media (min-width: 782px) { @@ -740,7 +770,7 @@ div[data-type="amp/amp-story-page"] .wp-block-image { bottom: initial; } .amp-stories__template-inserter__popover.components-popover:not(.is-without-arrow):not(.is-mobile).is-top { - margin-top: 44px; + margin-top: 55px; } .amp-stories__editor-inserter__results li { @@ -811,7 +841,6 @@ div[data-type="amp/amp-story-page"] .wp-block-image { padding: 10px; } - /* * Preview Picker component * diff --git a/assets/src/components/story-controls.js b/assets/src/components/story-controls.js index 8d51ef756d3..7918a6ac65f 100644 --- a/assets/src/components/story-controls.js +++ b/assets/src/components/story-controls.js @@ -7,6 +7,7 @@ * Internal dependencies */ import { TemplateInserter } from './'; +import { ICONS } from './../constants'; /** * WordPress dependencies @@ -45,7 +46,7 @@ function StoryControls( { isReordering, startReordering, saveOrder, resetOrder } diff --git a/assets/src/components/template-inserter/block-preview.js b/assets/src/components/template-inserter/block-preview.js index 025c3571217..1545f7484b1 100644 --- a/assets/src/components/template-inserter/block-preview.js +++ b/assets/src/components/template-inserter/block-preview.js @@ -18,11 +18,15 @@ import { Disabled } from '@wordpress/components'; * @return {WPElement} Rendered element. */ function BlockPreview( props ) { + // @todo Probably there's a better way to handle this. + // Disable reason: This should be a button, however, there can be buttons within Pages, too. Buttons shouldn't be within buttons. + /* eslint-disable */ return ( -
  • + -
  • + ); + /* eslint-enable */ } export function BlockPreviewContent( { name, attributes } ) { diff --git a/assets/src/components/template-inserter/index.js b/assets/src/components/template-inserter/index.js index 59a2179737a..7ec3b337757 100644 --- a/assets/src/components/template-inserter/index.js +++ b/assets/src/components/template-inserter/index.js @@ -13,6 +13,7 @@ import { compose } from '@wordpress/compose'; */ import BlockPreview from './block-preview'; import pageIcon from './icon'; +import { ICONS } from './../../constants'; const storyPageBlockName = 'amp/amp-story-page'; @@ -59,7 +60,7 @@ class TemplateInserter extends Component { expandOnMobile renderToggle={ ( { onToggle, isOpen } ) => ( , }; +export const ICONS = { + 'add-template': + + + + + + + + + + , + reorder: + + + + + + + + + + , +}; + export const ANIMATION_DURATION_DEFAULTS = { drop: 1600, 'fade-in': 500, diff --git a/assets/src/helpers.js b/assets/src/helpers.js index 6ecfaed5b64..1173d539c13 100644 --- a/assets/src/helpers.js +++ b/assets/src/helpers.js @@ -75,11 +75,11 @@ export const setBlockParent = ( props ) => { // Only amp/amp-story-page blocks can be on the top level. return { ...props, - parent: [ 'amp/amp-story-page' ], + parent: [ 'amp/amp-story-page', 'core/block' ], }; } - if ( name !== 'amp/amp-story-page' ) { + if ( name !== 'amp/amp-story-page' && name !== 'core/block' ) { // Do not allow inserting any of the blocks if they're not AMP Story blocks. return { ...props, From 7eb3a3e98a9d399a446dc045b4bcf4755f731d2d Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Thu, 28 Mar 2019 12:36:06 +0100 Subject: [PATCH 10/23] Allow saving custom templates. --- assets/src/amp-story-editor-blocks.js | 4 ++ .../src/components/template-inserter/index.js | 2 +- assets/src/helpers.js | 4 +- assets/src/plugins/template-menu-item.js | 64 +++++++++++++++++++ 4 files changed, 71 insertions(+), 3 deletions(-) create mode 100644 assets/src/plugins/template-menu-item.js diff --git a/assets/src/amp-story-editor-blocks.js b/assets/src/amp-story-editor-blocks.js index 956f34956de..3c236232887 100644 --- a/assets/src/amp-story-editor-blocks.js +++ b/assets/src/amp-story-editor-blocks.js @@ -36,6 +36,10 @@ import { ALLOWED_BLOCKS, ALLOWED_TOP_LEVEL_BLOCKS, ALLOWED_CHILD_BLOCKS, MEDIA_I import store from './stores/amp-story'; +// Register plugin. +// @todo Consider importing automatically, especially in case of more plugins. +import './plugins/template-menu-item'; + const { getSelectedBlockClientId, getBlocksByClientId, diff --git a/assets/src/components/template-inserter/index.js b/assets/src/components/template-inserter/index.js index 7ec3b337757..fbd8a0398a7 100644 --- a/assets/src/components/template-inserter/index.js +++ b/assets/src/components/template-inserter/index.js @@ -108,7 +108,7 @@ class TemplateInserter extends Component {
    { storyTemplates && storyTemplates.map( ( item ) => { diff --git a/assets/src/helpers.js b/assets/src/helpers.js index 1173d539c13..6ecfaed5b64 100644 --- a/assets/src/helpers.js +++ b/assets/src/helpers.js @@ -75,11 +75,11 @@ export const setBlockParent = ( props ) => { // Only amp/amp-story-page blocks can be on the top level. return { ...props, - parent: [ 'amp/amp-story-page', 'core/block' ], + parent: [ 'amp/amp-story-page' ], }; } - if ( name !== 'amp/amp-story-page' && name !== 'core/block' ) { + if ( name !== 'amp/amp-story-page' ) { // Do not allow inserting any of the blocks if they're not AMP Story blocks. return { ...props, diff --git a/assets/src/plugins/template-menu-item.js b/assets/src/plugins/template-menu-item.js new file mode 100644 index 00000000000..942a24bde12 --- /dev/null +++ b/assets/src/plugins/template-menu-item.js @@ -0,0 +1,64 @@ +/** + * WordPress dependencies + */ +import { registerPlugin } from '@wordpress/plugins'; +import { PluginBlockSettingsMenuItem } from '@wordpress/edit-post'; +import { __ } from '@wordpress/i18n'; +import { select, dispatch } from '@wordpress/data'; +import { cloneBlock } from '@wordpress/blocks'; + +/** + * External dependencies + */ +import { uniqueId } from 'lodash'; + +const addTemplate = () => { + const { getSelectedBlockClientId, getBlock } = select( 'core/block-editor' ); + const { + __experimentalReceiveReusableBlocks: receiveReusableBlocks, + __experimentalSaveReusableBlock: saveReusableBlock, + } = dispatch( 'core/editor' ); + + // @todo Allow multi-page templates. + const parsedBlock = getBlock( getSelectedBlockClientId() ); + if ( 'amp/amp-story-page' !== parsedBlock.name ) { + return; + } + + // Clone for having a different ID. + const templateBlock = cloneBlock( parsedBlock ); + + // @todo Allow choosing name for the template. + const reusableBlock = { + id: uniqueId( 'reusable' ), + clientId: templateBlock.clientId, + title: __( 'Template', 'amp' ), + }; + + receiveReusableBlocks( [ { + reusableBlock, + parsedBlock: templateBlock, + } ] ); + + // @todo Display notice. + saveReusableBlock( reusableBlock.id ); +}; + +/** + * Register plugin for adding Templates (Reusable blocks) without converting the page itself to a reusable block. + */ +export function registerTemplateSaveMenuItem() { + // @todo Change icon. + registerPlugin( 'amp-story', { + render: ( ) => ( + + ), + } ); +} + +registerTemplateSaveMenuItem(); From 24bf37cf8dc2a13971e968c09f040767a9e9debe Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Thu, 28 Mar 2019 15:39:45 +0100 Subject: [PATCH 11/23] Update dashicon. --- assets/src/plugins/template-menu-item.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/src/plugins/template-menu-item.js b/assets/src/plugins/template-menu-item.js index 942a24bde12..26f925b8532 100644 --- a/assets/src/plugins/template-menu-item.js +++ b/assets/src/plugins/template-menu-item.js @@ -53,7 +53,7 @@ export function registerTemplateSaveMenuItem() { render: ( ) => ( From 364a61f85276f10515a8ac543867939b496acd7e Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Thu, 28 Mar 2019 20:23:36 +0100 Subject: [PATCH 12/23] Prevent endless loading. --- assets/src/components/template-inserter/index.js | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/assets/src/components/template-inserter/index.js b/assets/src/components/template-inserter/index.js index fbd8a0398a7..bd091d1f0e6 100644 --- a/assets/src/components/template-inserter/index.js +++ b/assets/src/components/template-inserter/index.js @@ -2,7 +2,7 @@ * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { Dropdown, IconButton, Spinner } from '@wordpress/components'; +import { Dropdown, IconButton } from '@wordpress/components'; import { Component } from '@wordpress/element'; import { withSelect, withDispatch } from '@wordpress/data'; import { createBlock, cloneBlock } from '@wordpress/blocks'; @@ -24,7 +24,7 @@ class TemplateInserter extends Component { this.onToggle = this.onToggle.bind( this ); this.state = { - reusableBlocks: null, + reusableBlocks: [], }; } @@ -80,11 +80,7 @@ class TemplateInserter extends Component { // Clone block to avoid duplicate ID-s. insertBlock( cloneBlock( block ) ); }; - if ( ! this.state.reusableBlocks ) { - return ( - - ); - } + const storyTemplates = this.state.reusableBlocks.filter( ( { clientId } ) => isStoryBlock( clientId ) ); return ( From 788d22d0835f3e2a8a04c0ebe64672abc4a7b0c8 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Thu, 28 Mar 2019 21:03:12 +0100 Subject: [PATCH 13/23] Style fix. --- assets/css/amp-editor-story-blocks.css | 1 - 1 file changed, 1 deletion(-) diff --git a/assets/css/amp-editor-story-blocks.css b/assets/css/amp-editor-story-blocks.css index e2adb8acea2..64352640457 100644 --- a/assets/css/amp-editor-story-blocks.css +++ b/assets/css/amp-editor-story-blocks.css @@ -751,7 +751,6 @@ div[data-type="amp/amp-story-page"] .wp-block-image { width: 49px; border: 1px solid #AAAEB3; border-radius: 50%; - margin-right: 10px; } .amp-stories__template-inserter__popover.components-popover .components-popover__content:not(.is-mobile) { From 46834cf7463b4308543beba3cd026a8c0b8d632f Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Fri, 29 Mar 2019 13:30:36 +0100 Subject: [PATCH 14/23] Add todo notice. --- assets/src/plugins/template-menu-item.js | 1 + 1 file changed, 1 insertion(+) diff --git a/assets/src/plugins/template-menu-item.js b/assets/src/plugins/template-menu-item.js index 26f925b8532..960fa33c092 100644 --- a/assets/src/plugins/template-menu-item.js +++ b/assets/src/plugins/template-menu-item.js @@ -49,6 +49,7 @@ const addTemplate = () => { */ export function registerTemplateSaveMenuItem() { // @todo Change icon. + // @todo allowedBlockNames restriction is not working properly. registerPlugin( 'amp-story', { render: ( ) => ( Date: Mon, 1 Apr 2019 12:03:18 +0200 Subject: [PATCH 15/23] Use pre-existing pageIcon file --- .../src/components/template-inserter/icon.js | 20 ------------------- .../src/components/template-inserter/index.js | 4 ++-- 2 files changed, 2 insertions(+), 22 deletions(-) delete mode 100644 assets/src/components/template-inserter/icon.js diff --git a/assets/src/components/template-inserter/icon.js b/assets/src/components/template-inserter/icon.js deleted file mode 100644 index 8f26ebdd034..00000000000 --- a/assets/src/components/template-inserter/icon.js +++ /dev/null @@ -1,20 +0,0 @@ -const pageIcon = ( - - - - - - - - - - - - - - - - -); - -export default pageIcon; diff --git a/assets/src/components/template-inserter/index.js b/assets/src/components/template-inserter/index.js index bd091d1f0e6..fe2ef7fb7d0 100644 --- a/assets/src/components/template-inserter/index.js +++ b/assets/src/components/template-inserter/index.js @@ -12,7 +12,7 @@ import { compose } from '@wordpress/compose'; * Internal dependencies */ import BlockPreview from './block-preview'; -import pageIcon from './icon'; +import pageIcon from '../../../images/add-page-inserter.svg'; import { ICONS } from './../../constants'; const storyPageBlockName = 'amp/amp-story-page'; @@ -94,7 +94,7 @@ class TemplateInserter extends Component {
    { onSelect( null ); From 9f4d919a3994a7e5085ba219705986cb216035af Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Mon, 1 Apr 2019 12:24:21 +0200 Subject: [PATCH 16/23] Use pre-existing BlockPreview component --- .../{editor-carousel => }/block-preview.js | 10 ++-- .../editor-carousel/reorderer-item.js | 2 +- assets/src/components/index.js | 1 + .../template-inserter/block-preview.js | 48 ------------------- .../src/components/template-inserter/index.js | 20 ++++---- 5 files changed, 20 insertions(+), 61 deletions(-) rename assets/src/components/{editor-carousel => }/block-preview.js (67%) delete mode 100644 assets/src/components/template-inserter/block-preview.js diff --git a/assets/src/components/editor-carousel/block-preview.js b/assets/src/components/block-preview.js similarity index 67% rename from assets/src/components/editor-carousel/block-preview.js rename to assets/src/components/block-preview.js index 779aab0abe8..24dba88713e 100644 --- a/assets/src/components/editor-carousel/block-preview.js +++ b/assets/src/components/block-preview.js @@ -6,14 +6,16 @@ import { Disabled } from '@wordpress/components'; import { BlockEdit } from '@wordpress/editor'; /** - * BlockPreview component that is used within the reordering UI. + * Block Preview Component: It renders a preview given a block name and attributes. * - * @return {Object} Block preview. + * @param {Object} props Component props. + * + * @return {WPElement} Rendered element. */ -const BlockPreview = ( { clientId, name, attributes, innerBlocks } ) => { +const BlockPreview = ( { clientId, name, attributes, innerBlocks = [] } ) => { const block = createBlock( name, attributes, innerBlocks ); return ( - + - - - ); - /* eslint-enable */ -} - -export function BlockPreviewContent( { name, attributes } ) { - // @todo Importing this outside of the function causes error for some reason. - const BlockEdit = wp.blockEditor.BlockEdit; - const block = createBlock( name, attributes ); - return ( - - - - ); -} - -export default BlockPreview; diff --git a/assets/src/components/template-inserter/index.js b/assets/src/components/template-inserter/index.js index fe2ef7fb7d0..c83c1ce7f9b 100644 --- a/assets/src/components/template-inserter/index.js +++ b/assets/src/components/template-inserter/index.js @@ -2,7 +2,7 @@ * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { Dropdown, IconButton } from '@wordpress/components'; +import { Dropdown, IconButton, Button } from '@wordpress/components'; import { Component } from '@wordpress/element'; import { withSelect, withDispatch } from '@wordpress/data'; import { createBlock, cloneBlock } from '@wordpress/blocks'; @@ -11,7 +11,7 @@ import { compose } from '@wordpress/compose'; /** * Internal dependencies */ -import BlockPreview from './block-preview'; +import { BlockPreview } from '../'; import pageIcon from '../../../images/add-page-inserter.svg'; import { ICONS } from './../../constants'; @@ -102,16 +102,20 @@ class TemplateInserter extends Component { className="amp-stories__blank-page-inserter editor-block-preview__content block-editor-block-preview__content editor-styles-wrapper" />
    - { storyTemplates && storyTemplates.map( ( item ) => - ( + + ) ) }
    From de7736388b5e2279d480dddda12d2b54d57f1daa Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Mon, 1 Apr 2019 12:32:57 +0200 Subject: [PATCH 17/23] Extract all SVGs into separate files --- assets/images/add-template.svg | 11 +++++++ assets/images/amp-story-page-icon.svg | 1 + assets/images/reorder.svg | 11 +++++++ assets/src/blocks/amp-story/index.js | 5 ++-- assets/src/components/story-controls.js | 14 ++++----- .../src/components/template-inserter/index.js | 4 +-- assets/src/constants.js | 29 ------------------- 7 files changed, 35 insertions(+), 40 deletions(-) create mode 100644 assets/images/add-template.svg create mode 100644 assets/images/amp-story-page-icon.svg create mode 100644 assets/images/reorder.svg diff --git a/assets/images/add-template.svg b/assets/images/add-template.svg new file mode 100644 index 00000000000..34e0931fc66 --- /dev/null +++ b/assets/images/add-template.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/assets/images/amp-story-page-icon.svg b/assets/images/amp-story-page-icon.svg new file mode 100644 index 00000000000..962789c0621 --- /dev/null +++ b/assets/images/amp-story-page-icon.svg @@ -0,0 +1 @@ + diff --git a/assets/images/reorder.svg b/assets/images/reorder.svg new file mode 100644 index 00000000000..a6786eaef01 --- /dev/null +++ b/assets/images/reorder.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/assets/src/blocks/amp-story/index.js b/assets/src/blocks/amp-story/index.js index a2aefea0e75..fec2247d63d 100644 --- a/assets/src/blocks/amp-story/index.js +++ b/assets/src/blocks/amp-story/index.js @@ -8,8 +8,9 @@ import { InnerBlocks } from '@wordpress/editor'; /** * Internal dependencies */ -import { BLOCK_ICONS, IMAGE_BACKGROUND_TYPE, VIDEO_BACKGROUND_TYPE } from '../../constants'; +import { IMAGE_BACKGROUND_TYPE, VIDEO_BACKGROUND_TYPE } from '../../constants'; import EditPage from './edit'; +import blockIcon from '../../../images/amp-story-page-icon.svg'; export const name = 'amp/amp-story-page'; @@ -54,7 +55,7 @@ const schema = { export const settings = { title: __( 'Page', 'amp' ), category: 'layout', - icon: BLOCK_ICONS[ 'amp/amp-story-page' ], + icon: blockIcon( { width: 24, height: 24 } ), attributes: schema, supports: { diff --git a/assets/src/components/story-controls.js b/assets/src/components/story-controls.js index 7918a6ac65f..205a4ecc7c4 100644 --- a/assets/src/components/story-controls.js +++ b/assets/src/components/story-controls.js @@ -3,12 +3,6 @@ * to add new pages and start/stop reordering pages. */ -/** - * Internal dependencies - */ -import { TemplateInserter } from './'; -import { ICONS } from './../constants'; - /** * WordPress dependencies */ @@ -18,6 +12,12 @@ import { Fragment } from '@wordpress/element'; import { withDispatch, withSelect } from '@wordpress/data'; import { compose } from '@wordpress/compose'; +/** + * Internal dependencies + */ +import { TemplateInserter } from './'; +import reorderIcon from '../../images/reorder.svg'; + function StoryControls( { isReordering, startReordering, saveOrder, resetOrder } ) { if ( isReordering ) { return ( @@ -46,7 +46,7 @@ function StoryControls( { isReordering, startReordering, saveOrder, resetOrder } diff --git a/assets/src/components/template-inserter/index.js b/assets/src/components/template-inserter/index.js index c83c1ce7f9b..14651fd651d 100644 --- a/assets/src/components/template-inserter/index.js +++ b/assets/src/components/template-inserter/index.js @@ -13,7 +13,7 @@ import { compose } from '@wordpress/compose'; */ import { BlockPreview } from '../'; import pageIcon from '../../../images/add-page-inserter.svg'; -import { ICONS } from './../../constants'; +import addTemplateIcon from '../../../images/add-template.svg'; const storyPageBlockName = 'amp/amp-story-page'; @@ -60,7 +60,7 @@ class TemplateInserter extends Component { expandOnMobile renderToggle={ ( { onToggle, isOpen } ) => ( , -}; - -export const ICONS = { - 'add-template': - - - - - - - - - - , - reorder: - - - - - - - - - - , -}; - export const ANIMATION_DURATION_DEFAULTS = { drop: 1600, 'fade-in': 500, From 379d51d25563d4637933bff2f5517cfe6b7ec760 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Mon, 1 Apr 2019 12:33:05 +0200 Subject: [PATCH 18/23] Fix reorder cancel button styling --- assets/css/amp-editor-story-blocks.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/css/amp-editor-story-blocks.css b/assets/css/amp-editor-story-blocks.css index 64352640457..82b97789306 100644 --- a/assets/css/amp-editor-story-blocks.css +++ b/assets/css/amp-editor-story-blocks.css @@ -386,8 +386,8 @@ div[data-type="amp/amp-story-page"] .editor-inner-blocks .editor-block-list__lay } .amp-story-controls-reorder-cancel { - padding-top: 2px; - padding-bottom: 2px; + padding-top: 5px; + padding-bottom: 5px; margin-right: 20px; display: inline-flex; } From 6859bfd684474efa138d8e136f9d76e79e2a751b Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Mon, 1 Apr 2019 12:34:49 +0200 Subject: [PATCH 19/23] ESLint fix --- assets/src/components/story-controls.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/src/components/story-controls.js b/assets/src/components/story-controls.js index 205a4ecc7c4..693d93b5cdf 100644 --- a/assets/src/components/story-controls.js +++ b/assets/src/components/story-controls.js @@ -46,7 +46,7 @@ function StoryControls( { isReordering, startReordering, saveOrder, resetOrder } From abd0879e9495373c4ceae936b9f6553d40b2fa9b Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Mon, 1 Apr 2019 12:50:32 +0200 Subject: [PATCH 20/23] Remove unused import after merge --- assets/src/components/story-controls.js | 1 - 1 file changed, 1 deletion(-) diff --git a/assets/src/components/story-controls.js b/assets/src/components/story-controls.js index 854f2edab1d..693d93b5cdf 100644 --- a/assets/src/components/story-controls.js +++ b/assets/src/components/story-controls.js @@ -9,7 +9,6 @@ import { __ } from '@wordpress/i18n'; import { IconButton, Button } from '@wordpress/components'; import { Fragment } from '@wordpress/element'; -import { Inserter } from '@wordpress/block-editor'; import { withDispatch, withSelect } from '@wordpress/data'; import { compose } from '@wordpress/compose'; From d72d6eed1f22299966dde81e839d4604254e1c2d Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Mon, 1 Apr 2019 15:08:36 +0200 Subject: [PATCH 21/23] Add role to PluginBlockSettingsMenuItem --- assets/src/plugins/template-menu-item.js | 1 + 1 file changed, 1 insertion(+) diff --git a/assets/src/plugins/template-menu-item.js b/assets/src/plugins/template-menu-item.js index 960fa33c092..1e75ffc4d85 100644 --- a/assets/src/plugins/template-menu-item.js +++ b/assets/src/plugins/template-menu-item.js @@ -56,6 +56,7 @@ export function registerTemplateSaveMenuItem() { allowedBlockNames={ [ 'amp/amp-story-page' ] } icon="welcome-add-page" label={ __( 'Save as Template', 'amp' ) } + role="menuitem" onClick={ addTemplate } /> ), From 53def88cc74d2bcb20d43a9c740c4780d286b698 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Mon, 1 Apr 2019 15:08:54 +0200 Subject: [PATCH 22/23] Remove allowedBlockNames todo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It’s an upstream bug, see https://github.com/WordPress/gutenberg/pull/14741 --- assets/src/plugins/template-menu-item.js | 1 - 1 file changed, 1 deletion(-) diff --git a/assets/src/plugins/template-menu-item.js b/assets/src/plugins/template-menu-item.js index 1e75ffc4d85..1596bc93d62 100644 --- a/assets/src/plugins/template-menu-item.js +++ b/assets/src/plugins/template-menu-item.js @@ -49,7 +49,6 @@ const addTemplate = () => { */ export function registerTemplateSaveMenuItem() { // @todo Change icon. - // @todo allowedBlockNames restriction is not working properly. registerPlugin( 'amp-story', { render: ( ) => ( Date: Mon, 1 Apr 2019 16:35:33 +0200 Subject: [PATCH 23/23] Rename allowedBlockNames to allowedBlocks as per upstream discussion See https://github.com/WordPress/gutenberg/pull/14741 --- assets/src/plugins/template-menu-item.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/src/plugins/template-menu-item.js b/assets/src/plugins/template-menu-item.js index 1596bc93d62..a8a7bace5c7 100644 --- a/assets/src/plugins/template-menu-item.js +++ b/assets/src/plugins/template-menu-item.js @@ -52,7 +52,7 @@ export function registerTemplateSaveMenuItem() { registerPlugin( 'amp-story', { render: ( ) => (