X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=planetstack%2Fcore%2Fxoslib%2Fstatic%2Fjs%2Fxoslib%2Fxos-backbone.js;h=bbf13a498aa91a1650a80e826cd4eaab1bdaf233;hb=912f63a970b2db8affe4ae87b6ff0b19fe5caa24;hp=5403212382af77a9f5548a988f4e7715957ed1e6;hpb=b6e1066832744dc5aee07980e1127e68af9b0552;p=plstackapi.git diff --git a/planetstack/core/xoslib/static/js/xoslib/xos-backbone.js b/planetstack/core/xoslib/static/js/xoslib/xos-backbone.js index 5403212..bbf13a4 100644 --- a/planetstack/core/xoslib/static/js/xoslib/xos-backbone.js +++ b/planetstack/core/xoslib/static/js/xoslib/xos-backbone.js @@ -1,202 +1,423 @@ -SLIVER_API = "/plstackapi/slivers/"; -SLICE_API = "/plstackapi/slices/"; -NODE_API = "/plstackapi/nodes/"; -SITE_API = "/plstackapi/sites/"; -USER_API = "/plstackapi/users/"; -DEPLOYMENT_API = "/plstackapi/deployments"; +if (! window.XOSLIB_LOADED ) { + window.XOSLIB_LOADED=true; + + SLIVER_API = "/plstackapi/slivers/"; + SLICE_API = "/plstackapi/slices/"; + SLICEROLE_API = "/plstackapi/slice_roles/"; + NODE_API = "/plstackapi/nodes/"; + SITE_API = "/plstackapi/sites/"; + USER_API = "/plstackapi/users/"; + USERDEPLOYMENT_API = "/plstackapi/user_deployments/"; + DEPLOYMENT_API = "/plstackapi/deployments/"; + IMAGE_API = "/plstackapi/images/"; + NETWORKTEMPLATE_API = "/plstackapi/networktemplates/"; + NETWORK_API = "/plstackapi/networks/"; + NETWORKSLIVER_API = "/plstackapi/networkslivers/"; + SERVICE_API = "/plstackapi/services/"; + SLICEPRIVILEGE_API = "/plstackapi/slice_privileges/"; + NETWORKDEPLOYMENT_API = "/plstackapi/networkdeployments/"; + + /* changed as a side effect of the big rename + SLICEDEPLOYMENT_API = "/plstackapi/slice_deployments/"; + USERDEPLOYMENT_API = "/plstackapi/user_deployments/"; + */ + + SLICEDEPLOYMENT_API = "/plstackapi/slicedeployments/"; + USERDEPLOYMENT_API = "/plstackapi/userdeployments/"; + + SLICEPLUS_API = "/xoslib/slicesplus/"; + + XOSModel = Backbone.Model.extend({ + /* from backbone-tastypie.js */ + //idAttribute: 'resource_uri', + + /* from backbone-tastypie.js */ + url: function() { + var url = this.attributes.resource_uri; + + if (!url) { + if (this.id) { + url = this.urlRoot + this.id; + } else { + // this happens when creating a new model. + url = this.urlRoot; + } + } + + if (!url) { + // XXX I'm not sure this does anything useful + url = ( _.isFunction( this.collection.url ) ? this.collection.url() : this.collection.url ); + url = url || this.urlRoot; + } + + // remove any existing query parameters + url && ( url.indexOf("?") > -1 ) && ( url = url.split("?")[0] ); + + url && ( url += ( url.length > 0 && url.charAt( url.length - 1 ) === '/' ) ? '' : '/' ); + + url && ( url += "?no_hyperlinks=1" ); + + return url; + }, + + listMethods: function() { + var res = []; + for(var m in this) { + if(typeof this[m] == "function") { + res.push(m) + } + } + return res; + } + }); + + XOSCollection = Backbone.Collection.extend({ + objects: function() { + return this.models.map(function(element) { return element.attributes; }); + }, + + initialize: function(){ + this.isLoaded = false; + this.failedLoad = false; + this.startedLoad = false; + this.sortVar = 'name'; + this.sortOrder = 'asc'; + this.on( "sort", this.sorted ); + }, + + relatedCollections: [], + foreignCollections: [], + + sorted: function() { + //console.log("sorted " + this.modelName); + }, + + simpleComparator: function( model ){ + parts=this.sortVar.split("."); + result = model.get(parts[0]); + for (index=1; index r ? -1 : 0; + } else { + return l < r ? -1 : l > r ? 1 : 0; + } + }, + + fetchSuccess: function(collection, response, options) { + //console.log("fetch succeeded " + collection.modelName); + this.failedLoad = false; + this.fetching = false; + if (!this.isLoaded) { + this.isLoaded = true; + Backbone.trigger("xoslib:collectionLoadChange", this); + } + this.trigger("fetchStateChange"); + if (options["orig_success"]) { + options["orig_success"](collection, response, options); + } + }, + + fetchFailure: function(collection, response, options) { + //console.log("fetch failed " + collection.modelName); + this.fetching = false; + if ((!this.isLoaded) && (!this.failedLoad)) { + this.failedLoad=true; + Backbone.trigger("xoslib:collectionLoadChange", this); + } + this.trigger("fetchStateChange"); + if (options["orig_failure"]) { + options["orig_failure"](collection, response, options); + } + }, + + fetch: function(options) { + var self=this; + this.fetching=true; + //console.log("fetch " + this.modelName); + if (!this.startedLoad) { + this.startedLoad=true; + Backbone.trigger("xoslib:collectionLoadChange", this); + } + this.trigger("fetchStateChange"); + if (options == undefined) { + options = {}; + } + options["orig_success"] = options["success"]; + options["orig_failure"] = options["failure"]; + options["success"] = function(collection, response, options) { self.fetchSuccess.call(self, collection, response, options); }; + options["failure"] = this.fetchFailure; + Backbone.Collection.prototype.fetch.call(this, options); + }, + + startPolling: function() { + if (!this._polling) { + var collection=this; + setInterval(function() { collection.fetch(); }, 10000); + this._polling=true; + this.fetch(); + } + }, + + refresh: function(refreshRelated) { + if (!this.fetching) { + this.fetch(); + } + if (refreshRelated) { + for (related in this.relatedCollections) { + related = xos[related]; + if (!related.fetching) { + related.fetch(); + } + } + } + }, + + maybeFetch: function(options){ + // Helper function to fetch only if this collection has not been fetched before. + if(this._fetched){ + // If this has already been fetched, call the success, if it exists + options.success && options.success(); + console.log("alreadyFetched"); + return; + } + + // when the original success function completes mark this collection as fetched + var self = this, + successWrapper = function(success){ + return function(){ + self._fetched = true; + success && success.apply(this, arguments); + }; + }; + options.success = successWrapper(options.success); + console.log("call fetch"); + this.fetch(options); + }, + + getOrFetch: function(id, options){ + // Helper function to use this collection as a cache for models on the server + var model = this.get(id); + + if(model){ + options.success && options.success(model); + return; + } + + model = new this.model({ + resource_uri: id + }); + + model.fetch(options); + }, + + filterBy: function(fieldName, value) { + filtered = this.filter(function(obj) { + return obj.get(fieldName) == value; + }); + return new this.constructor(filtered); + }, + + /* from backbone-tastypie.js */ + url: function( models ) { + var url = this.urlRoot || ( models && models.length && models[0].urlRoot ); + url && ( url += ( url.length > 0 && url.charAt( url.length - 1 ) === '/' ) ? '' : '/' ); + + // Build a url to retrieve a set of models. This assume the last part of each model's idAttribute + // (set to 'resource_uri') contains the model's id. + if ( models && models.length ) { + var ids = _.map( models, function( model ) { + var parts = _.compact( model.id.split('/') ); + return parts[ parts.length - 1 ]; + }); + url += 'set/' + ids.join(';') + '/'; + } + + url && ( url += "?no_hyperlinks=1" ); + + return url; + }, -SLICEPLUS_API = "/xoslib/slicesplus/"; + listMethods: function() { + var res = []; + for(var m in this) { + if(typeof this[m] == "function") { + res.push(m) + } + } + return res; + }, + }); -XOSModel = Backbone.Model.extend({ - /* from backbone-tastypie.js */ - //idAttribute: 'resource_uri', + function define_model(lib, attrs) { + modelName = attrs.modelName; + modelClassName = modelName; + collectionClassName = modelName + "Collection"; - /* from backbone-tastypie.js */ - url: function() { - var url = this.attributes.resource_uri; + if (!attrs.collectionName) { + attrs.collectionName = modelName + "s"; + } + collectionName = attrs.collectionName; + + modelAttrs = {} + collectionAttrs = {} + + for (key in attrs) { + value = attrs[key]; + if ($.inArray(key, ["urlRoot", "modelName"])>=0) { + modelAttrs[key] = value; + } + if ($.inArray(key, ["urlRoot", "modelName", "relatedCollections", "foreignCollections"])>=0) { + collectionAttrs[key] = value; + } + } - if (!url) { - url = this.urlRoot + this.id; - } + if (xosdefaults && xosdefaults[modelName]) { + modelAttrs["defaults"] = xosdefaults[modelName]; + } - if (!url) { - // XXX I'm not sure this does anything useful - url = ( _.isFunction( this.collection.url ) ? this.collection.url() : this.collection.url ); - url = url || this.urlRoot; - } + lib[modelName] = XOSModel.extend(modelAttrs); - // remove any existing query parameters - url && ( url.indexOf("?") > -1 ) && ( url = url.split("?")[0] ); + collectionAttrs["model"] = lib[modelName]; - url && ( url += ( url.length > 0 && url.charAt( url.length - 1 ) === '/' ) ? '' : '/' ); + lib[collectionClassName] = XOSCollection.extend(collectionAttrs); + lib[collectionName] = new lib[collectionClassName](); - url && ( url += "?no_hyperlinks=1" ); + lib.allCollectionNames.push(collectionName); + lib.allCollections.push(lib[collectionName]); + }; - return url; - }, + function xoslib() { + this.allCollectionNames = []; + this.allCollections = []; - listMethods: function() { - var res = []; - for(var m in this) { - if(typeof this[m] == "function") { - res.push(m) - } - } - return res; - } -}); + define_model(this, {urlRoot: SLIVER_API, + relatedCollections: {"networkSlivers": "sliver"}, + foreignCollections: ["slices", "deployments", "images", "nodes", "users"], + modelName: "sliver"}); -XOSCollection = Backbone.Collection.extend({ - objects: function() { - return this.models.map(function(element) { return element.attributes; }); - }, + define_model(this, {urlRoot: SLICE_API, + relatedCollections: {"slivers": "slice", "sliceDeployments": "slice", "slicePrivileges": "slice", "networks": "owner"}, + foreignCollections: ["services", "sites"], + modelName: "slice"}); - initialize: function(){ - this.sortVar = 'name'; - this.sortOrder = 'asc'; - }, - - simpleComparator: function( model ){ - parts=this.sortVar.split("."); - result = model.get(parts[0]); - for (index=1; index r ? -1 : 0; - } else { - return l < r ? -1 : l > r ? 1 : 0; - } - }, - - startPolling: function() { - if (!this._polling) { - collection=this; - setInterval(function() { console.log(collection); collection.fetch(); }, 10000); - this._polling=true; - this.fetch(); - } - }, - - maybeFetch: function(options){ - // Helper function to fetch only if this collection has not been fetched before. - if(this._fetched){ - // If this has already been fetched, call the success, if it exists - options.success && options.success(); - console.log("alreadyFetched"); - return; - } + define_model(this, {urlRoot: SLICEDEPLOYMENT_API, + foreignCollections: ["slices", "deployments"], + modelName: "sliceDeployment"}); - // when the original success function completes mark this collection as fetched - var self = this, - successWrapper = function(success){ - return function(){ - self._fetched = true; - success && success.apply(this, arguments); - }; - }; - options.success = successWrapper(options.success); - console.log("call fetch"); - this.fetch(options); - }, - - getOrFetch: function(id, options){ - // Helper function to use this collection as a cache for models on the server - var model = this.get(id); - - if(model){ - options.success && options.success(model); - return; - } + define_model(this, {urlRoot: SLICEPRIVILEGE_API, + foreignCollections: ["slices", "users", "sliceRoles"], + modelName: "slicePrivilege"}); - model = new this.model({ - resource_uri: id - }); + define_model(this, {urlRoot: SLICEROLE_API, + modelName: "sliceRole"}); - model.fetch(options); - }, + define_model(this, {urlRoot: NODE_API, + foreignCollections: ["sites", "deployments"], + modelName: "node"}); - /* from backbone-tastypie.js */ - url: function( models ) { - var url = this.urlRoot || ( models && models.length && models[0].urlRoot ); - url && ( url += ( url.length > 0 && url.charAt( url.length - 1 ) === '/' ) ? '' : '/' ); + define_model(this, {urlRoot: SITE_API, + relatedCollections: {"users": "site", "slices": "site", "nodes": "site"}, + modelName: "site"}); - // Build a url to retrieve a set of models. This assume the last part of each model's idAttribute - // (set to 'resource_uri') contains the model's id. - if ( models && models.length ) { - var ids = _.map( models, function( model ) { - var parts = _.compact( model.id.split('/') ); - return parts[ parts.length - 1 ]; - }); - url += 'set/' + ids.join(';') + '/'; - } + define_model(this, {urlRoot: USER_API, + relatedCollections: {"slicePrivileges": "user", "slices": "owner", "userDeployments": "user"}, + foreignCollections: ["sites"], + modelName: "user"}); - url && ( url += "?no_hyperlinks=1" ); + define_model(this, {urlRoot: USERDEPLOYMENT_API, + foreignCollections: ["users","deployments"], + modelName: "userDeployment"}); - return url; - }, + define_model(this, { urlRoot: DEPLOYMENT_API, + relatedCollections: {"nodes": "deployment", "slivers": "deploymentNetwork", "networkDeployments": "deployment", "userDeployments": "deployment"}, + modelName: "deployment"}); - listMethods: function() { - var res = []; - for(var m in this) { - if(typeof this[m] == "function") { - res.push(m) + define_model(this, {urlRoot: IMAGE_API, + model: this.image, + modelName: "image"}); + + define_model(this, {urlRoot: NETWORKTEMPLATE_API, + modelName: "networkTemplate"}); + + define_model(this, {urlRoot: NETWORK_API, + relatedCollections: {"networkDeployments": "network", "networkSlivers": "network"}, + foreignCollections: ["slices", "networkTemplates"], + modelName: "network"}); + + define_model(this, {urlRoot: NETWORKSLIVER_API, + modelName: "networkSliver"}); + + define_model(this, {urlRoot: NETWORKDEPLOYMENT_API, + modelName: "networkDeployment"}); + + define_model(this, {urlRoot: SERVICE_API, + modelName: "service"}); + + // enhanced REST + define_model(this, {urlRoot: SLICEPLUS_API, + relatedCollections: {'slivers': "slice"}, + modelName: "slicePlus", + collectionName: "slicesPlus"}); + + this.listObjects = function() { return this.allCollectionNames; }; + + this.getCollectionStatus = function() { + stats = {isLoaded: 0, failedLoad: 0, startedLoad: 0}; + for (index in this.allCollections) { + collection = this.allCollections[index]; + if (collection.isLoaded) { + stats["isLoaded"] = stats["isLoaded"] + 1; + } + if (collection.failedLoad) { + stats["failedLoad"] = stats["failedLoad"] + 1; + } + if (collection.startedLoad) { + stats["startedLoad"] = stats["startedLoad"] + 1; + } + } + stats["completedLoad"] = stats["failedLoad"] + stats["isLoaded"]; + return stats; + }; + }; + + xos = new xoslib(); + + function getCookie(name) { + var cookieValue = null; + if (document.cookie && document.cookie != '') { + var cookies = document.cookie.split(';'); + for (var i = 0; i < cookies.length; i++) { + var cookie = jQuery.trim(cookies[i]); + // Does this cookie string begin with the name we want? + if (cookie.substring(0, name.length + 1) == (name + '=')) { + cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); + break; } } - return res; - } -}); - -function xoslib() { - // basic REST - this.sliver = XOSModel.extend({ urlRoot: SLIVER_API }); - this.sliverCollection = XOSCollection.extend({ urlRoot: SLIVER_API, - model: this.sliver}); - this.slivers = new this.sliverCollection(); - - this.slice = XOSModel.extend({ urlRoot: SLICE_API }); - this.sliceCollection = XOSCollection.extend({ urlRoot: SLICE_API, - model: this.slice}); - this.slices = new this.sliceCollection(); - - this.node = XOSModel.extend({ urlRoot: NODE_API }); - this.nodeCollection = XOSCollection.extend({ urlRoot: NODE_API, - model: this.node}); - this.nodes = new this.nodeCollection(); - - this.site = XOSModel.extend({ urlRoot: SITE_API }); - this.siteCollection = XOSCollection.extend({ urlRoot: SITE_API, - model: this.site}); - this.sites = new this.siteCollection(); - - this.user = XOSModel.extend({ urlRoot: USER_API }); - this.userCollection = XOSCollection.extend({ urlRoot: USER_API, - model: this.user}); - this.users = new this.userCollection(); - - this.deployment = XOSModel.extend({ urlRoot: DEPLOYMENT_API }); - this.deploymentCollection = XOSCollection.extend({ urlRoot: DEPLOYMENT_API, - model: this.deployment}); - this.deployments = new this.deploymentCollection(); - - // enhanced REST - this.slicePlus = XOSModel.extend({ urlRoot: SLICEPLUS_API }); - this.slicePlusCollection = XOSCollection.extend({ urlRoot: SLICEPLUS_API, - model: this.slicePlus}); - this.slicesPlus = new this.slicePlusCollection(); - - this.listObjects = function() { return ["slivers", "slices", "nodes", "sites", "users", "deployments"]; }; -}; - -xos = new xoslib(); - + } + return cookieValue; + } + + (function() { + var _sync = Backbone.sync; + Backbone.sync = function(method, model, options){ + options.beforeSend = function(xhr){ + var token = getCookie("csrftoken"); + xhr.setRequestHeader('X-CSRFToken', token); + }; + return _sync(method, model, options); + }; + })(); +}