Statistics
| Branch: | Tag: | Revision:

root / ui / templates / machines.html @ f4a0f054

History | View | Annotate | Download (42.6 kB)

1
<!--
2
Copyright 2011 GRNET S.A. All rights reserved.
3

4
Redistribution and use in source and binary forms, with or
5
without modification, are permitted provided that the following
6
conditions are met:
7

8
  1. Redistributions of source code must retain the above
9
     copyright notice, this list of conditions and the following
10
     disclaimer.
11

12
  2. Redistributions in binary form must reproduce the above
13
     copyright notice, this list of conditions and the following
14
     disclaimer in the documentation and/or other materials
15
     provided with the distribution.
16

17
THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
18
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
21
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
24
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28
POSSIBILITY OF SUCH DAMAGE.
29

30
The views and conclusions contained in the software and
31
documentation are those of the authors and should not be
32
interpreted as representing official policies, either expressed
33
or implied, of GRNET S.A.
34
-->
35

    
36
{% load i18n %}
37

    
38
<div id="machines" class="separator"></div>
39

    
40
<!-- the create button -->
41
<div id="ie-fix">
42
    <div id="createcontainer">
43
        <div id="beforecreate" style="display:inline;"></div>
44
        <a id="create" rel="#wizard" href="#">{% trans "Create New +" %}</a>
45
    </div>
46
</div>
47

    
48
<!-- changing between standard/list view -->
49
<div id="ie-fix-view-select">
50
    <div id="view-select">
51
        <a id="standard" href="{% url machines-standard %}" title="{% trans "Icon " %}"></a>
52
        <a id="list" href="{% url machines-list %}" title="{% trans "List " %}"></a>
53
        <a id="single" href="{% url machines-single %}" title="{% trans "Single " %}"></a>
54
    </div>
55
</div>
56

    
57
<div id="emptymachineslist">
58
    <h1 id="welcomeheader">{% trans "Welcome to ~okeanos !" %}</h1>
59
    <br />
60
    <span class="welcomebody">{% trans "From this panel you will be able to manage your Virtual Machines (VMs)." %} <!-- If you don't know what a VM is: " %}<br /><a href="#">{% trans "take the tour" %}. --></a></span>
61
    <br />
62
    <br />
63
    <span class="welcomebody">{% trans "The panel is currently empty, because you don't have any VMs yet. Start by clicking the orange button on the top left. The wizard will guide you through the whole process." %}</span>
64
    <br />
65
    <br />
66
    <span class="welcomefooter">{% trans "For more information or help, click " %}<a href="/about">{% trans "here" %}</a>.</span>
67
</div>
68

    
69
<!-- the form -->
70
<form action="#">
71
    <!-- scrollable root element -->
72
    <div class="modal" id="wizard">
73
        <!-- status bar -->
74
        <ul id="status">
75
            <li class="active li-0">
76
                <span class="headernumber" class="first">1</span>
77
                <div class="headerbody first">{% trans "Image" %}</div>
78
                <img src="static/check.png" class="img-check" style="visibility:hidden;" />
79
            </li>
80
            <li class="li-1">
81
                <span class="headernumber">2</span>
82
                <div class="headerbody">{% trans "Flavor" %}</div>
83
                <img src="static/check.png" class="img-check" style="visibility:hidden;" />
84
            </li>
85
            <li class="li-2">
86
                <span class="headernumber">3</span>
87
                <div class="headerbody">{% trans "Name" %}</div>
88
            </li>
89
        </ul>
90
        <!-- scrollable items -->
91
        <div class="items">
92
            <!-- pages -->
93
            <div class="page page1">
94
                <h2>{% trans "Select an OS" %}</h2>
95
                <hr class="topruler" />
96
                <div id="tabscontainer">
97
                    <ul class="tabs">
98
                        <li><a href="#">{% trans "system images" %}</a></li>
99
                        <li><a href="#">{% trans "custom images" %}</a></li>
100
                    </ul>
101
                </div>
102
                <div class="panes">
103
                    <li id="image-template" style="display:none;">
104
                        <label for="image.id">
105
                            <a>
106
                                <div class="image-container">
107
                                    <div class="image">
108
                                        <input class="radio" type="radio" name="image-id" id="image-id" />
109
                                        <img src="" class="image-logo"/>
110
                                        <strong class="image-title">image.title</strong>
111
                                        <br />
112
                                        <div class="description-container">
113
                                            <span class="description">image.description</span>
114
                                            <span id="size" class="size">?? MB</span><span class="size"> MB</span>
115
                                        </div>
116
                                    </div>
117
                                </div>
118
                            </a>
119
                        </label>
120
                    </li>
121
                    <ul class="pane" id="standard-images">
122
                        <!-- standard images -->
123
                    </ul>
124
                    <ul class="pane" id="custom-images">
125
                        <!-- custom images -->
126
                    </ul>
127
                </div>
128
                <hr class="bottomruler" />
129
                <button type="button" class="prev" id="cancel">{% trans "Cancel" %}</button>
130
                <button type="button" class="next right">{% trans "Next" %}<img src="static/next.png" class="img-next" /></button>
131
            </div>
132
            <div class="page page2">
133
                <h2>{% trans "Select CPUs, RAM and Disk Size" %}</h2>
134
                <hr class="topruler" />
135
                <ul>
136
                    <li id="machinetype">
137
                        <div class="machine-type">
138
                            <label for="small" id="small">
139
                                <input type="radio" id="small" name="machine-type" value="small" checked="true" />
