const { __ } = wp.i18n;
const { Component } = wp.element;
const { Dashicon } = wp.components;
const { apiFetch } = wp;
/**
* Get the identifier for an attribute. The identifier can be used to determine
* the slug or the ID of the attribute.
*
* @param string slug The attribute slug.
* @param int|numeric string id The attribute ID.
*/
export function getAttributeIdentifier( slug, id ) {
return slug + ',' + id;
}
/**
* Get the attribute slug from an identifier.
*
* @param string identifier The attribute identifier.
* @return string
*/
export function getAttributeSlug( identifier ) {
return identifier.split( ',' )[ 0 ];
}
/**
* Get the attribute ID from an identifier.
*
* @param string identifier The attribute identifier.
* @return numeric string
*/
export function getAttributeID( identifier ) {
return identifier.split( ',' )[ 1 ];
}
/**
* When the display mode is 'Attribute' search for and select product attributes to pull products from.
*/
export class ProductsAttributeSelect extends Component {
/**
* Constructor.
*/
constructor( props ) {
super( props );
/**
* The first item in props.selected_display_setting is the attribute slug and id separated by a comma.
* This is to work around limitations in the API which sometimes requires a slug and sometimes an id.
* The rest of the elements in selected_display_setting are the term ids for any selected terms.
*/
this.state = {
selectedAttribute: props.selected_display_setting.length ? props.selected_display_setting[ 0 ] : '',
selectedTerms: props.selected_display_setting.length > 1 ? props.selected_display_setting.slice( 1 ) : [],
filterQuery: '',
};
this.setSelectedAttribute = this.setSelectedAttribute.bind( this );
this.addTerm = this.addTerm.bind( this );
this.removeTerm = this.removeTerm.bind( this );
}
/**
* Set the selected attribute.
*
* @param identifier string Attribute slug and id separated by a comma.
*/
setSelectedAttribute( identifier ) {
this.setState( {
selectedAttribute: identifier,
selectedTerms: [],
} );
this.props.update_display_setting_callback( [ identifier ] );
}
/**
* Add a term to the selected attribute's terms.
*
* @param id int Term id.
*/
addTerm( id ) {
const terms = this.state.selectedTerms;
terms.push( id );
this.setState( {
selectedTerms: terms,
} );
let displaySetting = [ this.state.selectedAttribute ];
displaySetting = displaySetting.concat( terms );
this.props.update_display_setting_callback( displaySetting );
}
/**
* Remove a term from the selected attribute's terms.
*
* @param id int Term id.
*/
removeTerm( id ) {
const newTerms = [];
for ( const termId of this.state.selectedTerms ) {
if ( termId !== id ) {
newTerms.push( termId );
}
}
this.setState( {
selectedTerms: newTerms,
} );
let displaySetting = [ this.state.selectedAttribute ];
displaySetting = displaySetting.concat( newTerms );
this.props.update_display_setting_callback( displaySetting );
}
/**
* Update the search results when typing in the attributes box.
*
* @param evt Event object
*/
updateFilter( evt ) {
this.setState( {
filterQuery: evt.target.value,
} );
}
/**
* Render the whole section.
*/
render() {
return (
);
}
}
/**
* Search area for filtering through the attributes list.
*/
const ProductAttributeFilter = ( props ) => {
return (
);
};
/**
* List of attributes.
*/
class ProductAttributeList extends Component {
/**
* Constructor
*/
constructor( props ) {
super( props );
this.state = {
attributes: [],
loaded: false,
query: '',
};
this.updatePreview = this.updatePreview.bind( this );
this.getQuery = this.getQuery.bind( this );
}
/**
* Get the preview when component is first loaded.
*/
componentDidMount() {
if ( this.getQuery() !== this.state.query ) {
this.updatePreview();
}
}
/**
* Update the preview when component is updated.
*/
componentDidUpdate() {
if ( this.getQuery() !== this.state.query && this.state.loaded ) {
this.updatePreview();
}
}
/**
* Get the endpoint for the current state of the component.
*
* @return string
*/
getQuery() {
const endpoint = '/wc-pb/v3/products/attributes';
return endpoint;
}
/**
* Update the preview with the latest settings.
*/
updatePreview() {
const self = this;
const query = this.getQuery();
self.setState( {
loaded: false,
} );
apiFetch( { path: query } ).then( ( attributes ) => {
self.setState( {
attributes: attributes,
loaded: true,
query: query,
} );
} );
}
/**
* Render.
*/
render() {
const { selectedAttribute, filterQuery, selectedTerms, setSelectedAttribute, addTerm, removeTerm } = this.props;
if ( ! this.state.loaded ) {
return (