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(