You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by ga...@apache.org on 2016/12/15 11:18:40 UTC

fauxton commit: updated refs/heads/master to 2a3dcca

Repository: couchdb-fauxton
Updated Branches:
  refs/heads/master 1e5e8567f -> 2a3dccaf4


remove tray and use only traycontents

The start of removing non-react-bootstrap components


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/2a3dccaf
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/2a3dccaf
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/2a3dccaf

Branch: refs/heads/master
Commit: 2a3dccaf437d6f02f1770aaea43c6e92804c97a0
Parents: 1e5e856
Author: Garren Smith <ga...@gmail.com>
Authored: Wed Dec 14 16:59:02 2016 +0200
Committer: Garren Smith <ga...@gmail.com>
Committed: Thu Dec 15 13:17:31 2016 +0200

----------------------------------------------------------------------
 .../activetasks/assets/less/activetasks.less    |   2 +-
 app/addons/activetasks/components.react.jsx     |  69 ++++++----
 app/addons/components/components/apibar.js      |  23 +---
 app/addons/components/components/tray.js        |  40 +++++-
 .../tests/apiBarControllerSpec.react.jsx        | 132 +++----------------
 app/addons/databases/assets/less/databases.less |   2 +-
 app/addons/databases/components.react.jsx       |  98 +++++++-------
 .../databases/tests/componentsSpec.react.jsx    |  15 +--
 .../queryoptions/queryoptions.react.jsx         |  21 +--
 .../documents/tests/nightwatch/queryOptions.js  |   2 +-
 .../tests/nightwatch/queryOptionsCloseBug.js    |   6 +-
 .../tests/nightwatch/viewQueryOptions.js        |   4 +-
 app/addons/fauxton/components.react.jsx         |  80 -----------
 .../fauxton/tests/componentsSpec.react.jsx      |  97 --------------
 test/dev.js                                     |   2 +-
 15 files changed, 169 insertions(+), 424 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/2a3dccaf/app/addons/activetasks/assets/less/activetasks.less
