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

Query Loop: Allow "enhanced pagination" only with core blocks #54347

Merged
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/**
* WordPress dependencies
*/
import {
Button,
Modal,
__experimentalVStack as VStack,
} from '@wordpress/components';
import { __ } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import { useContainsThirdPartyBlocks } from '../utils';

const disableEnhancedPaginationDescription = __(
'Third-party blocks are not supported inside a Query Loop block with enhanced pagination enabled. To re-enable it, remove any third-party block and then update it in the Query Loop settings.'
);

const modalDescriptionId =
'wp-block-query-enhanced-pagination-modal__description';

export default function EnhancedPaginationModal( {
clientId,
attributes: { enhancedPagination },
setAttributes,
} ) {
const containsThirdPartyBlocks = useContainsThirdPartyBlocks( clientId );

return (
containsThirdPartyBlocks &&
enhancedPagination && (
<Modal
title={ __( 'Enhanced pagination will be disabled' ) }
className={ 'wp-block-query-enhanced-pagination-modal' }
aria={ {
describedby: modalDescriptionId,
} }
isDismissible={ false }
shouldCloseOnEsc={ false }
shouldCloseOnClickOutside={ false }
>
<p id={ modalDescriptionId }>
{ disableEnhancedPaginationDescription }
</p>
<VStack alignment="right" spacing={ 3 }>
<Button
variant="primary"
onClick={ () => {
setAttributes( { enhancedPagination: false } );
} }
>
{ __( 'OK, understood' ) }
</Button>
</VStack>
</Modal>
)
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/**
* WordPress dependencies
*/
import { ToggleControl, Notice } from '@wordpress/components';
import { __ } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import { useContainsThirdPartyBlocks } from '../../utils';

export default function EnhancedPaginationControl( {
enhancedPagination,
setAttributes,
clientId,
} ) {
const enhancedPaginationNotice = __(
'Enhanced pagination requires all descendants to be Core blocks. If you want to enable it, you have to remove all third-party blocks contained inside the Query Loop block.'
);

const containsThirdPartyBlocks = useContainsThirdPartyBlocks( clientId );

return (
<>
<ToggleControl
label={ __( 'Enhanced pagination' ) }
help={ __(
'Browsing between pages won’t require a full page reload.'
) }
checked={ !! enhancedPagination }
disabled={ containsThirdPartyBlocks }
onChange={ ( value ) => {
setAttributes( {
enhancedPagination: !! value,
} );
} }
/>
{ containsThirdPartyBlocks && (
<div>
<Notice status="warning" isDismissible={ false }>
{ enhancedPaginationNotice }
</Notice>
</div>
) }
</>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ import {
privateApis as blockEditorPrivateApis,
} from '@wordpress/block-editor';
import { debounce } from '@wordpress/compose';
import { useEffect, useState, useCallback, useRef } from '@wordpress/element';
import { speak } from '@wordpress/a11y';
import { useEffect, useState, useCallback } from '@wordpress/element';

/**
* Internal dependencies
Expand All @@ -28,6 +27,7 @@ import AuthorControl from './author-control';
import ParentControl from './parent-control';
import { TaxonomyControls } from './taxonomy-controls';
import StickyControl from './sticky-control';
import EnhancedPaginationControl from './enhanced-pagination-control';
import CreateNewPostLink from './create-new-post-link';
import { unlock } from '../../../lock-unlock';
import {
Expand All @@ -41,7 +41,8 @@ import {
const { BlockInfo } = unlock( blockEditorPrivateApis );

export default function QueryInspectorControls( props ) {
const { attributes, setQuery, setDisplayLayout, setAttributes } = props;
const { attributes, setQuery, setDisplayLayout, setAttributes, clientId } =
props;
const { query, displayLayout, enhancedPagination } = attributes;
const {
order,
Expand Down Expand Up @@ -124,18 +125,6 @@ export default function QueryInspectorControls( props ) {
isControlAllowed( allowedControls, 'parents' ) &&
isPostTypeHierarchical;

const enhancedPaginationNotice = __(
'Enhanced Pagination might cause interactive blocks within the Post Template to stop working. Disable it if you experience any issues.'
);

const isFirstRender = useRef( true ); // Don't speak on first render.
useEffect( () => {
if ( ! isFirstRender.current && enhancedPagination ) {
speak( enhancedPaginationNotice );
}
isFirstRender.current = false;
}, [ enhancedPagination, enhancedPaginationNotice ] );

const showFiltersPanel =
showTaxControl ||
showAuthorControl ||
Expand Down Expand Up @@ -215,29 +204,11 @@ export default function QueryInspectorControls( props ) {
}
/>
) }
<ToggleControl
label={ __( 'Enhanced pagination' ) }
help={ __(
'Browsing between pages won’t require a full page reload.'
) }
checked={ !! enhancedPagination }
onChange={ ( value ) =>
setAttributes( {
enhancedPagination: !! value,
} )
}
<EnhancedPaginationControl
enhancedPagination={ enhancedPagination }
setAttributes={ setAttributes }
clientId={ clientId }
/>
{ enhancedPagination && (
<div>
<Notice
spokenMessage={ null }
status="warning"
isDismissible={ false }
>
{ enhancedPaginationNotice }
</Notice>
</div>
) }
</PanelBody>
</InspectorControls>
) }
Expand Down
8 changes: 8 additions & 0 deletions packages/block-library/src/query/edit/query-content.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { store as coreStore } from '@wordpress/core-data';
*/
import QueryToolbar from './query-toolbar';
import QueryInspectorControls from './inspector-controls';
import EnhancedPaginationModal from './enhanced-pagination-modal';

const DEFAULTS_POSTS_PER_PAGE = 3;

Expand Down Expand Up @@ -103,13 +104,20 @@ export default function QueryContent( {
"The <aside> element should represent a portion of a document whose content is only indirectly related to the document's main content."
),
};

return (
<>
<EnhancedPaginationModal
attributes={ attributes }
setAttributes={ setAttributes }
clientId={ clientId }
/>
<QueryInspectorControls
attributes={ attributes }
setQuery={ updateQuery }
setDisplayLayout={ updateDisplayLayout }
setAttributes={ setAttributes }
clientId={ clientId }
/>
<BlockControls>
<QueryToolbar
Expand Down
6 changes: 6 additions & 0 deletions packages/block-library/src/query/editor.scss
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,9 @@
margin-bottom: $grid-unit-30;
}
}

.wp-block-query-enhanced-pagination-modal {
@include break-small() {
max-width: $break-mobile;
}
}
18 changes: 18 additions & 0 deletions packages/block-library/src/query/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -344,3 +344,21 @@ export const usePatterns = ( clientId, name ) => {
[ name, clientId ]
);
};

/**
* Hook that returns whether the Query Loop with the given `clientId` contains
* any third-party block.
*
* @param {string} clientId The block's client ID.
* @return {boolean} True if it contains third-party blocks.
*/
export const useContainsThirdPartyBlocks = ( clientId ) =>
useSelect( ( select ) => {
const { getClientIdsOfDescendants, getBlockName } =
select( blockEditorStore );

return getClientIdsOfDescendants( [ clientId ] ).some(
( descendantClientId ) =>
! getBlockName( descendantClientId ).startsWith( 'core/' )
);
} );
Loading