Statistics
| Branch: | Tag: | Revision:

root / ui / templates / standard.html @ daa78d17

History | View | Annotate | Download (19.5 kB)

1
{% load i18n %}
2

    
3
<!-- the standard view -->
4
<div id="machinesview" class="standard">
5
    <div id="spinner"></div>
6
    <div class="machine" id="machine-template" style="display:none">
7
        <div class="actions">
8
            <a href="#" class="action-start">{% trans "Start" %}</a>
9
            <a href="#" class="action-reboot">{% trans "Reboot" %}</a>
10
            <a href="#" class="action-shutdown">{% trans "Shutdown" %}</a>
11
            <a href="#" class="action-destroy">{% trans "Destroy" %}</a>
12
        </div>        
13
        <div class="state">
14
            <div class="status">{% trans "Running" %}</div>
15
            <div class="indicator"></div>
16
            <div class="indicator"></div>
17
            <div class="indicator"></div>
18
            <div class="indicator"></div>
19
            <img class="spinner" style="display:none" src="/static/progress.gif" />
20
            <img class="wave" style="display:none" src="/static/wave.gif" />
21
        </div>
22
        <img class="logo" src="" />
23
        <div href="#" class="name">
24
            <h5 class="namecontainer editable">
25
                {% trans "Name: " %}<span class="name">node.name</span><span class="rename"></span>
26
                <div class="editbuttons" style="display:none">
27
                    <span class="save" />
28
                    <span class="cancel" />
29
                </div>
30
            </h5>
31
        </div>
32
        <a href="#" class="ip">
33
            <h5>{% trans "IP: " %}<span class="public">node.public_ip</span></h5>
34
        </a>
35
        <h5 class="settings">
36
            {% trans "Show:" %} 
37
            <a class="show-disks"href="#">{% trans "disks" %}</a> | 
38
            <a class="show-networks"href="#">{% trans "networks" %}</a> | 
39
            <a class="show-info" href="#">{% trans "more info" %}</a>
40
        </h5>
41
        <div class="confirm_single">
42
            <button class="yes">{% trans "Confirm" %}</button>
43
            <button class="no">{% trans "Cancel" %}</button>
44
        </div>
45
        <div class="action_error" align="center">
46
            {% trans "<span class='orange'>Error</span> on" %} <span class="action">{% trans "error action" %}</span>
47
            <span class="code"></span>            
48
            <span class="message"></span>
49
            <button class="details">{% trans "Details" %}</button>
50
        </div>
51
        <div class="separator"></div>
52
    </div>
53
    <div class="running"></div>
54
    <div id="mini" class="separator"></div>
55
    <div class="terminated"></div>
56
</div>
57

    
58
<script>
59

60
// intercept edit metadata click
61
$("a.show-info").live('click', function() {
62
    // get server name and server ID
63
    var serverID = $(this).parent().parent().attr("id");
64
    var serverName = $(this).parent().parent().find("span.name").text();
65
    // set server name to all related metadata dialogs
66
    $("#edit-dialog h3 span").text(serverName);
67
    $("#add-dialog h3 span").text(serverName);
68
    // set server id to all related metadata dialogs
69
    $("#edit-dialog h3 p").text(serverID);
70
    $("#add-dialog h3 p").text(serverID);
71
    show_metadata_edit_dialog();
72
    return false;
73
});
74

75
//initiate machine renaming
76
$(".rename, h5.editable span.name").live('click', function() {
77
    $(this).parent().find('.name').html("<input id=\"txtEdit\" type=\"text\" class=\"nametextbox\" value=\"" +
78
                                        $(this).parent().find('.name').text() + 
79
                                        "\" / ><span class=\"oldValue\" style=\"display:none;\" >" + 
80
                                        $(this).parent().find('.name').text() + "</span>");
81
    $(this).parent().find('.rename').hide();
82
    $(this).parent().find(".editbuttons").fadeIn();
83
    $(this).parent().find(".nametextbox").focus();
84
    $(this).parent().removeClass('editable');
85
    return false;
86
});
87

