From 0edea5d3565bc40750609aeb246dde80ee74bbeb Mon Sep 17 00:00:00 2001 From: ramon Date: Mon, 18 Sep 2023 15:36:12 +1000 Subject: [PATCH] Testing out parsing name params, e.g., post:id:revisions --- packages/core-data/src/entities.js | 4 +- packages/core-data/src/reducer.js | 8 +++- packages/core-data/src/resolvers.js | 67 +++++++++++++++++++++++++---- packages/core-data/src/selectors.ts | 15 ++++++- 4 files changed, 81 insertions(+), 13 deletions(-) diff --git a/packages/core-data/src/entities.js b/packages/core-data/src/entities.js index 6c1579de1ecdf..04a0ab9a9aa03 100644 --- a/packages/core-data/src/entities.js +++ b/packages/core-data/src/entities.js @@ -266,8 +266,9 @@ export const prePersistPostType = ( persistedRecord, edits ) => { * @return {Promise} Entities promise */ async function loadPostTypeEntities() { + // @TODO 'edit' context required to get supports collection. const postTypes = await apiFetch( { - path: '/wp/v2/types?context=view', + path: '/wp/v2/types?context=edit', } ); return Object.entries( postTypes ?? {} ).map( ( [ name, postType ] ) => { const isTemplate = [ 'wp_template', 'wp_template_part' ].includes( @@ -285,6 +286,7 @@ async function loadPostTypeEntities() { selection: true, }, mergedEdits: { meta: true }, + supports: postType?.supports, rawAttributes: POST_RAW_ATTRIBUTES, getTitle: ( record ) => record?.title?.rendered || diff --git a/packages/core-data/src/reducer.js b/packages/core-data/src/reducer.js index 68c0cc233d7b6..532457aea6feb 100644 --- a/packages/core-data/src/reducer.js +++ b/packages/core-data/src/reducer.js @@ -231,7 +231,8 @@ function entity( entityConfig ) { ( action ) => action.name && action.kind && - action.name === entityConfig.name && + // @TODO Create predictable parsing rules for names like post:[key]:revisions. + action.name.split( ':' )[ 0 ] === entityConfig.name && action.kind === entityConfig.kind ), @@ -245,7 +246,10 @@ function entity( entityConfig ) { ] )( combineReducers( { queriedData: queriedDataReducer, - + // @TODO can this be filtered by supports above? + ...( entityConfig?.supports?.revisions + ? { revisions: queriedDataReducer } + : {} ), edits: ( state = {}, action ) => { switch ( action.type ) { case 'RECEIVE_ITEMS': diff --git a/packages/core-data/src/resolvers.js b/packages/core-data/src/resolvers.js index e01bb12b2e253..3d3b52564acb2 100644 --- a/packages/core-data/src/resolvers.js +++ b/packages/core-data/src/resolvers.js @@ -189,11 +189,17 @@ export const getEditedEntityRecord = forwardResolver( 'getEntityRecord' ); */ export const getEntityRecords = ( kind, name, query = {} ) => - async ( { dispatch } ) => { + async ( { dispatch, select } ) => { const configs = await dispatch( getOrLoadEntitiesConfig( kind ) ); + // @TODO Create predictable parsing rules for names like post:[key]:revisions. + const splitName = name.split( ':' )[ 0 ]; + const entityConfig = configs.find( - ( config ) => config.name === name && config.kind === kind + ( config ) => config.name === splitName && config.kind === kind ); + const isRevisionEntityRecords = + entityConfig?.supports?.revisions && + name.split( ':' )?.[ 2 ] === 'revisions'; if ( ! entityConfig || entityConfig?.__experimentalNoFetch ) { return; } @@ -221,12 +227,36 @@ export const getEntityRecords = }; } - const path = addQueryArgs( entityConfig.baseURL, { - ...entityConfig.baseURLParams, - ...query, - } ); + // @TODO Create predictable URL building rules for names like post:[key]:revisions. + // @TODO Possibly `entityConfig.getRevisionsUrl( { name } )? + let path, records; + if ( isRevisionEntityRecords ) { + const [ parentName, parentKey ] = name.split( ':' ); + const parent = await select.getEntityRecord( + kind, + parentName, + parentKey + ); + const revisionsURL = + parent?._links?.[ 'version-history' ]?.[ 0 ]?.href; + const url = addQueryArgs( revisionsURL, { + ...{ + // @TODO Default query params for revisions should be defined in the entity config? + context: 'view', + order: 'desc', + orderby: 'date', + }, + ...query, + } ); + records = Object.values( await apiFetch( { url } ) ); + } else { + path = addQueryArgs( entityConfig.baseURL, { + ...entityConfig.baseURLParams, + ...query, + } ); + records = Object.values( await apiFetch( { path } ) ); + } - let records = Object.values( await apiFetch( { path } ) ); // If we request fields but the result doesn't contain the fields, // explicitly set these fields as "undefined" // that way we consider the query "fullfilled". @@ -242,7 +272,28 @@ export const getEntityRecords = } ); } - dispatch.receiveEntityRecords( kind, name, records, query ); + // @TODO just dispatching here to send the default query params. + if ( isRevisionEntityRecords ) { + dispatch( { + type: 'RECEIVE_ITEMS', + kind, + name, + items: records, + query: { + ...{ + // @TODO Default query params for revisions should be defined in the entity config? + order: 'desc', + orderby: 'date', + }, + ...query, + }, + invalidateCache: false, + } ); + } else { + dispatch.receiveEntityRecords( kind, name, records, query ); + } + + // When requesting all fields, the list of results can be used to // resolve the `getEntityRecord` selector in addition to `getEntityRecords`. diff --git a/packages/core-data/src/selectors.ts b/packages/core-data/src/selectors.ts index 3536a3ef55adf..570a78aa4fa64 100644 --- a/packages/core-data/src/selectors.ts +++ b/packages/core-data/src/selectors.ts @@ -520,11 +520,22 @@ export const getEntityRecords = ( < ): EntityRecord[] | null => { // Queried data state is prepopulated for all known entities. If this is not // assigned for the given parameters, then it is known to not exist. - const queriedState = - state.entities.records?.[ kind ]?.[ name ]?.queriedData; + // @TODO Create predictable parsing rules for names like post:[key]:revisions. + const splitName = name.split( ':' ); + let queriedState = null; + + if ( splitName?.[ 2 ] === 'revisions' ) { + queriedState = + state.entities.records?.[ kind ]?.[ splitName[ 0 ] ]?.revisions?.[ + splitName?.[ 1 ] + ]; + } else { + queriedState = state.entities.records?.[ kind ]?.[ name ]?.queriedData; + } if ( ! queriedState ) { return null; } + // @TODO this is not returning anything yet. return getQueriedItems( queriedState, query ); } ) as GetEntityRecords;