woocommerce/plugins/woocommerce-blocks/assets/js/hocs/with-attributes.js

123 lines
2.9 KiB
JavaScript

/**
* External dependencies
*/
import { useState, useEffect } from '@wordpress/element';
import { getAttributes, getTerms } from '@woocommerce/block-components/utils';
import { find } from 'lodash';
/**
* 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} attributeList List of attributes.
* @param {string} matchField Field to match on. e.g. id or slug.
*/
const getAttributeData = ( attributeId, attributeList, matchField = 'id' ) => {
return attributeList
? find( attributeList, [ matchField, attributeId ] )
: null;
};
/**
* HOC that calls the useAttributes hook.
*
* @param {Function} OriginalComponent Component being wrapped.
*/
const withAttributes = ( OriginalComponent ) => {
return ( props ) => {
const { selected } = props;
const [ attributes, setAttributes ] = useState( [] );
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( () => {
getAttributes()
.then( ( newAttributes ) => {
newAttributes = newAttributes.map( ( attribute ) => ( {
...attribute,
parent: 0,
} ) );
setAttributes( newAttributes );
if ( selected.length > 0 ) {
const selectedAttributeFromTerm = attributes
? getAttributeData(
selected[ 0 ].attr_slug,
newAttributes,
'slug'
)
: null;
if ( selectedAttributeFromTerm ) {
setExpandedAttribute(
selectedAttributeFromTerm.id
);
}
}
} )
.catch( async ( e ) => {
setError( await formatError( e ) );
} )
.finally( () => {
setLoading( false );
} );
}, [] );
useEffect( () => {
const attributeData = attributes
? getAttributeData( expandedAttribute, attributes )
: null;
if ( ! attributeData ) {
return;
}
setTermsLoading( true );
getTerms( expandedAttribute )
.then( ( newTerms ) => {
newTerms = newTerms.map( ( term ) => ( {
...term,
parent: expandedAttribute,
attr_slug: attributeData.slug,
} ) );
setTermsList( {
...termsList,
[ 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;