Statistics
| Branch: | Tag: | Revision:

root / ui / static / snf / js / ui / web / ui_networks_view.js @ 8d08f18a

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
202
        beforeOpen: function() {
203
            this.create_button.removeClass("in-progress")
204
            this.text.val("");
205
            this.text.show();
206
            this.text.focus();
207
        },
208

    
209
        onOpen: function() {
210
            this.text.focus();
211
        }
212
    });
213

    
214
    views.NetworkVMView = views.View.extend({
215

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

    
224
            this.init_layout();
225
            this.update_layout();
226

    
227
            this.disconnect = this.$(".action-disconnect");
228
            this.confirm_el = this.$(".confirm_single");
229
            this.cancel = this.$("button.no");
230
            this.confirm = this.$("button.yes");
231
            this.details = this.$(".action-details");
232

    
233
            this.init_handlers();
234
            
235
            this.firewall_view = undefined;
236
            if (this.firewall_controls) {
237
                this.firewall_view = new views.FirewallEditView(this.vm, this.parent.network, this);
238
            }
239

    
240
        },
241
        
242
        init_handlers: function() {
243
            if (!this.parent.network.is_public()) {
244
                this.disconnect.click(_.bind(function(e){
245
                    e.preventDefault();
246
                    this.confirm_disconnect();
247
                }, this));
248
                this.cancel.click(_.bind(function(e){
249
                    e.preventDefault()
250
                    this.confirm_el.hide();
251
                    this.disconnect.removeClass("selected");
252
                }, this));
253
                this.confirm.click(_.bind(function(e){
254
                    e.preventDefault()
255
                    this.disconnect_vm();
256
                    this.confirm_el.hide();
257
                    this.disconnect.removeClass("selected");
258
                }, this));
259

    
260
                snf.ui.main.bind("view:change", _.bind(function(v) {
261
                    if (v == "networks" ){ return }
262
                    this.confirm_el.hide();
263
                    this.disconnect.removeClass("selected");
264
                }, this));
265

    
266
                this.$(".remove-icon").click(_.bind(function(){
267
                    this.confirm_disconnect();
268
                }, this))
269
            }
270
            
271
            var vm = this.vm;
272
            this.details.click(function(){
273
                snf.ui.main.show_vm_details(vm);
274
            })
275

    
276
        },
277

    
278
        confirm_disconnect: function() {
279
            this.confirm_el.show();
280
            this.disconnect.addClass("selected");
281
        },
282

    
283
        init_layout: function() {
284
            if (!this.firewall_controls) { return };
285
        },
286

    
287
        update_layout: function() {
288
            this.$(".vm-name").text(snf.util.truncate(this.vm.get("name"), 40));
289
            this.$("img.logo").attr("src", ui.helpers.vm_icon_path(this.vm, "medium"));
290

    
291
            if (this.firewall_view) {
292
                this.$(".ipv4-text").text(this.vm.get_addresses().ip4);
293
                this.$(".ipv6-text").text(this.vm.get_addresses().ip6);
294
            }
295

    
296
            if (this.firewall_view) {
297
                this.firewall_view.update_layout();
298
            }
299
        },
300

    
301
        disconnect_vm: function() {
302
            this.$("a.selected").removeClass("selected");
303
            this.parent.network.remove_vm(this.vm);
304
        },
305

    
306
        update_firewall_layout: function() {
307
        }
308

    
309

    
310
    })
