diff --git a/docs/reference-guides/core-blocks.md b/docs/reference-guides/core-blocks.md index ac43e93ccbcc6..27182a0f87ead 100644 --- a/docs/reference-guides/core-blocks.md +++ b/docs/reference-guides/core-blocks.md @@ -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 diff --git a/packages/block-library/src/query/block.json b/packages/block-library/src/query/block.json index 6267e53f24c12..cd09e22ee57f7 100644 --- a/packages/block-library/src/query/block.json +++ b/packages/block-library/src/query/block.json @@ -37,6 +37,9 @@ "default": { "type": "list" } + }, + "namespace": { + "type": "string" } }, "providesContext": { diff --git a/packages/block-library/src/query/edit/inspector-controls/index.js b/packages/block-library/src/query/edit/inspector-controls/index.js index 72db4563054e4..33e77def49352 100644 --- a/packages/block-library/src/query/edit/inspector-controls/index.js +++ b/packages/block-library/src/query/edit/inspector-controls/index.js @@ -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 @@ -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, @@ -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 ); @@ -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 ( <> - - - + + { showInheritControl && ( + + setQuery( { inherit: !! value } ) + } + /> ) } - checked={ !! inherit } - onChange={ ( value ) => - setQuery( { inherit: !! value } ) - } - /> - { ! inherit && ( - - ) } - { displayLayout?.type === 'flex' && ( - <> - + ) } + { showColumnsControl && ( + <> + + setDisplayLayout( { columns: value } ) + } + min={ 2 } + max={ Math.max( 6, displayLayout.columns ) } + /> + { displayLayout.columns > 6 && ( + + { __( + 'This column count exceeds the recommended amount and may cause visual breakage.' + ) } + + ) } + + ) } + { showOrderControl && ( + + ) } + { showStickyControl && ( + - setDisplayLayout( { columns: value } ) + setQuery( { sticky: value } ) } - min={ 2 } - max={ Math.max( 6, displayLayout.columns ) } /> - { displayLayout.columns > 6 && ( - - { __( - 'This column count exceeds the recommended amount and may cause visual breakage.' - ) } - - ) } - - ) } - { ! inherit && ( - - ) } - { ! inherit && showSticky && ( - - setQuery( { sticky: value } ) - } - /> - ) } - - + ) } + + + ) } { ! inherit && ( - { !! taxonomiesInfo?.length && ( + { !! taxonomiesInfo?.length && + isControlAllowed( allowedControls, 'taxQuery' ) && ( + + Object.values( taxQuery || {} ).some( + ( terms ) => !! terms.length + ) + } + onDeselect={ () => + setQuery( { taxQuery: null } ) + } + > + + + ) } + { isControlAllowed( allowedControls, 'author' ) && ( - Object.values( taxQuery || {} ).some( - ( terms ) => !! terms.length - ) - } - onDeselect={ () => - setQuery( { taxQuery: null } ) - } + hasValue={ () => !! authorIds } + label={ __( 'Authors' ) } + onDeselect={ () => setQuery( { author: '' } ) } > - ) } - !! authorIds } - label={ __( 'Authors' ) } - onDeselect={ () => setQuery( { author: '' } ) } - > - - - !! querySearch } - label={ __( 'Keyword' ) } - onDeselect={ () => setQuerySearch( '' ) } - > - - - { isPostTypeHierarchical && ( + { isControlAllowed( allowedControls, 'search' ) && ( !! parents?.length } - label={ __( 'Parents' ) } - onDeselect={ () => setQuery( { parents: [] } ) } + hasValue={ () => !! querySearch } + label={ __( 'Keyword' ) } + onDeselect={ () => setQuerySearch( '' ) } > - ) } + { isPostTypeHierarchical && + ! isControlAllowed( + allowedControls, + 'parents' + ) && ( + !! parents?.length } + label={ __( 'Parents' ) } + onDeselect={ () => + setQuery( { parents: [] } ) + } + > + + + ) } ) } diff --git a/packages/block-library/src/query/utils.js b/packages/block-library/src/query/utils.js index fb62191696f11..d363357561663 100644 --- a/packages/block-library/src/query/utils.js +++ b/packages/block-library/src/query/utils.js @@ -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 @@ -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.