Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose Template part block variations to the Inserter #30032

Merged
merged 2 commits into from
Mar 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions packages/block-library/src/template-part/block.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
},
"tagName": {
"type": "string"
},
"area": {
"type": "string"
}
},
"supports": {
Expand Down
4 changes: 3 additions & 1 deletion packages/block-library/src/template-part/edit/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,11 @@ import { TemplatePartAdvancedControls } from './advanced-controls';
import { getTagBasedOnArea } from './get-tag-based-on-area';

export default function TemplatePartEdit( {
attributes: { slug, theme, tagName, layout = {} },
attributes,
setAttributes,
clientId,
} ) {
const { slug, theme, tagName, layout = {} } = attributes;
const templatePartId = theme && slug ? theme + '//' + slug : null;

const [ hasAlreadyRendered, RecursionProvider ] = useNoRecursiveRenders(
Expand Down Expand Up @@ -116,6 +117,7 @@ export default function TemplatePartEdit( {
<TagName { ...blockProps }>
{ isPlaceholder && (
<TemplatePartPlaceholder
area={ attributes.area }
setAttributes={ setAttributes }
innerBlocks={ innerBlocks }
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,36 @@ import { store as coreStore } from '@wordpress/core-data';
import TemplatePartSelection from '../selection';

export default function TemplatePartPlaceholder( {
area,
setAttributes,
innerBlocks,
} ) {
const { saveEntityRecord } = useDispatch( coreStore );
const onCreate = useCallback( async () => {
const title = __( 'Untitled Template Part' );
// If we have `area` set from block attributes, means an exposed
// block variation was inserted. So add this prop to the template
// part entity on creation. Afterwards remove `area` value from
// block attributes.
const record = {
title,
slug: 'template-part',
content: serialize( innerBlocks ),
// `area` is filterable on the server and defaults to `UNCATEGORIZED`
// if provided value is not allowed.
area,
};
const templatePart = await saveEntityRecord(
'postType',
'wp_template_part',
{
title,
slug: 'template-part',
content: serialize( innerBlocks ),
}
record
);
setAttributes( {
slug: templatePart.slug,
theme: templatePart.theme,
area: undefined,
} );
}, [ setAttributes ] );
}, [ setAttributes, area ] );

return (
<Placeholder
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ function TemplatePartItem( {
const { createSuccessNotice } = useDispatch( noticesStore );

const onClick = useCallback( () => {
setAttributes( { slug, theme } );
setAttributes( { slug, theme, area: undefined } );
createSuccessNotice(
sprintf(
/* translators: %s: template part title. */
Expand Down
42 changes: 26 additions & 16 deletions packages/block-library/src/template-part/variations.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,6 @@ import { store as coreDataStore } from '@wordpress/core-data';
import { select } from '@wordpress/data';
import { __ } from '@wordpress/i18n';

const createIsActiveBasedOnArea = ( area ) => ( { theme, slug } ) => {
if ( ! slug ) {
return false;
}

const entity = select( coreDataStore ).getEntityRecord(
'postType',
'wp_template_part',
`${ theme }//${ slug }`
);

return entity?.area === area;
};

const variations = [
{
name: 'header',
Expand All @@ -28,7 +14,7 @@ const variations = [
"The header template defines a page area that typically contains a title, logo, and main navigation. Since it's a global element it can be present across all pages and posts."
),
icon: header,
isActive: createIsActiveBasedOnArea( 'header' ),
attributes: { area: 'header' },
scope: [ 'inserter' ],
},
{
Expand All @@ -38,9 +24,33 @@ const variations = [
"The footer template defines a page area that typically contains site credits, social links, or any other combination of blocks. Since it's a global element it can be present across all pages and posts."
),
icon: footer,
isActive: createIsActiveBasedOnArea( 'footer' ),
attributes: { area: 'footer' },
scope: [ 'inserter' ],
},
];

/**
* Add `isActive` function to all `Template Part` variations, if not defined.
* `isActive` function is used to find a variation match from a created
* Block by providing its attributes.
*/
variations.forEach( ( variation ) => {
if ( variation.isActive ) return;
variation.isActive = ( blockAttributes, variationAttributes ) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know this predates the PR, but the isActive nomenclature is quite confusing to me. What does it represent?

Copy link
Contributor Author

@ntsekouras ntsekouras Mar 22, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From the docs:

A function that accepts a block’s attributes and the variation’s attributes and determines if a variation is active. This function doesn’t try to find a match dynamically based on all block’s attributes, as in many cases some attributes are irrelevant. An example would be for embed block where we only care about providerNameSlug attribute’s value.

This is useful for cases you want to use information from the block variation, after a block’s creation. In this case though we have a combination with information from variation and entity attributes (before and after creation).

const { area, theme, slug } = blockAttributes;
// We first check the `area` block attribute which is set during insertion.
// This property is removed on the creation of a template part.
if ( area ) return area === variationAttributes.area;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this flow, it should make a lot of things more flexible for full template patterns

// Find a matching variation from the created template part
// by checking the entity's `area` property.
if ( ! slug ) return false;
const entity = select( coreDataStore ).getEntityRecord(
'postType',
'wp_template_part',
`${ theme }//${ slug }`
);
return entity?.area === variationAttributes.area;
};
} );

export default variations;