diff --git a/superset/assets/javascripts/explorev2/actions/exploreActions.js b/superset/assets/javascripts/explorev2/actions/exploreActions.js
index 08849e9b2fd20..a026d9094bd4b 100644
--- a/superset/assets/javascripts/explorev2/actions/exploreActions.js
+++ b/superset/assets/javascripts/explorev2/actions/exploreActions.js
@@ -98,41 +98,24 @@ export function setFieldValue(datasource_type, key, value, label) {
return { type: SET_FIELD_VALUE, datasource_type, key, value, label };
}
-export const UPDATE_CHART = 'UPDATE_CHART';
-export function updateChart(viz) {
- return { type: UPDATE_CHART, viz };
-}
-
export const CHART_UPDATE_STARTED = 'CHART_UPDATE_STARTED';
export function chartUpdateStarted() {
return { type: CHART_UPDATE_STARTED };
}
-export const CHART_UPDATE_FAILED = 'CHART_UPDATE_FAILED ';
+export const CHART_UPDATE_SUCCEEDED = 'CHART_UPDATE_SUCCEEDED';
+export function chartUpdateSucceeded(query) {
+ return { type: CHART_UPDATE_SUCCEEDED, query };
+}
+
+export const CHART_UPDATE_FAILED = 'CHART_UPDATE_FAILED';
export function chartUpdateFailed(error) {
return { type: CHART_UPDATE_FAILED, error };
}
-export function updateExplore(datasource_type, datasource_id, form_data) {
- return function (dispatch) {
- dispatch(chartUpdateStarted());
- const updateUrl =
- `/superset/update_explore/${datasource_type}/${datasource_id}/`;
-
- $.ajax({
- type: 'POST',
- url: updateUrl,
- data: {
- data: JSON.stringify(form_data),
- },
- success: (data) => {
- dispatch(updateChart(JSON.parse(data)));
- },
- error(error) {
- dispatch(chartUpdateFailed(error.responseJSON.error));
- },
- });
- };
+export const UPDATE_EXPLORE_ENDPOINTS = 'UPDATE_EXPLORE_ENDPOINTS';
+export function updateExploreEndpoints(jsonUrl, csvUrl, standaloneUrl) {
+ return { type: UPDATE_EXPLORE_ENDPOINTS, jsonUrl, csvUrl, standaloneUrl };
}
export const REMOVE_CONTROL_PANEL_ALERT = 'REMOVE_CONTROL_PANEL_ALERT';
diff --git a/superset/assets/javascripts/explorev2/components/ChartContainer.jsx b/superset/assets/javascripts/explorev2/components/ChartContainer.jsx
index 7cb2711482dd2..ff59c35b9c01a 100644
--- a/superset/assets/javascripts/explorev2/components/ChartContainer.jsx
+++ b/superset/assets/javascripts/explorev2/components/ChartContainer.jsx
@@ -26,13 +26,13 @@ const propTypes = {
json_endpoint: PropTypes.string.isRequired,
csv_endpoint: PropTypes.string.isRequired,
standalone_endpoint: PropTypes.string.isRequired,
- query: PropTypes.string.isRequired,
+ query: PropTypes.string,
column_formats: PropTypes.object,
data: PropTypes.any,
- chartStatus: PropTypes.bool,
+ chartStatus: PropTypes.string,
isStarred: PropTypes.bool.isRequired,
- chartUpdateStartTime: PropTypes.string.isRequired,
- chartUpdateEndTime: PropTypes.string.isRequired,
+ chartUpdateStartTime: PropTypes.number.isRequired,
+ chartUpdateEndTime: PropTypes.number,
alert: PropTypes.string,
table_name: PropTypes.string,
};
@@ -55,7 +55,15 @@ class ChartContainer extends React.Component {
}
componentWillReceiveProps(nextProps) {
- this.setState({ mockSlice: this.getMockedSliceObject(nextProps) });
+ if (nextProps.chartStatus !== this.props.chartStatus
+ || nextProps.height !== this.props.height) {
+ this.setState({ mockSlice: this.getMockedSliceObject(nextProps) });
+ }
+ }
+
+ shouldComponentUpdate(nextProps) {
+ return (nextProps.chartStatus !== this.props.chartStatus
+ || nextProps.height !== this.props.height);
}
componentDidUpdate() {
@@ -114,8 +122,10 @@ class ChartContainer extends React.Component {
{}
),
- done: () => {
+ done: (payload) => {
// finished rendering callback
+ // Todo: end timer and chartLoading set to success
+ props.actions.chartUpdateSucceeded(payload.query);
},
clearError: () => {
@@ -166,16 +176,19 @@ class ChartContainer extends React.Component {
);
}
- if (this.props.chartStatus === 'loading') {
- return ();
- }
+ const loading = this.props.chartStatus === 'loading';
return (
-
{ this.chartContainerRef = ref; }}
- className={this.props.viz_type}
- style={{ overflowX: 'scroll' }}
- />
+
+ {loading &&
+
+ }
+
{ this.chartContainerRef = ref; }}
+ className={this.props.viz_type}
+ style={{ overflowX: 'auto' }}
+ />
+
);
}
@@ -219,7 +232,7 @@ class ChartContainer extends React.Component {
endTime={this.props.chartUpdateEndTime}
isRunning={this.props.chartStatus === 'loading'}
state={CHART_STATUS_MAP[this.props.chartStatus]}
- style={{ 'font-size': '10px', 'margin-right': '5px' }}
+ style={{ fontSize: '10px', marginRight: '5px' }}
/>
diff --git a/superset/assets/javascripts/explorev2/exploreUtils.js b/superset/assets/javascripts/explorev2/exploreUtils.js
index 52a9ed70444b6..15ac8e3517c37 100644
--- a/superset/assets/javascripts/explorev2/exploreUtils.js
+++ b/superset/assets/javascripts/explorev2/exploreUtils.js
@@ -1,4 +1,5 @@
/* eslint camelcase: 0 */
+const $ = require('jquery');
function formatFilters(filters) {
// outputs an object of url params of filters
// prefix can be 'flt' or 'having'
@@ -22,7 +23,7 @@ export function getParamObject(form_data, datasource_type, saveNewSlice) {
};
Object.keys(form_data).forEach((field) => {
// filter out null fields
- if (form_data[field] !== null && field !== 'datasource'
+ if (form_data[field] !== null && field !== 'datasource' && field !== 'filters'
&& !(saveNewSlice && field === 'slice_name')) {
data[field] = form_data[field];
}
@@ -31,3 +32,21 @@ export function getParamObject(form_data, datasource_type, saveNewSlice) {
Object.assign(data, filterParams);
return data;
}
+
+export function getExploreUrl(form_data, datasource_type, endpoint = 'base') {
+ const data = getParamObject(form_data, datasource_type);
+ const params = `${datasource_type}/` +
+ `${form_data.datasource}/?${$.param(data, true)}`;
+ switch (endpoint) {
+ case 'base':
+ return `/superset/explore/${params}`;
+ case 'json':
+ return `/superset/explore_json/${params}`;
+ case 'csv':
+ return `/superset/explore/${params}&csv=true`;
+ case 'standalone':
+ return `/superset/explore/${params}&standalone=true`;
+ default:
+ return `/superset/explore/${params}`;
+ }
+}
diff --git a/superset/assets/javascripts/explorev2/reducers/exploreReducer.js b/superset/assets/javascripts/explorev2/reducers/exploreReducer.js
index 4d8dc9d3637f7..176c0ecbca761 100644
--- a/superset/assets/javascripts/explorev2/reducers/exploreReducer.js
+++ b/superset/assets/javascripts/explorev2/reducers/exploreReducer.js
@@ -1,7 +1,9 @@
+/* eslint camelcase: 0 */
import { defaultFormData } from '../stores/store';
import * as actions from '../actions/exploreActions';
import { addToArr, removeFromArr, alterInArr } from '../../../utils/reducerUtils';
import { now } from '../../modules/dates';
+import { getExploreUrl } from '../exploreUtils';
export const exploreReducer = function (state, action) {
const actionHandlers = {
@@ -105,29 +107,35 @@ export const exploreReducer = function (state, action) {
{ viz: Object.assign({}, state.viz, { form_data: newFormData }) }
);
},
- [actions.UPDATE_CHART]() {
+ [actions.CHART_UPDATE_SUCCEEDED]() {
const vizUpdates = {
- column_formats: action.viz.column_formats,
- json_endpoint: action.viz.json_endpoint,
- csv_endpoint: action.viz.csv_endpoint,
- standalone_endpoint: action.viz.standalone_endpoint,
- query: action.viz.query,
- data: action.viz.data,
+ query: action.query,
};
- const chartUpdateEndTime = now();
return Object.assign(
{},
state,
{
- viz: Object.assign({}, state.viz, vizUpdates),
chartStatus: 'success',
- chartUpdateEndTime,
+ viz: Object.assign({}, state.viz, vizUpdates),
});
},
[actions.CHART_UPDATE_STARTED]() {
const chartUpdateStartTime = now();
+ const form_data = Object.assign({}, state.viz.form_data);
+ const datasource_type = state.datasource_type;
+ const vizUpdates = {
+ json_endpoint: getExploreUrl(form_data, datasource_type, 'json'),
+ csv_endpoint: getExploreUrl(form_data, datasource_type, 'csv'),
+ standalone_endpoint:
+ getExploreUrl(form_data, datasource_type, 'standalone'),
+ };
return Object.assign({}, state,
- { chartStatus: 'loading', chartUpdateEndTime: null, chartUpdateStartTime });
+ {
+ chartStatus: 'loading',
+ chartUpdateEndTime: null,
+ chartUpdateStartTime,
+ viz: Object.assign({}, state.viz, vizUpdates),
+ });
},
[actions.CHART_UPDATE_FAILED]() {
const chartUpdateEndTime = now();
diff --git a/superset/views.py b/superset/views.py
index 55b570dfec258..92abaec4aa4db 100755
--- a/superset/views.py
+++ b/superset/views.py
@@ -1364,28 +1364,6 @@ def slice(self, slice_id):
viz_obj = self.get_viz(slice_id)
return redirect(viz_obj.get_url(**request.args))
- @log_this
- @has_access_api
- @expose(
- "/update_explore///", methods=['POST'])
- def update_explore(self, datasource_type, datasource_id):
- """Send back new viz on POST request for updating update explore view"""
- form_data = json.loads(request.form.get('data'))
- try:
- viz_obj = self.get_viz(
- datasource_type=datasource_type,
- datasource_id=datasource_id,
- args=form_data)
- except Exception as e:
- logging.exception(e)
- return json_error_response('{}'.format(e))
- try:
- viz_json = viz_obj.get_json()
- except Exception as e:
- logging.exception(e)
- return json_error_response(utils.error_msg_from_exception(e))
- return viz_json
-
@has_access_api
@expose("/explore_json///")
def explore_json(self, datasource_type, datasource_id):
diff --git a/tests/base_tests.py b/tests/base_tests.py
index 2a2e627b45b2e..3ff744fc9bd86 100644
--- a/tests/base_tests.py
+++ b/tests/base_tests.py
@@ -265,7 +265,6 @@ def assert_can_all(view_menu):
self.assertIn(('can_fave_slices', 'Superset'), gamma_perm_set)
self.assertIn(('can_save_dash', 'Superset'), gamma_perm_set)
self.assertIn(('can_slice', 'Superset'), gamma_perm_set)
- self.assertIn(('can_update_explore', 'Superset'), gamma_perm_set)
diff --git a/tests/core_tests.py b/tests/core_tests.py
index 3f73a975dfe60..c7f05f4e7907e 100644
--- a/tests/core_tests.py
+++ b/tests/core_tests.py
@@ -95,25 +95,6 @@ def assert_admin_view_menus_in(role_name, assert_func):
assert_admin_view_menus_in('Alpha', self.assertNotIn)
assert_admin_view_menus_in('Gamma', self.assertNotIn)
- def test_update_explore(self):
- self.login(username='admin')
- tbl_id = self.table_ids.get('energy_usage')
- data = json.dumps({
- 'viz_type': 'sankey',
- 'groupby': ['source', 'target'],
- 'metrics': ['sum__value'],
- 'row_limit': 5000,
- 'flt_col_0': 'source',
- 'datasource_name': 'energy_usage',
- 'datasource_id': tbl_id,
- 'datasource_type': 'table',
- 'previous_viz_type': 'sankey'
- })
- response = self.client.post('/superset/update_explore/table/{}/'.format(tbl_id),
- data=dict(data=data))
- assert response.status_code == 200
- self.logout()
-
def test_save_slice(self):
self.login(username='admin')
slice_name = "Energy Sankey"