Skip to content

Commit

Permalink
Query Loop: Allow "enhanced pagination" only with core blocks (#54347)
Browse files Browse the repository at this point in the history
* Move enhanced pagination control to its own file

* Add hook to detect third-party blocks

* Disable toggle when third-party blocks are found

* Add modal to disable enhance pagination

* Remove spokenMessage null

* Check for third-party blocks inside Query Loop

* Improve descriptions

* Remove undo button

* Open the modal with a useEffect
  • Loading branch information
DAreRodz authored Sep 13, 2023
1 parent 7652de9 commit 6e9c1d3
Show file tree
Hide file tree
Showing 6 changed files with 152 additions and 37 deletions.
65 changes: 65 additions & 0 deletions packages/block-library/src/query/edit/enhanced-pagination-modal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/**
* WordPress dependencies
*/
import {
Button,
Modal,
__experimentalVStack as VStack,
} from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import { useState, useEffect } from '@wordpress/element';

/**
* 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 [ isOpen, setOpen ] = useState( false );

const containsThirdPartyBlocks = useContainsThirdPartyBlocks( clientId );

useEffect( () => {
setOpen( containsThirdPartyBlocks && enhancedPagination );
}, [ containsThirdPartyBlocks, enhancedPagination, setOpen ] );

return (
isOpen && (
<Modal
title={ __( 'Enhanced pagination will be disabled' ) }
className={ 'wp-block-query-enhanced-pagination-modal' }
aria={ {
describedby: modalDescriptionId,
} }
isDismissible={ false }
shouldCloseOnEsc={ false }
shouldCloseOnClickOutside={ false }
>
<VStack alignment="right" spacing={ 8 }>
<span id={ modalDescriptionId }>
{ disableEnhancedPaginationDescription }
</span>
<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>
) }
</>
);
}
45 changes: 8 additions & 37 deletions packages/block-library/src/query/edit/inspector-controls/index.js
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/' )
);
} );

0 comments on commit 6e9c1d3

Please sign in to comment.