Skip to content

Commit

Permalink
[Block Library - Query Loop]: Add allowedControls in block variatio…
Browse files Browse the repository at this point in the history
…ns for better extensibility (#43632)

* allowedControls in Query Loop variations

* allow empty array as value of allowedControls

* remove test variation

* move to utils

* allow to hide the 'inherit' control

* fix typo
  • Loading branch information
ntsekouras authored Sep 13, 2022
1 parent e5dca9d commit bc16c8d
Show file tree
Hide file tree
Showing 4 changed files with 191 additions and 115 deletions.
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

0 comments on commit bc16c8d

Please sign in to comment.