311

    
312
    views.NetworkModelRenameView = views.View.extend({
313
        initialize: function(parent, network) {
314
            this.parent = parent;
315
            this.network = network;
316
            this.el = this.parent.el.find(".name-div");
317

    
318
            this.icon = this.$(".rename-network");
319
            this.save = this.$("span.save");
320
            this.cancel = this.$("span.cancel");
321
            this.buttons = this.$(".editbuttons");
322
            this.name = this.$("span.name");
323
            this.editing = false;
324
            this.init_handlers();
325
            this.update_layout();
326
        },
327

    
328
        init_handlers: function() {
329
            this.icon.click(_.bind(function(){
330
                this.editing = true;
331
                this.update_layout();
332
            }, this));
333
            this.cancel.click(_.bind(function(){
334
                this.editing = false;
335
                this.update_layout();
336
            }, this));
337
            this.save.click(_.bind(function(){
338
                this.submit();
339
            }, this))
340
        },
341
        
342
        submit: function() {
343
            var value = _(this.input.val()).trim();
344
            if (value == "") { return }
345

    
346
            this.network.rename(value, _.bind(function(){
347
                this.editing = false;
348
                this.update_layout();
349
            }, this));
350
        },
351

    
352
        create_input: function() {
353
            this.input = $('<input type="text" class="network-rename-input" />');
354
            this.input.val(this.network.get("name"));
355
            this.el.append(this.input);
356
            this.input.focus();
357
            this.input.bind("keypress", _.bind(function(ev){
358
                if (ev.which == 13) {
359
                    this.submit();
360
                }
361
                if (ev.keyCode == 17) {this.editing = false; this.update_layout()};
362
            }, this));
363
        },
364

    
365
        remove_input: function() {
366
            if (!this.input) { return }
367
            this.input.remove();
368
        },
369

    
370
        update_layout: function() {
371
            if (this.editing) {
372
                if (this.buttons.is(":visible")) { return }
373
                this.icon.hide();
374
                this.buttons.show();
375
                this.create_input();
376
                this.name.hide();
377
            } else {
378
                this.buttons.hide();
379
                this.remove_input();
380
                this.name.show();
381
                this.icon.show();
382
            }
383
        }
384
    })
385

    
386
    views.FirewallEditView = views.View.extend({
387
        initialize: function(vm, network, parent) {
388
            this.parent = parent;
389
            this.vm = vm;
390
            this.network = network;
391
            this.el = this.parent.el;
392

    
393
            views.FirewallEditView.__super__.initialize.apply(this);
394

    
395
            // elements
396
            this.toggler = this.$(".firewall-toggle");
397
            this.indicator = this.$(".machines-label span");
398
            this.progress = this.$(".network-progress-indicator");
399
            this.content = this.$(".firewall-content");
400
            this.inputs = this.$("input[type=radio]");
401
            this.labels = this.$("span.checkbox-legends, label.checkbox-legends");
402
            this.apply = this.$(".firewall-apply");
403

    
404
            this.$(".firewall-content").hide();
405
            this.$(".firewall-content input[type=radio]").attr("name", "firewall-opt-for-{0}".format(this.vm.id))
406
            var mode = this.vm.firewall_profile(this.network.id);
407
            this.$(".firewall-content input[value={0}]".format(mode)).attr("checked", true);
408

    
409
            this.init_handlers();
410
            this.update_layout();
411
        },
412
        
413
        _get_selected: function() {
414
            return this.inputs.filter(":checked");
415
        },
416

    
417
        reset_selected: function() {
418
        },
419

    
420
        submit: function() {
421
        },
422

    
423
        reset_value: function() {
424
            this.inputs.filter("[value={0}]".format(this.vm.firewall_profile(this.network.id))).attr("checked");
425
        },
426

    
427
        init_handlers: function() {
428
            this.toggler.click(_.bind(function(){
429
                cont = this.content;
430
                if (cont.is(":visible")) {
431
                    this.hide_firewall();
432
                    this.reset_value();
433
                } else {
434
                    this.show_firewall();
435
                }
436

    
437
                $(window).trigger("resize");
438
            }, this))
439

    
440
            this.apply.click(_.bind(function(){
441
                this.apply.addClass("in-progress");
442
                this.vm.set_firewall(this.network.id, this.value(), _.bind(function() {
443
                }, this));
444
                this.hide_firewall();
445
            }, this))
446

    
447
            this.inputs.change(_.bind(function(){
448
                this.update_selected();
449
            }, this))
450
            
451
            var self = this;
452
            this.$(".checkbox-legends").click(function(el) {
453
                var el = $(this);
454
                el.prev().click();
455
                self.update_selected();
456
            })
457
        },
458

    
459
        update_selected: function() {
460
            this.update_layout();
461
        },
462

    
463
        show_firewall: function() {
464
            this.content.slideDown(100, function(){$(window).trigger("resize")});
465
            this.toggler.addClass("open");
466
        },
467

    
468
        hide_firewall: function() {
469
            this.content.slideUp(100, function(){$(window).trigger("resize")});
470
            this.toggler.removeClass("open");
471
        },
472

    
473
        value: function() {
474
            return this._get_selected().val();
475
        },
476

    
477
        update_layout: function() {
478
            if (this.value() == this.vm.firewall_profile(this.network.id)) {
479
                this.apply.hide();
480
            } else {
481
                this.apply.show();
482
            }
483

    
484
            profile = this.vm.firewall_profile(this.network.id);
485
            if (this.vm.has_firewall(this.network.id)) {
486
                this.$(".firewall-toggle .label span").text("On");
487
                this.$(".firewall-toggle .label span").removeClass("firewall-off");
488
                this.$(".firewall-toggle .label span").addClass("firewall-on");
489
            } else {
490
                this.$(".firewall-toggle .label span").text("Off");
491
                this.$(".firewall-toggle .label span").removeClass("firewall-on");
492
                this.$(".firewall-toggle .label span").addClass("firewall-off");
493
            }
494
            
495
            this.$("span.checkbox-legends").removeClass("current");
496
            this.inputs.filter("[value={0}]".format(this.vm.firewall_profile(this.network.id))).next().addClass("current");
497

    
498
            var firewalling = this.vm.firewall_pending(this.network.id);
499
            var el = this.el;
500
            
501
            if (firewalling) {
502
                el.find("button").addClass("in-progress").show();
503
                el.find(".network-progress-indicator").show();
504
            } else {
505
                el.find("button").removeClass("in-progress");
506
                el.find(".network-progress-indicator").hide();
507
            }
508
        }
509
    })
