Revision 664f05f0

b/snf-cyclades-app/synnefo/ui/static/snf/js/ui/web/ui_networks_view.js
1
// Copyright 2011 GRNET S.A. All rights reserved.
1
// Copyright 2013 GRNET S.A. All rights reserved.
2 2
// 
3 3
// Redistribution and use in source and binary forms, with or
4 4
// without modification, are permitted provided that the following
......
52 52
    var logger = new snf.logging.logger("SNF-VIEWS");
53 53
    var debug = _.bind(logger.debug, logger);
54 54
    
55
    
56
    views.NetworkConnectVMsOverlay = views.Overlay.extend({
57
        title: "Connect machine",
58
        overlay_id: "overlay-select-vms",
59
        content_selector: "#network-vms-select-content",
60
        css_class: "overlay-info",
61

  
62
        initialize: function() {
63
            views.NetworkConnectVMsOverlay.__super__.initialize.apply(this);
64
            this.list = this.$(".vms-list ul");
65
            this.empty_message = this.$(".empty-message");
66

  
67
            // flag for submit handler to avoid duplicate bindings
68
            this.submit_handler_set = false;
69
        },
70
        
71
        handle_vm_click: function(el) {
72
            $(el).toggleClass("selected");
73
        },
74

  
75
        init_handlers: function() {
76
            var self = this;
77
            this.list.find("li").click(function() {
78
                self.handle_vm_click($(this));
79
            });
80
            
81
            if (!this.submit_handler_set) {
82
                // avoid duplicate submits
83
                this.el.find(".create").click(_.bind(function() {
84
                    this.submit();
85
                }, this));
86
                this.submit_handler_set = true;
87
            }
88
        },
89

  
90
        reset: function() {
91
            this.list.find("li").remove();
92
        },
93

  
94
        beforeOpen: function() {
95
            this.reset();
96
            this.update_layout();
97
        },
98
        
99
        vm: function(vm) {
100
            if (vm.id) { var id = vm.id } else {var id = vm}
101
            return this.list.find(".vm-" + id);
102
        },
103

  
104
        get_selected: function() {
105
            return this.list.find(".selected").map(function() {return $(this).data('vm')})
106
        },
107

  
108
        update_layout: function() {
109
            if (this.vms.length == 0) {
110
                this.empty_message.show();
111
            } else {
112
                this.empty_message.hide();
113
            }
114

  
115
            _.each(this.vms, _.bind(function(vm){
116
                
117
                var html = '<li class="vm option options-object vm-{0}">' +
118
                           '<div class="options-object-cont">' +
119
                           '{2}' + 
120
                           '<span class="title">{1}</span>' + 
121
                           '<span class="value">{3}</span></div>' + 
122
                           '</li>';
123
                var el = $(html.format(vm.id, 
124
                                       util.truncate(_.escape(vm.get("name")), 23), 
125
                                       snf.ui.helpers.vm_icon_tag(vm, "small", {'class':'os'}),
126
                                       _.escape(vm.get_os())
127
                                      ))
128
                el.data({vm:vm, vm_id:vm.id})
129
                this.list.append(el);
130

  
131
                vm.bind("remove", function(){ el.remove()})
132
                vm.bind("change:name", function(i,v){el.find(".title").text(v)})
133
            }, this));
134
            
135
            this.init_handlers();
136
            this.set_selected();
137
        },
138

  
139
        set_selected: function() {
140
            _.each(this.selected, _.bind(function(el){
141
                this.vm(el).addClass("selected");
142
            }, this));
143
        },
144

  
145
        show_vms: function(network, vms, selected, callback, subtitle) {
146
            this.network = network;
147
            this.reset();
148
            if (network) {
149
              this.set_subtitle(network.escape("name"));
150
            } else {
151
              this.set_subtitle(subtitle);
152
            }
153

  
154
            this.vms = vms;
155
            if (!synnefo.config.network_allow_duplicate_vm_nics && this.network) {
156
                this.vms = _.filter(this.vms, function(vm) {
157
                    return !vm.connected_to(this.network);
158
                }, this);
159
            }
160

  
161
            this.selected = selected;
162
            this.cb = callback;
163
            this.show();
164
        },
165

  
166
        submit: function() {
167
            this.cb(this.get_selected());
168
        }
169
    })
170

  
171
    views.NetworkActionsView = views.View.extend({
172
        
173
        initialize: function(view, net, el, opts) {
174
            this.parent = view
175
            this.network = net;
176
            this.el = el;
177
            
178
            this.actions = this.$(".actions");
179
            this.selected = undefined;
180

  
181
            this.destroy = this.$(".actions .destroy a");
182
            this.connect = this.$(".actions .add");
183

  
184
            this.init_handlers();
185
            this.update_layout();
186
        },
187

  
188
        init_handlers: function() {
189
            this.connect.click(_.bind(function(e){
190
                e.preventDefault();
191
            }))
192
        },
193

  
194
        update_layout: function() {
195
        }
196
    });
197

  
198 55
    views.NetworkCreateView = views.Overlay.extend({
199 56
        view_id: "network_create_view",
200 57
        content_selector: "#networks-create-content",
......
380 237
        }
381 238
    });
