mirror of
https://github.com/apache/superset.git
synced 2024-09-19 03:59:49 -04:00
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
This commit is contained in:
parent
5718d6bbaf
commit
3949d39478
@ -53,6 +53,14 @@ class EditableTitle extends React.PureComponent {
|
|||||||
isEditing: false,
|
isEditing: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!this.state.title.length) {
|
||||||
|
this.setState({
|
||||||
|
title: this.state.lastTitle,
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.state.lastTitle !== this.state.title) {
|
if (this.state.lastTitle !== this.state.title) {
|
||||||
this.setState({
|
this.setState({
|
||||||
lastTitle: this.state.title,
|
lastTitle: this.state.title,
|
||||||
|
@ -150,3 +150,8 @@ export const RENDER_TRIGGERED = 'RENDER_TRIGGERED';
|
|||||||
export function renderTriggered() {
|
export function renderTriggered() {
|
||||||
return { type: RENDER_TRIGGERED };
|
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 };
|
||||||
|
}
|
||||||
|
@ -153,15 +153,22 @@ class ChartContainer extends React.PureComponent {
|
|||||||
this.props.actions.runQuery(this.props.formData, true, this.props.timeout);
|
this.props.actions.runQuery(this.props.formData, true, this.props.timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateChartTitle(newTitle) {
|
updateChartTitleOrSaveSlice(newTitle) {
|
||||||
|
const isNewSlice = !this.props.slice;
|
||||||
const params = {
|
const params = {
|
||||||
slice_name: newTitle,
|
slice_name: newTitle,
|
||||||
action: 'overwrite',
|
action: isNewSlice ? 'saveas' : 'overwrite',
|
||||||
};
|
};
|
||||||
const saveUrl = getExploreUrl(this.props.formData, 'base', false, null, params);
|
const saveUrl = getExploreUrl(this.props.formData, 'base', false, null, params);
|
||||||
this.props.actions.saveSlice(saveUrl)
|
this.props.actions.saveSlice(saveUrl)
|
||||||
.then(() => {
|
.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);
|
this.props.actions.updateChartTitle(newTitle);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -263,8 +270,8 @@ class ChartContainer extends React.PureComponent {
|
|||||||
>
|
>
|
||||||
<EditableTitle
|
<EditableTitle
|
||||||
title={this.renderChartTitle()}
|
title={this.renderChartTitle()}
|
||||||
canEdit={this.props.can_overwrite}
|
canEdit={!this.props.slice || this.props.can_overwrite}
|
||||||
onSaveTitle={this.updateChartTitle.bind(this)}
|
onSaveTitle={this.updateChartTitleOrSaveSlice.bind(this)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{this.props.slice &&
|
{this.props.slice &&
|
||||||
|
@ -108,7 +108,7 @@ class SaveModal extends React.Component {
|
|||||||
this.props.actions.saveSlice(saveUrl)
|
this.props.actions.saveSlice(saveUrl)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
// Go to new slice url or dashboard url
|
// Go to new slice url or dashboard url
|
||||||
window.location = data;
|
window.location = data.slice.slice_url;
|
||||||
});
|
});
|
||||||
this.props.onHide();
|
this.props.onHide();
|
||||||
}
|
}
|
||||||
@ -185,6 +185,7 @@ class SaveModal extends React.Component {
|
|||||||
{t('Add slice to existing dashboard')}
|
{t('Add slice to existing dashboard')}
|
||||||
</Radio>
|
</Radio>
|
||||||
<Select
|
<Select
|
||||||
|
className="save-modal-selector"
|
||||||
options={this.props.dashboards}
|
options={this.props.dashboards}
|
||||||
onChange={this.onChange.bind(this, 'saveToDashboardId')}
|
onChange={this.onChange.bind(this, 'saveToDashboardId')}
|
||||||
autoSize={false}
|
autoSize={false}
|
||||||
|
@ -104,3 +104,6 @@
|
|||||||
right: 0;
|
right: 0;
|
||||||
top: 12px;
|
top: 12px;
|
||||||
}
|
}
|
||||||
|
.save-modal-selector {
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
@ -72,6 +72,15 @@ export default function exploreReducer(state = {}, action) {
|
|||||||
[actions.RENDER_TRIGGERED]() {
|
[actions.RENDER_TRIGGERED]() {
|
||||||
return Object.assign({}, state, { triggerRender: false });
|
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) {
|
if (action.type in actionHandlers) {
|
||||||
return actionHandlers[action.type]();
|
return actionHandlers[action.type]();
|
||||||
|
@ -81,5 +81,12 @@ describe('EditableTitle', () => {
|
|||||||
// no change
|
// no change
|
||||||
expect(callback.callCount).to.equal(0);
|
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);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1067,6 +1067,8 @@ class Superset(BaseSupersetView):
|
|||||||
slice_overwrite_perm = is_owner(slc, g.user)
|
slice_overwrite_perm = is_owner(slc, g.user)
|
||||||
slice_download_perm = self.can_access('can_download', 'SliceModelView')
|
slice_download_perm = self.can_access('can_download', 'SliceModelView')
|
||||||
|
|
||||||
|
form_data['datasource'] = str(datasource_id) + '__' + datasource_type
|
||||||
|
|
||||||
# handle save or overwrite
|
# handle save or overwrite
|
||||||
action = request.args.get('action')
|
action = request.args.get('action')
|
||||||
|
|
||||||
@ -1078,10 +1080,10 @@ class Superset(BaseSupersetView):
|
|||||||
request.args,
|
request.args,
|
||||||
slc, slice_add_perm,
|
slc, slice_add_perm,
|
||||||
slice_overwrite_perm,
|
slice_overwrite_perm,
|
||||||
|
slice_download_perm,
|
||||||
datasource_id,
|
datasource_id,
|
||||||
datasource_type)
|
datasource_type)
|
||||||
|
|
||||||
form_data['datasource'] = str(datasource_id) + '__' + datasource_type
|
|
||||||
standalone = request.args.get("standalone") == "true"
|
standalone = request.args.get("standalone") == "true"
|
||||||
bootstrap_data = {
|
bootstrap_data = {
|
||||||
"can_add": slice_add_perm,
|
"can_add": slice_add_perm,
|
||||||
@ -1137,7 +1139,7 @@ class Superset(BaseSupersetView):
|
|||||||
return json_success(payload)
|
return json_success(payload)
|
||||||
|
|
||||||
def save_or_overwrite_slice(
|
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):
|
datasource_id, datasource_type):
|
||||||
"""Save or overwrite a slice"""
|
"""Save or overwrite a slice"""
|
||||||
slice_name = args.get('slice_name')
|
slice_name = args.get('slice_name')
|
||||||
@ -1192,7 +1194,13 @@ class Superset(BaseSupersetView):
|
|||||||
if request.args.get('goto_dash') == 'true':
|
if request.args.get('goto_dash') == 'true':
|
||||||
return dash.url
|
return dash.url
|
||||||
else:
|
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):
|
def save_slice(self, slc):
|
||||||
session = db.session()
|
session = db.session()
|
||||||
|
Loading…
Reference in New Issue
Block a user