Statistics
| Branch: | Tag: | Revision:

root / snf-app / synnefo / ui / static / snf / js / ui / web / ui_networks_view.js @ 483c9197

History | View | Annotate | Download (33.4 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 || {};
12
    var views = snf.views = snf.views || {}
13

    
14
    // shortcuts
15
    var bb = root.Backbone;
16
    
17
    // logging
18
    var logger = new snf.logging.logger("SNF-VIEWS");
19
    var debug = _.bind(logger.debug, logger);
20
    
21
    
22
    views.NetworkConnectVMsOverlay = views.Overlay.extend({
23
        title: "Connect machine",
24
        overlay_id: "overlay-select-vms",
25
        content_selector: "#network-vms-select-content",
26
        css_class: "overlay-info",
27

    
28
        initialize: function() {
29
            views.NetworkConnectVMsOverlay.__super__.initialize.apply(this);
30
            this.list = this.$(".vms-list ul");
31
            this.empty_message = this.$(".empty-message");
32
        },
33
        
34
        init_handlers: function() {
35
            var self = this;
36
            this.list.find("li").click(function(){
37
                $(this).toggleClass("selected");
38
            });
39

    
40
            this.el.find(".create").click(_.bind(function() {
41
                this.submit();
42
            }, this));
43
        },
44

    
45
        reset: function() {
46
            this.list.find("li").remove();
47
        },
48

    
49
        beforeOpen: function() {
50
            this.reset();
51
            this.update_layout();
52
        },
53
        
54
        vm: function(vm) {
55
            if (vm.id) { var id = vm.id } else {var id = vm}
56
            return this.list.find(".vm-" + id);
57
        },
58

    
59
        get_selected: function() {
60
            return this.list.find(".selected").map(function() {return $(this).data('vm')})
61
        },
62

    
63
        update_layout: function() {
64
            if (this.vms.length == 0) {
65
                this.empty_message.show();
66
            } else {
67
                this.empty_message.hide();
68
            }
69

    
70
            _.each(this.vms, _.bind(function(vm){
71
                var html = '<li class="vm option options-object vm-{0}">' +
72
                           '<div class="options-object-cont">' +
73
                           '{2}' + 
74
                           '<span class="title">{1}</span>' + 
75
                           '<span class="value">{3}</span></div>' + 
76
                           '</li>';
77
                var el = $(html.format(vm.id, 
78
                                       util.truncate(vm.get("name"), 23), 
79
                                       snf.ui.helpers.vm_icon_tag(vm, "small", {'class':'os'}),
80
                                       vm.get_os()
81
                                      ))
82
                el.data({vm:vm,vm_id:vm.id})
83
                this.list.append(el);
84

    
85
                vm.bind("remove", function(){ el.remove()})
86
                vm.bind("change:name", function(i,v){el.find(".title").text(v)})
87
            }, this));
88

    
89
            this.init_handlers();
90
            this.set_selected();
91
        },
92

    
93
        set_selected: function() {
94
            _.each(this.selected, _.bind(function(el){
95
                this.vm(el).addClass("selected");
96
            }, this));
97
        },
98

    
99
        show_vms: function(network, vms, selected, callback) {
100
            this.network = network;
101
            this.reset();
102
            this.set_subtitle(network.get("name"));
103
            this.vms = vms;
104
            this.selected = selected;
105
            this.cb = callback;
106
            this.show();
107
        },
108

    
109
        submit: function() {
110
            this.cb(this.get_selected());
111
        }
112
    })
113

    
114
    views.NetworkActionsView = views.View.extend({
115
        
116
        initialize: function(view, net, el, opts) {
117
            this.parent = view
118
            this.network = net;
119
            this.el = el;
120
            
121
            this.actions = this.$(".actions");
122
            this.selected = undefined;
123

    
124
            this.destroy = this.$(".actions .destroy a");
125
            this.connect = this.$(".actions .add");
126

    
127
            this.init_handlers();
128
            this.update_layout();
129
        },
130

    
131
        init_handlers: function() {
132
            this.connect.click(_.bind(function(e){
133
                e.preventDefault();
134
            }))
135
        },
136

    
137
        update_layout: function() {
138
        }
139
    });
140

    
141
    views.NetworkCreateView = views.Overlay.extend({
142
        view_id: "network_create_view",
143
        content_selector: "#networks-create-content",
144
        css_class: 'overlay-networks-create overlay-info',
145
        overlay_id: "network-create-overlay",
146

    
147
        title: "Create new private network",
148
        subtitle: "Networks",
149

    
150
        initialize: function(options) {
151
            views.NetworkCreateView.__super__.initialize.apply(this);
152

    
153
            this.create_button = this.$("form .form-action.create");
154
            this.text = this.$(".network-create-name");
155
            this.form = this.$("form");
156
            this.init_handlers();
157
        },
158

    
159
        init_handlers: function() {
160
            this.create_button.click(_.bind(function(e){
161
                this.submit();
162
            }, this));
163

    
164
            this.form.submit(_.bind(function(e){
165
                e.preventDefault();
166
                this.submit;
167
                return false;
168
            }, this))
169

    
170
            this.text.keypress(_.bind(function(e){
171
                if (e.which == 13) {this.submit()};
172
            },this))
173
        },
174

    
175
        submit: function() {
176
            if (this.validate()) {
177
                this.create();
178
            };
179
        },
180
        
181
        validate: function() {
182
            // sanitazie
183
            var t = this.text.val();
184
            t = t.replace(/^\s+|\s+$/g,"");
185
            this.text.val(t);
186

    
187
            if (this.text.val() == "") {
188
                this.text.closest(".form-field").addClass("error");
189
                this.text.focus();
190
                return false;
191
            } else {
192
                return true;
193
            }
194
        },
195

    
196
        create: function() {
197
            this.create_button.addClass("in-progress");
198
            snf.storage.networks.create(this.text.val(), _.bind(function(){
199
                this.hide();
200
            }, this));
201
        },
202

    
203
        beforeOpen: function() {
204
            this.create_button.removeClass("in-progress")
205
            this.text.closest(".form-field").removeClass("error");
206
            this.text.val("");
207
            this.text.show();
208
            this.text.focus();
209
        },
210

    
211
        onOpen: function() {
212
            this.text.focus();
213
        }
214
    });
215

    
216
    views.NetworkVMView = views.View.extend({
217

    
218
        initialize: function(vm, parent, firewall_controls, el) {
219
            this.firewall_controls = firewall_controls || false;
220
            this.vm = vm;
221
            // parent view di
222
            this.parent = parent;
223
            // TODO make it better
224
            this.el = el || this.parent.vm(vm);
225

    
226
            this.init_layout();
227
            this.update_layout();
228

    
229
            this.disconnect = this.$(".action-disconnect");
230
            this.confirm_el = this.$(".confirm_single");
231
            this.cancel = this.$("button.no");
232
            this.confirm = this.$("button.yes");
233
            this.details = this.$(".action-details");
234
            this.vm_connect = this.$(".machine-connect");
235

    
236
            this.init_handlers();
237
            this.connect_overlay = new views.VMConnectView();
238
            
239
            this.firewall_view = undefined;
240
            if (this.firewall_controls) {
241
                this.firewall_view = new views.FirewallEditView(this.vm, this.parent.network, this);
242
            }
243

    
244
        },
245
        
246
        init_handlers: function() {
247
            if (!this.parent.network.is_public()) {
248
                this.disconnect.click(_.bind(function(e){
249
                    e.preventDefault();
250
                    this.parent.network.get("actions").add("disconnect", this.vm.id);
251
                    this.parent.network.get("actions").remove("destroy");
252
                }, this));
253
                this.cancel.click(_.bind(function(e){
254
                    this.parent.network.get("actions").remove("disconnect", this.vm.id);
255
                    e.preventDefault()
256
                }, this));
257
                this.confirm.click(_.bind(function(e){
258
                    e.preventDefault()
259
                    this.disconnect_vm();
260
                    this.confirm_el.hide();
261
                    this.disconnect.removeClass("selected");
262
                }, this));
263

    
264
                snf.ui.main.bind("view:change", _.bind(function(v) {
265
                    if (v == "networks" ){ return }
266
                    this.confirm_el.hide();
267
                    this.disconnect.removeClass("selected");
268
                }, this));
269

    
270
                this.$(".remove-icon").click(_.bind(function(){
271
                    this.parent.network.get("actions").add("disconnect", this.vm.id);
272
                    this.parent.network.get("actions").remove("destroy");
273
                }, this));
274

    
275
                this.vm_connect.click(_.bind(function() {
276
                    this.connect_overlay.show(this.vm);
277
                }, this));
278
                
279
                this.parent.network.bind("change:actions", _.bind(function(model, action){
280
                    if (this.parent.network.get("actions").contains("disconnect", this.vm.id)) {
281
                        this.confirm_disconnect();
282
                    } else {
283
                        this.cancel_disconnect();
284
                    }
285
                }, this));
286
            }
287
            
288
            var vm = this.vm;
289
            this.details.click(function(){
290
                snf.ui.main.show_vm_details(vm);
291
            });
292

    
293
        },
294

    
295
        cancel_disconnect: function() {
296
            this.confirm_el.hide();
297
            this.disconnect.removeClass("selected");
298
            this.$(".net-vm-actions a").removeClass("visible");
299
        },
300

    
301
        confirm_disconnect: function() {
302
            this.confirm_el.show();
303
            this.disconnect.addClass("selected");
304
            this.$(".net-vm-actions a").addClass("visible");
305
        },
306

    
307
        init_layout: function() {
308
            if (!this.firewall_controls) { return };
309
        },
310

    
311
        update_layout: function() {
312
            this.$(".vm-name").text(snf.util.truncate(this.vm.get("name"), 40));
313
            this.$("img.logo").attr("src", ui.helpers.vm_icon_path(this.vm, "medium"));
314

    
315
            if (this.firewall_view) {
316
                this.$(".ipv4-text").text(this.vm.get_addresses().ip4);
317
                this.$(".ipv6-text").text(this.vm.get_addresses().ip6);
318
            }
319

    
320
            if (this.firewall_view) {
321
                this.firewall_view.update_layout();
322
            }
323
        },
324

    
325
        disconnect_vm: function() {
326
            this.$("a.selected").removeClass("selected");
327
            this.parent.network.remove_vm(this.vm);
328
        },
329

    
330
        update_firewall_layout: function() {
331
        }
332

    
333

    
334
    })
335

    
336
    views.NetworkModelRenameView = views.View.extend({
337
        initialize: function(parent, network) {
338
            this.parent = parent;
339
            this.network = network;
340
            this.el = this.parent.el.find(".name-div");
341

    
342
            this.icon = this.$(".rename-network");
343
            this.save = this.$("span.save");
344
            this.cancel = this.$("span.cancel");
345
            this.buttons = this.$(".editbuttons");
346
            this.name = this.$("span.name");
347
            this.editing = false;
348
            this.init_handlers();
349
            this.update_layout();
350
        },
351

    
352
        init_handlers: function() {
353
            this.icon.click(_.bind(function(){
354
                this.editing = true;
355
                this.update_layout();
356
            }, this));
357
            this.cancel.click(_.bind(function(){
358
                this.editing = false;
359
                this.update_layout();
360
            }, this));
361
            this.save.click(_.bind(function(){
362
                this.submit();
363
            }, this))
364
        },
365
        
366
        submit: function() {
367
            var value = _(this.input.val()).trim();
368
            if (value == "") { return }
369

    
370
            this.network.rename(value, _.bind(function(){
371
                this.editing = false;
372
                this.update_layout();
373
            }, this));
374
        },
375

    
376
        create_input: function() {
377
            this.input = $('<input type="text" class="network-rename-input" />');
378
            this.input.val(this.network.get("name"));
379
            this.el.append(this.input);
380
            this.input.focus();
381
            this.input.bind("keydown", _.bind(function(ev){
382
                ev.keyCode = ev.keyCode || ev.which;
383
                if (ev.keyCode == 13) { this.submit(); };
384
                if (ev.keyCode == 27) {this.editing = false; this.update_layout()};
385
            }, this));
386
        },
387

    
388
        remove_input: function() {
389
            if (!this.input) { return }
390
            this.input.remove();
391
        },
392

    
393
        update_layout: function() {
394
            if (this.editing) {
395
                if (this.buttons.is(":visible")) { return }
396
                this.icon.hide();
397
                this.buttons.show();
398
                this.create_input();
399
                this.name.hide();
400
            } else {
401
                this.buttons.hide();
402
                this.remove_input();
403
                this.name.show();
404
                this.icon.show();
405
            }
406
        }
407
    })
408

    
409
    views.FirewallEditView = views.View.extend({
410
        initialize: function(vm, network, parent) {
411
            this.parent = parent;
412
            this.vm = vm;
413
            this.network = network;
414
            this.el = this.parent.el;
415

    
416
            views.FirewallEditView.__super__.initialize.apply(this);
417

    
418
            // elements
419
            this.toggler = this.$(".firewall-toggle");
420
            this.indicator = this.$(".machines-label span");
421
            this.progress = this.$(".network-progress-indicator");
422
            this.content = this.$(".firewall-content");
423
            this.inputs = this.$("input[type=radio]");
424
            this.labels = this.$("span.checkbox-legends, label.checkbox-legends");
425
            this.apply = this.$(".firewall-apply");
426

    
427
            this.$(".firewall-content").hide();
428
            this.$(".firewall-content input[type=radio]").attr("name", "firewall-opt-for-{0}".format(this.vm.id))
429
            var mode = this.vm.firewall_profile(this.network.id);
430
            this.$(".firewall-content input[value={0}]".format(mode)).attr("checked", true);
431

    
432
            this.init_handlers();
433
            this.update_layout();
434
        },
435
        
436
        _get_selected: function() {
437
            return this.inputs.filter(":checked");
438
        },
439

    
440
        reset_selected: function() {
441
        },
442

    
443
        submit: function() {
444
        },
445

    
446
        reset_value: function() {
447
            this.inputs.filter("[value={0}]".format(this.vm.firewall_profile(this.network.id))).attr("checked");
448
        },
449

    
450
        init_handlers: function() {
451
            this.toggler.click(_.bind(function(){
452
                cont = this.content;
453
                if (cont.is(":visible")) {
454
                    this.hide_firewall();
455
                    this.reset_value();
456
                } else {
457
                    this.show_firewall();
458
                }
459

    
460
                $(window).trigger("resize");
461
            }, this))
462
            
463
            this.apply.click(_.bind(function(){
464
                this.apply.addClass("in-progress");
465
                
466
                // make the api call
467
                this.vm.set_firewall(this.network.id, this.value(), 
468
                // complete
469
                _.bind(function() {
470
                    // complete callback
471
                    this.apply.removeClass("in-progress");
472
                }, this), 
473
                // error
474
                _.bind(function(){
475
                    this.vm.remove_pending_firewall(this.network.id, this.value());
476
                }, this));
477
                this.hide_firewall();
478
            }, this))
479

    
480
            this.inputs.change(_.bind(function(){
481
                this.update_selected();
482
            }, this))
483
            
484
            var self = this;
485
            this.$(".checkbox-legends").click(function(el) {
486
                var el = $(this);
487
                el.prev().click();
488
                self.update_selected();
489
            })
490
        },
491

    
492
        update_selected: function() {
493
            this.update_layout();
494
        },
495

    
496
        show_firewall: function() {
497
            this.content.slideDown(100, function(){$(window).trigger("resize")});
498
            this.toggler.addClass("open");
499
        },
500

    
501
        hide_firewall: function() {
502
            this.content.slideUp(100, function(){$(window).trigger("resize")});
503
            this.toggler.removeClass("open");
504
        },
505

    
506
        value: function() {
507
            return this._get_selected().val();
508
        },
509

    
510
        update_layout: function() {
511
            if (this.value() == this.vm.firewall_profile(this.network.id)) {
512
                this.apply.hide();
513
            } else {
514
                this.apply.show();
515
            }
516

    
517
            profile = this.vm.firewall_profile(this.network.id);
518
            if (this.vm.has_firewall(this.network.id)) {
519
                this.$(".firewall-toggle .label span").text("On");
520
                this.$(".firewall-toggle .label span").removeClass("firewall-off");
521
                this.$(".firewall-toggle .label span").addClass("firewall-on");
522
            } else {
523
                this.$(".firewall-toggle .label span").text("Off");
524
                this.$(".firewall-toggle .label span").removeClass("firewall-on");
525
                this.$(".firewall-toggle .label span").addClass("firewall-off");
526
            }
527
            
528
            this.$("span.checkbox-legends").removeClass("current");
529
            this.inputs.filter("[value={0}]".format(this.vm.firewall_profile(this.network.id))).next().addClass("current");
530

    
531
            var firewalling = this.vm.firewall_pending(this.network.id);
532
            var el = this.el;
533
            
534
            if (firewalling) {
535
                el.find("button").addClass("in-progress").show();
536
                el.find(".network-progress-indicator").show();
537
            } else {
538
                el.find("button").removeClass("in-progress");
539
                el.find(".network-progress-indicator").hide();
540
            }
541
        }
542
    })
543

    
544
    views.NetworkModelView = views.View.extend({
545
        
546
        firewall: false,
547

    
548
        initialize: function(network, view) {
549
            this.parent_view = view;
550
            this.network = network;
551
            this.is_public = network.is_public();
552

    
553
            this.init_vm_handlers();
554

    
555
            this.view_id = "networks_view_" + network.id;
556
            views.NetworkModelView.__super__.initialize.call(this);
557

    
558
            this.vm_views = {};
559

    
560
            this.el = this.create_el();
561

    
562
            // element helpers
563
            this.vms_list = this.$(".machines-list");
564
            this.vms_list_toggler = this.$(".list-toggle");
565
            
566
            this.init_handlers();
567
            this.update_vms();
568
            this.update_layout();
569

    
570
            this.hide_vm_list();
571
            this.vms_list.hide();
572

    
573
            this.rename_view = undefined;
574
            if (!this.network.is_public()) {
575
                this.rename_view = new views.NetworkModelRenameView(this, network);
576
            }
577
        },
578

    
579
        show_vm_list: function() {
580
            if (this.vms_empty()) { return }
581
            this.vms_list_toggler.addClass("open");
582
            this.vms_list.slideDown(function(){
583
                $(window).trigger("resize");
584
            }).closest(".network").addClass("expand");
585
            this.$(".empty-network-slot").show();
586
            this.vms_visible = true;
587
        },
588

    
589
        hide_vm_list: function() {
590
            this.vms_list_toggler.removeClass("open");
591
            this.vms_list.slideUp(function(){
592
                $(window).trigger("resize");
593
            }).closest(".network").removeClass("expand");
594
            this.$(".empty-network-slot").hide();
595
            this.vms_visible = false;
596
        },
597
        
598
        // fix left border position
599
        fix_left_border: function() {
600
            if (!this.vms_visible) { return };
601
            
602
            var imgheight = 2783;
603
            var opened_vm_height = 133 + 20;
604
            var closed_vm_height = 61 + 20;
605
            var additional_height = 25;
606

    
607
            if (!this.is_public) { 
608
                imgheight = 2700;
609
                additional_height = 65;
610
            };
611
            
612
            var contents = this.$(".network-contents");
613
            var last_vm = this.$(".network-machine:last .cont-toggler.open").length;
614
            var last_vm_height = closed_vm_height;
615
            if (last_vm > 0){
616
                last_vm_height = opened_vm_height;
617
            }
618

    
619
            var vms_opened = this.$(".network-machine .cont-toggler.open").length;
620
            var vms_closed = this.$(".network-machine").length - vms_opened;
621

    
622
            var calc_height = (vms_opened * opened_vm_height) + (vms_closed * closed_vm_height) + additional_height; 
623
            var bgpos = imgheight - calc_height + last_vm_height - 30;
624
            this.$(".network-contents").css({'background-position':'33px ' + (-bgpos) + 'px'});
625
        },
626

    
627

    
628
        init_handlers: function() {
629
            var self = this;
630

    
631
            this.vms_list_toggler.click(_.bind(function(){
632
                if (this.vms_list.is(":visible")) {
633
                    this.hide_vm_list();
634
                } else {
635
                    this.fix_left_border();
636
                    this.show_vm_list();
637
                }
638

    
639
                this.check_empty_vms();
640
            }, this));
641

    
642
            this.$(".action-add").click(_.bind(function(e){
643
                e.preventDefault();
644
                this.network.get("actions").remove("destroy");
645
                this.show_connect_vms();
646
            }, this))
647

    
648
            this.$(".add-icon").click(_.bind(function(e){
649
                e.preventDefault();
650
                this.show_connect_vms();
651
            }, this))
652

    
653
            this.$(".net-actions .destroy a").click(_.bind(function(e){
654
                e.preventDefault();
655
                self.network.get("actions").add("destroy");
656
                self.network.get("actions").remove_all("disconnect");
657
            }, this));
658

    
659
            self.network.bind("change:actions", _.bind(function(net, action) {
660
                if (this.network.get("actions").contains("destroy")) {
661
                    this.confirm_destroy();
662
                } else {
663
                    this.cancel_destroy();
664
                }
665
            }, this))
666

    
667
            this.$(".net-actions button.no").click(function(e){
668
                e.preventDefault();
669
                self.network.get("actions").remove("destroy");
670
            });
671

    
672
            this.$(".net-actions button.yes").click(function(e){
673
                e.preventDefault();
674
                var el = $(this);
675
                el.closest(".confirm_single").hide();
676
                el.parent().parent().find(".selected").removeClass("selected");
677
                self.network.call('destroy', {}, function(){
678
                    el.closest(".confirm_single").removeClass("in-progress");
679
                });
680
                el.closest(".confirm_single").addClass("in-progress");
681
            });
682

    
683
            snf.ui.main.bind("view:change", _.bind(function(v) {
684
                if (v == "networks" ){ return }
685
                this.$(".confirm_single").hide();
686
                this.$("a.selected").removeClass("selected");
687
            }, this));
688

    
689
            $(window).bind("resize", _.bind(function() {
690
                this.fix_left_border();
691
            }, this));
692
        },
693

    
694
        show_connect_vms: function() {
695
            this.$(".confirm_single").hide();
696
            this.$("a.selected").removeClass("selected");
697
            var vms = this.network.get_connectable_vms();
698
            this.parent_view.connect_machines_view.show_vms(this.network,
699
                                                            vms, [], 
700
                                                            _.bind(this.connect_vms, this));
701
        },
702

    
703
        cancel_destroy: function() {
704
            this.$(".net-actions .destroy .confirm_single").hide();
705
            this.$(".net-actions .destroy a.selected").removeClass("selected");
706
            this.$(".net-actions a").removeClass("visible");
707
        },
708

    
709
        confirm_destroy: function() {
710
            this.$(".destroy .confirm_single").show();
711
            this.$(".destroy a").addClass("selected");
712
            this.$(".net-actions a").addClass("visible");
713
        },
714

    
715
        connect_vms: function(vms) {
716
            _.each(vms, _.bind(function(vm){
717
                this.network.add_vm(vm);
718
            }, this));
719

    
720
            this.parent_view.connect_machines_view.hide();
721
        },
722

    
723
        create_el: function() {
724
            var el = this.$(this.tpl).clone().attr("id", "network-" + this.network.id)
725
            return el;
726
        },
727

    
728
        init_vm_handlers: function() {
729
            storage.vms.bind("add", _.bind(this.vm_added_handler, this, "add"));
730
            storage.vms.bind("network:connect", _.bind(this.vm_changed_handler, this, "connect"));
731
            storage.vms.bind("change", _.bind(this.vm_changed_handler, this, "change"));
732
            storage.vms.bind("reset", _.bind(this.vm_changed_handler, this, "reset"));
733
            storage.vms.bind("remove", _.bind(this.vm_removed_handler, this, "remove"));
734
            storage.vms.bind("network:disconnect", _.bind(this.vm_removed_handler, this, "disconnect"));
735
        },
736

    
737
        get_vm_id: function(vm) {
738
            return this.vm_id_tpl.format(this.network.id, vm.id)
739
        },
740

    
741
        vm: function(vm) {
742
            return $(this.get_vm_id(vm))
743
        },
744

    
745
        vm_added_handler: function(action, vm) {
746
            if (!this.network.contains_vm(vm)) { return }
747
            this.add_or_update_vm(vm);
748
            this.update_layout();
749
            this.fix_left_border();
750
        },
751

    
752
        vm_changed_handler: function(action, vms, model, changes) {
753
            var vms = vms || [];
754
            // reset or change
755
            if (action == "reset") {
756
                vms = vms;
757
            } else {
758
                if (!_.isArray(vms)) {
759
                    vms = [vms]
760
                }
761
            }
762

    
763
            if (action == "connect") {
764
                vms = [model];
765
            }
766
            
767
            _.each(vms, _.bind(function(vm) {
768
                if (!this.network.contains_vm(vm)) { return }
769
                this.add_or_update_vm(vm);
770
            }, this));
771
            this.update_layout();
772
        },
773

    
774
        vm_removed_handler: function(action, vm, model) {
775
            if (action == "disconnect") { vm = model };
776
            this.fix_left_border();
777
            this.remove_vm(vm);
778
            this.update_layout();
779
        },
780

    
781
        remove_vm: function(vm) {
782
            if (this.vm(vm).length) {
783
                this.vm(vm).remove();
784
                try {
785
                    delete this.vm_views[vm.id]
786
                } catch (err) {
787
                }
788
            }
789
        },
790
        
791
        create_vm: function(vm) {
792
            vm_el = $(this.vm_tpl).clone().attr({id:this.get_vm_id(vm).replace("#","")});
793
            this.vms_list.append(vm_el);
794
            this.post_vm_add(vm);
795

    
796
            if (!this.vm_views[vm.id]) {
797
                vm_view = this.vm_views[vm.id] = new views.NetworkVMView(vm, this, this.firewall, vm_el);
798
            }
799
        },
800

    
801
        add_or_update_vm: function(vm) {
802
            if (!vm || !this.network.contains_vm(vm)) { return };
803

    
804
            var vm_el = this.vm(vm);
805
            var vm_view = this.vm_views[vm.id];
806

    
807
            if (vm_el.length == 0) {
808
                this.create_vm(vm);
809
            }
810
            
811
            if (vm_view) { vm_view.update_layout() };
812

    
813
            this.update_vm(vm);
814
            this.post_vm_update(vm);
815
        },
816
        update_vm: function(vm){},
817
        post_vm_add: function(vm){},
818
        post_vm_update: function(vm){},
819

    
820
        update_vms: function(vms) {
821
            if (!vms) { vms = this.network.vms.list() };
822
            _.each(vms, _.bind(function(vm){
823
                this.add_or_update_vm(vm);
824
            }, this));
825
        },
826

    
827
        check_empty_vms: function() {
828
            if (this.network.vms.get().length == 0) {
829
                this.hide_vm_list();
830
            }
831
        },
832

    
833
        vms_empty: function() {
834
            return this.network.vms.get().length == 0;
835
        },
836

    
837
        remove: function() {
838
            $(this.el).remove();
839
        },
840

    
841
        update_layout: function() {
842
            // has vms ???
843
            this.check_empty_vms(this.network.vms.list());
844

    
845
            // is expanded ???
846
            //
847
            // whats the network status ???
848
            //
849
            this.$(".machines-count").text(this.network.vms.get().length);
850

    
851
            var net_name = this.network.get("name");
852
            if (net_name == "public") { net_name = "Internet" }
853
            this.$(".name-div span.name").text(net_name);
854

    
855
            if (this.rename_view) {
856
                this.rename_view.update_layout();
857
            }
858
            
859
            this.$(".net-status").text(this.network.state_message());
860

    
861
            if (this.network.in_progress())  {
862
                this.$(".spinner").show();
863
                this.$(".network-indicator").addClass("in-progress");
864
            } else {
865
                this.$(".spinner").hide();
866
                this.$(".network-indicator").removeClass("in-progress");
867
            }
868

    
869
            if (this.network.get("state") == "DESTROY") {
870
                this.$(".spinner").show();
871
                this.$(".state").addClass("destroying-state");
872
            }
873
        }
874
    })
875

    
876
    views.PublicNetworkView = views.NetworkModelView.extend({
877
        firewall: true,
878
        tpl: "#public-template",
879
        vm_tpl: "#public-machine-template",
880
        vm_id_tpl: "#network-{0}-vm-{1}",
881

    
882
        update_vm: function(vm) {
883
        }
884
    })
885
    
886
    views.PrivateNetworkView = views.NetworkModelView.extend({
887
        tpl: "#private-template",
888
        vm_tpl: "#private-machine-template",
889
        vm_id_tpl: "#network-{0}-vm-{1}"
890
    })
891

    
892
    views.NetworksView = views.View.extend({
893
        
894
        view_id: "networks",
895
        pane: "#networks-pane",
896
        el: "#networks-pane",
897

    
898
        initialize: function() {
899
            // elements shortcuts
900
            this.create_cont = this.$("#networks-createcontainer");
901
            this.container = this.$("#networks-container");
902
            this.public_list = this.$(".public-networks");
903
            this.private_list = this.$(".private-networks");
904

    
905
            views.NetworksView.__super__.initialize.call(this);
906
            this.init_handlers();
907
            this.network_views = {};
908
            this.update_networks(storage.networks.models);
909

    
910
            this.create_view = new views.NetworkCreateView();
911
            this.connect_machines_view = new views.NetworkConnectVMsOverlay();
912

    
913
        },
914
        
915
        exists: function(net) {
916
            return this.network_views[net.id];
917
        },
918

    
919
        add_or_update: function(net) {
920
            var nv = this.exists(net);
921
            if (!nv) {
922
                nv = this.create_network_view(net)
923
                this.network_views[net.id] = nv;
924
                
925
                if (net.is_public()) {
926
                    this.public_list.append(nv.el);
927
                    this.public_list.show();
928
                } else {
929
                    this.private_list.append(nv.el);
930
                    this.private_list.show();
931
                }
932
            }
933

    
934
            // update vms
935
            // for cases where network servers list
936
            // get updated after vm addition and
937
            // vm_added_handler fails to append the
938
            // vm to the list
939
            nv.update_vms();
940
            nv.update_layout();
941
        },
942
        
943
        create_network_view: function(net) {
944
            if (net.is_public()) {
945
                return new views.PublicNetworkView(net, this);
946
            }
947
            return new views.PrivateNetworkView(net, this);
948
        },
949
        
950
        init_handlers: function() {
951
            storage.networks.bind("add", _.bind(this.network_added_handler, this, "add"));
952
            storage.networks.bind("change", _.bind(this.network_changed_handler, this, "change"));
953
            storage.networks.bind("reset", _.bind(this.network_changed_handler, this, "reset"));
954
            storage.networks.bind("remove", _.bind(this.network_removed_handler, this, "remove"));
955

    
956
            this.$("#networkscreate").click(_.bind(function(e){
957
                e.preventDefault();
958
                this.create_view.show();
959
            }, this));
960
            
961
        },
962

    
963
        update_networks: function(nets) {
964
            _.each(nets, _.bind(function(net){
965
                if (net.get("status") == "DELETED") { return }
966
                view = this.add_or_update(net);
967
            }, this));
968
        },
969

    
970
        show: function() {
971
            this.container.show();
972
            $(this.el).show();
973
        },
974

    
975
        network_added_handler: function(type, net) {
976
            this.update_networks([net]);
977
        },
978

    
979
        network_changed_handler: function(type, models) {
980
            var nets = [];
981
            if (type == "change") {
982
                nets = [models]
983
            } else {
984
                nets = models.models;
985
            }
986

    
987
            this.update_networks(nets)
988
        },
989

    
990
        network_removed_handler: function(type, net) {
991
            this.remove_net(net)
992
            if (this.private_list.find(".network").length == 0) {
993
                this.private_list.hide();
994
            }
995
        },
996

    
997
        network_added: function(net) {
998
            return this.network_views[net.id];
999
        },
1000

    
1001
        get_network_view: function(net) {
1002
            return this.network_views[net.id];
1003
        },
1004

    
1005
        remove_net: function(net) {
1006
            if (this.network_added(net)) {
1007
                var view = this.get_network_view(net);
1008
                view.remove();
1009
                delete this.network_views[net.id];
1010
            }
1011
        },
1012

    
1013
        __update_layout: function() {
1014
        }
1015
    });
1016

    
1017
})(this);