88
//rename machine
89
$(".editbuttons .save").live('click', function() {
90
    serverID = $(this).closest('.machine').attr("id");
91
    serverName = $(this).parent().parent().find('.name').find('.nametextbox').val();
92
    if (serverName.trim() == ''){
93
        return false;
94
    }
95
    $(this).parent().parent().find('.name').html($(this).parent().parent().find('.nametextbox').val());
96
    $(this).parent().parent().find(".editbuttons").fadeOut("fast");
97
    $(this).parent().parent().find(".rename").fadeIn("slow");
98
    rename(serverID, serverName);
99
    return false;
100
});
101

102
//cancel renaming
103
$(".editbuttons .cancel").live('click', function() {
104
    $(this).parent().parent().find('.name').html($(this).parent().parent().find('.name').find('.oldValue').text());
105
    $(this).parent().parent().find(".editbuttons").hide();
106
    $(this).parent().parent().find(".rename").fadeIn();
107
    $(this).parent().parent().addClass('editable');
108
});
109

110
// intercept reboot click 
111
$("div.actions a.action-reboot").live('click', function(){
112
    var serverID = $(this).parent().parent().attr("id");
113
    var serverName = $(this).parent().prevAll("div.name").find("span.name").text();
114
    var found = false;
115
    
116
    $(this).parent().children('a').removeClass('selected');
117
    $(this).addClass('selected');
118
    $(this).parent().addClass('display');
119
    $(this).parent().parent().find('.action_error').hide();
120
    for (i=0;i<pending_actions.length;i++){ // if there is already a pending action for this server replace it
121
        if (pending_actions[i][1]==serverID){
122
            pending_actions[i][0] = reboot;
123
            found = true
124
        }
125
    }
126
    if (!found) // no pending action for this server was found, so let's just add it to the list
127
        pending_actions.push([reboot, serverID, serverName])
128
    update_confirmations();
129
    return false;
130
});
131

132
// intercept shutdown click
133
$("div.actions a.action-shutdown").live('click', function(){ 
134
    var serverID = $(this).parent().parent().attr("id");
135
    var serverName = $(this).parent().prevAll("div.name").find("span.name").text();
136
    var found = false;
137
    $(this).parent().children('a').removeClass('selected');
138
    $(this).addClass('selected');
139
    $(this).parent().addClass('display')
140
    $(this).parent().parent().find('.action_error').hide();
141

142
    for (i=0;i<pending_actions.length;i++){ // if there is already a pending action for this server replace it
143
        if (pending_actions[i][1]==serverID){
144
            pending_actions[i][0] = shutdown;
145
            found = true
146
        }
147
    }
148
    if (!found) // no pending action for this server was found, so let's just add it to the list 
149
        pending_actions.push([shutdown, serverID, serverName])
150
    update_confirmations();
151
    return false;
152
});
153

154
// intercept start click
155
$("div.actions a.action-start").live('click', function(){ 
156
    var serverID = $(this).parent().parent().attr("id");
157
    var serverName = $(this).parent().prevAll("div.name").find("span.name").text();
158
    var found = false;
159
    $(this).parent().children('a').removeClass('selected');
160
    $(this).addClass('selected');
161
    $(this).parent().addClass('display')
162
    $(this).parent().parent().find('.action_error').hide();
163

164
    for (i=0;i<pending_actions.length;i++){ // if there is already a pending action for this server replace it
165
        if (pending_actions[i][1]==serverID){
166
            pending_actions[i][0] = start;
167
            found = true
168
        }
169
    }
170
    if (!found) // no pending action for this server was found, so let's just add it to the list
171
        pending_actions.push([start, serverID, serverName])
172
    update_confirmations();    
173
    return false;
174
});
175

