From 7ebaa5e25990ceeb939ccc8b313cbaa148b86ea0 Mon Sep 17 00:00:00 2001 From: Grace Guo Date: Wed, 29 Aug 2018 12:01:41 -0700 Subject: [PATCH 1/3] [dashboard] Update font style for markdown component (#5722) (cherry picked from commit 772ae77) --- .../dashboard/stylesheets/components/markdown.less | 11 +++++++++++ .../assets/src/dashboard/stylesheets/variables.less | 1 + 2 files changed, 12 insertions(+) diff --git a/superset/assets/src/dashboard/stylesheets/components/markdown.less b/superset/assets/src/dashboard/stylesheets/components/markdown.less index 87974d9ac669..44deeea20d63 100644 --- a/superset/assets/src/dashboard/stylesheets/components/markdown.less +++ b/superset/assets/src/dashboard/stylesheets/components/markdown.less @@ -1,6 +1,17 @@ .dashboard-markdown { overflow: hidden; + h4, h5 { + font-weight: 300; + } + h5 { + color: @gray-heading; + } + h6 { + font-weight: 400; + font-size: 12px; + } + .dashboard-component-chart-holder { overflow-y: auto; overflow-x: hidden; diff --git a/superset/assets/src/dashboard/stylesheets/variables.less b/superset/assets/src/dashboard/stylesheets/variables.less index 8f53f99a8a81..c062c57928b6 100644 --- a/superset/assets/src/dashboard/stylesheets/variables.less +++ b/superset/assets/src/dashboard/stylesheets/variables.less @@ -5,6 +5,7 @@ @gray: #879399; @gray-light: #CFD8DC; @gray-bg: #f5f5f5; +@gray-heading: #A3A3A3; @menu-hover: #F2F3F5; /* builder component pane */ From 9a72a348de89ddbcfcaee90f40cd4d6b1b970505 Mon Sep 17 00:00:00 2001 From: Grace Guo Date: Thu, 6 Sep 2018 10:23:56 -0700 Subject: [PATCH 2/3] [dashboard] Add alert on user delete root level tab (#5771) (cherry picked from commit 0c98ecb) --- .../components/gridComponents/Tab_spec.jsx | 18 +++--- .../assets/src/components/ModalTrigger.jsx | 11 ++-- .../components/DeleteComponentModal.jsx | 62 +++++++++++++++++++ .../components/gridComponents/Tab.jsx | 10 ++- .../components/menu/WithPopoverMenu.jsx | 23 +++---- .../src/dashboard/stylesheets/dashboard.less | 36 +++++++++-- 6 files changed, 131 insertions(+), 29 deletions(-) create mode 100644 superset/assets/src/dashboard/components/DeleteComponentModal.jsx diff --git a/superset/assets/spec/javascripts/dashboard/components/gridComponents/Tab_spec.jsx b/superset/assets/spec/javascripts/dashboard/components/gridComponents/Tab_spec.jsx index a984565b4c4f..fae59b2590e3 100644 --- a/superset/assets/spec/javascripts/dashboard/components/gridComponents/Tab_spec.jsx +++ b/superset/assets/spec/javascripts/dashboard/components/gridComponents/Tab_spec.jsx @@ -6,7 +6,7 @@ import { expect } from 'chai'; import sinon from 'sinon'; import DashboardComponent from '../../../../../src/dashboard/containers/DashboardComponent'; -import DeleteComponentButton from '../../../../../src/dashboard/components/DeleteComponentButton'; +import DeleteComponentModal from '../../../../../src/dashboard/components/DeleteComponentModal'; import DragDroppable from '../../../../../src/dashboard/components/dnd/DragDroppable'; import EditableTitle from '../../../../../src/components/EditableTitle'; import WithPopoverMenu from '../../../../../src/dashboard/components/menu/WithPopoverMenu'; @@ -86,14 +86,14 @@ describe('Tabs', () => { expect(wrapper.find(WithPopoverMenu)).to.have.length(1); }); - it('should render a DeleteComponentButton when focused if its not the only tab', () => { + it('should render a DeleteComponentModal when focused if its not the only tab', () => { let wrapper = setup(); wrapper.find(WithPopoverMenu).simulate('click'); // focus - expect(wrapper.find(DeleteComponentButton)).to.have.length(0); + expect(wrapper.find(DeleteComponentModal)).to.have.length(0); wrapper = setup({ editMode: true }); wrapper.find(WithPopoverMenu).simulate('click'); - expect(wrapper.find(DeleteComponentButton)).to.have.length(1); + expect(wrapper.find(DeleteComponentModal)).to.have.length(1); wrapper = setup({ editMode: true, @@ -103,16 +103,18 @@ describe('Tabs', () => { }, }); wrapper.find(WithPopoverMenu).simulate('click'); - expect(wrapper.find(DeleteComponentButton)).to.have.length(0); + expect(wrapper.find(DeleteComponentModal)).to.have.length(0); }); - it('should call deleteComponent when deleted', () => { + it('should show modal when clicked delete icon', () => { const deleteComponent = sinon.spy(); const wrapper = setup({ editMode: true, deleteComponent }); wrapper.find(WithPopoverMenu).simulate('click'); // focus - wrapper.find(DeleteComponentButton).simulate('click'); + wrapper.find('.icon-button').simulate('click'); - expect(deleteComponent.callCount).to.equal(1); + const modal = document.getElementsByClassName('modal'); + expect(modal).to.have.length(1); + expect(deleteComponent.callCount).to.equal(0); }); }); diff --git a/superset/assets/src/components/ModalTrigger.jsx b/superset/assets/src/components/ModalTrigger.jsx index 67a83e6c2162..83e8db361f3d 100644 --- a/superset/assets/src/components/ModalTrigger.jsx +++ b/superset/assets/src/components/ModalTrigger.jsx @@ -8,7 +8,7 @@ import Button from './Button'; const propTypes = { animation: PropTypes.bool, triggerNode: PropTypes.node.isRequired, - modalTitle: PropTypes.node.isRequired, + modalTitle: PropTypes.node, modalBody: PropTypes.node, // not required because it can be generated by beforeOpen modalFooter: PropTypes.node, beforeOpen: PropTypes.func, @@ -28,6 +28,7 @@ const defaultProps = { isMenuItem: false, bsSize: null, className: '', + modalTitle: '', }; export default class ModalTrigger extends React.Component { @@ -59,9 +60,11 @@ export default class ModalTrigger extends React.Component { bsSize={this.props.bsSize} className={this.props.className} > - - {this.props.modalTitle} - + {this.props.modalTitle && + + {this.props.modalTitle} + + } {this.props.modalBody} diff --git a/superset/assets/src/dashboard/components/DeleteComponentModal.jsx b/superset/assets/src/dashboard/components/DeleteComponentModal.jsx new file mode 100644 index 000000000000..ea7721c037e1 --- /dev/null +++ b/superset/assets/src/dashboard/components/DeleteComponentModal.jsx @@ -0,0 +1,62 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { Button } from 'react-bootstrap'; + +import ModalTrigger from '../../components/ModalTrigger'; +import { t } from '../../locales'; + +const propTypes = { + triggerNode: PropTypes.node.isRequired, + onDelete: PropTypes.func.isRequired, +}; + +export default class DeleteComponentModal extends React.PureComponent { + constructor(props) { + super(props); + + this.modal = null; + this.close = this.close.bind(this); + this.deleteTab = this.deleteTab.bind(this); + this.setModalRef = this.setModalRef.bind(this); + } + + setModalRef(ref) { + this.modal = ref; + } + + close() { + this.modal.close(); + } + + deleteTab() { + this.modal.close(); + this.props.onDelete(); + } + + render() { + return ( + +

{t('Delete dashboard tab?')}

+
+ Deleting a tab will remove all content within it. You may still + reverse this action with the undo button (cmd + z) until + you save your changes. +
+
+ + +
+ + } + /> + ); + } +} + +DeleteComponentModal.propTypes = propTypes; diff --git a/superset/assets/src/dashboard/components/gridComponents/Tab.jsx b/superset/assets/src/dashboard/components/gridComponents/Tab.jsx index b91d8089fd2f..dad3be4c72bb 100644 --- a/superset/assets/src/dashboard/components/gridComponents/Tab.jsx +++ b/superset/assets/src/dashboard/components/gridComponents/Tab.jsx @@ -4,7 +4,7 @@ import PropTypes from 'prop-types'; import DashboardComponent from '../../containers/DashboardComponent'; import DragDroppable from '../dnd/DragDroppable'; import EditableTitle from '../../../components/EditableTitle'; -import DeleteComponentButton from '../DeleteComponentButton'; +import DeleteComponentModal from '../DeleteComponentModal'; import WithPopoverMenu from '../menu/WithPopoverMenu'; import { componentShape } from '../../util/propShapes'; import { DASHBOARD_ROOT_DEPTH } from '../../util/constants'; @@ -178,6 +178,11 @@ export default class Tab extends React.PureComponent { renderTab() { const { isFocused } = this.state; const { component, parentComponent, index, depth, editMode } = this.props; + const deleteTabIcon = ( +
+ +
+ ); return ( , ] diff --git a/superset/assets/src/dashboard/components/menu/WithPopoverMenu.jsx b/superset/assets/src/dashboard/components/menu/WithPopoverMenu.jsx index 2a047ac573a1..f98b17e65036 100644 --- a/superset/assets/src/dashboard/components/menu/WithPopoverMenu.jsx +++ b/superset/assets/src/dashboard/components/menu/WithPopoverMenu.jsx @@ -20,7 +20,8 @@ const defaultProps = { onPressDelete() {}, menuItems: [], isFocused: false, - shouldFocus: (event, container) => container.contains(event.target), + shouldFocus: (event, container) => + container && container.contains(event.target), style: null, }; @@ -36,19 +37,19 @@ class WithPopoverMenu extends React.PureComponent { componentWillReceiveProps(nextProps) { if (nextProps.editMode && nextProps.isFocused && !this.state.isFocused) { - document.addEventListener('click', this.handleClick, true); - document.addEventListener('drag', this.handleClick, true); + document.addEventListener('click', this.handleClick); + document.addEventListener('drag', this.handleClick); this.setState({ isFocused: true }); } else if (this.state.isFocused && !nextProps.editMode) { - document.removeEventListener('click', this.handleClick, true); - document.removeEventListener('drag', this.handleClick, true); + document.removeEventListener('click', this.handleClick); + document.removeEventListener('drag', this.handleClick); this.setState({ isFocused: false }); } } componentWillUnmount() { - document.removeEventListener('click', this.handleClick, true); - document.removeEventListener('drag', this.handleClick, true); + document.removeEventListener('click', this.handleClick); + document.removeEventListener('drag', this.handleClick); } setRef(ref) { @@ -69,15 +70,15 @@ class WithPopoverMenu extends React.PureComponent { 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); - document.addEventListener('drag', this.handleClick, true); + document.addEventListener('click', this.handleClick); + document.addEventListener('drag', this.handleClick); this.setState(() => ({ isFocused: true })); if (onChangeFocus) { onChangeFocus(true); } } else if (!shouldFocus && this.state.isFocused) { - document.removeEventListener('click', this.handleClick, true); - document.removeEventListener('drag', this.handleClick, true); + document.removeEventListener('click', this.handleClick); + document.removeEventListener('drag', this.handleClick); this.setState(() => ({ isFocused: false })); if (onChangeFocus) { onChangeFocus(false); diff --git a/superset/assets/src/dashboard/stylesheets/dashboard.less b/superset/assets/src/dashboard/stylesheets/dashboard.less index 56f5d437745c..2b5242e87ac5 100644 --- a/superset/assets/src/dashboard/stylesheets/dashboard.less +++ b/superset/assets/src/dashboard/stylesheets/dashboard.less @@ -129,10 +129,38 @@ body { } } -.modal img.loading { - width: 50px; - margin: 0; - position: relative; +.modal { + img.loading { + width: 50px; + margin: 0; + position: relative; + } + + .modal-body { + padding: 24px 24px 29px 24px; + + div { + margin-top: 24px; + + &:first-child { + margin-top: 0; + } + } + } + + .delete-modal-actions-container { + .btn { + margin-right: 16px; + &:last-child { + margin-right: 0; + } + + &.btn-primary { + background: @pink !important; + border-color: @pink !important; + } + } + } } .react-bs-container-body { From 26c2f7cf4ca0922070f17bfacb7ece5fe30de63d Mon Sep 17 00:00:00 2001 From: Grace Guo Date: Tue, 11 Sep 2018 10:27:46 -0700 Subject: [PATCH 3/3] update dashboard sidepane title (#5850) (cherry picked from commit 965c838) --- .../assets/src/dashboard/components/BuilderComponentPane.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/superset/assets/src/dashboard/components/BuilderComponentPane.jsx b/superset/assets/src/dashboard/components/BuilderComponentPane.jsx index a21ec11de7ba..dd634c0a05b2 100644 --- a/superset/assets/src/dashboard/components/BuilderComponentPane.jsx +++ b/superset/assets/src/dashboard/components/BuilderComponentPane.jsx @@ -68,7 +68,7 @@ class BuilderComponentPane extends React.PureComponent { >
- {t('Insert')} + {t('Insert components')} - {t('All components')} + {t('Your charts and filters')}