Revision a37c5497

b/snf-cyclades-app/synnefo/ui/static/snf/css/main.css
7290 7290
}
7291 7291

  
7292 7292
.select-item {
7293
  font-size: 0.9em;
7293
  font-size: 12px;
7294 7294
  padding: 5px 4px;
7295 7295
  margin-bottom: 3px;
7296 7296
  background-color: #efefef;
......
7345 7345
  width: 50%;
7346 7346
}
7347 7347

  
7348
.select-item.vm .status .indicators {
7349
  width: 60px;
7350
  float: left;
7351
  margin: 0px 0 0 0;
7352
}
7353

  
7354
.select-item.vm .status span {
7355
  text-align: right;
7356
  display: block;
7357
  width: 100px;
7358
  float: left;
7359
  font-size: 0.9em;
7360
  margin-top: 2px;
7361
}
7362

  
7363
.select-item.vm .status {
7364
  float: right;
7365
  margin-right: 0px;
7366
  width: 170px;
7367
}
7368

  
7348 7369
.select-item.private-network .cidr {
7349 7370
  float: right;
7350 7371
  width: 40%;
b/snf-cyclades-app/synnefo/ui/static/snf/js/models.js
1006 1006
        unbind: function() {
1007 1007
            models.VM.__super__.unbind.apply(this, arguments);
1008 1008
        },
1009
        
1010
        can_connect: function() {
1011
          return _.contains(["ACTIVE", "STOPPED"], this.get("status"))
1012
        },
1009 1013

  
1010 1014
        can_resize: function() {
1011 1015
          return this.get('status') == 'STOPPED';
b/snf-cyclades-app/synnefo/ui/static/snf/js/neutron.js
158 158
          this.update_connecting_status();
159 159
        }, this);
160 160
        this.set({ports: this.ports});
161

  
162
        this.connectable_vms = new Backbone.FilteredCollection(undefined, {
163
          collection: synnefo.storage.vms,
164
          collectionFilter: function(m) {
165
            return m.can_connect();
166
          }
167
        });
161 168
      },
162 169
      
163 170
      update_connecting_status: function() {
......
178 185
        return this.get('router:external')
179 186
      },
180 187

  
181
      pluggable_vms: function() {
182
        var vms = synnefo.storage.vms.models;
183
        // TODO: filter out vms
184
        return vms;
185
      },
186
      
