Skip to content

Commit 32e8a28

Browse files
committed
feat: add MatchAttributeFilter to visualization model
This reflects the filter type recently added on the backend. Support it also in the visualization_to_sdk_converter. JIRA: CQ-2005 risk: low
1 parent 5f3eea1 commit 32e8a28

File tree

4 files changed

+147
-0
lines changed

4 files changed

+147
-0
lines changed

packages/gooddata-sdk/src/gooddata_sdk/compute/visualization_to_sdk_converter.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
AllTimeDateFilter,
99
BoundedFilter,
1010
Filter,
11+
MatchAttributeFilter,
1112
NegativeAttributeFilter,
1213
PositiveAttributeFilter,
1314
RelativeDateFilter,
@@ -43,13 +44,18 @@ def convert_filter(filter_dict: dict[str, Any]) -> Filter:
4344
- using: str - The identifier of the attribute/dataset to filter on
4445
- include: list[str] (optional) - Values to include in positive filter
4546
- exclude: list[str] (optional) - Values to exclude in negative filter
47+
- literal: str (optional) - Literal value for match attribute filter
48+
- matchType: str (optional) - Match type (STARTS_WITH, ENDS_WITH, CONTAINS)
49+
- negate: bool (optional) - Whether to negate the match
50+
- caseSensitive: bool (optional) - Whether match is case-sensitive
4651
- from: str (optional) - Start date/shift for date filters
4752
- to: str (optional) - End date/shift for date filters
4853
- granularity: str (optional) - Time granularity for relative date filters
4954
Returns:
5055
Filter: One of:
5156
- PositiveAttributeFilter: When include values specified
5257
- NegativeAttributeFilter: When exclude values specified
58+
- MatchAttributeFilter: When literal and matchType specified
5359
- RelativeDateFilter: When granularity and from/to shifts specified
5460
- AbsoluteDateFilter: When from/to dates specified
5561
- AllTimeDateFilter: When no date range specified
@@ -61,10 +67,21 @@ def convert_filter(filter_dict: dict[str, Any]) -> Filter:
6167
_to = filter_dict.get("to")
6268
granularity = filter_dict.get("granularity")
6369

70+
literal = filter_dict.get("literal")
71+
match_type = filter_dict.get("matchType")
72+
6473
if include is not None:
6574
return PositiveAttributeFilter(label=ObjId(using, "label"), values=include)
6675
elif exclude is not None:
6776
return NegativeAttributeFilter(label=ObjId(using, "label"), values=exclude)
77+
elif literal is not None and match_type is not None:
78+
return MatchAttributeFilter(
79+
label=ObjId(using, "label"),
80+
match_type=match_type,
81+
literal=literal,
82+
negate=filter_dict.get("negate", False),
83+
case_sensitive=filter_dict.get("caseSensitive", False),
84+
)
6885
elif granularity is not None and _from is not None and _to is not None:
6986
bounded_filter = None
7087
if "boundedFilter" in filter_dict:

packages/gooddata-sdk/src/gooddata_sdk/visualization.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
AllTimeDateFilter,
1616
BoundedFilter,
1717
Filter,
18+
MatchAttributeFilter,
1819
MetricValueFilter,
1920
NegativeAttributeFilter,
2021
PositiveAttributeFilter,
@@ -80,6 +81,12 @@
8081
"change": "CHANGE",
8182
}
8283

84+
_MATCH_OPERATOR_CONVERSION = {
85+
"contains": "CONTAINS",
86+
"startsWith": "STARTS_WITH",
87+
"endsWith": "ENDS_WITH",
88+
}
89+
8390

8491
class BucketType(Enum):
8592
"""
@@ -178,6 +185,15 @@ def _convert_filter_to_computable(filter_obj: dict[str, Any]) -> Filter:
178185
not_in_values = f["notIn"]["values"] if "values" in f["notIn"] else f["notIn"]["uris"]
179186

180187
return NegativeAttributeFilter(label=ref_extract(f["displayForm"]), values=not_in_values)
188+
elif "matchAttributeFilter" in filter_obj:
189+
f = filter_obj["matchAttributeFilter"]
190+
return MatchAttributeFilter(
191+
label=ref_extract(f["label"]),
192+
match_type=_MATCH_OPERATOR_CONVERSION[f["operator"]],
193+
literal=f["literal"],
194+
negate=f.get("negativeSelection", False),
195+
case_sensitive=f.get("caseSensitive", False),
196+
)
181197
elif "relativeDateFilter" in filter_obj:
182198
f = filter_obj["relativeDateFilter"]
183199

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
{
2+
"buckets": [
3+
{
4+
"items": [
5+
{
6+
"measure": {
7+
"definition": {
8+
"measureDefinition": {
9+
"item": {
10+
"identifier": {
11+
"id": "aangOxLSeztu",
12+
"type": "metric"
13+
}
14+
}
15+
}
16+
},
17+
"localIdentifier": "m_aangOxLSeztu"
18+
}
19+
}
20+
],
21+
"localIdentifier": "measures"
22+
},
23+
{
24+
"items": [
25+
{
26+
"attribute": {
27+
"displayForm": {
28+
"identifier": {
29+
"id": "label.opportunity.id.name",
30+
"type": "label"
31+
}
32+
},
33+
"localIdentifier": "a_label.opportunity.id.name"
34+
}
35+
}
36+
],
37+
"localIdentifier": "view"
38+
},
39+
{
40+
"items": [],
41+
"localIdentifier": "stack"
42+
}
43+
],
44+
"filters": [
45+
{
46+
"matchAttributeFilter": {
47+
"label": {
48+
"identifier": {
49+
"id": "label.opportunity.id.name",
50+
"type": "label"
51+
}
52+
},
53+
"operator": "contains",
54+
"literal": "search term",
55+
"negativeSelection": false,
56+
"caseSensitive": true
57+
}
58+
}
59+
],
60+
"identifier": "AreaChart.a97be468994b89529a3efba0a264a799",
61+
"properties": {
62+
"controls": {}
63+
},
64+
"sorts": [],
65+
"title": "AreaChart - with match attribute filter",
66+
"uri": "AreaChart.a97be468994b89529a3efba0a264a799",
67+
"visualizationUrl": "local:area"
68+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
{
2+
"attributes": [
3+
{
4+
"label": {
5+
"identifier": {
6+
"id": "label.opportunity.id.name",
7+
"type": "label"
8+
}
9+
},
10+
"local_identifier": "a_label.opportunity.id.name"
11+
}
12+
],
13+
"filters": [
14+
{
15+
"match_attribute_filter": {
16+
"case_sensitive": true,
17+
"label": {
18+
"identifier": {
19+
"id": "label.opportunity.id.name",
20+
"type": "label"
21+
}
22+
},
23+
"literal": "search term",
24+
"match_type": "CONTAINS",
25+
"negate": false
26+
}
27+
}
28+
],
29+
"measures": [
30+
{
31+
"definition": {
32+
"measure": {
33+
"compute_ratio": false,
34+
"filters": [],
35+
"item": {
36+
"identifier": {
37+
"id": "aangOxLSeztu",
38+
"type": "metric"
39+
}
40+
}
41+
}
42+
},
43+
"local_identifier": "m_aangOxLSeztu"
44+
}
45+
]
46+
}

0 commit comments

Comments
 (0)