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

Reuse and unify post and page actions, accross the different use cases. #59849

Closed
wants to merge 11 commits into from

Conversation

jorgefilipecosta
Copy link
Member

This PR implements the post and page actions in a single place (editor packages):
And reuses the actions in the following scenarios:

  • Dataviews item action and bulk action.
  • Details view actions (left sidebar).
  • Edit site page inspector.
  • Edit post inspector.

The edit post inspector in trunk does not contain a "summary view at the top with the actions" this PR adds it to make things consistent.

Screenshots

Screenshot 2024-03-13 at 21 24 18 Screenshot 2024-03-13 at 21 25 11 Screenshot 2024-03-13 at 21 31 38 Screenshot 2024-03-13 at 21 32 10

Testing Instructions for Keyboard

Verified in all the cases where the page actions are used that they work as expected.

@jorgefilipecosta jorgefilipecosta added [Type] Enhancement A suggestion for improvement. [Type] Code Quality Issues or PRs that relate to code quality labels Mar 13, 2024
Copy link

Warning: Type of PR label mismatch

To merge this PR, it requires exactly 1 label indicating the type of PR. Other labels are optional and not being checked here.

  • Type-related labels to choose from: [Type] Automated Testing, [Type] Breaking Change, [Type] Bug, [Type] Build Tooling, [Type] Code Quality, [Type] Copy, [Type] Developer Documentation, [Type] Enhancement, [Type] Experimental, [Type] Feature, [Type] New API, [Type] Task, [Type] Technical Prototype, [Type] Performance, [Type] Project Management, [Type] Regression, [Type] Security, [Type] WP Core Ticket, Backport from WordPress Core.
  • Labels found: [Type] Enhancement, [Type] Code Quality.

Read more about Type labels in Gutenberg. Don't worry if you don't have the required permissions to add labels; the PR reviewer should be able to help with the task.

Copy link

github-actions bot commented Mar 13, 2024

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org>
Co-authored-by: youknowriad <youknowriad@git.wordpress.org>
Co-authored-by: mcsf <mcsf@git.wordpress.org>
Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@ntsekouras
Copy link
Contributor

That's a great start, thanks! We can start testing/reviewing here, but at first sight I was wondering if we could split this to some chunks to make things easier. There are quite a few changes here and we might miss some things and also this PR might take a bit more time to land..

What do you think? For example PostSidebarCard would land super quick 😄

postRevisionsAction,
} = postManagementActions;

function PostActions( { postType, postId } ) {
Copy link
Contributor

Choose a reason for hiding this comment

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

What is specific about edit-post that is forcing us to override the default "editor" PostActions?

Copy link
Member Author

Choose a reason for hiding this comment

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

When we execute an action, it may require us to navigate to a different page. For example, when we delete a post while editing it, we need to navigate to a completely different page using "window.location.href". This is a unique requirement on the edit-post. We are not replacing the action, but rather, we are adding specific callbacks to the onPerform function when needed.

Copy link
Contributor

Choose a reason for hiding this comment

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

But it's almost always the same kind of override. So rather than all of this complex code, some simple onNavigateToList/onNavigateToPost props or something like that could work.

Copy link
Member Author

Choose a reason for hiding this comment

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

But it's almost always the same kind of override. So rather than all of this complex code, some simple onNavigateToList/onNavigateToPost props or something like that could work.

That would work. Thank you for the suggestion @youknowriad 👍 Another possibility is a a generic usePostActions( onPerform ) with a global onPerform( actionId, items) that receives the actionId and the items where the action was executed. And then the usage would be very simple:

usePostActions( onPerform( actionId, items)=> {
switch(actionId)
case: moveToTrass
case: permanentlyDelete:
onNavigateToList();
break:
case: editPost:
navigateToPost
} );

Let me know which API would you prefer a onNavigateToList and a onNavigateToPost or a global onPerform.

Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe the generic onPerform is slightly better.

Copy link
Contributor

Choose a reason for hiding this comment

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

  • onPerform is not very obvious. Maybe onNavigateAfterAction? onAfterAction? onActionPerformed?
  • I wonder whether that API is too powerful, though. Concerns:
    • For the reader, how obvious is it that this prop is meant to strictly set whether and where to route after the action is completed?
    • Is there a clearer and stricter alternative?
    • Does this introduce indirection, in the sense that the reader needs to juggle two distinct components to understand the whole cascade of effects?
    • (This is not a strong opinion, just caution.)

Copy link
Member Author

Choose a reason for hiding this comment

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

Good points. The onPerform may be used for other things besides navigation e.g: close a menu after the action is performed etc. And we already had onPerform for actions before:

if ( onPerform ) {
onPerform();
}
closeModal();

But not all of the actions had it.

I think I will go for onActionPerformed, it more clear on what it does and what is expected when compared with just onPerform.

postId: post.id,
postType: post.type,
canvas: 'edit',
} );
Copy link
Contributor

