Merge branch 'master' of ssh://git.planet-lab.org/git/plstackapi
[plstackapi.git] / planetstack / core / xoslib / static / js / xosTenant.js
1 XOSTenantSite = XOSModel.extend( {
2     listFields: ["name", "allocated"],
3     modelName: "tenantSite",
4     collectionName: "tenantSites"
5 });
6
7 XOSTenantSiteCollection = XOSCollection.extend( {
8     listFields: ["name", "allocated"],
9     modelName: "tenantSite",
10     collectionName: "tenantSites",
11
12     getFromSlice: function(slice) {
13         var tenantSites = [];
14         var id = 0;
15         for (siteName in slice.attributes.site_allocation) {
16             allocated = slice.attributes.site_allocation[siteName];
17             tenantSites.push(new XOSTenantSite( { name: siteName, allocated: allocated, id: id} ));
18             id = id + 1;
19         }
20         for (index in xos.tenantview.models[0].attributes.blessed_site_names) {
21             siteName = xos.tenantview.models[0].attributes.blessed_site_names[index];
22             if (! (siteName in slice.attributes.site_allocation)) {
23                 tenantSites.push(new XOSTenantSite( { name: siteName, allocated: 0, id: id} ));
24                 id = id + 1;
25             }
26         }
27         this.set(tenantSites);
28     },
29
30     putToSlice: function(slice) {
31         slice.attributes.site_allocation = {};
32         for (index in this.models) {
33             model = this.models[index];
34             slice.attributes.site_allocation[ model.attributes.name ] = model.attributes.allocated;
35         }
36     },
37 });
38
39 XOSEditUsersView = Marionette.ItemView.extend({
40             template: "#tenant-edit-users",
41             viewInitializers: [],
42
43             onShow: function() {
44                 _.each(this.viewInitializers, function(initializer) {
45                     initializer();
46                 });
47             },
48
49             templateHelpers: function() { return { detailView: this, model: this.model }; },
50
51             });
52
53
54 XOSTenantButtonView = Marionette.ItemView.extend({
55             template: "#xos-tenant-buttons-template",
56
57             events: {"click button.btn-tenant-create": "createClicked",
58                      "click button.btn-tenant-delete": "deleteClicked",
59                      "click button.btn-tenant-add-user": "addUserClicked",
60                      "click button.btn-tenant-save": "saveClicked",
61                      },
62
63             createClicked: function(e) {
64                      XOSTenantApp.addSlice();
65                      },
66
67             deleteClicked: function(e) {
68                      XOSTenantApp.deleteSlice(this.options.linkedView.model);
69                      },
70
71             addUserClicked: function(e) {
72                      XOSTenantApp.editUsers(this.options.linkedView.model);
73                      },
74
75             saveClicked: function(e) {
76                      model = this.options.linkedView.model;
77                      model.tenantSiteCollection.putToSlice(model);
78                      this.options.linkedView.submitContinueClicked.call(this.options.linkedView, e);
79                      },
80             });
81
82 XOSTenantApp = new XOSApplication({
83     logTableId: "#logTable",
84     statusMsgId: "#statusMsg",
85     hideTabsByDefault: true,
86     varName: "XOSTenantApp",
87 });
88
89 XOSTenantApp.addRegions({
90     tenantSliceSelector: "#tenantSliceSelector",
91     tenantSummary: "#tenantSummary",
92     tenantSiteList: "#tenantSiteList",
93     tenantButtons: "#tenantButtons",
94     tenantAddSliceInterior: "#tenant-addslice-interior",
95     tenantEditUsersInterior: "#tenant-edit-users-interior",
96 });
97
98 XOSTenantApp.buildViews = function() {
99      XOSTenantApp.tenantSites = new XOSTenantSiteCollection();\r
100 \r
101      tenantSummaryClass = XOSDetailView.extend({template: "#xos-detail-template",\r
102                                                 app: XOSTenantApp,\r
103                                                 detailFields: ["serviceClass", "default_image", "default_flavor", "network_ports", "mount_data_sets"],\r
104                                                 fieldDisplayNames: {serviceClass: "Service Level", "default_flavor": "Flavor", "default_image": "Image"},\r
105                                                 });\r
106 \r
107      XOSTenantApp.tenantSummaryView = tenantSummaryClass;\r
108 \r
109      tenantAddClass = XOSDetailView.extend({template: "#xos-detail-template",\r
110                                                 app: XOSTenantApp,\r
111                                                 detailFields: ["name", "description"]});\r
112 \r
113      XOSTenantApp.tenantAddView = tenantAddClass;\r
114 \r
115      tenantSiteItemClass = XOSItemView.extend({template: "#xos-listitem-template",\r
116                                                app: XOSTenantApp});\r
117 \r
118      XOSTenantApp.tenantSiteItemView = tenantSiteItemClass;\r
119 \r
120      tenantSiteListClass = XOSDataTableView.extend({template: "#xos-list-template",\r
121                                                app: XOSTenantApp,\r
122                                                childView: tenantSiteItemClass,\r
123                                                collection: XOSTenantApp.tenantSites,\r
124                                                title: "sites",\r
125                                                inputType: {allocated: "spinner"},\r
126                                                noDeleteColumn: true,\r
127                                                });\r
128 \r
129      XOSTenantApp.tenantSiteListView = tenantSiteListClass;\r
130 \r
131      XOSTenantApp.tenantSliceSelectorView = SliceSelectorView.extend( {\r
132          sliceChanged: function(id) {\r
133              XOSTenantApp.navToSlice(id);\r
134          },\r
135      });\r
136 \r
137      xos.sites.fetch();\r
138      xos.slicesPlus.fetch();\r
139      xos.tenantview.fetch();\r
140 };\r
141 \r
142 make_choices = function(list_of_names, list_of_values) {\r
143     result = [];\r
144     if (!list_of_values) {\r
145         for (index in list_of_names) {\r
146             displayName = list_of_names[index];\r
147             result.push( [displayName, displayName] );\r
148         }\r
149     } else {\r
150         for (index in list_of_names) {\r
151             displayName = list_of_names[index];\r
152             id = list_of_values[index];\r
153             result.push( [displayName, id] );\r
154         }\r
155     }\r
156     return result;\r
157 };\r
158 \r
159 XOSTenantApp.navToSlice = function(id) {\r
160     XOSTenantApp.viewSlice(xos.slicesPlus.get(id));\r
161 };\r
162 \r
163 XOSTenantApp.adjustCollectionField = function(collectionName, id, fieldName, amount) {\r
164     model = XOSTenantApp[collectionName].get(id);\r
165     model.set(fieldName, Math.max(model.get(fieldName) + amount, 0));\r
166 };\r
167 \r
168 XOSTenantApp.addSlice = function() {\r
169     var app=this;\r
170     model = new xos.slicesPlus.model({site: xos.tenant().current_user_site_id,\r
171                                       name: xos.tenant().current_user_login_base + "_"});\r
172     console.log(model);\r
173     var detailView = new XOSTenantApp.tenantAddView({model: model,\r
174                                                     collection: xos.slicesPlus,\r
175                                                     noSubmitButton: true,\r
176                                                     });\r
177     detailView.dialog = $("#tenant-addslice-dialog");\r
178     app.tenantAddSliceInterior.show(detailView);\r
179     $("#tenant-addslice-dialog").dialog({\r
180        autoOpen: false,
181        modal: true,
182        width: 640,
183        buttons : {
184             "Save" : function() {
185               var addDialog = this;
186               console.log("SAVE!!!");
187               detailView.synchronous = true;
188               detailView.afterSave = function() { $(addDialog).dialog("close"); XOSTenantApp.navToSlice(detailView.model.id); }
189               detailView.save();
190             },
191             "Cancel" : function() {
192               $(this).dialog("close");
193             }
194           }
195         });
196     $("#tenant-addslice-dialog").dialog("open");\r
197 };\r
198 \r
199 XOSTenantApp.editUsers = function(model) {\r
200     var app=this;\r
201     var detailView = new XOSEditUsersView({model: model, collection: xos.slicesPlus});\r
202     detailView.dialog = $("#tenant-edit-users-dialog");\r
203     app.tenantEditUsersInterior.show(detailView);\r
204     $("#tenant-edit-users-dialog").dialog({\r
205        autoOpen: false,
206        modal: true,
207        width: 640,
208        buttons : {
209             "Save" : function() {
210               var editDialog = this;
211               user_ids = all_options($("#tenant-edit-users-dialog").find(".select-picker-to"));
212               user_ids = user_ids.map( function(x) { return parseInt(x,10); } );
213               model.attributes.users = user_ids;
214               $(editDialog).dialog("close");
215             },
216             "Cancel" : function() {
217               $(this).dialog("close");
218             }
219           }
220         });
221     $("#tenant-edit-users-dialog").dialog("open");\r
222 };\r
223 \r
224 XOSTenantApp.deleteSlice = function(model) {\r
225     var app=this;\r
226     app.deleteDialog(model, function() { console.log("afterDelete"); app.viewSlice(undefined); });\r
227 };\r
228 \r
229 XOSTenantApp.viewSlice = function(model) {\r
230     if (!model && xos.slicesPlus.models.length > 0) {\r
231         model = xos.slicesPlus.models[0];\r
232     }\r
233 \r
234     sliceSelector = new XOSTenantApp.tenantSliceSelectorView({collection: xos.slicesPlus,\r
235                                                               selectedID: model.id,\r
236                                                              } );\r
237     XOSTenantApp.sliceSelector = sliceSelector;\r
238     XOSTenantApp.tenantSliceSelector.show(sliceSelector);\r
239 \r
240     tenantSummary = new XOSTenantApp.tenantSummaryView({model: model,\r
241                                                         choices: {mount_data_sets: make_choices(xos.tenant().public_volume_names, null),\r
242                                                                   serviceClass: make_choices(xos.tenant().blessed_service_class_names, xos.tenant().blessed_service_classes),\r
243                                                                   default_image: make_choices(xos.tenant().blessed_image_names, xos.tenant().blessed_images),\r
244                                                                   default_flavor: make_choices(xos.tenant().blessed_flavor_names, xos.tenant().blessed_flavors),},\r
245                                                        });\r
246     XOSTenantApp.tenantSummary.show(tenantSummary);\r
247 \r
248     tenantSites = new XOSTenantSiteCollection();\r
249     tenantSites.getFromSlice(model);\r
250     model.tenantSiteCollection = tenantSites;\r
251     XOSTenantApp.tenantSites = tenantSites;\r
252 \r
253     tenantSiteList = new XOSTenantApp.tenantSiteListView({collection: tenantSites });\r
254     XOSTenantApp.tenantSiteList.show(tenantSiteList);\r
255     // on xos.slicePlus.sort, need to update xostenantapp.tenantSites\r
256 \r
257     XOSTenantApp.tenantButtons.show( new XOSTenantButtonView( { app: XOSTenantApp,\r
258                                                                 linkedView: tenantSummary } ) );\r
259 };\r
260 \r
261 XOSTenantApp.sanityCheck = function() {\r
262     errors = [];\r
263     if (xos.tenant().blessed_service_classes.length == 0) {\r
264         errors.push("no blessed service classes");\r
265     }\r
266     if (xos.tenant().blessed_flavors.length == 0) {\r
267         errors.push("no blessed flavors");\r
268     }\r
269     if (xos.tenant().blessed_images.length == 0) {\r
270         errors.push("no blessed images");\r
271     }\r
272     if (xos.tenant().blessed_sites.length == 0) {\r
273         errors.push("no blessed sites");\r
274     }\r
275 \r
276     if (errors.length > 0) {\r
277          $("#tenantSummary").html("Tenant view sanity check failed<br>" + errors.join("<br>"));\r
278          return false;\r
279     }\r
280 \r
281     return true;\r
282 }\r
283 \r
284 XOSTenantApp.collectionLoadChange = function() {\r
285     stats = xos.getCollectionStatus();\r
286 \r
287     if (!XOSTenantApp.navigationStarted) {\r
288         if (stats["isLoaded"] + stats["failedLoad"] >= stats["startedLoad"]) {\r
289             if (XOSTenantApp.sanityCheck()) {\r
290                 XOSTenantApp.viewSlice(undefined);\r
291             }\r
292         } else {\r
293             $("#tenantSummary").html("<h3>Loading...</h3><div id='xos-startup-progress'></div>");\r
294             $("#xos-startup-progress").progressbar({value: stats["completedLoad"], max: stats["startedLoad"]});\r
295         }\r
296     }\r
297 };\r
298 \r
299 XOSTenantApp.on("start", function() {\r
300      XOSTenantApp.buildViews();
301
302      // fire it once to initially show the progress bar
303      XOSTenantApp.collectionLoadChange();
304
305      // fire it each time the collection load status is updated
306      Backbone.on("xoslib:collectionLoadChange", XOSTenantApp.collectionLoadChange);
307 });
308
309 $(document).ready(function(){
310     XOSTenantApp.start();
311 });
312