Statistics
| Branch: | Tag: | Revision:

root / ui / static / snf / js / ui / web / ui_list_view.js @ 23a3bb8e

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

    
13
    var views = snf.views = snf.views || {}
14

    
15
    // shortcuts
16
    var bb = root.Backbone;
17
    
18
    views.ListMultipleActions = views.View.extend({
19
        
20
        view_id: "list_actions",
21

    
22
        initialize: function(view) {
23
            this.parent = view;
24
            this.el = this.parent.el;
25
           
26
            views.ListMultipleActions.__super__.initialize.call(this);
27
            this.set_handlers();
28
            this.update_layout();
29

    
30
            this.selected_action = undefined;
31
            this.available_actions = [];
32
            this.multi_view = synnefo.ui.main.multiple_actions_view;
33
        },
34

    
35
        set_handlers: function() {
36
            var self = this;
37
            storage.vms.bind("change:pending_action", function() {
38
                if (!storage.vms.has_pending_actions()) {
39
                    self.parent.$(".actions a").removeClass("selected");
40
                }
41
            })
42
            
43
            var self = this;
44
            this.parent.$(".actions a.enabled").live('click', function() {
45
                self.parent.$(".actions a").removeClass("selected");
46
                $(this).addClass("selected");
47
                self.parent.select_action($(this).attr("id").replace("action-",""));
48
            })
49
        },
50
        
51
        update_actions: function() {
52
            actions = undefined;
53
            this.available_actions = [];
54
            _.each(this.parent.get_selected_vms(), function(vm) {
55
                if (!actions) {
56
                    actions = vm.get_available_actions();
57
                    return;
58
                }
59
                actions = _.intersection(actions, vm.get_available_actions());
60
            });
61

    
62
            this.available_actions = actions;
63

    
64
            this.$(".actions a").removeClass("enabled");
65
            _.each(this.available_actions, _.bind(function(name){
66
                this.$("#action-" + name).addClass("enabled");
67
            }, this))
68
        },
69

    
70
        update_layout: function() {
71
            this.update_actions();
72
        }
73
    });
74

    
75
    // VMs list view
