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 2015/04/13 13:20:32 UTC
fauxton commit: updated refs/heads/master to 02a5ee3
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 <ga...@gmail.com>
Authored: Wed Apr 1 15:54:08 2015 +0200
Committer: Garren Smith <ga...@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);
+
+ });
+
+ });
+ });
+
});