From commits-return-850-archive-asf-public=cust-asf.ponee.io@superset.incubator.apache.org Wed Apr 4 20:40:24 2018 Return-Path: X-Original-To: archive-asf-public@cust-asf.ponee.io Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx-eu-01.ponee.io (Postfix) with SMTP id CE05D180677 for ; Wed, 4 Apr 2018 20:40:22 +0200 (CEST) Received: (qmail 47975 invoked by uid 500); 4 Apr 2018 18:40:22 -0000 Mailing-List: contact commits-help@superset.incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@superset.incubator.apache.org Delivered-To: mailing list commits@superset.incubator.apache.org Received: (qmail 47935 invoked by uid 99); 4 Apr 2018 18:40:21 -0000 Received: from ec2-52-202-80-70.compute-1.amazonaws.com (HELO gitbox.apache.org) (52.202.80.70) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 04 Apr 2018 18:40:21 +0000 Received: by gitbox.apache.org (ASF Mail Server at gitbox.apache.org, from userid 33) id 4927780856; Wed, 4 Apr 2018 18:40:21 +0000 (UTC) Date: Wed, 04 Apr 2018 18:40:21 +0000 To: "commits@superset.apache.org" Subject: [incubator-superset] 01/02: [edit mode] add edit mode to redux and propogate to all s MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit From: ccwilliams@apache.org In-Reply-To: <152286722090.6132.7760727316490539135@gitbox.apache.org> References: <152286722090.6132.7760727316490539135@gitbox.apache.org> X-Git-Host: gitbox.apache.org X-Git-Repo: incubator-superset X-Git-Refname: refs/heads/chris--grid-root-and-spacer X-Git-Reftype: branch X-Git-Rev: 1a4bc3172d0b992c91b6ef9b05af83fcbd1f7e8d X-Git-NotificationType: diff X-Git-Multimail-Version: 1.5.dev Auto-Submitted: auto-generated Message-Id: <20180404184021.4927780856@gitbox.apache.org> This is an automated email from the ASF dual-hosted git repository. ccwilliams pushed a commit to branch chris--grid-root-and-spacer in repository https://gitbox.apache.org/repos/asf/incubator-superset.git commit 1a4bc3172d0b992c91b6ef9b05af83fcbd1f7e8d Author: Chris Williams AuthorDate: Tue Apr 3 15:56:07 2018 -0700 [edit mode] add edit mode to redux and propogate to all s --- superset/assets/javascripts/dashboard/index.jsx | 1 + .../javascripts/dashboard/v2/actions/editMode.js | 9 ++++++ .../dashboard/v2/components/DashboardBuilder.jsx | 16 ++++++---- .../dashboard/v2/components/DashboardGrid.jsx | 10 +++--- .../dashboard/v2/components/DashboardHeader.jsx | 10 +++--- .../dashboard/v2/components/dnd/DragDroppable.jsx | 4 +++ .../v2/components/gridComponents/Chart.jsx | 17 ++++++---- .../v2/components/gridComponents/Column.jsx | 22 ++++++++----- .../v2/components/gridComponents/Divider.jsx | 10 ++++-- .../v2/components/gridComponents/Header.jsx | 13 +++++--- .../dashboard/v2/components/gridComponents/Row.jsx | 21 +++++++----- .../dashboard/v2/components/gridComponents/Tab.jsx | 6 +++- .../v2/components/gridComponents/Tabs.jsx | 25 +++++++++------ .../gridComponents/new/DraggableNewComponent.jsx | 1 + .../v2/components/menu/WithPopoverMenu.jsx | 37 ++++++++++++++-------- .../v2/components/resizable/ResizableContainer.jsx | 14 ++++++-- .../dashboard/v2/containers/DashboardBuilder.jsx | 3 +- .../dashboard/v2/containers/DashboardComponent.jsx | 3 +- .../dashboard/v2/containers/DashboardGrid.jsx | 2 +- .../dashboard/v2/containers/DashboardHeader.jsx | 6 +++- .../javascripts/dashboard/v2/reducers/editMode.js | 11 +++++++ .../javascripts/dashboard/v2/reducers/index.js | 2 ++ .../dashboard/v2/stylesheets/builder.less | 6 ++-- .../dashboard/v2/stylesheets/components/chart.less | 4 +-- .../v2/stylesheets/components/column.less | 17 ++++++++++ .../v2/stylesheets/components/divider.less | 2 +- .../dashboard/v2/stylesheets/components/row.less | 18 +++++++++++ .../javascripts/dashboard/v2/stylesheets/grid.less | 24 +++----------- 28 files changed, 211 insertions(+), 103 deletions(-) diff --git a/superset/assets/javascripts/dashboard/index.jsx b/superset/assets/javascripts/dashboard/index.jsx index 926f6b2..f7471f5 100644 --- a/superset/assets/javascripts/dashboard/index.jsx +++ b/superset/assets/javascripts/dashboard/index.jsx @@ -25,6 +25,7 @@ const initState = { present: emptyDashboardLayout, future: [], }, + editMode: true, }; const store = createStore( diff --git a/superset/assets/javascripts/dashboard/v2/actions/editMode.js b/superset/assets/javascripts/dashboard/v2/actions/editMode.js new file mode 100644 index 0000000..0a849ea --- /dev/null +++ b/superset/assets/javascripts/dashboard/v2/actions/editMode.js @@ -0,0 +1,9 @@ +export const SET_EDIT_MODE = 'SET_EDIT_MODE'; +export function setEditMode(editMode) { + return { + type: SET_EDIT_MODE, + payload: { + editMode, + }, + }; +} diff --git a/superset/assets/javascripts/dashboard/v2/components/DashboardBuilder.jsx b/superset/assets/javascripts/dashboard/v2/components/DashboardBuilder.jsx index 2a0bfe7..fc938b1 100644 --- a/superset/assets/javascripts/dashboard/v2/components/DashboardBuilder.jsx +++ b/superset/assets/javascripts/dashboard/v2/components/DashboardBuilder.jsx @@ -1,3 +1,4 @@ +import cx from 'classnames'; import React from 'react'; import PropTypes from 'prop-types'; import HTML5Backend from 'react-dnd-html5-backend'; @@ -18,11 +19,10 @@ import { } from '../util/constants'; const propTypes = { - editMode: PropTypes.bool, - // redux dashboardLayout: PropTypes.object.isRequired, deleteTopLevelTabs: PropTypes.func.isRequired, + editMode: PropTypes.bool.isRequired, handleComponentDrop: PropTypes.func.isRequired, }; @@ -52,7 +52,7 @@ class DashboardBuilder extends React.Component { render() { const { tabIndex } = this.state; - const { handleComponentDrop, dashboardLayout, deleteTopLevelTabs } = this.props; + const { handleComponentDrop, dashboardLayout, deleteTopLevelTabs, editMode } = this.props; const dashboardRoot = dashboardLayout[DASHBOARD_ROOT_ID]; const rootChildId = dashboardRoot.children[0]; const topLevelTabs = rootChildId !== DASHBOARD_GRID_ID && dashboardLayout[rootChildId]; @@ -64,8 +64,8 @@ class DashboardBuilder extends React.Component { const gridComponent = dashboardLayout[gridComponentId]; return ( -
- {topLevelTabs ? ( // you cannot drop on/displace tabs if they already exist +
+ {topLevelTabs || !editMode ? ( // you cannot drop on/displace tabs if they already exist ) : ( {({ dropIndicatorProps }) => (
@@ -94,6 +95,7 @@ class DashboardBuilder extends React.Component { onClick={deleteTopLevelTabs} />, ]} + editMode={editMode} > } -
+
- + {editMode && }
); diff --git a/superset/assets/javascripts/dashboard/v2/components/DashboardGrid.jsx b/superset/assets/javascripts/dashboard/v2/components/DashboardGrid.jsx index cfe99c7..9f4cb93 100644 --- a/superset/assets/javascripts/dashboard/v2/components/DashboardGrid.jsx +++ b/superset/assets/javascripts/dashboard/v2/components/DashboardGrid.jsx @@ -13,6 +13,7 @@ import { const propTypes = { depth: PropTypes.number.isRequired, + editMode: PropTypes.bool.isRequired, gridComponent: componentShape.isRequired, handleComponentDrop: PropTypes.func.isRequired, resizeComponent: PropTypes.func.isRequired, @@ -70,7 +71,7 @@ class DashboardGrid extends React.PureComponent { } render() { - const { gridComponent, handleComponentDrop, depth } = this.props; + const { gridComponent, handleComponentDrop, depth, editMode } = this.props; const { isResizing, rowGuideTop } = this.state; return ( @@ -99,18 +100,19 @@ class DashboardGrid extends React.PureComponent { ))} {/* render an empty drop target */} - {gridComponent.children.length === 0 && + {editMode && {({ dropIndicatorProps }) => dropIndicatorProps && -
} +
} } {isResizing && Array(GRID_COLUMN_COUNT).fill(null).map((_, i) => ( diff --git a/superset/assets/javascripts/dashboard/v2/components/DashboardHeader.jsx b/superset/assets/javascripts/dashboard/v2/components/DashboardHeader.jsx index 2c89f33..ca204e5 100644 --- a/superset/assets/javascripts/dashboard/v2/components/DashboardHeader.jsx +++ b/superset/assets/javascripts/dashboard/v2/components/DashboardHeader.jsx @@ -7,8 +7,7 @@ import { componentShape } from '../util/propShapes'; import EditableTitle from '../../../components/EditableTitle'; const propTypes = { - // editMode: PropTypes.bool.isRequired, - // setEditMode: PropTypes.func.isRequired, + editMode: PropTypes.bool.isRequired, component: componentShape.isRequired, // redux @@ -17,6 +16,7 @@ const propTypes = { onRedo: PropTypes.func.isRequired, canUndo: PropTypes.bool.isRequired, canRedo: PropTypes.bool.isRequired, + setEditMode: PropTypes.func.isRequired, }; class DashboardHeader extends React.Component { @@ -27,8 +27,7 @@ class DashboardHeader extends React.Component { } toggleEditMode() { - console.log('@TODO toggleEditMode'); - // this.props.setEditMode(!this.props.editMode); + this.props.setEditMode(!this.props.editMode); } handleChangeText(nextText) { @@ -47,8 +46,7 @@ class DashboardHeader extends React.Component { } render() { - const { component, onUndo, onRedo, canUndo, canRedo } = this.props; - const editMode = true; + const { component, onUndo, onRedo, canUndo, canRedo, editMode } = this.props; return (
diff --git a/superset/assets/javascripts/dashboard/v2/components/dnd/DragDroppable.jsx b/superset/assets/javascripts/dashboard/v2/components/dnd/DragDroppable.jsx index 89664e5..775e092 100644 --- a/superset/assets/javascripts/dashboard/v2/components/dnd/DragDroppable.jsx +++ b/superset/assets/javascripts/dashboard/v2/components/dnd/DragDroppable.jsx @@ -18,6 +18,7 @@ const propTypes = { index: PropTypes.number.isRequired, style: PropTypes.object, onDrop: PropTypes.func, + editMode: PropTypes.bool.isRequired, // from react-dnd isDragging: PropTypes.bool.isRequired, @@ -70,8 +71,11 @@ class DragDroppable extends React.Component { isDragging, isDraggingOver, style, + editMode, } = this.props; + if (!editMode) return children({}); + const { dropIndicator } = this.state; return ( diff --git a/superset/assets/javascripts/dashboard/v2/components/gridComponents/Chart.jsx b/superset/assets/javascripts/dashboard/v2/components/gridComponents/Chart.jsx index 7ca506d..668d268 100644 --- a/superset/assets/javascripts/dashboard/v2/components/gridComponents/Chart.jsx +++ b/superset/assets/javascripts/dashboard/v2/components/gridComponents/Chart.jsx @@ -9,10 +9,7 @@ import ResizableContainer from '../resizable/ResizableContainer'; import WithPopoverMenu from '../menu/WithPopoverMenu'; import { componentShape } from '../../util/propShapes'; import { ROW_TYPE } from '../../util/componentTypes'; -import { - GRID_MIN_COLUMN_COUNT, - GRID_MIN_ROW_UNITS, -} from '../../util/constants'; +import { GRID_MIN_COLUMN_COUNT, GRID_MIN_ROW_UNITS } from '../../util/constants'; const propTypes = { id: PropTypes.string.isRequired, @@ -21,6 +18,7 @@ const propTypes = { parentComponent: componentShape.isRequired, index: PropTypes.number.isRequired, depth: PropTypes.number.isRequired, + editMode: PropTypes.bool.isRequired, // grid related availableColumnCount: PropTypes.number.isRequired, @@ -71,6 +69,7 @@ class Chart extends React.Component { onResize, onResizeStop, handleComponentDrop, + editMode, } = this.props; return ( @@ -82,6 +81,7 @@ class Chart extends React.Component { depth={depth} onDrop={handleComponentDrop} disableDragDrop={isFocused} + editMode={editMode} > {({ dropIndicatorProps, dragSourceRef }) => ( - - - + {editMode && + + + } , ]} + editMode={editMode} >
diff --git a/superset/assets/javascripts/dashboard/v2/components/gridComponents/Column.jsx b/superset/assets/javascripts/dashboard/v2/components/gridComponents/Column.jsx index bf33710..fe5a721 100644 --- a/superset/assets/javascripts/dashboard/v2/components/gridComponents/Column.jsx +++ b/superset/assets/javascripts/dashboard/v2/components/gridComponents/Column.jsx @@ -24,6 +24,7 @@ const propTypes = { parentComponent: componentShape.isRequired, index: PropTypes.number.isRequired, depth: PropTypes.number.isRequired, + editMode: PropTypes.bool.isRequired, // grid related availableColumnCount: PropTypes.number.isRequired, @@ -90,6 +91,7 @@ class Column extends React.PureComponent { onResize, onResizeStop, handleComponentDrop, + editMode, } = this.props; const columnItems = columnComponent.children || []; @@ -105,6 +107,7 @@ class Column extends React.PureComponent { index={index} depth={depth} onDrop={handleComponentDrop} + editMode={editMode} > {({ dropIndicatorProps, dragSourceRef }) => ( , ]} + editMode={editMode} >
- - - - - + {editMode && + + + + + } {columnItems.map((componentId, itemIndex) => ( {({ dropIndicatorProps, dragSourceRef }) => (
- - - + {editMode && + + + }
diff --git a/superset/assets/javascripts/dashboard/v2/components/gridComponents/Header.jsx b/superset/assets/javascripts/dashboard/v2/components/gridComponents/Header.jsx index d8744d6..594cf6b 100644 --- a/superset/assets/javascripts/dashboard/v2/components/gridComponents/Header.jsx +++ b/superset/assets/javascripts/dashboard/v2/components/gridComponents/Header.jsx @@ -22,6 +22,7 @@ const propTypes = { depth: PropTypes.number.isRequired, parentComponent: componentShape.isRequired, index: PropTypes.number.isRequired, + editMode: PropTypes.bool.isRequired, // redux handleComponentDrop: PropTypes.func.isRequired, @@ -79,6 +80,7 @@ class Header extends React.PureComponent { parentComponent, index, handleComponentDrop, + editMode, } = this.props; const headerStyle = headerStyleOptions.find( @@ -98,12 +100,14 @@ class Header extends React.PureComponent { depth={depth} onDrop={handleComponentDrop} disableDragDrop={isFocused} + editMode={editMode} > {({ dropIndicatorProps, dragSourceRef }) => (
- - - + {editMode && + + + } , , ]} + editMode={editMode} >
diff --git a/superset/assets/javascripts/dashboard/v2/components/gridComponents/Row.jsx b/superset/assets/javascripts/dashboard/v2/components/gridComponents/Row.jsx index 99296dd..9866bc8 100644 --- a/superset/assets/javascripts/dashboard/v2/components/gridComponents/Row.jsx +++ b/superset/assets/javascripts/dashboard/v2/components/gridComponents/Row.jsx @@ -22,6 +22,7 @@ const propTypes = { parentComponent: componentShape.isRequired, index: PropTypes.number.isRequired, depth: PropTypes.number.isRequired, + editMode: PropTypes.bool.isRequired, // grid related availableColumnCount: PropTypes.number.isRequired, @@ -90,6 +91,7 @@ class Row extends React.PureComponent { onResize, onResizeStop, handleComponentDrop, + editMode, } = this.props; const rowItems = rowComponent.children || []; @@ -106,6 +108,7 @@ class Row extends React.PureComponent { index={index} depth={depth} onDrop={handleComponentDrop} + editMode={editMode} > {({ dropIndicatorProps, dragSourceRef }) => ( , ]} + editMode={editMode} >
- - - - - + {editMode && + + + + + } {rowItems.map((componentId, itemIndex) => ( {({ dropIndicatorProps, dragSourceRef }) => (
@@ -149,10 +152,11 @@ export default class Tab extends React.PureComponent { menuItems={parentComponent.children.length <= 1 ? [] : [ , ]} + editMode={editMode} > diff --git a/superset/assets/javascripts/dashboard/v2/components/gridComponents/Tabs.jsx b/superset/assets/javascripts/dashboard/v2/components/gridComponents/Tabs.jsx index f76fa19..1f5f0c6 100644 --- a/superset/assets/javascripts/dashboard/v2/components/gridComponents/Tabs.jsx +++ b/superset/assets/javascripts/dashboard/v2/components/gridComponents/Tabs.jsx @@ -22,7 +22,8 @@ const propTypes = { parentComponent: componentShape.isRequired, index: PropTypes.number.isRequired, depth: PropTypes.number.isRequired, - renderTabContent: PropTypes.bool, + renderTabContent: PropTypes.bool, // whether to render tabs + content or just tabs + editMode: PropTypes.bool.isRequired, // grid related availableColumnCount: PropTypes.number, @@ -130,6 +131,7 @@ class Tabs extends React.PureComponent { onResizeStop, handleComponentDrop, renderTabContent, + editMode, } = this.props; const { tabIndex: selectedTabIndex } = this.state; @@ -143,13 +145,15 @@ class Tabs extends React.PureComponent { index={index} depth={depth} onDrop={handleComponentDrop} + editMode={editMode} > {({ dropIndicatorProps: tabsDropIndicatorProps, dragSourceRef: tabsDragSourceRef }) => (
- - - - + {editMode && + + + + } ))} - {tabIds.length < MAX_TAB_COUNT && - } - />} + {editMode && + tabIds.length < MAX_TAB_COUNT && + } + />} diff --git a/superset/assets/javascripts/dashboard/v2/components/gridComponents/new/DraggableNewComponent.jsx b/superset/assets/javascripts/dashboard/v2/components/gridComponents/new/DraggableNewComponent.jsx index 778f58e..eebd6e0 100644 --- a/superset/assets/javascripts/dashboard/v2/components/gridComponents/new/DraggableNewComponent.jsx +++ b/superset/assets/javascripts/dashboard/v2/components/gridComponents/new/DraggableNewComponent.jsx @@ -26,6 +26,7 @@ export default class DraggableNewComponent extends React.PureComponent { parentComponent={{ id: NEW_COMPONENTS_SOURCE_ID, type: NEW_COMPONENT_SOURCE_TYPE }} index={0} depth={0} + editMode > {({ dragSourceRef }) => (
diff --git a/superset/assets/javascripts/dashboard/v2/components/menu/WithPopoverMenu.jsx b/superset/assets/javascripts/dashboard/v2/components/menu/WithPopoverMenu.jsx index a1d4c0e..f213442 100644 --- a/superset/assets/javascripts/dashboard/v2/components/menu/WithPopoverMenu.jsx +++ b/superset/assets/javascripts/dashboard/v2/components/menu/WithPopoverMenu.jsx @@ -9,6 +9,7 @@ const propTypes = { onChangeFocus: PropTypes.func, isFocused: PropTypes.bool, shouldFocus: PropTypes.func, + editMode: PropTypes.bool.isRequired, }; const defaultProps = { @@ -32,10 +33,14 @@ class WithPopoverMenu extends React.PureComponent { } componentWillReceiveProps(nextProps) { - if (nextProps.isFocused && !this.state.isFocused) { + if (nextProps.editMode && nextProps.isFocused && !this.state.isFocused) { document.addEventListener('click', this.handleClick, true); document.addEventListener('drag', this.handleClick, true); this.setState({ isFocused: true }); + } else if (this.state.isFocused && !nextProps.editMode) { + document.removeEventListener('click', this.handleClick, true); + document.removeEventListener('drag', this.handleClick, true); + this.setState({ isFocused: false }); } } @@ -49,10 +54,14 @@ class WithPopoverMenu extends React.PureComponent { } handleClick(event) { - const { onChangeFocus, shouldFocus: shouldFocusThunk } = this.props; - const shouldFocus = shouldFocusThunk(event, this.container); + const { onChangeFocus, shouldFocus: shouldFocusFunc, disableClick, editMode } = this.props; + const shouldFocus = shouldFocusFunc(event, this.container); + + if (!editMode) { + return; + } - if (shouldFocus && !this.state.isFocused) { + if (!disableClick && shouldFocus && !this.state.isFocused) { // if not focused, set focus and add a window event listener to capture outside clicks // this enables us to not set a click listener for ever item on a dashboard document.addEventListener('click', this.handleClick, true); @@ -72,26 +81,28 @@ class WithPopoverMenu extends React.PureComponent { } render() { - const { children, menuItems, disableClick } = this.props; + const { children, menuItems, editMode } = this.props; const { isFocused } = this.state; return (
{children} - {isFocused && menuItems.length ? -
- {menuItems.map((node, i) => ( -
{node}
- ))} -
: null} + {editMode && + isFocused && + menuItems.length > 0 && +
+ {menuItems.map((node, i) => ( +
{node}
+ ))} +
}
); } diff --git a/superset/assets/javascripts/dashboard/v2/components/resizable/ResizableContainer.jsx b/superset/assets/javascripts/dashboard/v2/components/resizable/ResizableContainer.jsx index 0b1e975..a532ff0 100644 --- a/superset/assets/javascripts/dashboard/v2/components/resizable/ResizableContainer.jsx +++ b/superset/assets/javascripts/dashboard/v2/components/resizable/ResizableContainer.jsx @@ -28,6 +28,7 @@ const propTypes = { onResizeStop: PropTypes.func, onResize: PropTypes.func, onResizeStart: PropTypes.func, + editMode: PropTypes.bool.isRequired, }; const defaultProps = { @@ -101,9 +102,9 @@ class ResizableContainer extends React.PureComponent { if (onResizeStop) { const nextWidthMultiple = - widthMultiple + Math.floor(delta.width / (widthStep + gutterWidth)); + widthMultiple + Math.round(delta.width / (widthStep + gutterWidth)); const nextHeightMultiple = - heightMultiple + Math.ceil(delta.height / heightStep); + heightMultiple + Math.round(delta.height / heightStep); onResizeStop({ id, @@ -133,6 +134,7 @@ class ResizableContainer extends React.PureComponent { minHeightMultiple, maxHeightMultiple, gutterWidth, + editMode, } = this.props; const size = { @@ -148,6 +150,14 @@ class ResizableContainer extends React.PureComponent { || undefined, }; + if (!editMode) { + return ( +
+ {children} +
+ ); + } + let enableConfig = resizableConfig.notAdjustable; if (adjustableWidth && adjustableHeight) enableConfig = resizableConfig.widthAndHeight; else if (adjustableWidth) enableConfig = resizableConfig.widthOnly; diff --git a/superset/assets/javascripts/dashboard/v2/containers/DashboardBuilder.jsx b/superset/assets/javascripts/dashboard/v2/containers/DashboardBuilder.jsx index 7ed5bfc..b8d717e 100644 --- a/superset/assets/javascripts/dashboard/v2/containers/DashboardBuilder.jsx +++ b/superset/assets/javascripts/dashboard/v2/containers/DashboardBuilder.jsx @@ -7,9 +7,10 @@ import { handleComponentDrop, } from '../actions/dashboardLayout'; -function mapStateToProps({ dashboardLayout: undoableLayout }) { +function mapStateToProps({ dashboardLayout: undoableLayout, editMode }) { return { dashboardLayout: undoableLayout.present, + editMode, }; } diff --git a/superset/assets/javascripts/dashboard/v2/containers/DashboardComponent.jsx b/superset/assets/javascripts/dashboard/v2/containers/DashboardComponent.jsx index 7af3f5f..add5a6d 100644 --- a/superset/assets/javascripts/dashboard/v2/containers/DashboardComponent.jsx +++ b/superset/assets/javascripts/dashboard/v2/containers/DashboardComponent.jsx @@ -25,13 +25,14 @@ const propTypes = { handleComponentDrop: PropTypes.func.isRequired, }; -function mapStateToProps({ dashboardLayout: undoableLayout, selectedTabs }, ownProps) { +function mapStateToProps({ dashboardLayout: undoableLayout, editMode }, ownProps) { const dashboardLayout = undoableLayout.present; const { id, parentId } = ownProps; const component = dashboardLayout[id]; const props = { component, parentComponent: dashboardLayout[parentId], + editMode, }; // rows and columns need more data about their child dimensions diff --git a/superset/assets/javascripts/dashboard/v2/containers/DashboardGrid.jsx b/superset/assets/javascripts/dashboard/v2/containers/DashboardGrid.jsx index ddb2fc0..67b2396 100644 --- a/superset/assets/javascripts/dashboard/v2/containers/DashboardGrid.jsx +++ b/superset/assets/javascripts/dashboard/v2/containers/DashboardGrid.jsx @@ -14,4 +14,4 @@ function mapDispatchToProps(dispatch) { }, dispatch); } -export default connect(null, mapDispatchToProps)(DashboardGrid); +export default connect(({ editMode }) => ({ editMode }), mapDispatchToProps)(DashboardGrid); diff --git a/superset/assets/javascripts/dashboard/v2/containers/DashboardHeader.jsx b/superset/assets/javascripts/dashboard/v2/containers/DashboardHeader.jsx index 985f9ee..8855d2c 100644 --- a/superset/assets/javascripts/dashboard/v2/containers/DashboardHeader.jsx +++ b/superset/assets/javascripts/dashboard/v2/containers/DashboardHeader.jsx @@ -10,11 +10,14 @@ import { handleComponentDrop, } from '../actions/dashboardLayout'; -function mapStateToProps({ dashboardLayout: undoableLayout }) { +import { setEditMode } from '../actions/editMode'; + +function mapStateToProps({ dashboardLayout: undoableLayout, editMode }) { return { component: undoableLayout.present[DASHBOARD_HEADER_ID], canUndo: undoableLayout.past.length > 0, canRedo: undoableLayout.future.length > 0, + editMode, }; } @@ -24,6 +27,7 @@ function mapDispatchToProps(dispatch) { handleComponentDrop, onUndo: UndoActionCreators.undo, onRedo: UndoActionCreators.redo, + setEditMode, }, dispatch); } diff --git a/superset/assets/javascripts/dashboard/v2/reducers/editMode.js b/superset/assets/javascripts/dashboard/v2/reducers/editMode.js new file mode 100644 index 0000000..b1a1630 --- /dev/null +++ b/superset/assets/javascripts/dashboard/v2/reducers/editMode.js @@ -0,0 +1,11 @@ +import { SET_EDIT_MODE } from '../actions/editMode'; + +export default function editModeReducer(editMode = false, action) { + switch (action.type) { + case SET_EDIT_MODE: + return action.payload.editMode; + + default: + return editMode; + } +} diff --git a/superset/assets/javascripts/dashboard/v2/reducers/index.js b/superset/assets/javascripts/dashboard/v2/reducers/index.js index 994a1df..b824e9a 100644 --- a/superset/assets/javascripts/dashboard/v2/reducers/index.js +++ b/superset/assets/javascripts/dashboard/v2/reducers/index.js @@ -2,6 +2,7 @@ import { combineReducers } from 'redux'; import undoable, { distinctState } from 'redux-undo'; import dashboardLayout from './dashboardLayout'; +import editMode from './editMode'; const undoableLayout = undoable(dashboardLayout, { limit: 15, @@ -10,4 +11,5 @@ const undoableLayout = undoable(dashboardLayout, { export default combineReducers({ dashboardLayout: undoableLayout, + editMode, }); diff --git a/superset/assets/javascripts/dashboard/v2/stylesheets/builder.less b/superset/assets/javascripts/dashboard/v2/stylesheets/builder.less index 206d63b..3651c57 100644 --- a/superset/assets/javascripts/dashboard/v2/stylesheets/builder.less +++ b/superset/assets/javascripts/dashboard/v2/stylesheets/builder.less @@ -14,7 +14,7 @@ box-shadow: 0 4px 4px 0 rgba(0, 0, 0, 0.1); /* @TODO color */ } -.dashboard-builder { +.dashboard-content { display: flex; flex-direction: row; flex-wrap: nowrap; @@ -32,12 +32,12 @@ padding-left: 8px; /* note this is added to tab-level padding, to match header */ } -.dashboard-builder .grid-container .dashboard-component-tabs { +.dashboard-content .grid-container .dashboard-component-tabs { box-shadow: none; padding-left: 0; } -.dashboard-builder > div:first-child { +.dashboard-content > div:first-child { width: 100%; flex-grow: 1; position: relative; diff --git a/superset/assets/javascripts/dashboard/v2/stylesheets/components/chart.less b/superset/assets/javascripts/dashboard/v2/stylesheets/components/chart.less index 2bdf3cc..141c3e9 100644 --- a/superset/assets/javascripts/dashboard/v2/stylesheets/components/chart.less +++ b/superset/assets/javascripts/dashboard/v2/stylesheets/components/chart.less @@ -14,8 +14,6 @@ opacity: 0.3; } -.grid-container--resizing .dashboard-component-chart, -.dashboard-builder--dragging .dashboard-component-chart, -.dashboard-component-chart:hover { +.dashboard-v2--editing .dashboard-component-chart:hover { box-shadow: inset 0 0 0 1px @gray-light; } diff --git a/superset/assets/javascripts/dashboard/v2/stylesheets/components/column.less b/superset/assets/javascripts/dashboard/v2/stylesheets/components/column.less index caf31e7..9565112 100644 --- a/superset/assets/javascripts/dashboard/v2/stylesheets/components/column.less +++ b/superset/assets/javascripts/dashboard/v2/stylesheets/components/column.less @@ -2,10 +2,27 @@ width: 100%; } +/* gutters between elements in a column */ .grid-column > :not(:only-child):not(.hover-menu):not(:last-child) { margin-bottom: 16px; } +.dashboard-v2--editing .grid-column:after { + border: 1px dashed transparent; + content: ""; + position: absolute; + width: 100%; + height: 100%; + top: 1px; + left: 0; + z-index: 1; + pointer-events: none; +} + +.dashboard-v2--editing .grid-column:hover:after { + border: 1px solid @gray-light; +} + .grid-column > .hover-menu--top { top: -20px; } diff --git a/superset/assets/javascripts/dashboard/v2/stylesheets/components/divider.less b/superset/assets/javascripts/dashboard/v2/stylesheets/components/divider.less index f1d3d86..9347a4e 100644 --- a/superset/assets/javascripts/dashboard/v2/stylesheets/components/divider.less +++ b/superset/assets/javascripts/dashboard/v2/stylesheets/components/divider.less @@ -1,6 +1,6 @@ .dashboard-component-divider { width: 100%; - padding: 24px 0; /* this is padding not margin to enable a larger mouse target */ + padding: 16px 0; /* this is padding not margin to enable a larger mouse target */ background-color: transparent; } diff --git a/superset/assets/javascripts/dashboard/v2/stylesheets/components/row.less b/superset/assets/javascripts/dashboard/v2/stylesheets/components/row.less index 30f14b8..956966d 100644 --- a/superset/assets/javascripts/dashboard/v2/stylesheets/components/row.less +++ b/superset/assets/javascripts/dashboard/v2/stylesheets/components/row.less @@ -7,10 +7,28 @@ height: fit-content; } +/* gutters between elements in a row */ .grid-row > :not(:only-child):not(:last-child):not(.hover-menu) { margin-right: 16px; } +/* hover indicator */ +.dashboard-v2--editing .grid-row:after { + border: 1px dashed transparent; + content: ""; + position: absolute; + width: 100%; + height: 100%; + top: 1px; + left: 0; + z-index: 1; + pointer-events: none; +} + +.dashboard-v2--editing .grid-row:hover:after { + border: 1px solid @gray-light; +} + .grid-row.grid-row--empty { align-items: center; /* this centers the empty note content */ height: 80px; diff --git a/superset/assets/javascripts/dashboard/v2/stylesheets/grid.less b/superset/assets/javascripts/dashboard/v2/stylesheets/grid.less index 7c55dee..45b8a42 100644 --- a/superset/assets/javascripts/dashboard/v2/stylesheets/grid.less +++ b/superset/assets/javascripts/dashboard/v2/stylesheets/grid.less @@ -9,6 +9,11 @@ flex-direction: column; } +/* gutters between rows */ +.grid-content > div:not(:only-child):not(:last-child):not(.empty-grid-droptarget) { + margin-bottom: 16px; +} + .empty-grid-droptarget { width: 100%; height: 100%; @@ -33,22 +38,3 @@ pointer-events: none; z-index: 10; } - - -.grid-container .grid-row:after, -.grid-container .grid-column:after { - border: 1px dashed transparent; - content: ""; - position: absolute; - width: 100%; - height: 100%; - top: 1px; - left: 0; - z-index: 1; - pointer-events: none; -} - -.grid-container .grid-row:hover:after, -.grid-container .grid-column:hover:after { - border: 1px solid @gray-light; -} -- To stop receiving notification emails like this one, please contact ccwilliams@apache.org.