Skip to content

Commit

Permalink
Recursively step through edits to track individually changed post meta (
Browse files Browse the repository at this point in the history
#10827)

* Only send edited meta values as state to editPost

* Recursively step through edits to granularly update state on EDIT_POST

* Don't recurse for arrays

* Editor: Deeply diff/merge edited property edits/updates

* Editor: Pass meta updates from block as patch

* Editor: Shallow merge on whitelisted post property edits
  • Loading branch information
earnjam authored and aduth committed Nov 19, 2018
1 parent 2aea727 commit 6ae6285
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 8 deletions.
7 changes: 1 addition & 6 deletions packages/editor/src/components/block-list/block.js
Original file line number Diff line number Diff line change
Expand Up @@ -179,10 +179,7 @@ export class BlockListBlock extends Component {
}, {} );

if ( size( metaAttributes ) ) {
this.props.onMetaChange( {
...this.props.meta,
...metaAttributes,
} );
this.props.onMetaChange( metaAttributes );
}
}

Expand Down Expand Up @@ -646,7 +643,6 @@ const applyWithSelect = withSelect( ( select, { clientId, rootClientId, isLargeV
isTyping,
isCaretWithinFormattedText,
getBlockIndex,
getEditedPostAttribute,
getBlockMode,
isSelectionEnabled,
getSelectedBlocksInitialCaretPosition,
Expand All @@ -673,7 +669,6 @@ const applyWithSelect = withSelect( ( select, { clientId, rootClientId, isLargeV
isTypingWithinBlock: ( isSelected || isParentOfSelectedBlock ) && isTyping(),
isCaretWithinFormattedText: isCaretWithinFormattedText(),
order: getBlockIndex( clientId, rootClientId ),
meta: getEditedPostAttribute( 'meta' ),
mode: getBlockMode( clientId ),
isSelectionEnabled: isSelectionEnabled(),
initialPosition: getSelectedBlocksInitialCaretPosition(),
Expand Down
21 changes: 19 additions & 2 deletions packages/editor/src/store/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,16 @@ import {
} from './defaults';
import { insertAt, moveTo } from './array';

/**
* Set of post properties for which edits should assume a merging behavior,
* assuming an object value.
*
* @type {Set}
*/
const EDIT_MERGE_PROPERTIES = new Set( [
'meta',
] );

/**
* Returns a post attribute value, flattening nested rendered content using its
* raw value in place of its original object form.
Expand Down Expand Up @@ -244,7 +254,14 @@ export const editor = flow( [
// Only assign into result if not already same value
if ( value !== state[ key ] ) {
result = getMutateSafeObject( state, result );
result[ key ] = value;

if ( EDIT_MERGE_PROPERTIES.has( key ) ) {
// Merge properties should assign to current value.
result[ key ] = { ...result[ key ], ...value };
} else {
// Otherwise override.
result[ key ] = value;
}
}

return result;
Expand All @@ -264,7 +281,7 @@ export const editor = flow( [
( key ) => getPostRawValue( action.post[ key ] );

return reduce( state, ( result, value, key ) => {
if ( value !== getCanonicalValue( key ) ) {
if ( ! isEqual( value, getCanonicalValue( key ) ) ) {
return result;
}

Expand Down
84 changes: 84 additions & 0 deletions packages/editor/src/store/test/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -1040,6 +1040,90 @@ describe( 'state', () => {
} );
} );

it( 'should merge object values', () => {
const original = editor( undefined, {
type: 'EDIT_POST',
edits: {
meta: {
a: 1,
},
},
} );

const state = editor( original, {
type: 'EDIT_POST',
edits: {
meta: {
b: 2,
},
},
} );

expect( state.present.edits ).toEqual( {
meta: {
a: 1,
b: 2,
},
} );
} );

it( 'return state by reference on unchanging update', () => {
const original = editor( undefined, {} );

const state = editor( original, {
type: 'UPDATE_POST',
edits: {},
} );

expect( state.present.edits ).toBe( original.present.edits );
} );

it( 'unset reset post values which match by canonical value', () => {
const original = editor( undefined, {
type: 'EDIT_POST',
edits: {
title: 'modified title',
},
} );

const state = editor( original, {
type: 'RESET_POST',
post: {
title: {
raw: 'modified title',
},
},
} );

expect( state.present.edits ).toEqual( {} );
} );

it( 'unset reset post values by deep match', () => {
const original = editor( undefined, {
type: 'EDIT_POST',
edits: {
title: 'modified title',
meta: {
a: 1,
b: 2,
},
},
} );

const state = editor( original, {
type: 'UPDATE_POST',
edits: {
title: 'modified title',
meta: {
a: 1,
b: 2,
},
},
} );

expect( state.present.edits ).toEqual( {} );
} );

it( 'should omit content when resetting', () => {
// Use case: When editing in Text mode, we defer to content on
// the property, but we reset blocks by parse when switching
Expand Down

0 comments on commit 6ae6285

Please sign in to comment.