diff --git a/superset/assets/javascripts/addSlice/AddSliceContainer.jsx b/superset/assets/javascripts/addSlice/AddSliceContainer.jsx
index 051693468..6b1f5e7a8 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 (
{t('Create a new slice')}}>
-
-
-
-
-
{t('Choose a datasource')}
-
-
-
-
-
{t('Choose a visualization type')}
-
-
-
-
-
-
-
-
+
+
{t('Choose a datasource')}
+
+
+
+
+ {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 ')}
+ {t('Superset tutorial')}
+
+
+
+
+
{t('Choose a visualization type')}
+
+
+
+
+
);
diff --git a/superset/connectors/base/models.py b/superset/connectors/base/models.py
index 7a115988a..68a020e36 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 0a6291ab4..79f876acf 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 703304864..8ed708079 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 3d4779535..2b8da0e45 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 000000000..be17c50c0
--- /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 6ffa4ee2c..6629dbd30 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)