diff --git a/server/src/uds/static/adm/css/buttons.css b/server/src/uds/static/adm/css/buttons.css index a874d5407..3ad634f38 100644 --- a/server/src/uds/static/adm/css/buttons.css +++ b/server/src/uds/static/adm/css/buttons.css @@ -14,27 +14,27 @@ .btn3d:active { top:9px; } -.btn-default { +.btn3d-default { box-shadow:0 0 0 1px #ebebeb inset, 0 0 0 2px rgba(255,255,255,0.15) inset, 0 8px 0 0 #adadad, 0 8px 0 1px rgba(0,0,0,0.4), 0 8px 8px 1px rgba(0,0,0,0.5); background-color:#fff; } -.btn-primary { +.btn3d-primary { box-shadow:0 0 0 1px #428bca inset, 0 0 0 2px rgba(255,255,255,0.15) inset, 0 8px 0 0 #357ebd, 0 8px 0 1px rgba(0,0,0,0.4), 0 8px 8px 1px rgba(0,0,0,0.5); background-color:#428bca; } - .btn-success { + .btn3d-success { box-shadow:0 0 0 1px #5cb85c inset, 0 0 0 2px rgba(255,255,255,0.15) inset, 0 8px 0 0 #4cae4c, 0 8px 0 1px rgba(0,0,0,0.4), 0 8px 8px 1px rgba(0,0,0,0.5); background-color:#5cb85c; } - .btn-info { + .btn3d-info { box-shadow:0 0 0 1px #5bc0de inset, 0 0 0 2px rgba(255,255,255,0.15) inset, 0 8px 0 0 #46b8da, 0 8px 0 1px rgba(0,0,0,0.4), 0 8px 8px 1px rgba(0,0,0,0.5); background-color:#5bc0de; } -.btn-warning { +.btn3d-warning { box-shadow:0 0 0 1px #f0ad4e inset, 0 0 0 2px rgba(255,255,255,0.15) inset, 0 8px 0 0 #eea236, 0 8px 0 1px rgba(0,0,0,0.4), 0 8px 8px 1px rgba(0,0,0,0.5); background-color:#f0ad4e; } -.btn-danger { +.btn3d-danger { box-shadow:0 0 0 1px #c63702 inset, 0 0 0 2px rgba(255,255,255,0.15) inset, 0 8px 0 0 #C24032, 0 8px 0 1px rgba(0,0,0,0.4), 0 8px 8px 1px rgba(0,0,0,0.5); background-color:#c63702; } diff --git a/server/src/uds/static/adm/css/uds-admin.css b/server/src/uds/static/adm/css/uds-admin.css index d586bb005..83232c2a9 100644 --- a/server/src/uds/static/adm/css/uds-admin.css +++ b/server/src/uds/static/adm/css/uds-admin.css @@ -84,6 +84,12 @@ table.tablesorter thead tr th:hover { .btn3d-tables { margin-top:0px; + margin-botton: 8px; + margin-right: 8px; +} + +.btn-group-3d { + margin-bottom:12px; } diff --git a/server/src/uds/static/adm/img/loading.gif b/server/src/uds/static/adm/img/loading.gif new file mode 100644 index 000000000..35218b31b Binary files /dev/null and b/server/src/uds/static/adm/img/loading.gif differ diff --git a/server/src/uds/static/adm/js/api.js b/server/src/uds/static/adm/js/api.js index ee9c30d8b..9c0413c50 100644 --- a/server/src/uds/static/adm/js/api.js +++ b/server/src/uds/static/adm/js/api.js @@ -11,7 +11,12 @@ } }; - + + // Returns a cache object (for easy caching requests, templates, etc...) + api.cache = function(cacheName) { + return new Cache(cacheName); + }; + api.getJson = function(path, success_fnc) { url = api.url_for(path); api.doLog('Ajax GET Json for "' + url + '"'); @@ -37,6 +42,33 @@ api.debug = false; }(window.api = window.api || {}, jQuery)); + +// Cache related +function Cache(cacheName) { + api.cacheTable = api.cacheTable || {}; + + api.cacheTable[cacheName] = api.cacheTable[cacheName] || {}; + + this.name = cacheName; + this.cache = api.cacheTable[cacheName]; +} + +Cache.prototype = { + get: function(key, not_found_fnc){ + not_found_fnc = not_found_fnc || function() { return undefined; }; + + if( this.cache[key] === undefined ) { + this.cache[key] = not_found_fnc(); + } + return this.cache[key]; + }, + + put: function(key, value) { + this.cache[key] = value; + }, +}; + + // Great part of UDS REST api provides same methods. // We will take advantage of this and save a lot of nonsense, prone to failure // code :-) diff --git a/server/src/uds/static/adm/js/dataTables.bootstrap.js b/server/src/uds/static/adm/js/dataTables.bootstrap.js index 2db25c528..382554f4a 100644 --- a/server/src/uds/static/adm/js/dataTables.bootstrap.js +++ b/server/src/uds/static/adm/js/dataTables.bootstrap.js @@ -114,7 +114,7 @@ if ($.fn.DataTable.TableTools) { $.extend(true, $.fn.DataTable.TableTools.classes, { "container" : "DTTT btn-group-3d", "buttons" : { - "normal" : "btn btn-default", + "normal" : "btn btn3d-default", "disabled" : "disabled" }, "collection" : { diff --git a/server/src/uds/static/adm/js/gui-elements.js b/server/src/uds/static/adm/js/gui-elements.js index 37026e4a6..afd12f2d7 100644 --- a/server/src/uds/static/adm/js/gui-elements.js +++ b/server/src/uds/static/adm/js/gui-elements.js @@ -1,8 +1,34 @@ +/* jshint strict: true */ // Compose gui elements +gui.dashboard = new BasicGuiElement('Dashboard'); +gui.dashboard.link = function(event) { + "use strict"; + gui.clearWorkspace(); + api.templates.get('dashboard', function(tmpl) { + gui.doLog('enter dashboard'); + gui.appendToWorkspace(api.templates.evaluate(tmpl, { + })); + gui.setLinksEvents(); + + $.each($('.btn3d'), function() { + console.log(this); + var counter = 0; + $(this).click(function(){ + counter += 1; + $(this).text($(this).text().split(' ')[0] + ' ' + counter); + /*$('Click ' + counter + ' on ' + $(this).text() + '--').appendTo('#out');*/ + }); + }); + + api.tools.fix3dButtons('#test'); + }); +}; + // Service providers gui.providers = new GuiElement(api.providers, 'provi'); gui.providers.link = function(event) { + "use strict"; gui.clearWorkspace(); gui.appendToWorkspace(gui.breadcrumbs(gettext('Service Providers'))); @@ -25,6 +51,7 @@ gui.providers.link = function(event) { gui.authenticators = new GuiElement(api.authenticators, 'auth'); gui.authenticators.link = function(event) { + "use strict"; gui.doLog('enter auths'); api.templates.get('authenticators', function(tmpl) { gui.clearWorkspace(); @@ -39,6 +66,7 @@ gui.authenticators.link = function(event) { rowSelect : 'single', buttons : [ 'edit', 'refresh', 'delete', 'xls' ], onRowSelect : function(nodes) { + api.tools.blockUI(); var id = this.fnGetSelectedData()[0].id; var user = new GuiElement(api.authenticators.detail(id, 'users'), 'users'); user.table({ @@ -46,6 +74,9 @@ gui.authenticators.link = function(event) { rowSelect : 'multi', buttons : [ 'edit', 'refresh', 'delete', 'xls' ], scroll : true, + onLoad: function(k) { + api.tools.unblockUI(); + }, }); return false; }, @@ -60,6 +91,7 @@ gui.authenticators.link = function(event) { gui.osmanagers = new GuiElement(api.osmanagers, 'osm'); gui.osmanagers.link = function(event) { + "use strict"; gui.clearWorkspace(); gui.appendToWorkspace(gui.breadcrumbs('Os Managers')); @@ -77,6 +109,7 @@ gui.connectivity = { }; gui.connectivity.link = function(event) { + "use strict"; api.templates.get('connectivity', function(tmpl) { gui.clearWorkspace(); gui.appendToWorkspace(api.templates.evaluate(tmpl, { diff --git a/server/src/uds/static/adm/js/gui.js b/server/src/uds/static/adm/js/gui.js index bba91888d..96d2d7c1e 100644 --- a/server/src/uds/static/adm/js/gui.js +++ b/server/src/uds/static/adm/js/gui.js @@ -69,11 +69,6 @@ }; // Links methods - gui.dashboard = function() { - gui.clearWorkspace(); - gui.appendToWorkspace(gui.breadcrumbs('Dasboard')); - gui.doLog(this); - }; gui.deployed_services = function() { gui.clearWorkspace(); @@ -83,7 +78,7 @@ gui.setLinksEvents = function() { var sidebarLinks = [ { id : 'lnk-dashboard', - exec : gui.dashboard + exec : gui.dashboard.link, }, { id : 'lnk-service_providers', exec : gui.providers.link @@ -114,12 +109,18 @@ gui.init = function() { gui.setLinksEvents(); + gui.dashboard.link(); }; // Public attributes gui.debug = true; }(window.gui = window.gui || {}, jQuery)); +function BasicGuiElement(name) { + "use strict"; + this.name = name; +} + function GuiElement(restItem, name) { "use strict"; this.rest = restItem; @@ -308,16 +309,23 @@ GuiElement.prototype = { var refreshFnc = function(btn) { // Refreshes table content var tbl = $('#' + tableId).dataTable(); - var width = $(btn).width(); + /*var width = $(btn).width(); var saved = $(btn).html(); - /*$(btn).addClass('disabled').html('') + $(btn).addClass('disabled').html('') .width(width);*/ - onRefresh(); + if( data.length > 1000 ) + api.tools.blockUI(); + + onRefresh($this); + $this.rest.get({ success : function(data) { - tbl.fnClearTable(); - tbl.fnAddData(data); /*$(btn).removeClass('disabled').width('').html(saved);*/ + setTimeout( function() { + tbl.fnClearTable(); + tbl.fnAddData(data); + api.tools.unblockUI(); + }, 0); } }); }; @@ -326,17 +334,17 @@ GuiElement.prototype = { var editSelected = function(btn, obj, node) { var sel = this.fnGetSelectedData(); if (sel.length == 1) { - $(btn).removeClass('disabled').addClass('btn-info'); + $(btn).removeClass('disabled').addClass('btn3d-success'); } else { - $(btn).removeClass('btn-info').addClass('disabled'); + $(btn).removeClass('btn3d-success').addClass('disabled'); } }; var deleteSelected = function(btn, obj, node) { var sel = this.fnGetSelectedData(); if (sel.length > 0) { - $(btn).removeClass('disabled').addClass('btn-warning'); + $(btn).removeClass('disabled').addClass('btn3d-warning'); } else { - $(btn).removeClass('btn-warning').addClass('disabled'); + $(btn).removeClass('btn3d-warning').addClass('disabled'); } }; @@ -366,7 +374,7 @@ GuiElement.prototype = { "sExtends" : "text", "sButtonText" : gettext('Refresh'), "fnClick" : refreshFnc, - "sButtonClass" : "btn-info btn3d btn3d-tables" + "sButtonClass" : "btn3d-primary btn3d btn3d-tables" }; break; case 'xls': @@ -413,7 +421,7 @@ GuiElement.prototype = { }, 20); }); }, - "sButtonClass" : "btn-info btn3d btn3d-tables" + "sButtonClass" : "btn3d-info btn3d btn3d-tables" }; /*case 'csv': btn = { @@ -470,11 +478,18 @@ GuiElement.prototype = { "sDom" : "<'row'<'col-xs-8'T><'col-xs-4'f>r>t<'row'<'col-xs-5'i><'col-xs-7'p>>", }); - $('#' + tableId + '_filter input').addClass('form-control'); + // Fix 3dbuttons + api.tools.fix3dButtons('#' + tableId + '_wrapper .btn-group-3d'); + // Fix form + //$('#' + tableId + '_filter input').addClass('form-control'); if (options.scroll !== undefined ) { var tableTop = $('#' + tableId).offset().top; $('html, body').scrollTop(tableTop); } + // if table rendered event + if( options.onLoad ) { + options.onLoad($this); + } } }); }); diff --git a/server/src/uds/static/adm/js/jquery.blockUI.js b/server/src/uds/static/adm/js/jquery.blockUI.js new file mode 100644 index 000000000..42a7db68b --- /dev/null +++ b/server/src/uds/static/adm/js/jquery.blockUI.js @@ -0,0 +1,618 @@ +/*! + * jQuery blockUI plugin + * Version 2.66.0-2013.10.09 + * Requires jQuery v1.7 or later + * + * Examples at: http://malsup.com/jquery/block/ + * Copyright (c) 2007-2013 M. Alsup + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + * + * Thanks to Amir-Hossein Sobhi for some excellent contributions! + */ + +;(function() { +"use strict"; + + function setup($) { + $.fn._fadeIn = $.fn.fadeIn; + + var noOp = $.noop || function() {}; + + // this bit is to ensure we don't call setExpression when we shouldn't (with extra muscle to handle + // confusing userAgent strings on Vista) + var msie = /MSIE/.test(navigator.userAgent); + var ie6 = /MSIE 6.0/.test(navigator.userAgent) && ! /MSIE 8.0/.test(navigator.userAgent); + var mode = document.documentMode || 0; + var setExpr = $.isFunction( document.createElement('div').style.setExpression ); + + // global $ methods for blocking/unblocking the entire page + $.blockUI = function(opts) { install(window, opts); }; + $.unblockUI = function(opts) { remove(window, opts); }; + + // convenience method for quick growl-like notifications (http://www.google.com/search?q=growl) + $.growlUI = function(title, message, timeout, onClose) { + var $m = $('
'); + if (title) $m.append('

'+title+'

'); + if (message) $m.append('

'+message+'

'); + if (timeout === undefined) timeout = 3000; + + // Added by konapun: Set timeout to 30 seconds if this growl is moused over, like normal toast notifications + var callBlock = function(opts) { + opts = opts || {}; + + $.blockUI({ + message: $m, + fadeIn : typeof opts.fadeIn !== 'undefined' ? opts.fadeIn : 700, + fadeOut: typeof opts.fadeOut !== 'undefined' ? opts.fadeOut : 1000, + timeout: typeof opts.timeout !== 'undefined' ? opts.timeout : timeout, + centerY: false, + showOverlay: false, + onUnblock: onClose, + css: $.blockUI.defaults.growlCSS + }); + }; + + callBlock(); + var nonmousedOpacity = $m.css('opacity'); + $m.mouseover(function() { + callBlock({ + fadeIn: 0, + timeout: 30000 + }); + + var displayBlock = $('.blockMsg'); + displayBlock.stop(); // cancel fadeout if it has started + displayBlock.fadeTo(300, 1); // make it easier to read the message by removing transparency + }).mouseout(function() { + $('.blockMsg').fadeOut(1000); + }); + // End konapun additions + }; + + // plugin method for blocking element content + $.fn.block = function(opts) { + if ( this[0] === window ) { + $.blockUI( opts ); + return this; + } + var fullOpts = $.extend({}, $.blockUI.defaults, opts || {}); + this.each(function() { + var $el = $(this); + if (fullOpts.ignoreIfBlocked && $el.data('blockUI.isBlocked')) + return; + $el.unblock({ fadeOut: 0 }); + }); + + return this.each(function() { + if ($.css(this,'position') == 'static') { + this.style.position = 'relative'; + $(this).data('blockUI.static', true); + } + this.style.zoom = 1; // force 'hasLayout' in ie + install(this, opts); + }); + }; + + // plugin method for unblocking element content + $.fn.unblock = function(opts) { + if ( this[0] === window ) { + $.unblockUI( opts ); + return this; + } + return this.each(function() { + remove(this, opts); + }); + }; + + $.blockUI.version = 2.66; // 2nd generation blocking at no extra cost! + + // override these in your code to change the default behavior and style + $.blockUI.defaults = { + // message displayed when blocking (use null for no message) + message: '

Please wait...

', + + title: null, // title string; only used when theme == true + draggable: true, // only used when theme == true (requires jquery-ui.js to be loaded) + + theme: false, // set to true to use with jQuery UI themes + + // styles for the message when blocking; if you wish to disable + // these and use an external stylesheet then do this in your code: + // $.blockUI.defaults.css = {}; + css: { + padding: 0, + margin: 0, + width: '30%', + top: '40%', + left: '35%', + textAlign: 'center', + color: '#000', + border: '3px solid #aaa', + backgroundColor:'#fff', + cursor: 'wait' + }, + + // minimal style set used when themes are used + themedCSS: { + width: '30%', + top: '40%', + left: '35%' + }, + + // styles for the overlay + overlayCSS: { + backgroundColor: '#000', + opacity: 0.6, + cursor: 'wait' + }, + + // style to replace wait cursor before unblocking to correct issue + // of lingering wait cursor + cursorReset: 'default', + + // styles applied when using $.growlUI + growlCSS: { + width: '350px', + top: '10px', + left: '', + right: '10px', + border: 'none', + padding: '5px', + opacity: 0.6, + cursor: 'default', + color: '#fff', + backgroundColor: '#000', + '-webkit-border-radius':'10px', + '-moz-border-radius': '10px', + 'border-radius': '10px' + }, + + // IE issues: 'about:blank' fails on HTTPS and javascript:false is s-l-o-w + // (hat tip to Jorge H. N. de Vasconcelos) + /*jshint scripturl:true */ + iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank', + + // force usage of iframe in non-IE browsers (handy for blocking applets) + forceIframe: false, + + // z-index for the blocking overlay + baseZ: 1000, + + // set these to true to have the message automatically centered + centerX: true, // <-- only effects element blocking (page block controlled via css above) + centerY: true, + + // allow body element to be stetched in ie6; this makes blocking look better + // on "short" pages. disable if you wish to prevent changes to the body height + allowBodyStretch: true, + + // enable if you want key and mouse events to be disabled for content that is blocked + bindEvents: true, + + // be default blockUI will supress tab navigation from leaving blocking content + // (if bindEvents is true) + constrainTabKey: true, + + // fadeIn time in millis; set to 0 to disable fadeIn on block + fadeIn: 200, + + // fadeOut time in millis; set to 0 to disable fadeOut on unblock + fadeOut: 400, + + // time in millis to wait before auto-unblocking; set to 0 to disable auto-unblock + timeout: 0, + + // disable if you don't want to show the overlay + showOverlay: true, + + // if true, focus will be placed in the first available input field when + // page blocking + focusInput: true, + + // elements that can receive focus + focusableElements: ':input:enabled:visible', + + // suppresses the use of overlay styles on FF/Linux (due to performance issues with opacity) + // no longer needed in 2012 + // applyPlatformOpacityRules: true, + + // callback method invoked when fadeIn has completed and blocking message is visible + onBlock: null, + + // callback method invoked when unblocking has completed; the callback is + // passed the element that has been unblocked (which is the window object for page + // blocks) and the options that were passed to the unblock call: + // onUnblock(element, options) + onUnblock: null, + + // callback method invoked when the overlay area is clicked. + // setting this will turn the cursor to a pointer, otherwise cursor defined in overlayCss will be used. + onOverlayClick: null, + + // don't ask; if you really must know: http://groups.google.com/group/jquery-en/browse_thread/thread/36640a8730503595/2f6a79a77a78e493#2f6a79a77a78e493 + quirksmodeOffsetHack: 4, + + // class name of the message block + blockMsgClass: 'blockMsg', + + // if it is already blocked, then ignore it (don't unblock and reblock) + ignoreIfBlocked: false + }; + + // private data and functions follow... + + var pageBlock = null; + var pageBlockEls = []; + + function install(el, opts) { + var css, themedCSS; + var full = (el == window); + var msg = (opts && opts.message !== undefined ? opts.message : undefined); + opts = $.extend({}, $.blockUI.defaults, opts || {}); + + if (opts.ignoreIfBlocked && $(el).data('blockUI.isBlocked')) + return; + + opts.overlayCSS = $.extend({}, $.blockUI.defaults.overlayCSS, opts.overlayCSS || {}); + css = $.extend({}, $.blockUI.defaults.css, opts.css || {}); + if (opts.onOverlayClick) + opts.overlayCSS.cursor = 'pointer'; + + themedCSS = $.extend({}, $.blockUI.defaults.themedCSS, opts.themedCSS || {}); + msg = msg === undefined ? opts.message : msg; + + // remove the current block (if there is one) + if (full && pageBlock) + remove(window, {fadeOut:0}); + + // if an existing element is being used as the blocking content then we capture + // its current place in the DOM (and current display style) so we can restore + // it when we unblock + if (msg && typeof msg != 'string' && (msg.parentNode || msg.jquery)) { + var node = msg.jquery ? msg[0] : msg; + var data = {}; + $(el).data('blockUI.history', data); + data.el = node; + data.parent = node.parentNode; + data.display = node.style.display; + data.position = node.style.position; + if (data.parent) + data.parent.removeChild(node); + } + + $(el).data('blockUI.onUnblock', opts.onUnblock); + var z = opts.baseZ; + + // blockUI uses 3 layers for blocking, for simplicity they are all used on every platform; + // layer1 is the iframe layer which is used to supress bleed through of underlying content + // layer2 is the overlay layer which has opacity and a wait cursor (by default) + // layer3 is the message content that is displayed while blocking + var lyr1, lyr2, lyr3, s; + if (msie || opts.forceIframe) + lyr1 = $(''); + else + lyr1 = $(''); + + if (opts.theme) + lyr2 = $(''); + else + lyr2 = $(''); + + if (opts.theme && full) { + s = ''; + } + else if (opts.theme) { + s = ''; + } + else if (full) { + s = ''; + } + else { + s = ''; + } + lyr3 = $(s); + + // if we have a message, style it + if (msg) { + if (opts.theme) { + lyr3.css(themedCSS); + lyr3.addClass('ui-widget-content'); + } + else + lyr3.css(css); + } + + // style the overlay + if (!opts.theme /*&& (!opts.applyPlatformOpacityRules)*/) + lyr2.css(opts.overlayCSS); + lyr2.css('position', full ? 'fixed' : 'absolute'); + + // make iframe layer transparent in IE + if (msie || opts.forceIframe) + lyr1.css('opacity',0.0); + + //$([lyr1[0],lyr2[0],lyr3[0]]).appendTo(full ? 'body' : el); + var layers = [lyr1,lyr2,lyr3], $par = full ? $('body') : $(el); + $.each(layers, function() { + this.appendTo($par); + }); + + if (opts.theme && opts.draggable && $.fn.draggable) { + lyr3.draggable({ + handle: '.ui-dialog-titlebar', + cancel: 'li' + }); + } + + // ie7 must use absolute positioning in quirks mode and to account for activex issues (when scrolling) + var expr = setExpr && (!$.support.boxModel || $('object,embed', full ? null : el).length > 0); + if (ie6 || expr) { + // give body 100% height + if (full && opts.allowBodyStretch && $.support.boxModel) + $('html,body').css('height','100%'); + + // fix ie6 issue when blocked element has a border width + if ((ie6 || !$.support.boxModel) && !full) { + var t = sz(el,'borderTopWidth'), l = sz(el,'borderLeftWidth'); + var fixT = t ? '(0 - '+t+')' : 0; + var fixL = l ? '(0 - '+l+')' : 0; + } + + // simulate fixed position + $.each(layers, function(i,o) { + var s = o[0].style; + s.position = 'absolute'; + if (i < 2) { + if (full) + s.setExpression('height','Math.max(document.body.scrollHeight, document.body.offsetHeight) - (jQuery.support.boxModel?0:'+opts.quirksmodeOffsetHack+') + "px"'); + else + s.setExpression('height','this.parentNode.offsetHeight + "px"'); + if (full) + s.setExpression('width','jQuery.support.boxModel && document.documentElement.clientWidth || document.body.clientWidth + "px"'); + else + s.setExpression('width','this.parentNode.offsetWidth + "px"'); + if (fixL) s.setExpression('left', fixL); + if (fixT) s.setExpression('top', fixT); + } + else if (opts.centerY) { + if (full) s.setExpression('top','(document.documentElement.clientHeight || document.body.clientHeight) / 2 - (this.offsetHeight / 2) + (blah = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "px"'); + s.marginTop = 0; + } + else if (!opts.centerY && full) { + var top = (opts.css && opts.css.top) ? parseInt(opts.css.top, 10) : 0; + var expression = '((document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + '+top+') + "px"'; + s.setExpression('top',expression); + } + }); + } + + // show the message + if (msg) { + if (opts.theme) + lyr3.find('.ui-widget-content').append(msg); + else + lyr3.append(msg); + if (msg.jquery || msg.nodeType) + $(msg).show(); + } + + if ((msie || opts.forceIframe) && opts.showOverlay) + lyr1.show(); // opacity is zero + if (opts.fadeIn) { + var cb = opts.onBlock ? opts.onBlock : noOp; + var cb1 = (opts.showOverlay && !msg) ? cb : noOp; + var cb2 = msg ? cb : noOp; + if (opts.showOverlay) + lyr2._fadeIn(opts.fadeIn, cb1); + if (msg) + lyr3._fadeIn(opts.fadeIn, cb2); + } + else { + if (opts.showOverlay) + lyr2.show(); + if (msg) + lyr3.show(); + if (opts.onBlock) + opts.onBlock(); + } + + // bind key and mouse events + bind(1, el, opts); + + if (full) { + pageBlock = lyr3[0]; + pageBlockEls = $(opts.focusableElements,pageBlock); + if (opts.focusInput) + setTimeout(focus, 20); + } + else + center(lyr3[0], opts.centerX, opts.centerY); + + if (opts.timeout) { + // auto-unblock + var to = setTimeout(function() { + if (full) + $.unblockUI(opts); + else + $(el).unblock(opts); + }, opts.timeout); + $(el).data('blockUI.timeout', to); + } + } + + // remove the block + function remove(el, opts) { + var count; + var full = (el == window); + var $el = $(el); + var data = $el.data('blockUI.history'); + var to = $el.data('blockUI.timeout'); + if (to) { + clearTimeout(to); + $el.removeData('blockUI.timeout'); + } + opts = $.extend({}, $.blockUI.defaults, opts || {}); + bind(0, el, opts); // unbind events + + if (opts.onUnblock === null) { + opts.onUnblock = $el.data('blockUI.onUnblock'); + $el.removeData('blockUI.onUnblock'); + } + + var els; + if (full) // crazy selector to handle odd field errors in ie6/7 + els = $('body').children().filter('.blockUI').add('body > .blockUI'); + else + els = $el.find('>.blockUI'); + + // fix cursor issue + if ( opts.cursorReset ) { + if ( els.length > 1 ) + els[1].style.cursor = opts.cursorReset; + if ( els.length > 2 ) + els[2].style.cursor = opts.cursorReset; + } + + if (full) + pageBlock = pageBlockEls = null; + + if (opts.fadeOut) { + count = els.length; + els.stop().fadeOut(opts.fadeOut, function() { + if ( --count === 0) + reset(els,data,opts,el); + }); + } + else + reset(els, data, opts, el); + } + + // move blocking element back into the DOM where it started + function reset(els,data,opts,el) { + var $el = $(el); + if ( $el.data('blockUI.isBlocked') ) + return; + + els.each(function(i,o) { + // remove via DOM calls so we don't lose event handlers + if (this.parentNode) + this.parentNode.removeChild(this); + }); + + if (data && data.el) { + data.el.style.display = data.display; + data.el.style.position = data.position; + if (data.parent) + data.parent.appendChild(data.el); + $el.removeData('blockUI.history'); + } + + if ($el.data('blockUI.static')) { + $el.css('position', 'static'); // #22 + } + + if (typeof opts.onUnblock == 'function') + opts.onUnblock(el,opts); + + // fix issue in Safari 6 where block artifacts remain until reflow + var body = $(document.body), w = body.width(), cssW = body[0].style.width; + body.width(w-1).width(w); + body[0].style.width = cssW; + } + + // bind/unbind the handler + function bind(b, el, opts) { + var full = el == window, $el = $(el); + + // don't bother unbinding if there is nothing to unbind + if (!b && (full && !pageBlock || !full && !$el.data('blockUI.isBlocked'))) + return; + + $el.data('blockUI.isBlocked', b); + + // don't bind events when overlay is not in use or if bindEvents is false + if (!full || !opts.bindEvents || (b && !opts.showOverlay)) + return; + + // bind anchors and inputs for mouse and key events + var events = 'mousedown mouseup keydown keypress keyup touchstart touchend touchmove'; + if (b) + $(document).bind(events, opts, handler); + else + $(document).unbind(events, handler); + + // former impl... + // var $e = $('a,:input'); + // b ? $e.bind(events, opts, handler) : $e.unbind(events, handler); + } + + // event handler to suppress keyboard/mouse events when blocking + function handler(e) { + // allow tab navigation (conditionally) + if (e.type === 'keydown' && e.keyCode && e.keyCode == 9) { + if (pageBlock && e.data.constrainTabKey) { + var els = pageBlockEls; + var fwd = !e.shiftKey && e.target === els[els.length-1]; + var back = e.shiftKey && e.target === els[0]; + if (fwd || back) { + setTimeout(function(){focus(back);},10); + return false; + } + } + } + var opts = e.data; + var target = $(e.target); + if (target.hasClass('blockOverlay') && opts.onOverlayClick) + opts.onOverlayClick(e); + + // allow events within the message content + if (target.parents('div.' + opts.blockMsgClass).length > 0) + return true; + + // allow events for content that is not being blocked + return target.parents().children().filter('div.blockUI').length === 0; + } + + function focus(back) { + if (!pageBlockEls) + return; + var e = pageBlockEls[back===true ? pageBlockEls.length-1 : 0]; + if (e) + e.focus(); + } + + function center(el, x, y) { + var p = el.parentNode, s = el.style; + var l = ((p.offsetWidth - el.offsetWidth)/2) - sz(p,'borderLeftWidth'); + var t = ((p.offsetHeight - el.offsetHeight)/2) - sz(p,'borderTopWidth'); + if (x) s.left = l > 0 ? (l+'px') : '0'; + if (y) s.top = t > 0 ? (t+'px') : '0'; + } + + function sz(el, p) { + return parseInt($.css(el,p),10)||0; + } + + } + + + /*global define:true */ + if (typeof define === 'function' && define.amd && define.amd.jQuery) { + define(['jquery'], setup); + } else { + setup(jQuery); + } + +})(); diff --git a/server/src/uds/static/adm/js/tools.js b/server/src/uds/static/adm/js/tools.js index 054d7503b..6418ae4fa 100644 --- a/server/src/uds/static/adm/js/tools.js +++ b/server/src/uds/static/adm/js/tools.js @@ -1,5 +1,54 @@ +/* jshint strict: true */ (function(tools, $, undefined) { + "use strict"; tools.base64 = function(s) { return window.btoa(unescape(encodeURIComponent(s))); }; + + tools.fix3dButtons = function(selector) { + selector = selector || ''; + selector += ' .btn3d'; + console.log(selector); + $.each($(selector), function(index, value) { + var $this = $(this); + + var clkEvents = []; + + // Store old click events, so we can reconstruct click chain later + $.each($._data(value, 'events').click, function(index, fnc) { + clkEvents.push(fnc); + }); + $this.unbind('click'); + + /* If Mousedown registers a temporal mouseUp event on parent, to lauch button click */ + $this.mousedown(function(event){ + $this.parent().mouseup(function(e){ + // Remove temporal mouseup handler + $(this).unbind('mouseup'); + + // If movement of mouse is not too far... (16 px maybe well for 3d buttons?) + var x = event.pageX - e.pageX, y = event.pageY - e.pageY; + var dist_square = x*x + y*y; + if( dist_square < 16*16 ) { + // Register again old event handlers + $.each(clkEvents, function(index, fnc){ + $this.click(fnc.handler); + }); + $this.click(); + $this.unbind('click'); + } + }); + }); + }); + }; + + tools.blockUI = function(message) { + message = message || '

' + gettext('Just a moment...') + '

' + $.blockUI({ message: message }); + }; + + tools.unblockUI = function() { + $.unblockUI(); + }; + }(api.tools = api.tools || {}, jQuery)); diff --git a/server/src/uds/templates/uds/admin/index.html b/server/src/uds/templates/uds/admin/index.html index 5cc82b094..31ecaeab2 100644 --- a/server/src/uds/templates/uds/admin/index.html +++ b/server/src/uds/templates/uds/admin/index.html @@ -46,6 +46,7 @@ + @@ -68,6 +69,7 @@ api.token = "{% auth_token %}"; api.auth_header = "{% auth_token_header %}"; api.base_url = "{% url 'REST' '' %}"; + api.img_url = "{% get_static_prefix %}adm/img/"; api.url_for = function(path) { return api.base_url + path; @@ -75,8 +77,8 @@ }(window.api = window.api || {}, jQuery)); - - + + diff --git a/server/src/uds/templates/uds/admin/tmpl/dashboard.html b/server/src/uds/templates/uds/admin/tmpl/dashboard.html index 2d762f9da..314b0ed03 100644 --- a/server/src/uds/templates/uds/admin/tmpl/dashboard.html +++ b/server/src/uds/templates/uds/admin/tmpl/dashboard.html @@ -7,3 +7,16 @@ + +
+
+ + + + +
+
+
+
+
+
\ No newline at end of file