Statistics
| Branch: | Tag: | Revision:

root / ui / static / snf / js / ui / web / ui_create_view.js @ 709a6319

History | View | Annotate | Download (28.2 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
            this.copy = this.$(".clip-copy");
34

    
35
            this.$(".show-machine").click(_.bind(function(){
36
                this.hide();
37
                snf.ui.main.show_vm_details(storage.vms.get(this.vm_id));
38
            }, this));
39
            
40
        },
41
        
42
        show_password: function() {
43
            this.password.text(this.pass);
44
        },
45

    
46
        onClose: function() {
47
            this.password.text("");
48
        },
49
        
50
        beforeOpen: function() {
51
            if (this.clipboard) { return };
52
            this.clipboard = new util.ClipHelper(this.copy);
53
            this.clipboard.el.tooltip();
54
        },
55
        
56
        onOpen: function() {
57
            try {
58
                this.clipboard.setText(this.pass);
59
                this.copy.show();
60
            } catch (err) {
61
                this.copy.hide();
62
            }
63
        },
64

    
65
        show: function(pass, vm_id) {
66
            this.pass = pass;
67
            this.vm_id = vm_id;
68

    
69
            views.VMCreationPasswordView.__super__.show.apply(this, arguments);
70
            this.show_password();
71
        }
72
    })
73

    
74

    
75
    
76
    views.CreateVMStepView = views.View.extend({
77
        step: "1",
78
        title: "Image",
79
        submit: false,
80

    
81
        initialize: function(view) {
82
            this.parent = view;
83
            this.el = view.$("div.create-step-cont.step-" + this.step);
84
            this.header = this.$(".step-header .step-" + this.step);
85
            this.view_id = "create_step_" + this.step;
86

    
87
            views.CreateVMStepView.__super__.initialize.apply(this);
88
        },
89

    
90
        show: function() {
91
            // show current
92
            this.el.show();
93
            this.header.addClass("current");
94
            this.header.show();
95
            this.update_layout();
96
        },
97

    
98
        reset: function() {
99
        }
100
    })