140
                                <span class="typebody" id="small-body">{% trans "small" %}</span>
141
                            </label>
142
                        </div>
143
                        <div class="machine-type">
144
                            <label for="medium" id="medium">
145
                                <input type="radio" id="medium" name="machine-type" value="medium" />
146
                                <span class="typebody" id="medium-body">{% trans "medium" %}</span>
147
                            </label>
148
                        </div>
149
                        <div class="machine-type">
150
                            <label for="large" id="large">
151
                                <input type="radio" id="large" name="machine-type" value="large" />
152
                                <span class="typebody" id="large-body">{% trans "large" %}</span>
153
                            </label>
154
                        </div>
155
                        <div class="machine-type">
156
                            <label for="custom" id="custom">
157
                                <input type="radio" name="machine-type" id="custom" value="large" />
158
                                <span class="typebody" id="custom-body">{% trans "custom" %}</span>
159
                            </label>
160
                        </div>
161
                    </li>
162
                    <div id="page2-container">
163
                        <li class="slider-container">
164
                            <label><strong class="sliders">{% trans "CPUs" %}</strong></label>
165
                            <input type="range" id="cpu" style="display:none" />
166
                            <input type="text" class="range" id="cpu-indicator" />
167
                            <span class="units">{% trans "cores" %}</span>
168
                        </li>
169
                        <li class="slider-container">
170
                            <label><strong class="sliders">{% trans "RAM" %}</strong></label>
171
                            <input type="range" id="ram" style="display:none" />
172
                            <input type="text" class="range" id="ram-indicator" />
173
                            <span class="units">MB</span>
174
                        </li>
175
                        <li class="slider-container">
176
                            <label><strong class="sliders">{% trans "Size" %}</strong></label>
177
                            <input type="range" id="storage" style="display:none" />
178
                            <input type="text" class="range" id="storage-indicator" />
179
                            <span class="units">GB</span>
180
                        </li>
181
                        <li>
182
                            <div class="cost">
183
                                <span> {% trans "Your wallet:" %} 10,000 {% trans "Credits" %} </span> | <span>{% trans "This setup will cost you:" %}<input type="text" id="credits-indicator" value="0" class="range" disabled="disabled" /> {% trans "C/hour" %}</span>
184
                            </div>
185
                        </li>
186
                    </div>
187
                </ul>
188
                <hr class="bottomruler" />
189
                <button type="button" class="prev"><img src="static/prev.png" class="img-prev" />{% trans "Back" %}</button>
190
                <button type="button" class="next right">{% trans "Next" %}<img src="static/next.png" class="img-next" /></button>
191
            </div>
192
            <div class="page page3">
193
                <h2>{% trans "Confirm your settings" %}</h2>
194
                <hr class="topruler" />
195
                <ul id="page3-container">
196
                    <li class="required" id="label-name">
197
                        <label>
198
                            <strong>{% trans "Name" %}:</strong>
199
                            <input type="text" class="text" name="machine_name" id="name" value="My Ubuntu 10.04 x86_64 server"/>
200
                        </label>
201
                    </li>
202
                    <li>
203
                        <span>{% trans "Image:" %}</span> <span id="machine_image-label">Ubuntu 10.04 x86_64 server</span>
204
                    </li>
205
                    <li>
206
                        <span>{% trans "CPUs:" %}</span> <span id="machine_cpu-label">2</span> <span>{% trans "cores" %}</span>
207
                    </li>
208
                    <li>
209
                        <span>{% trans "RAM:" %}</span> <span id="machine_ram-label">1024</span><span>MB</span>
210
                    </li>
211
                    <li>
212
                        <span>{% trans "System Disk:" %}</span> <span id="machine_storage-label">10</span><span>GB</span>
213
                    </li>
214
                    <li>
215
                        <span>{% trans "Cost per Hour:" %}</span> <span>40 {% trans "credits" %}</span>
216
                    </li>
217
                    <li>
218
                        <span>{% trans "Credits in Wallet:" %}</span> <span>10.000</span>
219
                    </li>
220
                </ul>
221
                <hr class="bottomruler" />
222
                <button type="button" class="prev"><img src="static/prev.png" class="img-prev" />{% trans "Back" %}</button>
223
                <button type="button" class="next right" id="start">{% trans "Create VM" %}</button>
224
            </div>
225
        </div>
226
        <div class="separator-end"></div>
227
    </div>
228
</form>
229

    
230
<!-- metadata overlay -->
231
<div>
232
    <div id="metadata-wizard" class="modal">
233
        <h3 class="popup-header">{% trans "Manage Tags" %}</h3>
234
        <p style='display:none;'>hidden server id</p>
235
        <div id="on-off" style='display:none;'>hidden server id</div>
236
        <div class="popup-body">
237
            <div class="popup-body-inner">
238
                <div class="popup-title">{% trans "Create, edit and delete Tags for machine:" %}</div>
239
                <div class="name-container">
240
                    <img src="" class="machine-icon" />
241
                    <div class="machine-name"></div>
242
                </div>
243
                <div class="popup-separator"></div>
244
                <div class="large-spinner" style="display:none;"></div>
245
                <div class="metadata-labels">
246
                    <div class="metadata-label">{% trans "Tag" %}</div>
247
                    <div class="metadata-label last">{% trans "Value" %}</div>
248
                </div>
249
                <div class="metadata-container">
250
                    <!-- append metadata entries here -->
251
                </div>
252
                <div class="metadata-add-template" style="display:none;">
253
                    <input type="text" id="add-meta-key" maxlength="15"></input>
