You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@superset.apache.org by GitBox <gi...@apache.org> on 2018/04/02 21:59:10 UTC

[GitHub] graceguo-supercat closed pull request #4738: [SqlLab] 1-click tab closing in SqlLab

graceguo-supercat closed pull request #4738: [SqlLab] 1-click tab closing in SqlLab
URL: https://github.com/apache/incubator-superset/pull/4738
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/superset/assets/javascripts/SqlLab/components/TabStatusIcon.jsx b/superset/assets/javascripts/SqlLab/components/TabStatusIcon.jsx
new file mode 100644
index 0000000000..33f86469d9
--- /dev/null
+++ b/superset/assets/javascripts/SqlLab/components/TabStatusIcon.jsx
@@ -0,0 +1,42 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+
+const propTypes = {
+  onClose: PropTypes.func.isRequired,
+  tabState: PropTypes.string.isRequired,
+};
+
+class TabStatusIcon extends React.Component {
+  constructor(props) {
+    super(props);
+    this.onMouseOver = this.onMouseOver.bind(this);
+    this.onMouseOut = this.onMouseOut.bind(this);
+
+    this.state = { isHovered: false };
+  }
+
+  onMouseOver() {
+    this.setState({ isHovered: true });
+  }
+
+  onMouseOut() {
+    this.setState({ isHovered: false });
+  }
+
+  render() {
+    return (
+      <span
+        onMouseOver={this.onMouseOver}
+        onMouseOut={this.onMouseOut}
+        onClick={this.props.onClose}
+      >
+        <div className={'circle ' + this.props.tabState}>
+          {this.state.isHovered ? '×' : null}
+        </div>
+      </span>
+    );
+  }
+}
+
+TabStatusIcon.propTypes = propTypes;
+export default TabStatusIcon;
diff --git a/superset/assets/javascripts/SqlLab/components/TabbedSqlEditors.jsx b/superset/assets/javascripts/SqlLab/components/TabbedSqlEditors.jsx
index c890b5bf6e..b9acc160d5 100644
--- a/superset/assets/javascripts/SqlLab/components/TabbedSqlEditors.jsx
+++ b/superset/assets/javascripts/SqlLab/components/TabbedSqlEditors.jsx
@@ -10,6 +10,7 @@ import SqlEditor from './SqlEditor';
 import CopyQueryTabUrl from './CopyQueryTabUrl';
 import { areArraysShallowEqual } from '../../reduxUtils';
 import { t } from '../../locales';
+import TabStatusIcon from './TabStatusIcon';
 
 const propTypes = {
   actions: PropTypes.object.isRequired,
@@ -160,7 +161,7 @@ class TabbedSqlEditors extends React.PureComponent {
 
       const tabTitle = (
         <div>
-          <div className={'circle ' + state} /> {qe.title} {' '}
+          <TabStatusIcon onClose={this.removeQueryEditor.bind(this, qe)} tabState={state} /> {qe.title} {' '}
           <DropdownButton
             bsSize="small"
             id={'ddbtn-tab-' + i}
diff --git a/superset/assets/javascripts/SqlLab/main.less b/superset/assets/javascripts/SqlLab/main.less
index 5a2b9b7f08..df3ba9b95e 100644
--- a/superset/assets/javascripts/SqlLab/main.less
+++ b/superset/assets/javascripts/SqlLab/main.less
@@ -129,6 +129,12 @@ div.Workspace {
     height: 10px;
     display: inline-block;
     background-color: #ccc;
+    line-height: 8px;
+    text-align: center;
+    vertical-align: middle;
+    font-size: 15px;
+    margin-top: -3px;
+    font-weight: bold;
 }
 .running {
     background-color: lime;
diff --git a/superset/assets/spec/javascripts/sqllab/TabStatusIcon_spec.jsx b/superset/assets/spec/javascripts/sqllab/TabStatusIcon_spec.jsx
new file mode 100644
index 0000000000..1dde254cc3
--- /dev/null
+++ b/superset/assets/spec/javascripts/sqllab/TabStatusIcon_spec.jsx
@@ -0,0 +1,35 @@
+import React from 'react';
+import sinon from 'sinon';
+import { expect } from 'chai';
+import { describe, it } from 'mocha';
+import { shallow } from 'enzyme';
+
+import TabStatusIcon from '../../../javascripts/SqlLab/components/TabStatusIcon';
+
+function setup() {
+  const onClose = sinon.spy();
+  const wrapper = shallow(<TabStatusIcon onClose={onClose} tabState="running" />);
+  return { wrapper, onClose };
+}
+
+describe('TabStatusIcon', () => {
+  it('renders a circle without an x when hovered', () => {
+    const { wrapper } = setup();
+    expect(wrapper.find('div.circle')).to.have.length(1);
+    expect(wrapper.text()).to.equal('');
+  });
+
+  it('renders a circle with an x when hovered', () => {
+    const { wrapper } = setup();
+    wrapper.simulate('mouseOver');
+    expect(wrapper.find('div.circle')).to.have.length(1);
+    expect(wrapper.text()).to.equal('×');
+  });
+
+  it('calls onClose from props when clicked', () => {
+    const { wrapper, onClose } = setup();
+    wrapper.simulate('click');
+    // eslint-disable-next-line no-unused-expressions
+    expect(onClose.calledOnce).to.be.true;
+  });
+});


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services