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

   ### SUMMARY
   
   Fixes a dashboard post-save redirect bug (Shortcut sc-107323): when the 
**URL Slug** in *Edit dashboard properties* starts with a reserved URL 
character (`?` or `/`), saving succeeds but the post-save redirect lands on a 
malformed/blank URL on the **first** render. A manual page reload afterwards 
works, because the reload uses the stored, backend-sanitized slug.
   
   **Root cause.** In 
`superset-frontend/src/dashboard/actions/dashboardState.ts`, the 
`onUpdateSuccess` handler in `saveDashboardRequest` built the redirect from the 
**raw, locally-submitted** slug:
   
   ```ts
   navigateWithState(`/dashboard/${slug || id}/`, { event: 
'dashboard_properties_changed' });
   ```
   
   The backend sanitizes reserved characters out of the slug before persisting 
it — `BaseDashboardSchema.post_load` in `superset/dashboards/schemas.py` runs 
`re.sub(r"[^\w\-]+", "", ...)` — so the persisted slug returned in the `PUT 
/api/v1/dashboard/{id}` response can differ from what was submitted. Building 
the redirect from the raw value produces e.g. `/dashboard/?test/`, which the 
router resolves to a slug-less `/dashboard/` and renders blank on first paint.
   
   **Fix.** Build the redirect from the slug in the update response 
(`updatedDashboard.slug`), falling back to `id` when the response carries no 
slug:
   
   ```ts
   const updatedSlug = updatedDashboard.slug as string | null | undefined;
   navigateWithState(`/dashboard/${updatedSlug || id}/`, { event: 
'dashboard_properties_changed' });
   ```
   
   The Copy / *Save as* path (`onCopySuccess`) already redirects on the 
response `id` only and is unaffected. The change is one decision point plus 
regression tests.
   
   ### BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF
   
   Captured in a real dev environment at a fixed 1280×800 viewport. Scenario 
(identical for both): log in → open the *USA Births Names* dashboard → **Edit 
dashboard** → **⋯ → Edit properties** → set **URL Slug** to `?test` → **Apply** 
→ **Save** → observe the address bar on first render (no manual reload). A 
`location.href` banner is injected into each still because Playwright 
screenshots don't include browser chrome.
   
   **Before (master)** — post-save URL is `/dashboard/` with the slug lost; the 
dashboard renders **blank**:
   
   ![Before — post-save URL is slug-less /dashboard/, blank 
page](https://raw.githubusercontent.com/sadpandajoe/superset/pr-assets-sc107323/pr-assets/sc107323/before-after-save.png)
   
   ![Before — rendered result is 
blank](https://raw.githubusercontent.com/sadpandajoe/superset/pr-assets-sc107323/pr-assets/sc107323/before-render-redirected.png)
   
   **After (this PR)** — post-save URL is the sanitized `/dashboard/test/`; the 
dashboard **renders correctly**:
   
   ![After — post-save URL is /dashboard/test/, dashboard 
renders](https://raw.githubusercontent.com/sadpandajoe/superset/pr-assets-sc107323/pr-assets/sc107323/after-after-save.png)
   
   ![After — full dashboard 
renders](https://raw.githubusercontent.com/sadpandajoe/superset/pr-assets-sc107323/pr-assets/sc107323/after-render-redirected.png)
   
   Full screen recordings (VP8 WebM): 
[before-master.webm](https://raw.githubusercontent.com/sadpandajoe/superset/pr-assets-sc107323/pr-assets/sc107323/before-master.webm)
 · 
[after-fix.webm](https://raw.githubusercontent.com/sadpandajoe/superset/pr-assets-sc107323/pr-assets/sc107323/after-fix.webm).
 Capture script: 
[capture.mjs](https://raw.githubusercontent.com/sadpandajoe/superset/pr-assets-sc107323/pr-assets/sc107323/capture.mjs).
   
   ### TESTING INSTRUCTIONS
   
   Manual:
   1. Open any dashboard, enter edit mode, open **⋯ → Edit properties**.
   2. Set **URL Slug** to a value starting with a reserved character, e.g. 
`?test`, and **Save**.
   3. On `master` the first render is blank (URL missing the dashboard); with 
this change the redirect goes to `/dashboard/test/` (the sanitized slug) and 
the dashboard renders. A slug of only reserved characters (e.g. `?`) sanitizes 
to empty and correctly falls back to `/dashboard/<id>/`.
   
   Automated (`superset-frontend`):
   ```
   npm run test -- src/dashboard/actions/dashboardState.test.ts
   ```
   Two regression tests were added: (a) submitted slug `?test` + PUT-response 
slug `test` ⇒ redirect `/dashboard/test/`; (b) PUT-response slug empty/null ⇒ 
redirect falls back to `/dashboard/<id>/`. Both fail on `master` and pass with 
this change.
   
   ### ADDITIONAL INFORMATION
   <!--- Check any relevant boxes with "x" -->
   - [ ] Has associated issue:
   - [ ] Required feature flags:
   - [x] Changes UI
   - [ ] Includes DB Migration (follow approval process in 
[SIP-59](https://github.com/apache/superset/issues/13351))
   - [ ] 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