diff --git a/assets/js/base/components/filter-update-heading/index.tsx b/assets/js/base/components/filter-update-heading/index.tsx new file mode 100644 index 00000000000..f940fdaf576 --- /dev/null +++ b/assets/js/base/components/filter-update-heading/index.tsx @@ -0,0 +1,28 @@ +/** + * External dependencies + */ +import { __ } from '@wordpress/i18n'; +import { Warning } from '@wordpress/block-editor'; +import { Button } from '@wordpress/components'; + +const UpdateFilterHeadingsPrompt = ( { onClick } ) => { + const actions = [ + , + ]; + + return ( + + { __( + 'This block is outdated. Please upgrade to the latest version!', + 'woo-gutenberg-products-block' + ) } + + ); +}; + +export default UpdateFilterHeadingsPrompt; diff --git a/assets/js/base/components/filter-update-heading/style.scss b/assets/js/base/components/filter-update-heading/style.scss new file mode 100644 index 00000000000..36e3bf9c2a6 --- /dev/null +++ b/assets/js/base/components/filter-update-heading/style.scss @@ -0,0 +1,35 @@ +.wc-block-components-filter-update-heading { + background: transparent; + border-radius: 0; + border-width: 0 0 1px; + margin: 1px 0; + + .block-editor-warning__contents { + gap: $gap; + } + + .block-editor-warning__actions { + margin-top: 0; + } +} + +.wc-blocks-components-title-migration { + border: 1px solid $gray-900; + position: relative; + + &::before { + background: rgba($white, 0.6); + bottom: 0; + content: ""; + display: block; + left: 0; + position: absolute; + right: 0; + top: 0; + z-index: 1; + } + + > .wp-block { + padding: 0 $gap; + } +} diff --git a/assets/js/blocks/active-filters/attributes.ts b/assets/js/blocks/active-filters/attributes.ts deleted file mode 100644 index 0944adf13cc..00000000000 --- a/assets/js/blocks/active-filters/attributes.ts +++ /dev/null @@ -1,11 +0,0 @@ -/** - * External dependencies - */ -import { __ } from '@wordpress/i18n'; - -export const blockAttributes = { - heading: { - type: 'string', - default: __( 'Active filters', 'woo-gutenberg-products-block' ), - }, -}; diff --git a/assets/js/blocks/active-filters/block.json b/assets/js/blocks/active-filters/block.json index 83b791c35eb..4b80aa9edef 100644 --- a/assets/js/blocks/active-filters/block.json +++ b/assets/js/blocks/active-filters/block.json @@ -18,6 +18,10 @@ "type": "string", "default": "list" }, + "heading": { + "type": "string", + "default": "" + }, "headingLevel": { "type": "number", "default": 3 diff --git a/assets/js/blocks/active-filters/edit.tsx b/assets/js/blocks/active-filters/edit.tsx index c001bd714f6..f87d06c03dd 100644 --- a/assets/js/blocks/active-filters/edit.tsx +++ b/assets/js/blocks/active-filters/edit.tsx @@ -21,6 +21,7 @@ import { */ import Block from './block'; import type { Attributes } from './types'; +import withTitleMigration from '../../hocs/with-title-migration'; const Edit = ( { attributes, @@ -91,14 +92,16 @@ const Edit = ( { return (
{ getInspectorControls() } - - setAttributes( { heading: value } ) - } - /> + { heading && ( + + setAttributes( { heading: value } ) + } + /> + ) } @@ -106,4 +109,4 @@ const Edit = ( { ); }; -export default withSpokenMessages( Edit ); +export default withSpokenMessages( withTitleMigration( Edit ) ); diff --git a/assets/js/blocks/active-filters/frontend.ts b/assets/js/blocks/active-filters/frontend.ts index 245a5704cf9..93ae1d46e65 100644 --- a/assets/js/blocks/active-filters/frontend.ts +++ b/assets/js/blocks/active-filters/frontend.ts @@ -8,7 +8,6 @@ import { renderFrontend } from '@woocommerce/base-utils'; */ import Block from './block'; import metadata from './block.json'; -import { blockAttributes } from './attributes'; const getProps = ( el: HTMLElement ) => { return { @@ -16,7 +15,7 @@ const getProps = ( el: HTMLElement ) => { displayStyle: el.dataset.displayStyle || metadata.attributes.displayStyle.default, - heading: el.dataset.heading || blockAttributes.heading.default, + heading: el.dataset.heading || metadata.attributes.heading.default, headingLevel: el.dataset.headingLevel ? parseInt( el.dataset.headingLevel, 10 ) : metadata.attributes.headingLevel.default, diff --git a/assets/js/blocks/active-filters/index.tsx b/assets/js/blocks/active-filters/index.tsx index b1cb933b8c0..0a047fbd1a1 100644 --- a/assets/js/blocks/active-filters/index.tsx +++ b/assets/js/blocks/active-filters/index.tsx @@ -13,7 +13,6 @@ import { useBlockProps } from '@wordpress/block-editor'; */ import edit from './edit'; import metadata from './block.json'; -import { blockAttributes } from './attributes'; import { Attributes } from './types'; registerBlockType( metadata, { @@ -30,10 +29,6 @@ registerBlockType( metadata, { /> ), }, - attributes: { - ...metadata.attributes, - ...blockAttributes, - }, transforms: { from: [ { @@ -60,19 +55,13 @@ registerBlockType( metadata, { edit, // Save the props to post content. save( { attributes }: { attributes: Attributes } ) { - const { className, displayStyle, heading, headingLevel } = attributes; - const data = { - 'data-display-style': displayStyle, - 'data-heading': heading, - 'data-heading-level': headingLevel, - }; + const { className } = attributes; return (
); }, + deprecated: [ + { + attributes: { + ...metadata.attributes, + heading: { + type: 'string', + default: __( + 'Active filters', + 'woo-gutenberg-products-block' + ), + }, + }, + + save( { attributes }: { attributes: Attributes } ) { + const { className, displayStyle, heading, headingLevel } = + attributes; + const data = { + 'data-display-style': displayStyle, + 'data-heading': heading, + 'data-heading-level': headingLevel, + }; + + return ( +
+ +
+ ); + }, + }, + ], } ); diff --git a/assets/js/editor-components/block-title/index.js b/assets/js/editor-components/block-title/index.js index 18ccd0f605d..f5b4f0b0ff7 100644 --- a/assets/js/editor-components/block-title/index.js +++ b/assets/js/editor-components/block-title/index.js @@ -5,6 +5,7 @@ import PropTypes from 'prop-types'; import { PlainText } from '@wordpress/block-editor'; import { withInstanceId } from '@wordpress/compose'; import { __ } from '@wordpress/i18n'; +import { Disabled } from '@wordpress/components'; /** * Internal dependencies @@ -17,9 +18,10 @@ const BlockTitle = ( { onChange, heading, instanceId, + disabled = false, } ) => { const TagName = `h${ headingLevel }`; - return ( + const Component = () => ( ); + + if ( disabled ) { + return ( + + + + ); + } + + return ; }; BlockTitle.propTypes = { @@ -54,6 +66,10 @@ BlockTitle.propTypes = { * Level of the heading tag (1, 2, 3... will render

,

,

... elements). */ headingLevel: PropTypes.number, + /** + * If the title is a disabled element + */ + disabled: PropTypes.bool, }; export default withInstanceId( BlockTitle ); diff --git a/assets/js/hocs/with-title-migration.tsx b/assets/js/hocs/with-title-migration.tsx new file mode 100644 index 00000000000..5fb5808eb9a --- /dev/null +++ b/assets/js/hocs/with-title-migration.tsx @@ -0,0 +1,64 @@ +/** + * External dependencies + */ +import UpdateFilterHeadingsPrompt from '@woocommerce/base-components/filter-update-heading'; +import { getSettingWithCoercion } from '@woocommerce/settings'; +import type { BlockEditProps } from '@wordpress/blocks'; +import { isBoolean } from '@woocommerce/types'; + +/** + * Internal dependencies + */ +import useUpdateFilterHeadings from '../shared/hooks/use-update-filter-headings'; + +interface Attributes { + heading: string; + headingLevel: number; + className?: string; +} + +const withTitleMigration = ( + OriginalComponent: React.FunctionComponent< Record< string, unknown > > +) => { + return ( props: BlockEditProps< Attributes > ): JSX.Element => { + const { attributes, setAttributes, clientId } = props; + const { heading, headingLevel } = attributes; + + /** + * Since WooCommerce Blocks 8.2.0, we have decoupled the block title from the filter block itself. + * So we need to prompt users who are already using the block with title to click update, + * where we will create a title block for them. + */ + const shouldRemoveBlockTitle = getSettingWithCoercion( + 'shouldRemoveBlockTitle', + false, + isBoolean + ); + + const updateBlockHeading = useUpdateFilterHeadings( { + heading, + headingLevel, + clientId, + setAttributes, + } ); + + return ( +
+ { shouldRemoveBlockTitle && heading && ( + + ) } + +
+ ); + }; +}; + +export default withTitleMigration; diff --git a/assets/js/shared/hooks/use-update-filter-headings.tsx b/assets/js/shared/hooks/use-update-filter-headings.tsx new file mode 100644 index 00000000000..c9b3e567192 --- /dev/null +++ b/assets/js/shared/hooks/use-update-filter-headings.tsx @@ -0,0 +1,49 @@ +/** + * External dependencies + */ +import { createBlock, BlockEditProps } from '@wordpress/blocks'; +import { useDispatch, useSelect } from '@wordpress/data'; + +interface Attributes { + heading: string; + headingLevel: number; + clientId: string; +} + +const useUpdateFilterHeadings = ( { + heading, + headingLevel, + clientId, + setAttributes, +}: Attributes & Pick< BlockEditProps< Attributes >, 'setAttributes' > ) => { + const { insertBlock } = useDispatch( 'core/block-editor' ); + const { currentBlockIndex, currentParentBlockId } = useSelect( + ( select ) => { + const store = select( 'core/block-editor' ); + return { + currentBlockIndex: store.getBlockIndex( clientId ), + currentParentBlockId: store.getBlockRootClientId( clientId ), + }; + } + ); + + const updateBlock = () => { + const headingBlock = createBlock( 'core/heading', { + content: heading, + level: headingLevel, + } ); + insertBlock( + headingBlock, + currentBlockIndex, + currentParentBlockId, + false + ); + setAttributes( { + heading: '', + } ); + }; + + return updateBlock; +}; + +export default useUpdateFilterHeadings; diff --git a/src/BlockTypes/ActiveFilters.php b/src/BlockTypes/ActiveFilters.php index 61473c26c5c..320e4547207 100644 --- a/src/BlockTypes/ActiveFilters.php +++ b/src/BlockTypes/ActiveFilters.php @@ -1,6 +1,8 @@ asset_data_registry->add( + 'shouldRemoveBlockTitle', + version_compare( Package::get_version(), '8.2.0', '>' ), + true + ); + } } diff --git a/tests/e2e/specs/backend/active-filters.test.js b/tests/e2e/specs/backend/active-filters.test.js index 6c81df7e098..f32c9d58a4a 100644 --- a/tests/e2e/specs/backend/active-filters.test.js +++ b/tests/e2e/specs/backend/active-filters.test.js @@ -44,7 +44,7 @@ describe( `${ block.name } Block`, () => { await selectBlockByName( block.slug ); } ); - it( "allows changing the block's title", async () => { + it.skip( "allows changing the block's title", async () => { const textareaSelector = `.wp-block[data-type="${ block.slug }"] textarea.wc-block-editor-components-title`; await expect( page ).toFill( textareaSelector, 'New Title' ); await page.click(