You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by cc...@apache.org on 2018/03/16 06:46:49 UTC
[incubator-superset] branch chris--top-level-tabs updated:
[undo-redo] add redux undo redo
This is an automated email from the ASF dual-hosted git repository.
ccwilliams pushed a commit to branch chris--top-level-tabs
in repository https://gitbox.apache.org/repos/asf/incubator-superset.git
The following commit(s) were added to refs/heads/chris--top-level-tabs by this push:
new 43d6ec7 [undo-redo] add redux undo redo
43d6ec7 is described below
commit 43d6ec7000244966bafb8cef029a995b7f0ac0eb
Author: Chris Williams <ch...@airbnb.com>
AuthorDate: Thu Mar 15 23:46:32 2018 -0700
[undo-redo] add redux undo redo
---
superset/assets/javascripts/dashboard/index.jsx | 6 +++++-
.../javascripts/dashboard/v2/actions/index.js | 3 ++-
.../dashboard/v2/components/DashboardHeader.jsx | 25 ++++++++++++++++++++--
.../dashboard/v2/containers/DashboardBuilder.jsx | 4 ++--
.../dashboard/v2/containers/DashboardComponent.jsx | 3 ++-
.../dashboard/v2/containers/DashboardHeader.jsx | 9 ++++++--
.../javascripts/dashboard/v2/reducers/index.js | 9 +++++++-
superset/assets/package.json | 1 +
8 files changed, 50 insertions(+), 10 deletions(-)
diff --git a/superset/assets/javascripts/dashboard/index.jsx b/superset/assets/javascripts/dashboard/index.jsx
index f3480d3..bb21a43 100644
--- a/superset/assets/javascripts/dashboard/index.jsx
+++ b/superset/assets/javascripts/dashboard/index.jsx
@@ -20,7 +20,11 @@ const appContainer = document.getElementById('app');
// const bootstrapData = JSON.parse(appContainer.getAttribute('data-bootstrap'));
// const initState = Object.assign({}, getInitialState(bootstrapData));
const initState = {
- dashboard: emptyDashboardLayout,
+ dashboard: {
+ past: [],
+ present: emptyDashboardLayout,
+ future: [],
+ },
};
const store = createStore(
diff --git a/superset/assets/javascripts/dashboard/v2/actions/index.js b/superset/assets/javascripts/dashboard/v2/actions/index.js
index effdeeb..99ce5f3 100644
--- a/superset/assets/javascripts/dashboard/v2/actions/index.js
+++ b/superset/assets/javascripts/dashboard/v2/actions/index.js
@@ -87,7 +87,8 @@ export function handleComponentDrop(dropResult) {
}
if (source) {
- const { dashboard } = getState();
+ const { dashboard: undoableDashboard } = getState();
+ const { present: dashboard } = undoableDashboard;
const sourceComponent = dashboard[source.droppableId];
if (sourceComponent.type === TABS_TYPE && sourceComponent.children.length === 0) {
diff --git a/superset/assets/javascripts/dashboard/v2/components/DashboardHeader.jsx b/superset/assets/javascripts/dashboard/v2/components/DashboardHeader.jsx
index f65e55a..e0d14c4 100644
--- a/superset/assets/javascripts/dashboard/v2/components/DashboardHeader.jsx
+++ b/superset/assets/javascripts/dashboard/v2/components/DashboardHeader.jsx
@@ -1,6 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
-import { ButtonToolbar, DropdownButton, MenuItem } from 'react-bootstrap';
+import { ButtonGroup, ButtonToolbar, DropdownButton, MenuItem } from 'react-bootstrap';
import Button from '../../../components/Button';
import { componentShape } from '../util/propShapes';
@@ -13,6 +13,10 @@ const propTypes = {
// redux
updateComponents: PropTypes.func.isRequired,
+ onUndo: PropTypes.func.isRequired,
+ onRedo: PropTypes.func.isRequired,
+ canUndo: PropTypes.bool.isRequired,
+ canRedo: PropTypes.bool.isRequired,
};
class DashboardHeader extends React.Component {
@@ -43,7 +47,7 @@ class DashboardHeader extends React.Component {
}
render() {
- const { component } = this.props;
+ const { component, onUndo, onRedo, canUndo, canRedo } = this.props;
const editMode = true;
return (
@@ -57,6 +61,23 @@ class DashboardHeader extends React.Component {
/>
</h1>
<ButtonToolbar>
+ <ButtonGroup>
+ <Button
+ bsSize="small"
+ onClick={onUndo}
+ disabled={!canUndo}
+ >
+ Undo
+ </Button>
+ <Button
+ bsSize="small"
+ onClick={onRedo}
+ disabled={!canRedo}
+ >
+ Redo
+ </Button>
+ </ButtonGroup>
+
<DropdownButton title="Actions" bsSize="small" id="btn-dashboard-actions">
<MenuItem>Action 1</MenuItem>
<MenuItem>Action 2</MenuItem>
diff --git a/superset/assets/javascripts/dashboard/v2/containers/DashboardBuilder.jsx b/superset/assets/javascripts/dashboard/v2/containers/DashboardBuilder.jsx
index 5505f20..48305ef 100644
--- a/superset/assets/javascripts/dashboard/v2/containers/DashboardBuilder.jsx
+++ b/superset/assets/javascripts/dashboard/v2/containers/DashboardBuilder.jsx
@@ -8,9 +8,9 @@ import {
handleComponentDrop,
} from '../actions';
-function mapStateToProps({ dashboard = {} }) {
+function mapStateToProps({ dashboard: undoableDashboard }) {
return {
- dashboard,
+ dashboard: undoableDashboard.present,
};
}
diff --git a/superset/assets/javascripts/dashboard/v2/containers/DashboardComponent.jsx b/superset/assets/javascripts/dashboard/v2/containers/DashboardComponent.jsx
index 1340781..df18233 100644
--- a/superset/assets/javascripts/dashboard/v2/containers/DashboardComponent.jsx
+++ b/superset/assets/javascripts/dashboard/v2/containers/DashboardComponent.jsx
@@ -24,7 +24,8 @@ const propTypes = {
handleComponentDrop: PropTypes.func.isRequired,
};
-function mapStateToProps({ dashboard = {} }, ownProps) {
+function mapStateToProps({ dashboard: undoableDashboard }, ownProps) {
+ const dashboard = undoableDashboard.present;
const { id, parentId } = ownProps;
const props = {
component: dashboard[id],
diff --git a/superset/assets/javascripts/dashboard/v2/containers/DashboardHeader.jsx b/superset/assets/javascripts/dashboard/v2/containers/DashboardHeader.jsx
index 1356057..52e7e7a 100644
--- a/superset/assets/javascripts/dashboard/v2/containers/DashboardHeader.jsx
+++ b/superset/assets/javascripts/dashboard/v2/containers/DashboardHeader.jsx
@@ -1,3 +1,4 @@
+import { ActionCreators as UndoActionCreators } from 'redux-undo'
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
@@ -9,9 +10,11 @@ import {
handleComponentDrop,
} from '../actions';
-function mapStateToProps({ dashboard }) {
+function mapStateToProps({ dashboard: undoableDashboard }) {
return {
- component: dashboard[DASHBOARD_HEADER_ID],
+ component: undoableDashboard.present[DASHBOARD_HEADER_ID],
+ canUndo: undoableDashboard.past.length > 0,
+ canRedo: undoableDashboard.future.length > 0,
};
}
@@ -19,6 +22,8 @@ function mapDispatchToProps(dispatch) {
return bindActionCreators({
updateComponents,
handleComponentDrop,
+ onUndo: UndoActionCreators.undo,
+ onRedo: UndoActionCreators.redo,
}, dispatch);
}
diff --git a/superset/assets/javascripts/dashboard/v2/reducers/index.js b/superset/assets/javascripts/dashboard/v2/reducers/index.js
index 103fda0..9c0575e 100644
--- a/superset/assets/javascripts/dashboard/v2/reducers/index.js
+++ b/superset/assets/javascripts/dashboard/v2/reducers/index.js
@@ -1,6 +1,13 @@
import { combineReducers } from 'redux';
+import undoable, { distinctState } from 'redux-undo';
+
import dashboard from './dashboard';
+const undoableDashboard = undoable(dashboard, {
+ limit: 10,
+ filter: distinctState(),
+});
+
export default combineReducers({
- dashboard,
+ dashboard: undoableDashboard,
});
diff --git a/superset/assets/package.json b/superset/assets/package.json
index d2a2022..cd6e9e3 100644
--- a/superset/assets/package.json
+++ b/superset/assets/package.json
@@ -107,6 +107,7 @@
"redux": "^3.5.2",
"redux-localstorage": "^0.4.1",
"redux-thunk": "^2.1.0",
+ "redux-undo": "^0.6.1",
"shortid": "^2.2.6",
"sprintf-js": "^1.1.1",
"srcdoc-polyfill": "^1.0.0",
--
To stop receiving notification emails like this one, please contact
ccwilliams@apache.org.