Product Block Editor: add tracks to the Variations tab (#39914)

* Add product_options_add tracking event to add variation options

* Add product_options_edit tracking event to variation options

* Add product_options_update tracking event to variation options

* Fix set default attribute when editing it

* Add changelog file

* Add product_options_add_button_click tracking event

* Get attribute options from the terms prop instead of options, this ensures to get the updated values when the user edits the options

* Add Variation options section back

* Add changelog file
This commit is contained in:
Maikel David Pérez Gómez 2023-08-30 14:36:44 -04:00 committed by GitHub
parent c1befca115
commit a425a62fb8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 74 additions and 26 deletions

View File

@ -0,0 +1,4 @@
Significance: minor
Type: add
Add tracking events to add edit and update attribute

View File

@ -74,7 +74,6 @@ export function Edit() {
productId: useEntityId( 'postType', 'product' ), productId: useEntityId( 'postType', 'product' ),
onChange( values ) { onChange( values ) {
setEntityAttributes( values ); setEntityAttributes( values );
setEntityDefaultAttributes( manageDefaultAttributes( values ) );
generateProductVariations( values ); generateProductVariations( values );
}, },
} ); } );
@ -131,7 +130,12 @@ export function Edit() {
attributes, attributes,
entityDefaultAttributes, entityDefaultAttributes,
] ) } ] ) }
onChange={ handleChange } onChange={ ( values ) => {
handleChange( values );
setEntityDefaultAttributes(
manageDefaultAttributes( values )
);
} }
createNewAttributesAsGlobal={ true } createNewAttributesAsGlobal={ true }
useRemoveConfirmationModal={ true } useRemoveConfirmationModal={ true }
onNoticeDismiss={ () => onNoticeDismiss={ () =>

View File

@ -6,6 +6,7 @@ import type { BlockEditProps } from '@wordpress/blocks';
import { Button } from '@wordpress/components'; import { Button } from '@wordpress/components';
import { Link } from '@woocommerce/components'; import { Link } from '@woocommerce/components';
import { Product, ProductAttribute } from '@woocommerce/data'; import { Product, ProductAttribute } from '@woocommerce/data';
import { recordEvent } from '@woocommerce/tracks';
import { import {
createElement, createElement,
useState, useState,
@ -36,6 +37,7 @@ import {
import { getAttributeId } from '../../components/attribute-control/utils'; import { getAttributeId } from '../../components/attribute-control/utils';
import { useProductVariationsHelper } from '../../hooks/use-product-variations-helper'; import { useProductVariationsHelper } from '../../hooks/use-product-variations-helper';
import { hasAttributesUsedForVariations } from '../../utils'; import { hasAttributesUsedForVariations } from '../../utils';
import { TRACKS_SOURCE } from '../../constants';
function getFirstOptionFromEachAttribute( function getFirstOptionFromEachAttribute(
attributes: Product[ 'attributes' ] attributes: Product[ 'attributes' ]
@ -101,15 +103,22 @@ export function Edit( {
}; };
const handleAdd = ( newOptions: EnhancedProductAttribute[] ) => { const handleAdd = ( newOptions: EnhancedProductAttribute[] ) => {
handleChange( [ const addedAttributesOnly = newOptions.filter(
...newOptions.filter( ( newAttr ) =>
( newAttr ) => ! variationOptions.some(
! variationOptions.find( ( attr: ProductAttribute ) =>
( attr: ProductAttribute ) => getAttributeId( newAttr ) === getAttributeId( attr )
getAttributeId( newAttr ) === getAttributeId( attr ) )
) );
), recordEvent( 'product_options_add', {
] ); source: TRACKS_SOURCE,
options: addedAttributesOnly.map( ( attribute ) => ( {
attribute: attribute.name,
values: attribute.options,
} ) ),
} );
handleChange( addedAttributesOnly );
closeNewModal(); closeNewModal();
}; };

View File

@ -31,6 +31,7 @@ import {
import { AttributeListItem } from '../attribute-list-item'; import { AttributeListItem } from '../attribute-list-item';
import { NewAttributeModal } from './new-attribute-modal'; import { NewAttributeModal } from './new-attribute-modal';
import { RemoveConfirmationModal } from './remove-confirmation-modal'; import { RemoveConfirmationModal } from './remove-confirmation-modal';
import { TRACKS_SOURCE } from '../../constants';
type AttributeControlProps = { type AttributeControlProps = {
value: EnhancedProductAttribute[]; value: EnhancedProductAttribute[];
@ -157,6 +158,10 @@ export const AttributeControl: React.FC< AttributeControlProps > = ( {
}; };
const openEditModal = ( attribute: ProductAttribute ) => { const openEditModal = ( attribute: ProductAttribute ) => {
recordEvent( 'product_options_edit', {
source: TRACKS_SOURCE,
attribute: attribute.name,
} );
setCurrentAttributeId( getAttributeId( attribute ) ); setCurrentAttributeId( getAttributeId( attribute ) );
onEditModalOpen( attribute ); onEditModalOpen( attribute );
}; };
@ -167,21 +172,35 @@ export const AttributeControl: React.FC< AttributeControlProps > = ( {
}; };
const handleAdd = ( newAttributes: EnhancedProductAttribute[] ) => { const handleAdd = ( newAttributes: EnhancedProductAttribute[] ) => {
handleChange( [ const addedAttributesOnly = newAttributes.filter(
...value, ( newAttr ) =>
...newAttributes.filter( ! value.some(
( newAttr ) => ( current: ProductAttribute ) =>
! value.find( getAttributeId( newAttr ) === getAttributeId( current )
( attr ) => )
getAttributeId( newAttr ) === getAttributeId( attr ) );
) recordEvent( 'product_options_add', {
), source: TRACKS_SOURCE,
] ); options: addedAttributesOnly.map( ( attribute ) => ( {
attribute: attribute.name,
values: attribute.options,
} ) ),
} );
handleChange( [ ...value, ...addedAttributesOnly ] );
onAdd( newAttributes ); onAdd( newAttributes );
closeNewModal(); closeNewModal();
}; };
const handleEdit = ( updatedAttribute: ProductAttribute ) => { const handleEdit = ( updatedAttribute: EnhancedProductAttribute ) => {
recordEvent( 'product_options_update', {
source: TRACKS_SOURCE,
attribute: updatedAttribute.name,
values: updatedAttribute.terms?.map( ( term ) => term.name ),
default: updatedAttribute.isDefault,
visible: updatedAttribute.visible,
filter: true, // default true until attribute filter gets implemented
} );
const updatedAttributes = value.map( ( attr ) => { const updatedAttributes = value.map( ( attr ) => {
if ( if (
getAttributeId( attr ) === getAttributeId( updatedAttribute ) getAttributeId( attr ) === getAttributeId( updatedAttribute )
@ -221,7 +240,9 @@ export const AttributeControl: React.FC< AttributeControlProps > = ( {
className="woocommerce-add-attribute-list-item__add-button" className="woocommerce-add-attribute-list-item__add-button"
onClick={ () => { onClick={ () => {
openNewModal(); openNewModal();
recordEvent( 'product_add_attributes_click' ); recordEvent( 'product_options_add_button_click', {
source: TRACKS_SOURCE,
} );
} } } }
> >
{ uiStrings.newAttributeListItemLabel } { uiStrings.newAttributeListItemLabel }

View File

@ -0,0 +1,4 @@
Significance: minor
Type: fix
Add Variation options section back to the product blocks template

View File

@ -725,15 +725,21 @@ class SimpleProductTemplate extends AbstractProductFormTemplate implements Produ
], ],
] ]
); );
$variation_fields->add_block( $variation_options_section = $variation_fields->add_block(
[ [
'id' => 'product-variation-options', 'id' => 'product-variation-options-section',
'blockName' => 'woocommerce/product-variations-options-field', 'blockName' => 'woocommerce/product-section',
'attributes' => [ 'attributes' => [
'title' => __( 'Variation options', 'woocommerce' ), 'title' => __( 'Variation options', 'woocommerce' ),
], ],
] ]
); );
$variation_options_section->add_block(
[
'id' => 'product-variation-options',
'blockName' => 'woocommerce/product-variations-options-field',
]
);
$variation_section = $variation_fields->add_block( $variation_section = $variation_fields->add_block(
[ [
'id' => 'product-variation-section', 'id' => 'product-variation-section',