Skip to content

[Discover] Add unsaved changes modal (#218500)#225252

Merged
AlexGPlay merged 15 commits intoelastic:mainfrom
AlexGPlay:218500-unsaved-changes-modal
Aug 11, 2025
Merged

[Discover] Add unsaved changes modal (#218500)#225252
AlexGPlay merged 15 commits intoelastic:mainfrom
AlexGPlay:218500-unsaved-changes-modal

Conversation

@AlexGPlay
Copy link
Contributor

@AlexGPlay AlexGPlay commented Jun 25, 2025

Summary

Closes #218500

When there are unsaved changes in Discover a modal will prompt the user to either risk losing them or not leaving the page.

unsaved.changes.modal.mov

Checklist

Check the PR satisfies following conditions.

Reviewers should verify this PR satisfies this list as well.

@AlexGPlay AlexGPlay self-assigned this Jun 25, 2025
Comment on lines 114 to 137
const tabs = runtimeStateManager.tabs.byId;
const hasAnyUnsavedTab = Object.values(tabs).some((tab) => {
const stateContainer = tab.stateContainer$.getValue();
if (!stateContainer) {
return false;
}

return stateContainer.savedSearchState.getHasChanged$().getValue();
});

if (!hasAnyUnsavedTab) return actions.default();

return actions.confirm(
i18n.translate('discover.confirmModal.confirmTextDescription', {
defaultMessage: 'Leaving Discover without saving may result in lost changes.',
}),
i18n.translate('discover.confirmModal.title', {
defaultMessage: 'Unsaved changes',
})
);
});
Copy link
Member

Choose a reason for hiding this comment

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

Thx @AlexGPlay , so this already works for tabs, which is great, but I guess this could also be tied to

TABS_ENABLED?

or, it should just be tied getHasChanged$()., but then it would work out of the box for Discover, something we could consider

interested in hearing your opinion @elastic/kibana-data-discovery 🙏

Copy link
Contributor

Choose a reason for hiding this comment

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

It looks like the current logic would work both when tabs are and aren't enabled, which is great. But whether or not we want to enable it before tabs are released is a separate product question. If we don't want to enable it until then, we could definitely throw in a TABS_ENABLED condition.

Copy link
Member

@kertal kertal Jun 27, 2025

Choose a reason for hiding this comment

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

FYI @ninoslavmiskovic this is a feature of tabs, we could already release, warning the users that they might loose there changes when leaving Discover. With our "Single" tab mode, there's less to loose, but still. wdyt

a) Yes, let's use it already
b) No, let's use it when tabs is enabled
c) Let's discuss it on Monday, after the beach party with the flaky ones

Copy link
Contributor

Choose a reason for hiding this comment

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

a) it seems risk free and good ux.

Just so I understand this is only for dirty state of a Discover session ?

Not general ad-hoc data exploration? If yes then a) .

Just want to make sure we do not annoy existing scratch pad / ad hoc explores.

Copy link
Contributor

Choose a reason for hiding this comment

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

Great, let's make the final call in our Monday sync then. I won't be there, but I'm happy with whatever the team decides.

++ to the "only for dirty state" comment. I haven't tested locally to confirm it works that way, but that should be a requirement.

Two questions to consider since I won't be in Monday:

  • Should we offer a third button to quickly open the save modal and reduce friction, e.g. "Cancel" / "Save my session" / "Continue without saving"? Again, probably need copy input for title/body/buttons.
  • Should we offer a "Don't ask me again" checkbox for users who find it annoying / don't care, similar to the ES|QL -> classic mode modal?

Might even be worth referring to the ES|QL modal for inspiration:
CleanShot 2025-06-27 at 15 44 13@2x

Copy link
Member

Choose a reason for hiding this comment

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

@florent-leborgne good hint, thx 👍

So I guess it should work like this

CleanShot 2025-07-01 at 12 27 43

Copy link
Contributor

@andreadelrio andreadelrio Jul 2, 2025

Choose a reason for hiding this comment

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

@kertal I agree with following the EUI guidelines. In this case, we'd need to update the ES|QL and Lens modals as well. We'll also need to align in the color of the button and the use (or not) of icons. Also, in the screenshot from EUI, I would make Leave anyway a danger action.

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've been taking a look at this and there are a couple of things here:

  • With the current tools that onAppLeave provides we can't do the "Don't ask me again" checkbox because it provides very limited functionality, pretty much a yes/no question and that's it. Hooking up our own component here isn't doable right now either.
  • This confirmation modal kind of works the opposite as we want, it only allows for actions when the user stays in the page but no when leaving it. What I mean is that we can't have a Save changes that saves the changes and leaves the page. It's pretty much the opposite, like "Stay and save" or "Leave the page"