382 239

  
383
    views.NetworkNICView = views.View.extend({
240
    views.NetworkPortView = views.ext.ModelView.extend({
241
      tpl: '#network-port-view-tpl',
242
      
243
      vm_logo_url: function(vm) {
244
        if (!this.model.get('vm')) { return '' }
245
        return synnefo.ui.helpers.vm_icon_path(this.model.get('vm'), 'medium');
246
      },
247
      
248
      set_confirm: function() {
249
        var parent = this.parent_view.parent_view.el;
250
        parent.addClass("subactionpending");
251
      },
252

  
253
      unset_confirm: function() {
254
        var parent = this.parent_view.parent_view.el;
255
        parent.removeClass("subactionpending");
256
      },
257

  
258
      post_init_element: function() {
259
        this.in_progress = false;
260
        this.firewall = this.$(".firewall-content").hide();
261
        this.firewall_toggler = this.$(".firewall-toggle");
262
        this.firewall_apply = this.$(".firewall-apply");
263
        this.firewall_legends = this.firewall.find(".checkbox-legends");
264
        this.firewall_inputs = this.firewall.find("input");
265
        this.firewall_apply = this.firewall.find("button");
266
        this.firewall_visible = false;
267

  
268
        this.firewall_toggler.click(_.bind(function() {
269
          this.toggle_firewall();
270
        }, this));
271

  
272
        this.firewall.find(".checkbox-legends, input").click(
273
          _.bind(this.handle_firewall_choice_click, this));
274
        this.update_firewall();
275
      },
276
      
277
      toggle_firewall: function(e, hide, cb) {
278
          hide = hide === undefined ? false : hide;
279
          if (hide) {
280
            this.firewall.stop().hide();
281
          } else {
282
            if (!cb) { cb = function() {}}
283
            this.firewall.slideToggle(cb);
284
          }
285
          this.firewall_toggler.toggleClass("open");
286
          this.firewall_visible = this.firewall_toggler.hasClass("open");
287
          if (!this.firewall_visible) {
288
            this.firewall_apply.fadeOut(50);
289
          }
290
          this.update_firewall();
291
      },
292
    
293
      post_hide: function() {
294
        views.NetworkPortView.__super__.post_hide.apply(this);
295
        if (this.firewall_visible) {
296
          this.toggle_firewall({}, true);
297
        }
298
      },
299

  
300
      handle_firewall_choice_click: function(e) {
301
          var el = $(e.currentTarget);
302
          if (el.get(0).tagName == "INPUT") {
303
            el = el.next();
304
          }
305
          var current = this.model.get("firewall_status");
306
          var selected = el.prev().val();
307

  
308
          el.parent().find("input").attr("checked", false);
309
          el.prev().attr("checked", true);
310

  
311
          if (selected != current) {
312
            this.firewall_apply.show();
313
          } else {
314
            this.firewall_apply.hide();
315
          }
316
      },
317
      
318
      disconnect_port: function(model, e) {
319
        e && e.stopPropagation();
320
        this.model.actions.reset_pending();
321
        this.model.disconnect(_.bind(this.disconnect_port_complete, this));
322
      },
323

  
324
      disconnect_port_complete: function() {
325
      },
326

  
327
      set_firewall: function() {
328
        var value = this.get_selected_value();
329
        this.firewall_apply.addClass("in-progress");
330
        this.model.set({'pending_firewall': value});
331
        this.model.set_firewall(value, this.set_firewall_complete, 
332
                                       this.set_firewall_complete);
333
        this.in_progress = true;
334
      },
335
      
336
      set_firewall_complete: function() {
337
        this.in_progress = false;
338
        this.toggle_firewall({}, false, _.bind(function() {
339
          this.firewall_apply.removeClass("in-progress").show();
340
        }, this));
341
      },
342

  
343
      get_selected_value: function() {
344
        return this.firewall_inputs.filter(":checked").val();
345
      },
346

  
347
      update_firewall: function() {
348
        var value = this.model.get("firewall_status");
349
        var value_selector = "[value=" + value + "]"
350
        var status_span = this.firewall_toggler.find("span span");
351
        var current_choice = this.firewall_inputs.filter(value_selector);
352

  
353
        if (_.contains(["PROTECTED", "ENABLED"], value)) {
354
          status_span.removeClass("firewall-off").addClass("firewall-on");
355
          status_span.text("On");
356
        } else {
357
          status_span.removeClass("firewall-on").addClass("firewall-off");
358
          status_span.text("Off");
359
        }
360
        
361
        this.firewall_inputs.attr("checked", false);
362
        this.firewall_legends.removeClass("current");
363
        current_choice.attr("checked", true)
364
        current_choice.next().addClass("current");
365
      },
366

  
367
      show_vm_details: function() {
368
        var vm = this.model.get('vm');
369
        if (vm) { snf.ui.main.show_vm_details(vm) }
370
      }
371
    });
384 372

  
385
        initialize: function(nic, parent, firewall_controls, el) {
386
            this.firewall_controls = firewall_controls || false;
387
            this.nic = nic;
388
            this.vm = nic.get_vm();
389
            // parent view di
390
            this.parent = parent;
391
            // TODO make it better
392
            this.el = el || this.parent.get_nic_view(nic);
373
    views.NetworkPortCollectionView = views.ext.CollectionView.extend({
374
      tpl: '#network-port-collection-view-tpl',
375
      model_view_cls: views.NetworkPortView,
376
      rivets_view: true,
377
      get_rivet_object: function() {
378
        return {
379
          model: this.collection.network
380
        }
381
      },
382
      resolve_storage_object: function() {
383
        return this.collection
384
      },
385

  
386
      show_connect_vms_overlay: function() {
387
        this.parent_view.show_connect_vms_overlay();
388
      }
389
    });
393 390

  
394
            this.init_layout();
395
            this.update_layout();
391
    views.NetworkView = views.ext.ModelView.extend({
392
      tpl: '#network-view-tpl',
393
      auto_bind: ['connect_vm'],
394
      post_init_element: function() {
395
        this.ports = this.$(".ports.nested-model-list");
396
        this.ports.hide();
397
        this.ports_toggler = this.$(".network-ports-toggler");
398
        this.ports_toggler.click(this.toggle_ports);
399
        this.ports_visible = false;
400
      },
401

  
402
      toggle_ports: function(e, hide) {
403
        hide = hide === undefined ? false : hide;
404
        if (hide) {
405
          this.ports.stop().hide();
406
        } else {
407
          this.ports.stop().slideToggle();
408
        }
409
        this.ports_toggler.find(".cont-toggler").toggleClass("open");
410
        this.ports_visible = this.ports_toggler.find(".cont-toggler").hasClass("open");
411
      },
412

  
413
      post_hide: function() {
414
        views.NetworkView.__super__.post_hide.apply(this);
415
        if (this.ports_visible) {
416
          this.toggle_ports({}, true);
417
        }
418
      },
419
      
420
      status_map: {
421
        'ACTIVE': 'Active',
422
        'CONNECTING': 'Connecting',
423
        'DISCONNECTING': 'Disconnecting',
424
        'REMOVING': 'Removing'
425
      },
426

  
427
      status_cls_map: {
428
        'ACTIVE': 'status-active',
429
        'DISCONNECTING': 'status-progress',
430
        'CONNECTING': 'status-progress',
431
        'REMOVING': 'status-progress'
432
      },
433
      
434
      status_cls: function(status) {    
435
        return this.status_cls_map[this.model.get('ext_status')]
436
      },
437

  
438
      status_display: function(status) {
439
        var status;
440
        if (this.model.id == "snf-combined-public-network") {
441
          return "Internet"
442
        }
396 443

  
397
            this.disconnect = this.$(".action-disconnect");
398
            this.confirm_el = this.$(".confirm_single");
399
            this.cancel = this.$("button.no");
400
            this.confirm = this.$("button.yes");
401
            this.details = this.$(".action-details");
402
            this.vm_connect = this.$(".machine-connect");
403
            this.actions = this.$(".net-vm-actions");
444
        status = this.status_map[this.model.get('ext_status')];
445
        return status;
446
      },
447
      
448
      connect_vms: function(vms, cb) {
449
        var finished = 0;
450
        var completed = function() {
451
          finished++;
452
          if (finished == vms.length) {
453
            cb();
454
          }
455
        }
456
        _.each(vms, function(vm) {
457
          this.model.connect_vm(vm, completed);
458
        }, this);
459
      },
460
      
461
      remove: function(e) {
462
        e.stopPropagation();
463
        this.model.actions.reset_pending();
464
        this.model.destroy({
465
          complete: _.bind(function() {
466
            this.model.set({status: 'REMOVING'})
467
          }, this),
468
          silent: true
469
        });
470
      },
471

  
472
      show_connect_vms_overlay: function() {
473
        var view = new views.NetworkConnectVMsOverlay();
474
        vms = this.model.pluggable_vms();
475
        var cb = _.bind(function(vms) {
476
          view.set_in_progress();
477
          var cbinner = function() {
478
            view.hide();
479
            delete view;
480
          }
481
          this.connect_vms(vms, cbinner);
482
        }, this);
483
        view.show_vms(this.model, vms, [], cb, "subtitle");
484
      }
404 485

  
405
            this.init_handlers();
406
            this.connect_overlay = new views.VMConnectView();
407
            
408
            this.firewall_view = undefined;
409
            if (this.firewall_controls) {
410
                this.firewall_view = new views.FirewallEditView(this.nic, this.parent.network, this);
411
            }
486
    });
487
    
488
    views.NetworksCollectionView = views.ext.CollectionView.extend({
489
      collection: storage.networks,
490
      collection_name: 'networks',
491
      model_view_cls: views.NetworkView,
492
      create_view_cls: views.NetworkCreateView,
493
      
494
      init: function() {
495
        this.public_added = false;
496
        views.NetworksCollectionView.__super__.init.apply(this, arguments);
497
      },
498
      
499
      check_empty: function() {
500
        views.NetworksCollectionView.__super__.check_empty.apply(this, arguments);
501
        //if (this.$(".private").children().length == 0) {
502
          //this.$(".private").hide();
503
        //} else {
504
          //this.$(".private").show();
505
        //}
506
      },
507

  
508
      add_model: function(m) {
509
        if (m.get('is_public') && !this.public_added) {
510
          this.combined_public = new models.networks.CombinedPublicNetwork();
511
          this.combined_public_view = new views.NetworkView({
512
            model: this.combined_public
513
          });
514
          this.add_model_view(this.combined_public_view, this.combined_public, 0);
515
          this.combined_public_view.$("i").hide();
516
          this.public_added = true;
517
        }
518
        return views.NetworksCollectionView.__super__.add_model.call(this, m);
519
      },
520

  
521
      remove_model: function(m) {
522
        if (m.id == 'snf-combined-public-network') {
523
          return;
524
        } else {
525
          return views.NetworksCollectionView.__super__.remove_model.call(this, m);
526
        }
527
      },
528

  
529
      get_model_view_cls: function(m) {
530
        if (!this.public_added) {
531
        }
532
        if (m.get('is_public')) {
533
          return false;
534
        }
535
        return views.NetworksCollectionView.__super__.get_model_view_cls.apply(this, [m]);
536
      },
537
      
538
      parent_for_model: function(m) {
539
        if (m.get('is_public')) {
540
          return this.list_el.find(".public");
541
        } else {
542
          return this.list_el.find(".private");
543
        }
544
      }
545
    });
546

  
547
    views.NetworksPaneView = views.ext.PaneView.extend({
548
      id: "pane",
549
      el: '#networks-pane',
550
      collection_view_cls: views.NetworksCollectionView,
551
      collection_view_selector: '#networks-list-view'
552
    });
553

  
554
    views.NetworkConnectVMsOverlay = views.Overlay.extend({
555
        title: "Connect machine",
556
        overlay_id: "overlay-select-vms",
557
        content_selector: "#network-vms-select-content",
558
        css_class: "overlay-info",
559
        allow_multiple: true,
412 560

  
561
        initialize: function() {
562
            views.NetworkConnectVMsOverlay.__super__.initialize.apply(this);
563
            this.list = this.$(".vms-list ul");
564
            this.empty_message = this.$(".empty-message");
565
            // flag for submit handler to avoid duplicate bindings
566
            this.submit_handler_set = false;
567
            this.in_progress = false;
413 568
        },
414 569
        
415
        reset_all_net_actions: function(act_types) {
416
            synnefo.storage.networks.each(function(n){
417
                var actions = n.get('actions');
418
                _.each(act_types, function(type){
419
                    actions.remove_all(type);
420
                })
421
            })
570
        handle_vm_click: function(el) {
571
            if (!this.allow_multiple) {
572
              $(el).closest("ul").find(".selected").removeClass("selected");
573
              $(el).addClass("selected");
574
            } else {
575
              $(el).toggleClass("selected");
576
            }
422 577
        },
423 578

  
424 579
        init_handlers: function() {
425
            if (!this.parent.network.is_public()) {
426
                this.disconnect.click(_.bind(function(e){
427
                    e.preventDefault();
428
                    this.reset_all_net_actions(['destroy','disconnect']);
429
                    this.parent.network.get("actions").remove_all("disconnect");
430
                    this.parent.network.get("actions").add("disconnect", this.nic.id);
431
                    this.parent.network.get("actions").remove("destroy");
432
                }, this));
433
                this.cancel.click(_.bind(function(e){
434
                    this.parent.network.get("actions").remove("disconnect", this.nic.id);
435
                    e.preventDefault()
436
                }, this));
437

  
438
                this.confirm.click(_.bind(function(e){
439
                    e.preventDefault()
440
                    this.disconnect_nic();
441
                    this.confirm_el.hide();
442
                    this.disconnect.removeClass("selected");
443
                    this.actions.find("a").removeClass("visible");
444
                }, this));
445

  
446
                snf.ui.main.bind("view:change", _.bind(function(v) {
447
                    if (v == "networks" ){ return }
448
                    this.confirm_el.hide();
449
                    this.disconnect.removeClass("selected");
450
                }, this));
451

  
452
                this.$(".remove-icon").click(_.bind(function(){
453
                    this.reset_all_net_actions(['destroy','disconnect']);
454
                    this.parent.network.get("actions").remove_all("disconnect");
455
                    this.parent.network.get("actions").add("disconnect", this.nic.id);
456
                    this.parent.network.get("actions").remove("destroy");
457
                }, this));
458

  
459
                this.vm_connect.click(_.bind(function() {
460
                    this.connect_overlay.show(this.vm);
461
                }, this));
462
                
463
                this.parent.network.bind("change:actions", _.bind(function(model, action){
464
                    if (this.parent.network.get("actions").contains("disconnect", this.nic.id)) {
465
                        this.confirm_disconnect();
466
                    } else {
467
                        this.cancel_disconnect();
468
                    }
580
            var self = this;
581
            this.list.find("li").click(function() {
582
                self.handle_vm_click($(this));
583
            });
584
            
585
            if (!this.submit_handler_set) {
586
                // avoid duplicate submits
587
                this.el.find(".create, .assign").click(_.bind(function() {
588
                  if (!this.in_progress) {
589
                    this.submit();
590
                  }
469 591
                }, this));
592
                this.submit_handler_set = true;
470 593
            }
471
            
472
            var vm = this.vm;
473
            this.details.click(function(e){
474
                e.preventDefault();
475
                snf.ui.main.show_vm_details(vm);
476
            });
477

  
478 594
        },
479 595

  
480
        cancel_disconnect: function() {
481
            this.confirm_el.hide();
482
            this.disconnect.removeClass("selected");
483
            this.$(".net-vm-actions a").removeClass("visible");
596
        reset: function() {
597
            this.list.find("li").remove();
484 598
        },
485 599

  
486
        confirm_disconnect: function() {
487
            this.confirm_el.show();
488
            this.disconnect.addClass("selected");
489
            this.$(".net-vm-actions a").addClass("visible");
600
        beforeOpen: function() {
601
            this.reset();
602
            this.update_layout();
603
        },
604
        
605
        vm: function(vm) {
606
            if (vm.id) { var id = vm.id } else {var id = vm}
607
            return this.list.find(".vm-" + id);
490 608
        },
491 609

  
492
        init_layout: function() {
493
            if (!this.firewall_controls) { return };
610
        get_selected: function() {
611
            return this.list.find(".selected").map(function() {return $(this).data('vm')})
494 612
        },
495 613

  
496 614
        update_layout: function() {
497
            this.$(".vm-name").text(snf.util.truncate(this.vm.get("name"), 40));
498
            this.$("img.logo").attr("src", ui.helpers.vm_icon_path(this.vm, "medium"));
499

  
500
            if (this.firewall_view) {
501
                this.$(".ipv4-text").text(this.nic.get_v4_address());
502
                this.$(".ipv6-text").text(this.nic.get_v6_address());
503
            }
504

  
505
            if (this.firewall_view) {
506
                this.firewall_view.update_layout();
507
            }
615
            this.unset_in_progress();
616
            this.in_progress = false;
508 617

  
509
            if (!this.firewall_view) {
510
                this.$(".ip4-container").hide();
511
                this.$(".ip6-container").hide();
512
                
513
                if (this.nic.get("ipv4")) {
514
                    this.$(".ipv4-text").text(this.nic.get_v4_address());
515
                    this.$(".ip4-container").show();
516
                    this.$(".machine-connect .content").hide();
517
                } else if (this.nic.get("ipv6")) {
518
                    this.$(".ipv6-text").text(this.nic.get_v6_address());
519
                    this.$(".ip6-container").show();
520
                    this.$(".machine-connect .content").hide();
521
                } else {
522
                    this.$(".machine-connect .content").show();
523
                }
618
            if (this.vms.length == 0) {
619
                this.empty_message.show();
524 620
            } else {
621
                this.empty_message.hide();
525 622
            }
526
        },
527 623

  
528
        disconnect_nic: function() {
529
            this.$("a.selected").removeClass("selected");
530
            this.nic.get_network().remove_nic(this.nic);
531
        }
532
    })
624
            _.each(this.vms, _.bind(function(vm){
625
                var html = '<li class="vm option options-object vm-{0}">' +
626
                           '<div class="options-object-cont">' +
627
                           '{2}' + 
628
                           '<span class="title">{1}</span>' + 
629
                           '<span class="value">{3}</span></div>' + 
630
                           '</li>';
631
                var el = $(html.format(vm.id, 
632
                       util.truncate(_.escape(vm.get("name")), 23), 
633
                       snf.ui.helpers.vm_icon_tag(vm, "small", {'class':'os'}),
634
                       _.escape(vm.get_os())
635
                ));
636
                el.data({vm:vm, vm_id:vm.id});
637
                this.list.append(el);
533 638

  
534
    views.NetworkModelRenameView = views.View.extend({
535
        initialize: function(parent, network) {
536
            this.parent = parent;
537
            this.network = network;
538
            this.el = this.parent.el.find(".name-div");
539

  
540
            this.icon = this.$(".rename-network");
541
            this.save = this.$("span.save");
542
            this.cancel = this.$("span.cancel");
543
            this.buttons = this.$(".editbuttons");
544
            this.name = this.$("span.name");
545
            this.editing = false;
639
                vm.bind("remove", function(){ el.remove()})
640
                vm.bind("change:name", function(i,v){el.find(".title").text(v)})
641
            }, this));
642
            
546 643
            this.init_handlers();
547
            this.update_layout();
644
            this.set_selected();
548 645
        },
549 646

  
550
        init_handlers: function() {
551
            this.icon.click(_.bind(function(){
552
                this.editing = true;
553
                this.update_layout();
554
            }, this));
555
            this.cancel.click(_.bind(function(){
556
                this.editing = false;
557
                this.update_layout();
647
        set_selected: function() {
648
            _.each(this.selected, _.bind(function(el){
649
                this.vm(el).addClass("selected");
558 650
            }, this));
559
            this.save.click(_.bind(function(){
560
                this.submit();
561
            }, this))
562 651
        },
563 652
        
564
        submit: function() {
565
            var value = _(this.input.val()).trim();
566
            if (value == "") { return }
567

  
568
            this.network.rename(value, _.bind(function(){
569
                this.editing = false;
570
                this.update_layout();
571
            }, this));
572
        },
573

  
574
        create_input: function() {
575
            this.input = $('<input type="text" class="network-rename-input" />');
576
            this.input.val(this.network.get("name"));
577
            this.el.append(this.input);
578
            this.input.focus();
579
            this.input.bind("keydown", _.bind(function(ev){
580
                ev.keyCode = ev.keyCode || ev.which;
581
                if (ev.keyCode == 13) { this.submit(); };
582
                if (ev.keyCode == 27) {this.editing = false; this.update_layout()};
583
            }, this));
653
        set_in_progress: function() {
654
          this.$(".form-action").addClass("in-progress");
655
          this.in_progress = true;
584 656
        },
585 657

  
586
        remove_input: function() {
587
            if (!this.input) { return }
588
            this.input.remove();
658
        unset_in_progress: function() {
659
          this.$(".form-action").removeClass("in-progress");
660
          this.in_progress = false;
589 661
        },
590 662

  
591
        update_layout: function() {
592
            if (this.editing) {
593
                if (this.buttons.is(":visible")) { return }
594
                this.icon.hide();
595
                this.buttons.show();
596
                this.create_input();
597
                this.name.hide();
663
        show_vms: function(network, vms, selected, callback, subtitle) {
664
            this.network = network;
665
            this.reset();
666
            if (network) {
667
              this.set_subtitle(network.escape("name"));
598 668
            } else {
599
                this.buttons.hide();
600
                this.remove_input();
601
                this.name.show();
602
                this.icon.show();
669
              this.set_subtitle(subtitle);
603 670
            }
604
        }
605
    })
606 671

  
607
    views.FirewallEditView = views.View.extend({
608

  
609
        initialize: function(nic, network, parent) {
610
            this.parent = parent;
611
            this.vm = nic.get_vm();
612
            this.nic = nic;
613
            this.network = network;
614
            this.el = this.parent.el;
615

  
616
            views.FirewallEditView.__super__.initialize.apply(this);
617

  
618
            // elements
619
            this.toggler = this.$(".firewall-toggle");
620
            this.indicator = this.$(".machines-label span");
621
            this.progress = this.$(".network-progress-indicator");
622
            this.content = this.$(".firewall-content");
623
            this.inputs = this.$("input[type=radio]");
624
            this.labels = this.$("span.checkbox-legends, label.checkbox-legends");
625
            this.apply = this.$(".firewall-apply");
626

  
627
            this.$(".firewall-content").hide();
628
            this.$(".firewall-content input[type=radio]").attr("name", "firewall-opt-for-{0}".format(this.vm.id))
629
            var mode = this.vm.get_firewall_profile();
630
            this.$(".firewall-content input[value={0}]".format(mode)).attr("checked", true);
631

  
632
            this.init_handlers();
633
            this.update_layout();
634

  
635
            var self = this;
636
            this.nic.bind("change:pending_firewall_sending", function(nic, value) {
637
                if (value) {
638
                    self.apply.addClass("in-progress");       
639
                    self.progress.show();
640
                } else {
641
                    self.apply.removeClass("in-progress");       
642
                    self.progress.hide();
643
                    self.toggler.click();
644
                }
645
            });
646

  
647
            this.nic.bind("change:firewallProfile", function(nic){
648
                self.update_layout();
649
                self.reset_value();
650
            })
651

  
652
        },
653
        
654
        _get_selected: function() {
655
            return this.inputs.filter(":checked");
656
        },
657

  
658
        reset_selected: function() {
659
        },
672
            this.vms = vms;
673
            this.selected = selected;
674
            this.cb = callback;
675
            this.unset_in_progress();
676
            this.show(true);
677
        },
660 678

  
661 679
        submit: function() {
662
        },
663

  
664
        reset_value: function() {
665
            this.inputs.filter("[value={0}]".format(
666
              this.nic.get('firewallProfile'))).attr("checked", true);
667
        },
668

  
669
        init_handlers: function() {
670
            this.toggler.click(_.bind(function(){
671
                cont = this.content;
672
                if (cont.is(":visible")) {
673
                    this.hide_firewall();
674
                    this.reset_value();
675
                } else {
676
                    this.show_firewall();
677
                }
678

  
679
                $(window).trigger("resize");
680
            }, this))
681
            
682
            this.apply.click(_.bind(function(){
683
                this.nic.set_firewall(this.value());
684
            }, this))
685

  
686
            this.inputs.change(_.bind(function(){
687
                this.update_selected();
688
            }, this))
689
            
690
            var self = this;
691
            this.$(".checkbox-legends").click(function(el) {
692
                var el = $(this);
693
                el.prev().click();
694
                self.update_selected();
695
            })
696
        },
697

  
698
        update_selected: function() {
699
            this.update_layout();
700
        },
701

  
702
        show_firewall: function() {
703
            this.content.slideDown(100, function(){$(window).trigger("resize")});
704
            this.toggler.addClass("open");
705
        },
706

  
707
        hide_firewall: function() {
708
            this.content.slideUp(100, function(){$(window).trigger("resize")});
709
            this.toggler.removeClass("open");
710
        },
711

  
712
        value: function() {
713
            return this._get_selected().val();
714
        },
715

  
716
        update_layout: function() {
717
            if (this.value() == this.vm.get_firewall_profile()) {
718
                this.apply.hide();
719
            } else {
720
                this.apply.show();
721
            }
722

  
723
            var profile = this.vm.get_firewall_profile();
724
            if (this.vm.has_firewall(this.network.id)) {
725
                this.$(".firewall-toggle .label span").text("On");
726
                this.$(".firewall-toggle .label span").removeClass("firewall-off");
727
                this.$(".firewall-toggle .label span").addClass("firewall-on");
728
            } else {
729
                this.$(".firewall-toggle .label span").text("Off");
730
                this.$(".firewall-toggle .label span").removeClass("firewall-on");
731
                this.$(".firewall-toggle .label span").addClass("firewall-off");
732
            }
733
            
734
            this.$("span.checkbox-legends").removeClass("current");
735
            this.inputs.filter("[value={0}]".format(profile)).next().addClass("current");
736
            
737
        }
738
    })
739

  
740
    views.NetworkModelView = views.View.extend({
741
        
742
        firewall: false,
743

  
744
        initialize: function(network, view) {
745
            this.parent_view = view;
746
            this.network = network;
747
            this.main_view_id = this.main_view_id ? this.main_view_id : "networks_view_" + network.id;
748
            this.is_public = network.is_public();
749

  
750
            this.init_nics_handlers();
751
            
752
            this.view_id = "networks_view_" + network.id;
753
            views.NetworkModelView.__super__.initialize.call(this);
754

  
755
            this.nics_views = {};
756

  
757
            this.el = this.create_el();
758

  
759
            // element helpers
760
            this.nics_list = this.$(".machines-list");
761
            this.nics_list_toggler = this.$(".list-toggle");
762
            
763
            this.init_handlers();
764
            this.init_toggler_handlers();
765
            this.update_nics();
766
            this.update_layout();
767

  
768
            this.hide_nics_list();
769
            this.nics_list.hide();
770

  
771
            this.rename_view = undefined;
772
            if (!this.network.is_public()) {
773
                // allow network rename for non public networks only
774
                this.rename_view = new views.NetworkModelRenameView(this, network);
775
            }
776
            
777
            var self = this;
778
            this.network.bind('change:status', function() {
779
                self.update_layout();
780
            });
781

  
782
        },
783

  
784
        init_nics_handlers: function() {
785
            storage.nics.bind("add", _.bind(this.nic_added_handler, this, "add"));
786
            storage.nics.bind("change", _.bind(this.nic_changed_handler, this, "change"));
787
            storage.nics.bind("reset", _.bind(this.nic_changed_handler, this, "reset"));
788
            storage.nics.bind("remove", _.bind(this.nic_removed_handler, this, "remove"));
789
        },
790

  
791

  
792
        show_nics_list: function() {
793
            //if (this.nics_empty()) { return }
794
            var self = this;
795
            this.nics_list_toggler.addClass("open");
796
            this.nics_list.slideDown(function(){
797
                $(window).trigger("resize");
798
            }).closest(".network").addClass("expand");
799
            this.$(".empty-network-slot").slideDown();
800
            this.nics_visible = true;
801
        },
802

  
803
        hide_nics_list: function() {
804
            this.nics_list_toggler.removeClass("open");
805
            this.nics_list.slideUp(function(){
806
                $(window).trigger("resize");
807
            }).closest(".network").removeClass("expand");
808
            this.$(".empty-network-slot").slideUp();
809
            this.nics_visible = false;
810
        },
811
        
812
        init_toggler_handlers: function() {
813
            this.nics_list_toggler.click(_.bind(function(){
814
                if (this.nics_list.is(":visible")) {
815
                    this.hide_nics_list();
816
                } else {
817
                    this.show_nics_list();
818
                    this.fix_left_border();
819
                }
820

  
821
            }, this));
822
            $(window).bind("resize", _.bind(function() {
823
                this.fix_left_border();
824
            }, this));
825
        },
826

  
827
        init_handlers: function() {
828
            var self = this;
829

  
830

  
831
            this.$(".action-add").click(_.bind(function(e){
832
                e.preventDefault();
833
                this.network.get("actions").remove("destroy");
834
                this.show_connect_vms();
835
            }, this))
836

  
837
            this.$(".add-icon").click(_.bind(function(e){
838
                e.preventDefault();
839
                this.show_connect_vms();
840
            }, this))
841

  
842
            this.$(".net-actions .destroy a").click(_.bind(function(e){
843
                e.preventDefault();
844
                synnefo.storage.networks.each(function(n) {
845
                    n.get('actions').remove_all("disconnect");
846
                    if (!synnefo.config.network_allow_multiple_destory) {
847
                        n.get('actions').remove_all("destroy");
848
                    }
849
                });
850
                self.network.get("actions").add("destroy");
851
                self.network.get("actions").remove_all("disconnect");
852
            }, this));
853

  
854
            self.network.bind("change:actions", _.bind(function(net, action) {
855
                if (this.network.get("actions").contains("destroy")) {
856
                    this.confirm_destroy();
857
                } else {
858
                    this.cancel_destroy();
859
                }
860
            }, this));
861
            
862

  
863
            // reset pending destory action after successful removal
864
            self.network.bind("remove", _.bind(function(net){
865
                net.get("actions").remove_all("destroy");
866
            }));
867

  
868
            this.$(".net-actions button.no").click(function(e){
869
                e.preventDefault();
870
                self.network.get("actions").remove("destroy");
871
            });
872

  
873
            this.$(".net-actions button.yes").click(function(e){
874
                e.preventDefault();
875
                var el = $(this);
876
                el.closest(".confirm_single").hide();
877
                el.parent().parent().find(".selected").removeClass("selected");
878
                self.network.call('destroy', {}, function(){
879
                    el.closest(".confirm_single").removeClass("in-progress");
880
                });
881
                el.closest(".confirm_single").addClass("in-progress");
882
            });
883

  
884
            snf.ui.main.bind("view:change", _.bind(function(v) {
885
                if (v == "networks" ){ return }
886
                this.$(".confirm_single").hide();
887
                this.$("a.selected").removeClass("selected");
888
            }, this));
889
            
890
            this.$(".empty-network-slot").hide();
891
        },
892

  
893
        show_connect_vms: function() {
894
            this.$(".confirm_single").hide();
895
            this.$("a.selected").removeClass("selected");
896
            var vms = this.network.get_connectable_vms();
897
            this.parent_view.connect_machines_view.show_vms(this.network,
898
                                                            vms, [], 
899
                                                            _.bind(this.connect_vms, this));
900
        },
901

  
902
        cancel_destroy: function() {
903
            this.$(".net-actions .destroy .confirm_single").hide();
904
            this.$(".net-actions .destroy a.selected").removeClass("selected");
905
            this.$(".net-actions a").removeClass("visible");
906
        },
907

  
908
        confirm_destroy: function() {
909
            this.$(".destroy .confirm_single").show();
910
            this.$(".destroy a").addClass("selected");
911
            this.$(".net-actions a").addClass("visible");
912
        },
913

  
914
        connect_vms: function(vms) {
915
            _.each(vms, _.bind(function(vm){
916
                this.network.add_vm(vm, function() {
917
                  if (!synnefo.config.private_networks_nic_hotplug) {
918
                    vm.require_reboot();
919
                  }
920
                });
921
            }, this));
922

  
923
            this.parent_view.connect_machines_view.hide();
924
        },
925

  
926
        create_el: function() {
927
            return this.$(this.tpl).clone().attr("id", this.main_view_id);
928
        },
929

  
930
        get_nic_id: function(nic) {
931
            return this.nic_id_tpl.format(nic.id);
932
        },
933

  
934
        get_nic_view: function(nic) {
935
            return $(this.get_nic_id(nic));
936
        },
937
        
938
        nic_in_network: function(nic) {
939
          return nic.get_network().id == this.network.id;
940
        },
941

  
942
        nic_added_handler: function(action, nic) {
943
            if (!this.nic_in_network(nic)) { return };
944
            this.add_or_update_nic(nic);
945
            this.update_layout();
946
            this.fix_left_border();
947
        },
948

  
949
        nic_changed_handler: function(action, nics, model, changes) {
950
            var nics = nics || [];
951

  
952
            // reset or update
953
            if (action == "reset") {
954
                nics = nics;
955
            } else {
956
                if (!_.isArray(nics)) {
957
                    nics = [nics]
958
                }
959
            }
960
            
961
            _.each(nics, _.bind(function(nic) {
962
                if (!this.nic_in_network(nic)) { return };
963
                this.add_or_update_nic(nic);
964
            }, this));
965

  
966
            this.update_layout();
967
        },
968

  
969
        nic_removed_handler: function(action, nic, model) {
970
            if (!this.nic_in_network(nic)) { return };
971
            this.fix_left_border();
972
            this.remove_nic(nic);
973
            this.update_layout();
974
        },
975

  
976
        remove_nic: function(nic) {
977
            var nic_view = this.get_nic_view(nic);
978
            if (nic_view.length) {
979
                nic_view.remove();
980
                try {
981
                    delete this.nics_views[nic.id]
982
                } catch (err) {
983
                }
984
            }
985
        },
986
        
987
        create_nic_view: function(nic) {
988
            var nic_el = $(this.nic_tpl).clone().attr({
989
                id: this.get_nic_id(nic).replace("#","")
990
            });
991
            this.nics_list.append(nic_el);
992
            this.post_nic_add(nic);
993

  
994
            if (!this.nics_views[nic.id]) {
995
                var nic_view = this.nics_views[nic.id] = new views.NetworkNICView(nic, this, this.firewall, nic_el);
996
            }
997
        },
998

  
999
        add_or_update_nic: function(nic) {
1000
            if (!nic) { return };
1001
                
1002
            var nic_el = this.get_nic_view(nic);
1003
            var nic_view = this.nics_views[nic.id];
1004

  
1005
            if (nic_el.length == 0) {
1006
                nic_view = this.create_nic_view(nic);
1007
            }
1008
            
1009
            if (nic_view) { nic_view.update_layout() };
1010

  
1011
            this.update_nic(nic);
1012
            this.post_nic_update(nic);
1013
        },
1014

  
1015
        update_nic: function(vm){},
1016
        post_nic_add: function(vm){},
1017
        post_nic_update: function(vm){},
1018
        
1019
        get_nics: function() {
1020
          return this.network.get_nics();
1021
        },
1022

  
1023
        update_nics: function(nics) {
1024
            if (!nics) { nics = this.get_nics() };
1025
            _.each(nics, _.bind(function(nic){
1026
                this.add_or_update_nic(nic);
1027
            }, this));
1028
        },
1029

  
1030
        check_empty_nics: function() {
1031
            if (this.get_nics().length == 0) {
1032
                this.hide_nics_list();
1033
            }
1034
        },
1035

  
1036
        nics_empty: function() {
1037
            return this.get_nics().length == 0;
1038
        },
1039

  
1040
        remove: function() {
1041
            $(this.el).remove();
1042
        },
1043
        
1044
        get_name: function() {
1045
          var net_name = this.network.get('name');
1046
          if (net_name == "public") { net_name = "Internet" };
1047
          return net_name;
1048
        },
1049

  
1050
        update_layout: function() {
1051
            // has vms ???
1052
            this.check_empty_nics();
1053

  
1054
            // is expanded ???
1055
            //
1056
            // whats the network status ???
1057
            //
1058
            this.$(".machines-count").text(this.get_nics().length);
1059

  
1060
            var net_name = this.get_name();
1061
            this.$(".name-div span.name").text(net_name);
1062

  
1063
            if (this.rename_view) {
1064
                this.rename_view.update_layout();
1065
            }
1066
            
1067
            this.$(".net-status").text(this.network.state_message());
1068

  
1069
            if (this.network.in_progress())  {
1070
                this.$(".spinner").show();
1071
                this.$(".network-indicator").addClass("in-progress");
1072
            } else {
1073
                this.$(".spinner").hide();
1074
                this.$(".network-indicator").removeClass("in-progress");
1075
            }
1076
                
1077
            if (this.network.get('state') == 'PENDING') {
1078
                this.el.addClass("pending");
1079
            } else {
1080
                this.el.removeClass("pending");
1081
            }
1082

  
1083
            if (this.network.get('state') == 'ERROR') {
1084
                this.el.addClass("in-error");
1085
                this.$(".network-indicator").addClass("error-state");
1086
            } else {
1087
                this.el.removeClass("in-error");
1088
                this.$(".network-indicator").removeClass("error-state");
1089
            }
1090

  
1091
            if (synnefo.config.network_strict_destroy) {
1092
                if (this.get_nics().length == 0 && 
1093
                        !this.network.in_progress()) {
1094
                    this.el.removeClass("disable-destroy");
1095
                } else {
1096
                    this.el.addClass("disable-destroy");
1097
                }
1098
            }
1099

  
1100
            if (this.network.get("state") == "DESTROY") {
1101
                this.$(".spinner").show();
1102
                this.$(".state").addClass("destroying-state");
1103
                this.$(".actions").hide();
1104
            } else {
1105
                this.$(".state").removeClass("destroying-state");
1106
                this.$(".actions").show();
1107
                this.$(".actions a").removeClass("visible");
1108
            }
1109
        },
1110

  
1111
        // fix left border position
1112
        fix_left_border: function(force) {
1113
            if (!this.nics_visible && !force) { return };
1114
            
1115
            var imgheight = 2783;
1116
            var opened_vm_height = 133 + 18;
1117
            var closed_vm_height = 61 + 20;
1118
            var additional_height = 25;
1119

  
1120
            if (!this.is_public) { 
1121
                imgheight = 2700;
1122
                additional_height = 65;
1123
            };
1124
            
1125
            var contents = this.$(".network-contents");
1126
            var last_vm = this.$(".network-machine:last .cont-toggler.open").length;
1127
            var last_vm_height = closed_vm_height;
1128
            if (last_vm > 0){
1129
                last_vm_height = opened_vm_height;
1130
            }
1131

  
1132
            var nics_opened = this.$(".network-machine .cont-toggler.open").length;
1133
            var nics_closed = this.$(".network-machine").length - nics_opened;
1134

  
1135
            var calc_height = (nics_opened * opened_vm_height) + (nics_closed * closed_vm_height) + additional_height; 
1136
            var bgpos = imgheight - calc_height + last_vm_height - 30;
1137
            this.$(".network-contents").css({'background-position':'33px ' + (-bgpos) + 'px'});
1138
        }
1139
    })
1140

  
1141
    views.PublicNetworkView = views.NetworkModelView.extend({
1142
        firewall: true,
1143
        tpl: "#public-template",
1144
        nic_tpl: "#public-nic-template",
1145
        nic_id_tpl: "#nic-{0}",
1146
        
1147
        initialize: function(network, view) {
1148
          views.PublicNetworkView.__super__.initialize.call(this, network, view);
1149
          this.fix_left_border(1);
1150
        },
1151

  
1152
        init_handlers: function(vm) {
1153
          $(window).bind("resize", _.bind(function() {
1154
              this.fix_left_border();
1155
          }, this));
1156
        }
1157
    });
1158

  
1159
    views.GroupedPublicNetworkView = views.PublicNetworkView.extend({
1160
        main_view_id: "grouped-public",
1161

  
1162
        initialize: function(network, view) {
1163
          this.networks = {};
1164
          this.add_network(network);
1165
          views.GroupedPublicNetworkView.__super__.initialize.call(this, 
1166
                                                                   network, 
1167
                                                                   view);
1168
        },
1169
          
1170
        get_name: function() {
1171
          return synnefo.config.grouped_public_network_name || views.GroupedPublicNetworkView.__super__.get_name.call(this);
1172
        },
1173

  
1174
        nic_in_network: function(nic) {
1175
          var nic_net  = nic.get_network();
1176
          return _.filter(this.networks, function(n) { 
1177
            return nic_net.id == n.id;
1178
          }).length > 0;
1179
        },
1180

  
1181
        get_nics: function() {
1182
          var n = _.flatten(_.map(this.networks, function(n){ return n.get_nics(); }));
1183
          return n
1184
        },
1185

  
1186
        add_network: function(net) {
1187
          this.networks[net.id] = net;
1188
        },
1189

  
1190
        remove_network: function(net) {
1191
          delete this.networks[net.id];
1192
          this.update_nics();
1193
        }
1194

  
1195
    })
1196
    
1197
    views.PrivateNetworkView = views.NetworkModelView.extend({
1198
        tpl: "#private-template",
1199
        nic_tpl: "#private-nic-template",
1200
        nic_id_tpl: "#nic-{0}"
1201
    })
1202

  
1203
    views.NetworksView = views.View.extend({
1204
        
1205
        view_id: "networks",
1206
        pane: "#networks-pane",
1207
        el: "#networks-pane",
1208

  
1209
        initialize: function() {
1210
            // elements shortcuts
1211
            this.create_cont = this.$("#networks-createcontainer");
1212
            this.container = this.$("#networks-container");
1213
            this.public_list = this.$(".public-networks");
1214
            this.private_list = this.$(".private-networks");
1215
            views.NetworksView.__super__.initialize.call(this);
1216
            this.init_handlers();
1217
            this.network_views = {};
1218
            this.public_network = false;
1219
            this.update_networks(storage.networks.models);
1220
            this.create_view = new views.NetworkCreateView();
1221
            this.connect_machines_view = new views.NetworkConnectVMsOverlay();
1222
        },
1223
        
1224
        exists: function(net) {
1225
            return this.network_views[net.id];
1226
        },
1227

  
1228
        add_or_update: function(net) {
1229
            var nv = this.exists(net);
1230
            if (!nv) {
1231
                if (net.is_public()){
1232
                  if (synnefo.config.group_public_networks) {
1233
                    if (!this.public_network) {
1234
                      // grouped public not initialized
1235
                      this.public_network = this.create_network_view(net);
1236
                    } else {
1237
                      // grouped public initialized, append
1238
                      this.public_network.add_network(net);
1239
                    }
1240
                    nv = this.public_network;
1241
                  } else {
1242
                    // no grouped view asked, fallback to default create
1243
                    nv = this.create_network_view(net);
1244
                  }
1245
                } else {
1246
                  nv = this.create_network_view(net);
1247
                }
1248

  
1249
                this.network_views[net.id] = nv;
1250
                
1251
                if (net.is_public()) {
1252
                    this.public_list.append(nv.el);
1253
                    this.public_list.show();
1254
                } else {
1255
                    this.private_list.append(nv.el);
1256
                    this.private_list.show();
1257
                }
1258
            }
1259

  
1260
            // update vms
1261
            // for cases where network servers list
1262
            // get updated after vm addition and
1263
            // vm_added_handler fails to append the
1264
            // vm to the list
1265
            nv.update_nics();
1266
            nv.update_layout();
1267
        },
1268
        
1269
        create_network_view: function(net) {
1270
            if (net.is_public()) {
1271
                if (synnefo.config.group_public_networks) {
1272
                  if (self.public_network) { return self.public_network }
1273
                  return new views.GroupedPublicNetworkView(net, this);
1274
                } else {
1275
                  return new views.PublicNetworkView(net, this);
1276
                }
1277
            }
1278
            return new views.PrivateNetworkView(net, this);
1279
        },
1280
        
1281
        init_handlers: function() {
1282
            storage.networks.bind("add", _.bind(this.network_added_handler, this, "add"));
1283
            storage.networks.bind("change", _.bind(this.network_changed_handler, this, "change"));
1284
            storage.networks.bind("reset", _.bind(this.network_changed_handler, this, "reset"));
1285
            storage.networks.bind("remove", _.bind(this.network_removed_handler, this, "remove"));
1286

  
1287
            this.$("#networkscreate").click(_.bind(function(e){
1288
              e.preventDefault();
1289
              if ($(this.$("#networkscreate")).hasClass("disabled")) { return }
1290
              this.create_view.show();
1291
            }, this));
1292
            
1293
            var self = this;
1294
            storage.networks.bind("quota_reached", function(){
1295
              self.$("#networkscreate").addClass("disabled").attr("title", 
1296
                                                            "Networks limit reached");
1297
            });
1298
            storage.networks.bind("quota_free", function(){
1299
              self.$("#networkscreate").removeClass("disabled").attr("title", 
1300
                                                            "");
1301
            });
1302
        },
1303

  
1304
        update_networks: function(nets) {
1305
            _.each(nets, _.bind(function(net){
1306
                if (net.get("status") == "DELETED") { return };
1307
                view = this.add_or_update(net);
1308
            }, this));
1309
        },
1310

  
1311
        show: function() {
1312
            this.container.show();
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff