Expose metadata as object from useProductMetadata hook (#43860)
* Add useParentMetadata hook * Move functionality to existing useProductMetadata hook * Update changelog * Remove deleted hook from index * Update useProductMetadata API and unit tests
This commit is contained in:
parent
80b4ec13e3
commit
c7d4c88270
|
@ -0,0 +1,4 @@
|
||||||
|
Significance: minor
|
||||||
|
Type: add
|
||||||
|
|
||||||
|
Expose metadata as object from useProductMetadata hook
|
|
@ -10,24 +10,36 @@ import useProductMetadata from '../use-product-metadata';
|
||||||
|
|
||||||
const mockFnMetadataProp = jest.fn();
|
const mockFnMetadataProp = jest.fn();
|
||||||
jest.mock( '@wordpress/core-data', () => ( {
|
jest.mock( '@wordpress/core-data', () => ( {
|
||||||
useEntityProp: jest.fn().mockImplementation( () => {
|
useEntityId: jest.fn().mockReturnValue( 123 ),
|
||||||
return [
|
} ) );
|
||||||
[
|
|
||||||
{
|
jest.mock( '@wordpress/data', () => ( {
|
||||||
key: 'field1',
|
useSelect: jest.fn().mockImplementation( ( callback ) => {
|
||||||
value: 'value1',
|
return callback(
|
||||||
},
|
jest.fn().mockReturnValue( {
|
||||||
{
|
getEditedEntityRecord: () => ( {
|
||||||
key: 'field2',
|
meta_data: [
|
||||||
value: 'value1',
|
{
|
||||||
},
|
key: 'field1',
|
||||||
{
|
value: 'value1',
|
||||||
key: 'existing_field',
|
},
|
||||||
value: 'value1',
|
{
|
||||||
},
|
key: 'field2',
|
||||||
],
|
value: 'value1',
|
||||||
mockFnMetadataProp,
|
},
|
||||||
];
|
{
|
||||||
|
key: 'existing_field',
|
||||||
|
value: 'value1',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
} ),
|
||||||
|
} )
|
||||||
|
);
|
||||||
|
} ),
|
||||||
|
useDispatch: jest.fn().mockImplementation( () => {
|
||||||
|
return {
|
||||||
|
editEntityRecord: mockFnMetadataProp,
|
||||||
|
};
|
||||||
} ),
|
} ),
|
||||||
} ) );
|
} ) );
|
||||||
|
|
||||||
|
@ -45,19 +57,36 @@ describe( 'useProductMetadata', () => {
|
||||||
value: 'value2',
|
value: 'value2',
|
||||||
},
|
},
|
||||||
] );
|
] );
|
||||||
expect( mockFnMetadataProp ).toHaveBeenCalledWith( [
|
expect( mockFnMetadataProp ).toHaveBeenCalledWith(
|
||||||
|
'postType',
|
||||||
|
'product',
|
||||||
|
123,
|
||||||
{
|
{
|
||||||
key: 'existing_field',
|
meta_data: [
|
||||||
value: 'value1',
|
{
|
||||||
},
|
key: 'existing_field',
|
||||||
{
|
value: 'value1',
|
||||||
key: 'field1',
|
},
|
||||||
value: 'value2',
|
{
|
||||||
},
|
key: 'field1',
|
||||||
{
|
value: 'value2',
|
||||||
key: 'field2',
|
},
|
||||||
value: 'value2',
|
{
|
||||||
},
|
key: 'field2',
|
||||||
] );
|
value: 'value2',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
it( 'should return the metadata as an object for easy readings', async () => {
|
||||||
|
const { metadata } = renderHook( () =>
|
||||||
|
useProductMetadata( { postType: 'product', id: 123 } )
|
||||||
|
).result.current;
|
||||||
|
expect( metadata ).toEqual( {
|
||||||
|
field1: 'value1',
|
||||||
|
field2: 'value1',
|
||||||
|
existing_field: 'value1',
|
||||||
|
} );
|
||||||
} );
|
} );
|
||||||
} );
|
} );
|
||||||
|
|
|
@ -1,30 +1,62 @@
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore No types for this exist yet.
|
||||||
|
// eslint-disable-next-line @woocommerce/dependency-group
|
||||||
|
import { useEntityId } from '@wordpress/core-data';
|
||||||
/**
|
/**
|
||||||
* External dependencies
|
* External dependencies
|
||||||
*/
|
*/
|
||||||
import { useEntityProp } from '@wordpress/core-data';
|
import { useDispatch, useSelect } from '@wordpress/data';
|
||||||
|
import { Product } from '@woocommerce/data';
|
||||||
/**
|
/**
|
||||||
* Internal dependencies
|
* Internal dependencies
|
||||||
*/
|
*/
|
||||||
import { Metadata } from '../types';
|
import { Metadata } from '../types';
|
||||||
|
|
||||||
function useProductMetadata( postType?: string ) {
|
interface Options {
|
||||||
const [ metadata, setMetadata ] = useEntityProp< Metadata< string >[] >(
|
postType?: string;
|
||||||
'postType',
|
id?: number;
|
||||||
postType || 'product',
|
}
|
||||||
'meta_data'
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
function useProductMetadata( options?: Options ) {
|
||||||
updateMetadata: ( entries: Metadata< string >[] ) => {
|
const postType = options?.postType || 'product';
|
||||||
setMetadata( [
|
const thisId = useEntityId( 'postType', postType );
|
||||||
...metadata.filter(
|
const id = options?.id || thisId;
|
||||||
( item ) =>
|
|
||||||
entries.findIndex( ( e ) => e.key === item.key ) === -1
|
// @ts-expect-error There are no types for this.
|
||||||
),
|
const { editEntityRecord } = useDispatch( 'core' );
|
||||||
...entries,
|
|
||||||
] );
|
return useSelect(
|
||||||
|
( select ) => {
|
||||||
|
// @ts-expect-error There are no types for this.
|
||||||
|
const { getEditedEntityRecord } = select( 'core' );
|
||||||
|
const { meta_data: metadata }: Product = getEditedEntityRecord(
|
||||||
|
'postType',
|
||||||
|
postType,
|
||||||
|
id
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
metadata: metadata.reduce( function ( acc, cur ) {
|
||||||
|
acc[ cur.key ] = cur.value;
|
||||||
|
return acc;
|
||||||
|
}, {} as Record< string, string | undefined > ),
|
||||||
|
updateMetadata: ( entries: Metadata< string >[] ) => {
|
||||||
|
editEntityRecord( 'postType', postType, id, {
|
||||||
|
meta_data: [
|
||||||
|
...metadata.filter(
|
||||||
|
( item ) =>
|
||||||
|
entries.findIndex(
|
||||||
|
( e ) => e.key === item.key
|
||||||
|
) === -1
|
||||||
|
),
|
||||||
|
...entries,
|
||||||
|
],
|
||||||
|
} );
|
||||||
|
},
|
||||||
|
};
|
||||||
},
|
},
|
||||||
};
|
[ id ]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default useProductMetadata;
|
export default useProductMetadata;
|
||||||
|
|
Loading…
Reference in New Issue