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

[Embeddable Rebuild] [Controls] Apply selections on reset #189580

Closed
Heenawter opened this issue Jul 30, 2024 · 9 comments · Fixed by #189830
Closed

[Embeddable Rebuild] [Controls] Apply selections on reset #189580

Heenawter opened this issue Jul 30, 2024 · 9 comments · Fixed by #189830
Assignees
Labels
impact:critical This issue should be addressed immediately due to a critical level of impact on the product. loe:small Small Level of Effort project:embeddableRebuild Team:Presentation Presentation Team for Dashboard, Input Controls, and Canvas

Comments

@Heenawter
Copy link
Contributor

Heenawter commented Jul 30, 2024

#189128 introduces a few changes in behaviour for the control group apply button compared to the version currently on main. To summarize these changes:

  1. Selections now trigger unsaved changes: Previously, unsaved changes were only triggered when the filters changed; but now, unsaved changes are triggered immediately after selection.
  2. Backed up selections are auto-applied on load: Previously, if you had unsaved selections, these selections were not auto-applied to the dashboard on load - instead, loading that unsaved dashboard would simply enable the "apply" button. Now, the control group auto-applies all selections, even those that are not saved to the control group - this means that a dashboard should never load with the apply button enabled.

Because of (1) specifically, this creates an awkward user experience where, on dashboard reset, the user must also click "apply" in order to see the true unsaved state of the dashboard:

Screen.Recording.2024-07-30.at.3.14.03.PM.mov

If I am resetting my dashboard, I am expecting it to reset all my state to the last saved state - but this breaks that pattern because I have to hit “reset” and “apply” to see my true last saved state. So, we need to fix this before the React control group is ready to replace the legacy control group.

@Heenawter Heenawter added Team:Presentation Presentation Team for Dashboard, Input Controls, and Canvas loe:medium Medium Level of Effort impact:critical This issue should be addressed immediately due to a critical level of impact on the product. project:embeddableRebuild labels Jul 30, 2024
@elasticmachine
Copy link
Contributor

Pinging @elastic/kibana-presentation (Team:Presentation)

@nreese
Copy link
Contributor

nreese commented Jul 30, 2024

One potential path forward

Each control must expose a hasUnreportedSelections$ publishing subject in their API. hasUnreportedSelections$ contains the value true when a selection is made but filters$ or timeslice$ does not reflect the new selection. hasUnreportedSelections$ contains the value false when selections are captured in filters$ or timeslice$.

Then control group resetUnsavedChanges will call controlApi.resetUnsavedChanges and subscribe to all children hasUnreportedSelections$ and await until all return false. At that point control group resetUnsavedChanges can call applySelections.

@Heenawter Heenawter added loe:small Small Level of Effort and removed loe:medium Medium Level of Effort labels Jul 30, 2024
@ThomThomson
Copy link
Contributor

This wouldn't be such a problem if we could synchronously transform selections into filters.

Because we can't, the above solution is basically introducing an asynchronous state transition which can get very complicated. For instance. Will the Dashboard's reset function wait for the control group's reset function to complete before resetting itself? If not we run the risk of querying twice.

To be completely aligned here, would we need to make the reset functions in the embeddable framework asynchronous?

Can we think of another way to do this?

@Heenawter
Copy link
Contributor Author

Heenawter commented Jul 31, 2024

I explored @ThomThomson's suggestion of a selectionsToFilters method and while I was able to get something that "worked", it added a race condition where "reset" could happen on the wrong data view / field if it was clicked before the dataview had time to be fetched. So, after talking with him, we've pretty much destroyed that idea :)

So we're back to what you suggested @nreese - however, with a few small details:

  1. We need to make sure that only the control group reset is async. On the dashboard side, on reset, we will await the control group's reset function - then, once that is done, we will go ahead with the synchronous reset of all panels. This means the control group will have its own special PublishesUnsavedChanges interface where resetUnsavedChanges is async (PublishesContainerUnsavedChanges? HasAsyncReset? The name should be generic since technically the Dashboard API should also use this interface).

  2. With this method you suggested @nreese, we are essentially recreating the "initialize" logic but on reset - i.e. in both initialization and reset, we will have to await for all controls to say "Hey, my filter is ready!" before we proceed. Is there a way we can unify this logic?

    So for example, instead of hasUnreportedSelections$, we could have filtersReady$ or something along those lines. Then, untilFiltersInitialized would await filtersReady$ to be true the first time, but we continue updating that value (as you suggested with hasUnreportedSelections$) rather than it being a one-off thing (like it currently is for initialize) and also await that during our reset.

    Basically, on both initialize and reset, we need a reliable way to know that filters are ready to be published - and we should try to unify this logic so that it is clear.

@Heenawter
Copy link
Contributor Author

I've created a draft PR against the unsaved changes PR here to show off what this could look like: nreese#41 (the types are still angry - would need to figure that out)

@Heenawter Heenawter self-assigned this Aug 1, 2024
@nreese
Copy link
Contributor

nreese commented Aug 1, 2024

I've created a draft PR against the unsaved changes PR here to show off what this could look like: nreese#41 (the types are still angry - would need to figure that out)

Thanks for pathfinding a solution, this looks promising. Each control would need to filtersReady$.next(false); when a selection changes as well.

What is the plan with this? Are we waiting until #189128 merges and then working on a solution? Or are we trying to incorporate a solution into #189128?

@Heenawter
Copy link
Contributor Author

@nreese Up to you! I'm okay either way - what would be easiest for you? :)

@nreese
Copy link
Contributor

nreese commented Aug 1, 2024

Up to you! I'm okay either way - what would be easiest for you? :)

I think after is preferred so we can focus on as small a problem is possible without all the noise of the entire unsaved implementation. I think there will be lots of iterating on the fix, so it would be best to do this in isolation.

@Heenawter
Copy link
Contributor Author

@nreese Sounds good! I will review #189128 as-is.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
impact:critical This issue should be addressed immediately due to a critical level of impact on the product. loe:small Small Level of Effort project:embeddableRebuild Team:Presentation Presentation Team for Dashboard, Input Controls, and Canvas
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants