From f8bc173cfbae4961a72ccbd7dd15ba07784bc19e Mon Sep 17 00:00:00 2001 From: Jeff Stieler Date: Tue, 31 Mar 2020 09:08:40 -0600 Subject: [PATCH] Only query requested stat totals in reports. (https://github.com/woocommerce/woocommerce-admin/pull/4009) * Pass specified totals/intervals fields parameter to the Order Stats Query. * Only request stats used in render for report summaries and charts. Implement Orders as an example. * Specify stats fields for all report requests. * Add 'fields' parameter handling to all stats endpoint controllers. * Reduce stats fields requested by dashboard charts. --- .../components/report-chart/index.js | 5 ++ .../components/report-summary/index.js | 4 ++ .../components/report-table/index.js | 6 +++ .../analytics/report/categories/index.js | 1 + .../analytics/report/categories/table.js | 5 ++ .../client/analytics/report/coupons/index.js | 1 + .../client/analytics/report/coupons/table.js | 5 ++ .../analytics/report/customers/table.js | 6 +++ .../analytics/report/downloads/index.js | 1 + .../analytics/report/downloads/table.js | 1 + .../client/analytics/report/orders/index.js | 1 + .../client/analytics/report/orders/table.js | 9 ++++ .../client/analytics/report/products/index.js | 1 + .../report/products/table-variations.js | 6 +++ .../client/analytics/report/products/table.js | 6 +++ .../client/analytics/report/revenue/index.js | 1 + .../client/analytics/report/revenue/table.js | 10 ++++ .../client/analytics/report/stock/table.js | 7 +++ .../client/analytics/report/taxes/index.js | 1 + .../client/analytics/report/taxes/table.js | 7 +++ .../dashboard/dashboard-charts/block.js | 28 +++++----- .../dashboard/dashboard-charts/index.js | 52 +++++++++++++------ .../client/wc-api/reports/utils.js | 5 +- .../API/Reports/Coupons/Stats/Controller.php | 7 +++ .../Reports/Customers/Stats/Controller.php | 7 +++ .../Reports/Downloads/Stats/Controller.php | 7 +++ .../API/Reports/Orders/Stats/Controller.php | 24 +++++---- .../API/Reports/Products/Stats/Controller.php | 6 +++ .../API/Reports/Revenue/Stats/Controller.php | 1 + .../API/Reports/Taxes/Stats/Controller.php | 7 +++ 30 files changed, 189 insertions(+), 39 deletions(-) diff --git a/plugins/woocommerce-admin/client/analytics/components/report-chart/index.js b/plugins/woocommerce-admin/client/analytics/components/report-chart/index.js index f971db14cb1..5c1a119f82b 100644 --- a/plugins/woocommerce-admin/client/analytics/components/report-chart/index.js +++ b/plugins/woocommerce-admin/client/analytics/components/report-chart/index.js @@ -330,6 +330,7 @@ ReportChart.defaultProps = { export default compose( withSelect( ( select, props ) => { const { + charts, endpoint, filters, isRequesting, @@ -366,6 +367,8 @@ export default compose( }; } + const fields = charts && charts.map( chart => chart.key ); + const primaryData = getReportChartData( { endpoint, dataType: 'primary', @@ -375,6 +378,7 @@ export default compose( filters, advancedFilters, defaultDateRange, + fields, } ); if ( chartMode === 'item-comparison' ) { @@ -393,6 +397,7 @@ export default compose( filters, advancedFilters, defaultDateRange, + fields, } ); return { ...newProps, diff --git a/plugins/woocommerce-admin/client/analytics/components/report-summary/index.js b/plugins/woocommerce-admin/client/analytics/components/report-summary/index.js index f3bf2177fb2..f9dff86b3cf 100644 --- a/plugins/woocommerce-admin/client/analytics/components/report-summary/index.js +++ b/plugins/woocommerce-admin/client/analytics/components/report-summary/index.js @@ -195,6 +195,7 @@ ReportSummary.defaultProps = { export default compose( withSelect( ( select, props ) => { const { + charts, endpoint, isRequesting, limitProperties, @@ -218,6 +219,8 @@ export default compose( }; } + const fields = charts && charts.map( chart => chart.key ); + const { woocommerce_default_date_range: defaultDateRange } = select( SETTINGS_STORE_NAME ).getSetting( 'wc_admin', 'wcAdminSettings' ); @@ -230,6 +233,7 @@ export default compose( filters, advancedFilters, defaultDateRange, + fields, } ); return { diff --git a/plugins/woocommerce-admin/client/analytics/components/report-table/index.js b/plugins/woocommerce-admin/client/analytics/components/report-table/index.js index e5b47925bc0..93c7a4dc96c 100644 --- a/plugins/woocommerce-admin/client/analytics/components/report-table/index.js +++ b/plugins/woocommerce-admin/client/analytics/components/report-table/index.js @@ -552,6 +552,10 @@ ReportTable.propTypes = { * The string to use as a query parameter when searching row items. */ searchBy: PropTypes.string, + /** + * List of fields used for summary numbers. (Reduces queries) + */ + summaryFields: PropTypes.arrayOf( PropTypes.string ), /** * Table data of that report. If it's not provided, it will be automatically * loaded via the provided `endpoint`. @@ -596,6 +600,7 @@ export default compose( columnPrefsKey, filters, advancedFilters, + summaryFields, } = props; let userPrefColumns = []; @@ -638,6 +643,7 @@ export default compose( advancedFilters, tableQuery, defaultDateRange, + fields: summaryFields, } ) : {}; const queriedTableData = diff --git a/plugins/woocommerce-admin/client/analytics/report/categories/index.js b/plugins/woocommerce-admin/client/analytics/report/categories/index.js index ac1e0a49fdb..688454ac55e 100644 --- a/plugins/woocommerce-admin/client/analytics/report/categories/index.js +++ b/plugins/woocommerce-admin/client/analytics/report/categories/index.js @@ -80,6 +80,7 @@ export default class CategoriesReport extends Component { report="categories" /> { - const { charts } = this.props; + const { selectedChart } = this.props; - if ( ! charts || ! charts.length ) { - return null; - } - - getHistory().push( this.getChartPath( charts[ 0 ] ) ); + getHistory().push( this.getChartPath( selectedChart ) ); }; getChartPath( chart ) { @@ -42,9 +38,15 @@ class ChartBlock extends Component { } render() { - const { charts, endpoint, path, query } = this.props; + const { + charts, + endpoint, + path, + query, + selectedChart, + } = this.props; - if ( ! charts || ! charts.length ) { + if ( ! selectedChart ) { return null; } @@ -56,27 +58,28 @@ class ChartBlock extends Component { > { /* translators: %s is the chart type */ sprintf( __( '%s Report', 'woocommerce-admin' ), - charts[ 0 ].label + selectedChart.label ) } @@ -90,6 +93,7 @@ ChartBlock.propTypes = { endpoint: PropTypes.string.isRequired, path: PropTypes.string.isRequired, query: PropTypes.object.isRequired, + selectedChart: PropTypes.object.isRequired, }; export default ChartBlock; diff --git a/plugins/woocommerce-admin/client/dashboard/dashboard-charts/index.js b/plugins/woocommerce-admin/client/dashboard/dashboard-charts/index.js index da2f85f8fcd..c4c6b35f5e2 100644 --- a/plugins/woocommerce-admin/client/dashboard/dashboard-charts/index.js +++ b/plugins/woocommerce-admin/client/dashboard/dashboard-charts/index.js @@ -164,8 +164,42 @@ class DashboardCharts extends Component { } ); }; + renderChartBlocks( query ) { + const { hiddenBlocks, path } = this.props; + + // Reduce the API response to only the necessary stat fields + // by supplying all charts common to each endpoint. + const chartsByEndpoint = uniqCharts.reduce( ( byEndpoint, chart ) => { + if ( typeof byEndpoint[ chart.endpoint ] === 'undefined' ) { + byEndpoint[ chart.endpoint ] = []; + } + byEndpoint[ chart.endpoint ].push( chart ); + + return byEndpoint; + }, {} ); + + return ( +
+ { uniqCharts.map( ( chart ) => { + return hiddenBlocks.includes( + chart.endpoint + '_' + chart.key + ) ? null : ( + + ); + } ) } +
+ ); + } + render() { - const { hiddenBlocks, path, title } = this.props; + const { title } = this.props; const { chartType, interval } = this.state; const query = { ...this.props.query, chartType, interval }; return ( @@ -218,21 +252,7 @@ class DashboardCharts extends Component { /> -
- { uniqCharts.map( ( chart ) => { - return hiddenBlocks.includes( - chart.endpoint + '_' + chart.key - ) ? null : ( - - ); - } ) } -
+ { this.renderChartBlocks( query ) } ); diff --git a/plugins/woocommerce-admin/client/wc-api/reports/utils.js b/plugins/woocommerce-admin/client/wc-api/reports/utils.js index 5bf6715f2f3..4c98807c4dc 100644 --- a/plugins/woocommerce-admin/client/wc-api/reports/utils.js +++ b/plugins/woocommerce-admin/client/wc-api/reports/utils.js @@ -197,7 +197,7 @@ export function isReportDataEmpty( report, endpoint ) { * @return {Object} data request query parameters. */ function getRequestQuery( options ) { - const { endpoint, dataType, query } = options; + const { endpoint, dataType, query, fields } = options; const datesFromQuery = getCurrentDates( query, options.defaultDateRange ); const interval = getIntervalForQuery( query ); const filterQuery = getFilterQuery( options ); @@ -205,7 +205,7 @@ function getRequestQuery( options ) { const noIntervals = includes( noIntervalEndpoints, endpoint ); return noIntervals - ? { ...filterQuery } + ? { ...filterQuery, fields } : { order: 'asc', interval, @@ -216,6 +216,7 @@ function getRequestQuery( options ) { ), before: appendTimestamp( end, 'end' ), segmentby: query.segmentby, + fields, ...filterQuery, }; } diff --git a/plugins/woocommerce-admin/src/API/Reports/Coupons/Stats/Controller.php b/plugins/woocommerce-admin/src/API/Reports/Coupons/Stats/Controller.php index fe4c73b4928..79993e31cc9 100644 --- a/plugins/woocommerce-admin/src/API/Reports/Coupons/Stats/Controller.php +++ b/plugins/woocommerce-admin/src/API/Reports/Coupons/Stats/Controller.php @@ -53,6 +53,7 @@ class Controller extends \WC_REST_Reports_Controller { $args['order'] = $request['order']; $args['coupons'] = (array) $request['coupons']; $args['segmentby'] = $request['segmentby']; + $args['fields'] = $request['fields']; return $args; } @@ -352,6 +353,12 @@ class Controller extends \WC_REST_Reports_Controller { ), 'validate_callback' => 'rest_validate_request_arg', ); + $params['fields'] = array( + 'description' => __( 'Limit stats fields to the specified items.', 'woocommerce-admin' ), + 'type' => 'array', + 'sanitize_callback' => 'wp_parse_slug_list', + 'validate_callback' => 'rest_validate_request_arg', + ); return $params; } diff --git a/plugins/woocommerce-admin/src/API/Reports/Customers/Stats/Controller.php b/plugins/woocommerce-admin/src/API/Reports/Customers/Stats/Controller.php index 8dd06ca977e..02ffdfc6a5e 100644 --- a/plugins/woocommerce-admin/src/API/Reports/Customers/Stats/Controller.php +++ b/plugins/woocommerce-admin/src/API/Reports/Customers/Stats/Controller.php @@ -65,6 +65,7 @@ class Controller extends \WC_REST_Reports_Controller { $args['last_order_before'] = $request['last_order_before']; $args['last_order_after'] = $request['last_order_after']; $args['customers'] = $request['customers']; + $args['fields'] = $request['fields']; $between_params_numeric = array( 'orders_count', 'total_spend', 'avg_order_value' ); $normalized_params_numeric = TimeInterval::normalize_between_params( $request, $between_params_numeric, false ); @@ -362,6 +363,12 @@ class Controller extends \WC_REST_Reports_Controller { 'type' => 'integer', ), ); + $params['fields'] = array( + 'description' => __( 'Limit stats fields to the specified items.', 'woocommerce-admin' ), + 'type' => 'array', + 'sanitize_callback' => 'wp_parse_slug_list', + 'validate_callback' => 'rest_validate_request_arg', + ); return $params; } diff --git a/plugins/woocommerce-admin/src/API/Reports/Downloads/Stats/Controller.php b/plugins/woocommerce-admin/src/API/Reports/Downloads/Stats/Controller.php index 4e0e30c27b7..d5610a8df93 100644 --- a/plugins/woocommerce-admin/src/API/Reports/Downloads/Stats/Controller.php +++ b/plugins/woocommerce-admin/src/API/Reports/Downloads/Stats/Controller.php @@ -57,6 +57,7 @@ class Controller extends \WC_REST_Reports_Controller { $args['order_excludes'] = (array) $request['order_excludes']; $args['ip_address_includes'] = (array) $request['ip_address_includes']; $args['ip_address_excludes'] = (array) $request['ip_address_excludes']; + $args['fields'] = $request['fields']; return $args; } @@ -369,6 +370,12 @@ class Controller extends \WC_REST_Reports_Controller { 'type' => 'string', ), ); + $params['fields'] = array( + 'description' => __( 'Limit stats fields to the specified items.', 'woocommerce-admin' ), + 'type' => 'array', + 'sanitize_callback' => 'wp_parse_slug_list', + 'validate_callback' => 'rest_validate_request_arg', + ); return $params; } diff --git a/plugins/woocommerce-admin/src/API/Reports/Orders/Stats/Controller.php b/plugins/woocommerce-admin/src/API/Reports/Orders/Stats/Controller.php index e27a176657d..eb6398cdfa7 100644 --- a/plugins/woocommerce-admin/src/API/Reports/Orders/Stats/Controller.php +++ b/plugins/woocommerce-admin/src/API/Reports/Orders/Stats/Controller.php @@ -42,15 +42,15 @@ class Controller extends \Automattic\WooCommerce\Admin\API\Reports\Controller { * @return array */ protected function prepare_reports_query( $request ) { - $args = array(); - $args['before'] = $request['before']; - $args['after'] = $request['after']; - $args['interval'] = $request['interval']; - $args['page'] = $request['page']; - $args['per_page'] = $request['per_page']; - $args['orderby'] = $request['orderby']; - $args['order'] = $request['order']; - + $args = array(); + $args['before'] = $request['before']; + $args['after'] = $request['after']; + $args['interval'] = $request['interval']; + $args['page'] = $request['page']; + $args['per_page'] = $request['per_page']; + $args['orderby'] = $request['orderby']; + $args['order'] = $request['order']; + $args['fields'] = $request['fields']; $args['match'] = $request['match']; $args['status_is'] = (array) $request['status_is']; $args['status_is_not'] = (array) $request['status_is_not']; @@ -513,6 +513,12 @@ class Controller extends \Automattic\WooCommerce\Admin\API\Reports\Controller { ), 'validate_callback' => 'rest_validate_request_arg', ); + $params['fields'] = array( + 'description' => __( 'Limit stats fields to the specified items.', 'woocommerce-admin' ), + 'type' => 'array', + 'sanitize_callback' => 'wp_parse_slug_list', + 'validate_callback' => 'rest_validate_request_arg', + ); return $params; } diff --git a/plugins/woocommerce-admin/src/API/Reports/Products/Stats/Controller.php b/plugins/woocommerce-admin/src/API/Reports/Products/Stats/Controller.php index 25db8ed3833..549184488e5 100644 --- a/plugins/woocommerce-admin/src/API/Reports/Products/Stats/Controller.php +++ b/plugins/woocommerce-admin/src/API/Reports/Products/Stats/Controller.php @@ -415,6 +415,12 @@ class Controller extends \WC_REST_Reports_Controller { ), 'validate_callback' => 'rest_validate_request_arg', ); + $params['fields'] = array( + 'description' => __( 'Limit stats fields to the specified items.', 'woocommerce-admin' ), + 'type' => 'array', + 'sanitize_callback' => 'wp_parse_slug_list', + 'validate_callback' => 'rest_validate_request_arg', + ); return $params; } diff --git a/plugins/woocommerce-admin/src/API/Reports/Revenue/Stats/Controller.php b/plugins/woocommerce-admin/src/API/Reports/Revenue/Stats/Controller.php index b06183fa74e..5ad23e2707a 100644 --- a/plugins/woocommerce-admin/src/API/Reports/Revenue/Stats/Controller.php +++ b/plugins/woocommerce-admin/src/API/Reports/Revenue/Stats/Controller.php @@ -58,6 +58,7 @@ class Controller extends \WC_REST_Reports_Controller implements ExportableInterf $args['orderby'] = $request['orderby']; $args['order'] = $request['order']; $args['segmentby'] = $request['segmentby']; + $args['fields'] = $request['fields']; return $args; } diff --git a/plugins/woocommerce-admin/src/API/Reports/Taxes/Stats/Controller.php b/plugins/woocommerce-admin/src/API/Reports/Taxes/Stats/Controller.php index fdd8da47194..5ffab8b8e78 100644 --- a/plugins/woocommerce-admin/src/API/Reports/Taxes/Stats/Controller.php +++ b/plugins/woocommerce-admin/src/API/Reports/Taxes/Stats/Controller.php @@ -80,6 +80,7 @@ class Controller extends \WC_REST_Reports_Controller { $args['order'] = $request['order']; $args['taxes'] = (array) $request['taxes']; $args['segmentby'] = $request['segmentby']; + $args['fields'] = $request['fields']; return $args; } @@ -387,6 +388,12 @@ class Controller extends \WC_REST_Reports_Controller { ), 'validate_callback' => 'rest_validate_request_arg', ); + $params['fields'] = array( + 'description' => __( 'Limit stats fields to the specified items.', 'woocommerce-admin' ), + 'type' => 'array', + 'sanitize_callback' => 'wp_parse_slug_list', + 'validate_callback' => 'rest_validate_request_arg', + ); return $params; }