diff --git a/assets/js/blocks/classic-template/constants.ts b/assets/js/blocks/classic-template/constants.ts index f75f9f78b82..dfeb37b3308 100644 --- a/assets/js/blocks/classic-template/constants.ts +++ b/assets/js/blocks/classic-template/constants.ts @@ -2,10 +2,14 @@ * External dependencies */ import { __ } from '@wordpress/i18n'; - export const BLOCK_SLUG = 'woocommerce/legacy-template'; -export const TEMPLATES: Record< string, Record< string, string > > = { +/** + * Internal dependencies + */ +import { TemplateDetails } from './types'; + +export const TEMPLATES: TemplateDetails = { 'single-product': { title: __( 'WooCommerce Single Product Block', diff --git a/assets/js/blocks/classic-template/index.tsx b/assets/js/blocks/classic-template/index.tsx index 2bbf623b1c8..18bf8237ed2 100644 --- a/assets/js/blocks/classic-template/index.tsx +++ b/assets/js/blocks/classic-template/index.tsx @@ -2,7 +2,6 @@ * External dependencies */ import { - Block, BlockEditProps, createBlock, getBlockType, @@ -26,6 +25,11 @@ import { useEffect } from '@wordpress/element'; import './editor.scss'; import './style.scss'; import { BLOCK_SLUG, TEMPLATES } from './constants'; +import { + isClassicTemplateBlockRegisteredWithAnotherTitle, + hasTemplateSupportForClassicTemplateBlock, + getTemplateDetailsBySlug, +} from './utils'; type Attributes = { template: string; @@ -40,10 +44,12 @@ const Edit = ( { const { replaceBlock } = useDispatch( 'core/block-editor' ); const blockProps = useBlockProps(); - const templateTitle = - TEMPLATES[ attributes.template ]?.title ?? attributes.template; - const templatePlaceholder = - TEMPLATES[ attributes.template ]?.placeholder ?? 'fallback'; + const templateDetails = getTemplateDetailsBySlug( + attributes.template, + TEMPLATES + ); + const templateTitle = templateDetails?.title ?? attributes.template; + const templatePlaceholder = templateDetails?.placeholder ?? 'fallback'; useEffect( () => @@ -118,8 +124,6 @@ const Edit = ( { ); }; -const templates = Object.keys( TEMPLATES ); - const registerClassicTemplateBlock = ( { template, inserter, @@ -136,12 +140,13 @@ const registerClassicTemplateBlock = ( { * See https://github.com/woocommerce/woocommerce-gutenberg-products-block/issues/5861 for more context */ registerBlockType( BLOCK_SLUG, { - title: template - ? TEMPLATES[ template ].title - : __( - 'WooCommerce Classic Template', - 'woo-gutenberg-products-block' - ), + title: + template && TEMPLATES[ template ] + ? TEMPLATES[ template ].title + : __( + 'WooCommerce Classic Template', + 'woo-gutenberg-products-block' + ), icon: ( | undefined, - parsedTemplate: string -) => block?.title !== TEMPLATES[ parsedTemplate ].title; - -const hasTemplateSupportForClassicTemplateBlock = ( parsedTemplate: string ) => - templates.includes( parsedTemplate ); - // @todo Refactor when there will be possible to show a block according on a template/post with a Gutenberg API. https://github.com/WordPress/gutenberg/pull/41718 let currentTemplateId: string | undefined; @@ -235,7 +231,10 @@ if ( isExperimentalBuild() ) { if ( block !== undefined && - ( ! hasTemplateSupportForClassicTemplateBlock( parsedTemplate ) || + ( ! hasTemplateSupportForClassicTemplateBlock( + parsedTemplate, + TEMPLATES + ) || isClassicTemplateBlockRegisteredWithAnotherTitle( block, parsedTemplate @@ -248,7 +247,10 @@ if ( isExperimentalBuild() ) { if ( block === undefined && - hasTemplateSupportForClassicTemplateBlock( parsedTemplate ) + hasTemplateSupportForClassicTemplateBlock( + parsedTemplate, + TEMPLATES + ) ) { registerClassicTemplateBlock( { template: parsedTemplate, diff --git a/assets/js/blocks/classic-template/test/utils.ts b/assets/js/blocks/classic-template/test/utils.ts new file mode 100644 index 00000000000..8f413c21ab0 --- /dev/null +++ b/assets/js/blocks/classic-template/test/utils.ts @@ -0,0 +1,47 @@ +/** + * Internal dependencies + */ +import { getTemplateDetailsBySlug } from '../utils'; + +const TEMPLATES = { + 'single-product': { + title: 'Single Product Title', + placeholder: 'Single Product Placeholder', + }, + 'archive-product': { + title: 'Product Archive Title', + placeholder: 'Product Archive Placeholder', + }, + 'archive-product': { + title: 'Product Archive Title', + placeholder: 'Product Archive Placeholder', + }, + 'taxonomy-product_cat': { + title: 'Product Taxonomy Title', + placeholder: 'Product Taxonomy Placeholder', + }, +}; + +describe( 'getTemplateDetailsBySlug', function () { + it( 'should return single-product object when given an exact match', () => { + expect( + getTemplateDetailsBySlug( 'single-product', TEMPLATES ) + ).toBeTruthy(); + expect( + getTemplateDetailsBySlug( 'single-product', TEMPLATES ) + ).toStrictEqual( TEMPLATES[ 'single-product' ] ); + } ); + + it( 'should return single-product object when given a partial match', () => { + expect( + getTemplateDetailsBySlug( 'single-product-hoodie', TEMPLATES ) + ).toBeTruthy(); + expect( + getTemplateDetailsBySlug( 'single-product-hoodie', TEMPLATES ) + ).toStrictEqual( TEMPLATES[ 'single-product' ] ); + } ); + + it( 'should return null object when given an incorrect match', () => { + expect( getTemplateDetailsBySlug( 'void', TEMPLATES ) ).toBeNull(); + } ); +} ); diff --git a/assets/js/blocks/classic-template/types.ts b/assets/js/blocks/classic-template/types.ts new file mode 100644 index 00000000000..3e28296b652 --- /dev/null +++ b/assets/js/blocks/classic-template/types.ts @@ -0,0 +1 @@ +export type TemplateDetails = Record< string, Record< string, string > >; diff --git a/assets/js/blocks/classic-template/utils.ts b/assets/js/blocks/classic-template/utils.ts new file mode 100644 index 00000000000..76a31299be4 --- /dev/null +++ b/assets/js/blocks/classic-template/utils.ts @@ -0,0 +1,49 @@ +/** + * External dependencies + */ +import { Block } from '@wordpress/blocks'; + +/** + * Internal dependencies + */ +import { TEMPLATES } from './constants'; +import { TemplateDetails } from './types'; + +// Finds the most appropriate template details object for specific template keys such as single-product-hoodie. +export function getTemplateDetailsBySlug( + parsedTemplate: string, + templates: TemplateDetails +) { + const templateKeys = Object.keys( templates ); + let templateDetails = null; + + for ( let i = 0; templateKeys.length > i; i++ ) { + const keyToMatch = parsedTemplate.substr( 0, templateKeys[ i ].length ); + const maybeTemplate = templates[ keyToMatch ]; + if ( maybeTemplate ) { + templateDetails = maybeTemplate; + break; + } + } + + return templateDetails; +} + +export function isClassicTemplateBlockRegisteredWithAnotherTitle( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + block: Block< any > | undefined, + parsedTemplate: string +) { + const templateDetails = getTemplateDetailsBySlug( + parsedTemplate, + TEMPLATES + ); + return block?.title !== templateDetails?.title; +} + +export function hasTemplateSupportForClassicTemplateBlock( + parsedTemplate: string, + templates: TemplateDetails +): boolean { + return getTemplateDetailsBySlug( parsedTemplate, templates ) ? true : false; +}