Fix attributes/options lists corrupt render (#36236)

* Fix attributes/options lists reordering

* Add changelog

* Fix element key

* Remove comment

* Add tests

* Fix changelog

Co-authored-by: Fernando Marichal <contacto@fernandomarichal.com>
This commit is contained in:
Fernando Marichal 2023-01-03 10:33:29 -03:00 committed by GitHub
parent 216a7505df
commit af9f493c43
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 46 additions and 24 deletions

View File

@ -24,7 +24,10 @@ import { getAdminLink } from '@woocommerce/settings';
import './attribute-field.scss'; import './attribute-field.scss';
import { AddAttributeModal } from './add-attribute-modal'; import { AddAttributeModal } from './add-attribute-modal';
import { EditAttributeModal } from './edit-attribute-modal'; import { EditAttributeModal } from './edit-attribute-modal';
import { reorderSortableProductAttributePositions } from './utils'; import {
getAttributeKey,
reorderSortableProductAttributePositions,
} from './utils';
import { sift } from '../../../utils'; import { sift } from '../../../utils';
import { AttributeEmptyState } from '../attribute-empty-state'; import { AttributeEmptyState } from '../attribute-empty-state';
import { import {
@ -244,10 +247,10 @@ export const AttributeField: React.FC< AttributeFieldProps > = ( {
); );
const attributeKeyValues = filteredAttributes.reduce( const attributeKeyValues = filteredAttributes.reduce(
( (
keyValue: Record< number, ProductAttribute >, keyValue: Record< number | string, ProductAttribute >,
attribute: ProductAttribute attribute: ProductAttribute
) => { ) => {
keyValue[ attribute.id ] = attribute; keyValue[ getAttributeKey( attribute ) ] = attribute;
return keyValue; return keyValue;
}, },
{} as Record< number, ProductAttribute > {} as Record< number, ProductAttribute >

View File

@ -6,7 +6,10 @@ import { ProductAttribute } from '@woocommerce/data';
/** /**
* Internal dependencies * Internal dependencies
*/ */
import { reorderSortableProductAttributePositions } from '../utils'; import {
getAttributeKey,
reorderSortableProductAttributePositions,
} from '../utils';
const attributeList: Record< number, ProductAttribute > = { const attributeList: Record< number, ProductAttribute > = {
15: { 15: {
@ -38,9 +41,9 @@ const attributeList: Record< number, ProductAttribute > = {
describe( 'reorderSortableProductAttributePositions', () => { describe( 'reorderSortableProductAttributePositions', () => {
it( 'should update product attribute positions depending on JSX.Element order', () => { it( 'should update product attribute positions depending on JSX.Element order', () => {
const elements = [ const elements = [
{ key: '3' }, { props: { attribute: attributeList[ '3' ] } },
{ key: '15' }, { props: { attribute: attributeList[ '15' ] } },
{ key: '1' }, { props: { attribute: attributeList[ '1' ] } },
] as JSX.Element[]; ] as JSX.Element[];
const newList = reorderSortableProductAttributePositions( const newList = reorderSortableProductAttributePositions(
elements, elements,
@ -53,19 +56,19 @@ describe( 'reorderSortableProductAttributePositions', () => {
expect( newList[ 2 ].position ).toEqual( 2 ); expect( newList[ 2 ].position ).toEqual( 2 );
expect( newList[ 2 ].id ).toEqual( 1 ); expect( newList[ 2 ].id ).toEqual( 1 );
} ); } );
} );
it( 'should filter out elements that do not contain a key', () => { describe( 'getAttributeKey', () => {
const elements = [ attributeList[ '20' ] = {
{ key: '3' }, id: 0,
{}, name: 'Quality',
{ key: '15' }, position: 3,
{}, visible: true,
{ key: '1' }, variation: true,
] as JSX.Element[]; options: [ 'low', 'high' ],
const newList = reorderSortableProductAttributePositions( };
elements, it( 'should return the attribute key', () => {
attributeList expect( getAttributeKey( attributeList[ '15' ] ) ).toEqual( 15 );
); expect( getAttributeKey( attributeList[ '20' ] ) ).toEqual( 'Quality' );
expect( newList.length ).toEqual( 3 );
} ); } );
} ); } );

View File

@ -3,6 +3,18 @@
*/ */
import { ProductAttribute } from '@woocommerce/data'; import { ProductAttribute } from '@woocommerce/data';
/**
* Returns the attribute key. The key will be the `id` or the `name` when the id is 0.
*
* @param { ProductAttribute } attribute product attribute.
* @return string|number
*/
export function getAttributeKey(
attribute: ProductAttribute
): number | string {
return attribute.id !== 0 ? attribute.id : attribute.name;
}
/** /**
* Updates the position of a product attribute from the new items JSX.Element list. * Updates the position of a product attribute from the new items JSX.Element list.
* *
@ -11,12 +23,12 @@ import { ProductAttribute } from '@woocommerce/data';
*/ */
export function reorderSortableProductAttributePositions( export function reorderSortableProductAttributePositions(
items: JSX.Element[], items: JSX.Element[],
attributeKeyValues: Record< number, ProductAttribute > attributeKeyValues: Record< number | string, ProductAttribute >
): ProductAttribute[] { ): ProductAttribute[] {
return items return items
.map( ( item, index ): ProductAttribute | undefined => { .map( ( { props }, index ): ProductAttribute | undefined => {
const key = item.key ? parseInt( item.key as string, 10 ) : NaN; const key = getAttributeKey( props?.attribute );
if ( key !== NaN && attributeKeyValues[ key ] ) { if ( attributeKeyValues[ key ] ) {
return { return {
...attributeKeyValues[ key ], ...attributeKeyValues[ key ],
position: index, position: index,

View File

@ -0,0 +1,4 @@
Significance: minor
Type: fix
Fix attributes/options lists corrupt render #36236