codeant-ai-for-open-source[bot] commented on code in PR #45038:
URL: https://github.com/apache/superset/pull/45038#discussion_r4217841317
##########
superset/daos/dashboard.py:
##########
@@ -531,6 +535,109 @@ def favorited_ids(dashboards: list[Dashboard]) ->
list[FavStar]:
.all()
]
+ @staticmethod
+ def _remap_filter_scope(
+ container: dict[str, Any] | Any,
+ old_to_new_slice_ids: dict[int, int],
+ ) -> None:
+ """Remap scope.excluded and chartsInScope of a filter container.
+
+ This method updates in-place the chart ID references stored inside
+ a filter configuration container. Both native filters and cross-filter
+ scopes store denormalized lists of chart IDs in chartsInScope and
+ scope.excluded. When duplicate_slices is requested during dashboard
+ copy, these identifiers must point to the newly cloned slice IDs.
+
+ Non-dictionary elements, visual dividers (type DIVIDER or IDs starting
+ with NATIVE_FILTER_DIVIDER), and non-list attributes are skipped
safely.
+
+ :param container: Dictionary holding filter scope or cross-filter
+ configuration.
+ :param old_to_new_slice_ids: Mapping from original chart ID to
+ duplicated chart ID.
+ """
+ if not isinstance(container, dict):
+ return
+
+ # Skip divider entities which represent visual section dividers in
filter bar
+ if container.get("type") == "DIVIDER" or str(
+ container.get("id", "")
+ ).startswith(("NATIVE_FILTER_DIVIDER", "DIVIDER")):
+ return
+
+ scope = container.get("scope")
+ if isinstance(scope, dict) and isinstance(scope.get("excluded"), list):
+ remapped_excluded: list[int] = []
+ for cid in scope["excluded"]:
+ try:
+ int_id = int(cid)
+ remapped_excluded.append(old_to_new_slice_ids.get(int_id,
int_id))
+ except (ValueError, TypeError):
+ remapped_excluded.append(cid)
+ scope["excluded"] = remapped_excluded
Review Comment:
✅ **CodeAnt verified this suggestion was addressed in subsequent commits and
marked this thread resolved** as of `d7e799a`.
Added `_remap_selected_layers`, which extracts chart IDs from
`selectedLayers` keys, maps them to the duplicated chart IDs, and preserves
each key’s suffix.
<sub>If that's not right, unresolve this thread and CodeAnt will leave it
open.</sub>
<!-- codeant-auto-resolve-reply -->
##########
superset/daos/dashboard.py:
##########
@@ -531,6 +535,109 @@ def favorited_ids(dashboards: list[Dashboard]) ->
list[FavStar]:
.all()
]
+ @staticmethod
+ def _remap_filter_scope(
+ container: dict[str, Any] | Any,
+ old_to_new_slice_ids: dict[int, int],
+ ) -> None:
+ """Remap scope.excluded and chartsInScope of a filter container.
+
+ This method updates in-place the chart ID references stored inside
+ a filter configuration container. Both native filters and cross-filter
+ scopes store denormalized lists of chart IDs in chartsInScope and
+ scope.excluded. When duplicate_slices is requested during dashboard
+ copy, these identifiers must point to the newly cloned slice IDs.
+
+ Non-dictionary elements, visual dividers (type DIVIDER or IDs starting
+ with NATIVE_FILTER_DIVIDER), and non-list attributes are skipped
safely.
+
+ :param container: Dictionary holding filter scope or cross-filter
+ configuration.
+ :param old_to_new_slice_ids: Mapping from original chart ID to
+ duplicated chart ID.
+ """
+ if not isinstance(container, dict):
+ return
+
+ # Skip divider entities which represent visual section dividers in
filter bar
+ if container.get("type") == "DIVIDER" or str(
+ container.get("id", "")
+ ).startswith(("NATIVE_FILTER_DIVIDER", "DIVIDER")):
+ return
+
+ scope = container.get("scope")
+ if isinstance(scope, dict) and isinstance(scope.get("excluded"), list):
+ remapped_excluded: list[int] = []
+ for cid in scope["excluded"]:
+ try:
+ int_id = int(cid)
+ remapped_excluded.append(old_to_new_slice_ids.get(int_id,
int_id))
+ except (ValueError, TypeError):
+ remapped_excluded.append(cid)
+ scope["excluded"] = remapped_excluded
+
+ if isinstance(container.get("chartsInScope"), list):
+ remapped_in_scope: list[int] = []
+ for cid in container["chartsInScope"]:
+ try:
+ int_id = int(cid)
+ remapped_in_scope.append(old_to_new_slice_ids.get(int_id,
int_id))
+ except (ValueError, TypeError):
+ remapped_in_scope.append(cid)
+ container["chartsInScope"] = remapped_in_scope
+
+ @classmethod
+ def _remap_filter_scopes(
+ cls,
+ metadata: dict[str, Any],
+ old_to_new_slice_ids: dict[int, int],
+ ) -> None:
+ """Remap filter scopes and cross-filter references in dashboard
metadata.
+
+ Mutates metadata in-place to redirect slice ID references across:
+ 1. native_filter_configuration: list of native filter definitions.
+ 2. global_chart_configuration: dashboard-wide cross-filter scoping.
+ 3. chart_configuration: per-chart cross-filter scopes, keys, and chart
IDs.
+
+ This ensures that after duplicating dashboard charts, all filter
+ scopes remain bound to the new chart copies instead of the originals.
+
+ :param metadata: Deserialized dashboard json_metadata dictionary.
+ :param old_to_new_slice_ids: Mapping from original chart ID to
+ duplicated chart ID.
+ """
+ if not isinstance(metadata, dict) or not old_to_new_slice_ids:
+ return
+
+ if isinstance(metadata.get("native_filter_configuration"), list):
+ for native_filter in metadata["native_filter_configuration"]:
+ cls._remap_filter_scope(native_filter, old_to_new_slice_ids)
Review Comment:
✅ **CodeAnt verified this suggestion was addressed in subsequent commits and
marked this thread resolved** as of `d7e799a`.
The metadata traversal now applies `_remap_filter_scope` to entries in both
`native_filter_configuration` and `chart_customization_config`, remapping their
exclusions, selected layers, and chart-scope references.
<sub>If that's not right, unresolve this thread and CodeAnt will leave it
open.</sub>
<!-- codeant-auto-resolve-reply -->
--
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]