couchdb-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From robertkowal...@apache.org
Subject [2/2] fauxton commit: updated refs/heads/master to e6f089a
Date Thu, 19 Feb 2015 12:59:42 GMT
Two pane editor

 - introduce a editor on the left which changes a resultview on
   the right

 - delete old unused templates: design_doc_selector.html,
   view_editor.html

 - introduce styled dropdowns with no round corners

 - allow breadcrumbs without mouseover effects

 - populateDatabase handler now accepts a doc count and creates a
   stubview

Based on a concept and design from Sean Barclay
<fudd1011@hotmail.com>

Watermark by Jenn Schiffer <jenn@pancaketheorem.com> and Sue
Lockwood <deathbear@apache.org>

Closes #33


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

Branch: refs/heads/master
Commit: e6f089aa1ecd28d779d24fad57b118b2f525e9b4
Parents: a014c0b
Author: Robert Kowalski <robertkowalski@apache.org>
Authored: Thu Jan 29 17:04:52 2015 +0100
Committer: Robert Kowalski <robertkowalski@apache.org>
Committed: Thu Feb 19 13:56:14 2015 +0100

----------------------------------------------------------------------
 .../databases/tests/nightwatch/createsView.js   |  65 -----
 app/addons/documents/assets/less/documents.less |   1 +
 .../documents/assets/less/index-results.less    |  27 ++
 .../documents/assets/less/viewEditor.less       | 265 +++++++++++++----
 app/addons/documents/index-editor/actions.js    |  32 +--
 .../documents/index-editor/actiontypes.js       |   1 -
 .../documents/index-editor/components.react.jsx | 240 ++++++++++------
 app/addons/documents/index-editor/stores.js     |  18 +-
 .../index-results.components.react.jsx          |  52 ++++
 app/addons/documents/routes-documents.js        | 287 +------------------
 app/addons/documents/routes-index-editor.js     | 156 ++++++++++
 app/addons/documents/routes.js                  |   8 +-
 app/addons/documents/shared-routes.js           | 173 +++++++++++
 .../templates/design_doc_selector.html          |  36 ---
 app/addons/documents/templates/view_editor.html |  86 ------
 app/addons/documents/tests/actionsSpec.js       |   7 +-
 .../tests/nightwatch/navigateToNewView.js       |   2 +-
 .../documents/tests/nightwatch/viewCreate.js    |  94 ++++++
 .../documents/tests/nightwatch/viewEdit.js      |  89 ++++++
 .../tests/nightwatch/viewQueryOptions.js        |  34 +++
 app/addons/documents/tests/routeSpec.js         |   7 -
 app/addons/documents/tests/storesSpec.js        |  67 -----
 .../tests/viewIndex.componentsSpec.react.jsx    |  63 ++--
 app/addons/documents/views-index.js             |  19 +-
 app/addons/fauxton/components.js                |  13 +-
 app/templates/layouts/two_pane.html             |  36 ++-
 assets/img/couch-watermark.png                  | Bin 0 -> 7053 bytes
 assets/less/fauxton.less                        |   7 +
 assets/less/templates.less                      |  27 +-
 .../custom-commands/populateDatabase.js         |  49 +++-
 30 files changed, 1172 insertions(+), 789 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/e6f089aa/app/addons/databases/tests/nightwatch/createsView.js
----------------------------------------------------------------------
diff --git a/app/addons/databases/tests/nightwatch/createsView.js b/app/addons/databases/tests/nightwatch/createsView.js
deleted file mode 100644
index 0523993..0000000
--- a/app/addons/databases/tests/nightwatch/createsView.js
+++ /dev/null
@@ -1,65 +0,0 @@
-// Licensed under the Apache License, Version 2.0 (the "License"); you may not
-// use this file except in compliance with the License. You may obtain a copy of
-// the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations under
-// the License.
-
-module.exports = {
-  'Creates a View' : function (client) {
-    /*jshint multistr: true */
-    var waitTime = 10000,
-        newDatabaseName = client.globals.testDatabaseName,
-        newDocumentName = 'create_view_doc',
-        baseUrl = client.globals.test_settings.launch_url;
-
-    var indexFunctionString = function (parity) {
-      return 'function (doc) {'               +  
-        ' if (doc.number%2 === '+parity+'){'  +
-        '   emit(doc._id, doc.number);'       +  
-        ' }'                                  +
-        '}';
-    };
-
-    client
-      .loginToGUI()
-      .populateDatabase(newDatabaseName)
-      .url(baseUrl+'/#/database/'+newDatabaseName+'/_all_docs')
-      .waitForElementPresent('#new-design-docs-button', waitTime, false)
-      .click('#new-design-docs-button a')
-      .click('#new-design-docs-button a[href="#/database/'+newDatabaseName+'/new_view"]')
-      .waitForElementPresent('#new-ddoc', waitTime, false)
-      .setValue('#new-ddoc','test_design_doc')
-      .clearValue('#index-name')
-      .setValue('#index-name','even_ids')
-      .execute('\
-        var editor = ace.edit("map-function");\
-        editor.getSession().setValue("'+indexFunctionString(0)+'");\
-      ')
-      .click('button.btn.btn-success.save')
-      .waitForElementPresent('#test_design_doc_even_ids', waitTime, false)
-      .click('#test_design_doc_even_ids')
-      .waitForElementPresent('#nav-header-test_design_doc', waitTime, false)
-      .click('#nav-header-test_design_doc .dropdown-toggle.icon.fonticon-plus-circled')
-      .waitForElementPresent('#nav-header-test_design_doc', waitTime, false)
-      .click('#nav-header-test_design_doc a[href="#/database/'+newDatabaseName+'/new_view/test_design_doc"]')
-      .waitForElementPresent('#db-views-tabs-nav', waitTime, false)
-      .click('#db-views-tabs-nav')
-      .verify.valueContains('#index-name','new-view')
-      .clearValue('#index-name')
-      .setValue('#index-name','odd_ids')
-      .execute('\
-        var editor = ace.edit("map-function");\
-        editor.getSession().setValue("'+indexFunctionString(1)+'");\
-      ')
-      .click('button.btn.btn-success.save')
-      .waitForElementPresent('#test_design_doc_even_ids', waitTime, false)
-      .waitForElementPresent('#test_design_doc_odd_ids', waitTime, false)
-    .end();
-  }
-};

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/e6f089aa/app/addons/documents/assets/less/documents.less
----------------------------------------------------------------------
diff --git a/app/addons/documents/assets/less/documents.less b/app/addons/documents/assets/less/documents.less
index a08a191..8e2df47 100644
--- a/app/addons/documents/assets/less/documents.less
+++ b/app/addons/documents/assets/less/documents.less
@@ -17,6 +17,7 @@
 @import "viewEditor.less";
 @import "changes.less";
 @import "sidenav.less";
+@import "index-results.less";
 
 @import "header.less";
 

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/e6f089aa/app/addons/documents/assets/less/index-results.less
----------------------------------------------------------------------
diff --git a/app/addons/documents/assets/less/index-results.less b/app/addons/documents/assets/less/index-results.less
new file mode 100644
index 0000000..7809757
--- /dev/null
+++ b/app/addons/documents/assets/less/index-results.less
@@ -0,0 +1,27 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+.watermark-logo {
+  background: transparent url('../img/couch-watermark.png') no-repeat 50% 50%;
+  min-height: 400px;
+  padding-top: 60%;
+  text-align: center;
+  margin: 0 20%;
+  h3 {
+    border-bottom: 1px solid #ccc;
+    padding-bottom: 10px;
+    margin-bottom: 20px;
+  }
+  .preview {
+    margin: 0 10px;
+  }
+}

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/e6f089aa/app/addons/documents/assets/less/viewEditor.less
----------------------------------------------------------------------
diff --git a/app/addons/documents/assets/less/viewEditor.less b/app/addons/documents/assets/less/viewEditor.less
index 37fc797..c4d8316 100644
--- a/app/addons/documents/assets/less/viewEditor.less
+++ b/app/addons/documents/assets/less/viewEditor.less
@@ -10,76 +10,223 @@
 // License for the specific language governing permissions and limitations under
 // the License.
 
-@import "../../../../../assets/less/animations.less";
 @import "../../../../../assets/less/variables.less";
 
