Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: update IDs when importing dashboards #11991

Merged
merged 2 commits into from
Dec 12, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions superset/dashboards/commands/importers/v1/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@
from superset.charts.schemas import ImportV1ChartSchema
from superset.commands.importers.v1 import ImportModelsCommand
from superset.dashboards.commands.exceptions import DashboardImportError
from superset.dashboards.commands.importers.v1.utils import import_dashboard
from superset.dashboards.commands.importers.v1.utils import (
import_dashboard,
update_id_refs,
)
from superset.dashboards.dao import DashboardDAO
from superset.dashboards.schemas import ImportV1DashboardSchema
from superset.databases.commands.importers.v1.utils import import_database
Expand Down Expand Up @@ -128,8 +131,8 @@ def _import(
dashboard_chart_ids: List[Tuple[int, int]] = []
for file_name, config in configs.items():
if file_name.startswith("dashboards/"):
config = update_id_refs(config, chart_ids)
dashboard = import_dashboard(session, config, overwrite=overwrite)

for uuid in find_chart_uuids(config["position"]):
chart_id = chart_ids[uuid]
if (dashboard.id, chart_id) not in existing_relationships:
Expand Down
64 changes: 64 additions & 0 deletions superset/dashboards/commands/importers/v1/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,70 @@
JSON_KEYS = {"position": "position_json", "metadata": "json_metadata"}


def build_uuid_to_id_map(position: Dict[str, Any]) -> Dict[str, int]:
return {
child["meta"]["uuid"]: child["meta"]["chartId"]
for child in position.values()
if (
isinstance(child, dict)
and child["type"] == "CHART"
and "uuid" in child["meta"]
)
}


def update_id_refs(config: Dict[str, Any], chart_ids: Dict[str, int]) -> Dict[str, Any]:
"""Update dashboard metadata to use new IDs"""
if not config.get("metadata"):
return config

fixed = config.copy()

# build map old_id => new_id
old_ids = build_uuid_to_id_map(fixed["position"])
id_map = {old_id: chart_ids[uuid] for uuid, old_id in old_ids.items()}

# fix metadata
metadata = fixed["metadata"]
if "timed_refresh_immune_slices" in metadata:
metadata["timed_refresh_immune_slices"] = [
id_map[old_id] for old_id in metadata["timed_refresh_immune_slices"]
]

if "filter_scopes" in metadata:
# in filter_scopes the key is a chart ID as a string; we nede to udpate
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit typos

# them to be the new ID as a string:
metadata["filter_scopes"] = {
str(id_map[int(old_id)]): columns
for old_id, columns in metadata["filter_scopes"].items()
}

# now update columns to use new IDs:
for columns in metadata["filter_scopes"].values():
for attributes in columns.values():
attributes["immune"] = [
id_map[old_id] for old_id in attributes["immune"]
]

if "expanded_slices" in metadata:
metadata["expanded_slices"] = {
str(id_map[int(old_id)]): value
for old_id, value in metadata["expanded_slices"].items()
}

# fix position
position = fixed["position"]
for child in position.values():
if (
isinstance(child, dict)
and child["type"] == "CHART"
and "uuid" in child["meta"]
):
child["meta"]["chartId"] = chart_ids[child["meta"]["uuid"]]

return fixed


def import_dashboard(
session: Session, config: Dict[str, Any], overwrite: bool = False
) -> Dashboard:
Expand Down
21 changes: 14 additions & 7 deletions tests/dashboards/commands_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,12 @@ def test_import_v1_dashboard(self):
dashboard = (
db.session.query(Dashboard).filter_by(uuid=dashboard_config["uuid"]).one()
)

assert len(dashboard.slices) == 1
chart = dashboard.slices[0]
assert str(chart.uuid) == chart_config["uuid"]
new_chart_id = chart.id

assert dashboard.dashboard_title == "Test dash"
assert dashboard.description is None
assert dashboard.css == ""
Expand All @@ -272,7 +278,7 @@ def test_import_v1_dashboard(self):
"children": [],
"id": "CHART-SVAlICPOSJ",
"meta": {
"chartId": 83,
"chartId": new_chart_id,
"height": 50,
"sliceName": "Number of California Births",
"uuid": "0c23747a-6528-4629-97bf-e4b78d3b9df1",
Expand Down Expand Up @@ -305,17 +311,18 @@ def test_import_v1_dashboard(self):
assert json.loads(dashboard.json_metadata) == {
"color_scheme": None,
"default_filters": "{}",
"expanded_slices": {},
"expanded_slices": {str(new_chart_id): True},
"filter_scopes": {
str(new_chart_id): {
"region": {"scope": ["ROOT_ID"], "immune": [new_chart_id]}
},
},
"import_time": 1604342885,
"refresh_frequency": 0,
"remote_id": 7,
"timed_refresh_immune_slices": [],
"timed_refresh_immune_slices": [new_chart_id],
}

assert len(dashboard.slices) == 1
chart = dashboard.slices[0]
assert str(chart.uuid) == chart_config["uuid"]

dataset = chart.table
assert str(dataset.uuid) == dataset_config["uuid"]

Expand Down
5 changes: 3 additions & 2 deletions tests/fixtures/importexport.py
Original file line number Diff line number Diff line change
Expand Up @@ -488,8 +488,9 @@
},
},
"metadata": {
"timed_refresh_immune_slices": [],
"expanded_slices": {},
"timed_refresh_immune_slices": [83],
"filter_scopes": {"83": {"region": {"scope": ["ROOT_ID"], "immune": [83]}},},
"expanded_slices": {"83": True},
"refresh_frequency": 0,
"default_filters": "{}",
"color_scheme": None,
Expand Down