ayushanand13 opened a new pull request, #41252:
URL: https://github.com/apache/superset/pull/41252

   ### SUMMARY
   
   Creating a dashboard via **+ Dashboard** lands the user directly in edit 
mode at `/superset/dashboard/<id>/?edit=true`. In that flow the **Undo** 
control was enabled before any user action, and clicking it threw:
   
   ```
   TypeError: Cannot read properties of undefined (reading 'type')
   ```
   
   …reverting the layout to an empty state and leaving the UI broken until 
reload.
   
   **Root cause.** `HYDRATE_DASHBOARD` is a tracked layout action, and 
`redux-undo`'s `CLEAR_HISTORY` resets its internal `_latestUnfiltered` pointer 
to the *current* `present` (non-null). When the undo history is cleared while 
the layout is still the pre-hydration `{}` (as happens during dashboard 
navigation), the next hydration captures that empty layout as an undoable 
baseline. **Undo** then reverts `dashboardLayout.present` to `{}`, and 
rendering code that reads `component.type` dereferences `undefined`.
   
   This builds on #40569, which cleared history *after* hydrate from the page 
component. That mitigates the common path but is order-dependent and 
bypassable; this PR closes the gap at the reducer level so it holds for the **+ 
Dashboard** flow and for SPA navigation between dashboards.
   
   **Fix** — harden the `undoableDashboardLayout` reducer:
   
   1. **Reset undo history on every `HYDRATE_DASHBOARD`.** Hydration 
establishes the baseline for the dashboard being opened — it is not a user edit 
and must never be undoable. Doing this in the reducer (rather than relying on a 
follow-up `clearDashboardHistory()` dispatch) guarantees the **Undo** control 
starts disabled and that no layout from a previously edited dashboard lingers 
after navigation.
   2. **Guard undo/redo against invalid layouts.** A valid dashboard layout 
always contains the root component (`ROOT_ID`). Undo/redo is never allowed to 
replace a valid layout with a rootless one; if it would, the corrupt history is 
dropped and the last valid layout is kept — so clicking **Undo** can never 
crash the dashboard.
   
   ### BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF
   
   _See the screen recording in #41246._
   
   - **Before:** on a brand-new dashboard (`?edit=true`), **Undo** is enabled 
with no user action and clicking it throws `TypeError: Cannot read properties 
of undefined (reading 'type')`.
   - **After:** **Undo** is disabled until a real layout change is made, and 
undo/redo can never revert to an empty/invalid layout.
   
   ### TESTING INSTRUCTIONS
   
   **Automated** (new reducer unit tests):
   
   ```bash
   cd superset-frontend
   npm run test -- src/dashboard/reducers/undoableDashboardLayout.test.ts
   ```
   
   The tests cover:
   - the undo history is empty/disabled right after hydration;
   - a stale/empty baseline left by a premature `clearHistory` does **not** 
survive hydration;
   - re-hydrating a different dashboard drops the previous one from the undo 
stack (SPA navigation);
   - undo never reverts the layout to an invalid state and drops corrupt 
history;
   - a genuine layout edit is still undone correctly.
   
   **Manual:**
   
   1. Log in as a user who can create dashboards.
   2. Go to **Dashboards** → **+ Dashboard** (opens 
`/superset/dashboard/<id>/?edit=true`).
   3. Without making any change, confirm the **Undo** button is **disabled**.
   4. Add a chart / drag a component, then click **Undo** — it reverts that 
change with no error.
   5. Navigate to another dashboard in edit mode and confirm **Undo** does not 
act on the previous dashboard's layout.
   
   ### ADDITIONAL INFORMATION
   
   - [x] Has associated issue: Fixes #41246
   - [ ] Required feature flags:
   - [x] Changes UI
   - [ ] Includes DB Migration (follow approval process in 
[SIP-59](https://github.com/apache/superset/issues/13351))
     - [ ] Migration is atomic, supports rollback & is backwards-compatible
     - [ ] Confirm DB migration upgrade and downgrade tested
     - [ ] Runtime estimates and downtime expectations provided
   - [ ] Introduces new feature or API
   - [ ] Removes existing feature or API
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to