From 63bfdcb609cdcbce3a3065ed724e4c3b6e88ce0a Mon Sep 17 00:00:00 2001 From: Nik Tsekouras Date: Tue, 17 Nov 2020 17:31:49 +0200 Subject: [PATCH] [Query block]: Add Posts List variation (#26990) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Query block]: Add Posts List variation * fix typo Co-authored-by: Greg Ziółkowski * add variation description * expose __experimentalGetMatchingVariation * augment Query Placeholder - try to match a block variation * fix import Co-authored-by: Greg Ziółkowski --- .../block-variation-transforms/index.js | 20 ++--- .../block-variation-transforms/test/index.js | 75 ------------------- .../src/utils/block-variation-transforms.js | 31 ++++++++ packages/block-editor/src/utils/index.js | 1 + .../utils/test/block-variation-transforms.js | 70 +++++++++++++++++ .../src/query/edit/query-placeholder.js | 22 ++++-- .../block-library/src/query/variations.js | 25 +++++++ 7 files changed, 148 insertions(+), 96 deletions(-) delete mode 100644 packages/block-editor/src/components/block-variation-transforms/test/index.js create mode 100644 packages/block-editor/src/utils/block-variation-transforms.js create mode 100644 packages/block-editor/src/utils/test/block-variation-transforms.js diff --git a/packages/block-editor/src/components/block-variation-transforms/index.js b/packages/block-editor/src/components/block-variation-transforms/index.js index 5d07bbe8d9a823..251637d39a08bf 100644 --- a/packages/block-editor/src/components/block-variation-transforms/index.js +++ b/packages/block-editor/src/components/block-variation-transforms/index.js @@ -1,8 +1,3 @@ -/** - * External dependencies - */ -import { isMatch } from 'lodash'; - /** * WordPress dependencies */ @@ -16,15 +11,10 @@ import { useSelect, useDispatch } from '@wordpress/data'; import { useState, useEffect } from '@wordpress/element'; import { chevronDown } from '@wordpress/icons'; -export const getMatchingVariationName = ( blockAttributes, variations ) => { - if ( ! variations || ! blockAttributes ) return; - const matches = variations.filter( ( { attributes } ) => { - if ( ! attributes || ! Object.keys( attributes ).length ) return false; - return isMatch( blockAttributes, attributes ); - } ); - if ( matches.length !== 1 ) return; - return matches[ 0 ].name; -}; +/** + * Internal dependencies + */ +import { __experimentalGetMatchingVariation as getMatchingVariation } from '../../utils'; function __experimentalBlockVariationTransforms( { blockClientId } ) { const [ selectedValue, setSelectedValue ] = useState(); @@ -46,7 +36,7 @@ function __experimentalBlockVariationTransforms( { blockClientId } ) { ); useEffect( () => { setSelectedValue( - getMatchingVariationName( blockAttributes, variations ) + getMatchingVariation( blockAttributes, variations )?.name ); }, [ blockAttributes, variations ] ); if ( ! variations?.length ) return null; diff --git a/packages/block-editor/src/components/block-variation-transforms/test/index.js b/packages/block-editor/src/components/block-variation-transforms/test/index.js deleted file mode 100644 index 31b75099919cad..00000000000000 --- a/packages/block-editor/src/components/block-variation-transforms/test/index.js +++ /dev/null @@ -1,75 +0,0 @@ -/** - * Internal dependencies - */ -import { getMatchingVariationName } from '../index'; - -describe( 'BlockVariationTransforms', () => { - describe( 'getMatchingVariationName', () => { - describe( 'should not find a match', () => { - it( 'when no variations or attributes passed', () => { - expect( - getMatchingVariationName( null, { content: 'hi' } ) - ).toBeUndefined(); - expect( getMatchingVariationName( {} ) ).toBeUndefined(); - } ); - it( 'when no variation matched', () => { - const variations = [ - { name: 'one', attributes: { level: 1 } }, - { name: 'two', attributes: { level: 2 } }, - ]; - expect( - getMatchingVariationName( { level: 4 }, variations ) - ).toBeUndefined(); - } ); - it( 'when more than one match found', () => { - const variations = [ - { name: 'one', attributes: { level: 1 } }, - { name: 'two', attributes: { level: 1, content: 'hi' } }, - ]; - expect( - getMatchingVariationName( - { level: 1, content: 'hi', other: 'prop' }, - variations - ) - ).toBeUndefined(); - } ); - it( 'when variation is a superset of attributes', () => { - const variations = [ - { name: 'one', attributes: { level: 1, content: 'hi' } }, - ]; - expect( - getMatchingVariationName( - { level: 1, other: 'prop' }, - variations - ) - ).toBeUndefined(); - } ); - } ); - describe( 'should find a match', () => { - it( 'when variation has one attribute', () => { - const variations = [ - { name: 'one', attributes: { level: 1 } }, - { name: 'two', attributes: { level: 2 } }, - ]; - expect( - getMatchingVariationName( - { level: 2, content: 'hi', other: 'prop' }, - variations - ) - ).toEqual( 'two' ); - } ); - it( 'when variation has many attributes', () => { - const variations = [ - { name: 'one', attributes: { level: 1, content: 'hi' } }, - { name: 'two', attributes: { level: 2 } }, - ]; - expect( - getMatchingVariationName( - { level: 1, content: 'hi', other: 'prop' }, - variations - ) - ).toEqual( 'one' ); - } ); - } ); - } ); -} ); diff --git a/packages/block-editor/src/utils/block-variation-transforms.js b/packages/block-editor/src/utils/block-variation-transforms.js new file mode 100644 index 00000000000000..db0901e6280127 --- /dev/null +++ b/packages/block-editor/src/utils/block-variation-transforms.js @@ -0,0 +1,31 @@ +/** + * External dependencies + */ +import { isMatch } from 'lodash'; + +/** @typedef {import('@wordpress/blocks').WPBlockVariation} WPBlockVariation */ + +/** + * Matches the provided block variations with a block's attributes. If no match + * or more than one matches are found it returns `undefined`. If a single match is + * found it returns it. + * + * This is a simple implementation for now as it takes into account only the attributes + * of a block variation and not `InnerBlocks`. + * + * @param {Object} blockAttributes - The block attributes to try to find a match. + * @param {WPBlockVariation[]} variations - A list of block variations to test for a match. + * @return {?WPBlockVariation} - If a match is found returns it. If not or more than one matches are found returns `undefined`. + */ +export const __experimentalGetMatchingVariation = ( + blockAttributes, + variations +) => { + if ( ! variations || ! blockAttributes ) return; + const matches = variations.filter( ( { attributes } ) => { + if ( ! attributes || ! Object.keys( attributes ).length ) return false; + return isMatch( blockAttributes, attributes ); + } ); + if ( matches.length !== 1 ) return; + return matches[ 0 ]; +}; diff --git a/packages/block-editor/src/utils/index.js b/packages/block-editor/src/utils/index.js index c1ba2027f62065..f498a6bf4740bb 100644 --- a/packages/block-editor/src/utils/index.js +++ b/packages/block-editor/src/utils/index.js @@ -1,2 +1,3 @@ export { default as transformStyles } from './transform-styles'; export * from './theme'; +export * from './block-variation-transforms'; diff --git a/packages/block-editor/src/utils/test/block-variation-transforms.js b/packages/block-editor/src/utils/test/block-variation-transforms.js new file mode 100644 index 00000000000000..17c82bdb951329 --- /dev/null +++ b/packages/block-editor/src/utils/test/block-variation-transforms.js @@ -0,0 +1,70 @@ +/** + * Internal dependencies + */ +import { __experimentalGetMatchingVariation as getMatchingVariation } from '../block-variation-transforms'; + +describe( 'getMatchingVariation', () => { + describe( 'should not find a match', () => { + it( 'when no variations or attributes passed', () => { + expect( + getMatchingVariation( null, { content: 'hi' } ) + ).toBeUndefined(); + expect( getMatchingVariation( {} ) ).toBeUndefined(); + } ); + it( 'when no variation matched', () => { + const variations = [ + { name: 'one', attributes: { level: 1 } }, + { name: 'two', attributes: { level: 2 } }, + ]; + expect( + getMatchingVariation( { level: 4 }, variations ) + ).toBeUndefined(); + } ); + it( 'when more than one match found', () => { + const variations = [ + { name: 'one', attributes: { level: 1 } }, + { name: 'two', attributes: { level: 1, content: 'hi' } }, + ]; + expect( + getMatchingVariation( + { level: 1, content: 'hi', other: 'prop' }, + variations + ) + ).toBeUndefined(); + } ); + it( 'when variation is a superset of attributes', () => { + const variations = [ + { name: 'one', attributes: { level: 1, content: 'hi' } }, + ]; + expect( + getMatchingVariation( { level: 1, other: 'prop' }, variations ) + ).toBeUndefined(); + } ); + } ); + describe( 'should find a match', () => { + it( 'when variation has one attribute', () => { + const variations = [ + { name: 'one', attributes: { level: 1 } }, + { name: 'two', attributes: { level: 2 } }, + ]; + expect( + getMatchingVariation( + { level: 2, content: 'hi', other: 'prop' }, + variations + ).name + ).toEqual( 'two' ); + } ); + it( 'when variation has many attributes', () => { + const variations = [ + { name: 'one', attributes: { level: 1, content: 'hi' } }, + { name: 'two', attributes: { level: 2 } }, + ]; + expect( + getMatchingVariation( + { level: 1, content: 'hi', other: 'prop' }, + variations + ).name + ).toEqual( 'one' ); + } ); + } ); +} ); diff --git a/packages/block-library/src/query/edit/query-placeholder.js b/packages/block-library/src/query/edit/query-placeholder.js index 0cad4e809bdf8b..1d638f8f5a1be0 100644 --- a/packages/block-library/src/query/edit/query-placeholder.js +++ b/packages/block-library/src/query/edit/query-placeholder.js @@ -5,11 +5,17 @@ import { useSelect, useDispatch } from '@wordpress/data'; import { useBlockProps, __experimentalBlockVariationPicker, + __experimentalGetMatchingVariation as getMatchingVariation, } from '@wordpress/block-editor'; import { createBlocksFromInnerBlocksTemplate } from '@wordpress/blocks'; -const QueryPlaceholder = ( { clientId, name, setAttributes } ) => { - const { blockType, defaultVariation, variations } = useSelect( +const QueryPlaceholder = ( { clientId, name, attributes, setAttributes } ) => { + const { + blockType, + defaultVariation, + scopeVariations, + allVariations, + } = useSelect( ( select ) => { const { getBlockVariations, @@ -20,19 +26,23 @@ const QueryPlaceholder = ( { clientId, name, setAttributes } ) => { return { blockType: getBlockType( name ), defaultVariation: getDefaultBlockVariation( name, 'block' ), - variations: getBlockVariations( name, 'block' ), + scopeVariations: getBlockVariations( name, 'block' ), + allVariations: getBlockVariations( name ), }; }, [ name ] ); const { replaceInnerBlocks } = useDispatch( 'core/block-editor' ); const blockProps = useBlockProps(); + const matchingVariation = getMatchingVariation( attributes, allVariations ); + const icon = matchingVariation?.icon || blockType?.icon?.src; + const label = matchingVariation?.title || blockType?.title; return (
<__experimentalBlockVariationPicker - icon={ blockType?.icon?.src } - label={ blockType?.title } - variations={ variations } + icon={ icon } + label={ label } + variations={ scopeVariations } onSelect={ ( nextVariation = defaultVariation ) => { if ( nextVariation.attributes ) { setAttributes( nextVariation.attributes ); diff --git a/packages/block-library/src/query/variations.js b/packages/block-library/src/query/variations.js index 18434d21853437..4d6d4f1913530a 100644 --- a/packages/block-library/src/query/variations.js +++ b/packages/block-library/src/query/variations.js @@ -2,6 +2,7 @@ * WordPress dependencies */ import { __ } from '@wordpress/i18n'; +import { postList } from '@wordpress/icons'; /** * Internal dependencies @@ -14,6 +15,30 @@ import { } from './icons'; const variations = [ + { + name: 'posts-list', + title: __( 'Posts List' ), + description: __( + 'Display a list of your most recent posts, excluding sticky posts.' + ), + icon: postList, + attributes: { + query: { + perPage: 4, + pages: 1, + offset: 0, + postType: 'post', + categoryIds: [], + tagIds: [], + order: 'desc', + orderBy: 'date', + author: '', + search: '', + sticky: 'exclude', + }, + }, + scope: [ 'inserter' ], + }, { name: 'title-date', title: __( 'Title and Date' ),