Choose a reason for hiding this comment

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

I believe we have some "commands" that either navigate using the url or use history depending on whether we detect that we're in the site editor. Can't we do the same thing within the shared action and avoid overriding it entirely?

Copy link
Member Author

Choose a reason for hiding this comment

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

The action itself does not determine whether navigation is necessary or not. For instance, on data views (such as the posts list), the action is used as it is, without requiring any navigation. It is the specific location where the action is utilized that determines whether performing an action has a side effect, such as navigation.

The commands always navigate to the site editor, even if the post was in the post editor:

				const targetUrl = addQueryArgs( 'site-editor.php', args );
				if ( isSiteEditor ) {
					history.push( args );
				} else {
					document.location = targetUrl;
				} 

When we are in the post editor and a post is deleted we want to go back to the "old post" list "edit.php?post_type=page" at least for now. We may also need to go to "edit.php?post_type=post" or to "edit.php?post_type=custom_post_type" so we don't want to go to the site editor every time like in commands.

We could have in the editor something like

usePostActions(withNavigation =true/false)

Where
usePostActions(false) is used on dataviews.

usePostActions(true) is used on post editor, site editor details and site editor inspector.

When it is true we would have some logic to check if we are in the site editor isSiteEditor(). If yes we navigate in a way if not we navigate in another way. But that approach seems wrong to me it is editor package that is implementing the specific logic of post-edit, and site-edit while to me it seems it should be the other way around.

return actions;
}

export default function PostActions( { postType, postId } ) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why are we overriding the default PostActions here, what's specific to the site editor?

Copy link
Member Author

Choose a reason for hiding this comment

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

As referred above what is specific in this case is that for certain actions we need to navigate using history.push, while in other cases we should not navigate at all or we should navigate to a different page.

@jorgefilipecosta
Copy link
Member Author

That's a great start, thanks! We can start testing/reviewing here, but at first sight I was wondering if we could split this to some chunks to make things easier. There are quite a few changes here and we might miss some things and also this PR might take a bit more time to land..

What do you think? For example PostSidebarCard would land super quick 😄

Hi @ntsekouras, yes the idea is to merge things in chunks but having a working end result, allows us to have a better idea of the direction.

A PR for PostSidebarCard is available at #59870.
The next PR is one that just moves the actions to WordPress editor without using the actions in new places.
And the final PR is the usage of the actions across the new places.

);
}

// Copied as is from packages/dataviews/src/utils.js
Copy link
Contributor

Choose a reason for hiding this comment

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

Sometimes just copying + duplicating a small thing is nice, rather than defaulting to DRY. I think it's underrated, even. But in this case I would either:

  • Duplicate directly to where it will be used, i.e. editor/src/components/post-actions/index.js and don't export as a util.
  • Make the decision to upgrade WithDropDownMenuSeparators to something reusable, in which case it belongs in @wordpress/components alongside DropdownMenuSeparator. Although, honestly, I'm more in favour of the first option for now.

Copy link
Member Author

Choose a reason for hiding this comment

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

Hi @mcsf the reason for "post-actions/utility-components.js" was to have a file where everything inside it is duplicated code. But keeping it where it used also works and we can have a "start duplicated components" and an "end duplicated components" mark.

Comment on lines +84 to +85
// Copied as is from packages/dataviews/src/item-actions.js
export function ActionsDropdownMenuGroup( { actions, item } ) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same observation as for WithDropDownMenuSeparators.

postRevisionsAction,
} = postManagementActions;

function PostActions( { postType, postId } ) {
Copy link
Contributor

Choose a reason for hiding this comment

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

  • onPerform is not very obvious. Maybe onNavigateAfterAction? onAfterAction? onActionPerformed?
  • I wonder whether that API is too powerful, though. Concerns:
    • For the reader, how obvious is it that this prop is meant to strictly set whether and where to route after the action is completed?
    • Is there a clearer and stricter alternative?
    • Does this introduce indirection, in the sense that the reader needs to juggle two distinct components to understand the whole cascade of effects?
    • (This is not a strong opinion, just caution.)

Comment on lines +52 to +54
if ( props.onPerform ) {
props.onPerform();
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Just for fun:

Suggested change
if ( props.onPerform ) {
props.onPerform();
}
props.onPerform?.();

Co-authored-by: Miguel Fonseca <150562+mcsf@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Type] Code Quality Issues or PRs that relate to code quality [Type] Enhancement A suggestion for improvement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants