couchdb-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From benk...@apache.org
Subject fauxton commit: updated refs/heads/master to 15d49fc
Date Mon, 12 Jan 2015 20:20:45 GMT
Repository: couchdb-fauxton
Updated Branches:
  refs/heads/master 71e7e7af9 -> 15d49fcb2


Add sidebar to compaction docs page

This ticket adds the sidebar to the Compaction docs page and refactors
the code a little to start explictly stating what resources and Views
in the documents addon are intended for sharing.

Closes COUCHDB-2404


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

Branch: refs/heads/master
Commit: 15d49fcb21ec194b68736799887a5ca040e02fef
Parents: 71e7e7a
Author: Benjamin Keen <ben.keen@gmail.com>
Authored: Wed Dec 17 17:57:47 2014 -0800
Committer: Benjamin Keen <ben.keen@gmail.com>
Committed: Mon Jan 12 11:03:30 2015 -0800

----------------------------------------------------------------------
 app/addons/compaction/routes.js                 |  43 +--
 app/addons/documents/resources.js               | 348 +++----------------
 app/addons/documents/routes-documents.js        | 106 +-----
 app/addons/documents/routes.js                  |   2 +-
 app/addons/documents/shared-resources.js        | 320 +++++++++++++++++
 app/addons/documents/shared-routes.js           |  66 ++++
 app/addons/documents/shared-views.js            | 278 +++++++++++++++
 app/addons/documents/templates/sidebar.html     |   2 +-
 app/addons/documents/tests/views-sidebarSpec.js |   4 +-
 app/addons/documents/views-sidebar.js           | 278 ---------------
 app/addons/documents/views.js                   |   4 +-
 11 files changed, 745 insertions(+), 706 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/15d49fcb/app/addons/compaction/routes.js
