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: Allow user update slice title in visualize flow (#3466)
Date Mon, 25 Sep 2017 18:38:31 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 3949d39  Allow user update slice title in visualize flow (#3466)
3949d39 is described below

commit 3949d39478f482993e4b11d51e7229a3784f5be1
Author: Grace Guo <grace.guo@airbnb.com>
AuthorDate: Mon Sep 25 11:38:29 2017 -0700

    Allow user update slice title in visualize flow (#3466)
    
    * 1. after user make sql query and visualize, allow user click title to update slice title,
and create a new slice at the same time.
    2. don't save new title if it is empty. Will still show old title.
    
    * change saveSlice call response and update explore view
---
 .../assets/javascripts/components/EditableTitle.jsx   |  8 ++++++++
 .../javascripts/explore/actions/exploreActions.js     |  5 +++++
 .../javascripts/explore/components/ChartContainer.jsx | 19 +++++++++++++------
 .../javascripts/explore/components/SaveModal.jsx      |  3 ++-
 superset/assets/javascripts/explore/main.css          |  3 +++
 .../javascripts/explore/reducers/exploreReducer.js    |  9 +++++++++
 .../spec/javascripts/profile/EditableTitle_spec.jsx   |  7 +++++++
 superset/views/core.py                                | 14 +++++++++++---
 8 files changed, 58 insertions(+), 10 deletions(-)

diff --git a/superset/assets/javascripts/components/EditableTitle.jsx b/superset/assets/javascripts/components/EditableTitle.jsx
index 9ea64a3..31c4c53 100644
--- a/superset/assets/javascripts/components/EditableTitle.jsx
+++ b/superset/assets/javascripts/components/EditableTitle.jsx
@@ -53,6 +53,14 @@ class EditableTitle extends React.PureComponent {
       isEditing: false,
     });
 
+    if (!this.state.title.length) {
+      this.setState({
+        title: this.state.lastTitle,
+      });
+
+      return;
+    }
+
     if (this.state.lastTitle !== this.state.title) {
       this.setState({
         lastTitle: this.state.title,
diff --git a/superset/assets/javascripts/explore/actions/exploreActions.js b/superset/assets/javascripts/explore/actions/exploreActions.js
index 1608282..dbba7b7 100644
--- a/superset/assets/javascripts/explore/actions/exploreActions.js
+++ b/superset/assets/javascripts/explore/actions/exploreActions.js
@@ -150,3 +150,8 @@ export const RENDER_TRIGGERED = 'RENDER_TRIGGERED';
 export function renderTriggered() {
   return { type: RENDER_TRIGGERED };
 }
+
+export const CREATE_NEW_SLICE = 'CREATE_NEW_SLICE';
+export function createNewSlice(can_add, can_download, can_overwrite, slice, form_data) {
+  return { type: CREATE_NEW_SLICE, can_add, can_download, can_overwrite, slice, form_data
};
+}
diff --git a/superset/assets/javascripts/explore/components/ChartContainer.jsx b/superset/assets/javascripts/explore/components/ChartContainer.jsx
index 2d0830d..f3c660a 100644
--- a/superset/assets/javascripts/explore/components/ChartContainer.jsx
+++ b/superset/assets/javascripts/explore/components/ChartContainer.jsx
@@ -153,15 +153,22 @@ class ChartContainer extends React.PureComponent {
     this.props.actions.runQuery(this.props.formData, true, this.props.timeout);
   }
 
-  updateChartTitle(newTitle) {
+  updateChartTitleOrSaveSlice(newTitle) {
+    const isNewSlice = !this.props.slice;
     const params = {
       slice_name: newTitle,
-      action: 'overwrite',
+      action: isNewSlice ? 'saveas' : 'overwrite',
     };
     const saveUrl = getExploreUrl(this.props.formData, 'base', false, null, params);
     this.props.actions.saveSlice(saveUrl)
-      .then(() => {
-        this.props.actions.updateChartTitle(newTitle);
+      .then((data) => {
+        if (isNewSlice) {
+          this.props.actions.createNewSlice(
+              data.can_add, data.can_download, data.can_overwrite,
+              data.slice, data.form_data);
+        } else {
+          this.props.actions.updateChartTitle(newTitle);
+        }
       });
   }
 
@@ -263,8 +270,8 @@ class ChartContainer extends React.PureComponent {
             >
               <EditableTitle
                 title={this.renderChartTitle()}
-                canEdit={this.props.can_overwrite}
-                onSaveTitle={this.updateChartTitle.bind(this)}
+                canEdit={!this.props.slice || this.props.can_overwrite}
+                onSaveTitle={this.updateChartTitleOrSaveSlice.bind(this)}
               />
 
               {this.props.slice &&
diff --git a/superset/assets/javascripts/explore/components/SaveModal.jsx b/superset/assets/javascripts/explore/components/SaveModal.jsx
index ac76e3a..9de8353 100644
--- a/superset/assets/javascripts/explore/components/SaveModal.jsx
+++ b/superset/assets/javascripts/explore/components/SaveModal.jsx
@@ -108,7 +108,7 @@ class SaveModal extends React.Component {
     this.props.actions.saveSlice(saveUrl)
       .then((data) => {
         // Go to new slice url or dashboard url
-        window.location = data;
+        window.location = data.slice.slice_url;
       });
     this.props.onHide();
   }
@@ -185,6 +185,7 @@ class SaveModal extends React.Component {
             {t('Add slice to existing dashboard')}
           </Radio>
           <Select
+            className="save-modal-selector"
             options={this.props.dashboards}
             onChange={this.onChange.bind(this, 'saveToDashboardId')}
             autoSize={false}
diff --git a/superset/assets/javascripts/explore/main.css b/superset/assets/javascripts/explore/main.css
index abae1ce..50b1ed2 100644
--- a/superset/assets/javascripts/explore/main.css
+++ b/superset/assets/javascripts/explore/main.css
@@ -104,3 +104,6 @@
   right: 0;
   top: 12px;
 }
+.save-modal-selector {
+  margin: 10px 0;
+}
\ No newline at end of file
diff --git a/superset/assets/javascripts/explore/reducers/exploreReducer.js b/superset/assets/javascripts/explore/reducers/exploreReducer.js
index 35281aa..e37df6e 100644
--- a/superset/assets/javascripts/explore/reducers/exploreReducer.js
+++ b/superset/assets/javascripts/explore/reducers/exploreReducer.js
@@ -72,6 +72,15 @@ export default function exploreReducer(state = {}, action) {
     [actions.RENDER_TRIGGERED]() {
       return Object.assign({}, state, { triggerRender: false });
     },
+    [actions.CREATE_NEW_SLICE]() {
+      return Object.assign({}, state, {
+        slice: action.slice,
+        controls: getControlsState(state, action.form_data),
+        can_add: action.can_add,
+        can_download: action.can_download,
+        can_overwrite: action.can_overwrite,
+      });
+    },
   };
   if (action.type in actionHandlers) {
     return actionHandlers[action.type]();
diff --git a/superset/assets/spec/javascripts/profile/EditableTitle_spec.jsx b/superset/assets/spec/javascripts/profile/EditableTitle_spec.jsx
index 4e63b26..9a9e551 100644
--- a/superset/assets/spec/javascripts/profile/EditableTitle_spec.jsx
+++ b/superset/assets/spec/javascripts/profile/EditableTitle_spec.jsx
@@ -81,5 +81,12 @@ describe('EditableTitle', () => {
       // no change
       expect(callback.callCount).to.equal(0);
     });
+    it('should not save empty title', () => {
+      editableWrapper.setState({ title: '' });
+      editableWrapper.find('input').simulate('blur');
+      expect(editableWrapper.find('input').props().type).to.equal('button');
+      expect(editableWrapper.find('input').props().value).to.equal('my title');
+      expect(callback.callCount).to.equal(0);
+    });
   });
 });
diff --git a/superset/views/core.py b/superset/views/core.py
index 386ec5a..86e5221 100755
--- a/superset/views/core.py
+++ b/superset/views/core.py
@@ -1067,6 +1067,8 @@ class Superset(BaseSupersetView):
         slice_overwrite_perm = is_owner(slc, g.user)
         slice_download_perm = self.can_access('can_download', 'SliceModelView')
 
+        form_data['datasource'] = str(datasource_id) + '__' + datasource_type
+
         # handle save or overwrite
         action = request.args.get('action')
 
@@ -1078,10 +1080,10 @@ class Superset(BaseSupersetView):
                 request.args,
                 slc, slice_add_perm,
                 slice_overwrite_perm,
+                slice_download_perm,
                 datasource_id,
                 datasource_type)
 
-        form_data['datasource'] = str(datasource_id) + '__' + datasource_type
         standalone = request.args.get("standalone") == "true"
         bootstrap_data = {
             "can_add": slice_add_perm,
@@ -1137,7 +1139,7 @@ class Superset(BaseSupersetView):
         return json_success(payload)
 
     def save_or_overwrite_slice(
-            self, args, slc, slice_add_perm, slice_overwrite_perm,
+            self, args, slc, slice_add_perm, slice_overwrite_perm, slice_download_perm,
             datasource_id, datasource_type):
         """Save or overwrite a slice"""
         slice_name = args.get('slice_name')
@@ -1192,7 +1194,13 @@ class Superset(BaseSupersetView):
         if request.args.get('goto_dash') == 'true':
             return dash.url
         else:
-            return slc.slice_url
+            return json_success(json.dumps({
+                "can_add": slice_add_perm,
+                "can_download": slice_download_perm,
+                "can_overwrite": is_owner(slc, g.user),
+                'form_data': form_data,
+                'slice': slc.data,
+            }))
 
     def save_slice(self, slc):
         session = db.session()

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

Mime
View raw message