From ee5f12f806a0675f98affcdeca4f8c6d079d0dc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dami=C3=A1n=20Su=C3=A1rez?= Date: Tue, 30 Apr 2024 07:18:03 -0400 Subject: [PATCH] Product Block Editor: tidy product attribute TS types (#46998) * rename type for item of attribuite input field * options is not part of the input item * update type of getProductAttributeObject * update types * changelog * fix eslint issue * fix test --- .../update-product-editor-attribute-types | 4 ++ .../attribute-control/new-attribute-modal.tsx | 13 ++---- .../src/components/attribute-control/utils.ts | 19 +++++--- .../attribute-input-field.tsx | 44 +++++++++---------- .../menu-attribute-list.tsx | 8 ++-- .../test/attribute-input-field.spec.tsx | 2 - .../components/attribute-input-field/types.ts | 23 +++++----- 7 files changed, 58 insertions(+), 55 deletions(-) create mode 100644 packages/js/product-editor/changelog/update-product-editor-attribute-types diff --git a/packages/js/product-editor/changelog/update-product-editor-attribute-types b/packages/js/product-editor/changelog/update-product-editor-attribute-types new file mode 100644 index 00000000000..72609e884ac --- /dev/null +++ b/packages/js/product-editor/changelog/update-product-editor-attribute-types @@ -0,0 +1,4 @@ +Significance: patch +Type: update + +Product Block Editor: tidy product attribute types diff --git a/packages/js/product-editor/src/components/attribute-control/new-attribute-modal.tsx b/packages/js/product-editor/src/components/attribute-control/new-attribute-modal.tsx index 574afedcff4..72a7794182b 100644 --- a/packages/js/product-editor/src/components/attribute-control/new-attribute-modal.tsx +++ b/packages/js/product-editor/src/components/attribute-control/new-attribute-modal.tsx @@ -11,8 +11,7 @@ import { } from '@woocommerce/components'; import { EXPERIMENTAL_PRODUCT_ATTRIBUTE_TERMS_STORE_NAME, - ProductProductAttribute, - ProductAttributeTerm, + type ProductAttributeTerm, } from '@woocommerce/data'; import { Button, Modal, Notice } from '@wordpress/components'; @@ -24,8 +23,9 @@ import { AttributeTermInputField, CustomAttributeTermInputField, } from '../attribute-term-input-field'; -import { EnhancedProductAttribute } from '../../hooks/use-product-attributes'; import { getProductAttributeObject } from './utils'; +import type { AttributeInputFieldItemProps } from '../attribute-input-field/types'; +import type { EnhancedProductAttribute } from '../../hooks/use-product-attributes'; type NewAttributeModalProps = { title?: string; @@ -225,12 +225,7 @@ export const NewAttributeModal: React.FC< NewAttributeModalProps > = ( { } ) => { function getAttributeOnChange( index: number ) { return function handleAttributeChange( - value?: - | Omit< - ProductProductAttribute, - 'position' | 'visible' | 'variation' - > - | string + value?: AttributeInputFieldItemProps | string ) { if ( termsAutoSelection && diff --git a/packages/js/product-editor/src/components/attribute-control/utils.ts b/packages/js/product-editor/src/components/attribute-control/utils.ts index d223e452ecc..9d28cc4dd4d 100644 --- a/packages/js/product-editor/src/components/attribute-control/utils.ts +++ b/packages/js/product-editor/src/components/attribute-control/utils.ts @@ -1,7 +1,12 @@ /** * External dependencies */ -import { ProductProductAttribute } from '@woocommerce/data'; +import type { ProductProductAttribute } from '@woocommerce/data'; + +/** + * Internal dependencies + */ +import type { AttributeInputFieldItemProps } from '../attribute-input-field/types'; /** * Returns the attribute key. The key will be the `id` or the `name` when the id is 0. @@ -50,21 +55,21 @@ export function reorderSortableProductAttributePositions( } /** - * Helper function to return the product attribute object. If attribute is a string it will create an object. + * Helper function to return an EnhancedProductAttribute object, + * based on the provided attribute object. + * + * If attribute is a string it will create an object. * * @param { Object | string } attribute product attribute as string or object. */ export function getProductAttributeObject( - attribute: - | string - | Omit< ProductProductAttribute, 'position' | 'visible' | 'variation' > -): Omit< ProductProductAttribute, 'position' | 'visible' | 'variation' > { + attribute: string | AttributeInputFieldItemProps +): AttributeInputFieldItemProps { return typeof attribute === 'string' ? { id: 0, name: attribute, slug: attribute, - options: [], } : attribute; } diff --git a/packages/js/product-editor/src/components/attribute-input-field/attribute-input-field.tsx b/packages/js/product-editor/src/components/attribute-input-field/attribute-input-field.tsx index 68c47ae44c3..4a0f67b16f4 100644 --- a/packages/js/product-editor/src/components/attribute-input-field/attribute-input-field.tsx +++ b/packages/js/product-editor/src/components/attribute-input-field/attribute-input-field.tsx @@ -26,7 +26,7 @@ import { AttributeInputFieldProps, getItemPropsType, getMenuPropsType, - NarrowedQueryAttribute, + AttributeInputFieldItemProps, UseComboboxGetItemPropsOptions, UseComboboxGetMenuPropsOptions, } from './types'; @@ -65,26 +65,30 @@ export const AttributeInputField: React.FC< AttributeInputFieldProps > = ( { const markedAttributes = useMemo( function setDisabledAttribute() { return ( - attributes?.map( ( attribute: NarrowedQueryAttribute ) => ( { - ...attribute, - isDisabled: disabledAttributeIds.includes( attribute.id ), - } ) ) ?? [] + attributes?.map( + ( attribute: AttributeInputFieldItemProps ) => ( { + ...attribute, + isDisabled: disabledAttributeIds.includes( + attribute.id + ), + } ) + ) ?? [] ); }, [ attributes, disabledAttributeIds ] ); function isNewAttributeListItem( - attribute: NarrowedQueryAttribute + attribute: AttributeInputFieldItemProps ): boolean { return attribute.id === -99; } const getFilteredItems = ( - allItems: NarrowedQueryAttribute[], + allItems: AttributeInputFieldItemProps[], inputValue: string ) => { - const ignoreIdsFilter = ( item: NarrowedQueryAttribute ) => + const ignoreIdsFilter = ( item: AttributeInputFieldItemProps ) => ignoredAttributeIds.length ? ! ignoredAttributeIds.includes( item.id ) : true; @@ -117,7 +121,7 @@ export const AttributeInputField: React.FC< AttributeInputFieldProps > = ( { return filteredItems; }; - const addNewAttribute = ( attribute: NarrowedQueryAttribute ) => { + const addNewAttribute = ( attribute: AttributeInputFieldItemProps ) => { recordEvent( 'product_attribute_add_custom_attribute', { source: TRACKS_SOURCE, } ); @@ -130,11 +134,9 @@ export const AttributeInputField: React.FC< AttributeInputFieldProps > = ( { { optimisticQueryUpdate: sortCriteria, } - ).then( - ( newAttr ) => { - onChange( { ...newAttr, options: [] } ); - }, - ( error ) => { + ) + .then( onChange ) + .catch( ( error ) => { let message = __( 'Failed to create new attribute.', 'woocommerce' @@ -146,15 +148,14 @@ export const AttributeInputField: React.FC< AttributeInputFieldProps > = ( { createErrorNotice( message, { explicitDismiss: true, } ); - } - ); + } ); } else { onChange( attribute.name ); } }; return ( - + className="woocommerce-attribute-input-field" items={ markedAttributes || [] } label={ label || '' } @@ -164,7 +165,7 @@ export const AttributeInputField: React.FC< AttributeInputFieldProps > = ( { getItemLabel={ ( item ) => item?.name || '' } getItemValue={ ( item ) => item?.id || '' } selected={ value } - onSelect={ ( attribute: NarrowedQueryAttribute ) => { + onSelect={ ( attribute: AttributeInputFieldItemProps ) => { if ( isNewAttributeListItem( attribute ) ) { addNewAttribute( attribute ); } else { @@ -172,7 +173,6 @@ export const AttributeInputField: React.FC< AttributeInputFieldProps > = ( { id: attribute.id, name: attribute.name, slug: attribute.slug as string, - options: [], } ); } } } @@ -186,10 +186,10 @@ export const AttributeInputField: React.FC< AttributeInputFieldProps > = ( { getMenuProps, isOpen, }: { - items: NarrowedQueryAttribute[]; + items: AttributeInputFieldItemProps[]; highlightedIndex: number; getItemProps: ( - options: UseComboboxGetItemPropsOptions< NarrowedQueryAttribute > + options: UseComboboxGetItemPropsOptions< AttributeInputFieldItemProps > // eslint-disable-next-line @typescript-eslint/no-explicit-any ) => any; getMenuProps: getMenuPropsType; @@ -209,7 +209,7 @@ export const AttributeInputField: React.FC< AttributeInputFieldProps > = ( { getItemProps={ getItemProps as ( options: UseComboboxGetMenuPropsOptions - ) => getItemPropsType< NarrowedQueryAttribute > + ) => getItemPropsType< AttributeInputFieldItemProps > } /> ) } diff --git a/packages/js/product-editor/src/components/attribute-input-field/menu-attribute-list.tsx b/packages/js/product-editor/src/components/attribute-input-field/menu-attribute-list.tsx index 0fcec286d32..996ee49f3a9 100644 --- a/packages/js/product-editor/src/components/attribute-input-field/menu-attribute-list.tsx +++ b/packages/js/product-editor/src/components/attribute-input-field/menu-attribute-list.tsx @@ -10,13 +10,15 @@ import { __experimentalSelectControlMenuItem as MenuItem } from '@woocommerce/co /** * Internal dependencies */ -import { +import type { MenuAttributeListProps, - NarrowedQueryAttribute, + AttributeInputFieldItemProps, UseComboboxGetMenuPropsOptions, } from './types'; -function isNewAttributeListItem( attribute: NarrowedQueryAttribute ): boolean { +function isNewAttributeListItem( + attribute: AttributeInputFieldItemProps +): boolean { return attribute.id === -99; } diff --git a/packages/js/product-editor/src/components/attribute-input-field/test/attribute-input-field.spec.tsx b/packages/js/product-editor/src/components/attribute-input-field/test/attribute-input-field.spec.tsx index 6d3eae2422b..a7fd11ca0cb 100644 --- a/packages/js/product-editor/src/components/attribute-input-field/test/attribute-input-field.spec.tsx +++ b/packages/js/product-editor/src/components/attribute-input-field/test/attribute-input-field.spec.tsx @@ -234,7 +234,6 @@ describe( 'AttributeInputField', () => { id: attributeList[ 0 ].id, name: attributeList[ 0 ].name, slug: attributeList[ 0 ].slug, - options: [], } ); } ); @@ -325,7 +324,6 @@ describe( 'AttributeInputField', () => { name: 'Co', slug: 'co', id: 123, - options: [], } ); } ); diff --git a/packages/js/product-editor/src/components/attribute-input-field/types.ts b/packages/js/product-editor/src/components/attribute-input-field/types.ts index 63b78b0f23f..008378f42d2 100644 --- a/packages/js/product-editor/src/components/attribute-input-field/types.ts +++ b/packages/js/product-editor/src/components/attribute-input-field/types.ts @@ -1,28 +1,27 @@ /** * External dependencies */ -import { ProductAttribute, ProductProductAttribute } from '@woocommerce/data'; +import { ProductAttribute } from '@woocommerce/data'; /** * Internal dependencies */ import { EnhancedProductAttribute } from '../../hooks/use-product-attributes'; -export type NarrowedQueryAttribute = Pick< ProductAttribute, 'id' | 'name' > & { +/* + * AttributeInputField item props. + */ +export type AttributeInputFieldItemProps = Pick< + ProductAttribute, + 'id' | 'name' +> & { slug?: string; isDisabled?: boolean; }; export type AttributeInputFieldProps = { value?: EnhancedProductAttribute | null; - onChange: ( - value?: - | Omit< - ProductProductAttribute, - 'position' | 'visible' | 'variation' - > - | string - ) => void; + onChange: ( value?: AttributeInputFieldItemProps | string ) => void; label?: string; placeholder?: string; disabled?: boolean; @@ -33,12 +32,12 @@ export type AttributeInputFieldProps = { }; export type MenuAttributeListProps = { - renderItems: NarrowedQueryAttribute[]; + renderItems: AttributeInputFieldItemProps[]; highlightedIndex: number; disabledAttributeMessage?: string; getItemProps: ( options: UseComboboxGetMenuPropsOptions - ) => getItemPropsType< NarrowedQueryAttribute >; + ) => getItemPropsType< AttributeInputFieldItemProps >; }; export interface GetPropsWithRefKey {