Statistics
| Branch: | Tag: | Revision:

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