[dashboard] fix filter_scopes when copy dashboard with duplicate_slices (#9188)

* [dashboard] fix filter_scopes when copy dashboard with duplicate_slices

* code cleanup
This commit is contained in:
Grace Guo 2020-02-24 13:45:29 -08:00 committed by GitHub
parent 8c095a6e39
commit 421aeb4605
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 38 additions and 16 deletions

View File

@ -44,7 +44,10 @@ from superset.models.slice import Slice as Slice
from superset.models.tags import DashboardUpdater
from superset.models.user_attributes import UserAttribute
from superset.utils import core as utils
from superset.utils.dashboard_filter_scopes_converter import convert_filter_scopes
from superset.utils.dashboard_filter_scopes_converter import (
convert_filter_scopes,
copy_filter_scopes,
)
if TYPE_CHECKING:
# pylint: disable=unused-import
@ -288,10 +291,10 @@ class Dashboard( # pylint: disable=too-many-instance-attributes
# and will remove the existing dashboard - slice association
slices = copy(dashboard_to_import.slices)
old_json_metadata = json.loads(dashboard_to_import.json_metadata or "{}")
old_to_new_slc_id_dict = {}
old_to_new_slc_id_dict: Dict[int, int] = {}
new_timed_refresh_immune_slices = []
new_expanded_slices = {}
new_filter_scopes = {}
new_filter_scopes: Dict[str, Dict] = {}
i_params_dict = dashboard_to_import.params_dict
remote_id_slice_map = {
slc.params_dict["remote_id"]: slc
@ -338,13 +341,11 @@ class Dashboard( # pylint: disable=too-many-instance-attributes
filter_scopes = old_json_metadata.get("filter_scopes")
# then replace old slice id to new slice id:
for (slice_id, scopes) in filter_scopes.items():
new_filter_key = old_to_new_slc_id_dict[int(slice_id)]
new_filter_scopes[str(new_filter_key)] = scopes
for scope in scopes.values():
scope["immune"] = [
old_to_new_slc_id_dict[slice_id] for slice_id in scope.get("immune")
]
if filter_scopes:
new_filter_scopes = copy_filter_scopes(
old_to_new_slc_id_dict=old_to_new_slc_id_dict,
old_filter_scopes=filter_scopes,
)
# override the dashboard
existing_dashboard = None

View File

@ -70,3 +70,17 @@ def convert_filter_scopes(json_metadata: Dict, filters: List[Slice]):
filter_scopes[filter_id] = filter_fields
return filter_scopes
def copy_filter_scopes(
old_to_new_slc_id_dict: Dict[int, int], old_filter_scopes: Dict[str, Dict]
) -> Dict:
new_filter_scopes = {}
for (slice_id, scopes) in old_filter_scopes.items():
new_filter_key = old_to_new_slc_id_dict[int(slice_id)]
new_filter_scopes[str(new_filter_key)] = scopes
for scope in scopes.values():
scope["immune"] = [
old_to_new_slc_id_dict[slice_id] for slice_id in scope.get("immune")
]
return new_filter_scopes

View File

@ -81,6 +81,7 @@ from superset.models.user_attributes import UserAttribute
from superset.sql_parse import ParsedQuery
from superset.sql_validators import get_validator_by_name
from superset.utils import core as utils, dashboard_import_export
from superset.utils.dashboard_filter_scopes_converter import copy_filter_scopes
from superset.utils.dates import now_as_float
from superset.utils.decorators import etag_cache, stats_timing
from superset.views.database.filters import DatabaseFilter
@ -1177,27 +1178,33 @@ class Superset(BaseSupersetView):
if data["duplicate_slices"]:
# Duplicating slices as well, mapping old ids to new ones
old_to_new_sliceids = {}
old_to_new_sliceids: Dict[int, int] = {}
for slc in original_dash.slices:
new_slice = slc.clone()
new_slice.owners = [g.user] if g.user else []
session.add(new_slice)
session.flush()
new_slice.dashboards.append(dash)
old_to_new_sliceids["{}".format(slc.id)] = "{}".format(new_slice.id)
old_to_new_sliceids[slc.id] = new_slice.id
# update chartId of layout entities
# in v2_dash positions json data, chartId should be integer,
# while in older version slice_id is string type
for value in data["positions"].values():
if (
isinstance(value, dict)
and value.get("meta")
and value.get("meta").get("chartId")
):
old_id = "{}".format(value.get("meta").get("chartId"))
new_id = int(old_to_new_sliceids[old_id])
old_id = value.get("meta").get("chartId")
new_id = old_to_new_sliceids[old_id]
value["meta"]["chartId"] = new_id
# replace filter_id and immune ids from old slice id to new slice id:
if "filter_scopes" in data:
new_filter_scopes = copy_filter_scopes(
old_to_new_slc_id_dict=old_to_new_sliceids,
old_filter_scopes=json.loads(data["filter_scopes"] or "{}"),
)
data["filter_scopes"] = json.dumps(new_filter_scopes)
else:
dash.slices = original_dash.slices
dash.params = original_dash.params