diff --git a/superset-frontend/spec/javascripts/components/TableSelector_spec.jsx b/superset-frontend/spec/javascripts/components/TableSelector_spec.jsx
index 96b1d2e343a..320e4f52803 100644
--- a/superset-frontend/spec/javascripts/components/TableSelector_spec.jsx
+++ b/superset-frontend/spec/javascripts/components/TableSelector_spec.jsx
@@ -60,11 +60,12 @@ const schemaOptions = {
};
const selectedSchema = { label: 'main', title: 'main', value: 'main' };
const selectedTable = {
+ extra: null,
label: 'birth_names',
schema: 'main',
title: 'birth_names',
- value: 'birth_names',
type: undefined,
+ value: 'birth_names',
};
async function mountAndWait(props = mockedProps) {
diff --git a/superset-frontend/src/components/CertifiedIconWithTooltip.tsx b/superset-frontend/src/components/CertifiedIconWithTooltip.tsx
index e96b35f5140..e4132dc828b 100644
--- a/superset-frontend/src/components/CertifiedIconWithTooltip.tsx
+++ b/superset-frontend/src/components/CertifiedIconWithTooltip.tsx
@@ -24,11 +24,13 @@ import TooltipWrapper from 'src/components/TooltipWrapper';
interface CertifiedIconWithTooltipProps {
certifiedBy?: string;
details?: string;
+ size?: number;
}
function CertifiedIconWithTooltip({
certifiedBy,
details,
+ size = 24,
}: CertifiedIconWithTooltipProps) {
return (
}
>
-
+
);
}
diff --git a/superset-frontend/src/components/TableSelector.tsx b/superset-frontend/src/components/TableSelector.tsx
index 4c59359091f..c5c3a52af21 100644
--- a/superset-frontend/src/components/TableSelector.tsx
+++ b/superset-frontend/src/components/TableSelector.tsx
@@ -29,6 +29,7 @@ import FormLabel from 'src/components/FormLabel';
import DatabaseSelector from './DatabaseSelector';
import RefreshLabel from './RefreshLabel';
+import CertifiedIconWithTooltip from './CertifiedIconWithTooltip';
const FieldTitle = styled.p`
color: ${({ theme }) => theme.colors.secondary.light2};
@@ -65,7 +66,14 @@ const TableSelectorWrapper = styled.div`
`;
const TableLabel = styled.span`
+ align-items: center;
+ display: flex;
white-space: nowrap;
+
+ > svg,
+ > small {
+ margin-right: ${({ theme }) => theme.gridUnit}px;
+ }
`;
interface TableSelectorProps {
@@ -146,6 +154,7 @@ const TableSelector: FunctionComponent = ({
label: o.label,
title: o.title,
type: o.type,
+ extra: o?.extra,
}));
setTableLoading(false);
setTableOptions(options);
@@ -244,13 +253,16 @@ const TableSelector: FunctionComponent = ({
function renderTableOption(option: any) {
return (
-
-
-
-
-
+ {option.extra?.certification && (
+
+ )}
+
+
+
{option.label}
);
@@ -308,6 +320,7 @@ const TableSelector: FunctionComponent = ({
// @ts-ignore
value={currentTableName}
optionRenderer={renderTableOption}
+ valueRenderer={renderTableOption}
/>
);
} else if (formMode) {
diff --git a/superset/connectors/sqla/models.py b/superset/connectors/sqla/models.py
index c75c081cb55..e19c1b93945 100644
--- a/superset/connectors/sqla/models.py
+++ b/superset/connectors/sqla/models.py
@@ -700,6 +700,13 @@ class SqlaTable( # pylint: disable=too-many-public-methods,too-many-instance-at
data_["is_sqllab_view"] = self.is_sqllab_view
return data_
+ @property
+ def extra_dict(self) -> Dict[str, Any]:
+ try:
+ return json.loads(self.extra)
+ except (TypeError, json.JSONDecodeError):
+ return {}
+
def values_for_column(self, column_name: str, limit: int = 10000) -> List[Any]:
"""Runs query against sqla to retrieve some
sample values for the given column.
diff --git a/superset/views/core.py b/superset/views/core.py
index e12e50c248c..e5730e5f99f 100755
--- a/superset/views/core.py
+++ b/superset/views/core.py
@@ -981,6 +981,8 @@ class Superset(BaseSupersetView): # pylint: disable=too-many-public-methods
max_tables = max_items * len(tables) // total_items
max_views = max_items * len(views) // total_items
+ dataset_tables = {table.name: table for table in database.tables}
+
table_options = [
{
"value": tn.table,
@@ -988,6 +990,9 @@ class Superset(BaseSupersetView): # pylint: disable=too-many-public-methods
"label": get_datasource_label(tn),
"title": get_datasource_label(tn),
"type": "table",
+ "extra": dataset_tables[f"{tn.schema}.{tn.table}"].extra_dict
+ if (f"{tn.schema}.{tn.table}" in dataset_tables)
+ else None,
}
for tn in tables[:max_tables]
]
diff --git a/tests/core_tests.py b/tests/core_tests.py
index 87b698f4d80..94f3c29a60f 100644
--- a/tests/core_tests.py
+++ b/tests/core_tests.py
@@ -155,7 +155,7 @@ class TestCore(SupersetTestCase):
response = json.loads(rv.data.decode("utf-8"))
self.assertEqual(rv.status_code, 200)
- expeted_response = {
+ expected_response = {
"options": [
{
"label": "ab_role",
@@ -163,11 +163,12 @@ class TestCore(SupersetTestCase):
"title": "ab_role",
"type": "table",
"value": "ab_role",
+ "extra": None,
}
],
"tableLength": 1,
}
- self.assertEqual(response, expeted_response)
+ self.assertEqual(response, expected_response)
def test_get_superset_tables_not_found(self):
self.login(username="admin")
@@ -862,7 +863,7 @@ class TestCore(SupersetTestCase):
def test_get_select_star_not_allowed(self):
"""
- Database API: Test get select star not allowed
+ Database API: Test get select star not allowed
"""
self.login(username="gamma")
example_db = utils.get_example_database()