-.keyframes(fadeInDownNoReduce, {
-    opacity: 0;
-    height: 0px;
-},
-{
-    opacity: 1;
-    height: 546px;
-});
-
-
-.keyframes(fadeInDownReduce, {
-    opacity: 0;
-    height: 0px;
-},
-{
-    opacity: 1;
-    height: 745px;
-});
-
-.keyframes(fadeOutUpReduce, {
-    opacity: 1;
-    height: 745px;
-},
-{
-    opacity: 0;
-    height: 0px;
-});
-
-.keyframes(fadeOutUpNoReduce, {
-    opacity: 1;
-    height: 546px;
-},
-{
-    opacity: 0;
-    height: 0px;
-});
-
-
-.fadeInDownNoReduce-enter {
- .animation(fadeInDownNoReduce 1s both);
-}
+.editor-wrapper {
 
-.fadeInDownNoReduce-leave {
- .animation(fadeOutUpNoReduce 1s both);
-}
 
-.fadeInDownReduce-enter {
- .animation(fadeInDownReduce 1s both);
-}
+  .define-view {
+    padding-bottom: 70px;
+  }
+
+  .define-view {
+    .help-link {
+      margin-left: 3px;
+    }
+  }
+  label {
+    font-size: 16px;
+  }
+  .bordered-box {
+    border-bottom: 1px solid #ccc;
+  }
+  .padded-box {
+    margin: 25px 30px;
+  }
+  .db-title {
+    color: @brandPrimary;
+    line-height: 30px;
+  }
+  .new-ddoc-input {
+    margin-top: 25px;
+  }
 
-.fadeInDownReduce-leave {
- .animation(fadeOutUpReduce 1s both);
+  .styled-select {
+    width: 250px;
+  }
+  .styled-select label {
+    margin: 0;
+  }
+  .styled-select select {
+    -webkit-appearance: none;
+    -moz-appearance: none;
+    appearance: none;
+    background-color: #e6e6e6;
+    border: 1px solid #b3b3b3;
+    height: 45px;
+    width: 250px;
+  }
+  .styled-select select:-moz-focusring {
+    color: transparent;
+    text-shadow: 0 0 0 #000;
+  }
+  .styled-select select::-ms-expand {
+    display: none;
+  }
+  .styled-select i {
+    position: absolute;
+    right: 10px;
+    top: 12px;
+    pointer-events: none;
+  }
 }
 
-#dashboard-upper-content{
-  .editor-wrapper {
-    padding-bottom: 70px;
+// 940px grid without margin
+// -------------------------
+@gridColumnWidthNoMargin:         60px;
+@gridGutterWidthNoMargin:         0px;
+@gridRowWidthNoMargin:            (@gridColumns * @gridColumnWidthNoMargin) + (@gridGutterWidthNoMargin * (@gridColumns - 1));
+
+// 1200px min
+@gridColumnWidth1200NoMargin:     70px;
+@gridGutterWidth1200NoMargin:     0px;
+@gridRowWidth1200NoMargin:        (@gridColumns * @gridColumnWidth1200NoMargin) + (@gridGutterWidth1200NoMargin * (@gridColumns - 1));
+
+// 768px-979px
+@gridColumnWidth768NoMargin:      42px;
+@gridGutterWidth768NoMargin:      0px;
+@gridRowWidth768NoMargin:         (@gridColumns * @gridColumnWidth768NoMargin) + (@gridGutterWidth768NoMargin * (@gridColumns - 1));
+// Fluid grid
+// -------------------------
+@fluidGridColumnWidthNoMargin:    percentage(@gridColumnWidthNoMargin/@gridRowWidthNoMargin);
+@fluidGridGutterWidthNoMargin:    percentage(@gridGutterWidthNoMargin/@gridRowWidthNoMargin);
+// 1200px min
+@fluidGridColumnWidth1200NoMargin:     percentage(@gridColumnWidth1200NoMargin/@gridRowWidth1200NoMargin);
+@fluidGridGutterWidth1200NoMargin:     percentage(@gridGutterWidth1200NoMargin/@gridRowWidth1200NoMargin);
+// 768px-979px
+@fluidGridColumnWidth768NoMargin:      percentage(@gridColumnWidth768NoMargin/@gridRowWidth768NoMargin);
+@fluidGridGutterWidth768NoMargin:      percentage(@gridGutterWidth768NoMargin/@gridRowWidth768NoMargin);
+
+
+.two-pane > .fluid(@fluidGridColumnWidth1200NoMargin, @fluidGridGutterWidth1200NoMargin);
+
+.two-pane {
+
+  .core (@gridColumnWidth, @gridGutterWidth) {
+
+    .spanX (@index) when (@index > 0) {
+      .span@{index} { .span(@index); }
+      .spanX(@index - 1);
+    }
+    .spanX (0) {}
+
+    .offsetX (@index) when (@index > 0) {
+      .offset@{index} { .offset(@index); }
+      .offsetX(@index - 1);
+    }
+    .offsetX (0) {}
+
+    .offset (@columns) {
+      margin-left: (@gridColumnWidth * @columns) + (@gridGutterWidth * (@columns + 1));
+    }
+
+    .span (@columns) {
+      width: (@gridColumnWidth * @columns) + (@gridGutterWidth * (@columns - 1));
+    }
+
+    .row {
+      margin-left: @gridGutterWidth * -1;
+      .clearfix();
+    }
+
+    [class*="span"] {
+      float: left;
+      min-height: 1px; // prevent collapsing columns
+      margin-left: @gridGutterWidth;
+    }
+
+    // Set the container width, and override it for fixed navbars in media queries
+    .container,
+    .navbar-static-top .container,
+    .navbar-fixed-top .container,
+    .navbar-fixed-bottom .container { .span(@gridColumns); }
+
+    // generate .spanX and .offsetX
+    .spanX (@gridColumns);
+    .offsetX (@gridColumns);
+
   }
 
-  .tab-content {
-    height: auto;
-    padding-top: 70px;
+  .fluid (@fluidGridColumnWidth, @fluidGridGutterWidth) {
+
+    .spanX (@index) when (@index > 0) {
+      .span@{index} { .span(@index); }
+      .spanX(@index - 1);
+    }
+    .spanX (0) {}
+
+    .offsetX (@index) when (@index > 0) {
+      .offset@{index} { .offset(@index); }
+      .offset@{index}:first-child { .offsetFirstChild(@index); }
+      .offsetX(@index - 1);
+    }
+    .offsetX (0) {}
+
+    .offset (@columns) {
+      margin-left: (@fluidGridColumnWidth * @columns) + (@fluidGridGutterWidth * (@columns - 1)) + (@fluidGridGutterWidth*2);
+      *margin-left: (@fluidGridColumnWidth * @columns) + (@fluidGridGutterWidth * (@columns - 1)) - (.5 / @gridRowWidth * 100 * 1%) + (@fluidGridGutterWidth*2) - (.5 / @gridRowWidth * 100 * 1%);
+    }
+
+    .offsetFirstChild (@columns) {
+      margin-left: (@fluidGridColumnWidth * @columns) + (@fluidGridGutterWidth * (@columns - 1)) + (@fluidGridGutterWidth);
+      *margin-left: (@fluidGridColumnWidth * @columns) + (@fluidGridGutterWidth * (@columns - 1)) - (.5 / @gridRowWidth * 100 * 1%) + @fluidGridGutterWidth - (.5 / @gridRowWidth * 100 * 1%);
+    }
+
+    .span (@columns) {
+      width: (@fluidGridColumnWidth * @columns) + (@fluidGridGutterWidth * (@columns - 1));
+      *width: (@fluidGridColumnWidth * @columns) + (@fluidGridGutterWidth * (@columns - 1)) - (.5 / @gridRowWidth * 100 * 1%);
+    }
+
+    .row-fluid {
+      width: 100%;
+      .clearfix();
+      [class*="span"] {
+        .input-block-level();
+        float: left;
+        margin-left: @fluidGridGutterWidth;
+        *margin-left: @fluidGridGutterWidth - (.5 / @gridRowWidth * 100 * 1%);
+      }
+      [class*="span"]:first-child {
+        margin-left: 0;
+      }
+
+      // Space grid-sized controls properly if multiple per line
+      .controls-row [class*="span"] + [class*="span"] {
+        margin-left: @fluidGridGutterWidth;
+      }
+
+      // generate .spanX and .offsetX
+      .spanX (@gridColumns);
+      .offsetX (@gridColumns);
+    }
+
   }
 
-  #define-view {
-    .help-link {
-      margin-left: 3px;
+  .input(@gridColumnWidth, @gridGutterWidth) {
+
+    .spanX (@index) when (@index > 0) {
+      input.span@{index}, textarea.span@{index}, .uneditable-input.span@{index} { .span(@index); }
+      .spanX(@index - 1);
     }
+    .spanX (0) {}
+
+    .span(@columns) {
+      width: ((@gridColumnWidth) * @columns) + (@gridGutterWidth * (@columns - 1)) - 14;
+    }
+
+    input,
+    textarea,
+    .uneditable-input {
+      margin-left: 0; // override margin-left from core grid system
+    }
+
+    // Space grid-sized controls properly if multiple per line
+    .controls-row [class*="span"] + [class*="span"] {
+      margin-left: @gridGutterWidth;
+    }
+
+    // generate .spanX
+    .spanX (@gridColumns);
+
   }
 }

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/e6f089aa/app/addons/documents/index-editor/actions.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/index-editor/actions.js b/app/addons/documents/index-editor/actions.js
index c731b90..2dc320f 100644
--- a/app/addons/documents/index-editor/actions.js
+++ b/app/addons/documents/index-editor/actions.js
@@ -39,11 +39,6 @@ function (app, FauxtonAPI, Documents, ActionTypes) {
   return {
     //helpers are added here for use in testing actions
     helpers: ActionHelpers,
-    toggleEditor: function () {
-      FauxtonAPI.dispatch({
-        type: ActionTypes.TOGGLE_EDITOR
-      });
-    },
 
     selectReduceChanged: function (reduceOption) {
       FauxtonAPI.dispatch({
@@ -96,7 +91,6 @@ function (app, FauxtonAPI, Documents, ActionTypes) {
 
       if (viewInfo.newDesignDoc) {
         designDoc = ActionHelpers.createNewDesignDoc(viewInfo.designDocId, viewInfo.database);
-
       } else {
         designDoc = ActionHelpers.findDesignDoc(designDocs, viewInfo.designDocId);
       }
@@ -123,30 +117,20 @@ function (app, FauxtonAPI, Documents, ActionTypes) {
             clear: true
           });
 
-          if (_.any([viewInfo.designDocChanged, viewInfo.newDesignDoc, viewInfo.newView])) {
+          if (_.any([viewInfo.designDocChanged, viewInfo.hasViewNameChanged, viewInfo.newDesignDoc, viewInfo.newView])) {
             FauxtonAPI.dispatch({
               type: ActionTypes.VIEW_SAVED
             });
-
             var fragment = '/database/' +
-              viewInfo.database.safeID() +
-              '/' + designDoc.safeID() +
-              '/_view/' +
-              app.utils.safeURLName(viewInfo.viewName);
-
-            FauxtonAPI.navigate(fragment);
+                viewInfo.database.safeID() +
+                '/' + designDoc.safeID() +
+                '/_view/' +
+                app.utils.safeURLName(viewInfo.viewName);
 
-            //This should be changed to a dispatch once implemented
-            FauxtonAPI.triggerRouteEvent('reloadDesignDocs', {
-              selectedTab: app.utils.removeSpecialCharacters(designDoc.id.replace(/_design\//,'')) + '_' + app.utils.removeSpecialCharacters(viewInfo.viewName)
-            });
-          } else {
-            FauxtonAPI.dispatch({
-              type: ActionTypes.VIEW_SAVED
-            });
-            //This will should be changed to a dispatch once implemented
-            FauxtonAPI.triggerRouteEvent('updateAllDocs', {ddoc: designDoc.id, view: viewInfo.viewName});
+            FauxtonAPI.navigate(fragment, {trigger: true});
           }
+
+          FauxtonAPI.triggerRouteEvent('updateAllDocs', {ddoc: designDoc.id, view: viewInfo.viewName});
         });
       }
     },

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/e6f089aa/app/addons/documents/index-editor/actiontypes.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/index-editor/actiontypes.js b/app/addons/documents/index-editor/actiontypes.js
index b2463da..fcce54e 100644
--- a/app/addons/documents/index-editor/actiontypes.js
+++ b/app/addons/documents/index-editor/actiontypes.js
@@ -14,7 +14,6 @@ define([], function () {
   return {
     EDIT_INDEX: 'EDIT_INDEX',
     EDIT_NEW_INDEX: 'EDIT_NEW_INDEX',
-    TOGGLE_EDITOR: 'TOGGLE_EDITOR',
     SELECT_REDUCE_CHANGE: 'SELECT_REDUCE_CHANGE',
     VIEW_SAVED: 'VIEW_SAVED',
     VIEW_CREATED: 'VIEW_CREATED',

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/e6f089aa/app/addons/documents/index-editor/components.react.jsx
----------------------------------------------------------------------
diff --git a/app/addons/documents/index-editor/components.react.jsx b/app/addons/documents/index-editor/components.react.jsx
index c1c81af..6d83683 100644
--- a/app/addons/documents/index-editor/components.react.jsx
+++ b/app/addons/documents/index-editor/components.react.jsx
@@ -24,19 +24,22 @@ function(app, FauxtonAPI, React, Stores, Actions, Components, beautifyHelper) {
   var indexEditorStore = Stores.indexEditorStore;
   var getDocUrl = app.helpers.getDocUrl;
 
-  var ToggleButton = React.createClass({
-
-    render: function() {
+  // global component
+  var StyledSelect = React.createClass({
+    render: function () {
       return (
-        <div className="dashboard-upper-menu">
-          <ul className="nav nav-tabs" id="db-views-tabs-nav">
-            <li>
-              <a ref="toggle" data-bypass="true" id="index-nav" data-toggle="tab" href="#index" onClick={this.props.toggleEditor}>
-                <i className="fonticon-wrench fonticon"></i>
-                {this.props.title}
-              </a>
-            </li>
-          </ul>
+        <div className="styled-select">
+          <label htmlFor={this.props.selectId}>
+            <i className="fonticon-down-dir"></i>
+            <select
+              value={this.props.selectValue}
+              id={this.props.selectId}
+              className={this.props.selectValue}
+              onChange={this.props.selectChange}
+            >
+              {this.props.selectContent}
+            </select>
+          </label>
         </div>
       );
     }
@@ -58,10 +61,9 @@ function(app, FauxtonAPI, React, Stores, Actions, Components, beautifyHelper) {
 
     getNewDesignDocInput: function () {
       return (
-        <div id="new-ddoc-section" className="span5">
-          <label className="control-label" htmlFor="new-ddoc"> _design/ </label>
-          <div className="controls">
-            <input value={this.state.designDoc} type="text" id="new-ddoc" onChange={this.onDesignDocChange} placeholder="newDesignDoc" />
+        <div className="new-ddoc-section">
+          <div className="new-ddoc-input">
+            <input value={this.state.designDoc} type="text" id="new-ddoc" onChange={this.onDesignDocChange} placeholder="Enter a Design Doc name" />
           </div>
         </div>
       );
@@ -77,8 +79,18 @@ function(app, FauxtonAPI, React, Stores, Actions, Components, beautifyHelper) {
       });
     },
 
-    render: function () {
+    getSelectContent: function () {
       var designDocOptions = this.getDesignDocOptions();
+
+      return (
+        <optgroup label="Select a document">
+          <option value="new">New Design Document </option>
+          {designDocOptions}
+        </optgroup>
+      );
+    },
+
+    render: function () {
       var designDocInput;
       var designDocId = this.state.designDocId;
 
@@ -88,23 +100,30 @@ function(app, FauxtonAPI, React, Stores, Actions, Components, beautifyHelper) {
       }
 
       return (
-        <div className="control-group design-doc-group">
-          <div className="span3">
-            <label htmlFor="ddoc">Save to Design Document
-              <a className="help-link" data-bypass="true" href={getDocUrl('DESIGN_DOCS')} target="_blank">
-                <i className="icon-question-sign">
-                </i>
-              </a>
-            </label>
-            <select id="ddoc" value={designDocId} onChange={this.selectChange}>
-              <optgroup label="Select a document">
-                <option value="new">New Design Document </option>
-                {designDocOptions}
-              </optgroup>
-            </select>
+        <div className="new-ddoc-section">
+          <div className="bordered-box">
+            <div className="padded-box">
+              <div className="control-group design-doc-group">
+                <div className="pull-left">
+                  <label htmlFor="ddoc"><strong>Design Document</strong>
+                    <a className="help-link" data-bypass="true" href={getDocUrl('DESIGN_DOCS')} target="_blank">
+                      <i className="icon-question-sign">
+                      </i>
+                    </a>
+                  </label>
+                  <StyledSelect
+                    selectContent={this.getSelectContent()}
+                    selectChange={this.selectChange}
+                    selectId="ddoc"
+                    selectValue={designDocId}
+                  />
+                </div>
+                <div className="pull-left">
+                  {designDocInput}
+                </div>
+              </div>
+            </div>
           </div>
-
-          {designDocInput}
         </div>
       );
     },
@@ -189,7 +208,7 @@ function(app, FauxtonAPI, React, Stores, Actions, Components, beautifyHelper) {
       return (
         <div className="control-group">
           <label htmlFor="ace-function">
-            {this.props.title}
+            <strong>{this.props.title}</strong>
             {docsLink}
           </label>
           <div className="js-editor" id={this.props.id}>{this.props.code}</div>
@@ -280,18 +299,28 @@ function(app, FauxtonAPI, React, Stores, Actions, Components, beautifyHelper) {
       customReduceSection;
 
       if (this.state.hasCustomReduce) {
-        //customReduceSection = <CustomReduce ref="reduceEditor" reduce={this.state.reduce} />;
         customReduceSection = <CodeEditor ref='reduceEditor' id={'reduce-function'} code={this.state.reduce} docs={false} title={'Custom Reduce function'} />;
       }
 
       return (
         <div>
           <div className="control-group">
-            <label htmlFor="reduce-function-selector">Reduce (optional)<a className="help-link" data-bypass="true" href={getDocUrl('REDUCE_FUNCS')} target="_blank"><i className="icon-question-sign"></i></a></label>
-
-            <select id="reduce-function-selector" value={this.state.reduceSelectedOption} onChange={this.selectChange}>
-              {reduceOptions}
-            </select>
+            <label htmlFor="reduce-function-selector">
+              <strong>Reduce (optional)</strong>
+              <a
+                className="help-link"
+                data-bypass="true"
+                href={getDocUrl('REDUCE_FUNCS')}
+                target="_blank"
+              >
+                <i className="icon-question-sign"></i>
+              </a>
+            </label>
+            <StyledSelect
+              selectContent={reduceOptions}
+              selectChange={this.selectChange}
+              selectId="reduce-function-selector"
+              selectValue={this.state.reduceSelectedOption} />
           </div>
 
           {customReduceSection}
@@ -363,6 +392,7 @@ function(app, FauxtonAPI, React, Stores, Actions, Components, beautifyHelper) {
   var Editor = React.createClass({
     getStoreState: function () {
       return {
+        hasViewNameChanged: indexEditorStore.hasViewNameChanged(),
         database: indexEditorStore.getDatabase(),
         isNewView: indexEditorStore.isNewView(),
         viewName: indexEditorStore.getViewName(),
@@ -400,6 +430,16 @@ function(app, FauxtonAPI, React, Stores, Actions, Components, beautifyHelper) {
       }, this);
     },
 
+    clearNotifications: function () {
+      ['mapEditor', 'reduceEditor'].forEach(function (editorName) {
+        if (editorName === 'reduceEditor' && !indexEditorStore.hasCustomReduce()) {
+          return;
+        }
+        var editor = this.refs[editorName].getEditor();
+        editor.editSaved();
+      }.bind(this));
+    },
+
     saveView: function (event) {
       event.preventDefault();
 
@@ -412,6 +452,8 @@ function(app, FauxtonAPI, React, Stores, Actions, Components, beautifyHelper) {
         return;
       }
 
+      this.clearNotifications();
+
       Actions.saveView({
         database: this.state.database,
         newView: this.state.isNewView,
@@ -419,6 +461,7 @@ function(app, FauxtonAPI, React, Stores, Actions, Components, beautifyHelper) {
         designDocId: this.state.designDocId,
         newDesignDoc: this.state.newDesignDoc,
         designDocChanged: this.state.hasDesignDocChanged,
+        hasViewNameChanged: this.state.hasViewNameChanged,
         map: this.refs.mapEditor.getValue(),
         reduce: this.refs.reduceEditor.getReduceValue(),
         designDocs: this.state.designDocs
@@ -431,29 +474,68 @@ function(app, FauxtonAPI, React, Stores, Actions, Components, beautifyHelper) {
 
     render: function () {
       return (
-        <div className="tab-content" >
-          <div className="tab-pane active" id="index">
-            <div id="define-view" className="ddoc-alert well">
-              <form className="form-horizontal view-query-save" onSubmit={this.saveView}>
-
-                <DesignDocSelector />
-
-                <div className="control-group">
-                  <label htmlFor="index-name">Index name<a className="help-link" data-bypass="true" href={getDocUrl('VIEW_FUNCS')} target="_blank"><i className="icon-question-sign"></i></a></label>
-                  <input type="text" id="index-name" value={this.state.viewName} onChange={this.viewChange} placeholder="Index name" />
-                </div>
-
-                <CodeEditor id={'map-function'} ref="mapEditor" title={"Map function"} docs={'MAP_FUNCS'} code={this.state.map}/>
-                <ReduceEditor ref="reduceEditor"/>
-
-                <div className="control-group">
-                  <button className="btn btn-success save"><i className="icon fonticon-ok-circled"></i> Save &amp; Build Index</button>
-                  <DeleteView />
-                </div>
-              </form>
+        <div className="define-view">
+          <div className="bordered-box">
+            <div className="padded-box">
+              Views are the primary tools for querying and reporting.
+            </div>
+          </div>
+          <div className="bordered-box">
+            <div className="padded-box">
+              <strong>Database</strong>
+              <div className="db-title">{this.state.database.id}</div>
             </div>
-
           </div>
+          <form className="form-horizontal view-query-save" onSubmit={this.saveView}>
+            <DesignDocSelector />
+            <div className="control-group">
+              <div className="bordered-box">
+                <div className="padded-box">
+                  <label htmlFor="index-name">
+                    <strong>Index name</strong>
+                    <a
+                      className="help-link"
+                      data-bypass="true"
+                      href={getDocUrl('VIEW_FUNCS')}
+                      target="_blank">
+                      <i className="icon-question-sign"></i>
+                    </a>
+                  </label>
+                  <input
+                    type="text"
+                    id="index-name"
+                    value={this.state.viewName}
+                    onChange={this.viewChange}
+                    placeholder="Index name" />
+                 </div>
+              </div>
+            </div>
+            <div className="control-group">
+              <div className="bordered-box">
+                <div className="padded-box">
+                  <CodeEditor
+                    id={'map-function'}
+                    ref="mapEditor"
+                    title={"Map function"}
+                    docs={'MAP_FUNCS'}
+                    code={this.state.map} />
+                 </div>
+              </div>
+            </div>
+            <div className="bordered-box">
+              <div className="padded-box">
+                <ReduceEditor ref="reduceEditor" />
+              </div>
+            </div>
+            <div className="padded-box">
+              <div className="control-group">
+                <button type="submit" className="btn btn-success save">
+                  <i className="icon fonticon-ok-circled"></i> Save &amp; Build Index
+                </button>
+                <DeleteView />
+              </div>
+            </div>
+          </form>
         </div>
       );
     }
@@ -464,17 +546,10 @@ function(app, FauxtonAPI, React, Stores, Actions, Components, beautifyHelper) {
   var EditorController = React.createClass({
     getInitialState: function () {
       return {
-        showEditor: indexEditorStore.showEditor(),
-        isNewView: indexEditorStore.isNewView(),
-        title: indexEditorStore.getTitle(),
-        hasCustomReduce: indexEditorStore.hasCustomReduce()
+        title: indexEditorStore.getTitle()
       };
     },
 
-    onChange: function () {
-      this.setState({showEditor: indexEditorStore.showEditor()});
-    },
-
     componentDidMount: function() {
       indexEditorStore.on('change', this.onChange, this);
     },
@@ -488,28 +563,9 @@ function(app, FauxtonAPI, React, Stores, Actions, Components, beautifyHelper) {
     },
 
     render: function () {
-      var editor = null;
-      //a bit of hack for now.
-      var wrapperClassName = 'editor-wrapper';
-      var doTransitions = !this.state.isNewView;
-      var editorTransitionName = 'fadeInDownNoReduce';
-
-      if (this.state.showEditor) {
-        //key is needed for animation;
-        editor = <Editor key={1} />;
-        wrapperClassName = '';
-
-        if (this.state.hasCustomReduce) {
-          editorTransitionName = 'fadeInDownReduce';
-        }
-      }
-
       return (
-        <div className={wrapperClassName}>
-          <ToggleButton title={this.state.title} toggleEditor={this.toggleEditor} />
-          <ReactCSSTransitionGroup transitionName={editorTransitionName} transitionLeave={doTransitions} transitionEnter={doTransitions}>
-            {editor}
-          </ReactCSSTransitionGroup>
+        <div className="editor-wrapper span5 scrollable">
+          <Editor />
         </div>
       );
     }
@@ -523,11 +579,11 @@ function(app, FauxtonAPI, React, Stores, Actions, Components, beautifyHelper) {
     removeEditor: function (el) {
       React.unmountComponentAtNode(el);
     },
-    ToggleButton: ToggleButton,
     ReduceEditor: ReduceEditor,
     Editor: Editor,
     DesignDocSelector: DesignDocSelector,
-    Beautify: Beautify
+    Beautify: Beautify,
+    StyledSelect: StyledSelect
   };
 
   return Views;

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/e6f089aa/app/addons/documents/index-editor/stores.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/index-editor/stores.js b/app/addons/documents/index-editor/stores.js
index cff8ba6..198a440 100644
--- a/app/addons/documents/index-editor/stores.js
+++ b/app/addons/documents/index-editor/stores.js
@@ -30,8 +30,8 @@ function(FauxtonAPI, ActionTypes) {
       this._viewName = options.viewName || 'viewName';
       this._designDocs = options.designDocs;
       this._designDocId = options.designDocId;
-      this._showEditor = this._newView;
       this._designDocChanged = false;
+      this._viewNameChanged = false;
 
       if (!this._newView && !this._newDesignDoc) {
         this._view = this.getDesignDoc().get('views')[this._viewName];
@@ -106,14 +106,11 @@ function(FauxtonAPI, ActionTypes) {
 
     setViewName: function (name) {
       this._viewName = name;
-    },
-
-    showEditor: function () {
-      return this._showEditor;
+      this._viewNameChanged = true;
     },
 
     hasCustomReduce: function () {
-      if (!this.hasReduce()) {return false; }
+      if (!this.hasReduce()) { return false; }
 
       return !_.contains(this.builtInReduces(), this.getReduce());
     },
@@ -124,6 +121,10 @@ function(FauxtonAPI, ActionTypes) {
       return true;
     },
 
+    hasViewNameChanged: function () {
+      return this._viewNameChanged;
+    },
+
     builtInReduces: function () {
       return ['_sum', '_count', '_stats'];
     },
@@ -175,11 +176,6 @@ function(FauxtonAPI, ActionTypes) {
           this.triggerChange();
         break;
 
-        case ActionTypes.TOGGLE_EDITOR:
-          this._showEditor = !this._showEditor;
-          this.triggerChange();
-        break;
-
         case ActionTypes.SELECT_REDUCE_CHANGE:
           this.updateReduceFromSelect(action.reduceSelectedOption);
           this.triggerChange();

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/e6f089aa/app/addons/documents/index-results/index-results.components.react.jsx
----------------------------------------------------------------------
diff --git a/app/addons/documents/index-results/index-results.components.react.jsx b/app/addons/documents/index-results/index-results.components.react.jsx
new file mode 100644
index 0000000..8c77739
--- /dev/null
+++ b/app/addons/documents/index-results/index-results.components.react.jsx
@@ -0,0 +1,52 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+define([
+  'app',
+  'api',
+  'react'
+],
+
+function (app, FauxtonAPI, React) {
+
+  var NoResultScreen = React.createClass({
+    render: function () {
+      return (
+        <div className="watermark-logo">
+          <h3>No Index Created Yet!</h3>
+        </div>
+      );
+    }
+  });
+
+  var ViewResultListController = React.createClass({
+    render: function () {
+      var view = <NoResultScreen />;
+
+      return (
+        view
+      );
+    }
+  });
+
+  var Views = {
+    renderViewResultList: function (el) {
+      React.render(<ViewResultListController />, el);
+    },
+    removeViewResultList: function (el) {
+      React.unmountComponentAtNode(el);
+    },
+    List: ViewResultListController
+  };
+
+  return Views;
+});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/e6f089aa/app/addons/documents/routes-documents.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/routes-documents.js b/app/addons/documents/routes-documents.js
index 5d5e2af..488ff6b 100644
--- a/app/addons/documents/routes-documents.js
+++ b/app/addons/documents/routes-documents.js
@@ -36,39 +36,20 @@ function(app, FauxtonAPI, BaseRoute, Documents, Changes, Index, DocEditor, Datab
         route: "allDocs",
         roles: ["fx_loggedIn"]
       },
-      "database/:database/_design/:ddoc/_view/:view": {
-        route: "viewFn",
-        roles: ['fx_loggedIn']
-      },
-      "database/:database/_design/:ddoc/_lists/:fn": {
-        route: "tempFn",
-        roles: ['fx_loggedIn']
-      },
-      "database/:database/_design/:ddoc/_filters/:fn": {
-        route: "tempFn",
-        roles: ['fx_loggedIn']
-      },
-      "database/:database/_design/:ddoc/_show/:fn": {
-        route: "tempFn",
-        roles: ['fx_loggedIn']
-      },
       "database/:database/_design/:ddoc/_info": {
         route: "designDocMetadata",
         roles: ['fx_loggedIn']
       },
-      "database/:database/new_view": "newViewEditor",
-      "database/:database/new_view/:designDoc": "newViewEditor",
       "database/:database/_changes(:params)": "changes"
     },
 
     events: {
-      "route:updateAllDocs": "updateAllDocsFromView",
       "route:reloadDesignDocs": "reloadDesignDocs",
-      "route:paginate": "paginate",
-      "route:perPageChange": "perPageChange",
       "route:changesFilterAdd": "addFilter",
       "route:changesFilterRemove": "removeFilter",
-      "route:updateQueryOptions": "updateQueryOptions"
+      'route:updateAllDocs': 'updateAllDocsFromView',
+      'route:paginate': 'paginate',
+      'route:perPageChange': 'perPageChange',
     },
 
     initialize: function (route, masterLayout, options) {
@@ -139,26 +120,6 @@ function(app, FauxtonAPI, BaseRoute, Documents, Changes, Index, DocEditor, Datab
       this.apiUrl = [designDocInfo.url('apiurl'), designDocInfo.documentation()];
     },
 
-    tempFn: function(databaseName, ddoc, fn){
-      this.setView("#dashboard-upper-content", new Documents.Views.temp({}));
-      this.crumbs = function () {
-        return [
-          {"name": this.database.id, "link": Databases.databaseUrl(this.database)},
-        ];
-      };
-    },
-
-    createParams: function (options) {
-      var urlParams = app.getParams(options),
-          params = Documents.QueryParams.parse(urlParams),
-          limit = this.getDocPerPageLimit(params, FauxtonAPI.constants.MISC.DEFAULT_PAGE_SIZE);
-
-      return {
-        urlParams: urlParams,
-        docParams: _.extend(params, {limit: limit})
-      };
-    },
-
     /*
      * docParams are the options collection uses to fetch from the server
      * urlParams are what are shown in the url and to the user
@@ -236,219 +197,6 @@ function(app, FauxtonAPI, BaseRoute, Documents, Changes, Index, DocEditor, Datab
       this.rightHeader.showQueryOptions();
     },
 
-    viewFn: function (databaseName, ddoc, viewName) {
-      var params = this.createParams(),
-          urlParams = params.urlParams,
-          docParams = params.docParams,
-          decodeDdoc = decodeURIComponent(ddoc);
-
-      viewName = viewName.replace(/\?.*$/,'');
-
-      this.footer = this.setView('#footer', new Documents.Views.Footer());
-
-      this.indexedDocs = new Documents.IndexCollection(null, {
-        database: this.database,
-        design: decodeDdoc,
-        view: viewName,
-        params: docParams,
-        paging: {
-          pageSize: this.getDocPerPageLimit(urlParams, parseInt(docParams.limit, 10))
-        }
-      });
-
-      this.viewEditor = this.setView("#dashboard-upper-content", new Index.ViewEditorReact({
-        viewName: viewName,
-        newView: false,
-        database: this.database,
-        designDocs: this.designDocs,
-        designDocId: "_design/" + decodeDdoc
-      }));
-
-      this.toolsView && this.toolsView.remove();
-
-      this.documentsView = this.createViewDocumentsView({
-        designDoc: decodeDdoc,
-        docParams: docParams,
-        urlParams: urlParams,
-        database: this.database,
-        indexedDocs: this.indexedDocs,
-        designDocs: this.designDocs,
-        view: viewName
-      });
-
-      this.sidebar.setSelectedTab(app.utils.removeSpecialCharacters(ddoc) + '_' + app.utils.removeSpecialCharacters(viewName));
-
-      this.apiUrl = function() {
-        return [this.indexedDocs.urlRef("apiurl", urlParams), FauxtonAPI.constants.DOC_URLS.GENERAL];
-      };
-
-      this.showQueryOptions(urlParams, ddoc, viewName);
-    },
-
-    showQueryOptions: function (urlParams, ddoc, viewName) {
-      var promise = this.designDocs.fetch({reset: true}),
-      that = this,
-      hasReduceFunction;
-
-      promise.then(function(resp) {
-        var design = _.findWhere(that.designDocs.models, {id: '_design/'+ddoc}); 
-        !_.isUndefined(hasReduceFunction = design.attributes.doc.views[viewName].reduce);
-
-        that.rightHeader.showQueryOptions();
-        that.rightHeader.resetQueryOptions({
-          queryParams: urlParams,
-          showStale: true,
-          hasReduce: hasReduceFunction,
-          viewName: viewName,
-          ddocName: ddoc
-        });
-      });
-    },
-
-    ddocInfo: function (designDoc, designDocs, view) {
-      return {
-        id: "_design/" + designDoc,
-        currView: view,
-        designDocs: designDocs
-      };
-    },
-
-    createViewDocumentsView: function (options) {
-      if (!options.docParams) {
-        options.docParams = {};
-      }
-
-      this.perPageDefault = options.docParams.limit || FauxtonAPI.constants.MISC.DEFAULT_PAGE_SIZE;
-
-      this.pagination = new Components.IndexPagination({
-        collection: options.indexedDocs,
-        scrollToSelector: '.scrollable',
-        docLimit: options.urlParams.limit,
-        perPage: this.perPageDefault
-      });
-      this.setView('#documents-pagination', this.pagination);
-
-      this.allDocsNumber = new Documents.Views.AllDocsNumber({
-        collection: options.indexedDocs,
-        pagination: this.pagination,
-        perPageDefault: this.perPageDefault
-      });
-
-      this.setView('#item-numbers', this.allDocsNumber);
-
-      return this.setView("#dashboard-lower-content", new Documents.Views.AllDocsList({
-        pagination: this.pagination,
-        allDocsNumber: this.allDocsNumber,
-        database: options.database,
-        collection: options.indexedDocs,
-        viewList: true,
-        ddocInfo: this.ddocInfo(options.designDoc, options.designDocs, options.view),
-        docParams: options.docParams,
-        perPageDefault: this.perPageDefault,
-      }));
-    },
-
-    newViewEditor: function (database, _designDoc) {
-      var params = app.getParams();
-      var newDesignDoc = true;
-      var designDoc;
-        
-      if (!_.isUndefined(_designDoc)) {
-        designDoc = "_design/" + _designDoc;
-        newDesignDoc = false;
-      }
-
-      this.footer && this.footer.remove();
-      this.toolsView && this.toolsView.remove();
-      this.documentsView && this.documentsView.remove();
-
-      this.viewEditor = this.setView("#dashboard-upper-content", new Index.ViewEditorReact({
-        viewName: 'new-view',
-        newView: true,
-        database: this.database,
-        designDocs: this.designDocs,
-        designDocId: designDoc,
-        newDesignDoc: newDesignDoc
-      }));
-
-      this.sidebar.setSelectedTab("new-view");
-      this.rightHeader.hideQueryOptions();
-
-      // clear out anything that was in the lower section
-      this.removeView("#dashboard-lower-content");
-    },
-
-    updateAllDocsFromView: function (event) {
-      var view = event.view,
-          params = this.createParams(),
-          urlParams = params.urlParams,
-          docParams = params.docParams,
-          ddoc = event.ddoc,
-          defaultPageSize,
-          isLazyInit,
-          pageSize,
-          collection;
-
-      isLazyInit = _.isUndefined(this.documentsView) || _.isUndefined(this.documentsView.allDocsNumber);
-      defaultPageSize = isLazyInit ? FauxtonAPI.constants.MISC.DEFAULT_PAGE_SIZE : this.documentsView.perPage();
-      docParams.limit = pageSize = this.getDocPerPageLimit(urlParams, defaultPageSize);
-
-      if (event.allDocs) {
-        this.eventAllDocs = true; // this is horrible. But I cannot get the trigger not to fire the route!
-        this.database.buildAllDocs(docParams);
-        collection = this.database.allDocs;
-        collection.paging.pageSize = pageSize;
-      } else {
-        collection = this.indexedDocs = new Documents.IndexCollection(null, {
-          database: this.database,
-          design: ddoc,
-          view: view,
-          params: docParams,
-          paging: {
-            pageSize: pageSize
-          }
-        });
-
-        if (!this.documentsView) {
-          this.documentsView = this.createViewDocumentsView({
-            designDoc: ddoc,
-            docParams: docParams,
-            urlParams: urlParams,
-            database: this.database,
-            indexedDocs: this.indexedDocs,
-            designDocs: this.designDocs,
-            view: view
-          });
-        }
-      }
-
-      this.documentsView.setParams(docParams, urlParams);
-
-      // this will lazily initialize all sub-views and render them
-      this.documentsView.forceRender();
-    },
-
-    perPageChange: function (perPage) {
-      // We need to restore the collection parameters to the defaults (1st page)
-      // and update the page size
-      this.perPage = perPage;
-      this.documentsView.forceRender();
-      this.documentsView.collection.pageSizeReset(perPage, {fetch: false});
-      this.allDocsNumber.forceRender();
-      this.setDocPerPageLimit(perPage);
-    },
-
-    paginate: function (options) {
-      var collection = this.documentsView.collection;
-      this.documentsView.collection.reset(collection);
-
-      this.documentsView.forceRender();
-      this.allDocsNumber.forceRender();
-
-      collection.paging.pageSize = options.perPage;
-      var promise = collection[options.direction]({fetch: false});
-    },
-
     reloadDesignDocs: function (event) {
       this.sidebar.forceRender();
 
@@ -457,31 +205,6 @@ function(app, FauxtonAPI, BaseRoute, Documents, Changes, Index, DocEditor, Datab
       }
     },
 
-    setDocPerPageLimit: function (perPage) {
-      app.utils.localStorageSet('fauxton:perpage', perPage);
-    },
-
-    getDocPerPageLimit: function (urlParams, perPage) {
-      var storedPerPage = perPage;
-
-      if (window.localStorage) {
-        storedPerPage = app.utils.localStorageGet('fauxton:perpage');
-
-        if (!storedPerPage) {
-          this.setDocPerPageLimit(perPage);
-          storedPerPage = perPage;
-        } else {
-          storedPerPage = parseInt(storedPerPage, 10);
-        }
-      }
-
-      if (!urlParams.limit || urlParams.limit > storedPerPage) {
-        return parseInt(storedPerPage, 10);
-      } else {
-        return parseInt(urlParams.limit, 10);
-      }
-    },
-
     changes: function () {
       var docParams = app.getParams();
       this.database.buildChanges(docParams);
@@ -521,10 +244,6 @@ function(app, FauxtonAPI, BaseRoute, Documents, Changes, Index, DocEditor, Datab
       this.changesView.render();
     },
 
-    updateQueryOptions: function(options) {
-      this.rightHeader.updateQueryOptions(options);
-    },
-
     cleanup: function () {
       if (this.reactHeader) {
         this.removeView('#react-headerbar');

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/e6f089aa/app/addons/documents/routes-index-editor.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/routes-index-editor.js b/app/addons/documents/routes-index-editor.js
new file mode 100644
index 0000000..250dafc
--- /dev/null
+++ b/app/addons/documents/routes-index-editor.js
@@ -0,0 +1,156 @@
+// Licensed under the Apache License, Version 2.0 (the 'License'); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an 'AS IS' BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+define([
+  'app',
+  'api',
+
+  // Modules
+  'addons/documents/shared-routes',
+  'addons/documents/views',
+  'addons/documents/views-index',
+  'addons/databases/base',
+  'addons/fauxton/components'
+
+],
+
+function (app, FauxtonAPI, BaseRoute, Documents, Index, Databases, Components) {
+
+
+  var IndexEditorAndResults = BaseRoute.extend({
+    layout: 'two_pane',
+    routes: {
+      'database/:database/new_view': 'newViewEditor',
+      'database/:database/new_view/:designDoc': 'newViewEditor',
+      'database/:database/_design/:ddoc/_view/:view': {
+        route: 'viewFn',
+        roles: ['fx_loggedIn']
+      }
+    },
+
+    events: {
+      'route:updateAllDocs': 'updateAllDocsFromView',
+      'route:paginate': 'paginate',
+      'route:perPageChange': 'perPageChange',
+    },
+
+    initialize: function (route, masterLayout, options) {
+      var databaseName = options[0];
+
+      this.databaseName = databaseName;
+      this.database = new Databases.Model({id: databaseName});
+      this.allDatabases = new Databases.List();
+      this.createDesignDocsCollection();
+    },
+
+    establish: function () {
+      return [
+        this.designDocs.fetch({reset: true}),
+        this.allDatabases.fetchOnce()
+      ];
+    },
+
+    viewFn: function (databaseName, ddoc, viewName) {
+      var params = this.createParams(),
+          urlParams = params.urlParams,
+          docParams = params.docParams,
+          decodeDdoc = decodeURIComponent(ddoc);
+
+
+      this.rightHeader = this.setView('#right-header', new Documents.Views.RightAllDocsHeader({
+        database: this.database
+      }));
+
+
+      this.breadcrumbs = this.setView('#breadcrumbs', new Components.Breadcrumbs({
+        toggleDisabled: true,
+        crumbs: [
+          {'type': 'back', 'link': Databases.databaseUrl(this.database)},
+          {'name': this.database.id, 'link': Databases.databaseUrl(this.database) }
+        ]
+      }));
+
+      viewName = viewName.replace(/\?.*$/,'');
+
+      this.footer = this.setView('#footer', new Documents.Views.Footer());
+
+      this.indexedDocs = new Documents.IndexCollection(null, {
+        database: this.database,
+        design: decodeDdoc,
+        view: viewName,
+        params: docParams,
+        paging: {
+          pageSize: this.getDocPerPageLimit(urlParams, parseInt(docParams.limit, 10))
+        }
+      });
+
+      this.viewEditor = this.setView('#left-content', new Index.ViewEditorReact({
+        viewName: viewName,
+        newView: false,
+        database: this.database,
+        designDocs: this.designDocs,
+        designDocId: '_design/' + decodeDdoc
+      }));
+
+      this.documentsView = this.createViewDocumentsView({
+        designDoc: decodeDdoc,
+        docParams: docParams,
+        urlParams: urlParams,
+        database: this.database,
+        indexedDocs: this.indexedDocs,
+        designDocs: this.designDocs,
+        view: viewName
+      });
+
+      this.apiUrl = function () {
+        return [this.indexedDocs.urlRef('apiurl', urlParams), FauxtonAPI.constants.DOC_URLS.GENERAL];
+      };
+
+      this.showQueryOptions(urlParams, ddoc, viewName);
+    },
+
+    newViewEditor: function (database, _designDoc) {
+      var params = app.getParams();
+      var newDesignDoc = true;
+      var designDoc;
+
+      if (_designDoc) {
+        designDoc = '_design/' + _designDoc;
+        newDesignDoc = false;
+      }
+
+      this.breadcrumbs = this.setView('#breadcrumbs', new Components.Breadcrumbs({
+        toggleDisabled: true,
+        crumbs: [
+          {'type': 'back', 'link': Databases.databaseUrl(this.database)},
+          {'name': 'Create new index', 'link': Databases.databaseUrl(this.database) }
+        ]
+      }));
+
+      this.viewEditor = this.setView('#left-content', new Index.ViewEditorReact({
+        viewName: 'new-view',
+        newView: true,
+        database: this.database,
+        designDocs: this.designDocs,
+        designDocId: designDoc,
+        newDesignDoc: newDesignDoc
+      }));
+
+      this.resultList = this.setView('#dashboard-lower-content', new Index.ViewResultListReact({
+        documents: null
+      }));
+    }
+
+  });
+
+  return IndexEditorAndResults;
+});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/e6f089aa/app/addons/documents/routes.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/routes.js b/app/addons/documents/routes.js
index 4756665..5c1e5a1 100644
--- a/app/addons/documents/routes.js
+++ b/app/addons/documents/routes.js
@@ -13,15 +13,17 @@
 define([
   "addons/documents/views",
   "addons/documents/routes-documents",
-  "addons/documents/routes-doc-editor"
+  'addons/documents/routes-doc-editor',
+  'addons/documents/routes-index-editor'
 ],
 
-function(Documents, DocumentsRouteObject, docEditor) {
+function(Documents, DocumentsRouteObject, docEditor, IndexEditorRouteObject) {
 
   Documents.RouteObjects = [
     docEditor.DocEditorRouteObject, 
     docEditor.NewDocEditorRouteObject, 
-    DocumentsRouteObject
+    DocumentsRouteObject,
+    IndexEditorRouteObject
   ];
 
   return Documents;

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/e6f089aa/app/addons/documents/shared-routes.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/shared-routes.js b/app/addons/documents/shared-routes.js
index 9564530..8c0db94 100644
--- a/app/addons/documents/shared-routes.js
+++ b/app/addons/documents/shared-routes.js
@@ -29,6 +29,26 @@ define([
       });
     },
 
+    showQueryOptions: function (urlParams, ddoc, viewName) {
+      var promise = this.designDocs.fetch({reset: true}),
+      that = this,
+      hasReduceFunction;
+
+      promise.then(function (resp) {
+        var design = _.findWhere(that.designDocs.models, {id: '_design/'+ddoc});
+        !_.isUndefined(hasReduceFunction = design.attributes.doc.views[viewName].reduce);
+
+        that.rightHeader.showQueryOptions();
+        that.rightHeader.resetQueryOptions({
+          queryParams: urlParams,
+          showStale: true,
+          hasReduce: hasReduceFunction,
+          viewName: viewName,
+          ddocName: ddoc
+        });
+      });
+    },
+
     addLeftHeader: function () {
       this.leftheader = this.setView('#breadcrumbs', new Components.LeftHeader({
         crumbs: this.getCrumbs(this.database),
@@ -62,6 +82,159 @@ define([
         { "type": "back", "link": FauxtonAPI.urls('allDBs', 'app')},
         { "name": database.id, "link": FauxtonAPI.urls('allDocs', 'app', dbname, '?limit=' + Databases.DocLimit), className: "lookahead-tray-link" }
       ];
+    },
+
+    // document-list
+
+    setDocPerPageLimit: function (perPage) {
+      app.utils.localStorageSet('fauxton:perpage', perPage);
+    },
+
+    createViewDocumentsView: function (options) {
+      if (!options.docParams) {
+        options.docParams = {};
+      }
+
+      this.perPageDefault = options.docParams.limit || FauxtonAPI.constants.MISC.DEFAULT_PAGE_SIZE;
+
+      this.pagination = new Components.IndexPagination({
+        collection: options.indexedDocs,
+        scrollToSelector: '.scrollable',
+        docLimit: options.urlParams.limit,
+        perPage: this.perPageDefault
+      });
+      this.setView('#documents-pagination', this.pagination);
+
+      this.allDocsNumber = new Documents.Views.AllDocsNumber({
+        collection: options.indexedDocs,
+        pagination: this.pagination,
+        perPageDefault: this.perPageDefault
+      });
+
+      this.setView('#item-numbers', this.allDocsNumber);
+
+      return this.setView("#dashboard-lower-content", new Documents.Views.AllDocsList({
+        pagination: this.pagination,
+        allDocsNumber: this.allDocsNumber,
+        database: options.database,
+        collection: options.indexedDocs,
+        viewList: true,
+        ddocInfo: this.ddocInfo(options.designDoc, options.designDocs, options.view),
+        docParams: options.docParams,
+        perPageDefault: this.perPageDefault,
+      }));
+    },
+
+    ddocInfo: function (designDoc, designDocs, view) {
+      return {
+        id: "_design/" + designDoc,
+        currView: view,
+        designDocs: designDocs
+      };
+    },
+
+    getDocPerPageLimit: function (urlParams, perPage) {
+      var storedPerPage = perPage;
+
+      if (window.localStorage) {
+        storedPerPage = app.utils.localStorageGet('fauxton:perpage');
+
+        if (!storedPerPage) {
+          this.setDocPerPageLimit(perPage);
+          storedPerPage = perPage;
+        } else {
+          storedPerPage = parseInt(storedPerPage, 10);
+        }
+      }
+
+      if (!urlParams.limit || urlParams.limit > storedPerPage) {
+        return parseInt(storedPerPage, 10);
+      } else {
+        return parseInt(urlParams.limit, 10);
+      }
+    },
+
+    createParams: function (options) {
+      var urlParams = app.getParams(options),
+          params = Documents.QueryParams.parse(urlParams),
+          limit = this.getDocPerPageLimit(params, FauxtonAPI.constants.MISC.DEFAULT_PAGE_SIZE);
+
+      return {
+        urlParams: urlParams,
+        docParams: _.extend(params, {limit: limit})
+      };
+    },
+
+    updateAllDocsFromView: function (event) {
+      var view = event.view,
+          params = this.createParams(),
+          urlParams = params.urlParams,
+          docParams = params.docParams,
+          ddoc = event.ddoc,
+          defaultPageSize,
+          isLazyInit,
+          pageSize,
+          collection;
+
+      isLazyInit = _.isUndefined(this.documentsView) || _.isUndefined(this.documentsView.allDocsNumber);
+      defaultPageSize = isLazyInit ? FauxtonAPI.constants.MISC.DEFAULT_PAGE_SIZE : this.documentsView.perPage();
+      docParams.limit = pageSize = this.getDocPerPageLimit(urlParams, defaultPageSize);
+
+      if (event.allDocs) {
+        this.eventAllDocs = true; // this is horrible. But I cannot get the trigger not to fire the route!
+        this.database.buildAllDocs(docParams);
+        collection = this.database.allDocs;
+        collection.paging.pageSize = pageSize;
+      } else {
+        collection = this.indexedDocs = new Documents.IndexCollection(null, {
+          database: this.database,
+          design: ddoc,
+          view: view,
+          params: docParams,
+          paging: {
+            pageSize: pageSize
+          }
+        });
+
+        if (!this.documentsView) {
+          this.documentsView = this.createViewDocumentsView({
+            designDoc: ddoc,
+            docParams: docParams,
+            urlParams: urlParams,
+            database: this.database,
+            indexedDocs: this.indexedDocs,
+            designDocs: this.designDocs,
+            view: view
+          });
+        }
+      }
+
+      this.documentsView.setParams(docParams, urlParams);
+
+      // this will lazily initialize all sub-views and render them
+      this.documentsView.forceRender();
+    },
+
+    perPageChange: function (perPage) {
+      // We need to restore the collection parameters to the defaults (1st page)
+      // and update the page size
+      this.perPage = perPage;
+
+      this.documentsView.forceRender();
+      this.documentsView.collection.pageSizeReset(perPage, {fetch: false});
+
+      this.setDocPerPageLimit(perPage);
+    },
+
+    paginate: function (options) {
+      var collection = this.documentsView.collection;
+      this.documentsView.collection.reset(collection);
+
+      this.documentsView.forceRender();
+      this.allDocsNumber.forceRender();
+
+      collection.paging.pageSize = options.perPage;
+      var promise = collection[options.direction]({fetch: false});
     }
   });
 

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/e6f089aa/app/addons/documents/templates/design_doc_selector.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/design_doc_selector.html b/app/addons/documents/templates/design_doc_selector.html
deleted file mode 100644
index 46435a7..0000000
--- a/app/addons/documents/templates/design_doc_selector.html
+++ /dev/null
@@ -1,36 +0,0 @@
-<!--
-Licensed under the Apache License, Version 2.0 (the "License"); you may not
-use this file except in compliance with the License. You may obtain a copy of
-the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-License for the specific language governing permissions and limitations under
-the License.
--->
-<div class="span3">
-  <label for="ddoc">Save to Design Document <a class="help-link" data-bypass="true" href="<%-getDocUrl('DOC_URL_DESIGN_DOCS')%>" target="_blank"><i class="icon-question-sign"></i></a></label>
-  <select id="ddoc">
-    <optgroup label="Select a document">
-      <option value="new-doc">New document</option>
-
-      <% ddocs.each(function(ddoc) { %>
-      <% if (ddoc.id === ddocName) { %>
-      <option selected="selected" value="<%- ddoc.id %>"><%- ddoc.id %></option>
-      <% } else { %>
-      <option value="<%- ddoc.id %>"><%- ddoc.id %></option>
-      <% } %>
-      <% }); %>
-    </optgroup>
-  </select>
-</div>
-
-<div id="new-ddoc-section" class="span5" style="display:none">
-  <label class="control-label" for="new-ddoc"> _design/ </label>
-  <div class="controls">
-    <input type="text" id="new-ddoc" placeholder="newDesignDoc" />
-  </div>
-</div>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/e6f089aa/app/addons/documents/templates/view_editor.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/view_editor.html b/app/addons/documents/templates/view_editor.html
deleted file mode 100644
index 731d2cc..0000000
--- a/app/addons/documents/templates/view_editor.html
+++ /dev/null
@@ -1,86 +0,0 @@
-<!--
-Licensed under the Apache License, Version 2.0 (the "License"); you may not
-use this file except in compliance with the License. You may obtain a copy of
-the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-License for the specific language governing permissions and limitations under
-the License.
--->
-<div class="dashboard-upper-menu">
-  <ul class="nav nav-tabs" id="db-views-tabs-nav">
-    <li class="active"> <a data-bypass="true" id="index-nav" data-toggle="tab" href="#index">
-      <i class="fonticon-wrench fonticon"></i>
-      <% if (newView) { %>Create Index <% } else { %>Edit Index <% } %></a>
-    </li>
-  </ul>
-</div>
-  <div class="tab-content">
-	 <div id="query-options-wrapper"></div>
-    <div class="tab-pane active" id="index">
-      <div id="define-view" class="ddoc-alert well">
-        <form class="form-horizontal view-query-save">
-
-          <div class="control-group design-doc-group">
-          </div>
-
-          <div class="control-group">
-            <label for="index-name">Index name <a class="help-link" data-bypass="true" href="<%-getDocUrl('VIEW_FUNCS')%>" target="_blank"><i class="icon-question-sign"></i></a></label>
-            <input type="text" id="index-name" value="<%- viewName %>" placeholder="Index name" />
-          </div>
-
-
-          <div class="control-group">
-            <label for="map-function">Map function <a class="help-link" data-bypass="true" href="<%-getDocUrl('MAP_FUNCS')%>" target="_blank"><i class="icon-question-sign"></i></a></label>
-            <% if (newView) { %>
-            <div class="js-editor" id="map-function"><%= langTemplates.map %></div>
-            <% } else { %>
-            <div class="js-editor" id="map-function"><%- ddoc.get('views')[viewName].map %></div>
-            <button class="beautify beautify_map btn btn-primary btn-large hide beautify-tooltip" type="button" data-toggle="tooltip" title="Reformat your minified code to make edits to it.">beautify this code</button>
-            <% } %>
-          </div>
-
-
-          <div class="control-group">
-            <label for="reduce-function-selector">Reduce (optional) <a class="help-link" data-bypass="true" href="<%-getDocUrl('REDUCE_FUNCS')%>" target="_blank"><i class="icon-question-sign"></i></a></label>
-
-            <select id="reduce-function-selector">
-              <option value="" <%- !reduceFunStr ? 'selected="selected"' : '' %>>None</option>
-              <% _.each(["_sum", "_count", "_stats"], function(reduce) { %>
-              <option value="<%- reduce %>" <% if (reduce == reduceFunStr) { %>selected<% } %>><%= reduce %></option>
-              <% }) %>
-              <option value="CUSTOM" <% if (isCustomReduce) { %>selected<% } %>>Custom Reduce function</option>
-            </select>
-          </div>
-
-          <div class="control-group reduce-function">
-            <label for="reduce-function">Custom Reduce function</label>
-            <% if (newView) { %>
-            <div class="js-editor" id="reduce-function"><%- langTemplates.reduce %></div>
-            <% } else { %>
-            <div class="js-editor" id="reduce-function"><%- ddoc.get('views')[viewName].reduce %></div>
-            <button class="beautify beautify_reduce btn btn-primary btn-large hide beautify-tooltip" type="button" data-toggle="tooltip" title="Reformat your minified code to make edits to it.">beautify this code</button>
-            <% } %>
-          </div>
-
-          <div class="control-group">
-            <button class="btn btn-success save"><i class="icon fonticon-ok-circled"></i> Save &amp; Build Index</button>
-            <% if (!newView) { %>
-            <button class="btn btn-danger delete"><i class="icon fonticon-cancel-circled"></i> Delete</button>
-            <% } %>
-            <span id="viewBtnExtensions"></span>
-          </div>
-          <div class="clearfix"></div>
-        </form>
-      </div>
-    </div>
-    <div class="tab-pane" id="metadata">
-      <div id="ddoc-info" class="well"> </div>
-    </div>
-    <div class="tab-pane" id="query">
-    </div>
-  </div>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/e6f089aa/app/addons/documents/tests/actionsSpec.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/tests/actionsSpec.js b/app/addons/documents/tests/actionsSpec.js
index a37c769..594e399 100644
--- a/app/addons/documents/tests/actionsSpec.js
+++ b/app/addons/documents/tests/actionsSpec.js
@@ -158,7 +158,12 @@ define([
           reduce: '_sum',
           newDesignDoc: false,
           newView: false,
-          designDocs: designDocs
+          designDocs: designDocs,
+          database: {
+            safeID: function () {
+              return 'foo';
+            }
+          }
         };
         var designDoc = designDocs.first();
 

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/e6f089aa/app/addons/documents/tests/nightwatch/navigateToNewView.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/tests/nightwatch/navigateToNewView.js b/app/addons/documents/tests/nightwatch/navigateToNewView.js
index 9bbdccf..4f93e94 100644
--- a/app/addons/documents/tests/nightwatch/navigateToNewView.js
+++ b/app/addons/documents/tests/nightwatch/navigateToNewView.js
@@ -26,7 +26,7 @@ module.exports = {
       .click('#new-all-docs-button a')
       .waitForElementPresent('#new-all-docs-button a[href="#/database/' + newDatabaseName + '/new_view"]', waitTime, false)
       .click('#new-all-docs-button a[href="#/database/' + newDatabaseName + '/new_view"]')
-      .waitForElementPresent('#define-view', waitTime, false)
+      .waitForElementPresent('.define-view', waitTime, false)
       .verify.urlEquals(baseUrl+'/#/database/' + newDatabaseName + '/new_view')
 
       // now redirect back to the database page and check it's loaded properly

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/e6f089aa/app/addons/documents/tests/nightwatch/viewCreate.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/tests/nightwatch/viewCreate.js b/app/addons/documents/tests/nightwatch/viewCreate.js
new file mode 100644
index 0000000..8857af0
--- /dev/null
+++ b/app/addons/documents/tests/nightwatch/viewCreate.js
@@ -0,0 +1,94 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+var waitTime = 10000,
+    baseUrl,
+    newDatabaseName,
+    newDocumentName,
+    modifier;
+
+var tests = {
+
+  'Creates a Design Doc using the dropdown at "all documents"': function (client) {
+    /*jshint multistr: true */
+    openDifferentDropdownsAndClick(client, '#header-dropdown-menu')
+      .setValue('#new-ddoc', 'test_design_doc-selenium-1')
+      .clearValue('#index-name')
+      .setValue('#index-name', 'hasenindex')
+      .execute('\
+        var editor = ace.edit("map-function");\
+        editor.getSession().setValue("function (doc) { emit(\'hasehase\'); }");\
+      ')
+      .click('button.btn.btn-success.save')
+      .waitForElementPresent('.prettyprint', waitTime, false)
+      .assert.containsText('.prettyprint', 'hasehase')
+    .end();
+  },
+
+
+  'Creates a Design Doc using the dropdown at "the upper dropdown in the header"': function (client) {
+    /*jshint multistr: true */
+    openDifferentDropdownsAndClick(client, '#header-dropdown-menu')
+      .setValue('#new-ddoc', 'test_design_doc-selenium-2')
+      .clearValue('#index-name')
+      .setValue('#index-name', 'gaenseindex')
+      .execute('\
+        var editor = ace.edit("map-function");\
+        editor.getSession().setValue("function (doc) { emit(\'gansgans\'); }");\
+      ')
+      .execute('$(".save")[0].scrollIntoView();')
+      .click('button.btn-success.save')
+      .waitForElementPresent('.prettyprint', waitTime, false)
+      .assert.containsText('.prettyprint', 'gansgans')
+    .end();
+  },
+
+  'Adds a View to a DDoc using an existing DDoc': function (client) {
+    /*jshint multistr: true */
+
+    openDifferentDropdownsAndClick(client, '[data-target="#testdesigndoc"]')
+      .clearValue('#index-name')
+      .setValue('#index-name', 'test-new-view')
+      .execute('\
+        var editor = ace.edit("map-function");\
+        editor.getSession().setValue("function (doc) { emit(\'enteente\', 1); }");\
+      ')
+      .execute('$(".save")[0].scrollIntoView();')
+      .click('button.btn-success.save')
+      .url(baseUrl + '/#/database/' + newDatabaseName + '/_all_docs')
+      .waitForElementPresent('[data-target="#testdesigndoc"]', waitTime, false)
+      .click('[data-target="#testdesigndoc"]')
+      .clickWhenVisible('[data-target="#testdesigndocviews"]', waitTime, false)
+      .clickWhenVisible('#testdesigndoc_testnewview', waitTime, false)
+      .waitForElementPresent('.prettyprint', waitTime, false)
+      .assert.containsText('.prettyprint', 'enteente')
+    .end();
+  },
+};
+
+function openDifferentDropdownsAndClick (client, dropDownElement) {
+  modifier =  + dropDownElement.slice(1);
+  newDatabaseName = client.globals.testDatabaseName;
+  newDocumentName = 'create_view_doc' + modifier;
+  baseUrl = client.globals.test_settings.launch_url;
+
+  return client
+    .loginToGUI()
+    .populateDatabase(newDatabaseName)
+    .url(baseUrl + '/#/database/' + newDatabaseName + '/_all_docs')
+    .waitForElementPresent(dropDownElement, waitTime, false)
+    .click(dropDownElement + ' a')
+    .click(dropDownElement + ' a[href*="new_view"]')
+    .waitForElementPresent('.editor-wrapper', waitTime, false);
+}
+
+module.exports = tests;

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/e6f089aa/app/addons/documents/tests/nightwatch/viewEdit.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/tests/nightwatch/viewEdit.js b/app/addons/documents/tests/nightwatch/viewEdit.js
new file mode 100644
index 0000000..f3ea6da
--- /dev/null
+++ b/app/addons/documents/tests/nightwatch/viewEdit.js
@@ -0,0 +1,89 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+module.exports = {
+
+  'Edits a design doc - set new index name': function (client) {
+    /*jshint multistr: true */
+    var waitTime = 10000,
+        newDatabaseName = client.globals.testDatabaseName,
+        baseUrl = client.globals.test_settings.launch_url;
+
+    client
+      .populateDatabase(newDatabaseName)
+      .loginToGUI()
+      .url(baseUrl + '/#/database/' + newDatabaseName + '/_design/testdesigndoc/_view/stubview')
+      .waitForElementPresent('.prettyprint', waitTime, false)
+      .assert.containsText('.prettyprint', 'stub')
+      .clearValue('#index-name')
+      .setValue('#index-name', 'hasenindex5000')
+      .execute('\
+        var editor = ace.edit("map-function");\
+        editor.getSession().setValue("function (doc) { emit(\'hasehase5000\', 1); }");\
+      ')
+      .execute('$(".save")[0].scrollIntoView();')
+      .click('button.btn-success.save')
+
+      .waitForElementNotVisible('.global-notification', waitTime, false)
+      .assert.containsText('.prettyprint', 'hasehase5000')
+    .end();
+  },
+
+  'Edits a design doc': function (client) {
+    /*jshint multistr: true */
+    var waitTime = 10000,
+        newDatabaseName = client.globals.testDatabaseName,
+        baseUrl = client.globals.test_settings.launch_url;
+
+    client
+      .populateDatabase(newDatabaseName)
+      .loginToGUI()
+      .url(baseUrl + '/#/database/' + newDatabaseName + '/_design/testdesigndoc/_view/stubview')
+      .waitForElementPresent('.prettyprint', waitTime, false)
+      .assert.containsText('.prettyprint', 'stub')
+
+      .execute('\
+        var editor = ace.edit("map-function");\
+        editor.getSession().setValue("function (doc) { emit(\'hasehase5000\', 1); }");\
+      ')
+      .execute('$(".save")[0].scrollIntoView();')
+      .click('button.btn-success.save')
+
+      .waitForElementNotVisible('.global-notification', waitTime, false)
+      .assert.containsText('.prettyprint', 'hasehase5000')
+    .end();
+  },
+
+  'Query Options are kept after a new reduce method is chosen': function (client) {
+    /*jshint multistr: true */
+    var waitTime = 10000,
+        newDatabaseName = client.globals.testDatabaseName,
+        baseUrl = client.globals.test_settings.launch_url;
+
+    client
+      .populateDatabase(newDatabaseName)
+      .loginToGUI()
+      .url(baseUrl + '/#/database/' + newDatabaseName + '/_design/testdesigndoc/_view/stubview?reduce=true&group_level=0')
+      .waitForElementPresent('.prettyprint', waitTime, false)
+      .assert.containsText('.prettyprint', '20')
+      .clickWhenVisible('#reduce-function-selector option[value="_sum"]')
+      .execute('\
+        var editor = ace.edit("map-function");\
+        editor.getSession().setValue("function (doc) { emit(\'newstub\', 2); }");\
+      ')
+      .execute('$(".save")[0].scrollIntoView();')
+      .click('button.btn-success.save')
+      .waitForElementNotVisible('.global-notification', waitTime, false)
+      .assert.containsText('.prettyprint', '40')
+    .end();
+  }
+};

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/e6f089aa/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
new file mode 100644
index 0000000..245b89d
--- /dev/null
+++ b/app/addons/documents/tests/nightwatch/viewQueryOptions.js
@@ -0,0 +1,34 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+module.exports = {
+  'Edit view: Queryoptions work': function (client) {
+    /*jshint multistr: true */
+    var waitTime = 10000,
+        newDatabaseName = client.globals.testDatabaseName,
+        baseUrl = client.globals.test_settings.launch_url;
+
+    client
+      .populateDatabase(newDatabaseName, 3)
+      .loginToGUI()
+      .url(baseUrl + '/#/database/' + newDatabaseName + '/_design/keyview/_view/keyview')
+      .clickWhenVisible('#toggle-query')
+      .clickWhenVisible('[data-action="showByKeys"]')
+      .setValue('#keys-input', '["document_1"]')
+      .click('#query-options .btn-success')
+      .waitForElementNotPresent('#right-content [data-id="document_2"]', waitTime, false)
+      .assert.elementNotPresent('#right-content [data-id="document_2"]')
+      .assert.elementNotPresent('#right-content [data-id="document_0"]')
+      .assert.elementPresent('#right-content [data-id="document_1"]')
+    .end();
+  }
+};

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/e6f089aa/app/addons/documents/tests/routeSpec.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/tests/routeSpec.js b/app/addons/documents/tests/routeSpec.js
index c59003a..1e14302 100644
--- a/app/addons/documents/tests/routeSpec.js
+++ b/app/addons/documents/tests/routeSpec.js
@@ -26,13 +26,6 @@ define([
       assert.equal(typeof routeObj.rightHeader, 'object');
     });
 
-    it('the view that shows a view has a right header', function () {
-      var routeObj = new DocumentRoute(null, null, ['test']);
-
-      routeObj.viewFn('newdatabase', 'ads', 'newView');
-      assert.equal(typeof routeObj.rightHeader, 'object');
-    });
-
     // after saving a new CouchDB-View we are calling the updateAllDocsFromView function.
     // The backbone-view AllDocsList is lazily initializing other views, in particular the
     // view AllDocsNumber and the pagination in the beforeRender method.

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/e6f089aa/app/addons/documents/tests/storesSpec.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/tests/storesSpec.js b/app/addons/documents/tests/storesSpec.js
index 5511a8e..89adfaa 100644
--- a/app/addons/documents/tests/storesSpec.js
+++ b/app/addons/documents/tests/storesSpec.js
@@ -33,44 +33,6 @@ define([
       FauxtonAPI.dispatcher.unregister(dispatchToken);
     });
 
-    describe('TOGGLE EDITOR', function () {
-
-      it('toggles editor', function () {
-        var designDoc = {
-          _id: '_design/test-doc',
-          views: {
-            'test-view': {
-              map: 'boom'
-            }
-          }
-        };
-
-        var designDocs = new Documents.AllDocs([designDoc], {
-          params: { limit: 10 },
-          database: {
-            safeID: function () { return 'id';}
-          }
-        });
-
-        FauxtonAPI.dispatch({
-          type: ActionTypes.EDIT_NEW_INDEX,
-          options: {
-            newView: false,
-            designDocs: designDocs,
-            designDocId: '_design/test-doc'
-          }
-        });
-
-
-        FauxtonAPI.dispatch({
-          type: ActionTypes.TOGGLE_EDITOR
-        });
-
-        assert.ok(store.showEditor());
-      });
-
-    });
-
     describe('map editor', function () {
 
       describe('new view', function () {
@@ -346,35 +308,6 @@ define([
         assert.equal(store.getReduce(), '_sum');
       });
 
-      it('showEditor() is false for editing index', function () {
-        FauxtonAPI.dispatch({
-          type: ActionTypes.EDIT_INDEX,
-          options: {
-            newView: false,
-            viewName: 'test-view',
-            designDocs: designDocs,
-            designDocId: designDoc._id
-          }
-        });
-
-        assert.notOk(store.showEditor());
-      });
-
-      it('showEditor() is true for creating index', function () {
-        FauxtonAPI.dispatch({
-          type: ActionTypes.EDIT_INDEX,
-          options: {
-            newView: true,
-            viewName: 'test-view',
-            newDesignDoc: false,
-            designDocs: designDocs,
-            designDocId: designDoc._id
-          }
-        });
-
-        assert.ok(store.showEditor());
-      });
-
     });
 
   });

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/e6f089aa/app/addons/documents/tests/viewIndex.componentsSpec.react.jsx
----------------------------------------------------------------------
diff --git a/app/addons/documents/tests/viewIndex.componentsSpec.react.jsx b/app/addons/documents/tests/viewIndex.componentsSpec.react.jsx
index 74eddca..7f3eee9 100644
--- a/app/addons/documents/tests/viewIndex.componentsSpec.react.jsx
+++ b/app/addons/documents/tests/viewIndex.componentsSpec.react.jsx
@@ -32,6 +32,7 @@ define([
     });
 
     Actions.editIndex({
+      database: {id: 'rockos-db'},
       newView: false,
       viewName: 'test-view',
       designDocs: designDocs,
@@ -39,30 +40,6 @@ define([
     });
   };
 
-  describe('View editor', function () {
-
-    describe('Toggle button', function () {
-      var container, toggleEl, toggleEditor;
-
-      beforeEach(function () {
-        toggleEditor = sinon.spy();
-        container = document.createElement('div');
-        toggleEl = TestUtils.renderIntoDocument(<Views.ToggleButton toggleEditor={toggleEditor} />, container);
-      });
-
-      afterEach(function () {
-        React.unmountComponentAtNode(container);
-      });
-
-      it('should toggle editor on click', function () {
-        TestUtils.Simulate.click($(toggleEl.getDOMNode()).find('a')[0]);
-        assert.ok(toggleEditor.calledOnce);
-      });
-
-    });
-
-  });
-
   describe('reduce editor', function () {
     var container, reduceEl;
 
@@ -123,6 +100,44 @@ define([
     });
   });
 
+  describe('styled select', function () {
+    var container, selectorEl, spy = sinon.spy();
+
+    beforeEach(function () {
+      container = document.createElement('div');
+
+      var selectContent = (
+        <optgroup label="Select a document">
+          <option value="new">New Design Document</option>
+          <option value="foo">New Design Document</option>
+        </optgroup>
+      );
+
+      selectorEl = TestUtils.renderIntoDocument(
+        <Views.StyledSelect
+          selectId="new-ddoc"
+          selectClass=""
+          selectContent={selectContent}
+          selectChange={spy} />,
+        container
+      );
+    });
+
+    afterEach(function () {
+      React.unmountComponentAtNode(container);
+    });
+
+    it('calls the callback on select', function () {
+      TestUtils.Simulate.change($(selectorEl.getDOMNode()).find('#new-ddoc')[0], {
+        target: {
+          value: 'new'
+        }
+      });
+      assert.ok(spy.calledOnce);
+    });
+
+  });
+
   describe('design Doc Selector', function () {
     var container, selectorEl;
 

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/e6f089aa/app/addons/documents/views-index.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/views-index.js b/app/addons/documents/views-index.js
index eb24944..e64963f 100644
--- a/app/addons/documents/views-index.js
+++ b/app/addons/documents/views-index.js
@@ -14,9 +14,10 @@ define([
   "api",
   "addons/documents/index-editor/components.react",
   "addons/documents/index-editor/actions",
+  'addons/documents/index-results/index-results.components.react'
 ],
 
-function(FauxtonAPI, ViewEditor, Actions) {
+function (FauxtonAPI, ViewEditor, ActionsIndexEditor, ViewResultList) {
 
   var Views = {};
 
@@ -26,7 +27,7 @@ function(FauxtonAPI, ViewEditor, Actions) {
     },
 
     afterRender: function () {
-      Actions.editIndex(this.options);
+      ActionsIndexEditor.editIndex(this.options);
       ViewEditor.renderEditor(this.el);
     },
 
@@ -35,5 +36,19 @@ function(FauxtonAPI, ViewEditor, Actions) {
     }
   });
 
+  Views.ViewResultListReact = FauxtonAPI.View.extend({
+    initialize: function (options) {
+      this.options = options;
+    },
+
+    afterRender: function () {
+      ViewResultList.renderViewResultList(this.el);
+    },
+
+    cleanup: function () {
+      ViewResultList.removeViewResultList(this.el);
+    }
+  });
+
   return Views;
 });


Mime
View raw message