diff --git a/superset/assets/src/explore/components/controls/index.js b/superset/assets/src/explore/components/controls/index.js
index d1a2f2c27..32a8d449c 100644
--- a/superset/assets/src/explore/components/controls/index.js
+++ b/superset/assets/src/explore/components/controls/index.js
@@ -20,6 +20,7 @@ import AnnotationLayerControl from './AnnotationLayerControl';
import BoundsControl from './BoundsControl';
import CheckboxControl from './CheckboxControl';
import CollectionControl from './CollectionControl';
+import ColorMapControl from './ColorMapControl';
import ColorPickerControl from './ColorPickerControl';
import ColorSchemeControl from './ColorSchemeControl';
import DatasourceControl from './DatasourceControl';
@@ -45,6 +46,7 @@ const controlMap = {
BoundsControl,
CheckboxControl,
CollectionControl,
+ ColorMapControl,
ColorPickerControl,
ColorSchemeControl,
DatasourceControl,
diff --git a/superset/assets/src/explore/controlPanels/Area.js b/superset/assets/src/explore/controlPanels/Area.js
index 73b5994a8..b978cd15e 100644
--- a/superset/assets/src/explore/controlPanels/Area.js
+++ b/superset/assets/src/explore/controlPanels/Area.js
@@ -30,7 +30,7 @@ export default {
controlSetRows: [
['show_brush', 'show_legend'],
['line_interpolation', 'stacked_style'],
- ['color_scheme'],
+ ['color_scheme', 'label_colors'],
['rich_tooltip', 'show_controls'],
],
},
diff --git a/superset/assets/src/explore/controlPanels/Bar.js b/superset/assets/src/explore/controlPanels/Bar.js
index c3cbc733e..b21fb4727 100644
--- a/superset/assets/src/explore/controlPanels/Bar.js
+++ b/superset/assets/src/explore/controlPanels/Bar.js
@@ -28,7 +28,7 @@ export default {
label: t('Chart Options'),
expanded: true,
controlSetRows: [
- ['color_scheme'],
+ ['color_scheme', 'label_colors'],
['show_brush', 'show_legend', 'show_bar_value'],
['rich_tooltip', 'bar_stacked'],
['line_interpolation', 'show_controls'],
diff --git a/superset/assets/src/explore/controlPanels/BigNumber.js b/superset/assets/src/explore/controlPanels/BigNumber.js
index b931c7100..e621ee1f7 100644
--- a/superset/assets/src/explore/controlPanels/BigNumber.js
+++ b/superset/assets/src/explore/controlPanels/BigNumber.js
@@ -29,13 +29,21 @@ export default {
],
},
{
- label: t('Chart Options'),
+ label: t('Options'),
expanded: true,
controlSetRows: [
['compare_lag', 'compare_suffix'],
['y_axis_format', null],
['show_trend_line', 'start_y_axis_at_zero'],
+ ],
+ },
+ {
+ label: t('Chart Options'),
+ expanded: true,
+ controlSetRows: [
['color_picker', null],
+ ['header_font_size'],
+ ['subheader_font_size'],
],
},
],
@@ -43,5 +51,8 @@ export default {
y_axis_format: {
label: t('Number format'),
},
+ header_font_size: {
+ label: t('Big Number Font Size'),
+ },
},
};
diff --git a/superset/assets/src/explore/controlPanels/BigNumberTotal.js b/superset/assets/src/explore/controlPanels/BigNumberTotal.js
index 22a7d6980..7b3e730ce 100644
--- a/superset/assets/src/explore/controlPanels/BigNumberTotal.js
+++ b/superset/assets/src/explore/controlPanels/BigNumberTotal.js
@@ -29,17 +29,28 @@ export default {
],
},
{
- label: t('Chart Options'),
+ label: t('Options'),
expanded: true,
controlSetRows: [
['subheader'],
['y_axis_format'],
],
},
+ {
+ label: t('Chart Options'),
+ expanded: true,
+ controlSetRows: [
+ ['header_font_size'],
+ ['subheader_font_size'],
+ ],
+ },
],
controlOverrides: {
y_axis_format: {
label: t('Number format'),
},
+ header_font_size: {
+ label: t('Big Number Font Size'),
+ },
},
};
diff --git a/superset/assets/src/explore/controlPanels/BoxPlot.js b/superset/assets/src/explore/controlPanels/BoxPlot.js
index 142c1d663..1cdf320d9 100644
--- a/superset/assets/src/explore/controlPanels/BoxPlot.js
+++ b/superset/assets/src/explore/controlPanels/BoxPlot.js
@@ -34,7 +34,7 @@ export default {
label: t('Chart Options'),
expanded: true,
controlSetRows: [
- ['color_scheme'],
+ ['color_scheme', 'label_colors'],
['whisker_options', 'x_ticks_layout'],
],
},
diff --git a/superset/assets/src/explore/controlPanels/Bubble.js b/superset/assets/src/explore/controlPanels/Bubble.js
index d3cdaca64..891fe29cf 100644
--- a/superset/assets/src/explore/controlPanels/Bubble.js
+++ b/superset/assets/src/explore/controlPanels/Bubble.js
@@ -38,7 +38,7 @@ export default {
label: t('Chart Options'),
expanded: true,
controlSetRows: [
- ['color_scheme'],
+ ['color_scheme', 'label_colors'],
['show_legend', null],
],
},
@@ -62,9 +62,6 @@ export default {
},
],
controlOverrides: {
- x_axis_format: {
- default: '.3s',
- },
color_scheme: {
renderTrigger: false,
},
diff --git a/superset/assets/src/explore/controlPanels/Chord.js b/superset/assets/src/explore/controlPanels/Chord.js
index 18ae6eb67..b932c3f0e 100644
--- a/superset/assets/src/explore/controlPanels/Chord.js
+++ b/superset/assets/src/explore/controlPanels/Chord.js
@@ -37,7 +37,7 @@ export default {
expanded: true,
controlSetRows: [
['y_axis_format', null],
- ['color_scheme'],
+ ['color_scheme', 'label_colors'],
],
},
],
diff --git a/superset/assets/src/explore/controlPanels/Compare.js b/superset/assets/src/explore/controlPanels/Compare.js
index 091e8db49..3c50834ae 100644
--- a/superset/assets/src/explore/controlPanels/Compare.js
+++ b/superset/assets/src/explore/controlPanels/Compare.js
@@ -28,7 +28,7 @@ export default {
label: t('Chart Options'),
expanded: true,
controlSetRows: [
- ['color_scheme'],
+ ['color_scheme', 'label_colors'],
],
},
{
diff --git a/superset/assets/src/explore/controlPanels/DeckArc.js b/superset/assets/src/explore/controlPanels/DeckArc.js
index d54d59dc5..e0bee756f 100644
--- a/superset/assets/src/explore/controlPanels/DeckArc.js
+++ b/superset/assets/src/explore/controlPanels/DeckArc.js
@@ -42,7 +42,7 @@ export default {
label: t('Arc'),
controlSetRows: [
['color_picker', 'target_color_picker'],
- ['dimension', 'color_scheme'],
+ ['dimension', 'color_scheme', 'label_colors'],
['stroke_width', 'legend_position'],
],
},
diff --git a/superset/assets/src/explore/controlPanels/DeckScatter.js b/superset/assets/src/explore/controlPanels/DeckScatter.js
index 79476228c..8e60029fe 100644
--- a/superset/assets/src/explore/controlPanels/DeckScatter.js
+++ b/superset/assets/src/explore/controlPanels/DeckScatter.js
@@ -62,7 +62,7 @@ export default {
label: t('Point Color'),
controlSetRows: [
['color_picker', 'legend_position'],
- ['dimension', 'color_scheme'],
+ ['dimension', 'color_scheme', 'label_colors'],
],
},
{
diff --git a/superset/assets/src/explore/controlPanels/DistBar.js b/superset/assets/src/explore/controlPanels/DistBar.js
index fff22d688..41b944e1c 100644
--- a/superset/assets/src/explore/controlPanels/DistBar.js
+++ b/superset/assets/src/explore/controlPanels/DistBar.js
@@ -36,7 +36,7 @@ export default {
label: t('Chart Options'),
expanded: true,
controlSetRows: [
- ['color_scheme'],
+ ['color_scheme', 'label_colors'],
['show_legend', 'show_bar_value'],
['bar_stacked', 'order_bars'],
['y_axis_format', 'y_axis_label'],
diff --git a/superset/assets/src/explore/controlPanels/DualLine.js b/superset/assets/src/explore/controlPanels/DualLine.js
index 4792b4a2c..11d930fd3 100644
--- a/superset/assets/src/explore/controlPanels/DualLine.js
+++ b/superset/assets/src/explore/controlPanels/DualLine.js
@@ -27,7 +27,7 @@ export default {
label: t('Chart Options'),
expanded: true,
controlSetRows: [
- ['color_scheme'],
+ ['color_scheme', 'label_colors'],
['x_axis_format'],
],
},
diff --git a/superset/assets/src/explore/controlPanels/Histogram.js b/superset/assets/src/explore/controlPanels/Histogram.js
index 1df41842f..d95ff80a2 100644
--- a/superset/assets/src/explore/controlPanels/Histogram.js
+++ b/superset/assets/src/explore/controlPanels/Histogram.js
@@ -35,7 +35,7 @@ export default {
label: t('Chart Options'),
expanded: true,
controlSetRows: [
- ['color_scheme'],
+ ['color_scheme', 'label_colors'],
['link_length'],
['x_axis_label', 'y_axis_label'],
['global_opacity'],
diff --git a/superset/assets/src/explore/controlPanels/Line.js b/superset/assets/src/explore/controlPanels/Line.js
index 012976a6e..a92427dee 100644
--- a/superset/assets/src/explore/controlPanels/Line.js
+++ b/superset/assets/src/explore/controlPanels/Line.js
@@ -28,7 +28,7 @@ export default {
label: t('Chart Options'),
expanded: true,
controlSetRows: [
- ['color_scheme'],
+ ['color_scheme', 'label_colors'],
['show_brush', 'send_time_range', 'show_legend'],
['rich_tooltip', 'show_markers'],
['line_interpolation'],
diff --git a/superset/assets/src/explore/controlPanels/LineMulti.js b/superset/assets/src/explore/controlPanels/LineMulti.js
index 0966712bd..71c0182ed 100644
--- a/superset/assets/src/explore/controlPanels/LineMulti.js
+++ b/superset/assets/src/explore/controlPanels/LineMulti.js
@@ -27,7 +27,7 @@ export default {
label: t('Chart Options'),
expanded: true,
controlSetRows: [
- ['color_scheme'],
+ ['color_scheme', 'label_colors'],
['prefix_metric_with_slice_name', null],
['show_legend', 'show_markers'],
['line_interpolation', null],
diff --git a/superset/assets/src/explore/controlPanels/Partition.js b/superset/assets/src/explore/controlPanels/Partition.js
index 2bee2180a..a450da2ba 100644
--- a/superset/assets/src/explore/controlPanels/Partition.js
+++ b/superset/assets/src/explore/controlPanels/Partition.js
@@ -33,7 +33,7 @@ export default {
label: t('Chart Options'),
expanded: true,
controlSetRows: [
- ['color_scheme'],
+ ['color_scheme', 'label_colors'],
['number_format', 'date_time_format'],
['partition_limit', 'partition_threshold'],
['log_scale', 'equal_date_size'],
diff --git a/superset/assets/src/explore/controlPanels/Pie.js b/superset/assets/src/explore/controlPanels/Pie.js
index ee9481b93..e3b120394 100644
--- a/superset/assets/src/explore/controlPanels/Pie.js
+++ b/superset/assets/src/explore/controlPanels/Pie.js
@@ -37,7 +37,7 @@ export default {
['pie_label_type', 'number_format'],
['donut', 'show_legend'],
['show_labels', 'labels_outside'],
- ['color_scheme'],
+ ['color_scheme', 'label_colors'],
],
},
],
diff --git a/superset/assets/src/explore/controlPanels/Rose.js b/superset/assets/src/explore/controlPanels/Rose.js
index 5939d0cbe..135b0d5ad 100644
--- a/superset/assets/src/explore/controlPanels/Rose.js
+++ b/superset/assets/src/explore/controlPanels/Rose.js
@@ -27,7 +27,7 @@ export default {
label: t('Chart Options'),
expanded: true,
controlSetRows: [
- ['color_scheme'],
+ ['color_scheme', 'label_colors'],
['number_format', 'date_time_format'],
['rich_tooltip', 'rose_area_proportion'],
],
diff --git a/superset/assets/src/explore/controlPanels/Sankey.js b/superset/assets/src/explore/controlPanels/Sankey.js
index dfb337ab7..c7c2f21b1 100644
--- a/superset/assets/src/explore/controlPanels/Sankey.js
+++ b/superset/assets/src/explore/controlPanels/Sankey.js
@@ -34,7 +34,7 @@ export default {
label: t('Chart Options'),
expanded: true,
controlSetRows: [
- ['color_scheme'],
+ ['color_scheme', 'label_colors'],
],
},
],
diff --git a/superset/assets/src/explore/controlPanels/Sunburst.js b/superset/assets/src/explore/controlPanels/Sunburst.js
index 1272c83bc..6d84b2d47 100644
--- a/superset/assets/src/explore/controlPanels/Sunburst.js
+++ b/superset/assets/src/explore/controlPanels/Sunburst.js
@@ -35,7 +35,7 @@ export default {
label: t('Chart Options'),
expanded: true,
controlSetRows: [
- ['color_scheme'],
+ ['color_scheme', 'label_colors'],
],
},
],
diff --git a/superset/assets/src/explore/controlPanels/Treemap.js b/superset/assets/src/explore/controlPanels/Treemap.js
index 9ed05d958..8342ee55b 100644
--- a/superset/assets/src/explore/controlPanels/Treemap.js
+++ b/superset/assets/src/explore/controlPanels/Treemap.js
@@ -34,7 +34,7 @@ export default {
label: t('Chart Options'),
expanded: true,
controlSetRows: [
- ['color_scheme'],
+ ['color_scheme', 'label_colors'],
['treemap_ratio'],
['number_format'],
],
diff --git a/superset/assets/src/explore/controlPanels/WordCloud.js b/superset/assets/src/explore/controlPanels/WordCloud.js
index 35c396baa..79c8fc1ae 100644
--- a/superset/assets/src/explore/controlPanels/WordCloud.js
+++ b/superset/assets/src/explore/controlPanels/WordCloud.js
@@ -37,7 +37,7 @@ export default {
controlSetRows: [
['size_from', 'size_to'],
['rotation'],
- ['color_scheme'],
+ ['color_scheme', 'label_colors'],
],
},
],
diff --git a/superset/assets/src/explore/controlPanels/sections.jsx b/superset/assets/src/explore/controlPanels/sections.jsx
index e3b32ca28..e4ad95c8f 100644
--- a/superset/assets/src/explore/controlPanels/sections.jsx
+++ b/superset/assets/src/explore/controlPanels/sections.jsx
@@ -42,7 +42,7 @@ export const datasourceAndVizType = {
export const colorScheme = {
label: t('Color Scheme'),
controlSetRows: [
- ['color_scheme'],
+ ['color_scheme', 'label_colors'],
],
};
diff --git a/superset/assets/src/explore/controls.jsx b/superset/assets/src/explore/controls.jsx
index 913d7fdc2..95e2b64e9 100644
--- a/superset/assets/src/explore/controls.jsx
+++ b/superset/assets/src/explore/controls.jsx
@@ -79,6 +79,7 @@ const D3_FORMAT_DOCS = 'D3 format syntax: https://github.com/d3/d3-format';
// input choices & options
const D3_FORMAT_OPTIONS = [
+ ['SMART_NUMBER', 'Adaptative formating'],
['.1s', '.1s (12345.432 => 10k)'],
['.3s', '.3s (12345.432 => 12.3k)'],
[',.1%', ',.1% (12345.432 => 1,234,543.2%)'],
@@ -989,7 +990,7 @@ export const controls = {
freeForm: true,
label: t('Number format'),
renderTrigger: true,
- default: '.3s',
+ default: 'SMART_NUMBER',
choices: D3_FORMAT_OPTIONS,
description: D3_FORMAT_DOCS,
},
@@ -1232,7 +1233,7 @@ export const controls = {
freeForm: true,
label: t('X Axis Format'),
renderTrigger: true,
- default: '.3s',
+ default: 'SMART_NUMBER',
choices: D3_FORMAT_OPTIONS,
description: D3_FORMAT_DOCS,
},
@@ -1252,7 +1253,7 @@ export const controls = {
freeForm: true,
label: t('Y Axis Format'),
renderTrigger: true,
- default: '.3s',
+ default: 'SMART_NUMBER',
choices: D3_FORMAT_OPTIONS,
description: D3_FORMAT_DOCS,
mapStateToProps: (state) => {
@@ -1273,7 +1274,7 @@ export const controls = {
type: 'SelectControl',
freeForm: true,
label: t('Right Axis Format'),
- default: '.3s',
+ default: 'SMART_NUMBER',
choices: D3_FORMAT_OPTIONS,
description: D3_FORMAT_DOCS,
},
@@ -1401,6 +1402,68 @@ export const controls = {
description: t('Font size for the biggest value in the list'),
},
+ header_font_size: {
+ type: 'SelectControl',
+ label: t('Header Font Size'),
+ renderTrigger: true,
+ clearable: false,
+ default: 0.3,
+ // Values represent the percentage of space a header should take
+ options: [
+ {
+ label: t('Tiny'),
+ value: 0.125,
+ },
+ {
+ label: t('Small'),
+ value: 0.2,
+ },
+ {
+ label: t('Normal'),
+ value: 0.3,
+ },
+ {
+ label: t('Large'),
+ value: 0.4,
+ },
+ {
+ label: t('Huge'),
+ value: 0.5,
+ },
+ ],
+ },
+
+ subheader_font_size: {
+ type: 'SelectControl',
+ label: t('Subheader Font Size'),
+ renderTrigger: true,
+ clearable: false,
+ default: 0.125,
+ // Values represent the percentage of space a subheader should take
+ options: [
+ {
+ label: t('Tiny'),
+ value: 0.125,
+ },
+ {
+ label: t('Small'),
+ value: 0.2,
+ },
+ {
+ label: t('Normal'),
+ value: 0.3,
+ },
+ {
+ label: t('Large'),
+ value: 0.4,
+ },
+ {
+ label: t('Huge'),
+ value: 0.5,
+ },
+ ],
+ },
+
instant_filtering: {
type: 'CheckboxControl',
label: t('Instant Filtering'),
@@ -2028,6 +2091,16 @@ export const controls = {
schemes: () => categoricalSchemeRegistry.getMap(),
},
+ label_colors: {
+ type: 'ColorMapControl',
+ label: t('Color Map'),
+ default: {},
+ mapStateToProps: state => ({
+ colorNamespace: state.form_data.color_namespace,
+ colorScheme: state.form_data.color_scheme,
+ }),
+ },
+
significance_level: {
type: 'TextControl',
label: t('Significance Level'),
diff --git a/superset/assets/src/explore/exploreUtils.js b/superset/assets/src/explore/exploreUtils.js
index 48bb60a4f..eabedbabb 100644
--- a/superset/assets/src/explore/exploreUtils.js
+++ b/superset/assets/src/explore/exploreUtils.js
@@ -95,6 +95,7 @@ export function getExploreUrlAndPayload({
curUrl = null,
requestParams = {},
allowDomainSharding = false,
+ method = 'POST',
}) {
if (!formData.datasource) {
return null;
@@ -118,8 +119,19 @@ export function getExploreUrlAndPayload({
// Building the querystring (search) part of the URI
const search = uri.search(true);
- if (formData.slice_id) {
- search.form_data = safeStringify({ slice_id: formData.slice_id });
+ const { slice_id, extra_filters, adhoc_filters, viz_type } = formData;
+ if (slice_id) {
+ const form_data = { slice_id };
+ if (method === 'GET') {
+ form_data.viz_type = viz_type;
+ if (extra_filters && extra_filters.length) {
+ form_data.extra_filters = extra_filters;
+ }
+ if (adhoc_filters && adhoc_filters.length) {
+ form_data.adhoc_filters = adhoc_filters;
+ }
+ }
+ search.form_data = safeStringify(form_data);
}
if (force) {
search.force = 'true';
diff --git a/superset/assets/src/explore/reducers/exploreReducer.js b/superset/assets/src/explore/reducers/exploreReducer.js
index 382388881..6f6a1a9e6 100644
--- a/superset/assets/src/explore/reducers/exploreReducer.js
+++ b/superset/assets/src/explore/reducers/exploreReducer.js
@@ -17,7 +17,8 @@
* under the License.
*/
/* eslint camelcase: 0 */
-import { getControlsState, getFormDataFromControls } from '../store';
+import { validateControl, getControlsState, getFormDataFromControls } from '../store';
+import controls from '../controls';
import * as actions from '../actions/exploreActions';
export default function exploreReducer(state = {}, action) {
@@ -75,24 +76,28 @@ export default function exploreReducer(state = {}, action) {
};
},
[actions.SET_FIELD_VALUE]() {
- const controls = Object.assign({}, state.controls);
- const control = Object.assign({}, controls[action.controlName]);
- control.value = action.value;
- control.validationErrors = action.validationErrors;
- controls[action.controlName] = control;
- const changes = {
- controls,
+ // These errors are reported from the Control components
+ let errors = action.validationErrors || [];
+ let control = {
+ ...controls[action.controlName],
+ value: action.value,
};
- if (control.renderTrigger) {
- changes.triggerRender = true;
- } else {
- changes.triggerRender = false;
- }
- const newState = {
+ control = validateControl(control);
+
+ // These errors are based on control config `validators`
+ errors = errors.concat(control.validationErrors || []);
+ const hasErrors = errors && errors.length > 0;
+ return {
...state,
- ...changes,
+ triggerRender: control.renderTrigger && !hasErrors,
+ controls: {
+ ...state.controls,
+ [action.controlName]: {
+ ...control,
+ validationErrors: errors,
+ },
+ },
};
- return newState;
},
[actions.SET_EXPLORE_CONTROLS]() {
return {
diff --git a/superset/assets/src/explore/reducers/getInitialState.js b/superset/assets/src/explore/reducers/getInitialState.js
index 48c85c757..98b979914 100644
--- a/superset/assets/src/explore/reducers/getInitialState.js
+++ b/superset/assets/src/explore/reducers/getInitialState.js
@@ -52,14 +52,14 @@ export default function getInitialState(bootstrapData) {
[chartKey]: {
id: chartKey,
chartAlert: null,
- chartStatus: 'loading',
+ chartStatus: null,
chartUpdateEndTime: null,
chartUpdateStartTime: 0,
latestQueryFormData: getFormDataFromControls(controls),
sliceFormData,
queryController: null,
queryResponse: null,
- triggerQuery: true,
+ triggerQuery: false,
lastRendered: 0,
},
},
diff --git a/superset/assets/src/explore/store.js b/superset/assets/src/explore/store.js
index be2be7b32..df456c29e 100644
--- a/superset/assets/src/explore/store.js
+++ b/superset/assets/src/explore/store.js
@@ -29,6 +29,24 @@ export function getFormDataFromControls(controlsState) {
return formData;
}
+export function validateControl(control) {
+ const validators = control.validators;
+ const validationErrors = [];
+ if (validators && validators.length > 0) {
+ validators.forEach((f) => {
+ const v = f(control.value);
+ if (v) {
+ validationErrors.push(v);
+ }
+ });
+ }
+ if (validationErrors.length > 0) {
+ return { ...control, validationErrors };
+ }
+ return control;
+}
+
+
export function getControlNames(vizType, datasourceType) {
const controlNames = [];
sectionsToRender(vizType, datasourceType).forEach(
@@ -109,7 +127,7 @@ export function getControlsState(state, form_data) {
) {
control.value = formData[k];
}
- controlsState[k] = control;
+ controlsState[k] = validateControl(control);
});
if (viz.onInit) {
return viz.onInit(controlsState);
diff --git a/superset/assets/src/visualizations/deckgl/AnimatableDeckGLContainer.jsx b/superset/assets/src/visualizations/deckgl/AnimatableDeckGLContainer.jsx
index f206522cf..fe2c7165d 100644
--- a/superset/assets/src/visualizations/deckgl/AnimatableDeckGLContainer.jsx
+++ b/superset/assets/src/visualizations/deckgl/AnimatableDeckGLContainer.jsx
@@ -34,6 +34,9 @@ const propTypes = {
disabled: PropTypes.bool,
viewport: PropTypes.object.isRequired,
children: PropTypes.node,
+ mapStyle: PropTypes.string,
+ mapboxApiAccessToken: PropTypes.string.isRequired,
+ setControlValue: PropTypes.func,
onViewportChange: PropTypes.func,
onValuesChange: PropTypes.func,
};
@@ -41,6 +44,8 @@ const propTypes = {
const defaultProps = {
aggregation: false,
disabled: false,
+ mapStyle: 'light',
+ setControlValue: () => {},
onViewportChange: () => {},
onValuesChange: () => {},
};
@@ -48,9 +53,6 @@ const defaultProps = {
export default class AnimatableDeckGLContainer extends React.Component {
constructor(props) {
super(props);
- const { getLayers, start, end, getStep, values, disabled, viewport, ...other } = props;
- this.other = other;
-
this.onViewportChange = this.onViewportChange.bind(this);
}
onViewportChange(viewport) {
@@ -71,6 +73,9 @@ export default class AnimatableDeckGLContainer extends React.Component {
values,
onValuesChange,
viewport,
+ setControlValue,
+ mapStyle,
+ mapboxApiAccessToken,
} = this.props;
const layers = getLayers(values);
@@ -83,9 +88,11 @@ export default class AnimatableDeckGLContainer extends React.Component {
return (
{!disabled &&
diff --git a/superset/assets/src/visualizations/deckgl/CategoricalDeckGLContainer.jsx b/superset/assets/src/visualizations/deckgl/CategoricalDeckGLContainer.jsx
index 3765f7d49..e1933a4b1 100644
--- a/superset/assets/src/visualizations/deckgl/CategoricalDeckGLContainer.jsx
+++ b/superset/assets/src/visualizations/deckgl/CategoricalDeckGLContainer.jsx
@@ -31,9 +31,9 @@ import { fitViewport } from './layers/common';
const { getScale } = CategoricalColorNamespace;
function getCategories(fd, data) {
- const c = fd.colorPicker || { r: 0, g: 0, b: 0, a: 1 };
+ const c = fd.color_picker || { r: 0, g: 0, b: 0, a: 1 };
const fixedColor = [c.r, c.g, c.b, 255 * c.a];
- const colorFn = getScale(fd.colorScheme);
+ const colorFn = getScale(fd.color_scheme);
const categories = {};
data.forEach((d) => {
if (d.cat_color != null && !categories.hasOwnProperty(d.cat_color)) {
@@ -108,7 +108,7 @@ export default class CategoricalDeckGLContainer extends React.PureComponent {
// the granularity has to be read from the payload form_data, not the
// props formData which comes from the instantaneous controls state
const granularity = (
- props.payload.form_data.timeGrainSqla ||
+ props.payload.form_data.time_grain_sqla ||
props.payload.form_data.granularity ||
'P1D'
);
@@ -154,8 +154,8 @@ export default class CategoricalDeckGLContainer extends React.PureComponent {
features = this.addColor(features, fd);
// Apply user defined data mutator if defined
- if (fd.jsDataMutator) {
- const jsFnMutator = sandboxedEval(fd.jsDataMutator);
+ if (fd.js_data_mutator) {
+ const jsFnMutator = sandboxedEval(fd.js_data_mutator);
features = jsFnMutator(features);
}
@@ -180,8 +180,8 @@ export default class CategoricalDeckGLContainer extends React.PureComponent {
return [getLayer(fd, filteredPayload, onAddFilter, setTooltip)];
}
addColor(data, fd) {
- const c = fd.colorPicker || { r: 0, g: 0, b: 0, a: 1 };
- const colorFn = getScale(fd.colorScheme);
+ const c = fd.color_picker || { r: 0, g: 0, b: 0, a: 1 };
+ const colorFn = getScale(fd.color_scheme);
return data.map((d) => {
let color;
if (fd.dimension) {
@@ -229,14 +229,14 @@ export default class CategoricalDeckGLContainer extends React.PureComponent {
viewport={this.state.viewport}
onViewportChange={this.onViewportChange}
mapboxApiAccessToken={this.props.mapboxApiKey}
- mapStyle={this.props.formData.mapboxStyle}
+ mapStyle={this.props.formData.mapbox_style}
setControlValue={this.props.setControlValue}
>
diff --git a/superset/assets/src/visualizations/deckgl/DeckGLContainer.jsx b/superset/assets/src/visualizations/deckgl/DeckGLContainer.jsx
index c10f16ac9..ff414bfc0 100644
--- a/superset/assets/src/visualizations/deckgl/DeckGLContainer.jsx
+++ b/superset/assets/src/visualizations/deckgl/DeckGLContainer.jsx
@@ -22,6 +22,7 @@ import MapGL from 'react-map-gl';
import DeckGL from 'deck.gl';
import 'mapbox-gl/dist/mapbox-gl.css';
import { isEqual } from 'lodash';
+import '../stylesheets/deckgl.css';
const TICK = 2000; // milliseconds
diff --git a/superset/assets/src/visualizations/deckgl/Multi/Multi.jsx b/superset/assets/src/visualizations/deckgl/Multi/Multi.jsx
index 792b94ad0..e9da1f772 100644
--- a/superset/assets/src/visualizations/deckgl/Multi/Multi.jsx
+++ b/superset/assets/src/visualizations/deckgl/Multi/Multi.jsx
@@ -56,7 +56,7 @@ class DeckMulti extends React.PureComponent {
const filters = [
...(subslice.form_data.filters || []),
...(formData.filters || []),
- ...(formData.extraFilters || []),
+ ...(formData.extra_filters || []),
];
const subsliceCopy = {
...subslice,
@@ -70,7 +70,7 @@ class DeckMulti extends React.PureComponent {
endpoint: getExploreLongUrl(subsliceCopy.form_data, 'json'),
})
.then(({ json }) => {
- const layer = layerGenerators[subsliceCopy.form_data.vizType](
+ const layer = layerGenerators[subsliceCopy.form_data.viz_type](
subsliceCopy.form_data,
json,
);
@@ -96,7 +96,7 @@ class DeckMulti extends React.PureComponent {
mapboxApiAccessToken={payload.data.mapboxApiKey}
viewport={viewport}
layers={layers}
- mapStyle={formData.mapboxStyle}
+ mapStyle={formData.mapbox_style}
setControlValue={setControlValue}
/>
);
diff --git a/superset/assets/src/visualizations/deckgl/TooltipRow.jsx b/superset/assets/src/visualizations/deckgl/TooltipRow.jsx
new file mode 100644
index 000000000..cc85bfd98
--- /dev/null
+++ b/superset/assets/src/visualizations/deckgl/TooltipRow.jsx
@@ -0,0 +1,36 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import React from 'react';
+import PropTypes from 'prop-types';
+
+const propTypes = {
+ label: PropTypes.string.isRequired,
+ value: PropTypes.string.isRequired,
+};
+
+
+export default class TooltipRow extends React.PureComponent {
+ render() {
+ return (
+
{this.props.label}{this.props.value}
+ );
+ }
+}
+
+TooltipRow.propTypes = propTypes;
diff --git a/superset/assets/src/visualizations/deckgl/factory.jsx b/superset/assets/src/visualizations/deckgl/factory.jsx
index 348bdeeb7..1ad8bd373 100644
--- a/superset/assets/src/visualizations/deckgl/factory.jsx
+++ b/superset/assets/src/visualizations/deckgl/factory.jsx
@@ -90,7 +90,7 @@ export function createDeckGLComponent(getLayer, getPoints) {
mapboxApiAccessToken={payload.data.mapboxApiKey}
viewport={viewport}
layers={[layer]}
- mapStyle={formData.mapboxStyle}
+ mapStyle={formData.mapbox_style}
setControlValue={setControlValue}
onViewportChange={this.onViewportChange}
/>);
diff --git a/superset/assets/src/visualizations/deckgl/layers/Arc/Arc.jsx b/superset/assets/src/visualizations/deckgl/layers/Arc/Arc.jsx
index 75894b089..2c0a99b09 100644
--- a/superset/assets/src/visualizations/deckgl/layers/Arc/Arc.jsx
+++ b/superset/assets/src/visualizations/deckgl/layers/Arc/Arc.jsx
@@ -17,8 +17,11 @@
* under the License.
*/
import { ArcLayer } from 'deck.gl';
+import React from 'react';
+import { t } from '@superset-ui/translation';
import { commonLayerProps } from '../common';
import { createCategoricalDeckGLComponent } from '../../factory';
+import TooltipRow from '../../TooltipRow';
function getPoints(data) {
const points = [];
@@ -29,17 +32,29 @@ function getPoints(data) {
return points;
}
+function setTooltipContent(formData) {
+ return o => (
+
+
+
+ {
+ formData.dimension &&
+ }
+
+ );
+}
+
export function getLayer(fd, payload, onAddFilter, setTooltip) {
const data = payload.data.features;
- const sc = fd.colorPicker;
- const tc = fd.targetColorPicker;
+ const sc = fd.color_picker;
+ const tc = fd.target_color_picker;
return new ArcLayer({
- id: `path-layer-${fd.sliceId}`,
+ id: `path-layer-${fd.slice_id}`,
data,
getSourceColor: d => d.sourceColor || d.color || [sc.r, sc.g, sc.b, 255 * sc.a],
getTargetColor: d => d.targetColor || d.color || [tc.r, tc.g, tc.b, 255 * tc.a],
- strokeWidth: (fd.strokeWidth) ? fd.strokeWidth : 3,
- ...commonLayerProps(fd, setTooltip),
+ strokeWidth: (fd.stroke_width) ? fd.stroke_width : 3,
+ ...commonLayerProps(fd, setTooltip, setTooltipContent(fd)),
});
}
diff --git a/superset/assets/src/visualizations/deckgl/layers/Geojson/Geojson.jsx b/superset/assets/src/visualizations/deckgl/layers/Geojson/Geojson.jsx
index d698a0b8a..7488a3ddf 100644
--- a/superset/assets/src/visualizations/deckgl/layers/Geojson/Geojson.jsx
+++ b/superset/assets/src/visualizations/deckgl/layers/Geojson/Geojson.jsx
@@ -25,6 +25,7 @@ import DeckGLContainer from '../../DeckGLContainer';
import { hexToRGB } from '../../../../modules/colors';
import sandboxedEval from '../../../../modules/sandbox';
import { commonLayerProps } from '../common';
+import TooltipRow from '../../TooltipRow';
const propertyMap = {
fillColor: 'fillColor',
@@ -75,10 +76,23 @@ const recurseGeoJson = (node, propOverrides, extraProps) => {
}
};
+function setTooltipContent(o) {
+ return (
+ o.object.extraProps &&
+
+ {
+ Object.keys(o.object.extraProps).map((prop, index) =>
+ ,
+ )
+ }
+
+ );
+}
+
export function getLayer(formData, payload, onAddFilter, setTooltip) {
const fd = formData;
- const fc = fd.fillColorPicker;
- const sc = fd.strokeColorPicker;
+ const fc = fd.fill_color_picker;
+ const sc = fd.stroke_color_picker;
const fillColor = [fc.r, fc.g, fc.b, 255 * fc.a];
const strokeColor = [sc.r, sc.g, sc.b, 255 * sc.a];
const propOverrides = {};
@@ -93,20 +107,20 @@ export function getLayer(formData, payload, onAddFilter, setTooltip) {
recurseGeoJson(payload.data, propOverrides);
let jsFnMutator;
- if (fd.jsDataMutator) {
+ if (fd.js_data_mutator) {
// Applying user defined data mutator if defined
- jsFnMutator = sandboxedEval(fd.jsDataMutator);
+ jsFnMutator = sandboxedEval(fd.js_data_mutator);
features = jsFnMutator(features);
}
return new GeoJsonLayer({
- id: `geojson-layer-${fd.sliceId}`,
+ id: `geojson-layer-${fd.slice_id}`,
filled: fd.filled,
data: features,
stroked: fd.stroked,
extruded: fd.extruded,
- pointRadiusScale: fd.pointRadiusScale,
- ...commonLayerProps(fd, setTooltip),
+ pointRadiusScale: fd.point_radius_scale,
+ ...commonLayerProps(fd, setTooltip, setTooltipContent),
});
}
@@ -145,7 +159,7 @@ function deckGeoJson(props) {
mapboxApiAccessToken={payload.data.mapboxApiKey}
viewport={viewport}
layers={[layer]}
- mapStyle={formData.mapboxStyle}
+ mapStyle={formData.mapbox_style}
setControlValue={setControlValue}
/>
);
diff --git a/superset/assets/src/visualizations/deckgl/layers/Grid/Grid.jsx b/superset/assets/src/visualizations/deckgl/layers/Grid/Grid.jsx
index 2baba1e7a..a0cc8613f 100644
--- a/superset/assets/src/visualizations/deckgl/layers/Grid/Grid.jsx
+++ b/superset/assets/src/visualizations/deckgl/layers/Grid/Grid.jsx
@@ -17,38 +17,50 @@
* under the License.
*/
import { GridLayer } from 'deck.gl';
+import React from 'react';
+import { t } from '@superset-ui/translation';
import { commonLayerProps, getAggFunc } from '../common';
import sandboxedEval from '../../../../modules/sandbox';
import { createDeckGLComponent } from '../../factory';
+import TooltipRow from '../../TooltipRow';
+
+function setTooltipContent(o) {
+ return (
+
+
+
+
+ );
+}
export function getLayer(formData, payload, onAddFilter, setTooltip) {
const fd = formData;
- const c = fd.colorPicker;
+ const c = fd.color_picker;
let data = payload.data.features.map(d => ({
...d,
color: [c.r, c.g, c.b, 255 * c.a],
}));
- if (fd.jsDataMutator) {
+ if (fd.js_data_mutator) {
// Applying user defined data mutator if defined
- const jsFnMutator = sandboxedEval(fd.jsDataMutator);
+ const jsFnMutator = sandboxedEval(fd.js_data_mutator);
data = jsFnMutator(data);
}
- const aggFunc = getAggFunc(fd.jsAggFunction, p => p.weight);
+ const aggFunc = getAggFunc(fd.js_agg_function, p => p.weight);
return new GridLayer({
- id: `grid-layer-${fd.sliceId}`,
+ id: `grid-layer-${fd.slice_id}`,
data,
pickable: true,
- cellSize: fd.gridSize,
+ cellSize: fd.grid_size,
minColor: [0, 0, 0, 0],
extruded: fd.extruded,
maxColor: [c.r, c.g, c.b, 255 * c.a],
outline: false,
getElevationValue: aggFunc,
getColorValue: aggFunc,
- ...commonLayerProps(fd, setTooltip),
+ ...commonLayerProps(fd, setTooltip, setTooltipContent),
});
}
diff --git a/superset/assets/src/visualizations/deckgl/layers/Hex/Hex.jsx b/superset/assets/src/visualizations/deckgl/layers/Hex/Hex.jsx
index b17116f21..9901b2262 100644
--- a/superset/assets/src/visualizations/deckgl/layers/Hex/Hex.jsx
+++ b/superset/assets/src/visualizations/deckgl/layers/Hex/Hex.jsx
@@ -17,37 +17,49 @@
* under the License.
*/
import { HexagonLayer } from 'deck.gl';
+import React from 'react';
+import { t } from '@superset-ui/translation';
import { commonLayerProps, getAggFunc } from '../common';
import sandboxedEval from '../../../../modules/sandbox';
import { createDeckGLComponent } from '../../factory';
+import TooltipRow from '../../TooltipRow';
+
+function setTooltipContent(o) {
+ return (
+
+
+
+
+ );
+}
export function getLayer(formData, payload, onAddFilter, setTooltip) {
const fd = formData;
- const c = fd.colorPicker;
+ const c = fd.color_picker;
let data = payload.data.features.map(d => ({
...d,
color: [c.r, c.g, c.b, 255 * c.a],
}));
- if (fd.jsDataMutator) {
+ if (fd.js_data_mutator) {
// Applying user defined data mutator if defined
- const jsFnMutator = sandboxedEval(fd.jsDataMutator);
+ const jsFnMutator = sandboxedEval(fd.js_data_mutator);
data = jsFnMutator(data);
}
- const aggFunc = getAggFunc(fd.jsAggFunction, p => p.weight);
+ const aggFunc = getAggFunc(fd.js_agg_function, p => p.weight);
return new HexagonLayer({
- id: `hex-layer-${fd.sliceId}`,
+ id: `hex-layer-${fd.slice_id}`,
data,
pickable: true,
- radius: fd.gridSize,
+ radius: fd.grid_size,
minColor: [0, 0, 0, 0],
extruded: fd.extruded,
maxColor: [c.r, c.g, c.b, 255 * c.a],
outline: false,
getElevationValue: aggFunc,
getColorValue: aggFunc,
- ...commonLayerProps(fd, setTooltip),
+ ...commonLayerProps(fd, setTooltip, setTooltipContent),
});
}
diff --git a/superset/assets/src/visualizations/deckgl/layers/Path/Path.jsx b/superset/assets/src/visualizations/deckgl/layers/Path/Path.jsx
index bd1b44979..7bf098241 100644
--- a/superset/assets/src/visualizations/deckgl/layers/Path/Path.jsx
+++ b/superset/assets/src/visualizations/deckgl/layers/Path/Path.jsx
@@ -17,32 +17,47 @@
* under the License.
*/
import { PathLayer } from 'deck.gl';
+import React from 'react';
import { commonLayerProps } from '../common';
import sandboxedEval from '../../../../modules/sandbox';
import { createDeckGLComponent } from '../../factory';
+import TooltipRow from '../../TooltipRow';
+
+function setTooltipContent(o) {
+ return (
+ o.object.extraProps &&
+
+ {
+ Object.keys(o.object.extraProps).map((prop, index) =>
+ ,
+ )
+ }
+
+ );
+}
export function getLayer(formData, payload, onAddFilter, setTooltip) {
const fd = formData;
- const c = fd.colorPicker;
+ const c = fd.color_picker;
const fixedColor = [c.r, c.g, c.b, 255 * c.a];
let data = payload.data.features.map(feature => ({
...feature,
path: feature.path,
- width: fd.lineWidth,
+ width: fd.line_width,
color: fixedColor,
}));
- if (fd.jsDataMutator) {
- const jsFnMutator = sandboxedEval(fd.jsDataMutator);
+ if (fd.js_data_mutator) {
+ const jsFnMutator = sandboxedEval(fd.js_data_mutator);
data = jsFnMutator(data);
}
return new PathLayer({
- id: `path-layer-${fd.sliceId}`,
+ id: `path-layer-${fd.slice_id}`,
data,
rounded: true,
widthScale: 1,
- ...commonLayerProps(fd, setTooltip),
+ ...commonLayerProps(fd, setTooltip, setTooltipContent),
});
}
diff --git a/superset/assets/src/visualizations/deckgl/layers/Polygon/Polygon.jsx b/superset/assets/src/visualizations/deckgl/layers/Polygon/Polygon.jsx
index b69bbf782..7e30668e2 100644
--- a/superset/assets/src/visualizations/deckgl/layers/Polygon/Polygon.jsx
+++ b/superset/assets/src/visualizations/deckgl/layers/Polygon/Polygon.jsx
@@ -25,6 +25,7 @@ import { PolygonLayer } from 'deck.gl';
import AnimatableDeckGLContainer from '../../AnimatableDeckGLContainer';
import Legend from '../../../Legend';
+import TooltipRow from '../../TooltipRow';
import { getBuckets, getBreakPointColorScaler } from '../../utils';
import { commonLayerProps, fitViewport } from '../common';
@@ -48,10 +49,22 @@ function getElevation(d, colorScaler) {
: d.elevation;
}
+function setTooltipContent(formData) {
+ return (o) => {
+ const metricLabel = formData.metric.label || formData.metric;
+ return (
+
+
+ {formData.metric && }
+
+ );
+ };
+}
+
export function getLayer(formData, payload, setTooltip, selected, onSelect, filters) {
const fd = formData;
- const fc = fd.fillColorPicker;
- const sc = fd.strokeColorPicker;
+ const fc = fd.fill_color_picker;
+ const sc = fd.stroke_color_picker;
let data = [...payload.data.features];
if (filters != null) {
@@ -60,9 +73,9 @@ export function getLayer(formData, payload, setTooltip, selected, onSelect, filt
});
}
- if (fd.jsDataMutator) {
+ if (fd.js_data_mutator) {
// Applying user defined data mutator if defined
- const jsFnMutator = sandboxedEval(fd.jsDataMutator);
+ const jsFnMutator = sandboxedEval(fd.js_data_mutator);
data = jsFnMutator(data);
}
@@ -76,13 +89,16 @@ export function getLayer(formData, payload, setTooltip, selected, onSelect, filt
// when polygons are selected, reduce the opacity of non-selected polygons
const colorScaler = (d) => {
const baseColor = baseColorScaler(d);
- if (selected.length > 0 && selected.indexOf(d[fd.lineColumn]) === -1) {
+ if (selected.length > 0 && selected.indexOf(d[fd.line_column]) === -1) {
baseColor[3] /= 2;
}
return baseColor;
};
+ const tooltipContentGenerator = (fd.line_column && fd.metric && ['geohash', 'zipcode'].indexOf(fd.line_type) >= 0)
+ ? setTooltipContent(fd)
+ : undefined;
return new PolygonLayer({
- id: `path-layer-${fd.sliceId}`,
+ id: `path-layer-${fd.slice_id}`,
data,
pickable: true,
filled: fd.filled,
@@ -90,12 +106,12 @@ export function getLayer(formData, payload, setTooltip, selected, onSelect, filt
getPolygon: d => d.polygon,
getFillColor: colorScaler,
getLineColor: [sc.r, sc.g, sc.b, 255 * sc.a],
- getLineWidth: fd.lineWidth,
+ getLineWidth: fd.line_width,
extruded: fd.extruded,
getElevation: d => getElevation(d, colorScaler),
elevationScale: fd.multiplier,
fp64: true,
- ...commonLayerProps(fd, setTooltip, onSelect),
+ ...commonLayerProps(fd, setTooltip, tooltipContentGenerator, onSelect),
});
}
@@ -138,7 +154,7 @@ class DeckGLPolygon extends React.Component {
// the granularity has to be read from the payload form_data, not the
// props formData which comes from the instantaneous controls state
const granularity = (
- props.payload.form_data.timeGrainSqla ||
+ props.payload.form_data.time_grain_sqla ||
props.payload.form_data.granularity ||
'P1D'
);
@@ -177,7 +193,7 @@ class DeckGLPolygon extends React.Component {
const selected = [...this.state.selected];
if (doubleClick) {
selected.splice(0, selected.length, polygon);
- } else if (formData.togglePolygons) {
+ } else if (formData.toggle_polygons) {
const i = selected.indexOf(polygon);
if (i === -1) {
selected.push(polygon);
@@ -189,8 +205,8 @@ class DeckGLPolygon extends React.Component {
}
this.setState({ selected, lastClick: now });
- if (formData.tableFilter) {
- onAddFilter(formData.lineColumn, selected, false, true);
+ if (formData.table_filter) {
+ onAddFilter(formData.line_column, selected, false, true);
}
}
onValuesChange(values) {
@@ -249,14 +265,14 @@ class DeckGLPolygon extends React.Component {
viewport={viewport}
onViewportChange={this.onViewportChange}
mapboxApiAccessToken={payload.data.mapboxApiKey}
- mapStyle={formData.mapboxStyle}
+ mapStyle={formData.mapbox_style}
setControlValue={setControlValue}
aggregation
>
{formData.metric !== null &&
}
diff --git a/superset/assets/src/visualizations/deckgl/layers/Scatter/Scatter.jsx b/superset/assets/src/visualizations/deckgl/layers/Scatter/Scatter.jsx
index ebc26c899..8ca13aac4 100644
--- a/superset/assets/src/visualizations/deckgl/layers/Scatter/Scatter.jsx
+++ b/superset/assets/src/visualizations/deckgl/layers/Scatter/Scatter.jsx
@@ -17,36 +17,53 @@
* under the License.
*/
import { ScatterplotLayer } from 'deck.gl';
+import React from 'react';
+import { t } from '@superset-ui/translation';
import { commonLayerProps } from '../common';
import { createCategoricalDeckGLComponent } from '../../factory';
+import TooltipRow from '../../TooltipRow';
import { unitToRadius } from '../../../../modules/geo';
function getPoints(data) {
return data.map(d => d.position);
}
+function setTooltipContent(formData) {
+ return o => (
+