Variation attributes can not be enabled in Attributes section and Non Variations attributes cannot be enabled in Variation Options section (#39770)

* Disabled attributes used in different section

* Let the attribute input field to disable some items within the dropdown list

* Define disabled attribute ids and message

* Filter non variable attributes as disabled to be used under variations options

* Filter variable attributes as disabled to be used under attributes

* Add changelog file

* Fix linter error

* Add tooltip option to menu item and use it for attribute and variations

* Fix some rebase conflicts

* Add changelog file

---------

Co-authored-by: Lourens Schep <lourensschep@gmail.com>
This commit is contained in:
Maikel David Pérez Gómez 2023-08-21 15:39:31 -04:00 committed by GitHub
parent 0c161dcacb
commit a4ed336a0d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 129 additions and 30 deletions

View File

@ -0,0 +1,4 @@
Significance: minor
Type: add
Add Tooltip to each list item when need it

View File

@ -1,6 +1,7 @@
/**
* External dependencies
*/
import { Tooltip } from '@wordpress/components';
import { createElement, CSSProperties, ReactElement } from 'react';
/**
@ -15,6 +16,7 @@ export type MenuItemProps< ItemType > = {
children: ReactElement | string;
getItemProps: getItemPropsType< ItemType >;
activeStyle?: CSSProperties;
tooltipText?: string;
};
export const MenuItem = < ItemType, >( {
@ -24,14 +26,27 @@ export const MenuItem = < ItemType, >( {
isActive,
activeStyle = { backgroundColor: '#bde4ff' },
item,
tooltipText,
}: MenuItemProps< ItemType > ) => {
return (
<li
style={ isActive ? activeStyle : {} }
{ ...getItemProps( { item, index } ) }
className="woocommerce-experimental-select-control__menu-item"
>
{ children }
</li>
);
function renderListItem() {
return (
<li
style={ isActive ? activeStyle : {} }
{ ...getItemProps( { item, index } ) }
className="woocommerce-experimental-select-control__menu-item"
>
{ children }
</li>
);
}
if ( tooltipText ) {
return (
<Tooltip text={ tooltipText } position="top center">
{ renderListItem() }
</Tooltip>
);
}
return renderListItem();
};

View File

@ -0,0 +1,4 @@
Significance: minor
Type: add
Disable attributes used in different sections

View File

@ -139,6 +139,9 @@ export function Edit() {
product_block_variable_options_notice_dismissed: 'yes',
} )
}
disabledAttributeIds={ entityAttributes
.filter( ( attr ) => ! attr.variation )
.map( ( attr ) => attr.id ) }
uiStrings={ {
notice,
globalAttributeHelperMessage: '',

View File

@ -158,6 +158,9 @@ export function Edit( {
selectedAttributeIds={ variationOptions.map(
( attr ) => attr.id
) }
disabledAttributeIds={ productAttributes
.filter( ( attr ) => ! attr.variation )
.map( ( attr ) => attr.id ) }
/>
) }
</div>

View File

@ -48,6 +48,7 @@ type AttributeControlProps = {
onNoticeDismiss?: () => void;
createNewAttributesAsGlobal?: boolean;
useRemoveConfirmationModal?: boolean;
disabledAttributeIds?: number[];
uiStrings?: {
notice?: string | React.ReactElement;
emptyStateSubtitle?: string;
@ -59,7 +60,8 @@ type AttributeControlProps = {
attributeRemoveLabel?: string;
attributeRemoveConfirmationMessage?: string;
attributeRemoveConfirmationModalMessage?: string;
globalAttributeHelperMessage: string;
globalAttributeHelperMessage?: string;
disabledAttributeMessage?: string;
};
};
@ -80,6 +82,7 @@ export const AttributeControl: React.FC< AttributeControlProps > = ( {
uiStrings,
createNewAttributesAsGlobal = false,
useRemoveConfirmationModal = false,
disabledAttributeIds = [],
} ) => {
uiStrings = {
newAttributeListItemLabel: __( 'Add new', 'woocommerce' ),
@ -279,6 +282,10 @@ export const AttributeControl: React.FC< AttributeControlProps > = ( {
onAdd={ handleAdd }
selectedAttributeIds={ value.map( ( attr ) => attr.id ) }
createNewAttributesAsGlobal={ createNewAttributesAsGlobal }
disabledAttributeIds={ disabledAttributeIds }
disabledAttributeMessage={
uiStrings.disabledAttributeMessage
}
/>
) }
<SelectControlMenuSlot />
@ -292,22 +299,26 @@ export const AttributeControl: React.FC< AttributeControlProps > = ( {
customAttributeHelperMessage={
uiStrings.customAttributeHelperMessage
}
globalAttributeHelperMessage={ createInterpolateElement(
uiStrings.globalAttributeHelperMessage,
{
link: (
<Link
href={ getAdminLink(
'edit.php?post_type=product&page=product_attributes'
) }
target="_blank"
type="wp-admin"
>
<></>
</Link>
),
}
) }
globalAttributeHelperMessage={
uiStrings.globalAttributeHelperMessage
? createInterpolateElement(
uiStrings.globalAttributeHelperMessage,
{
link: (
<Link
href={ getAdminLink(
'edit.php?post_type=product&page=product_attributes'
) }
target="_blank"
type="wp-admin"
>
<></>
</Link>
),
}
)
: undefined
}
onCancel={ () => {
closeEditModal( currentAttribute );
onEditModalCancel( currentAttribute );

View File

@ -55,6 +55,8 @@ type NewAttributeModalProps = {
onAdd: ( newCategories: EnhancedProductAttribute[] ) => void;
selectedAttributeIds?: number[];
createNewAttributesAsGlobal?: boolean;
disabledAttributeIds?: number[];
disabledAttributeMessage?: string;
};
type AttributeForm = {
@ -88,6 +90,11 @@ export const NewAttributeModal: React.FC< NewAttributeModalProps > = ( {
onAdd,
selectedAttributeIds = [],
createNewAttributesAsGlobal = false,
disabledAttributeIds = [],
disabledAttributeMessage = __(
'Already used in Attributes',
'woocommerce'
),
} ) => {
const scrollAttributeIntoView = ( index: number ) => {
setTimeout( () => {
@ -317,6 +324,12 @@ export const NewAttributeModal: React.FC< NewAttributeModalProps > = ( {
createNewAttributesAsGlobal={
createNewAttributesAsGlobal
}
disabledAttributeIds={
disabledAttributeIds
}
disabledAttributeMessage={
disabledAttributeMessage
}
/>
</td>
<td className="woocommerce-new-attribute-modal__table-attribute-value-column">

View File

@ -8,3 +8,13 @@
margin-right: $gap-small;
}
}
.woocommerce-experimental-select-control__popover-menu-container {
.woocommerce-experimental-select-control__menu-item[disabled] {
pointer-events: none;
color: $gray-600;
}
.disabled-element-wrapper {
cursor: not-allowed;
}
}

View File

@ -5,7 +5,7 @@ import { sprintf, __ } from '@wordpress/i18n';
import { useDispatch, useSelect } from '@wordpress/data';
import { Spinner, Icon } from '@wordpress/components';
import { plus } from '@wordpress/icons';
import { createElement } from '@wordpress/element';
import { createElement, useMemo } from '@wordpress/element';
import {
EXPERIMENTAL_PRODUCT_ATTRIBUTES_STORE_NAME,
QueryProductAttribute,
@ -27,7 +27,9 @@ import {
import { EnhancedProductAttribute } from '../../hooks/use-product-attributes';
import { TRACKS_SOURCE } from '../../constants';
type NarrowedQueryAttribute = Pick< QueryProductAttribute, 'id' | 'name' >;
type NarrowedQueryAttribute = Pick< QueryProductAttribute, 'id' | 'name' > & {
isDisabled?: boolean;
};
type AttributeInputFieldProps = {
value?: EnhancedProductAttribute | null;
@ -39,6 +41,8 @@ type AttributeInputFieldProps = {
label?: string;
placeholder?: string;
disabled?: boolean;
disabledAttributeIds?: number[];
disabledAttributeMessage?: string;
ignoredAttributeIds?: number[];
createNewAttributesAsGlobal?: boolean;
};
@ -53,6 +57,8 @@ export const AttributeInputField: React.FC< AttributeInputFieldProps > = ( {
placeholder,
label,
disabled,
disabledAttributeIds = [],
disabledAttributeMessage,
ignoredAttributeIds = [],
createNewAttributesAsGlobal = false,
} ) => {
@ -72,6 +78,18 @@ export const AttributeInputField: React.FC< AttributeInputFieldProps > = ( {
};
} );
const markedAttributes = useMemo(
function setDisabledAttribute() {
return (
attributes?.map( ( attribute ) => ( {
...attribute,
isDisabled: disabledAttributeIds.includes( attribute.id ),
} ) ) ?? []
);
},
[ attributes, disabledAttributeIds ]
);
const getFilteredItems = (
allItems: NarrowedQueryAttribute[],
inputValue: string
@ -139,7 +157,7 @@ export const AttributeInputField: React.FC< AttributeInputFieldProps > = ( {
return (
<SelectControl< NarrowedQueryAttribute >
className="woocommerce-attribute-input-field"
items={ attributes || [] }
items={ markedAttributes || [] }
label={ label || '' }
disabled={ disabled }
getFilteredItems={ getFilteredItems }
@ -179,7 +197,15 @@ export const AttributeInputField: React.FC< AttributeInputFieldProps > = ( {
index={ index }
isActive={ highlightedIndex === index }
item={ item }
getItemProps={ getItemProps }
getItemProps={ ( options ) => ( {
...getItemProps( options ),
disabled: item.isDisabled || undefined,
} ) }
tooltipText={
item.isDisabled
? disabledAttributeMessage
: undefined
}
>
{ isNewAttributeListItem( item ) ? (
<div className="woocommerce-attribute-input-field__add-new">

View File

@ -3,6 +3,7 @@
*/
import { createElement } from '@wordpress/element';
import { ProductAttribute } from '@woocommerce/data';
import { __ } from '@wordpress/i18n';
import { recordEvent } from '@woocommerce/tracks';
/**
@ -31,6 +32,15 @@ export const Attributes: React.FC< AttributesProps > = ( {
return (
<AttributeControl
value={ attributes }
disabledAttributeIds={ value
.filter( ( attr ) => !! attr.variation )
.map( ( attr ) => attr.id ) }
uiStrings={ {
disabledAttributeMessage: __(
'Already used in Variations',
'woocommerce'
),
} }
onAdd={ () => {
recordEvent( 'product_add_attributes_modal_add_button_click' );
} }