[Embeddables Rebuild] Fix unsaved changes on new dashboards bug (#184955)

Closes https://github.com/elastic/kibana/issues/184174

## Summary

This PR fixes the bug where, on a new and unsaved dashboard, adding both
a legacy embeddable and an image embeddable would result in a dashboard
getting stuck with unsaved changes on the first save. This was caused by
a race condition - since the `debounce` on the React embeddable unsaved
changes observable was **before** the `switchMap`, the React embeddable
observable fired **immediately** on save which then triggered the
`diffingSubscription` to fire too early.

**Before:**



44be114a-0c6d-4f40-a5c1-c05889d53ace



**After:**


52f50fd4-0e8f-4aff-8fe6-19b9038623ee
This commit is contained in:
Hannah Mudge 2024-06-06 12:31:09 -06:00 committed by GitHub
parent cb2345a902
commit a4cd61422a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -90,7 +90,6 @@ export function startDiffingDashboardState(
const reactEmbeddableUnsavedChanges = this.children$.pipe(
map((children) => Object.keys(children)),
distinctUntilChanged(deepEqual),
debounceTime(CHANGE_CHECK_DEBOUNCE),
// children may change, so make sure we subscribe/unsubscribe with switchMap
switchMap((newChildIds: string[]) => {
@ -107,6 +106,7 @@ export function startDiffingDashboardState(
)
);
}),
debounceTime(CHANGE_CHECK_DEBOUNCE),
map((children) => children.filter((child) => Boolean(child.unsavedChanges)))
);
@ -118,18 +118,17 @@ export function startDiffingDashboardState(
startWith(null),
debounceTime(CHANGE_CHECK_DEBOUNCE),
switchMap(() => {
return new Observable<Partial<DashboardContainerInput>>((observer) => {
return (async () => {
const {
explicitInput: currentInput,
componentState: { lastSavedInput },
} = this.getState();
getDashboardUnsavedChanges
.bind(this)(lastSavedInput, currentInput)
.then((unsavedChanges) => {
if (observer.closed) return;
observer.next(unsavedChanges);
});
});
const unsavedChanges = await getDashboardUnsavedChanges.bind(this)(
lastSavedInput,
currentInput
);
return unsavedChanges;
})();
})
);