Copy link
Member

Choose a reason for hiding this comment

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

thank you @AlexGPlay , So think we need to decide the following due to the limitations:

Should we move forward with the given approach as a first step?

I think what we are discussing here needs a separate issue, will involve more teams, and it's something we should do, but currently, as @AlexGPlay mentions we are limited in this area. We can't provide a custom onAppLeave experience, which would in our case similar like when users want to open new discover sessions, and they are warned they have unsaved changes.

interested in hearing the teams opinion 🙏

Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm yeah that definitely has an impact on our plans, thanks for looking into it @AlexGPlay. I agree for the scope of this PR we don't have much choice but to work with what's available to us for now. We can definitely follow up after and see if we can enhance this since I think there's value in offering more than what's possible currently, but even the more limited experience is an improvement on what we have today.

@AlexGPlay AlexGPlay added release_note:fix Team:DataDiscovery Discover, search (data plugin and KQL), data views, saved searches. For ES|QL, use Team:ES|QL. t// Feature:UnifiedDocViewer Issues relating to the unified doc viewer component and removed release_note:fix Team:DataDiscovery Discover, search (data plugin and KQL), data views, saved searches. For ES|QL, use Team:ES|QL. t// Feature:UnifiedDocViewer Issues relating to the unified doc viewer component labels Jun 27, 2025
@AlexGPlay AlexGPlay force-pushed the 218500-unsaved-changes-modal branch from a32106f to 3562306 Compare July 7, 2025 06:57
@AlexGPlay AlexGPlay force-pushed the 218500-unsaved-changes-modal branch 2 times, most recently from 7cbe949 to f2a3e69 Compare July 21, 2025 06:38
@AlexGPlay AlexGPlay marked this pull request as ready for review July 21, 2025 13:21
@AlexGPlay AlexGPlay requested a review from a team as a code owner July 21, 2025 13:21
@AlexGPlay AlexGPlay added release_note:enhancement Team:DataDiscovery Discover, search (data plugin and KQL), data views, saved searches. For ES|QL, use Team:ES|QL. t// labels Jul 24, 2025
@elasticmachine
Copy link
Contributor

Pinging @elastic/kibana-data-discovery (Team:DataDiscovery)

Copy link
Contributor

@davismcphee davismcphee left a comment

Choose a reason for hiding this comment

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

Code changes look good overall and it worked well when testing! Just left a bit of feedback.

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for updating these tests to RTL!

Comment on lines 129 to 137
return actions.confirm(
i18n.translate('discover.confirmModal.confirmTextDescription', {
defaultMessage: 'Leaving Discover without saving may result in lost changes.',
}),
i18n.translate('discover.confirmModal.title', {
defaultMessage: 'Unsaved changes',
})
);
});
Copy link
Contributor

Choose a reason for hiding this comment

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

@florent-leborgne Could we get a quick copy check on this? We're a bit limited in what we can do with the modal technically since it's managed by code outside of Discover, basically a "yes, leave" or "no, stay" choice for the user. We can only customize the title, body, and confirm button text + colour.

The caveat is that they're not guaranteed to lose their changes (depends on if they navigate to another Discover link before returning), but there's a chance they will if they don't save. This is what it currently looks like:

And the Lens one for comparison:

I know there was some discussion about making broader changes to the various confirmation modals, but we're aiming to keep this PR scoped to just this Discover modal for now.

Copy link
Contributor

Choose a reason for hiding this comment

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

Could something like this work? We can tweak the body if what I wrote isn't exactly it, but I feel like saying just "may" is too vague

image
Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks @florent-leborgne, I think that works for now and is an improvement over what we had before. There might be a bit more nuance to consider here, but not worth me holding up the PR over. @AlexGPlay Could you please implement these changes in the PR?

CC @ninoslavmiskovic for awareness. We may want to discuss more and clarify the messaging here, but we can merge this for now and do any necessary changes in a small followup PR if needed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated - it looks like this
image

@AlexGPlay AlexGPlay force-pushed the 218500-unsaved-changes-modal branch from aaa0dab to 535000c Compare July 30, 2025 08:07
@AlexGPlay AlexGPlay requested a review from a team as a code owner July 30, 2025 08:07
@AlexGPlay AlexGPlay removed the request for review from a team July 30, 2025 08:44
@kertal kertal added the Feature:Discover Discover Application label Jul 31, 2025
Copy link
Contributor

