mikebridge opened a new pull request, #44028:
URL: https://github.com/apache/superset/pull/44028
### SUMMARY
`position_json` (the dashboard layout JSON) is a plain column with no
coordination against the `dashboard_slices` association. A chart hard-deleted
while it was a live dashboard member leaves a layout node referencing a
chart id
that no longer resolves to any `Slice` row, and a restore-with-skips
reproduces
the same divergence — a layout tile pointing at a chart absent from `slices`.
The divergence is invisible to the API consumer and accumulates: every save
writes `meta.uuid = None` into the dangling slot.
This reconciles `position_json` against membership **on write**. A `CHART`
layout
node whose `chartId` does not resolve to any `Slice` row is swapped in place
for
a markdown placeholder — keeping the node id, children, and geometry and
replacing only `type`+`meta`. This mirrors the frontend
`swapUnreachableChartSlots`
(#41551) and the runtime `MissingChart` placeholder, **persisting** what the
client already renders rather than re-deriving it on every load.
Key design decisions:
- **Soft-deleted members are preserved.** The dangling check keys on
"chartId not
resolvable to any `Slice` row **with the soft-delete visibility filter
bypassed**", so a soft-deleted (recoverable) member — whose
`dashboard_slices`
junction row still exists — is never treated as dangling. Only
genuinely-absent
(hard-deleted / never-existed) references are repaired. The existing
`test_set_dash_metadata_preserves_soft_deleted_members` stays green.
- **Both write paths are covered.** `DashboardDAO.set_dash_metadata`
(positions in
`json_metadata`, reusing its already-resolved `uuid_map`) and the raw
`position_json`-field PUT in `UpdateDashboardCommand.run` (which resolves
membership itself via `reconcile_position_json`).
- **The placeholder text is a plain literal, not `gettext`.**
`position_json` is
persisted, shared data rendered verbatim to every viewer, so translating
it to
the saving user's request locale would bake one language into content
shown to
everyone. Per-viewer localization stays the frontend's render-time job.
Refs: sc-115325. Found during the #42469 (version-restore) review but
pre-existing product-wide behavior, not a restore regression.
### BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF
No UI screenshot — this is a backend reconcile. Behaviorally: a dashboard
whose
layout references a hard-deleted chart previously kept a broken `CHART` tile
(`meta.uuid = null`) accumulating on every save; after this change, saving
swaps
that slot to a markdown "This chart no longer exists." tile (the same
content the
frontend already renders at read time for such a slot).
### TESTING INSTRUCTIONS
1. Create a dashboard with a chart, then hard-delete the chart.
2. Save the dashboard (PUT). Observe the layout node for the deleted chart
is now
a markdown placeholder rather than a dangling `CHART` node, and
`position_json` no longer references the absent chart id.
3. Repeat with a **soft-deleted** chart — its tile must be preserved (still a
`CHART` node with its uuid), confirming recoverable members are not
repaired.
Automated: `pytest tests/unit_tests/dao/dashboard_test.py` (both write paths,
live + soft-deleted + genuinely-absent chartIds, non-dict-`position_json`
guard,
and a reverted-fix control) and
`pytest tests/integration_tests/dashboards/api_tests.py -k
reconciles_dangling`
(a PUT end-to-end pinning that `run()` invokes the reconcile).
### ADDITIONAL INFORMATION
- [ ] 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))
- [ ] 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
🤖 Generated with [Claude Code](https://claude.com/claude-code)
--
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]