Revision 5153f2a9

b/ui/static/alt-main.css
14 14
	font-size: 100%;
15 15
	vertical-align: baseline;
16 16
	background: transparent;
17
    font-family: Verdana, Bitstream Charter, sans-serif;
17
    font-family: 'PT Sans', Verdana, Bitstream Charter, sans-serif;
18 18
}
19 19
body {
20 20
	line-height: 1;
......
56 56
    margin: 0;
57 57
}
58 58

  
59
h1, h2, h3, h4, h5 {
60
    margin-top: 0em;
61
    margin-bottom: .6em;
62
}
63

  
64 59
h5 {
65 60
    font-weight: normal;
66
    margin-bottom: 1em;
67
}
68

  
69
#footer {
70
    text-align:center;
71
    color: #666;
72
    font-size: .5em;
73
    padding:2em;
61
    font-size: 10pt;
62
    margin-bottom:3px;
74 63
}
75 64

  
76 65
/* get rid of those system borders being generated for A tags */
......
87 76
	margin: 0 0 0 10px; 
88 77
    padding: 0;
89 78
	height:31px;
90
    font-size:34px;	
79
    font-size:32px;	
91 80
    overflow: hidden; 	
92 81
}
93 82

  
......
107 96
	color:#d2d2d2;
108 97
	position:relative;
109 98
	outline:0;
110
    padding: 0 7px 0 10px;
111
    margin-top: 7px;
99
    padding: 0 9px 0 13px;
100
    margin-top: 6px;
101
}
102

  
103
ul.css-tabs a#instances {
104
    color: #87aade;
105
}
106

  
107

  
108
ul.css-tabs a#disks {
109
    color: #deb358;
110
}
111

  
112
ul.css-tabs a#networks {
113
    color: #bc9399;
114
}
115

  
116
ul.css-tabs a#images {
117
    color: #9ba97b;
112 118
}
113 119

  
114 120
ul.css-tabs a:hover {
......
117 123
	
118 124
/* selected tab */
119 125
ul.css-tabs a.current {
120
    color: #87aade;
121 126
	cursor:default;
122 127
    margin-top: 2px;
123 128
}
......
148 153
.error {
149 154
	background-color:#E8FF6D;
150 155
	padding:4px;
151
	-webkit-box-shadow: #000 0 0 12px;
152
	-moz-box-shadow: #000 0 0 12px;
156
	-webkit-box-shadow: #000 0 0 10pt;
157
	-moz-box-shadow: #000 0 0 10pt;
153 158
}
154 159

  
155 160
/* nested arrow inside error message. It's 100% CSS. No images. */
......
171 176

  
172 177
#create {
173 178
    background-color: #87aade;
174
    color: #162d50;
179
    color: #000;
175 180
    cursor: pointer;
176 181
    display: block;
177
    padding: 0.7em .4em 0.7em 2.2em;
182
    padding: 6px 24px;
178 183
    margin-top: 9px;
179
    width: 7.9em;
184
    width: 125px;
180 185
    text-decoration: none;
181 186
    margin-left: -2.3em;
187
    border:1px solid #bfd2ed;
182 188
}
183 189

  
184 190
#create:hover {
......
237 243
/* scrollable root element */
238 244
#wizard {	
239 245
	border:5px solid #87AADE;
240
	font-size:12px;
246
	font-size:10pt;
241 247
	height:480px;
242 248
	margin:0px auto;	
243 249
	width:500px;
......
300 306

  
301 307
#wizard h2 em {
302 308
	display:block;
303
	font-size:14px;
309
	font-size:10pt;
304 310
	color:#666;
305 311
	font-style:normal;
306 312
	margin-top:5px;
......
330 336
}
331 337

  
332 338
#wizard label em {
333
	font-size:11px;
339
	font-size:10pt;
334 340
	color:#666;	
335 341
	font-style:normal;
336 342
}
......
396 402
}
397 403

  
398 404
#wizard div.image span.size {
399
    font-size: 0.8em;
405
    font-size: 10pt;
400 406
    color: #666;
401 407
}
402 408

  
......
405 411
}
406 412

  
407 413
#wizard div.image span.image-id, #wizard div.image span.description {
408
    font-size: 0.8em;
414
    font-size: 10pt;
409 415
    color: #666;
410 416
    font-weight: normal;
411 417
    display:inline;
......
418 424
#wizard .cost {
419 425
    color: #666;
420 426
    margin-top: 5em;
421
    font-size: .8em;
427
    font-size: 10pt;
422 428
}
423 429

  
424 430
#wizard #status {
......
493 499
    cursor: move;
494 500
    display: block;
495 501
    height: 22px;
496
    margin-top: -11px;
502
    margin-top: -10pt;
497 503
    position: absolute;
498 504
    width: 10px;
499 505
}
......
519 525
	-webkit-border-radius:5px; 		
520 526
}
521 527

  
522
.instance {
528
div.instance {
523 529
    clear: both;
524 530
    margin: 1em 0 0 -2em;
525
    padding: 1em 2em 1em 1em;
526
    width: 70%;
531
    padding: 5px;
532
    width: 523px;
527 533
    border: 1px dashed transparent;
528 534
    color: #666;
529
    height: 70px;
535
    height: 67px;
530 536
}
531 537

  
532 538
.instance a {
533
    color: #6892d2;
539
    color: #3d3d3d;
534 540
    font-weight: normal;
535 541
    text-decoration: none;
536
    font-size: .8em;
542
    font-size: 10pt;
537 543
}
538 544

  
539 545
.instance a:hover {
540
    color: #162d50;
546
    color: #000;
541 547
}
542 548

  
543 549
.state {
......
587 593

  
588 594
.instance img {
589 595
    float: left;
590
    margin: 0em 2em 0 1em;
596
    margin: 0em 14px 0 14px;
591 597
}
592 598

  
593 599
div.ip, div.state {
594
    font-size:.7em;
595
    color: #6892D2;
600
    font-size:10pt;
601
    color: #3d3d3d;
596 602
}
597 603

  
598 604
div.indicator {
......
610 616

  
611 617

  
612 618
.instance:hover div.uptime, .instance:hover a.rename, .instance:hover a.configure {
613
    color: #6892D2;
619
    color: #000;
614 620
}
615 621

  
616 622
div.uptime {
......
629 635
span.rename, span.configure {
630 636
    background-repeat: no-repeat;
631 637
    color: transparent;
632
    font-size: 11px;
638
    font-size: 10pt;
633 639
    font-weight: normal;
634 640
    margin-left: 2em;
635 641
    padding-left: 2em;
......
637 643
}
638 644

  
639 645
a.name:hover span.rename {
640
    color: #213D55;
646
    color: #3D3D3D;
641 647
    margin-top: 0.4em;
642 648
    background-image: url(/static/pencil.png);
643 649
}
644 650

  
645
a.ip:hover span.configure {
646
    color: #213D55;
647
    background-image: url(/static/pencil.png);
648
}
649 651

  
650 652
a.storage:hover span.configure {
651
    color: #213D55;
652
    background-image: url(/static/pencil.png);
653
    color: #3D3D3D;
653 654
}
654 655

  
655 656
#ubuntu {
......
665 666
    border-width: 1px 1px 0.2em;
666 667
    color: #FFFFFF;
667 668
    cursor: pointer;
668
    font-size: 1em;
669
    font-size: 10pt;
669 670
    line-height: 1;
670 671
    padding: 0.7em 2em;
671 672

  
......
694 695
a#list, a#standard {
695 696
    float: right;
696 697
    clear: both;
697
    color: #666;
698
    color: white;
698 699
    text-decoration: none;
699
    margin-top: -2em;
700
    margin-right: 5em;
701
    font-size: 0.8em
700
    margin-top: -65px;
701
    margin-right: -36px;
702
    font-size: 10pt;
703
    background-color: #87aade;
704
    padding: 5px 10px;
702 705
}
703 706

  
704 707
div.instance-type {
......
727 730

  
728 731
div.list label {
729 732
    color: #87AADE;
730
    font-size:.8em;
733
    font-size:10pt;
731 734
}
732 735

  
733 736
div.list div.running {
......
790 793
    clear: left;
791 794
    color: #666 !important;
792 795
    display: block;
793
    font-size: .8em;
796
    font-size:10pt;
794 797
}
795 798

  
796 799
input.instance {
b/ui/templates/alt_instances.pt
1
<a id="create" rel="#wizard" href="#">Create New +</a>
2

  
3
<div id="instancesview" class="standard" tal:define="nodes context['nodes']">
4
    <a id="list" href="/instances/list">list view</a>
5
    <div class="instance running" tal:repeat="node nodes">
6
        <div tal:condition="node['state']=='3'" tal:omit-tag="">
7

  
8
        <div class="actions">
9
            <a href="#" class="action">reboot</a>
10
            <a href="#" class="action">shutdown</a>
11
            <a href="#" class="more">more &hellip;</a>
12
        </div>
13
        
14
        <div class="state">
15
            <div>Running</div>
16
            <div class="indicator" />
17
            <div class="indicator" />
18
            <div class="indicator" />
19
            <div class="indicator" />
20
        </div>
21

  
22
        <img src="static/pc.png" />
23
        <a href="#" class="name">
24
            <h5>Hostname: <span tal:replace="node['name']" /><span class="rename">rename</span></h5>
25
        </a>
26
        <a href="#" class="ip">
27
            <h5>IP: <span tal:replace="node['public_ip']" /></h5>
28
        </a>
29
        <br />
30
        <a href="#" class="storage">
31
            <h5>Show: disks | networks | group | uptime: 24 days</h5>
32
        </a>
33
        </div>
34
    </div>
35
</div>
36

  
37
<!-- the form -->
38
<form action="#">
39
	<!-- scrollable root element -->
40
	<div class="modal" id="wizard">
41
		<!-- status bar -->
42
		<ul id="status">
43
			<li class="active"><strong>1.</strong> Select image</li>
44
			<li><strong>2.</strong> Instance type</li>
45
			<li><strong>3.</strong> Review</li>
46
		</ul>
47
		<!-- scrollable items -->
48
		<div class="items">
49
			<!-- pages -->
50
			<div class="page">
51
                <h2>
52
					<strong>Step 1: </strong> Select image
53
					<em>Select an OS image to boot from</em>
54
				</h2>
55
                <ul class="tabs">
56
                    <li><a href="#">standard</a></li>
57
                    <li><a href="#">custom</a></li>
58
                </ul>
59
                <div class="panes" tal:define="images context['images']">
60
                    <ul class="pane">
61
					    <!-- standard images -->
62
					    <li>
63
						    <label for="${image['id']}" tal:repeat="image images"> 
64
                                <a tal:condition="image['type']=='standard'">
65
                                    <div class="image">
66
                                        <img tal:attributes="src image['logo']" class="image-logo" /> <strong>${image['title']}</strong><br />
67
                                        <span class="description">${image['description']}</span> 
68
                                        <span class="size">${image['size']}MB</span>
69
                                        <input class="radio" type="radio" name="image-id" id="${image['id']}" value="${image['id']}" checked="${repeat.image.start}" />
70
                                    </div>
71
                                </a>
72
						    </label> 
73
					    </li>
74
				    </ul>
75
                    <ul class="pane">
76
					    <!-- custom images -->
77
					    <li>
78
						    <label for="${image['id']}" tal:repeat="image images"> 
79
                                <a tal:condition="image['type']=='custom'">
80
                                    <div class="image">
81
                                        <img tal:attributes="src image['logo']" class="image-logo" /> <strong>${image['title']}</strong><br />
82
                                        <span class="description">${image['description']}</span> 
83
                                        <span class="size">${image['size']}MB</span>
84
                                        <input class="radio" type="radio" name="image-id" id="${image['id']}" value="${image['id']}" checked="${repeat.image.start}" />
85
                                    </div>
86
                                </a>
87
						    </label> 
88
					    </li>
89
                    </ul>
90
                </div>
91
				<button type="button" class="prev" id="cancel">Cancel</button>
92
				<button type="button" class="next right">Next &raquo;</button>
93
            </div>
94
			<div class="page">
95
				<h2>
96
					<strong>Step 2: </strong> Instance type <b></b>
97
					<em>Select CPU cores, RAM and storage space for your instance</em>
98
				</h2>
99
                <ul>
100
                    <li>
101
                        <div class="instance-type">
102
                            <label for="small">
103
                                <input type="radio" id="small" name="instance-type" value="small" checked="true" />
104
                                <strong>small</strong>
105
                            </label>
106
                        </div>
107
                        <div class="instance-type">      
108
                            <label for="medium">
109
                                <input type="radio" id="medium" name="instance-type" value="medium" />                  
110
                                <strong>medium</strong>
111
                            </label>
112
                        </div>
113
                        <div class="instance-type">
114
                            <label for="large">
115
                                <input type="radio" id="large" name="instance-type" value="large" />
116
                                <strong>large</strong>
117
                            </label>
118
                        </div>
119
                        <div class="instance-type">
120
                            <label for="custom">
121
                                <input type="radio" name="instance-type" id="custom" value="large" />
122
                                <strong>custom</strong>
123
                            </label>
124
                        </div>
125
                    </li>
126
                    <li>
127
			            <label><strong class="sliders">CPU (cores)</strong></label>
128
                        <input type="range" id="cpu" value="1" max="8" min="1" />
129
                    </li>
130
                    <li>
131
			            <label><strong class="sliders">RAM (MB)</strong></label>
132
                        <input type="range" id="ram" value="256" max="2048" min="256" step="256" />
133
                    </li>
134
                    <li>
135
		                <label><strong class="sliders">Storage (GB)</strong></label>
136
                        <input type="range" id="storage" value="5" step="1" max="100" min="2" />
137
                    </li>
138
                    <li>
139
                        <div class="cost">
140
                            Cost per hour for this VM: 20 credits | Credits currently in account: 10.000
141
                        </div>
142
                    </li>
143
                </ul>
144
				<button type="button" class="prev">&laquo; Back</button>
145
				<button type="button" class="next right">Next &raquo;</button>
146
            </div>
147
			<div class="page">
148
				<h2>
149
					<strong>Step 3: </strong> Review <b></b>
150
					<em>Confirm the settings below and create your new instance</em>
151
				</h2>
152
                <ul>
153
                    <li class="required">
154
                        <label>
155
                            <strong></strong> Instance name <span>*</span><br />
156
                            <input type="text" class="text" name="instance_name" value="My Ubuntu 10.04 x86_64 server"/>
157
                        </label>
158
                    </li>
159
                    <li>
160
                        <strong>Image:</strong> <span>Ubuntu 10.04 x86_64 server</span>
161
                    </li>
162
                    <li>
163
                        <strong>CPU:</strong> <span>2 cores</span>
164
                    </li>
165
                    <li>
166
                        <strong>RAM:</strong> <span>1024MB</span>
167
                    </li>
168
                    <li>
169
                        <strong>Storage:</strong> <span>10GB</span>
170
                    </li>
171
                    <li>
172
                        <strong>Cost per hour:</strong> <span>20 credits</span>
173
                    </li>
174
                    <li>
175
                        <strong>Remaining credits:</strong> <span>10.000</span>
176
                    </li>
177
                </ul>
178
				<button type="button" class="prev">&laquo; Back</button>
179
				<button type="button" class="next right" id="start">Create VM</button>        
180
            </div>
181
		</div>
182
	</div>
183
</form>
184

  
185
<div class="modal" id="misc">
186
    <h3>Your VM is being created!</h3>
187
    <p>Your password is:<strong> sdeEFre</strong></p>
188
    <p>Please copy this! Without it you can not connect to your VM.</p>
189
</div>
190

  
191
<script>
192
// <![CDATA[ 
193

  
194
$("#list").click(function(event){
195
    $("div#instancesview").load($("#list").attr("href"));
196
    return false;
197
});
198

  
199
$("ul.tabs").tabs("div.panes ul");
200

  
201
$(":range").rangeinput();
202

  
203
function disableSliders() {
204
    $("#cpu").attr('disabled',true);
205
    $("#ram").attr('disabled',true);
206
    $("#storage").attr('disabled',true);
207
}
208

  
209
$("#custom").click(function(event){
210
    $("#cpu").attr('disabled',false);
211
    $("#ram").attr('disabled',false);
212
    $("#storage").attr('disabled',false);
213
    $("strong.sliders").style = 'color: #778899;';
214
});
215

  
216
$("#small").click(function(event){
217
    $("#cpu").data('rangeinput').setValue(1);
218
    $("#ram").data('rangeinput').setValue(256);
219
    $("#storage").data('rangeinput').setValue(5);
220
});
221

  
222
$("#medium").click(function(event){
223
    $("#cpu").data('rangeinput').setValue(4);
224
    $("#ram").data('rangeinput').setValue(1024);
225
    $("#storage").data('rangeinput').setValue(30);
226
});
227

  
228
$("#large").click(function(event){
229
    $("#cpu").data('rangeinput').setValue(8);
230
    $("#ram").data('rangeinput').setValue(4096);
231
    $("#storage").data('rangeinput').setValue(80);
232
});
233

  
234
$("#cancel").click(function(event){
235
    $("a#create[rel]").overlay().close();
236
});
237

  
238
$("#start").click(function(event){
239
    $("a#create[rel]").overlay().close();
240

  
241
    var triggers = $("div#misc").overlay({
242
	    // some mask tweaks suitable for modal dialogs
243
	    mask: {
244
		    color: '#ebecff',
245
		    opacity: '0.9'
246
	    },
247
        top: 'center',
248
        load: 'true',
249
	    closeOnClick: 'false'  
250
    });
251
});
252

  
253
$("a#create").click(function(event){
254
    $("#wizard").scrollable().begin();
255
});
256

  
257
$("#cpu").change(function(event){
258
    $("#custom").click();
259
});
260

  
261
$("#ram").change(function(event){
262
    $("#custom").click();
263
});
264

  
265
$("#storage").change(function(event){
266
    $("#custom").click();
267
});
268

  
269
$(function() { 
270
    $("a#create[rel]").overlay({mask: '#000', effect: 'default', top: '5%'});
271

  
272
});
273

  
274
$(function() {
275
    var root = $("#wizard").scrollable();
276

  
277
    // some variables that we need
278
    var api = root.scrollable();
279

  
280
    // rangeinput with default configuration
281
    // validation logic is done inside the onBeforeSeek callback
282
    api.onBeforeSeek(function(event, i) {
283
	    // we are going 1 step backwards so no need for validation
284
	    if (api.getIndex() < i) {
285
             // 1. get current page
286
		     var page = root.find(".page").eq(api.getIndex()),
287
			 // 2. .. and all required fields inside the page
288
			 inputs = page.find(".required :input").removeClass("error"),
289
			 // 3. .. which are empty
290
			 empty = inputs.filter(function() {
291
				return $(this).val().replace(/\s*/g, '') == '';
292
			 });
293
		     // if there are empty fields, then
294
		    if (empty.length) {
295
			    // add a CSS class name "error" for empty & required fields
296
			    empty.addClass("error");
297
			    // cancel seeking of the scrollable by returning false
298
			    return false;
299
		    // everything is good
300
		    } 
301
	    }
302
	    // update status bar
303
	    $("#status li").removeClass("active").eq(i).addClass("active");
304
    });
305

  
306
    // if tab is pressed on the next button seek to next page
307
    root.find("button.next").keydown(function(e) {
308
	    if (e.keyCode == 9) {
309
		    // seeks to next tab by executing our validation routine
310
		    api.next();
311
		    e.preventDefault();
312
	    }
313
    });
314
// ]]>
315
});
316
</script>
317

  
b/ui/templates/home.pt
6 6
	<!-- include the Tools -->
7 7
	<script src="static/jquery.tools.min.js"></script>
8 8
	<link rel="stylesheet" type="text/css" href="static/alt-main.css"/>	
9
    <link href='http://fonts.googleapis.com/css?family=PT+Sans' rel='stylesheet' type='text/css' />
10

  
9 11
</head>
10 12

  
11 13
<body>
......
19 21
        </div>
20 22
        <!-- tabs -->
21 23
        <ul class="css-tabs">
22
	        <li><a href="instances" title="manage your virtual machines">instances</a></li>
23
	        <li><a href="disks" title="manage your storage volumes">disks</a></li>
24
	        <li><a href="images" title="manage boot images">images</a></li>
25
	        <li><a href="networks" title="configure networking">networks</a></li>
24
	        <li><a href="alt-instances" title="manage your virtual machines" id="instances">instances</a></li>
25
	        <li><a href="disks" title="manage your storage volumes" id="disks">disks</a></li>
26
	        <li><a href="images" title="manage boot images" id="images">images</a></li>
27
	        <li><a href="networks" title="configure networking" id="networks">networks</a></li>
26 28
        </ul>
27 29
        <div class="css-panes">
28 30
	        <div class="pane" style="display:block"></div>
b/ui/urls.py
4 4
urlpatterns = patterns('',
5 5
    (r'^$', 'synnefo.ui.views.home'),
6 6
    (r'^instances$', 'synnefo.ui.views.instances'),
7
    (r'^alt-instances$', 'synnefo.ui.views.alt_instances'),
7 8
    (r'^instances/list$', 'synnefo.ui.views.instances_list'),
8 9
    (r'^disks$', 'synnefo.ui.views.disks'),
9 10
    (r'^images$', 'synnefo.ui.views.images'),
b/ui/views.py
32 32
def instances(request):
33 33
    context = {'nodes': DEFAULT_NODES, 'images': DEFAULT_IMAGES}
34 34
    return template('instances', context)
35

  
36
def alt_instances(request):
37
    context = {'nodes': DEFAULT_NODES, 'images': DEFAULT_IMAGES}
38
    return template('alt_instances', context)
35 39
   
36 40
def instances_list(request):
37 41
    context = {'nodes': DEFAULT_NODES, 'images': DEFAULT_IMAGES}

Also available in: Unified diff