mirror of https://github.com/apache/superset.git
fix: dashboard extra filters (#10692)
Co-authored-by: John Bodley <john.bodley@airbnb.com>
This commit is contained in:
parent
45f4c689a2
commit
1ee87cc4d1
|
@ -153,7 +153,7 @@ def load_world_bank_health_n_pop( # pylint: disable=too-many-locals, too-many-s
|
|||
"column": "region",
|
||||
"key": "2s98dfu",
|
||||
"metric": "sum__SP_POP_TOTL",
|
||||
"multiple": True,
|
||||
"multiple": False,
|
||||
},
|
||||
{
|
||||
"asc": False,
|
||||
|
|
|
@ -336,7 +336,7 @@ def get_dashboard_extra_filters(
|
|||
return []
|
||||
|
||||
|
||||
def build_extra_filters(
|
||||
def build_extra_filters( # pylint: disable=too-many-locals,too-many-nested-blocks
|
||||
layout: Dict[str, Dict[str, Any]],
|
||||
filter_scopes: Dict[str, Dict[str, Any]],
|
||||
default_filters: Dict[str, Dict[str, List[Any]]],
|
||||
|
@ -344,11 +344,22 @@ def build_extra_filters(
|
|||
) -> List[Dict[str, Any]]:
|
||||
extra_filters = []
|
||||
|
||||
# do not apply filters if chart is not in filter's scope or
|
||||
# chart is immune to the filter
|
||||
# do not apply filters if chart is not in filter's scope or chart is immune to the
|
||||
# filter.
|
||||
for filter_id, columns in default_filters.items():
|
||||
filter_slice = db.session.query(Slice).filter_by(id=filter_id).one_or_none()
|
||||
|
||||
filter_configs = (
|
||||
json.loads(filter_slice.params or "{}").get("filter_configs") or []
|
||||
if filter_slice
|
||||
else []
|
||||
)
|
||||
|
||||
scopes_by_filter_field = filter_scopes.get(filter_id, {})
|
||||
for col, val in columns.items():
|
||||
if not val:
|
||||
continue
|
||||
|
||||
current_field_scopes = scopes_by_filter_field.get(col, {})
|
||||
scoped_container_ids = current_field_scopes.get("scope", ["ROOT_ID"])
|
||||
immune_slice_ids = current_field_scopes.get("immune", [])
|
||||
|
@ -357,7 +368,25 @@ def build_extra_filters(
|
|||
if slice_id not in immune_slice_ids and is_slice_in_container(
|
||||
layout, container_id, slice_id
|
||||
):
|
||||
extra_filters.append({"col": col, "op": "in", "val": val})
|
||||
# Ensure that the filter value encoding adheres to the filter select
|
||||
# type.
|
||||
for filter_config in filter_configs:
|
||||
if filter_config["column"] == col:
|
||||
is_multiple = filter_config["multiple"]
|
||||
|
||||
if not is_multiple and isinstance(val, list):
|
||||
val = val[0]
|
||||
elif is_multiple and not isinstance(val, list):
|
||||
val = [val]
|
||||
break
|
||||
|
||||
extra_filters.append(
|
||||
{
|
||||
"col": col,
|
||||
"op": "in" if isinstance(val, list) else "==",
|
||||
"val": val,
|
||||
}
|
||||
)
|
||||
|
||||
return extra_filters
|
||||
|
||||
|
|
|
@ -168,7 +168,7 @@ class TestCacheWarmUp(SupersetTestCase):
|
|||
"slice_id": chart_id,
|
||||
"extra_filters": [
|
||||
{"col": "name", "op": "in", "val": ["Alice", "Bob"]},
|
||||
{"col": "__time_range", "op": "in", "val": "100 years ago : today"},
|
||||
{"col": "__time_range", "op": "==", "val": "100 years ago : today"},
|
||||
],
|
||||
}
|
||||
self.assertEqual(result, expected)
|
||||
|
|
|
@ -35,6 +35,8 @@ import tests.test_app
|
|||
from superset import app, db, security_manager
|
||||
from superset.exceptions import CertificateException, SupersetException
|
||||
from superset.models.core import Database, Log
|
||||
from superset.models.dashboard import Dashboard
|
||||
from superset.models.slice import Slice
|
||||
from superset.utils.cache_manager import CacheManager
|
||||
from superset.utils.core import (
|
||||
base_json_conv,
|
||||
|
@ -965,268 +967,47 @@ class TestUtils(SupersetTestCase):
|
|||
self.assertListEqual(get_iterable("foo"), ["foo"])
|
||||
|
||||
def test_build_extra_filters(self):
|
||||
layout = {
|
||||
"CHART-2ee52f30": {
|
||||
"children": [],
|
||||
"id": "CHART-2ee52f30",
|
||||
"meta": {
|
||||
"chartId": 1020,
|
||||
"height": 38,
|
||||
"sliceName": "Chart 927",
|
||||
"width": 6,
|
||||
},
|
||||
"parents": [
|
||||
"ROOT_ID",
|
||||
"TABS-Qq4sdkANSY",
|
||||
"TAB-VrhTX2WUlO",
|
||||
"TABS-N1zN4CIZP0",
|
||||
"TAB-asWdJzKmTN",
|
||||
"ROW-i_sG4ccXE",
|
||||
],
|
||||
"type": "CHART",
|
||||
},
|
||||
"CHART-36bfc934": {
|
||||
"children": [],
|
||||
"id": "CHART-36bfc934",
|
||||
"meta": {
|
||||
"chartId": 1018,
|
||||
"height": 26,
|
||||
"sliceName": "Region Filter",
|
||||
"width": 2,
|
||||
},
|
||||
"parents": [
|
||||
"ROOT_ID",
|
||||
"TABS-Qq4sdkANSY",
|
||||
"TAB-W62P60D88",
|
||||
"ROW-1e064e3c",
|
||||
"COLUMN-fe3914b8",
|
||||
],
|
||||
"type": "CHART",
|
||||
},
|
||||
"CHART-E_y2cuNHTv": {
|
||||
"children": [],
|
||||
"id": "CHART-E_y2cuNHTv",
|
||||
"meta": {"chartId": 998, "height": 55, "sliceName": "MAP", "width": 6},
|
||||
"parents": [
|
||||
"ROOT_ID",
|
||||
"TABS-Qq4sdkANSY",
|
||||
"TAB-W62P60D88",
|
||||
"ROW-1e064e3c",
|
||||
],
|
||||
"type": "CHART",
|
||||
},
|
||||
"CHART-JNxDOsAfEb": {
|
||||
"children": [],
|
||||
"id": "CHART-JNxDOsAfEb",
|
||||
"meta": {
|
||||
"chartId": 1015,
|
||||
"height": 27,
|
||||
"sliceName": "Population",
|
||||
"width": 4,
|
||||
},
|
||||
"parents": [
|
||||
"ROOT_ID",
|
||||
"TABS-Qq4sdkANSY",
|
||||
"TAB-W62P60D88",
|
||||
"ROW-1e064e3c",
|
||||
"COLUMN-fe3914b8",
|
||||
],
|
||||
"type": "CHART",
|
||||
},
|
||||
"CHART-KoOwqalV80": {
|
||||
"children": [],
|
||||
"id": "CHART-KoOwqalV80",
|
||||
"meta": {
|
||||
"chartId": 927,
|
||||
"height": 20,
|
||||
"sliceName": "Chart 927",
|
||||
"width": 4,
|
||||
},
|
||||
"parents": [
|
||||
"ROOT_ID",
|
||||
"TABS-Qq4sdkANSY",
|
||||
"TAB-VrhTX2WUlO",
|
||||
"TABS-N1zN4CIZP0",
|
||||
"TAB-cHNWcBZC9",
|
||||
"ROW-9b9vrWKPY",
|
||||
],
|
||||
"type": "CHART",
|
||||
},
|
||||
"CHART-YCQAPVK7mQ": {
|
||||
"children": [],
|
||||
"id": "CHART-YCQAPVK7mQ",
|
||||
"meta": {
|
||||
"chartId": 1023,
|
||||
"height": 38,
|
||||
"sliceName": "World's Population",
|
||||
"width": 4,
|
||||
},
|
||||
"parents": [
|
||||
"ROOT_ID",
|
||||
"TABS-Qq4sdkANSY",
|
||||
"TAB-VrhTX2WUlO",
|
||||
"ROW-UfxFT36oV5",
|
||||
],
|
||||
"type": "CHART",
|
||||
},
|
||||
"COLUMN-fe3914b8": {
|
||||
"children": ["CHART-36bfc934", "CHART-JNxDOsAfEb"],
|
||||
"id": "COLUMN-fe3914b8",
|
||||
"meta": {"background": "BACKGROUND_TRANSPARENT", "width": 6},
|
||||
"parents": [
|
||||
"ROOT_ID",
|
||||
"TABS-Qq4sdkANSY",
|
||||
"TAB-W62P60D88",
|
||||
"ROW-1e064e3c",
|
||||
],
|
||||
"type": "COLUMN",
|
||||
},
|
||||
"DASHBOARD_VERSION_KEY": "v2",
|
||||
"GRID_ID": {
|
||||
"children": [],
|
||||
"id": "GRID_ID",
|
||||
"parents": ["ROOT_ID"],
|
||||
"type": "GRID",
|
||||
},
|
||||
"HEADER_ID": {
|
||||
"id": "HEADER_ID",
|
||||
"meta": {"text": "Test warmup 1023"},
|
||||
"type": "HEADER",
|
||||
},
|
||||
"ROOT_ID": {
|
||||
"children": ["TABS-Qq4sdkANSY"],
|
||||
"id": "ROOT_ID",
|
||||
"type": "ROOT",
|
||||
},
|
||||
"ROW-1e064e3c": {
|
||||
"children": ["COLUMN-fe3914b8", "CHART-E_y2cuNHTv"],
|
||||
"id": "ROW-1e064e3c",
|
||||
"meta": {"background": "BACKGROUND_TRANSPARENT"},
|
||||
"parents": ["ROOT_ID", "TABS-Qq4sdkANSY", "TAB-W62P60D88"],
|
||||
"type": "ROW",
|
||||
},
|
||||
"ROW-9b9vrWKPY": {
|
||||
"children": ["CHART-KoOwqalV80"],
|
||||
"id": "ROW-9b9vrWKPY",
|
||||
"meta": {"background": "BACKGROUND_TRANSPARENT"},
|
||||
"parents": [
|
||||
"ROOT_ID",
|
||||
"TABS-Qq4sdkANSY",
|
||||
"TAB-VrhTX2WUlO",
|
||||
"TABS-N1zN4CIZP0",
|
||||
"TAB-cHNWcBZC9",
|
||||
],
|
||||
"type": "ROW",
|
||||
},
|
||||
"ROW-UfxFT36oV5": {
|
||||
"children": ["CHART-YCQAPVK7mQ"],
|
||||
"id": "ROW-UfxFT36oV5",
|
||||
"meta": {"background": "BACKGROUND_TRANSPARENT"},
|
||||
"parents": ["ROOT_ID", "TABS-Qq4sdkANSY", "TAB-VrhTX2WUlO"],
|
||||
"type": "ROW",
|
||||
},
|
||||
"ROW-i_sG4ccXE": {
|
||||
"children": ["CHART-2ee52f30"],
|
||||
"id": "ROW-i_sG4ccXE",
|
||||
"meta": {"background": "BACKGROUND_TRANSPARENT"},
|
||||
"parents": [
|
||||
"ROOT_ID",
|
||||
"TABS-Qq4sdkANSY",
|
||||
"TAB-VrhTX2WUlO",
|
||||
"TABS-N1zN4CIZP0",
|
||||
"TAB-asWdJzKmTN",
|
||||
],
|
||||
"type": "ROW",
|
||||
},
|
||||
"TAB-VrhTX2WUlO": {
|
||||
"children": ["ROW-UfxFT36oV5", "TABS-N1zN4CIZP0"],
|
||||
"id": "TAB-VrhTX2WUlO",
|
||||
"meta": {"text": "New Tab"},
|
||||
"parents": ["ROOT_ID", "TABS-Qq4sdkANSY"],
|
||||
"type": "TAB",
|
||||
},
|
||||
"TAB-W62P60D88": {
|
||||
"children": ["ROW-1e064e3c"],
|
||||
"id": "TAB-W62P60D88",
|
||||
"meta": {"text": "Tab 2"},
|
||||
"parents": ["ROOT_ID", "TABS-Qq4sdkANSY"],
|
||||
"type": "TAB",
|
||||
},
|
||||
"TAB-asWdJzKmTN": {
|
||||
"children": ["ROW-i_sG4ccXE"],
|
||||
"id": "TAB-asWdJzKmTN",
|
||||
"meta": {"text": "nested tab 1"},
|
||||
"parents": [
|
||||
"ROOT_ID",
|
||||
"TABS-Qq4sdkANSY",
|
||||
"TAB-VrhTX2WUlO",
|
||||
"TABS-N1zN4CIZP0",
|
||||
],
|
||||
"type": "TAB",
|
||||
},
|
||||
"TAB-cHNWcBZC9": {
|
||||
"children": ["ROW-9b9vrWKPY"],
|
||||
"id": "TAB-cHNWcBZC9",
|
||||
"meta": {"text": "test2d tab 2"},
|
||||
"parents": [
|
||||
"ROOT_ID",
|
||||
"TABS-Qq4sdkANSY",
|
||||
"TAB-VrhTX2WUlO",
|
||||
"TABS-N1zN4CIZP0",
|
||||
],
|
||||
"type": "TAB",
|
||||
},
|
||||
"TABS-N1zN4CIZP0": {
|
||||
"children": ["TAB-asWdJzKmTN", "TAB-cHNWcBZC9"],
|
||||
"id": "TABS-N1zN4CIZP0",
|
||||
"meta": {},
|
||||
"parents": ["ROOT_ID", "TABS-Qq4sdkANSY", "TAB-VrhTX2WUlO"],
|
||||
"type": "TABS",
|
||||
},
|
||||
"TABS-Qq4sdkANSY": {
|
||||
"children": ["TAB-VrhTX2WUlO", "TAB-W62P60D88"],
|
||||
"id": "TABS-Qq4sdkANSY",
|
||||
"meta": {},
|
||||
"parents": ["ROOT_ID"],
|
||||
"type": "TABS",
|
||||
},
|
||||
}
|
||||
world_health = db.session.query(Dashboard).filter_by(slug="world_health").one()
|
||||
layout = json.loads(world_health.position_json)
|
||||
filter_ = db.session.query(Slice).filter_by(slice_name="Region Filter").one()
|
||||
world = db.session.query(Slice).filter_by(slice_name="World's Population").one()
|
||||
box_plot = db.session.query(Slice).filter_by(slice_name="Box plot").one()
|
||||
treemap = db.session.query(Slice).filter_by(slice_name="Treemap").one()
|
||||
|
||||
filter_scopes = {
|
||||
"1018": {
|
||||
"region": {"scope": ["TAB-W62P60D88"], "immune": [998]},
|
||||
"country_name": {"scope": ["ROOT_ID"], "immune": [927, 998]},
|
||||
str(filter_.id): {
|
||||
"region": {"scope": ["ROOT_ID"], "immune": [treemap.id]},
|
||||
"country_name": {
|
||||
"scope": ["ROOT_ID"],
|
||||
"immune": [treemap.id, box_plot.id],
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
default_filters = {
|
||||
"1018": {"region": ["North America"], "country_name": ["United States"]}
|
||||
str(filter_.id): {
|
||||
"region": ["North America"],
|
||||
"country_name": ["United States"],
|
||||
}
|
||||
}
|
||||
|
||||
# immune to all filters
|
||||
slice_id = 998
|
||||
extra_filters = build_extra_filters(
|
||||
layout, filter_scopes, default_filters, slice_id
|
||||
assert (
|
||||
build_extra_filters(layout, filter_scopes, default_filters, treemap.id)
|
||||
== []
|
||||
)
|
||||
expected = []
|
||||
self.assertEqual(extra_filters, expected)
|
||||
|
||||
# in scope
|
||||
slice_id = 1015
|
||||
extra_filters = build_extra_filters(
|
||||
layout, filter_scopes, default_filters, slice_id
|
||||
)
|
||||
expected = [
|
||||
{"col": "region", "op": "in", "val": ["North America"]},
|
||||
assert build_extra_filters(
|
||||
layout, filter_scopes, default_filters, world.id
|
||||
) == [
|
||||
{"col": "region", "op": "==", "val": "North America"},
|
||||
{"col": "country_name", "op": "in", "val": ["United States"]},
|
||||
]
|
||||
self.assertEqual(extra_filters, expected)
|
||||
|
||||
# not in scope
|
||||
slice_id = 927
|
||||
extra_filters = build_extra_filters(
|
||||
layout, filter_scopes, default_filters, slice_id
|
||||
)
|
||||
expected = []
|
||||
self.assertEqual(extra_filters, expected)
|
||||
assert build_extra_filters(
|
||||
layout, filter_scopes, default_filters, box_plot.id
|
||||
) == [{"col": "region", "op": "==", "val": "North America"}]
|
||||
|
||||
def test_ssl_certificate_parse(self):
|
||||
parsed_certificate = parse_ssl_cert(ssl_certificate)
|
||||
|
|
Loading…
Reference in New Issue