@davismcphee davismcphee left a comment

Choose a reason for hiding this comment

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

Apologies for the delay, and thanks for making the requested changes! Just some minor changes to the confirmation modal left, but otherwise LGTM so approving now 👍

Comment on lines 129 to 137
return actions.confirm(
i18n.translate('discover.confirmModal.confirmTextDescription', {
defaultMessage: 'Leaving Discover without saving may result in lost changes.',
}),
i18n.translate('discover.confirmModal.title', {
defaultMessage: 'Unsaved changes',
})
);
});
Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks @florent-leborgne, I think that works for now and is an improvement over what we had before. There might be a bit more nuance to consider here, but not worth me holding up the PR over. @AlexGPlay Could you please implement these changes in the PR?

CC @ninoslavmiskovic for awareness. We may want to discuss more and clarify the messaging here, but we can merge this for now and do any necessary changes in a small followup PR if needed.

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for adding functional tests 👍

Copy link
Contributor

Choose a reason for hiding this comment

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

I won't hold up merging the PR over it, but I still don't like the idea of maintaining dedicated mocks for things when the real implementations are readily available, and in general would encourage us to use the real implementations whenever possible. It can help isolate the test logic, but pulls it further away from the actual runtime behaviour which is more important IMO.

@davismcphee davismcphee added the backport:skip This PR does not require backporting label Aug 5, 2025
@AlexGPlay AlexGPlay force-pushed the 218500-unsaved-changes-modal branch from 17dccfb to 0fe671d Compare August 11, 2025 07:55
@elasticmachine
Copy link
Contributor

💛 Build succeeded, but was flaky

Failed CI Steps

Test Failures

  • [job] [logs] FTR Configs #60 / Dataset Quality Dataset quality handles user privileges User can read logs-* User can monitor some data streams "before all" hook for "shows underprivileged warning when size cannot be accessed for some data streams"
  • [job] [logs] FTR Configs #38 / Search solution tests Search Home page Solution Nav - Search search home page with existing indices "before each" hook for "displays the feedbacks link"

Metrics [docs]

Async chunks

Total size of all lazy-loaded chunks that will be downloaded as the user navigates the app

id before after diff
discover 1.1MB 1.1MB +693.0B

Public APIs missing exports

Total count of every type that is part of your API that should be exported but is not. This will cause broken links in the API documentation system. Target amount is 0. Run node scripts/build_api_docs --plugin [yourplugin] --stats exports for more detailed information.

id before after diff
discover 28 29 +1

Page load bundle

Size of the bundles that are downloaded on every page load. Target size is below 100kb

id before after diff
discover 22.8KB 22.8KB +24.0B

History

cc @AlexGPlay

@AlexGPlay AlexGPlay merged commit 14828f6 into elastic:main Aug 11, 2025
12 checks passed
NicholasPeretti pushed a commit to NicholasPeretti/kibana that referenced this pull request Aug 18, 2025
## Summary

Closes elastic#218500

When there are unsaved changes in Discover a modal will prompt the user
to either risk losing them or not leaving the page.


https://github.com/user-attachments/assets/c516b3a7-0954-496b-8494-574ba8547d27

### Checklist

Check the PR satisfies following conditions. 

Reviewers should verify this PR satisfies this list as well.

- [x] Any text added follows [EUI's writing
guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses
sentence case text and includes [i18n
support](https://github.com/elastic/kibana/blob/main/src/platform/packages/shared/kbn-i18n/README.md)
- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
- [x] The PR description includes the appropriate Release Notes section,
and the correct `release_note:*` label is applied per the
[guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
qn895 pushed a commit to qn895/kibana that referenced this pull request Aug 26, 2025
## Summary

Closes elastic#218500

When there are unsaved changes in Discover a modal will prompt the user
to either risk losing them or not leaving the page.


https://github.com/user-attachments/assets/c516b3a7-0954-496b-8494-574ba8547d27

### Checklist

Check the PR satisfies following conditions. 

Reviewers should verify this PR satisfies this list as well.

- [x] Any text added follows [EUI's writing
guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses
sentence case text and includes [i18n
support](https://github.com/elastic/kibana/blob/main/src/platform/packages/shared/kbn-i18n/README.md)
- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
- [x] The PR description includes the appropriate Release Notes section,
and the correct `release_note:*` label is applied per the
[guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport:skip This PR does not require backporting Feature:Discover Discover Application release_note:enhancement Team:DataDiscovery Discover, search (data plugin and KQL), data views, saved searches. For ES|QL, use Team:ES|QL. t// v9.2.0

8 participants