You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by ga...@apache.org on 2013/05/23 17:42:31 UTC

[09/10] git commit: updated refs/heads/fauxton-view-improvements to 2171e16

previews working with views


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

Branch: refs/heads/fauxton-view-improvements
Commit: 9eba40bf3e5ac7cfd933078466f7067e1dde2552
Parents: 642343c
Author: Garren Smith <ga...@gmail.com>
Authored: Wed May 22 19:04:19 2013 +0200
Committer: Garren Smith <ga...@gmail.com>
Committed: Thu May 23 10:26:45 2013 +0200

----------------------------------------------------------------------
 src/fauxton/app/modules/documents/resources.js     |   51 +++++++++
 src/fauxton/app/modules/documents/routes.js        |   23 ++++-
 src/fauxton/app/modules/documents/views.js         |   79 +++++++++++----
 src/fauxton/app/modules/pouchdb/base.js            |   17 ++--
 .../app/modules/pouchdb/pouchdb.mapreduce.js       |   50 ++++++++-
 5 files changed, 185 insertions(+), 35 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/9eba40bf/src/fauxton/app/modules/documents/resources.js
----------------------------------------------------------------------
diff --git a/src/fauxton/app/modules/documents/resources.js b/src/fauxton/app/modules/documents/resources.js
index 4a2a280..36820ae 100644
--- a/src/fauxton/app/modules/documents/resources.js
+++ b/src/fauxton/app/modules/documents/resources.js
@@ -289,6 +289,57 @@ function(app, FauxtonAPI) {
       return this.models;
     }
   });
+  
+  Documents.PouchIndexCollection = Backbone.Collection.extend({
+    model: Documents.ViewRow,
+
+    initialize: function(_models, options) {
+      this.database = options.database;
+      this.rows = options.rows;
+      this.view = options.view;
+      this.design = options.design.replace('_design/','');
+      this.params = _.extend({limit: 10, reduce: false}, options.params);
+      this.idxType = "_view";
+    },
+
+    url: function () {
+      return '';
+    },
+
+    fetch: function() {
+      console.log('fetching');
+      var deferred = FauxtonAPI.Deferred();
+      this.reset(this.rows, {silent: true});
+
+      this.viewMeta = {
+        total_rows: this.rows.length,
+        offest: 0,
+        update_seq: false
+      };
+
+      deferred.resolve();
+      return deferred;
+    },
+
+    totalRows: function() {
+      console.log('rows');
+      console.log(this);
+      return this.viewMeta.total_rows || "unknown";
+    },
+
+    updateSeq: function() {
+      return this.viewMeta.update_seq || false;
+    },
+
+    buildAllDocs: function(){
+      this.fetch();
+    },
+
+    allDocs: function(){
+      return this.models;
+    }
+  });
+
 
   return Documents;
 });

