Revision faad3c72

b/snf-cyclades-app/synnefo/ui/new_ui/ui/Gruntfile.js
6 6
    emberTemplates: {
7 7
      compile: {
8 8
        options: {
9
          templateBasePath: /javascripts\/templates\//
9
          templateBasePath: /app\/templates\//
10 10
        },
11 11
        files: {
12
          'javascripts/templates.js': 'javascripts/templates/**/*.hbs'
12
          'dist/templates.js': 'app/templates/**/*.hbs'
13 13
        }
14 14
      }
15 15
    },
......
22 22
      },
23 23
      js: {
24 24
        files: [
25
          'javascripts/vendor/*.js',
26
          'javascripts/ember/**/*.js',
25
          'vendor/*.js',
26
          'app/**/*.js',
27 27
        ],
28 28
        tasks: ['concat']
29 29
      },
30 30
      emberTemplates: {
31
        files: 'javascripts/templates/**/*.hbs',
31
        files: 'app/templates/**/*.hbs',
32 32
        tasks: ['emberTemplates']
33 33
      },
34 34
      jshint: {
35
        files: ['javascripts/ember/**/*.js'],
35
        files: ['app/**/*.js'],
36 36
        tasks: ['jshint'],
37 37
      }
38 38
    },
......
50 50
        separator: ';',
51 51
      },
52 52
      dist: {
53
        src: ['javascripts/vendor/custom.modernizr.js', 'javascripts/vendor/jquery.js','javascripts/vendor/handlebars.js','javascripts/vendor/ember.js','javascripts/vendor/ember-data.js','javascripts/vendor/underscore-min.js','javascripts/vendor/jquery.farbtastic.js'],
53
        src: ['vendor/custom.modernizr.js', 'vendor/jquery.js','vendor/handlebars.js','vendor/ember.js','vendor/ember-data.js','vendor/underscore-min.js','vendor/jquery.farbtastic.js'],
54 54
        dest: 'dist/vendor.js',
55 55
      },
56 56
      ember: {
57
        dest: 'dist/vendor.js',
58
      },
59
      ember: {
60
        src: ['javascripts/ember/dict.js', 'javascripts/ember/**/*.js'],
61
        dest: 'dist/ember.js',
57
        src: ['app/**/*.js'],
58
        dest: 'dist/ember-app.js',
62 59
      }
63 60
    },
64 61
    jshint: {
65
      beforeconcat: ['javascripts/ember/**/*.js'],
62
      beforeconcat: ['app/**/*.js'],
66 63
    },
67 64
  });
