Initial run
Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/719617e3 Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/719617e3 Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/719617e3 Branch: refs/heads/fauxton-file-reorder Commit: 719617e336454807ce8fd3f5289f3a5aeb0f6a2a Parents: 3150bb1 Author: Garren Smith <[email protected]> Authored: Mon Jan 13 20:34:32 2014 +0200 Committer: Garren Smith <[email protected]> Committed: Mon Jan 27 08:41:29 2014 +0200 ---------------------------------------------------------------------- src/fauxton/app/core/couchdb.js | 78 +++++++++ src/fauxton/app/core/resources.js | 301 +++++++++++++++++++++++++++++++++ 2 files changed, 379 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/couchdb/blob/719617e3/src/fauxton/app/core/couchdb.js ---------------------------------------------------------------------- diff --git a/src/fauxton/app/core/couchdb.js b/src/fauxton/app/core/couchdb.js new file mode 100644 index 0000000..39cdc1a --- /dev/null +++ b/src/fauxton/app/core/couchdb.js @@ -0,0 +1,78 @@ +// 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", + "core/base" +], +function (app, FauxtonAPI) { + //this later needs to be dynamically loaded + + FauxtonAPI.UUID = FauxtonAPI.Model.extend({ + initialize: function(options) { + options = _.extend({count: 1}, options); + this.count = options.count; + }, + + url: function() { + return app.host + "/_uuids?count=" + this.count; + }, + + next: function() { + return this.get("uuids").pop(); + } + }); + + FauxtonAPI.Session = FauxtonAPI.Model.extend({ + url: app.host + '/_session', + + user: function () { + var userCtx = this.get('userCtx'); + + if (!userCtx || !userCtx.name) { return null; } + + return { + name: userCtx.name, + roles: userCtx.roles + }; + }, + + fetchUser: function (opt) { + var that = this, + currentUser = this.user(); + + return this.fetchOnce(opt).then(function () { + var user = that.user(); + + // Notify anyone listening on these events that either a user has changed + // or current user is the same + if (currentUser !== user) { + that.trigger('session:userChanged'); + } else { + that.trigger('session:userFetched'); + } + + // this will return the user as a value to all function that calls done on this + // eg. session.fetchUser().done(user) { .. do something with user ..} + return user; + }); + } + }); + + FauxtonAPI.setSession = function (newSession) { + app.session = FauxtonAPI.session = newSession; + return FauxtonAPI.session.fetchUser(); + }; + + //set default session + FauxtonAPI.setSession(new FauxtonAPI.Session()); + + return FauxtonAPI; +}); http://git-wip-us.apache.org/repos/asf/couchdb/blob/719617e3/src/fauxton/app/core/resources.js ---------------------------------------------------------------------- diff --git a/src/fauxton/app/core/resources.js b/src/fauxton/app/core/resources.js new file mode 100644 index 0000000..83111c7 --- /dev/null +++ b/src/fauxton/app/core/resources.js @@ -0,0 +1,301 @@ +// 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", + "core/couchdb", + "addons/fauxton/base", + "backbone" +], +function(app, FauxtonAPI, Fauxton) { + + // This is not exposed externally as it should not need to be accessed or overridden + var Auth = function (options) { + this._options = options; + this.initialize.apply(this, arguments); + }; + + // Piggy-back on Backbone's self-propagating extend function, + Auth.extend = Backbone.Model.extend; + + _.extend(Auth.prototype, Backbone.Events, { + authDeniedCb: function() {}, + + initialize: function() { + var that = this; + }, + + authHandlerCb : function (roles) { + var deferred = $.Deferred(); + deferred.resolve(); + return deferred; + }, + + registerAuth: function (authHandlerCb) { + this.authHandlerCb = authHandlerCb; + }, + + registerAuthDenied: function (authDeniedCb) { + this.authDeniedCb = authDeniedCb; + }, + + checkAccess: function (roles) { + var requiredRoles = roles || [], + that = this; + + if (!FauxtonAPI.session) { + throw new Error("Fauxton.session is not configured."); + } + + return FauxtonAPI.session.fetchUser().then(function (user) { + return FauxtonAPI.when(that.authHandlerCb(FauxtonAPI.session, requiredRoles)); + }); + } + }); + + FauxtonAPI.auth = new Auth(); + + FauxtonAPI.RouteObject = function(options) { + this._options = options; + + this._configure(options || {}); + this.initialize.apply(this, arguments); + this.addEvents(); + }; + + var broadcaster = {}; + _.extend(broadcaster, Backbone.Events); + + FauxtonAPI.RouteObject.on = function (eventName, fn) { + broadcaster.on(eventName, fn); + }; + + /* How Route Object events work + To listen to a specific route objects events: + + myRouteObject = FauxtonAPI.RouteObject.extend({ + events: { + "beforeRender": "beforeRenderEvent" + }, + + beforeRenderEvent: function (view, selector) { + console.log('Hey, beforeRenderEvent triggered',arguments); + }, + }); + + It is also possible to listen to events triggered from all Routeobjects. + This is great for more general things like adding loaders, hooks. + + FauxtonAPI.RouteObject.on('beforeRender', function (routeObject, view, selector) { + console.log('hey, this will trigger when any routeobject renders a view'); + }); + + Current Events to subscribe to: + * beforeFullRender -- before a full render is being done + * beforeEstablish -- before the routeobject calls establish + * AfterEstablish -- after the routeobject has run establish + * beforeRender -- before a view is rendered + * afterRender -- a view is finished being rendered + * renderComplete -- all rendering is complete + + */ + + // Piggy-back on Backbone's self-propagating extend function + FauxtonAPI.RouteObject.extend = Backbone.Model.extend; + + var routeObjectOptions = ["views", "routes", "events", "roles", "crumbs", "layout", "apiUrl", "establish"]; + + _.extend(FauxtonAPI.RouteObject.prototype, Backbone.Events, { + // Should these be default vals or empty funcs? + views: {}, + routes: {}, + events: {}, + crumbs: [], + layout: "with_sidebar", + apiUrl: null, + disableLoader: false, + loaderClassname: 'loader', + renderedState: false, + establish: function() {}, + route: function() {}, + roles: [], + initialize: function() {} + }, { + + renderWith: function(route, masterLayout, args) { + var routeObject = this, + triggerBroadcast = _.bind(this.triggerBroadcast, this); + + // Only want to redo the template if its a full render + if (!this.renderedState) { + masterLayout.setTemplate(this.layout); + triggerBroadcast('beforeFullRender'); + $('#primary-navbar li').removeClass('active'); + + if (this.selectedHeader) { + app.selectedHeader = this.selectedHeader; + $('#primary-navbar li[data-nav-name="' + this.selectedHeader + '"]').addClass('active'); + } + } + + masterLayout.clearBreadcrumbs(); + var crumbs = this.get('crumbs'); + + if (crumbs.length) { + masterLayout.setBreadcrumbs(new Fauxton.Breadcrumbs({ + crumbs: crumbs + })); + } + + triggerBroadcast('beforeEstablish'); + FauxtonAPI.when(this.establish()).then(function(resp) { + triggerBroadcast('afterEstablish'); + _.each(routeObject.getViews(), function(view, selector) { + if(view.hasRendered) { + triggerBroadcast('viewHasRendered', view, selector); + return; + } + + triggerBroadcast('beforeRender', view, selector); + FauxtonAPI.when(view.establish()).then(function(resp) { + masterLayout.setView(selector, view); + + masterLayout.renderView(selector); + triggerBroadcast('afterRender', view, selector); + }, function(resp) { + view.establishError = { + error: true, + reason: resp + }; + + if (resp) { + var errorText = JSON.parse(resp.responseText).reason; + FauxtonAPI.addNotification({ + msg: 'An Error occurred: ' + errorText, + type: 'error', + clear: true + }); + } + + masterLayout.renderView(selector); + }); + + }); + }.bind(this), function (resp) { + if (!resp) { return; } + FauxtonAPI.addNotification({ + msg: 'An Error occurred' + JSON.parse(resp.responseText).reason, + type: 'error', + clear: true + }); + }); + + if (this.get('apiUrl')){ + masterLayout.apiBar.update(this.get('apiUrl')); + } else { + masterLayout.apiBar.hide(); + } + + // Track that we've done a full initial render + this.renderedState = true; + triggerBroadcast('renderComplete'); + }, + + triggerBroadcast: function (eventName) { + var args = Array.prototype.slice.call(arguments); + this.trigger.apply(this, args); + + args.splice(0,1, eventName, this); + broadcaster.trigger.apply(broadcaster, args); + }, + + get: function(key) { + return _.isFunction(this[key]) ? this[key]() : this[key]; + }, + + addEvents: function(events) { + events = events || this.get('events'); + _.each(events, function(method, event) { + if (!_.isFunction(method) && !_.isFunction(this[method])) { + throw new Error("Invalid method: "+method); + } + method = _.isFunction(method) ? method : this[method]; + + this.on(event, method); + }, this); + }, + + _configure: function(options) { + _.each(_.intersection(_.keys(options), routeObjectOptions), function(key) { + this[key] = options[key]; + }, this); + }, + + getView: function(selector) { + return this.views[selector]; + }, + + setView: function(selector, view) { + this.views[selector] = view; + return view; + }, + + getViews: function() { + return this.views; + }, + + removeViews: function () { + _.each(this.views, function (view, selector) { + view.remove(); + delete this.views[selector]; + }, this); + }, + + getRouteUrls: function () { + return _.keys(this.get('routes')); + }, + + hasRoute: function (route) { + if (this.get('routes')[route]) { + return true; + } + return false; + }, + + routeCallback: function (route, args) { + var routes = this.get('routes'), + routeObj = routes[route], + routeCallback; + + if (typeof routeObj === 'object') { + routeCallback = this[routeObj.route]; + } else { + routeCallback = this[routeObj]; + } + + routeCallback.apply(this, args); + }, + + getRouteRoles: function (routeUrl) { + var route = this.get('routes')[routeUrl]; + + if ((typeof route === 'object') && route.roles) { + return route.roles; + } + + return this.roles; + } + + }); + + return FauxtonAPI; +});