176
// intercept destroy click
177
$("div.actions a.action-destroy").live('click', function(){ 
178
    var serverID = $(this).parent().parent().attr("id");
179
    var serverName = $(this).parent().prevAll("div.name").find("span.name").text();
180
    var found = false;
181
    $(this).parent().children('a').removeClass('selected');
182
    $(this).addClass('selected');
183
    $(this).parent().addClass('display')
184
    $(this).parent().parent().find('.action_error').hide();
185

186
    for (i=0;i<pending_actions.length;i++){ // if there is already a pending action for this server replace it
187
        if (pending_actions[i][1]==serverID){
188
            pending_actions[i][0] = destroy;
189
            found = true
190
        }
191
    }
192
    if (!found) // no pending action for this server was found, so let's just add it to the list
193
        pending_actions.push([destroy, serverID, serverName])
194
    update_confirmations();    
195
    return false;
196
});
197

198
$("div.confirm_single .yes").live('click', function(){
199
    var serverID = $(this).parent().parent().attr("id");
200
    for (i=0;i<pending_actions.length;i++){ // if there is a pending action for this server execute it
201
        if (pending_actions[i][1]==serverID){
202
            action = pending_actions.splice(i,1)[0]; // extract action
203
            // change the status text in cases where no api state exists
204
            if (action[0] == start) {
205
                $(this).parent().parent().find('.status').text('Starting');
206
                $(this).parent().parent().find('.spinner').show();
207
            } else if (action[0] == shutdown) {
208
                $(this).parent().parent().find('.status').text('Shutting down');
209
                $(this).parent().parent().find('.spinner').show();
210
            } else if (action[0] == reboot) {
211
                $(this).parent().parent().find('.status').text('Rebooting');
212
                $(this).parent().parent().find('.spinner').show();
213
            }  else if (action[0] == destroy) {
214
                $(this).parent().parent().find('.status').text('Destroying');
215
                $(this).parent().parent().find('.spinner').show();
216
            }                    
217
            action[0]([action[1]]); // execute action
218
        }
219
    }
220
    $(this).parent().hide();
221
    $(this).parent().parent().children('div.actions').children('a').removeClass('selected');
222
    $(this).parent().parent().children('.state').children('.spinner').show()
223
    $(this).parent().parent().children('div.actions').removeClass('display');
224
    update_confirmations(); 
225
    return false;
226
});
227

228
$("div.confirm_single .no").live('click', function(){
229
    // remove the action from the pending list
230
    var serverID = $(this).parent().parent().attr("id");
231
    
232
    $(this).parent().parent().children('div.actions').children('a').removeClass('selected');
233
    $(this).parent().parent().children('div.actions').removeClass('display');    
234
    for (i=0;i<pending_actions.length;i++){ // if there is a pending action for this server remove it
235
        if (pending_actions[i][1]==serverID){
236
            pending_actions.splice(i,1);
237
        }
238
    }
239
    $(this).parent().hide();
240
    update_confirmations();    
241
    return false;
242
});
243

244
$("div.action_error .details").live('click', function(){
245
    // remove the action from the pending list
246
    ajax_error($(this).parent().children('.code').text(), undefined, $(this).parent().children('.action').text(), $(this).parent().children('.message').text());
247
    $(this).parent().hide();
248
});
249

250

