const { __ } = wp.i18n; const { Toolbar, withAPIData, Dropdown, Dashicon } = wp.components; /** * When the display mode is 'Product category' search for and select product categories to pull products from. */ export class ProductsCategorySelect extends React.Component { /** * Constructor. */ constructor( props ) { super( props ); this.state = { selectedCategories: props.selected_display_setting, openAccordion: [], filterQuery: '', firstLoad: true, } this.checkboxChange = this.checkboxChange.bind( this ); this.accordionToggle = this.accordionToggle.bind( this ); this.filterResults = this.filterResults.bind( this ); this.setFirstLoad = this.setFirstLoad.bind( this ); } /** * Handle checkbox toggle. * * @param Checked? boolean checked * @param Categories array categories */ checkboxChange( checked, categories ) { let selectedCategories = this.state.selectedCategories; selectedCategories = selectedCategories.filter( category => ! categories.includes( category ) ); if ( checked ) { selectedCategories.push( ...categories ); } this.setState( { selectedCategories: selectedCategories } ); this.props.update_display_setting_callback( selectedCategories ); } /** * Handle accordion toggle. * * @param Category ID category */ accordionToggle( category ) { let openAccordions = this.state.openAccordion; if ( openAccordions.includes( category ) ) { openAccordions = openAccordions.filter( c => c !== category ); } else { openAccordions.push( category ); } this.setState( { openAccordion: openAccordions } ); } /** * Filter categories. * * @param Event object evt */ filterResults( evt ) { this.setState( { filterQuery: evt.target.value } ); } /** * Update firstLoad state. * * @param Booolean loaded */ setFirstLoad( loaded ) { this.setState( { firstLoad: !! loaded } ); } /** * Render the list of categories and the search input. */ render() { return (
); } } /** * The category search input. */ const ProductCategoryFilter = ( { filterResults } ) => { return (
); } /** * Fetch and build a tree of product categories. */ const ProductCategoryList = withAPIData( ( props ) => { return { categories: '/wc/v2/products/categories' }; } )( ( { categories, filterQuery, selectedCategories, checkboxChange, accordionToggle, openAccordion, firstLoad, setFirstLoad } ) => { if ( ! categories.data ) { return __( 'Loading' ); } if ( 0 === categories.data.length ) { return __( 'No categories found' ); } const handleCategoriesToCheck = ( evt, parent, categories ) => { let ids = getCategoryChildren( parent, categories ).map( category => { return category.id; } ); ids.push( parent.id ); checkboxChange( evt.target.checked, ids ); }; const getCategoryChildren = ( parent, categories ) => { let children = []; categories.filter( ( category ) => category.parent === parent.id ).forEach( function( category ) { children.push( category ); children.push( ...getCategoryChildren( category, categories ) ); } ); return children; }; const categoryHasChildren = ( parent, categories ) => { return !! getCategoryChildren( parent, categories ).length; }; const isIndeterminate = ( category, categories ) => { // Currect category selected? if ( selectedCategories.includes( category.id ) ) { return false; } // Has children? let children = getCategoryChildren( category, categories ).map( category => { return category.id; } ); for ( let child of children ) { if ( selectedCategories.includes( child ) ) { return true; } } return false; } const AccordionButton = ( { category, categories } ) => { let icon = 'arrow-down-alt2'; if ( openAccordion.includes( category.id ) ) { icon = 'arrow-up-alt2'; } let style = null; if ( ! categoryHasChildren( category, categories ) ) { style = { visibility: 'hidden', }; }; return ( ); }; const CategoryTree = ( { categories, parent } ) => { let filteredCategories = categories.filter( ( category ) => category.parent === parent ); if ( firstLoad && selectedCategories.length > 0 ) { categoriesData.filter( ( category ) => category.parent === 0 ).forEach( function( category ) { let children = getCategoryChildren( category, categoriesData ); for ( let child of children ) { if ( selectedCategories.includes( child.id ) && ! openAccordion.includes( category.id ) ) { accordionToggle( category.id ); break; } } } ); setFirstLoad( false ); } return ( filteredCategories.length > 0 ) && ( ); }; let categoriesData = categories.data; if ( '' !== filterQuery ) { categoriesData = categoriesData.filter( category => category.slug.includes( filterQuery.toLowerCase() ) ); } return (
); } );