first commit
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { useState, useEffect } from '@wordpress/element';
|
||||
import { getAttributes, getTerms } from '@woocommerce/editor-components/utils';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { formatError } from '../base/utils/errors.js';
|
||||
|
||||
/**
|
||||
* Get attribute data (name, taxonomy etc) from server data.
|
||||
*
|
||||
* @param {number} attributeId Attribute ID to look for.
|
||||
* @param {Array|null} attributeList List of attributes.
|
||||
* @param {string} matchField Field to match on. e.g. id or slug.
|
||||
*/
|
||||
const getAttributeData = ( attributeId, attributeList, matchField = 'id' ) => {
|
||||
return Array.isArray( attributeList )
|
||||
? attributeList.find( ( attr ) => attr[ matchField ] === attributeId )
|
||||
: null;
|
||||
};
|
||||
|
||||
/**
|
||||
* HOC that calls the useAttributes hook.
|
||||
*
|
||||
* @param {Function} OriginalComponent Component being wrapped.
|
||||
*/
|
||||
const withAttributes = ( OriginalComponent ) => {
|
||||
return ( props ) => {
|
||||
const { selected = [] } = props;
|
||||
const selectedSlug = selected.length ? selected[ 0 ].attr_slug : null;
|
||||
const [ attributes, setAttributes ] = useState( null );
|
||||
const [ expandedAttribute, setExpandedAttribute ] = useState( 0 );
|
||||
const [ termsList, setTermsList ] = useState( {} );
|
||||
const [ loading, setLoading ] = useState( true );
|
||||
const [ termsLoading, setTermsLoading ] = useState( false );
|
||||
const [ error, setError ] = useState( null );
|
||||
|
||||
useEffect( () => {
|
||||
if ( attributes === null ) {
|
||||
getAttributes()
|
||||
.then( ( newAttributes ) => {
|
||||
newAttributes = newAttributes.map( ( attribute ) => ( {
|
||||
...attribute,
|
||||
parent: 0,
|
||||
} ) );
|
||||
|
||||
setAttributes( newAttributes );
|
||||
|
||||
if ( selectedSlug ) {
|
||||
const selectedAttributeFromTerm = getAttributeData(
|
||||
selectedSlug,
|
||||
newAttributes,
|
||||
'taxonomy'
|
||||
);
|
||||
|
||||
if ( selectedAttributeFromTerm ) {
|
||||
setExpandedAttribute(
|
||||
selectedAttributeFromTerm.id
|
||||
);
|
||||
}
|
||||
}
|
||||
} )
|
||||
.catch( async ( e ) => {
|
||||
setError( await formatError( e ) );
|
||||
} )
|
||||
.finally( () => {
|
||||
setLoading( false );
|
||||
} );
|
||||
}
|
||||
}, [ attributes, selectedSlug ] );
|
||||
|
||||
useEffect( () => {
|
||||
const attributeData = getAttributeData(
|
||||
expandedAttribute,
|
||||
attributes
|
||||
);
|
||||
|
||||
if ( ! attributeData ) {
|
||||
return;
|
||||
}
|
||||
|
||||
setTermsLoading( true );
|
||||
|
||||
getTerms( expandedAttribute )
|
||||
.then( ( newTerms ) => {
|
||||
newTerms = newTerms.map( ( term ) => ( {
|
||||
...term,
|
||||
parent: expandedAttribute,
|
||||
attr_slug: attributeData.taxonomy,
|
||||
} ) );
|
||||
|
||||
setTermsList( ( previousTermsList ) => ( {
|
||||
...previousTermsList,
|
||||
[ expandedAttribute ]: newTerms,
|
||||
} ) );
|
||||
} )
|
||||
.catch( async ( e ) => {
|
||||
setError( await formatError( e ) );
|
||||
} )
|
||||
.finally( () => {
|
||||
setTermsLoading( false );
|
||||
} );
|
||||
}, [ expandedAttribute, attributes ] );
|
||||
|
||||
return (
|
||||
<OriginalComponent
|
||||
{ ...props }
|
||||
attributes={ attributes || [] }
|
||||
error={ error }
|
||||
expandedAttribute={ expandedAttribute }
|
||||
onExpandAttribute={ setExpandedAttribute }
|
||||
isLoading={ loading }
|
||||
termsAreLoading={ termsLoading }
|
||||
termsList={ termsList }
|
||||
/>
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
export default withAttributes;
|
||||
Reference in New Issue
Block a user