101

    
102
    views.CreateImageSelectView = views.CreateVMStepView.extend({
103

    
104
        initialize: function() {
105
            views.CreateImageSelectView.__super__.initialize.apply(this, arguments);
106

    
107
            // elements
108
            this.images_list_cont = this.$(".images-list-cont");
109
            this.images_list = this.$(".images-list-cont ul");
110
            this.image_details = this.$(".images-info-cont");
111
            this.image_details_desc = this.$(".images-info-cont .description p");
112
            this.image_details_title = this.$(".images-info-cont h4");
113
            this.image_details_size = this.$(".images-info-cont .size p");
114
            this.image_details_os = this.$(".images-info-cont .os p");
115
            this.image_details_kernel = this.$(".images-info-cont .kernel p");
116
            this.image_details_gui = this.$(".images-info-cont .gui p");
117

    
118
            this.types = this.$(".type-filter li");
119
            this.categories_list = this.$(".category-filters");
120

    
121
            // params initialization
122
            this.type_selections = ["system", "custom"]
123
            this.selected_type = "system";
124
            this.selected_categories = [];
125
            this.images = [];
126

    
127
            // update
128
            this.update_images();
129

    
130
            // handlers initialization
131
            this.init_handlers();
132
            this.init_position();
133
        },
134

    
135
        init_position: function() {
136
            //this.el.css({position: "absolute"});
137
            //this.el.css({top:"10px"})
138
        },
139
        
140
        init_handlers: function() {
141
            var self = this;
142
            this.types.live("click", function() {
143
                self.select_type($(this).attr("id").replace("type-select-",""));
144
            })
145
        },
146

    
147
        update_images: function() {
148
            this.images = storage.images.active();
149
            this.images_ids = _.map(this.images, function(img){return img.id});
150
            if (this.selected_type == "custom") { this.images = []; this.images_ids = []; }
151

    
152
            return this.images;
153
        },
154

    
155
        update_layout: function() {
156
            this.select_type(this.selected_type);
157
        },
158
        
159
        get_categories: function(images) {
160
            return [];
161
            return ["Desktop", "Server", "Linux", "Windows"];
162
        },
163

    
164
        reset_categories: function() {
165
            var categories = this.get_categories(this.images);
166
            this.categories_list.find("li").remove();
167

    
168
            _.each(categories, _.bind(function(cat) {
169
                var el = $("<li />");
170
                el.text(cat);
171
                this.categories_list.append(el);
172
            }, this));
173

    
174
            if (!categories.length) { 
175
                this.categories_list.parent().find(".clear").hide();
176
                this.categories_list.parent().find(".empty").show();
177
            } else {
178
                this.categories_list.parent().find(".clear").show();
179
                this.categories_list.parent().find(".empty").hide();
180
            }
181
        },
182
        
183
        select_type: function(type) {
184
            this.selected_type = type;
185
            this.types.removeClass("selected");
186
            this.types.filter("#type-select-" + this.selected_type).addClass("selected");
187

    
188
            this.reset_categories();
189
            this.update_images();
190
            this.reset_images();
191
            this.select_image();
192
        },
193

    
194
        select_image: function(image) {
195
            if (!image && this.images_ids.length) {
196
                if (this.selected_image && this.images_ids.indexOf(this.selected_image.id) > -1) {
197
                    image = this.selected_image;
198
                } else {
199
                    image = storage.images.get(this.images_ids[0]);
200
                }
201
            }
202

    
203
            if (!this.images_ids.length) { image = this.selected_image || undefined };
204
            
205
            this.selected_image = image;
206
            this.trigger("change", image);
207
            
208
            if (image) {
209
                this.image_details.show();
210
                this.images_list.find(".image-details").removeClass("selected");
211
                this.images_list.find(".image-details#create-vm-image-" + this.selected_image.id).addClass("selected");
212
                
213
                this.image_details_desc.text(image.get("description"));
214
                
215
                var img = snf.ui.helpers.os_icon_tag(image.get("OS"))
216
                this.image_details_title.html(img + image.get("name"));
217
                this.image_details_os.text(_(image.get("OS")).capitalize());
218
                this.image_details_kernel.text(image.get("kernel"));
219

    
220
                var size = util.readablizeBytes(parseInt(image.get("size")) * 1024 * 1024);
221
                this.image_details_size.text(size);
222
                this.image_details_gui.text(image.get("GUI"));
223

    
224
            } else {
225
                this.image_details.hide();
226
            }
227
        },
228

    
229
        reset_images: function() {
230
            this.images_list.find("li").remove();
231
            _.each(this.images, _.bind(function(img){
232
                this.add_image(img);
233
            }, this))
234
            
235
            if (this.images.length) {
236
                this.images_list.parent().find(".empty").hide();
237
            } else {
238
                this.images_list.parent().find(".empty").show();
239
            }
240

    
241
            this.select_image();
242
            
243
            var self = this;
244
            this.images_list.find(".image-details").click(function(){
245
                self.select_image($(this).data("image"));
246
            });
247
            
248
        },
249

    
250
        show: function() {
251
            views.CreateImageSelectView.__super__.show.apply(this, arguments);
252
        },
253

    
254
        add_image: function(img) {
255
            var image = $(('<li id="create-vm-image-{1}"' +
256
                           'class="image-details clearfix">{2}{0}' +
257
                           '<p>{4}</p><span class="size">{3}' +
258
                           '</span></li>').format(img.get("name"), 
259
                                                  img.id, 
260
                                                  snf.ui.helpers.os_icon_tag(img.get("OS")),
261
                                                  util.readablizeBytes(parseInt(img.get("size"))* 1024 * 1024),
262
                                                  util.truncate(img.get("description"),35)));
263
            image.data("image", img);
264
            image.data("image_id", img.id);
265
            this.images_list.append(image);
266
        },
267

    
268
        reset: function() {
269
            this.selected_image = undefined;
270
            this.reset_images();
271
        },
272

    
273
        get: function() {
274
            return {'image': this.selected_image};
275
        }
276
    });