http://git-wip-us.apache.org/repos/asf/couchdb/blob/9eba40bf/src/fauxton/app/modules/documents/routes.js
----------------------------------------------------------------------
diff --git a/src/fauxton/app/modules/documents/routes.js b/src/fauxton/app/modules/documents/routes.js
index 1facb3b..9604915 100644
--- a/src/fauxton/app/modules/documents/routes.js
+++ b/src/fauxton/app/modules/documents/routes.js
@@ -181,7 +181,8 @@ function(app, FauxtonAPI, Documents, Databases) {
     },
 
     events: {
-      "route:updateAllDocs": "updateAllDocsFromView"
+      "route:updateAllDocs": "updateAllDocsFromView",
+      "route:updatePreviewDocs": "updateAllDocsFromPreview"
     },
 
     initialize: function (route, masterLayout, options) {
@@ -219,6 +220,7 @@ function(app, FauxtonAPI, Documents, Databases) {
       var docOptions = app.getParams(options);
 
       docOptions.include_docs = true;
+      console.log('doc options', docOptions);
       this.data.database.buildAllDocs(docOptions);
 
       if (docOptions.startkey && docOptions.startkey.indexOf('_design') > -1) {
@@ -267,6 +269,7 @@ function(app, FauxtonAPI, Documents, Databases) {
         viewName: view,
         params: params,
         newView: false,
+        database: this.data.database,
         ddocInfo: ddocInfo
       }));
 
@@ -313,7 +316,6 @@ function(app, FauxtonAPI, Documents, Databases) {
       var view = event.view,
           ddoc = event.ddoc;
 
-       console.log('updae', event);
       this.data.indexedDocs = new Documents.IndexCollection(null, {
         database: this.data.database,
         design: ddoc,
@@ -323,6 +325,23 @@ function(app, FauxtonAPI, Documents, Databases) {
 
       this.documentsView.collection = this.data.indexedDocs;
       this.documentsView.forceRender();
+    },
+
+    updateAllDocsFromPreview: function (event) {
+      var view = event.view,
+          rows = event.rows,
+          ddoc = event.ddoc;
+
+      this.data.indexedDocs = new Documents.PouchIndexCollection(null, {
+        database: this.data.database,
+        design: ddoc,
+        view: view,
+        rows: rows
+      });
+
+      console.log(this.data.indexedDocs);
+      this.documentsView.collection = this.data.indexedDocs;
+      this.documentsView.forceRender();
     }
   });
 

http://git-wip-us.apache.org/repos/asf/couchdb/blob/9eba40bf/src/fauxton/app/modules/documents/views.js
----------------------------------------------------------------------
diff --git a/src/fauxton/app/modules/documents/views.js b/src/fauxton/app/modules/documents/views.js
index c267f31..1213ce3 100644
--- a/src/fauxton/app/modules/documents/views.js
+++ b/src/fauxton/app/modules/documents/views.js
@@ -16,6 +16,7 @@ define([
   "api",
  
   "modules/documents/resources",
+  "modules/pouchdb/base",
 
   // Libs
   "codemirror",
@@ -27,7 +28,7 @@ define([
 
 ],
 
-function(app, FauxtonAPI, Documents, Codemirror, JSHint) {
+function(app, FauxtonAPI, Documents, pouchdb, Codemirror, JSHint) {
   var Views = {};
 
   Views.Tabs = FauxtonAPI.View.extend({
@@ -294,7 +295,7 @@ function(app, FauxtonAPI, Documents, Codemirror, JSHint) {
     },
 
     establish: function() {
-      return this.collection.fetch().error(function() {
+      return this.collection.fetch().fail(function() {
         // TODO: handle error requests that slip through
         // This should just throw a notification, not break the page
         console.log("ERROR: ", arguments);
@@ -389,7 +390,7 @@ function(app, FauxtonAPI, Documents, Codemirror, JSHint) {
         this.model.clear({silent:true});
         this.model.set(json);
         notification = FauxtonAPI.addNotification({msg: "Saving document."});
-        this.model.save().error(function(xhr) {
+        this.model.save().fail(function(xhr) {
           var responseText = JSON.parse(xhr.responseText).reason;
           notification = FauxtonAPI.addNotification({
             msg: "Save failed: " + responseText,
@@ -519,6 +520,7 @@ function(app, FauxtonAPI, Documents, Codemirror, JSHint) {
       this.viewCollection = options.viewCollection;
       this.viewName = options.viewName;
       this.params = options.params;
+      this.database = options.database;
       if (this.newView) {
         //TODO: CREATE NEW HERE
       } else {
@@ -547,11 +549,8 @@ function(app, FauxtonAPI, Documents, Codemirror, JSHint) {
       }
     },
 
-    updateView: function(event) {
-      var $form = $(event.currentTarget);
-
-      event.preventDefault();
-
+    queryParams: function () {
+      var $form = $(".view-query-update");
       // Ignore params without a value
       var params = _.filter($form.serializeArray(), function(param) {
         return param.value;
@@ -572,6 +571,16 @@ function(app, FauxtonAPI, Documents, Codemirror, JSHint) {
         }
       });
 
+      return {params: params, errorParams: errorParams};
+    },
+
+    updateView: function(event) {
+      event.preventDefault();
+
+      var paramInfo = this.queryParams(),
+          errorParams = paramInfo.errorParams,
+          params = paramInfo.params;
+
       if (_.any(errorParams)) {
         _.map(errorParams, function(param) {
 
@@ -638,17 +647,42 @@ function(app, FauxtonAPI, Documents, Codemirror, JSHint) {
     },
 
     previewView: function(event) {
+      var that = this,
+          mapVal = this.mapEditor.getValue(),
+          reduceVal = this.reduceVal(),
+          paramsArr = this.queryParams().params;
+
+      var params = _.reduce(paramsArr, function (params, param) {
+        params[param.name] = param.value;
+        return params;
+      }, {reduce: false});
+
       event.preventDefault();
+
       FauxtonAPI.addNotification({
         msg: "<strong>Warning!</strong> Preview executes the Map/Reduce functions in your browser, and may behave differently from CouchDB.",
         type: "warning",
         selector: "#define-view .errors-container",
-        fade: false
+        fade: true
       });
-      FauxtonAPI.addNotification({
-        msg: "Preview Functionality Coming Soon",
-        type: "warning",
-        selector: "#define-view .errors-container"
+     
+      var promise = FauxtonAPI.Deferred();
+
+      if (!this.database.allDocs) {
+        this.database.buildAllDocs({limit: "100", include_docs: true});
+        promise = this.database.allDocs.fetch();
+      } else {
+        promise.resolve();
+      }
+
+      promise.then(function () {
+        params.docs = that.database.allDocs.map(function (model) { return model.get('doc');}); 
+
+        var queryPromise = pouchdb.runViewQuery({map: mapVal, reduce: reduceVal}, params);
+          queryPromise.then(function (results) {
+            console.log('promise', arguments, results);
+            FauxtonAPI.triggerRouteEvent('updatePreviewDocs', {rows: results.rows, ddoc: that.ddocID, view: that.viewName});
+          });
       });
     },
 
@@ -661,18 +695,13 @@ function(app, FauxtonAPI, Documents, Codemirror, JSHint) {
       if (this.hasValidCode()) {
         var mapVal = this.mapEditor.getValue(), 
             reduceVal = "",
-            reduceOption = this.$('#reduce-function-selector :selected').val(),
+            
             viewName = this.$('#index-name').val();
             ddocName = this.$('#ddoc :selected').val();
 
          this.viewName = viewName;
 
-         if (reduceOption === 'CUSTOM') {
-            reduceVal = this.reduceEditor.getValue();
-         } else if ( reduceOption !== 'NONE') {
-           reduceVal = reduceOption;
-         }
-
+         
          var ddoc = this.ddocs.find(function (ddoc) {
            return ddoc.id === ddocName;
          }).dDocModel();
@@ -715,6 +744,16 @@ function(app, FauxtonAPI, Documents, Codemirror, JSHint) {
     },
 
     reduceVal: function() {
+      var reduceOption = this.$('#reduce-function-selector :selected').val(),
+          reduceVal = "";
+
+      if (reduceOption === 'CUSTOM') {
+        reduceVal = this.reduceEditor.getValue();
+      } else if ( reduceOption !== 'NONE') {
+        reduceVal = reduceOption;
+      }
+      
+      return reduceVal;
     },
 
     hasValidCode: function() {

http://git-wip-us.apache.org/repos/asf/couchdb/blob/9eba40bf/src/fauxton/app/modules/pouchdb/base.js
----------------------------------------------------------------------
diff --git a/src/fauxton/app/modules/pouchdb/base.js b/src/fauxton/app/modules/pouchdb/base.js
index 2b7cfc9..ddaf06d 100644
--- a/src/fauxton/app/modules/pouchdb/base.js
+++ b/src/fauxton/app/modules/pouchdb/base.js
@@ -31,8 +31,8 @@ function(app, FauxtonAPI, MapReduce) {
   var Pouch = {};
   Pouch.MapReduce = MapReduce;
 
-  Pouch.runViewQuery = function(fun, docs) {
-    docs = [
+  Pouch.runViewQuery = function(fun, opts) {
+    /*docs = [
       {_id: 'test_doc_1', foo: 'bar-1'},
       {_id: 'test_doc_2', foo: 'bar-2'},
       {_id: 'test_doc_3', foo: 'bar-3'},
@@ -43,15 +43,18 @@ function(app, FauxtonAPI, MapReduce) {
       {_id: 'test_doc_8', foo: 'bar-8'},
       {_id: 'test_doc_9', foo: 'bar-9'},
       {_id: 'test_doc_10', foo: 'bar-10'}
-    ];
+    ];*/
 
     var deferred = FauxtonAPI.Deferred();
-    var complete = function(resp) {
-      console.log("COMPLETE TRIGGERED", arguments);
+    var complete = function(resp, rows) {
+      deferred.resolve(rows);
     };
 
-    return Pouch.MapReduce.query(fun, {docs: docs, complete:complete});
-  };
+    var options = _.extend(opts, {complete: complete});
 
+    Pouch.MapReduce.query(fun, options);
+    return deferred;
+  };
+  //pdb.runViewQuery({map:function(doc) { emit(doc._id, doc.foo) }})
   return Pouch;
 });

http://git-wip-us.apache.org/repos/asf/couchdb/blob/9eba40bf/src/fauxton/app/modules/pouchdb/pouchdb.mapreduce.js
----------------------------------------------------------------------
diff --git a/src/fauxton/app/modules/pouchdb/pouchdb.mapreduce.js b/src/fauxton/app/modules/pouchdb/pouchdb.mapreduce.js
index b97eb7f..a2d0b91 100644
--- a/src/fauxton/app/modules/pouchdb/pouchdb.mapreduce.js
+++ b/src/fauxton/app/modules/pouchdb/pouchdb.mapreduce.js
@@ -39,6 +39,36 @@ function(app, FauxtonAPI, Collate) {
   //var MapReduce = function(db) {
   var MapReduce = function() {
 
+    var builtInReduce = {
+      "_sum": function(keys, values){
+        return sum(values);
+      },
+
+      "_count": function(keys, values, rereduce){
+        if (rereduce){
+          return sum(values);
+        } else {
+          return values.length;
+        }
+      },
+
+      "_stats": function(keys, values, rereduce){
+        return {
+          'sum': sum(values),
+          'min': Math.min.apply(null, values),
+          'max': Math.max.apply(null, values),
+          'count': values.length,
+          'sumsqr': (function(){
+            _sumsqr = 0;
+            for(var idx in values){
+              _sumsqr += values[idx] * values[idx];
+            }
+            return _sumsqr;
+          })()
+        };
+      }
+    };
+
     function viewQuery(fun, options) {
       console.log("IN VIEW QUERY");
       if (!options.complete) {
@@ -55,13 +85,13 @@ function(app, FauxtonAPI, Collate) {
       var completed= false;
 
       var emit = function(key, val) {
-        console.log("IN EMIT: ", key, val, current);
+        //console.log("IN EMIT: ", key, val, current);
         var viewRow = {
           id: current.doc._id,
           key: key,
           value: val
         }; 
-        console.log("VIEW ROW: ", viewRow);
+        //console.log("VIEW ROW: ", viewRow);
 
         if (options.startkey && Pouch.collate(key, options.startkey) < 0) return;
         if (options.endkey && Pouch.collate(key, options.endkey) > 0) return;
@@ -95,7 +125,11 @@ function(app, FauxtonAPI, Collate) {
       // ugly way to make sure references to 'emit' in map/reduce bind to the
       // above emit
       eval('fun.map = ' + fun.map.toString() + ';');
-      if (fun.reduce) {
+      if (fun.reduce && options.reduce) {
+        if (builtInReduce[fun.reduce]) {
+          console.log('built in reduce');
+          fun.reduce = builtInReduce[fun.reduce];
+        }
         eval('fun.reduce = ' + fun.reduce.toString() + ';');
       }
 
@@ -105,6 +139,7 @@ function(app, FauxtonAPI, Collate) {
 
       //only proceed once all documents are mapped and joined
       var checkComplete= function(){
+        console.log('check');
         if (completed && results.length == num_started){
           results.sort(function(a, b) {
             return Pouch.collate(a.key, b.key);
@@ -116,6 +151,7 @@ function(app, FauxtonAPI, Collate) {
             return options.complete(null, {rows: results});
           }
 
+          console.log('reducing', options);
           var groups = [];
           results.forEach(function(e) {
             var last = groups[groups.length-1] || null;
@@ -130,19 +166,21 @@ function(app, FauxtonAPI, Collate) {
             e.value = fun.reduce(e.key, e.value) || null;
             e.key = e.key[0][0];
           });
+          console.log('GROUPs', groups);
           options.complete(null, {rows: groups});
         }
       };
 
       if (options.docs) {
-        console.log("RUNNING MR ON DOCS: ", options.docs);
+        //console.log("RUNNING MR ON DOCS: ", options.docs);
         _.each(options.docs, function(doc) {
           current = {doc: doc};
           fun.map.call(this, doc);
         }, this);
-        return options.complete(null, {rows: results});
+        completed = true;
+        return checkComplete();//options.complete(null, {rows: results});
       } else {
-        console.log("COULD NOT FIND DOCS");
+        //console.log("COULD NOT FIND DOCS");
         return false;
       }