add sliceDeployment; add relatedCollections, add filterBy
[plstackapi.git] / planetstack / core / xoslib / static / js / xoslib / xos-backbone.js
1 if (! window.XOSLIB_LOADED ) {
2     window.XOSLIB_LOADED=true;
3
4     SLIVER_API = "/plstackapi/slivers/";
5     SLICE_API = "/plstackapi/slices/";
6     SLICEDEPLOYMENT_API = "/plstackapi/slice_deployments/";
7     NODE_API = "/plstackapi/nodes/";
8     SITE_API = "/plstackapi/sites/";
9     USER_API = "/plstackapi/users/";
10     DEPLOYMENT_API = "/plstackapi/deployments/";
11     IMAGE_API = "/plstackapi/images/";
12     NETWORKTEMPLATE_API = "/plstackapi/networktemplates/";
13     NETWORK_API = "/plstackapi/networks/";
14     SERVICE_API = "/plstackapi/services/";
15
16     SLICEPLUS_API = "/xoslib/slicesplus/";
17
18     XOSModel = Backbone.Model.extend({
19         /* from backbone-tastypie.js */
20         //idAttribute: 'resource_uri',
21
22         /* from backbone-tastypie.js */
23         url: function() {
24                     var url = this.attributes.resource_uri;
25
26                     if (!url) {
27                         url = this.urlRoot + this.id;
28                     }
29
30                     if (!url) {
31                         // XXX I'm not sure this does anything useful
32                         url = ( _.isFunction( this.collection.url ) ? this.collection.url() : this.collection.url );
33                         url = url || this.urlRoot;
34                     }
35
36                     // remove any existing query parameters
37                     url && ( url.indexOf("?") > -1 ) && ( url = url.split("?")[0] );
38
39                     url && ( url += ( url.length > 0 && url.charAt( url.length - 1 ) === '/' ) ? '' : '/' );
40
41                     url && ( url += "?no_hyperlinks=1" );
42
43                     return url;
44             },
45
46             listMethods: function() {
47                 var res = [];\r
48                 for(var m in this) {\r
49                     if(typeof this[m] == "function") {\r
50                         res.push(m)\r
51                     }\r
52                 }\r
53                 return res;\r
54             }
55     });
56
57     XOSCollection = Backbone.Collection.extend({
58         objects: function() {
59                     return this.models.map(function(element) { return element.attributes; });
60                  },
61
62         initialize: function(){
63           this.sortVar = 'name';\r
64           this.sortOrder = 'asc';\r
65         },\r
66 \r
67         relatedCollections: [],\r
68 \r
69         simpleComparator: function( model ){\r
70           parts=this.sortVar.split(".");\r
71           result = model.get(parts[0]);\r
72           for (index=1; index<parts.length; ++index) {\r
73               result=result[parts[index]];\r
74           }\r
75           return result;\r
76         },\r
77 \r
78         comparator: function (left, right) {\r
79             var l = this.simpleComparator(left);\r
80             var r = this.simpleComparator(right);\r
81 \r
82             if (l === void 0) return -1;\r
83             if (r === void 0) return 1;\r
84 \r
85             if (this.sortOrder=="desc") {\r
86                 return l < r ? 1 : l > r ? -1 : 0;\r
87             } else {\r
88                 return l < r ? -1 : l > r ? 1 : 0;\r
89             }\r
90         },\r
91 \r
92         startPolling: function() {\r
93             if (!this._polling) {\r
94                 var collection=this;
95                 setInterval(function() { collection.fetch(); }, 10000);
96                 this._polling=true;
97                 this.fetch();
98             }
99         },
100
101         maybeFetch: function(options){
102                 // Helper function to fetch only if this collection has not been fetched before.
103             if(this._fetched){
104                     // If this has already been fetched, call the success, if it exists
105                 options.success && options.success();
106                 console.log("alreadyFetched");
107                 return;
108             }
109
110                 // when the original success function completes mark this collection as fetched
111             var self = this,
112             successWrapper = function(success){
113                 return function(){
114                     self._fetched = true;
115                     success && success.apply(this, arguments);
116                 };
117             };
118             options.success = successWrapper(options.success);
119             console.log("call fetch");
120             this.fetch(options);
121         },
122
123         getOrFetch: function(id, options){
124                 // Helper function to use this collection as a cache for models on the server
125             var model = this.get(id);
126
127             if(model){
128                 options.success && options.success(model);
129                 return;
130             }
131
132             model = new this.model({
133                 resource_uri: id
134             });
135
136             model.fetch(options);
137         },
138
139         filterBy: function(fieldName, value) {
140              filtered = this.filter(function(obj) {
141                  return obj.get(fieldName) == value;
142                  });
143              return new this.constructor(filtered);
144         },
145
146         /* from backbone-tastypie.js */
147         url: function( models ) {
148                     var url = this.urlRoot || ( models && models.length && models[0].urlRoot );
149                     url && ( url += ( url.length > 0 && url.charAt( url.length - 1 ) === '/' ) ? '' : '/' );
150
151                     // Build a url to retrieve a set of models. This assume the last part of each model's idAttribute
152                     // (set to 'resource_uri') contains the model's id.
153                     if ( models && models.length ) {
154                             var ids = _.map( models, function( model ) {
155                                             var parts = _.compact( model.id.split('/') );
156                                             return parts[ parts.length - 1 ];
157                                     });
158                             url += 'set/' + ids.join(';') + '/';
159                     }
160
161                     url && ( url += "?no_hyperlinks=1" );
162
163                     return url;
164             },
165
166         listMethods: function() {
167                 var res = [];\r
168                 for(var m in this) {\r
169                     if(typeof this[m] == "function") {\r
170                         res.push(m)\r
171                     }\r
172                 }\r
173                 return res;\r
174             },
175
176         templateHelpers: function() {
177             return { title: "foo" };
178             }
179     });
180
181     function xoslib() {
182         // basic REST
183         this.sliver = XOSModel.extend({ urlRoot: SLIVER_API });
184         this.sliverCollection = XOSCollection.extend({ urlRoot: SLIVER_API,
185                                                        model: this.sliver});
186         this.slivers = new this.sliverCollection();
187
188         this.slice = XOSModel.extend({ urlRoot: SLICE_API });
189         this.sliceCollection = XOSCollection.extend({ urlRoot: SLICE_API,
190                                                        relatedCollections: {"slivers": "slice", "sliceDeployments": "slice"},
191                                                        model: this.slice});
192         this.slices = new this.sliceCollection();
193
194         this.sliceDeployment = XOSModel.extend({ urlRoot: SLICEDEPLOYMENT_API });
195         this.sliceDeploymentCollection = XOSCollection.extend({ urlRoot: SLICEDEPLOYMENT_API,
196                                                        model: this.slice});
197         this.sliceDeployments = new this.sliceDeploymentCollection();
198
199         this.node = XOSModel.extend({ urlRoot: NODE_API });
200         this.nodeCollection = XOSCollection.extend({ urlRoot: NODE_API,
201                                                        model: this.node});
202         this.nodes = new this.nodeCollection();
203
204         this.site = XOSModel.extend({ urlRoot: SITE_API });
205         this.siteCollection = XOSCollection.extend({ urlRoot: SITE_API,
206                                                        model: this.site});
207         this.sites = new this.siteCollection();
208
209         this.user = XOSModel.extend({ urlRoot: USER_API });
210         this.userCollection = XOSCollection.extend({ urlRoot: USER_API,
211                                                        model: this.user});
212         this.users = new this.userCollection();
213
214         this.deployment = XOSModel.extend({ urlRoot: DEPLOYMENT_API });
215         this.deploymentCollection = XOSCollection.extend({ urlRoot: DEPLOYMENT_API,
216                                                            model: this.deployment});
217         this.deployments = new this.deploymentCollection();
218
219         this.image = XOSModel.extend({ urlRoot: IMAGE_API });
220         this.imageCollection = XOSCollection.extend({ urlRoot: IMAGE_API,
221                                                            model: this.image});
222         this.images = new this.imageCollection();
223
224         this.networkTemplate = XOSModel.extend({ urlRoot: NETWORKTEMPLATE_API });
225         this.networkTemplateCollection = XOSCollection.extend({ urlRoot: NETWORKTEMPLATE_API,
226                                                            model: this.networkTemplate});
227         this.networkTemplates = new this.networkTemplateCollection();
228
229         this.network = XOSModel.extend({ urlRoot: NETWORK_API });
230         this.networkCollection = XOSCollection.extend({ urlRoot: NETWORK_API,
231                                                            model: this.network});
232         this.networks = new this.networkCollection();
233
234         this.service = XOSModel.extend({ urlRoot: SERVICE_API });
235         this.serviceCollection = XOSCollection.extend({ urlRoot: SERVICE_API,
236                                                        model: this.service});
237         this.services = new this.serviceCollection();
238
239         // enhanced REST
240         this.slicePlus = XOSModel.extend({ urlRoot: SLICEPLUS_API, relatedCollections: {'slivers': "slice"} });
241         this.slicePlusCollection = XOSCollection.extend({ urlRoot: SLICEPLUS_API,
242                                                           model: this.slicePlus});
243         this.slicesPlus = new this.slicePlusCollection();
244
245         this.listObjects = function() { return ["slivers", "slices", "nodes", "sites", "users", "deployments"]; };
246     };
247
248     xos = new xoslib();
249
250     function getCookie(name) {
251         var cookieValue = null;\r
252         if (document.cookie && document.cookie != '') {\r
253             var cookies = document.cookie.split(';');\r
254             for (var i = 0; i < cookies.length; i++) {\r
255                 var cookie = jQuery.trim(cookies[i]);\r
256                 // Does this cookie string begin with the name we want?\r
257                 if (cookie.substring(0, name.length + 1) == (name + '=')) {\r
258                     cookieValue = decodeURIComponent(cookie.substring(name.length + 1));\r
259                     break;\r
260                 }\r
261             }\r
262         }\r
263         return cookieValue;\r
264     }
265
266     (function() {
267       var _sync = Backbone.sync;\r
268       Backbone.sync = function(method, model, options){\r
269         options.beforeSend = function(xhr){\r
270           var token = getCookie("csrftoken");\r
271           xhr.setRequestHeader('X-CSRFToken', token);\r
272         };\r
273         return _sync(method, model, options);\r
274       };\r
275     })();
276 }