Skip to content

Commit

Permalink
Core Data: Retrieve the pagination totals in the getEntityRecords cal…
Browse files Browse the repository at this point in the history
…ls (#55164)
  • Loading branch information
youknowriad authored Oct 10, 2023
1 parent 9d15719 commit da1290d
Show file tree
Hide file tree
Showing 17 changed files with 275 additions and 72 deletions.
31 changes: 31 additions & 0 deletions docs/reference-guides/data/data-core.md
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,36 @@ _Returns_

- `EntityRecord[] | null`: Records.

### getEntityRecordsTotalItems

Returns the Entity's total available records for a given query (ignoring pagination).

_Parameters_

- _state_ `State`: State tree
- _kind_ `string`: Entity kind.
- _name_ `string`: Entity name.
- _query_ `GetRecordsHttpQuery`: Optional terms query. If requesting specific fields, fields must always include the ID. For valid query parameters see the [Reference](https://developer.wordpress.org/rest-api/reference/) in the REST API Handbook and select the entity kind. Then see the arguments available for "List [Entity kind]s".

_Returns_

- `number | null`: number | null.

### getEntityRecordsTotalPages

Returns the number of available pages for the given query.

_Parameters_

- _state_ `State`: State tree
- _kind_ `string`: Entity kind.
- _name_ `string`: Entity name.
- _query_ `GetRecordsHttpQuery`: Optional terms query. If requesting specific fields, fields must always include the ID. For valid query parameters see the [Reference](https://developer.wordpress.org/rest-api/reference/) in the REST API Handbook and select the entity kind. Then see the arguments available for "List [Entity kind]s".

_Returns_

- `number | null`: number | null.

### getLastEntityDeleteError

Returns the specified entity record's last delete error.
Expand Down Expand Up @@ -630,6 +660,7 @@ _Parameters_
- _query_ `?Object`: Query Object.
- _invalidateCache_ `?boolean`: Should invalidate query caches.
- _edits_ `?Object`: Edits to reset.
- _meta_ `?Object`: Meta information about pagination.

_Returns_

Expand Down
4 changes: 4 additions & 0 deletions packages/core-data/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

## Enhancements

- Add `getEntityRecordsTotalItems` and `getEntityRecordsTotalPages` selectors. [#55164](https://github.com/WordPress/gutenberg/pull/55164).

## 6.20.0 (2023-10-05)

## 6.19.0 (2023-09-20)
Expand Down
31 changes: 31 additions & 0 deletions packages/core-data/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ _Parameters_
- _query_ `?Object`: Query Object.
- _invalidateCache_ `?boolean`: Should invalidate query caches.
- _edits_ `?Object`: Edits to reset.
- _meta_ `?Object`: Meta information about pagination.

_Returns_

Expand Down Expand Up @@ -592,6 +593,36 @@ _Returns_

- `EntityRecord[] | null`: Records.

### getEntityRecordsTotalItems

Returns the Entity's total available records for a given query (ignoring pagination).

_Parameters_

- _state_ `State`: State tree
- _kind_ `string`: Entity kind.
- _name_ `string`: Entity name.
- _query_ `GetRecordsHttpQuery`: Optional terms query. If requesting specific fields, fields must always include the ID. For valid query parameters see the [Reference](https://developer.wordpress.org/rest-api/reference/) in the REST API Handbook and select the entity kind. Then see the arguments available for "List [Entity kind]s".

_Returns_

- `number | null`: number | null.

### getEntityRecordsTotalPages

Returns the number of available pages for the given query.

_Parameters_

- _state_ `State`: State tree
- _kind_ `string`: Entity kind.
- _name_ `string`: Entity name.
- _query_ `GetRecordsHttpQuery`: Optional terms query. If requesting specific fields, fields must always include the ID. For valid query parameters see the [Reference](https://developer.wordpress.org/rest-api/reference/) in the REST API Handbook and select the entity kind. Then see the arguments available for "List [Entity kind]s".

_Returns_

- `number | null`: number | null.

### getLastEntityDeleteError

Returns the specified entity record's last delete error.
Expand Down
8 changes: 5 additions & 3 deletions packages/core-data/src/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ export function addEntities( entities ) {
* @param {?Object} query Query Object.
* @param {?boolean} invalidateCache Should invalidate query caches.
* @param {?Object} edits Edits to reset.
* @param {?Object} meta Meta information about pagination.
* @return {Object} Action object.
*/
export function receiveEntityRecords(
Expand All @@ -88,7 +89,8 @@ export function receiveEntityRecords(
records,
query,
invalidateCache = false,
edits
edits,
meta
) {
// Auto drafts should not have titles, but some plugins rely on them so we can't filter this
// on the server.
Expand All @@ -102,9 +104,9 @@ export function receiveEntityRecords(
}
let action;
if ( query ) {
action = receiveQueriedItems( records, query, edits );
action = receiveQueriedItems( records, query, edits, meta );
} else {
action = receiveItems( records, edits );
action = receiveItems( records, edits, meta );
}

return {
Expand Down
2 changes: 2 additions & 0 deletions packages/core-data/src/entities.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ export const rootEntitiesConfig = [
plural: 'mediaItems',
label: __( 'Media' ),
rawAttributes: [ 'caption', 'title', 'description' ],
supportsPagination: true,
},
{
name: 'taxonomy',
Expand Down Expand Up @@ -326,6 +327,7 @@ async function loadPostTypeEntities() {
},
syncObjectType: 'postType/' + postType.name,
getSyncObjectId: ( id ) => id,
supportsPagination: true,
};
} );
}
Expand Down
4 changes: 4 additions & 0 deletions packages/core-data/src/hooks/test/use-entity-records.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ describe( 'useEntityRecords', () => {
hasResolved: false,
isResolving: false,
status: 'IDLE',
totalItems: null,
totalPages: null,
} );

// Fetch request should have been issued
Expand All @@ -65,6 +67,8 @@ describe( 'useEntityRecords', () => {
hasResolved: true,
isResolving: false,
status: 'SUCCESS',
totalItems: null,
totalPages: null,
} );
} );
} );
37 changes: 37 additions & 0 deletions packages/core-data/src/hooks/use-entity-records.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*/
import { addQueryArgs } from '@wordpress/url';
import deprecated from '@wordpress/deprecated';
import { useSelect } from '@wordpress/data';

/**
* Internal dependencies
Expand All @@ -28,6 +29,16 @@ interface EntityRecordsResolution< RecordType > {

/** Resolution status */
status: Status;

/**
* The total number of available items (if not paginated).
*/
totalItems: number | null;

/**
* The total number of pages.
*/
totalPages: number | null;
}

const EMPTY_ARRAY = [];
Expand Down Expand Up @@ -97,8 +108,34 @@ export default function useEntityRecords< RecordType >(
[ kind, name, queryAsString, options.enabled ]
);

const { totalItems, totalPages } = useSelect(
( select ) => {
if ( ! options.enabled ) {
return {
totalItems: null,
totalPages: null,
};
}
return {
totalItems: select( coreStore ).getEntityRecordsTotalItems(
kind,
name,
queryArgs
),
totalPages: select( coreStore ).getEntityRecordsTotalPages(
kind,
name,
queryArgs
),
};
},
[ kind, name, queryAsString, options.enabled ]
);

return {
records,
totalItems,
totalPages,
...rest,
};
}
Expand Down
9 changes: 6 additions & 3 deletions packages/core-data/src/queried-data/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@
*
* @param {Array} items Items received.
* @param {?Object} edits Optional edits to reset.
* @param {?Object} meta Meta information about pagination.
*
* @return {Object} Action object.
*/
export function receiveItems( items, edits ) {
export function receiveItems( items, edits, meta ) {
return {
type: 'RECEIVE_ITEMS',
items: Array.isArray( items ) ? items : [ items ],
persistedEdits: edits,
meta,
};
}

Expand Down Expand Up @@ -41,12 +43,13 @@ export function removeItems( kind, name, records, invalidateCache = false ) {
* @param {Array} items Queried items received.
* @param {?Object} query Optional query object.
* @param {?Object} edits Optional edits to reset.
* @param {?Object} meta Meta information about pagination.
*
* @return {Object} Action object.
*/
export function receiveQueriedItems( items, query = {}, edits ) {
export function receiveQueriedItems( items, query = {}, edits, meta ) {
return {
...receiveItems( items, edits ),
...receiveItems( items, edits, meta ),
query,
};
}
27 changes: 17 additions & 10 deletions packages/core-data/src/queried-data/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -222,19 +222,22 @@ const receiveQueries = compose( [
// Queries shape is shared, but keyed by query `stableKey` part. Original
// reducer tracks only a single query object.
onSubKey( 'stableKey' ),
] )( ( state = null, action ) => {
] )( ( state = {}, action ) => {
const { type, page, perPage, key = DEFAULT_ENTITY_KEY } = action;

if ( type !== 'RECEIVE_ITEMS' ) {
return state;
}

return getMergedItemIds(
state || [],
action.items.map( ( item ) => item[ key ] ),
page,
perPage
);
return {
itemIds: getMergedItemIds(
state?.itemIds || [],
action.items.map( ( item ) => item[ key ] ),
page,
perPage
),
meta: action.meta,
};
} );

/**
Expand Down Expand Up @@ -263,9 +266,13 @@ const queries = ( state = {}, action ) => {
Object.entries( contextQueries ).map(
( [ query, queryItems ] ) => [
query,
queryItems.filter(
( queryId ) => ! removedItems[ queryId ]
),
{
...queryItems,
itemIds: queryItems.itemIds.filter(
( queryId ) =>
! removedItems[ queryId ]
),
},
]
)
),
Expand Down
14 changes: 13 additions & 1 deletion packages/core-data/src/queried-data/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ function getQueriedItemsUncached( state, query ) {
let itemIds;

if ( state.queries?.[ context ]?.[ stableKey ] ) {
itemIds = state.queries[ context ][ stableKey ];
itemIds = state.queries[ context ][ stableKey ].itemIds;
}

if ( ! itemIds ) {
Expand Down Expand Up @@ -118,3 +118,15 @@ export const getQueriedItems = createSelector( ( state, query = {} ) => {
queriedItemsCache.set( query, items );
return items;
} );

export function getQueriedTotalItems( state, query = {} ) {
const { stableKey, context } = getQueryParts( query );

return state.queries?.[ context ]?.[ stableKey ]?.meta?.totalItems ?? null;
}

export function getQueriedTotalPages( state, query = {} ) {
const { stableKey, context } = getQueryParts( query );

return state.queries?.[ context ]?.[ stableKey ]?.meta?.totalPages ?? null;
}
18 changes: 9 additions & 9 deletions packages/core-data/src/queried-data/test/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ describe( 'reducer', () => {
default: { 1: true },
},
queries: {
default: { 's=a': [ 1 ] },
default: { 's=a': { itemIds: [ 1 ] } },
},
} );
} );
Expand Down Expand Up @@ -200,8 +200,8 @@ describe( 'reducer', () => {
},
queries: {
default: {
'': [ 1, 2, 3, 4 ],
's=a': [ 1, 3 ],
'': { itemIds: [ 1, 2, 3, 4 ] },
's=a': { itemIds: [ 1, 3 ] },
},
},
} );
Expand All @@ -218,8 +218,8 @@ describe( 'reducer', () => {
},
queries: {
default: {
'': [ 1, 2, 4 ],
's=a': [ 1 ],
'': { itemIds: [ 1, 2, 4 ] },
's=a': { itemIds: [ 1 ] },
},
},
} );
Expand All @@ -238,8 +238,8 @@ describe( 'reducer', () => {
},
queries: {
default: {
'': [ 'foo//bar1', 'foo//bar2', 'foo//bar3' ],
's=2': [ 'foo//bar2' ],
'': { itemIds: [ 'foo//bar1', 'foo//bar2', 'foo//bar3' ] },
's=2': { itemIds: [ 'foo//bar2' ] },
},
},
} );
Expand All @@ -258,8 +258,8 @@ describe( 'reducer', () => {
},
queries: {
default: {
'': [ 'foo//bar1', 'foo//bar3' ],
's=2': [],
'': { itemIds: [ 'foo//bar1', 'foo//bar3' ] },
's=2': { itemIds: [] },
},
},
} );
Expand Down
Loading

1 comment on commit da1290d

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Flaky tests detected in da1290d.
Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/6468008210
📝 Reported issues:

Please sign in to comment.