root / ui / templates / standard.html @ 6902f72e
History | View | Annotate | Download (12.9 kB)
1 |
{% load i18n %} |
---|---|
2 |
|
3 |
<!-- the standard view -->
|
4 |
<div id="machinesview" class="standard"> |
5 |
<div id="emptymachineslist"><h1 id="welcomeheader">{% trans "Welcome to the ocean!" %}</h1><br /> |
6 |
<span class="welcomebody">From this panel you will be able to manage your Virtual Machines (VMs). If you don't know what a VM is: take the <a href="#">tour</a>.</span><br /><br /> |
7 |
<span class="welcomebody">The panel is currently empty, because you don't have any VMs yet. You can start by creating your new VM by clicking the blue button on the right. The wizard will guide you through the hole process.</span><br /><br /> |
8 |
<span class="welcomefooter">For more information or text, click <a href="#">here</a>.</span> |
9 |
</div>
|
10 |
<div id="spinner"></div> |
11 |
<div class="machine" id="machine-template" style="display:none"> |
12 |
<div class="actions"> |
13 |
<a href="#" class="action-start">{% trans "Start" %}</a> |
14 |
<a href="#" class="action-reboot">{% trans "Reboot" %}</a> |
15 |
<a href="#" class="action-shutdown">{% trans "Shutdown" %}</a> |
16 |
<a href="#" class="more">{% trans "more …" %}</a> |
17 |
</div>
|
18 |
<div class="state"> |
19 |
<div class="status">{% trans "Running" %}</div> |
20 |
<div class="indicator"></div> |
21 |
<div class="indicator"></div> |
22 |
<div class="indicator"></div> |
23 |
<div class="indicator"></div> |
24 |
<img class="spinner" style="display:none" src="/static/progress.gif" /> |
25 |
<img class="wave" style="display:none" src="/static/wave.gif" /> |
26 |
</div>
|
27 |
<img class="logo" src="" /> |
28 |
<a href="#" class="name"> |
29 |
<h5>Name: <span class="name">node.name</span><span class="rename"></span></h5> |
30 |
</a>
|
31 |
<a href="#" class="ip"> |
32 |
<h5>IP: <span class="public">node.public_ip</span></h5> |
33 |
</a>
|
34 |
<h5 class="settings"> |
35 |
{% trans "Show:" %} <a href="#">{% trans "disks" %}</a> | <a href="#">{% trans "networks" %}</a> | <a href="#">{% trans "group" %}</a> |
36 |
</h5>
|
37 |
|
38 |
<div class="confirm_single"> |
39 |
<button class="yes">{% trans "Confirm" %}</button> |
40 |
<button class="no">{% trans "Cancel" %}</button> |
41 |
</div>
|
42 |
<div class="action_error" align="center"> |
43 |
{% trans "<span class='orange'>Error</span> on" %} <span class="action">error action</span> |
44 |
<span class="code"></span> |
45 |
<span class="message"></span> |
46 |
<button class="details">Details</button> |
47 |
</div>
|
48 |
<div class="separator"></div> |
49 |
</div>
|
50 |
|
51 |
<div class="running"></div> |
52 |
<div id="mini" class="separator"></div> |
53 |
<div class="terminated"></div> |
54 |
</div>
|
55 |
|
56 |
<script>
|
57 |
|
58 |
// intercept reboot click
|
59 |
$("div.actions a.action-reboot").live('click', function(){
|
60 |
var serverID = $(this).parent().parent().attr("id");
|
61 |
var serverName = $(this).parent().prevAll("a.name").find("span.name").text();
|
62 |
var found = false;
|
63 |
|
64 |
$(this).parent().children('a').removeClass('selected');
|
65 |
$(this).addClass('selected');
|
66 |
$(this).parent().addClass('display');
|
67 |
$(this).parent().parent().find('.action_error').hide();
|
68 |
for (i=0;i<pending_actions.length;i++){ // if there is already a pending action for this server replace it
|
69 |
if (pending_actions[i][1]==serverID){
|
70 |
pending_actions[i][0] = reboot;
|
71 |
found = true
|
72 |
}
|
73 |
}
|
74 |
if (!found) // no pending action for this server was found, so let's just add it to the list
|
75 |
pending_actions.push([reboot, serverID, serverName])
|
76 |
update_confirmations();
|
77 |
return false;
|
78 |
});
|
79 |
|
80 |
// intercept shutdown click
|
81 |
$("div.actions a.action-shutdown").live('click', function(){
|
82 |
var serverID = $(this).parent().parent().attr("id");
|
83 |
var serverName = $(this).parent().prevAll("a.name").find("span.name").text();
|
84 |
var found = false;
|
85 |
$(this).parent().children('a').removeClass('selected');
|
86 |
$(this).addClass('selected');
|
87 |
$(this).parent().addClass('display')
|
88 |
$(this).parent().parent().find('.action_error').hide();
|
89 |
|
90 |
for (i=0;i<pending_actions.length;i++){ // if there is already a pending action for this server replace it
|
91 |
if (pending_actions[i][1]==serverID){
|
92 |
pending_actions[i][0] = shutdown;
|
93 |
found = true
|
94 |
}
|
95 |
}
|
96 |
if (!found) // no pending action for this server was found, so let's just add it to the list
|
97 |
pending_actions.push([shutdown, serverID, serverName])
|
98 |
update_confirmations();
|
99 |
return false;
|
100 |
});
|
101 |
|
102 |
// intercept start click
|
103 |
$("div.actions a.action-start").live('click', function(){
|
104 |
var serverID = $(this).parent().parent().attr("id");
|
105 |
var serverName = $(this).parent().prevAll("a.name").find("span.name").text();
|
106 |
var found = false;
|
107 |
$(this).parent().children('a').removeClass('selected');
|
108 |
$(this).addClass('selected');
|
109 |
$(this).parent().addClass('display')
|
110 |
$(this).parent().parent().find('.action_error').hide();
|
111 |
|
112 |
for (i=0;i<pending_actions.length;i++){ // if there is already a pending action for this server replace it
|
113 |
if (pending_actions[i][1]==serverID){
|
114 |
pending_actions[i][0] = start;
|
115 |
found = true
|
116 |
}
|
117 |
}
|
118 |
if (!found) // no pending action for this server was found, so let's just add it to the list
|
119 |
pending_actions.push([start, serverID, serverName])
|
120 |
update_confirmations();
|
121 |
return false;
|
122 |
});
|
123 |
|
124 |
$("div.confirm_single .yes").live('click', function(){
|
125 |
var serverID = $(this).parent().parent().attr("id");
|
126 |
for (i=0;i<pending_actions.length;i++){ // if there is a pending action for this server execute it
|
127 |
if (pending_actions[i][1]==serverID){
|
128 |
action = pending_actions.splice(i,1)[0]; // extract action
|
129 |
action[0]([action[1]]); // execute action
|
130 |
}
|
131 |
}
|
132 |
$(this).parent().hide();
|
133 |
$(this).parent().parent().children('div.actions').children('a').removeClass('selected');
|
134 |
$(this).parent().parent().children('.state').children('.spinner').show()
|
135 |
$(this).parent().parent().children('div.actions').removeClass('display');
|
136 |
update_confirmations();
|
137 |
return false;
|
138 |
});
|
139 |
|
140 |
$("div.confirm_single .no").live('click', function(){
|
141 |
// remove the action from the pending list
|
142 |
var serverID = $(this).parent().parent().attr("id");
|
143 |
|
144 |
$(this).parent().parent().children('div.actions').children('a').removeClass('selected');
|
145 |
$(this).parent().parent().children('div.actions').removeClass('display');
|
146 |
for (i=0;i<pending_actions.length;i++){ // if there is a pending action for this server remove it
|
147 |
if (pending_actions[i][1]==serverID){
|
148 |
pending_actions.splice(i,1);
|
149 |
}
|
150 |
}
|
151 |
$(this).parent().hide();
|
152 |
update_confirmations();
|
153 |
return false;
|
154 |
});
|
155 |
|
156 |
$("div.action_error .details").live('click', function(){
|
157 |
// remove the action from the pending list
|
158 |
ajax_error($(this).parent().children('.code').text(), undefined, $(this).parent().children('.action').text(), $(this).parent().children('.message').text());
|
159 |
$(this).parent().hide();
|
160 |
});
|
161 |
|
162 |
|
163 |
// update the servers list
|
164 |
function update_machines_view(data){
|
165 |
/*
|
166 |
Go through the servers in the input data. Update existing entries, add
|
167 |
new ones to the list
|
168 |
*/
|
169 |
$.each(data.servers.values, function(i,server){
|
170 |
existing = $('#' + server.id);
|
171 |
|
172 |
// if multiple machines exist in the DOM, delete all but one
|
173 |
// defensive coding - that shouldn't happen normally
|
174 |
while (existing.length > 1){
|
175 |
existing.remove();
|
176 |
}
|
177 |
|
178 |
// server already exists in DOM
|
179 |
if (existing.length){
|
180 |
$("div.machine:last-child").find("div.separator").show();
|
181 |
|
182 |
// if the status is deleted, delete it from the DOM
|
183 |
if (server.status == 'DELETED') {
|
184 |
existing.remove();
|
185 |
try {
|
186 |
console.info(existing.find("a.name span.name").text() + ' removed');
|
187 |
} catch(err) {}
|
188 |
} else if (existing.find(".status").text() != STATUS_MESSAGES[server.status]) {
|
189 |
|
190 |
try { // firebug console logging
|
191 |
console.info(existing.find("a.name span.name").text() + ' from '
|
192 |
+ existing.find(".status").text() + ' to ' + STATUS_MESSAGES[server.status]);
|
193 |
} catch(err) {}
|
194 |
|
195 |
if (['BUILD','ACTIVE','REBOOT'].indexOf(server.status) >= 0 &&
|
196 |
[STATUS_MESSAGES['STOPPED'], STATUS_MESSAGES['ERROR']].indexOf(existing.find(".status").text()) >= 0) {
|
197 |
// from stopped to running
|
198 |
moved = existing.clone().appendTo(".running");
|
199 |
moved.find("img.logo").attr("src","static/machines/"+image_tags[server.imageRef]+'.png');
|
200 |
existing.remove();
|
201 |
existing = moved;
|
202 |
} else if (['STOPPED','ERROR'].indexOf(server.status) >= 0 &&
|
203 |
[STATUS_MESSAGES['ACTIVE'], STATUS_MESSAGES['BUILD'], STATUS_MESSAGES['REBOOT']].indexOf(existing.find(".status").text()) >= 0) {
|
204 |
moved = existing.clone().appendTo(".terminated");
|
205 |
moved.find("img.logo").attr("src","static/machines/"+image_tags[server.imageRef]+'-off.png');
|
206 |
existing.remove();
|
207 |
existing = moved;
|
208 |
}
|
209 |
existing.find('.spinner').hide();
|
210 |
existing.find(' .wave').attr('src','static/wave.gif').show();
|
211 |
setTimeout("$('#" + server.id +" .wave').attr('src','').hide()", 3000);
|
212 |
existing.find(".status").text(STATUS_MESSAGES[server.status]);
|
213 |
|
214 |
}
|
215 |
existing.find("a.name span.name").text(server.name);
|
216 |
existing.find("a.ip span.public").text(String(server.addresses.values[0].values[0].addr).replace(',',' '));
|
217 |
} else if (server.status != 'DELETED') {
|
218 |
// If it does not exist and it's not deleted, we should create it
|
219 |
var machine = $("#machine-template").clone().attr("id", server.id).fadeIn("slow");
|
220 |
machine.find("a.name span.name").text(server.name);
|
221 |
machine.find("img.logo").attr("src","static/machines/"+image_tags[server.imageRef]+'.png');
|
222 |
machine.find("span.imagetag").text(image_tags[server.imageRef]);
|
223 |
machine.find("a.ip span.public").text(String(server.addresses.values[0].values[0].addr).replace(',',' '));
|
224 |
machine.find(".status").text(STATUS_MESSAGES[server.status]);
|
225 |
if (['BUILD', 'ACTIVE', 'REBOOT'].indexOf(server.status) >= 0){
|
226 |
machine.appendTo(".running");
|
227 |
} else {
|
228 |
machine.find("img.logo").attr("src","static/machines/"+image_tags[server.imageRef]+'-off.png');
|
229 |
machine.appendTo(".terminated");
|
230 |
}
|
231 |
//machine.find(' .wave').attr('src','static/wave.gif').show();
|
232 |
//setTimeout("$('#" + server.id +" .wave').attr('src','').hide()", 3000);
|
233 |
}
|
234 |
});
|
235 |
|
236 |
$("#spinner").hide();
|
237 |
// show all separators
|
238 |
$("div.machine div.separator").show();
|
239 |
// hide the last one
|
240 |
$("div.machine:last-child").find("div.separator").hide();
|
241 |
// the separator shows only when running and terminated machines are available
|
242 |
if ($(".terminated a.name").length > 0 && $(".running a.name").length > 0) {
|
243 |
$("#mini.separator").fadeIn("slow");
|
244 |
} else {
|
245 |
$("#mini.separator").fadeOut("slow");
|
246 |
}
|
247 |
|
248 |
// show message in case user has no servers!
|
249 |
if (servers.length == 0) {
|
250 |
showWelcome()
|
251 |
} else {
|
252 |
hideWelcome()
|
253 |
}
|
254 |
|
255 |
// set confirm box position
|
256 |
if (window.innerHeight - 220 < $('#machinesview').height())
|
257 |
$('.confirm_multiple').addClass('fixed');
|
258 |
else
|
259 |
$('.confirm_multiple').removeClass('fixed');
|
260 |
}
|
261 |
|
262 |
// indicate that the requested action was succesfully completed
|
263 |
function display_success(serverID) {
|
264 |
|
265 |
}
|
266 |
|
267 |
// indicate that the requested action was not completed
|
268 |
function display_failure(status, serverID, action, responseText) {
|
269 |
$('#'+serverID+ ' .spinner').hide();
|
270 |
$('#'+serverID+ ' .action_error .action').text(action);
|
271 |
$('#'+serverID+ ' .action_error .code').text(status);
|
272 |
$('#'+serverID+ ' .action_error .message').text(responseText);
|
273 |
$('#'+serverID+ ' .action_error').show();
|
274 |
|
275 |
}
|
276 |
|
277 |
if (images.length == 0) {
|
278 |
// populate image list
|
279 |
update_images();
|
280 |
}
|
281 |
if (flavors.length == 0) {
|
282 |
// configure flavors
|
283 |
update_flavors();
|
284 |
}
|
285 |
// set the label of the multiple buttons
|
286 |
$('div.confirm_multiple button.yes').text('Confirm All');
|
287 |
$('div.confirm_multiple button.no').text('Cancel All');
|
288 |
|
289 |
// reposition multiple confirmation box on window resize
|
290 |
$(window).resize(function(){
|
291 |
if (this.innerHeight - 220 < $('#machinesview').height())
|
292 |
$('.confirm_multiple').addClass('fixed');
|
293 |
else
|
294 |
$('.confirm_multiple').removeClass('fixed');
|
295 |
});
|
296 |
|
297 |
// start updating vm list
|
298 |
update_vms(UPDATE_INTERVAL);
|
299 |
</script>
|