254
                    <ul style="display:none;" class="dropdown-container">
255
                        {% for o in default_keywords %}
256
                            <li><span class="dropdownitem">{{o}}</span></li>
257
                        {% endfor %}
258
                    </ul>
259
                    <input type="text" id="add-meta-value" maxlength="150" value="{% trans 'max 150 characters' %}"></input>
260
                    <div class="addbuttons">
261
                        <div class="save"></div>
262
                        <div class="cancel"></div>
263
                    </div>
264
                </div>
265
                <div class="metadata-pair-template" style="display:none;">
266
                    <div class="metadata-key">{% trans "OS" %}</div>
267
                    <div class="vertical-separator"></div>
268
                    <div class="metadata-value">{% trans "Debian" %}</div>
269
                    <div class="metadata-full-value" style="display:none;"></div>
270
                    <div class="metadata-edit">
271
                        <div class="edit"></div>
272
                        <div class="remove"></div>
273
                    </div>
274
                    <div class="editbuttons" style="display:none;">
275
                        <div class="save"></div>
276
                        <div class="remove"></div>
277
                    </div>
278
                </div>
279
            </div>
280
        </div>
281
        <div class="buttons">
282
            <button type="button" class="save" id="metadata-cancel">{% trans "Close" %}</button>
283
            <button type="button" class="create" id="metadata-create">{% trans "Create New" %}</button>
284
        </div>
285
    </div>
286
</div>
287

    
288
<a id="metadata-scrollable" href="#" rel="#metadata-wizard"></a>
289

    
290
<div id="machinesview"></div>
291

    
292
<div class="confirm_multiple">
293
    <p>{% trans "Your actions will affect" %} <span class="actionLen">XX</span> {% trans "machines" %}</p>
294
    <button class="yes">{% trans "Confirm All" %}</button>
295
    <button class="no">{% trans "Cancel All" %}</button>
296
</div>
297

    
298
<script>
299

300
// TODO: This should be populated with more rules for all available states
301
var actions = { 'reboot':        ['UNKOWN', 'ACTIVE', 'REBOOT'],
302
                'shutdown':      ['UNKOWN', 'ACTIVE', 'REBOOT'],
303
                'console':       ['ACTIVE'],
304
                'start':         ['UNKOWN', 'STOPPED'],
305
                'destroy':       ['UNKOWN', 'ACTIVE', 'STOPPED', 'REBOOT', 'ERROR', 'BUILD']
306
               };
307

308

309
//change hover icon on prev,next buttons
310
$("#wizard button.next").hover(function() {
311
        $(this).find(".img-next").attr("src","static/next-hover.png");
312
    },
313
    function() {
314
        $(this).find(".img-next").attr("src","static/next.png");
315
    }
316
);
317
$("#wizard button.prev").hover(function() {
318
        $(this).find(".img-prev").attr("src","static/prev-hover.png");
319
    },
320
    function() {
321
        $(this).find(".img-prev").attr("src","static/prev.png");
322
    }
323
);
324

325
//add hover to labels
326
$('#machines-pane span.typebody').mouseover(function() {
327
    $(this).addClass('typehover');
328
});
329
$('#machines-pane span.typebody').mouseout(function() {
330
    $(this).removeClass('typehover');
331
});
332

333
// switch to list view
334
$("#machines-pane a#list").click(function(){
335
    list_view();
336
    return false;
337
});
338

339
// switch to standard view
340
$("#machines-pane a#standard").click(function(){
341
    standard_view();
342
    return false;
343
});
344

345
// switch to single view
346
$("#machines-pane a#single").click(function(){
347
    single_view();
348
    return false;
349
});
350

351
// launch VM creation wizard
352
$("#machines-pane a#create").click(function(){
353
    // launch wizard only if images and flavors are found
354
    if (images.length > 0  && flavors.length > 0) {
355
        $('#machines-pane a#create').data('overlay').close();
356
        $("#wizard").scrollable().begin();
357
        $("#wizard").show();
358
        $('#machines-pane a#create').data('overlay').load();
359
        // enable submit button
360
        $("#wizard #start").removeAttr('disabled');
361
    } else if (images.length == 0 ) {
362
        ajax_error('NO_IMAGES');
363
        return false;
364
    } else if (flavors.length == 0) {
365
        ajax_error('NO_FLAVORS');
366
        return false;
367
    }
368
});
369

370
// create wizard overlay
371
$(function() {
372
    $("#machines-pane a#create").overlay({
373
        mask: '#666',
374
        effect: 'default',
375
        top: '5%',
376
        oneInstance: false,
377
        closeOnClick: false
378
    });
379
});
380