277

    
278
    views.CreateFlavorSelectView = views.CreateVMStepView.extend({
279
        step: 2,
280
        initialize: function() {
281
            views.CreateFlavorSelectView.__super__.initialize.apply(this, arguments);
282
            this.parent.bind("image:change", _.bind(this.handle_image_change, this));
283

    
284
            this.cpus = this.$(".flavors-cpu-list");
285
            this.disks = this.$(".flavors-disk-list");
286
            this.mems = this.$(".flavors-mem-list");
287

    
288
            this.predefined_flavors = SUGGESTED_FLAVORS;
289
            this.predefined = this.$(".predefined-list");
290
            this.update_predefined_flavors();
291
        },
292

    
293
        handle_image_change: function(data) {
294
            this.current_image = data;
295
            this.update_valid_predefined();
296
            this.update_flavors_data();
297
            this.reset_flavors();
298
            this.update_layout();
299
        },
300

    
301
        reset_flavors: function() {
302
            this.$(".flavor-opts-list .option").remove();
303
            this.create_flavors();
304
        },
305

    
306
        update_predefined_flavors: function() {
307
            this.predefined.find("li").remove();
308
            _.each(this.predefined_flavors, _.bind(function(val, key) {
309
                var el = $(('<li class="predefined-selection" id="predefined-flavor-{0}">' +
310
                           '{1}</li>').format(key, key));
311

    
312
                this.predefined.append(el);
313
                el.data({flavor: storage.flavors.get_flavor(val.cpu, val.ram, val.disk, this.flavors)})
314
                el.click(_.bind(function() {
315
                    this.handle_predefined_click(el);
316
                }, this))
317
            }, this));
318
            this.update_valid_predefined();
319
        },
320

    
321
        handle_predefined_click: function(el) {
322
            if (el.hasClass("disabled")) { return };
323
            this.set_current(el.data("flavor"))
324
        },
325

    
326
        update_valid_predefined: function() {
327
            this.update_unavailable_values();
328
            var self = this;
329
            this.valid_predefined = _.select(_.map(this.predefined_flavors, function(flv, key){
330
                var existing = storage.flavors.get_flavor(flv.cpu, flv.ram, flv.disk, self.flavors);
331
                // non existing
332
                if (!existing) {
333
                    return false;
334
                }
335
                
336
                // not available for image
337
                if (self.unavailable_values && self.unavailable_values.disk.indexOf(existing.get_disk_size()) > -1) {
338
                    return false
339
                }
340

    
341
                return key;
342
            }), function(ret) { return ret });
343
            
344
            $("li.predefined-selection").addClass("disabled");
345
            _.each(this.valid_predefined, function(key) {
346
                $("#predefined-flavor-" + key).removeClass("disabled");
347
            })
348
        },
349

    
350
        update_selected_predefined: function() {
351
            var self = this;
352
            this.predefined.find("li").removeClass("selected");
353

    
354
            _.each(this.valid_predefined, function(key){
355
                var flv = self.predefined_flavors[key];
356
                var exists = storage.flavors.get_flavor(flv.cpu, flv.ram, flv.disk, self.flavors);
357

    
358
                if (exists && (exists.id == self.current_flavor.id)) {
359
                    $("#predefined-flavor-" + key).addClass("selected");
360
                }
361
            })
362
        },
363
        
364
        update_flavors_data: function() {
365
            this.flavors = storage.flavors.active();
366
            this.flavors_data = storage.flavors.get_data(this.flavors);
367
            
368
            var self = this;
369
            var set = false;
370
            
371
            // FIXME: validate current flavor
372
            
373
            if (!this.current_flavor) {
374
                _.each(this.valid_predefined, function(key) {
375
                    var flv = self.predefined_flavors[key];
376
                    var exists = storage.flavors.get_flavor(flv.cpu, flv.ram, flv.disk, self.flavors);
377
                    if (exists && !set) {
378
                        self.set_current(exists);
379
                        set = true;
380
                    }
381
                })
382
            }
383

    
384
            this.update_unavailable_values();
385
        },
386

    
387
        update_unavailable_values: function() {
388
            if (!this.current_image) { this.unavailable_values = {disk:[], ram:[], cpu:[]}; return };
389
            this.unavailable_values = storage.flavors.unavailable_values_for_image(this.current_image);
390
        },
391
        
392
        flavor_is_valid: function(flv) {
393
            if (!flv) { return false };
394
            var existing = storage.flavors.get_flavor(flv.get("cpu"), flv.get("ram"), flv.get("disk"), this.flavors);
395
            if (!existing) { return false };
396
            if (this.unavailable_values && this.unavailable_values.disk.indexOf(flv.get("disk") > -1)) {
397
                return false
398
            }
399
            return true;
400
        },
401
            
402
        set_current: function(flv) {
403
            //console.log(flv);
404
            //if (!this.flavor_is_valid(flv)) { flv = undefined };
405
            
406
            this.current_flavor = flv;
407
            this.trigger("change");
408
            this.update_selected_flavor();
409
            this.update_selected_predefined();
410
        },
411
        
412
        select_default_flavor: function() {
413
               
414
        },
415

    
416
        update_selected_from_ui: function() {
417
            this.set_current(this.ui_selected());
418
        },
419
        
420
        update_disabled_flavors: function() {
421
            this.$(".flavor-options.disk li").removeClass("disabled");
422
            if (!this.unavailable_values) { return }
423

    
424
            this.$(".flavor-options.disk li").each(_.bind(function(i, el){
425
                var el_value = $(el).data("value") * 1024;
426
                if (this.unavailable_values.disk.indexOf(el_value) > -1) {
427
                    $(el).addClass("disabled");
428
                };
429
            }, this));
430
        },
431

    
432
        create_flavors: function() {
433
            var flavors = this.get_active_flavors();
434
            var valid_flavors = this.get_valid_flavors();
435

    
436
            _.each(flavors, _.bind(function(flv){
437
                this.add_flavor(flv);
438
            }, this));
439
            
440
            var self = this;
441
            this.$(".flavor-options li.option").click(function(){
442
                var el = $(this);
443

    
444
                if (el.hasClass("disabled")) { return }
445

    
446
                el.parent().find(".option").removeClass("selected");
447
                el.addClass("selected");
448
                
449
                if (el.hasClass("mem")) { this.last_choice = "mem" }
450
                if (el.hasClass("cpu")) { this.last_choice = "cpu" }
451
                if (el.hasClass("disk")) { this.last_choice = "disk" }
452

    
453
                self.update_selected_from_ui();
454
            })
455
        },
456
        
457
        ui_selected: function() {
458
            var args = [this.$(".option.cpu.selected").data("value"), 
459
                this.$(".option.mem.selected").data("value"), 
460
                this.$(".option.disk.selected").data("value"),
461
            this.flavors];
462

    
463
            var flv = storage.flavors.get_flavor.apply(storage.flavors, args);
464
            return flv;
465
        },
466

    
467
        update_selected_flavor: function() {
468
            var flv = this.current_flavor;
469
            this.$(".option").removeClass("selected");
470

    
471
            this.$(".option.cpu.value-" + flv.get("cpu")).addClass("selected");
472
            this.$(".option.mem.value-" + flv.get("ram")).addClass("selected");
473
            this.$(".option.disk.value-" + flv.get("disk")).addClass("selected");
474
        },
475

    
476
        add_flavor: function(flv) {
477
            var values = {'cpu': flv.get('cpu'), 'mem': flv.get('ram'), 'disk': flv.get('disk')};
478

    
479
            disabled = "";
480

    
481
            if (this.$('li.option.cpu.value-{0}'.format(values.cpu)).length == 0) {
482
                var cpu = $(('<li class="option cpu value-{0} {1}">' + 
483
                             '<span class="value">{0}</span>' + 
484
                             '<span class="metric">x</span></li>').format(values.cpu, disabled)).data('value', values.cpu);
485

    
486
                this.cpus.append(cpu);
487
            }
488
            if (this.$('li.option.mem.value-{0}'.format(values.mem)).length == 0) {
489
                var mem = $(('<li class="option mem value-{0}">' + 
490
                             '<span class="value">{0}</span>' + 
491
                             '<span class="metric">MB</span></li>').format(values.mem)).data('value', values.mem);
492

    
493
                this.mems.append(mem);
494
            }
495
            if (this.$('li.option.disk.value-{0}'.format(values.disk)).length == 0) {
496
                var disk = $(('<li class="option disk value-{0}">' + 
497
                              '<span class="value">{0}</span>' + 
498
                              '<span class="metric">GB</span></li>').format(values.disk)).data('value', values.disk);
499

    
500
                this.disks.append(disk);
501
            }
502
            
503
        },
504
        
505
        get_active_flavors: function() {
506
            return storage.flavors.active();
507
        },
508

    
509
        get_valid_flavors: function() {
510
            return this.flavors;
511
        },
512

    
513
        update_layout: function() {
514
            this.update_selected_flavor();
515
            this.update_disabled_flavors();
516
        },
517

    
518
        reset: function() {
519
            this.current_image = storage.images.at(0);
520
            this.flavors = [];
521
            this.flavors_data = {'cpu':[], 'mem':[], 'disk':[]};
522
            this.update_flavors_data();
523
            this.reset_flavors();
524
        },
525

    
526
        get: function() {
527
            return {'flavor': this.current_flavor}
528
        }
529

    
530
    });
531

    
532
    views.CreateSubmitView = views.CreateVMStepView.extend({
533
        step: 3,
534
        initialize: function() {
535
            views.CreateSubmitView.__super__.initialize.apply(this, arguments);
536
            this.roles = this.$("li.predefined-meta.role .values");
537
            this.confirm = this.$(".confirm-params ul");
538
            this.name = this.$("input.rename-field");
539
            this.name_changed = false;
540
            this.init_suggested_roles();
541
            this.init_handlers();
542
        },
543

    
544
        init_suggested_roles: function() {
545
            var cont = this.roles;
546
            cont.empty();
547
            
548
            // TODO: get suggested from snf.api.conf
549
            _.each(window.SUGGESTED_ROLES, function(r){
550
                var el = $('<span class="val">{0}</span>'.format(r));
551
                el.data("value", r);
552
                cont.append(el);
553
                el.click(function() {
554
                    $(this).parent().find(".val").removeClass("selected");
555
                    $(this).toggleClass("selected");
556
                })
557
            })
558
        },
559

    
560
        init_handlers: function() {
561
            this.name.bind("keypress", _.bind(function(e) {
562
                this.name_changed = true;
563
                if (e.keyCode == 13) { this.parent.submit() };    
564
            }, this));
565

    
566
            this.name.bind("click", _.bind(function() {
567
                if (!this.name_changed) {
568
                    this.name.val("");
569
                }
570
            }, this))
571
        },
572

    
573
        show: function() {
574
            views.CreateSubmitView.__super__.show.apply(this, arguments);
575
            this.update_layout();
576
        },
577
        
578
        update_flavor_details: function() {
579
            var flavor = this.parent.get_params().flavor;
580

    
581
            function set_detail(sel, key) {
582
                var val = key;
583
                if (key == undefined) { val = flavor.get(sel) };
584
                this.$(".confirm-cont.flavor .flavor-" + sel + " .value").text(val)
585
            }
586
            
587
            set_detail("cpu");
588
            set_detail("ram", flavor.get("ram") + " MB");
589
            set_detail("disk", util.readablizeBytes(flavor.get("disk") * 1024 * 1024 * 1024));
590
        },
591

    
592
        update_image_details: function() {
593
            var image = this.parent.get_params().image;
594

    
595
            function set_detail(sel, key) {
596
                var val = key;
597
                if (key == undefined) { val = image.get(sel) };
598
                this.$(".confirm-cont.image .image-" + sel + " .value").text(val)
599
            }
600
            
601
            set_detail("description");
602
            set_detail("name");
603
            set_detail("os", image.get("OS"));
604
            set_detail("gui", image.get("GUI"));
605
            set_detail("size", util.readablizeBytes(image.get_size() * 1024 * 1024));
606
            set_detail("kernel");
607
        },
608

    
609
        update_layout: function() {
610
            var params = this.parent.get_params();
611

    
612
            if (!params.image) { return }
613
            var vm_name = "My {0} server".format(params.image.get("name"));
614
            var orig_name = vm_name;
615
            
616
            var existing = true;
617
            var j = 0;
618

    
619
            while (existing && !this.name_changed) {
620
                var existing = storage.vms.select(function(vm){return vm.get("name") == vm_name}).length
621
                if (existing) {
622
                    j++;
623
                    vm_name = orig_name + " " + j;
624
                }
625
            }
626
            if (!_(this.name.val()).trim() || !this.name_changed) {
627
                this.name.val(vm_name);
628
            }
629

    
630
            this.confirm.find("li.image .value").text(params.flavor.get("image"));
631
            this.confirm.find("li.cpu .value").text(params.flavor.get("cpu") + "x");
632
            this.confirm.find("li.mem .value").text(params.flavor.get("ram"));
633
            this.confirm.find("li.disk .value").text(params.flavor.get("disk"));
634

    
635
            if (!this.name_changed) {
636
            }
637
            
638
            var img = snf.ui.helpers.os_icon_path(params.image.get("OS"))
639
            this.name.css({backgroundImage:"url({0})".format(img)})
640

    
641
            this.update_image_details();
642
            this.update_flavor_details();
643
        },
644

    
645
        reset: function() {
646
            this.roles.find(".val").removeClass("selected");
647
            this.name_changed = false;
648
            this.update_layout();
649
        },
650

    
651
        get_meta: function() {
652
            if (this.roles.find(".selected").length == 0) {
653
                return false;
654
            }
655

    
656
            var role = $(this.roles.find(".selected").get(0)).data("value");
657
            return {'Role': role }
658
        },
659

    
660
        get: function() {
661
            var val = {'name': this.name.val() };
662
            if (this.get_meta()) {
663
                val.metadata = this.get_meta();
664
            }
665
            
666
            return val;
667
        }
668
    });
