Repository: helix Updated Branches: refs/heads/master 9087ce08e -> 5b4fddea2
http://git-wip-us.apache.org/repos/asf/helix/blob/6cbafef0/helix-ui/src/main/resources/assets/js/landing-view.js ---------------------------------------------------------------------- diff --git a/helix-ui/src/main/resources/assets/js/landing-view.js b/helix-ui/src/main/resources/assets/js/landing-view.js new file mode 100644 index 0000000..e40375a --- /dev/null +++ b/helix-ui/src/main/resources/assets/js/landing-view.js @@ -0,0 +1,6 @@ +$(document).ready(function() { + $("#landing-form-button").click(function(event) { + event.preventDefault() + window.location = "/dashboard/" + encodeURIComponent($("#zk-address").val()) + }) +}) \ No newline at end of file http://git-wip-us.apache.org/repos/asf/helix/blob/6cbafef0/helix-ui/src/main/resources/assets/js/resource-state-table.js ---------------------------------------------------------------------- diff --git a/helix-ui/src/main/resources/assets/js/resource-state-table.js b/helix-ui/src/main/resources/assets/js/resource-state-table.js new file mode 100644 index 0000000..b232140 --- /dev/null +++ b/helix-ui/src/main/resources/assets/js/resource-state-table.js @@ -0,0 +1,55 @@ +$(document).ready(function() { + + // Don't submit when enter is pressed anywhere on the page + $(window).keydown(function(event){ + if(event.keyCode == 13) { + event.preventDefault() + return false + } + }) + + $('#filter-add').click(function(event) { + event.preventDefault() + + var div = $('<div></div>', { + class: 'uk-form-row' + }) + + var select = $('<select></select>') + .append($('<option></option>', { + text: 'Partition', + value: 0 + })) + .append($('<option></option>', { + text: 'Instance', + value: 1 + })) + .append($('<option></option>', { + text: 'Ideal', + value: 2 + })) + .append($('<option></option>', { + text: 'External', + value: 3 + })) + + var input = $('<input></input>', { + type: 'text' + }).keyup(function() { + filterTable("#filter-form", "#resource-state-table") + }) + + var closeButton = $('<a></a>', { + class: 'uk-close' + }).click(function() { + div.remove() + filterTable("#filter-form", "#resource-state-table") + }) + + div.append(select) + .append(input) + .append(closeButton) + + $("#filter-form").append(div) + }) +}) \ No newline at end of file http://git-wip-us.apache.org/repos/asf/helix/blob/6cbafef0/helix-ui/src/main/resources/assets/js/resource-table.js ---------------------------------------------------------------------- diff --git a/helix-ui/src/main/resources/assets/js/resource-table.js b/helix-ui/src/main/resources/assets/js/resource-table.js new file mode 100644 index 0000000..8674967 --- /dev/null +++ b/helix-ui/src/main/resources/assets/js/resource-table.js @@ -0,0 +1,43 @@ +$(document).ready(function() { + + // Don't submit when enter is pressed anywhere on the page + $(window).keydown(function(event){ + if(event.keyCode == 13) { + event.preventDefault() + return false + } + }) + + $('#resource-filter-add').click(function(event) { + event.preventDefault() + + var div = $('<div></div>', { + class: 'uk-form-row' + }) + + var select = $('<select></select>') + .append($('<option></option>', { + text: 'Name', + value: 0 + })) + + var input = $('<input></input>', { + type: 'text' + }).keyup(function() { + filterTable("#resource-filter-form", "#resource-table") + }) + + var closeButton = $('<a></a>', { + class: 'uk-close' + }).click(function() { + div.remove() + filterTable("#resource-filter-form", "#resource-table") + }) + + div.append(select) + .append(input) + .append(closeButton) + + $("#resource-filter-form").append(div) + }) +}) http://git-wip-us.apache.org/repos/asf/helix/blob/6cbafef0/helix-ui/src/main/resources/assets/js/uikit.min.js ---------------------------------------------------------------------- diff --git a/helix-ui/src/main/resources/assets/js/uikit.min.js b/helix-ui/src/main/resources/assets/js/uikit.min.js new file mode 100644 index 0000000..8e10af5 --- /dev/null +++ b/helix-ui/src/main/resources/assets/js/uikit.min.js @@ -0,0 +1,3 @@ +/*! UIkit 2.16.2 | http://www.getuikit.com | (c) 2014 YOOtheme | MIT License */ +!function(t){if("function"==typeof define&&define.amd&&define("uikit",function(){var i=window.UIkit||t(window,window.jQuery,window.document);return i.load=function(t,e,n,o){var s,a=t.split(","),r=[],l=(o.config&&o.config.uikit&&o.config.uikit.base?o.config.uikit.base:"").replace(/\/+$/g,"");if(!l)throw new Error("Please define base path to UIkit in the requirejs config.");for(s=0;s<a.length;s+=1){var c=a[s].replace(/\./g,"/");r.push(l+"/components/"+c)}e(r,function(){n(i)})},i}),!window.jQuery)throw new Error("UIkit requires jQuery");window&&window.jQuery&&t(window,window.jQuery,window.document)}(function(t,i,e){"use strict";var n={},o=window.UIkit;if(n.version="2.16.2",n._prefix="uk",n.noConflict=function(t){return o&&(window.UIkit=o,i.UIkit=o,i.fn.uk=o.fn),n._prefix=t,n},n.prefix=function(t){return"string"==typeof t?t.replace(/@/g,n._prefix):t},n.$=function(){arguments[0]&&"string"==typeof arguments[0]&&(arguments[0]=n.prefix(arguments[0]));var t,e=i.apply(i,arguments);return e.le ngth?(["find","filter","closest","attr","parent","parents","children","addClass","removeClass","toggleClass","hasClass","is","on","one"].forEach(function(i){var o,s=e[i],a=["find","filter","parent","parents","children","closest"];return e[i]=function(){for(t=0;t<arguments.length;t++)"string"==typeof arguments[t]&&(arguments[t]=n.prefix(arguments[t]));return o=s.apply(this,arguments),a.indexOf(i)>-1?n.$(o):o},e}),e):e},n.$doc=n.$(document),n.$win=n.$(window),n.$html=n.$("html"),n.fn=function(t,e){var o=arguments,s=t.match(/^([a-z\-]+)(?:\.([a-z]+))?/i),a=s[1],r=s[2];return n[a]?this.each(function(){var t=i(this),s=t.data(a);s||t.data(a,s=n[a](this,r?void 0:e)),r&&s[r].apply(s,Array.prototype.slice.call(o,1))}):(i.error("UIkit component ["+a+"] does not exist."),this)},n.support={},n.support.transition=function(){var t=function(){var t,i=e.body||e.documentElement,n={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transit ion:"transitionend"};for(t in n)if(void 0!==i.style[t])return n[t]}();return t&&{end:t}}(),n.support.animation=function(){var t=function(){var t,i=e.body||e.documentElement,n={WebkitAnimation:"webkitAnimationEnd",MozAnimation:"animationend",OAnimation:"oAnimationEnd oanimationend",animation:"animationend"};for(t in n)if(void 0!==i.style[t])return n[t]}();return t&&{end:t}}(),n.support.requestAnimationFrame=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.msRequestAnimationFrame||window.oRequestAnimationFrame||function(t){setTimeout(t,1e3/60)},n.support.touch="ontouchstart"in window&&navigator.userAgent.toLowerCase().match(/mobile|tablet/)||t.DocumentTouch&&document instanceof t.DocumentTouch||t.navigator.msPointerEnabled&&t.navigator.msMaxTouchPoints>0||t.navigator.pointerEnabled&&t.navigator.maxTouchPoints>0||!1,n.support.mutationobserver=t.MutationObserver||t.WebKitMutationObserver||null,n.Utils={},n.Utils.str2json=function( t){return t.replace(/([\$\w]+)\s*:/g,function(t,i){return'"'+i+'":'}).replace(/'([^']+)'/g,function(t,i){return'"'+i+'"'})},n.Utils.debounce=function(t,i,e){var n;return function(){var o=this,s=arguments,a=function(){n=null,e||t.apply(o,s)},r=e&&!n;clearTimeout(n),n=setTimeout(a,i),r&&t.apply(o,s)}},n.Utils.removeCssRules=function(t){var i,e,n,o,s,a,r,l,c,h;t&&setTimeout(function(){try{for(h=document.styleSheets,o=0,r=h.length;r>o;o++){for(n=h[o],e=[],n.cssRules=n.cssRules,i=s=0,l=n.cssRules.length;l>s;i=++s)n.cssRules[i].type===CSSRule.STYLE_RULE&&t.test(n.cssRules[i].selectorText)&&e.unshift(i);for(a=0,c=e.length;c>a;a++)n.deleteRule(e[a])}}catch(d){}},0)},n.Utils.isInView=function(t,e){var o=i(t);if(!o.is(":visible"))return!1;var s=n.$win.scrollLeft(),a=n.$win.scrollTop(),r=o.offset(),l=r.left,c=r.top;return e=i.extend({topoffset:0,leftoffset:0},e),c+o.height()>=a&&c-e.topoffset<=a+n.$win.height()&&l+o.width()>=s&&l-e.leftoffset<=s+n.$win.width()?!0:!1},n.Utils.checkDisplay=funct ion(t,e){var o=n.$("[data-@-margin], [data-@-grid-match], [data-@-grid-margin], [data-@-check-display]",t||document);return t&&!o.length&&(o=i(t)),o.trigger(n.prefix("[email protected]")),e&&("string"!=typeof e&&(e=n.prefix('[class*="@-animation-"]')),o.find(e).each(function(){var t=n.$(this),i=t.attr("class"),e=i.match(/uk\-animation\-(.+)/);t.removeClass(e[0]).width(),t.addClass(e[0])})),o},n.Utils.options=function(t){if(i.isPlainObject(t))return t;var e=t?t.indexOf("{"):-1,o={};if(-1!=e)try{o=JSON.parse(n.Utils.str2json(t.substr(e)))}catch(s){}return o},n.Utils.animate=function(t,e){var o=i.Deferred();return t=n.$(t),e=n.prefix(e),t.css("display","none").addClass(e).one(n.support.animation.end,function(){t.removeClass(e),o.resolve()}).width(),t.css("display",""),o.promise()},n.Utils.uid=function(t){return(t||"id")+(new Date).getTime()+"RAND"+Math.ceil(1e5*Math.random())},n.Utils.template=function(t,i){for(var e,n,o,s,a=t.replace(/\n/g,"\\n").replace(/\{\{\{\s*(.+?)\s*\}\}\}/g,"{{!$ 1}}").split(/(\{\{\s*(.+?)\s*\}\})/g),r=0,l=[],c=0;r<a.length;){if(e=a[r],e.match(/\{\{\s*(.+?)\s*\}\}/))switch(r+=1,e=a[r],n=e[0],o=e.substring(e.match(/^(\^|\#|\!|\~|\:)/)?1:0),n){case"~":l.push("for(var $i=0;$i<"+o+".length;$i++) { var $item = "+o+"[$i];"),c++;break;case":":l.push("for(var $key in "+o+") { var $val = "+o+"[$key];"),c++;break;case"#":l.push("if("+o+") {"),c++;break;case"^":l.push("if(!"+o+") {"),c++;break;case"/":l.push("}"),c--;break;case"!":l.push("__ret.push("+o+");");break;default:l.push("__ret.push(escape("+o+"));")}else l.push("__ret.push('"+e.replace(/\'/g,"\\'")+"');");r+=1}return s=new Function("$data",["var __ret = [];","try {","with($data){",c?'__ret = ["Not all blocks are closed correctly."]':l.join(""),"};","}catch(e){__ret = [e.message];}",'return __ret.join("").replace(/\\n\\n/g, "\\n");',"function escape(html) { return String(html).replace(/&/g, '&').replace(/\"/g, '"').replace(/</g, '<').replace(/>/g, '>');}"].join("\n")),i?s(i):s}, n.Utils.events={},n.Utils.events.click=n.support.touch?"tap":"click",window.UIkit=n,i.UIkit=n,i.fn.uk=n.fn,n.langdirection="rtl"==n.$html.attr("dir")?"right":"left",n.components={},n.component=function(t,e){var o=function(e,s){var a=this;return this.UIkit=n,this.element=e?n.$(e):null,this.options=i.extend(!0,{},this.defaults,s),this.plugins={},this.element&&this.element.data(t,this),this.init(),(this.options.plugins.length?this.options.plugins:Object.keys(o.plugins)).forEach(function(t){o.plugins[t].init&&(o.plugins[t].init(a),a.plugins[t]=!0)}),this.trigger("init.uk.component",[t,this]),this};return o.plugins={},i.extend(!0,o.prototype,{defaults:{plugins:[]},boot:function(){},init:function(){},on:function(t,i,e){return n.$(this.element||this).on(t,i,e)},one:function(t,i,e){return n.$(this.element||this).one(t,i,e)},off:function(t){return n.$(this.element||this).off(t)},trigger:function(t,i){return n.$(this.element||this).trigger(t,i)},find:function(t){return n.$(this.element?this.e lement:[]).find(t)},proxy:function(t,i){var e=this;i.split(" ").forEach(function(i){e[i]||(e[i]=function(){return t[i].apply(t,arguments)})})},mixin:function(t,i){var e=this;i.split(" ").forEach(function(i){e[i]||(e[i]=t[i].bind(e))})}},e),this.components[t]=o,this[t]=function(){var e,o;if(arguments.length)switch(arguments.length){case 1:"string"==typeof arguments[0]||arguments[0].nodeType||arguments[0]instanceof jQuery?e=i(arguments[0]):o=arguments[0];break;case 2:e=i(arguments[0]),o=arguments[1]}return e&&e.data(t)?e.data(t):new n.components[t](e,o)},n.domready&&n.component.boot(t),o},n.plugin=function(t,i,e){this.components[t].plugins[i]=e},n.component.boot=function(t){n.components[t].prototype&&n.components[t].prototype.boot&&!n.components[t].booted&&(n.components[t].prototype.boot.apply(n,[]),n.components[t].booted=!0)},n.component.bootComponents=function(){for(var t in n.components)n.component.boot(t)},n.domObservers=[],n.domready=!1,n.ready=function(t){n.domObservers.push(t), n.domready&&t(document)},n.on=function(t,i,e){return t&&t.indexOf("ready.uk.dom")>-1&&n.domready&&i.apply(n.$doc),n.$doc.on(t,i,e)},n.one=function(t,i,e){return t&&t.indexOf("ready.uk.dom")>-1&&n.domready?(i.apply(n.$doc),n.$doc):n.$doc.one(t,i,e)},n.trigger=function(t,i){return n.$doc.trigger(t,i)},n.domObserve=function(t,i){n.support.mutationobserver&&(i=i||function(){},n.$(t).each(function(){var t=this,e=n.$(t);if(!e.data("observer"))try{var o=new n.support.mutationobserver(n.Utils.debounce(function(){i.apply(t,[]),e.trigger(n.prefix("[email protected]"))},50));o.observe(t,{childList:!0,subtree:!0}),e.data("observer",o)}catch(s){}}))},i(function(){n.$body=n.$("body"),n.ready(function(){n.domObserve("[data-@-observe]")}),n.on("ready.uk.dom",function(){n.domObservers.forEach(function(t){t(document)}),n.domready&&n.Utils.checkDisplay(document)}),n.on("changed.uk.dom",function(t){var i=t.target;n.domObservers.forEach(function(t){t(i)}),n.Utils.checkDisplay(i)}),n.trigger("beforeready.uk. dom"),n.component.bootComponents(),setInterval(function(){var t,i={x:window.pageXOffset,y:window.pageYOffset},e=function(){(i.x!=window.pageXOffset||i.y!=window.pageYOffset)&&(t={x:0,y:0},window.pageXOffset!=i.x&&(t.x=window.pageXOffset>i.x?1:-1),window.pageYOffset!=i.y&&(t.y=window.pageYOffset>i.y?1:-1),i={dir:t,x:window.pageXOffset,y:window.pageYOffset},n.$doc.trigger("scrolling.uk.document",[i]))};return n.support.touch&&n.$html.on("touchmove touchend MSPointerMove MSPointerUp pointermove pointerup",e),(i.x||i.y)&&e(),e}(),15),n.trigger("ready.uk.dom"),n.support.touch&&navigator.userAgent.match(/(iPad|iPhone|iPod)/g)&&n.$win.on("load orientationchange resize",n.Utils.debounce(function(){var t=function(){return i(n.prefix(".@-height-viewport")).css("height",window.innerHeight),t};return t()}(),100)),n.trigger("afterready.uk.dom"),n.domready=!0}),n.$html.addClass(n.support.touch?"@-touch":"@-notouch"),n.support.touch){var s,a=!1,r=".@-overlay, .@-overlay-toggle, .@-caption-toggle, .@-animation-hover, .@-has-hover";n.$html.on("touchstart MSPointerDown pointerdown",r,function(){a&&n.$(".@-hover").removeClass("@-hover"),a=n.$(this).addClass("@-hover")}).on("touchend MSPointerUp pointerup",function(t){s=n.$(t.target).parents(r),a&&a.not(s).removeClass("@-hover")})}return n}),function(t){function i(t,i,e,n){return Math.abs(t-i)>=Math.abs(e-n)?t-i>0?"Left":"Right":e-n>0?"Up":"Down"}function e(){c=null,d.last&&(d.el.trigger("longTap"),d={})}function n(){c&&clearTimeout(c),c=null}function o(){a&&clearTimeout(a),r&&clearTimeout(r),l&&clearTimeout(l),c&&clearTimeout(c),a=r=l=c=null,d={}}function s(t){return t.pointerType==t.MSPOINTER_TYPE_TOUCH&&t.isPrimary}if(!t.fn.swipeLeft){var a,r,l,c,h,d={},u=750;t(function(){var f,p,g,m=0,v=0;"MSGesture"in window&&(h=new MSGesture,h.target=document.body),t(document).on("MSGestureEnd gestureend",function(t){var i=t.originalEvent.velocityX>1?"Right":t.originalEvent.velocityX<-1?"Left":t.originalEvent.velocityY>1?"Down":t.originalEv ent.velocityY<-1?"Up":null;i&&(d.el.trigger("swipe"),d.el.trigger("swipe"+i))}).on("touchstart MSPointerDown pointerdown",function(i){("MSPointerDown"!=i.type||s(i.originalEvent))&&(g="MSPointerDown"==i.type||"pointerdown"==i.type?i:i.originalEvent.touches[0],f=Date.now(),p=f-(d.last||f),d.el=t("tagName"in g.target?g.target:g.target.parentNode),a&&clearTimeout(a),d.x1=g.pageX,d.y1=g.pageY,p>0&&250>=p&&(d.isDoubleTap=!0),d.last=f,c=setTimeout(e,u),!h||"MSPointerDown"!=i.type&&"pointerdown"!=i.type&&"touchstart"!=i.type||h.addPointer(i.originalEvent.pointerId))}).on("touchmove MSPointerMove pointermove",function(t){("MSPointerMove"!=t.type||s(t.originalEvent))&&(g="MSPointerMove"==t.type||"pointermove"==t.type?t:t.originalEvent.touches[0],n(),d.x2=g.pageX,d.y2=g.pageY,m+=Math.abs(d.x1-d.x2),v+=Math.abs(d.y1-d.y2))}).on("touchend MSPointerUp pointerup",function(e){("MSPointerUp"!=e.type||s(e.originalEvent))&&(n(),d.x2&&Math.abs(d.x1-d.x2)>30||d.y2&&Math.abs(d.y1-d.y2)>30?l=setTimeout(f unction(){d.el.trigger("swipe"),d.el.trigger("swipe"+i(d.x1,d.x2,d.y1,d.y2)),d={}},0):"last"in d&&(isNaN(m)||30>m&&30>v?r=setTimeout(function(){var i=t.Event("tap");i.cancelTouch=o,d.el.trigger(i),d.isDoubleTap?(d.el.trigger("doubleTap"),d={}):a=setTimeout(function(){a=null,d.el.trigger("singleTap"),d={}},250)},0):d={},m=v=0))}).on("touchcancel MSPointerCancel",o),t(window).on("scroll",o)}),["swipe","swipeLeft","swipeRight","swipeUp","swipeDown","doubleTap","tap","singleTap","longTap"].forEach(function(i){t.fn[i]=function(e){return t(this).on(i,e)}})}}(jQuery),function(t,i){"use strict";var e=[];i.component("stackMargin",{defaults:{cls:"@-margin-small-top"},boot:function(){i.ready(function(t){i.$("[data-@-margin]",t).each(function(){var t,e=i.$(this);e.data("stackMargin")||(t=i.stackMargin(e,i.Utils.options(e.attr("data-@-margin"))))})})},init:function(){var n=this;this.columns=this.element.children(),this.columns.length&&(i.$win.on("resize orientationchange",function(){var e=functi on(){n.process()};return t(function(){e(),i.$win.on("load",e)}),i.Utils.debounce(e,20)}()),i.$html.on("changed.uk.dom",function(){n.columns=n.element.children(),n.process()}),this.on("display.uk.check",function(){n.columns=n.element.children(),this.element.is(":visible")&&this.process()}.bind(this)),e.push(this))},process:function(){return i.Utils.stackMargin(this.columns,this.options),this},revert:function(){return this.columns.removeClass(this.options.cls),this}}),i.ready(function(){var e=[],n=function(){e.forEach(function(t){if(t.is(":visible")){var i=t.parent().width(),e=t.data("width"),n=i/e,o=Math.floor(n*t.data("height"));t.css({height:e>i?o:t.data("height")})}})};return i.$win.on("resize",i.Utils.debounce(n,15)),function(o){i.$("iframe.@-responsive-width",o).each(function(){var i=t(this);!i.data("responsive")&&i.attr("width")&&i.attr("height")&&(i.data("width",i.attr("width")),i.data("height",i.attr("height")),i.data("responsive",!0),e.push(i))}),n()}}()),i.Utils.stackMargin =function(e,n){n=t.extend({cls:"@-margin-small-top"},n),n.cls=i.prefix(n.cls),e=t(e).removeClass(n.cls);var o=!1,s=e.filter(":visible:first"),a=s.length?s.position().top+s.outerHeight()-1:!1;a!==!1&&e.each(function(){var t=i.$(this);t.is(":visible")&&(o?t.addClass(n.cls):t.position().top>=a&&(o=t.addClass(n.cls)))})}}(jQuery,UIkit),function(t,i){"use strict";function e(e,n){n=t.extend({duration:1e3,transition:"easeOutExpo",offset:0,complete:function(){}},n);var o=e.offset().top-n.offset,s=i.$doc.height(),a=window.innerHeight;o+a>s&&(o=s-a),i.$("html,body").stop().animate({scrollTop:o},n.duration,n.transition).promise().done(n.complete)}i.component("smoothScroll",{boot:function(){i.$html.on("click.smooth-scroll.uikit","[data-@-smooth-scroll]",function(){var t=i.$(this);if(!t.data("smoothScroll")){{i.smoothScroll(t,i.Utils.options(t.attr("data-@-smooth-scroll")))}t.trigger("click")}return!1})},init:function(){var t=this;this.on("click",function(n){n.preventDefault(),e(i.$(this.hash).l ength?i.$(this.hash):i.$("body"),t.options)})}}),i.Utils.scrollToElement=e,t.easing.easeOutExpo||(t.easing.easeOutExpo=function(t,i,e,n,o){return i==o?e+n:n*(-Math.pow(2,-10*i/o)+1)+e})}(jQuery,UIkit),function(t,i){"use strict";var e=i.$win,n=i.$doc,o=[],s=function(){for(var t=0;t<o.length;t++)i.support.requestAnimationFrame.apply(window,[o[t].check])};i.component("scrollspy",{defaults:{cls:"@-scrollspy-inview",initcls:"@-scrollspy-init-inview",topoffset:0,leftoffset:0,repeat:!1,delay:0},boot:function(){n.on("scrolling.uk.document",s),e.on("resize orientationchange",i.Utils.debounce(s,50)),i.ready(function(t){i.$("[data-@-scrollspy]",t).each(function(){var t=i.$(this);if(!t.data("scrollspy")){i.scrollspy(t,i.Utils.options(t.attr("data-@-scrollspy")))}})})},init:function(){var t,e,n,s=this,a=function(){var o=i.Utils.isInView(s.element,s.options);o&&!e&&(t&&clearTimeout(t),n||(s.element.addClass(s.options.initcls),s.offset=s.element.offset(),n=!0,s.trigger("init.uk.scrollspy")),t=setT imeout(function(){o&&s.element.addClass("@-scrollspy-inview").addClass(s.options.cls).width()},s.options.delay),e=!0,s.trigger("inview.uk.scrollspy")),!o&&e&&s.options.repeat&&(s.element.removeClass("@-scrollspy-inview").removeClass(s.options.cls),e=!1,s.trigger("outview.uk.scrollspy"))};a(),this.check=a,o.push(this)}});var a=[],r=function(){for(var t=0;t<a.length;t++)i.support.requestAnimationFrame.apply(window,[a[t].check])};i.component("scrollspynav",{defaults:{cls:"@-active",closest:!1,topoffset:0,leftoffset:0,smoothscroll:!1},boot:function(){n.on("scrolling.uk.document",r),e.on("resize orientationchange",i.Utils.debounce(r,50)),i.ready(function(t){i.$("[data-@-scrollspy-nav]",t).each(function(){var t=i.$(this);if(!t.data("scrollspynav")){i.scrollspynav(t,i.Utils.options(t.attr("data-@-scrollspy-nav")))}})})},init:function(){var n,o=[],s=this.find("a[href^='#']").each(function(){o.push(t(this).attr("href"))}),r=t(o.join(",")),l=i.prefix(this.options.cls),c=i.prefix(this.options. closest||this.options.closest),h=this,d=function(){n=[];for(var t=0;t<r.length;t++)i.Utils.isInView(r.eq(t),h.options)&&n.push(r.eq(t));if(n.length){var o,a=e.scrollTop(),d=function(){for(var t=0;t<n.length;t++)if(n[t].offset().top>=a)return n[t]}();if(!d)return;h.options.closest?(s.closest(c).removeClass(l),o=s.filter("a[href='#"+d.attr("id")+"']").closest(c).addClass(l)):o=s.removeClass(l).filter("a[href='#"+d.attr("id")+"']").addClass(l),h.element.trigger("inview.uk.scrollspynav",[d,o])}};this.options.smoothscroll&&i.smoothScroll&&s.each(function(){i.smoothScroll(this,h.options.smoothscroll)}),d(),this.element.data("scrollspynav",this),this.check=d,a.push(this)}})}(jQuery,UIkit),function(t,i,e){"use strict";var n=[];e.component("toggle",{defaults:{target:!1,cls:"@-hidden",animation:!1,duration:200},boot:function(){e.ready(function(t){e.$("[data-@-toggle]",t).each(function(){var t=e.$(this);if(!t.data("toggle")){e.toggle(t,e.Utils.options(t.attr("data-@-toggle")))}}),setTimeout(fu nction(){n.forEach(function(t){t.getToggles()})},0)})},init:function(){var t=this;this.getToggles(),this.on("click",function(i){t.element.is('a[href="#"]')&&i.preventDefault(),t.toggle()}),n.push(this)},toggle:function(){if(this.totoggle.length)if(this.options.animation&&e.support.animation){var t=this,n=e.prefix(this.options.animation).split(",");1==n.length&&(n[1]=n[0]),n[0]=n[0].trim(),n[1]=n[1].trim(),this.totoggle.css("animation-duration",this.options.duration+"ms"),this.totoggle.hasClass(this.options.cls)?(this.totoggle.toggleClass(this.options.cls),this.totoggle.each(function(){e.Utils.animate(this,n[0]).then(function(){i(this).css("animation-duration",""),e.Utils.checkDisplay(this)})})):this.totoggle.each(function(){e.Utils.animate(this,n[1]+" @-animation-reverse").then(function(){e.$(this).toggleClass(t.options.cls).css("animation-duration",""),e.Utils.checkDisplay(this)}.bind(this))})}else this.totoggle.toggleClass(this.options.cls),e.Utils.checkDisplay(this.totoggle)},get Toggles:function(){this.totoggle=this.options.target?e.$(this.options.target):[]}})}(this,jQuery,UIkit),function(t,i){"use strict";i.component("alert",{defaults:{fade:!0,duration:200,trigger:".@-alert-close"},boot:function(){i.$html.on("click.alert.uikit","[data-@-alert]",function(t){var e=i.$(this);if(!e.data("alert")){var n=i.alert(e,i.Utils.options(e.attr("data-@-alert")));i.$(t.target).is(n.options.trigger)&&(t.preventDefault(),n.close())}})},init:function(){var t=this;this.on("click",this.options.trigger,function(i){i.preventDefault(),t.close()})},close:function(){var t=this.trigger("close.uk.alert"),i=function(){this.trigger("closed.uk.alert").remove()}.bind(this);this.options.fade?t.css("overflow","hidden").css("max-height",t.height()).animate({height:0,opacity:0,"padding-top":0,"padding-bottom":0,"margin-top":0,"margin-bottom":0},this.options.duration,i):i()}})}(jQuery,UIkit),function(t,i){"use strict";i.component("buttonRadio",{defaults:{target:".@-button"},boot:function(){ i.$html.on("click.buttonradio.uikit","[data-@-button-radio]",function(t){var e=i.$(this);if(!e.data("buttonRadio")){var n=i.buttonRadio(e,i.Utils.options(e.attr("data-@-button-radio"))),o=i.$(t.target);o.is(n.options.target)&&o.trigger("click")}})},init:function(){var t=this;this.on("click",this.options.target,function(e){var n=i.$(this);n.is('a[href="#"]')&&e.preventDefault(),t.find(t.options.target).not(n).removeClass(i.prefix("@-active")).blur(),t.trigger("change.uk.button",[n.addClass("@-active")])})},getSelected:function(){return this.find(".@-active")}}),i.component("buttonCheckbox",{defaults:{target:".@-button"},boot:function(){i.$html.on("click.buttoncheckbox.uikit","[data-@-button-checkbox]",function(t){var e=i.$(this);if(!e.data("buttonCheckbox")){var n=i.buttonCheckbox(e,i.Utils.options(e.attr("data-@-button-checkbox"))),o=i.$(t.target);o.is(n.options.target)&&e.trigger("change.uk.button",[o.toggleClass("@-active").blur()])}})},init:function(){var e=this;this.on("click",t his.options.target,function(n){t(this).is('a[href="#"]')&&n.preventDefault(),e.trigger("change.uk.button",[i.$(this).toggleClass("@-active").blur()])})},getSelected:function(){return this.find(".@-active")}}),i.component("button",{defaults:{},boot:function(){i.$html.on("click.button.uikit","[data-@-button]",function(){var t=i.$(this);if(!t.data("button")){{i.button(t,i.Utils.options(t.attr("data-@-button")))}t.trigger("click")}})},init:function(){var t=this;this.on("click",function(i){t.element.is('a[href="#"]')&&i.preventDefault(),t.toggle(),t.trigger("change.uk.button",[t.element.blur().hasClass("@-active")])})},toggle:function(){this.element.toggleClass("@-active")}})}(jQuery,UIkit),function(t,i){"use strict";var e,n=!1;i.component("dropdown",{defaults:{mode:"hover",remaintime:800,justify:!1,boundary:i.$win,delay:0},remainIdle:!1,boot:function(){var t=i.support.touch?"click":"mouseenter";i.$html.on(t+".dropdown.uikit","[data-@-dropdown]",function(e){var n=i.$(this);if(!n.data("dr opdown")){var o=i.dropdown(n,i.Utils.options(n.attr("data-@-dropdown")));("click"==t||"mouseenter"==t&&"hover"==o.options.mode)&&o.element.trigger(t),o.element.find(".@-dropdown").length&&e.preventDefault()}})},init:function(){var n=this;this.dropdown=this.find(".@-dropdown"),this.centered=this.dropdown.hasClass("@-dropdown-center"),this.justified=this.options.justify?i.$(this.options.justify):!1,this.boundary=i.$(this.options.boundary),this.flipped=this.dropdown.hasClass("@-dropdown-flip"),this.boundary.length||(this.boundary=i.$win),"click"==this.options.mode||i.support.touch?this.on("click",function(t){var e=i.$(t.target);e.parents(".@-dropdown").length||((e.is("a[href='#']")||e.parent().is("a[href='#']")||n.dropdown.length&&!n.dropdown.is(":visible"))&&t.preventDefault(),e.blur()),n.element.hasClass("@-open")?(e.is("a:not(.js-@-prevent)")||e.is(".@-dropdown-close")||!n.dropdown.find(t.target).length)&&n.hide():n.show()}):this.on("mouseenter",function(){n.remainIdle&&clearTimeout (n.remainIdle),e&&clearTimeout(e),e=setTimeout(n.show.bind(n),n.options.delay)}).on("mouseleave",function(){e&&clearTimeout(e),n.remainIdle=setTimeout(function(){n.hide()},n.options.remaintime)}).on("click",function(i){var e=t(i.target);n.remainIdle&&clearTimeout(n.remainIdle),(e.is("a[href='#']")||e.parent().is("a[href='#']"))&&i.preventDefault(),n.show()})},show:function(){i.$html.off("click.outer.dropdown"),n&&n[0]!=this.element[0]&&n.removeClass("@-open"),e&&clearTimeout(e),this.checkDimensions(),this.element.addClass("@-open"),this.trigger("show.uk.dropdown",[this]),i.Utils.checkDisplay(this.dropdown,!0),n=this.element,this.registerOuterClick()},hide:function(){this.element.removeClass("@-open"),this.remainIdle=!1,n&&n[0]==this.element[0]&&(n=!1)},registerOuterClick:function(){var t=this;i.$html.off("click.outer.dropdown"),setTimeout(function(){i.$html.on("click.outer.dropdown",function(o){e&&clearTimeout(e);var s=i.$(o.target);n&&n[0]==t.element[0]&&(s.is("a:not(.js-@-prevent) ")||s.is(".@-dropdown-close")||!t.dropdown.find(o.target).length)&&(t.hide(),i.$html.off("click.outer.dropdown"))})},10)},checkDimensions:function(){if(this.dropdown.length){this.justified&&this.justified.length&&this.dropdown.css("min-width","");var t=this,e=this.dropdown.css("margin-"+i.langdirection,""),n=e.show().offset(),o=e.outerWidth(),s=this.boundary.width(),a=this.boundary.offset()?this.boundary.offset().left:0;if(this.centered&&(e.css("margin-"+i.langdirection,-1*(parseFloat(o)/2-e.parent().width()/2)),n=e.offset(),(o+n.left>s||n.left<0)&&(e.css("margin-"+i.langdirection,""),n=e.offset())),this.justified&&this.justified.length){var r=this.justified.outerWidth();if(e.css("min-width",r),"right"==i.langdirection){var l=s-(this.justified.offset().left+r),c=s-(e.offset().left+e.outerWidth());e.css("margin-right",l-c)}else e.css("margin-left",this.justified.offset().left-n.left);n=e.offset()}o+(n.left-a)>s&&(e.addClass("@-dropdown-flip"),n=e.offset()),n.left-a<0&&(e.addClass("@- dropdown-stack"),e.hasClass("@-dropdown-flip")&&(this.flipped||(e.removeClass("@-dropdown-flip"),n=e.offset(),e.addClass("@-dropdown-flip")),setTimeout(function(){(e.offset().left-a<0||!t.flipped&&e.outerWidth()+(n.left-a)<s)&&e.removeClass("@-dropdown-flip")},0)),this.trigger("stack.uk.dropdown",[this])),e.css("display","")}}})}(jQuery,UIkit),function(t,i){"use strict";var e=[];i.component("gridMatchHeight",{defaults:{target:!1,row:!0},boot:function(){i.ready(function(t){i.$("[data-@-grid-match]",t).each(function(){var t,e=i.$(this);e.data("gridMatchHeight")||(t=i.gridMatchHeight(e,i.Utils.options(e.attr("data-@-grid-match"))))})})},init:function(){var n=this;this.columns=this.element.children(),this.elements=this.options.target?this.find(this.options.target):this.columns,this.columns.length&&(i.$win.on("resize orientationchange",function(){var e=function(){n.match()};return t(function(){e(),i.$win.on("load",e)}),i.Utils.debounce(e,50)}()),i.$html.on("changed.uk.dom",function(){n.c olumns=n.element.children(),n.elements=n.options.target?n.find(n.options.target):n.columns,n.match()}),this.on("display.uk.check",function(){this.element.is(":visible")&&this.match()}.bind(this)),e.push(this))},match:function(){return i.Utils.matchHeights(this.elements,this.options),this},revert:function(){return this.elements.css("min-height",""),this}}),i.component("gridMargin",{defaults:{cls:"@-grid-margin"},boot:function(){i.ready(function(t){i.$("[data-@-grid-margin]",t).each(function(){var t,e=i.$(this);e.data("gridMargin")||(t=i.gridMargin(e,i.Utils.options(e.attr("data-@-grid-margin"))))})})},init:function(){i.stackMargin(this.element,this.options)}}),i.Utils.matchHeights=function(i,e){i=t(i).css("min-height",""),e=t.extend({row:!0},e);var n=i.filter(":visible:first");if(n.length){var o=Math.ceil(100*parseFloat(n.css("width"))/parseFloat(n.parent().css("width")))>=100?!0:!1,s=function(i){if(!(i.length<2)){var e=0;i.each(function(){e=Math.max(e,t(this).outerHeight())}).each(f unction(){var i=t(this),n=e-(i.outerHeight()-i.height());i.css("min-height",n+"px")})}};o||(e.row?(n.width(),setTimeout(function(){var e=!1,n=[];i.each(function(){var i=t(this),o=i.offset().top;o!=e&&n.length&&(s(t(n)),n=[],o=i.offset().top),n.push(i),e=o}),n.length&&s(t(n))},0)):s(i))}}}(jQuery,UIkit),function(t,i){"use strict";function e(e,n){return n?("object"==typeof e?(e=e instanceof jQuery?e:i.$(e),e.parent().length&&(n.persist=e,n.persist.data("modalPersistParent",e.parent()))):e="string"==typeof e||"number"==typeof e?t("<div></div>").html(e):t("<div></div>").html("UIkit.modal Error: Unsupported data type: "+typeof e),e.appendTo(n.element.find(".@-modal-dialog")),n):void 0}var n,o=!1,s=i.$html;i.component("modal",{defaults:{keyboard:!0,bgclose:!0,minScrollHeight:150,center:!1},scrollable:!1,transition:!1,init:function(){n||(n=t("body"));var e=this;this.transition=i.support.transition,this.paddingdir="padding-"+("left"==i.langdirection?"right":"left"),this.dialog=this.find(".@ -modal-dialog"),this.on("click",".@-modal-close",function(t){t.preventDefault(),e.hide()}).on("click",function(i){var n=t(i.target);n[0]==e.element[0]&&e.options.bgclose&&e.hide()})},toggle:function(){return this[this.isActive()?"hide":"show"]()},show:function(){if(!this.isActive())return o&&o.hide(!0),this.element.removeClass("@-open").show(),this.resize(),o=this,s.addClass("@-modal-page").height(),this.element.addClass("@-open").trigger("show.uk.modal"),i.Utils.checkDisplay(this.dialog,!0),this},hide:function(t){if(this.isActive()){if(!t&&i.support.transition){var e=this;this.one(i.support.transition.end,function(){e._hide()}).removeClass("@-open")}else this._hide();return this}},resize:function(){var t=n.width();if(this.scrollbarwidth=window.innerWidth-t,n.css(this.paddingdir,this.scrollbarwidth),this.element.css("overflow-y",this.scrollbarwidth?"scroll":"auto"),!this.updateScrollable()&&this.options.center){var i=this.dialog.outerHeight(),e=parseInt(this.dialog.css("margin-top") ,10)+parseInt(this.dialog.css("margin-bottom"),10);i+e<window.innerHeight?this.dialog.css({top:window.innerHeight/2-i/2-e}):this.dialog.css({top:""})}},updateScrollable:function(){var t=this.dialog.find(".@-overflow-container:visible:first");if(t.length){t.css("height",0);var i=Math.abs(parseInt(this.dialog.css("margin-top"),10)),e=this.dialog.outerHeight(),n=window.innerHeight,o=n-2*(20>i?20:i)-e;return t.css("height",o<this.options.minScrollHeight?"":o),!0}return!1},_hide:function(){this.element.hide().removeClass("@-open"),s.removeClass("@-modal-page"),n.css(this.paddingdir,""),o===this&&(o=!1),this.trigger("hide.uk.modal")},isActive:function(){return o==this}}),i.component("modalTrigger",{boot:function(){i.$html.on("click.modal.uikit","[data-@-modal]",function(t){var e=i.$(this);if(e.is("a")&&t.preventDefault(),!e.data("modalTrigger")){var n=i.modalTrigger(e,i.Utils.options(e.attr("data-@-modal")));n.show()}}),i.$html.on("keydown.modal.uikit",function(t){o&&27===t.keyCode&&o.opt ions.keyboard&&(t.preventDefault(),o.hide())}),i.$win.on("resize orientationchange",i.Utils.debounce(function(){o&&o.resize()},150))},init:function(){var e=this;this.options=t.extend({target:e.element.is("a")?e.element.attr("href"):!1},this.options),this.modal=i.modal(this.options.target,this.options),this.on("click",function(t){t.preventDefault(),e.show()}),this.proxy(this.modal,"show hide isActive")}}),i.modal.dialog=function(t,n){var o=i.modal(i.$(i.modal.dialog.template).appendTo("body"),n);return o.on("hide.uk.modal",function(){o.persist&&(o.persist.appendTo(o.persist.data("modalPersistParent")),o.persist=!1),o.element.remove()}),e(t,o),o},i.modal.dialog.template='<div class="@-modal"><div class="@-modal-dialog"></div></div>',i.modal.alert=function(e,n){i.modal.dialog(['<div class="@-margin @-modal-content">'+String(e)+"</div>",'<div class="@-modal-buttons"><button class="@-button @-button-primary @-modal-close">Ok</button></div>'].join("").replace(/@-/g,i._prefix+"-").replace( /@-/g,i._prefix+"-"),t.extend({bgclose:!1,keyboard:!1},n)).show()},i.modal.confirm=function(e,n,o){n=t.isFunction(n)?n:function(){};var s=i.modal.dialog(['<div class="@-margin @-modal-content">'+String(e)+"</div>",'<div class="@-modal-buttons"><button class="@-button @-button-primary js-modal-confirm">Ok</button> <button class="@-button @-modal-close">Cancel</button></div>'].join("").replace(/@-/g,i._prefix+"-"),t.extend({bgclose:!1,keyboard:!1},o));s.element.find(".js-modal-confirm").on("click",function(){n(),s.hide()}),s.show()}}(jQuery,UIkit),function(t,i){"use strict";function e(t){var e=i.$(t),n="auto";if(e.is(":visible"))n=e.outerHeight();else{var o={position:e.css("position"),visibility:e.css("visibility"),display:e.css("display")};n=e.css({position:"absolute",visibility:"hidden",display:"block"}).outerHeight(),e.css(o)}return n}i.component("nav",{defaults:{toggle:">li.@-parent > a[href='#']",lists:">li.@-parent > ul",multiple:!1},boot:function(){i.ready(function(t){i.$("[dat a-@-nav]",t).each(function(){var t=i.$(this);if(!t.data("nav")){i.nav(t,i.Utils.options(t.attr("data-@-nav"))) +}})})},init:function(){var t=this;this.on("click",this.options.toggle,function(e){e.preventDefault();var n=i.$(this);t.open(n.parent()[0]==t.element[0]?n:n.parent("li"))}),this.find(this.options.lists).each(function(){var e=i.$(this),n=e.parent(),o=n.hasClass("@-active");e.wrap('<div style="overflow:hidden;height:0;position:relative;"></div>'),n.data("list-container",e.parent()),o&&t.open(n,!0)})},open:function(t,n){var o=this,s=this.element,a=i.$(t);this.options.multiple||s.children(".@-open").not(t).each(function(){var t=i.$(this);t.data("list-container")&&t.data("list-container").stop().animate({height:0},function(){i.$(this).parent().removeClass("@-open")})}),a.toggleClass("@-open"),a.data("list-container")&&(n?(a.data("list-container").stop().height(a.hasClass("@-open")?"auto":0),this.trigger("display.uk.check")):a.data("list-container").stop().animate({height:a.hasClass("@-open")?e(a.data("list-container").find("ul:first")):0},function(){o.trigger("display.uk.check")}))}})}(jQ uery,UIkit),function(t,i){"use strict";var e={x:window.scrollX,y:window.scrollY},n=(i.$win,i.$doc),o=i.$html,s={show:function(t){if(t=i.$(t),t.length){var s=i.$("body"),a=t.find(".@-offcanvas-bar:first"),r="right"==i.langdirection,l=a.hasClass("@-offcanvas-bar-flip")?-1:1,c=l*(r?-1:1);e={x:window.pageXOffset,y:window.pageYOffset},t.addClass("@-active"),s.css({width:window.innerWidth,height:window.innerHeight}).addClass("@-offcanvas-page"),s.css(r?"margin-right":"margin-left",(r?-1:1)*a.outerWidth()*c).width(),o.css("margin-top",-1*e.y),a.addClass("@-offcanvas-bar-show"),this._initElement(t),n.trigger("show.uk.offcanvas",[t,a])}},hide:function(t){var n=i.$("body"),s=i.$(".@-offcanvas.@-active"),a="right"==i.langdirection,r=s.find(".@-offcanvas-bar:first"),l=function(){n.removeClass("@-offcanvas-page").css({width:"",height:"","margin-left":"","margin-right":""}),s.removeClass("@-active"),r.removeClass("@-offcanvas-bar-show"),o.css("margin-top",""),window.scrollTo(e.x,e.y),i.$doc.trigg er("hide.uk.offcanvas",[s,r])};s.length&&(i.support.transition&&!t?(n.one(i.support.transition.end,function(){l()}).css(a?"margin-right":"margin-left",""),setTimeout(function(){r.removeClass("@-offcanvas-bar-show")},0)):l())},_initElement:function(e){e.data("OffcanvasInit")||(e.on("click.uk.offcanvas swipeRight.uk.offcanvas swipeLeft.uk.offcanvas",function(t){var e=i.$(t.target);if(!t.type.match(/swipe/)&&!e.hasClass("@-offcanvas-close")){if(e.hasClass("@-offcanvas-bar"))return;if(e.parents(".@-offcanvas-bar:first").length)return}t.stopImmediatePropagation(),s.hide()}),e.on("click","a[href^='#']",function(){var e=t(this),n=e.attr("href");"#"!=n&&(i.$doc.one("hide.uk.offcanvas",function(){var e=t(n);e.length||(e=i.$('[name="'+n.replace("#","")+'"]')),i.Utils.scrollToElement&&e.length?i.Utils.scrollToElement(e):window.location.href=n}),s.hide())}),e.data("OffcanvasInit",!0))}};i.component("offcanvasTrigger",{boot:function(){o.on("click.offcanvas.uikit","[data-@-offcanvas]",function(t) {t.preventDefault();var e=i.$(this);if(!e.data("offcanvasTrigger")){{i.offcanvasTrigger(e,i.Utils.options(e.attr("data-@-offcanvas")))}e.trigger("click")}}),o.on("keydown.uk.offcanvas",function(t){27===t.keyCode&&s.hide()})},init:function(){var i=this;this.options=t.extend({target:i.element.is("a")?i.element.attr("href"):!1},this.options),this.on("click",function(t){t.preventDefault(),s.show(i.options.target)})}}),i.offcanvas=s}(jQuery,UIkit),function(t,i){"use strict";function e(e,n,o){var s,a=t.Deferred(),r=i.prefix(e),l=e;return o[0]===n[0]?(a.resolve(),a.promise()):("object"==typeof e&&(r=e[0],l=e[1]||e[0]),s=function(){n&&n.hide().removeClass(i.prefix("@-active "+l+" @-animation-reverse")),o.addClass(r).one(i.support.animation.end,function(){o.removeClass(""+r).css({opacity:"",display:""}),a.resolve(),n&&n.css({opacity:"",display:""})}.bind(this)).show()},o.css("animation-duration",this.options.duration+"ms"),n&&n.length?(n.css("animation-duration",this.options.duration+"ms"),n .css("display","none").addClass(i.prefix(l+" @-animation-reverse")).one(i.support.animation.end,function(){s()}.bind(this)).css("display","")):(o.addClass("@-active"),s()),a.promise())}var n;i.component("switcher",{defaults:{connect:!1,toggle:">*",active:0,animation:!1,duration:200},animating:!1,boot:function(){i.ready(function(t){i.$("[data-@-switcher]",t).each(function(){var t=i.$(this);if(!t.data("switcher")){i.switcher(t,i.Utils.options(t.attr("data-@-switcher")))}})})},init:function(){var t=this;if(this.on("click",this.options.toggle,function(i){i.preventDefault(),t.show(this)}),this.options.connect){this.connect=i.$(this.options.connect),this.connect.find(".@-active").removeClass(".@-active"),this.connect.length&&this.connect.on("click","[data-@-switcher-item]",function(e){e.preventDefault();var n=i.$(this).data(i._prefix+"SwitcherItem");if(t.index!=n)switch(n){case"next":case"previous":t.show(t.index+("next"==n?1:-1));break;default:t.show(n)}});var e=this.find(this.options.to ggle),n=e.filter(".@-active");if(n.length)this.show(n,!1);else{if(this.options.active===!1)return;n=e.eq(i.prefix(this.options.active)),this.show(n.length?n:e.eq(0),!1)}this.on(i.prefix("[email protected]"),function(){t.connect=i.$(t.options.connect)})}},show:function(t,o){if(!this.animating){if(isNaN(t))t=i.$(t);else{var s=this.find(this.options.toggle);t=0>t?s.length-1:t,t=s.eq(s[t]?t:0)}var a=this,r=i.$(t),l=n[this.options.animation]||function(t,i){if(!a.options.animation)return n.none.apply(a);var o=a.options.animation.split(",");return 1==o.length&&(o[1]=o[0]),o[0]=o[0].trim(),o[1]=o[1].trim(),e.apply(a,[o,t,i])};o!==!1&&i.support.animation||(l=n.none),r.hasClass("@-disabled")||(this.find(this.options.toggle).filter(".@-active").removeClass("@-active"),r.addClass("@-active"),this.options.connect&&this.connect.length&&(this.index=this.find(this.options.toggle).index(r),-1==this.index&&(this.index=0),this.connect.each(function(){var t=i.$(this),e=i.$(t.children()),n=i.$(e.filter(".@- active")),o=i.$(e.eq(a.index));a.animating=!0,l.apply(a,[n,o]).then(function(){n.removeClass("@-active"),o.addClass("@-active"),i.Utils.checkDisplay(o,!0),a.animating=!1})})),this.trigger("show.uk.switcher",[r]))}}}),n={none:function(){var i=t.Deferred();return i.resolve(),i.promise()},fade:function(t,i){return e.apply(this,["@-animation-fade",t,i])},"slide-bottom":function(t,i){return e.apply(this,["@-animation-slide-bottom",t,i])},"slide-top":function(t,i){return e.apply(this,["@-animation-slide-top",t,i])},"slide-vertical":function(t,i){var n=["@-animation-slide-top","@-animation-slide-bottom"];return t&&t.index()>i.index()&&n.reverse(),e.apply(this,[n,t,i])},"slide-left":function(t,i){return e.apply(this,["@-animation-slide-left",t,i])},"slide-right":function(t,i){return e.apply(this,["@-animation-slide-right",t,i])},"slide-horizontal":function(t,i){var n=["@-animation-slide-left","@-animation-slide-right"];return t&&t.index()>i.index()&&n.reverse(),e.apply(this,[n,t,i])},scale: function(t,i){return e.apply(this,["@-animation-scale-up",t,i])}},i.switcher.animations=n}(jQuery,UIkit),function(t,i){"use strict";i.component("tab",{defaults:{target:">li:not(.@-tab-responsive, .@-disabled)",connect:!1,active:0,animation:!1,duration:200},boot:function(){i.ready(function(t){i.$("[data-@-tab]",t).each(function(){var t=i.$(this);if(!t.data("tab")){i.tab(t,i.Utils.options(t.attr("data-@-tab")))}})})},init:function(){var e=this;this.on("click",this.options.target,function(t){t.preventDefault(),e.find(e.options.target).not(this).removeClass(i.prefix("@-active")).blur(),e.trigger("change.uk.tab",[i.$(this).addClass("@-active")])}),this.options.connect&&(this.connect=t(this.options.connect)),this.responsivetab=i.$('<li class="@-tab-responsive @-active"><a></a></li>').append(i.prefix('<div class="@-dropdown @-dropdown-small"><ul class="@-nav @-nav-dropdown"></ul><div>')),this.responsivetab.dropdown=this.responsivetab.find(".@-dropdown"),this.responsivetab.lst=this.responsi vetab.dropdown.find("ul"),this.responsivetab.caption=this.responsivetab.find("a:first"),this.element.hasClass("@-tab-bottom")&&this.responsivetab.dropdown.addClass("@-dropdown-up"),this.responsivetab.lst.on("click","a",function(i){i.preventDefault(),i.stopPropagation();var n=t(this);e.element.children(":not(.@-tab-responsive)").eq(n.data("index")).trigger("click")}),this.on("show.uk.switcher change.uk.tab",function(t,i){e.responsivetab.caption.html(i.text())}),this.element.append(this.responsivetab),this.options.connect&&i.switcher(this.element,{toggle:">li:not(.@-tab-responsive)",connect:this.options.connect,active:this.options.active,animation:this.options.animation,duration:this.options.duration}),i.dropdown(this.responsivetab,{mode:"click"}),e.trigger("change.uk.tab",[this.element.find(this.options.target).filter(".@-active")]),this.check(),i.$win.on("resize orientationchange",i.Utils.debounce(function(){e.element.is(":visible")&&e.check()},100)),this.on("display.uk.check",funct ion(){e.element.is(":visible")&&e.check()})},check:function(){var e=this.element.children(":not(.@-tab-responsive)").removeClass("@-hidden");if(e.length){var n,o,s=e.eq(0).offset().top+Math.ceil(e.eq(0).height()/2),a=!1;if(this.responsivetab.lst.empty(),e.each(function(){t(this).offset().top>s&&(a=!0)}),a)for(var r=0;r<e.length;r++)n=i.$(e.eq(r)),o=n.find("a"),"none"==n.css("float")||n.attr("@-dropdown")||(n.addClass("@-hidden"),n.hasClass("@-disabled")||this.responsivetab.lst.append('<li><a href="'+o.attr("href")+'" data-index="'+r+'">'+o.html()+"</a></li>"));this.responsivetab[this.responsivetab.lst.children().length?"removeClass":"addClass"]("@-hidden")}}})}(jQuery,UIkit),function(t,i){"use strict";var e,n,o;i.component("tooltip",{defaults:{offset:5,pos:"top",animation:!1,delay:0,cls:"",src:function(){return this.attr("title")}},tip:"",boot:function(){i.$html.on("mouseenter.tooltip.uikit focus.tooltip.uikit","[data-@-tooltip]",function(){var t=i.$(this);if(!t.data("tooltip")){{i. tooltip(t,i.Utils.options(t.attr("data-@-tooltip")))}t.trigger("mouseenter")}})},init:function(){var t=this;e||(e=i.$('<div class="@-tooltip"></div>').appendTo("body")),this.on({focus:function(){t.show()},blur:function(){t.hide()},mouseenter:function(){t.show()},mouseleave:function(){t.hide()}}),this.tip="function"==typeof this.options.src?this.options.src.call(this.element):this.options.src,this.element.attr("data-cached-title",this.element.attr("title")).attr("title","")},show:function(){if(n&&clearTimeout(n),o&&clearTimeout(o),this.tip.length){e.stop().css({top:-2e3,visibility:"hidden"}).show(),e.html(i.prefix('<div class="@-tooltip-inner">')+this.tip+"</div>");var s=this,a=t.extend({},this.element.offset(),{width:this.element[0].offsetWidth,height:this.element[0].offsetHeight}),r=e[0].offsetWidth,l=e[0].offsetHeight,c="function"==typeof this.options.offset?this.options.offset.call(this.element):this.options.offset,h="function"==typeof this.options.pos?this.options.pos.call(this. element):this.options.pos,d=h.split("-"),u={display:"none",visibility:"visible",top:a.top+a.height+l,left:a.left};if("fixed"==t("html").css("position")||"fixed"==t("body").css("position")){var f=i.$("body").offset(),p=i.$("html").offset(),g={top:p.top+f.top,left:p.left+f.left};a.left-=g.left,a.top-=g.top}"left"!=d[0]&&"right"!=d[0]||"right"!=i.langdirection||(d[0]="left"==d[0]?"right":"left");var m={bottom:{top:a.top+a.height+c,left:a.left+a.width/2-r/2},top:{top:a.top-l-c,left:a.left+a.width/2-r/2},left:{top:a.top+a.height/2-l/2,left:a.left-r-c},right:{top:a.top+a.height/2-l/2,left:a.left+a.width+c}};t.extend(u,m[d[0]]),2==d.length&&(u.left="left"==d[1]?a.left:a.left+a.width-r);var v=this.checkBoundary(u.left,u.top,r,l);if(v){switch(v){case"x":h=2==d.length?d[0]+"-"+(u.left<0?"left":"right"):u.left<0?"right":"left";break;case"y":h=2==d.length?(u.top<0?"bottom":"top")+"-"+d[1]:u.top<0?"bottom":"top";break;case"xy":h=2==d.length?(u.top<0?"bottom":"top")+"-"+(u.left<0?"left":"right"): u.left<0?"right":"left"}d=h.split("-"),t.extend(u,m[d[0]]),2==d.length&&(u.left="left"==d[1]?a.left:a.left+a.width-r)}u.left-=t("body").position().left,n=setTimeout(function(){e.css(u).attr("class",i.prefix(["@-tooltip","@-tooltip-"+h,s.options.cls].join(" "))),s.options.animation?e.css({opacity:0,display:"block"}).animate({opacity:1},parseInt(s.options.animation,10)||400):e.show(),n=!1,o=setInterval(function(){s.element.is(":visible")||s.hide()},150)},parseInt(this.options.delay,10)||0)}},hide:function(){this.element.is("input")&&this.element[0]===document.activeElement||(n&&clearTimeout(n),o&&clearTimeout(o),e.stop(),this.options.animation?e.fadeOut(parseInt(this.options.animation,10)||400):e.hide())},content:function(){return this.tip},checkBoundary:function(t,e,n,o){var s="";return(0>t||t-i.$win.scrollLeft()+n>window.innerWidth)&&(s+="x"),(0>e||e-i.$win.scrollTop()+o>window.innerHeight)&&(s+="y"),s}})}(jQuery,UIkit); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/helix/blob/6cbafef0/helix-ui/src/main/resources/assets/js/visualizer.js ---------------------------------------------------------------------- diff --git a/helix-ui/src/main/resources/assets/js/visualizer.js b/helix-ui/src/main/resources/assets/js/visualizer.js new file mode 100644 index 0000000..13b0279 --- /dev/null +++ b/helix-ui/src/main/resources/assets/js/visualizer.js @@ -0,0 +1,90 @@ +$(document).ready(function() { + + var uri = $("#visualizer-data-uri").text() + + if (uri) { + var diameter = 960, + format = d3.format(",d"); + + var color = d3.scale.category20(); + + var pack = d3.layout.pack() + .size([diameter - 4, diameter - 4]) + .value(function(d) { return d.size; }); + + var svg = d3.select("#resource-visualizer").append("svg") + .attr("width", diameter) + .attr("height", diameter) + .append("g") + .attr("transform", "translate(2,2)"); + + var loading = svg.append("text") + .attr("x", diameter / 2) + .attr("y", diameter / 4) + .attr("dy", ".35em") + .style("text-anchor", "middle") + .text("Rendering..."); + + /** Some fixed state colors */ + var stateColors = { + "MASTER": "#405898", + "SLAVE": "#8c9ac1", + "OFFLINE": "#c5c5c5", + "ONLINE": "#92ca4e", + "STANDBY": "#c2c0c3", + "LEADER": "#ffd700", + "ERROR": "#ff002d", + "DEAD": "#FF9494", + "DISABLED": "#FFFF94", + "LIVE": "#C7FAB1", + "": "#F0F2FF", + "N/A": "#DF7F4D" + } + + d3.json(uri, function(error, root) { + var node = svg.datum(root).selectAll(".node") + .data(pack.nodes) + .enter().append("g") + .attr("class", function(d) { return d.children ? "node" : "leaf node"; }) + .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }); + + node.append("title") + .text(function(d) { + var title = d.name + if (!d.children) { + title += " (" + d.parentName + ")" + } + if (d.state) { + title += ": " + d.state + } + return title + }); + + node.append("circle") + .attr("r", function(d) { return d.r; }) + .style("fill", function(d) { + if (stateColors[d.state]) { + return stateColors[d.state] + } else { + return color(d.state) // random color + } + }); + + node.filter(function(d) { return !d.children; }).append("text") + .attr("dy", ".3em") + .style("text-anchor", "middle") + .text(function(d) { + var suffix = d.name.substring(d.name.lastIndexOf("_") + 1) + var id = new Number(suffix) + if (isNaN(id)) { + return d.name.substring(0, d.r / 3); + } + return id + }); + + loading.remove() + }); + + d3.select(self.frameElement).style("height", diameter + "px"); + } +}) http://git-wip-us.apache.org/repos/asf/helix/blob/6cbafef0/helix-ui/src/main/resources/org/apache/helix/ui/view/cluster-view.ftl ---------------------------------------------------------------------- diff --git a/helix-ui/src/main/resources/org/apache/helix/ui/view/cluster-view.ftl b/helix-ui/src/main/resources/org/apache/helix/ui/view/cluster-view.ftl new file mode 100644 index 0000000..55b9d45 --- /dev/null +++ b/helix-ui/src/main/resources/org/apache/helix/ui/view/cluster-view.ftl @@ -0,0 +1,61 @@ +<!DOCTYPE html> +<html> + <head> + <title>${zkAddress}</title> + <meta charset="UTF-8"> + <#include "common/css.ftl"> + </head> + + <body> + + <div class="uk-grid"> + <div class="uk-width-medium-2-10"> + <#include "common/side-nav.ftl"> + </div> + + <div class="uk-width-medium-8-10"> + <div id="cluster-views-area"> + <#if (activeValid)> + <h1>${activeCluster}</h1> + + <ul id="switcher-tabs" class="uk-subnav uk-subnav-pill" data-uk-switcher="{connect: '#switcher'}"> + <li><a href="">Resources</a></li> + <li><a href="">Instances</a></li> + <li><a href="">Config</a></li> + </ul> + + <ul id="switcher" class="uk-switcher"> + <li> + <#include "common/resource-table.ftl"> + <#if (adminMode)> + <#include "common/resource-admin.ftl"> + </#if> + </li> + <li> + <#include "common/instance-table.ftl"> + <#if (adminMode)> + <#include "common/instance-admin.ftl"> + </#if> + </li> + <li> + <#include "common/config-table.ftl"> + <#if (adminMode)> + <#include "common/cluster-admin.ftl"> + </#if> + </li> + </ul> + <#else> + <div class="uk-alert uk-alert-danger"> + <p> + ${activeCluster} is an invalid Helix cluster + </p> + </div> + </#if> + </div> + </div> + </div> + + <#include "common/js.ftl"> + <script src="/assets/js/resource-table.js"></script> + </body> +</html> http://git-wip-us.apache.org/repos/asf/helix/blob/6cbafef0/helix-ui/src/main/resources/org/apache/helix/ui/view/common/cluster-admin.ftl ---------------------------------------------------------------------- diff --git a/helix-ui/src/main/resources/org/apache/helix/ui/view/common/cluster-admin.ftl b/helix-ui/src/main/resources/org/apache/helix/ui/view/common/cluster-admin.ftl new file mode 100644 index 0000000..98360ea --- /dev/null +++ b/helix-ui/src/main/resources/org/apache/helix/ui/view/common/cluster-admin.ftl @@ -0,0 +1,5 @@ +<form id="cluster-admin-form" class="uk-form"> + <div class="uk-form-controls"> + <button id="drop-cluster-button" class="uk-button uk-button-danger">Drop Cluster</button> + </div> +</form> http://git-wip-us.apache.org/repos/asf/helix/blob/6cbafef0/helix-ui/src/main/resources/org/apache/helix/ui/view/common/config-table.ftl ---------------------------------------------------------------------- diff --git a/helix-ui/src/main/resources/org/apache/helix/ui/view/common/config-table.ftl b/helix-ui/src/main/resources/org/apache/helix/ui/view/common/config-table.ftl new file mode 100644 index 0000000..ff74742 --- /dev/null +++ b/helix-ui/src/main/resources/org/apache/helix/ui/view/common/config-table.ftl @@ -0,0 +1,24 @@ +<#if (configTable?size == 0)> + <div class="uk-alert"> + <p> + No Helix configuration available for ${activeResource!activeCluster} + </p> + </div> +<#else> + <table class="uk-table"> + <thead> + <tr> + <th>Name</th> + <th>Value</th> + </tr> + </thead> + <tbody> + <#list configTable as row> + <tr> + <td>${row.name}</td> + <td>${row.value}</td> + </tr> + </#list> + </tbody> + </table> +</#if> http://git-wip-us.apache.org/repos/asf/helix/blob/6cbafef0/helix-ui/src/main/resources/org/apache/helix/ui/view/common/css.ftl ---------------------------------------------------------------------- diff --git a/helix-ui/src/main/resources/org/apache/helix/ui/view/common/css.ftl b/helix-ui/src/main/resources/org/apache/helix/ui/view/common/css.ftl new file mode 100644 index 0000000..a212114 --- /dev/null +++ b/helix-ui/src/main/resources/org/apache/helix/ui/view/common/css.ftl @@ -0,0 +1,2 @@ +<link rel="stylesheet" href="/assets/css/uikit.almost-flat.min.css" /> +<link rel="stylesheet" href="/assets/css/app.css" /> http://git-wip-us.apache.org/repos/asf/helix/blob/6cbafef0/helix-ui/src/main/resources/org/apache/helix/ui/view/common/ideal-state-table.ftl ---------------------------------------------------------------------- diff --git a/helix-ui/src/main/resources/org/apache/helix/ui/view/common/ideal-state-table.ftl b/helix-ui/src/main/resources/org/apache/helix/ui/view/common/ideal-state-table.ftl new file mode 100644 index 0000000..05f608b --- /dev/null +++ b/helix-ui/src/main/resources/org/apache/helix/ui/view/common/ideal-state-table.ftl @@ -0,0 +1,34 @@ +<table class="uk-table"> + <tr> + <td class="ideal-state-prop">Partitions</td> + <td>${idealStateSpec.numPartitions}</td> + </tr> + <tr> + <td class="ideal-state-prop">Replicas</td> + <td>${idealStateSpec.replicas}</td> + </tr> + <#if (idealStateSpec.instanceGroupTag??)> + <tr> + <td class="ideal-state-prop">Tag</td> + <td>${idealStateSpec.instanceGroupTag}</td> + </tr> + </#if> + <tr> + <td class="ideal-state-prop">Rebalance Mode</td> + <td>${idealStateSpec.rebalanceMode}</td> + </tr> + <#if (idealStateSpec.rebalancerClassName??)> + <tr> + <td class="ideal-state-prop">Rebalancer Class</td> + <td>${idealStateSpec.rebalancerClassName}</td> + </tr> + </#if> + <tr> + <td class="ideal-state-prop">State Model</td> + <td>${idealStateSpec.stateModel}</td> + </tr> + <tr> + <td class="ideal-state-prop">Batch Messaging</td> + <td>${idealStateSpec.batchMessageMode?string("true", "false")}</td> + </tr> +</table> http://git-wip-us.apache.org/repos/asf/helix/blob/6cbafef0/helix-ui/src/main/resources/org/apache/helix/ui/view/common/instance-admin.ftl ---------------------------------------------------------------------- diff --git a/helix-ui/src/main/resources/org/apache/helix/ui/view/common/instance-admin.ftl b/helix-ui/src/main/resources/org/apache/helix/ui/view/common/instance-admin.ftl new file mode 100644 index 0000000..ae36f3b --- /dev/null +++ b/helix-ui/src/main/resources/org/apache/helix/ui/view/common/instance-admin.ftl @@ -0,0 +1,8 @@ +<form id="instance-admin-form" class="uk-form"> + <div class="uk-form-row"> + <div class="uk-form-controls"> + <input type="text" placeholder="localhost_8080" id="instance-name" /> + <button id="add-instance-button" class="uk-button uk-button-primary" cluster="${activeCluster}">Add</button> + </div> + </div> +</form> http://git-wip-us.apache.org/repos/asf/helix/blob/6cbafef0/helix-ui/src/main/resources/org/apache/helix/ui/view/common/instance-table.ftl ---------------------------------------------------------------------- diff --git a/helix-ui/src/main/resources/org/apache/helix/ui/view/common/instance-table.ftl b/helix-ui/src/main/resources/org/apache/helix/ui/view/common/instance-table.ftl new file mode 100644 index 0000000..bbfdb7d --- /dev/null +++ b/helix-ui/src/main/resources/org/apache/helix/ui/view/common/instance-table.ftl @@ -0,0 +1,38 @@ +<#if (instanceSpecs?size == 0)> + <div class="uk-alert"> + <p> + There are no instances assigned to ${activeResource!activeCluster} + </p> + </div> +<#else> + <table class="uk-table"> + <thead> + <tr> + <th>Instance</th> + <th>Enabled</th> + <th>Live</th> + <#if (adminMode)> + <th></th> + </#if> + </tr> + </thead> + <tbody> + <#list instanceSpecs as instanceSpec> + <tr class="${instanceSpec.enabled?string("instance-enabled", "instance-disabled")} ${instanceSpec.live?string("", "instance-down")}"> + <td>${instanceSpec.instanceName}</td> + <td>${instanceSpec.enabled?string("Yes", "No")}</td> + <td>${instanceSpec.live?string("Yes", "No")}</td> + <#if (adminMode)> + <td class="table-button"> + <div class="uk-button-group"> + <button class="uk-button enable-instance-button" cluster="${activeCluster}" instance="${instanceSpec.instanceName}">Enable</button> + <button class="uk-button disable-instance-button" cluster="${activeCluster}" instance="${instanceSpec.instanceName}">Disable</button> + <button class="uk-button uk-button-danger drop-instance-button" cluster="${activeCluster}" instance="${instanceSpec.instanceName}">Drop</button> + </div> + </td> + </#if> + </tr> + </#list> + </tbody> + </table> +</#if> http://git-wip-us.apache.org/repos/asf/helix/blob/6cbafef0/helix-ui/src/main/resources/org/apache/helix/ui/view/common/js.ftl ---------------------------------------------------------------------- diff --git a/helix-ui/src/main/resources/org/apache/helix/ui/view/common/js.ftl b/helix-ui/src/main/resources/org/apache/helix/ui/view/common/js.ftl new file mode 100644 index 0000000..680ad65 --- /dev/null +++ b/helix-ui/src/main/resources/org/apache/helix/ui/view/common/js.ftl @@ -0,0 +1,6 @@ +<script src="/assets/js/jquery-1.11.2.min.js"></script> +<script src="/assets/js/uikit.min.js"></script> +<script src="/assets/js/app.js"></script> +<script src="/assets/js/admin.js"></script> +<script src="/assets/js/d3.min.js"></script> +<script src="/assets/js/visualizer.js"></script> http://git-wip-us.apache.org/repos/asf/helix/blob/6cbafef0/helix-ui/src/main/resources/org/apache/helix/ui/view/common/resource-admin.ftl ---------------------------------------------------------------------- diff --git a/helix-ui/src/main/resources/org/apache/helix/ui/view/common/resource-admin.ftl b/helix-ui/src/main/resources/org/apache/helix/ui/view/common/resource-admin.ftl new file mode 100644 index 0000000..d191e8e --- /dev/null +++ b/helix-ui/src/main/resources/org/apache/helix/ui/view/common/resource-admin.ftl @@ -0,0 +1,39 @@ +<form id="resource-add-form" class="uk-form uk-form-horizontal"> + <div class="uk-form-row"> + <span class="uk-form-label">Name</span> + <input type="text" placeholder="MyResource" id="resource-name" /> + </div> + + <div class="uk-form-row"> + <span class="uk-form-label">Partitions</span> + <input id="resource-partitions" type="number"/> + </div> + + <div class="uk-form-row"> + <span class="uk-form-label">Replicas</span> + <input id="resource-replicas" type="number"/> + </div> + + <div class="uk-form-row"> + <span class="uk-form-label">State Model</span> + <select id="resource-state-model"> + <#list stateModels as stateModel> + <option>${stateModel}</option> + </#list> + </select> + </div> + + <div class="uk-form-row"> + <span class="uk-form-label">Rebalance Mode</span> + <select id="resource-rebalance-mode"> + <#list rebalanceModes as rebalanceMode> + <option>${rebalanceMode}</option> + </#list> + </select> + </div> + + <div class="uk-form-row"> + <span class="uk-form-label"></span> + <button id="add-resource-button" class="uk-button uk-button-primary" cluster="${activeCluster}">Add</button> + </div> +</form> http://git-wip-us.apache.org/repos/asf/helix/blob/6cbafef0/helix-ui/src/main/resources/org/apache/helix/ui/view/common/resource-state-table.ftl ---------------------------------------------------------------------- diff --git a/helix-ui/src/main/resources/org/apache/helix/ui/view/common/resource-state-table.ftl b/helix-ui/src/main/resources/org/apache/helix/ui/view/common/resource-state-table.ftl new file mode 100644 index 0000000..acba7a9 --- /dev/null +++ b/helix-ui/src/main/resources/org/apache/helix/ui/view/common/resource-state-table.ftl @@ -0,0 +1,35 @@ +<#if (resourceStateTable?size == 0)> + <div class="uk-alert uk-alert-warning"> + <p> + No partitions of ${activeResource} are assigned! + </p> + </div> +<#else> + <div class="filter-area"> + <p> + <i>Filter</i> <button id="filter-add" class="uk-button uk-button-mini">+</button> + </p> + <form id="filter-form" class="uk-form"></form> + </div> + + <table class="uk-table" id="resource-state-table"> + <thead> + <tr> + <th>Partition</th> + <th>Instance</th> + <th>Ideal</th> + <th>External</th> + </tr> + </thead> + <tbody> + <#list resourceStateTable as row> + <tr class="${(row.ideal == row.external)?string("state-ok", "state-warn")} ${(row.external == "ERROR")?string("state-error", "")}"> + <td>${row.partitionName}</td> + <td>${row.instanceName}</td> + <td>${row.ideal}</td> + <td>${row.external}</td> + </tr> + </#list> + </tbody> + </table> +</#if> http://git-wip-us.apache.org/repos/asf/helix/blob/6cbafef0/helix-ui/src/main/resources/org/apache/helix/ui/view/common/resource-table.ftl ---------------------------------------------------------------------- diff --git a/helix-ui/src/main/resources/org/apache/helix/ui/view/common/resource-table.ftl b/helix-ui/src/main/resources/org/apache/helix/ui/view/common/resource-table.ftl new file mode 100644 index 0000000..b7118d4 --- /dev/null +++ b/helix-ui/src/main/resources/org/apache/helix/ui/view/common/resource-table.ftl @@ -0,0 +1,35 @@ +<#if (activeClusterResources?size == 0)> + <div class="uk-alert"> + <p> + There are no resources in ${activeCluster} + </p> + </div> +<#else> + <div class="filter-area"> + <p> + <i>Filter</i> <button id="resource-filter-add" class="uk-button uk-button-mini">+</button> + </p> + <form id="resource-filter-form" class="uk-form"></form> + </div> + + <table class="uk-table" id="resource-table"> + <thead> + <th>Name</th> + <#if (adminMode)> + <th></th> + </#if> + </thead> + <tbody> + <#list activeClusterResources as resource> + <tr> + <td><a href="/dashboard/${zkAddress}/${activeCluster}/${resource}">${resource}</a></td> + <#if (adminMode)> + <td class="table-button"> + <button class="uk-button uk-button-danger drop-resource-button" cluster="${activeCluster}" resource="${resource}">Drop</button> + </td> + </#if> + </tr> + </#list> + </tbody> + </table> +</#if> http://git-wip-us.apache.org/repos/asf/helix/blob/6cbafef0/helix-ui/src/main/resources/org/apache/helix/ui/view/common/resource-visualizer.ftl ---------------------------------------------------------------------- diff --git a/helix-ui/src/main/resources/org/apache/helix/ui/view/common/resource-visualizer.ftl b/helix-ui/src/main/resources/org/apache/helix/ui/view/common/resource-visualizer.ftl new file mode 100644 index 0000000..26468ce --- /dev/null +++ b/helix-ui/src/main/resources/org/apache/helix/ui/view/common/resource-visualizer.ftl @@ -0,0 +1,10 @@ +<style> + +text { + font: 12px sans-serif; +} + +</style> + +<div id="resource-visualizer"></div> +<div id="visualizer-data-uri" style="display: none">/visualizer/${zkAddress}/${activeCluster}/${activeResource}</div> http://git-wip-us.apache.org/repos/asf/helix/blob/6cbafef0/helix-ui/src/main/resources/org/apache/helix/ui/view/common/side-nav.ftl ---------------------------------------------------------------------- diff --git a/helix-ui/src/main/resources/org/apache/helix/ui/view/common/side-nav.ftl b/helix-ui/src/main/resources/org/apache/helix/ui/view/common/side-nav.ftl new file mode 100644 index 0000000..1002d0a --- /dev/null +++ b/helix-ui/src/main/resources/org/apache/helix/ui/view/common/side-nav.ftl @@ -0,0 +1,21 @@ +<!-- Side nav (clusters) --> +<div class="uk-panel uk-panel-box"> + <h3 id="panel-helix-logo" class="uk-panel-title"> + <a href="/dashboard"> + <img src="/assets/img/helix-logo.png" alt="Helix"/> + </a> + </h3> + + <ul class="uk-nav uk-nav-side"> + <#list clusters as cluster> + <li class="${(cluster == activeCluster)?string("uk-active", "")}"><a href="/dashboard/${zkAddress}/${cluster}">${cluster}</a></li> + </#list> + </ul> + + <#if (adminMode)> + <form id="add-cluster-form" class="uk-form"> + <input type="text" placeholder="CLUSTER_NAME"/> + <button class="uk-button">Add</button> + </form> + </#if> +</div> http://git-wip-us.apache.org/repos/asf/helix/blob/6cbafef0/helix-ui/src/main/resources/org/apache/helix/ui/view/landing-view.ftl ---------------------------------------------------------------------- diff --git a/helix-ui/src/main/resources/org/apache/helix/ui/view/landing-view.ftl b/helix-ui/src/main/resources/org/apache/helix/ui/view/landing-view.ftl new file mode 100644 index 0000000..d4f3b42 --- /dev/null +++ b/helix-ui/src/main/resources/org/apache/helix/ui/view/landing-view.ftl @@ -0,0 +1,21 @@ +<!DOCTYPE html> +<html> + <head> + <title>Helix</title> + <meta charset="UTF-8"> + <#include "common/css.ftl"> + </head> + + <body> + <div id="landing-area"> + <img src="/assets/img/helix-logo.png"> + <form id="landing-form" class="uk-form"> + <input id="zk-address" type="text" placeholder="ZooKeeper Address (e.g. localhost:2181)"/> + <button id="landing-form-button" class="uk-button">Go</button> + </form> + </div> + + <#include "common/js.ftl"> + <script src="/assets/js/landing-view.js"></script> + </body> +</html> http://git-wip-us.apache.org/repos/asf/helix/blob/6cbafef0/helix-ui/src/main/resources/org/apache/helix/ui/view/resource-view.ftl ---------------------------------------------------------------------- diff --git a/helix-ui/src/main/resources/org/apache/helix/ui/view/resource-view.ftl b/helix-ui/src/main/resources/org/apache/helix/ui/view/resource-view.ftl new file mode 100644 index 0000000..dcfb8bc --- /dev/null +++ b/helix-ui/src/main/resources/org/apache/helix/ui/view/resource-view.ftl @@ -0,0 +1,49 @@ +<!DOCTYPE html> +<html> + <head> + <title>${zkAddress}</title> + <meta charset="UTF-8"> + <#include "common/css.ftl"> + </head> + + <body> + + <div class="uk-grid"> + <div class="uk-width-medium-2-10"> + <#include "common/side-nav.ftl"> + </div> + + <div class="uk-width-medium-8-10"> + <div id="cluster-views-area"> + <#if (activeValid)> + <h1><a href="/dashboard/${zkAddress}/${activeCluster}">${activeCluster}</a> / ${activeResource}</h1> + + <ul id="switcher-tabs" class="uk-subnav uk-subnav-pill" data-uk-switcher="{connect: '#switcher'}"> + <li><a href="">Partitions</a></li> + <li><a href="">Visualizer</a></li> + <li><a href="">Config</a></li> + </ul> + + <ul id="switcher" class="uk-switcher"> + <li><#include "common/resource-state-table.ftl"></li> + <li><#include "common/resource-visualizer.ftl"></li> + <li> + <#include "common/ideal-state-table.ftl"> + <#include "common/config-table.ftl"> + </li> + </ul> + <#else> + <div class="uk-alert uk-alert-danger"> + <p> + ${activeCluster} is an invalid Helix cluster + </p> + </div> + </#if> + </div> + </div> + </div> + + <#include "common/js.ftl"> + <script src="/assets/js/resource-state-table.js"></script> + </body> +</html> http://git-wip-us.apache.org/repos/asf/helix/blob/6cbafef0/pom.xml ---------------------------------------------------------------------- diff --git a/pom.xml b/pom.xml index 06a18a5..c4cb615 100644 --- a/pom.xml +++ b/pom.xml @@ -200,6 +200,7 @@ under the License. <module>helix-provisioning</module> <module>helix-examples</module> <module>helix-ipc</module> + <module>helix-ui</module> <module>recipes</module> </modules>
