Skip to content

Commit

Permalink
Simplify detection of metadata changes
Browse files Browse the repository at this point in the history
Removed unnecessary code added in previous commit
and instead modified existing functions to add a flag on
existing dirtyEntityRecord structures to indicate when
metadata changes have been made.
  • Loading branch information
artemiomorales committed May 24, 2024
1 parent 314e81c commit b9e7cde
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 62 deletions.
4 changes: 0 additions & 4 deletions docs/reference-guides/data/data-core-editor.md
Original file line number Diff line number Diff line change
Expand Up @@ -507,10 +507,6 @@ _Returns_

- `Object`: Object of key value pairs comprising unsaved edits.

### getPostEntityBlockMetadataChanges

Undocumented declaration.

### getPostLockUser

Returns details about the post lock user.
Expand Down
50 changes: 42 additions & 8 deletions packages/core-data/src/selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,7 @@ type DirtyEntityRecord = {
key: EntityRecordKey;
name: string;
kind: string;
hasMetaChanges?: boolean;
};
/**
* Returns the list of dirty entity records.
Expand All @@ -655,15 +656,46 @@ export const __experimentalGetDirtyEntityRecords = createSelector(
const dirtyRecords: DirtyEntityRecord[] = [];
Object.keys( records ).forEach( ( kind ) => {
Object.keys( records[ kind ] ).forEach( ( name ) => {
const metadataKeys: string[] = [];
const primaryKeys = (
Object.keys( records[ kind ][ name ].edits ) as string[]
).filter(
( primaryKey ) =>
// The entity record must exist (not be deleted),
// and it must have edits.
getEntityRecord( state, kind, name, primaryKey ) &&
hasEditsForEntityRecord( state, kind, name, primaryKey )
);
).filter( ( primaryKey ) => {
// The entity record must exist (not be deleted),
// and it must have edits.
const entityRecord = getEntityRecord(
state,
kind,
name,
primaryKey
);
const nonTransientEdits = getEntityRecordNonTransientEdits(
state,
kind,
name,
primaryKey
);

if ( entityRecord ) {
if ( Object.keys( nonTransientEdits ).length > 0 ) {
if ( nonTransientEdits.meta ) {
metadataKeys.push( primaryKey );
}
return true;
}

if (
isSavingEntityRecord(
state,
kind,
name,
primaryKey
)
) {
return true;
}
}
return false;
} );

if ( primaryKeys.length ) {
const entityConfig = getEntityConfig( state, kind, name );
Expand All @@ -686,6 +718,9 @@ export const __experimentalGetDirtyEntityRecords = createSelector(
entityConfig?.getTitle?.( entityRecord ) || '',
name,
kind,
hasMetaChanges: metadataKeys.includes( primaryKey )
? true
: false,
} );
} );
}
Expand Down Expand Up @@ -714,7 +749,6 @@ export const __experimentalGetDirtyEntityRecordsEdits = createSelector(
( state ) => [ state.entities.records ]
);


/**
* Returns the list of entities currently being saved.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,22 @@ import { store as coreStore } from '@wordpress/core-data';
import { useMemo, useState } from '@wordpress/element';

export const useIsDirty = () => {
const { editedEntities, siteEdits, postEdits, siteEntityConfig } =
useSelect( ( select ) => {
const { editedEntities, siteEdits, siteEntityConfig } = useSelect(
( select ) => {
const {
__experimentalGetDirtyEntityRecords,
getEntityRecordEdits,
__experimentalGetDirtyEntityRecordsEdits,
getEntityConfig,
} = select( coreStore );

return {
editedEntities: __experimentalGetDirtyEntityRecords(),
siteEdits: getEntityRecordEdits( 'root', 'site' ),
postEdits: __experimentalGetDirtyEntityRecordsEdits(),
siteEntityConfig: getEntityConfig( 'root', 'site' ),
};
}, [] );
},
[]
);

const dirtyEntityRecords = useMemo( () => {
// Remove site object and decouple into its edited pieces.
Expand All @@ -43,20 +43,6 @@ export const useIsDirty = () => {
return [ ...editedEntitiesWithoutSite, ...editedSiteEntities ];
}, [ editedEntities, siteEdits, siteEntityConfig ] );

const metaRecords = useMemo( () => {
return Object.keys( postEdits ).map( ( key ) => {
const post = postEdits[ key ];
return Object.keys( post.meta ).map( ( property ) => {
return {
key: `${ key }_${ property }`,
kind: 'postType',
name: 'post',
title: property,
};
} );
} );
}, [ postEdits ] );

// Unchecked entities to be ignored by save function.
const [ unselectedEntities, _setUnselectedEntities ] = useState( [] );

Expand Down Expand Up @@ -86,7 +72,6 @@ export const useIsDirty = () => {

return {
dirtyEntityRecords,
metaRecords,
isDirty,
setUnselectedEntities,
unselectedEntities,
Expand Down
3 changes: 0 additions & 3 deletions packages/editor/src/components/entities-saved-states/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ export function EntitiesSavedStatesExtensible( {
saveLabel = __( 'Save' ),
renderDialog = undefined,
dirtyEntityRecords,
metaRecords,
isDirty,
setUnselectedEntities,
unselectedEntities,
Expand All @@ -65,8 +64,6 @@ export function EntitiesSavedStatesExtensible( {
return acc;
}, {} );

partitionedSavables.meta = metaRecords[ 0 ];

// Sort entity groups.
const {
site: siteSavables,
Expand Down
16 changes: 3 additions & 13 deletions packages/editor/src/components/post-publish-button/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,21 +45,14 @@ export class PostPublishButton extends Component {

createOnClick( callback ) {
return ( ...args ) => {
const {
hasNonPostEntityChanges,
getPostEntityBlockMetadataChanges,
setEntitiesSavedStatesCallback,
} = this.props;
const { hasNonPostEntityChanges, setEntitiesSavedStatesCallback } =
this.props;
// If a post with non-post entities is published, but the user
// elects to not save changes to the non-post entities, those
// entities will still be dirty when the Publish button is clicked.
// We also need to check that the `setEntitiesSavedStatesCallback`
// prop was passed. See https://github.com/WordPress/gutenberg/pull/37383
if (
( hasNonPostEntityChanges ||
getPostEntityBlockMetadataChanges ) &&
setEntitiesSavedStatesCallback
) {
if ( hasNonPostEntityChanges && setEntitiesSavedStatesCallback ) {
// The modal for multiple entity saving will open,
// hold the callback for saving/publishing the post
// so that we can call it if the post entity is checked.
Expand Down Expand Up @@ -216,7 +209,6 @@ export default compose( [
getCurrentPostType,
getCurrentPostId,
hasNonPostEntityChanges,
getPostEntityBlockMetadataChanges,
isSavingNonPostEntityChanges,
getEditedPostAttribute,
getPostEdits,
Expand All @@ -237,8 +229,6 @@ export default compose( [
postStatus: getEditedPostAttribute( 'status' ),
postStatusHasChanged: getPostEdits()?.status,
hasNonPostEntityChanges: hasNonPostEntityChanges(),
getPostEntityBlockMetadataChanges:
getPostEntityBlockMetadataChanges(),
isSavingNonPostEntityChanges: isSavingNonPostEntityChanges(),
};
} ),
Expand Down
16 changes: 2 additions & 14 deletions packages/editor/src/store/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,24 +125,12 @@ export const hasNonPostEntityChanges = createRegistrySelector(
( entityRecord ) =>
entityRecord.kind !== 'postType' ||
entityRecord.name !== type ||
entityRecord.key !== id
entityRecord.key !== id ||
entityRecord.hasMetaChanges
);
}
);

export const getPostEntityBlockMetadataChanges = createRegistrySelector(
( select ) => ( state ) => {
const postEdits =
select( coreStore ).__experimentalGetDirtyEntityRecordsEdits();

const id = getCurrentPostId( state );

if ( postEdits && postEdits[ id ]?.meta ) {
return postEdits[ id ].meta;
}
}
);

/**
* Returns true if there are no unsaved values for the current edit session and
* if the currently edited post is new (has never been saved before).
Expand Down

0 comments on commit b9e7cde

Please sign in to comment.