diff --git a/plugins/woocommerce-admin/client/analytics/settings/config.js b/plugins/woocommerce-admin/client/analytics/settings/config.js
index 440fb0bc6d3..dbe92100b8f 100644
--- a/plugins/woocommerce-admin/client/analytics/settings/config.js
+++ b/plugins/woocommerce-admin/client/analytics/settings/config.js
@@ -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();
+ } );
+ },
+ },
] );
diff --git a/plugins/woocommerce-admin/client/analytics/settings/index.js b/plugins/woocommerce-admin/client/analytics/settings/index.js
index a26311710b0..fafb215d736 100644
--- a/plugins/woocommerce-admin/client/analytics/settings/index.js
+++ b/plugins/woocommerce-admin/client/analytics/settings/index.js
@@ -124,13 +124,9 @@ class Settings extends Component {
{ analyticsSettings.map( setting => (
) ) }
diff --git a/plugins/woocommerce-admin/client/analytics/settings/setting.js b/plugins/woocommerce-admin/client/analytics/settings/setting.js
index ef7b96286ab..d22104c8282 100644
--- a/plugins/woocommerce-admin/client/analytics/settings/setting.js
+++ b/plugins/woocommerce-admin/client/analytics/settings/setting.js
@@ -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 (
+
+ );
case 'text':
default:
return (
-
+
);
}
};
+ 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 }
@@ -75,7 +121,7 @@ class Setting extends Component {
{ label }
-
+
{ this.renderInput() }
{ helpText && { helpText } }
@@ -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 );
diff --git a/plugins/woocommerce-admin/client/analytics/settings/setting.scss b/plugins/woocommerce-admin/client/analytics/settings/setting.scss
index 98440fdcbfb..6a9e1b6c2f1 100644
--- a/plugins/woocommerce-admin/client/analytics/settings/setting.scss
+++ b/plugins/woocommerce-admin/client/analytics/settings/setting.scss
@@ -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 {
diff --git a/plugins/woocommerce-admin/includes/class-wc-admin-reports-sync.php b/plugins/woocommerce-admin/includes/class-wc-admin-reports-sync.php
index 7c9b0a70525..a816c2b6a5a 100644
--- a/plugins/woocommerce-admin/includes/class-wc-admin-reports-sync.php
+++ b/plugins/woocommerce-admin/includes/class-wc-admin-reports-sync.php
@@ -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(