diff --git a/superset/assets/javascripts/explore/stores/controls.jsx b/superset/assets/javascripts/explore/stores/controls.jsx
index cc35d0e573..617c717d5f 100644
--- a/superset/assets/javascripts/explore/stores/controls.jsx
+++ b/superset/assets/javascripts/explore/stores/controls.jsx
@@ -1,5 +1,9 @@
import React from 'react';
-import { formatSelectOptionsForRange, formatSelectOptions } from '../../modules/utils';
+import {
+ formatSelectOptionsForRange,
+ formatSelectOptions,
+ mainMetric,
+} from '../../modules/utils';
import * as v from '../validators';
import { colorPrimary, ALL_COLOR_SCHEMES, spectrums } from '../../modules/colors';
import { defaultViewport } from '../../modules/geo';
@@ -82,6 +86,7 @@ const jsFunctionInfo = (
.
);
+
function jsFunctionControl(label, description, extraDescr = null, height = 100, defaultText = '') {
return {
type: 'TextAreaControl',
@@ -131,7 +136,10 @@ export const controls = {
valueKey: 'metric_name',
optionRenderer: m => ,
valueRenderer: m => ,
- default: c => c.options && c.options.length > 0 ? [c.options[0].metric_name] : null,
+ default: (c) => {
+ const metric = mainMetric(c.options);
+ return metric ? [metric] : null;
+ },
mapStateToProps: state => ({
options: (state.datasource) ? state.datasource.metrics : [],
}),
@@ -218,7 +226,7 @@ export const controls = {
validators: [v.nonEmpty],
optionRenderer: m => ,
valueRenderer: m => ,
- default: c => c.options && c.options.length > 0 ? c.options[0].metric_name : null,
+ default: c => mainMetric(c.options),
valueKey: 'metric_name',
mapStateToProps: state => ({
options: (state.datasource) ? state.datasource.metrics : [],
diff --git a/superset/assets/javascripts/modules/utils.js b/superset/assets/javascripts/modules/utils.js
index b5590f0e79..61807837c2 100644
--- a/superset/assets/javascripts/modules/utils.js
+++ b/superset/assets/javascripts/modules/utils.js
@@ -259,3 +259,19 @@ export function getParam(name) {
const results = regex.exec(location.search);
return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' '));
}
+
+export function mainMetric(metricOptions) {
+ // Using 'count' as default metric if it exists, otherwise using whatever one shows up first
+ let metric;
+ if (metricOptions && metricOptions.length > 0) {
+ metricOptions.forEach((m) => {
+ if (m.metric_name === 'count') {
+ metric = 'count';
+ }
+ });
+ if (!metric) {
+ metric = metricOptions[0].metric_name;
+ }
+ }
+ return metric;
+}
diff --git a/superset/assets/spec/javascripts/modules/utils_spec.jsx b/superset/assets/spec/javascripts/modules/utils_spec.jsx
index 174e0e1e61..309d62f4cf 100644
--- a/superset/assets/spec/javascripts/modules/utils_spec.jsx
+++ b/superset/assets/spec/javascripts/modules/utils_spec.jsx
@@ -3,6 +3,7 @@ import { expect } from 'chai';
import {
tryNumify, slugify, formatSelectOptionsForRange, d3format,
d3FormatPreset, d3TimeFormatPreset, defaultNumberFormatter,
+ mainMetric,
} from '../../../javascripts/modules/utils';
describe('utils', () => {
@@ -69,4 +70,31 @@ describe('utils', () => {
expect(defaultNumberFormatter(-111000000)).to.equal('-111M');
expect(defaultNumberFormatter(-0.23)).to.equal('-230m');
});
+ describe('mainMetric', () => {
+ it('is null when no options', () => {
+ expect(mainMetric([])).to.equal(undefined);
+ expect(mainMetric(null)).to.equal(undefined);
+ });
+ it('prefers the "count" metric when first', () => {
+ const metrics = [
+ { metric_name: 'count' },
+ { metric_name: 'foo' },
+ ];
+ expect(mainMetric(metrics)).to.equal('count');
+ });
+ it('prefers the "count" metric when not first', () => {
+ const metrics = [
+ { metric_name: 'foo' },
+ { metric_name: 'count' },
+ ];
+ expect(mainMetric(metrics)).to.equal('count');
+ });
+ it('selects the first metric when "count" is not an option', () => {
+ const metrics = [
+ { metric_name: 'foo' },
+ { metric_name: 'not_count' },
+ ];
+ expect(mainMetric(metrics)).to.equal('foo');
+ });
+ });
});