Remove Custom Fields for New Product Editor (#45493)
* Add remove custom field for the new product editor * Add changelog file * Show add button when the custom fields are empty * Ensures to always convert the metas into a string array since it can be anything * Add changelog file
This commit is contained in:
parent
3f1dbd5b13
commit
0fc75c5148
|
@ -0,0 +1,4 @@
|
|||
Significance: minor
|
||||
Type: add
|
||||
|
||||
Remove Custom Fields for New Product Editor
|
|
@ -4,6 +4,7 @@
|
|||
import { Button } from '@wordpress/components';
|
||||
import { createElement, Fragment, useState } from '@wordpress/element';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { closeSmall } from '@wordpress/icons';
|
||||
import classNames from 'classnames';
|
||||
|
||||
/**
|
||||
|
@ -21,17 +22,17 @@ export function CustomFields( {
|
|||
renderActionButtonsWrapper = ( buttons ) => buttons,
|
||||
...props
|
||||
}: CustomFieldsProps ) {
|
||||
const { customFields, addCustomFields, updateCustomField } =
|
||||
useCustomFields();
|
||||
const {
|
||||
customFields,
|
||||
addCustomFields,
|
||||
updateCustomField,
|
||||
removeCustomField,
|
||||
} = useCustomFields();
|
||||
|
||||
const [ showCreateModal, setShowCreateModal ] = useState( false );
|
||||
const [ selectedCustomField, setSelectedCustomField ] =
|
||||
useState< Metadata< string > >();
|
||||
|
||||
if ( customFields.length === 0 ) {
|
||||
return <EmptyState />;
|
||||
}
|
||||
|
||||
function handleAddNewButtonClick() {
|
||||
setShowCreateModal( true );
|
||||
}
|
||||
|
@ -44,6 +45,14 @@ export function CustomFields( {
|
|||
};
|
||||
}
|
||||
|
||||
function customFieldRemoveButtonClickHandler(
|
||||
customField: Metadata< string >
|
||||
) {
|
||||
return function handleCustomFieldRemoveButtonClick() {
|
||||
removeCustomField( customField );
|
||||
};
|
||||
}
|
||||
|
||||
function handleCreateModalCreate( value: Metadata< string >[] ) {
|
||||
addCustomFields( value );
|
||||
setShowCreateModal( false );
|
||||
|
@ -70,46 +79,61 @@ export function CustomFields( {
|
|||
</Button>
|
||||
) }
|
||||
|
||||
<table
|
||||
{ ...props }
|
||||
className={ classNames(
|
||||
'woocommerce-product-custom-fields__table',
|
||||
className
|
||||
) }
|
||||
>
|
||||
<thead>
|
||||
<tr className="woocommerce-product-custom-fields__table-row">
|
||||
<th>{ __( 'Name', 'woocommerce' ) }</th>
|
||||
<th>{ __( 'Value', 'woocommerce' ) }</th>
|
||||
<th>{ __( 'Actions', 'woocommerce' ) }</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{ customFields.map( ( customField ) => (
|
||||
<tr
|
||||
className="woocommerce-product-custom-fields__table-row"
|
||||
key={ customField.id ?? customField.key }
|
||||
>
|
||||
<td className="woocommerce-product-custom-fields__table-datacell">
|
||||
{ customField.key }
|
||||
</td>
|
||||
<td className="woocommerce-product-custom-fields__table-datacell">
|
||||
{ customField.value }
|
||||
</td>
|
||||
<td className="woocommerce-product-custom-fields__table-datacell">
|
||||
<Button
|
||||
variant="tertiary"
|
||||
onClick={ customFieldEditButtonClickHandler(
|
||||
customField
|
||||
) }
|
||||
>
|
||||
{ __( 'Edit', 'woocommerce' ) }
|
||||
</Button>
|
||||
</td>
|
||||
{ customFields.length === 0 ? (
|
||||
<EmptyState />
|
||||
) : (
|
||||
<table
|
||||
{ ...props }
|
||||
className={ classNames(
|
||||
'woocommerce-product-custom-fields__table',
|
||||
className
|
||||
) }
|
||||
>
|
||||
<thead>
|
||||
<tr className="woocommerce-product-custom-fields__table-row">
|
||||
<th>{ __( 'Name', 'woocommerce' ) }</th>
|
||||
<th>{ __( 'Value', 'woocommerce' ) }</th>
|
||||
<th>{ __( 'Actions', 'woocommerce' ) }</th>
|
||||
</tr>
|
||||
) ) }
|
||||
</tbody>
|
||||
</table>
|
||||
</thead>
|
||||
<tbody>
|
||||
{ customFields.map( ( customField ) => (
|
||||
<tr
|
||||
className="woocommerce-product-custom-fields__table-row"
|
||||
key={ customField.id ?? customField.key }
|
||||
>
|
||||
<td className="woocommerce-product-custom-fields__table-datacell">
|
||||
{ customField.key }
|
||||
</td>
|
||||
<td className="woocommerce-product-custom-fields__table-datacell">
|
||||
{ customField.value }
|
||||
</td>
|
||||
<td className="woocommerce-product-custom-fields__table-datacell">
|
||||
<Button
|
||||
variant="tertiary"
|
||||
onClick={ customFieldEditButtonClickHandler(
|
||||
customField
|
||||
) }
|
||||
>
|
||||
{ __( 'Edit', 'woocommerce' ) }
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
icon={ closeSmall }
|
||||
onClick={ customFieldRemoveButtonClickHandler(
|
||||
customField
|
||||
) }
|
||||
aria-label={ __(
|
||||
'Remove custom field',
|
||||
'woocommerce'
|
||||
) }
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
) ) }
|
||||
</tbody>
|
||||
</table>
|
||||
) }
|
||||
|
||||
{ showCreateModal && (
|
||||
<CreateModal
|
||||
|
|
|
@ -5,5 +5,5 @@ import { Metadata } from '../../types';
|
|||
|
||||
export type DisjoinMetas< T extends Metadata< string > > = {
|
||||
customFields: T[];
|
||||
internalMetas: T[];
|
||||
otherMetas: T[];
|
||||
};
|
||||
|
|
|
@ -20,11 +20,11 @@ export function useCustomFields<
|
|||
'meta_data'
|
||||
);
|
||||
|
||||
const { customFields, internalMetas } = useMemo(
|
||||
const { customFields, otherMetas } = useMemo(
|
||||
function extractCustomFieldsFromMetas() {
|
||||
return metas.reduce( disjoinMetas< T >, {
|
||||
customFields: [],
|
||||
internalMetas: [],
|
||||
otherMetas: [],
|
||||
} );
|
||||
},
|
||||
[ metas ]
|
||||
|
@ -34,7 +34,7 @@ export function useCustomFields<
|
|||
const newValue =
|
||||
typeof value === 'function' ? value( customFields ) : value;
|
||||
|
||||
setMetas( [ ...internalMetas, ...newValue ] );
|
||||
setMetas( [ ...otherMetas, ...newValue ] );
|
||||
}
|
||||
|
||||
function addCustomFields( value: T[] ) {
|
||||
|
@ -52,10 +52,36 @@ export function useCustomFields<
|
|||
);
|
||||
}
|
||||
|
||||
function removeCustomField( customField: T ) {
|
||||
setCustomFields( ( current ) => {
|
||||
// If the id is undefined then it is a local copy.
|
||||
if ( customField.id === undefined ) {
|
||||
return current.filter( function isNotEquals( field ) {
|
||||
return ! (
|
||||
field.key === customField.key &&
|
||||
field.value === customField.value
|
||||
);
|
||||
} );
|
||||
}
|
||||
|
||||
return current.map( ( field ) => {
|
||||
if ( field.id === customField.id ) {
|
||||
return {
|
||||
...field,
|
||||
value: null,
|
||||
};
|
||||
}
|
||||
|
||||
return field;
|
||||
} );
|
||||
} );
|
||||
}
|
||||
|
||||
return {
|
||||
customFields,
|
||||
addCustomFields,
|
||||
setCustomFields,
|
||||
updateCustomField,
|
||||
removeCustomField,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -4,8 +4,10 @@
|
|||
import type { Metadata } from '../../../types';
|
||||
import type { DisjoinMetas } from '../types';
|
||||
|
||||
export function isCustomField< T extends Metadata< string > >( value: T ) {
|
||||
return ! value.key.startsWith( '_' );
|
||||
export function isCustomField< T extends Metadata< string > >(
|
||||
customField: T
|
||||
) {
|
||||
return ! customField.key.startsWith( '_' ) && customField.value !== null;
|
||||
}
|
||||
|
||||
export function disjoinMetas< T extends Metadata< string > >(
|
||||
|
@ -15,7 +17,7 @@ export function disjoinMetas< T extends Metadata< string > >(
|
|||
if ( isCustomField( meta ) ) {
|
||||
state.customFields.push( meta );
|
||||
} else {
|
||||
state.internalMetas.push( meta );
|
||||
state.otherMetas.push( meta );
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Significance: minor
|
||||
Type: add
|
||||
|
||||
Ensures to always convert the metas into a string array since it can be anything
|
|
@ -393,7 +393,8 @@ class Init {
|
|||
$hidden = get_user_meta( $object['id'], $attr, true );
|
||||
|
||||
if ( is_array( $hidden ) ) {
|
||||
return $hidden;
|
||||
// Ensures to always return a string array.
|
||||
return array_values( $hidden );
|
||||
}
|
||||
|
||||
return array( 'postcustom' );
|
||||
|
|
Loading…
Reference in New Issue