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

[SharedUX] Merge similar toast messages in case of a toast-flood/storm #161738

Merged
merged 20 commits into from
Jul 27, 2023

Conversation

delanni
Copy link
Contributor

@delanni delanni commented Jul 12, 2023

Summary

This PR addresses the occasional toast-floods/toast-storms with a simple catch mechanism: deduplicate/group toasts by their broad alikeness, their text and title.

This implementation plugs in to the global_toast_list.tsx in Kibana's GlobalToastList component, capturing updates on the toast update stream, and collapses toasts before passing them further to the downstream EUI Toast list react components.

The core idea is to not display notifications directly, but to keep the toast notifications apart from their visual representation. This way, we can represent more notifications with one toast on our end, if we group rightly. The only issue then, is to clean up everything nicely when it's time. For this we're also exporting a mapping that shows which toast ID represents which grouped toasts.

I also changed the type ToastInputFields to accept rendered react components as title/text - this will prevent attempts to unmount react components from elements that are not displayed, thus causing React warnings.

The close-all button is an EUI feature, which we've started discussing here, probably not part of this PR.

What toasts get merged?

The exact merging strategy was not settled, and it's kind of a valve, where we trade off potential detail lost in toasts for the prevented noise in the toast floods. The current strategy is as folows:

 * These toasts will be merged:
 *  - where title and text are strings, and the same (1)
 *  - where titles are the same, and texts are missing (2)
 *  - where titles are the same, and the text's mount function is the same string (3)
 *  - where titles are missing, but the texts are the same string (4)

The base merge case is (1) & (2), after some discussion with @Dosant we decided to include (3) as a compromise, where we're still merging somewhat similar toasts, and extend the merging to ToastsApi::addError where all error toasts have a MountPoint as their text. We understand this might hide some details (e.g.: same titles, but very slightly different MountPoints as their text) but realistically this shouldn't really happen.

The ultimate future improvement will be (as suggested in the comments by @jloleysens) a sort of identifier to the toast, based on which we can group without fear of losing information. But this will require more work on all the call-sites.

Relates to: #161482

1ca12f39-75af-4d24-8906-9f27fad33c45

Checklist

Delete any items that are not applicable to this PR.

For maintainers

@delanni delanni force-pushed the sharedux-deduplicate-toaststorms branch from 31dff78 to 3948f10 Compare July 12, 2023 13:11
@delanni
Copy link
Contributor Author

delanni commented Jul 18, 2023

@elasticmachine merge upstream

@delanni delanni force-pushed the sharedux-deduplicate-toaststorms branch from abb7801 to 7fabc6e Compare July 18, 2023 11:48
@delanni
Copy link
Contributor Author

delanni commented Jul 18, 2023

@elasticmachine merge upstream

@petrklapka petrklapka added the Team:SharedUX Team label for AppEx-SharedUX (formerly Global Experience) label Jul 18, 2023
@delanni delanni changed the title Merge similar toast messages in case of a toast-flood/storm [SharedUX] Merge similar toast messages in case of a toast-flood/storm Jul 18, 2023
@delanni delanni force-pushed the sharedux-deduplicate-toaststorms branch from 31f97a4 to 15dd131 Compare July 19, 2023 08:41
@delanni delanni marked this pull request as ready for review July 19, 2023 10:22
@delanni delanni requested a review from a team as a code owner July 19, 2023 10:22
@elasticmachine
Copy link
Contributor

Pinging @elastic/appex-sharedux (Team:SharedUX)

@delanni delanni self-assigned this Jul 19, 2023
@delanni delanni added release_note:feature Makes this part of the condensed release notes backport:all-open Backport to all branches that could still receive a release v8.10.0 release_note:enhancement and removed release_note:feature Makes this part of the condensed release notes backport:all-open Backport to all branches that could still receive a release labels Jul 19, 2023
@Dosant Dosant removed the v8.10.0 label Jul 19, 2023
@Dosant
Copy link
Contributor