669

    
670
    views.CreateVMView = views.Overlay.extend({
671
        
672
        view_id: "create_vm_view",
673
        content_selector: "#createvm-overlay-content",
674
        css_class: 'overlay-createvm overlay-info',
675
        overlay_id: "metadata-overlay",
676

    
677
        subtitle: false,
678
        title: "Create new machine",
679

    
680
        initialize: function(options) {
681
            views.CreateVMView.__super__.initialize.apply(this);
682
            this.current_step = 1;
683

    
684
            this.password_view = new views.VMCreationPasswordView();
685

    
686
            this.steps = [];
687
            this.steps[1] = new views.CreateImageSelectView(this);
688
            this.steps[1].bind("change", _.bind(function(data) {this.trigger("image:change", data)}, this));
689

    
690
            this.steps[2] = new views.CreateFlavorSelectView(this);
691
            this.steps[3] = new views.CreateSubmitView(this);
692

    
693
            this.cancel_btn = this.$(".create-controls .cancel")
694
            this.next_btn = this.$(".create-controls .next")
695
            this.prev_btn = this.$(".create-controls .prev")
696
            this.submit_btn = this.$(".create-controls .submit")
697
            
698
            this.init_handlers();
699
            this.update_layout();
700

    
701
        },
702

    
703
        init_handlers: function() {
704
            this.next_btn.click(_.bind(function(){
705
                this.set_step(this.current_step + 1);
706
                this.update_layout();
707
            }, this))
708
            this.prev_btn.click(_.bind(function(){
709
                this.set_step(this.current_step - 1);
710
                this.update_layout();
711
            }, this))
712
            this.cancel_btn.click(_.bind(function(){
713
                this.close_all();
714
            }, this))
715
            this.submit_btn.click(_.bind(function(){
716
                this.submit();
717
            }, this))
718
        },
719

    
720
        set_step: function(st) {
721
        },
722
        
723
        validate: function(data) {
724
            if (_(data.name).trim() == "") {
725
                this.$(".form-field").addClass("error");
726
                return false;
727
            } else {
728
                return true;
729
            }
730
        },
731

    
732
        submit: function() {
733
            if (this.submiting) { return };
734
            var data = this.get_params();
735
            var meta = {};
736
            if (this.validate(data)) {
737
                this.submit_btn.addClass("in-progress");
738
                this.submiting = true;
739
                if (data.metadata) { meta = data.metadata; }
740
                storage.vms.create(data.name, data.image, data.flavor, meta, {}, _.bind(function(data){
741
                    this.close_all();
742
                    this.password_view.show(data.server.adminPass, data.server.id);
743
                    this.submiting = false;
744
                }, this));
745
            }
746
        },
747

    
748
        close_all: function() {
749
            this.hide();
750
        },
751

    
752
        reset: function() {
753
            this.current_step = 1;
754

    
755
            this.steps[1].reset();
756
            this.steps[2].reset();
757
            this.steps[3].reset();
758

    
759
            this.steps[1].show();
760
            this.steps[2].show();
761
            this.steps[3].show();
762

    
763
            this.submit_btn.removeClass("in-progress");
764
        },
765

    
766
        onShow: function() {
767
            this.reset()
768
            this.update_layout();
769
        },
770

    
771
        update_layout: function() {
772
            this.show_step(this.current_step);
773
            this.current_view.update_layout();
774
        },
775

    
776
        beforeOpen: function() {
777
            this.submiting = false;
778
            this.reset();
779
            this.current_step = 1;
780
            this.$(".steps-container").css({"margin-left":0 + "px"});
781
            this.show_step(1);
782
        },
783
        
784
        set_step: function(step) {
785
            if (step <= 1) {
786
                step = 1
787
            }
788
            if (step > this.steps.length - 1) {
789
                step = this.steps.length - 1;
790
            }
791
            this.current_step = step;
792
        },
793

    
794
        show_step: function(step) {
795
            this.current_view = this.steps[step];
796
            this.update_controls();
797

    
798
            this.steps[step].show();
799
            var width = this.el.find('.container').width();
800
            var left = (step -1) * width * -1;
801
            this.$(".steps-container").css({"margin-left": left + "px"});
802
        },
803

    
804
        update_controls: function() {
805
            var step = this.current_step;
806
            if (step == 1) {
807
                this.prev_btn.hide();
808
                this.cancel_btn.show();
809
            } else {
810
                this.prev_btn.show();
811
                this.cancel_btn.hide();
812
            }
813
            
814
            if (step == this.steps.length - 1) {
815
                this.next_btn.hide();
816
                this.submit_btn.show();
817
            } else {
818
                this.next_btn.show();
819
                this.submit_btn.hide();
820
            }
821
        },
822

    
823
        get_params: function() {
824
            return _.extend({}, this.steps[1].get(), this.steps[2].get(), this.steps[3].get());
825
        }
826
    });
827
    
828
})(this);
829