http://git-wip-us.apache.org/repos/asf/ambari/blob/529ef7f7/contrib/views/storm/src/main/resources/libs/require-js/js/require.min.js ---------------------------------------------------------------------- diff --git a/contrib/views/storm/src/main/resources/libs/require-js/js/require.min.js b/contrib/views/storm/src/main/resources/libs/require-js/js/require.min.js new file mode 100644 index 0000000..a6d55d5 --- /dev/null +++ b/contrib/views/storm/src/main/resources/libs/require-js/js/require.min.js @@ -0,0 +1,36 @@ +/* + RequireJS 2.2.0 Copyright jQuery Foundation and other contributors. + Released under MIT license, http://github.com/requirejs/requirejs/LICENSE +*/ +var requirejs,require,define; +(function(ga){function ka(b,c,d,g){return g||""}function K(b){return"[object Function]"===Q.call(b)}function L(b){return"[object Array]"===Q.call(b)}function y(b,c){if(b){var d;for(d=0;d<b.length&&(!b[d]||!c(b[d],d,b));d+=1);}}function X(b,c){if(b){var d;for(d=b.length-1;-1<d&&(!b[d]||!c(b[d],d,b));--d);}}function x(b,c){return la.call(b,c)}function e(b,c){return x(b,c)&&b[c]}function D(b,c){for(var d in b)if(x(b,d)&&c(b[d],d))break}function Y(b,c,d,g){c&&D(c,function(c,e){if(d||!x(b,e))!g||"object"!== +typeof c||!c||L(c)||K(c)||c instanceof RegExp?b[e]=c:(b[e]||(b[e]={}),Y(b[e],c,d,g))});return b}function z(b,c){return function(){return c.apply(b,arguments)}}function ha(b){throw b;}function ia(b){if(!b)return b;var c=ga;y(b.split("."),function(b){c=c[b]});return c}function F(b,c,d,g){c=Error(c+"\nhttp://requirejs.org/docs/errors.html#"+b);c.requireType=b;c.requireModules=g;d&&(c.originalError=d);return c}function ma(b){function c(a,n,b){var h,k,f,c,d,l,g,r;n=n&&n.split("/");var q=p.map,m=q&&q["*"]; +if(a){a=a.split("/");k=a.length-1;p.nodeIdCompat&&U.test(a[k])&&(a[k]=a[k].replace(U,""));"."===a[0].charAt(0)&&n&&(k=n.slice(0,n.length-1),a=k.concat(a));k=a;for(f=0;f<k.length;f++)c=k[f],"."===c?(k.splice(f,1),--f):".."===c&&0!==f&&(1!==f||".."!==k[2])&&".."!==k[f-1]&&0<f&&(k.splice(f-1,2),f-=2);a=a.join("/")}if(b&&q&&(n||m)){k=a.split("/");f=k.length;a:for(;0<f;--f){d=k.slice(0,f).join("/");if(n)for(c=n.length;0<c;--c)if(b=e(q,n.slice(0,c).join("/")))if(b=e(b,d)){h=b;l=f;break a}!g&&m&&e(m,d)&& +(g=e(m,d),r=f)}!h&&g&&(h=g,l=r);h&&(k.splice(0,l,h),a=k.join("/"))}return(h=e(p.pkgs,a))?h:a}function d(a){E&&y(document.getElementsByTagName("script"),function(n){if(n.getAttribute("data-requiremodule")===a&&n.getAttribute("data-requirecontext")===l.contextName)return n.parentNode.removeChild(n),!0})}function m(a){var n=e(p.paths,a);if(n&&L(n)&&1<n.length)return n.shift(),l.require.undef(a),l.makeRequire(null,{skipMap:!0})([a]),!0}function r(a){var n,b=a?a.indexOf("!"):-1;-1<b&&(n=a.substring(0, +b),a=a.substring(b+1,a.length));return[n,a]}function q(a,n,b,h){var k,f,d=null,g=n?n.name:null,p=a,q=!0,m="";a||(q=!1,a="_@r"+(Q+=1));a=r(a);d=a[0];a=a[1];d&&(d=c(d,g,h),f=e(v,d));a&&(d?m=f&&f.normalize?f.normalize(a,function(a){return c(a,g,h)}):-1===a.indexOf("!")?c(a,g,h):a:(m=c(a,g,h),a=r(m),d=a[0],m=a[1],b=!0,k=l.nameToUrl(m)));b=!d||f||b?"":"_unnormalized"+(T+=1);return{prefix:d,name:m,parentMap:n,unnormalized:!!b,url:k,originalName:p,isDefine:q,id:(d?d+"!"+m:m)+b}}function u(a){var b=a.id, +c=e(t,b);c||(c=t[b]=new l.Module(a));return c}function w(a,b,c){var h=a.id,k=e(t,h);if(!x(v,h)||k&&!k.defineEmitComplete)if(k=u(a),k.error&&"error"===b)c(k.error);else k.on(b,c);else"defined"===b&&c(v[h])}function A(a,b){var c=a.requireModules,h=!1;if(b)b(a);else if(y(c,function(b){if(b=e(t,b))b.error=a,b.events.error&&(h=!0,b.emit("error",a))}),!h)g.onError(a)}function B(){V.length&&(y(V,function(a){var b=a[0];"string"===typeof b&&(l.defQueueMap[b]=!0);G.push(a)}),V=[])}function C(a){delete t[a]; +delete Z[a]}function J(a,b,c){var h=a.map.id;a.error?a.emit("error",a.error):(b[h]=!0,y(a.depMaps,function(h,f){var d=h.id,g=e(t,d);!g||a.depMatched[f]||c[d]||(e(b,d)?(a.defineDep(f,v[d]),a.check()):J(g,b,c))}),c[h]=!0)}function H(){var a,b,c=(a=1E3*p.waitSeconds)&&l.startTime+a<(new Date).getTime(),h=[],k=[],f=!1,g=!0;if(!aa){aa=!0;D(Z,function(a){var l=a.map,e=l.id;if(a.enabled&&(l.isDefine||k.push(a),!a.error))if(!a.inited&&c)m(e)?f=b=!0:(h.push(e),d(e));else if(!a.inited&&a.fetched&&l.isDefine&& +(f=!0,!l.prefix))return g=!1});if(c&&h.length)return a=F("timeout","Load timeout for modules: "+h,null,h),a.contextName=l.contextName,A(a);g&&y(k,function(a){J(a,{},{})});c&&!b||!f||!E&&!ja||ba||(ba=setTimeout(function(){ba=0;H()},50));aa=!1}}function I(a){x(v,a[0])||u(q(a[0],null,!0)).init(a[1],a[2])}function O(a){a=a.currentTarget||a.srcElement;var b=l.onScriptLoad;a.detachEvent&&!ca?a.detachEvent("onreadystatechange",b):a.removeEventListener("load",b,!1);b=l.onScriptError;a.detachEvent&&!ca||a.removeEventListener("error", +b,!1);return{node:a,id:a&&a.getAttribute("data-requiremodule")}}function P(){var a;for(B();G.length;){a=G.shift();if(null===a[0])return A(F("mismatch","Mismatched anonymous define() module: "+a[a.length-1]));I(a)}l.defQueueMap={}}var aa,da,l,R,ba,p={waitSeconds:7,baseUrl:"./",paths:{},bundles:{},pkgs:{},shim:{},config:{}},t={},Z={},ea={},G=[],v={},W={},fa={},Q=1,T=1;R={require:function(a){return a.require?a.require:a.require=l.makeRequire(a.map)},exports:function(a){a.usingExports=!0;if(a.map.isDefine)return a.exports? +v[a.map.id]=a.exports:a.exports=v[a.map.id]={}},module:function(a){return a.module?a.module:a.module={id:a.map.id,uri:a.map.url,config:function(){return e(p.config,a.map.id)||{}},exports:a.exports||(a.exports={})}}};da=function(a){this.events=e(ea,a.id)||{};this.map=a;this.shim=e(p.shim,a.id);this.depExports=[];this.depMaps=[];this.depMatched=[];this.pluginMaps={};this.depCount=0};da.prototype={init:function(a,b,c,h){h=h||{};if(!this.inited){this.factory=b;if(c)this.on("error",c);else this.events.error&& +(c=z(this,function(a){this.emit("error",a)}));this.depMaps=a&&a.slice(0);this.errback=c;this.inited=!0;this.ignore=h.ignore;h.enabled||this.enabled?this.enable():this.check()}},defineDep:function(a,b){this.depMatched[a]||(this.depMatched[a]=!0,--this.depCount,this.depExports[a]=b)},fetch:function(){if(!this.fetched){this.fetched=!0;l.startTime=(new Date).getTime();var a=this.map;if(this.shim)l.makeRequire(this.map,{enableBuildCallback:!0})(this.shim.deps||[],z(this,function(){return a.prefix?this.callPlugin(): +this.load()}));else return a.prefix?this.callPlugin():this.load()}},load:function(){var a=this.map.url;W[a]||(W[a]=!0,l.load(this.map.id,a))},check:function(){if(this.enabled&&!this.enabling){var a,b,c=this.map.id;b=this.depExports;var h=this.exports,k=this.factory;if(!this.inited)x(l.defQueueMap,c)||this.fetch();else if(this.error)this.emit("error",this.error);else if(!this.defining){this.defining=!0;if(1>this.depCount&&!this.defined){if(K(k)){if(this.events.error&&this.map.isDefine||g.onError!== +ha)try{h=l.execCb(c,k,b,h)}catch(d){a=d}else h=l.execCb(c,k,b,h);this.map.isDefine&&void 0===h&&((b=this.module)?h=b.exports:this.usingExports&&(h=this.exports));if(a)return a.requireMap=this.map,a.requireModules=this.map.isDefine?[this.map.id]:null,a.requireType=this.map.isDefine?"define":"require",A(this.error=a)}else h=k;this.exports=h;if(this.map.isDefine&&!this.ignore&&(v[c]=h,g.onResourceLoad)){var f=[];y(this.depMaps,function(a){f.push(a.normalizedMap||a)});g.onResourceLoad(l,this.map,f)}C(c); +this.defined=!0}this.defining=!1;this.defined&&!this.defineEmitted&&(this.defineEmitted=!0,this.emit("defined",this.exports),this.defineEmitComplete=!0)}}},callPlugin:function(){var a=this.map,b=a.id,d=q(a.prefix);this.depMaps.push(d);w(d,"defined",z(this,function(h){var k,f,d=e(fa,this.map.id),M=this.map.name,r=this.map.parentMap?this.map.parentMap.name:null,m=l.makeRequire(a.parentMap,{enableBuildCallback:!0});if(this.map.unnormalized){if(h.normalize&&(M=h.normalize(M,function(a){return c(a,r,!0)})|| +""),f=q(a.prefix+"!"+M,this.map.parentMap),w(f,"defined",z(this,function(a){this.map.normalizedMap=f;this.init([],function(){return a},null,{enabled:!0,ignore:!0})})),h=e(t,f.id)){this.depMaps.push(f);if(this.events.error)h.on("error",z(this,function(a){this.emit("error",a)}));h.enable()}}else d?(this.map.url=l.nameToUrl(d),this.load()):(k=z(this,function(a){this.init([],function(){return a},null,{enabled:!0})}),k.error=z(this,function(a){this.inited=!0;this.error=a;a.requireModules=[b];D(t,function(a){0=== +a.map.id.indexOf(b+"_unnormalized")&&C(a.map.id)});A(a)}),k.fromText=z(this,function(h,c){var d=a.name,f=q(d),M=S;c&&(h=c);M&&(S=!1);u(f);x(p.config,b)&&(p.config[d]=p.config[b]);try{g.exec(h)}catch(e){return A(F("fromtexteval","fromText eval for "+b+" failed: "+e,e,[b]))}M&&(S=!0);this.depMaps.push(f);l.completeLoad(d);m([d],k)}),h.load(a.name,m,k,p))}));l.enable(d,this);this.pluginMaps[d.id]=d},enable:function(){Z[this.map.id]=this;this.enabling=this.enabled=!0;y(this.depMaps,z(this,function(a, +b){var c,h;if("string"===typeof a){a=q(a,this.map.isDefine?this.map:this.map.parentMap,!1,!this.skipMap);this.depMaps[b]=a;if(c=e(R,a.id)){this.depExports[b]=c(this);return}this.depCount+=1;w(a,"defined",z(this,function(a){this.undefed||(this.defineDep(b,a),this.check())}));this.errback?w(a,"error",z(this,this.errback)):this.events.error&&w(a,"error",z(this,function(a){this.emit("error",a)}))}c=a.id;h=t[c];x(R,c)||!h||h.enabled||l.enable(a,this)}));D(this.pluginMaps,z(this,function(a){var b=e(t,a.id); +b&&!b.enabled&&l.enable(a,this)}));this.enabling=!1;this.check()},on:function(a,b){var c=this.events[a];c||(c=this.events[a]=[]);c.push(b)},emit:function(a,b){y(this.events[a],function(a){a(b)});"error"===a&&delete this.events[a]}};l={config:p,contextName:b,registry:t,defined:v,urlFetched:W,defQueue:G,defQueueMap:{},Module:da,makeModuleMap:q,nextTick:g.nextTick,onError:A,configure:function(a){a.baseUrl&&"/"!==a.baseUrl.charAt(a.baseUrl.length-1)&&(a.baseUrl+="/");if("string"===typeof a.urlArgs){var b= +a.urlArgs;a.urlArgs=function(a,c){return(-1===c.indexOf("?")?"?":"&")+b}}var c=p.shim,h={paths:!0,bundles:!0,config:!0,map:!0};D(a,function(a,b){h[b]?(p[b]||(p[b]={}),Y(p[b],a,!0,!0)):p[b]=a});a.bundles&&D(a.bundles,function(a,b){y(a,function(a){a!==b&&(fa[a]=b)})});a.shim&&(D(a.shim,function(a,b){L(a)&&(a={deps:a});!a.exports&&!a.init||a.exportsFn||(a.exportsFn=l.makeShimExports(a));c[b]=a}),p.shim=c);a.packages&&y(a.packages,function(a){var b;a="string"===typeof a?{name:a}:a;b=a.name;a.location&& +(p.paths[b]=a.location);p.pkgs[b]=a.name+"/"+(a.main||"main").replace(na,"").replace(U,"")});D(t,function(a,b){a.inited||a.map.unnormalized||(a.map=q(b,null,!0))});(a.deps||a.callback)&&l.require(a.deps||[],a.callback)},makeShimExports:function(a){return function(){var b;a.init&&(b=a.init.apply(ga,arguments));return b||a.exports&&ia(a.exports)}},makeRequire:function(a,n){function m(c,d,f){var e,r;n.enableBuildCallback&&d&&K(d)&&(d.__requireJsBuild=!0);if("string"===typeof c){if(K(d))return A(F("requireargs", +"Invalid require call"),f);if(a&&x(R,c))return R[c](t[a.id]);if(g.get)return g.get(l,c,a,m);e=q(c,a,!1,!0);e=e.id;return x(v,e)?v[e]:A(F("notloaded",'Module name "'+e+'" has not been loaded yet for context: '+b+(a?"":". Use require([])")))}P();l.nextTick(function(){P();r=u(q(null,a));r.skipMap=n.skipMap;r.init(c,d,f,{enabled:!0});H()});return m}n=n||{};Y(m,{isBrowser:E,toUrl:function(b){var d,f=b.lastIndexOf("."),g=b.split("/")[0];-1!==f&&("."!==g&&".."!==g||1<f)&&(d=b.substring(f,b.length),b=b.substring(0, +f));return l.nameToUrl(c(b,a&&a.id,!0),d,!0)},defined:function(b){return x(v,q(b,a,!1,!0).id)},specified:function(b){b=q(b,a,!1,!0).id;return x(v,b)||x(t,b)}});a||(m.undef=function(b){B();var c=q(b,a,!0),f=e(t,b);f.undefed=!0;d(b);delete v[b];delete W[c.url];delete ea[b];X(G,function(a,c){a[0]===b&&G.splice(c,1)});delete l.defQueueMap[b];f&&(f.events.defined&&(ea[b]=f.events),C(b))});return m},enable:function(a){e(t,a.id)&&u(a).enable()},completeLoad:function(a){var b,c,d=e(p.shim,a)||{},g=d.exports; +for(B();G.length;){c=G.shift();if(null===c[0]){c[0]=a;if(b)break;b=!0}else c[0]===a&&(b=!0);I(c)}l.defQueueMap={};c=e(t,a);if(!b&&!x(v,a)&&c&&!c.inited)if(!p.enforceDefine||g&&ia(g))I([a,d.deps||[],d.exportsFn]);else return m(a)?void 0:A(F("nodefine","No define call for "+a,null,[a]));H()},nameToUrl:function(a,b,c){var d,k,f,m;(d=e(p.pkgs,a))&&(a=d);if(d=e(fa,a))return l.nameToUrl(d,b,c);if(g.jsExtRegExp.test(a))d=a+(b||"");else{d=p.paths;k=a.split("/");for(f=k.length;0<f;--f)if(m=k.slice(0,f).join("/"), +m=e(d,m)){L(m)&&(m=m[0]);k.splice(0,f,m);break}d=k.join("/");d+=b||(/^data\:|^blob\:|\?/.test(d)||c?"":".js");d=("/"===d.charAt(0)||d.match(/^[\w\+\.\-]+:/)?"":p.baseUrl)+d}return p.urlArgs&&!/^blob\:/.test(d)?d+p.urlArgs(a,d):d},load:function(a,b){g.load(l,a,b)},execCb:function(a,b,c,d){return b.apply(d,c)},onScriptLoad:function(a){if("load"===a.type||oa.test((a.currentTarget||a.srcElement).readyState))N=null,a=O(a),l.completeLoad(a.id)},onScriptError:function(a){var b=O(a);if(!m(b.id)){var c=[]; +D(t,function(a,d){0!==d.indexOf("_@r")&&y(a.depMaps,function(a){if(a.id===b.id)return c.push(d),!0})});return A(F("scripterror",'Script error for "'+b.id+(c.length?'", needed by: '+c.join(", "):'"'),a,[b.id]))}}};l.require=l.makeRequire();return l}function pa(){if(N&&"interactive"===N.readyState)return N;X(document.getElementsByTagName("script"),function(b){if("interactive"===b.readyState)return N=b});return N}var g,B,C,H,O,I,N,P,u,T,qa=/(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg,ra=/[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g, +U=/\.js$/,na=/^\.\//;B=Object.prototype;var Q=B.toString,la=B.hasOwnProperty,E=!("undefined"===typeof window||"undefined"===typeof navigator||!window.document),ja=!E&&"undefined"!==typeof importScripts,oa=E&&"PLAYSTATION 3"===navigator.platform?/^complete$/:/^(complete|loaded)$/,ca="undefined"!==typeof opera&&"[object Opera]"===opera.toString(),J={},w={},V=[],S=!1;if("undefined"===typeof define){if("undefined"!==typeof requirejs){if(K(requirejs))return;w=requirejs;requirejs=void 0}"undefined"===typeof require|| +K(require)||(w=require,require=void 0);g=requirejs=function(b,c,d,m){var r,q="_";L(b)||"string"===typeof b||(r=b,L(c)?(b=c,c=d,d=m):b=[]);r&&r.context&&(q=r.context);(m=e(J,q))||(m=J[q]=g.s.newContext(q));r&&m.configure(r);return m.require(b,c,d)};g.config=function(b){return g(b)};g.nextTick="undefined"!==typeof setTimeout?function(b){setTimeout(b,4)}:function(b){b()};require||(require=g);g.version="2.2.0";g.jsExtRegExp=/^\/|:|\?|\.js$/;g.isBrowser=E;B=g.s={contexts:J,newContext:ma};g({});y(["toUrl", +"undef","defined","specified"],function(b){g[b]=function(){var c=J._;return c.require[b].apply(c,arguments)}});E&&(C=B.head=document.getElementsByTagName("head")[0],H=document.getElementsByTagName("base")[0])&&(C=B.head=H.parentNode);g.onError=ha;g.createNode=function(b,c,d){c=b.xhtml?document.createElementNS("http://www.w3.org/1999/xhtml","html:script"):document.createElement("script");c.type=b.scriptType||"text/javascript";c.charset="utf-8";c.async=!0;return c};g.load=function(b,c,d){var m=b&&b.config|| +{},e;if(E){e=g.createNode(m,c,d);e.setAttribute("data-requirecontext",b.contextName);e.setAttribute("data-requiremodule",c);!e.attachEvent||e.attachEvent.toString&&0>e.attachEvent.toString().indexOf("[native code")||ca?(e.addEventListener("load",b.onScriptLoad,!1),e.addEventListener("error",b.onScriptError,!1)):(S=!0,e.attachEvent("onreadystatechange",b.onScriptLoad));e.src=d;if(m.onNodeCreated)m.onNodeCreated(e,m,c,d);P=e;H?C.insertBefore(e,H):C.appendChild(e);P=null;return e}if(ja)try{setTimeout(function(){}, +0),importScripts(d),b.completeLoad(c)}catch(q){b.onError(F("importscripts","importScripts failed for "+c+" at "+d,q,[c]))}};E&&!w.skipDataMain&&X(document.getElementsByTagName("script"),function(b){C||(C=b.parentNode);if(O=b.getAttribute("data-main"))return u=O,w.baseUrl||-1!==u.indexOf("!")||(I=u.split("/"),u=I.pop(),T=I.length?I.join("/")+"/":"./",w.baseUrl=T),u=u.replace(U,""),g.jsExtRegExp.test(u)&&(u=O),w.deps=w.deps?w.deps.concat(u):[u],!0});define=function(b,c,d){var e,g;"string"!==typeof b&& +(d=c,c=b,b=null);L(c)||(d=c,c=null);!c&&K(d)&&(c=[],d.length&&(d.toString().replace(qa,ka).replace(ra,function(b,d){c.push(d)}),c=(1===d.length?["require"]:["require","exports","module"]).concat(c)));S&&(e=P||pa())&&(b||(b=e.getAttribute("data-requiremodule")),g=J[e.getAttribute("data-requirecontext")]);g?(g.defQueue.push([b,c,d]),g.defQueueMap[b]=!0):V.push([b,c,d])};define.amd={jQuery:!0};g.exec=function(b){return eval(b)};g(w)}})(this); \ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/529ef7f7/contrib/views/storm/src/main/resources/libs/require-text/js/text.js ---------------------------------------------------------------------- diff --git a/contrib/views/storm/src/main/resources/libs/require-text/js/text.js b/contrib/views/storm/src/main/resources/libs/require-text/js/text.js new file mode 100644 index 0000000..49e242c --- /dev/null +++ b/contrib/views/storm/src/main/resources/libs/require-text/js/text.js @@ -0,0 +1,390 @@ +/** + * @license RequireJS text 2.0.12 Copyright (c) 2010-2014, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/requirejs/text for details + */ +/*jslint regexp: true */ +/*global require, XMLHttpRequest, ActiveXObject, + define, window, process, Packages, + java, location, Components, FileUtils */ + +define(['module'], function (module) { + 'use strict'; + + var text, fs, Cc, Ci, xpcIsWindows, + progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'], + xmlRegExp = /^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im, + bodyRegExp = /<body[^>]*>\s*([\s\S]+)\s*<\/body>/im, + hasLocation = typeof location !== 'undefined' && location.href, + defaultProtocol = hasLocation && location.protocol && location.protocol.replace(/\:/, ''), + defaultHostName = hasLocation && location.hostname, + defaultPort = hasLocation && (location.port || undefined), + buildMap = {}, + masterConfig = (module.config && module.config()) || {}; + + text = { + version: '2.0.12', + + strip: function (content) { + //Strips <?xml ...?> declarations so that external SVG and XML + //documents can be added to a document without worry. Also, if the string + //is an HTML document, only the part inside the body tag is returned. + if (content) { + content = content.replace(xmlRegExp, ""); + var matches = content.match(bodyRegExp); + if (matches) { + content = matches[1]; + } + } else { + content = ""; + } + return content; + }, + + jsEscape: function (content) { + return content.replace(/(['\\])/g, '\\$1') + .replace(/[\f]/g, "\\f") + .replace(/[\b]/g, "\\b") + .replace(/[\n]/g, "\\n") + .replace(/[\t]/g, "\\t") + .replace(/[\r]/g, "\\r") + .replace(/[\u2028]/g, "\\u2028") + .replace(/[\u2029]/g, "\\u2029"); + }, + + createXhr: masterConfig.createXhr || function () { + //Would love to dump the ActiveX crap in here. Need IE 6 to die first. + var xhr, i, progId; + if (typeof XMLHttpRequest !== "undefined") { + return new XMLHttpRequest(); + } else if (typeof ActiveXObject !== "undefined") { + for (i = 0; i < 3; i += 1) { + progId = progIds[i]; + try { + xhr = new ActiveXObject(progId); + } catch (e) {} + + if (xhr) { + progIds = [progId]; // so faster next time + break; + } + } + } + + return xhr; + }, + + /** + * Parses a resource name into its component parts. Resource names + * look like: module/name.ext!strip, where the !strip part is + * optional. + * @param {String} name the resource name + * @returns {Object} with properties "moduleName", "ext" and "strip" + * where strip is a boolean. + */ + parseName: function (name) { + var modName, ext, temp, + strip = false, + index = name.indexOf("."), + isRelative = name.indexOf('./') === 0 || + name.indexOf('../') === 0; + + if (index !== -1 && (!isRelative || index > 1)) { + modName = name.substring(0, index); + ext = name.substring(index + 1, name.length); + } else { + modName = name; + } + + temp = ext || modName; + index = temp.indexOf("!"); + if (index !== -1) { + //Pull off the strip arg. + strip = temp.substring(index + 1) === "strip"; + temp = temp.substring(0, index); + if (ext) { + ext = temp; + } else { + modName = temp; + } + } + + return { + moduleName: modName, + ext: ext, + strip: strip + }; + }, + + xdRegExp: /^((\w+)\:)?\/\/([^\/\\]+)/, + + /** + * Is an URL on another domain. Only works for browser use, returns + * false in non-browser environments. Only used to know if an + * optimized .js version of a text resource should be loaded + * instead. + * @param {String} url + * @returns Boolean + */ + useXhr: function (url, protocol, hostname, port) { + var uProtocol, uHostName, uPort, + match = text.xdRegExp.exec(url); + if (!match) { + return true; + } + uProtocol = match[2]; + uHostName = match[3]; + + uHostName = uHostName.split(':'); + uPort = uHostName[1]; + uHostName = uHostName[0]; + + return (!uProtocol || uProtocol === protocol) && + (!uHostName || uHostName.toLowerCase() === hostname.toLowerCase()) && + ((!uPort && !uHostName) || uPort === port); + }, + + finishLoad: function (name, strip, content, onLoad) { + content = strip ? text.strip(content) : content; + if (masterConfig.isBuild) { + buildMap[name] = content; + } + onLoad(content); + }, + + load: function (name, req, onLoad, config) { + //Name has format: some.module.filext!strip + //The strip part is optional. + //if strip is present, then that means only get the string contents + //inside a body tag in an HTML string. For XML/SVG content it means + //removing the <?xml ...?> declarations so the content can be inserted + //into the current doc without problems. + + // Do not bother with the work if a build and text will + // not be inlined. + if (config && config.isBuild && !config.inlineText) { + onLoad(); + return; + } + + masterConfig.isBuild = config && config.isBuild; + + var parsed = text.parseName(name), + nonStripName = parsed.moduleName + + (parsed.ext ? '.' + parsed.ext : ''), + url = req.toUrl(nonStripName), + useXhr = (masterConfig.useXhr) || + text.useXhr; + + // Do not load if it is an empty: url + if (url.indexOf('empty:') === 0) { + onLoad(); + return; + } + + //Load the text. Use XHR if possible and in a browser. + if (!hasLocation || useXhr(url, defaultProtocol, defaultHostName, defaultPort)) { + text.get(url, function (content) { + text.finishLoad(name, parsed.strip, content, onLoad); + }, function (err) { + if (onLoad.error) { + onLoad.error(err); + } + }); + } else { + //Need to fetch the resource across domains. Assume + //the resource has been optimized into a JS module. Fetch + //by the module name + extension, but do not include the + //!strip part to avoid file system issues. + req([nonStripName], function (content) { + text.finishLoad(parsed.moduleName + '.' + parsed.ext, + parsed.strip, content, onLoad); + }); + } + }, + + write: function (pluginName, moduleName, write, config) { + if (buildMap.hasOwnProperty(moduleName)) { + var content = text.jsEscape(buildMap[moduleName]); + write.asModule(pluginName + "!" + moduleName, + "define(function () { return '" + + content + + "';});\n"); + } + }, + + writeFile: function (pluginName, moduleName, req, write, config) { + var parsed = text.parseName(moduleName), + extPart = parsed.ext ? '.' + parsed.ext : '', + nonStripName = parsed.moduleName + extPart, + //Use a '.js' file name so that it indicates it is a + //script that can be loaded across domains. + fileName = req.toUrl(parsed.moduleName + extPart) + '.js'; + + //Leverage own load() method to load plugin value, but only + //write out values that do not have the strip argument, + //to avoid any potential issues with ! in file names. + text.load(nonStripName, req, function (value) { + //Use own write() method to construct full module value. + //But need to create shell that translates writeFile's + //write() to the right interface. + var textWrite = function (contents) { + return write(fileName, contents); + }; + textWrite.asModule = function (moduleName, contents) { + return write.asModule(moduleName, fileName, contents); + }; + + text.write(pluginName, nonStripName, textWrite, config); + }, config); + } + }; + + if (masterConfig.env === 'node' || (!masterConfig.env && + typeof process !== "undefined" && + process.versions && + !!process.versions.node && + !process.versions['node-webkit'])) { + //Using special require.nodeRequire, something added by r.js. + fs = require.nodeRequire('fs'); + + text.get = function (url, callback, errback) { + try { + var file = fs.readFileSync(url, 'utf8'); + //Remove BOM (Byte Mark Order) from utf8 files if it is there. + if (file.indexOf('\uFEFF') === 0) { + file = file.substring(1); + } + callback(file); + } catch (e) { + if (errback) { + errback(e); + } + } + }; + } else if (masterConfig.env === 'xhr' || (!masterConfig.env && + text.createXhr())) { + text.get = function (url, callback, errback, headers) { + var xhr = text.createXhr(), header; + xhr.open('GET', url, true); + + //Allow plugins direct access to xhr headers + if (headers) { + for (header in headers) { + if (headers.hasOwnProperty(header)) { + xhr.setRequestHeader(header.toLowerCase(), headers[header]); + } + } + } + + //Allow overrides specified in config + if (masterConfig.onXhr) { + masterConfig.onXhr(xhr, url); + } + + xhr.onreadystatechange = function (evt) { + var status, err; + //Do not explicitly handle errors, those should be + //visible via console output in the browser. + if (xhr.readyState === 4) { + status = xhr.status || 0; + if (status > 399 && status < 600) { + //An http 4xx or 5xx error. Signal an error. + err = new Error(url + ' HTTP status: ' + status); + err.xhr = xhr; + if (errback) { + errback(err); + } + } else { + callback(xhr.responseText); + } + + if (masterConfig.onXhrComplete) { + masterConfig.onXhrComplete(xhr, url); + } + } + }; + xhr.send(null); + }; + } else if (masterConfig.env === 'rhino' || (!masterConfig.env && + typeof Packages !== 'undefined' && typeof java !== 'undefined')) { + //Why Java, why is this so awkward? + text.get = function (url, callback) { + var stringBuffer, line, + encoding = "utf-8", + file = new java.io.File(url), + lineSeparator = java.lang.System.getProperty("line.separator"), + input = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(file), encoding)), + content = ''; + try { + stringBuffer = new java.lang.StringBuffer(); + line = input.readLine(); + + // Byte Order Mark (BOM) - The Unicode Standard, version 3.0, page 324 + // http://www.unicode.org/faq/utf_bom.html + + // Note that when we use utf-8, the BOM should appear as "EF BB BF", but it doesn't due to this bug in the JDK: + // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058 + if (line && line.length() && line.charAt(0) === 0xfeff) { + // Eat the BOM, since we've already found the encoding on this file, + // and we plan to concatenating this buffer with others; the BOM should + // only appear at the top of a file. + line = line.substring(1); + } + + if (line !== null) { + stringBuffer.append(line); + } + + while ((line = input.readLine()) !== null) { + stringBuffer.append(lineSeparator); + stringBuffer.append(line); + } + //Make sure we return a JavaScript string and not a Java string. + content = String(stringBuffer.toString()); //String + } finally { + input.close(); + } + callback(content); + }; + } else if (masterConfig.env === 'xpconnect' || (!masterConfig.env && + typeof Components !== 'undefined' && Components.classes && + Components.interfaces)) { + //Avert your gaze! + Cc = Components.classes; + Ci = Components.interfaces; + Components.utils['import']('resource://gre/modules/FileUtils.jsm'); + xpcIsWindows = ('@mozilla.org/windows-registry-key;1' in Cc); + + text.get = function (url, callback) { + var inStream, convertStream, fileObj, + readData = {}; + + if (xpcIsWindows) { + url = url.replace(/\//g, '\\'); + } + + fileObj = new FileUtils.File(url); + + //XPCOM, you so crazy + try { + inStream = Cc['@mozilla.org/network/file-input-stream;1'] + .createInstance(Ci.nsIFileInputStream); + inStream.init(fileObj, 1, 0, false); + + convertStream = Cc['@mozilla.org/intl/converter-input-stream;1'] + .createInstance(Ci.nsIConverterInputStream); + convertStream.init(inStream, "utf-8", inStream.available(), + Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER); + + convertStream.readString(inStream.available(), readData); + convertStream.close(); + inStream.close(); + callback(readData.value); + } catch (e) { + throw new Error((fileObj && fileObj.path || '') + ': ' + e); + } + }; + } + return text; +}); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/529ef7f7/contrib/views/storm/src/main/resources/scripts/App.js ---------------------------------------------------------------------- diff --git a/contrib/views/storm/src/main/resources/scripts/App.js b/contrib/views/storm/src/main/resources/scripts/App.js deleted file mode 100644 index 1efaff1..0000000 --- a/contrib/views/storm/src/main/resources/scripts/App.js +++ /dev/null @@ -1,41 +0,0 @@ -/** -* Licensed to the Apache Software Foundation (ASF) under one -* or more contributor license agreements. See the NOTICE file -* distributed with this work for additional information -* regarding copyright ownership. The ASF licenses this file -* to you under the Apache License, Version 2.0 (the -* "License"); you may not use this file except in compliance -* with the License. You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -define(['marionette', 'utils/LangSupport', 'utils/Utils'], function(Marionette, localization, Utils) { - /* - * Localization initialization - */ - localization.setDefaultCulture(); // will take default that is en - localization.chooseCulture(); - var App = new Marionette.Application(); - - App.addRegions({ - rHeader: '#header', - rContent: '#content', - rTopology: '#topology', - rCluster: '#cluster' - }); - - App.baseUrl = Utils.getStormHostDetails(); - - App.addInitializer(function() { - Backbone.history.start(); - }); - - return App; -}); http://git-wip-us.apache.org/repos/asf/ambari/blob/529ef7f7/contrib/views/storm/src/main/resources/scripts/collection/BaseCollection.js ---------------------------------------------------------------------- diff --git a/contrib/views/storm/src/main/resources/scripts/collection/BaseCollection.js b/contrib/views/storm/src/main/resources/scripts/collection/BaseCollection.js deleted file mode 100644 index 0844fa5..0000000 --- a/contrib/views/storm/src/main/resources/scripts/collection/BaseCollection.js +++ /dev/null @@ -1,61 +0,0 @@ -/** -* Licensed to the Apache Software Foundation (ASF) under one -* or more contributor license agreements. See the NOTICE file -* distributed with this work for additional information -* regarding copyright ownership. The ASF licenses this file -* to you under the Apache License, Version 2.0 (the -* "License"); you may not use this file except in compliance -* with the License. You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -define(['require', - 'utils/Globals', - 'utils/Utils' - ], function (require, Globals, Utils) { - 'use strict'; - - var BaseCollection = Backbone.Collection.extend( - /** @lends BaseCollection.prototype */ - { - initialize: function () {}, - bindErrorEvents: function () { - this.bind("error", Utils.defaultErrorHandler); - }, - - }, - /** BaseCollection's Static Attributes */ - { - // Static functions - getTableCols: function (cols, collection) { - var retCols = _.map(cols, function (v, k, l) { - var defaults = collection.constructor.tableCols[k]; - if (!defaults) { - defaults = {}; - } - return _.extend({ - 'name': k - }, defaults, v); - }); - - return retCols; - }, - - nonCrudOperation: function (url, requestMethod, options) { - return Backbone.sync.call(this, null, this, _.extend({ - url: url, - type: requestMethod - }, options)); - } - - }); - - return BaseCollection; -}); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/529ef7f7/contrib/views/storm/src/main/resources/scripts/collection/VTopologyList.js ---------------------------------------------------------------------- diff --git a/contrib/views/storm/src/main/resources/scripts/collection/VTopologyList.js b/contrib/views/storm/src/main/resources/scripts/collection/VTopologyList.js deleted file mode 100644 index 600ed3d..0000000 --- a/contrib/views/storm/src/main/resources/scripts/collection/VTopologyList.js +++ /dev/null @@ -1,42 +0,0 @@ -/** -* Licensed to the Apache Software Foundation (ASF) under one -* or more contributor license agreements. See the NOTICE file -* distributed with this work for additional information -* regarding copyright ownership. The ASF licenses this file -* to you under the Apache License, Version 2.0 (the -* "License"); you may not use this file except in compliance -* with the License. You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -define(['require', - 'utils/Globals', - 'collection/BaseCollection', - 'models/VTopology' - ], function (require, Globals, BaseCollection, vTopology) { - 'use strict'; - var vTopologyList = BaseCollection.extend( - //Prototypal attributes - { - - url: Globals.baseURL + '/api/v1/topology/summary', - - model: vTopology, - - - initialize: function () { - this.modelName = 'VTopology'; - this.modelAttrName = 'topologies'; - this.bindErrorEvents(); - } - } - ); - return vTopologyList; -}); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/529ef7f7/contrib/views/storm/src/main/resources/scripts/collections/BaseCollection.js ---------------------------------------------------------------------- diff --git a/contrib/views/storm/src/main/resources/scripts/collections/BaseCollection.js b/contrib/views/storm/src/main/resources/scripts/collections/BaseCollection.js new file mode 100644 index 0000000..29b1ce9 --- /dev/null +++ b/contrib/views/storm/src/main/resources/scripts/collections/BaseCollection.js @@ -0,0 +1,175 @@ +/** + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at +* + http://www.apache.org/licenses/LICENSE-2.0 +* + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +define(['require', + 'utils/Globals', + 'backbone.paginator' + ], function (require, Globals) { + 'use strict'; + + var BaseCollection = Backbone.PageableCollection.extend( + /** @lends BaseCollection.prototype */ + { + /** + * BaseCollection's initialize function + * @augments Backbone.PageableCollection + * @constructs + */ + + initialize: function () { + + }, + bindErrorEvents: function () { + this.bind("error", function(model, error) { + if (error.status == 401) { + throw new Error("ERROR 401 occured."); + } + }); + }, + search : function(letters){ + var self = this; + if(letters === ""){ + if(this.unfilteredCollection){ + this.getFirstPage().fullCollection.reset(this.unfilteredCollection.models); + } + } else { + if(this.unfilteredCollection){ + this.getFirstPage().fullCollection.reset(this.unfilteredCollection.models); + } + var results = _.filter(this.fullCollection.models,function(model) { + var regexTest = new RegExp(letters,"i"); + var result = false; + _.each(this.searchFields, function(field) { + if(regexTest.test(model.get(field))) { + result = true; + } + }); + return result; + }.bind(this)); + if(!this.unfilteredCollection) { + this.unfilteredCollection = this.fullCollection.clone(); + } + + this.getFirstPage().fullCollection.reset(results); + } + }, + /** + * state required for the PageableCollection + */ + state: { + // firstPage: 0, + pageSize: Globals.settings.PAGE_SIZE + }, + + mode: 'client', + + /** + * override the parseState of PageableCollection for our use + */ + parse: function (resp, options) { + var newState = this.parseState(resp, _.clone(this.queryParams), _.clone(this.state), options); + try { + if (newState) { + this.state = this._checkState(_.extend({}, this.state, newState)); + } + } catch (error) { + if (error.name === 'RangeError') { + this.state.currentPage = 0; + this.state.startIndex = 0; + this.fetch({ + reset: true + }); + } + } + return this.parseRecords(resp, options); + }, + parseRecords: function (resp, options) { + // try { + // if (!this.modelAttrName) { + // throw new Error("this.modelAttrName not defined for " + this); + // } + // return Globalize.byString(resp, this.modelAttrName); + // } catch (e) { + // console.log(e); + // } + }, + + //////////////////////////////////////////////////////////// + // Overriding backbone-pageable page handlers methods // + //////////////////////////////////////////////////////////// + getFirstPage: function (options) { + return this.getPage("first", _.extend({ + reset: true + }, options)); + }, + + getPreviousPage: function (options) { + return this.getPage("prev", _.extend({ + reset: true + }, options)); + }, + + getNextPage: function (options) { + return this.getPage("next", _.extend({ + reset: true + }, options)); + }, + + getLastPage: function (options) { + return this.getPage("last", _.extend({ + reset: true + }, options)); + }, + + getParticularPage: function (pageNumber, options){ + return this.getPage(pageNumber, _.extend({ + reset: true + }, options)); + } + ///////////////////////////// + // End overriding methods // + ///////////////////////////// + }, + /** BaseCollection's Static Attributes */ + { + // Static functions + getTableCols: function (cols, collection) { + var retCols = _.map(cols, function (v, k, l) { + var defaults = collection.constructor.tableCols[k]; + if (!defaults) { + defaults = {}; + } + return _.extend({ + 'name': k + }, defaults, v); + }); + + return retCols; + }, + + nonCrudOperation: function (url, requestMethod, options) { + return Backbone.sync.call(this, null, this, _.extend({ + url: url, + type: requestMethod + }, options)); + } + + }); + + return BaseCollection; +}); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/529ef7f7/contrib/views/storm/src/main/resources/scripts/collections/VNimbusConfigList.js ---------------------------------------------------------------------- diff --git a/contrib/views/storm/src/main/resources/scripts/collections/VNimbusConfigList.js b/contrib/views/storm/src/main/resources/scripts/collections/VNimbusConfigList.js new file mode 100644 index 0000000..a372299 --- /dev/null +++ b/contrib/views/storm/src/main/resources/scripts/collections/VNimbusConfigList.js @@ -0,0 +1,52 @@ +/** + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at +* + http://www.apache.org/licenses/LICENSE-2.0 +* + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +define(['require', + 'utils/Globals', + 'collections/BaseCollection', + 'models/VNimbusConfig' + ], function (require, Globals, BaseCollection, vNimbusConfig) { + 'use strict'; + var vNimbusConfigList = BaseCollection.extend( + //Prototypal attributes + { + + url: Globals.baseURL + '/api/v1/cluster/configuration', + + model: vNimbusConfig, + + searchFields:['key'], + + initialize: function () { + this.modelName = 'VNimbusConfig'; + this.modelAttrName = 'key'; + this.bindErrorEvents(); + } + }, + //Static Class Members + { + /** + * Table Cols to be passed to Backgrid + * UI has to use this as base and extend this. + * + */ + tableCols: {} + } + ); + return vNimbusConfigList; +}); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/529ef7f7/contrib/views/storm/src/main/resources/scripts/collections/VNimbusList.js ---------------------------------------------------------------------- diff --git a/contrib/views/storm/src/main/resources/scripts/collections/VNimbusList.js b/contrib/views/storm/src/main/resources/scripts/collections/VNimbusList.js new file mode 100644 index 0000000..a6f2108 --- /dev/null +++ b/contrib/views/storm/src/main/resources/scripts/collections/VNimbusList.js @@ -0,0 +1,52 @@ +/** + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at +* + http://www.apache.org/licenses/LICENSE-2.0 +* + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +define(['require', + 'utils/Globals', + 'collections/BaseCollection', + 'models/VNimbus' + ], function (require, Globals, BaseCollection, vNimbus) { + 'use strict'; + var vNimbusList = BaseCollection.extend( + //Prototypal attributes + { + + url: Globals.baseURL + '/api/v1/nimbus/summary', + + model: vNimbus, + + searchFields:['host:port'], + + initialize: function () { + this.modelName = 'VNimbus'; + this.modelAttrName = 'nimbuses'; + this.bindErrorEvents(); + } + }, + //Static Class Members + { + /** + * Table Cols to be passed to Backgrid + * UI has to use this as base and extend this. + * + */ + tableCols: {} + } + ); + return vNimbusList; +}); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/529ef7f7/contrib/views/storm/src/main/resources/scripts/collections/VSupervisorList.js ---------------------------------------------------------------------- diff --git a/contrib/views/storm/src/main/resources/scripts/collections/VSupervisorList.js b/contrib/views/storm/src/main/resources/scripts/collections/VSupervisorList.js new file mode 100644 index 0000000..5bc066c --- /dev/null +++ b/contrib/views/storm/src/main/resources/scripts/collections/VSupervisorList.js @@ -0,0 +1,52 @@ +/** + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at +* + http://www.apache.org/licenses/LICENSE-2.0 +* + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +define(['require', + 'utils/Globals', + 'collections/BaseCollection', + 'models/VSupervisor' + ], function (require, Globals, BaseCollection, vSupervisor) { + 'use strict'; + var vSupervisorList = BaseCollection.extend( + //Prototypal attributes + { + + url: Globals.baseURL + '/api/v1/supervisor/summary', + + model: vSupervisor, + + searchFields:['host'], + + initialize: function () { + this.modelName = 'VSupervisor'; + this.modelAttrName = 'supervisors'; + this.bindErrorEvents(); + } + }, + //Static Class Members + { + /** + * Table Cols to be passed to Backgrid + * UI has to use this as base and extend this. + * + */ + tableCols: {} + } + ); + return vSupervisorList; +}); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/529ef7f7/contrib/views/storm/src/main/resources/scripts/collections/VTopologyConfigList.js ---------------------------------------------------------------------- diff --git a/contrib/views/storm/src/main/resources/scripts/collections/VTopologyConfigList.js b/contrib/views/storm/src/main/resources/scripts/collections/VTopologyConfigList.js new file mode 100644 index 0000000..250517f --- /dev/null +++ b/contrib/views/storm/src/main/resources/scripts/collections/VTopologyConfigList.js @@ -0,0 +1,49 @@ +/** + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at +* + http://www.apache.org/licenses/LICENSE-2.0 +* + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +define(['require', + 'utils/Globals', + 'collections/BaseCollection', + 'models/VTopologyConfig' + ], function (require, Globals, BaseCollection, vTopologyConfig) { + 'use strict'; + var vTopologyConfigList = BaseCollection.extend( + //Prototypal attributes + { + model: vTopologyConfig, + + searchFields:['key'], + + initialize: function () { + this.modelName = 'vTopologyConfig'; + // this.modelAttrName = ''; + this.bindErrorEvents(); + } + }, + //Static Class Members + { + /** + * Table Cols to be passed to Backgrid + * UI has to use this as base and extend this. + * + */ + tableCols: {} + } + ); + return vTopologyConfigList; +}); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/529ef7f7/contrib/views/storm/src/main/resources/scripts/collections/VTopologyList.js ---------------------------------------------------------------------- diff --git a/contrib/views/storm/src/main/resources/scripts/collections/VTopologyList.js b/contrib/views/storm/src/main/resources/scripts/collections/VTopologyList.js new file mode 100644 index 0000000..82297d5 --- /dev/null +++ b/contrib/views/storm/src/main/resources/scripts/collections/VTopologyList.js @@ -0,0 +1,52 @@ +/** + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at +* + http://www.apache.org/licenses/LICENSE-2.0 +* + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +define(['require', + 'utils/Globals', + 'collections/BaseCollection', + 'models/VTopology' + ], function (require, Globals, BaseCollection, vTopology) { + 'use strict'; + var vTopologyList = BaseCollection.extend( + //Prototypal attributes + { + + url: Globals.baseURL + '/api/v1/topology/summary', + + model: vTopology, + + + initialize: function () { + this.modelName = 'VTopology'; + this.modelAttrName = 'topologies'; + this.bindErrorEvents(); + }, + searchFields:['name'] + }, + //Static Class Members + { + /** + * Table Cols to be passed to Backgrid + * UI has to use this as base and extend this. + * + */ + tableCols: {} + } + ); + return vTopologyList; +}); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/529ef7f7/contrib/views/storm/src/main/resources/scripts/components/Breadcrumbs.jsx ---------------------------------------------------------------------- diff --git a/contrib/views/storm/src/main/resources/scripts/components/Breadcrumbs.jsx b/contrib/views/storm/src/main/resources/scripts/components/Breadcrumbs.jsx new file mode 100644 index 0000000..75c2fa9 --- /dev/null +++ b/contrib/views/storm/src/main/resources/scripts/components/Breadcrumbs.jsx @@ -0,0 +1,47 @@ +/** + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at +* + http://www.apache.org/licenses/LICENSE-2.0 +* + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +define(['react', + 'react-dom'], + function(React, ReactDOM) { + 'use strict'; + return React.createClass({ + displayName: 'Breadcrumbs', + getInitialState: function() { + return null; + }, + render: function() { + return ( + <ol id="breadcrumb"> + {this.renderLinks()} + </ol> + ); + }, + renderLinks: function() { + var links = []; + for(var i = 0; i < this.props.links.length; i++){ + var object = this.props.links[i]; + if(object.link === '#!/dashboard'){ + object.title = <i className="fa fa-home"></i> + } + links.push(<li key={i}><a href={object.link}>{object.title}</a></li>); + } + return links; + } + }); +}); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/529ef7f7/contrib/views/storm/src/main/resources/scripts/components/Modal.jsx ---------------------------------------------------------------------- diff --git a/contrib/views/storm/src/main/resources/scripts/components/Modal.jsx b/contrib/views/storm/src/main/resources/scripts/components/Modal.jsx new file mode 100644 index 0000000..e37b734 --- /dev/null +++ b/contrib/views/storm/src/main/resources/scripts/components/Modal.jsx @@ -0,0 +1,54 @@ +/** + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at +* + http://www.apache.org/licenses/LICENSE-2.0 +* + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +define(['react', 'react-dom', 'bootstrap'], function(React, ReactDOM) { + 'use strict'; + return React.createClass({ + displayName: 'Modal', + getInitialState: function(){ + + return null; + }, + componentDidUpdate: function(){ + + }, + componentDidMount: function(){ + + }, + render: function() { + return ( + <div className="modal fade" id={this.props.modalId} role="dialog"> + <div className="modal-dialog"> + <div className="modal-content"> + <div className="modal-header"> + <button type="button" className="close" data-dismiss="modal">×</button> + <h4 className="modal-title">{this.props.header ? <this.props.header /> : null}</h4> + </div> + <div className="modal-body"> + {this.props.content ? <this.props.content /> : null} + </div> + <div className="modal-footer"> + {this.props.footer ? <this.props.footer /> : <button type="button" className="btn btn-default" data-dismiss="modal">Close</button>} + </div> + </div> + </div> + </div> + ); + }, + }); +}); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/529ef7f7/contrib/views/storm/src/main/resources/scripts/components/RadialChart.jsx ---------------------------------------------------------------------- diff --git a/contrib/views/storm/src/main/resources/scripts/components/RadialChart.jsx b/contrib/views/storm/src/main/resources/scripts/components/RadialChart.jsx new file mode 100644 index 0000000..f28b08a --- /dev/null +++ b/contrib/views/storm/src/main/resources/scripts/components/RadialChart.jsx @@ -0,0 +1,118 @@ +/** + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at +* + http://www.apache.org/licenses/LICENSE-2.0 +* + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +define(['react', 'react-dom', 'd3', 'd3.tip'], function(React, ReactDOM, d3) { + 'use strict'; + return React.createClass({ + displayName: 'RadialChart', + getInitialState: function(){ + this.const = { + tau: 2 * Math.PI, + width: this.props.width || "64", + height: this.props.height || "52", + innerRadius: parseInt(this.props.innerRadius, 10) || 20, + outerRadius: parseInt(this.props.outerRadius, 10) || 25, + color: this.props.color || d3.scale.category20() + }; + this.arc = d3.svg.arc() + .innerRadius(this.const.innerRadius) + .outerRadius(this.const.outerRadius) + .startAngle(0); + + return null; + }, + componentDidUpdate: function(){ + this.animateGraph(); + }, + componentDidMount: function(){ + this.tip = d3.tip() + .attr('class', 'd3-tip') + .offset([-10, 0]) + .html(function() { + var text = "<div class='summary'>"+this.props.labels[0]+": "+this.props.data[0]+"</div>"; + text += "<div class='summary'>Free: "+(parseInt(this.props.data[1],10) - parseInt(this.props.data[0],10))+"</div>"; + text += "<div class='summary'>"+this.props.labels[1]+": "+this.props.data[1]+"</div>"; + return text; + }.bind(this)); + var svg = this.svg = d3.select(ReactDOM.findDOMNode(this)) + .attr('width', this.const.width+"px") + .attr('height', this.const.height+"px") + .append('g').attr('transform', 'translate('+(this.const.width/2)+', '+(this.const.height/2)+')'); + + this.text = svg.append("text") + .attr("y", "0.3em") + .attr("class","graphVal") + .attr("text-anchor", "middle") + .attr("font-size", this.const.fontSize) + .on("mouseover", function(d){ + this.tip.show(); + }.bind(this)) + .on("mouseout", function(d){ + this.tip.hide(); + }.bind(this)) + .text("0"); + + var background = svg.append("path") + .datum({endAngle: this.const.tau}) + .style("fill", this.const.color[0]) + .attr("d", this.arc); + + this.foreground = svg.append("path") + .datum({endAngle: 0}) + .style("fill", function(d, i) { return this.const.color[1]; }.bind(this)) + .attr("d", this.arc); + this.svg.call(this.tip); + $('#container').append($('body > .d3-tip')); + this.animateGraph(); + }, + animateGraph: function(){ + var percent = (parseInt(this.props.data[0],10)/parseInt(this.props.data[1],10)*100); + if(percent){ + percent = percent.toFixed(0)+' %'; + } else { + percent = '0 %'; + } + + d3.select(ReactDOM.findDOMNode(this)).select('.graphVal').text(percent); + + var newValue = this.props.data[0] / this.props.data[1] * 100; + this.foreground.transition() + .duration(750) + .call(this._arcTween, this.const.tau * (newValue/100)); + }, + _arcTween: function(transition, newAngle) { + var arc = this.arc; + transition.attrTween("d", function(d) { + var interpolate = d3.interpolate(d.endAngle, newAngle); + return function(t) { + d.endAngle = interpolate(t); + if(!d.endAngle){ + d.endAngle = 0; + } + return arc(d); + }; + + }); + }, + render: function() { + return ( + <svg className="radial-chart"></svg> + ); + }, + }); +}); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/529ef7f7/contrib/views/storm/src/main/resources/scripts/components/SpoutGraph.jsx ---------------------------------------------------------------------- diff --git a/contrib/views/storm/src/main/resources/scripts/components/SpoutGraph.jsx b/contrib/views/storm/src/main/resources/scripts/components/SpoutGraph.jsx new file mode 100644 index 0000000..cec4c85 --- /dev/null +++ b/contrib/views/storm/src/main/resources/scripts/components/SpoutGraph.jsx @@ -0,0 +1,136 @@ +/** + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at +* + http://www.apache.org/licenses/LICENSE-2.0 +* + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +define(['react', + 'react-dom' + ], function(React, ReactDOM){ + 'use strict'; + return React.createClass({ + displayName: 'SpoutGraph', + getInitialState: function(){ + this.syncData(); + this.fields = ['', 'Acked', 'Failed', 'Emitted', 'Transferred']; + this.colors = ['#0000b4','#0082ca','#0094ff','#0d4bcf']; + this.grid = d3.range(10).map(function(i){ + return {'x1':0,'y1':0,'x2':0,'y2':240}; + }); + + this.tickVals = this.grid.map(function(d,i){ + if(i>0){ return i*10; } + else if(i===0){ return "100";} + }); + + this.xscale = d3.scale.linear() + .domain([10,250]) + .range([0,350]); + + this.yscale = d3.scale.linear() + .domain([0,this.fields.length]) + .range([0,600]); + + this.colorScale = d3.scale.quantize() + .domain([0,this.fields.length]) + .range(this.colors); + return null; + }, + syncData: function(){ + this.values = [this.props.spout.acked, this.props.spout.failed, + this.props.spout.emitted, this.props.spout.transferred]; + console.log(this.values); + }, + componentDidMount: function(){ + this.renderGraph(); + }, + componentWillUpdate: function(){ + this.syncData(); + }, + componentDidUpdate: function(){ + + }, + renderGraph: function(){ + this.canvas = d3.select(ReactDOM.findDOMNode(this)) + .attr({'width':640,'height':400}); + + this.grids = this.canvas.append('g') + .attr('transform','translate(150,10)') + .selectAll('line') + .data(this.grid) + .enter() + .append('line') + .attr({'x1':function(d,i){ return i*30; }, + 'y1':function(d){ return d.y1; }, + 'x2':function(d,i){ return i*30; }, + 'y2':function(d){ return d.y2; }, + }) + .style({'stroke':'#adadad','stroke-width':'1px'}); + var xAxis = d3.svg.axis(); + xAxis + .orient('bottom') + .scale(this.xscale) + .tickValues(this.tickVals); + + var yAxis = d3.svg.axis(); + yAxis + .orient('left') + .scale(this.yscale) + .tickSize(2) + .tickFormat(function(d,i){ return this.fields[i]; }.bind(this)) + .tickValues(d3.range(this.fields.length)); + + var y_xis = this.canvas.append('g') + .attr("transform", "translate(150,0)") + .call(yAxis); + + var x_xis = this.canvas.append('g') + .attr("transform", "translate(150,480)") + .call(xAxis); + + var chart = this.canvas.append('g') + .attr("transform", "translate(150,0)") + .attr('class','bars') + .selectAll('rect') + .data(this.values) + .enter() + .append('rect') + .attr('height',19) + .attr({'x':0,'y':function(d,i){ return this.yscale(i)+19; }.bind(this)}) + .style('fill',function(d,i){ return this.colorScale(i); }.bind(this)) + .attr('width',function(d){ return 0; }); + + + var transit = d3.select("svg").selectAll("rect") + .data(this.values) + .transition() + .duration(1000) + .attr("width", function(d) {return this.xscale(d); }.bind(this)); + + var transitext = this.canvas.select('.bars') + .selectAll('text') + .data(this.values) + .enter() + .append('text') + .attr({'x':function(d) {return this.xscale(d)-200; }.bind(this),'y':function(d,i){ return this.yscale(i)+35; }.bind(this)}) + .text(function(d){ return d; }).style({'fill':'#fff','font-size':'14px'}); + }, + render: function(){ + return ( + <svg className="spout-chart"></svg> + ); + } + }); +}); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/529ef7f7/contrib/views/storm/src/main/resources/scripts/components/Table.jsx ---------------------------------------------------------------------- diff --git a/contrib/views/storm/src/main/resources/scripts/components/Table.jsx b/contrib/views/storm/src/main/resources/scripts/components/Table.jsx new file mode 100644 index 0000000..3b0ad50 --- /dev/null +++ b/contrib/views/storm/src/main/resources/scripts/components/Table.jsx @@ -0,0 +1,92 @@ +/** + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at +* + http://www.apache.org/licenses/LICENSE-2.0 +* + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +define(['react', 'react-dom'], function(React, ReactDOM) { + 'use strict'; + var Row = React.createClass({ + displayName: 'Row', + componentDidMount: function(){ + if(!this.props.model._highlighted){ + $(ReactDOM.findDOMNode(this)).addClass(''); + this.props.model._highlighted = true; + } + }, + render: function(){ + return (<tr>{this.props.children}</tr>); + } + }); + return React.createClass({ + displayName: 'Table', + getInitialState: function(){ + this.highlight = false; + return null; + }, + componentDidMount: function() { + this.props.collection.on('add remove change reset', this.forceUpdate.bind(this, null)); + this.highlight = true; + $('[data-rel="tooltip"]').tooltip({ + container: '#container' + }); + }, + render: function() { + return ( <div className="table-responsive"><table className={this.props.className}> + <thead> + <tr> + {this.getHeaderTHs()} + </tr> + </thead> + <tbody> + {this.getRows()} + </tbody> + </table> </div>); + }, + getRows: function(){ + var self = this; + var limitRows = this.props.collection.models.length; + if(this.props.limitRows){ + limitRows = parseInt(this.props.limitRows, 10); + } + var rows = this.props.collection.map(function(model, i) { + if(i < limitRows){ + if(!self.highlight){ + model._highlighted = true; + } + var tds = self.getRowsTDs(model); + return (<Row key={i} model={model}>{tds}</Row>); + } + }); + if(!rows.length) + rows.push(<tr key="0"><td>{this.props.emptyText}</td></tr>); + return rows; + }, + getRowsTDs: function(model){ + var tds = this.props.columns.map(function(column, i){ + var content = column.component ? <column.component model={model} column={column}/> : model.get(column.name); + return (<td key={i}>{content}</td>); + }); + return tds; + }, + getHeaderTHs: function(){ + var ths = this.props.columns.map(function(column, i){ + var stringTitle = typeof column.title === 'string' ? true : false; + return (<th key={i}><span data-rel="tooltip" title={column.tooltip ? column.tooltip : ""}>{stringTitle ? column.title : <column.title/>}</span></th>); + }); + return ths; + } + }); +}); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/529ef7f7/contrib/views/storm/src/main/resources/scripts/components/TopologyGraph.jsx ---------------------------------------------------------------------- diff --git a/contrib/views/storm/src/main/resources/scripts/components/TopologyGraph.jsx b/contrib/views/storm/src/main/resources/scripts/components/TopologyGraph.jsx new file mode 100644 index 0000000..e74a251 --- /dev/null +++ b/contrib/views/storm/src/main/resources/scripts/components/TopologyGraph.jsx @@ -0,0 +1,270 @@ +/** + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at +* + http://www.apache.org/licenses/LICENSE-2.0 +* + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +define(['react', 'react-dom', 'd3', 'd3.tip'], function(React, ReactDOM, d3) { + 'use strict'; + return React.createClass({ + displayName: 'TopologyGraph', + getInitialState: function(){ + this.width = this.props.width || '1100'; + this.height = this.props.height || '260'; + this.syncData(this.props.data); + return null; + }, + componentWillUpdate: function(){ + + }, + componentDidUpdate: function(){ + this.syncData(this.props.data); + this.updateGraph(); + this.force.start(); + for (var i = 300; i > 0; --i) this.force.tick(); + this.force.stop(); + }, + componentDidMount: function(){ + var width = this.width, + height = this.height, + nodes = this.nodeArray, + links = this.linkArray, + radius = this.radius = 20.75; + + var svg = this.svg = d3.select(ReactDOM.findDOMNode(this)) + .attr('width', width) + .attr('height', height); + + //Set up tooltip + this.tip = d3.tip() + .attr('class', function() { + return 'd3-tip'; + }) + .offset([-10, 0]) + .html(function(d) { + var tip = "<ul>"; + if (d[":capacity"] !== null) tip += "<li>Capacity: " + d[":capacity"].toFixed(2) + "</li>"; + if (d[":latency"] !== null) tip += "<li>Latency: " + d[":latency"].toFixed(2) + "</li>"; + if (d[":transferred"] !== null) tip += "<li>Transferred: " + d[":transferred"].toFixed(2) + "</li>"; + tip += "</ul>"; + return tip; + }); + svg.call(this.tip); + + // define arrow markers for graph links + svg.append('svg:defs').append('svg:marker') + .attr('id', 'end-arrow') + .attr('viewBox', '0 -5 10 10') + .attr('refX', 6) + .attr('markerWidth', 6) + .attr('markerHeight', 6.5) + .attr('orient', 'auto') + .append('svg:path') + .attr('d', 'M0,-5L10,0L0,5'); + + svg.append('svg:defs').append('svg:marker') + .attr('id', 'start-arrow') + .attr('viewBox', '0 -5 10 10') + .attr('refX', 4) + .attr('markerWidth', 3) + .attr('markerHeight', 3) + .attr('orient', 'auto') + .append('svg:path') + .attr('d', 'M10,-5L0,0L10,5'); + + // handles to link and node element groups + this.path = svg.append('svg:g').selectAll('path'); + this.image = svg.append('svg:g').selectAll('g'); + + this.selected_node = null; + + // only respond once per keydown + this.lastKeyDown = -1; + d3.select(window) + .on('keydown', this.keydown) + .on('keyup', this.keyup); + this.updateGraph(); + this.force.start(); + this.force.tick(); + this.force.stop(); + }, + // update graph (called when needed) + updateGraph: function(){ + // init D3 force layout + this.force = d3.layout.force() + .nodes(this.nodeArray) + .links(this.linkArray) + .size([this.width, this.height]) + .linkDistance(150) + .charge(-500) + .on('tick', this.tick); + + // path (link) group + this.path = this.path.data(this.linkArray); + + // update existing links + this.path.style('marker-start', function(d) { + return ''; }) + .style('marker-end', function(d) { + return 'url(#end-arrow)'; }); + + + // add new links + this.path.enter().append('svg:path') + .attr('class', 'link') + .style('marker-start', function(d) { + return ''; }) + .attr("stroke-dasharray", "5, 5") + .attr('stroke-width', '2') + .style('marker-end', function(d) { + return 'url(#end-arrow)'; }); + + // remove old links + this.path.exit().remove(); + + + // image (node) group + // NB: the function arg is crucial here! nodes are known by id, not by index! + this.image = this.image.data(this.nodeArray, function(d) { + return d.id; + }); + + //update old nodes + this.image + .on('mouseover', function(d) { + this.tip.show(d); + }.bind(this)) + .on('mouseout', function(d) { + this.tip.hide(); + }.bind(this)); + + // add new nodes + var g = this.image.enter().append('svg:g'); + + g.append('svg:image') + .attr("xlink:href", function(d){ + if(d.type === 'spout'){ + return "images/icon-spout.png"; + } else if(d.type === 'bolt'){ + return "images/icon-bolt.png"; + } + }) + .attr("width", "68px") + .attr("height", "68px") + .on('mouseover', function(d) { + this.tip.show(d); + }.bind(this)) + .on('mouseout', function(d) { + this.tip.hide(); + }.bind(this)); + + g.append("svg:text") + .attr("dx", 18) + .attr("dy", 78) + .text(function(d) { + return d.id; }); + + // remove old nodes + this.image.exit().remove(); + }, + // update force layout (called automatically each iteration) + tick: function(){ + // draw directed edges with proper padding from node centers + this.path.attr('d', function(d) { + var deltaX = d.target.x - d.source.x, + deltaY = d.target.y - d.source.y, + dist = Math.sqrt(deltaX * deltaX + deltaY * deltaY), + normX = deltaX / dist, + normY = deltaY / dist, + sourcePadding = 68, + targetPadding = 5, + sourceX = d.source.x + (sourcePadding * normX), + sourceY = d.source.y + (sourcePadding * normY) + 34, + targetX = d.target.x - (targetPadding * normX), + targetY = d.target.y - (targetPadding * normY) + 34; + return 'M' + sourceX + ',' + sourceY + 'L' + targetX + ',' + targetY; + }); + + this.image.attr('transform', function(d) { + return 'translate(' + Math.max(this.radius, Math.min(this.width - this.radius, d.x)) + ',' + Math.max(this.radius, Math.min(this.height - this.radius, d.y)) + ')'; + }.bind(this)); + }, + keydown: function(){ + if (this.lastKeyDown !== -1) return; + this.lastKeyDown = d3.event.keyCode; + + // ctrl + if (d3.event.keyCode === 17) { + d3.event.preventDefault(); + this.tip.hide(); + this.image.call(this.force.drag); + this.svg.classed('ctrl', true); + } + }, + keyup: function(){ + this.lastKeyDown = -1; + // ctrl + if (d3.event.keyCode === 17) { + this.image + .on('mousedown.drag', null) + .on('touchstart.drag', null); + this.svg.classed('ctrl', false); + } + }, + syncData: function(data){ + this.nodeArray = []; + this.linkArray = []; + if(data){ + var keys = _.keys(data); + keys.map(function(key){ + if(!key.startsWith('__')){ + data[key].id = key; + data[key].type = data[key][":type"]; + this.nodeArray.push(data[key]); + } + }.bind(this)); + + var spoutObjArr = _.where(this.nodeArray, { "type": "spout" }); + if (spoutObjArr.length > 1) { + var index = this.nodeArray.length - 1; + this.nodeArray[index].x = 50; + this.nodeArray[index].y = 100; + this.nodeArray[index].fixed = true; + } else if (spoutObjArr.length == 1) { + spoutObjArr[0].x = 50; + spoutObjArr[0].y = 100; + spoutObjArr[0].fixed = true; + } + + this.nodeArray.map(function(node){ + var inputArr = node[":inputs"] || []; + inputArr.map(function(input){ + if(!input[":component"].startsWith("__")){ + this.linkArray.push({ + source: _.findWhere(this.nodeArray, {id: input[":component"]}), + target: node + }); + } + }.bind(this)); + }.bind(this)); + } + }, + render: function() { + return ( + <svg className="topology-graph"></svg> + ); + }, + }); +}); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/529ef7f7/contrib/views/storm/src/main/resources/scripts/containers/ClusterSummary.jsx ---------------------------------------------------------------------- diff --git a/contrib/views/storm/src/main/resources/scripts/containers/ClusterSummary.jsx b/contrib/views/storm/src/main/resources/scripts/containers/ClusterSummary.jsx new file mode 100644 index 0000000..b022987 --- /dev/null +++ b/contrib/views/storm/src/main/resources/scripts/containers/ClusterSummary.jsx @@ -0,0 +1,122 @@ +/** + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at +* + http://www.apache.org/licenses/LICENSE-2.0 +* + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +define(['react', + 'react-dom', + 'utils/Utils', + 'jsx!components/RadialChart', + 'models/VCluster', + 'jsx!containers/NimbusSummary', + ], function(React, ReactDOM, Utils, RadialChart, VCluster, NimbusSummary){ + 'use strict'; + + return React.createClass({ + displayName: 'ClusterSummary', + getInitialState: function(){ + this.initializeData(); + return { + executorsTotal: 0, + tasksTotal: 0, + supervisors: 0, + slotsUsed: 0, + slotsTotal:0 + }; + }, + initializeData: function(){ + this.model = new VCluster(); + this.model.fetch({ + success: function(model, response){ + if(response.error){ + Utils.notifyError(response.error); + } else { + this.setState(model.attributes); + } + }.bind(this), + error: function(model, response, options){ + Utils.notifyError("Error occured in fetching cluster summary data."); + } + }); + }, + componentDidMount: function(){ + $('[data-rel="tooltip1"]').tooltip({ + placement: 'bottom' + }); + }, + render: function(){ + return ( + <div className="col-sm-5"> + <div className="row"> + <div className="col-sm-6"> + <div className="tile primary" title="Executors are threads in a Worker process." data-rel="tooltip1"> + <div className="tile-header">Executor</div> + <div className="tile-body"> + <i className="fa fa-play-circle-o"></i> + <span className="count">{this.state.executorsTotal}</span> + </div> + </div> + </div> + <div className="col-sm-6"> + <div className="tile warning" title="A Task is an instance of a Bolt or Spout. The number of Tasks is almost always equal to the number of Executors." data-rel="tooltip1"> + <div className="tile-header">Tasks</div> + <div className="tile-body"> + <i className="fa fa-tasks"></i> + <span className="count">{this.state.tasksTotal}</span> + </div> + </div> + </div> + </div> + <div className="row"> + <div className="col-sm-6"> + <div className="tile success" title="The number of nodes in the cluster currently." data-rel="tooltip1"> + <div className="tile-header" style={{textAlign:"center"}}>Supervisor</div> + <div className="tile-body" style={{textAlign:"center"}}> + <div id="supervisorCount"> + <RadialChart width="100" height="100" innerRadius="46" outerRadius="50" + color={["rgba(255,255,255,0.6)", "rgba(255,255,255,1)"]} + data={[this.state.supervisors, this.state.supervisors]} + labels={['Used','Total']} + /> + </div> + </div> + </div> + </div> + <div className="col-sm-6"> + <div className="tile danger" title="Slots are Workers (processes)." data-rel="tooltip1"> + <div className="tile-header" style={{textAlign:"center"}}>Slots</div> + <div className="tile-body" style={{textAlign:"center"}}> + <div id="slotsCount"> + <RadialChart width="100" height="100" innerRadius="46" outerRadius="50" + color={["rgba(255,255,255,0.6)", "rgba(255,255,255,1)"]} + data={[this.state.slotsUsed, this.state.slotsTotal]} + labels={['Used','Total']} + /> + </div> + </div> + </div> + </div> + </div> + <div className="row"> + <div className="col-sm-12"> + <NimbusSummary fromDashboard={true} /> + </div> + </div> + </div> + ); + } + }); +}); \ No newline at end of file