Dosant commented Jul 19, 2023

I've tested, not sure what is wrong, but toasts doesn't seem to always auto-close. Maybe there is a race condition inside the GlobalToastComponent or something like that...

This is what I did:

  1. In Kibana changed advanced settings to make toasts life shorter:
Screenshot 2023-07-19 at 13 59 55
  1. Then went to visualize library > create > tsvb
  2. Opened dev tools and blocked the data request:
Screenshot 2023-07-19 at 14 02 17
  1. Hit reload, see fetch errors as toasts and see them grouped 👍
Screenshot 2023-07-19 at 14 03 17

The problem is that I expect the toasts to go away automatically after 5 seconds, but this doesn't happen

@delanni delanni force-pushed the sharedux-deduplicate-toaststorms branch from 472e6c5 to a231d52 Compare July 25, 2023 13:51
@delanni
Copy link
Contributor Author

delanni commented Jul 25, 2023

@elasticmachine merge upstream

@andreadelrio
Copy link
Contributor

@ryankeairns @andreadelrio Thanks, I also quite like the outside-of-title counter. However, that will probably require an update form EUI to support this on a toast level. I can do this now with absolute positioning but I think it's more prone to errors on the long run, and harder to set up accessibility for. Also, it would relieve us from having to combine a counter with a title in a collapsed notification.

This is what I got with some basic CSS:

position: absolute;
top: -8px;
right: -8px;
scale: 1.2;
Screenshot 2023-07-25 at 9 40 34 If you all like this approach for now, I am happy to shape this up, and commit to this, but I'll need some help from the accessibility aspect.

I think this is fine for the time being. I can create the issue requesting the implementation of the counter in the EUI repo. What do you think @ryankeairns ?

@delanni are you using EuiNotificationBadge in size "m"? I think that size will work nicely.

@ryankeairns
Copy link
Contributor

Yes, this seems like the right approach: quick fix, then replace with EUI solution once available

Thanks all!

Copy link
Contributor

@pgayvallet pgayvallet left a comment

Choose a reason for hiding this comment

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

LGTM

@delanni delanni force-pushed the sharedux-deduplicate-toaststorms branch from d421da7 to f227247 Compare July 26, 2023 12:14
@Dosant Dosant self-requested a review July 26, 2023 12:50
@Dosant
Copy link
Contributor

Dosant commented Jul 26, 2023

@delanni, It seems that MountPoint still has some edge cases, I've tried the following two toasts with different texts set inside the mount point and those are grouped together. I don't think this is expected

const toast1 = () => {
      core.notifications.toasts.addInfo({
        title: 'Hello World!',
        text: (element) => {
          element.innerText = 'Toast text 1';
          return () => {};
        },
      });
    };

    const toast2 = () => {
      core.notifications.toasts.addInfo({
        title: 'Hello World!',
        text: (element) => {
          element.innerText = 'Toast text 2';
          return () => {};
        },
      });
    };

Copy link
Contributor

@Dosant Dosant left a comment

Choose a reason for hiding this comment

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

We discussed in slack:

Currently when grouping we check that title + text are the same if they both are texts. But if there is a MountPoint in one of those, then it skips it and checks just either title or text. This means we might group toasts with completely different contents inside the mount point.

I think that the chance is quite small to miss something important there, but I’d personally prefer a safer route and to always not group if there is a MountPoint

It also seems that if we simplify this MountPoint thing , it means that we won’t ever have a MountPoint in a grouped toast. Then TitleWithBadge could be simplified to not worry about the MountPoint edge case

This is just my opinion and I don't think this is critical, so 👍

@delanni
Copy link
Contributor Author

delanni commented Jul 26, 2023

After syncing with @Dosant , I'm taking a more conservative take on what to merge/collapse. This commit contains the changes (5b6079d) can be reverted alone if we decide we'd want to collapse over MountPoints.

@lukeelmers
Copy link
Member

Maybe with this change we could also finally close #67270?

