couchdb-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From gar...@apache.org
Subject fauxton commit: updated refs/heads/master to 02a5ee3
Date Mon, 13 Apr 2015 11:20:32 GMT
Repository: couchdb-fauxton
Updated Branches:
  refs/heads/master 4d863a8f2 -> 02a5ee3f0


Add built in React support for route objects

This removes the need for a backbone wrapper view for any React
components. React components can now be rendered directly in a
RouteObject.


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

Branch: refs/heads/master
Commit: 02a5ee3f0067432d3abf4fd683397ed6d66137ab
Parents: 4d863a8
Author: Garren Smith <garren.smith@gmail.com>
Authored: Wed Apr 1 15:54:08 2015 +0200
Committer: Garren Smith <garren.smith@gmail.com>
Committed: Mon Apr 13 13:03:06 2015 +0200

----------------------------------------------------------------------
 app/addons/config/routes.js                     |  13 +-
 app/addons/cors/actions.js                      |  12 ++
 app/addons/cors/base.js                         |   6 +-
 app/addons/cors/components.react.jsx            |  13 +-
 app/addons/cors/stores.js                       |  17 +--
 app/addons/cors/views.js                        |  53 --------
 app/addons/documents/changes/actions.js         |   7 +
 app/addons/documents/index-editor/actions.js    |   6 +
 .../documents/index-editor/components.react.jsx |   9 +-
 app/addons/documents/index-editor/stores.js     |  11 ++
 app/addons/documents/routes-documents.js        |  63 +++------
 app/addons/documents/routes-index-editor.js     |  27 ++--
 app/addons/documents/views-changes.js           |  66 ---------
 app/addons/documents/views-index.js             |  54 --------
 app/core/auth.js                                |   1 -
 app/core/layout.js                              |   5 +-
 app/core/routeObject.js                         |  42 +++++-
 app/core/router.js                              |   1 -
 app/core/tests/routeObjectSpec.js               | 133 +++++++++++++++++--
 19 files changed, 255 insertions(+), 284 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/02a5ee3f/app/addons/config/routes.js
