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:
parent
0c161dcacb
commit
a4ed336a0d
|
@ -0,0 +1,4 @@
|
|||
Significance: minor
|
||||
Type: add
|
||||
|
||||
Add Tooltip to each list item when need it
|
|
@ -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();
|
||||
};
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Significance: minor
|
||||
Type: add
|
||||
|
||||
Disable attributes used in different sections
|
|
@ -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: '',
|
||||
|
|
|
@ -158,6 +158,9 @@ export function Edit( {
|
|||
selectedAttributeIds={ variationOptions.map(
|
||||
( attr ) => attr.id
|
||||
) }
|
||||
disabledAttributeIds={ productAttributes
|
||||
.filter( ( attr ) => ! attr.variation )
|
||||
.map( ( attr ) => attr.id ) }
|
||||
/>
|
||||
) }
|
||||
</div>
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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' );
|
||||
} }
|
||||
|
|
Loading…
Reference in New Issue