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

[Block Library - Query Loop]: Add allowedControls in block variations for better extensibility #43632

Merged
merged 6 commits into from
Sep 13, 2022
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
2 changes: 1 addition & 1 deletion docs/reference-guides/core-blocks.md
Original file line number Diff line number Diff line change
Expand Up @@ -609,7 +609,7 @@ An advanced block that allows displaying post types based on different query par
- **Name:** core/query
- **Category:** theme
- **Supports:** align (full, wide), color (background, gradients, link, text), ~~html~~
- **Attributes:** displayLayout, query, queryId, tagName
- **Attributes:** displayLayout, namespace, query, queryId, tagName

## No results

Expand Down
3 changes: 3 additions & 0 deletions packages/block-library/src/query/block.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@
"default": {
"type": "list"
}
},
"namespace": {
"type": "string"
}
},
"providesContext": {
Expand Down
252 changes: 139 additions & 113 deletions packages/block-library/src/query/edit/inspector-controls/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ import {
import { __ } from '@wordpress/i18n';
import { InspectorControls } from '@wordpress/block-editor';
import { useEffect, useState, useCallback } from '@wordpress/element';
import { useSelect } from '@wordpress/data';
import { store as coreStore } from '@wordpress/core-data';

/**
* Internal dependencies
Expand All @@ -30,23 +28,19 @@ import AuthorControl from './author-control';
import ParentControl from './parent-control';
import { TaxonomyControls, useTaxonomiesInfo } from './taxonomy-controls';
import StickyControl from './sticky-control';
import { usePostTypes } from '../../utils';

function useIsPostTypeHierarchical( postType ) {
return useSelect(
( select ) => {
const type = select( coreStore ).getPostType( postType );
return type?.viewable && type?.hierarchical;
},
[ postType ]
);
}
import {
usePostTypes,
useIsPostTypeHierarchical,
useAllowedControls,
isControlAllowed,
} from '../../utils';

export default function QueryInspectorControls( {
attributes: { query, displayLayout },
attributes,
setQuery,
setDisplayLayout,
} ) {
const { query, displayLayout } = attributes;
const {
order,
orderBy,
Expand All @@ -57,6 +51,7 @@ export default function QueryInspectorControls( {
taxQuery,
parents,
} = query;
const allowedControls = useAllowedControls( attributes );
const [ showSticky, setShowSticky ] = useState( postType === 'post' );
const { postTypesTaxonomiesMap, postTypesSelectOptions } = usePostTypes();
const taxonomiesInfo = useTaxonomiesInfo( postType );
Expand Down Expand Up @@ -102,70 +97,90 @@ export default function QueryInspectorControls( {
onChangeDebounced();
return onChangeDebounced.cancel;
}, [ querySearch, onChangeDebounced ] );
const showInheritControl = isControlAllowed( allowedControls, 'inherit' );
const showPostTypeControl =
! inherit && isControlAllowed( allowedControls, 'postType' );
const showColumnsControl = displayLayout?.type === 'flex';
const showOrderControl =
! inherit && isControlAllowed( allowedControls, 'order' );
const showStickyControl =
! inherit &&
showSticky &&
isControlAllowed( allowedControls, 'sticky' );
const showSettingsPanel =
showInheritControl ||
showPostTypeControl ||
showColumnsControl ||
showOrderControl ||
showStickyControl;
return (
<>
<InspectorControls>
<PanelBody title={ __( 'Settings' ) }>
<ToggleControl
label={ __( 'Inherit query from template' ) }
help={ __(
'Toggle to use the global query context that is set with the current template, such as an archive or search. Disable to customize the settings independently.'
{ showSettingsPanel && (
<InspectorControls>
<PanelBody title={ __( 'Settings' ) }>
{ showInheritControl && (
<ToggleControl
label={ __( 'Inherit query from template' ) }
help={ __(
'Toggle to use the global query context that is set with the current template, such as an archive or search. Disable to customize the settings independently.'
) }
checked={ !! inherit }
onChange={ ( value ) =>
setQuery( { inherit: !! value } )
}
/>
) }
checked={ !! inherit }
onChange={ ( value ) =>
setQuery( { inherit: !! value } )
}
/>
{ ! inherit && (
<SelectControl
options={ postTypesSelectOptions }
value={ postType }
label={ __( 'Post type' ) }
onChange={ onPostTypeChange }
help={ __(
'WordPress contains different types of content and they are divided into collections called "Post types". By default there are a few different ones such as blog posts and pages, but plugins could add more.'
) }
/>
) }
{ displayLayout?.type === 'flex' && (
<>
<RangeControl
label={ __( 'Columns' ) }
value={ displayLayout.columns }
{ showPostTypeControl && (
<SelectControl
options={ postTypesSelectOptions }
value={ postType }
label={ __( 'Post type' ) }
onChange={ onPostTypeChange }
help={ __(
'WordPress contains different types of content and they are divided into collections called "Post types". By default there are a few different ones such as blog posts and pages, but plugins could add more.'
) }
/>
) }
{ showColumnsControl && (
<>
<RangeControl
label={ __( 'Columns' ) }
value={ displayLayout.columns }
onChange={ ( value ) =>
setDisplayLayout( { columns: value } )
}
min={ 2 }
max={ Math.max( 6, displayLayout.columns ) }
/>
{ displayLayout.columns > 6 && (
<Notice
status="warning"
isDismissible={ false }
>
{ __(
'This column count exceeds the recommended amount and may cause visual breakage.'
) }
</Notice>
) }
</>
) }
{ showOrderControl && (
<OrderControl
{ ...{ order, orderBy } }
onChange={ setQuery }
/>
) }
{ showStickyControl && (
<StickyControl
value={ sticky }
onChange={ ( value ) =>
setDisplayLayout( { columns: value } )
setQuery( { sticky: value } )
}
min={ 2 }
max={ Math.max( 6, displayLayout.columns ) }
/>
{ displayLayout.columns > 6 && (
<Notice
status="warning"
isDismissible={ false }
>
{ __(
'This column count exceeds the recommended amount and may cause visual breakage.'
) }
</Notice>
) }
</>
) }
{ ! inherit && (
<OrderControl
{ ...{ order, orderBy } }
onChange={ setQuery }
/>
) }
{ ! inherit && showSticky && (
<StickyControl
value={ sticky }
onChange={ ( value ) =>
setQuery( { sticky: value } )
}
/>
) }
</PanelBody>
</InspectorControls>
) }
</PanelBody>
</InspectorControls>
) }
{ ! inherit && (
<InspectorControls>
<ToolsPanel
Expand All @@ -181,58 +196,69 @@ export default function QueryInspectorControls( {
setQuerySearch( '' );
} }
>
{ !! taxonomiesInfo?.length && (
{ !! taxonomiesInfo?.length &&
isControlAllowed( allowedControls, 'taxQuery' ) && (
<ToolsPanelItem
label={ __( 'Taxonomies' ) }
hasValue={ () =>
Object.values( taxQuery || {} ).some(
( terms ) => !! terms.length
)
}
onDeselect={ () =>
setQuery( { taxQuery: null } )
}
>
<TaxonomyControls
onChange={ setQuery }
query={ query }
/>
</ToolsPanelItem>
) }
{ isControlAllowed( allowedControls, 'author' ) && (
<ToolsPanelItem
label={ __( 'Taxonomies' ) }
hasValue={ () =>
Object.values( taxQuery || {} ).some(
( terms ) => !! terms.length
)
}
onDeselect={ () =>
setQuery( { taxQuery: null } )
}
hasValue={ () => !! authorIds }
label={ __( 'Authors' ) }
onDeselect={ () => setQuery( { author: '' } ) }
>
<TaxonomyControls
<AuthorControl
value={ authorIds }
onChange={ setQuery }
query={ query }
/>
</ToolsPanelItem>
) }
<ToolsPanelItem
hasValue={ () => !! authorIds }
label={ __( 'Authors' ) }
onDeselect={ () => setQuery( { author: '' } ) }
>
<AuthorControl
value={ authorIds }
onChange={ setQuery }
/>
</ToolsPanelItem>
<ToolsPanelItem
hasValue={ () => !! querySearch }
label={ __( 'Keyword' ) }
onDeselect={ () => setQuerySearch( '' ) }
>
<TextControl
label={ __( 'Keyword' ) }
value={ querySearch }
onChange={ setQuerySearch }
/>
</ToolsPanelItem>
{ isPostTypeHierarchical && (
{ isControlAllowed( allowedControls, 'search' ) && (
<ToolsPanelItem
hasValue={ () => !! parents?.length }
label={ __( 'Parents' ) }
onDeselect={ () => setQuery( { parents: [] } ) }
hasValue={ () => !! querySearch }
label={ __( 'Keyword' ) }
onDeselect={ () => setQuerySearch( '' ) }
>
<ParentControl
parents={ parents }
postType={ postType }
onChange={ setQuery }
<TextControl
label={ __( 'Keyword' ) }
value={ querySearch }
onChange={ setQuerySearch }
/>
</ToolsPanelItem>
) }
{ isPostTypeHierarchical &&
! isControlAllowed(
allowedControls,
'parents'
) && (
<ToolsPanelItem
hasValue={ () => !! parents?.length }
label={ __( 'Parents' ) }
onDeselect={ () =>
setQuery( { parents: [] } )
}
>
<ParentControl
parents={ parents }
postType={ postType }
onChange={ setQuery }
/>
</ToolsPanelItem>
) }
</ToolsPanel>
</InspectorControls>
) }
Expand Down
49 changes: 48 additions & 1 deletion packages/block-library/src/query/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@ import { useSelect } from '@wordpress/data';
import { useMemo } from '@wordpress/element';
import { store as coreStore } from '@wordpress/core-data';
import { decodeEntities } from '@wordpress/html-entities';
import { cloneBlock } from '@wordpress/blocks';
import { cloneBlock, store as blocksStore } from '@wordpress/blocks';

/**
* Internal dependencies
*/
import { name as queryLoopName } from './block.json';

/**
* @typedef IHasNameAndId
Expand Down Expand Up @@ -127,6 +132,48 @@ export const useTaxonomies = ( postType ) => {
return taxonomies;
};

/**
* Hook that returns whether a specific post type is hierarchical.
*
* @param {string} postType The post type to check.
* @return {boolean} Whether a specific post type is hierarchical.
*/
export function useIsPostTypeHierarchical( postType ) {
return useSelect(
( select ) => {
const type = select( coreStore ).getPostType( postType );
return type?.viewable && type?.hierarchical;
},
[ postType ]
);
}

/**
* Hook that returns the query properties' names defined by the active
* block variation, to determine which block's filters to show.
*
* @param {Object} attributes Block attributes.
* @return {string[]} An array of the query attributes.
*/
export function useAllowedControls( attributes ) {
return useSelect(
( select ) =>
select( blocksStore ).getActiveBlockVariation(
queryLoopName,
attributes
)?.allowControls,

[ attributes ]
);
}
export function isControlAllowed( allowedControls, key ) {
// Every controls is allowed if the list is not defined.
if ( ! allowedControls ) {
return true;
}
return allowedControls.includes( key );
}

/**
* Clones a pattern's blocks and then recurses over that list of blocks,
* transforming them to retain some `query` attribute properties.
Expand Down