76
    views.ListView = views.VMListView.extend({
77
        
78
        // view id (this could be used to identify 
79
        // the view object from global context
80
        view_id: 'vm_list',
81

    
82
        el: '#machinesview-list',
83
        id_tpl: 'list-vm-',
84
        link_id_tpl: 'list-vm-at-',
85

    
86
        hide_actions: false,
87

    
88
        selectors: {
89
            'vms': '.list-container',
90
            'vm': '#list-vm-{0}',
91
            'view': '#machinesview-list',
92
            'tpl': '.list-container#machine-container-template',
93
            'spinner': '.large-spinner',
94
            'vm_spinner': '#list-vm-{0} .spinner',
95
            'vm_wave': '#list-vm-{0} .wave',
96
            'os_icon': '#list-vm-{0} .os_icon',
97
            'vm_cont_active': '#machinesview-list',
98
            'vm_cont_terminated': '#machinesview-list'
99
        },
100
        
101
        initialize: function() {
102
            this.current_vm = 0;
103
            
104
            // button selectors
105
            this.prev_button = this.$(".controls .previous");
106
            this.next_button = this.$(".controls .next");
107

    
108
            this.actions = this.$(".actions").show();
109
            this.datatable_cont = this.$(".dataTables_wrapper").show();
110
            this.content = this.$("#machinesview_content").show();
111
            this.filter = this.$(".dataTables_filter").show().css({'display':'block'});
112
            this.table_el = this.$(".list-machines").show();
113
            this.select_all = $("#list-view-select-all");
114

    
115
            this.actions = new views.ListMultipleActions(this);
116

    
117
            this.table = $("div.list table.list-machines").dataTable({
118
                "bInfo": false,
119
                "bRetrieve": true,
120
                "bPaginate": false,
121
                "bAutoWidth": false,
122
                "bSort": true,
123
                "bStateSave": true,
124
                "sScrollXInner": "500px",
125
                "aoColumnDefs": [
126
                    { "bSortable": false, "aTargets": [ 0 ] }
127
                ]
128
            });
129

    
130
            this.table_data = {};
131
            views.ListView.__super__.initialize.apply(this, arguments);
132
        },
133
        
134
        reset: function() {
135
        },
136

    
137
        hide_actions: function() {
138
            this.$(".actions a").removeClass("selected");
139
        },
140

    
141
        // overload show function
142
        show_view: function() {
143
            this.log.debug("showing");
144
            this.sel('spinner').hide();
145
            this.__update_layout();
146
        },
147
        
148
        check_vm_container: function() {
149
        },
150

    
151
        // identify vm model instance id based on DOM element
152
        vm_id_for_element: function(el) {
153
            return el.attr('id').replace("list-vm-", "");
154
        },
155

    
156
        reset_actions: function() {
157
            this.$(".actions a").removeClass("selected");
158
            storage.vms.reset_pending_actions();
159
        },
160
        
161
        // set generic view handlers
162
        set_handlers: function() {
163
            //init_action_indicator_handlers('list');
164

    
165
            this.$(".list-vm-checkbox").live('change', _.bind(function(){
166
                this.reset_actions();
167
                this.actions.update_layout();
168
                if (this.$("tbody input:checked").length > 0) {
169
                    this.select_all.attr("checked", true);
170
                } else {
171
                    this.select_all.attr("checked", false);
172
                }
173
            }, this))
174

    
175
            var self = this;
176
            this.select_all.click(function(){
177
                if ($(this).is(":checked")) {
178
                    self.$("tbody input").attr("checked", true);
179
                } else {
180
                    self.$("tbody input").attr("checked", false);
181
                }
182
                self.actions.update_layout();
183
            });
184
        },  
185

    
186
        get_selected_vms: function() {
187
            var selected = $(this.el).find(".list-vm-checkbox:checked");
188
            var vms = []
189
            _.each(selected, function(el){
190
                var id = parseInt($(el).attr("id").replace("checkbox-list-vm-", ""));
191
                vm = storage.vms.get(id);
192
                vms.push(vm);
193
            });
194

    
195
            return vms;
196
        },
197

    
198
        select_action: function(action) {
199
            this.reset_actions();
200
            this.$(".actions a#action-" + action).addClass("selected");
201
            var vms = this.get_selected_vms();
202
            _.each(vms, function(vm){
203
                vm.update_pending_action(action);
204
            })
205
        },
206

    
207
        reset: function() {
208
            this.reset_actions();
209
        },
210

    
211
        create_vm: function(vm) {
212
            params = this.get_vm_table_data(vm);
213
            var index = this.table.fnAddData.call(this.table, params);
214
            this.table_data["vm_" + vm.id] = {index: index[0], params: params};
215
            
216
            // append row id
217
            $(this.table.fnGetNodes(index)).attr("id", this.id_tpl + vm.id);
218
            
219
            // hide indicators on creation
220
            this.vm(vm).find(".spinner").hide();
221
            this.vm(vm).find(".wave").hide();
222
            this.vm(vm).find(".os_icon").show();
223
            
224
            // ancestor method
225
            this.__set_vm_handlers(vm);
226
            this.set_vm_handlers(vm);
227
            this.post_add(vm);
228
        },
229

    
230
        // remove vm
231
        remove_vm: function(vm) {
232
            var index = this.table_data["vm_" + vm.id].index;
233
            this.table.fnDeleteRow(index);
234
            delete this.table_data["vm_" + vm.id];
235
            this.update_data();
236
        },
237

    
238
        update_data: function() {
239
            var new_data = this.table.fnGetData();
240
            _.each(new_data, _.bind(function(row, i){
241
                this.table_data["vm_" + row[5]].index = i;
242
                this.table_data["vm_" + row[5]].params = row;
243
            }, this));
244
        },
245

    
246
        get_vm_table_data: function(vm) {
247
            var checkbox = '<input type="checkbox" class="' + 
248
                views.ListView.STATE_CLASSES[vm.state()].join(" ") + 
249
                ' list-vm-checkbox" id="checkbox-' + this.id_tpl + vm.id + '"/>';
250

    
251
            var img = '<img class="os_icon" src="'+ this.get_vm_icon_path(vm, "small") +'" />';
252
            img = img + '<img src="static/icons/indicators/small/progress.gif" class="spinner" />';
253
            img = img + '<img src="static/icons/indicators/medium/wave.gif" class="wave" />';
254

    
255
            var name = util.truncate(vm.get('name'), 20);
256
            var flavor = vm.get_flavor().details_string();
257
            var status = STATE_TEXTS[vm.state()];
258
            
259
            return [checkbox, img, name, flavor, status, vm.id];
260
        },
261

    
262
        post_add: function(vm) {
263
        },
264

    
265
        // is vm in transition ??? show the progress spinner
266
        update_transition_state: function(vm) {
267
            if (vm.in_transition()){
268
                this.sel('vm_spinner', vm.id).show();
269
                this.sel('vm_wave', vm.id).hide();
270
                this.sel('os_icon', vm.id).hide();
271
            } else {
272
                this.sel('vm_spinner', vm.id).hide();
273
            }
274
        },
275

    
276
        // display transition animations
277
        show_transition: function(vm) {
278
            var wave = this.sel('vm_wave', vm.id);
279
            if (!wave.length) {
280
                return
281
            }
282
            
283
            this.sel('vm_spinner', vm.id).hide();
284
            this.sel('os_icon', vm.id).hide();
285

    
286
            var src = wave.attr('src');
287
            var self = this;
288

    
289
            // change src to force gif play from the first frame
290
            // animate for 500 ms then hide
291
            wave.attr('src', "").show().attr('src', src).fadeIn(500).delay(700).fadeOut(300, function() {
292
                if (vm.in_transition()) {
293
                    self.sel("vm_spinner", vm.id).fadeIn(200);
294
                } else {
295
                    self.sel("os_icon", vm.id).fadeIn(200);
296
                }
297
            });
298
        },
299

    
300
        update_actions_layout: function(vm) {
301
        },
302

    
303
        post_update_vm: function(vm) {
304
            var index = this.table_data["vm_" + vm.id].index;
305
            params = this.get_vm_table_data(vm);
306
            this.table_data["vm_" + vm.id].params = params;
307
            data = this.table.fnGetData()[index];
308

    
309
            // do not recreate checkboxes and images to avoid messing
310
            // with user interaction
311
            this.table.fnUpdate(params[2], parseInt(index), 2);
312
            this.table.fnUpdate(params[3], parseInt(index), 3);
313
            this.table.fnUpdate(params[4], parseInt(index), 4);
314
            
315
            this.update_os_icon(vm);
316
            this.update_transition_state(vm);
317
        },
318

    
319
        update_os_icon: function(vm) {
320
            this.sel('os_icon', vm.id).attr('src', this.get_vm_icon_path(vm, "small"));
321
        },
322
        
323
        // vm specific event handlers
324
        set_vm_handlers: function(vm) {
325

    
326
        },
327

    
328
        // generic stuff to do on each view update
329
        // called once after each vm has been updated
330
        update_layout: function() {
331
            this.actions.update_layout();
332
        },
333

    
334
        // update vm details
335
        update_details: function(vm) {
336
        },
337
            
338
        get_vm_icon_os: function(vm) {
339
            var os = vm.get_os();
340
            var icons = window.os_icons || views.ListView.VM_OS_ICONS;
341
            if (icons.indexOf(os) == -1) {
342
                os = "unknown";
343
            }
344
            return os;
345
        },
346

    
347
        // TODO: move to views.utils (the method and the VM_OS_ICON vars)
348
        get_vm_icon_path: function(vm, icon_type) {
349
            var os = vm.get_os();
350
            var icons = window.os_icons || views.ListView.VM_OS_ICONS;
351

    
352
            if (icons.indexOf(os) == -1) {
353
                os = "unknown";
354
            }
355
            
356
            var st = "off";
357
            if (vm.is_active()) {
358
                st = "on"
359
            }
360

    
361
            return views.ListView.VM_OS_ICON_TPLS[icon_type].format(os, st);
362
        }
363
    })
364

    
365
    views.ListView.VM_OS_ICON_TPLS = {
366
        "small": "/static/icons/machines/small/{0}-{1}.png"
367
    }
368

    
369
    views.ListView.VM_OS_ICONS = window.os_icons || [];
370

    
371
    views.ListView.STATE_CLASSES = {
372
        'UNKNOWN':          ['error-state'],
373
        'BUILD':            ['build-state'],
374
        'REBOOT':           ['rebooting-state'],
375
        'STOPPED':          ['terminated-state'],
376
        'ACTIVE':           ['running-state'],
377
        'ERROR':            ['error-state'],
378
        'DELETE':           ['destroying-state'],
379
        'DESTROY':          ['destroying-state'],
380
        'BUILD_INIT':       ['build-state'], 
381
        'BUILD_COPY':       ['build-state'],
382
        'BUILD_FINAL':      ['build-state'],
383
        'SHUTDOWN':         ['shutting-state'],
384
        'START':            ['starting-state'],
385
        'CONNECT':          ['connecting-state'],
386
        'DISCONNECT':       ['disconnecting-state']
387
    };
388

    
389
})(this);