-
Notifications
You must be signed in to change notification settings - Fork 14.1k
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: add certification to metrics #10630
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this requires a db migration?
Also, maybe we should add this to BaseMetric
instead of SQLMetric
since it's nice-to-have for all metrics.
bbf345d
to
2fd9766
Compare
Nope, no db migration as we've already added this column to the Also, we only added it to |
superset/connectors/sqla/models.py
Outdated
def is_certified(self) -> bool: | ||
try: | ||
extra_object = json.loads(self.extra) | ||
return bool(extra_object.get("certification", False)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return bool(extra_object.get("certification", False)) | |
return bool(extra_object.get("certification")) |
🐍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
superset/connectors/sqla/models.py
Outdated
def certified_by(self) -> Optional[str]: | ||
try: | ||
extra_object = json.loads(self.extra) | ||
return extra_object.get("certification", {}).get("certified_by", None) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return extra_object.get("certification", {}).get("certified_by", None) | |
return extra_object.get("certification", {}).get("certified_by") |
🐍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
superset/connectors/sqla/models.py
Outdated
def certification_details(self) -> Optional[str]: | ||
try: | ||
extra_object = json.loads(self.extra) | ||
return extra_object.get("certification", {}).get("details", None) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return extra_object.get("certification", {}).get("details", None) | |
return extra_object.get("certification", {}).get("details") |
🐍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
@property | ||
def data(self) -> Dict[str, Any]: | ||
attrs = ("is_certified", "certified_by", "certification_details") | ||
attr_dict = {s: getattr(self, s) for s in attrs} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a little weird that we have these related attributes floating around as separate attributes in the attr_dict
. Does data
need to be a flat dict, or can we keep these all in one "certification" object, sorta like how they're stored in extra
? So, .data
could return
{
"certification": {
"is_certified": ...,
"certified_by": ...,
"certification_details": ...
},
...
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm, that's a good point. Unfortunately, the way the CRUD view works on the frontend is that these fields are expected to be in a flat dict here. It's possible I could modify it though, I'll take a look
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a decent bit of magic in the CRUD JS code, so I think keeping as a flat dict is the easiest for now. I'm going to leave this as is
2fd9766
to
260c782
Compare
Codecov Report
@@ Coverage Diff @@
## master #10630 +/- ##
==========================================
- Coverage 64.22% 60.12% -4.11%
==========================================
Files 778 779 +1
Lines 36709 36835 +126
Branches 3461 3492 +31
==========================================
- Hits 23578 22148 -1430
- Misses 13022 14498 +1476
- Partials 109 189 +80
Flags with carried forward coverage won't be shown. Click here to find out more.
Continue to review full report at Codecov.
|
If it's certified by Taylor Swift then it must be good. |
260c782
to
e3deabf
Compare
@@ -32,7 +32,7 @@ import './crud.less'; | |||
const propTypes = { | |||
value: PropTypes.any.isRequired, | |||
label: PropTypes.string.isRequired, | |||
descr: PropTypes.node, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why make this shorter and less clear? Turns out because this file is JSX, some usages of this component set the description
prop, which doesn't even work!
I've cleaned it all up to use description
instead
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM with a suggestion on the Icon component
@@ -32,7 +32,7 @@ import './crud.less'; | |||
const propTypes = { | |||
value: PropTypes.any.isRequired, | |||
label: PropTypes.string.isRequired, | |||
descr: PropTypes.node, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
import Icon from 'src/components/Icon'; | ||
import TooltipWrapper from 'src/components/TooltipWrapper'; | ||
|
||
interface CertifiedIconWithTooltipProps { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Naming/API design nit: is there a variant of CertifiedIcon
which doesn't have a tooltip? If no, then WithTooltip
is probably not needed; if yes, you can also just make tooltip
as an optional prop and add the TooltipWrapper
conditionally.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the Icon file, we do:
import { ReactComponent as CertifiedIcon } from 'images/icons/certified.svg';
so I think there's a general understanding of an "Icon" component only including the icon and nothing else.
superset/connectors/sqla/models.py
Outdated
@property | ||
def is_certified(self) -> bool: | ||
try: | ||
extra_object = json.loads(self.extra) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure what's the practice of other SQLA models, but do you think it makes sense parse self.extra
on initialization? Or at least make it a property to DRY.
def __init__(...):
...
self._extra_json = None
@property
def extra_json(self) -> Dict[String, Any]:
if self._extra_json:
return self._extra_object
try:
self._extra_object = json.loads(self.extra)
return extra_object
except (TypeError, json.JSONDecodeError):
self._extra_json = {}
return self._extra_object
@property
def is_certified(self) -> bool:
return bool(self.extra_json.get("certification"))
@property
def certified_by(self) -> Optional[str]:
return self.extra_json.get("certification", {}).get("certified_by")
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ooo, i like the property idea to parse extra as a dict. I'll make that change
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also, looking at other models that do this, we don't bother with the optimization of only parsing once on init
e3deabf
to
20faa16
Compare
* master: (43 commits) feat: Getting fancier with Storybook (apache#10647) fix: dedup groupby in viz.py while preserving order (apache#10633) feat: bump superset-ui for certified tag (apache#10650) feat: setup react page with submenu for datasources listview (apache#10642) feat: add certification to metrics (apache#10630) feat(viz-plugins): add date formatting to pivot-table (apache#10637) fix: controls scroll issue (apache#10644) feat: Allow tests files in /src (plus Label component tests) (apache#10634) fix: remove duplicated params and cache_timeout from list_columns; add viz_type to list_columns (apache#10643) chore: splitting button stories into separate stories (apache#10631) refactor: remove slice level label_colors from dashboard init load (apache#10603) feat: card view bulk select (apache#10607) style: Label styling/storybook touchups (apache#10627) fix: removing unsupported modal sizes (apache#10625) feat(datasource): remove deleted columns and update column type on metadata refresh (apache#10619) improve documentation for country maps (apache#10621) chore: npm audit fix as of 2020-08-15 (apache#10613) feat: dataset REST API for distinct values (apache#10595) chore: bump react-redux to 5.1.2, whittling console noise (apache#10602) fixing console error about bad html attribute (apache#10604) ... # Conflicts: # superset-frontend/src/explore/components/ExploreViewContainer.jsx # superset-frontend/src/views/App.tsx # superset/config.py
SUMMARY
Makes use of the extra column in
sql_metrics
to add certification labels to metrics. This shows the certification label in the datasource editor, and future work will add it to the metric control in superset-ui.further implementation of #10591
BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF
TEST PLAN
ADDITIONAL INFORMATION
to: @nytai @graceguo-supercat @mistercrunch @serenajiang