mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
[dashboard] Do not reset panel to undefined or empty last saved state (#203158)
Part of https://github.com/elastic/kibana/issues/201627 This is a short term fix for serverless and 8.x branches (long term fix is an architectural change that will only be merged into 9.0 and 8.18 branches). Fix prevents users from reseting a panel edited via embeddable transfer service. This prevents panel from getting into an invalid state. --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
parent
418e50b4e0
commit
e103a253d9
7 changed files with 31 additions and 7 deletions
|
@ -250,6 +250,7 @@ export function getPageApi() {
|
|||
children$.next(children);
|
||||
}
|
||||
newPanels = {};
|
||||
return true;
|
||||
},
|
||||
timeRange$,
|
||||
unsavedChanges: unsavedChanges$ as PublishingSubject<object | undefined>,
|
||||
|
|
|
@ -14,11 +14,11 @@ import { waitFor } from '@testing-library/react';
|
|||
describe('childrenUnsavedChanges$', () => {
|
||||
const child1Api = {
|
||||
unsavedChanges: new BehaviorSubject<object | undefined>(undefined),
|
||||
resetUnsavedChanges: () => undefined,
|
||||
resetUnsavedChanges: () => true,
|
||||
};
|
||||
const child2Api = {
|
||||
unsavedChanges: new BehaviorSubject<object | undefined>(undefined),
|
||||
resetUnsavedChanges: () => undefined,
|
||||
resetUnsavedChanges: () => true,
|
||||
};
|
||||
const children$ = new BehaviorSubject<{ [key: string]: unknown }>({});
|
||||
const onFireMock = jest.fn();
|
||||
|
@ -99,7 +99,7 @@ describe('childrenUnsavedChanges$', () => {
|
|||
...children$.value,
|
||||
child3: {
|
||||
unsavedChanges: new BehaviorSubject<object | undefined>({ key1: 'modified value' }),
|
||||
resetUnsavedChanges: () => undefined,
|
||||
resetUnsavedChanges: () => true,
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
@ -95,10 +95,19 @@ export const initializeUnsavedChanges = <RuntimeState extends {} = {}>(
|
|||
unsavedChanges,
|
||||
resetUnsavedChanges: () => {
|
||||
const lastSaved = lastSavedState$.getValue();
|
||||
|
||||
// Do not reset to undefined or empty last saved state
|
||||
// Temporary fix for https://github.com/elastic/kibana/issues/201627
|
||||
// TODO remove when architecture fix resolves issue.
|
||||
if (comparatorKeys.length && (!lastSaved || Object.keys(lastSaved).length === 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const key of comparatorKeys) {
|
||||
const setter = comparators[key][1]; // setter function is the 1st element of the tuple
|
||||
setter(lastSaved?.[key] as RuntimeState[typeof key]);
|
||||
}
|
||||
return true;
|
||||
},
|
||||
snapshotRuntimeState,
|
||||
} as PublishesUnsavedChanges<RuntimeState> & HasSnapshottableState<RuntimeState>,
|
||||
|
|
|
@ -11,7 +11,7 @@ import { PublishingSubject } from '../publishing_subject';
|
|||
|
||||
export interface PublishesUnsavedChanges<Runtime extends object = object> {
|
||||
unsavedChanges: PublishingSubject<Partial<Runtime> | undefined>;
|
||||
resetUnsavedChanges: () => void;
|
||||
resetUnsavedChanges: () => boolean;
|
||||
}
|
||||
|
||||
export const apiPublishesUnsavedChanges = (api: unknown): api is PublishesUnsavedChanges => {
|
||||
|
|
|
@ -43,7 +43,9 @@ export const getMockedBuildApi =
|
|||
uuid,
|
||||
parentApi: controlGroupApi ?? getMockedControlGroupApi(),
|
||||
unsavedChanges: new BehaviorSubject<Partial<StateType> | undefined>(undefined),
|
||||
resetUnsavedChanges: () => {},
|
||||
resetUnsavedChanges: () => {
|
||||
return true;
|
||||
},
|
||||
type: factory.type,
|
||||
};
|
||||
};
|
||||
|
|
|
@ -48,7 +48,9 @@ describe('TimesliderControlApi', () => {
|
|||
uuid,
|
||||
parentApi: controlGroupApi,
|
||||
unsavedChanges: new BehaviorSubject<Partial<TimesliderControlState> | undefined>(undefined),
|
||||
resetUnsavedChanges: () => {},
|
||||
resetUnsavedChanges: () => {
|
||||
return true;
|
||||
},
|
||||
type: factory.type,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -68,6 +68,7 @@ import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render';
|
|||
import { LocatorPublic } from '@kbn/share-plugin/common';
|
||||
import { ExitFullScreenButtonKibanaProvider } from '@kbn/shared-ux-button-exit-full-screen';
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { DASHBOARD_CONTAINER_TYPE, DashboardApi, DashboardLocatorParams } from '../..';
|
||||
import type { DashboardAttributes } from '../../../server/content_management';
|
||||
import { DashboardContainerInput, DashboardPanelMap, DashboardPanelState } from '../../../common';
|
||||
|
@ -957,7 +958,16 @@ export class DashboardContainer
|
|||
for (const panelId of Object.keys(currentChildren)) {
|
||||
if (this.getInput().panels[panelId]) {
|
||||
const child = currentChildren[panelId];
|
||||
if (apiPublishesUnsavedChanges(child)) child.resetUnsavedChanges();
|
||||
if (apiPublishesUnsavedChanges(child)) {
|
||||
const success = child.resetUnsavedChanges();
|
||||
if (!success) {
|
||||
coreServices.notifications.toasts.addWarning(
|
||||
i18n.translate('dashboard.reset.panelError', {
|
||||
defaultMessage: 'Unable to reset panel changes',
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// if reset resulted in panel removal, we need to update the list of children
|
||||
delete currentChildren[panelId];
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue