This is an automated email from the ASF dual-hosted git repository.
maximebeauchemin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-superset.git
The following commit(s) were added to refs/heads/master by this push:
new b043590 Filtering out SQLLab views out of table list view by default (#4746)
b043590 is described below
commit b04359003ec8ea0ecae55166941b6589528592bd
Author: Maxime Beauchemin <maximebeauchemin@gmail.com>
AuthorDate: Thu Apr 12 13:52:47 2018 -0700
Filtering out SQLLab views out of table list view by default (#4746)
* Filtering out SQLLab views out of table list view by default
This adds a `is_sqllab_view` flag in the "tables" table, and makes the
filters those out in the Tables list view.
The filter showing on top may be a bit confusing, but certainly less
than seeing lots of user generated views.
* flake
* Addressing comments
---
.../javascripts/addSlice/AddSliceContainer.jsx | 86 ++++++++++++----------
superset/connectors/base/models.py | 4 +
superset/connectors/connector_registry.py | 6 +-
superset/connectors/sqla/models.py | 5 ++
superset/connectors/sqla/views.py | 21 ++++--
.../versions/130915240929_is_sqllab_viz_flow.py | 54 ++++++++++++++
superset/views/core.py | 1 +
7 files changed, 129 insertions(+), 48 deletions(-)
diff --git a/superset/assets/javascripts/addSlice/AddSliceContainer.jsx b/superset/assets/javascripts/addSlice/AddSliceContainer.jsx
index 0516934..6b1f5e7 100644
--- a/superset/assets/javascripts/addSlice/AddSliceContainer.jsx
+++ b/superset/assets/javascripts/addSlice/AddSliceContainer.jsx
@@ -1,6 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
-import { Button, Panel, Grid, Row, Col } from 'react-bootstrap';
+import { Button, Panel } from 'react-bootstrap';
import Select from 'react-virtualized-select';
import visTypes from '../explore/stores/visTypes';
import { t } from '../locales';
@@ -12,6 +12,8 @@ const propTypes = {
})).isRequired,
};
+const styleSelectWidth = { width: 300 };
+
export default class AddSliceContainer extends React.PureComponent {
constructor(props) {
super(props);
@@ -55,44 +57,50 @@ export default class AddSliceContainer extends React.PureComponent {
return (
<div className="container">
<Panel header={<h3>{t('Create a new slice')}</h3>}>
- <Grid>
- <Row>
- <Col xs={12} sm={6}>
- <div>
- <p>{t('Choose a datasource')}</p>
- <Select
- clearable={false}
- name="select-datasource"
- onChange={this.changeDatasource.bind(this)}
- options={this.props.datasources}
- placeholder={t('Choose a datasource')}
- value={this.state.datasourceValue}
- />
- </div>
- <br />
- <div>
- <p>{t('Choose a visualization type')}</p>
- <Select
- clearable={false}
- name="select-vis-type"
- onChange={this.changeVisType.bind(this)}
- options={this.vizTypeOptions}
- placeholder={t('Choose a visualization type')}
- value={this.state.visType}
- />
- </div>
- <br />
- <Button
- bsStyle="primary"
- disabled={this.isBtnDisabled()}
- onClick={this.gotoSlice.bind(this)}
- >
- {t('Create new slice')}
- </Button>
- <br /><br />
- </Col>
- </Row>
- </Grid>
+ <div>
+ <p>{t('Choose a datasource')}</p>
+ <div style={styleSelectWidth}>
+ <Select
+ clearable={false}
+ style={styleSelectWidth}
+ name="select-datasource"
+ onChange={this.changeDatasource.bind(this)}
+ options={this.props.datasources}
+ placeholder={t('Choose a datasource')}
+ value={this.state.datasourceValue}
+ width={200}
+ />
+ </div>
+ <p className="text-muted">
+ {t(
+ 'If the datasource your are looking for is not ' +
+ 'available in the list, ' +
+ 'follow the instructions on the how to add it on the ')}
+ <a href="http://superset.apache.org/tutorial.html">{t('Superset tutorial')}</a>
+ </p>
+ </div>
+ <br />
+ <div>
+ <p>{t('Choose a visualization type')}</p>
+ <Select
+ clearable={false}
+ name="select-vis-type"
+ style={styleSelectWidth}
+ onChange={this.changeVisType.bind(this)}
+ options={this.vizTypeOptions}
+ placeholder={t('Choose a visualization type')}
+ value={this.state.visType}
+ />
+ </div>
+ <br />
+ <Button
+ bsStyle="primary"
+ disabled={this.isBtnDisabled()}
+ onClick={this.gotoSlice.bind(this)}
+ >
+ {t('Create new slice')}
+ </Button>
+ <br /><br />
</Panel>
</div>
);
diff --git a/superset/connectors/base/models.py b/superset/connectors/base/models.py
index 7a11598..68a020e 100644
--- a/superset/connectors/base/models.py
+++ b/superset/connectors/base/models.py
@@ -207,6 +207,10 @@ class BaseDatasource(AuditMixinNullable, ImportMixin):
values in filters in the explore view"""
raise NotImplementedError()
+ @staticmethod
+ def default_query(qry):
+ return qry
+
class BaseColumn(AuditMixinNullable, ImportMixin):
"""Interface for column"""
diff --git a/superset/connectors/connector_registry.py b/superset/connectors/connector_registry.py
index 0a6291a..79f876a 100644
--- a/superset/connectors/connector_registry.py
+++ b/superset/connectors/connector_registry.py
@@ -33,8 +33,10 @@ class ConnectorRegistry(object):
def get_all_datasources(cls, session):
datasources = []
for source_type in ConnectorRegistry.sources:
- datasources.extend(
- session.query(ConnectorRegistry.sources[source_type]).all())
+ source_class = ConnectorRegistry.sources[source_type]
+ qry = session.query(source_class)
+ qry = source_class.default_query(qry)
+ datasources.extend(qry.all())
return datasources
@classmethod
diff --git a/superset/connectors/sqla/models.py b/superset/connectors/sqla/models.py
index 7033048..8ed7080 100644
--- a/superset/connectors/sqla/models.py
+++ b/superset/connectors/sqla/models.py
@@ -268,6 +268,7 @@ class SqlaTable(Model, BaseDatasource):
foreign_keys=[database_id])
schema = Column(String(255))
sql = Column(Text)
+ is_sqllab_view = Column(Boolean, default=False)
baselink = 'tablemodelview'
@@ -819,6 +820,10 @@ class SqlaTable(Model, BaseDatasource):
query = query.filter_by(schema=schema)
return query.all()
+ @staticmethod
+ def default_query(qry):
+ return qry.filter_by(is_sqllab_view=False)
+
sa.event.listen(SqlaTable, 'after_insert', set_perm)
sa.event.listen(SqlaTable, 'after_update', set_perm)
diff --git a/superset/connectors/sqla/views.py b/superset/connectors/sqla/views.py
index 3d47795..2b8da0e 100644
--- a/superset/connectors/sqla/views.py
+++ b/superset/connectors/sqla/views.py
@@ -171,12 +171,15 @@ class TableModelView(DatasourceModelView, DeleteMixin, YamlExportMixin):
# noqa
'table_name', 'sql', 'filter_select_enabled', 'slices',
'fetch_values_predicate', 'database', 'schema',
'description', 'owner',
- 'main_dttm_col', 'default_endpoint', 'offset', 'cache_timeout']
+ 'main_dttm_col', 'default_endpoint', 'offset', 'cache_timeout',
+ 'is_sqllab_view',
+ ]
+ base_filters = [['id', DatasourceFilter, lambda: []]]
show_columns = edit_columns + ['perm']
related_views = [TableColumnInlineView, SqlMetricInlineView]
base_order = ('changed_on', 'desc')
search_columns = (
- 'database', 'schema', 'table_name', 'owner',
+ 'database', 'schema', 'table_name', 'owner', 'is_sqllab_view',
)
description_columns = {
'slices': _(
@@ -213,8 +216,10 @@ class TableModelView(DatasourceModelView, DeleteMixin, YamlExportMixin):
# noqa
"Whether to populate the filter's dropdown in the explore "
"view's filter section with a list of distinct values fetched "
'from the backend on the fly'),
+ 'is_sqllab_view': _(
+ "Whether the table was generated by the 'Visualize' flow "
+ 'in SQL Lab'),
}
- base_filters = [['id', DatasourceFilter, lambda: []]]
label_columns = {
'slices': _('Associated Charts'),
'link': _('Table'),
@@ -231,6 +236,7 @@ class TableModelView(DatasourceModelView, DeleteMixin, YamlExportMixin):
# noqa
'owner': _('Owner'),
'main_dttm_col': _('Main Datetime Column'),
'description': _('Description'),
+ 'is_sqllab_view': _('SQL Lab View'),
}
def pre_add(self, table):
@@ -298,13 +304,14 @@ class TableModelView(DatasourceModelView, DeleteMixin, YamlExportMixin):
# noqa
return redirect('/tablemodelview/list/')
-appbuilder.add_view(
- TableModelView,
+appbuilder.add_view_no_menu(TableModelView)
+appbuilder.add_link(
'Tables',
label=__('Tables'),
+ href='/tablemodelview/list/?_flt_1_is_sqllab_view=y',
+ icon='fa-upload',
category='Sources',
category_label=__('Sources'),
- icon='fa-table',
-)
+ category_icon='fa-table')
appbuilder.add_separator('Sources')
diff --git a/superset/migrations/versions/130915240929_is_sqllab_viz_flow.py b/superset/migrations/versions/130915240929_is_sqllab_viz_flow.py
new file mode 100644
index 0000000..be17c50
--- /dev/null
+++ b/superset/migrations/versions/130915240929_is_sqllab_viz_flow.py
@@ -0,0 +1,54 @@
+"""is_sqllab_view
+
+Revision ID: 130915240929
+Revises: f231d82b9b26
+Create Date: 2018-04-03 08:19:34.098789
+
+"""
+from alembic import op
+import sqlalchemy as sa
+from sqlalchemy.ext.declarative import declarative_base
+
+from superset import db
+
+# revision identifiers, used by Alembic.
+revision = '130915240929'
+down_revision = 'f231d82b9b26'
+
+Base = declarative_base()
+
+
+class Table(Base):
+ """Declarative class to do query in upgrade"""
+ __tablename__ = 'tables'
+ id = sa.Column(sa.Integer, primary_key=True)
+ sql = sa.Column(sa.Text)
+ is_sqllab_view = sa.Column(sa.Boolean())
+
+
+def upgrade():
+ bind = op.get_bind()
+ op.add_column(
+ 'tables',
+ sa.Column(
+ 'is_sqllab_view',
+ sa.Boolean(),
+ nullable=True,
+ default=False,
+ server_default=sa.false(),
+ ),
+ )
+
+ session = db.Session(bind=bind)
+
+ # Use Slice class defined here instead of models.Slice
+ for tbl in session.query(Table).all():
+ if tbl.sql:
+ tbl.is_sqllab_view = True
+ session.merge(tbl)
+ session.commit()
+ db.session.close()
+
+
+def downgrade():
+ op.drop_column('tables', 'is_sqllab_view')
diff --git a/superset/views/core.py b/superset/views/core.py
index 6ffa4ee..6629dbd 100755
--- a/superset/views/core.py
+++ b/superset/views/core.py
@@ -2144,6 +2144,7 @@ class Superset(BaseSupersetView):
table = SqlaTable(table_name=table_name)
table.database_id = data.get('dbId')
table.schema = data.get('schema')
+ table.is_sqllab_view = True
q = SupersetQuery(data.get('sql'))
table.sql = q.stripped()
db.session.add(table)
--
To stop receiving notification emails like this one, please contact
maximebeauchemin@apache.org.
|