187 188
      connect_vm: function(vm, cb) {
188 189
        var self = this;
189 190
        var data = {
b/snf-cyclades-app/synnefo/ui/static/snf/js/ui/web/ui_networks_view.js
383 383
      resolve_storage_object: function() {
384 384
        return this.collection
385 385
      },
386

  
386 387
      show_connect_vms_overlay: function() {
387 388
        this.parent_view.show_connect_vms_overlay();
388 389
      }
......
489 490

  
490 491
      show_connect_vms_overlay: function() {
491 492
        var view = new views.NetworkConnectVMsOverlay();
492
        vms = this.model.pluggable_vms();
493
        vms = this.model.connectable_vms;
493 494
        var cb = _.bind(function(vms) {
494 495
          view.set_in_progress();
495 496
          var cbinner = function() {
......
567 568
      collection_view_cls: views.NetworksCollectionView,
568 569
      collection_view_selector: '#networks-list-view'
569 570
    });
571
    
572
    views.VMSelectView = views.ext.SelectModelView.extend({
573
      tpl: '#vm-select-model-tpl',
574
      get_vm_icon: function() {
575
        return $(snf.ui.helpers.vm_icon_tag(this.model, "small")).attr("src")
576
      },
577

  
578
      status_cls: function() {
579
        return (views.IconView.STATE_CLASSES[this.model.get("state")] || []).join(" ") + " status clearfix"
580
      },
581
      status_display: function() {
582
        return STATE_TEXTS[this.model.get("state")]
583
      }
584
    });
585

  
586
    views.VMSelectView = views.ext.CollectionView.extend({
587
      init: function() {
588
        views.VMSelectView.__super__.init.apply(this);
589
      },
590
      tpl: '#vm-select-collection-tpl',
591
      model_view_cls: views.VMSelectView,
592
      
593
      trigger_select: function(view, select) {
594
        this.trigger("change:select", view, select);
595
      },
596

  
597
      post_add_model_view: function(view) {
598
        view.bind("change:select", this.trigger_select, this);
599
        if (!this.options.allow_multiple) {
600
          view.input.prop("type", "radio");
601
        }
602
      },
603

  
604
      post_remove_model_view: function(view) {
605
        view.unbind("change:select", this.trigger_select, this);
606
      },
607

  
608
      deselect_all: function(except) {
609
        _.each(this._subviews, function(view) {
610
          if (view != except) { view.deselect() }
611
        });
612
      },
613

  
614
      get_selected: function() {
615
        return _.filter(_.map(this._subviews, function(view) {
616
          if (view.selected) {
617
            return view.model;
618
          }
619
        }), function(m) { return m });
620
      }
621
    });
570 622

  
571 623
    views.NetworkConnectVMsOverlay = views.Overlay.extend({
572 624
        title: "Connect machine",
......
582 634
            // flag for submit handler to avoid duplicate bindings
583 635
            this.submit_handler_set = false;
584 636
            this.in_progress = false;
637

  
585 638
        },
586 639
        
640
        init_collection_view: function(collection) {
641
            this.collection_view = new views.VMSelectView({
642
              collection: collection,
643
              el: this.list,
644
              allow_multiple: this.allow_multiple
645
            });
646
            this.collection_view.show(true);
647
            this.list.append($(this.collection_view.el));
648
            if (!this.allow_multiple) {
649
              this.collection_view.bind("change:select", 
650
                                        function(view, selected) {
651
                if (!selected) { return }
652
                this.collection_view.deselect_all(view);
653
              }, this);
654
            }
655
        },
656

  
587 657
        handle_vm_click: function(el) {
588 658
            if (!this.allow_multiple) {
589 659
              $(el).closest("ul").find(".selected").removeClass("selected");
......
595 665

  
596 666
        init_handlers: function() {
597 667
            var self = this;
598
            this.list.find("li").click(function() {
599
                self.handle_vm_click($(this));
600
            });
601 668
            
602 669
            if (!this.submit_handler_set) {
603 670
                // avoid duplicate submits
......
609 676
                this.submit_handler_set = true;
610 677
            }
611 678
        },
612

  
613
        reset: function() {
614
            this.list.find("li").remove();
615
        },
616

  
679
        
680
        reset: function() {},
617 681
        beforeOpen: function() {
618 682
            this.reset();
619 683
            this.update_layout();
620 684
        },
621 685
        
622
        vm: function(vm) {
623
            if (vm.id) { var id = vm.id } else {var id = vm}
624
            return this.list.find(".vm-" + id);
625
        },
626

  
627 686
        get_selected: function() {
628
            return this.list.find(".selected").map(function() {return $(this).data('vm')})
687
          return this.collection_view.get_selected();
629 688
        },
630 689

  
631 690
        update_layout: function() {
......
638 697
                this.empty_message.hide();
639 698
            }
640 699

  
641
            _.each(this.vms, _.bind(function(vm){
642
                var html = '<li class="vm option options-object vm-{0}">' +
643
                           '<div class="options-object-cont">' +
644
                           '{2}' + 
645
                           '<span class="title">{1}</span>' + 
646
                           '<span class="value">{3}</span></div>' + 
647
                           '</li>';
648
                var el = $(html.format(vm.id, 
649
                       util.truncate(_.escape(vm.get("name")), 23), 
650
                       snf.ui.helpers.vm_icon_tag(vm, "small", {'class':'os'}),
651
                       _.escape(vm.get_os())
652
                ));
653
                el.data({vm:vm, vm_id:vm.id});
654
                this.list.append(el);
655

  
656
                vm.bind("remove", function(){ el.remove()})
657
                vm.bind("change:name", function(i,v){el.find(".title").text(v)})
658
            }, this));
659
            
660 700
            this.init_handlers();
661
            this.set_selected();
662 701
        },
663 702

  
664
        set_selected: function() {
665
            _.each(this.selected, _.bind(function(el){
666
                this.vm(el).addClass("selected");
667
            }, this));
668
        },
669
        
670 703
        set_in_progress: function() {
671 704
          this.$(".form-action").addClass("in-progress");
672 705
          this.in_progress = true;
......
678 711
        },
679 712

  
680 713
        show_vms: function(network, vms, selected, callback, subtitle) {
714
            this.init_collection_view(vms);
681 715
            this.network = network;
682 716
            this.reset();
683 717
            if (network) {
......
691 725
            this.unset_in_progress();
692 726
            this.show(true);
693 727
        },
728
        
729
        onClose: function() {
730
          this.collection_view.hide(true);
731
          delete this.collection_view;
732
        },
694 733

  
695 734
        submit: function() {
696 735
            if (!this.get_selected().length) { return }
......
698 737
        }
699 738
    });
700 739
    
701
    views.NetworkSelectModelView = views.ext.ModelView.extend({
702
      select: function() {
703
        if (!this.delegate_checked) {
704
          this.input.attr("checked", true);
705
          this.item.addClass("selected");
706
        }
707
        this.selected = true;
708
        this.trigger("change:select", this, this.selected);
709
      },
710

  
711
      deselect: function() {
712
        if (!this.delegate_checked) {
713
          this.input.attr("checked", false);
714
          this.item.removeClass("selected");
715
        }
716
        this.selected = false;
717
        this.trigger("change:select", this, this.selected);
718
      },
719
      
720
      toggle_select: function() {
721
        if (this.selected) { 
722
          this.deselect();
723
        } else {
724
          this.select();
725
        }
726
      },
727

  
728
      post_init_element: function() {
729
        this.input = $(this.$("input").get(0));
730
        this.item = $(this.$(".select-item").get(0));
731
        this.delegate_checked = this.model.get('noselect');
732
        this.deselect();
733

  
734
        var self = this;
735
        if (self.model.get('forced')) {
736
          this.select();
737
          this.input.attr("disabled", true);
738
          $(this.el).attr('title', this.forced_title);
739
          $(this.el).tooltip({
740
            'tipClass': 'tooltip', 
741
            'position': 'top center',
742
            'offset': [29, 0]
743
          });
744
        }
745
        
746
        $(this.item).click(function(e) {
747
          if (self.model.get('forced')) { return }
748
          e.stopPropagation();
749
          self.toggle_select();
750
        });
751
        
752
        views.NetworkSelectModelView.__super__.post_init_element.apply(this,
753
                                                                       arguments);
754
      }
755
    });
740
    views.NetworkSelectModelView = views.ext.SelectModelView.extend({});
756 741

  
757 742
    views.NetworkSelectNetworkTypeModelView = views.NetworkSelectModelView.extend({
758 743
      get_network_icon: function() {
b/snf-cyclades-app/synnefo/ui/static/snf/js/views_ext.js
518 518
        }
519 519
      }
520 520
    });
521

  
522
    views.ext.SelectModelView = views.ext.ModelView.extend({
523
      select: function() {
524
        if (!this.delegate_checked) {
525
          this.input.attr("checked", true);
526
          this.item.addClass("selected");
527
        }
528
        this.selected = true;
529
        this.trigger("change:select", this, this.selected);
530
      },
531

  
532
      deselect: function() {
533
        if (!this.delegate_checked) {
534
          this.input.attr("checked", false);
535
          this.item.removeClass("selected");
536
        }
537
        this.selected = false;
538
        this.trigger("change:select", this, this.selected);
539
      },
540
      
541
      toggle_select: function() {
542
        if (this.selected) { 
543
          this.deselect();
544
        } else {
545
          this.select();
546
        }
547
      },
548

  
549
      post_init_element: function() {
550
        this.input = $(this.$("input").get(0));
551
        this.item = $(this.$(".select-item").get(0));
552
        this.delegate_checked = this.model.get('noselect');
553
        this.deselect();
554

  
555
        var self = this;
556
        if (self.model.get('forced')) {
557
          this.select();
558
          this.input.attr("disabled", true);
559
          $(this.el).attr('title', this.forced_title);
560
          $(this.el).tooltip({
561
            'tipClass': 'tooltip', 
562
            'position': 'top center',
563
            'offset': [29, 0]
564
          });
565
        }
566
        
567
        $(this.item).click(function(e) {
568
          if (self.model.get('forced')) { return }
569
          e.stopPropagation();
570
          self.toggle_select();
571
        });
572
        
573
        views.ext.SelectModelView.__super__.post_init_element.apply(this,
574
                                                                    arguments);
575
      }
576
    });
577

  
521 578
    
522 579
    views.ext.ModelCreateView = views.ext.ModelView.extend({});
523 580
    views.ext.ModelEditView = views.ext.ModelCreateView.extend({});
b/snf-cyclades-app/synnefo/ui/templates/partials/machines.html
32 32
{% include "partials/manage_metadata.html" %}
33 33
{% include "partials/vm_connect.html" %}
34 34

  
35
<div id="vm-select-collection-tpl" class="hidden">
36
  <div class="collection fixed-ips-list">
37
    <div class="empty-list hidden">No available machines.</div>
38
    <div class="items-list clearfix"></div>
39
  </div>
40
</div>
41

  
42
<div id="vm-select-model-tpl" class="hidden">
43
  <div class="select-item clearfix vm">
44
    <div class="checkbox">
45
      <input type="checkbox" data-rv-data-id="model.id" />
46
    </div>
47
    <div class="ico"><img data-rv-src="model.status|get_vm_icon" /></div>
48
    <div class="name">
49
      <span class="" data-rv-text="model.name"></span>
50
      <div data-rv-class="model.state|status_cls">
51
        <span data-rv-text="model.state|status_display"></span>
52
        <div class="indicators">
53
          <div class="indicator1"></div>
54
          <div class="indicator2"></div>
55
          <div class="indicator3"></div>
56
          <div class="indicator4"></div>
57
        </div>
58
      </div>
59
    </div>
60
  </div>
61
</div>
62

  
35 63
<div id="vm-port-ips-tpl" class="hidden">
36 64
  <div class="collection fixed-ips-list">
37 65
    <div class="empty-list hidden">pending ...</div>

Also available in: Unified diff