You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by gr...@apache.org on 2018/04/02 21:59:11 UTC

[incubator-superset] branch master updated: easier tab closing in sqllab (#4738)

This is an automated email from the ASF dual-hosted git repository.

graceguo pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-superset.git


The following commit(s) were added to refs/heads/master by this push:
     new e0f541f  easier tab closing in sqllab (#4738)
e0f541f is described below

commit e0f541f4861510b4dc8935168511dc7dac160824
Author: Gabe Lyons <ga...@airbnb.com>
AuthorDate: Mon Apr 2 14:59:08 2018 -0700

    easier tab closing in sqllab (#4738)
---
 .../SqlLab/components/TabStatusIcon.jsx            | 42 ++++++++++++++++++++++
 .../SqlLab/components/TabbedSqlEditors.jsx         |  3 +-
 superset/assets/javascripts/SqlLab/main.less       |  6 ++++
 .../spec/javascripts/sqllab/TabStatusIcon_spec.jsx | 35 ++++++++++++++++++
 4 files changed, 85 insertions(+), 1 deletion(-)

diff --git a/superset/assets/javascripts/SqlLab/components/TabStatusIcon.jsx b/superset/assets/javascripts/SqlLab/components/TabStatusIcon.jsx
new file mode 100644
index 0000000..33f8646
--- /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 c890b5b..b9acc16 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 5a2b9b7..df3ba9b 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 0000000..1dde254
--- /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;
+  });
+});

-- 
To stop receiving notification emails like this one, please contact
graceguo@apache.org.