----------------------------------------------------------------------
diff --git a/app/addons/compaction/routes.js b/app/addons/compaction/routes.js
index ff15c88..83740b0 100644
--- a/app/addons/compaction/routes.js
+++ b/app/addons/compaction/routes.js
@@ -11,35 +11,30 @@
 // the License.
 
 define([
-       "app",
+  'app',
+  'api',
 
-       "api",
-
-       // Modules
-       "addons/compaction/views",
-       "addons/databases/resources"
+  // Modules
+  'addons/compaction/views',
+  'addons/databases/resources',
+  'addons/documents/shared-routes'
 ],
 
-function(app, FauxtonAPI, Compaction, Databases) {
-
-  var  CompactionRouteObject = FauxtonAPI.RouteObject.extend({
-    layout: "one_pane",
-
-    crumbs: function () {
-      return [
-        {"name": this.database.id, "link": Databases.databaseUrl(this.database)},
-        {"name": "Compact & Clean", "link": "compact"}
-      ];
-    },
+function(app, FauxtonAPI, Compaction, Databases, BaseRoute) {
 
+  var CompactionRouteObject = BaseRoute.extend({
     routes: {
       "database/:database/compact": "compaction"
     },
 
-    initialize: function(route, masterLayout, options) {
+    initialize: function (route, masterLayout, options) {
       var databaseName = options[0];
+      this.database = this.database || new Databases.Model({ id: databaseName });
+      this.allDatabases = new Databases.List();
 
-      this.database = this.database || new Databases.Model({id: databaseName});
+      this.createDesignDocsCollection();
+      this.addLeftHeader();
+      this.addSidebar('docLink_compact');
     },
 
     compaction: function () {
@@ -47,13 +42,11 @@ function(app, FauxtonAPI, Compaction, Databases) {
     },
 
     establish: function () {
-      return this.database.fetch();
+      return [
+        this.designDocs.fetch({reset: true}),
+        this.allDatabases.fetchOnce()
+      ];
     }
-
-    /*apiUrl: function() {
-      return [this.compactions.url(), this.compactions.documentation];
-    },*/
-
   });
 
   Compaction.RouteObjects = [CompactionRouteObject];

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/15d49fcb/app/addons/documents/resources.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/resources.js b/app/addons/documents/resources.js
index 7a80ab2..660a52f 100644
--- a/app/addons/documents/resources.js
+++ b/app/addons/documents/resources.js
@@ -11,13 +11,13 @@
 // the License.
 
 define([
-  "app",
-  "api",
-  "cloudant.pagingcollection"
+  'app',
+  'api',
+  'addons/documents/shared-resources',
+  'cloudant.pagingcollection'
 ],
 
-function(app, FauxtonAPI, PagingCollection) {
-  var Documents = FauxtonAPI.addon();
+function(app, FauxtonAPI, Documents, PagingCollection) {
 
   Documents.QueryParams = (function () {
     var _eachParams = function (params, action) {
@@ -44,195 +44,6 @@ function(app, FauxtonAPI, PagingCollection) {
     };
   })();
 
-  Documents.Doc = FauxtonAPI.Model.extend({
-    idAttribute: "_id",
-    documentation: function(){
-      return FauxtonAPI.constants.DOC_URLS.GENERAL;
-    },
-    url: function(context) {
-      if (context === "app") {
-        return this.getDatabase().url("app") + "/" + this.safeID();
-      } else if (context === "web-index") {
-        return this.getDatabase().url("app") + "/" + app.utils.safeURLName(this.id);
-      } else if (context === "apiurl"){
-        return window.location.origin + "/" + this.getDatabase().safeID() + "/" + this.safeID();
-      } else {
-        return app.host + "/" + this.getDatabase().safeID() + "/" + this.safeID();
-      }
-    },
-
-    initialize: function(_attrs, options) {
-      if (this.collection && this.collection.database) {
-        this.database = this.collection.database;
-      } else if (options.database) {
-        this.database = options.database;
-      }
-    },
-
-    // HACK: the doc needs to know about the database, but it may be
-    // set directly or indirectly in all docs
-    getDatabase: function() {
-      return this.database ? this.database : this.collection.database;
-    },
-
-    validate: function(attrs, options) {
-      if (this.id && this.id !== attrs._id && this.get('_rev') ) {
-        return "Cannot change a documents id.";
-      }
-    },
-
-    docType: function() {
-      return this.id && this.id.match(/^_design\//) ? "design doc" : "doc";
-    },
-
-    isEditable: function() {
-      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";
-    },
-
-    hasViews: function() {
-      if (!this.isDdoc()) return false;
-      var doc = this.get('doc');
-      if (doc) {
-        return doc && doc.views && _.keys(doc.views).length > 0;
-      }
-
-      var views = this.get('views');
-      return views && _.keys(views).length > 0;
-    },
-
-    hasAttachments: function () {
-      return !!this.get('_attachments');
-    },
-
-    getDdocView: function(view) {
-      if (!this.isDdoc() || !this.hasViews()) return false;
-
-      var doc = this.get('doc');
-      if (doc) {
-        return doc.views[view];
-      }
-
-      return this.get('views')[view];
-    },
-
-    setDdocView: function (view, map, reduce) {
-      if (!this.isDdoc()) return false;
-      var views = this.get('views'),
-          tempView = views[view] || {};
-
-      if (reduce) {
-        tempView.reduce=reduce;
-      } else {
-        delete tempView.reduce;
-      }
-      tempView.map= map;
-
-      views[view] = tempView;
-      this.set({views: views});
-
-      return true;
-    },
-
-    removeDdocView: function (viewName) {
-      if (!this.isDdoc()) return false;
-      var views = this.get('views');
-
-      delete views[viewName];
-      this.set({views: views});
-    },
-
-    dDocModel: function () {
-      if (!this.isDdoc()) return false;
-      var doc = this.get('doc');
-
-      if (doc) {
-        return new Documents.Doc(doc, {database: this.database});
-      }
-
-      return this;
-    },
-
-    viewHasReduce: function(viewName) {
-      var view = this.getDdocView(viewName);
-
-      return view && view.reduce;
-    },
-
-    // Need this to work around backbone router thinking _design/foo
-    // is a separate route. Alternatively, maybe these should be
-    // treated separately. For instance, we could default into the
-    // json editor for docs, or into a ddoc specific page.
-    safeID: function() {
-      if (this.isDdoc()){
-        var ddoc = this.id.replace(/^_design\//,"");
-        return "_design/"+app.utils.safeURLName(ddoc);
-      }else{
-        return app.utils.safeURLName(this.id);
-      }
-    },
-
-    destroy: function() {
-      var url = this.url() + "?rev=" + this.get('_rev');
-      return $.ajax({
-        url: url,
-        dataType: 'json',
-        type: 'DELETE'
-      });
-    },
-
-    parse: function(resp) {
-      if (resp.rev) {
-        resp._rev = resp.rev;
-        delete resp.rev;
-      }
-      if (resp.id) {
-        if (_.isUndefined(this.id)) {
-          resp._id = resp.id;
-        }
-      }
-
-      if (resp.ok) {
-        delete resp.id;
-        delete resp.ok;
-      }
-
-      return resp;
-    },
-
-    prettyJSON: function() {
-      var data = this.get("doc") ? this.get("doc") : this.attributes;
-
-      return JSON.stringify(data, null, "  ");
-    },
-
-    copy: function (copyId) {
-      return $.ajax({
-        type: 'COPY',
-        url: '/' + this.database.safeID() + '/' + this.safeID(),
-        headers: {Destination: copyId}
-      });
-    },
-
-    isNewDoc: function () {
-      return this.get('_rev') ? false : true;
-    }
-  });
 
   Documents.DdocInfo = FauxtonAPI.Model.extend({
     idAttribute: "_id",
@@ -366,111 +177,6 @@ function(app, FauxtonAPI, PagingCollection) {
     }
   });
 
-
-  Documents.AllDocs = PagingCollection.extend({
-    model: Documents.Doc,
-    documentation: function(){
-      return FauxtonAPI.constants.DOC_URLS.GENERAL;
-    },
-    initialize: function(_models, options) {
-      this.viewMeta = options.viewMeta;
-      this.database = options.database;
-      this.params = _.clone(options.params);
-
-      this.on("remove",this.decrementTotalRows , this);
-      this.perPageLimit = options.perPageLimit || 20;
-
-      if (!this.params.limit) {
-        this.params.limit = this.perPageLimit;
-      }
-    },
-
-    urlRef: function(context, params) {
-      var query = "";
-
-      if (params) {
-        if (!_.isEmpty(params)) {
-          query = "?" + $.param(params);
-        } else {
-          query = '';
-        }
-      } else if (this.params) {
-        query = "?" + $.param(this.params);
-      }
-
-      if (context === 'app') {
-        return 'database/' + this.database.safeID() + "/_all_docs" + query;
-      } else if (context === "apiurl"){
-        return window.location.origin + "/" + this.database.safeID() + "/_all_docs" + query;
-      } else {
-        return app.host + "/" + this.database.safeID() + "/_all_docs" + query;
-      }
-    },
-
-    url: function () {
-      return this.urlRef.apply(this, arguments);
-    },
-
-    simple: function () {
-      var docs = this.map(function (item) {
-        return {
-          _id: item.id,
-          _rev: item.get('_rev'),
-        };
-      });
-
-      return new Documents.AllDocs(docs, {
-        database: this.database,
-        params: this.params
-      });
-    },
-
-    totalRows: function() {
-      return this.viewMeta.total_rows || "unknown";
-    },
-
-    decrementTotalRows: function () {
-      if (this.viewMeta.total_rows) {
-        this.viewMeta.total_rows = this.viewMeta.total_rows -1;
-        this.trigger('totalRows:decrement');
-      }
-    },
-
-    updateSeq: function() {
-      return this.viewMeta.update_seq || false;
-    },
-
-    parse: function(resp) {
-      var rows = resp.rows;
-
-      // remove any query errors that may return without doc info
-      // important for when querying keys on all docs
-      var cleanRows = _.filter(rows, function(row){
-        return row.value;
-      });
-
-      resp.rows = _.map(cleanRows, function(row){
-        return {
-          _id: row.id,
-          _rev: row.value.rev,
-          value: row.value,
-          key: row.key,
-          doc: row.doc || undefined
-        };
-      });
-
-      return PagingCollection.prototype.parse.call(this, resp);
-    },
-
-    clone: function () {
-      return new this.constructor(this.models, {
-        database: this.database,
-        params: this.params,
-        paging: this.paging
-      });
-    }
-  });
-
   Documents.IndexCollection = PagingCollection.extend({
     model: Documents.Doc,
     documentation: function(){
@@ -674,7 +380,49 @@ function(app, FauxtonAPI, PagingCollection) {
     }
   });
 
-
+  Documents.setUpDropdown = function (database) {
+    var defaultMenuLinks = [{
+      links: [{
+        title: 'Replicate Database',
+        icon: 'fonticon-replicate',
+        url: '#/replication/' + database.get('id')
+      },{
+        title: 'Delete',
+        icon: 'fonticon-trash',
+        trigger: 'database:delete'
+      }]
+    }];
+
+    defaultMenuLinks.push({
+      title: 'Add new',
+      links: Documents.getExtensionLinks(database)
+    });
+
+    return defaultMenuLinks;
+  };
+
+  Documents.getExtensionLinks = function (database) {
+    var newUrlPrefix = "#" + database.url('app');
+
+    var menuLinks = [{
+      title: 'New Doc',
+      url: newUrlPrefix + '/new',
+      icon: 'fonticon-plus-circled'
+    },{
+      title: 'New View',
+      url: newUrlPrefix + '/new_view',
+      icon: 'fonticon-plus-circled'
+    }];
+
+    return _.reduce(FauxtonAPI.getExtensions('sidebar:links'), function (menuLinks, link) {
+      menuLinks.push({
+        title: link.title,
+        url: newUrlPrefix + "/" + link.url,
+        icon: 'fonticon-plus-circled'
+      });
+      return menuLinks;
+    }, menuLinks);
+  };
 
   return Documents;
 });

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/15d49fcb/app/addons/documents/routes-documents.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/routes-documents.js b/app/addons/documents/routes-documents.js
index 7c02bba..74eb48b 100644
--- a/app/addons/documents/routes-documents.js
+++ b/app/addons/documents/routes-documents.js
@@ -15,6 +15,7 @@ define([
   "api",
 
   // Modules
+  'addons/documents/shared-routes',
   "addons/documents/views",
   "addons/documents/views-changes",
   "addons/documents/views-index",
@@ -25,30 +26,12 @@ define([
   "addons/fauxton/components"
 ],
 
-function(app, FauxtonAPI, Documents, Changes, Index, DocEditor, Databases, Resources, Components) {
+function(app, FauxtonAPI, BaseRoute, Documents, Changes, Index, DocEditor, Databases, Resources, Components) {
 
-  // TODO these are the same. Legacy code?
-  var crumbs = {
-    allDocs: function (database) {
-      return [
-        { "type": "back", "link": "/_all_dbs" },
-        { "name": database.id, "link": Databases.databaseUrl(database), className: "lookahead-tray-link" }
-      ];
-    },
-
-    changes: function (database) {
-      return [
-        { "type": "back", "link": "/_all_dbs" },
-        { "name": database.id, "link": Databases.databaseUrl(database), className: "lookahead-tray-link" }
-      ];
-    }
-  };
 
-  var DocumentsRouteObject = FauxtonAPI.RouteObject.extend({
+  var DocumentsRouteObject = BaseRoute.extend({
     layout: "with_tabs_sidebar",
-    selectedHeader: "Databases",
     routes: {
-
       "database/:database/_all_docs(:extra)": {
         route: "allDocs",
         roles: ["fx_loggedIn"]
@@ -88,8 +71,6 @@ function(app, FauxtonAPI, Documents, Changes, Index, DocEditor, Databases, Resou
       "route:updateQueryOptions": "updateQueryOptions"
     },
 
-    overrideBreadcrumbs: true,
-
     initialize: function (route, masterLayout, options) {
       this.initViews(options[0]);
       this.listenToLookaheadTray();
@@ -107,38 +88,14 @@ function(app, FauxtonAPI, Documents, Changes, Index, DocEditor, Databases, Resou
       this.database = new Databases.Model({id: this.databaseName});
       this.allDatabases = new Databases.List();
 
-      this.designDocs = new Documents.AllDocs(null, {
-        database: this.database,
-        paging: {
-          pageSize: 500
-        },
-        params: {
-          startkey: '_design/',
-          endkey: '_design0',
-          include_docs: true,
-          limit: 500
-        }
-      });
+      this.createDesignDocsCollection();
 
       this.rightHeader = this.setView("#right-header", new Documents.Views.RightAllDocsHeader({
         database: this.database
       }));
 
-      this.leftheader = this.setView("#breadcrumbs", new Components.LeftHeader({
-        crumbs: crumbs.allDocs(this.database),
-        dropdownMenu: this.setUpDropdown(),
-        lookaheadTrayOptions: {
-          databaseCollection: this.allDatabases,
-          toggleEventName: 'lookaheadTray:toggle',
-          onUpdateEventName: 'lookaheadTray:update',
-          placeholder: 'Enter database name'
-        }
-      }));
-
-      this.sidebar = this.setView("#sidebar-content", new Documents.Views.Sidebar({
-        collection: this.designDocs,
-        database: this.database
-      }));
+      this.addLeftHeader();
+      this.addSidebar();
     },
 
     // this safely assumes the db name is valid
@@ -159,51 +116,6 @@ function(app, FauxtonAPI, Documents, Changes, Index, DocEditor, Databases, Resou
       this.listenTo(FauxtonAPI.Events, 'lookaheadTray:update', this.onSelectDatabase);
     },
 
-    setUpDropdown: function() {
-      var defaultMenuLinks = [{
-        links: [{
-          title: 'Replicate Database',
-          icon: 'fonticon-replicate',
-          url: '#/replication/' + this.databaseName
-        },{
-          title: 'Delete',
-          icon: 'fonticon-trash',
-          trigger: 'database:delete'
-        }]
-      }];
-
-      defaultMenuLinks.push({
-        title: 'Add new',
-        links: this.getExtensionLinks()
-      });
-
-      return defaultMenuLinks;
-    },
-
-    getExtensionLinks: function () {
-      var database = this.database,
-          newurlPrefix = "#" + database.url('app');
-
-      var menuLinks = [{
-          title: 'New Doc',
-          url: newurlPrefix + '/new',
-          icon: 'fonticon-plus-circled'
-        },{
-          title: 'New View',
-          url: newurlPrefix + '/new_view',
-          icon: 'fonticon-plus-circled'
-      }];
-
-      return _.reduce(FauxtonAPI.getExtensions('sidebar:links'), function (menuLinks, link) {
-        menuLinks.push({
-          title: link.title,
-          url: newurlPrefix + "/" + link.url,
-          icon: 'fonticon-plus-circled'
-        });
-        return menuLinks;
-      }, menuLinks);
-    },
-
     designDocMetadata: function (database, ddoc) {
       this.footer && this.footer.remove();
       this.toolsView && this.toolsView.remove();
@@ -216,7 +128,7 @@ function(app, FauxtonAPI, Documents, Changes, Index, DocEditor, Databases, Resou
       }));
 
       this.sidebar.setSelectedTab(app.utils.removeSpecialCharacters(ddoc)+"_metadata");
-      this.leftheader.updateCrumbs(crumbs.allDocs(this.database));
+      this.leftheader.updateCrumbs(this.getCrumbs(this.database));
       this.rightHeader.hideQueryOptions();
 
       this.apiUrl = [designDocInfo.url('apiurl'), designDocInfo.documentation()];
@@ -260,7 +172,7 @@ function(app, FauxtonAPI, Documents, Changes, Index, DocEditor, Databases, Resou
 
       this.footer = this.setView('#footer', new Documents.Views.Footer());
 
-      this.leftheader.updateCrumbs(crumbs.allDocs(this.database));
+      this.leftheader.updateCrumbs(this.getCrumbs(this.database));
 
       this.database.buildAllDocs(docParams);
       collection = this.database.allDocs;
@@ -576,7 +488,7 @@ function(app, FauxtonAPI, Documents, Changes, Index, DocEditor, Databases, Resou
       this.viewEditor && this.viewEditor.remove();
 
       this.sidebar.setSelectedTab('changes');
-      this.leftheader.updateCrumbs(crumbs.changes(this.database));
+      this.leftheader.updateCrumbs(this.getCrumbs(this.database));
       this.rightHeader.hideQueryOptions();
 
       this.apiUrl = function () {

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/15d49fcb/app/addons/documents/routes.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/routes.js b/app/addons/documents/routes.js
index 02106c8..4756665 100644
--- a/app/addons/documents/routes.js
+++ b/app/addons/documents/routes.js
@@ -13,7 +13,7 @@
 define([
   "addons/documents/views",
   "addons/documents/routes-documents",
-  "addons/documents/routes-doc-editor",
+  "addons/documents/routes-doc-editor"
 ],
 
 function(Documents, DocumentsRouteObject, docEditor) {

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/15d49fcb/app/addons/documents/shared-resources.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/shared-resources.js b/app/addons/documents/shared-resources.js
new file mode 100644
index 0000000..2d086aa
--- /dev/null
+++ b/app/addons/documents/shared-resources.js
@@ -0,0 +1,320 @@
+// 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',
+  'cloudant.pagingcollection'
+], function (app, FauxtonAPI, PagingCollection) {
+
+  // defined here because this is contains the base resources used throughout the addon and outside,
+  // so it's the first code that gets run
+  var Documents = FauxtonAPI.addon();
+
+
+  Documents.Doc = FauxtonAPI.Model.extend({
+    idAttribute: "_id",
+    documentation: function(){
+      return FauxtonAPI.constants.DOC_URLS.GENERAL;
+    },
+    url: function(context) {
+      if (context === "app") {
+        return this.getDatabase().url("app") + "/" + this.safeID();
+      } else if (context === "web-index") {
+        return this.getDatabase().url("app") + "/" + app.utils.safeURLName(this.id);
+      } else if (context === "apiurl"){
+        return window.location.origin + "/" + this.getDatabase().safeID() + "/" + this.safeID();
+      } else {
+        return app.host + "/" + this.getDatabase().safeID() + "/" + this.safeID();
+      }
+    },
+
+    initialize: function(_attrs, options) {
+      if (this.collection && this.collection.database) {
+        this.database = this.collection.database;
+      } else if (options.database) {
+        this.database = options.database;
+      }
+    },
+
+    // HACK: the doc needs to know about the database, but it may be
+    // set directly or indirectly in all docs
+    getDatabase: function() {
+      return this.database ? this.database : this.collection.database;
+    },
+
+    validate: function(attrs, options) {
+      if (this.id && this.id !== attrs._id && this.get('_rev') ) {
+        return "Cannot change a documents id.";
+      }
+    },
+
+    docType: function() {
+      return this.id && this.id.match(/^_design\//) ? "design doc" : "doc";
+    },
+
+    isEditable: function() {
+      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";
+    },
+
+    hasViews: function() {
+      if (!this.isDdoc()) return false;
+      var doc = this.get('doc');
+      if (doc) {
+        return doc && doc.views && _.keys(doc.views).length > 0;
+      }
+
+      var views = this.get('views');
+      return views && _.keys(views).length > 0;
+    },
+
+    hasAttachments: function () {
+      return !!this.get('_attachments');
+    },
+
+    getDdocView: function(view) {
+      if (!this.isDdoc() || !this.hasViews()) return false;
+
+      var doc = this.get('doc');
+      if (doc) {
+        return doc.views[view];
+      }
+
+      return this.get('views')[view];
+    },
+
+    setDdocView: function (view, map, reduce) {
+      if (!this.isDdoc()) return false;
+      var views = this.get('views'),
+        tempView = views[view] || {};
+
+      if (reduce) {
+        tempView.reduce=reduce;
+      } else {
+        delete tempView.reduce;
+      }
+      tempView.map= map;
+
+      views[view] = tempView;
+      this.set({views: views});
+
+      return true;
+    },
+
+    removeDdocView: function (viewName) {
+      if (!this.isDdoc()) return false;
+      var views = this.get('views');
+
+      delete views[viewName];
+      this.set({views: views});
+    },
+
+    dDocModel: function () {
+      if (!this.isDdoc()) return false;
+      var doc = this.get('doc');
+
+      if (doc) {
+        return new Documents.Doc(doc, {database: this.database});
+      }
+
+      return this;
+    },
+
+    viewHasReduce: function(viewName) {
+      var view = this.getDdocView(viewName);
+
+      return view && view.reduce;
+    },
+
+    // Need this to work around backbone router thinking _design/foo
+    // is a separate route. Alternatively, maybe these should be
+    // treated separately. For instance, we could default into the
+    // json editor for docs, or into a ddoc specific page.
+    safeID: function() {
+      if (this.isDdoc()){
+        var ddoc = this.id.replace(/^_design\//,"");
+        return "_design/"+app.utils.safeURLName(ddoc);
+      }else{
+        return app.utils.safeURLName(this.id);
+      }
+    },
+
+    destroy: function() {
+      var url = this.url() + "?rev=" + this.get('_rev');
+      return $.ajax({
+        url: url,
+        dataType: 'json',
+        type: 'DELETE'
+      });
+    },
+
+    parse: function(resp) {
+      if (resp.rev) {
+        resp._rev = resp.rev;
+        delete resp.rev;
+      }
+      if (resp.id) {
+        if (_.isUndefined(this.id)) {
+          resp._id = resp.id;
+        }
+      }
+
+      if (resp.ok) {
+        delete resp.id;
+        delete resp.ok;
+      }
+
+      return resp;
+    },
+
+    prettyJSON: function() {
+      var data = this.get("doc") ? this.get("doc") : this.attributes;
+
+      return JSON.stringify(data, null, "  ");
+    },
+
+    copy: function (copyId) {
+      return $.ajax({
+        type: 'COPY',
+        url: '/' + this.database.safeID() + '/' + this.safeID(),
+        headers: {Destination: copyId}
+      });
+    },
+
+    isNewDoc: function () {
+      return this.get('_rev') ? false : true;
+    }
+  });
+
+
+  Documents.AllDocs = PagingCollection.extend({
+    model: Documents.Doc,
+    documentation: function () {
+      return FauxtonAPI.constants.DOC_URLS.GENERAL;
+    },
+    initialize: function(_models, options) {
+      this.viewMeta = options.viewMeta;
+      this.database = options.database;
+      this.params = _.clone(options.params);
+
+      this.on("remove",this.decrementTotalRows , this);
+      this.perPageLimit = options.perPageLimit || 20;
+
+      if (!this.params.limit) {
+        this.params.limit = this.perPageLimit;
+      }
+    },
+
+    urlRef: function(context, params) {
+      var query = "";
+
+      if (params) {
+        if (!_.isEmpty(params)) {
+          query = "?" + $.param(params);
+        } else {
+          query = '';
+        }
+      } else if (this.params) {
+        query = "?" + $.param(this.params);
+      }
+
+      if (context === 'app') {
+        return 'database/' + this.database.safeID() + "/_all_docs" + query;
+      } else if (context === "apiurl"){
+        return window.location.origin + "/" + this.database.safeID() + "/_all_docs" + query;
+      } else {
+        return app.host + "/" + this.database.safeID() + "/_all_docs" + query;
+      }
+    },
+
+    url: function () {
+      return this.urlRef.apply(this, arguments);
+    },
+
+    simple: function () {
+      var docs = this.map(function (item) {
+        return {
+          _id: item.id,
+          _rev: item.get('_rev'),
+        };
+      });
+
+      return new Documents.AllDocs(docs, {
+        database: this.database,
+        params: this.params
+      });
+    },
+
+    totalRows: function() {
+      return this.viewMeta.total_rows || "unknown";
+    },
+
+    decrementTotalRows: function () {
+      if (this.viewMeta.total_rows) {
+        this.viewMeta.total_rows = this.viewMeta.total_rows -1;
+        this.trigger('totalRows:decrement');
+      }
+    },
+
+    updateSeq: function() {
+      return this.viewMeta.update_seq || false;
+    },
+
+    parse: function(resp) {
+      var rows = resp.rows;
+
+      // remove any query errors that may return without doc info
+      // important for when querying keys on all docs
+      var cleanRows = _.filter(rows, function(row){
+        return row.value;
+      });
+
+      resp.rows = _.map(cleanRows, function(row){
+        return {
+          _id: row.id,
+          _rev: row.value.rev,
+          value: row.value,
+          key: row.key,
+          doc: row.doc || undefined
+        };
+      });
+
+      return PagingCollection.prototype.parse.call(this, resp);
+    },
+
+    clone: function () {
+      return new this.constructor(this.models, {
+        database: this.database,
+        params: this.params,
+        paging: this.paging
+      });
+    }
+  });
+
+  return Documents;
+});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/15d49fcb/app/addons/documents/shared-routes.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/shared-routes.js b/app/addons/documents/shared-routes.js
new file mode 100644
index 0000000..df991cb
--- /dev/null
+++ b/app/addons/documents/shared-routes.js
@@ -0,0 +1,66 @@
+define([
+  'app',
+  'api',
+  'addons/documents/shared-resources',
+  'addons/databases/base',
+  'addons/fauxton/components'
+], function (app, FauxtonAPI, Documents, Databases, Components) {
+
+
+  // The Documents section is built up a lot of different route object which share code. This contains
+  // base functionality that can be used across routes / addons
+  var BaseRoute = FauxtonAPI.RouteObject.extend({
+    layout: 'with_tabs_sidebar',
+    selectedHeader: 'Databases',
+    overrideBreadcrumbs: true,
+
+    createDesignDocsCollection: function () {
+      this.designDocs = new Documents.AllDocs(null, {
+        database: this.database,
+        paging: {
+          pageSize: 500
+        },
+        params: {
+          startkey: '_design/',
+          endkey: '_design0',
+          include_docs: true,
+          limit: 500
+        }
+      });
+    },
+
+    addLeftHeader: function () {
+      this.leftheader = this.setView('#breadcrumbs', new Components.LeftHeader({
+        crumbs: this.getCrumbs(this.database),
+        dropdownMenu: Documents.setUpDropdown(this.database),
+        lookaheadTrayOptions: {
+          databaseCollection: this.allDatabases,
+          toggleEventName: 'lookaheadTray:toggle',
+          onUpdateEventName: 'lookaheadTray:update',
+          placeholder: 'Enter database name'
+        }
+      }));
+    },
+
+    addSidebar: function (selectedTab) {
+      var params = {
+        collection: this.designDocs,
+        database: this.database
+      };
+      if (selectedTab) {
+        params.selectedTab = selectedTab;
+      }
+      this.sidebar = this.setView("#sidebar-content", new Documents.Views.Sidebar(params));
+    },
+
+    getCrumbs: function (database) {
+      return [
+        { "type": "back", "link": "/_all_dbs" },
+        { "name": database.id, "link": Databases.databaseUrl(database), className: "lookahead-tray-link" }
+      ];
+    }
+  });
+
+
+  return BaseRoute;
+});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/15d49fcb/app/addons/documents/shared-views.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/shared-views.js b/app/addons/documents/shared-views.js
new file mode 100644
index 0000000..5c37225
--- /dev/null
+++ b/app/addons/documents/shared-views.js
@@ -0,0 +1,278 @@
+// 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",
+       "addons/fauxton/components",
+
+       "addons/documents/resources",
+       "addons/databases/resources"
+],
+
+function(app, FauxtonAPI, Components, Documents, Databases) {
+  var Views = {};
+
+  Views.Sidebar = FauxtonAPI.View.extend({
+    template: "addons/documents/templates/sidebar",
+    className: "sidenav",
+    tagName: "nav",
+
+    initialize: function(options) {
+      this.database = options.database;
+      if (options.ddocInfo) {
+        this.ddocID = options.ddocInfo.id;
+        this.currView = options.ddocInfo.currView;
+      }
+
+      this.designDocList = [];
+    },
+
+    serialize: function() {
+      var docLinks = FauxtonAPI.getExtensions('docLinks'),
+          newLinks = FauxtonAPI.getExtensions('sidebar:newLinks'),
+          addLinks = FauxtonAPI.getExtensions('sidebar:links'),
+          extensionList = FauxtonAPI.getExtensions('sidebar:list');
+      return {
+        changes_url: '#' + this.database.url('changes'),
+        permissions_url: '#' + this.database.url('app') + '/permissions',
+        db_url: '#' + this.database.url('index'),
+        database: this.collection.database,
+        database_url: '#' + this.database.url('app'),
+        docLinks: docLinks,
+        addLinks: addLinks,
+        newLinks: newLinks,
+        extensionList: extensionList > 0
+      };
+    },
+
+    getNewButtonLinks: function () {
+      var database = this.collection.database,
+          newurlPrefix = "#" + database.url('app'),
+          addLinks = FauxtonAPI.getExtensions('sidebar:links');
+
+      return _.reduce(FauxtonAPI.getExtensions('sidebar:links'), function (menuLinks, link) {
+
+        menuLinks.push({
+          title: link.title,
+          url: newurlPrefix + "/" + link.url,
+          icon: 'fonticon-plus-circled'
+        });
+
+        return menuLinks; 
+     }, [{
+          title: 'New Doc',
+          url: newurlPrefix + '/new',
+          icon: 'fonticon-plus-circled'
+        },{
+          title: 'New View',
+          url: newurlPrefix + '/new_view',
+          icon: 'fonticon-plus-circled'
+        }]);
+    },
+
+
+    beforeRender: function(manage) {
+      this.deleteDBModal = this.setView(
+        '#delete-db-modal',
+        new Views.DeleteDBModal({database: this.database})
+      );
+
+      var newLinks = [{
+        title: 'Add new',
+        links: this.getNewButtonLinks()
+      }];
+
+      this.setView("#new-all-docs-button", new Components.MenuDropDown({
+        links: newLinks,
+      }));
+
+      this.setView("#new-design-docs-button", new Components.MenuDropDown({
+        links: newLinks,
+      }));
+
+      _.each(this.designDocList, function (view) { view.remove(); view = undefined;});
+      this.designDocList = [];
+
+      this.collection.each(function(design) {
+        if (design.has('doc')){
+          design.collection = this.collection;
+          var view = this.insertView(new Views.DdocSidenav({
+            model: design,
+            collection: this.collection
+          }));
+
+          this.designDocList.push(view);
+        }
+      },this);
+    },
+
+    afterRender: function () {
+      if (this.selectedTab) {
+        this.setSelectedTab(this.selectedTab);
+      }
+    },
+
+    setSelectedTab: function (selectedTab) {
+      this.selectedTab = selectedTab;
+      var $selectedTab = this.$('#' + selectedTab);
+
+      this.$('li').removeClass('active');
+      $selectedTab.parent().addClass('active');
+
+      if ($selectedTab.parents(".accordion-body").length !== 0){
+        $selectedTab
+        .parents(".accordion-body")
+        .addClass("in")
+        .parents(".nav-header")
+        .find(">.js-collapse-toggle").addClass("down");
+
+        this.$('.js-toggle-' + $selectedTab.data('ddoctype')).addClass("down");
+      }
+    }
+  });
+
+  Views.DdocSidenav = FauxtonAPI.View.extend({
+    tagName: "ul",
+    className:  "nav nav-list",
+    template: "addons/documents/templates/design_doc_menu",
+    events: {
+      "click .js-collapse-toggle": "toggleArrow"
+    },
+
+    toggleArrow:  function(e){
+      this.$(e.currentTarget).toggleClass("down");
+    },
+    buildIndexList: function(designDocs, info){
+      var design = this.model.id.replace(/^_design\//,"");
+      var databaseId = this.model.database.id;
+
+      if (_.isUndefined(designDocs[info.selector])) { return; }
+
+      this.insertView(".accordion-body", new Views.IndexItem({
+        selector: info.selector,
+        ddoc: design,
+        collection: designDocs[info.selector],
+        name: info.name,
+        database: databaseId
+      }));
+    },
+
+    serialize: function(){
+      var ddocName = this.model.id.replace(/^_design\//,"");
+      return{
+        database: this.collection.database,
+        designDoc: ddocName,
+        ddoc_clean: app.utils.removeSpecialCharacters(ddocName),
+        ddoc_encoded: app.utils.safeURLName(ddocName),
+        database_encoded: app.utils.safeURLName(this.model.database.id),
+      };
+    },
+
+    getSidebarLinks: function () {
+      var ddocName = this.model.id.replace(/^_design\//,""),
+          docSafe = app.utils.safeURLName(ddocName), 
+          database = this.collection.database;
+
+      return _.reduce(FauxtonAPI.getExtensions('sidebar:links'), function (menuLinks, link) {
+
+        menuLinks.push({
+          title: link.title,
+          url: "#" + database.url('app') + "/" + link.url + "/" + docSafe,
+          icon: 'fonticon-plus-circled'
+        });
+
+        return menuLinks; 
+     }, [{
+      title: 'New View',
+      url: "#" + database.url('app') + "/new_view/" + docSafe,
+      icon: 'fonticon-plus-circled'
+     }]);
+
+    },
+
+    renderIndexLists: function () {
+      var ddocDocs = this.model.get("doc"),
+          sidebarListTypes = FauxtonAPI.getExtensions('sidebar:list');
+
+      if (!ddocDocs){ return; }
+
+      this.buildIndexList(ddocDocs, {
+        selector: "views",
+        name: 'Views'
+      });
+
+      _.each(sidebarListTypes, function (info) {
+        this.buildIndexList(ddocDocs, info);
+      },this);
+
+    },
+
+    beforeRender: function(manage) {
+      var sideBarMenuLinks = [];
+
+      sideBarMenuLinks.push({
+        title: 'Add new',
+        links: this.getSidebarLinks()
+      });
+
+      this.renderIndexLists();
+      this.setView(".new-button", new Components.MenuDropDown({
+        links: sideBarMenuLinks,
+      }));
+    }
+  });
+
+  Views.IndexItem = FauxtonAPI.View.extend({
+    template: "addons/documents/templates/index_menu_item",
+    tagName: 'li',
+
+    initialize: function(options){
+      this.index = options.index;
+      this.ddoc = options.ddoc;
+      this.database = options.database;
+      this.selected = !! options.selected;
+      this.selector = options.selector;
+      this.name = options.name;
+
+      this.indexTypeMap = {
+        views:   { icon: 'fonticon-sidenav-map-reduce', urlFolder: '_view' },
+        indexes: { icon: 'fonticon-sidenav-search', urlFolder: '_indexes' }
+      };
+    },
+
+    serialize: function() {
+      return {
+        icon: this.indexTypeMap[this.selector].icon,
+        urlFolder: this.indexTypeMap[this.selector].urlFolder,
+        ddocType:  this.selector,
+        name: this.name,
+        index: this.index,
+        ddoc: this.ddoc,
+        database: this.database,
+        selected: this.selected,
+        collection: this.collection
+      };
+    },
+
+    afterRender: function() {
+      if (this.selected) {
+        $(".sidenav ul.nav-list li").removeClass("active");
+        this.$el.addClass("active");
+      }
+    }
+  });
+
+  return Views;
+});
+

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/15d49fcb/app/addons/documents/templates/sidebar.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/sidebar.html b/app/addons/documents/templates/sidebar.html
index 23d113f..9019d9f 100644
--- a/app/addons/documents/templates/sidebar.html
+++ b/app/addons/documents/templates/sidebar.html
@@ -16,7 +16,7 @@ the License.
   <li><a id="permissions" href="<%= permissions_url %>">Permissions</a><li>
   <li><a id="changes" href="<%= changes_url %>">Changes</a><li>
   <% _.each(docLinks, function (link) { %>
-  <li><a href="<%= database_url + '/' + link.url %>"><%= link.title %></a></li>
+  <li><a id="docLink_<%=link.url%>" href="<%= database_url + '/' + link.url %>"><%= link.title %></a></li>
   <% }); %>
   <li class="active"> 
       <a id="all-docs" href="#<%= database.url('index') %>" class="toggle-view"> All Documents</a> 

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/15d49fcb/app/addons/documents/tests/views-sidebarSpec.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/tests/views-sidebarSpec.js b/app/addons/documents/tests/views-sidebarSpec.js
index c8286bf..60f1a16 100644
--- a/app/addons/documents/tests/views-sidebarSpec.js
+++ b/app/addons/documents/tests/views-sidebarSpec.js
@@ -10,8 +10,8 @@
 // License for the specific language governing permissions and limitations under
 // the License.
 define([
-        'addons/documents/views-sidebar',
-        'testUtils'
+  'addons/documents/shared-views',
+  'testUtils'
 ], function (Views, testUtils) {
   var assert = testUtils.assert,
       ViewSandbox = testUtils.ViewSandbox,

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/15d49fcb/app/addons/documents/views-sidebar.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/views-sidebar.js b/app/addons/documents/views-sidebar.js
deleted file mode 100644
index 5c37225..0000000
--- a/app/addons/documents/views-sidebar.js
+++ /dev/null
@@ -1,278 +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.
-
-define([
-       "app",
-
-       "api",
-       "addons/fauxton/components",
-
-       "addons/documents/resources",
-       "addons/databases/resources"
-],
-
-function(app, FauxtonAPI, Components, Documents, Databases) {
-  var Views = {};
-
-  Views.Sidebar = FauxtonAPI.View.extend({
-    template: "addons/documents/templates/sidebar",
-    className: "sidenav",
-    tagName: "nav",
-
-    initialize: function(options) {
-      this.database = options.database;
-      if (options.ddocInfo) {
-        this.ddocID = options.ddocInfo.id;
-        this.currView = options.ddocInfo.currView;
-      }
-
-      this.designDocList = [];
-    },
-
-    serialize: function() {
-      var docLinks = FauxtonAPI.getExtensions('docLinks'),
-          newLinks = FauxtonAPI.getExtensions('sidebar:newLinks'),
-          addLinks = FauxtonAPI.getExtensions('sidebar:links'),
-          extensionList = FauxtonAPI.getExtensions('sidebar:list');
-      return {
-        changes_url: '#' + this.database.url('changes'),
-        permissions_url: '#' + this.database.url('app') + '/permissions',
-        db_url: '#' + this.database.url('index'),
-        database: this.collection.database,
-        database_url: '#' + this.database.url('app'),
-        docLinks: docLinks,
-        addLinks: addLinks,
-        newLinks: newLinks,
-        extensionList: extensionList > 0
-      };
-    },
-
-    getNewButtonLinks: function () {
-      var database = this.collection.database,
-          newurlPrefix = "#" + database.url('app'),
-          addLinks = FauxtonAPI.getExtensions('sidebar:links');
-
-      return _.reduce(FauxtonAPI.getExtensions('sidebar:links'), function (menuLinks, link) {
-
-        menuLinks.push({
-          title: link.title,
-          url: newurlPrefix + "/" + link.url,
-          icon: 'fonticon-plus-circled'
-        });
-
-        return menuLinks; 
-     }, [{
-          title: 'New Doc',
-          url: newurlPrefix + '/new',
-          icon: 'fonticon-plus-circled'
-        },{
-          title: 'New View',
-          url: newurlPrefix + '/new_view',
-          icon: 'fonticon-plus-circled'
-        }]);
-    },
-
-
-    beforeRender: function(manage) {
-      this.deleteDBModal = this.setView(
-        '#delete-db-modal',
-        new Views.DeleteDBModal({database: this.database})
-      );
-
-      var newLinks = [{
-        title: 'Add new',
-        links: this.getNewButtonLinks()
-      }];
-
-      this.setView("#new-all-docs-button", new Components.MenuDropDown({
-        links: newLinks,
-      }));
-
-      this.setView("#new-design-docs-button", new Components.MenuDropDown({
-        links: newLinks,
-      }));
-
-      _.each(this.designDocList, function (view) { view.remove(); view = undefined;});
-      this.designDocList = [];
-
-      this.collection.each(function(design) {
-        if (design.has('doc')){
-          design.collection = this.collection;
-          var view = this.insertView(new Views.DdocSidenav({
-            model: design,
-            collection: this.collection
-          }));
-
-          this.designDocList.push(view);
-        }
-      },this);
-    },
-
-    afterRender: function () {
-      if (this.selectedTab) {
-        this.setSelectedTab(this.selectedTab);
-      }
-    },
-
-    setSelectedTab: function (selectedTab) {
-      this.selectedTab = selectedTab;
-      var $selectedTab = this.$('#' + selectedTab);
-
-      this.$('li').removeClass('active');
-      $selectedTab.parent().addClass('active');
-
-      if ($selectedTab.parents(".accordion-body").length !== 0){
-        $selectedTab
-        .parents(".accordion-body")
-        .addClass("in")
-        .parents(".nav-header")
-        .find(">.js-collapse-toggle").addClass("down");
-
-        this.$('.js-toggle-' + $selectedTab.data('ddoctype')).addClass("down");
-      }
-    }
-  });
-
-  Views.DdocSidenav = FauxtonAPI.View.extend({
-    tagName: "ul",
-    className:  "nav nav-list",
-    template: "addons/documents/templates/design_doc_menu",
-    events: {
-      "click .js-collapse-toggle": "toggleArrow"
-    },
-
-    toggleArrow:  function(e){
-      this.$(e.currentTarget).toggleClass("down");
-    },
-    buildIndexList: function(designDocs, info){
-      var design = this.model.id.replace(/^_design\//,"");
-      var databaseId = this.model.database.id;
-
-      if (_.isUndefined(designDocs[info.selector])) { return; }
-
-      this.insertView(".accordion-body", new Views.IndexItem({
-        selector: info.selector,
-        ddoc: design,
-        collection: designDocs[info.selector],
-        name: info.name,
-        database: databaseId
-      }));
-    },
-
-    serialize: function(){
-      var ddocName = this.model.id.replace(/^_design\//,"");
-      return{
-        database: this.collection.database,
-        designDoc: ddocName,
-        ddoc_clean: app.utils.removeSpecialCharacters(ddocName),
-        ddoc_encoded: app.utils.safeURLName(ddocName),
-        database_encoded: app.utils.safeURLName(this.model.database.id),
-      };
-    },
-
-    getSidebarLinks: function () {
-      var ddocName = this.model.id.replace(/^_design\//,""),
-          docSafe = app.utils.safeURLName(ddocName), 
-          database = this.collection.database;
-
-      return _.reduce(FauxtonAPI.getExtensions('sidebar:links'), function (menuLinks, link) {
-
-        menuLinks.push({
-          title: link.title,
-          url: "#" + database.url('app') + "/" + link.url + "/" + docSafe,
-          icon: 'fonticon-plus-circled'
-        });
-
-        return menuLinks; 
-     }, [{
-      title: 'New View',
-      url: "#" + database.url('app') + "/new_view/" + docSafe,
-      icon: 'fonticon-plus-circled'
-     }]);
-
-    },
-
-    renderIndexLists: function () {
-      var ddocDocs = this.model.get("doc"),
-          sidebarListTypes = FauxtonAPI.getExtensions('sidebar:list');
-
-      if (!ddocDocs){ return; }
-
-      this.buildIndexList(ddocDocs, {
-        selector: "views",
-        name: 'Views'
-      });
-
-      _.each(sidebarListTypes, function (info) {
-        this.buildIndexList(ddocDocs, info);
-      },this);
-
-    },
-
-    beforeRender: function(manage) {
-      var sideBarMenuLinks = [];
-
-      sideBarMenuLinks.push({
-        title: 'Add new',
-        links: this.getSidebarLinks()
-      });
-
-      this.renderIndexLists();
-      this.setView(".new-button", new Components.MenuDropDown({
-        links: sideBarMenuLinks,
-      }));
-    }
-  });
-
-  Views.IndexItem = FauxtonAPI.View.extend({
-    template: "addons/documents/templates/index_menu_item",
-    tagName: 'li',
-
-    initialize: function(options){
-      this.index = options.index;
-      this.ddoc = options.ddoc;
-      this.database = options.database;
-      this.selected = !! options.selected;
-      this.selector = options.selector;
-      this.name = options.name;
-
-      this.indexTypeMap = {
-        views:   { icon: 'fonticon-sidenav-map-reduce', urlFolder: '_view' },
-        indexes: { icon: 'fonticon-sidenav-search', urlFolder: '_indexes' }
-      };
-    },
-
-    serialize: function() {
-      return {
-        icon: this.indexTypeMap[this.selector].icon,
-        urlFolder: this.indexTypeMap[this.selector].urlFolder,
-        ddocType:  this.selector,
-        name: this.name,
-        index: this.index,
-        ddoc: this.ddoc,
-        database: this.database,
-        selected: this.selected,
-        collection: this.collection
-      };
-    },
-
-    afterRender: function() {
-      if (this.selected) {
-        $(".sidenav ul.nav-list li").removeClass("active");
-        this.$el.addClass("active");
-      }
-    }
-  });
-
-  return Views;
-});
-

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/15d49fcb/app/addons/documents/views.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/views.js b/app/addons/documents/views.js
index dacb937..23a5b5c 100644
--- a/app/addons/documents/views.js
+++ b/app/addons/documents/views.js
@@ -18,7 +18,7 @@ define([
   "addons/databases/resources",
 
   // Views
-  "addons/documents/views-sidebar",
+  "addons/documents/shared-views",
   "addons/documents/views-queryoptions",
 
   //plugins
@@ -36,7 +36,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, Views, QueryOptions)
   }
 
   Views.Footer = FauxtonAPI.View.extend({
-    template: "addons/documents/templates/all_docs_footer",
+    template: "addons/documents/templates/all_docs_footer"
   });
 
   Views.RightAllDocsHeader = FauxtonAPI.View.extend({


Mime
View raw message