381
// wizard
382
$(function() {
383
    var root = $("#wizard").scrollable();
384
    var api = root.scrollable();
385
    // rangeinput with default configuration
386
    // validation logic is done inside the onBeforeSeek callback
387
    api.onBeforeSeek(function(event, i) {
388
        // update status bar
389
        $("#status li").removeClass("active").eq(i).addClass("active");
390
        // we are going 1 step backwards so no need for validation
391
        if (api.getIndex() > i) {
392
            $("#wizard .li-" + i).removeClass("checked");
393
            $("#wizard .li-" + i).find(".img-check").css("visibility","hidden");
394
        }
395
        if (api.getIndex() < i) {
396
            $("#wizard .li-" + api.getIndex()).addClass("checked");
397
            $("#wizard .li-" + api.getIndex()).find(".img-check").css("visibility","visible");
398
             // 1. get current page
399
             var page = root.find(".page").eq(api.getIndex()),
400
             // 2. .. and all required fields inside the page
401
             inputs = page.find(".required :input").removeClass("error"),
402
             // 3. .. which are empty
403
             empty = inputs.filter(function() {
404
                return $(this).val().replace(/\s*/g, '') == '';
405
             });
406
             // if there are empty fields, then
407
            if (empty.length) {
408
                // add a CSS class name "error" for empty & required fields
409
                empty.addClass("error");
410
                // cancel seeking of the scrollable by returning false
411
                return false;
412
            // everything is good
413
            }
414
        }
415
        // update confirm step
416
        if (api.getIndex()==0) {
417
            var image = $("input[type=radio][name=image-id]:checked");
418
            var imageRef = image.length ? image[0].id : false
419
            if (imageRef) {
420
                var imageName = $("label[for=" + imageRef + "] .image-title").text();
421
                $("#machine_image-label")[0].textContent = imageName;
422
                $("input[type=text][name=machine_name]")[0].value = "My " + imageName + " server";
423
            }
424
        } else if (api.getIndex()==1) {
425
            $("#machine_cpu-label")[0].textContent = $("#cpu-indicator")[0].value;
426
            $("#machine_ram-label")[0].textContent = $("#ram-indicator")[0].value;
427
            $("#machine_storage-label")[0].textContent = $("#storage-indicator")[0].value;
428
        }
429
    });
430
    // if tab is pressed on the next button seek to next page
431
    $(root).live('keydown', function (e) {
432
       if ( e.keyCode == 9 ){
433
           if(e.preventDefault) {
434
               e.preventDefault();
435
           }
436
           api.next();
437
        }
438
    });
439
    //submit wizard by pressing enter on the name textbox
440
    $("#name").keypress(function (e) {
441
        if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
442
            $('#start').click();
443
            return false;
444
        } else {
445
            return true;
446
        }
447
    });
448
});
449

450
// disable sliders in flavor selection
451
function disableSliders() {
452
    $("#cpu").attr('disabled',true);
453
    $("#ram").attr('disabled',true);
454
    $("#storage").attr('disabled',true);
455
}
456

457
//update radio button when clicking on text
458
$("#small-body").live('click' ,function() {
459
    $(this).parent().find("#small").click();
460
});
461

462
$("#medium-body").live('click' ,function() {
463
    $(this).parent().find("#medium").click();
464
});
465

466
$("#large-body").live('click' ,function() {
467
    $(this).parent().find("#large").click();
468
});
469

470
$("#custom-body").live('click' ,function() {
471
    $(this).parent().find("#custom").click();
472
});
473

474
//select image div on radio button select
475
$('#machines-pane .radio').live('click' ,function() {
476
    $(this).parents("div").find(".image").removeClass('selecteddiv');
477
    if($(this).is(':checked'))  {
478
        $(this).parent().addClass('selecteddiv');
479
    }
480
});
481

482
// validate cpu input box
483
$("#cpu-indicator").live('change',function(){
484
    var v = Number(this.value);
485
    var i = cpus.indexOf(v);
486
    if (isNaN(v)) {
487
        $(this).value = cpus[0];
488
        $("#cpu").data('rangeinput').setValue(0);
489
    } else if (i == -1) {
490
        for (var j=0; j < cpus.length; j++)
491
            if (v<cpus[j])
492
                break;
493
        $("#cpu").data('rangeinput').setValue(j);
494
    } else {
495
        $("#cpu").data('rangeinput').setValue(i);
496
    }
497
    return false;
498
});
499

500
// validate ram input box
501
$("#ram-indicator").live('change',function(){
502
    var v = Number(this.value);
503
    var i = ram.indexOf(v);
504
    if (isNaN(v)) {
505
        $(this).value = cpus[0];
506
        $("#ram").data('rangeinput').setValue(0);
507
    } else if (i == -1) {
508
        for (var j=0; j < ram.length; j++)
509
            if (v<ram[j])
510
                break;
511
        $("#ram").data('rangeinput').setValue(j);
512
    } else {
513
        $("#ram").data('rangeinput').setValue(i);
514
    }
515
    return false;
516
});
517

518
// validate storage input box
519
$("#storage-indicator").live('change',function(){
520
    var v = Number(this.value);
521
    var i = disks.indexOf(v);
522
    if (isNaN(v)) {
523
        $(this).value = disks[0];
524
        $("#storage").data('rangeinput').setValue(0);
525
    } else if (i == -1) {
526
        for (var j=0; j < disks.length; j++)
527
            if (v<disks[j])
528
                break;
529
        $("#storage").data('rangeinput').setValue(j);
530
    } else {
531
        $("#storage").data('rangeinput').setValue(i);
532
    }
533
    return false;
534
});
535

536
// selecting the small size
537
$("#small").click(function(){
538
    $("#cpu").data('rangeinput').setValue(0);
539
    $("#ram").data('rangeinput').setValue(0);
540
    $("#storage").data('rangeinput').setValue(0);
541
    $("#cpu-indicator")[0].value = cpus[0];
542
    $("#ram-indicator")[0].value = ram[0];
543
    $("#storage-indicator")[0].value = disks[0];
544
    $("#small").addClass("active");
545
    $("#medium").removeClass("active");
546
    $("#large").removeClass("active");
547
    $("#custom").removeClass("active");
548
});
549