@Dosant Dosant self-requested a review July 27, 2023 12:27
Copy link
Contributor

@Dosant Dosant left a comment

Choose a reason for hiding this comment

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

I retested with the latest changes, looks great 👍

@Dosant
Copy link
Contributor

Dosant commented Jul 27, 2023

@elasticmachine merge upstream

@kibana-ci
Copy link
Collaborator

💚 Build Succeeded

Metrics [docs]

Module Count

Fewer modules leads to a faster build time

id before after diff
core 449 463 +14

Async chunks

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

id before after diff
core 145.4KB 145.5KB +125.0B

Page load bundle

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

id before after diff
core 361.7KB 369.1KB +7.4KB
Unknown metric groups

ESLint disabled line counts

id before after diff
@kbn/core-notifications-browser-internal 0 2 +2

Total ESLint disabled count

id before after diff
@kbn/core-notifications-browser-internal 0 2 +2

History

To update your PR or re-run it, just comment with:
@elasticmachine merge upstream

cc @delanni @Dosant

@delanni delanni merged commit a487ad7 into elastic:main Jul 27, 2023
@kibanamachine kibanamachine added v8.10.0 backport:skip This commit does not require backporting labels Jul 27, 2023
@delanni delanni deleted the sharedux-deduplicate-toaststorms branch July 27, 2023 15:18
ThomThomson pushed a commit to ThomThomson/kibana that referenced this pull request Aug 1, 2023
elastic#161738)

## Summary
This PR addresses the occasional toast-floods/toast-storms with a simple
catch mechanism: deduplicate/group toasts by their broad alikeness,
their text and title.

This implementation plugs in to the `global_toast_list.tsx` in Kibana's
GlobalToastList component, capturing updates on the toast update stream,
and collapses toasts before passing them further to the downstream EUI
Toast list react components.

The core idea is to not display notifications directly, but to keep the
toast notifications apart from their visual representation. This way, we
can represent more notifications with one toast on our end, if we group
rightly. The only issue then, is to clean up everything nicely when it's
time. For this we're also exporting a mapping that shows which toast ID
represents which grouped toasts.

I also changed the type `ToastInputFields` to accept rendered react
components as title/text - this will prevent attempts to unmount react
components from elements that are not displayed, thus causing React
warnings.

The close-all button is an EUI feature, which we've started discussing
[here](elastic/eui#6945), probably not part of
this PR.

## What toasts get merged?
The exact merging strategy was not settled, and it's kind of a valve,
where we trade off potential detail lost in toasts for the prevented
noise in the toast floods. The current strategy is as folows:
```
 * These toasts will be merged:
 *  - where title and text are strings, and the same (1)
 *  - where titles are the same, and texts are missing (2)
 *  - where titles are the same, and the text's mount function is the same string (3)
 *  - where titles are missing, but the texts are the same string (4)
``` 
The base merge case is `(1) & (2)`, after some discussion with @Dosant
we decided to include (3) as a compromise, where we're still merging
somewhat similar toasts, and extend the merging to `ToastsApi::addError`
where all error toasts have a MountPoint as their text. We understand
this might hide some details (e.g.: same titles, but very slightly
different MountPoints as their text) but realistically this shouldn't
really happen.

The ultimate future improvement will be (as suggested in the comments by
@jloleysens) a sort of identifier to the toast, based on which we can
group without fear of losing information. But this will require more
work on all the call-sites.
 
Relates to: elastic#161482 


![1ca12f39-75af-4d24-8906-9f27fad33c45](https://github.com/elastic/kibana/assets/4738868/b4578f2e-756d-40d0-9d24-fdffe8b9c724)


### Checklist

Delete any items that are not applicable to this PR.

- [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

### For maintainers

- [x] This was checked for breaking API changes and was [labeled
appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)

---------

Co-authored-by: Kibana Machine <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 commit does not require backporting release_note:enhancement Team:SharedUX Team label for AppEx-SharedUX (formerly Global Experience) v8.10.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.