mirror of
https://github.com/apache/superset.git
synced 2026-04-17 07:05:04 +00:00
Save modal component for explore v2 (#1612)
* Added specs for SaveModal * Move datasource_id and datasource_name to form_data * Add comments * Deleted redundant fetchDashboard * Replcae has_key for python3 * More react and less jquery * Added alert for save slice * Small changes based on comments * Use react bootstrap
This commit is contained in:
241
superset/assets/javascripts/explorev2/components/SaveModal.js
Normal file
241
superset/assets/javascripts/explorev2/components/SaveModal.js
Normal file
@@ -0,0 +1,241 @@
|
||||
/* eslint camel-case: 0 */
|
||||
import React, { PropTypes } from 'react';
|
||||
import $ from 'jquery';
|
||||
import { Modal, Alert, Button, Radio } from 'react-bootstrap';
|
||||
import Select from 'react-select';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
const propTypes = {
|
||||
can_edit: PropTypes.bool,
|
||||
onHide: PropTypes.func.isRequired,
|
||||
actions: PropTypes.object.isRequired,
|
||||
form_data: PropTypes.object,
|
||||
datasource_type: PropTypes.string.isRequired,
|
||||
user_id: PropTypes.string.isRequired,
|
||||
dashboards: PropTypes.array.isRequired,
|
||||
alert: PropTypes.string,
|
||||
};
|
||||
|
||||
class SaveModal extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
saveToDashboardId: null,
|
||||
newDashboardName: '',
|
||||
newSliceName: '',
|
||||
dashboards: [],
|
||||
alert: null,
|
||||
action: 'overwrite',
|
||||
addToDash: 'noSave',
|
||||
};
|
||||
}
|
||||
componentDidMount() {
|
||||
this.props.actions.fetchDashboards(this.props.user_id);
|
||||
}
|
||||
onChange(name, event) {
|
||||
switch (name) {
|
||||
case 'newSliceName':
|
||||
this.setState({ newSliceName: event.target.value });
|
||||
break;
|
||||
case 'saveToDashboardId':
|
||||
this.setState({ saveToDashboardId: event.value });
|
||||
this.changeDash('existing');
|
||||
break;
|
||||
case 'newDashboardName':
|
||||
this.setState({ newDashboardName: event.target.value });
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
changeAction(action) {
|
||||
this.setState({ action });
|
||||
}
|
||||
changeDash(dash) {
|
||||
this.setState({ addToDash: dash });
|
||||
}
|
||||
saveOrOverwrite(gotodash) {
|
||||
this.setState({ alert: null });
|
||||
this.props.actions.removeSaveModalAlert();
|
||||
const params = {};
|
||||
const sliceParams = {};
|
||||
params.datasource_id = this.props.form_data.datasource;
|
||||
params.datasource_type = this.props.datasource_type;
|
||||
params.datasource_name = this.props.form_data.datasource_name;
|
||||
|
||||
let sliceName = null;
|
||||
sliceParams.action = this.state.action;
|
||||
if (sliceParams.action === 'saveas') {
|
||||
sliceName = this.state.newSliceName;
|
||||
if (sliceName === '') {
|
||||
this.setState({ alert: 'Please enter a slice name' });
|
||||
return;
|
||||
}
|
||||
sliceParams.slice_name = sliceName;
|
||||
} else {
|
||||
sliceParams.slice_name = this.props.form_data.slice_name;
|
||||
}
|
||||
|
||||
Object.keys(this.props.form_data).forEach((field) => {
|
||||
if (this.props.form_data[field] !== null && field !== 'slice_name') {
|
||||
params[field] = this.props.form_data[field];
|
||||
}
|
||||
});
|
||||
|
||||
const addToDash = this.state.addToDash;
|
||||
sliceParams.add_to_dash = addToDash;
|
||||
let dashboard = null;
|
||||
switch (addToDash) {
|
||||
case ('existing'):
|
||||
dashboard = this.state.saveToDashboardId;
|
||||
if (!dashboard) {
|
||||
this.setState({ alert: 'Please select a dashboard' });
|
||||
return;
|
||||
}
|
||||
sliceParams.save_to_dashboard_id = dashboard;
|
||||
break;
|
||||
case ('new'):
|
||||
dashboard = this.state.newDashboardName;
|
||||
if (dashboard === '') {
|
||||
this.setState({ alert: 'Please enter a dashboard name' });
|
||||
return;
|
||||
}
|
||||
sliceParams.new_dashboard_name = dashboard;
|
||||
break;
|
||||
default:
|
||||
dashboard = null;
|
||||
}
|
||||
params.V2 = true;
|
||||
sliceParams.goto_dash = gotodash;
|
||||
const baseUrl = '/superset/explore/' +
|
||||
`${this.props.datasource_type}/${this.props.form_data.datasource}/`;
|
||||
const saveUrl = `${baseUrl}?${$.param(params, true)}&${$.param(sliceParams, true)}`;
|
||||
this.props.actions.saveSlice(saveUrl);
|
||||
this.props.onHide();
|
||||
}
|
||||
removeAlert() {
|
||||
if (this.props.alert) {
|
||||
this.props.actions.removeSaveModalAlert();
|
||||
}
|
||||
this.setState({ alert: null });
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<Modal
|
||||
show
|
||||
onHide={this.props.onHide}
|
||||
bsStyle="large"
|
||||
>
|
||||
<Modal.Header closeButton>
|
||||
<Modal.Title>
|
||||
Save A Slice
|
||||
</Modal.Title>
|
||||
</Modal.Header>
|
||||
<Modal.Body>
|
||||
{(this.state.alert || this.props.alert) &&
|
||||
<Alert>
|
||||
{this.state.alert ? this.state.alert : this.props.alert}
|
||||
<i
|
||||
className="fa fa-close pull-right"
|
||||
onClick={this.removeAlert.bind(this)}
|
||||
style={{ cursor: 'pointer' }}
|
||||
/>
|
||||
</Alert>
|
||||
}
|
||||
<Radio
|
||||
disabled={!this.props.can_edit}
|
||||
checked={this.state.action === 'overwrite'}
|
||||
onChange={this.changeAction.bind(this, 'overwrite')}
|
||||
>
|
||||
{`Overwrite slice ${this.props.form_data.slice_name}`}
|
||||
</Radio>
|
||||
|
||||
<Radio
|
||||
inline
|
||||
checked={this.state.action === 'saveas'}
|
||||
onChange={this.changeAction.bind(this, 'saveas')}
|
||||
> Save as
|
||||
</Radio>
|
||||
<input
|
||||
name="new_slice_name"
|
||||
placeholder="[slice name]"
|
||||
onChange={this.onChange.bind(this, 'newSliceName')}
|
||||
onFocus={this.changeAction.bind(this, 'saveas')}
|
||||
/>
|
||||
|
||||
|
||||
<br />
|
||||
<hr />
|
||||
|
||||
<Radio
|
||||
checked={this.state.addToDash === 'noSave'}
|
||||
onChange={this.changeDash.bind(this, 'noSave')}
|
||||
>
|
||||
Do not add to a dashboard
|
||||
</Radio>
|
||||
|
||||
<Radio
|
||||
inline
|
||||
checked={this.state.addToDash === 'existing'}
|
||||
onChange={this.changeDash.bind(this, 'existing')}
|
||||
>
|
||||
Add slice to existing dashboard
|
||||
</Radio>
|
||||
<Select
|
||||
options={this.props.dashboards}
|
||||
onChange={this.onChange.bind(this, 'saveToDashboardId')}
|
||||
autoSize={false}
|
||||
value={this.state.saveToDashboardId}
|
||||
/>
|
||||
|
||||
<Radio
|
||||
inline
|
||||
checked={this.state.addToDash === 'new'}
|
||||
onChange={this.changeDash.bind(this, 'new')}
|
||||
>
|
||||
Add to new dashboard
|
||||
</Radio>
|
||||
<input
|
||||
onChange={this.onChange.bind(this, 'newDashboardName')}
|
||||
onFocus={this.changeDash.bind(this, 'new')}
|
||||
placeholder="[dashboard name]"
|
||||
/>
|
||||
</Modal.Body>
|
||||
|
||||
<Modal.Footer>
|
||||
<Button
|
||||
type="button"
|
||||
id="btn_modal_save"
|
||||
className="btn pull-left"
|
||||
onClick={this.saveOrOverwrite.bind(this)}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
id="btn_modal_save_goto_dash"
|
||||
className="btn btn-primary pull-left gotodash"
|
||||
disabled={this.state.addToDash === 'noSave'}
|
||||
onClick={this.saveOrOverwrite.bind(this, true)}
|
||||
>
|
||||
Save & go to dashboard
|
||||
</Button>
|
||||
</Modal.Footer>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
SaveModal.propTypes = propTypes;
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
can_edit: state.can_edit,
|
||||
user_id: state.user_id,
|
||||
dashboards: state.dashboards,
|
||||
alert: state.saveModalAlert,
|
||||
};
|
||||
}
|
||||
|
||||
export { SaveModal };
|
||||
export default connect(mapStateToProps, () => ({}))(SaveModal);
|
||||
Reference in New Issue
Block a user