2019-01-31 01:04:11 +00:00
|
|
|
/**
|
|
|
|
* External dependencies
|
|
|
|
*/
|
2020-06-15 22:50:22 +00:00
|
|
|
import { Button, CheckboxControl } from '@wordpress/components';
|
2019-01-31 01:04:11 +00:00
|
|
|
import { Component } from '@wordpress/element';
|
2019-03-06 05:32:05 +00:00
|
|
|
import { compose } from '@wordpress/compose';
|
2019-01-31 01:04:11 +00:00
|
|
|
import PropTypes from 'prop-types';
|
|
|
|
import { uniqueId } from 'lodash';
|
2019-03-06 05:32:05 +00:00
|
|
|
import { withDispatch } from '@wordpress/data';
|
2019-01-31 01:04:11 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Internal dependencies
|
|
|
|
*/
|
|
|
|
import './setting.scss';
|
|
|
|
|
|
|
|
class Setting extends Component {
|
2019-03-06 05:32:05 +00:00
|
|
|
constructor( props ) {
|
|
|
|
super( props );
|
|
|
|
this.state = {
|
|
|
|
disabled: false,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2019-01-31 01:04:11 +00:00
|
|
|
renderInput = () => {
|
2020-02-14 02:23:21 +00:00
|
|
|
const {
|
|
|
|
handleChange,
|
|
|
|
name,
|
|
|
|
inputText,
|
|
|
|
inputType,
|
|
|
|
options,
|
|
|
|
value,
|
|
|
|
component,
|
|
|
|
} = this.props;
|
2019-03-06 05:32:05 +00:00
|
|
|
const { disabled } = this.state;
|
2019-01-31 01:04:11 +00:00
|
|
|
|
|
|
|
switch ( inputType ) {
|
|
|
|
case 'checkboxGroup':
|
|
|
|
return options.map(
|
2020-02-14 02:23:21 +00:00
|
|
|
( optionGroup ) =>
|
2019-01-31 01:04:11 +00:00
|
|
|
optionGroup.options.length > 0 && (
|
|
|
|
<div
|
|
|
|
className="woocommerce-setting__options-group"
|
|
|
|
key={ optionGroup.key }
|
|
|
|
aria-labelledby={ name + '-label' }
|
|
|
|
>
|
|
|
|
{ optionGroup.label && (
|
|
|
|
<span className="woocommerce-setting__options-group-label">
|
|
|
|
{ optionGroup.label }
|
|
|
|
</span>
|
|
|
|
) }
|
2020-02-14 02:23:21 +00:00
|
|
|
{ this.renderCheckboxOptions(
|
|
|
|
optionGroup.options
|
|
|
|
) }
|
2019-01-31 01:04:11 +00:00
|
|
|
</div>
|
|
|
|
)
|
|
|
|
);
|
|
|
|
case 'checkbox':
|
|
|
|
return this.renderCheckboxOptions( options );
|
2019-03-06 05:32:05 +00:00
|
|
|
case 'button':
|
|
|
|
return (
|
2020-02-14 02:23:21 +00:00
|
|
|
<Button
|
2020-06-11 19:22:20 +00:00
|
|
|
isSecondary
|
2020-02-14 02:23:21 +00:00
|
|
|
onClick={ this.handleInputCallback }
|
|
|
|
disabled={ disabled }
|
|
|
|
>
|
2019-03-06 05:32:05 +00:00
|
|
|
{ inputText }
|
|
|
|
</Button>
|
|
|
|
);
|
2019-05-22 21:43:04 +00:00
|
|
|
case 'component':
|
|
|
|
const SettingComponent = component;
|
2020-02-14 02:23:21 +00:00
|
|
|
return (
|
|
|
|
<SettingComponent
|
|
|
|
value={ value }
|
|
|
|
onChange={ handleChange }
|
|
|
|
{ ...this.props }
|
|
|
|
/>
|
|
|
|
);
|
2019-01-31 01:04:11 +00:00
|
|
|
case 'text':
|
|
|
|
default:
|
2020-02-14 02:23:21 +00:00
|
|
|
const id = uniqueId( name );
|
2019-01-31 01:04:11 +00:00
|
|
|
return (
|
2019-03-06 05:32:05 +00:00
|
|
|
<input
|
|
|
|
id={ id }
|
|
|
|
type="text"
|
|
|
|
name={ name }
|
|
|
|
onChange={ handleChange }
|
|
|
|
value={ value }
|
|
|
|
placeholder={ inputText }
|
|
|
|
disabled={ disabled }
|
|
|
|
/>
|
2019-01-31 01:04:11 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-03-06 05:32:05 +00:00
|
|
|
handleInputCallback = () => {
|
2019-07-23 03:26:46 +00:00
|
|
|
const { createNotice, callback } = this.props;
|
2019-03-06 05:32:05 +00:00
|
|
|
|
2020-02-14 02:23:21 +00:00
|
|
|
if ( typeof callback !== 'function' ) {
|
2019-03-06 05:32:05 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
return new Promise( ( resolve, reject ) => {
|
|
|
|
this.setState( { disabled: true } );
|
2019-07-23 03:26:46 +00:00
|
|
|
callback( resolve, reject, createNotice );
|
2019-03-06 05:32:05 +00:00
|
|
|
} )
|
|
|
|
.then( () => {
|
|
|
|
this.setState( { disabled: false } );
|
|
|
|
} )
|
|
|
|
.catch( () => {
|
|
|
|
this.setState( { disabled: false } );
|
|
|
|
} );
|
|
|
|
};
|
|
|
|
|
2019-01-31 01:04:11 +00:00
|
|
|
renderCheckboxOptions( options ) {
|
|
|
|
const { handleChange, name, value } = this.props;
|
2019-03-06 05:32:05 +00:00
|
|
|
const { disabled } = this.state;
|
2019-01-31 01:04:11 +00:00
|
|
|
|
2020-02-14 02:23:21 +00:00
|
|
|
return options.map( ( option ) => {
|
2019-01-31 01:04:11 +00:00
|
|
|
return (
|
2020-06-15 22:50:22 +00:00
|
|
|
<CheckboxControl
|
|
|
|
key={ name + '-' + option.value }
|
|
|
|
label={ option.label }
|
|
|
|
name={ name }
|
|
|
|
checked={ value && value.includes( option.value ) }
|
|
|
|
onChange={ ( checked ) =>
|
|
|
|
handleChange( {
|
|
|
|
target: {
|
|
|
|
checked,
|
|
|
|
name,
|
|
|
|
type: 'checkbox',
|
|
|
|
value: option.value,
|
|
|
|
},
|
|
|
|
} )
|
|
|
|
}
|
|
|
|
disabled={ disabled }
|
|
|
|
/>
|
2019-01-31 01:04:11 +00:00
|
|
|
);
|
|
|
|
} );
|
|
|
|
}
|
|
|
|
|
|
|
|
render() {
|
|
|
|
const { helpText, label, name } = this.props;
|
|
|
|
|
|
|
|
return (
|
|
|
|
<div className="woocommerce-setting">
|
2020-02-14 02:23:21 +00:00
|
|
|
<div
|
|
|
|
className="woocommerce-setting__label"
|
|
|
|
id={ name + '-label' }
|
|
|
|
>
|
2019-01-31 01:04:11 +00:00
|
|
|
{ label }
|
|
|
|
</div>
|
2019-03-06 05:32:05 +00:00
|
|
|
<div className="woocommerce-setting__input">
|
2019-01-31 01:04:11 +00:00
|
|
|
{ this.renderInput() }
|
2020-02-14 02:23:21 +00:00
|
|
|
{ helpText && (
|
|
|
|
<span className="woocommerce-setting__help">
|
|
|
|
{ helpText }
|
|
|
|
</span>
|
|
|
|
) }
|
2019-01-31 01:04:11 +00:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Setting.propTypes = {
|
2019-03-06 05:32:05 +00:00
|
|
|
/**
|
|
|
|
* A callback that is fired after actionable items, such as buttons.
|
|
|
|
*/
|
|
|
|
callback: PropTypes.func,
|
2019-01-31 01:04:11 +00:00
|
|
|
/**
|
|
|
|
* Function assigned to the onChange of all inputs.
|
|
|
|
*/
|
|
|
|
handleChange: PropTypes.func.isRequired,
|
|
|
|
/**
|
|
|
|
* Optional help text displayed underneath the setting.
|
|
|
|
*/
|
|
|
|
helpText: PropTypes.oneOfType( [ PropTypes.string, PropTypes.array ] ),
|
2019-03-06 05:32:05 +00:00
|
|
|
/**
|
|
|
|
* Text used as placeholder or button text in the input area.
|
|
|
|
*/
|
|
|
|
inputText: PropTypes.string,
|
2019-01-31 01:04:11 +00:00
|
|
|
/**
|
|
|
|
* Type of input to use; defaults to a text input.
|
|
|
|
*/
|
2020-02-14 02:23:21 +00:00
|
|
|
inputType: PropTypes.oneOf( [
|
|
|
|
'button',
|
|
|
|
'checkbox',
|
|
|
|
'checkboxGroup',
|
|
|
|
'text',
|
|
|
|
'component',
|
|
|
|
] ),
|
2019-01-31 01:04:11 +00:00
|
|
|
/**
|
|
|
|
* Label used for describing the setting.
|
|
|
|
*/
|
|
|
|
label: PropTypes.string.isRequired,
|
|
|
|
/**
|
|
|
|
* Setting slug applied to input names.
|
|
|
|
*/
|
|
|
|
name: PropTypes.string.isRequired,
|
|
|
|
/**
|
|
|
|
* Array of options used for when the `inputType` allows multiple selections.
|
|
|
|
*/
|
|
|
|
options: PropTypes.arrayOf(
|
|
|
|
PropTypes.shape( {
|
|
|
|
/**
|
|
|
|
* Input value for this option.
|
|
|
|
*/
|
|
|
|
value: PropTypes.string,
|
|
|
|
/**
|
|
|
|
* Label for this option or above a group for a group `inputType`.
|
|
|
|
*/
|
|
|
|
label: PropTypes.string,
|
|
|
|
/**
|
|
|
|
* Description used for screen readers.
|
|
|
|
*/
|
|
|
|
description: PropTypes.string,
|
|
|
|
/**
|
|
|
|
* Key used for a group `inputType`.
|
|
|
|
*/
|
|
|
|
key: PropTypes.string,
|
|
|
|
/**
|
|
|
|
* Nested options for a group `inputType`.
|
|
|
|
*/
|
|
|
|
options: PropTypes.array,
|
|
|
|
} )
|
|
|
|
),
|
|
|
|
/**
|
|
|
|
* The string value used for the input or array of items if the input allows multiselection.
|
|
|
|
*/
|
|
|
|
value: PropTypes.oneOfType( [ PropTypes.string, PropTypes.array ] ),
|
|
|
|
};
|
|
|
|
|
2019-03-06 05:32:05 +00:00
|
|
|
export default compose(
|
2020-02-14 02:23:21 +00:00
|
|
|
withDispatch( ( dispatch ) => {
|
2019-07-23 03:26:46 +00:00
|
|
|
const { createNotice } = dispatch( 'core/notices' );
|
|
|
|
return { createNotice };
|
2019-03-06 05:32:05 +00:00
|
|
|
} )
|
|
|
|
)( Setting );
|