251
// update the servers list
252
function update_machines_view(data){
253
    /* 
254
    Go through the servers in the input data. Update existing entries, add
255
    new ones to the list
256
    */
257
    
258
    $.each(data.servers.values, function(i,server){
259
    
260
        existing = $('#' + server.id);
261
        
262
        // if multiple machines exist in the DOM, delete all but one
263
        // defensive coding - that shouldn't happen normally
264
        while (existing.length > 1){
265
            existing.remove();
266
        }
267

268
        var server_image = os_icon(server.metadata);
269

270
        // server already exists in DOM
271
        if (existing.length){
272
            $("div.machine:last-child").find("div.separator").show();                
273
            //  if the status is deleted, delete it from the DOM
274
            if (server.status == 'DELETED') {
275
                existing.remove();
276
                try {
277
                    console.info(existing.find("div.name span.name").text() + ' removed');
278
                } catch(err) {}            
279
            } else if (existing.find(".status").text() != STATUS_MESSAGES[server.status]) {
280
                try { // firebug console logging
281
                    console.info(existing.find("div.name span.name").text() + ' from ' 
282
                                + existing.find(".status").text() + ' to ' + STATUS_MESSAGES[server.status]);
283
                } catch(err) {}
284
                //show reboot and shutdown actions
285
                if (server.status == 'ACTIVE' || server.status == 'REBOOT') {
286
                    
287
                    $('div.#' + server.id + ' a.action-reboot').attr('style','');
288
                    $('div.#' + server.id + ' a.action-shutdown').attr('style','');
289
                    $('div.#' + server.id + ' a.action-destroy').removeClass('destroy-padding');        
290
                }
291
                if (['BUILD','ACTIVE','REBOOT'].indexOf(server.status) >= 0 &&
292
                    [STATUS_MESSAGES['STOPPED'], STATUS_MESSAGES['ERROR'],
293
                     'Starting'].indexOf(existing.find(".status").text()) >= 0) {
294
                    // from stopped, on error or starting to building, active or rebooting
295
                    // starting is not an api state, it means the vm is stopped or on error
296
                    moved = existing.clone().appendTo(".running");
297
                    moved.find("img.logo").attr("src","static/machines/" + server_image + '-on.png');
298
                    existing.remove();
299
                    existing = moved;
300
                    existing.find(".status").text(STATUS_MESSAGES[server.status]); 
301
                } else if (['STOPPED','ERROR'].indexOf(server.status) >= 0 &&
302
                           [STATUS_MESSAGES['ACTIVE'], STATUS_MESSAGES['BUILD'], STATUS_MESSAGES['REBOOT'],
303
                            'Shutting down', 'Starting'].indexOf(existing.find(".status").text()) >= 0) {
304
                    // from active, building, rebooting, or shutting down to stopped or on error
305
                    // shutting down is not an api state, it means the server is active
306
                    moved = existing.clone().appendTo(".terminated");
307
                    moved.find("img.logo").attr("src","static/machines/" + server_image + '-off.png');
308
                    existing.remove();
309
                    existing = moved;
310
                    existing.find(".status").text(STATUS_MESSAGES[server.status]); 
311
                } else if (['BUILD','ACTIVE','REBOOT'].indexOf(server.status) >= 0 && 
312
                            [STATUS_MESSAGES['ACTIVE'], STATUS_MESSAGES['BUILD'],
313
                             STATUS_MESSAGES['REBOOT']].indexOf(existing.find(".status").text()) >= 0) {
314
                    // the server changes status, but remains in running list
315
                    existing.find(".status").text(STATUS_MESSAGES[server.status]); 
316
                } else if (['STOPPED','ERROR'].indexOf(server.status) >= 0 &&
317
                    [STATUS_MESSAGES['STOPPED'], 
318
                     STATUS_MESSAGES['ERROR']].indexOf(existing.find(".status").text()) >= 0) {
319
                    // the server changes status, but remains in terminated list
320
                    existing.find(".status").text(STATUS_MESSAGES[server.status]); 
321
                }        
322
                existing.find('.spinner').hide();
323
                existing.find(' .wave').attr('src','static/wave.gif').show();
324
                setTimeout("$('#" + server.id +" .wave').attr('src','').hide()", 3000);
325
                // show spinner while the server is rebooting, starting or shutting down  
326
                if ([STATUS_MESSAGES['REBOOT'], 
327
                    'Starting', 'Shutting down'].indexOf(existing.find(".status").text()) >= 0 ) {
328
                    existing.find(' .wave').hide();
329
                    existing.find('.spinner').show();
330
                }                            
331
            }
332
            //existing.find(".status").text(STATUS_MESSAGES[server.status]);
333
            existing.find("div.name span.name").text(server.name.substring(0,100));
334
            existing.find("a.ip span.public").text(String(server.addresses.values[0].values[0].addr).replace(',',' '));
335
        } else if (server.status != 'DELETED') {
336
            // If it does not exist and it's not deleted, we should create it
337
            var machine = $("#machine-template").clone().attr("id", server.id).fadeIn("slow");
338
            machine.find("div.name span.name").text(server.name.substring(0,100));
339
            machine.find("img.logo").attr("src","static/machines/"+server_image+'-on.png');
340
            machine.find("span.imagetag").text(server_image);
341
            machine.find("a.ip span.public").text(String(server.addresses.values[0].values[0].addr).replace(',',' '));            
342
            machine.find(".status").text(STATUS_MESSAGES[server.status]);
343
            if (['BUILD', 'ACTIVE', 'REBOOT'].indexOf(server.status) >= 0){
344
                machine.appendTo(".running");
345
            } else {
346
                machine.find("img.logo").attr("src","static/machines/"+server_image+'-off.png');
347
                machine.appendTo(".terminated");
348
            }
349
            //show spinner while machine is building
350
            if (server.status == 'BUILD' || 
351
                ['Starting', 'Shutting down'].indexOf(existing.find(".status").text()) >= 0 ) { 
352
                machine.find('.spinner').show();
353
            }   
354
            //allow destroy action only while machine is building
355
            if (server.status == 'BUILD') {
356
                $('div.#' + server.id + ' a.action-reboot').hide();
357
                $('div.#' + server.id + ' a.action-shutdown').hide();        
358
                $('div.#' + server.id + ' a.action-destroy').addClass('destroy-padding');        
359
            }
360
        } 
361
    });
362

363
    $("#spinner").hide();
364
    // show all separators
365
    $("div.machine div.separator").show();
366
    // hide the last one
367
    $("div.machine:last-child").find("div.separator").hide();
368
    // the separator shows only when running and terminated machines are available
369
    if ($(".terminated div.name").length > 0 && $(".running div.name").length > 0) {
370
        $("#mini.separator").fadeIn("slow");
371
    } else {
372
        $("#mini.separator").fadeOut("slow");
373
    }
374
    
375
    // show message in case user has no servers!
376
    if ($('.machine').length < 2) {
377
        showWelcome();
378
    } else {
379
        hideWelcome();
380
    }
381
    
382
    // set confirm box position
383
    if (window.innerHeight - 220 < $('#machinesview').height())
384
        $('.confirm_multiple').addClass('fixed');
385
    else
386
        $('.confirm_multiple').removeClass('fixed');
387
}
388

