Skip to content

Commit

Permalink
Layout selector performance improvements (#1577)
Browse files Browse the repository at this point in the history
* Add a bunch of test layouts

* Prune styles

* Rewrite preview to use static html from serialized blocks

* Load gallery block assets in the editor.

* Refresh masonry galleries once layouts load.

* Abstract results list so we can lazyload with useAsyncList

* Use new layout results component

* Add placeholder styles

* Remove test layouts

* Fix placeholder styles

* Use is_page_gutenberg over is_admin

* Add inline docs

* Fix preview wrapper and overlay
  • Loading branch information
jrtashjian committed Nov 9, 2020
1 parent 66a5427 commit dcf94d6
Show file tree
Hide file tree
Showing 5 changed files with 185 additions and 134 deletions.
11 changes: 6 additions & 5 deletions includes/class-coblocks-block-assets.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ public function __construct() {
add_action( 'enqueue_block_assets', array( $this, 'block_assets' ) );
add_action( 'init', array( $this, 'editor_assets' ) );
add_action( 'enqueue_block_editor_assets', array( $this, 'editor_scripts' ) );
add_action( 'enqueue_block_editor_assets', array( $this, 'frontend_scripts' ) );
add_action( 'wp_enqueue_scripts', array( $this, 'frontend_scripts' ) );
}

Expand Down Expand Up @@ -316,7 +317,7 @@ public function frontend_scripts() {
);

// Masonry block.
if ( has_block( 'coblocks/gallery-masonry' ) || has_block( 'core/block' ) ) {
if ( $this->is_page_gutenberg() || has_block( 'coblocks/gallery-masonry' ) || has_block( 'core/block' ) ) {
wp_enqueue_script(
'coblocks-masonry',
$dir . 'coblocks-masonry.js',
Expand All @@ -327,7 +328,7 @@ public function frontend_scripts() {
}

// Carousel block.
if ( has_block( 'coblocks/gallery-carousel' ) || has_block( 'core/block' ) ) {
if ( $this->is_page_gutenberg() || has_block( 'coblocks/gallery-carousel' ) || has_block( 'core/block' ) ) {
wp_enqueue_script(
'coblocks-flickity',
$vendors_dir . '/flickity.js',
Expand All @@ -336,7 +337,7 @@ public function frontend_scripts() {
true
);

if ( has_block( 'coblocks/accordion' ) || has_block( 'core/block' ) ) {
if ( $this->is_page_gutenberg() || has_block( 'coblocks/accordion' ) || has_block( 'core/block' ) ) {
wp_enqueue_script(
'coblocks-accordion-carousel',
$dir . 'coblocks-accordion-carousel.js',
Expand All @@ -348,7 +349,7 @@ public function frontend_scripts() {
}

// Post Carousel block.
if ( has_block( 'coblocks/post-carousel' ) || has_block( 'core/block' ) ) {
if ( $this->is_page_gutenberg() || has_block( 'coblocks/post-carousel' ) || has_block( 'core/block' ) ) {
wp_enqueue_script(
'coblocks-slick',
$vendors_dir . '/slick.js',
Expand All @@ -366,7 +367,7 @@ public function frontend_scripts() {
}

// Events block.
if ( has_block( 'coblocks/events' ) || has_block( 'core/block' ) ) {
if ( $this->is_page_gutenberg() || has_block( 'coblocks/events' ) || has_block( 'core/block' ) ) {
wp_enqueue_script(
'coblocks-slick',
$vendors_dir . '/slick.js',
Expand Down
21 changes: 13 additions & 8 deletions src/extensions/layout-selector/editor.scss
Original file line number Diff line number Diff line change
Expand Up @@ -248,22 +248,23 @@
}

&__layouts-column {
padding: 0 1rem;
width: 50%;
}

&__layout {
background-color: var(--go--color--background, $white);
border-radius: $radius-block-ui;
display: flex;
flex-basis: 50%;
flex-grow: 1;
margin: 0 5% 10% 5%;
height: auto;
margin-bottom: 2rem;
padding: 0;
position: relative;
text-decoration: none;
width: 100%;


@media (max-width: 1024px) {
flex-basis: 100%;
margin-right: 0;
max-width: 100%;
}
Expand All @@ -287,8 +288,14 @@
box-shadow: 0 0 0 1px $white, 0 0 0 3px var(--wp-admin-theme-color, #007cba);
}

&.is-selected::after {
box-shadow: 0 0 0 1px $white, 0 0 0 3px var(--wp-admin-theme-color, #007cba);
&.is-placeholder {
align-items: center;
justify-content: center;
min-height: 150px;

.components-spinner {
margin: 0;
}
}

&:hover,
Expand All @@ -300,9 +307,7 @@
&__layout--overlay {
align-items: center;
background: rgba(255, 255, 255, 0.75);
border: 2px solid var(--wp-admin-theme-color, #007cba);
bottom: 0;
display: none !important; // Hide this temp.
display: flex;
flex-direction: column;
justify-content: center;
Expand Down
141 changes: 28 additions & 113 deletions src/extensions/layout-selector/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,19 @@ import map from 'lodash/map';
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { Component, Fragment } from '@wordpress/element';
import { applyFilters } from '@wordpress/hooks';
import { Component, Fragment, useState } from '@wordpress/element';
import { registerPlugin } from '@wordpress/plugins';
import { compose } from '@wordpress/compose';
import { withSelect, withDispatch } from '@wordpress/data';
import { Button, Modal, Icon, SVG, Path, DropdownMenu, MenuGroup, MenuItem } from '@wordpress/components';
import { BlockPreview } from '@wordpress/block-editor';
import { createBlock, rawHandler } from '@wordpress/blocks';

/**
* Internal dependencies
*/
import './store';
import { LayoutSelectorResults } from './layout-selector-results';
import CoBlocksLayoutSelectorFill from './layout-selector-slot';

const getBlocksFromTemplate = ( name, attributes, innerBlocks = [] ) => {
Expand All @@ -32,66 +32,6 @@ const getBlocksFromTemplate = ( name, attributes, innerBlocks = [] ) => {
);
};

const getTemplateFromBlocks = ( name, attributes, innerBlocks = [] ) => {
return [ name, attributes,
innerBlocks && innerBlocks.map( ( blockObject ) => {
return getTemplateFromBlocks( blockObject.name, blockObject.attributes, blockObject.innerBlocks );
} ),
];
};

export const LayoutPreview = ( { layout, isSelected, registeredBlocks, onClick } ) => {
const [ overlay, setOverlay ] = useState( false );

/**
* Filters the list of blocks within the layout preview.
*
* @param {Array} blocks The block objects of the layout.
*/
const filterdLayoutBlocks = applyFilters(
'coblocks.layoutPreviewBlocks',
layout.blocks
? layout.blocks.map( ( block ) => Array.isArray( block ) ? getBlocksFromTemplate( block[ 0 ], block[ 1 ], block[ 2 ] ) : block )
: rawHandler( { HTML: layout.postContent } )
);

const layoutBlocks = filterdLayoutBlocks.map(
( blockObject ) => getTemplateFromBlocks( blockObject.name, blockObject.attributes, blockObject.innerBlocks )
);

return (
<a href="#!"
key={ layout }
className={ classnames( 'coblocks-layout-selector__layout', { 'is-selected': isSelected } ) }
onClick={ ( event ) => {
event.preventDefault();
onClick();
} }
onMouseEnter={ () => setOverlay( true ) }
onMouseLeave={ () => setOverlay( false ) }>

<div className={ classnames( 'coblocks-layout-selector__layout--overlay', { 'is-active': overlay } ) }>
<Button isPressed>
{ __( 'Select Layout', 'coblocks' ) }
</Button>
</div>

<BlockPreview
autoHeight
blocks={
layoutBlocks
.filter( ( currentLayout ) => registeredBlocks.includes( currentLayout[ 0 ] ) )
.map(
( [ name, attributes, innerBlocks = [] ] ) => {
return getBlocksFromTemplate( name, attributes, innerBlocks );
}
)
}
/>
</a>
);
};

const SidebarItem = ( { slug, title, isSelected, onClick } ) => {
return (
<li key={ slug } className="coblocks-layout-selector__sidebar__item">
Expand Down Expand Up @@ -125,21 +65,14 @@ class LayoutSelector extends Component {
}

// Replace any blocks with the selected layout.
useTemplateLayout = ( layout, registeredBlocks ) => {
useTemplateLayout = ( layout ) => {
const {
editPost,
} = this.props;

const layoutBlocks = layout.blocks || rawHandler( { HTML: layout.postContent } ).map(
( blockObject ) => getTemplateFromBlocks( blockObject.name, blockObject.attributes, blockObject.innerBlocks )
);

editPost( {
title: layout.label,
blocks: layoutBlocks.filter( ( layoutElem ) => registeredBlocks.includes( layoutElem[ 0 ] ) )
.map( ( [ name, attributes, innerBlocks = [] ] ) => {
return getBlocksFromTemplate( name, attributes, innerBlocks );
} ),
blocks: layout.blocks,
} );
}

Expand All @@ -151,46 +84,6 @@ class LayoutSelector extends Component {
return !! this.getLayoutsInCategory( category ).length;
}

renderContent = ( selectedCategory ) => {
const registeredBlocks = map( wp.blocks.getBlockTypes(), 'name' );

const foundLayouts = this.getLayoutsInCategory( selectedCategory );

const layoutsCol1 = foundLayouts.slice( 0, Math.ceil( foundLayouts.length / 2 ) );
const layoutsCol2 = foundLayouts.slice( Math.ceil( foundLayouts.length / 2 ) );

return this.hasLayoutsInCategory( selectedCategory ) ? (
<div className="coblocks-layout-selector__layouts">
<div className="coblocks-layout-selector__layouts-column">
{ layoutsCol1.map( ( layout, index ) => (
<LayoutPreview
key={ index }
layout={ layout }
registeredBlocks={ registeredBlocks }
onClick={ () => {
this.useTemplateLayout( layout, registeredBlocks );
this.props.closeTemplateSelector();
} }
/>
) ) }
</div>
<div className="coblocks-layout-selector__layouts-column">
{ layoutsCol2.map( ( layout, index ) => (
<LayoutPreview
key={ index }
layout={ layout }
registeredBlocks={ registeredBlocks }
onClick={ () => {
this.useTemplateLayout( layout, registeredBlocks );
this.props.closeTemplateSelector();
} }
/>
) ) }
</div>
</div>
) : ( <p><em>{ __( 'No layouts are available for this category.', 'coblocks' ) }</em></p> );
}

render() {
const { selectedCategory } = this.state;
const {
Expand Down Expand Up @@ -288,7 +181,14 @@ class LayoutSelector extends Component {
</div>

<div className="coblocks-layout-selector__content">
{ this.renderContent( selectedCategory ) }
<LayoutSelectorResults
layouts={ this.props.layouts }
category={ selectedCategory }
onInsert={ ( layout ) => {
this.useTemplateLayout( layout );
this.props.closeTemplateSelector();
} }
/>
</div>
</div>
</Modal>
Expand Down Expand Up @@ -317,10 +217,25 @@ if ( typeof coblocksLayoutSelector !== 'undefined' && coblocksLayoutSelector.pos
const isDraft = [ 'draft' ].indexOf( getCurrentPostAttribute( 'status' ) ) !== -1;
const isCleanUnpublishedPost = ! isCurrentPostPublished() && ! hasEditorUndo() && ! isDraft;

// Get block objects before passing into the component.
const layouts = getLayouts().map(
( layout ) => {
const blocks = layout.blocks
? layout.blocks.map(
( block ) => Array.isArray( block )
? getBlocksFromTemplate( block[ 0 ], block[ 1 ], block[ 2 ] )
: block
)
: rawHandler( { HTML: layout.postContent } );

return { ...layout, blocks };
}
);

return {
isActive: isCleanUnpublishedPost || isTemplateSelectorActive(),
layoutSelectorEnabled: getLayoutSelector() && hasLayouts() && hasCategories(),
layouts: getLayouts(),
layouts,
categories: getCategories(),
};
} ),
Expand Down
Loading

0 comments on commit dcf94d6

Please sign in to comment.