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

[8.16] [dashboard] fix Reset dashboard breaks panel state when ran after editor edits (#201687) #201896

Merged
merged 1 commit into from
Nov 27, 2024

Conversation

kibanamachine
Copy link
Contributor

Backport

This will backport the following commits from main to 8.16:

Questions ?

Please refer to the Backport tool documentation

…tor edits (elastic#201687)

Closes elastic#201627

### The problem
`ReactEmbeddableRender` uses `lastSavedRuntimeState` as last saved state
baseline. Resetting reverts to this state.
```
// Code sample from src/plugins/embeddable/public/react_embeddable_system/react_embeddable_renderer.tsx
const serializedState = parentApi.getSerializedStateForChild(uuid);
const lastSavedRuntimeState = serializedState
  ? await factory.deserializeState(serializedState)
  : ({} as RuntimeState);

...

const unsavedChanges = initializeUnsavedChanges<RuntimeState>(
  lastSavedRuntimeState,
  parentApi,
  comparators
);
```

`DashboardContainer` getSerializedStateForChild implemenation
```
// Code sample from src/plugins/dashboard/public/dashboard_container/embeddable/dashboard_container.tsx
public getSerializedStateForChild = (childId: string) => {
    const rawState = this.getInput().panels[childId].explicitInput;
    const { id, ...serializedState } = rawState;
    if (!rawState || Object.keys(serializedState).length === 0) return;
    const references = getReferencesForPanelId(childId, this.savedObjectReferences);
    return {
      rawState,
      // references from old installations may not be prefixed with panel id
      // fall back to passing all references in these cases to preserve backwards compatability
      references: references.length > 0 ? references : this.savedObjectReferences,
    };
  };
```

The problem is that `create_dashboard` clears
`this.getInput().panels[childId].explicitInput` for a panel with
embeddable transfer state. This causes `lastSavedRuntimeState` to be an
empty object, which causes reset to use `undefined` for the previous
value when reseting an embeddables keys.
```
// Code sample from src/plugins/dashboard/public/dashboard_container/embeddable/create/create_dashboard.ts
const incomingEmbeddable = creationOptions?.getIncomingEmbeddable?.();
if (
  incomingEmbeddable.embeddableId &&
  Boolean(initialDashboardInput.panels[incomingEmbeddable.embeddableId])
) {
  // this embeddable already exists, we will update the explicit input.
  const panelToUpdate = initialDashboardInput.panels[incomingEmbeddable.embeddableId];
  const sameType = panelToUpdate.type === incomingEmbeddable.type;

  panelToUpdate.type = incomingEmbeddable.type;
  const nextRuntimeState = {
    // if the incoming panel is the same type as what was there before we can safely spread the old panel's explicit input
    ...(sameType ? panelToUpdate.explicitInput : {}),

    ...incomingEmbeddable.input,
    id: incomingEmbeddable.embeddableId,

    // maintain hide panel titles setting.
    hidePanelTitles: panelToUpdate.explicitInput.hidePanelTitles,
  };
  if (embeddableService.reactEmbeddableRegistryHasKey(incomingEmbeddable.type)) {
    panelToUpdate.explicitInput = { id: panelToUpdate.explicitInput.id };
    runtimePanelsToRestore[incomingEmbeddable.embeddableId] = nextRuntimeState;
  } else {
    panelToUpdate.explicitInput = nextRuntimeState;
  }
}
```

### The fix
The solution is to retain `panelToUpdate.explicitInput` original value
so that `lastSavedRuntimeState` is set to the original runtime state and
reset will revert to this value instead of `{}`.

### test instructions
1) install web logs sample data
2) create new dashboard
3) click "Add panel" and select "Legacy => Agg based"
4) create pie chart with terms split on "machine.os", click "Save and
return"
5) save dashboard
6) edit pie chart, Under "options", unselect "donut". Click "Save and
return"
7) click reset in dashboard. Verify that visualization returns to
original state. Note, the same will not happen for map embeddables.
There is a bug in map embeddables where resetting "attributes" state
does not update the current map.

Co-authored-by: Elastic Machine <[email protected]>
(cherry picked from commit 289bb16)
@kibanamachine kibanamachine merged commit 49732de into elastic:8.16 Nov 27, 2024
24 checks passed
@elasticmachine
Copy link
Contributor

💚 Build Succeeded

Metrics [docs]

Async chunks

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

id before after diff
dashboard 636.7KB 636.7KB -42.0B

cc @nreese

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants