You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by ro...@apache.org on 2014/12/15 22:35:55 UTC

fauxton commit: updated refs/heads/master to c7fa6fa

Repository: couchdb-fauxton
Updated Branches:
  refs/heads/master bf1b42833 -> c7fa6fad7


Allow editing documents from a view

-included:
Allow entire document card to be clickable for editing
clickWhenVisible custom function for Nightwatch

Closes COUCH-2494


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

Branch: refs/heads/master
Commit: c7fa6fad7c4113e4f776830846ac0274cb7af422
Parents: bf1b428
Author: Michelle Phung <mi...@gmail.com>
Authored: Sun Dec 7 12:57:25 2014 -0500
Committer: Robert Kowalski <ro...@apache.org>
Committed: Mon Dec 15 22:31:21 2014 +0100

----------------------------------------------------------------------
 app/addons/documents/resources.js               | 46 +++++-----------
 app/addons/documents/routes-doc-editor.js       |  8 ++-
 app/addons/documents/routes-documents.js        | 35 +++++++-----
 .../documents/templates/all_docs_item.html      | 21 ++++----
 .../documents/templates/index_row_docular.html  | 29 ----------
 .../tests/nightwatch/editDocumentsFromView.js   | 57 ++++++++++++++++++++
 app/addons/documents/views-index.js             | 21 --------
 app/addons/documents/views.js                   |  8 +--
 .../custom-commands/clickWhenVisible.js         | 12 +++++
 .../custom-commands/createDocument.js           |  8 ++-
 .../custom-commands/populateDatabase.js         |  2 +-
 test/nightwatch_tests/nightwatch_README.md      |  4 +-
 12 files changed, 138 insertions(+), 113 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/c7fa6fad/app/addons/documents/resources.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/resources.js b/app/addons/documents/resources.js
index 1eaa6bb..7a80ab2 100644
--- a/app/addons/documents/resources.js
+++ b/app/addons/documents/resources.js
@@ -89,6 +89,18 @@ function(app, FauxtonAPI, PagingCollection) {
       return this.docType() != "reduction";
     },
 
+    isFromView: function(){
+      return !this.id;
+    },
+
+    isReducedShown : function () {
+      if (this.collection) {
+        return this.collection.params.reduce;
+      } else {
+        return false;
+      }
+    },
+
     isDdoc: function() {
       return this.docType() === "design doc";
     },
@@ -251,38 +263,6 @@ function(app, FauxtonAPI, PagingCollection) {
     }
   });
 
-  Documents.ViewRow = FauxtonAPI.Model.extend({
-    // this is a hack so that backbone.collections doesn't group
-    // these by id and reduce the number of items returned.
-    idAttribute: "_id",
-
-    docType: function() {
-      if (!this.id) return "reduction";
-
-      return this.id.match(/^_design/) ? "design doc" : "doc";
-    },
-    documentation: function(){
-      return FauxtonAPI.constants.DOC_URLS.GENERAL;
-    },
-    url: function(context) {
-      return this.collection.database.url(context) + "/" + this.safeID();
-    },
-
-    isEditable: function() {
-      return this.docType() != "reduction";
-    },
-    safeID: function() {
-      var id = this.id || this.get("id");
-
-      return app.utils.safeURLName(id);
-    },
-
-    prettyJSON: function() {
-      //var data = this.get("doc") ? this.get("doc") : this;
-      return JSON.stringify(this, null, "  ");
-    }
-  });
-
   Documents.NewDoc = Documents.Doc.extend({
     fetch: function() {
       var uuid = new FauxtonAPI.UUID();
@@ -492,7 +472,7 @@ function(app, FauxtonAPI, PagingCollection) {
   });
 
   Documents.IndexCollection = PagingCollection.extend({
-    model: Documents.ViewRow,
+    model: Documents.Doc,
     documentation: function(){
       return FauxtonAPI.constants.DOC_URLS.GENERAL;
     },

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/c7fa6fad/app/addons/documents/routes-doc-editor.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/routes-doc-editor.js b/app/addons/documents/routes-doc-editor.js
index 83cca0b..4efed7c 100644
--- a/app/addons/documents/routes-doc-editor.js
+++ b/app/addons/documents/routes-doc-editor.js
@@ -39,7 +39,8 @@ function(app, FauxtonAPI, Documents, DocEditor, Databases) {
 
     routes: {
       "database/:database/:doc/code_editor": "code_editor",
-      "database/:database/:doc": "code_editor"
+      "database/:database/:doc": "code_editor",
+      "database/:database/_design/:ddoc" :"showDesignDoc"
     },
 
     events: {
@@ -70,6 +71,11 @@ function(app, FauxtonAPI, Documents, DocEditor, Databases) {
         model: this.doc,
         database: this.database
       }));
+
+    },
+
+    showDesignDoc: function (database, ddoc) {
+      this.code_editor(database, '_design/' + ddoc);
     },
 
     reRenderDoc: function () {

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/c7fa6fad/app/addons/documents/routes-documents.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/routes-documents.js b/app/addons/documents/routes-documents.js
index cbec036..59e2044 100644
--- a/app/addons/documents/routes-documents.js
+++ b/app/addons/documents/routes-documents.js
@@ -86,8 +86,7 @@ function(app, FauxtonAPI, Documents, Changes, Index, DocEditor, Databases, Resou
       "route:perPageChange": "perPageChange",
       "route:changesFilterAdd": "addFilter",
       "route:changesFilterRemove": "removeFilter",
-      "route:updateQueryOptions": "updateQueryOptions",
-      "route:resetQueryOptions": "resetQueryOptions"
+      "route:updateQueryOptions": "updateQueryOptions"
     },
 
     overrideBreadcrumbs: true,
@@ -356,13 +355,26 @@ function(app, FauxtonAPI, Documents, Changes, Index, DocEditor, Databases, Resou
         return [this.indexedDocs.urlRef("apiurl", urlParams), FauxtonAPI.constants.DOC_URLS.GENERAL];
       };
 
-      this.rightHeader.showQueryOptions();
-      this.rightHeader.resetQueryOptions({
-        queryParams: urlParams,
-        showStale: true,
-        hasReduce: true,
-        viewName: viewName,
-        ddocName: ddoc
+      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
+        });
       });
     },
 
@@ -492,6 +504,7 @@ function(app, FauxtonAPI, Documents, Changes, Index, DocEditor, Databases, Resou
 
     paginate: function (options) {
       var collection = this.documentsView.collection;
+      this.documentsView.collection.reset(collection);
 
       this.documentsView.forceRender();
       collection.paging.pageSize = options.perPage;
@@ -570,10 +583,6 @@ function(app, FauxtonAPI, Documents, Changes, Index, DocEditor, Databases, Resou
       this.changesView.render();
     },
 
-    resetQueryOptions: function(options) {
-      this.rightHeader.resetQueryOptions(options);
-    },
-
     updateQueryOptions: function(options) {
       this.rightHeader.updateQueryOptions(options);
     },

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/c7fa6fad/app/addons/documents/templates/all_docs_item.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/all_docs_item.html b/app/addons/documents/templates/all_docs_item.html
index e0c62fc..74e944a 100644
--- a/app/addons/documents/templates/all_docs_item.html
+++ b/app/addons/documents/templates/all_docs_item.html
@@ -20,15 +20,18 @@ the License.
 </div>
 <div class="doc-item">
   <header>
-    <span class="header-keylabel"><%- doc.isEditable() ? 'id' : 'key' %></span> <span class="header-doc-id">"<%- docIdentifier %>"</span>
-
-  <% if (doc.isEditable()) { %>
-    <div class="doc-edit-symbol pull-right">
-      <a href="#<%- doc.url('web-index') %>">
-        <i class="fonticon-pencil"></i>
-      </a>
-    </div>
-  <% } %>
+    <span class="header-keylabel"><%- doc.isFromView() ? 'key' : 'id' %></span> <span class="header-doc-id">"<%- docIdentifier %>"</span>
+    <% if (!doc.isReducedShown()) { %>
+      <div class="doc-edit-symbol pull-right">
+        <% if (doc.isFromView()) { %>
+          <a href="#<%- doc.url('app') %>">
+        <% } else {  %>
+          <a href="#<%- doc.url('web-index')%>">
+        <% } %>
+            <i class="fonticon-pencil"></i>
+        </a>
+      </div>
+    <% } %>
   </header>
   <div class="doc-data">
     <pre class="prettyprint"><%- doc.prettyJSON() %></pre>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/c7fa6fad/app/addons/documents/templates/index_row_docular.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/index_row_docular.html b/app/addons/documents/templates/index_row_docular.html
deleted file mode 100644
index e8973ad..0000000
--- a/app/addons/documents/templates/index_row_docular.html
+++ /dev/null
@@ -1,29 +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.
--->
-<% if (doc.isEditable()) { %>
-  <td class="select"><input type="checkbox"></td>
-<% } %>
-<td>
-  <div>
-    <pre class="prettyprint"><%- doc.prettyJSON() %></pre>
-
-      <div class="btn-group">
-        <a href="#<%= url %>" class="btn btn-small edits">Edit <%= doc.docType() %></a>
-        <% if (doc.isEditable()) { %>
-          <button href="#" class="btn btn-small btn-danger delete" title="Delete this document."><i class="icon icon-trash"></i></button>
-        <% } %>
-      </div>
-
-  </div>
-</td>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/c7fa6fad/app/addons/documents/tests/nightwatch/editDocumentsFromView.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/tests/nightwatch/editDocumentsFromView.js b/app/addons/documents/tests/nightwatch/editDocumentsFromView.js
new file mode 100644
index 0000000..48c08f6
--- /dev/null
+++ b/app/addons/documents/tests/nightwatch/editDocumentsFromView.js
@@ -0,0 +1,57 @@
+// 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 is allowed from default Map Views' : function (client) {
+    var waitTime = 10000,
+        newDatabaseName = client.globals.testDatabaseName,
+        newDocumentName = '_design/abc',
+        baseUrl = client.globals.test_settings.launch_url,
+        ddocContents = {
+          "views": {
+            "evens": {
+              "map": "function (doc) { if (doc.number%2 === 0){ emit(doc._id, doc.number); } }",
+              "reduce" : "_count"
+            }
+          },
+          "language": "javascript"
+        };
+
+    client
+      .loginToGUI()
+      .createDocument(newDocumentName, newDatabaseName, ddocContents )
+      .populateDatabase(newDatabaseName)
+
+      //navigate to 'evens' view (declared above), then click on first document's pencil icon
+      .clickWhenVisible('#dashboard-content a[href="#/database/' + newDatabaseName + '/_all_docs"]')
+      .clickWhenVisible('#nav-header-abc')
+      .clickWhenVisible('#nav-design-function-abcviews')
+      .clickWhenVisible('#abc_evens')
+      .clickWhenVisible('a[href="#/database/fauxton-selenium-tests/document_10"]')
+
+      //navigated to editor
+      .waitForElementVisible('#editor-container', waitTime, false)
+      .verify.urlContains('#/database/' + newDatabaseName +'/document_10');
+  },
+
+  'Edit is not allowed for Map Views where reduce is checked' : function (client) {
+    var waitTime = 10000;
+
+    client
+      .clickWhenVisible('#doc-actions .cancel-button')
+      .clickWhenVisible('#toggle-query')
+      .clickWhenVisible('#query-options-tray label[for="qoReduce"]')
+      .clickWhenVisible('#button-options button[type="submit"]')
+      .waitForElementNotPresent('i.fonticon-pencil', waitTime)
+    .end();
+  }
+};

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/c7fa6fad/app/addons/documents/views-index.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/views-index.js b/app/addons/documents/views-index.js
index 6fda62c..e0445fc 100644
--- a/app/addons/documents/views-index.js
+++ b/app/addons/documents/views-index.js
@@ -33,16 +33,6 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, QueryOption
 
   var Views = {};
 
-
-  // this is a temporary workaround until I hear of a better on. The problem is that on initial page load (i.e. a refresh
-  // of the View page) the afterRender() functions calls a FauxtonAPI.triggerRouteEvent(). That causes this View to be
-  // rendered twice (at least, the afterRender() function then gets called twice) - and that causes the header content to
-  // disappear. This var tracks whether the View has been rendered and if not, doesn't call the triggerRouteEvent. btw,
-  // the reason the triggerRouteEvent('resetQueryOptions') code is there is that it ensures the Query Options tray shows
-  // the appropriate content for the current View (i.e. hasReduce or not)
-  var hasRenderedOnce = false;
-
-
   Views.ViewEditor = FauxtonAPI.View.extend({
     template: "addons/documents/templates/view_editor",
     builtinReduces: ['_sum', '_count', '_stats'],
@@ -454,15 +444,6 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, QueryOption
     },
 
     afterRender: function() {
-      if (this.params && !this.newView && hasRenderedOnce) {
-        FauxtonAPI.triggerRouteEvent('resetQueryOptions', {
-          queryParams: this.params,
-          hasReduce: this.hasReduce(),
-          showStale: true,
-          viewName: this.viewName,
-          ddocName: this.ddocInfo.get('name')
-        });
-      }
 
       this.designDocSelector.updateDesignDoc();
       if (this.newView || this.showIndex) {
@@ -473,8 +454,6 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, QueryOption
         this.$('#index-nav').parent().removeClass('active');
       }
 
-      // note that this View has been rendered
-      hasRenderedOnce = true;
     },
 
     showEditors: function () {

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/c7fa6fad/app/addons/documents/views.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/views.js b/app/addons/documents/views.js
index 06d092c..dc47feb 100644
--- a/app/addons/documents/views.js
+++ b/app/addons/documents/views.js
@@ -196,7 +196,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, Views, QueryOptions)
     },
 
     events: {
-      "dblclick pre.prettyprint": "edit"
+      "dblclick .doc-item": "edit"
     },
 
     attributes: function() {
@@ -207,7 +207,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, Views, QueryOptions)
 
     serialize: function() {
       return {
-        docIdentifier: this.model.isEditable() ? this.model.get('_id') : this.model.get('key'),
+        docIdentifier: this.model.isReducedShown() ? this.model.get('key') : this.model.get('_id'),
         doc: this.model,
         checked: this.checked
       };
@@ -219,7 +219,9 @@ function(app, FauxtonAPI, Components, Documents, Databases, Views, QueryOptions)
 
     edit: function(event) {
       event.preventDefault();
-      FauxtonAPI.navigate("#" + this.model.url('web-index'));
+      if (!this.model.isReducedShown()) {
+        FauxtonAPI.navigate(this.model.url('app'));
+      }
     }
   });
 

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/c7fa6fad/test/nightwatch_tests/custom-commands/clickWhenVisible.js
----------------------------------------------------------------------
diff --git a/test/nightwatch_tests/custom-commands/clickWhenVisible.js b/test/nightwatch_tests/custom-commands/clickWhenVisible.js
new file mode 100644
index 0000000..e1b4071
--- /dev/null
+++ b/test/nightwatch_tests/custom-commands/clickWhenVisible.js
@@ -0,0 +1,12 @@
+exports.command = function (element, waitTime) {
+
+  if(waitTime === undefined){
+    waitTime = 10000;
+  }
+
+  this
+    .waitForElementVisible(element, waitTime, false)
+    .click(element);
+
+  return this;
+};

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/c7fa6fad/test/nightwatch_tests/custom-commands/createDocument.js
----------------------------------------------------------------------
diff --git a/test/nightwatch_tests/custom-commands/createDocument.js b/test/nightwatch_tests/custom-commands/createDocument.js
index 388dc5a..4d08505 100644
--- a/test/nightwatch_tests/custom-commands/createDocument.js
+++ b/test/nightwatch_tests/custom-commands/createDocument.js
@@ -9,12 +9,16 @@ function CreateDocument () {
 // inherit from node's event emitter
 util.inherits(CreateDocument, events.EventEmitter);
 
-CreateDocument.prototype.command = function (documentName, databaseName) {
+CreateDocument.prototype.command = function (documentName, databaseName, docContents) {
   var that = this,
       nano = helpers.getNanoInstance(),
       database = nano.use(databaseName);
 
-  database.insert({ dummyKey: "testingValue" }, documentName, function (err, body, header) {
+  if (docContents === undefined) {
+    docContents = { dummyKey: "testingValue" }; 
+  }
+
+  database.insert(docContents, documentName, function (err, body, header) {
   
     if (err) {
       console.log('Error in nano CreateDocument Function: '+documentName+', in database: '+databaseName, err.message);

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/c7fa6fad/test/nightwatch_tests/custom-commands/populateDatabase.js
----------------------------------------------------------------------
diff --git a/test/nightwatch_tests/custom-commands/populateDatabase.js b/test/nightwatch_tests/custom-commands/populateDatabase.js
index ea1cbf8..bf01c97 100644
--- a/test/nightwatch_tests/custom-commands/populateDatabase.js
+++ b/test/nightwatch_tests/custom-commands/populateDatabase.js
@@ -19,7 +19,7 @@ PopulateDatabase.prototype.command = function (databaseName) {
     function () { return i < 20; },
     function (cb) {
         i++;
-        var document_id = 'document_ '+ i;
+        var document_id = 'document_'+ i;
         database.insert({ number: i }, document_id, cb);
     },
     function (err) {

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/c7fa6fad/test/nightwatch_tests/nightwatch_README.md
----------------------------------------------------------------------
diff --git a/test/nightwatch_tests/nightwatch_README.md b/test/nightwatch_tests/nightwatch_README.md
index a18d6a7..761d6f8 100644
--- a/test/nightwatch_tests/nightwatch_README.md
+++ b/test/nightwatch_tests/nightwatch_README.md
@@ -51,8 +51,10 @@ has failed, and will not exit or skip subsequent tests.
 3. `.waitForElementNotPresent()`, `.waitForElementNotVisible()`, `.waitForElementPresent()`, `.waitForElementVisible()`, 
 will exit testing by default if the Element is not found. There is a third argument, 'abortOnFailure', if you set this 
 to 'false', the rest of the tests will continue even if this assertion fails.
+> there is a custom function called clickWhenReady which will wait for an element to visible, then click on it
+
 4. Sometimes `.click()` doesn't work reliably (most likely if the element you are clicking on doesn't have an 
-individual ID selector). You can use jquery to simulate a click by using `.execute($("#CSS Selector.HERE").click();)`
+individual ID selector). You can use jquery to simulate a click by using `.execute('$("#CSS Selector.HERE").click();')`.  
 5. The function `.pause(time)` is sometimes necessary, although we have tried to avoid excessive use of a hard coded 
 pausing. Instead try and make use of the `.waitForElement` functions instead of `.pause(time)`.