mistercrunch closed pull request #4104: [explore] add datasource metadata
URL: https://github.com/apache/incubator-superset/pull/4104
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/superset/assets/javascripts/components/ColumnOption.jsx 
b/superset/assets/javascripts/components/ColumnOption.jsx
index c150937a0b..f579126b8d 100644
--- a/superset/assets/javascripts/components/ColumnOption.jsx
+++ b/superset/assets/javascripts/components/ColumnOption.jsx
@@ -5,9 +5,13 @@ import InfoTooltipWithTrigger from './InfoTooltipWithTrigger';
 
 const propTypes = {
   column: PropTypes.object.isRequired,
+  showType: PropTypes.bool,
+};
+const defaultProps = {
+  showType: false,
 };
 
-export default function ColumnOption({ column }) {
+export default function ColumnOption({ column, showType }) {
   return (
     <span>
       <span className="m-r-5 option-label">
@@ -29,6 +33,10 @@ export default function ColumnOption({ column }) {
           label={`expr-${column.column_name}`}
         />
       }
+      {showType &&
+        <span className="text-muted">{column.type}</span>
+      }
     </span>);
 }
 ColumnOption.propTypes = propTypes;
+ColumnOption.defaultProps = defaultProps;
diff --git 
a/superset/assets/javascripts/explore/components/controls/DatasourceControl.jsx 
b/superset/assets/javascripts/explore/components/controls/DatasourceControl.jsx
index eb7a63367c..e63c807089 100644
--- 
a/superset/assets/javascripts/explore/components/controls/DatasourceControl.jsx
+++ 
b/superset/assets/javascripts/explore/components/controls/DatasourceControl.jsx
@@ -2,10 +2,15 @@
 import React from 'react';
 import PropTypes from 'prop-types';
 import { Table } from 'reactable';
-import { Label, FormControl, Modal, OverlayTrigger, Tooltip } from 
'react-bootstrap';
+import {
+  Row, Col, Collapse, Label, FormControl, Modal,
+  OverlayTrigger, Tooltip, Well,
+} from 'react-bootstrap';
 
 import ControlHeader from '../ControlHeader';
 import { t } from '../../../locales';
+import ColumnOption from '../../../components/ColumnOption';
+import MetricOption from '../../../components/MetricOption';
 
 const propTypes = {
   description: PropTypes.string,
@@ -27,11 +32,14 @@ export default class DatasourceControl extends 
React.PureComponent {
       showModal: false,
       filter: '',
       loading: true,
+      showDatasource: false,
     };
+    this.toggleShowDatasource = this.toggleShowDatasource.bind(this);
+    this.onChange = this.onChange.bind(this);
+    this.onEnterModal = this.onEnterModal.bind(this);
     this.toggleModal = this.toggleModal.bind(this);
     this.changeSearch = this.changeSearch.bind(this);
-    this.setSearchRef = this.setSearchRef.bind(this);
-    this.onEnterModal = this.onEnterModal.bind(this);
+    this.selectDatasource = this.selectDatasource.bind(this);
   }
   onChange(vizType) {
     this.props.onChange(vizType);
@@ -75,6 +83,9 @@ export default class DatasourceControl extends 
React.PureComponent {
   setSearchRef(searchRef) {
     this.searchRef = searchRef;
   }
+  toggleShowDatasource() {
+    this.setState({ showDatasource: !this.state.showDatasource });
+  }
   toggleModal() {
     this.setState({ showModal: !this.state.showModal });
   }
@@ -85,6 +96,79 @@ export default class DatasourceControl extends 
React.PureComponent {
     this.setState({ showModal: false });
     this.props.onChange(datasourceId);
   }
+  renderModal() {
+    return (
+      <Modal
+        show={this.state.showModal}
+        onHide={this.toggleModal}
+        onEnter={this.onEnterModal}
+        onExit={this.setSearchRef}
+        bsSize="lg"
+      >
+        <Modal.Header closeButton>
+          <Modal.Title>{t('Select a datasource')}</Modal.Title>
+        </Modal.Header>
+        <Modal.Body>
+          <div>
+            <FormControl
+              id="formControlsText"
+              inputRef={(ref) => { this.setSearchRef(ref); }}
+              type="text"
+              bsSize="sm"
+              value={this.state.filter}
+              placeholder={t('Search / Filter')}
+              onChange={this.changeSearch}
+            />
+          </div>
+          {this.state.loading &&
+            <img
+              className="loading"
+              alt="Loading..."
+              src="/static/assets/images/loading.gif"
+            />
+          }
+          {this.state.datasources &&
+            <Table
+              columns={['name', 'type', 'schema', 'connection', 'creator']}
+              className="table table-condensed"
+              data={this.state.datasources}
+              itemsPerPage={20}
+              filterable={['rawName', 'type', 'connection', 'schema', 
'creator']}
+              filterBy={this.state.filter}
+              hideFilterInput
+            />
+          }
+        </Modal.Body>
+      </Modal>);
+  }
+  renderDatasource() {
+    const datasource = this.props.datasource;
+    return (
+      <div className="m-t-10">
+        <Well className="m-t-0">
+          <div className="m-b-10">
+            <Label>
+              <i className="fa fa-database" /> {datasource.database.backend}
+            </Label>
+            {` ${datasource.database.name} `}
+          </div>
+          <Row>
+            <Col md={6}>
+              <strong>Columns</strong>
+              {datasource.columns.map(col => (
+                <div key={col.column_name}><ColumnOption showType column={col} 
/></div>
+              ))}
+            </Col>
+            <Col md={6}>
+              <strong>Metrics</strong>
+              {datasource.metrics.map(m => (
+                <div key={m.metric_name}><MetricOption metric={m} /></div>
+              ))}
+            </Col>
+          </Row>
+        </Well>
+      </div>);
+  }
   render() {
     return (
       <div>
@@ -108,51 +192,28 @@ export default class DatasourceControl extends 
React.PureComponent {
           }
         >
           <a href={this.props.datasource.edit_url}>
-            <i className="fa fa-edit" />
+            <i className="fa fa-edit m-r-5" />
           </a>
         </OverlayTrigger>
-        <Modal
-          show={this.state.showModal}
-          onHide={this.toggleModal}
-          onEnter={this.onEnterModal}
-          onExit={this.setSearchRef}
-          bsSize="lg"
+        <OverlayTrigger
+          placement="right"
+          overlay={
+            <Tooltip id={'toggle-datasource-tooltip'}>
+              {t('Show datasource configuration')}
+            </Tooltip>
+          }
         >
-          <Modal.Header closeButton>
-            <Modal.Title>{t('Select a datasource')}</Modal.Title>
-          </Modal.Header>
-          <Modal.Body>
-            <div>
-              <FormControl
-                id="formControlsText"
-                inputRef={(ref) => { this.setSearchRef(ref); }}
-                type="text"
-                bsSize="sm"
-                value={this.state.filter}
-                placeholder={t('Search / Filter')}
-                onChange={this.changeSearch}
-              />
-            </div>
-            {this.state.loading &&
-              <img
-                className="loading"
-                alt="Loading..."
-                src="/static/assets/images/loading.gif"
-              />
-            }
-            {this.state.datasources &&
-              <Table
-                columns={['name', 'type', 'schema', 'connection', 'creator']}
-                className="table table-condensed"
-                data={this.state.datasources}
-                itemsPerPage={20}
-                filterable={['rawName', 'type', 'connection', 'schema', 
'creator']}
-                filterBy={this.state.filter}
-                hideFilterInput
-              />
-            }
-          </Modal.Body>
-        </Modal>
+          <a href="#">
+            <i
+              className={`fa fa-${this.state.showDatasource ? 'minus' : 
'plus'}-square m-r-5`}
+              onClick={this.toggleShowDatasource}
+            />
+          </a>
+        </OverlayTrigger>
+        <Collapse in={this.state.showDatasource}>
+          {this.renderDatasource()}
+        </Collapse>
+        {this.renderModal()}
       </div>);
   }
 }
diff --git 
a/superset/assets/spec/javascripts/explore/components/DatasourceControl_spec.jsx
 
b/superset/assets/spec/javascripts/explore/components/DatasourceControl_spec.jsx
index c46ded004a..d206829cd7 100644
--- 
a/superset/assets/spec/javascripts/explore/components/DatasourceControl_spec.jsx
+++ 
b/superset/assets/spec/javascripts/explore/components/DatasourceControl_spec.jsx
@@ -15,6 +15,12 @@ const defaultProps = {
     type: 'table',
     uid: '1__table',
     id: 1,
+    columns: [],
+    metrics: [],
+    database: {
+      backend: 'mysql',
+      name: 'main',
+    },
   },
   onChange: sinon.spy(),
 };
diff --git a/superset/assets/stylesheets/superset.less 
b/superset/assets/stylesheets/superset.less
index ae0be2cd64..14c7519bca 100644
--- a/superset/assets/stylesheets/superset.less
+++ b/superset/assets/stylesheets/superset.less
@@ -252,6 +252,9 @@ table.table-no-hover tr:hover {
 .m-t-10 {
     margin-top: 10px;
 }
+.m-b-10 {
+    margin-bottom: 10px;
+}
 .m-l-5 {
     margin-left: 5px;
 }
diff --git a/superset/connectors/base/models.py 
b/superset/connectors/base/models.py
index 9bead749dd..2057ea8aa9 100644
--- a/superset/connectors/base/models.py
+++ b/superset/connectors/base/models.py
@@ -157,6 +157,7 @@ def data(self):
         return {
             'all_cols': utils.choicify(self.column_names),
             'column_formats': self.column_formats,
+            'database': self.database.data,  # pylint: disable=no-member
             'edit_url': self.url,
             'filter_select': self.filter_select_enabled,
             'filterable_cols': utils.choicify(self.filterable_column_names),
@@ -256,7 +257,7 @@ def expression(self):
     def data(self):
         attrs = (
             'column_name', 'verbose_name', 'description', 'expression',
-            'filterable', 'groupby', 'is_dttm')
+            'filterable', 'groupby', 'is_dttm', 'type')
         return {s: getattr(self, s) for s in attrs}
 
 
diff --git a/superset/connectors/druid/models.py 
b/superset/connectors/druid/models.py
index a1d9ec0944..45d5d25913 100644
--- a/superset/connectors/druid/models.py
+++ b/superset/connectors/druid/models.py
@@ -91,6 +91,13 @@ class DruidCluster(Model, AuditMixinNullable, ImportMixin):
     def __repr__(self):
         return self.verbose_name if self.verbose_name else self.cluster_name
 
+    @property
+    def data(self):
+        return {
+            'name': self.cluster_name,
+            'backend': 'druid',
+        }
+
     def get_pydruid_client(self):
         cli = PyDruid(
             'http://{0}:{1}/'.format(self.broker_host, self.broker_port),
diff --git a/superset/models/core.py b/superset/models/core.py
index 396db2dc32..f2ca42bb13 100644
--- a/superset/models/core.py
+++ b/superset/models/core.py
@@ -581,6 +581,13 @@ def __repr__(self):
     def name(self):
         return self.verbose_name if self.verbose_name else self.database_name
 
+    @property
+    def data(self):
+        return {
+            'name': self.database_name,
+            'backend': self.backend,
+        }
+
     @property
     def unique_name(self):
         return self.database_name


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
[email protected]


With regards,
Apache Git Services

Reply via email to