550
// selecting the medium size
551
$("#medium").click(function(){
552
    $("#cpu").data('rangeinput').setValue(1);
553
    $("#ram").data('rangeinput').setValue(1);
554
    $("#storage").data('rangeinput').setValue(1);
555
    $("#cpu-indicator")[0].value = cpus[1];
556
    $("#ram-indicator")[0].value = ram[1];
557
    $("#storage-indicator")[0].value = disks[1];
558
    $("#medium").addClass("active");
559
    $("#small").removeClass("active");
560
    $("#large").removeClass("active");
561
    $("#custom").removeClass("active");
562
});
563

564
// selecting the large size
565
$("#large").click(function(){
566
    $("#cpu").data('rangeinput').setValue(2);
567
    $("#ram").data('rangeinput').setValue(2);
568
    $("#storage").data('rangeinput').setValue(2);
569
    $("#cpu-indicator")[0].value = cpus[2];
570
    $("#ram-indicator")[0].value = ram[2];
571
    $("#storage-indicator")[0].value = disks[2];
572
    $("#large").addClass("active");
573
    $("#medium").removeClass("active");
574
    $("#small").removeClass("active");
575
    $("#custom").removeClass("active");
576
});
577

578
// selecting the custom flavor enables the sliders
579
$("#custom").click(function(){
580
    $("#cpu").attr('disabled',false);
581
    $("#ram").attr('disabled',false);
582
    $("#storage").attr('disabled',false);
583
    $("strong.sliders").style = 'color: #778899;';
584
    $("#custom input").attr('checked', 'checked');
585
    $("#custom").addClass("active");
586
    $("#medium").removeClass("active");
587
    $("#large").removeClass("active");
588
    $("#small").removeClass("active");
589
});
590

591
//when textbox gains focus, add selection in css
592
$('#cpu-indicator').focus(function() {
593
    $(this).addClass('selectedrange');
594
});
595

596
$('#ram-indicator').focus(function() {
597
    $(this).addClass('selectedrange');
598
});
599

600
$('#storage-indicator').focus(function() {
601
    $(this).addClass('selectedrange');
602
});
603

604
//when textbox loses focus, clear selection in css
605
$('#cpu-indicator').blur(function() {
606
    $(this).removeClass('selectedrange');
607
});
608

609
$('#ram-indicator').blur(function() {
610
    $(this).removeClass('selectedrange');
611
});
612

613
$('#storage-indicator').blur(function() {
614
    $(this).removeClass('selectedrange');
615
});
616

617
// exit the wizard
618
$("#cancel").click(function() {
619
    $("#machines-pane a#create").overlay().close();
620
});
621

622
// starting a new VM through the wizard
623
$("#start").click(function() {
624
    var imageRef = $('input[type=radio][name=image-id]:checked')[0].id.replace('img-radio-','');
625
    var flavorRef = identify_flavor($("#cpu-indicator")[0].value, $("#storage-indicator")[0].value, $("#ram-indicator")[0].value);
626
    var machineName = $('input[name=machine_name]')[0].value;
627
    if (jQuery.trim(machineName) == ''){
628
        return false;
629
    }
630

631
    // replace text 'create new' with progress indicator
632
    $(this).text('');
633
    $(this).html('<img src="static/icons/indicators/medium/horizontal-progress.gif" / >');
634
    // disable submit button to prevent multiple calls
635
    $(this).attr("disabled", true);
636

637
    create_vm(machineName, imageRef, flavorRef);
638

639
    try {
640
        console.warn('creating ' + $("input[name=machine_name]")[0].value);
641
    } catch(err){}
642

643
});
644

645
// metadata wizard
646
$(function() {
647
    // create wizard overlay
648
    $("a#metadata-scrollable").overlay({
649
        mask: '#666',
650
        effect: 'default',
651
        top: '10%',
652
        closeOnClick: false,
653
        oneInstance: false,
654
        closeOnEsc: false,
655
        load: false,
656
        onClose: function() {
657
            // reset input areas
658
            serverID = $("#metadata-wizard p:first").text();
659
            $("#metadata-wizard div.metadata-container").empty();
660
            get_metadata(serverID, true);
661
        }
662
    });
663
});
664

665
// bring up metadata overlay
666
function show_metadata_wizard() {
667
    // get metadata for current server and fill the dialog
668
    serverID = $("#metadata-wizard p:first").text();
669
    get_metadata(serverID);
670
    $("#metadata-wizard").show();
671
    $("a#metadata-scrollable").data('overlay').load();
672
    $('#metadata-wizard .large-spinner').show();
673
    return false;
674
}
675

676
// update metadata list
677
function list_metadata(data) {
678
    // empty the list if it already exists
679
    $("#metadata-wizard div.metadata-container").empty();
680
    // get the values to show
681
    meta = data.metadata.values;
682
    // set serve icon
683
    var icon_name = os_icon(data.metadata);
684
    $("#metadata-wizard .machine-icon").attr("src","static/icons/machines/small/" + icon_name + '-' + $("#metadata-wizard div#on-off").text() + '.png');
685
    // show values
686
    for (key in meta) {
687
        pair = $("#metadata-wizard div.metadata-pair-template:last").clone();
688
        //truncate metadata
689
        pair.find("div.metadata-key").text(key.substring(0,15));
690
        if (meta[key].length > 25) {
691
            pair.find("div.metadata-value").text(meta[key].substring(0,25) + "...");
692
        } else {
693
            pair.find("div.metadata-value").text(meta[key]);
694
        }
695
        //get the serverID
696
        serverID = $("#metadata-wizard p:first").text();
697
        //store the full metadata value on a hidden div
698
        pair.find("div.metadata-full-value").text(meta[key]);
699
        // show/hide edit-remove buttons on hover
700
        pair.hover(function () {$(this).find('.metadata-edit').show();}, function () {$(this).find('.metadata-edit').hide();});
701
        // add it to the list
702
        pair.appendTo("#metadata-wizard div.metadata-container").fadeIn();
703
    }
704
}
705