510

    
511
    views.NetworkModelView = views.View.extend({
512
        
513
        firewall: false,
514

    
515
        initialize: function(network, view) {
516
            this.parent_view = view;
517
            this.network = network;
518
            this.init_vm_handlers();
519

    
520
            this.id = "networks_view_" + network.id;
521
            views.NetworkModelView.__super__.initialize.call(this);
522

    
523
            this.vm_views = {};
524

    
525
            this.el = this.create_el();
526

    
527
            // element helpers
528
            this.vms_list = this.$(".machines-list");
529
            this.vms_list_toggler = this.$(".list-toggle");
530
            
531
            this.init_handlers();
532
            this.update_vms();
533
            this.update_layout();
534

    
535
            this.hide_vm_list();
536
            this.vms_list.hide();
537

    
538
            this.rename_view = undefined;
539
            if (!this.network.is_public()) {
540
                this.rename_view = new views.NetworkModelRenameView(this, network);
541
            }
542
        },
543

    
544
        show_vm_list: function() {
545
            if (this.vms_empty()) { return }
546
            this.vms_list_toggler.addClass("open");
547
            this.vms_list.slideDown(function(){
548
                $(window).trigger("resize");
549
            }).closest(".network").addClass("expand");
550
            this.$(".empty-network-slot").show();
551
        },
552

    
553
        hide_vm_list: function() {
554
            this.vms_list_toggler.removeClass("open");
555
            this.vms_list.slideUp(function(){
556
                $(window).trigger("resize");
557
            }).closest(".network").removeClass("expand");
558
            this.$(".empty-network-slot").hide();
559
        },
560

    
561
        init_handlers: function() {
562
            var self = this;
563

    
564
            this.vms_list_toggler.click(_.bind(function(){
565
                if (this.vms_list.is(":visible")) {
566
                    this.hide_vm_list();
567
                } else {
568
                    this.show_vm_list();
569
                }
570

    
571
                this.check_empty_vms();
572
            }, this));
573

    
574
            this.$(".action-add").click(_.bind(function(e){
575
                e.preventDefault();
576
                this.show_connect_vms();
577
            }, this))
578

    
579
            this.$(".add-icon").click(_.bind(function(e){
580
                e.preventDefault();
581
                this.show_connect_vms();
582
            }, this))
583

    
584
            this.$(".net-actions .destroy a").click(_.bind(function(e){
585
                e.preventDefault();
586
                this.confirm_destroy();
587
            }, this));
588

    
589
            this.$(".net-actions button.no").click(function(e){
590
                e.preventDefault();
591
                var el = $(this);
592
                el.closest(".confirm_single").hide();
593
                el.parent().parent().find("a.selected").removeClass("selected");
594
            });
595

    
596
            this.$(".net-actions button.yes").click(function(e){
597
                e.preventDefault();
598
                var el = $(this);
599
                el.closest(".confirm_single").hide();
600
                el.parent().parent().find(".selected").removeClass("selected");
601
                self.network.remove(function(){
602
                    el.closest(".confirm_single").removeClass("in-progress");
603
                });
604
                el.closest(".confirm_single").addClass("in-progress");
605
            });
606

    
607
            snf.ui.main.bind("view:change", _.bind(function(v) {
608
                if (v == "networks" ){ return }
609
                this.$(".confirm_single").hide();
610
                this.$("a.selected").removeClass("selected");
611
            }, this));
612
        },
613

    
614
        show_connect_vms: function() {
615
            this.$(".confirm_single").hide();
616
            this.$("a.selected").removeClass("selected");
617
            var vms = this.network.get_connectable_vms();
618
            this.parent_view.connect_machines_view.show_vms(this.network,
619
                                                            vms, [], 
620
                                                            _.bind(this.connect_vms, this));
621
        },
622

    
623
        confirm_destroy: function() {
624
            this.$(".destroy .confirm_single").show();
625
            this.$(".destroy a").addClass("selected");
626
        },
627

    
628
        connect_vms: function(vms) {
629
            _.each(vms, _.bind(function(vm){
630
                this.network.add_vm(vm);
631
            }, this));
632

    
633
            this.parent_view.connect_machines_view.hide();
634
        },
635

    
636
        create_el: function() {
637
            var el = this.$(this.tpl).clone().attr("id", "network-" + this.network.id)
638
            return el;
639
        },
640

    
641
        init_vm_handlers: function() {
642
            storage.vms.bind("add", _.bind(this.vm_added_handler, this, "add"));
643
            storage.vms.bind("network:connect", _.bind(this.vm_changed_handler, this, "connect"));
644
            storage.vms.bind("change", _.bind(this.vm_changed_handler, this, "change"));
645
            storage.vms.bind("reset", _.bind(this.vm_changed_handler, this, "reset"));
646
            storage.vms.bind("remove", _.bind(this.vm_removed_handler, this, "remove"));
647
            storage.vms.bind("network:disconnect", _.bind(this.vm_removed_handler, this, "disconnect"));
648
        },
649

    
650
        get_vm_id: function(vm) {
651
            return this.vm_id_tpl.format(this.network.id, vm.id)
652
        },
653

    
654
        vm: function(vm) {
655
            return $(this.get_vm_id(vm))
656
        },
657

    
658
        vm_added_handler: function(action, vm) {
659
            if (!this.network.contains_vm(vm)) { return }
660
            this.add_or_update_vm(vm);
661
            this.update_layout();
662
        },
663

    
664
        vm_changed_handler: function(action, vms, model, changes) {
665
            var vms = vms || [];
666
            // reset or change
667
            if (action == "reset") {
668
                vms = vms;
669
            } else {
670
                if (!_.isArray(vms)) {
671
                    vms = [vms]
672
                }
673
            }
674

    
675
            if (action == "connect") {
676
                vms = [model];
677
            }
678
            
679
            _.each(vms, _.bind(function(vm) {
680
                if (!this.network.contains_vm(vm)) { return }
681
                this.add_or_update_vm(vm);
682
            }, this));
683
            this.update_layout();
684
        },
685

    
686
        vm_removed_handler: function(action, vm, model) {
687
            if (action == "disconnect") { vm = model };
688
            this.remove_vm(vm);
689
            this.update_layout();
690
        },
691

    
692
        remove_vm: function(vm) {
693
            if (this.vm(vm).length) {
694
                this.vm(vm).remove();
695
                try {
696
                    delete this.vm_views[vm.id]
697
                } catch (err) {
698
                }
699
            }
700
        },
701

    
702
        add_or_update_vm: function(vm) {
703
            if (!vm || !this.network.contains_vm(vm)) { return };
704

    
705
            var vm_el = this.vm(vm);
706
            var vm_view = this.vm_views[vm.id];
707

    
708
            if (vm_el.length == 0) {
709
                vm_el = $(this.vm_tpl).clone().attr({id:this.get_vm_id(vm).replace("#","")});
710
                this.vms_list.append(vm_el);
711
                this.post_vm_add(vm);
712

    
713
                if (!this.vm_views[vm.id]) {
714
                    vm_view = this.vm_views[vm.id] = new views.NetworkVMView(vm, this, this.firewall, vm_el);
715
                }
716
            }
717
            
718
            if (vm_view) { vm_view.update_layout() };
719

    
720
            this.update_vm(vm);
721
            this.post_vm_update(vm);
722
        },
723
        update_vm: function(vm){},
724
        post_vm_add: function(vm){},
725
        post_vm_update: function(vm){},
726

    
727
        update_vms: function(vms) {
728
            if (!vms) { vms = this.network.vms.list() };
729
            _.each(vms, _.bind(function(vm){
730
                this.add_or_update_vm(vm);
731
            }, this));
732
        },
733

    
734
        check_empty_vms: function() {
735
            if (this.network.vms.get().length == 0) {
736
                this.hide_vm_list();
737
            }
738
        },
739

    
740
        vms_empty: function() {
741
            return this.network.vms.get().length == 0;
742
        },
743

    
744
        remove: function() {
745
            $(this.el).remove();
746
        },
747

    
748
        update_layout: function() {
749
            // has vms ???
750
            this.check_empty_vms(this.network.vms.list());
751

    
752
            // is expanded ???
753
            //
754
            // whats the network status ???
755
            //
756
            this.$(".machines-count").text(this.network.vms.get().length);
757

    
758
            var net_name = this.network.get("name");
759
            if (net_name == "public") { net_name = "Internet" }
760
            this.$(".name-div span.name").text(net_name);
761

    
762
            if (this.rename_view) {
763
                this.rename_view.update_layout();
764
            }
765
            
766
            this.$(".net-status").text(this.network.state_message());
767

    
768
            if (this.network.in_progress())  {
769
                this.$(".spinner").show();
770
                this.$(".network-indicator").addClass("in-progress");
771
            } else {
772
                this.$(".spinner").hide();
773
                this.$(".network-indicator").removeClass("in-progress");
774
            }
775
        }
776
    })
