root / ui / static / snf / js / ui / web / ui_create_view.js @ 8d08f18a
History | View | Annotate | Download (14.1 kB)
1 |
;(function(root){
|
---|---|
2 |
|
3 |
// root
|
4 |
var root = root;
|
5 |
|
6 |
// setup namepsaces
|
7 |
var snf = root.synnefo = root.synnefo || {};
|
8 |
var models = snf.models = snf.models || {}
|
9 |
var storage = snf.storage = snf.storage || {};
|
10 |
var ui = snf.ui = snf.ui || {};
|
11 |
var util = snf.util = snf.util || {};
|
12 |
|
13 |
var views = snf.views = snf.views || {}
|
14 |
|
15 |
// shortcuts
|
16 |
var bb = root.Backbone;
|
17 |
|
18 |
|
19 |
views.VMCreationPasswordView = views.Overlay.extend({ |
20 |
view_id: "creation_password_view", |
21 |
content_selector: "#creation-password-overlay", |
22 |
css_class: 'overlay-password overlay-info', |
23 |
overlay_id: "creation-password-overlay", |
24 |
|
25 |
subtitle: "", |
26 |
title: "Machine password", |
27 |
|
28 |
initialize: function(options) { |
29 |
views.FeedbackView.__super__.initialize.apply(this, arguments); |
30 |
_.bindAll(this, 'show_password'); |
31 |
|
32 |
this.password = this.$("#new-machine-password"); |
33 |
}, |
34 |
|
35 |
show_password: function() { |
36 |
this.password.text(this.pass); |
37 |
}, |
38 |
|
39 |
onClose: function() { |
40 |
this.password.text(""); |
41 |
}, |
42 |
|
43 |
show: function(pass, vm_id) { |
44 |
this.pass = pass;
|
45 |
this.vm_id = vm_id;
|
46 |
|
47 |
views.VMCreationPasswordView.__super__.show.apply(this, arguments); |
48 |
this.show_password();
|
49 |
} |
50 |
}) |
51 |
|
52 |
|
53 |
|
54 |
views.CreateVMStepView = views.View.extend({ |
55 |
step: "1", |
56 |
title: "Image", |
57 |
submit: false, |
58 |
|
59 |
initialize: function(view) { |
60 |
this.parent = view;
|
61 |
this.el = view.$("div.create-step-cont.step-" + this.step); |
62 |
this.header = view.$(".subheader .step-" + this.step); |
63 |
this.view_id = "create_step_" + this.step; |
64 |
|
65 |
views.CreateVMStepView.__super__.initialize.apply(this);
|
66 |
}, |
67 |
|
68 |
show: function() { |
69 |
// show current
|
70 |
this.el.show();
|
71 |
this.header.addClass("current"); |
72 |
this.update_layout();
|
73 |
}, |
74 |
|
75 |
reset: function() { |
76 |
} |
77 |
}) |
78 |
|
79 |
views.CreateImageSelectView = views.CreateVMStepView.extend({ |
80 |
|
81 |
initialize: function() { |
82 |
views.CreateImageSelectView.__super__.initialize.apply(this, arguments); |
83 |
|
84 |
this.predefined = this.$(".predefined-images ul"); |
85 |
this.custom = this.$(".predefined-images ul"); |
86 |
this.selected_image = undefined; |
87 |
this.reset_images();
|
88 |
}, |
89 |
|
90 |
update_layout: function() { |
91 |
}, |
92 |
|
93 |
select_image: function(image) { |
94 |
if (!image) {
|
95 |
image = storage.images.at(0);
|
96 |
} |
97 |
|
98 |
this.selected_image = image;
|
99 |
this.trigger("change", this.selected_image); |
100 |
|
101 |
this.predefined.find(".image-details").removeClass("selected"); |
102 |
this.predefined.find(".image-details#create-vm-image-" + this.selected_image.id).addClass("selected") |
103 |
}, |
104 |
|
105 |
reset_images: function() { |
106 |
this.$(".image-details").remove(); |
107 |
storage.images.each(_.bind(function(img){
|
108 |
this.add_image(img);
|
109 |
}, this))
|
110 |
|
111 |
this.select_image();
|
112 |
|
113 |
var self = this; |
114 |
this.predefined.find(".image-details").click(function(){ |
115 |
self.select_image($(this).data("image")); |
116 |
}) |
117 |
}, |
118 |
|
119 |
add_image: function(img) { |
120 |
var image = $('<li id="create-vm-image-{1}" class="image-details">{0}</li>'.format(img.get("name"), img.id)); |
121 |
image.data("image", img);
|
122 |
image.data("image_id", img.id);
|
123 |
this.predefined.append(image);
|
124 |
}, |
125 |
|
126 |
reset: function() { |
127 |
this.selected_image = undefined; |
128 |
this.reset_images();
|
129 |
}, |
130 |
|
131 |
get: function() { |
132 |
return {'image': this.selected_image}; |
133 |
} |
134 |
}); |
135 |
|
136 |
views.CreateFlavorSelectView = views.CreateVMStepView.extend({ |
137 |
step: 2, |
138 |
initialize: function() { |
139 |
views.CreateFlavorSelectView.__super__.initialize.apply(this, arguments); |
140 |
this.parent.bind("image:change", _.bind(this.handle_image_change, this)); |
141 |
|
142 |
this.cpus = this.$(".flavors-cpu-list") |
143 |
this.disks = this.$(".flavors-disk-list") |
144 |
this.mems = this.$(".flavors-mem-list") |
145 |
|
146 |
this.reset();
|
147 |
this.update_layout();
|
148 |
}, |
149 |
|
150 |
handle_image_change: function(data) { |
151 |
this.current_image = data;
|
152 |
this.update_flavors_data();
|
153 |
this.reset_flavors();
|
154 |
this.update_layout();
|
155 |
}, |
156 |
|
157 |
reset_flavors: function() { |
158 |
this.$(".flavor-opts-list .option").remove(); |
159 |
this.create_flavors();
|
160 |
}, |
161 |
|
162 |
update_flavors_data: function() { |
163 |
this.flavors = storage.flavors.for_image(this.current_image); |
164 |
this.flavors_data = storage.flavors.get_data(this.flavors); |
165 |
|
166 |
if (this.flavors.indexOf(this.current_flavor) == -1) { |
167 |
this.set_current(this.flavors[0]); |
168 |
} |
169 |
}, |
170 |
|
171 |
set_current: function(flv) { |
172 |
this.current_flavor = flv;
|
173 |
this.trigger("change"); |
174 |
this.update_selected_flavor();
|
175 |
}, |
176 |
|
177 |
create_flavors: function() { |
178 |
var flavors = this.get_flavors(); |
179 |
_.each(flavors, _.bind(function(flv){
|
180 |
this.add_flavor(flv);
|
181 |
}, this));
|
182 |
|
183 |
var self = this; |
184 |
this.$(".flavor-options li.option").click(function(){ |
185 |
var el = $(this); |
186 |
el.parent().find(".option").removeClass("selected"); |
187 |
el.addClass("selected");
|
188 |
self.update_selected_from_ui(); |
189 |
}) |
190 |
}, |
191 |
|
192 |
ui_selected: function() { |
193 |
args = [this.$(".option.cpu.selected").data("value"), |
194 |
this.$(".option.mem.selected").data("value"), |
195 |
this.$(".option.disk.selected").data("value"), |
196 |
this.flavors];
|
197 |
|
198 |
storage.flavors.apply(storage.flavors, args) |
199 |
}, |
200 |
|
201 |
update_selected_flavor: function() { |
202 |
|
203 |
}, |
204 |
|
205 |
add_flavor: function(flv) { |
206 |
var values = {'cpu': flv.get('cpu'), 'mem': flv.get('ram'), 'disk': flv.get('disk')}; |
207 |
|
208 |
if (this.$('li.option.cpu.value-{0}'.format(values.cpu)).length == 0) { |
209 |
var cpu = $('<li class="option cpu value-{0}">{0}</li>'.format(values.cpu)).data('value', values.cpu); |
210 |
this.cpus.append(cpu);
|
211 |
} |
212 |
if (this.$('li.option.mem.value-{0}'.format(values.mem)).length == 0) { |
213 |
var mem = $('<li class="option mem value-{0}">{0}</li>'.format(values.mem)).data('value', values.mem); |
214 |
this.mems.append(mem);
|
215 |
} |
216 |
if (this.$('li.option.disk.value-{0}'.format(values.disk)).length == 0) { |
217 |
var disk = $('<li class="option disk value-{0}">{0}</li>'.format(values.disk)).data('value', values.disk); |
218 |
this.disks.append(disk);
|
219 |
} |
220 |
|
221 |
}, |
222 |
|
223 |
get_flavors: function() { |
224 |
return this.flavors; |
225 |
}, |
226 |
|
227 |
update_layout: function() { |
228 |
var flv = this.current_flavor; |
229 |
this.$(".option.value").removeClass("selected"); |
230 |
|
231 |
this.$(".option.cpu.value-" + flv.get("cpu")).addClass("selected"); |
232 |
this.$(".option.mem.value-" + flv.get("ram")).addClass("selected"); |
233 |
this.$(".option.disk.value-" + flv.get("disk")).addClass("selected"); |
234 |
}, |
235 |
|
236 |
reset: function() { |
237 |
this.current_image = storage.images.at(0); |
238 |
this.flavors = [];
|
239 |
this.flavors_data = {'cpu':[], 'mem':[], 'disk':[]}; |
240 |
this.update_flavors_data();
|
241 |
this.reset_flavors();
|
242 |
}, |
243 |
|
244 |
get: function() { |
245 |
return {'flavor': this.current_flavor} |
246 |
} |
247 |
|
248 |
}); |
249 |
|
250 |
views.CreateSubmitView = views.CreateVMStepView.extend({ |
251 |
step: 3, |
252 |
initialize: function() { |
253 |
views.CreateSubmitView.__super__.initialize.apply(this, arguments); |
254 |
this.confirm = this.$(".confirm-params ul"); |
255 |
this.name = this.$("input"); |
256 |
this.name_changed = false; |
257 |
this.init_handlers();
|
258 |
}, |
259 |
|
260 |
init_handlers: function() { |
261 |
this.name.bind("keypress", _.bind(function() { |
262 |
this.name_changed = true; |
263 |
}, this));
|
264 |
|
265 |
this.name.bind("click", _.bind(function() { |
266 |
if (!this.name_changed) { |
267 |
this.name.val(""); |
268 |
} |
269 |
}, this))
|
270 |
}, |
271 |
|
272 |
show: function() { |
273 |
views.CreateSubmitView.__super__.show.apply(this, arguments); |
274 |
this.update_layout();
|
275 |
}, |
276 |
|
277 |
update_layout: function() { |
278 |
var params = this.parent.get_params(); |
279 |
var vm_name = "My {0} server".format(params.image.get("name")); |
280 |
var orig_name = vm_name;
|
281 |
|
282 |
var existing = true; |
283 |
var j = 0; |
284 |
while (existing) {
|
285 |
var existing = storage.vms.select(function(vm){return vm.get("name") == vm_name}).length |
286 |
if (existing) {
|
287 |
j++; |
288 |
vm_name = orig_name + " " + j;
|
289 |
} |
290 |
} |
291 |
|
292 |
if (!_(this.name.val()).trim() || !this.name_changed) { |
293 |
this.name.val(vm_name);
|
294 |
} |
295 |
|
296 |
this.confirm.find("li.image .value").text(params.flavor.get("image")); |
297 |
this.confirm.find("li.cpu .value").text(params.flavor.get("cpu")); |
298 |
this.confirm.find("li.mem .value").text(params.flavor.get("ram")); |
299 |
this.confirm.find("li.disk .value").text(params.flavor.get("disk")); |
300 |
}, |
301 |
|
302 |
reset: function() { |
303 |
this.update_layout();
|
304 |
}, |
305 |
|
306 |
get: function() { |
307 |
return {'name': this.name.val() }; |
308 |
} |
309 |
}); |
310 |
|
311 |
views.CreateVMView = views.Overlay.extend({ |
312 |
|
313 |
view_id: "create_vm_view", |
314 |
content_selector: "#createvm-overlay-content", |
315 |
css_class: 'overlay-createvm overlay-info', |
316 |
overlay_id: "metadata-overlay", |
317 |
|
318 |
subtitle: false, |
319 |
title: "Create new machine", |
320 |
|
321 |
initialize: function(options) { |
322 |
views.CreateVMView.__super__.initialize.apply(this);
|
323 |
this.current_step = 1; |
324 |
|
325 |
this.password_view = new views.VMCreationPasswordView(); |
326 |
|
327 |
this.steps = [];
|
328 |
this.steps[1] = new views.CreateImageSelectView(this); |
329 |
this.steps[1].bind("change", _.bind(function(data) {this.trigger("image:change", data)}, this)); |
330 |
|
331 |
this.steps[2] = new views.CreateFlavorSelectView(this); |
332 |
this.steps[3] = new views.CreateSubmitView(this); |
333 |
|
334 |
this.cancel_btn = this.$(".create-controls .cancel") |
335 |
this.next_btn = this.$(".create-controls .next") |
336 |
this.prev_btn = this.$(".create-controls .prev") |
337 |
this.submit_btn = this.$(".create-controls .submit") |
338 |
|
339 |
this.init_handlers();
|
340 |
this.update_layout();
|
341 |
}, |
342 |
|
343 |
init_handlers: function() { |
344 |
this.next_btn.click(_.bind(function(){ |
345 |
this.show_step(this.current_step + 1); |
346 |
this.update_layout();
|
347 |
}, this))
|
348 |
this.prev_btn.click(_.bind(function(){ |
349 |
this.show_step(this.current_step - 1); |
350 |
this.update_layout();
|
351 |
}, this))
|
352 |
this.cancel_btn.click(_.bind(function(){ |
353 |
this.close_all();
|
354 |
}, this))
|
355 |
this.submit_btn.click(_.bind(function(){ |
356 |
this.submit();
|
357 |
}, this))
|
358 |
}, |
359 |
|
360 |
set_step: function(st) { |
361 |
}, |
362 |
|
363 |
validate: function(data) { |
364 |
if (_(data.name).trim() == "") { |
365 |
this.$(".form-field").addClass("error"); |
366 |
return false; |
367 |
} else {
|
368 |
return true; |
369 |
} |
370 |
}, |
371 |
|
372 |
submit: function() { |
373 |
var data = this.get_params(); |
374 |
if (this.validate(data)) { |
375 |
this.submit_btn.addClass("in-progress"); |
376 |
storage.vms.create(data.name, data.image, data.flavor, {}, {}, _.bind(function(data){
|
377 |
this.close_all();
|
378 |
this.password_view.show(data.server.adminPass);
|
379 |
}, this));
|
380 |
} |
381 |
}, |
382 |
|
383 |
close_all: function() { |
384 |
this.hide();
|
385 |
}, |
386 |
|
387 |
reset: function() { |
388 |
this.current_step = 1; |
389 |
this.steps[1].reset(); |
390 |
this.steps[2].reset(); |
391 |
this.steps[3].reset(); |
392 |
|
393 |
this.submit_btn.removeClass("in-progress"); |
394 |
}, |
395 |
|
396 |
onShow: function() { |
397 |
this.reset()
|
398 |
this.update_layout();
|
399 |
}, |
400 |
|
401 |
update_layout: function() { |
402 |
this.show_step(this.current_step); |
403 |
this.current_view.update_layout();
|
404 |
}, |
405 |
|
406 |
beforeOpen: function() { |
407 |
this.reset();
|
408 |
this.current_step = 1; |
409 |
this.show_step(1); |
410 |
}, |
411 |
|
412 |
show_step: function(step) { |
413 |
if (step <= 1) { |
414 |
step = 1
|
415 |
} |
416 |
if (step > this.steps.length - 1) { |
417 |
step = this.steps.length - 1; |
418 |
} |
419 |
|
420 |
// hide other
|
421 |
this.$(".subheader .header-step").removeClass("current"); |
422 |
this.$(".create-step-cont").hide(); |
423 |
|
424 |
this.steps[step].show();
|
425 |
this.current_step = step;
|
426 |
this.current_view = this.steps[step]; |
427 |
//
|
428 |
this.update_controls();
|
429 |
}, |
430 |
|
431 |
update_controls: function() { |
432 |
var step = this.current_step; |
433 |
if (step == 1) { |
434 |
this.prev_btn.hide();
|
435 |
this.cancel_btn.show();
|
436 |
} else {
|
437 |
this.prev_btn.show();
|
438 |
this.cancel_btn.hide();
|
439 |
} |
440 |
|
441 |
if (step == this.steps.length - 1) { |
442 |
this.next_btn.hide();
|
443 |
this.submit_btn.show();
|
444 |
} else {
|
445 |
this.next_btn.show();
|
446 |
this.submit_btn.hide();
|
447 |
} |
448 |
}, |
449 |
|
450 |
get_params: function() { |
451 |
return _.extend({}, this.steps[1].get(), this.steps[2].get(), this.steps[3].get()); |
452 |
} |
453 |
}); |
454 |
|
455 |
})(this);
|
456 |
|