-
Notifications
You must be signed in to change notification settings - Fork 4.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Test: Move the merge block handler to the actions file and unit test it #769
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,22 @@ | |
import { get } from 'lodash'; | ||
import { parse, stringify } from 'querystring'; | ||
|
||
export function focusBlock( uid, config ) { | ||
return { | ||
type: 'UPDATE_FOCUS', | ||
uid, | ||
config, | ||
}; | ||
} | ||
|
||
export function replaceBlocks( uids, blocks ) { | ||
return { | ||
type: 'REPLACE_BLOCKS', | ||
uids, | ||
blocks, | ||
}; | ||
} | ||
|
||
export function savePost( dispatch, postId, edits ) { | ||
const toSend = postId ? { id: postId, ...edits } : edits; | ||
const isNew = ! postId; | ||
|
@@ -41,3 +57,42 @@ export function savePost( dispatch, postId, edits ) { | |
} ); | ||
} ); | ||
} | ||
|
||
export function mergeBlocks( dispatch, blockA, blockB ) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similar to what we did with concatChildren, I wonder if this needs to be necessarily limited to merging two blocks (unless it becomes much more complex). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes not as easy as |
||
const blockASettings = wp.blocks.getBlockSettings( blockA.blockType ); | ||
|
||
// Only focus the previous block if it's not mergeable | ||
if ( ! blockASettings.merge ) { | ||
dispatch( focusBlock( blockA.uid ) ); | ||
return; | ||
} | ||
|
||
// We can only merge blocks with similar types | ||
// thus, we transform the block to merge first | ||
const blocksWithTheSameType = blockA.blockType === blockB.blockType | ||
? [ blockB ] | ||
: wp.blocks.switchToBlockType( blockB, blockA.blockType ); | ||
|
||
// If the block types can not match, do nothing | ||
if ( ! blocksWithTheSameType || ! blocksWithTheSameType.length ) { | ||
return; | ||
} | ||
|
||
// Calling the merge to update the attributes and remove the block to be merged | ||
const updatedAttributes = blockASettings.merge( blockA.attributes, blocksWithTheSameType[ 0 ].attributes ); | ||
|
||
dispatch( focusBlock( blockA.uid, { offset: -1 } ) ); | ||
dispatch( replaceBlocks( | ||
[ blockA.uid, blockB.uid ], | ||
[ | ||
{ | ||
...blockA, | ||
attributes: { | ||
...blockA.attributes, | ||
...updatedAttributes, | ||
}, | ||
}, | ||
...blocksWithTheSameType.slice( 1 ), | ||
] | ||
) ); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really don't like the idea of Editable assuming a context with the editor's store, but it sure would be nice if
onMerge
here were theconnect
ed dispatch, wouldn't it? 😄 Since it means blocks wouldn't need to pass this through at all.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but it's not that simple. Imagine a block having multiple editables. So the merge of the last one would probably merge its content with the previous one (or do nothing) but the merge of the first editable would actually trigger the merge with the previous block.
It could be way simpler if it's one block = one editable, but that's not the case. Could we provide more "metadata" on how the block uses the editable in this case and fallback to one editable mergeable with the previous block if this metadata is not provided? I don't know but that's something we should think about.
example:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, that's a good point. I hadn't considered this.
Interesting idea. I think at the point where we're saying a block implementer needs to be concerned with merge behavior (and it's fairly obvious they do), I'm not as much concerned about accepting and applying the
onMerge
prop handling anymore.It could be slightly more optimized if Editable were able to handle this by hints, but I'm not sure a clean way we can connect the Editable to the editor's store without tying it directly to the editor (not so great).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To your points here, do you think it's obvious to the block implementer what's happening when they pass
mergeBlocks
to an editable, specifically in merging with a previous block, next block, or between editables of the same block?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should be well documented. It's not obvious at all for now but I don't have any alternative. We should enhance our block API documentation once it's more stable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cc @mtias since we'd chatted about this topic today. Maybe for the sake of simplicity we don't allow complex merging within a block, and try to make editor smarter about knowing how to handle Editables. It's a very fuzzy desire, but maybe traversing returned element to find first or last editable to decide how to merge into previous or next. @mtias indicated some desire to avoid merging and transforms being responsibility of block at all, which sounds nice; difficult to pull off 😄 But I think it'd be fair to make some compromises about what merging can be performed if it helps simplify.
I don't think this needs to be settled here; in fact,
mergeBlocks
could very well be compatible with this future desire. Just a matter of usingcontext
to communicate directly betweenVisualEditorBlock
andEditable
to avoid block needing to handle directly.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I missed this comment @aduth. Let's create an issue for this so we don't lose sight of it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See #878