superset-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From maximebeauche...@apache.org
Subject [incubator-superset] branch master updated: Adding rowcount label to explore view header (#4059)
Date Fri, 15 Dec 2017 19:47:47 GMT
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 c21513f  Adding rowcount label to explore view header (#4059)
c21513f is described below

commit c21513fb8cfaafe7de564e57313f2a3ce7ea7f07
Author: Maxime Beauchemin <maximebeauchemin@gmail.com>
AuthorDate: Fri Dec 15 11:47:44 2017 -0800

    Adding rowcount label to explore view header (#4059)
---
 .../explore/components/ExploreChartHeader.jsx      | 19 +++++++---
 .../explore/components/RowCountLabel.jsx           | 42 ++++++++++++++++++++++
 superset/assets/javascripts/modules/utils.js       | 13 ++++++-
 .../explore/components/RowCountLabel_spec.jsx      | 33 +++++++++++++++++
 .../assets/spec/javascripts/modules/utils_spec.jsx | 19 +++++++++-
 superset/viz.py                                    |  3 ++
 6 files changed, 122 insertions(+), 7 deletions(-)

diff --git a/superset/assets/javascripts/explore/components/ExploreChartHeader.jsx b/superset/assets/javascripts/explore/components/ExploreChartHeader.jsx
index b8b52e3..30b4799 100644
--- a/superset/assets/javascripts/explore/components/ExploreChartHeader.jsx
+++ b/superset/assets/javascripts/explore/components/ExploreChartHeader.jsx
@@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
 
 import { chartPropType } from '../../chart/chartReducer';
 import ExploreActionButtons from './ExploreActionButtons';
+import RowCountLabel from './RowCountLabel';
 import EditableTitle from '../../components/EditableTitle';
 import AlteredSliceTag from '../../components/AlteredSliceTag';
 import FaveStar from '../../components/FaveStar';
@@ -66,11 +67,12 @@ class ExploreChartHeader extends React.PureComponent {
   }
 
   render() {
+    const formData = this.props.form_data;
     const queryResponse = this.props.chart.queryResponse;
     const data = {
-      csv_endpoint: getExploreUrl(this.props.form_data, 'csv'),
-      json_endpoint: getExploreUrl(this.props.form_data, 'json'),
-      standalone_endpoint: getExploreUrl(this.props.form_data, 'standalone'),
+      csv_endpoint: getExploreUrl(formData, 'csv'),
+      json_endpoint: getExploreUrl(formData, 'json'),
+      standalone_endpoint: getExploreUrl(formData, 'standalone'),
     };
 
     return (
@@ -109,13 +111,20 @@ class ExploreChartHeader extends React.PureComponent {
         {this.props.chart.sliceFormData &&
           <AlteredSliceTag
             origFormData={this.props.chart.sliceFormData}
-            currentFormData={this.props.form_data}
+            currentFormData={formData}
           />
         }
         <div className="pull-right">
+          {this.props.chart.chartStatus === 'success' && queryResponse &&
+            <RowCountLabel
+              rowcount={queryResponse.rowcount}
+              limit={formData.row_limit}
+            />
+          }
           {this.props.chart.chartStatus === 'success' &&
           queryResponse &&
           queryResponse.is_cached &&
+
           <CachedLabel
             onClick={this.runQuery.bind(this)}
             cachedTimestamp={queryResponse.cached_dttm}
@@ -133,7 +142,7 @@ class ExploreChartHeader extends React.PureComponent {
             canDownload={this.props.can_download}
             chartStatus={this.props.chart.chartStatus}
             queryResponse={queryResponse}
-            queryEndpoint={getExploreUrl(this.props.form_data, 'query')}
+            queryEndpoint={getExploreUrl(formData, 'query')}
           />
         </div>
       </div>
diff --git a/superset/assets/javascripts/explore/components/RowCountLabel.jsx b/superset/assets/javascripts/explore/components/RowCountLabel.jsx
new file mode 100644
index 0000000..1b29a03
--- /dev/null
+++ b/superset/assets/javascripts/explore/components/RowCountLabel.jsx
@@ -0,0 +1,42 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { Label } from 'react-bootstrap';
+
+import { t } from '../../locales';
+import { defaultNumberFormatter } from '../../modules/utils';
+import TooltipWrapper from '../../components/TooltipWrapper';
+
+
+const propTypes = {
+  rowcount: PropTypes.number,
+  limit: PropTypes.number,
+};
+
+const defaultProps = {
+};
+
+export default function RowCountLabel({ rowcount, limit }) {
+  const limitReached = rowcount === limit;
+  const bsStyle = (limitReached || rowcount === 0) ? 'warning' : 'default';
+  const formattedRowCount = defaultNumberFormatter(rowcount);
+  const tooltip = (
+    <span>
+      {limitReached &&
+        <div>{t('Limit reached')}</div>}
+      {rowcount}
+    </span>
+  );
+  return (
+    <TooltipWrapper label="tt-rowcount" tooltip={tooltip}>
+      <Label
+        bsStyle={bsStyle}
+        style={{ fontSize: '10px', marginRight: '5px', cursor: 'pointer' }}
+      >
+        {formattedRowCount} rows
+      </Label>
+    </TooltipWrapper>
+  );
+}
+
+RowCountLabel.propTypes = propTypes;
+RowCountLabel.defaultProps = defaultProps;
diff --git a/superset/assets/javascripts/modules/utils.js b/superset/assets/javascripts/modules/utils.js
index e7757d4..b5590f0 100644
--- a/superset/assets/javascripts/modules/utils.js
+++ b/superset/assets/javascripts/modules/utils.js
@@ -4,6 +4,17 @@ import $ from 'jquery';
 
 import { formatDate, UTC } from './dates';
 
+const siFormatter = d3.format('.3s');
+
+export function defaultNumberFormatter(n) {
+  let si = siFormatter(n);
+  // Removing trailing `.00` if any
+  if (si.slice(-1) < 'A') {
+    si = parseFloat(si).toString();
+  }
+  return si;
+}
+
 export function d3FormatPreset(format) {
   // like d3.format, but with support for presets like 'smart_date'
   if (format === 'smart_date') {
@@ -12,7 +23,7 @@ export function d3FormatPreset(format) {
   if (format) {
     return d3.format(format);
   }
-  return d3.format('.3s');
+  return defaultNumberFormatter;
 }
 export const d3TimeFormatPreset = function (format) {
   const effFormat = format || 'smart_date';
diff --git a/superset/assets/spec/javascripts/explore/components/RowCountLabel_spec.jsx b/superset/assets/spec/javascripts/explore/components/RowCountLabel_spec.jsx
new file mode 100644
index 0000000..1642fd7
--- /dev/null
+++ b/superset/assets/spec/javascripts/explore/components/RowCountLabel_spec.jsx
@@ -0,0 +1,33 @@
+import React from 'react';
+import { expect } from 'chai';
+import { describe, it } from 'mocha';
+import { shallow } from 'enzyme';
+import { Label } from 'react-bootstrap';
+
+import TooltipWrapper from './../../../../javascripts/components/TooltipWrapper';
+
+import RowCountLabel from '../../../../javascripts/explore/components/RowCountLabel';
+
+describe('RowCountLabel', () => {
+  const defaultProps = {
+    rowcount: 51,
+    limit: 100,
+  };
+
+  it('is valid', () => {
+    expect(React.isValidElement(<RowCountLabel {...defaultProps} />)).to.equal(true);
+  });
+  it('renders a Label and a TooltipWrapper', () => {
+    const wrapper = shallow(<RowCountLabel {...defaultProps} />);
+    expect(wrapper.find(Label)).to.have.lengthOf(1);
+    expect(wrapper.find(TooltipWrapper)).to.have.lengthOf(1);
+  });
+  it('renders a warning when limit is reached', () => {
+    const props = {
+      rowcount: 100,
+      limit: 100,
+    };
+    const wrapper = shallow(<RowCountLabel {...props} />);
+    expect(wrapper.find(Label).first().props().bsStyle).to.equal('warning');
+  });
+});
diff --git a/superset/assets/spec/javascripts/modules/utils_spec.jsx b/superset/assets/spec/javascripts/modules/utils_spec.jsx
index 1e3f2d4..174e0e1 100644
--- a/superset/assets/spec/javascripts/modules/utils_spec.jsx
+++ b/superset/assets/spec/javascripts/modules/utils_spec.jsx
@@ -2,7 +2,7 @@ import { it, describe } from 'mocha';
 import { expect } from 'chai';
 import {
   tryNumify, slugify, formatSelectOptionsForRange, d3format,
-  d3FormatPreset, d3TimeFormatPreset,
+  d3FormatPreset, d3TimeFormatPreset, defaultNumberFormatter,
 } from '../../../javascripts/modules/utils';
 
 describe('utils', () => {
@@ -52,4 +52,21 @@ describe('utils', () => {
       expect(d3FormatPreset('smart_date')(0)).to.equal('1970');
     });
   });
+  describe('d3TimeFormatPreset', () => {
+    expect(defaultNumberFormatter(10)).to.equal('10');
+    expect(defaultNumberFormatter(1)).to.equal('1');
+    expect(defaultNumberFormatter(1.0)).to.equal('1');
+    expect(defaultNumberFormatter(10.0)).to.equal('10');
+    expect(defaultNumberFormatter(10001)).to.equal('10.0k');
+    expect(defaultNumberFormatter(111000000)).to.equal('111M');
+    expect(defaultNumberFormatter(0.23)).to.equal('230m');
+
+    expect(defaultNumberFormatter(-10)).to.equal('-10');
+    expect(defaultNumberFormatter(-1)).to.equal('-1');
+    expect(defaultNumberFormatter(-1.0)).to.equal('-1');
+    expect(defaultNumberFormatter(-10.0)).to.equal('-10');
+    expect(defaultNumberFormatter(-10001)).to.equal('-10.0k');
+    expect(defaultNumberFormatter(-111000000)).to.equal('-111M');
+    expect(defaultNumberFormatter(-0.23)).to.equal('-230m');
+  });
 });
diff --git a/superset/viz.py b/superset/viz.py
index 2ea85d2..6551577 100644
--- a/superset/viz.py
+++ b/superset/viz.py
@@ -273,11 +273,13 @@ class BaseViz(object):
             cache_timeout = self.cache_timeout
             stacktrace = None
             annotations = []
+            rowcount = None
             try:
                 df = self.get_df()
                 if not self.error_message:
                     data = self.get_data(df)
                 annotations = self.get_annotations()
+                rowcount = len(df.index)
             except Exception as e:
                 logging.exception(e)
                 if not self.error_message:
@@ -295,6 +297,7 @@ class BaseViz(object):
                 'status': self.status,
                 'stacktrace': stacktrace,
                 'annotations': annotations,
+                'rowcount': rowcount,
             }
             payload['cached_dttm'] = datetime.utcnow().isoformat().split('.')[0]
             logging.info('Caching for the next {} seconds'.format(

-- 
To stop receiving notification emails like this one, please contact
['"commits@superset.apache.org" <commits@superset.apache.org>'].

Mime
View raw message