diff --git a/.gitignore b/.gitignore
index 30770ff639dfb..ab5126af5d5e3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -24,7 +24,6 @@
.coverage
.DS_Store
.eggs
-.envrc
.idea
.mypy_cache
.python-version
diff --git a/superset/assets/package.json b/superset/assets/package.json
index d275e865da70c..657b8c6c1f294 100644
--- a/superset/assets/package.json
+++ b/superset/assets/package.json
@@ -79,9 +79,9 @@
"@superset-ui/legacy-preset-chart-deckgl": "^0.1.0",
"@superset-ui/legacy-preset-chart-nvd3": "^0.11.0",
"@superset-ui/number-format": "^0.12.1",
+ "@superset-ui/query": "^0.12.2",
"@superset-ui/plugin-chart-table": "^0.11.0",
"@superset-ui/preset-chart-xy": "^0.11.0",
- "@superset-ui/query": "^0.12.2",
"@superset-ui/time-format": "^0.12.1",
"@superset-ui/translation": "^0.12.0",
"@types/react-json-tree": "^0.6.11",
diff --git a/superset/assets/spec/javascripts/sqllab/SaveQuery_spec.jsx b/superset/assets/spec/javascripts/sqllab/SaveQuery_spec.jsx
index 46c215ceca1dc..d4a2f469eb6db 100644
--- a/superset/assets/spec/javascripts/sqllab/SaveQuery_spec.jsx
+++ b/superset/assets/spec/javascripts/sqllab/SaveQuery_spec.jsx
@@ -19,18 +19,14 @@
import React from 'react';
import { FormControl } from 'react-bootstrap';
import { shallow } from 'enzyme';
-import * as sinon from 'sinon';
import SaveQuery from '../../../src/SqlLab/components/SaveQuery';
import ModalTrigger from '../../../src/components/ModalTrigger';
-import Button from '../../../src/components/Button';
describe('SavedQuery', () => {
const mockedProps = {
- query: {
- dbId: 1,
- schema: 'main',
- sql: 'SELECT * FROM t',
- },
+ dbId: 1,
+ schema: 'main',
+ sql: 'SELECT * FROM t',
defaultLabel: 'untitled',
animation: false,
};
@@ -58,27 +54,4 @@ describe('SavedQuery', () => {
const modal = shallow(wrapper.instance().renderModalBody());
expect(modal.find(FormControl)).toHaveLength(2);
});
- it('has a save button if this is a new query', () => {
- const saveSpy = sinon.spy();
- const wrapper = shallow();
- const modal = shallow(wrapper.instance().renderModalBody());
- expect(modal.find(Button)).toHaveLength(2);
- modal.find(Button).at(0).simulate('click');
- expect(saveSpy.calledOnce).toBe(true);
- });
- it('has an update button if this is an existing query', () => {
- const updateSpy = sinon.spy();
- const props = {
- ...mockedProps,
- query: {
- ...mockedProps.query,
- remoteId: '42',
- },
- };
- const wrapper = shallow();
- const modal = shallow(wrapper.instance().renderModalBody());
- expect(modal.find(Button)).toHaveLength(3);
- modal.find(Button).at(0).simulate('click');
- expect(updateSpy.calledOnce).toBe(true);
- });
});
diff --git a/superset/assets/src/SqlLab/actions/sqlLab.js b/superset/assets/src/SqlLab/actions/sqlLab.js
index f4fcc8e16a920..5f2baa71734fd 100644
--- a/superset/assets/src/SqlLab/actions/sqlLab.js
+++ b/superset/assets/src/SqlLab/actions/sqlLab.js
@@ -20,8 +20,6 @@ import shortid from 'shortid';
import JSONbig from 'json-bigint';
import { t } from '@superset-ui/translation';
import { SupersetClient } from '@superset-ui/connection';
-import invert from 'lodash/invert';
-import mapKeys from 'lodash/mapKeys';
import { now } from '../../modules/dates';
import {
@@ -34,7 +32,6 @@ import COMMON_ERR_MESSAGES from '../../utils/errorMessages';
export const RESET_STATE = 'RESET_STATE';
export const ADD_QUERY_EDITOR = 'ADD_QUERY_EDITOR';
-export const UPDATE_QUERY_EDITOR = 'UPDATE_QUERY_EDITOR';
export const CLONE_QUERY_TO_NEW_TAB = 'CLONE_QUERY_TO_NEW_TAB';
export const REMOVE_QUERY_EDITOR = 'REMOVE_QUERY_EDITOR';
export const MERGE_TABLE = 'MERGE_TABLE';
@@ -85,24 +82,6 @@ export const addInfoToast = addInfoToastAction;
export const addSuccessToast = addSuccessToastAction;
export const addDangerToast = addDangerToastAction;
-// a map of SavedQuery field names to the different names used client-side,
-// because for now making the names consistent is too complicated
-// so it might as well only happen in one place
-const queryClientMapping = {
- id: 'remoteId',
- db_id: 'dbId',
- client_id: 'id',
- label: 'title',
-};
-const queryServerMapping = invert(queryClientMapping);
-
-// uses a mapping like those above to convert object key names to another style
-const fieldConverter = mapping => obj =>
- mapKeys(obj, (value, key) => key in mapping ? mapping[key] : key);
-
-const convertQueryToServer = fieldConverter(queryServerMapping);
-const convertQueryToClient = fieldConverter(queryClientMapping);
-
export function resetState() {
return { type: RESET_STATE };
}
@@ -126,29 +105,13 @@ export function saveQuery(query) {
return dispatch =>
SupersetClient.post({
endpoint: '/savedqueryviewapi/api/create',
- postPayload: convertQueryToServer(query),
+ postPayload: query,
stringify: false,
})
.then(() => dispatch(addSuccessToast(t('Your query was saved'))))
.catch(() => dispatch(addDangerToast(t('Your query could not be saved'))));
}
-export function updateQueryEditor(alterations) {
- return { type: UPDATE_QUERY_EDITOR, alterations };
-}
-
-export function updateSavedQuery(query) {
- return dispatch =>
- SupersetClient.put({
- endpoint: `/savedqueryviewapi/api/update/${query.remoteId}`,
- postPayload: convertQueryToServer(query),
- stringify: false,
- })
- .then(() => dispatch(addSuccessToast(t('Your query was updated'))))
- .catch(() => dispatch(addDangerToast(t('Your query could not be updated'))))
- .then(() => dispatch(updateQueryEditor(query)));
-}
-
export function scheduleQuery(query) {
return dispatch =>
SupersetClient.post({
@@ -541,9 +504,13 @@ export function popSavedQuery(saveQueryId) {
return function (dispatch) {
return SupersetClient.get({ endpoint: `/savedqueryviewapi/api/get/${saveQueryId}` })
.then(({ json }) => {
+ const { result } = json;
const queryEditorProps = {
- ...convertQueryToClient(json.result),
+ title: result.label,
+ dbId: result.db_id ? parseInt(result.db_id, 10) : null,
+ schema: result.schema,
autorun: false,
+ sql: result.sql,
};
return dispatch(addQueryEditor(queryEditorProps));
})
diff --git a/superset/assets/src/SqlLab/components/SaveQuery.jsx b/superset/assets/src/SqlLab/components/SaveQuery.jsx
index 14650d048b805..1b3c5029a50e9 100644
--- a/superset/assets/src/SqlLab/components/SaveQuery.jsx
+++ b/superset/assets/src/SqlLab/components/SaveQuery.jsx
@@ -25,11 +25,12 @@ import Button from '../../components/Button';
import ModalTrigger from '../../components/ModalTrigger';
const propTypes = {
- query: PropTypes.object,
defaultLabel: PropTypes.string,
+ sql: PropTypes.string,
+ schema: PropTypes.string,
+ dbId: PropTypes.number,
animation: PropTypes.bool,
onSave: PropTypes.func,
- onUpdate: PropTypes.func,
saveQueryWarning: PropTypes.string,
};
const defaultProps = {
@@ -49,21 +50,23 @@ class SaveQuery extends React.PureComponent {
};
this.toggleSave = this.toggleSave.bind(this);
this.onSave = this.onSave.bind(this);
- this.onUpdate = this.onUpdate.bind(this);
this.onCancel = this.onCancel.bind(this);
this.onLabelChange = this.onLabelChange.bind(this);
this.onDescriptionChange = this.onDescriptionChange.bind(this);
}
onSave() {
- this.props.onSave(this.queryPayload());
- this.close();
- }
- onUpdate() {
- this.props.onUpdate(this.queryPayload());
- this.close();
+ const query = {
+ label: this.state.label,
+ description: this.state.description,
+ db_id: this.props.dbId,
+ schema: this.props.schema,
+ sql: this.props.sql,
+ };
+ this.props.onSave(query);
+ this.saveModal.close();
}
onCancel() {
- this.close();
+ this.saveModal.close();
}
onLabelChange(e) {
this.setState({ label: e.target.value });
@@ -71,21 +74,10 @@ class SaveQuery extends React.PureComponent {
onDescriptionChange(e) {
this.setState({ description: e.target.value });
}
- queryPayload() {
- return {
- ...this.props.query,
- title: this.state.label,
- description: this.state.description,
- };
- }
- close() {
- if (this.saveModal) this.saveModal.close();
- }
toggleSave(e) {
this.setState({ target: e.target, showSave: !this.state.showSave });
}
renderModalBody() {
- const isSaved = !!this.props.query.remoteId;
return (
@@ -132,21 +124,12 @@ class SaveQuery extends React.PureComponent {
)}
- {isSaved && (
-
- )}