diff --git a/packages/core-data/src/entities.js b/packages/core-data/src/entities.js index fcedb9a912cdb8..32fc616b339dce 100644 --- a/packages/core-data/src/entities.js +++ b/packages/core-data/src/entities.js @@ -319,6 +319,12 @@ async function loadPostTypeEntities() { }, syncObjectType: 'postType/' + postType.name, getSyncObjectId: ( id ) => id, + getRevisionsUrl: ( parentId, revisionId ) => + `/${ namespace }/${ + postType.rest_base + }/${ parentId }/revisions${ + revisionId ? '/' + revisionId : '' + }`, }; } ); } diff --git a/packages/core-data/src/resolvers.js b/packages/core-data/src/resolvers.js index dc6bba0cb22b81..210e289978daa8 100644 --- a/packages/core-data/src/resolvers.js +++ b/packages/core-data/src/resolvers.js @@ -152,9 +152,7 @@ export const getEntityRecord = if ( isRevisionEntityRecord ) { const [ , parentKey ] = name.split( ':' ); path = addQueryArgs( - `${ entityConfig.baseURL }/${ parentKey }/revisions${ - key ? '/' + key : '' - }`, + entityConfig.getRevisionsUrl( parentKey, key ), { // @TODO check if this is the default for revisions (should be view?). Is there anything else? context: 'view', @@ -205,7 +203,6 @@ export const getEntityRecord = context: 'view', ...query, }, - invalidateCache: false, } ); } else { dispatch.receiveEntityRecords( kind, name, record, query ); @@ -236,7 +233,7 @@ export const getEditedEntityRecord = forwardResolver( 'getEntityRecord' ); */ export const getEntityRecords = ( kind, name, query = {} ) => - async ( { dispatch, select } ) => { + async ( { dispatch } ) => { const configs = await dispatch( getOrLoadEntitiesConfig( kind ) ); // @TODO Create predictable parsing rules for names like post:[key]:revisions. const splitName = name.split( ':' )[ 0 ]; @@ -281,7 +278,7 @@ export const getEntityRecords = if ( isRevisionEntityRecords ) { const [ , parentKey ] = name.split( ':' ); path = addQueryArgs( - `${ entityConfig.baseURL }/${ parentKey }/revisions`, + entityConfig.getRevisionsUrl( parentKey ), { // @TODO Default query params for revisions should be defined in the entity config? order: 'desc', @@ -317,20 +314,6 @@ export const getEntityRecords = // @TODO just dispatching here to send the action type. if ( isRevisionEntityRecords ) { - const [ postType, revisionParentKey ] = name.split( ':' ); - const existingRecords = select.getEntityRecords( - 'postType', - `${ postType }:${ revisionParentKey }:revisions`, - { - // @TODO Default query params for revisions should be defined in the entity config? - order: 'desc', - orderby: 'date', - // @TODO check if this is the default for revisions (should be view?). Is there anything else? - context: 'view', - ...query, - } - ); - console.log( 'existingRecords, records, shouldInvalidate?', existingRecords, records, existingRecords?.length !== records?.length ); dispatch( { type: 'RECEIVE_ITEM_REVISIONS', kind, @@ -344,8 +327,8 @@ export const getEntityRecords = context: 'view', ...query, }, - invalidateCache: - existingRecords?.length !== records?.length, + invalidateCache: true, + } ); } else { dispatch.receiveEntityRecords( kind, name, records, query ); @@ -375,14 +358,16 @@ export const getEntityRecords = dispatch.__unstableReleaseStoreLock( lock ); } }; -// @TODO work out how to invalidate revisions. At the moment, adding a new post revisions doesn't update the state without page refresh. + getEntityRecords.shouldInvalidate = ( action, kind, name ) => { - if ( action.type === 'RECEIVE_ITEM_REVISIONS' && name === action.name ) { - console.log( 'action', action, kind, name ); + // Invalidate cache when a new revision is created. + if ( action.type === 'SAVE_ENTITY_RECORD_FINISH' ) { + const [ postType, recordId ] = name.split( ':' ); return ( - action.invalidateCache && kind === action.kind && - name === action.name + postType === action.name && + ! action.error && + Number( recordId ) === action.recordId ); } diff --git a/packages/core-data/src/selectors.ts b/packages/core-data/src/selectors.ts index d78d5fd6dfa557..78f962a9212a83 100644 --- a/packages/core-data/src/selectors.ts +++ b/packages/core-data/src/selectors.ts @@ -20,6 +20,7 @@ import { getNormalizedCommaSeparable, isRawAttribute, setNestedValue, + parseEntityName, } from './utils'; import type * as ET from './entity-types'; import type { UndoManager } from '@wordpress/undo-manager'; @@ -324,12 +325,15 @@ export const getEntityRecord = createSelector( // @TODO this is a mess. // @TODO Create predictable parsing rules for names like post:[key]:revisions. // @TODO update the resolver to fetch the revision item. - const splitName = name?.split( ':' ); - const isRevision = splitName?.[ 2 ] === 'revisions'; + const { + name: parsedName, + key: parsedKey, + isRevision, + } = parseEntityName( name ); const queriedState = isRevision - ? state.entities.records?.[ kind ]?.[ splitName[ 0 ] ]?.revisions[ - splitName[ 1 ] + ? state.entities.records?.[ kind ]?.[ parsedName[ 0 ] ]?.revisions[ + parsedKey ] : state.entities.records?.[ kind ]?.[ name ]?.queriedData; if ( ! queriedState ) { @@ -374,9 +378,11 @@ export const getEntityRecord = createSelector( return item; } ) as GetEntityRecord, ( state: State, kind, name, recordId, query ) => { - // @TODO this is a mess. - // @TODO Create predictable parsing rules for names like post:[key]:revisions. - const splitName = name?.split( ':' ); + const { + name: parsedName, + key: parsedKey, + isRevision, + } = parseEntityName( name ); const isRevision = splitName?.[ 2 ] === 'revisions'; const queryParams = isRevision ? { @@ -390,15 +396,15 @@ export const getEntityRecord = createSelector( return [ isRevision - ? state.entities.records?.[ kind ]?.[ splitName[ 0 ] ] - ?.revisions[ splitName[ 1 ] ]?.items[ recordId ] + ? state.entities.records?.[ kind ]?.[ parsedName ]?.revisions[ + parsedKey + ]?.items[ recordId ] : state.entities.records?.[ kind ]?.[ name ]?.queriedData ?.items[ context ]?.[ recordId ], isRevision - ? state.entities.records?.[ kind ]?.[ splitName[ 0 ] ] - ?.revisions[ splitName[ 1 ] ]?.itemIsComplete[ - context - ]?.[ recordId ] + ? state.entities.records?.[ kind ]?.[ parsedName ]?.revisions[ + parsedKey + ]?.itemIsComplete[ context ]?.[ recordId ] : state.entities.records?.[ kind ]?.[ name ]?.queriedData ?.itemIsComplete[ context ]?.[ recordId ], ]; @@ -567,8 +573,7 @@ export const getEntityRecords = ( < if ( ! queriedStateRevisions ) { return null; } - console.log( 'state.entities.records?.[ kind ]?.[ splitName[ 0 ] ]?.revisions', state.entities.records?.[ kind ]?.[ splitName[ 0 ] ]?.revisions ); - const extraQueryParams = { + const defaultQueryParams = { // @TODO Default query params for revisions should be defined in the entity config? order: 'desc', orderby: 'date', @@ -578,7 +583,7 @@ export const getEntityRecords = ( < return getQueriedItems( queriedStateRevisions, { ...query, - ...extraQueryParams, + ...defaultQueryParams, } ); } diff --git a/packages/core-data/src/utils/index.js b/packages/core-data/src/utils/index.js index f37efe6eee7fda..6c021e4b3caf7e 100644 --- a/packages/core-data/src/utils/index.js +++ b/packages/core-data/src/utils/index.js @@ -8,3 +8,4 @@ export { default as withWeakMapCache } from './with-weak-map-cache'; export { default as isRawAttribute } from './is-raw-attribute'; export { default as setNestedValue } from './set-nested-value'; export { default as getNestedValue } from './get-nested-value'; +export { default as parseEntityName } from './parse-entity-name'; diff --git a/packages/core-data/src/utils/parse-entity-name.js b/packages/core-data/src/utils/parse-entity-name.js new file mode 100644 index 00000000000000..5e751469227d47 --- /dev/null +++ b/packages/core-data/src/utils/parse-entity-name.js @@ -0,0 +1,9 @@ +export default function parseEntityName( name = '' ) { + const [ postType, key, revisions ] = name?.split( ':' ); + + return { + name: postType, + key, + isRevision: revisions === 'revisions', + }; +}