----------------------------------------------------------------------
diff --git a/app/addons/config/routes.js b/app/addons/config/routes.js
index f2cf2d0..77c5605 100644
--- a/app/addons/config/routes.js
+++ b/app/addons/config/routes.js
@@ -15,18 +15,17 @@ define([
   'api',
   'addons/config/resources',
   'addons/config/views',
-  'addons/cors/views'
+  'addons/cors/components.react',
+  'addons/cors/actions'
 ],
 
-function (app, FauxtonAPI, Config, Views, CORS) {
+function (app, FauxtonAPI, Config, Views, CORSComponents, CORSActions) {
 
   var ConfigRouteObject = FauxtonAPI.RouteObject.extend({
     layout: 'with_tabs_sidebar',
 
     initialize: function () {
       this.configs = new Config.Collection();
-      this.cors = new CORS.Config();
-      this.httpd = new CORS.Httpd();
 
       this.sidebar = this.setView("#sidebar-content", new Views.Tabs({
         sidebarItems: [
@@ -68,10 +67,8 @@ function (app, FauxtonAPI, Config, Views, CORS) {
 
     configCORS: function () {
       this.removeView('#right-header');
-      this.newSection = this.setView('#dashboard-content', new CORS.Views.CORSWrapper({
-        cors: this.cors,
-        httpd: this.httpd
-      }));
+      this.newSection = this.setComponent('#dashboard-content', CORSComponents.CORSController);
+      CORSActions.FetchAndEditCors();
       this.sidebar.setSelectedTab("cors");
     },
 

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/02a5ee3f/app/addons/cors/actions.js
----------------------------------------------------------------------
diff --git a/app/addons/cors/actions.js b/app/addons/cors/actions.js
index 071f2ed..cce1518 100644
--- a/app/addons/cors/actions.js
+++ b/app/addons/cors/actions.js
@@ -15,6 +15,18 @@ define([
   'addons/cors/resources'
   ], function (FauxtonAPI, ActionTypes, Resources) {
     return {
+      FetchAndEditCors: function () {
+        var cors = new Resources.Config();
+        var httpd = new Resources.Httpd();
+
+        FauxtonAPI.when([cors.fetch(), httpd.fetch()]).then(function () {
+          this.editCors({
+            origins: cors.get('origins'),
+            isEnabled: httpd.corsEnabled()
+          });
+        }.bind(this));
+      },
+
       editCors: function (options) {
         FauxtonAPI.dispatch({
           type: ActionTypes.EDIT_CORS,

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/02a5ee3f/app/addons/cors/base.js
----------------------------------------------------------------------
diff --git a/app/addons/cors/base.js b/app/addons/cors/base.js
index f4b9fac..bb98115 100644
--- a/app/addons/cors/base.js
+++ b/app/addons/cors/base.js
@@ -12,11 +12,11 @@
 
 define([
   "app",
-  "api",
-  "addons/cors/views"
+  "api"
 ],
 
-function (app, FauxtonAPI, CORS) {
+function (app, FauxtonAPI) {
+  var CORS = FauxtonAPI.addon();
 
   CORS.initialize = function () {};
 

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/02a5ee3f/app/addons/cors/components.react.jsx
----------------------------------------------------------------------
diff --git a/app/addons/cors/components.react.jsx b/app/addons/cors/components.react.jsx
index 9ea15d9..10727ff 100644
--- a/app/addons/cors/components.react.jsx
+++ b/app/addons/cors/components.react.jsx
@@ -225,7 +225,7 @@ define([
         origins: corsStore.getOrigins(),
         isAllOrigins: corsStore.isAllOrigins(),
         configChanged: corsStore.hasConfigChanged(),
-        savingStatus: corsStore.getSavingStatus()
+        shouldSaveChange: corsStore.shouldSaveChange()
       };
     },
 
@@ -242,7 +242,9 @@ define([
     },
 
     componentDidUpdate: function () {
-      this.save();
+      if (this.state.shouldSaveChange) {
+        this.save();
+      }
     },
 
     onChange: function () {
@@ -335,13 +337,6 @@ define([
   });
 
   return {
-    renderCORS: function (el) {
-      React.render(<CORSController />, el);
-    },
-
-    removeCORS: function (el) {
-      React.unmountComponentAtNode(el);
-    },
     CORSController: CORSController,
     OriginInput: OriginInput,
     Origins: Origins,

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/02a5ee3f/app/addons/cors/stores.js
----------------------------------------------------------------------
diff --git a/app/addons/cors/stores.js b/app/addons/cors/stores.js
index 3e6ce16..1200053 100644
--- a/app/addons/cors/stores.js
+++ b/app/addons/cors/stores.js
@@ -21,19 +21,11 @@ define([
       this._isEnabled = options.isEnabled;
       this._origins = options.origins;
       this._configChanged = false;
-      this.savingDone();
+      this._shouldSaveChange = false;
     },
 
-    saving: function () {
-      this._savingStatus = 'Saving';
-    },
-
-    savingDone: function () {
-      this._savingStatus = 'Save';
-    },
-
-    getSavingStatus: function () {
-      return this._savingStatus;
+    shouldSaveChange: function () {
+      return this._shouldSaveChange;
     },
 
     hasConfigChanged: function () {
@@ -96,6 +88,9 @@ define([
     },
 
     dispatch: function (action) {
+      // it should save after any change is triggered except for EDIT_CORS which is just
to update
+      // cors after the first change
+      this._shouldSaveChange = true;
 
       switch (action.type) {
         case ActionTypes.EDIT_CORS:

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/02a5ee3f/app/addons/cors/views.js
----------------------------------------------------------------------
diff --git a/app/addons/cors/views.js b/app/addons/cors/views.js
deleted file mode 100644
index 99a4d88..0000000
--- a/app/addons/cors/views.js
+++ /dev/null
@@ -1,53 +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/cors/resources",
-  "addons/cors/components.react",
-  "addons/cors/actions"
-],
-
-
-function (app, FauxtonAPI, CORS, Components, Actions) {
-  var Views = {};
-
-  Views.CORSWrapper = FauxtonAPI.View.extend({
-    className: 'list',
-    initialize: function (options) {
-      this.cors = options.cors;
-      this.httpd = options.httpd;
-    },
-
-    establish: function () {
-      return [this.cors.fetch(), this.httpd.fetch()];
-    },
-
-    afterRender: function () {
-      Actions.editCors({
-        origins: this.cors.get('origins'),
-        isEnabled: this.httpd.corsEnabled()
-      });
-      Components.renderCORS(this.el);
-    },
-
-    cleanup: function () {
-      Components.removeCORS(this.el);
-    }
-
-  });
-
-  CORS.Views = Views;
-
-  return CORS;
-});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/02a5ee3f/app/addons/documents/changes/actions.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/changes/actions.js b/app/addons/documents/changes/actions.js
index a62a6fe..d94da66 100644
--- a/app/addons/documents/changes/actions.js
+++ b/app/addons/documents/changes/actions.js
@@ -43,6 +43,13 @@ function (app, FauxtonAPI, ActionTypes) {
         type: ActionTypes.SET_CHANGES,
         options: options
       });
+    },
+
+    fetchChanges: function (options) {
+      var changes = options.changes;
+      changes.fetch().then(function () {
+        this.setChanges(options);
+      }.bind(this));
     }
   };
 

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/02a5ee3f/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 79ef149..a7b33c7 100644
--- a/app/addons/documents/index-editor/actions.js
+++ b/app/addons/documents/index-editor/actions.js
@@ -76,6 +76,12 @@ function (app, FauxtonAPI, Documents, ActionTypes, IndexResultsActions)
{
       });
     },
 
+    fetchDesignDocsBeforeEdit: function (options) {
+      options.designDocs.fetch({reset: true}).then(function () {
+        this.editIndex(options);
+      }.bind(this));
+    },
+
     saveView: function (viewInfo) {
       var designDoc;
       var designDocs = viewInfo.designDocs;

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/02a5ee3f/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 0887bac..c38be29 100644
--- a/app/addons/documents/index-editor/components.react.jsx
+++ b/app/addons/documents/index-editor/components.react.jsx
@@ -407,7 +407,7 @@ function (app, FauxtonAPI, React, Stores, Actions, Components, ReactComponents)
     }
   });
 
-  var EditorWrapper = React.createClass({
+  var EditorController = React.createClass({
     render: function () {
       return (
         <div className="editor-wrapper span5 scrollable">
@@ -418,12 +418,7 @@ function (app, FauxtonAPI, React, Stores, Actions, Components, ReactComponents)
   });
 
   var Views = {
-    renderEditor: function (el) {
-      React.render(<EditorWrapper/>, el);
-    },
-    removeEditor: function (el) {
-      React.unmountComponentAtNode(el);
-    },
+    EditorController: EditorController,
     ReduceEditor: ReduceEditor,
     Editor: Editor,
     DesignDocSelector: DesignDocSelector,

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/02a5ee3f/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 f9a3606..9839001 100644
--- a/app/addons/documents/index-editor/stores.js
+++ b/app/addons/documents/index-editor/stores.js
@@ -23,6 +23,17 @@ function (FauxtonAPI, ActionTypes) {
     defaultMap: 'function (doc) {\n  emit(doc._id, 1);\n}',
     defaultReduce: 'function (keys, values, rereduce) {\n  if (rereduce) {\n    return sum(values);\n
 } else {\n    return values.length;\n  }\n}',
 
+    initialize: function () {
+      this._designDocs = [];
+      this._view = {
+        reduce: this.defaultMap,
+        map: this.defaultReduce
+      };
+      this._database = {
+        id: '0'
+      };
+    },
+
     editIndex: function (options) {
       this._database = options.database;
       this._newView = options.newView;

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/02a5ee3f/app/addons/documents/routes-documents.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/routes-documents.js b/app/addons/documents/routes-documents.js
index 39617e3..652025e 100644
--- a/app/addons/documents/routes-documents.js
+++ b/app/addons/documents/routes-documents.js
@@ -17,8 +17,8 @@ define([
   // Modules
   'addons/documents/shared-routes',
   'addons/documents/views',
-  'addons/documents/views-changes',
-  'addons/documents/views-index',
+  'addons/documents/changes/components.react',
+  'addons/documents/changes/actions',
   'addons/documents/views-doceditor',
   'addons/documents/views-mango',
 
@@ -26,11 +26,12 @@ define([
   'addons/documents/resources',
   'addons/fauxton/components',
   'addons/documents/pagination/stores',
-  'addons/documents/index-results/actions'
+  'addons/documents/index-results/actions',
+  'addons/documents/index-results/index-results.components.react'
 ],
 
-function (app, FauxtonAPI, BaseRoute, Documents, Changes, Index, DocEditor, Mango,
-  Databases, Resources, Components, PaginationStores, IndexResultsActions) {
+function (app, FauxtonAPI, BaseRoute, Documents, Changes, ChangesActions, DocEditor, Mango,
+  Databases, Resources, Components, PaginationStores, IndexResultsActions, IndexResultsComponents)
{
 
 
     var DocumentsRouteObject = BaseRoute.extend({
@@ -82,7 +83,8 @@ function (app, FauxtonAPI, BaseRoute, Documents, Changes, Index, DocEditor,
Mang
       designDocMetadata: function (database, ddoc) {
         this.footer && this.footer.remove();
         this.toolsView && this.toolsView.remove();
-        this.viewEditor && this.viewEditor.remove();
+
+        this.removeComponent('#dashboard-upper-content');
 
         var designDocInfo = new Resources.DdocInfo({ _id: "_design/" + ddoc }, { database:
this.database });
         this.setView("#dashboard-lower-content", new Documents.Views.DdocInfo({
@@ -108,11 +110,6 @@ function (app, FauxtonAPI, BaseRoute, Documents, Changes, Index, DocEditor,
Mang
         docParams = params.docParams,
         collection;
 
-        if (this.eventAllDocs) {
-          this.eventAllDocs = false;
-          return;
-        }
-
         this.reactHeader = this.setView('#react-headerbar', new Documents.Views.ReactHeaderbar());
 
         this.footer = this.setView('#footer', new Documents.Views.Footer());
@@ -128,9 +125,7 @@ function (app, FauxtonAPI, BaseRoute, Documents, Changes, Index, DocEditor,
Mang
           this.sidebar.setSelectedTab("all-docs");
         }
 
-        this.viewEditor && this.viewEditor.remove();
-        this.headerView && this.headerView.remove();
-
+        this.removeComponent('#dashboard-upper-content');
 
         if (!docParams) {
           docParams = {};
@@ -144,7 +139,8 @@ function (app, FauxtonAPI, BaseRoute, Documents, Changes, Index, DocEditor,
Mang
 
         this.database.allDocs.paging.pageSize = PaginationStores.indexPaginationStore.getPerPage();
 
-        this.resultList = this.setView('#dashboard-lower-content', new Index.ViewResultListReact({}));
+        //this.resultList = this.setView('#dashboard-lower-content', new Index.ViewResultListReact({}));
+        this.setComponent('#dashboard-lower-content', IndexResultsComponents.List);
 
         // this used to be a function that returned the object, but be warned: it caused
a closure with a reference to
         // the initial this.database object which can change
@@ -167,11 +163,14 @@ function (app, FauxtonAPI, BaseRoute, Documents, Changes, Index, DocEditor,
Mang
         var docParams = app.getParams();
         this.database.buildChanges(docParams);
 
-        this.changesView = this.setView("#dashboard-lower-content", new Changes.ChangesReactWrapper({
-          model: this.database
-        }));
+        ChangesActions.fetchChanges({
+          changes: this.database.changes,
+          filters: [],
+          databaseName: this.database.id
+        });
 
-        this.headerView = this.setView('#dashboard-upper-content', new Changes.ChangesHeaderReactWrapper());
+        this.setComponent("#dashboard-lower-content", Changes.ChangesController);
+        this.setComponent('#dashboard-upper-content', Changes.ChangesHeaderController);
 
         this.footer && this.footer.remove();
         this.toolsView && this.toolsView.remove();
@@ -188,33 +187,9 @@ function (app, FauxtonAPI, BaseRoute, Documents, Changes, Index, DocEditor,
Mang
       },
 
       cleanup: function () {
-        if (this.reactHeader) {
-          this.removeView('#react-headerbar');
-        }
-        if (this.viewEditor) {
-          this.removeView('#dashboard-upper-content');
-        }
-        if (this.documentsView) {
-          this.removeView('#dashboard-lower-content');
-        }
-        if (this.rightHeader) {
-          this.removeView('#right-header');
-        }
-        if (this.leftheader) {
-          this.removeView('#breadcrumbs');
-        }
-        if (this.sidebar) {
-          this.removeView('#sidebar');
-        }
-        if (this.footer) {
-          this.removeView('#footer');
-        }
-        if (this.headerView) {
-          this.removeView('#dashboard-upper-content');
-        }
-
         // we're no longer interested in listening to the lookahead tray event on this route
object
         this.stopListening(FauxtonAPI.Events, 'lookaheadTray:update', this.onSelectDatabase);
+        FauxtonAPI.RouteObject.prototype.cleanup.apply(this);
       }
 
     });

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/02a5ee3f/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
index 4d1e3b3..e04b35b 100644
--- a/app/addons/documents/routes-index-editor.js
+++ b/app/addons/documents/routes-index-editor.js
@@ -18,16 +18,18 @@ define([
   "addons/documents/helpers",
   'addons/documents/shared-routes',
   'addons/documents/views',
-  'addons/documents/views-index',
+  'addons/documents/index-editor/components.react',
+  'addons/documents/index-editor/actions',
   'addons/databases/base',
   'addons/fauxton/components',
   'addons/documents/pagination/stores',
-  'addons/documents/index-results/actions'
+  'addons/documents/index-results/actions',
+  'addons/documents/index-results/index-results.components.react'
 
 ],
 
-function (app, FauxtonAPI, Helpers, BaseRoute, Documents, Index,
-        Databases, Components, PaginationStores, IndexResultsActions) {
+function (app, FauxtonAPI, Helpers, BaseRoute, Documents, IndexEditorComponents, ActionsIndexEditor,
+          Databases, Components, PaginationStores, IndexResultsActions, IndexResultsComponents)
{
 
 
   var IndexEditorAndResults = BaseRoute.extend({
@@ -52,7 +54,6 @@ function (app, FauxtonAPI, Helpers, BaseRoute, Documents, Index,
 
     establish: function () {
       return [
-        this.designDocs.fetch({reset: true}),
         this.allDatabases.fetchOnce()
       ];
     },
@@ -63,7 +64,6 @@ function (app, FauxtonAPI, Helpers, BaseRoute, Documents, Index,
           docParams = params.docParams,
           decodeDdoc = decodeURIComponent(ddoc);
 
-
       this.rightHeader = this.setView('#right-header', new Documents.Views.RightAllDocsHeader({
         database: this.database
       }));
@@ -95,15 +95,16 @@ function (app, FauxtonAPI, Helpers, BaseRoute, Documents, Index,
         isListDeletable: false
       });
 
-      this.viewEditor = this.setView('#left-content', new Index.ViewEditorReact({
+      ActionsIndexEditor.fetchDesignDocsBeforeEdit({
         viewName: viewName,
         newView: false,
         database: this.database,
         designDocs: this.designDocs,
         designDocId: '_design/' + decodeDdoc
-      }));
+      });
 
-      this.resultList = this.setView('#dashboard-lower-content', new Index.ViewResultListReact({}));
+      this.setComponent('#left-content', IndexEditorComponents.EditorController);
+      this.setComponent('#dashboard-lower-content', IndexResultsComponents.List);
 
       this.apiUrl = function () {
         return [this.indexedDocs.urlRef(urlParams), FauxtonAPI.constants.DOC_URLS.GENERAL];
@@ -130,16 +131,18 @@ function (app, FauxtonAPI, Helpers, BaseRoute, Documents, Index,
         ]
       }));
 
-      this.viewEditor = this.setView('#left-content', new Index.ViewEditorReact({
+      ActionsIndexEditor.fetchDesignDocsBeforeEdit({
         viewName: 'new-view',
         newView: true,
         database: this.database,
         designDocs: this.designDocs,
         designDocId: designDoc,
         newDesignDoc: newDesignDoc
-      }));
+      });
+
+      this.setComponent('#left-content', IndexEditorComponents.EditorController);
+      this.setComponent('#dashboard-lower-content', IndexResultsComponents.List);
 
-      this.resultList = this.setView('#dashboard-lower-content', new Index.ViewResultListReact({}));
       IndexResultsActions.newResultsList({
         collection: [],
         isListDeletable: false

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/02a5ee3f/app/addons/documents/views-changes.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/views-changes.js b/app/addons/documents/views-changes.js
deleted file mode 100644
index 416270d..0000000
--- a/app/addons/documents/views-changes.js
+++ /dev/null
@@ -1,66 +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",
-
-       // Libs
-       "addons/fauxton/components",
-  'addons/documents/changes/components.react',
-  'addons/documents/changes/actions'
-],
-
-function (app, FauxtonAPI, Components, Changes, ChangesActions) {
-
-  var Views = {};
-
-
-  // wrappers for React components. The wrapper allows us to tie the React component into
the Fauxton
-  // page load lifecycle
-  Views.ChangesHeaderReactWrapper = FauxtonAPI.View.extend({
-    afterRender: function () {
-      Changes.renderHeader(this.el);
-    },
-    cleanup: function () {
-      Changes.remove(this.el);
-    }
-  });
-
-
-  Views.ChangesReactWrapper = FauxtonAPI.View.extend({
-    initialize: function () {
-      this.filters = [];
-    },
-
-    afterRender: function () {
-      ChangesActions.setChanges({
-        changes: this.model.changes,
-        filters: this.filters,
-        databaseName: this.model.id
-      });
-      Changes.renderChanges(this.el);
-    },
-
-    establish: function () {
-      return [this.model.changes.fetchOnce({ prefill: true })];
-    },
-
-    cleanup: function () {
-      Changes.remove(this.el);
-    }
-  });
-
-
-  return Views;
-});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/02a5ee3f/app/addons/documents/views-index.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/views-index.js b/app/addons/documents/views-index.js
deleted file mode 100644
index e64963f..0000000
--- a/app/addons/documents/views-index.js
+++ /dev/null
@@ -1,54 +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([
-  "api",
-  "addons/documents/index-editor/components.react",
-  "addons/documents/index-editor/actions",
-  'addons/documents/index-results/index-results.components.react'
-],
-
-function (FauxtonAPI, ViewEditor, ActionsIndexEditor, ViewResultList) {
-
-  var Views = {};
-
-  Views.ViewEditorReact = FauxtonAPI.View.extend({
-    initialize: function (options) {
-      this.options = options;
-    },
-
-    afterRender: function () {
-      ActionsIndexEditor.editIndex(this.options);
-      ViewEditor.renderEditor(this.el);
-    },
-
-    cleanup: function () {
-      ViewEditor.removeEditor(this.el);
-    }
-  });
-
-  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;
-});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/02a5ee3f/app/core/auth.js
----------------------------------------------------------------------
diff --git a/app/core/auth.js b/app/core/auth.js
index af2e377..d31ef5e 100644
--- a/app/core/auth.js
+++ b/app/core/auth.js
@@ -62,4 +62,3 @@ function (FauxtonAPI, Backbone) {
 
   return Auth;
 });
-

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/02a5ee3f/app/core/layout.js
----------------------------------------------------------------------
diff --git a/app/core/layout.js b/app/core/layout.js
index 14d1518..7a4d6f0 100644
--- a/app/core/layout.js
+++ b/app/core/layout.js
@@ -11,8 +11,8 @@
 // the License.
 
 define([
-  "backbone",
-  "plugins/backbone.layoutmanager"
+  'backbone',
+  'plugins/backbone.layoutmanager'
 ], function (Backbone) {
 
   // A wrapper of the main Backbone.layoutmanager
@@ -24,6 +24,7 @@ define([
     });
 
     this.layoutViews = {};
+    this.reactComponents = {};
     //this views don't ever get removed. An example of this is the main navigation sidebar
     this.permanentViews = {};
     this.el = this.layout.el;

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/02a5ee3f/app/core/routeObject.js
----------------------------------------------------------------------
diff --git a/app/core/routeObject.js b/app/core/routeObject.js
index 6dae4a4..0af072a 100644
--- a/app/core/routeObject.js
+++ b/app/core/routeObject.js
@@ -11,13 +11,15 @@
 // the License.
 
 define([
-  "core/base",
-  "backbone"
+  'core/base',
+  'react',
+  'backbone'
 ],
-function (FauxtonAPI, Backbone) {
+function (FauxtonAPI, React, Backbone) {
 
   var RouteObject = function (options) {
     this._options = options;
+    this.reactComponents = {};
 
     this._configure(options || {});
     this.initialize.apply(this, arguments);
@@ -101,11 +103,13 @@ function (FauxtonAPI, Backbone) {
           establishError = _.bind(this.establishError, this),
           renderComplete = _.bind(this.renderComplete, this),
           callEstablish = _.bind(this.callEstablish, this),
+          renderReactComponents = _.bind(this.renderReactComponents, this),
           promise = this.establish();
 
       // Only start the view rendering process once the template has been rendered
       // otherwise we get double renders
       promiseLayout.then(function () {
+        renderReactComponents();
         callEstablish(promise)
           .then(renderAllViews, establishError)
           .then(renderComplete);
@@ -127,6 +131,12 @@ function (FauxtonAPI, Backbone) {
       return promise;
     },
 
+    renderReactComponents: function () {
+      _.each(this.reactComponents, function (component, selector) {
+        React.render(React.createElement(component, null), $(selector)[0]);
+      });
+    },
+
     callEstablish: function (establishPromise) {
       this.addPromise(establishPromise);
       return FauxtonAPI.when(establishPromise);
@@ -229,10 +239,34 @@ function (FauxtonAPI, Backbone) {
     },
 
     setView: function (selector, view) {
+      this.removeView(selector);
+      this.removeComponent(selector);
       this.views[selector] = view;
       return view;
     },
 
+    setComponent: function (selector, component) {
+      this.removeView(selector);
+      this.removeComponent(selector);
+      this.reactComponents[selector] = component;
+    },
+
+    removeComponent: function (selector) {
+      if (_.has(this.reactComponents, selector)) {
+        React.unmountComponentAtNode($(selector)[0]);
+        this.reactComponents[selector] = null;
+        delete this.reactComponents[selector];
+      }
+    },
+
+    removeComponents: function () {
+      _.each(this.reactComponents, function (component, selector) {
+        this.removeComponent(selector);
+      }, this);
+
+      this.reactComponents = {};
+    },
+
     getViews: function () {
       return this.views;
     },
@@ -246,6 +280,7 @@ function (FauxtonAPI, Backbone) {
     },
 
     removeViews: function () {
+      this.reactComponents = {};
       _.each(this.views, function (view, selector) {
         view.remove();
         delete this.views[selector];
@@ -267,6 +302,7 @@ function (FauxtonAPI, Backbone) {
 
     cleanup: function () {
       this.removeViews();
+      this.removeComponents();
       this.rejectPromises();
     },
 

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/02a5ee3f/app/core/router.js
----------------------------------------------------------------------
diff --git a/app/core/router.js b/app/core/router.js
index f6143b2..db37fd5 100644
--- a/app/core/router.js
+++ b/app/core/router.js
@@ -119,4 +119,3 @@ function (FauxtonAPI, Auth, Backbone) {
 
   return Router;
 });
-

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/02a5ee3f/app/core/tests/routeObjectSpec.js
----------------------------------------------------------------------
diff --git a/app/core/tests/routeObjectSpec.js b/app/core/tests/routeObjectSpec.js
index b454d14..e267f65 100644
--- a/app/core/tests/routeObjectSpec.js
+++ b/app/core/tests/routeObjectSpec.js
@@ -10,11 +10,13 @@
 // License for the specific language governing permissions and limitations under
 // the License.
 define([
-       'api',
-      'testUtils'
-], function (FauxtonAPI, testUtils) {
+  'api',
+  'react',
+  'testUtils'
+], function (FauxtonAPI, React, testUtils) {
   var assert = testUtils.assert,
-      RouteObject = FauxtonAPI.RouteObject;
+  restore = testUtils.restore,
+  RouteObject = FauxtonAPI.RouteObject;
 
   describe('RouteObjects', function () {
 
@@ -49,7 +51,7 @@ define([
 
       it('Should set template for first render ', function () {
         var setTemplateSpy = sinon.stub(mockLayout, 'setTemplate'),
-            promise = $.Deferred();
+        promise = $.Deferred();
 
         promise.resolve();
         setTemplateSpy.returns(promise);
@@ -60,7 +62,7 @@ define([
 
       it('Should not set template after first render', function () {
         var setTemplateSpy = sinon.stub(mockLayout, 'setTemplate'),
-            promise = $.Deferred();
+        promise = $.Deferred();
 
         promise.resolve();
         setTemplateSpy.returns(promise);
@@ -71,6 +73,12 @@ define([
         assert.ok(setTemplateSpy.calledOnce, 'SetTemplate not meant to be called');
       });
 
+      it('Should call renderReactComponents', function () {
+        var renderSpy = sinon.spy(testRouteObject, "renderReactComponents");
+
+        testRouteObject.renderWith('the-route', mockLayout, 'args');
+        assert.ok(renderSpy.calledOnce);
+      });
 
       it("Should call establish of routeObject", function () {
         var establishSpy = sinon.spy(testRouteObject, "establish");
@@ -81,8 +89,8 @@ define([
 
       it("Should render views", function () {
         var view = new FauxtonAPI.View(),
-            getViewsSpy = sinon.stub(testRouteObject, "getViews"),
-            viewSpy = sinon.stub(view, "establish");
+        getViewsSpy = sinon.stub(testRouteObject, "getViews"),
+        viewSpy = sinon.stub(view, "establish");
 
         view.hasRendered = false;
         view.promise = function () {
@@ -99,8 +107,8 @@ define([
 
       it("Should not re-render a view", function () {
         var view = new FauxtonAPI.View(),
-            getViewsSpy = sinon.stub(testRouteObject, "getViews"),
-            viewSpy = sinon.stub(view, "establish");
+        getViewsSpy = sinon.stub(testRouteObject, "getViews"),
+        viewSpy = sinon.stub(view, "establish");
 
         view.hasRendered = true;
         getViewsSpy.returns({'#view': view});
@@ -110,6 +118,111 @@ define([
       });
     });
 
+    describe('React Integration', function () {
+      var testRouteObject;
+
+      beforeEach(function () {
+        var TestRouteObject = RouteObject.extend({
+          crumbs: ['mycrumbs']
+        });
+
+        testRouteObject = new TestRouteObject();
+        var apiBar = {};
+        //apiBar.hide = sinon.spy();
+
+        var mockLayout = {
+          setTemplate: function () {
+            var promise = $.Deferred();
+            promise.resolve();
+            return promise;
+          },
+          clearBreadcrumbs: sinon.spy(),
+          setView: sinon.spy(),
+          renderView: sinon.spy(),
+          hooks: [],
+          setBreadcrumbs: sinon.spy(),
+          apiBar: apiBar
+        };
+
+      });
+
+      describe('setComponent', function () {
+
+        afterEach(function () {
+          restore(testRouteObject.removeComponent);
+          restore(testRouteObject.removeView);
+        });
+
+        it('removes existing view for selector', function () {
+          var fakeReactComponent = React.createElement('div');
+          var fakeSelector = '.fake-selector';
+          var spy = sinon.spy(testRouteObject, 'removeView');
+
+          testRouteObject.setComponent(fakeSelector, fakeReactComponent);
+
+          assert.ok(spy.calledWith(fakeSelector));
+        });
+
+        it('removes existing component for selector', function () {
+          var fakeReactComponent = React.createElement('div');
+          var fakeSelector = '.fake-selector';
+          var spy = sinon.spy(testRouteObject, 'removeComponent');
+
+          testRouteObject.setComponent(fakeSelector, fakeReactComponent);
+
+          assert.ok(spy.calledWith(fakeSelector));
+        });
+
+        it('sets component for selector', function () {
+          var fakeReactComponent = React.createElement('div');
+          var fakeSelector = '.fake-selector';
+
+          testRouteObject.setComponent(fakeSelector, fakeReactComponent);
+          assert.deepEqual(fakeReactComponent, testRouteObject.reactComponents[fakeSelector]);
+        });
+
+      });
+
+      describe('removeComponent', function () {
+
+        afterEach(function () {
+          restore(React.unmountComponentAtNode);
+        });
+
+        it('removes existing component via react', function () {
+          var spy = sinon.spy(React, 'unmountComponentAtNode');
+          var fakeSelector = 'remove-selector';
+          testRouteObject.reactComponents[fakeSelector] = React.createElement('div');
+
+          testRouteObject.removeComponent(fakeSelector);
+
+          assert.ok(spy.calledOnce);
+
+        });
+
+        it('removes existing components key', function () {
+          var fakeSelector = 'remove-selector';
+          testRouteObject.reactComponents[fakeSelector] = React.createElement('div');
+
+          testRouteObject.removeComponent(fakeSelector);
+
+          assert.ok(_.isUndefined(testRouteObject.reactComponents[fakeSelector]));
+
+        });
+
+        it('does nothing for non existing component', function () {
+          var spy = sinon.spy(React, 'unmountComponentAtNode');
+          var fakeSelector = 'remove-selector';
+
+          testRouteObject.removeComponent(fakeSelector);
+
+          assert.notOk(spy.calledOnce);
+
+        });
+
+      });
+    });
+
   });
 
 


Mime
View raw message