Skip to content
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

Block Settings Menu: Adding a duplicate block button #5098

Merged
merged 5 commits into from
Feb 26, 2018

Conversation

youknowriad
Copy link
Contributor

closes #2231

Testing instructions

  • Add any block
  • Open the block settings menu
  • Click "Duplicate"
  • A new block should be created right after the current block

It should also work for multiselection

@youknowriad youknowriad self-assigned this Feb 16, 2018
@@ -486,6 +486,16 @@ export const getBlocks = createSelector(
]
);

export const getBlocksByUid = createSelector(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More accurately: getBlocksByUids

Also need consensus on capitalization pattern getBlocksByUids vs. getBlocksByUIDs

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's your preference on the capitalization, let's make it a guideline ;)?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree a guideline would be good. I don't know which I prefer. I think capitalized abbreviations is more the norm, but there's exceptions. It also makes it difficult when a name has two adjacent abbreviations (imagine an XMLHTTPRequest).

🤷‍♂️

#2511

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess I'd slightly lean toward capitalized abbreviations.

index: getBlockIndex( state, last( ownProps.uids ), ownProps.rootUID ),
} ),
{ insertBlocks },
( { blocks, index }, dispatchProps, { rootUID } ) => ( {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see why it's used here, but I've becoming increasingly cautious of mergeProps upon discovery in #5090 about excessive renders it can incur.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another option would be to do this inside the component. Do you think it's better?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better in performance. Worse in having it become less purely presentational.

🤷‍♂️

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this blocking, I think we should keep it as is and revisit once we update the data module.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be possible to simplify now with #5137

import { insertBlocks } from '../../store/actions';

export function BlockDuplicateButton( { onDuplicate, onClick = noop, isLocked, small = false } ) {
if ( isLocked ) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should also check for useOnce here :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 Good catch

@mtias mtias added [Type] Task Issues or PRs that have been broken down into an individual action to take [Feature] Block API API that allows to express the block paradigm. [Feature] Blocks Overall functionality of blocks labels Feb 21, 2018
@jasmussen
Copy link
Contributor

This is VERY nice. I think this is going to be a very popular feature.

The block ellipsis menu is getting a little crowded, but that's due to the transformations rather than this addition. If we feel it's getting out of hand we can revisit having the transformations in this menu. Not for this PR.

One enhancement to consider for this, is selecting the new block after it's been duplicated. Especially if you multi select three blocks and duplicate, it'd be nice if the three duplicate blocks were simply still selected so you could move them around or whatever.

But no blocker.

👍 👍 nice work!

@youknowriad
Copy link
Contributor Author

One enhancement to consider for this, is selecting the new block after it's been duplicated

It works for a single block, but I'll take a look to see if we can keep the multi-selection as well.

@jasmussen
Copy link
Contributor

It's not a requirement, just a nicety.

@mtias
Copy link
Member

mtias commented Feb 22, 2018

I think we should do the flyout menu for transforms :)

Copy link
Member

@aduth aduth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most of my comments are minor. Seems to work well in my testing.

} ),
{ insertBlocks },
( { blocks, index }, dispatchProps, { rootUID } ) => ( {
blockNames: blocks.map( block => block.name ),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Honestly, it would probably be more efficient to pass in the blocks array in its entirety from getBlocksByUid, since at least that's memoized, not returning a new instance each time.

const type = getBlockType( name );
return ! type.useOnce;
} ) );
if ( isLocked || ! canDuplicate ) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor (since it's not a common scenario): if isLocked is true here, we've wasted effort calculating canDuplicate, when we could have done an early return before the every.

@@ -486,6 +486,16 @@ export const getBlocks = createSelector(
]
);

export const getBlocksByUid = createSelector(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess I'd slightly lean toward capitalized abbreviations.

return map( uids, ( uid ) => getBlock( state, uid ) );
},
( state ) => [
state.editor.present.blockOrder,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does this depend on blockOrder ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, since this depends on getBlock, it should define all of the dependants of getBlock.

Aside: rememo@3.0.0 adds a helper utility for this via getBlock.getDependants (changelog).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I avoided using getDependants because of two things:

  • I have to map over the uids, to call the getDependants of the getBlock
  • I thought it's simpler to just add the global block state as dependants instead of using specific uids since a selector returning multiple blocks.
  • blockOrder is necessary because getBlock depends on blockOrder see getBlockDependantsCacheBust

@youknowriad
Copy link
Contributor Author

I feel like I addressed everything here. Merging.

@youknowriad youknowriad merged commit 6e273fc into master Feb 26, 2018
@youknowriad youknowriad deleted the add/duplicate-button branch February 26, 2018 12:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Block API API that allows to express the block paradigm. [Feature] Blocks Overall functionality of blocks [Type] Task Issues or PRs that have been broken down into an individual action to take
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Allow Duplicating an existing block
4 participants