----------------------------------------------------------------------
diff --git a/app/addons/activetasks/assets/less/activetasks.less b/app/addons/activetasks/assets/less/activetasks.less
index eed5754..cad281c 100644
--- a/app/addons/activetasks/assets/less/activetasks.less
+++ b/app/addons/activetasks/assets/less/activetasks.less
@@ -161,7 +161,7 @@
     float: right;
 
     &:before {
-      right: 20px;
+      right: 110px;
     }
     input.input-xxlarge {
       margin-bottom: 0px;

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/2a3dccaf/app/addons/activetasks/components.react.jsx
----------------------------------------------------------------------
diff --git a/app/addons/activetasks/components.react.jsx b/app/addons/activetasks/components.react.jsx
index d95be2c..f739823 100644
--- a/app/addons/activetasks/components.react.jsx
+++ b/app/addons/activetasks/components.react.jsx
@@ -21,7 +21,7 @@ import Components from "../components/react-components.react";
 import ComponentsReact from "../fauxton/components.react";
 import ReactCSSTransitionGroup from "react-addons-css-transition-group";
 
-const {TabElement, TabElementWrapper, Polling} = Components;
+const {TabElement, TabElementWrapper, Polling, TrayContents} = Components;
 
 const activeTasksStore = Stores.activeTasksStore;
 
@@ -372,50 +372,61 @@ var ActiveTaskTableBodyContents = React.createClass({
 });
 
 var ActiveTasksViewSourceSequence = React.createClass({
-  onTrayToggle (e) {
+  getInitialState () {
+    return {
+      contentVisible: false
+    };
+  },
+
+  toggleTray (e) {
     e.preventDefault();
-    this.refs.view_source_sequence_btn.toggle(function (shown) {
-      if (shown) {
-        ReactDOM.findDOMNode(this.refs.view_source_sequence_btn).focus();
-      }
-    }.bind(this));
+    this.setState({contentVisible: !this.state.contentVisible});
+  },
+
+  closeTray () {
+    this.setState({contentVisible: false});
   },
 
   sequences (item) {
     if (_.isNumber(item) || _.isString(item)) {
-      return <ComponentsReact.ClipboardWithTextField textToCopy={item} uniqueKey={item}/>;
+      return <ComponentsReact.ClipboardWithTextField onClipBoardClick={() => {}} textToCopy={item.toString()} uniqueKey={item.toString()}/>;
     }
 
     if (_.isArray(item)) {
       return _.map(item, function (seq, i) {
-          return <ComponentsReact.ClipboardWithTextField textToCopy={seq} uniqueKey={i + Math.random(100)} key={i}/>;
+          return <ComponentsReact.ClipboardWithTextField onClipBoardClick={() => {}} textToCopy={seq.toString()} uniqueKey={`${i + Math.random(100)}`} key={i}/>;
         });
     }
 
-    return  <ComponentsReact.ClipboardWithTextField textToCopy="???" uniqueKey='unknownRevision'/>;
+    return  <ComponentsReact.ClipboardWithTextField textToCopy="???" onClipBoardClick={() => {}} uniqueKey='unknownRevision'/>;
   },
 
   render () {
-
-    if (_.has(this.props.item, 'source_seq')) {
-      var sequences = this.sequences(this.props.item.source_seq);
-      return (
-        <div>
-          Current source sequence:
-          <a href="#"
-            className="view-source-sequence-btn"
-            onClick={this.onTrayToggle}
-            data-bypass="true">
-            View
-          </a>
-          <ComponentsReact.Tray ref="view_source_sequence_btn" className="view-source-sequence-tray">
-            <span className="add-on">Source Sequence</span>
-            {sequences}
-          </ComponentsReact.Tray>
-        </div>
-      );
+    if (!_.has(this.props.item, 'source_seq')) {
+      return null;
     }
-    return null;
+
+    const sequences = this.sequences(this.props.item.source_seq);
+    return (
+      <div>
+        Current source sequence:
+        <a href="#"
+          className="view-source-sequence-btn"
+          onClick={this.toggleTray}
+          data-bypass="true">
+          View
+        </a>
+        <TrayContents
+          ref="view_source_sequence_btn"
+          contentVisible={this.state.contentVisible}
+          closeTray={this.closeTray}
+          container={this}
+          className="view-source-sequence-tray">
+          <span className="add-on">Source Sequence</span>
+          {sequences}
+        </TrayContents>
+      </div>
+    );
   }
 });
 

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/2a3dccaf/app/addons/components/components/apibar.js
----------------------------------------------------------------------
diff --git a/app/addons/components/components/apibar.js b/app/addons/components/components/apibar.js
index 0dbc5f2..6718604 100644
--- a/app/addons/components/components/apibar.js
+++ b/app/addons/components/components/apibar.js
@@ -53,12 +53,9 @@ export const APIBar = React.createClass({
   },
 
   getTray () {
-    if (!this.props.contentVisible) {
-      return null;
-    }
     const {endpoint} = this.props;
     return (
-      <TrayContents className="tray show-tray api-bar-tray">
+      <TrayContents closeTray={this.closeTray} contentVisible={this.props.contentVisible} className="tray show-tray api-bar-tray">
         <div className="input-prepend input-append">
           <span className="add-on">
             API URL
@@ -91,21 +88,8 @@ export const APIBar = React.createClass({
     Actions.toggleApiBarVisibility(!this.props.contentVisible);
   },
 
-  componentDidMount () {
-    $('body').on('click.APIBar', function (e) {
-
-      if (!$('.show-tray.api-bar-tray').length) {
-        return;
-      }
-
-      if ($(e.target).closest('.api-bar-tray,.control-toggle-api-url').length === 0) {
-        Actions.toggleApiBarVisibility(false);
-      }
-    }.bind(this));
-  },
-
-  componentWillUnmount () {
-    $('body').off('click.APIBar');
+  closeTray () {
+    Actions.toggleApiBarVisibility(false);
   },
 
   render () {
@@ -121,7 +105,6 @@ export const APIBar = React.createClass({
           fonticon="fonticon-link"
           text="API"
           toggleCallback={this.toggleTrayVisibility} />
-
         {this.getTray()}
       </div>
     );

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/2a3dccaf/app/addons/components/components/tray.js
----------------------------------------------------------------------
diff --git a/app/addons/components/components/tray.js b/app/addons/components/components/tray.js
index 6fc8f86..8b92967 100644
--- a/app/addons/components/components/tray.js
+++ b/app/addons/components/components/tray.js
@@ -13,8 +13,28 @@
 import React from "react";
 import ReactDOM from "react-dom";
 import ReactCSSTransitionGroup from "react-addons-css-transition-group";
+import {Overlay} from 'react-bootstrap';
+
+//With React 15.2.0 it validates props and throws a warning if props to a component are not acceptable
+//this means that with the overlay it will try and pass custom props to a div which causes the overlay to stop working
+//using a custom component gets around this.
+const OverlayWarningEater = ({children}) => {
+  return children;
+};
 
 export const TrayContents = React.createClass({
+  propTypes: {
+    contentVisible: React.PropTypes.bool.isRequired,
+    closeTray: React.PropTypes.func.isRequired,
+    onEnter: React.PropTypes.func,
+    container: React.PropTypes.object
+  },
+
+  defaultProps: {
+    onEnter: () => {},
+    container: this
+  },
+
   getChildren () {
     var className = "tray show-tray " + this.props.className;
     return (
@@ -25,10 +45,22 @@ export const TrayContents = React.createClass({
 
   render () {
     return (
-      <ReactCSSTransitionGroup transitionName="tray" transitionAppear={true} component="div" transitionAppearTimeout={500}
-        transitionEnterTimeout={500} transitionLeaveTimeout={300}>
-        {this.getChildren()}
-      </ReactCSSTransitionGroup>
+      <Overlay
+       show={this.props.contentVisible}
+       onHide={this.props.closeTray}
+       placement={"bottom"}
+       container={this.props.container}
+       rootClose={true}
+       target={() => ReactDOM.findDOMNode(this.refs.target)}
+       onEnter={this.props.onEnter}
+      >
+        <OverlayWarningEater>
+          <ReactCSSTransitionGroup transitionName="tray" transitionAppear={true} component="div" transitionAppearTimeout={500}
+            transitionEnterTimeout={500} transitionLeaveTimeout={300}>
+            {this.getChildren()}
+          </ReactCSSTransitionGroup>
+        </OverlayWarningEater>
+      </Overlay>
     );
   }
 });

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/2a3dccaf/app/addons/components/tests/apiBarControllerSpec.react.jsx
----------------------------------------------------------------------
diff --git a/app/addons/components/tests/apiBarControllerSpec.react.jsx b/app/addons/components/tests/apiBarControllerSpec.react.jsx
index edb016c..543e1d5 100644
--- a/app/addons/components/tests/apiBarControllerSpec.react.jsx
+++ b/app/addons/components/tests/apiBarControllerSpec.react.jsx
@@ -12,65 +12,58 @@
 import FauxtonAPI from "../../../core/api";
 import Actions from "../actions";
 import Stores from "../stores";
-import ReactComponents from "../react-components.react";
 import utils from "../../../../test/mocha/testUtils";
 import TestUtils from "react-addons-test-utils";
 import sinon from "sinon";
 import React from "react";
 import ReactDOM from "react-dom";
+import {APIBar, ApiBarController} from '../components/apibar';
+import {mount} from 'enzyme';
 
-var assert = utils.assert;
-var componentStore = Stores.componentStore;
-var ApiBarController = ReactComponents.ApiBarController;
+const assert = utils.assert;
+const componentStore = Stores.componentStore;
 
 
-describe('ApiBarController', function () {
-  var container;
-
-  beforeEach(function () {
-    container = document.createElement('div');
-  });
-
-  afterEach(function () {
-    ReactDOM.unmountComponentAtNode(container);
+describe('ApiBarController', () => {
+  afterEach(() => {
     componentStore.reset();
   });
 
-  it('Doesn\'t show up when explicitly set to visible false', function () {
-    var el = TestUtils.renderIntoDocument(<ApiBarController />, container);
+  it('Doesn\'t show up when explicitly set to visible false', () => {
+    const el = mount(<ApiBarController />);
     Actions.updateAPIBar({
       buttonVisible: false,
       endpoint: 'http://link.example.com',
       docURL: 'http://link.example.com',
       contentVisible: false
     });
-    assert.equal($(ReactDOM.findDOMNode(el)).find('.control-toggle-api-url').length, 0);
+    assert.equal(el.find('.control-toggle-api-url').length, 0);
   });
 
-  it('Shows up when set to visible', function () {
-    var el = TestUtils.renderIntoDocument(<ApiBarController />, container);
+  it('Shows up when set to visible', () => {
+    const el = mount(<ApiBarController />);
     Actions.updateAPIBar({
       buttonVisible: true,
       endpoint: 'http://link.example.com',
       docURL: 'http://link.example.com',
       contentVisible: false
     });
-    assert.equal($(ReactDOM.findDOMNode(el)).find('.control-toggle-api-url').length, 1);
+    assert.equal(el.find('.control-toggle-api-url').length, 1);
   });
 
-  it('Doesn\'t show up when set to visible BUT there\'s no endpoint defined', function () {
-    var el = TestUtils.renderIntoDocument(<ApiBarController />, container);
+  it('Doesn\'t show up when set to visible BUT there\'s no endpoint defined', () => {
+    const el = mount(<ApiBarController />);
     Actions.updateAPIBar({
       buttonVisible: true,
       endpoint: '',
       docURL: 'http://link.example.com',
       contentVisible: false
     });
-    assert.equal($(ReactDOM.findDOMNode(el)).find('.control-toggle-api-url').length, 0);
+    assert.equal(el.find('.control-toggle-api-url').length, 0);
   });
 
-  it('Confirm hide/show actions update component', function () {
-    var el = TestUtils.renderIntoDocument(<ApiBarController />, container);
+  it('Confirm hide/show actions update component', () => {
+    const el = mount(<ApiBarController />);
 
     Actions.updateAPIBar({
       buttonVisible: true,
@@ -80,97 +73,10 @@ describe('ApiBarController', function () {
     });
 
     Actions.showAPIBarButton();
-    assert.equal($(ReactDOM.findDOMNode(el)).find('.control-toggle-api-url').length, 1, 'showAPIBarButton');
+    assert.equal(el.find('.control-toggle-api-url').length, 1, 'showAPIBarButton');
 
     Actions.hideAPIBarButton();
-    assert.equal($(ReactDOM.findDOMNode(el)).find('.control-toggle-api-url').length, 0, 'hideAPIBarButton');
-  });
-
-  it('Confirm doc link icon appears when docURL set', function () {
-    var el = TestUtils.renderIntoDocument(<ApiBarController />, container);
-    Actions.updateAPIBar({
-      buttonVisible: true,
-      endpoint: 'http://rocko.example.com',
-      docURL: 'http://doc.example.com',
-      contentVisible: false
-    });
-
-    TestUtils.Simulate.click($(ReactDOM.findDOMNode(el)).find('.control-toggle-api-url')[0]);
-    assert.equal($(ReactDOM.findDOMNode(el)).find('.help-link').length, 1);
-  });
-
-  it('Confirm doc link icon doesn\'t appear with no docURL', function () {
-    var el = TestUtils.renderIntoDocument(<ApiBarController />, container);
-    Actions.updateAPIBar({
-      buttonVisible: true,
-      endpoint: 'http://rocko.example.com',
-      docURL: null,
-      contentVisible: false
-    });
-
-    TestUtils.Simulate.click($(ReactDOM.findDOMNode(el)).find('.control-toggle-api-url')[0]);
-    assert.equal($(ReactDOM.findDOMNode(el)).find('.help-link').length, 0);
-  });
-
-  it('Confirm endpoint appears in markup', function () {
-    var el = TestUtils.renderIntoDocument(<ApiBarController />, container);
-    var link = 'http://booyah.example.com';
-    Actions.updateAPIBar({
-      buttonVisible: true,
-      endpoint: link,
-      docURL: null,
-      contentVisible: false
-    });
-
-    TestUtils.Simulate.click($(ReactDOM.findDOMNode(el)).find('.control-toggle-api-url')[0]);
-    assert.equal($(ReactDOM.findDOMNode(el)).find('.text-field-to-copy').val(), link);
-  });
-
-  it('Confirm endpoint is updated in markup', function () {
-    var el = TestUtils.renderIntoDocument(<ApiBarController />, container);
-    var link = 'http://booyah.example.com';
-    Actions.updateAPIBar({
-      buttonVisible: true,
-      endpoint: link,
-      docURL: null,
-      contentVisible: false
-    });
-
-    TestUtils.Simulate.click($(ReactDOM.findDOMNode(el)).find('.control-toggle-api-url')[0]);
-    assert.equal($(ReactDOM.findDOMNode(el)).find('.text-field-to-copy').val(), link);
-
-    var newLink = 'http://chickensarenoisy.example.com';
-    Actions.updateAPIBar({
-      buttonVisible: true,
-      endpoint: newLink,
-      docURL: null,
-      contentVisible: true
-    });
-
-    assert.equal($(ReactDOM.findDOMNode(el)).find('.text-field-to-copy').val(), newLink);
-  });
-
-  it('Confirm doc URL is updated in markup after a change', function () {
-    var el = TestUtils.renderIntoDocument(<ApiBarController />, container);
-    var docLink = 'http://mydoc.example.com';
-    Actions.updateAPIBar({
-      buttonVisible: true,
-      endpoint: 'http://whatever.example.com',
-      docURL: docLink,
-      contentVisible: false
-    });
-
-    TestUtils.Simulate.click($(ReactDOM.findDOMNode(el)).find('.control-toggle-api-url')[0]);
-    assert.equal($(ReactDOM.findDOMNode(el)).find('.help-link').attr('href'), docLink);
-
-    var newDocLink = 'http://newawesomedoclink.example.com';
-    Actions.updateAPIBar({
-      buttonVisible: true,
-      endpoint: 'http://whatever.example.com',
-      docURL: newDocLink,
-      contentVisible: true
-    });
-    assert.equal($(ReactDOM.findDOMNode(el)).find('.help-link').attr('href'), newDocLink);
+    assert.equal(el.find('.control-toggle-api-url').length, 0, 'hideAPIBarButton');
   });
 
 });

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/2a3dccaf/app/addons/databases/assets/less/databases.less
----------------------------------------------------------------------
diff --git a/app/addons/databases/assets/less/databases.less b/app/addons/databases/assets/less/databases.less
index e075fc2..a2c14fc 100644
--- a/app/addons/databases/assets/less/databases.less
+++ b/app/addons/databases/assets/less/databases.less
@@ -21,7 +21,7 @@
 .new-database-tray {
   padding: 16px 20px 28px;
   &:before {
-    right: 206px;
+    right: 115px;
   }
 
   input.input-xxlarge {

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/2a3dccaf/app/addons/databases/components.react.jsx
----------------------------------------------------------------------
diff --git a/app/addons/databases/components.react.jsx b/app/addons/databases/components.react.jsx
index 849f284..47cfde4 100644
--- a/app/addons/databases/components.react.jsx
+++ b/app/addons/databases/components.react.jsx
@@ -25,15 +25,15 @@ import Actions from "./actions";
 import ReactSelect from "react-select";
 import {Tooltip, OverlayTrigger} from 'react-bootstrap';
 
-var ToggleHeaderButton = Components.ToggleHeaderButton;
-var databasesStore = Stores.databasesStore;
-var deleteDbModalStore = ComponentsStore.deleteDbModalStore;
-var DeleteDatabaseModal = Components.DeleteDatabaseModal;
+const databasesStore = Stores.databasesStore;
+const deleteDbModalStore = ComponentsStore.deleteDbModalStore;
+
+const {DeleteDatabaseModal, ToggleHeaderButton, TrayContents} = Components;
 
 
 var DatabasesController = React.createClass({
 
-  getStoreState: function () {
+  getStoreState () {
     return {
       dbList: databasesStore.getDbList(),
       loading: databasesStore.isLoading(),
@@ -41,27 +41,27 @@ var DatabasesController = React.createClass({
     };
   },
 
-  getInitialState: function () {
+  getInitialState () {
     return this.getStoreState();
   },
 
-  componentDidMount: function () {
+  componentDidMount () {
     databasesStore.on('change', this.onChange, this);
     deleteDbModalStore.on('change', this.onChange, this);
   },
 
-  componentWillUnmount: function () {
+  componentWillUnmount () {
     databasesStore.off('change', this.onChange, this);
     deleteDbModalStore.off('change', this.onChange, this);
   },
 
-  onChange: function () {
+  onChange () {
     if (this.isMounted()) {
       this.setState(this.getStoreState());
     }
   },
 
-  render: function () {
+  render () {
     const {loading, dbList} = this.state;
 
     return (
@@ -81,7 +81,7 @@ const DatabaseTable = React.createClass({
     loading: React.PropTypes.bool.isRequired,
   },
 
-  createRows: function (dbList) {
+  createRows (dbList) {
     return dbList.map((item, k) => {
       return (
         <DatabaseRow item={item} key={k} />
@@ -89,20 +89,20 @@ const DatabaseTable = React.createClass({
     });
   },
 
-  getExtensionColumns: function () {
+  getExtensionColumns () {
     var cols = FauxtonAPI.getExtensions('DatabaseTable:head');
     return _.map(cols, function (Item, index) {
       return <Item key={index} />;
     });
   },
 
-  showDeleteDatabaseModal: function (name) {
+  showDeleteDatabaseModal (name) {
     ComponentsActions.showDeleteDatabaseModal({
       showDeleteModal: !this.props.showDeleteDatabaseModal.showDeleteModal
     });
   },
 
-  render: function () {
+  render () {
     if (this.props.loading) {
       return (
         <div className="view">
@@ -142,18 +142,18 @@ var DatabaseRow = React.createClass({
     row: React.PropTypes.object
   },
 
-  getExtensionColumns: function (row) {
+  getExtensionColumns (row) {
     var cols = FauxtonAPI.getExtensions('DatabaseTable:databaseRow');
     return _.map(cols, function (Item, index) {
       return <Item row={row} key={index} />;
     });
   },
 
-  showDeleteDatabaseModal: function (name) {
+  showDeleteDatabaseModal (name) {
     ComponentsActions.showDeleteDatabaseModal({showDeleteModal: true, dbId: name});
   },
 
-  render: function () {
+  render () {
     const {
       item
     } = this.props;
@@ -220,52 +220,62 @@ const RightDatabasesHeader = () => {
 
 var AddDatabaseWidget = React.createClass({
 
-  onTrayToggle: function (e) {
-    e.preventDefault();
-
+  onTrayToggle () {
     this.setState({isPromptVisible: !this.state.isPromptVisible});
+  },
 
-    this.refs.newDbTray.toggle(function (shown) {
-      if (shown) {
-        ReactDOM.findDOMNode(this.refs.newDbName).focus();
-      }
-    }.bind(this));
+  closeTray () {
+    this.setState({isPromptVisible: false});
   },
 
-  onKeyUpInInput: function (e) {
+  focusInput () {
+    ReactDOM.findDOMNode(this.refs.newDbName).focus();
+  },
+
+  onKeyUpInInput (e) {
     if (e.which === 13) {
       this.onAddDatabase();
     }
   },
 
-  getInitialState: function () {
+  getInitialState () {
     return {
-      isPromptVisible: false
+      isPromptVisible: false,
+      databaseName: ''
     };
   },
 
-  onAddDatabase: function () {
-    var databaseName = ReactDOM.findDOMNode(this.refs.newDbName).value;
-    Actions.createNewDatabase(databaseName);
+  onChange (e) {
+    this.setState({databaseName: e.target.value});
   },
 
-  render: function () {
-    var headerButtonContainerClasses = 'header-control-box add-new-database-btn';
+  onAddDatabase () {
+    Actions.createNewDatabase(this.state.databaseName);
+  },
 
+  render () {
     return (
       <div>
         <ToggleHeaderButton
           selected={this.state.isPromptVisible}
           toggleCallback={this.onTrayToggle}
-          containerClasses={headerButtonContainerClasses}
+          containerClasses='header-control-box add-new-database-btn'
           title="Create Database"
           fonticon="fonticon-new-database"
           text="Create Database" />
-        <FauxtonComponentsReact.Tray ref="newDbTray" className="new-database-tray">
+        <TrayContents className="new-database-tray" contentVisible={this.state.isPromptVisible} closeTray={this.closeTray} onEnter={this.focusInput}>
           <span className="add-on">Create Database</span>
-          <input id="js-new-database-name" type="text" onKeyUp={this.onKeyUpInInput} ref="newDbName" className="input-xxlarge" placeholder="Name of database" />
+          <input
+            id="js-new-database-name"
+            ref="newDbName"
+            type="text"
+            value={this.state.databaseName}
+            onChange={this.onChange} onKeyUp={this.onKeyUpInInput}
+            className="input-xxlarge"
+            placeholder="Name of database"
+            />
           <a className="btn" id="js-create-database" onClick={this.onAddDatabase}>Create</a>
-        </FauxtonComponentsReact.Tray>
+        </TrayContents>
       </div>
     );
   }
@@ -294,14 +304,14 @@ JumpToDatabaseWidget.propTypes = {
 
 var DatabasePagination = React.createClass({
 
-  getDefaultProps: function () {
+  getDefaultProps () {
     return {
       linkPath: '_all_dbs',
       store: databasesStore
     };
   },
 
-  getStoreState: function () {
+  getStoreState () {
     const {store} = this.props;
 
     return {
@@ -310,26 +320,26 @@ var DatabasePagination = React.createClass({
     };
   },
 
-  getInitialState: function () {
+  getInitialState () {
     return this.getStoreState();
   },
 
-  componentDidMount: function () {
+  componentDidMount () {
     const {store} = this.props;
 
     store.on('change', this.onChange, this);
   },
 
-  componentWillUnmount: function () {
+  componentWillUnmount () {
     const {store} = this.props;
     store.off('change', this.onChange, this);
   },
 
-  onChange: function () {
+  onChange () {
     this.setState(this.getStoreState());
   },
 
-  render: function () {
+  render () {
     const {page, totalAmountOfDatabases} = this.state;
 
     const urlPrefix = `#/${this.props.linkPath}?page=`;

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/2a3dccaf/app/addons/databases/tests/componentsSpec.react.jsx
----------------------------------------------------------------------
diff --git a/app/addons/databases/tests/componentsSpec.react.jsx b/app/addons/databases/tests/componentsSpec.react.jsx
index 3554f8d..ab6f933 100644
--- a/app/addons/databases/tests/componentsSpec.react.jsx
+++ b/app/addons/databases/tests/componentsSpec.react.jsx
@@ -27,8 +27,8 @@ const store = Stores.databasesStore;
 
 describe('AddDatabaseWidget', function () {
 
-  var container, addEl, oldCreateNewDatabase;
-  var createCalled, passedDbName;
+  let oldCreateNewDatabase;
+  let createCalled, passedDbName;
 
   beforeEach(function () {
     oldCreateNewDatabase = Actions.createNewDatabase;
@@ -36,23 +36,20 @@ describe('AddDatabaseWidget', function () {
       createCalled = true;
       passedDbName = dbName;
     };
-    container = document.createElement('div');
-    addEl = ReactDOM.render(React.createElement(Views.AddDatabaseWidget, {}), container);
   });
 
   afterEach(function () {
     Actions.createNewDatabase = oldCreateNewDatabase;
-    ReactDOM.unmountComponentAtNode(container);
   });
 
   it("Creates a database with given name", function () {
     createCalled = false;
     passedDbName = null;
-    const el = TestUtils.findRenderedDOMComponentWithTag(addEl, 'input');
-    ReactDOM.findDOMNode(el).value = "testdb";
-    addEl.onAddDatabase();
+    const el = mount(<Views.AddDatabaseWidget />);
+    el.setState({databaseName: 'my-db'});
+    el.instance().onAddDatabase();
     assert.equal(true, createCalled);
-    assert.equal("testdb", passedDbName);
+    assert.equal("my-db", passedDbName);
   });
 
 });

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/2a3dccaf/app/addons/documents/queryoptions/queryoptions.react.jsx
----------------------------------------------------------------------
diff --git a/app/addons/documents/queryoptions/queryoptions.react.jsx b/app/addons/documents/queryoptions/queryoptions.react.jsx
index 3c608dc..f0a1987 100644
--- a/app/addons/documents/queryoptions/queryoptions.react.jsx
+++ b/app/addons/documents/queryoptions/queryoptions.react.jsx
@@ -370,30 +370,13 @@ var QueryTray = React.createClass({
     Actions.toggleQueryBarVisibility(false);
   },
 
-  componentDidMount: function () {
-    $('body').on('click.QueryTray', function (e) {
-      if ($(e.target).closest('#query-options').length) {
-        return;
-      }
-      Actions.toggleQueryBarVisibility(false);
-    }.bind(this));
-  },
-
-  componentWillUnmount: function () {
-    $('body').off('click.QueryTray');
-  },
-
   toggleIncludeDocs: function (e) {
     Actions.toggleIncludeDocs();
   },
 
   getTray: function () {
-    if (!this.props.contentVisible) {
-      return null;
-    }
-
     return (
-      <TrayContents contentVisible={this.props.contentVisible}
+      <TrayContents closeTray={this.closeTray} contentVisible={this.props.contentVisible}
         className="query-options"
         id="query-options-tray">
 
@@ -440,7 +423,7 @@ var QueryTray = React.createClass({
           title="Query Options"
           fonticon="fonticon-gears"
           text="Options" />
-        {this.getTray()}
+          {this.getTray()}
       </div>
     );
   }

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/2a3dccaf/app/addons/documents/tests/nightwatch/queryOptions.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/tests/nightwatch/queryOptions.js b/app/addons/documents/tests/nightwatch/queryOptions.js
index c325fad..e2465ca 100644
--- a/app/addons/documents/tests/nightwatch/queryOptions.js
+++ b/app/addons/documents/tests/nightwatch/queryOptions.js
@@ -27,7 +27,7 @@ module.exports = {
       .clickWhenVisible('.control-toggle-queryoptions')
       .clickWhenVisible('#betweenKeys', waitTime, false)
       .setValue('#startkey', '"document_2"')
-      .clickWhenVisible('#query-options .btn-success')
+      .clickWhenVisible('.query-options .btn-success')
       .waitForElementNotPresent('#doc-list [data-id="document_1"]', waitTime, false)
       .waitForElementPresent('#doc-list [data-id="document_2"]', waitTime, false)
       .assert.elementPresent('#doc-list [data-id="document_2"]')

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/2a3dccaf/app/addons/documents/tests/nightwatch/queryOptionsCloseBug.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/tests/nightwatch/queryOptionsCloseBug.js b/app/addons/documents/tests/nightwatch/queryOptionsCloseBug.js
index 81acd8c..ace3c72 100644
--- a/app/addons/documents/tests/nightwatch/queryOptionsCloseBug.js
+++ b/app/addons/documents/tests/nightwatch/queryOptionsCloseBug.js
@@ -27,12 +27,12 @@ module.exports = {
       .clickWhenVisible('.control-toggle-queryoptions')
       .clickWhenVisible('#betweenKeys', waitTime, false)
       .setValue('#startkey', '"document_2"')
-      .clickWhenVisible('#query-options .btn-success')
+      .clickWhenVisible('.query-options .btn-success')
       .waitForElementNotPresent('#doc-list [data-id="document_1"]', waitTime, false)
       .clickWhenVisible('.control-toggle-queryoptions')
-      .clickWhenVisible('#query-options .btn-cancel')
+      .clickWhenVisible('.query-options .btn-cancel')
 
-      .waitForElementNotPresent('#query-options .js-view-query-update', waitTime, false)
+      .waitForElementNotPresent('.query-options .js-view-query-update', waitTime, false)
 
     .end();
   }

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/2a3dccaf/app/addons/documents/tests/nightwatch/viewQueryOptions.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/tests/nightwatch/viewQueryOptions.js b/app/addons/documents/tests/nightwatch/viewQueryOptions.js
index eaa60f7..499ee18 100644
--- a/app/addons/documents/tests/nightwatch/viewQueryOptions.js
+++ b/app/addons/documents/tests/nightwatch/viewQueryOptions.js
@@ -26,7 +26,7 @@ module.exports = {
       .clickWhenVisible('.control-toggle-queryoptions')
       .clickWhenVisible('#byKeys', waitTime, false)
       .setValue('#keys-input', '["document_1"]')
-      .clickWhenVisible('#query-options .btn-success')
+      .clickWhenVisible('.query-options .btn-success')
       .waitForElementNotPresent('#doc-list [data-id="document_2"]', waitTime, false)
       .assert.elementNotPresent('#doc-list [data-id="document_2"]')
       .assert.elementNotPresent('#doc-list [data-id="document_0"]')
@@ -47,7 +47,7 @@ module.exports = {
       .clickWhenVisible('.control-toggle-queryoptions', waitTime, false)
       .clickWhenVisible('#byKeys', waitTime, false)
       .setValue('#keys-input', '["document_1",\n"document_2"]')
-      .clickWhenVisible('#query-options .btn-success')
+      .clickWhenVisible('.query-options .btn-success')
       .waitForElementNotPresent('#doc-list [data-id="document_0"]', waitTime, false)
       .assert.elementNotPresent('#doc-list [data-id="document_0"]')
       .assert.elementPresent('#doc-list [data-id="document_1"]')

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/2a3dccaf/app/addons/fauxton/components.react.jsx
----------------------------------------------------------------------
diff --git a/app/addons/fauxton/components.react.jsx b/app/addons/fauxton/components.react.jsx
index 741a56f..3ca7bfd 100644
--- a/app/addons/fauxton/components.react.jsx
+++ b/app/addons/fauxton/components.react.jsx
@@ -188,85 +188,6 @@ var CodeFormat = React.createClass({
   }
 });
 
-var _NextTrayInternalId = 0;
-var Tray = React.createClass({
-
-  propTypes: {
-    onAutoHide: React.PropTypes.func
-  },
-
-  getDefaultProps: function () {
-    return {
-      onAutoHide: function () { }
-    };
-  },
-
-  getInitialState: function () {
-    return {
-      show: false,
-      internalid: (_NextTrayInternalId++)
-    };
-  },
-
-  toggle: function (done) {
-    if (this.state.show) {
-      this.hide(done);
-    } else {
-      this.show(done);
-    }
-  },
-
-  setVisible: function (visible, done) {
-    if (this.state.show && !visible) {
-      this.hide(done);
-    } else if (!this.state.show && visible) {
-      this.show(done);
-    }
-  },
-
-  componentDidMount: function () {
-    $('body').on('click.Tray-' + this.state.internalid, function (e) {
-      var tgt = $(e.target);
-      if (this.state.show && tgt.closest('.tray').length === 0) {
-        this.hide();
-        this.props.onAutoHide();
-      }
-    }.bind(this));
-  },
-
-  componentWillUnmount: function () {
-    $('body').off('click.Tray-' + this.state.internalid);
-  },
-
-  show: function (done) {
-    this.setState({show: true});
-    $(ReactDOM.findDOMNode(this.refs.myself)).velocity('transition.slideDownIn', FauxtonAPI.constants.MISC.TRAY_TOGGLE_SPEED, function () {
-      if (done) {
-        done(true);
-      }
-    });
-  },
-
-  hide: function (done) {
-    $(ReactDOM.findDOMNode(this.refs.myself)).velocity('reverse', FauxtonAPI.constants.MISC.TRAY_TOGGLE_SPEED, function () {
-      this.setState({show: false});
-      if (done) {
-        done(false);
-      }
-    }.bind(this));
-  },
-
-  render: function () {
-    var styleSpec = this.state.show ? {"display": "block", "opacity": 1} :  {"display": "none", "opacity": 0};
-    var classSpec = this.props.className || "";
-    classSpec += " tray";
-    return (
-      <div ref="myself" style={styleSpec} className={classSpec}>{this.props.children}</div>
-    );
-  }
-});
-
-
 var Pagination = React.createClass({
 
   getDefaultProps: function () {
@@ -414,7 +335,6 @@ export default {
   Clipboard: Clipboard,
   ClipboardWithTextField: ClipboardWithTextField,
   CodeFormat: CodeFormat,
-  Tray: Tray,
   Pagination: Pagination,
   ConfirmationModal: ConfirmationModal
 };

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/2a3dccaf/app/addons/fauxton/tests/componentsSpec.react.jsx
----------------------------------------------------------------------
diff --git a/app/addons/fauxton/tests/componentsSpec.react.jsx b/app/addons/fauxton/tests/componentsSpec.react.jsx
index 46aac7d..3c1e16b 100644
--- a/app/addons/fauxton/tests/componentsSpec.react.jsx
+++ b/app/addons/fauxton/tests/componentsSpec.react.jsx
@@ -19,103 +19,6 @@ import sinon from "sinon";
 import { mount } from 'enzyme';
 var assert = utils.assert;
 
-describe('Tray', function () {
-
-  var container, trayEl, oldToggleSpeed;
-
-  beforeEach(function () {
-    container = document.createElement('div');
-
-    // when we want to control the diff, we have to render directly
-    trayEl = TestUtils.renderIntoDocument(<Views.Tray className="traytest" />, container);
-
-    oldToggleSpeed = FauxtonAPI.constants.MISC.TRAY_TOGGLE_SPEED;
-
-    // makes velocity toggle immediately
-    FauxtonAPI.constants.MISC.TRAY_TOGGLE_SPEED = 0;
-  });
-
-  afterEach(function () {
-    ReactDOM.unmountComponentAtNode(container);
-    FauxtonAPI.constants.MISC.TRAY_TOGGLE_SPEED = oldToggleSpeed;
-  });
-
-  it('renders trayid and custom classes', function () {
-    assert(ReactDOM.findDOMNode(trayEl).getAttribute('class').indexOf('traytest') >= 0);
-  });
-
-  it('is initially closed', function () {
-    assert.equal('none', ReactDOM.findDOMNode(trayEl).style.display);
-  });
-
-  it('shows when requested', function () {
-    trayEl.setVisible(true, function () {
-      assert.equal('block', ReactDOM.findDOMNode(trayEl).style.display);
-    });
-  });
-
-  it('hides when requested', function () {
-    trayEl.show(function () {
-      trayEl.setVisible(false, function () {
-        assert.equal('none', ReactDOM.findDOMNode(trayEl).style.display);
-      });
-    });
-  });
-
-  it('does nothing when already hidden', function () {
-    trayEl.setVisible(false, function () {
-      throw new Error('should do nothing');
-    });
-  });
-
-  it('toggles open with callback', function () {
-    trayEl.toggle(function () {
-      assert.equal('block', ReactDOM.findDOMNode(trayEl).style.display);
-    });
-  });
-
-  it('toggles close again with callback', function () {
-    trayEl.show(function () {
-      trayEl.toggle(function () {
-        assert.equal('none', ReactDOM.findDOMNode(trayEl).style.display);
-      });
-    });
-  });
-
-  it('calls props.onAutoHide when closing tray by clicking outside of it', function () {
-    var container = document.createElement('div');
-    var onClose = function () { };
-    var spy = sinon.spy();
-
-    var wrapper = React.createClass({
-
-      runTest: function () {
-        var trayEl = this.refs.tray;
-        var externalEl = this.refs.externalElement;
-        trayEl.show(function () {
-          TestUtils.Simulate.click(ReactDOM.findDOMNode(externalEl));
-          assert.ok(spy.calledOnce);
-        });
-      },
-
-      render: function () {
-        return (
-          <div>
-            <p ref="externalElement">Click me!</p>
-            <Views.Tray ref="tray" onAutoHide={onClose} />
-          </div>
-        );
-      }
-    });
-
-    var reactEl = TestUtils.renderIntoDocument(React.createElement(wrapper), container);
-    reactEl.runTest();
-
-    ReactDOM.unmountComponentAtNode(container);
-  });
-
-});
-
 describe('Pagination', function () {
 
   var nvl, container;

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/2a3dccaf/test/dev.js
----------------------------------------------------------------------
diff --git a/test/dev.js b/test/dev.js
index c88b3d4..1ed718b 100644
--- a/test/dev.js
+++ b/test/dev.js
@@ -13,7 +13,7 @@
 
 // This will search for files ending in .test.js and require them
 // so that they are added to the webpack bundle
-var context = require.context('../app/addons/documents/index-results', true, /[Ss]pec/);
+var context = require.context('../app/addons/warehouse/tests', true, /warehouse.edit.component[Ss]pec/);
 console.log('Testing files', context.keys());
 context.keys().forEach(context);
 module.exports = context;