mirror of
https://github.com/apache/superset.git
synced 2026-04-19 08:04:53 +00:00
allow user update slice name in dashboard view (#3467)
- if current user is allowed to edit dashboard, we will allow this user to edit slice name. - show different tooltip given allowed/not-allowed to update slice name. - user will click slice name and update. - after user submit edit, if he doesn't have right to alter slice, server-side will return error message to client-side. Slice name will not be changed or saved. - will show notification after save slice name.
This commit is contained in:
committed by
Maxime Beauchemin
parent
f3146ef6f9
commit
5718d6bbaf
@@ -6,7 +6,8 @@ import { t } from '../locales';
|
||||
const propTypes = {
|
||||
title: PropTypes.string,
|
||||
canEdit: PropTypes.bool,
|
||||
onSaveTitle: PropTypes.func.isRequired,
|
||||
onSaveTitle: PropTypes.func,
|
||||
noPermitTooltip: PropTypes.string,
|
||||
};
|
||||
const defaultProps = {
|
||||
title: t('Title'),
|
||||
@@ -26,6 +27,14 @@ class EditableTitle extends React.PureComponent {
|
||||
this.handleChange = this.handleChange.bind(this);
|
||||
this.handleKeyPress = this.handleKeyPress.bind(this);
|
||||
}
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.title !== this.state.title) {
|
||||
this.setState({
|
||||
lastTitle: this.state.title,
|
||||
title: nextProps.title,
|
||||
});
|
||||
}
|
||||
}
|
||||
handleClick() {
|
||||
if (!this.props.canEdit) {
|
||||
return;
|
||||
@@ -72,7 +81,8 @@ class EditableTitle extends React.PureComponent {
|
||||
<span className="editable-title">
|
||||
<TooltipWrapper
|
||||
label="title"
|
||||
tooltip={this.props.canEdit ? t('click to edit title') : t('You don\'t have the rights to alter this title.')}
|
||||
tooltip={this.props.canEdit ? t('click to edit title') :
|
||||
this.props.noPermitTooltip || t('You don\'t have the rights to alter this title.')}
|
||||
>
|
||||
<input
|
||||
required
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
/* global notify */
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Responsive, WidthProvider } from 'react-grid-layout';
|
||||
import $ from 'jquery';
|
||||
|
||||
import SliceCell from './SliceCell';
|
||||
import { getExploreUrl } from '../../explore/exploreUtils';
|
||||
|
||||
require('react-grid-layout/css/styles.css');
|
||||
require('react-resizable/css/styles.css');
|
||||
@@ -72,6 +74,42 @@ class GridLayout extends React.Component {
|
||||
this.props.dashboard.onChange();
|
||||
}
|
||||
|
||||
updateSliceName(sliceId, sliceName) {
|
||||
const index = this.state.slices.map(slice => (slice.slice_id)).indexOf(sliceId);
|
||||
if (index === -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// update slice_name first
|
||||
const oldSlices = this.state.slices;
|
||||
const currentSlice = this.state.slices[index];
|
||||
const updated = Object.assign({},
|
||||
this.state.slices[index], { slice_name: sliceName });
|
||||
const updatedSlices = this.state.slices.slice();
|
||||
updatedSlices[index] = updated;
|
||||
this.setState({ slices: updatedSlices });
|
||||
|
||||
const sliceParams = {};
|
||||
sliceParams.slice_id = currentSlice.slice_id;
|
||||
sliceParams.action = 'overwrite';
|
||||
sliceParams.slice_name = sliceName;
|
||||
const saveUrl = getExploreUrl(currentSlice.form_data, 'base', false, null, sliceParams);
|
||||
|
||||
$.ajax({
|
||||
url: saveUrl,
|
||||
type: 'GET',
|
||||
success: () => {
|
||||
notify.success('This slice name was saved successfully.');
|
||||
},
|
||||
error: () => {
|
||||
// if server-side reject the overwrite action,
|
||||
// revert to old state
|
||||
this.setState({ slices: oldSlices });
|
||||
notify.error('You don\'t have the rights to alter this slice');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
serialize() {
|
||||
return this.state.layout.map(reactPos => ({
|
||||
slice_id: reactPos.i,
|
||||
@@ -107,6 +145,8 @@ class GridLayout extends React.Component {
|
||||
slice={slice}
|
||||
removeSlice={this.removeSlice.bind(this, slice.slice_id)}
|
||||
expandedSlices={this.props.dashboard.metadata.expanded_slices}
|
||||
updateSliceName={this.props.dashboard.dash_edit_perm ?
|
||||
this.updateSliceName.bind(this) : null}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
|
||||
@@ -30,6 +30,7 @@ class Header extends React.PureComponent {
|
||||
title={dashboard.dashboard_title}
|
||||
canEdit={dashboard.dash_save_perm}
|
||||
onSaveTitle={this.handleSaveTitle}
|
||||
noPermitTooltip={'You don\'t have the rights to alter this dashboard.'}
|
||||
/>
|
||||
<span is class="favstar" class_name="Dashboard" obj_id={dashboard.id} />
|
||||
</h1>
|
||||
|
||||
@@ -4,22 +4,35 @@ import PropTypes from 'prop-types';
|
||||
|
||||
import { t } from '../../locales';
|
||||
import { getExploreUrl } from '../../explore/exploreUtils';
|
||||
import EditableTitle from '../../components/EditableTitle';
|
||||
|
||||
const propTypes = {
|
||||
slice: PropTypes.object.isRequired,
|
||||
removeSlice: PropTypes.func.isRequired,
|
||||
updateSliceName: PropTypes.func,
|
||||
expandedSlices: PropTypes.object,
|
||||
};
|
||||
|
||||
function SliceCell({ expandedSlices, removeSlice, slice }) {
|
||||
const SliceCell = ({ expandedSlices, removeSlice, slice, updateSliceName }) => {
|
||||
const onSaveTitle = (newTitle) => {
|
||||
if (updateSliceName) {
|
||||
updateSliceName(slice.slice_id, newTitle);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="slice-cell" id={`${slice.slice_id}-cell`}>
|
||||
<div className="chart-header">
|
||||
<div className="row">
|
||||
<div className="col-md-12 header">
|
||||
<span>{slice.slice_name}</span>
|
||||
<div className="row chart-header">
|
||||
<div className="col-md-12">
|
||||
<div className="header">
|
||||
<EditableTitle
|
||||
title={slice.slice_name}
|
||||
canEdit={!!updateSliceName}
|
||||
onSaveTitle={onSaveTitle}
|
||||
noPermitTooltip={'You don\'t have the rights to alter this dashboard.'}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-md-12 chart-controls">
|
||||
<div className="chart-controls">
|
||||
<div id={'controls_' + slice.slice_id} className="pull-right">
|
||||
<a title={t('Move chart')} data-toggle="tooltip">
|
||||
<i className="fa fa-arrows drag" />
|
||||
@@ -97,7 +110,7 @@ function SliceCell({ expandedSlices, removeSlice, slice }) {
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
SliceCell.propTypes = propTypes;
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ div.widget .chart-controls {
|
||||
position: absolute;
|
||||
z-index: 100;
|
||||
right: 0;
|
||||
left: 0;
|
||||
top: 5px;
|
||||
padding: 5px 5px;
|
||||
opacity: 0.75;
|
||||
@@ -117,6 +116,7 @@ div.widget .chart-controls {
|
||||
|
||||
.chart-header .header {
|
||||
font-size: 16px;
|
||||
margin: 0 -10px;
|
||||
}
|
||||
.ace_gutter {
|
||||
z-index: 0;
|
||||
|
||||
@@ -1069,6 +1069,10 @@ class Superset(BaseSupersetView):
|
||||
|
||||
# handle save or overwrite
|
||||
action = request.args.get('action')
|
||||
|
||||
if action == 'overwrite' and not slice_overwrite_perm:
|
||||
return json_error_response("You don't have the rights to alter this slice", status=400)
|
||||
|
||||
if action in ('saveas', 'overwrite'):
|
||||
return self.save_or_overwrite_slice(
|
||||
request.args,
|
||||
|
||||
Reference in New Issue
Block a user