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

[Time to Visualize] Fix Unlink Action via Rollback of ReplacePanel #83873

Merged
merged 4 commits into from
Nov 25, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -137,12 +137,17 @@ test('Add to library is not compatible when embeddable is not in a dashboard con
test('Add to library replaces embeddableId and retains panel count', async () => {
const dashboard = embeddable.getRoot() as IContainer;
const originalPanelCount = Object.keys(dashboard.getInput().panels).length;
const originalPanelKeySet = new Set(Object.keys(dashboard.getInput().panels));

const action = new AddToLibraryAction({ toasts: coreStart.notifications.toasts });
await action.execute({ embeddable });
expect(Object.keys(container.getInput().panels).length).toEqual(originalPanelCount);
expect(Object.keys(container.getInput().panels)).toContain(embeddable.id);
const newPanel = container.getInput().panels[embeddable.id!];

const newPanelId = Object.keys(container.getInput().panels).find(
(key) => !originalPanelKeySet.has(key)
);
expect(newPanelId).toBeDefined();
const newPanel = container.getInput().panels[newPanelId!];
expect(newPanel.type).toEqual(embeddable.type);
});

Expand All @@ -158,10 +163,15 @@ test('Add to library returns reference type input', async () => {
mockedByReferenceInput: { savedObjectId: 'testSavedObjectId', id: embeddable.id },
mockedByValueInput: { attributes: complicatedAttributes, id: embeddable.id } as EmbeddableInput,
});
const dashboard = embeddable.getRoot() as IContainer;
const originalPanelKeySet = new Set(Object.keys(dashboard.getInput().panels));
const action = new AddToLibraryAction({ toasts: coreStart.notifications.toasts });
await action.execute({ embeddable });
expect(Object.keys(container.getInput().panels)).toContain(embeddable.id);
const newPanel = container.getInput().panels[embeddable.id!];
const newPanelId = Object.keys(container.getInput().panels).find(
(key) => !originalPanelKeySet.has(key)
);
expect(newPanelId).toBeDefined();
const newPanel = container.getInput().panels[newPanelId!];
expect(newPanel.type).toEqual(embeddable.type);
expect(newPanel.explicitInput.attributes).toBeUndefined();
expect(newPanel.explicitInput.savedObjectId).toBe('testSavedObjectId');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@

import { i18n } from '@kbn/i18n';
import _ from 'lodash';
import uuid from 'uuid';
import { ActionByType, IncompatibleActionError } from '../../ui_actions_plugin';
import { ViewMode, PanelState, IEmbeddable } from '../../embeddable_plugin';
import {
Expand Down Expand Up @@ -89,9 +88,9 @@ export class AddToLibraryAction implements ActionByType<typeof ACTION_ADD_TO_LIB

const newPanel: PanelState<EmbeddableInput> = {
type: embeddable.type,
explicitInput: { ...newInput, id: uuid.v4() },
explicitInput: { ...newInput },
};
dashboard.replacePanel(panelToReplace, newPanel);
dashboard.replacePanel(panelToReplace, newPanel, true);

const title = i18n.translate('dashboard.panel.addToLibrary.successMessage', {
defaultMessage: `Panel '{panelTitle}' was added to the visualize library`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,11 +135,16 @@ test('Unlink is not compatible when embeddable is not in a dashboard container',
test('Unlink replaces embeddableId and retains panel count', async () => {
const dashboard = embeddable.getRoot() as IContainer;
const originalPanelCount = Object.keys(dashboard.getInput().panels).length;
const originalPanelKeySet = new Set(Object.keys(dashboard.getInput().panels));
const action = new UnlinkFromLibraryAction({ toasts: coreStart.notifications.toasts });
await action.execute({ embeddable });
expect(Object.keys(container.getInput().panels).length).toEqual(originalPanelCount);
expect(Object.keys(container.getInput().panels)).toContain(embeddable.id);
const newPanel = container.getInput().panels[embeddable.id!];

const newPanelId = Object.keys(container.getInput().panels).find(
(key) => !originalPanelKeySet.has(key)
);
expect(newPanelId).toBeDefined();
const newPanel = container.getInput().panels[newPanelId!];
expect(newPanel.type).toEqual(embeddable.type);
});

Expand All @@ -159,10 +164,15 @@ test('Unlink unwraps all attributes from savedObject', async () => {
mockedByReferenceInput: { savedObjectId: 'testSavedObjectId', id: embeddable.id },
mockedByValueInput: { attributes: complicatedAttributes, id: embeddable.id },
});
const dashboard = embeddable.getRoot() as IContainer;
const originalPanelKeySet = new Set(Object.keys(dashboard.getInput().panels));
const action = new UnlinkFromLibraryAction({ toasts: coreStart.notifications.toasts });
await action.execute({ embeddable });
expect(Object.keys(container.getInput().panels)).toContain(embeddable.id);
const newPanel = container.getInput().panels[embeddable.id!];
const newPanelId = Object.keys(container.getInput().panels).find(
(key) => !originalPanelKeySet.has(key)
);
expect(newPanelId).toBeDefined();
const newPanel = container.getInput().panels[newPanelId!];
expect(newPanel.type).toEqual(embeddable.type);
expect(newPanel.explicitInput.attributes).toEqual(complicatedAttributes);
});
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@

import { i18n } from '@kbn/i18n';
import _ from 'lodash';
import uuid from 'uuid';
import { ActionByType, IncompatibleActionError } from '../../ui_actions_plugin';
import { ViewMode, PanelState, IEmbeddable } from '../../embeddable_plugin';
import {
Expand Down Expand Up @@ -88,9 +87,9 @@ export class UnlinkFromLibraryAction implements ActionByType<typeof ACTION_UNLIN

const newPanel: PanelState<EmbeddableInput> = {
type: embeddable.type,
explicitInput: { ...newInput, id: uuid.v4() },
explicitInput: { ...newInput },
};
dashboard.replacePanel(panelToReplace, newPanel);
dashboard.replacePanel(panelToReplace, newPanel, true);

const title = embeddable.getTitle()
? i18n.translate('dashboard.panel.unlinkFromLibrary.successMessageWithTitle', {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,11 +173,30 @@ export class DashboardContainer extends Container<InheritedChildInput, Dashboard

public replacePanel(
previousPanelState: DashboardPanelState<EmbeddableInput>,
newPanelState: Partial<PanelState>
newPanelState: Partial<PanelState>,
generateNewId?: boolean
) {
// Because the embeddable type can change, we have to operate at the container level here
return this.updateInput({
panels: {
let panels;
if (generateNewId) {
// replace panel can be called with generateNewId in order to totally destroy and recreate the embeddable
panels = { ...this.input.panels };
delete panels[previousPanelState.explicitInput.id];
const newId = uuid.v4();
panels[newId] = {
...previousPanelState,
...newPanelState,
gridData: {
...previousPanelState.gridData,
i: newId,
},
explicitInput: {
...newPanelState.explicitInput,
id: newId,
},
};
} else {
// Because the embeddable type can change, we have to operate at the container level here
panels = {
...this.input.panels,
[previousPanelState.explicitInput.id]: {
...previousPanelState,
Expand All @@ -190,7 +209,11 @@ export class DashboardContainer extends Container<InheritedChildInput, Dashboard
id: previousPanelState.explicitInput.id,
},
},
},
};
}

return this.updateInput({
panels,
lastReloadRequestTime: new Date().getTime(),
});
}
Expand Down