woocommerce/plugins/woocommerce-blocks/assets/js/blocks/shared/scripts/migration-utils.tsx

87 lines
2.5 KiB
TypeScript
Raw Normal View History

Automatic migration path from Products to Product Collection - step 1 - automatic migration (https://github.com/woocommerce/woocommerce-blocks/pull/10115) * Foundation of the Products block replacement with Product Collection * Provide logic to replace Products with Product Collection * Make sure the blocks can be replaced * Add types and refactor replacement a bit * Fix the query attributes transform * Add upgrade Notice to the Product Collection block * Force upgrade notice to be displayed at the top of the Inspector Controls * Externalise migration code so it can be reused in both ways * Add util to get block IDs byt its name * Add a way to revert the Product Collection blocks to Products * Move the subscription to another place where it's triggered only once * Add default values * Remove attributes from Products block if they're not used to avoid incorrect query * WIP logic of unseen/seen/reverted notice * Change the state reading * Revert changes regarding notice displaying logic * Change the logc of firing replacement and bail early if there's no core/query blocks * Add todos * Implement inner blocks migration * Implement the revert transformation of inner blocks * Refactor types * Add layout transformation from Products to Product Collection * Add layout migration from Product Collection to Products * Disable migration by default * Simplify some parts of code * Remove additional keyword from Product Collection to move it to another PR * Adjust the logic to introduce the first step: conversion from Products to Product Collection * Disable automatic migration
2023-07-12 08:01:36 +00:00
/**
* External dependencies
*/
import { getSettingWithCoercion } from '@woocommerce/settings';
import { type BlockInstance } from '@wordpress/blocks';
import { select } from '@wordpress/data';
import { isBoolean } from '@woocommerce/types';
type GetBlocksClientIds = ( blocks: BlockInstance[] ) => string[];
export type IsBlockType = ( block: BlockInstance ) => boolean;
export type TransformBlock = (
block: BlockInstance,
innerBlock: BlockInstance[]
) => BlockInstance;
export type ProductGridLayoutTypes = 'flex' | 'list';
export type PostTemplateLayoutTypes = 'grid' | 'default';
export type ProductGridLayout = {
type: ProductGridLayoutTypes;
columns: number;
};
export type PostTemplateLayout = {
type: PostTemplateLayoutTypes;
columnCount: number;
};
const isProductsBlock: IsBlockType = ( block ) =>
block.name === 'core/query' &&
block.attributes.namespace === 'woocommerce/product-query';
const isProductCollectionBlock: IsBlockType = ( block ) =>
block.name === 'woocommerce/product-collection';
const getBlockClientIdsByPredicate = (
blocks: BlockInstance[],
predicate: ( block: BlockInstance ) => boolean
): string[] => {
let clientIds: string[] = [];
blocks.forEach( ( block ) => {
if ( predicate( block ) ) {
clientIds = [ ...clientIds, block.clientId ];
}
clientIds = [
...clientIds,
...getBlockClientIdsByPredicate( block.innerBlocks, predicate ),
];
} );
return clientIds;
};
const getProductsBlockClientIds: GetBlocksClientIds = ( blocks ) =>
getBlockClientIdsByPredicate( blocks, isProductsBlock );
const getProductCollectionBlockClientIds: GetBlocksClientIds = ( blocks ) =>
getBlockClientIdsByPredicate( blocks, isProductCollectionBlock );
const checkIfBlockCanBeInserted = (
clientId: string,
blockToBeInserted: string
) => {
// We need to duplicate checks that are happening within replaceBlocks method
// as replacement is initially blocked and there's no information returned
// that would determine if replacement happened or not.
// https://github.com/WordPress/gutenberg/issues/46740
const rootClientId =
select( 'core/block-editor' ).getBlockRootClientId( clientId ) ||
undefined;
return select( 'core/block-editor' ).canInsertBlockType(
blockToBeInserted,
rootClientId
);
};
const postTemplateHasSupportForGridView = getSettingWithCoercion(
'post_template_has_support_for_grid_view',
false,
isBoolean
);
export {
getProductsBlockClientIds,
getProductCollectionBlockClientIds,
checkIfBlockCanBeInserted,
postTemplateHasSupportForGridView,
};