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(