From 666d8e4a3bdf14babf7dbc2aceb6ec51a7c8029b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albert=20Juh=C3=A9=20Lluveras?= Date: Fri, 1 Feb 2019 11:01:42 +0100 Subject: [PATCH] Merge getOrders and getItems (https://github.com/woocommerce/woocommerce-admin/pull/1438) * Move labels loading logic into a lib * Move lib/labels into lib/async-requests * Implement tabular data filtering * Allow searching for string in report tables * Add table filtering to customers table * Get ids from searched string to populate the table * Fix autocompleter keyboard interactions * Improve props naming * Cleanup report customers data store * Prevent an edge case issue that might not update the selectedOptions when directily modifying the URL * Fix wrong selected autocompleter option * Add missing translation domain * Move searchItemsByString to wc-api/items/utils.js * Avoid autocompleter results appearing when there was no search string * Alphabetically order 'allowFreeTextSearch' prop * Reset selected table rows when directly modifying the URL * Simplify props destructuring * Undo customers data store change * Simplify isProductDetailsView expression * Improve order * Merge getOrders and getItems --- .../report/categories/breadcrumbs.js | 12 +- .../analytics/report/categories/table.js | 2 +- .../client/analytics/report/products/table.js | 4 +- .../header/activity-panel/panels/orders.js | 107 +++++++++--------- .../client/wc-api/items/operations.js | 1 + .../client/wc-api/items/selectors.js | 11 +- .../client/wc-api/items/utils.js | 19 ++-- .../client/wc-api/orders/index.js | 11 -- .../client/wc-api/orders/operations.js | 76 ------------- .../client/wc-api/orders/selectors.js | 53 --------- .../client/wc-api/wc-api-spec.js | 3 - 11 files changed, 76 insertions(+), 223 deletions(-) delete mode 100644 plugins/woocommerce-admin/client/wc-api/orders/index.js delete mode 100644 plugins/woocommerce-admin/client/wc-api/orders/operations.js delete mode 100644 plugins/woocommerce-admin/client/wc-api/orders/selectors.js diff --git a/plugins/woocommerce-admin/client/analytics/report/categories/breadcrumbs.js b/plugins/woocommerce-admin/client/analytics/report/categories/breadcrumbs.js index ccab307e680..7566bc92fd6 100644 --- a/plugins/woocommerce-admin/client/analytics/report/categories/breadcrumbs.js +++ b/plugins/woocommerce-admin/client/analytics/report/categories/breadcrumbs.js @@ -18,7 +18,7 @@ export default class CategoryBreadcrumbs extends Component { let parent = category.parent; while ( parent ) { ancestors.unshift( parent ); - parent = categories[ parent ].parent; + parent = categories.get( parent ).parent; } return ancestors; } @@ -30,20 +30,20 @@ export default class CategoryBreadcrumbs extends Component { return; } if ( ancestorIds.length === 1 ) { - return categories[ first( ancestorIds ) ].name + ' › '; + return categories.get( first( ancestorIds ) ).name + ' › '; } if ( ancestorIds.length === 2 ) { return ( - categories[ first( ancestorIds ) ].name + + categories.get( first( ancestorIds ) ).name + ' › ' + - categories[ last( ancestorIds ) ].name + + categories.get( last( ancestorIds ) ).name + ' › ' ); } return ( - categories[ first( ancestorIds ) ].name + + categories.get( first( ancestorIds ) ).name + ' … ' + - categories[ last( ancestorIds ) ].name + + categories.get( last( ancestorIds ) ).name + ' › ' ); } diff --git a/plugins/woocommerce-admin/client/analytics/report/categories/table.js b/plugins/woocommerce-admin/client/analytics/report/categories/table.js index fce5ba87789..95ad44e52c2 100644 --- a/plugins/woocommerce-admin/client/analytics/report/categories/table.js +++ b/plugins/woocommerce-admin/client/analytics/report/categories/table.js @@ -71,7 +71,7 @@ class CategoriesReportTable extends Component { return map( categoryStats, categoryStat => { const { category_id, items_sold, net_revenue, products_count, orders_count } = categoryStat; const { categories, query } = this.props; - const category = categories[ category_id ]; + const category = categories.get( category_id ); const persistedQuery = getPersistedQuery( query ); return [ diff --git a/plugins/woocommerce-admin/client/analytics/report/products/table.js b/plugins/woocommerce-admin/client/analytics/report/products/table.js index 61b7e1c8f46..fcb24f0dac7 100644 --- a/plugins/woocommerce-admin/client/analytics/report/products/table.js +++ b/plugins/woocommerce-admin/client/analytics/report/products/table.js @@ -119,11 +119,11 @@ class ProductsReportTable extends Component { filter: 'single_product', products: product_id, } ); - const categories = this.props.categories; + const { categories } = this.props; const productCategories = ( category_ids && - category_ids.map( category_id => categories[ category_id ] ).filter( Boolean ) ) || + category_ids.map( category_id => categories.get( category_id ) ).filter( Boolean ) ) || []; return [ diff --git a/plugins/woocommerce-admin/client/header/activity-panel/panels/orders.js b/plugins/woocommerce-admin/client/header/activity-panel/panels/orders.js index 8c0412a70ff..3ca799c08ed 100644 --- a/plugins/woocommerce-admin/client/header/activity-panel/panels/orders.js +++ b/plugins/woocommerce-admin/client/header/activity-panel/panels/orders.js @@ -92,6 +92,51 @@ function OrdersPanel( { orders, isRequesting, isError } ) { ); }; + const cards = []; + orders.forEach( ( order, id ) => { + // We want the billing address, but shipping can be used as a fallback. + const address = { ...order.shipping, ...order.billing }; + const productsCount = order.line_items.reduce( ( total, line ) => total + line.quantity, 0 ); + + const total = order.total; + const refundValue = getOrderRefundTotal( order ); + const remainingTotal = getCurrencyFormatDecimal( order.total ) + refundValue; + + cards.push( + + + { sprintf( + _n( '%d product', '%d products', productsCount, 'wc-admin' ), + productsCount + ) } + + { refundValue ? ( + + { formatCurrency( total, order.currency_symbol ) }{' '} + { formatCurrency( remainingTotal, order.currency_symbol ) } + + ) : ( + { formatCurrency( total, order.currency_symbol ) } + ) } + + } + actions={ + + } + > + + + ); + } ); + return ( @@ -105,55 +150,7 @@ function OrdersPanel( { orders, isRequesting, isError } ) { /> ) : ( - { orders.map( ( order, i ) => { - // We want the billing address, but shipping can be used as a fallback. - const address = { ...order.shipping, ...order.billing }; - const productsCount = order.line_items.reduce( - ( total, line ) => total + line.quantity, - 0 - ); - - const total = order.total; - const refundValue = getOrderRefundTotal( order ); - const remainingTotal = getCurrencyFormatDecimal( order.total ) + refundValue; - - return ( - - - { sprintf( - _n( '%d product', '%d products', productsCount, 'wc-admin' ), - productsCount - ) } - - { refundValue ? ( - - { formatCurrency( total, order.currency_symbol ) }{' '} - { formatCurrency( remainingTotal, order.currency_symbol ) } - - ) : ( - { formatCurrency( total, order.currency_symbol ) } - ) } - - } - actions={ - - } - > - - - ); - } ) } + { cards } { __( 'Manage all orders' ) } @@ -165,29 +162,29 @@ function OrdersPanel( { orders, isRequesting, isError } ) { } OrdersPanel.propTypes = { - orders: PropTypes.array.isRequired, + orders: PropTypes.instanceOf( Map ).isRequired, isError: PropTypes.bool, isRequesting: PropTypes.bool, }; OrdersPanel.defaultProps = { - orders: [], + orders: new Map(), isError: false, isRequesting: false, }; export default compose( withSelect( select => { - const { getOrders, getOrdersError, isGetOrdersRequesting } = select( 'wc-api' ); + const { getItems, getItemsError, isGetItemsRequesting } = select( 'wc-api' ); const ordersQuery = { page: 1, per_page: QUERY_DEFAULTS.pageSize, status: 'processing', }; - const orders = getOrders( ordersQuery ); - const isError = Boolean( getOrdersError( ordersQuery ) ); - const isRequesting = isGetOrdersRequesting( ordersQuery ); + const orders = getItems( 'orders', ordersQuery ); + const isError = Boolean( getItemsError( 'orders', ordersQuery ) ); + const isRequesting = isGetItemsRequesting( 'orders', ordersQuery ); return { orders, isError, isRequesting }; } ) diff --git a/plugins/woocommerce-admin/client/wc-api/items/operations.js b/plugins/woocommerce-admin/client/wc-api/items/operations.js index ccbd69b45cb..b6589727c7b 100644 --- a/plugins/woocommerce-admin/client/wc-api/items/operations.js +++ b/plugins/woocommerce-admin/client/wc-api/items/operations.js @@ -20,6 +20,7 @@ const typeEndpointMap = { 'items-query-categories': 'products/categories', 'items-query-customers': 'customers', 'items-query-coupons': 'coupons', + 'items-query-orders': 'orders', 'items-query-products': 'products', 'items-query-taxes': 'taxes', }; diff --git a/plugins/woocommerce-admin/client/wc-api/items/selectors.js b/plugins/woocommerce-admin/client/wc-api/items/selectors.js index 8330de59395..c998c51f10e 100644 --- a/plugins/woocommerce-admin/client/wc-api/items/selectors.js +++ b/plugins/woocommerce-admin/client/wc-api/items/selectors.js @@ -18,13 +18,10 @@ const getItems = ( getResource, requireResource ) => ( ) => { const resourceName = getResourceName( `items-query-${ type }`, query ); const ids = requireResource( requirement, resourceName ).data || []; - const items = ids.reduce( - ( acc, id ) => ( { - ...acc, - [ id ]: getResource( getResourceName( `items-query-${ type }-item`, id ) ).data || {}, - } ), - {} - ); + const items = new Map(); + ids.forEach( id => { + items.set( id, getResource( getResourceName( `items-query-${ type }-item`, id ) ).data ); + } ); return items; }; diff --git a/plugins/woocommerce-admin/client/wc-api/items/utils.js b/plugins/woocommerce-admin/client/wc-api/items/utils.js index 17f66a153ee..48d87968944 100644 --- a/plugins/woocommerce-admin/client/wc-api/items/utils.js +++ b/plugins/woocommerce-admin/client/wc-api/items/utils.js @@ -16,15 +16,16 @@ export function searchItemsByString( select, endpoint, search ) { const { getItems } = select( 'wc-api' ); const searchWords = search.split( ',' ); - const items = searchWords.reduce( ( acc, searchWord ) => { - return { - ...acc, - ...getItems( endpoint, { - search: searchWord, - per_page: 10, - } ), - }; - }, [] ); + const items = {}; + searchWords.forEach( searchWord => { + const newItems = getItems( endpoint, { + search: searchWord, + per_page: 10, + } ); + newItems.forEach( ( item, id ) => { + items[ id ] = item; + } ); + } ); return items; } diff --git a/plugins/woocommerce-admin/client/wc-api/orders/index.js b/plugins/woocommerce-admin/client/wc-api/orders/index.js deleted file mode 100644 index cd0cff2f807..00000000000 --- a/plugins/woocommerce-admin/client/wc-api/orders/index.js +++ /dev/null @@ -1,11 +0,0 @@ -/** @format */ -/** - * Internal dependencies - */ -import operations from './operations'; -import selectors from './selectors'; - -export default { - operations, - selectors, -}; diff --git a/plugins/woocommerce-admin/client/wc-api/orders/operations.js b/plugins/woocommerce-admin/client/wc-api/orders/operations.js deleted file mode 100644 index 061b4392ba2..00000000000 --- a/plugins/woocommerce-admin/client/wc-api/orders/operations.js +++ /dev/null @@ -1,76 +0,0 @@ -/** @format */ -/** - * External dependencies - */ -import apiFetch from '@wordpress/api-fetch'; - -/** - * WooCommerce dependencies - */ -import { stringifyQuery } from '@woocommerce/navigation'; - -/** - * Internal dependencies - */ -import { isResourcePrefix, getResourceIdentifier, getResourceName } from '../utils'; -import { NAMESPACE } from '../constants'; - -function read( resourceNames, fetch = apiFetch ) { - return [ ...readOrders( resourceNames, fetch ), ...readOrderQueries( resourceNames, fetch ) ]; -} - -function readOrderQueries( resourceNames, fetch ) { - const filteredNames = resourceNames.filter( name => isResourcePrefix( name, 'order-query' ) ); - - return filteredNames.map( async resourceName => { - const query = getResourceIdentifier( resourceName ); - const url = `${ NAMESPACE }/orders${ stringifyQuery( query ) }`; - - try { - const response = await fetch( { - parse: false, - path: url, - } ); - - const orders = await response.json(); - const totalCount = parseInt( response.headers.get( 'x-wp-total' ) ); - const ids = orders.map( order => order.id ); - const orderResources = orders.reduce( ( resources, order ) => { - resources[ getResourceName( 'order', order.id ) ] = { data: order }; - return resources; - }, {} ); - - return { - [ resourceName ]: { - data: ids, - totalCount, - }, - ...orderResources, - }; - } catch ( error ) { - return { [ resourceName ]: { error } }; - } - } ); -} - -function readOrders( resourceNames, fetch ) { - const filteredNames = resourceNames.filter( name => isResourcePrefix( name, 'order' ) ); - return filteredNames.map( resourceName => readOrder( resourceName, fetch ) ); -} - -function readOrder( resourceName, fetch ) { - const id = getResourceIdentifier( resourceName ); - const url = `${ NAMESPACE }/orders/${ id }`; - - return fetch( { path: url } ) - .then( order => { - return { [ resourceName ]: { data: order } }; - } ) - .catch( error => { - return { [ resourceName ]: { error } }; - } ); -} - -export default { - read, -}; diff --git a/plugins/woocommerce-admin/client/wc-api/orders/selectors.js b/plugins/woocommerce-admin/client/wc-api/orders/selectors.js deleted file mode 100644 index 9bb486699ae..00000000000 --- a/plugins/woocommerce-admin/client/wc-api/orders/selectors.js +++ /dev/null @@ -1,53 +0,0 @@ -/** @format */ - -/** - * External dependencies - */ -import { isNil } from 'lodash'; - -/** - * Internal dependencies - */ -import { getResourceName } from '../utils'; -import { DEFAULT_REQUIREMENT } from '../constants'; - -const getOrders = ( getResource, requireResource ) => ( - query = {}, - requirement = DEFAULT_REQUIREMENT -) => { - const resourceName = getResourceName( 'order-query', query ); - const ids = requireResource( requirement, resourceName ).data || []; - const orders = ids.map( id => getResource( getResourceName( 'order', id ) ).data || {} ); - return orders; -}; - -const getOrdersError = getResource => ( query = {} ) => { - const resourceName = getResourceName( 'order-query', query ); - return getResource( resourceName ).error; -}; - -const getOrdersTotalCount = ( getResource, requireResource ) => ( - query = {}, - requirement = DEFAULT_REQUIREMENT -) => { - const resourceName = getResourceName( 'order-query', query ); - return requireResource( requirement, resourceName ).totalCount || 0; -}; - -const isGetOrdersRequesting = getResource => ( query = {} ) => { - const resourceName = getResourceName( 'order-query', query ); - const { lastRequested, lastReceived } = getResource( resourceName ); - - if ( isNil( lastRequested ) || isNil( lastReceived ) ) { - return true; - } - - return lastRequested > lastReceived; -}; - -export default { - getOrders, - getOrdersError, - getOrdersTotalCount, - isGetOrdersRequesting, -}; diff --git a/plugins/woocommerce-admin/client/wc-api/wc-api-spec.js b/plugins/woocommerce-admin/client/wc-api/wc-api-spec.js index b1ec191657f..c9e9132b6f1 100644 --- a/plugins/woocommerce-admin/client/wc-api/wc-api-spec.js +++ b/plugins/woocommerce-admin/client/wc-api/wc-api-spec.js @@ -5,7 +5,6 @@ */ import items from './items'; import notes from './notes'; -import orders from './orders'; import reportItems from './reports/items'; import reportStats from './reports/stats'; import reviews from './reviews'; @@ -21,7 +20,6 @@ function createWcApiSpec() { selectors: { ...items.selectors, ...notes.selectors, - ...orders.selectors, ...reportItems.selectors, ...reportStats.selectors, ...reviews.selectors, @@ -33,7 +31,6 @@ function createWcApiSpec() { return [ ...items.operations.read( resourceNames ), ...notes.operations.read( resourceNames ), - ...orders.operations.read( resourceNames ), ...reportItems.operations.read( resourceNames ), ...reportStats.operations.read( resourceNames ), ...reviews.operations.read( resourceNames ),