[dashboard] give user feedback when there are unsaved changes (#1633)

* show alert and use dialog window if there are unsaved changes.

* add container class to alert
This commit is contained in:
Alanna Scott 2016-11-18 09:37:01 -08:00 committed by GitHub
parent d5ef937b31
commit ab5a4102cd
3 changed files with 41 additions and 0 deletions

View File

@ -4,6 +4,7 @@ const px = require('../modules/superset');
const d3 = require('d3'); const d3 = require('d3');
const urlLib = require('url'); const urlLib = require('url');
const utils = require('../modules/utils'); const utils = require('../modules/utils');
const { Alert } = require('react-bootstrap');
import React from 'react'; import React from 'react';
import { render } from 'react-dom'; import { render } from 'react-dom';
@ -33,6 +34,33 @@ export function getInitialState(dashboardData, context) {
return state; return state;
} }
function unload() {
const message = 'You have unsaved changes.';
window.event.returnValue = message; // Gecko + IE
return message; // Gecko + Webkit, Safari, Chrome etc.
}
function onBeforeUnload(hasChanged) {
if (hasChanged) {
window.addEventListener('beforeunload', unload);
} else {
window.removeEventListener('beforeunload', unload);
}
}
function renderAlert() {
render(
<div className="container-fluid">
<Alert bsStyle="warning">
<strong>You have unsaved changes.</strong> Click the&nbsp;
<i className="fa fa-save" />&nbsp;
button on the top right to save your changes.
</Alert>
</div>,
document.getElementById('alert-container')
);
}
function initDashboardView(dashboard) { function initDashboardView(dashboard) {
render( render(
<Header dashboard={dashboard} />, <Header dashboard={dashboard} />,
@ -96,6 +124,14 @@ export function dashboardContainer(dashboard) {
this.startPeriodicRender(0); this.startPeriodicRender(0);
this.bindResizeToWindowResize(); this.bindResizeToWindowResize();
}, },
onChange() {
onBeforeUnload(true);
renderAlert();
},
onSave() {
onBeforeUnload(false);
$('#alert-container').html('');
},
loadPreSelectFilters() { loadPreSelectFilters() {
try { try {
const filters = JSON.parse(px.getParam('preselect_filters') || '{}'); const filters = JSON.parse(px.getParam('preselect_filters') || '{}');

View File

@ -59,6 +59,7 @@ class Controls extends React.PureComponent {
data: JSON.stringify(data), data: JSON.stringify(data),
}, },
success() { success() {
dashboard.onSave();
showModal({ showModal({
title: 'Success', title: 'Success',
body: 'This dashboard was saved successfully.', body: 'This dashboard was saved successfully.',
@ -75,6 +76,7 @@ class Controls extends React.PureComponent {
} }
changeCss(css) { changeCss(css) {
this.setState({ css }); this.setState({ css });
this.props.dashboard.onChange();
} }
render() { render() {
const dashboard = this.props.dashboard; const dashboard = this.props.dashboard;

View File

@ -48,10 +48,12 @@ class GridLayout extends React.Component {
if (oldItem.w !== newItem.w || oldItem.h !== newItem.h) { if (oldItem.w !== newItem.w || oldItem.h !== newItem.h) {
this.setState({ layout }, () => newSlice.resize()); this.setState({ layout }, () => newSlice.resize());
} }
this.props.dashboard.onChange();
} }
onDragStop(layout) { onDragStop(layout) {
this.setState({ layout }); this.setState({ layout });
this.props.dashboard.onChange();
} }
removeSlice(sliceId) { removeSlice(sliceId) {
@ -64,6 +66,7 @@ class GridLayout extends React.Component {
return slice.slice_id !== sliceId; return slice.slice_id !== sliceId;
}), }),
}); });
this.props.dashboard.onChange();
} }
serialize() { serialize() {