* Add button input type to analytics settings

* Add callback prop and disabled state to setting

* Add rebuild tool to settings page

* Re-enable setting if error is caught

* Remove rebuild tool from system tools page

* Move report build success message to API response

* Add back key for settings map

* Fix misspelled option group classname

* Conditionally add rebuild tool to non-wc-status page instead of removal hook
This commit is contained in:
Joshua T Flowers 2019-03-06 13:32:05 +08:00 committed by GitHub
parent 3d15392ecd
commit 4d80cad52e
5 changed files with 113 additions and 14 deletions

View File

@ -3,6 +3,7 @@
* External dependencies
*/
import { __, sprintf } from '@wordpress/i18n';
import apiFetch from '@wordpress/api-fetch';
import { applyFilters } from '@wordpress/hooks';
import interpolateComponents from 'interpolate-components';
@ -88,4 +89,36 @@ export const analyticsSettings = applyFilters( SETTINGS_FILTER, [
initialValue: wcSettings.wcAdminSettings.woocommerce_actionable_order_statuses || [],
defaultValue: [ 'processing', 'on-hold' ],
},
{
name: 'woocommerce_rebuild_reports_data',
label: __( 'Rebuild reports data:', 'wc-admin' ),
inputType: 'button',
inputText: __( 'Rebuild reports', 'wc-admin' ),
helpText: __(
'This tool will rebuild all of the information used by the reports. ' +
'Data will be processed in the background and may take some time depending on the size of your store.',
'wc-admin'
),
callback: ( resolve, reject, addNotice ) => {
const errorMessage = __( 'There was a problem rebuilding your report data.', 'wc-admin' );
apiFetch( { path: '/wc/v3/system_status/tools/rebuild_stats', method: 'PUT' } )
.then( response => {
if ( response.success ) {
addNotice( { status: 'success', message: response.message } );
// @todo This should be changed to detect when the lookup table population is complete.
setTimeout( () => resolve(), 300000 );
} else {
addNotice( { status: 'error', message: errorMessage } );
reject();
}
} )
.catch( error => {
if ( error && error.message ) {
addNotice( { status: 'error', message: error.message } );
}
reject();
} );
},
},
] );

View File

