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">&times;</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

Reply via email to