Merged in feature/117-dev-dev01 (pull request #8)

auto-patch  117-dev-dev01-2023-12-15T16_09_06

* auto-patch  117-dev-dev01-2023-12-15T16_09_06
This commit is contained in:
Tony Volpe
2023-12-15 16:10:57 +00:00
parent 0825f6bd5f
commit 3dc9eca989
1424 changed files with 28118 additions and 10097 deletions

View File

@@ -4,7 +4,7 @@
import { useEffect } from '@wordpress/element';
import { useBlockProps } from '@wordpress/block-editor';
import { __ } from '@wordpress/i18n';
import { Button, Disabled, Tooltip } from '@wordpress/components';
import { Disabled, Tooltip } from '@wordpress/components';
import { Skeleton } from '@woocommerce/base-components/skeleton';
import { BlockEditProps } from '@wordpress/blocks';
@@ -37,31 +37,28 @@ const Edit = ( props: BlockEditProps< Attributes > ) => {
return (
<div { ...blockProps }>
<Tooltip
text="Customer will see product add-to-cart options in this space, dependend on the product type. "
text="Customer will see product add-to-cart options in this space, dependent on the product type. "
position="bottom right"
>
<div className="wc-block-editor-container">
<div className="wc-block-editor-add-to-cart-form-container">
<Skeleton numberOfLines={ 3 } />
<Disabled>
<input
type={ 'number' }
value={ '1' }
className={
'wc-block-editor-add-to-cart-form__quantity'
}
readOnly
/>
<Button
variant={ 'primary' }
className={
'wc-block-editor-add-to-cart-form__button'
}
<div className="quantity">
<input
type={ 'number' }
value={ '1' }
className={ 'input-text qty text' }
readOnly
/>
</div>
<button
className={ `single_add_to_cart_button button alt wp-element-button` }
>
{ __(
'Add to cart',
'woo-gutenberg-products-block'
) }
</Button>
</button>
</Disabled>
</div>
</Tooltip>

View File

@@ -1,30 +1,4 @@
.wc-block-editor-add-to-cart-form {
display: flex;
flex-direction: column;
row-gap: $default-block-margin;
}
input.wc-block-editor-add-to-cart-form__quantity[type="number"] {
max-width: 50px;
min-height: 23px;
float: left;
padding: 6px 6px 6px 12px;
margin-right: 10px;
font-size: 13px;
height: inherit;
}
input[type="number"]::-webkit-inner-spin-button {
opacity: 1;
}
button.components-button.wc-block-add-to-cart-form__button {
float: left;
padding: 20px 30px;
border-radius: 0;
}
.wc-block-editor-container {
.wc-block-editor-add-to-cart-form-container {
cursor: help;
gap: 10px;
display: flex;

View File

@@ -1,4 +1,4 @@
.wp-block-add-to-cart-form {
.wc-block-add-to-cart-form {
width: unset;
/**
* This is a base style for the input text element in WooCommerce that prevents inputs from appearing too small.
@@ -9,4 +9,17 @@
font-size: var(--wp--preset--font-size--small);
padding: 0.9rem 1.1rem;
}
.quantity {
display: inline-block;
float: none;
margin-right: 4px;
vertical-align: middle;
.qty {
margin-right: 0.5rem;
width: 3.631em;
text-align: center;
}
}
}

View File

@@ -7,7 +7,7 @@ import { SelectControl } from 'wordpress-components';
import type { SelectControl as SelectControlType } from '@wordpress/components';
import { useEffect } from '@wordpress/element';
import classnames from 'classnames';
import { ValidationInputError } from '@woocommerce/blocks-checkout';
import { ValidationInputError } from '@woocommerce/blocks-components';
import { VALIDATION_STORE_KEY } from '@woocommerce/block-data';
import { useDispatch, useSelect } from '@wordpress/data';

View File

@@ -13,8 +13,7 @@
display: inline-flex;
justify-content: center;
text-align: center;
// Set button font size and padding so it inherits from parent.
padding: 0.5em 1em;
// Set button font size so it inherits from parent.
font-size: 1em;
&.loading {
@@ -25,6 +24,7 @@
font-family: WooCommerce; /* stylelint-disable-line */
content: "\e031";
animation: spin 2s linear infinite;
margin-right: 0;
margin-left: 0.5em;
display: inline-block;
width: auto;
@@ -70,8 +70,9 @@
justify-content: center;
white-space: normal;
word-break: break-word;
width: 150px;
overflow: hidden;
align-items: center;
line-height: inherit;
span {

View File

@@ -0,0 +1,55 @@
/**
* External dependencies
*/
import {
BlockConfiguration,
registerBlockType,
unregisterBlockType,
registerBlockVariation,
unregisterBlockVariation,
BlockVariation,
BlockAttributes,
} from '@wordpress/blocks';
export interface BlockRegistrationStrategy {
register(
blockNameOrMetadata: string | Partial< BlockConfiguration >,
blockSettings: Partial< BlockConfiguration >
): boolean;
unregister( blockName: string, variationName?: string ): boolean;
}
export class BlockTypeStrategy implements BlockRegistrationStrategy {
register(
blockNameOrMetadata: string | Partial< BlockConfiguration >,
blockSettings: Partial< BlockConfiguration >
): boolean {
return Boolean(
// @ts-expect-error: `registerBlockType` is typed in WordPress core
registerBlockType( blockNameOrMetadata, blockSettings )
);
}
unregister( blockName: string ): boolean {
return Boolean( unregisterBlockType( blockName ) );
}
}
// Strategy for BlockVariation
export class BlockVariationStrategy implements BlockRegistrationStrategy {
register(
blockName: string,
blockSettings: Partial< BlockConfiguration >
): boolean {
return Boolean(
registerBlockVariation(
blockName,
blockSettings as BlockVariation< BlockAttributes >
)
);
}
unregister( blockName: string, variationName: string ): boolean {
return Boolean( unregisterBlockVariation( blockName, variationName ) );
}
}

View File

@@ -0,0 +1,182 @@
/**
* External dependencies
*/
import { getBlockType } from '@wordpress/blocks';
/**
* Internal dependencies
*/
import {
TemplateChangeDetector,
TemplateChangeDetectorObserver,
} from './template-change-detector';
import {
BlockRegistrationStrategy,
BlockTypeStrategy,
BlockVariationStrategy,
} from './block-registration-strategy';
import { BLOCKS_WITH_RESTRICTION } from './blocks-with-restriction';
/**
* Manages the registration and unregistration of blocks based on template or page restrictions.
*
* This class implements the TemplateChangeDetectorObserver interface and is responsible for managing the registration and unregistration of blocks based on the restrictions defined in the BLOCKS_WITH_RESTRICTION constant.
*
* The class maintains a list of unregistered blocks and uses a block registration strategy to register and unregister blocks as needed. The strategy used depends on whether the block is a variation block or a regular block.
*
* The `run` method is the main entry point for the class. It is called with a TemplateChangeDetector object and registers and unregisters blocks based on the current template and whether the editor is in post or page mode.
*/
export class BlockRegistrationManager
implements TemplateChangeDetectorObserver
{
private unregisteredBlocks: string[] = [];
private blockRegistrationStrategy: BlockRegistrationStrategy;
constructor() {
this.blockRegistrationStrategy = new BlockTypeStrategy();
}
/**
* Determines whether a block should be registered based on the current template or page.
*
* This method checks whether a block with restrictions should be registered based on the current template ID and
* whether the editor is in post or page mode. It checks whether the current template ID starts with any of the
* allowed templates or template parts for the block, and whether the block is available in the post or page editor.
*
* @param {Object} params - The parameters for the method.
* @param {string} params.blockWithRestrictionName - The name of the block with restrictions.
* @param {string} params.currentTemplateId - The ID of the current template.
* @param {boolean} params.isPostOrPage - Whether the editor is in a post or page.
* @return {boolean} True if the block should be registered, false otherwise.
*/
private shouldBlockBeRegistered( {
blockWithRestrictionName,
currentTemplateId,
isPostOrPage,
}: {
blockWithRestrictionName: string;
currentTemplateId: string;
isPostOrPage: boolean;
} ) {
const {
allowedTemplates,
allowedTemplateParts,
availableInPostOrPageEditor,
} = BLOCKS_WITH_RESTRICTION[ blockWithRestrictionName ];
const shouldBeAvailableOnTemplate = Object.keys(
allowedTemplates
).some( ( allowedTemplate ) =>
currentTemplateId.startsWith( allowedTemplate )
);
const shouldBeAvailableOnTemplatePart = Object.keys(
allowedTemplateParts
).some( ( allowedTemplate ) =>
currentTemplateId.startsWith( allowedTemplate )
);
const shouldBeAvailableOnPostOrPageEditor =
isPostOrPage && availableInPostOrPageEditor;
return (
shouldBeAvailableOnTemplate ||
shouldBeAvailableOnTemplatePart ||
shouldBeAvailableOnPostOrPageEditor
);
}
/**
* Unregisters blocks before entering a restricted area based on the current template or page/post.
*
* This method iterates over all blocks with restrictions and unregisters them if they should not be registered
* based on the current template ID and whether the editor is in a post or page. It uses a block registration
* strategy to unregister the blocks, which depends on whether the block is a variation block or a regular block.
*
* @param {Object} params - The parameters for the method.
* @param {string} params.currentTemplateId - The ID of the current template.
* @param {boolean} params.isPostOrPage - Whether the editor is in post or page mode.
*/
unregisterBlocksBeforeEnteringRestrictedArea( {
currentTemplateId,
isPostOrPage,
}: {
currentTemplateId: string;
isPostOrPage: boolean;
} ) {
for ( const blockWithRestrictionName of Object.keys(
BLOCKS_WITH_RESTRICTION
) ) {
if (
this.shouldBlockBeRegistered( {
blockWithRestrictionName,
currentTemplateId,
isPostOrPage,
} )
) {
continue;
}
if ( ! getBlockType( blockWithRestrictionName ) ) {
continue;
}
this.blockRegistrationStrategy = BLOCKS_WITH_RESTRICTION[
blockWithRestrictionName
].isVariationBlock
? new BlockVariationStrategy()
: new BlockTypeStrategy();
this.blockRegistrationStrategy.unregister(
blockWithRestrictionName
);
this.unregisteredBlocks.push( blockWithRestrictionName );
}
}
/**
* Registers blocks after leaving a restricted area.
*
* This method iterates over all unregistered blocks and registers them if they are not restricted in the current context.
* It uses a block registration strategy to register the blocks, which depends on whether the block is a variation block or a regular block.
* If the block is successfully registered, it is removed from the list of unregistered blocks.
*/
registerBlocksAfterLeavingRestrictedArea() {
for ( const unregisteredBlockName of this.unregisteredBlocks ) {
if ( ! getBlockType( unregisteredBlockName ) ) {
continue;
}
const restrictedBlockData =
BLOCKS_WITH_RESTRICTION[ unregisteredBlockName ];
this.blockRegistrationStrategy = BLOCKS_WITH_RESTRICTION[
unregisteredBlockName
].isVariationBlock
? new BlockVariationStrategy()
: new BlockTypeStrategy();
const isBlockRegistered = this.blockRegistrationStrategy.register(
restrictedBlockData.blockMetadata,
restrictedBlockData.blockSettings
);
this.unregisteredBlocks = isBlockRegistered
? this.unregisteredBlocks.filter(
( blockName ) => blockName !== unregisteredBlockName
)
: this.unregisteredBlocks;
}
}
/**
* Runs the block registration manager.
*
* This method is the main entry point for the block registration manager. It is called with a TemplateChangeDetector object,
* and registers and unregisters blocks based on the current template and whether the editor is in a post or page.
*
* @param {TemplateChangeDetector} templateChangeDetector - The template change detector object.
*/
run( templateChangeDetector: TemplateChangeDetector ) {
this.registerBlocksAfterLeavingRestrictedArea();
this.unregisterBlocksBeforeEnteringRestrictedArea( {
currentTemplateId:
templateChangeDetector.getCurrentTemplateId() || '',
isPostOrPage: templateChangeDetector.getIsPostOrPage(),
} );
}
}

View File

@@ -0,0 +1,42 @@
/**
* External dependencies
*/
import { BlockConfiguration } from '@wordpress/blocks';
import { ProductGalleryBlockSettings } from '@woocommerce/blocks/product-gallery/settings';
/**
* Internal dependencies
*/
import productGalleryBlockMetadata from '../../../blocks/product-gallery/block.json';
export interface BlocksWithRestriction {
[ key: string ]: {
blockMetadata: Partial< BlockConfiguration >;
blockSettings: Partial< BlockConfiguration >;
allowedTemplates: {
[ key: string ]: boolean;
};
allowedTemplateParts: {
[ key: string ]: boolean;
};
availableInPostOrPageEditor: boolean;
isVariationBlock: boolean;
};
}
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error: `metadata` currently does not have a type definition in WordPress core
export const BLOCKS_WITH_RESTRICTION: BlocksWithRestriction = {
[ productGalleryBlockMetadata.name ]: {
blockMetadata: productGalleryBlockMetadata,
blockSettings: ProductGalleryBlockSettings,
allowedTemplates: {
'single-product': true,
},
allowedTemplateParts: {
'product-gallery': true,
},
availableInPostOrPageEditor: false,
isVariationBlock: false,
},
};

View File

@@ -0,0 +1,16 @@
/**
* External dependencies
*/
import domReady from '@wordpress/dom-ready';
/**
* Internal dependencies
*/
import { BlockRegistrationManager } from './blocks-registration-manager';
import { TemplateChangeDetector } from './template-change-detector';
domReady( () => {
const templateChangeDetector = new TemplateChangeDetector();
const blockRegistrationManager = new BlockRegistrationManager();
templateChangeDetector.add( blockRegistrationManager );
} );

View File

@@ -0,0 +1,115 @@
/**
* External dependencies
*/
import { subscribe, select } from '@wordpress/data';
import { isNumber } from '@woocommerce/types';
interface TemplateChangeDetectorSubject {
add( observer: TemplateChangeDetectorObserver ): void;
getPreviousTemplateId(): string | undefined;
getCurrentTemplateId(): string | undefined;
notify(): void;
}
export interface TemplateChangeDetectorObserver {
run( subject: TemplateChangeDetectorSubject ): void;
}
/**
* This class implements the TemplateChangeDetectorSubject interface and is responsible for detecting changes in the
* current template or page and notifying any observers of these changes. It maintains a list of observers and provides methods
* to add observers and notify them of changes.
*
* The class also provides methods to get the previous and current template IDs and whether the editor is in a post or page.
*
* The `checkIfTemplateHasChangedAndNotifySubscribers` method is the main method of the class. It checks if the current
* template has changed and, if so, notifies all observers.
*/
export class TemplateChangeDetector implements TemplateChangeDetectorSubject {
private previousTemplateId: string | undefined;
private currentTemplateId: string | undefined;
private isPostOrPage: boolean;
private observers: TemplateChangeDetectorObserver[] = [];
constructor() {
this.isPostOrPage = false;
subscribe( () => {
this.checkIfTemplateHasChangedAndNotifySubscribers();
}, 'core/edit-site' );
}
public add( observer: TemplateChangeDetectorObserver ): void {
this.observers.push( observer );
}
/**
* Trigger an update in each subscriber.
*/
public notify(): void {
for ( const observer of this.observers ) {
observer.run( this );
}
}
public getPreviousTemplateId() {
return this.previousTemplateId;
}
public getCurrentTemplateId() {
return this.currentTemplateId;
}
public getIsPostOrPage() {
return this.isPostOrPage;
}
/**
* Parses the template ID.
*
* This method takes a template or a post ID and returns it parsed in the expected format.
*
* @param {string | number | undefined} templateId - The template ID to parse.
* @return {string | undefined} The parsed template ID.
*/
private parseTemplateId(
templateId: string | number | undefined
): string | undefined {
if ( isNumber( templateId ) ) {
return String( templateId );
}
return templateId?.split( '//' )[ 1 ];
}
/**
* Checks if the current template or page has changed and notifies subscribers.
*
* If the current template ID has changed and is not undefined (which means that it is not a page, post or template), it notifies all subscribers.
*/
public checkIfTemplateHasChangedAndNotifySubscribers(): void {
this.previousTemplateId = this.currentTemplateId;
const postOrPageId = select( 'core/editor' )?.getCurrentPostId<
string | number | undefined
>();
this.isPostOrPage = Boolean( postOrPageId );
const editedPostId =
postOrPageId ||
select( 'core/edit-site' )?.getEditedPostId<
string | number | undefined
>();
this.currentTemplateId = this.parseTemplateId( editedPostId );
const hasChangedTemplate =
this.previousTemplateId !== this.currentTemplateId;
const hasTemplateId = Boolean( this.currentTemplateId );
if ( ! hasChangedTemplate || ! hasTemplateId ) {
return;
}
this.notify();
}
}

View File

@@ -46,7 +46,7 @@ export const registerBlockSingleProductTemplate = ( {
// With GB 16.3.0 the return type can be a number: https://github.com/WordPress/gutenberg/issues/53230
currentTemplateId = parseTemplateId(
store?.getEditedPostId() as string | number | undefined
store?.getEditedPostId< string | number | undefined >()
);
const hasChangedTemplate = previousTemplateId !== currentTemplateId;
const hasTemplateId = Boolean( currentTemplateId );