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

Migrate Edit Navigation screen "Delete menu" button from confirm() #37492

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 35 additions & 21 deletions packages/edit-navigation/src/components/sidebar/delete-menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,45 @@
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { Button, PanelBody } from '@wordpress/components';
import {
Button,
PanelBody,
__experimentalConfirmDialog as ConfirmDialog,
} from '@wordpress/components';
import { useState } from '@wordpress/element';

export default function DeleteMenu( { onDeleteMenu, isMenuBeingDeleted } ) {
const [ showConfirmDialog, setShowConfirmDialog ] = useState( false );

const handleConfirm = () => {
setShowConfirmDialog( false );
onDeleteMenu();
Comment on lines +16 to +17
Copy link
Member

@kevin940726 kevin940726 Jan 24, 2022

Choose a reason for hiding this comment

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

Maybe we should await for onDeleteMenu() to finish? (I think it returns a promise?)

Bonus point if we can also catch errors here and display the message somewhere, but that's probably best for a different PR.

Another micro-optimization we can make is to show a loading state when the menu is still being deleted. Something like disabling the confirm button and showing a loading icon on the button. But again, probably best for a follow-up PR (I don't think it's possible now with the current API in __experimentalConfirmDialog anyway).

These are all just nitpicking though, I think we can merge this and work on those if needed.

Copy link
Contributor

@ciampo ciampo Jan 24, 2022

Choose a reason for hiding this comment

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

Maybe we should await for onDeleteMenu() to finish? (I think it returns a promise?)`

Hard to say for sure without any docs in this component.

I did a quick search in the codebase, and it looks like the only usage is in packages/edit-navigation/src/components/layout/index.js. In that case, the deleteMenu function comes from the useNavigationEditor() hook, and it is indeed an async function.

So yeah, we could technically

await onDeleteMenu();
setShowConfirmDialog( false );

Bonus point if we can also catch errors here and display the message somewhere, but that's probably best for a different PR.

Given the delete function definition, it looks like errors are handled via the createErrorNotice function, which seems to be connected to the notices store — I'm not familiar with what's the best "gutenberg" way to handle that?

Another micro-optimization we can make is to show a loading state when the menu is still being deleted. Something like disabling the confirm button and showing a loading icon on the button. But again, probably best for a follow-up PR (I don't think it's possible now with the current API in __experimentalConfirmDialog anyway).

We should have access to the loading state via the isMenuBeingDeleted prop passed to this component, but I don't think that the ConfirmDialog supports a way to disable its confirm button from outside the component (@fullofcaffeine can you confirm?)

Copy link
Member

Choose a reason for hiding this comment

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

c.c. @adamziel as this is a good example of lacking a clear and simple way to do loading state + error handling with the current API 😆 . (#38135)

Copy link
Member

@fullofcaffeine fullofcaffeine Jan 25, 2022

Choose a reason for hiding this comment

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

supports a way to disable its confirm button from outside the component (@fullofcaffeine can you confirm?)

You're right, that's not supported at the moment. I think it's a great improvement idea! What would that API look like do you think? A simple isLoading boolean prop that would disable the button and show a loading spinner when true?

Copy link
Member

Choose a reason for hiding this comment

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

A simple isLoading boolean prop that would disable the button and show a loading spinner when true?

Yeah, I think so. Since it should be a common feature, we can allow a simple prop like isLoading or disabled to do the job.

Copy link
Contributor

Choose a reason for hiding this comment

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

A simple isLoading boolean prop that would disable the button and show a loading spinner when true?

I think I like the sound of isDisabled more as it is closer to what we want to achieve — disable interactions with the modal. Let's also add a is in front of the prop to make it clear that it's a boolean flag.

We also have to disable pressing the ESC key and clicking on the background, and we'll have to make this feature work both in controlled and uncontrolled mode. We can discuss further these details and refine the UX separately in the PR implementing the feature.

};

return (
<PanelBody>
<Button
className="edit-navigation-inspector-additions__delete-menu-button"
variant="secondary"
isDestructive
isBusy={ isMenuBeingDeleted }
onClick={ () => {
if (
// eslint-disable-next-line no-alert
window.confirm(
__(
'Are you sure you want to delete this navigation? This action cannot be undone.'
)
)
) {
onDeleteMenu();
}
} }
>
{ __( 'Delete menu' ) }
</Button>
<>
<Button
className="edit-navigation-inspector-additions__delete-menu-button"
variant="secondary"
isDestructive
isBusy={ isMenuBeingDeleted }
onClick={ () => {
setShowConfirmDialog( true );
} }
ciampo marked this conversation as resolved.
Show resolved Hide resolved
>
{ __( 'Delete menu' ) }
</Button>
<ConfirmDialog
isOpen={ showConfirmDialog }
onConfirm={ handleConfirm }
onCancel={ () => setShowConfirmDialog( false ) }
ciampo marked this conversation as resolved.
Show resolved Hide resolved
>
{ __(
'Are you sure you want to delete this navigation? This action cannot be undone.'
) }
</ConfirmDialog>
</>
</PanelBody>
);
}