389
// indicate that the requested action was succesfully completed
390
function display_success(serverID) {
391

392
}
393

394
// indicate that the requested action was not completed
395
function display_failure(status, serverID, action, responseText) {
396
    $('#'+serverID+ ' .spinner').hide();
397
    $('#'+serverID+ ' .action_error .action').text(action);
398
    $('#'+serverID+ ' .action_error .code').text(status);
399
    $('#'+serverID+ ' .action_error .message').text(responseText);
400
    $('#'+serverID+ ' .action_error').show();    
401
}
402

403
// basic functions executed on page load
404
if ( flavors.length == 0 && images.length == 0 ) {
405
    // configure flavors, this also calls update_vms(UPDATE_INTERVAL)
406
    update_flavors();
407
    // populate image list
408
    update_images(); 
409
} else if ( flavors.length == 0 && images.length != 0 ) {
410
    // configure flavors, this also calls update_vms(UPDATE_INTERVAL)
411
    update_flavors();
412
} else if ( flavors.length != 0 && images.length == 0 ) {
413
    // populate image list
414
    update_images(); 
415
    update_vms(UPDATE_INTERVAL);
416
} else {
417
    // start updating vm list
418
    update_vms(UPDATE_INTERVAL);
419
}
420

421
// set the label of the multiple buttons 
422
$('div.confirm_multiple button.yes').text('Confirm All');
423
$('div.confirm_multiple button.no').text('Cancel All');
424

425
// reposition multiple confirmation box on window resize
426
$(window).resize(function(){
427
    if (this.innerHeight - 220 < $('#machinesview').height())
428
        $('.confirm_multiple').addClass('fixed');
429
    else
430
        $('.confirm_multiple').removeClass('fixed');
431
});
432
</script>