706
// exit the metadata wizard
707
$("#metadata-cancel").click(function(){
708
    $("a#metadata-scrollable").overlay().close();
709
});
710

711
//intercept create new metadata click
712
$("#metadata-wizard #metadata-create").click(function(){
713
    pair = $("#metadata-wizard div.metadata-add-template:first").clone();
714
    pair.prependTo("#metadata-wizard div.metadata-container").fadeIn();
715
      with (pair.find('input#add-meta-key')) {
716
        with (pair.find('ul:first')) {
717
          find('li').click(function() {
718
            $(this).parent().parent().find('.textdropdown-outer').find('input:first').attr('value', $(this).find('.dropdownitem').html());
719
            $(this).parent().hide();
720
          });
721
          hide();
722
        }
723

724
        keypress(function() {
725
          $(this).parent().next('ul:first').hide();
726
        });
727

728
        change(function() {
729
          $(this).parent().next('ul:first').hide();
730
        });
731

732
        wrap('<div class="textdropdown-outer" style="width: ' + width() + 'px; height: ' + (height() + 5) + 'px"></div>');
733
        var btn = parent().prepend('<div class="textdropdown-btn">&nbsp;</div>').find('.textdropdown-btn');
734
        width(width() - btn.width() - 5);
735
        css("border", "0");
736

737
        btn.click(function() {
738
          var p = $(this).parent();
739
          with (p.next('ul:first')) {
740
            $(this).parent().parent().find('ul:first').css('position', 'absolute');
741
            $(this).parent().parent().find('ul:first').css('width',    p.width());
742
            $(this).parent().parent().find('ul:first').css('left',     p.position().left + 4);
743
            $(this).parent().parent().find('ul:first').css('top',      p.position().top + p.height() + 1);
744
            var elem = $(this).parent().parent().find('ul:first')[0];
745
            if(elem.style.display == 'none') {
746
                 $(this).parent().parent().find('ul:first').show();
747
            } else {
748
                 $(this).parent().parent().find('ul:first').hide();
749
            }
750

751
          }
752
        });
753
      }
754
    pair.find('input#add-meta-key').focus();
755
    //submit keyword by pressing enter on the textbox
756
    $(this).parent().parent().find('input#add-meta-value').keypress(function (e) {
757
        if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
758
            $(this).parent().parent().find('.addbuttons .save').click();
759
            return false;
760
        } else {
761
            return true;
762
        }
763
    });
764
});
765

766
//save new metadata
767
$('#metadata-wizard .addbuttons .save').die('click');
768
$('#metadata-wizard .addbuttons .save').live('click', function(){
769
    keyValue = $(this).parent().parent().find('input#add-meta-key').val();
770
    valValue = $(this).parent().parent().find('input#add-meta-value').val();
771
    if ((keyValue == '{% trans 'max 15 characters' %}') || (valValue == '{% trans 'max 150 characters' %}')) {
772
        return false;
773
    } else {
774
        serverID = $("#metadata-wizard p:first").text();
775
        pair = $("#metadata-wizard div.metadata-pair-template:last").clone();
776
        pair.find("div.metadata-key").text(keyValue.substring(0,15));
777
        if (valValue.length > 25) {
778
            pair.find("div.metadata-value").text(valValue.substring(0,25) + "...");
779
        } else {
780
            pair.find("div.metadata-value").text(valValue);
781
        }
782
        pair.find("div.metadata-full-value").text(valValue);
783
        update_metadata(serverID, keyValue, valValue);
784
        $(this).parent().parent().remove();
785
        pair.hover(function () {$(this).find('.metadata-edit').show();}, function () {$(this).find('.metadata-edit').hide();});
786
        // add it to the list
787
        if ($("#metadata-wizard div.metadata-container").find("div.metadata-pair-template").length > 0) {
788
            pair.insertBefore("#metadata-wizard div.metadata-container div.metadata-pair-template:first").fadeIn();
789
        } else {
790
            pair.prependTo("#metadata-wizard div.metadata-container").fadeIn();
791
        }
792
    }
793
});
794

795
//intercept cancel new metadata creation
796
$("#metadata-wizard .addbuttons .cancel").die('click');
797
$("#metadata-wizard .addbuttons .cancel").live('click',function(){
798
    $(this).parent().parent().fadeOut('fast', function() { $(this).remove(); });
799
});
800

801
//metadata remove button
802
$("#metadata-wizard .metadata-edit .remove").die('click')
803
$("#metadata-wizard .metadata-edit .remove").live('click', function() {
804
    $(this).parent().parent().fadeOut('slow');
805
    serverID = $("#metadata-wizard p:first").text();
806
    keyValue = $(this).parent().parent().find('div.metadata-key').text();
807
    //update icons if deleting the OS metadata
808
    if (keyValue == "OS") {
809
        $("#metadata-wizard .machine-icon").attr("src","static/icons/machines/small/unknown-" + $("#metadata-wizard div#on-off").text() + '.png');
810
        $("#machinesview-icon").find("div#" + serverID).find("img.logo").attr("src", "static/icons/machines/medium/unknown-" + $("#metadata-wizard div#on-off").text() + '.png');
811
    }
812
    delete_metadata(serverID, keyValue);
813
});
814