@ -124,13 +124,9 @@ class Settings extends Component {
{ analyticsSettings.map( setting => (
<Setting
handleChange={ this.handleInputChange }
helpText={ setting.helpText }
inputType={ setting.inputType }
key={ setting.name }
label={ setting.label }
name={ setting.name }
options={ setting.options }
value={ this.state.settings[ setting.name ] }
key={ setting.name }
{ ...setting }
/>
) ) }
<div className="woocommerce-settings__actions">

View File

@ -2,9 +2,12 @@
/**
* External dependencies
*/
import { Button } from '@wordpress/components';
import { Component } from '@wordpress/element';
import { compose } from '@wordpress/compose';
import PropTypes from 'prop-types';
import { uniqueId } from 'lodash';
import { withDispatch } from '@wordpress/data';
/**
* Internal dependencies
@ -12,8 +15,16 @@ import { uniqueId } from 'lodash';
import './setting.scss';
class Setting extends Component {
constructor( props ) {
super( props );
this.state = {
disabled: false,
};
}
renderInput = () => {
const { handleChange, name, inputType, options, value } = this.props;
const { handleChange, name, inputText, inputType, options, value } = this.props;
const { disabled } = this.state;
const id = uniqueId( name );
switch ( inputType ) {
@ -37,16 +48,50 @@ class Setting extends Component {
);
case 'checkbox':
return this.renderCheckboxOptions( options );
case 'button':
return (
<Button isDefault onClick={ this.handleInputCallback } disabled={ disabled }>
{ inputText }
</Button>
);
case 'text':
default:
return (
<input id={ id } type="text" name={ name } onChange={ handleChange } value={ value } />
<input
id={ id }
type="text"
name={ name }
onChange={ handleChange }
value={ value }
placeholder={ inputText }
disabled={ disabled }
/>
);
}
};
handleInputCallback = () => {
const { addNotice, callback } = this.props;
if ( 'function' !== typeof callback ) {
return;
}
return new Promise( ( resolve, reject ) => {
this.setState( { disabled: true } );
callback( resolve, reject, addNotice );
} )
.then( () => {
this.setState( { disabled: false } );
} )
.catch( () => {
this.setState( { disabled: false } );
} );
};
renderCheckboxOptions( options ) {
const { handleChange, name, value } = this.props;
const { disabled } = this.state;
return options.map( option => {
const id = uniqueId( name + '-' + option.value );
@ -60,6 +105,7 @@ class Setting extends Component {
aria-label={ option.description }
checked={ value && value.includes( option.value ) }
value={ option.value }
disabled={ disabled }
/>
{ option.label }
</label>
@ -75,7 +121,7 @@ class Setting extends Component {
<div className="woocommerce-setting__label" id={ name + '-label' }>
{ label }
</div>
<div className="woocommerce-setting__options">
<div className="woocommerce-setting__input">
{ this.renderInput() }
{ helpText && <span className="woocommerce-setting__help">{ helpText }</span> }
</div>
@ -85,6 +131,10 @@ class Setting extends Component {
}
Setting.propTypes = {
/**
* A callback that is fired after actionable items, such as buttons.
*/
callback: PropTypes.func,
/**
* Function assigned to the onChange of all inputs.
*/
@ -93,10 +143,14 @@ Setting.propTypes = {
* Optional help text displayed underneath the setting.
*/
helpText: PropTypes.oneOfType( [ PropTypes.string, PropTypes.array ] ),
/**
* Text used as placeholder or button text in the input area.
*/
inputText: PropTypes.string,
/**
* Type of input to use; defaults to a text input.
*/
inputType: PropTypes.oneOf( [ 'checkbox', 'checkboxGroup', 'text' ] ),
inputType: PropTypes.oneOf( [ 'button', 'checkbox', 'checkboxGroup', 'text' ] ),
/**
* Label used for describing the setting.
*/
@ -138,4 +192,9 @@ Setting.propTypes = {
value: PropTypes.oneOfType( [ PropTypes.string, PropTypes.array ] ),
};
export default Setting;
export default compose(
withDispatch( dispatch => {
const { addNotice } = dispatch( 'wc-admin' );
return { addNotice };
} )
)( Setting );

View File

@ -18,7 +18,7 @@
}
}
.woocommerce-setting__options {
.woocommerce-setting__input {
display: flex;
flex-direction: column;
@include breakpoint( '>1280px' ) {
@ -35,6 +35,11 @@
input[type='checkbox'] {
margin-right: $gap-small;
}
button {
margin-bottom: $gap-small;
align-self: flex-start;
}
}
.woocommerce-setting__options-group-label {

View File

@ -79,7 +79,7 @@ class WC_Admin_Reports_Sync {
* Hook in sync methods.
*/
public static function init() {
// Add report regeneration to tools menu.
// Add report regeneration to tools REST API.
add_filter( 'woocommerce_debug_tools', array( __CLASS__, 'add_regenerate_tool' ) );
// Initialize syncing hooks.
@ -103,6 +103,8 @@ class WC_Admin_Reports_Sync {
self::customer_lookup_batch_init();
// Queue orders lookup to occur after customers lookup generation is done.
self::queue_dependent_action( self::ORDERS_LOOKUP_BATCH_INIT, array(), self::CUSTOMERS_BATCH_ACTION );
return __( 'Report table data is being rebuilt. Please allow some time for data to fully populate.', 'wc-admin' );
}
/**
@ -123,12 +125,16 @@ class WC_Admin_Reports_Sync {
}
/**
* Adds regenerate tool.
* Adds regenerate tool to WC system status tools API.
*
* @param array $tools List of tools.
* @return array
*/
public static function add_regenerate_tool( $tools ) {
if ( isset( $_GET['page'] ) && 'wc-status' === $_GET['page'] ) { // phpcs:ignore WordPress.Security.NonceVerification
return $tools;
}
return array_merge(
$tools,
array(