Use X-WP-Total header to set the total number of items in tables (https://github.com/woocommerce/woocommerce-admin/pull/952)
* Use X-WP-Total header to set the total number of items in tables * Improve naming * Improve tests * Make getReportItems() return a 'data' property by default * Make getSummary prop behavior more clear
This commit is contained in:
parent
b27aa9b0aa
commit
540a191b57
|
@ -29,7 +29,6 @@ class ReportTable extends Component {
|
|||
itemIdField,
|
||||
primaryData,
|
||||
tableData,
|
||||
totalsCountField,
|
||||
// These two props are not used in the render function, but are destructured
|
||||
// so they are not included in the `tableProps` variable.
|
||||
endpoint,
|
||||
|
@ -48,12 +47,11 @@ class ReportTable extends Component {
|
|||
const isRequesting = tableData.isRequesting || primaryData.isRequesting;
|
||||
|
||||
const headers = getHeadersContent();
|
||||
const orderedItems = orderBy( items, query.orderby, query.order );
|
||||
const orderedItems = orderBy( items.data, query.orderby, query.order );
|
||||
const ids = orderedItems.map( item => item[ itemIdField ] );
|
||||
const rows = getRowsContent( orderedItems );
|
||||
const totals = get( primaryData, [ 'data', 'totals' ], null );
|
||||
const summary = getSummary( totals );
|
||||
const totalRows = get( totals, [ totalsCountField ], items.length );
|
||||
const summary = getSummary ? getSummary( totals ) : null;
|
||||
|
||||
return (
|
||||
<TableCard
|
||||
|
@ -65,7 +63,7 @@ class ReportTable extends Component {
|
|||
rows={ rows }
|
||||
rowsPerPage={ query.per_page }
|
||||
summary={ summary }
|
||||
totalRows={ totalRows }
|
||||
totalRows={ items.totalCount || 0 }
|
||||
{ ...tableProps }
|
||||
/>
|
||||
);
|
||||
|
@ -109,25 +107,16 @@ ReportTable.propTypes = {
|
|||
* String to display as the title of the table.
|
||||
*/
|
||||
title: PropTypes.string.isRequired,
|
||||
/**
|
||||
* Name of the property in the primary data totals object which contains the
|
||||
* total number of items.
|
||||
*/
|
||||
totalsCountField: PropTypes.string,
|
||||
};
|
||||
|
||||
ReportTable.defaultProps = {
|
||||
getSummary: () => null,
|
||||
tableQuery: {},
|
||||
totalsCountField: '',
|
||||
};
|
||||
|
||||
export default compose(
|
||||
withSelect( ( select, props ) => {
|
||||
const { endpoint, query, tableQuery } = props;
|
||||
// @TODO allow loading the primary data for the variations table once #926 is fixed.
|
||||
const primaryData =
|
||||
endpoint === 'variations' ? {} : getReportChartData( endpoint, 'primary', query, select );
|
||||
const { endpoint, getSummary, query, tableQuery } = props;
|
||||
const primaryData = getSummary ? getReportChartData( endpoint, 'primary', query, select ) : {};
|
||||
const tableData = getReportTableData( endpoint, query, select, tableQuery );
|
||||
|
||||
return {
|
||||
|
|
|
@ -133,7 +133,6 @@ export default class CategoriesReportTable extends Component {
|
|||
getSummary={ this.getSummary }
|
||||
itemIdField="category_id"
|
||||
query={ query }
|
||||
totalsCountField="categories_count"
|
||||
title={ __( 'Categories', 'wc-admin' ) }
|
||||
/>
|
||||
);
|
||||
|
|
|
@ -160,7 +160,6 @@ export default class CouponsReportTable extends Component {
|
|||
getSummary={ this.getSummary }
|
||||
itemIdField="coupon_id"
|
||||
query={ query }
|
||||
totalsCountField="coupons_count"
|
||||
title={ __( 'Coupons', 'wc-admin' ) }
|
||||
/>
|
||||
);
|
||||
|
|
|
@ -210,7 +210,6 @@ export default class ProductsReportTable extends Component {
|
|||
order: query.order || 'desc',
|
||||
extended_product_info: true,
|
||||
} }
|
||||
totalsCountField="products_count"
|
||||
title={ __( 'Products', 'wc-admin' ) }
|
||||
/>
|
||||
);
|
||||
|
|
|
@ -153,7 +153,6 @@ export default class TaxesReportTable extends Component {
|
|||
getSummary={ this.getSummary }
|
||||
itemIdField="tax_rate_id"
|
||||
query={ query }
|
||||
totalsCountField="taxes_count"
|
||||
title={ __( 'Taxes', 'wc-admin' ) }
|
||||
/>
|
||||
);
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
/** @format */
|
||||
|
||||
export default {
|
||||
setReportItems( endpoint, items, query ) {
|
||||
setReportItems( endpoint, query, data, totalCount ) {
|
||||
return {
|
||||
type: 'SET_REPORT_ITEMS',
|
||||
endpoint,
|
||||
items,
|
||||
query: query || {},
|
||||
data,
|
||||
totalCount,
|
||||
};
|
||||
},
|
||||
setReportItemsError( endpoint, query ) {
|
||||
|
|
|
@ -20,7 +20,10 @@ export default function reportItemsReducer( state = DEFAULT_STATE, action ) {
|
|||
case 'SET_REPORT_ITEMS':
|
||||
return merge( {}, state, {
|
||||
[ action.endpoint ]: {
|
||||
[ queryKey ]: action.items,
|
||||
[ queryKey ]: {
|
||||
data: action.data,
|
||||
totalCount: action.totalCount,
|
||||
},
|
||||
},
|
||||
} );
|
||||
|
||||
|
|
|
@ -26,9 +26,9 @@ export default {
|
|||
const response = await fetch(
|
||||
SWAGGERNAMESPACE + 'reports/' + endpoint + stringifyQuery( query )
|
||||
);
|
||||
const items = await response.json();
|
||||
const itemsData = await response.json();
|
||||
|
||||
dispatch( 'wc-admin' ).setReportItems( endpoint, items, query );
|
||||
dispatch( 'wc-admin' ).setReportItems( endpoint, query, itemsData );
|
||||
} catch ( error ) {
|
||||
dispatch( 'wc-admin' ).setReportItemsError( endpoint, query );
|
||||
}
|
||||
|
@ -37,11 +37,14 @@ export default {
|
|||
}
|
||||
|
||||
try {
|
||||
const items = await apiFetch( {
|
||||
const response = await apiFetch( {
|
||||
parse: false,
|
||||
path: NAMESPACE + 'reports/' + endpoint + stringifyQuery( query ),
|
||||
} );
|
||||
|
||||
dispatch( 'wc-admin' ).setReportItems( endpoint, items, query );
|
||||
const itemsData = await response.json();
|
||||
const totalCount = parseInt( response.headers.get( 'x-wp-total' ) );
|
||||
dispatch( 'wc-admin' ).setReportItems( endpoint, query, itemsData, totalCount );
|
||||
} catch ( error ) {
|
||||
dispatch( 'wc-admin' ).setReportItemsError( endpoint, query );
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ import { getJsonString } from 'store/utils';
|
|||
* @return {Object} Report details
|
||||
*/
|
||||
function getReportItems( state, endpoint, query = {} ) {
|
||||
return get( state, [ 'reports', 'items', endpoint, getJsonString( query ) ], [] );
|
||||
return get( state, [ 'reports', 'items', endpoint, getJsonString( query ) ], { data: [] } );
|
||||
}
|
||||
|
||||
export default {
|
||||
|
|
|
@ -27,17 +27,22 @@ describe( 'reportItemsReducer()', () => {
|
|||
const query = {
|
||||
orderby: 'orders_count',
|
||||
};
|
||||
const items = [ { id: 1214 }, { id: 1215 }, { id: 1216 } ];
|
||||
const itemsData = [ { id: 1214 }, { id: 1215 }, { id: 1216 } ];
|
||||
const itemsTotalCount = 50;
|
||||
|
||||
const state = reportItemsReducer( originalState, {
|
||||
type: 'SET_REPORT_ITEMS',
|
||||
endpoint,
|
||||
query,
|
||||
items,
|
||||
data: itemsData,
|
||||
totalCount: itemsTotalCount,
|
||||
} );
|
||||
|
||||
const queryKey = getJsonString( query );
|
||||
expect( state[ endpoint ][ queryKey ] ).toEqual( items );
|
||||
expect( state[ endpoint ][ queryKey ] ).toEqual( {
|
||||
data: itemsData,
|
||||
totalCount: itemsTotalCount,
|
||||
} );
|
||||
} );
|
||||
|
||||
it( 'tracks multiple queries in items data', () => {
|
||||
|
@ -45,28 +50,40 @@ describe( 'reportItemsReducer()', () => {
|
|||
orderby: 'id',
|
||||
};
|
||||
const otherQueryKey = getJsonString( otherQuery );
|
||||
const otherItems = [ { id: 1 }, { id: 2 }, { id: 3 } ];
|
||||
const otherItemsData = [ { id: 1 }, { id: 2 }, { id: 3 } ];
|
||||
const otherItemsTotalCount = 70;
|
||||
const otherQueryState = {
|
||||
[ endpoint ]: {
|
||||
[ otherQueryKey ]: otherItems,
|
||||
[ otherQueryKey ]: {
|
||||
data: otherItemsData,
|
||||
totalCount: otherItemsTotalCount,
|
||||
},
|
||||
},
|
||||
};
|
||||
const originalState = deepFreeze( otherQueryState );
|
||||
const query = {
|
||||
orderby: 'orders_count',
|
||||
};
|
||||
const items = [ { id: 1214 }, { id: 1215 }, { id: 1216 } ];
|
||||
const itemsData = [ { id: 1214 }, { id: 1215 }, { id: 1216 } ];
|
||||
const itemsTotalCount = 50;
|
||||
|
||||
const state = reportItemsReducer( originalState, {
|
||||
type: 'SET_REPORT_ITEMS',
|
||||
endpoint,
|
||||
query,
|
||||
items,
|
||||
data: itemsData,
|
||||
totalCount: itemsTotalCount,
|
||||
} );
|
||||
|
||||
const queryKey = getJsonString( query );
|
||||
expect( state[ endpoint ][ queryKey ] ).toEqual( items );
|
||||
expect( state[ endpoint ][ otherQueryKey ] ).toEqual( otherItems );
|
||||
expect( state[ endpoint ][ queryKey ] ).toEqual( {
|
||||
data: itemsData,
|
||||
totalCount: itemsTotalCount,
|
||||
} );
|
||||
expect( state[ endpoint ][ otherQueryKey ] ).toEqual( {
|
||||
data: otherItemsData,
|
||||
totalCount: otherItemsTotalCount,
|
||||
} );
|
||||
} );
|
||||
|
||||
it( 'returns with received error data', () => {
|
||||
|
|
|
@ -24,16 +24,28 @@ jest.mock( '@wordpress/api-fetch', () => jest.fn() );
|
|||
|
||||
describe( 'getReportItems', () => {
|
||||
const ITEMS_1 = [ { id: 1214 }, { id: 1215 }, { id: 1216 } ];
|
||||
const ITEMS_1_COUNT = 50;
|
||||
const ITEMS_2 = [ { id: 1 }, { id: 2 }, { id: 3 } ];
|
||||
const ITEMS_2_COUNT = 75;
|
||||
const endpoint = 'products';
|
||||
|
||||
beforeAll( () => {
|
||||
apiFetch.mockImplementation( options => {
|
||||
if ( options.path === `/wc/v3/reports/${ endpoint }` ) {
|
||||
return Promise.resolve( ITEMS_1 );
|
||||
return Promise.resolve( {
|
||||
headers: {
|
||||
get: () => ITEMS_1_COUNT,
|
||||
},
|
||||
json: () => Promise.resolve( ITEMS_1 ),
|
||||
} );
|
||||
}
|
||||
if ( options.path === `/wc/v3/reports/${ endpoint }?orderby=id` ) {
|
||||
return Promise.resolve( ITEMS_2 );
|
||||
return Promise.resolve( {
|
||||
headers: {
|
||||
get: () => ITEMS_2_COUNT,
|
||||
},
|
||||
json: () => Promise.resolve( ITEMS_2 ),
|
||||
} );
|
||||
}
|
||||
} );
|
||||
} );
|
||||
|
@ -41,12 +53,22 @@ describe( 'getReportItems', () => {
|
|||
it( 'returns requested report data', async () => {
|
||||
expect.assertions( 1 );
|
||||
await getReportItems( endpoint );
|
||||
expect( dispatch().setReportItems ).toHaveBeenCalledWith( endpoint, ITEMS_1, undefined );
|
||||
expect( dispatch().setReportItems ).toHaveBeenCalledWith(
|
||||
endpoint,
|
||||
undefined,
|
||||
ITEMS_1,
|
||||
ITEMS_1_COUNT
|
||||
);
|
||||
} );
|
||||
|
||||
it( 'returns requested report data for a specific query', async () => {
|
||||
expect.assertions( 1 );
|
||||
await getReportItems( endpoint, { orderby: 'id' } );
|
||||
expect( dispatch().setReportItems ).toHaveBeenCalledWith( endpoint, ITEMS_2, { orderby: 'id' } );
|
||||
expect( dispatch().setReportItems ).toHaveBeenCalledWith(
|
||||
endpoint,
|
||||
{ orderby: 'id' },
|
||||
ITEMS_2,
|
||||
ITEMS_2_COUNT
|
||||
);
|
||||
} );
|
||||
} );
|
||||
|
|
|
@ -26,23 +26,28 @@ const queryKey = getJsonString( query );
|
|||
const endpoint = 'coupons';
|
||||
|
||||
describe( 'getReportItems()', () => {
|
||||
it( 'returns an empty array when no items are available', () => {
|
||||
it( 'returns an empty object when no items are available', () => {
|
||||
const state = deepFreeze( {} );
|
||||
expect( getReportItems( state, endpoint, query ) ).toEqual( [] );
|
||||
expect( getReportItems( state, endpoint, query ) ).toEqual( { data: [] } );
|
||||
} );
|
||||
|
||||
it( 'returns stored items for current query', () => {
|
||||
const items = [ { id: 1214 }, { id: 1215 }, { id: 1216 } ];
|
||||
const itemsData = [ { id: 1214 }, { id: 1215 }, { id: 1216 } ];
|
||||
const itemsTotalCount = 50;
|
||||
const queryState = {
|
||||
data: itemsData,
|
||||
totalCount: itemsTotalCount,
|
||||
};
|
||||
const state = deepFreeze( {
|
||||
reports: {
|
||||
items: {
|
||||
[ endpoint ]: {
|
||||
[ queryKey ]: items,
|
||||
[ queryKey ]: queryState,
|
||||
},
|
||||
},
|
||||
},
|
||||
} );
|
||||
expect( getReportItems( state, endpoint, query ) ).toEqual( items );
|
||||
expect( getReportItems( state, endpoint, query ) ).toEqual( queryState );
|
||||
} );
|
||||
} );
|
||||
|
||||
|
|
Loading…
Reference in New Issue