815
//metadata edit button
816
$("#metadata-wizard .metadata-edit .edit").die('click');
817
$("#metadata-wizard .metadata-edit .edit").live('click', function() {
818
    $(this).parent().parent().find('div.metadata-value').html("<input id=\"value-edit\" maxlength=\"150\" type=\"text\" class=\"metatextbox\" value=\"" + $(this).parent().parent().find('.metadata-full-value').text() +
819
                                    "\" / ><span class=\"oldValue\">" +
820
                                    $(this).parent().parent().find('.metadata-full-value').text() + "</span>");
821
    //submit keyword by pressing enter on the textbox
822
    $(this).parent().parent().find('input.metatextbox').keypress(function (e) {
823
        if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
824
            $(this).parent().parent().find('.editbuttons .save').click();
825
            return false;
826
        } else {
827
            return true;
828
        }
829
    });
830
    $(this).parent().parent().find('input.metatextbox').select()
831
    $(this).parent().hide();
832
    $(this).parent().parent().unbind('mouseenter').unbind('mouseleave');
833
    $(this).parent().parent().find('.editbuttons').show();
834
});
835

836
//capture Esc key
837
bar = {};
838
bar.keydown = function(e) {
839
    if (e.keyCode == 27) {
840
        //if we are inside an add or edit textbox, cancel editing
841
        if ($('input.metatextbox:focus').length > 0) {
842
            $('input.metatextbox:focus').parent().parent().find('.editbuttons .remove').click();
843
        } else if ($('input#add-meta-key:focus').length > 0)  {
844
            $('input#add-meta-key:focus').parent().parent().find('.addbuttons .cancel').click();
845
        } else if ($('input#add-meta-value:focus').length > 0) {
846
            $('input#add-meta-value:focus').parent().parent().find('.addbuttons .cancel').click();
847
        } else {
848
            //else close the metadata wizard
849
            $("a#metadata-scrollable").overlay().close();
850
        }
851
        e.preventDefault();
852
        e.stopPropagation();
853
    }
854
};
855
document.keydown = bar.keydown;
856

857
//metadata cancel edit button
858
$("#metadata-wizard .editbuttons .remove").die('click');
859
$("#metadata-wizard .editbuttons .remove").live('click', function() {
860
    var oldValue = $(this).parent().parent().find('.oldValue').text();
861
    if (oldValue.length > 25) {
862
        oldValue = oldValue.substring(0,25) + "...";
863
    }
864
    $(this).parent().parent().find('div.metadata-value').html(oldValue);
865
    $(this).parent().parent().hover(function () {$(this).find('.metadata-edit').show();}, function () {$(this).find('.metadata-edit').hide();});
866
    $(this).parent().hide();
867
});
868

869

870
//metadata save edit button
871
$("#metadata-wizard .editbuttons .save").die('click');
872
$("#metadata-wizard .editbuttons .save").live('click', function() {
873
    newValue = $(this).parent().parent().find('input.metatextbox').val();
874
    keyValue = $(this).parent().parent().find('div.metadata-key').text();
875
    oldValue = $(this).parent().parent().find('.oldValue').text();
876
    if (!(newValue == oldValue)) {
877
        update_metadata(serverID, keyValue, newValue);
878
    }
879
    if (newValue.length > 25) {
880
        newValueSort = newValue.substring(0,25) + "...";
881
    } else {
882
        newValueSort = newValue
883
    }
884
    $(this).parent().parent().find('div.metadata-value').html(newValueSort);
885
    $(this).parent().parent().find('div.metadata-full-value').html(newValue);
886
    $(this).parent().parent().hover(function () {$(this).find('.metadata-edit').show();}, function () {$(this).find('.metadata-edit').hide();});
887
    $(this).parent().hide();
888

889
});
890

891
// intercept create metadata key focus
892
$("#metadata-wizard input#add-meta-key").live('focusin', function() {
893
    if ($(this).parent().hasClass("div-enabled")) {
894
    } else {
895
        $(this).parent().addClass("div-enabled");
896
        $(this).addClass("input-enabled");
897
        if (this.value == '{% trans 'max 15 characters' %}') {
898
            this.value = '';
899
        }
900
    }
901
    return false;
902
});
903

904
// intercept create metadata key focus out
905
$("#metadata-wizard input#add-meta-key").live('focusout', function() {
906
    $(this).parent().removeClass("div-enabled");
907
    if (this.value == "") {
908
        $(this).removeClass("input-enabled");
909
        this.value = '{% trans 'max 15 characters' %}';
910
    }
911
    return false;
912
});
913

914

915
// intercept metadata dropdown item click
916
$(".metadata-add-template li").live('click', function() {
917
    $(this).parent().parent().parent().find("input#add-meta-value").focus();
918
    $(this).parent().parent().parent().find("input#add-meta-key").addClass("input-enabled");
919
});
920

921
// intercept create metadata key focus
922
$("#metadata-wizard input#add-meta-value").live('focusin', function() {
923
    if ($(this).hasClass("input-enabled")) {
924
    } else {
925
        $(this).addClass("input-enabled");
926
        this.value = '';
927
    }
928
    return false;
929
});
930

931
// intercept create metadata key focus out
932
$("#metadata-wizard input#add-meta-value").live('focusout', function() {
933
    if (this.value == "") {
934
        $(this).removeClass("input-enabled");
935
        this.value = '{% trans 'max 150 characters' %}';
936
    }
937
    return false;
938
});
939