68 65

  
b/snf-cyclades-app/synnefo/ui/new_ui/ui/app/app.js
1
window.App = Ember.Application.create();
2

  
3
App.ApplicationAdapter = DS.FixtureAdapter;
4

  
5
App.RawTransform = DS.Transform.extend({
6
  deserialize: function(serialized) {
7
    return serialized;
8
  },
9
  serialize: function(deserialized) {
10
    return deserialized;
11
  }
12
});
b/snf-cyclades-app/synnefo/ui/new_ui/ui/app/common.js
1
/*
2
* These functions are used throughout ember
3
*/
4

  
5

  
6

  
7

  
8
/* ---------------------- */
9
/* END OF EMBER FUNCTIONS */
10

  
11

  
12

  
13

  
14
/*
15
* Various functions that will be used throughout all templates
16
* are inside ui Object
17
*/
18

  
19
ui = {};
20
/*
21
* ui.wizards get populated in vm-wizard.js
22
* here is the declaration only
23
*/
24
ui.wizard = {};
25
ui.checkbox = {};
26
ui.radiobtn = {};
27

  
28
/* when closeEl el is clicked, its parent with class divToCloseClass slidesUp */
29
ui.closeDiv = function(closeEl, divToCloseClass) {
30
    closeEl.click(function(e){
31
        e.preventDefault();
32
        $(this).parents(divToCloseClass).slideUp('slow');
33
    });
34
}
35

  
36

  
37
ui.trimChars = function( str, chars) {
38
    if ( str.length>chars){
39
        return $.trim(str).substring(0, chars)+ "...";
40
    } else {
41
        return str;
42
    }
43
}
44

  
45

  
46
/* Sets element min-height
47
* Used for .details, .lt-bar divs
48
*/
49
ui.setElminHeight = function(el){
50
    var WindowHeight = $(window).height();
51
    var header = $('.header').outerHeight();
52
    var actions = $('.actions-bar').height();
53
    var h1= WindowHeight - (header+actions);
54
    el.css('min-height', h1);
55
}
56

  
57
/* Sets element height
58
* Used for .details, .lt-bar divs
59
*/
60
ui.setElHeight = function(el){
61
    var WindowHeight = $(window).height();
62
    var header = $('.header').outerHeight();
63
    var actions = $('.actions-bar').height();
64
    var h1= WindowHeight - (header+actions);
65
    el.css('height', h1);
66
}
67

  
68
/* Sets element max-height
69
* Used for div.storage-progress
70
*/
71
ui.setElmaxHeight = function(el){
72
    var WindowHeight = $(window).height();
73
    var header = $('.header').outerHeight();
74
    var actions = $('.actions-bar').height();
75
    var h1= WindowHeight - (header+actions);
76
    el.css('max-height', h1);
77
}
78

  
79
/* 
80
* Logic for Entities actions. Present in items_list pages
81
* Available categories are :
82
*  - both/single ( for multiple entities/single entities)
83
*  - running/off ( for running/off entities)
84
*  - permanent ( for entities always active )
85
* Can be used for pithos as well
86
* Available categories are :
87
* - files ( for files only actions)
88
* - folders ( for folders only actions)
89
* - all ( for files/folders actions)
90
*/
91
ui.entitiesActionsEnabled = function(){
92
    var all = $('.snf-checkbox-checked').length;
93
    var running = $('.snf-checkbox-checked').parents('li.running').length;
94
    var off = $('.snf-checkbox-checked').parents('li.off').length;
95
    var files = $('.snf-checkbox-checked').parents('li.file').length;
96
    var folders = $('.snf-checkbox-checked').parents('li.folder').length;
97

  
98
    console.log(files,'files');
99
    console.log(folders,'folders');
100

  
101
    $('.lt-bar .lt-actions li:not(.permanent) a').removeClass('active');
102

  
103
    if ( ( files * folders )>0 ) {
104
        $('.lt-actions li.all a').addClass('active');
105
    } else {
106
        if ( files>0 ) {
107
            $('.lt-actions li.files a').addClass('active');
108
        }
109
        if ( folders>0 ){
110
            $('.lt-actions li.folders a').addClass('active');
111
        }
112
    }
113

  
114
    if ( (running*off) > 0 ){
115
         $('.lt-actions li.both a').addClass('active');
116
         $('.lt-actions li.single a').removeClass('active');
117
    } else {
118
        if (running > 0) {
119
            $('.lt-actions li.both a').addClass('active');
120
            $('.lt-actions li.running a').addClass('active');
121
        } else if (off>0) {
122
            $('.lt-actions li.both a').addClass('active');
123
            $('.lt-actions li.off a').addClass('active');
124
        }
125
        if ( all > 1 ) {
126
            $('.lt-actions li.single a').removeClass('active');
127
        }
128
    }
129
}
130

  
131
ui.inactiveActions = function() {
132

  
133
    // Availble actions: connect, reboot, shut, destroy, start
134
    // These actions will be DISABLED
135
    var statesActions ={
136
        'off'      : ['connect', 'reboot', 'shut'],
137
        'error'    : ['connect', 'reboot', 'shut', 'start'],
138
        'building' : ['reboot', 'start'],
139
        'running'  : ['start'],
140
        'rebooting': ['start'],
141
        'starting' : ['start'],
142
        'shutting' : ['connect', 'reboot', 'shut']
143
    } ;
144

  
145
    _.each (statesActions, function(val, key) {
146
        _.each(val, function(value) {
147
            var el = '.' + key + ' .' + value;
148
            $(el).addClass('inactive');
149
        });
150
    })
151
}
152

  
153
ui.detailsCustom = function(area) {
154
    // position last connected item
155
    var el = area.find('.item').last();
156
    // -2 is the border width;
157
    var moveY = el.find('.connections >li').last().outerHeight(true) - 2;
158
    el.css('top',moveY);
159
    el.css('marginTop', -moveY);
160
}
161

  
162
ui.firewallSetup = function(){
163
    $('.firewall').each(function(){
164
        $(this).removeClass('fully unprotected basic');
165
        $(this).addClass($(this).data('firewall'));
166
        if($(this).hasClass('unprotected')){
167
            $(this).find('p').first().find('em').html('off');
168
        } else {
169
            $(this).find('p').first().find('em').html('on');
170
        }
171
    });
172
}
173

  
174

  
175

  
176
/*
177
* In order for the editable value functionality to work, the html markup
178
* should be:
179
    <div class="editable">
180
        <span class="input-txt">editable value</span>
181
        <input type="text">
182
        <a href="#" class="edit">edit</a>
183
        <a href="#" class="save">save</a>
184
        <a href="#" class="cancel">cancel</a>
185
    </div>
186
*/
187
ui.editable = function(){
188

  
189
/*
190
* resetForm hides save and cancel buttons,
191
* text input and shows input-txt. resetForm does not alter
192
* input-txt content.
193
*/
194

  
195
    function resetForm(e, elem) {
196
        var el = elem.parents('.editable');
197
        el.find('input[type="text"]').hide();
198
        el.find('a.cancel, a.save').hide();
199
        el.find('a.edit, .input-txt').show();
200
    }
201

  
202
/* 
203
* showForm hides input-txt, shows save and cancel buttons and
204
* sets input value to input-txt content.
205
*/
206
    function showForm(e,elem) {
207
        e.stopPropagation(); 
208
        e.preventDefault();
209
        var el = elem.parents('.editable'); 
210
        el.find('input[type="text"]').val(el.find('.input-txt').html());
211
        el.find('input[type="text"]').show().focus();
212
        el.find('a.cancel, a.save').show();
213
        elem.hide();
214
        el.find('.input-txt').hide();
215
    }
216

  
217
/*
218
setValue sets input-txt value to the input value.
219
Makes sure that the input value is not empty.
220
TODO:
221
Ajax request to submit form
222
*/
223

  
224
    function setValue(elem) {
225
        var el = elem.parents('.editable');
226
        if( el.find('input[type="text"]').val() ) {
227
            el.find('.input-txt').html(el.find('input[type="text"]').val());
228
        }
229
    }
230

  
231

  
232
    $('.editable .edit').click(function(e){
233
        showForm(e, $(this));
234
    })
235

  
236
    $('.editable .cancel').click(function(e){
237
        e.stopPropagation();
238
        e.preventDefault();
239
        resetForm(e, $(this));
240
    })
241

  
242
    $('.editable .save').click(function(e){
243
        e.stopPropagation();
244
        e.preventDefault();
245
        setValue($(this));
246
        resetForm(e, $(this));
247

  
248
    })
249

  
250

  
251
    $('.editable input[type="text"]').click(function(e){
252
        e.stopPropagation();
253
    })
254

  
255
    $('.editable input[type="text"]').keyup(function(e){
256
        if(e.keyCode == 13) { 
257
            setValue($(this));
258
            resetForm(e, $(this));
259
            
260
        }
261
    
262
    })
263

  
264
    $('html').click(function(e) {
265
        resetForm(e, $('.editable a.cancel'));
266
    });
267

  
268
}
269

  
270
/* TODO: better overlay functionality */
271
ui.overlay = function() {
272
    $('[data-overlay-id]').click(function(e){
273
        e.preventDefault();
274
        var el = $(this);
275
        var id = '#'+el.data('overlay-id');
276

  
277
        $('.overlay-area-custom').fadeIn(100);
278
        $('body').addClass('with-overlay');
279
        $(id).fadeIn('slow');
280
        if (id=='#network-wizard') {
281
            $(id).find('input').first().focus();
282
            return false;
283
        }
284
        $(id).find('a').first().focus();
285
    });
286
}
287

  
288
function goToByScroll(id){
289
      // Remove "link" from the ID
290
    id = id.replace("link", "");
291
      // Scroll
292
    $('html,body').animate({
293
        scrollTop: $("#"+id).offset().top},
294
        'slow');
295
}
296

  
297

  
298
// toggle expand arrrow  and  area
299
// todo: one function for all the areas we reveal
300
ui.expandDownArea = function(arrow_link, area) {
301
    var arrow_link = $(arrow_link);
302
    var area = $(area);
303
            arrow_link.find('span.snf-arrow-up, span.snf-arrow-down').toggleClass('snf-arrow-up snf-arrow-down');
304
            // $('.wizard-content').removeAttr('style');
305
            area.stop().slideToggle(600, function() {
306
                if (area.is(':visible')) {
307
                    arrow_link.find('.snf-arrow-down .snf-arrow-up').removeClass('snf-arrow-down').addClass('snf-arrow-up');
308
                } else {
309
                    arrow_link.find('.snf-arrow-down .snf-arrow-up').addClass('snf-arrow-down');
310
                }
311

  
312
            });
313
}
314

  
315
// toggle checkbox and area
316
ui.slideHiddenArea = function(checkbox_link, area) {
317
    area.stop().slideToggle(400, function() {
318
        if (area.is(':visible')) {
319
            ui.checkbox.check(checkbox_link);
320
        } else {
321
           ui.checkbox.uncheck(checkbox_link);
322
        }
323
    });
324
};
325
/* Tabs functionality
326
* tabsEl is the div/ul with the links to the sections and the sections that
327
* with toggle have class sectionEl.
328
* Markup needed is an href to each a with the id of the relative section.
329
*/
330

  
331
/*ui.tabsSection = function(link, sectionEl) {
332
    sectionEl.hide();
333
    var el = $(link.attr('href'));
334
    el.stop(true, true).show(0);
335
    el.css('opacity',0);
336
    ui.detailsCustom(el);
337
    el.animate({
338
        'opacity':1,
339
    }, 500)
340
}
341

  
342
ui.tabs = function(tabsEl, sectionEl) {
343
    var tabLink = tabsEl.find('a');
344
    ui.replaceClass(tabLink.find('.active'), 'outline', 'full', 'snf-');
345
    function href(a) {
346
        return a.attr('href');
347
    }
348
    tabLink.click(function(e){
349
        e.preventDefault();
350
        if ( $(this).hasClass('active')){
351
             return false;
352
        } else {
353
            window.location.hash = $(this).attr('href');
354
            ui.replaceClass($(this).parents(tabsEl).find('.active'), 'full', 'outline', 'snf-');
355
            $(this).parents(tabsEl).find('a').removeClass('active');
356
            $(this).addClass('active');
357
            ui.replaceClass($(this), 'outline', 'full', 'snf-');
358
            ui.tabsSection( $(this), sectionEl);
359
        }
360
    })
361
}*/
362

  
363
// the function replaces part of the class of a span that is placed inside an a element
364
// the class is a word with the form : firstSubStr+*+str1 and it will be converted to: firstSubStr+*+str2
365
// it must be uniquely recognized by the firstSubStr and the str1.
366

  
367
ui.replaceClass = function(elements, str1, str2, firstSubStr) {
368
    $.each($(elements), function() {
369
        var classOld = $(this).find('span').attr('class');
370
        var classNew;
371
        if(classOld != undefined && classOld.indexOf(str1) != -1) {
372
            if(classOld.indexOf(' ') == -1) {
373
                classNew = classOld.replace(str1, str2);
374
                $(this).find('.'+classOld).removeClass(classOld).addClass(classNew);
375
            }
376
            else {
377
                // the string starts with the firstSubStr and after the end of the word there's a space
378
                var expr1 = new RegExp('^'+firstSubStr+'+(\\S*)+'+str1+'+(\\s+)', 'g');
379

  
380
                // the word is between spaces
381
                var expr2 = new RegExp('(\\s+)'+firstSubStr+'+(\\S*)+'+str1+'+(\\s+)', 'g');
382

  
383
                // before the word there's at least one space and the string ends with this word
384
                var expr3 = new RegExp('(\\s+)'+firstSubStr+'+(\\S*)+'+str1+'$', 'g');
385

  
386
                // spaces all over the string
387
                var spacesExp = new RegExp('\\s+', 'g');
388

  
389
                if(classOld.match(expr1) != null) {
390
                    classToReplace = classOld.match(expr1);
391
                }
392
                else if(classOld.match(expr2) != null) {
393
                    classToReplace = classOld.match(expr2);
394
                }
395
                else if (classOld.match(expr3) != null) {
396
                    classToReplace = classOld.match(expr3);
397
                }
398
                classToReplace = classToReplace.toString().replace(spacesExp,"");
399
                classNew = classToReplace.replace(str1, str2);
400
                $(this).find('.'+classToReplace).removeClass(classToReplace).addClass(classNew);
401
            }
402
        }
403
    });
404
}
405

  
406
// in a page with tabs, allow navigation with hash tags
407
ui.hashTabs = function(tabsEl, sectionEl){
408
/*    var hash = window.location.hash;
409
    if ($(hash).length<=0){
410
        return;
411
    }
412
    tabsEl.find('a').removeClass('active');
413
    var link = tabsEl.find('a[href="'+hash+'"]');
414
    link.addClass('active');
415
    ui.tabsSection(link, sectionEl);
416
*/
417
}
418

  
419
// in a page with tabs, allow navigation with hash tags
420
ui.hashViews = function(viewsEl, sectionEl){
421
    /*var hash = window.location.hash;
422
    if (!(hash)){
423
        return;
424
    }
425
    var link = viewsEl.find('a[href="'+hash+'"]');
426
    console.log('link', link);
427
    if (link.length<=0){
428
        return;
429
    }
430
    viewsEl.find('a span').removeClass('current');
431
    link.find('span').addClass('current');
432
    sectionEl.removeClass('grid-view list-view');
433
    var sectionClass = hash.slice(1) + '-view';
434
    sectionEl.addClass(sectionClass);*/
435
}
436

  
437

  
438

  
439

  
440
ui.setCustomScrollBar = function() {
441
}
442

  
443
function bytesToSize(bytes) {
444
    var sizes = [ 'n/a', 'bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
445
    var i = +Math.floor(Math.log(bytes) / Math.log(1024));
446
    return  (bytes / Math.pow(1024, i)).toFixed( 0 ) + sizes[ isNaN( bytes ) ? 0 : i+1 ];
447
}
448
function date_ddmmmyytime(date)
449
{
450
  var d = date.getDate();
451
  var m = date.getMonth();
452
  var y = date.getYear();
453
  if(y >= 100)
454
  {
455
    y -= 100;
456
    y += 2000;
457
  }
458

  
459
    var curr_hour = date.getHours();
460

  
461
    if (curr_hour < 12){
462
        a_p = "am";
463
    } else {
464
       a_p = "pm";
465
    }
466

  
467
    if (curr_hour == 0) {
468
       curr_hour = 12;
469
    }
470
    if (curr_hour > 12){
471
       curr_hour = curr_hour - 12;
472
    }
473

  
474
    var curr_min = date.getMinutes();
475

  
476
  return "" +
477
    (d<10?"0"+d:d) + "/" +m + "/" + y + ' '+curr_hour + ":" + curr_min + a_p;
478
}
479

  
480
 // returns the file class/extension of a file
481
ui.mimeToExt = function( mimetype) {
482
  var mimeExt = {
483
    'image/jpeg': 'jpg',
484
    'image/png': 'png',
485
    'application/pdf': 'pdf',
486
    'text/plain': 'txt',
487
  };
488
  console.log(mimetype);
489
  return mimeExt[mimetype] || 'unknown';
490
}
491

  
492
$(document).ready(function(){
493

  
494
    $('html').click(function(e) {
495
        // not sure if we want to hide the error window after every click in the ui
496
        if($('.communication-error').css('bottom') == '0px') {
497
            $('.communication-error').animate({bottom: "-151px"});
498
        }
499
    });
500

  
501
    if($('.vms.entities').length!=0){
502
        ui.inactiveActions();
503
    };
504
    ui.setElminHeight($('.main > .details'));
505
    ui.setElminHeight($('.lt-bar'));
506
    ui.setElmaxHeight($('.storage-progress'));
507
    $('#hd-search .hd-icon-search').click(function(e){
508
        var that = this;
509
        $(this).parents('.hd-search').toggleClass('hd-open');
510
        if ($(this).parents('.hd-search').hasClass('hd-open')) {
511
            $(that).parents('.hd-search').find('input[type="search"]').focus();
512
        } else {
513
            $(that).parents('.hd-search').find('input[type="search"]').val('');
514
        }
515
    })
516

  
517
    $('.header .login').mouseenter(function(e){
518
        $(this).find('ul').stop(true, true).slideDown(200);
519
    });
520
    $('.header .login').mouseleave(function(e){
521
        $(this).find('ul').stop(true, true).slideUp(200);
522
    });
523

  
524
    $('.entities a').click(function(){
525
        if ($(this).attr('data-reveal-id') && !($(this).hasClass('inactive'))) {
526
            $('.entities li .more').hide();
527
        }
528
    });
529

  
530
    $('.inactive').click(function(e){
531
        e.stopPropagation();
532
        e.preventDefault();
533
     });
534

  
535
    $('.arrows').on('click','.inactive', function(e){
536
        e.preventDefault();
537
        e.stopPropagation();
538
    });
539

  
540

  
541
    $('.lt-actions a:not(.active)').click(function(e){
542
        e.preventDefault();
543
    })
544

  
545
    if ($('.entities .items-list >li').length == 1) {
546
        $('.body-wrapper').addClass('no-vm');
547
    };
548
    $('.entities li .more').each(function(){
549
        var width = $(this).parent('li').outerWidth()  + 20;
550
        $(this).css('width', width);
551
    });
552

  
553
    $('.items-list li .img-wrap').on("mouseenter", function(e) {
554
        var that = this;
555
        if ($(this).parents('.entities').hasClass('grid-view')) {
556
            if ($(that).parent('.container').siblings('.more').length>0) {
557
                $(that).parent('.container').fadeOut(50,'easeInCirc');
558
                $(that).parent('.container').siblings('.more').fadeIn(150,'easeInCirc');
559
            }
560
        }
561
    });
562
    $('.entities li .more').mouseleave(function(e) {
563
        $(this).fadeOut(50, function() {
564
            $(this).siblings('.container').fadeIn(50);
565
        });
566
    });
567
    $('.grid-view .items-list > li').mouseleave(function(e){
568
        var that = this;
569
        setTimeout(function(){
570
            $(that).find('.more').fadeOut(200, function() {
571
                $(this).siblings('.container').fadeIn('fast');
572
            });
573
        },50)
574
    });
575

  
576
    ui.closeDiv($('.info .close'), '.info');
577
    //ui.editable();
578
    ui.overlay();
579
    ui.colorPickerVisible = 0;
580

  
581
    $("a.disabled").each(function() {
582
        $(this).removeAttr('href');
583
    });
584
    
585
    $("a.disabled").click(function(e) {
586
        e.preventDefault();
587
    });
588

  
589
    $('.main-actions li a').click(function(e){
590
        if (!($(this).hasClass('active'))) {
591
            e.preventDefault();
592
        }
593
    });
594

  
595
    $('.main-actions li a').click(function(e){
596
        if (!($(this).hasClass('active'))) {
597
            e.preventDefault();
598
        }
599
    });
600
    $('.overlay-area-custom').children('.close').click(function(e){
601
        e.preventDefault();
602
        e.stopPropagation();
603
        $(this).parents('.overlay-area-custom').hide();
604
        $(this).parents('.overlay-area-custom').find($('.overlay-div')).hide();
605
        $('body').removeClass('with-overlay');
606
    })
607

  
608
    $('.browse-files').click(function(e){
609
        e.preventDefault();
610
    });
611

  
612
    if($('#picker-1').length>0) {
613
        $('#picker-1').farbtastic('#color-1');
614
    };
615
    if($('#picker-2').length>0) {
616
        $('#picker-2').farbtastic('#color-2');
617
    };
618
    if($('#sb-search').length>0) {
619
        new UISearch( document.getElementById( 'sb-search' ) );
620
    }
621

  
622
    if ($('.toggle-lt-bar').length>0) {
623
        ui.ltBarToggle(400);
624
    }
625

  
626
    /* grid/list view for items-list */
627

  
628
    $('.actions-bar .list, .actions-bar .grid').click(function(e){
629
        //e.preventDefault();
630
        /*if (!($(this).find('span').hasClass('current'))) {
631
            $('.actions-bar .grid span, .actions-bar .list span').removeClass('current');
632
            $(this).find('span').addClass('current');
633
            $('.entities').toggleClass('grid-view list-view');
634
        }*/
635
    });
636

  
637

  
638

  
639
    // set filter visible
640
    $('.filter-menu .filter').click(function(e) {
641
        e.preventDefault();
642
        $(this).parents('.filter-menu').toggleClass('current');
643
    });
644

  
645
    // temp function used to demonstrate the visual effect of the building state of vm
646
    $('[data-status="building"] .btn5.temp').click(function(e) {
647
        e.preventDefault();
648
        $(this).siblings('.container').find('.complete').toggleClass('build-progress');
649
    });
650

  
651
    $('[data-status="rebooting"] .btn5.temp').click(function(e) {
652
        e.preventDefault();
653
        $(this).siblings('.container').find('.snf-pc-full').toggleClass('reboot-progress');
654
    })
655

  
656
    // //temp function to preventDefault of links in modal
657
    // $('.reveal-modal a:not(".close-reveal-modal, .generate-key-btn, .import-key-btn")').click(function(e){
658
    //     e.preventDefault();
659
    //     $('a.close-reveal-modal').trigger('click');
660
    // });
661

  
662
     // temp btn to show communication error message
663
    $('.temp-for-btns .communication-error-btn').click(function(e) {
664
         e.preventDefault();
665
         e.stopPropagation();
666
         $('.communication-error').animate({bottom: "0px"});
667
     });
668

  
669
    $('.communication-error a').click(function(e) {
670
        e.preventDefault();
671
        e.stopPropagation();
672
        $('.communication-error').animate({bottom: "-151px"});
673

  
674
    });
675
    $('.communication-error').click(function(e) {
676
        e.stopPropagation();
677
    });
678

  
679
    $('.show-add-tag').click(function(e) {
680
        e.preventDefault();
681
        $(this).parents('.tags-area, .tags').find('.snf-color-picker').slideDown('slow', function() {
682
            $('#hide-add-tag-dummy').scrollintoview({
683
                'duration': 'slow'
684
        });
685
    });
686
    ui.colorPickerVisible = 1;
687
    });
688

  
689
    $('.hide-add-tag').click(function(e) {
690
    e.preventDefault();
691
    $(this).parents('.tags-area, .tags').find('.snf-color-picker').slideUp(400, function() {
692
        $('.show-add-tag').first().scrollintoview({
693
            'duration': 'slow'
694
        });
695
        ui.colorPickerVisible = 0;
696
    });
697
    });
698

  
699
    // connected details js
700
    ui.detailsCustom($('#disk-connected'));
701
    ui.detailsCustom($('#network-connected'));
702
    ui.detailsCustom($('#vm-connected'));
703
    ui.firewallSetup();
704

  
705
    $('.firewall').mouseenter(function(e){
706
        $(this).css('z-index',2);
707
        $(this).find('.more').stop(true, true).slideDown(200);
708
    });
709
    $('.firewall').mouseleave(function(e){
710
        $(this).css('z-index',1);
711
        $(this).find('.more').stop(true, true).slideUp(200);
712
    });
713
    //ui.tabs($('.tabs'), $('.content'));
714
    ui.hashTabs($('.tabs'), $('.content'));
715
    ui.hashViews($('.actions-bar .rt-actions'), $('.entities'));
716

  
717
    $('.act').click(function(e) {
718
        $(this).addClass('pending last');
719
    });
720

  
721
    $('.remove .cancel').click(function(e) {
722
        e.preventDefault();
723
        $('a.close-reveal-modal').trigger('click');
724
        $('.last').removeClass('pending last');
725
    });
726

  
727
    $('.remove .ok').click(function(e) {
728
        e.preventDefault();
729
        $('a.close-reveal-modal').trigger('click');
730
        
731
    });
732
    // end of connected details js
733

  
734
    ui.replaceClass($('a.current, a.active'), 'outline', 'full', 'snf-');
735

  
736

  
737

  
738
    $('.storage-progress').hover(
739
        function(e){
740
            $(this).find('.details').stop(false,true).slideDown();
741
        },
742
        function(e){
743
            $(this).find('.details').stop(false,true).slideUp();
744
        }
745
    );
746

  
747
    $('.btn-more').mouseenter(function(e) {
748
        $(this).find('.explain').stop(true, true).show('slow');
749
    });
750

  
751
    $('.btn-more').click(function(e) {
752
        e.preventDefault();
753
        e.stopPropagation();
754
        $('.btn-more').removeClass('clicked');
755
        $('.btn-more').siblings('ul').hide();
756
        $(this).addClass('clicked');
757
        $(this).siblings('ul').stop(true, true).slideDown('slow');
758
    });
759
    $('.containers .project').mouseleave(function(e){
760
        $(this).find('ul').fadeOut();
761
        $(this).find('.btn-more').removeClass('clicked');
762
    })
763

  
764
    if ($('.containers .btn-more').length>0) {
765
        $('body').click(function(e){
766
            $('.btn-more').removeClass('clicked');
767
            $('.btn-more').siblings('ul').fadeOut();
768
        })
769
    }
770

  
771
    // add a <span> element inside the content of each a.wrap-a element
772
    $('a.wrap-a').wrapInner('<span></span>');
773

  
774

  
775
    $('.side-actions .bottom .reassign').click(function(e){
776
        e.preventDefault();
777
        $(this).parents('.bottom').find('ul').hide();
778
        $(this).parents('.bottom').find('ul.options').show();
779
    });
780

  
781
    $('.side-actions ul.options').mouseleave(function(e){
782
        $(this).hide();
783
        $(this).siblings('ul').removeAttr('style');
784
    })
785

  
786
})
787

  
788

  
789
$(window).resize(function(e){
790
    ui.setElminHeight($('.main > .details'));
791
    ui.setElminHeight($('.lt-bar'));
792
    ui.setElHeight($('.scroll-wrap'));
793
    ui.setCustomScrollBar();
794
    ui.setElmaxHeight($('.storage-progress'));
795

  
796
});
797

  
798

  
799
_.mixin({
800
  capitalize: function(string) {
801
    return string.charAt(0).toUpperCase() + string.substring(1).toLowerCase();
802
  }
803
});
b/snf-cyclades-app/synnefo/ui/new_ui/ui/app/components/details-content.js
1
App.DetailsContentComponent = Ember.Component.extend({
2
    classNames: ['content'],
3
    tagName: 'section',
4
});
b/snf-cyclades-app/synnefo/ui/new_ui/ui/app/components/editable-prop.js
1
App.EditablePropComponent = Ember.Component.extend({
2

  
3
    tagName: 'div',
4
    classNames: ['editable'],
5
    layoutName: 'editable-prop',
6
    isEditable: false,
7

  
8
    actions: {
9
        allowEdit: function(){
10
            this.set('isEditable', true);
11
        },
12
        acceptEditableChanges: function(){
13
            this.set('isEditable', false);
14
            this.sendAction('ok');
15
        },
16
    }
17

  
18
});
b/snf-cyclades-app/synnefo/ui/new_ui/ui/app/components/network-el.js
1
App.NetworkElComponent = Ember.Component.extend({
2
    tagName: 'section',
3
});
b/snf-cyclades-app/synnefo/ui/new_ui/ui/app/components/reveal-modal.js
1
App.RevealModalComponent = Ember.Component.extend({
2
    classNames: ['reveal-modal', 'medium'],
3
    actions: {
4
        ok: function () {
5
            this.get("okCallback")();
6
        },
7
        close: function () {
8
            $(this.$()[0]).foundation('reveal', 'close');		
9
        },
10
    },
11
});
b/snf-cyclades-app/synnefo/ui/new_ui/ui/app/components/tag-el.js
1
App.TagElComponent = Ember.Component.extend({
2
    tagName: 'li',
3
    title:'tag1',
4
    color: 'yellow',
5
    style: function () {
6
        return 'background-color:'+this.color;
7
    }.property('color'),
8

  
9
    didInsertElement: function() {
10
        this.$().find('.tag').attr('data-tooltip','');
11
        Foundation.libs.tooltips.init();
12
    },
13

  
14
    actions: {
15
        deleteTag: function() {
16
            this.sendAction('deleteTag', this.get('param'));
17
        },
18
    },
19

  
20
});
b/snf-cyclades-app/synnefo/ui/new_ui/ui/app/components/volume-el.js
1
App.VolumeElComponent = Ember.Component.extend({
2
    tagName: 'section',
3

  
4
    actions: {
5

  
6
        revealModal: function(){
7

  
8
            var component = Ember.View.views.generic;
9
            component.set('message', '<p>Are you sure you want to dettach this Volume?</p>');
10
            component.set('okCallback', _.bind(function() {
11
                $("#generic").foundation('reveal', 'close');
12
                this.sendAction('ok',this.get('param'));
13
            }, this));
14
            $("#generic").foundation('reveal', 'open');
15
        },
16

  
17
    },
18
});
b/snf-cyclades-app/synnefo/ui/new_ui/ui/app/controllers/item.js
1
App.ItemsItemController = Ember.ObjectController.extend({
2

  
3
    codeName: 'vm',
4

  
5
    needs: [],
6

  
7
    hasViewCls: true,
8

  
9
    // i would like to get it from parent controller ????
10
    icon:  function () {
11
        var item = this.codeName;
12
        return 'snf-'+item+'-full';
13
    }.property(),
14

  
15
    hasTags: true,
16

  
17
    codeNameParent: function() {
18
        return this.codeName+'s';
19
    }.property(),
20

  
21
    codeNameChildInit: function() {
22
        return this.codeName+'init';
23
    }.property(),
24
    
25

  
26

  
27
});
b/snf-cyclades-app/synnefo/ui/new_ui/ui/app/controllers/items.js
1
App.ItemsListController = Ember.ArrayController.extend({
2
    
3
    codeName: '',
4

  
5
    // returns the same as codename, i.e. networks, serves as page title
6
    title: function () {
7
        return this.codeName;
8
    }.property(),
9

  
10
    // returns codename without an 's', i.e. network
11
    _item: function () {
12
        return this.codeName.substring(0, this.codeName.length - 1);
13
    }.property(),
14
    
15
    // returns codename without an 's', i.e. network
16
    itemController: function () {
17
        return this.get('_item');
18
    }.property(),
19

  
20
    // returns snf-network-full
21
    iconCls:  function () {
22
        return 'snf-'+this.get('_item')+'-full';
23
    }.property(),
24

  
25
    // returns snf-network-create-full
26
    newIcon:  function () {
27
        return 'snf-'+this.get('_item')+'-create-full';
28
    }.property(),
29

  
30
    // returns Create new network
31
    newTxt:  function () {
32
        return 'Create new '+this.get('_item');
33
    }.property(),
34
    
35
    // enables grid/list view in action bar
36
    hasViewCls: true,
37

  
38
    // enables search functionality action bar
39
    hasSearch: true,
40

  
41
    // enables filtering in action bar    
42
    hasFilter: true,
43

  
44
    codeNameParent: function () {
45
        return this.codeName;
46
    }.property(),
47

  
48
    codeNameChildInit: function () {
49
        return this.get('_item')+'init';
50
    }.property(),
51
    
52
});
53

  
54

  
55
App.NetworksController = App.ItemsListController.extend({
56
    codeName : 'networks',
57
});
58

  
59

  
60
App.VmsController = App.ItemsListController.extend({
61
    codeName : 'vms',
62
    newIcon  : 'snf-pc-create-full', 
63
    iconCls  : 'snf-pc-full',
64
});
65

  
66

  
67
App.VolumesController = App.ItemsListController.extend({
68
    codeName : 'volumes',
69
});
70

  
71
App.TagsController = Ember.ArrayController.extend();
b/snf-cyclades-app/synnefo/ui/new_ui/ui/app/controllers/network.js
1
App.NetworkController = App.ItemsItemController.extend({
2

  
3
    codeName: 'network',
4
    
5
    actionsMeta: function() {
6
        var enabledActions = this.get('model').get('enabledActions');
7
        return _.map(enabledActions, function(val,key) { return actionsMetaNetwork[val]; });      
8
    }.property('model.enabledActions'),
9

  
10
    submenu: [
11
        {
12
            'link': 'network.info',
13
            'icon': 'snf-info-outline',
14
        },
15
        {
16
            'link': 'network.vm-connected',
17
            'icon': 'snf-pc-outline',
18
        },
19
    ],
20

  
21
});
b/snf-cyclades-app/synnefo/ui/new_ui/ui/app/controllers/tag.js
1
App.TagController = Ember.ObjectController.extend({
2
    actions: {
3
        createTag: function(data, model) {
4
            var tag = this.store.createRecord('tag', data);
5
            tag.save();
6

  
7
            // model can be any model class instance which 
8
            // shares the tags interface used below.
9
            if (model) {
10
              model.get('tags').addObject(tag);
11
            }
12
        }
13
    },
14
});
15

  
16

  
17
var _defaultNewTagColor = '#16C1E9';
18

  
19
App.AddTagController = App.TagController.extend({
20
  newTagName: '',
21
  newTagColor: _defaultNewTagColor,
22
  closed: false,
23
  actions: {
24
    handleSubmit: function() {
25
      // resolve form params
26
      var tagDetails = {
27
        name: this.get('newTagName'),
28
        color: this.get('newTagColor')
29
      };
30
      
31
      // validate ???
32
      // failed validation messages ???
33

  
34
      // do create tag
35
      this.send('createTag', tagDetails, this.get('model'));
36
  
37
      // hide form (view should use this attr)
38
      this.set('closed', true);
39

  
40
      // reset the newTagXXX shit
41
      this.set('newTagName', '');
42
      this.set('newTagColor', _defaultNewTagColor);
43
    }
44
  }
45
});
b/snf-cyclades-app/synnefo/ui/new_ui/ui/app/controllers/vm.js
1
App.VmController =App.ItemsItemController.extend({
2
    icon: 'snf-pc-full',
3

  
4
    actionsMeta: function() {
5
        var enabledActions = this.get('model').get('enabledActions');
6
        return _.map(enabledActions, function(val,key) { return actionsMetaVm[val]; });      
7
    }.property('model.enabledActions'),
8

  
9
    submenu: [
10
        {
11
            'link': 'vm.info',
12
            'icon': 'snf-info-outline',
13
        },
14
        {
15
            'link': 'vm.disk-connected',
16
            'icon': 'snf-volume-outline',
17
        },
18
        {
19
            'link': 'vm.network-connected',
20
            'icon': 'snf-network-outline',
21
        }
22
    ],
23
    
24
    actions: {
25

  
26
        deleteTag: function(tag) {
27
            this.get('model').get('tags').removeObject(tag);
28
        },
29

  
30
        dettachVolume: function(volume){
31
            this.get('model').get('volumes').removeObject(volume);
32
        },
33

  
34
        saveModel: function(){
35
            this.get('model').save();
36
        },
37

  
38

  
39
        modalConnect: function(){
40
            var component = Ember.View.views["modal-connect"];
41
            component.set('message', 'connect to your <3 ' + this.get('model').get('name'));
42
            component.set('okCallback', _.bind(function() {
43
                alert("restarting " + this.get('model').get('name'));
44
            }, this));
45
            $("#modal-connect").foundation('reveal', 'open');
46
        },
47

  
48
        modalStart: function(){
49
            $("#modal-start").foundation('reveal', 'open');
50
        },
51

  
52
        modalShutdown: function(){
53
            $("#modal-shutdown").foundation('reveal', 'open');
54
        },
55

  
56
        modalReboot: function(){
57
            $("#modal-reboot").foundation('reveal', 'open');
58
            var component = Ember.View.views["modal-reboot"];
59
            component.set('message', '<p>Are you sure you want to reboot you VM <strong>' + this.get('model').get('name')+'</strong> ?</p>');
60
            component.set('okCallback', _.bind(function() {
61
                this.get('model').set('state','rebooting');
62
                $("#modal-reboot").foundation('reveal','close');
63
            }, this));
64
        },
65

  
66
        modalDestroy: function(){
67
            $("#modal-destroy").foundation('reveal', 'open');
68
            var component = Ember.View.views["modal-destroy"];
69
            component.set('message', '<p>Are you sure you want to delete you VM <strong>' + this.get('model').get('name')+'</strong> ?</p>');
70
            component.set('okCallback', _.bind(function() {
71
                this.get('model').deleteRecord();
72
                this.get('model').save();
73
                $("#modal-destroy").foundation('reveal','close');
74
            }, this));
75
        },
76

  
77
    },
78
});
79

  
80
App.VmInfoController = App.VmController.extend();
81

  
82
App.VmDiskConnectedController = App.VmController.extend();
b/snf-cyclades-app/synnefo/ui/new_ui/ui/app/controllers/volume.js
1
App.VolumeController = App.ItemsItemController.extend({
2

  
3
    codeName: 'volume',
4
    
5
    actionsMeta: function() {
6
        var enabledActions = this.get('model').get('enabledActions');
7
        return _.map(enabledActions, function(val,key) {return actionsMetaVolume[val]; });      
8
    }.property('model.enabledActions'),
9

  
10
    submenu: [
11
        {
12
            'link': 'volume.info',
13
            'icon': 'snf-info-outline',
14
        },
15
        {
16
            'link': 'volume.vm-connected',
17
            'icon': 'snf-pc-outline',
18
        },
19
    ],
20
});
b/snf-cyclades-app/synnefo/ui/new_ui/ui/app/helpers/helpers.js
1
Ember.Handlebars.helper('status-to-text', function(value) {
2
  return statusText[value];
3
}, 'status');
4

  
5
Ember.Handlebars.registerHelper('myrender', function(name, contextString, options) {
6
  // controller option set ???
7
  if (options.hash.controller) {
8
      // resolve string from current context
9
      var resolvedControllerName = Ember.Handlebars.get(options.contexts[0], options.hash.controller, options);
10
      if (resolvedControllerName) {
11
          options.hash.controller = resolvedControllerName;
12
      }
13
  }
14
  // call ember render helper
15
  return Ember.Handlebars.helpers.render.call(this, name, contextString, options);
16
});
17

  
18

  
19
Ember.Handlebars.helper('bytes-to-human',function (value) {
20
  function humanFileSize(bytes, si) {
21
      var thresh = si ? 1000 : 1024;
22
      if(bytes < thresh) return bytes + ' B';
23
      var units = si ? ['kB','MB','GB','TB','PB','EB','ZB','YB'] : ['KiB','MiB','GiB','TiB','PiB','EiB','ZiB','YiB'];
24
      var u = -1;
25
      do {
26
          bytes /= thresh;
27
          ++u;
28
      } while(bytes >= thresh);
29
      return bytes.toFixed(1)+' '+units[u];
30
  }
31
  console.log(value);
32
  return humanFileSize(value,false);
33
}, 'value');
b/snf-cyclades-app/synnefo/ui/new_ui/ui/app/index.html
1
<!DOCTYPE html>
2
    <!--[if lte IE 7]><script src="javascripts/lte-ie7.js"></script><![endif]-->
3
<!--[if IE 8]>               <html class="no-js lt-ie9" lang="en"> <![endif]-->
4
<!--[if gt IE 8]><!--> <html class="no-js" lang="en"> <!--<![endif]-->
5

  
6
<head>
7
    <meta charset="utf-8" />
8
    <meta name="viewport" content="width=device-width" />
9
    <title>Ember UI</title>
10
    <link href='https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700&amp;subset=latin,greek-ext,greek' rel='stylesheet' type='text/css'>
11
    <link rel="stylesheet" href="../stylesheets/normalize.css" />
12
    <link rel="stylesheet" href="../stylesheets/app.css" />
13
    <link rel="stylesheet" href="../stylesheets/farbtastic.css" />
14
    <link rel="stylesheet" href="../stylesheets/font_custom.css" />
15
    <link rel="stylesheet" href="../stylesheets/jquery.jscrollpane.css" media="all" />
16
    <link rel="stylesheet" href="../stylesheets/magnific-popup.css" />
17
</head>
18
<body>  
19

  
20

  
21
    <script src="../dist/vendor.js"></script>
22
    
23
    <script src="../vendor/foundation/foundation.js"></script>
24
    <script src="../vendor/foundation/foundation.alerts.js"></script>
25
    <script src="../vendor/foundation/foundation.clearing.js"></script>
26
    <script src="../vendor/foundation/foundation.cookie.js"></script>
27
    <script src="../vendor/foundation/foundation.dropdown.js"></script>
28
    <script src="../vendor/foundation/foundation.forms.js"></script>
29
    <script src="../vendor/foundation/foundation.joyride.js"></script>
30
    <script src="../vendor/foundation/foundation.magellan.js"></script>
31
    <script src="../vendor/foundation/foundation.orbit.js"></script>
32
    <script src="../vendor/foundation/foundation.placeholder.js"></script>
33
    <script src="../vendor/foundation/foundation.reveal.js"></script>
34
    <script src="../vendor/foundation/foundation.section.js"></script>
35
    <script src="../vendor/foundation/foundation.tooltips.js"></script>
36
    <script src="../vendor/foundation/foundation.topbar.js"></script>
37
    
38
    <script src="../dist/templates.js"></script>
39
    <script src="../dist/ember-app.js"></script>
40
        
41
  <script>
42
    $(document).foundation();
43
  </script>
44
</body>
45
</html>
b/snf-cyclades-app/synnefo/ui/new_ui/ui/app/metadata.js
1
var actionsMetaNetwork = {
2
    'start': {
3
        title: 'start',
4
        act: 'modalStart',
5
        spanCls: 'snf-switch',
6
    },
7
    'destroy': {
8
        title: 'destroy',
9
        act: 'modalDestroy',
10
        spanCls: 'snf-trash-outline',
11
    },
12
    'reboot': {
13
        title: 'reboot',
14
        act: 'modalReboot',
15
        spanCls: 'snf-refresh-outline',
16
    },
17
    'shutdown': {
18
        title: 'shutdown',
19
        act: 'modalShutdown',
20
        spanCls: 'snf-pc-broken-full',
21
    },
22
};
23

  
24
var actionsMetaVm = {
25
    'start': {
26
        title: 'start me now',
27
        act: 'modalStart',
28
        spanCls: 'snf-switch',
29
    },
30
    'destroy': {
31
        title: 'destroy',
32
        act: 'modalDestroy',
33
        spanCls: 'snf-trash-outline',
34
    },
35
    'reboot': {
36
        title: 'reboot',
37
        act: 'modalReboot',
38
        spanCls: 'snf-refresh-outline',
39
    },
40
    'shutdown': {
41
        title: 'shutdown',
42
        act: 'modalShutdown',
43
        spanCls: 'snf-pc-broken-full',
44
    },
45
};
46

  
47
var actionsMetaVolume = {
48
    'start': {
49
        title: 'start me now',
50
        act: 'modalStart',
51
        spanCls: 'snf-switch',
52
    },
53
    'destroy': {
54
        title: 'destroy',
55
        act: 'modalDestroy',
56
        spanCls: 'snf-trash-outline',
57
    },
58
    'reboot': {
59
        title: 'reboot',
60
        act: 'modalReboot',
61
        spanCls: 'snf-refresh-outline',
62
    },
63
    'shutdown': {
64
        title: 'shutdown',
65
        act: 'modalShutdown',
66
        spanCls: 'snf-pc-broken-full',
67
    },
68
};
69

  
70

  
71
var statusText ={
72
    'off'      : 'STOPPED',
73
    'error'    : 'ERROR',
74
    'building' : 'BUILDING',
75
    'running'  : 'RUNNING',
76
    'rebooting': 'REBOOTING',
77
    'starting' : 'STARTING',
78
    'shutting' : 'SHUTTING DOWN',
79
};
80

  
81

  
82
var statusActionsVm = {
83
    'off'      : {
84
        enabledActions : ['start', 'destroy'],
85
    },
86
    'error'      : {
87
        enabledActions : ['destroy'],
88
    },
89
    'building'      : {
90
        enabledActions : [],
91
    },
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff