-
Notifications
You must be signed in to change notification settings - Fork 14.4k
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
feat(explore): Show confirmation modal if user exits Explore without saving changes #20902
Conversation
Codecov Report
@@ Coverage Diff @@
## master #20902 +/- ##
==========================================
- Coverage 66.56% 66.55% -0.02%
==========================================
Files 1790 1791 +1
Lines 68393 68437 +44
Branches 7279 7284 +5
==========================================
+ Hits 45526 45546 +20
- Misses 20990 21012 +22
- Partials 1877 1879 +2
Flags with carried forward coverage won't be shown. Click here to find out more.
📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more |
/testenv up |
@jinghua-qa Ephemeral environment spinning up at http://35.86.174.73:8080. Credentials are |
// eslint-disable-next-line import/no-extraneous-dependencies | ||
import { PromptProps } from 'react-router'; | ||
|
||
const handleUnloadEvent = (e: BeforeUnloadEvent) => { |
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.
If someone tries to reuse this component to guard against route changes at two places in the same tree, I think there might be unexpected behavior because all addEventListener
/removeEventListener
calls from different instances of the component will reference the same function. How about moving it inside the component body so it's re-defined for each instantiation?
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.
Good point!
@kgabryje I'm not sure if this is fixable or if it was like this before, but I noticed that if you have unsaved changes and try to navigate to Dashboard, even if you click "cancel" the navigation indicator stays on Dashboard: |
@kgabryje Also not sure if this was intentional, but I noticed that if you edit the chart title but clicking directly on the rendered title and edit it, the "Altered" tag appears but it doesn't block navigation away. |
That's an existing bug - you can try it by going to charts list, then, dashboards list, then click "back" - dashboards will still be highlighted |
Oops, well spotted! |
@jinghua-qa can we test what happens when the chart is running on a query? Does it show the correct save chart modal with the dialog to save a dataset? |
/testenv up |
@jinghua-qa Ephemeral environment spinning up at http://18.236.190.110:8080. Credentials are |
I think it makes sense! @kasiazjc wdyt? |
Good point, I'm thinking - maybe for consistency we should follow chrome flow actually instead of adding this one. Your chart is not saved Thoughts? |
Do we have a final plan for this design? My personal feeling is will be great to have all, [Cancel][Leave][Save], if that is too complicated, i think i will vote for [Cancel][Leave] which is consistent with the chrome flow, and i can always cancel and do save on explore. |
I try to avoid adding 3 buttons as much as possible, as it can get quite confusing. After clicking "save" we would still have to open "save" modal, so I would say let's go with [Cancel][Leave] @kgabryje |
[Cancel] [Leave] makes the most sense to me too! As a user I think I'd expect there to be an option to just cancel the close. |
6cd3a91
to
97b60e9
Compare
@@ -337,7 +375,7 @@ function ExploreViewContainer(props) { | |||
} | |||
|
|||
function toggleModal() { | |||
setShowingModal(!showingModal); | |||
props.actions.setSaveModalVisible(!props.isSaveModalVisible); |
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 PR might be re-triggering the annoying bug that forced us to revert these two PRs:
Screen.Recording.2022-09-07.at.1.01.05.AM.mov
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 don't think we were able to solve it: IIRC it seemed to happen whenever we tried to send additional Redux actions at the same time as when Explore was rendering. Here's the PR that would have fixed it if we hadn't reverted the whole thing. Not sure if your case is similar? I think that also might be why Cypress is failing on yours.
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 also noticed that if I Save As and it doesn't refresh, it'll then show the modal every time even if I save it again.
/testenv up |
@jinghua-qa Ephemeral environment spinning up at http://34.211.247.176:8080. Credentials are |
SUMMARY
This PR adds a browser confirmation modal (similar to the one that we have in dashboard edit mode) when user makes a change in control panel and then tries to close Explore (either by closing the tab or moving to another page) without clicking Save button.
The modal that displays when user navigates out of SPA context (some external page or a Superset page that hasn't been migrated to SPA yet) or closes the tab, is not customizable.
In the case of navigating within SPA context, we can easily display a custom message in the modal thanks to react-router's
Prompt
component. However, displaying a custom modal instead of the default one rendered by<Prompt />
requires more effort and will be handled in a separate PR.CC @kasiazjc
BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF
Screen.Recording.2022-09-06.at.13.10.28.mov
TESTING INSTRUCTIONS
KNOWN LIMITATION: if the previous page is a SPA route (for example you opened Explore from charts list), clicking browser back button will not trigger the confirmation modal. It's very bugged in react-router and I decided to disable it for now. We'll try to find a workaround in the future
ADDITIONAL INFORMATION