777

    
778
    views.PublicNetworkView = views.NetworkModelView.extend({
779
        firewall: true,
780
        tpl: "#public-template",
781
        vm_tpl: "#public-machine-template",
782
        vm_id_tpl: "#network-{0}-vm-{1}",
783

    
784
        update_vm: function(vm) {
785
        }
786
    })
787
    
788
    views.PrivateNetworkView = views.NetworkModelView.extend({
789
        tpl: "#private-template",
790
        vm_tpl: "#private-machine-template",
791
        vm_id_tpl: "#network-{0}-vm-{1}"
792
    })
793

    
794
    views.NetworksView = views.View.extend({
795
        
796
        view_id: "networks",
797
        pane: "#networks-pane",
798
        el: "#networks-pane",
799

    
800
        initialize: function() {
801
            // elements shortcuts
802
            this.create_cont = this.$("#networks-createcontainer");
803
            this.container = this.$("#networks-container");
804
            this.public_list = this.$(".public-networks");
805
            this.private_list = this.$(".private-networks");
806

    
807
            views.NetworksView.__super__.initialize.call(this);
808
            this.init_handlers();
809
            this.network_views = {};
810
            this.update_networks(storage.networks.models);
811

    
812
            this.create_view = new views.NetworkCreateView();
813
            this.connect_machines_view = new views.NetworkConnectVMsOverlay();
814
        },
815
        
816
        exists: function(net) {
817
            return this.network_views[net.id];
818
        },
819

    
820
        add_or_update: function(net) {
821
            var nv = this.exists(net);
822
            if (!nv) {
823
                nv = this.create_network_view(net)
824
                this.network_views[net.id] = nv;
825
                
826
                if (net.is_public()) {
827
                    this.public_list.append(nv.el);
828
                    this.public_list.show();
829
                } else {
830
                    this.private_list.append(nv.el);
831
                    this.private_list.show();
832
                }
833
            }
834

    
835
            // update vms
836
            // for cases where network servers list
837
            // get updated after vm addition and
838
            // vm_added_handler fails to append the
839
            // vm to the list
840
            nv.update_vms();
841
            nv.update_layout();
842
        },
843
        
844
        create_network_view: function(net) {
845
            if (net.is_public()) {
846
                return new views.PublicNetworkView(net, this);
847
            }
848
            return new views.PrivateNetworkView(net, this);
849
        },
850
        
851
        // fix left border position
852
        fix_left_border: function() {
853
            var vms = this.$(".network-machine:not(:last-child)");
854
            var opened = vms.find(".firewall-content:visible").length;
855
            var bgpos = -2584 + (opened * 72);
856
            this.$(".network-contents").css({'background-position-y':bgpos + 'px'});
857
        },
858

    
859
        init_handlers: function() {
860
            storage.networks.bind("add", _.bind(this.network_added_handler, this, "add"));
861
            storage.networks.bind("change", _.bind(this.network_changed_handler, this, "change"));
862
            storage.networks.bind("reset", _.bind(this.network_changed_handler, this, "reset"));
863
            storage.networks.bind("remove", _.bind(this.network_removed_handler, this, "remove"));
864

    
865
            this.$("#networkscreate").click(_.bind(function(e){
866
                e.preventDefault();
867
                this.create_view.show();
868
            }, this));
869
            
870
            $(window).bind("resize", _.bind(function() {
871
                this.fix_left_border();
872
            }, this));
873
        },
874

    
875
        update_networks: function(nets) {
876
            _.each(nets, _.bind(function(net){
877
                if (net.get("status") == "DELETED") { return }
878
                view = this.add_or_update(net);
879
            }, this));
880
        },
881

    
882
        show: function() {
883
            this.container.show();
884
            $(this.el).show();
885
        },
886

    
887
        network_added_handler: function(type, net) {
888
            this.update_networks([net]);
889
        },
890

    
891
        network_changed_handler: function(type, models) {
892
            var nets = [];
893
            if (type == "change") {
894
                nets = [models]
895
            } else {
896
                nets = models.models;
897
            }
898

    
899
            this.update_networks(nets)
900
        },
901

    
902
        network_removed_handler: function(type, net) {
903
            this.remove_net(net)
904
            if (this.private_list.find(".network").length == 0) {
905
                this.private_list.hide();
906
            }
907
        },
908

    
909
        network_added: function(net) {
910
            return this.network_views[net.id];
911
        },
912

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

    
917
        remove_net: function(net) {
918
            if (this.network_added(net)) {
919
                var view = this.get_network_view(net);
920
                view.remove();
921
                delete this.network_views[net.id];
922
            }
923
        },
924

    
925
        __update_layout: function() {
926
        }
927
    });
928

    
929
})(this);