940
// intercept click on cancel button in metadata add dialog
941
$('#add-dialog button.cancel').live('click', function() {
942

943
});
944

945
// intercept click on save button in metadata add dialog
946
$('#add-dialog button.save').live('click', function() {
947
    // if both fields are filled in
948
    if ($('input.key').hasClass("input-enabled") && $('textarea.value').hasClass("input-enabled")) {
949
        // get the server id, meta key and meta value needed for the ajax call
950
        var serverID = $(this).parent().find('h3 p').text();
951
        var meta_key = $(this).parent().find('input.key').attr('value');
952
        var meta_value = $(this).parent().find('textarea.value')[0].value;
953
        // make the ajax call and list the new GET results
954
        add_metadata(serverID, meta_key, meta_value);
955
        // go to previous step
956
        $('#add-dialog button.prev').click();
957
    } else {
958
        // find which field is not filled in and focus there
959
        if (!$('input.key').hasClass("input-enabled")) {
960
            $('input.key').focus();
961
            $('input.key').focusin();
962
        } else {
963
            $('textarea.value').focus();
964
            $('textarea.value').focusin();
965
        }
966
    }
967
    return false;
968
});
969

970
// confirm all actions
971
$("#machines-pane div.confirm_multiple .yes").live('click', function(){
972
    while(pending_actions.length > 0){ // if there is a pending action for this server execute it
973
        action = pending_actions.pop(); // extract action
974
        var serverID = action[1];
975
        if ($.cookie("view") != '1') { // standard view
976
            $('#' + serverID + ' .selected').removeClass('selected');
977
            $('#' + serverID + ' .display').removeClass('display');
978
            if (action[0] == shutdown) {
979
                $('#' + serverID + ' .status').text(TRANSITIONS['Shutting down']);
980
                $('#' + serverID + ' .state').removeClass().addClass('state shutting-state');
981
            } else if (action[0] == start) {
982
                $('#' + serverID + ' .status').text(TRANSITIONS['Starting']);
983
                $('#' + serverID + ' .state').removeClass().addClass('state starting-state');
984
            } else if (action[0] == reboot) {
985
                $('#' + serverID + ' .status').text(TRANSITIONS['Rebooting']);
986
                $('#' + serverID + ' .state').removeClass().addClass('state rebooting-state');
987
            } else if (action[0] == destroy) {
988
                $('#' + serverID + ' .status').text(TRANSITIONS['Destroying']);
989
                $('#' + serverID + ' .state').removeClass().addClass('state destroying-state');
990
            }
991
            $('#' + serverID + ' .spinner').show();
992
        } else { // list view
993
            osIcon = $('#'+serverID).parent().parent().find('.list-logo');
994
            osIcon.attr('os',osIcon.attr('src'));
995
            osIcon.attr('src','static/icons/indicators/small/progress.gif');
996
            if (action[0] == shutdown) {
997
                $('#' + serverID).parent().parent().find('span.status').text(TRANSITIONS['Shutting down']);
998
            } else if (action[0] == start) {
999
                $('#' + serverID).parent().parent().find('span.status').text(TRANSITIONS['Starting']);
1000
            } else if (action[0] == reboot) {
1001
                $('#' + serverID).parent().parent().find('span.status').text(TRANSITIONS['Rebooting']);
1002
            } else if (action[0] == destroy) {
1003
                $('#' + serverID).parent().parent().find('span.status').text(TRANSITIONS['Destroying']);
1004
            }
1005
        }
1006
        action[0]([serverID]); // execute action
1007
    }
1008
    $('#machinesview-list .actions .selected').removeClass('selected');
1009
    update_confirmations();
1010
    return false;
1011
});
1012

1013
// cancel all actions
1014
$("#machines-pane div.confirm_multiple button.no").live('click', function(){
1015
    pending_actions = [];
1016
    $('#machines-pane .machine .selected').removeClass('selected');
1017
    $('#machinesview-list .actions .selected').removeClass('selected');
1018
    $('#machines-pane .machine .display').removeClass('display');
1019

1020
    update_confirmations();
1021
    return false;
1022
});
1023

1024
// basic functions executed on page load
1025
if (images.length > 0) {
1026
    // populate image list
1027
    update_wizard_images();
1028
}
1029
if (flavors.length > 0) {
1030
    // configure flavors
1031
    update_wizard_flavors();
1032
}
1033
// create tabs for main menu
1034
$("ul.tabs").tabs("div.panes ul");
1035

1036
//fix ie z-index bug by moving the overlays to the bottom
1037
$(document).ready(function() {
1038
    if ($.browser.msie) {
1039
        $("body").append($("#wizard"));
1040
        $("body").append($("#metadata-wizard"));
1041
    }
1042
});
1043

1044
//IE specific fixes
1045
if ($.browser.msie) {
1046
    //IE fix for dropdown li hover
1047
    $("#metadata-wizard ul li").live("mouseenter", function () {
1048
        $(this).css("background-color","#efefef");
1049
        $(this).css("cursor","pointer");
1050
    });
1051
    $("#metadata-wizard ul li").live("mouseleave", function () {
1052
        $(this).css("background-color","transparent");
1053
        $(this).css("cursor","default");
1054
    });
1055
    //IE fix for metadata wizard hover
1056
    $("#metadata-wizard div.metadata-pair-template").live("mouseenter", function () {
1057
        $(this).css("background-color","#74aec9");
1058
    });
1059
    $("#metadata-wizard ul li").live("mouseleave", function () {
1060
        $(this).css("background-color","transparent");
1061
    });
1062
}
1063

    
1064
</script>