display 'no slices' when there are no slices
[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     if (model) {\r
235         sliceSelector = new XOSTenantApp.tenantSliceSelectorView({collection: xos.slicesPlus,\r
236                                                                   selectedID: model ? model.id : null,\r
237                                                                  } );\r
238         XOSTenantApp.sliceSelector = sliceSelector;\r
239         XOSTenantApp.tenantSliceSelector.show(sliceSelector);\r
240 \r
241         tenantSummary = new XOSTenantApp.tenantSummaryView({model: model,\r
242                                                             choices: {mount_data_sets: make_choices(xos.tenant().public_volume_names, null),\r
243                                                                       serviceClass: make_choices(xos.tenant().blessed_service_class_names, xos.tenant().blessed_service_classes),\r
244                                                                       default_image: make_choices(xos.tenant().blessed_image_names, xos.tenant().blessed_images),\r
245                                                                       default_flavor: make_choices(xos.tenant().blessed_flavor_names, xos.tenant().blessed_flavors),},\r
246                                                            });\r
247         XOSTenantApp.tenantSummary.show(tenantSummary);\r
248 \r
249         tenantSites = new XOSTenantSiteCollection();\r
250         tenantSites.getFromSlice(model);\r
251         model.tenantSiteCollection = tenantSites;\r
252         XOSTenantApp.tenantSites = tenantSites;\r
253 \r
254         tenantSiteList = new XOSTenantApp.tenantSiteListView({collection: tenantSites });\r
255         XOSTenantApp.tenantSiteList.show(tenantSiteList);\r
256         // on xos.slicePlus.sort, need to update xostenantapp.tenantSites\r
257 \r
258         XOSTenantApp.tenantButtons.show( new XOSTenantButtonView( { app: XOSTenantApp,\r
259                                                                     linkedView: tenantSummary } ) );\r
260     } else {\r
261         XOSTenantApp.tenantSliceSelector.show(new HTMLView({html: ""}));\r
262         XOSTenantApp.tenantSummary.show(new HTMLView({html: "You have no slices"}));\r
263         XOSTenantApp.tenantSiteList.show(new HTMLView({html: ""}));\r
264         XOSTenantApp.tenantButtons.show( new XOSTenantButtonView( { template: "#xos-tenant-buttons-noslice-template",\r
265                                                                     app: XOSTenantApp,\r
266                                                                     linkedView: tenantSummary } ) );\r
267     }\r
268 };\r
269 \r
270 XOSTenantApp.sanityCheck = function() {\r
271     errors = [];\r
272     if (xos.tenant().blessed_service_classes.length == 0) {\r
273         errors.push("no blessed service classes");\r
274     }\r
275     if (xos.tenant().blessed_flavors.length == 0) {\r
276         errors.push("no blessed flavors");\r
277     }\r
278     if (xos.tenant().blessed_images.length == 0) {\r
279         errors.push("no blessed images");\r
280     }\r
281     if (xos.tenant().blessed_sites.length == 0) {\r
282         errors.push("no blessed sites");\r
283     }\r
284 \r
285     if (errors.length > 0) {\r
286          $("#tenantSummary").html("Tenant view sanity check failed<br>" + errors.join("<br>"));\r
287          return false;\r
288     }\r
289 \r
290     return true;\r
291 }\r
292 \r
293 XOSTenantApp.collectionLoadChange = function() {\r
294     stats = xos.getCollectionStatus();\r
295 \r
296     if (!XOSTenantApp.navigationStarted) {\r
297         if (stats["isLoaded"] + stats["failedLoad"] >= stats["startedLoad"]) {\r
298             if (XOSTenantApp.sanityCheck()) {\r
299                 XOSTenantApp.viewSlice(undefined);\r
300             }\r
301         } else {\r
302             $("#tenantSummary").html("<h3>Loading...</h3><div id='xos-startup-progress'></div>");\r
303             $("#xos-startup-progress").progressbar({value: stats["completedLoad"], max: stats["startedLoad"]});\r
304         }\r
305     }\r
306 };\r
307 \r
308 XOSTenantApp.on("start", function() {\r
309      XOSTenantApp.buildViews();
310
311      // fire it once to initially show the progress bar
312      XOSTenantApp.collectionLoadChange();
313
314      // fire it each time the collection load status is updated
315      Backbone.on("xoslib:collectionLoadChange", XOSTenantApp.collectionLoadChange);
316 });
317
318 $(document).ready(function(){
319     XOSTenantApp.start();
320 });
321