Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Zachary Tong committed 2013-04-18 14:19:32 -04:00
commit f8c5e464f9
18 files changed
+771 -254

No files matched your search

+4
View File
@@ -106,6 +106,10 @@
font-size: 85%;
}
.input-append label {
font-size: inherit !important;
}
.large {
font-size: 120%;
}
+5
View File
@@ -0,0 +1,5 @@
d3=function(){function n(n){return null!=n&&!isNaN(n)}function t(n){return n.length}function e(n){for(var t=1;n*t%1;)t*=10;return t}function r(n,t){try{for(var e in t)Object.defineProperty(n.prototype,e,{value:t[e],enumerable:!1})}catch(r){n.prototype=t}}function u(){}function i(){}function a(n,t,e){return function(){var r=e.apply(t,arguments);return r===t?n:r}}function o(){}function c(n){function t(){for(var t,r=e,u=-1,i=r.length;++u<i;)(t=r[u].on)&&t.apply(this,arguments);return n}var e=[],r=new u;return t.on=function(t,u){var i,a=r.get(t);return arguments.length<2?a&&a.on:(a&&(a.on=null,e=e.slice(0,i=e.indexOf(a)).concat(e.slice(i+1)),r.remove(t)),u&&e.push(r.set(t,{on:u})),n)},t}function l(){ca.event.stopPropagation(),ca.event.preventDefault()}function f(){for(var n,t=ca.event;n=t.sourceEvent;)t=n;return t}function s(n,t){function e(){n.on(t,null)}n.on(t,function(){l(),e()},!0),setTimeout(e,0)}function h(n){for(var t=new o,e=0,r=arguments.length;++e<r;)t[arguments[e]]=c(t);return t.of=function(e,r){return function(u){try{var i=u.sourceEvent=ca.event;u.target=n,ca.event=u,t[u.type].apply(e,r)}finally{ca.event=i}}},t}function g(n,t){var e=n.ownerSVGElement||n;if(e.createSVGPoint){var r=e.createSVGPoint();if(0>va&&(fa.scrollX||fa.scrollY)){e=ca.select(la.body).append("svg").style("position","absolute").style("top",0).style("left",0);var u=e[0][0].getScreenCTM();va=!(u.f||u.e),e.remove()}return va?(r.x=t.pageX,r.y=t.pageY):(r.x=t.clientX,r.y=t.clientY),r=r.matrixTransform(n.getScreenCTM().inverse()),[r.x,r.y]}var i=n.getBoundingClientRect();return[t.clientX-i.left-n.clientLeft,t.clientY-i.top-n.clientTop]}function p(n){for(var t=-1,e=n.length,r=[];++t<e;)r.push(n[t]);return r}function d(n){return Array.prototype.slice.call(n)}function m(n){return xa(n,ka),n}function v(n){return function(){return ba(n,this)}}function y(n){return function(){return _a(n,this)}}function M(n,t){function e(){this.removeAttribute(n)}function r(){this.removeAttributeNS(n.space,n.local)}function u(){this.setAttribute(n,t)}function i(){this.setAttributeNS(n.space,n.local,t)}function a(){var e=t.apply(this,arguments);null==e?this.removeAttribute(n):this.setAttribute(n,e)}function o(){var e=t.apply(this,arguments);null==e?this.removeAttributeNS(n.space,n.local):this.setAttributeNS(n.space,n.local,e)}return n=ca.ns.qualify(n),null==t?n.local?r:e:"function"==typeof t?n.local?o:a:n.local?i:u}function x(n){return n.trim().replace(/\s+/g," ")}function _(n){return RegExp("(?:^|\\s+)"+ca.requote(n)+"(?:\\s+|$)","g")}function w(n,t){function e(){for(var e=-1;++e<u;)n[e](this,t)}function r(){for(var e=-1,r=t.apply(this,arguments);++e<u;)n[e](this,r)}n=n.trim().split(/\s+/).map(S);var u=n.length;return"function"==typeof t?r:e}function S(n){var t=_(n);return function(e,r){if(u=e.classList)return r?u.add(n):u.remove(n);var u=e.getAttribute("class")||"";r?(t.lastIndex=0,t.test(u)||e.setAttribute("class",x(u+" "+n))):e.setAttribute("class",x(u.replace(t," ")))}}function E(n,t,e){function r(){this.style.removeProperty(n)}function u(){this.style.setProperty(n,t,e)}function i(){var r=t.apply(this,arguments);null==r?this.style.removeProperty(n):this.style.setProperty(n,r,e)}return null==t?r:"function"==typeof t?i:u}function k(n,t){function e(){delete this[n]}function r(){this[n]=t}function u(){var e=t.apply(this,arguments);null==e?delete this[n]:this[n]=e}return null==t?e:"function"==typeof t?u:r}function A(n){return{__data__:n}}function q(n){return function(){return Ea(this,n)}}function N(n){return arguments.length||(n=ca.ascending),function(t,e){return!t-!e||n(t.__data__,e.__data__)}}function T(){}function C(n,t,e){function r(){var t=this[a];t&&(this.removeEventListener(n,t,t.$),delete this[a])}function u(){var u=c(t,ya(arguments));r.call(this),this.addEventListener(n,this[a]=u,u.$=e),u._=t}function i(){var t,e=RegExp("^__on([^.]+)"+ca.requote(n)+"$");for(var r in this)if(t=r.match(e)){var u=this[r];this.removeEventListener(t[1],u,u.$),delete this[r]}}var a="__on"+n,o=n.indexOf("."),c=z;o>0&&(n=n.substring(0,o));var l=Na.get(n);return l&&(n=l,c=D),o?t?u:r:t?T:i}function z(n,t){return function(e){var r=ca.event;ca.event=e,t[0]=this.__data__;try{n.apply(this,t)}finally{ca.event=r}}}function D(n,t){var e=z(n,t);return function(n){var t=this,r=n.relatedTarget;r&&(r===t||r.compareDocumentPosition(t)&8)||e.call(t,n)}}function j(n,t){for(var e=0,r=n.length;r>e;e++)for(var u,i=n[e],a=0,o=i.length;o>a;a++)(u=i[a])&&t(u,a,e);return n}function L(n){return xa(n,Ta),n}function F(){}function H(n,t,e){return new P(n,t,e)}function P(n,t,e){this.h=n,this.s=t,this.l=e}function R(n,t,e){function r(n){return n>360?n-=360:0>n&&(n+=360),60>n?i+(a-i)*n/60:180>n?a:240>n?i+(a-i)*(240-n)/60:i}function u(n){return Math.round(r(n)*255)}var i,a;return n%=360,0>n&&(n+=360),t=0>t?0:t>1?1:t,e=0>e?0:e>1?1:e,a=.5>=e?e*(1+t):e+t-e*t,i=2*e-a,et(u(n+120),u(n),u(n-120))}function O(n){return n>0?1:0>n?-1:0}function Y(n){return Math.acos(Math.max(-1,Math.min(1,n)))}function U(n){return n>1Line truncated
return[u+h*a,c+h*f]}function rr(n,t){var e={list:n.map(function(n,t){return{index:t,x:n[0],y:n[1]}}).sort(function(n,t){return n.y<t.y?-1:n.y>t.y?1:n.x<t.x?-1:n.x>t.x?1:0}),bottomSite:null},r={list:[],leftEnd:null,rightEnd:null,init:function(){r.leftEnd=r.createHalfEdge(null,"l"),r.rightEnd=r.createHalfEdge(null,"l"),r.leftEnd.r=r.rightEnd,r.rightEnd.l=r.leftEnd,r.list.unshift(r.leftEnd,r.rightEnd)},createHalfEdge:function(n,t){return{edge:n,side:t,vertex:null,l:null,r:null}},insert:function(n,t){t.l=n,t.r=n.r,n.r.l=t,n.r=t},leftBound:function(n){var t=r.leftEnd;do t=t.r;while(t!=r.rightEnd&&u.rightOf(t,n));return t=t.l},del:function(n){n.l.r=n.r,n.r.l=n.l,n.edge=null},right:function(n){return n.r},left:function(n){return n.l},leftRegion:function(n){return n.edge==null?e.bottomSite:n.edge.region[n.side]},rightRegion:function(n){return n.edge==null?e.bottomSite:n.edge.region[Po[n.side]]}},u={bisect:function(n,t){var e={region:{l:n,r:t},ep:{l:null,r:null}},r=t.x-n.x,u=t.y-n.y,i=r>0?r:-r,a=u>0?u:-u;return e.c=n.x*r+n.y*u+.5*(r*r+u*u),i>a?(e.a=1,e.b=u/r,e.c/=r):(e.b=1,e.a=r/u,e.c/=u),e},intersect:function(n,t){var e=n.edge,r=t.edge;if(!e||!r||e.region.r==r.region.r)return null;var u=e.a*r.b-e.b*r.a;if(Math.abs(u)<1e-10)return null;var i,a,o=(e.c*r.b-r.c*e.b)/u,c=(r.c*e.a-e.c*r.a)/u,l=e.region.r,f=r.region.r;l.y<f.y||l.y==f.y&&l.x<f.x?(i=n,a=e):(i=t,a=r);var s=o>=a.region.r.x;return s&&i.side==="l"||!s&&i.side==="r"?null:{x:o,y:c}},rightOf:function(n,t){var e=n.edge,r=e.region.r,u=t.x>r.x;if(u&&n.side==="l")return 1;if(!u&&n.side==="r")return 0;if(e.a===1){var i=t.y-r.y,a=t.x-r.x,o=0,c=0;if(!u&&e.b<0||u&&e.b>=0?c=o=i>=e.b*a:(c=t.x+t.y*e.b>e.c,e.b<0&&(c=!c),c||(o=1)),!o){var l=r.x-e.region.l.x;c=e.b*(a*a-i*i)<l*i*(1+2*a/l+e.b*e.b),e.b<0&&(c=!c)}}else{var f=e.c-e.a*t.x,s=t.y-f,h=t.x-r.x,g=f-r.y;c=s*s>h*h+g*g}return n.side==="l"?c:!c},endPoint:function(n,e,r){n.ep[e]=r,n.ep[Po[e]]&&t(n)},distance:function(n,t){var e=n.x-t.x,r=n.y-t.y;return Math.sqrt(e*e+r*r)}},i={list:[],insert:function(n,t,e){n.vertex=t,n.ystar=t.y+e;for(var r=0,u=i.list,a=u.length;a>r;r++){var o=u[r];if(!(n.ystar>o.ystar||n.ystar==o.ystar&&t.x>o.vertex.x))break}u.splice(r,0,n)},del:function(n){for(var t=0,e=i.list,r=e.length;r>t&&e[t]!=n;++t);e.splice(t,1)},empty:function(){return i.list.length===0},nextEvent:function(n){for(var t=0,e=i.list,r=e.length;r>t;++t)if(e[t]==n)return e[t+1];return null},min:function(){var n=i.list[0];return{x:n.vertex.x,y:n.ystar}},extractMin:function(){return i.list.shift()}};r.init(),e.bottomSite=e.list.shift();for(var a,o,c,l,f,s,h,g,p,d,m,v,y,M=e.list.shift();;)if(i.empty()||(a=i.min()),M&&(i.empty()||M.y<a.y||M.y==a.y&&M.x<a.x))o=r.leftBound(M),c=r.right(o),h=r.rightRegion(o),v=u.bisect(h,M),s=r.createHalfEdge(v,"l"),r.insert(o,s),d=u.intersect(o,s),d&&(i.del(o),i.insert(o,d,u.distance(d,M))),o=s,s=r.createHalfEdge(v,"r"),r.insert(o,s),d=u.intersect(s,c),d&&i.insert(s,d,u.distance(d,M)),M=e.list.shift();else{if(i.empty())break;o=i.extractMin(),l=r.left(o),c=r.right(o),f=r.right(c),h=r.leftRegion(o),g=r.rightRegion(c),m=o.vertex,u.endPoint(o.edge,o.side,m),u.endPoint(c.edge,c.side,m),r.del(o),i.del(c),r.del(c),y="l",h.y>g.y&&(p=h,h=g,g=p,y="r"),v=u.bisect(h,g),s=r.createHalfEdge(v,y),r.insert(l,s),u.endPoint(v,Po[y],m),d=u.intersect(l,s),d&&(i.del(l),i.insert(l,d,u.distance(d,h))),d=u.intersect(s,f),d&&i.insert(s,d,u.distance(d,h))}for(o=r.right(r.leftEnd);o!=r.rightEnd;o=r.right(o))t(o.edge)}function ur(n){return n.x}function ir(n){return n.y}function ar(){return{leaf:!0,nodes:[],point:null,x:null,y:null}}function or(n,t,e,r,u,i){if(!n(t,e,r,u,i)){var a=.5*(e+u),o=.5*(r+i),c=t.nodes;c[0]&&or(n,c[0],e,r,a,o),c[1]&&or(n,c[1],a,r,u,o),c[2]&&or(n,c[2],e,o,a,i),c[3]&&or(n,c[3],a,o,u,i)}}function cr(n,t){n=ca.rgb(n),t=ca.rgb(t);var e=n.r,r=n.g,u=n.b,i=t.r-e,a=t.g-r,o=t.b-u;return function(n){return"#"+ut(Math.round(e+i*n))+ut(Math.round(r+a*n))+ut(Math.round(u+o*n))}}function lr(n){var t=[n.a,n.b],e=[n.c,n.d],r=sr(t),u=fr(t,e),i=sr(hr(e,t,-u))||0;t[0]*e[1]<e[0]*t[1]&&(t[0]*=-1,t[1]*=-1,r*=-1,u*=-1),this.rotate=(r?Math.atan2(t[1],t[0]):Math.atan2(-e[0],e[1]))*Ra,this.translate=[n.e,n.f],this.scale=[r,i],this.skew=i?Math.atan2(u,i)*Ra:0}function fr(n,t){return n[0]*t[0]+n[1]*t[1]}function sr(n){var t=Math.sqrt(fr(n,n));return t&&(n[0]/=t,n[1]/=t),t}function hr(n,t,e){return n[0]+=e*t[0],n[1]+=e*t[1],n}function gr(n,t){return t-=n=+n,function(e){return n+t*e}}function pr(n,t){var e,r=[],u=[],i=ca.transform(n),a=ca.transform(t),o=i.translate,c=a.translate,l=i.rotate,f=a.rotate,s=i.skew,h=a.skew,g=i.scale,p=a.scale;return o[0]!=c[0]||o[1]!=c[1]?(r.push("translate(",null,",",null,")"),u.push({i:1,x:gr(o[0],c[0])},{i:3,x:gr(o[1],c[1])})):c[0]||c[1]?r.push("translate("+c+")"):r.push(""),l!=f?(l-f>180?f+=360:f-l>180&&(l+=360),u.push({i:r.push(r.pop()+"rotate(",null,")")-2,x:gr(l,f)})):f&&r.push(r.pop()+"rotate("+f+")"),s!=h?u.push({i:r.push(r.pop()+"skewX(",null,")")-2,x:gr(s,h)}):h&&r.push(r.pop()+"skewX("+h+")"),g[0]!=p[0]||Line truncated
try{ya(la.documentElement.childNodes)[0].nodeType}catch(Ma){ya=p}var xa=[].__proto__?function(n,t){n.__proto__=t}:function(n,t){for(var e in t)n[e]=t[e]};ca.touches=function(n,t){return arguments.length<2&&(t=f().touches),t?ya(t).map(function(t){var e=g(n,t);return e.identifier=t.identifier,e}):[]},ca.behavior.drag=function(){function n(){this.on("mousedown.drag",t).on("touchstart.drag",t)}function t(){function n(){var n=a.parentNode;return null!=f?ca.touches(n).filter(function(n){return n.identifier===f})[0]:ca.mouse(n)}function t(){if(!a.parentNode)return u();var t=n(),e=t[0]-h[0],r=t[1]-h[1];g|=e|r,h=t,l(),o({type:"drag",x:t[0]+i[0],y:t[1]+i[1],dx:e,dy:r})}function u(){o({type:"dragend"}),g&&(l(),ca.event.target===c&&s(p,"click")),p.on(null!=f?"touchmove.drag-"+f:"mousemove.drag",null).on(null!=f?"touchend.drag-"+f:"mouseup.drag",null)}var i,a=this,o=e.of(a,arguments),c=ca.event.target,f=ca.event.touches?ca.event.changedTouches[0].identifier:null,h=n(),g=0,p=ca.select(fa).on(null!=f?"touchmove.drag-"+f:"mousemove.drag",t).on(null!=f?"touchend.drag-"+f:"mouseup.drag",u,!0);r?(i=r.apply(a,arguments),i=[i.x-h[0],i.y-h[1]]):i=[0,0],null==f&&l(),o({type:"dragstart"})}var e=h(n,"drag","dragstart","dragend"),r=null;return n.origin=function(t){return arguments.length?(r=t,n):r},ca.rebind(n,e,"on")};var ba=function(n,t){return t.querySelector(n)},_a=function(n,t){return t.querySelectorAll(n)},wa=la.documentElement,Sa=wa.matchesSelector||wa.webkitMatchesSelector||wa.mozMatchesSelector||wa.msMatchesSelector||wa.oMatchesSelector,Ea=function(n,t){return Sa.call(n,t)};"function"==typeof Sizzle&&(ba=function(n,t){return Sizzle(n,t)[0]||null},_a=function(n,t){return Sizzle.uniqueSort(Sizzle(n,t))},Ea=Sizzle.matchesSelector);var ka=[];ca.selection=function(){return Ca},ca.selection.prototype=ka,ka.select=function(n){var t,e,r,u,i=[];"function"!=typeof n&&(n=v(n));for(var a=-1,o=this.length;++a<o;){i.push(t=[]),t.parentNode=(r=this[a]).parentNode;for(var c=-1,l=r.length;++c<l;)(u=r[c])?(t.push(e=n.call(u,u.__data__,c)),e&&"__data__"in u&&(e.__data__=u.__data__)):t.push(null)}return m(i)},ka.selectAll=function(n){var t,e,r=[];"function"!=typeof n&&(n=y(n));for(var u=-1,i=this.length;++u<i;)for(var a=this[u],o=-1,c=a.length;++o<c;)(e=a[o])&&(r.push(t=ya(n.call(e,e.__data__,o))),t.parentNode=e);return m(r)};var Aa={svg:"http://www.w3.org/2000/svg",xhtml:"http://www.w3.org/1999/xhtml",xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/"};ca.ns={prefix:Aa,qualify:function(n){var t=n.indexOf(":"),e=n;return t>=0&&(e=n.substring(0,t),n=n.substring(t+1)),Aa.hasOwnProperty(e)?{space:Aa[e],local:n}:n}},ka.attr=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node();return n=ca.ns.qualify(n),n.local?e.getAttributeNS(n.space,n.local):e.getAttribute(n)}for(t in n)this.each(M(t,n[t]));return this}return this.each(M(n,t))},ca.requote=function(n){return n.replace(qa,"\\$&")};var qa=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;ka.classed=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node(),r=(n=n.trim().split(/^|\s+/g)).length,u=-1;if(t=e.classList){for(;++u<r;)if(!t.contains(n[u]))return!1}else for(t=e.getAttribute("class");++u<r;)if(!_(n[u]).test(t))return!1;return!0}for(t in n)this.each(w(t,n[t]));return this}return this.each(w(n,t))},ka.style=function(n,t,e){var r=arguments.length;if(3>r){if("string"!=typeof n){2>r&&(t="");for(e in n)this.each(E(e,n[e],t));return this}if(2>r)return fa.getComputedStyle(this.node(),null).getPropertyValue(n);e=""}return this.each(E(n,t,e))},ka.property=function(n,t){if(arguments.length<2){if("string"==typeof n)return this.node()[n];for(t in n)this.each(k(t,n[t]));return this}return this.each(k(n,t))},ka.text=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.textContent=null==t?"":t}:null==n?function(){this.textContent=""}:function(){this.textContent=n}):this.node().textContent},ka.html=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.innerHTML=null==t?"":t}:null==n?function(){this.innerHTML=""}:function(){this.innerHTML=n}):this.node().innerHTML},ka.append=function(n){function t(){return this.appendChild(la.createElementNS(this.namespaceURI,n))}function e(){return this.appendChild(la.createElementNS(n.space,n.local))}return n=ca.ns.qualify(n),this.select(n.local?e:t)},ka.insert=function(n,t){function e(e,r){return this.insertBefore(la.createElementNS(this.namespaceURI,n),t.call(this,e,r))}function r(e,r){return this.insertBefore(la.createElementNS(n.space,n.local),t.call(this,e,r))}return n=ca.ns.qualify(n),"function"!=typeof t&&(t=v(t)),this.select(n.local?r:e)},ka.remove=function(){return this.each(function(){var n=this.parentNode;n&&n.removeChild(this)})},ka.data=function(n,t){function e(n,e){var r,i,a,o=n.length,s=e.length,h=Math.min(o,s),g=Array(s),p=Array(s),d=Array(o);if(tLine truncated
}else n.x=e,n.y=r,n.point=t}else l(n,t,e,r,u,i,a,o)}function l(n,t,e,r,u,a,o,c){var l=.5*(u+o),f=.5*(a+c),s=e>=l,h=r>=f,g=(h<<1)+s;n.leaf=!1,n=n.nodes[g]||(n.nodes[g]=ar()),s?u=l:o=l,h?a=f:c=f,i(n,t,e,r,u,a,o,c)}var f,s,h,g,p,d,m,v,y,M=ft(o),x=ft(c);if(null!=t)d=t,m=e,v=r,y=u;else if(v=y=-(d=m=1/0),s=[],h=[],p=n.length,a)for(g=0;p>g;++g)f=n[g],f.x<d&&(d=f.x),f.y<m&&(m=f.y),f.x>v&&(v=f.x),f.y>y&&(y=f.y),s.push(f.x),h.push(f.y);else for(g=0;p>g;++g){var b=+M(f=n[g],g),_=+x(f,g);d>b&&(d=b),m>_&&(m=_),b>v&&(v=b),_>y&&(y=_),s.push(b),h.push(_)}var w=v-d,S=y-m;w>S?y=m+w:v=d+S;var E=ar();if(E.add=function(n){i(E,n,+M(n,++g),+x(n,g),d,m,v,y)},E.visit=function(n){or(n,E,d,m,v,y)},g=-1,null==t){for(;++g<p;)i(E,n[g],s[g],h[g],d,m,v,y);--g}else n.forEach(E.add);return s=h=n=f=null,E}var a,o=De,c=je;return(a=arguments.length)?(o=ur,c=ir,3===a&&(u=e,r=t,e=t=0),i(n)):(i.x=function(n){return arguments.length?(o=n,i):o},i.y=function(n){return arguments.length?(c=n,i):c},i.size=function(n){return arguments.length?(null==n?t=e=r=u=null:(t=e=0,r=+n[0],u=+n[1]),i):null==t?null:[r,u]},i)},ca.interpolateRgb=cr,ca.transform=function(n){var t=la.createElementNS(ca.ns.prefix.svg,"g");return(ca.transform=function(n){t.setAttribute("transform",n);var e=t.transform.baseVal.consolidate();return new lr(e?e.matrix:Ro)})(n)},lr.prototype.toString=function(){return"translate("+this.translate+")rotate("+this.rotate+")skewX("+this.skew+")scale("+this.scale+")"};var Ro={a:1,b:0,c:0,d:1,e:0,f:0};ca.interpolateNumber=gr,ca.interpolateTransform=pr,ca.interpolateObject=dr,ca.interpolateString=mr;var Oo=/[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g;ca.interpolate=vr,ca.interpolators=[function(n,t){var e=typeof t;return("string"===e||e!==typeof n?Ba.has(t)||/^(#|rgb\(|hsl\()/.test(t)?cr:mr:t instanceof F?cr:"object"===e?Array.isArray(t)?Mr:dr:gr)(n,t)}],ca.interpolateArray=Mr;var Yo=function(){return st},Uo=ca.map({linear:Yo,poly:kr,quad:function(){return wr},cubic:function(){return Sr},sin:function(){return Ar},exp:function(){return qr},circle:function(){return Nr},elastic:Tr,back:Cr,bounce:function(){return zr}}),Io=ca.map({"in":st,out:br,"in-out":_r,"out-in":function(n){return _r(br(n))}});ca.ease=function(n){var t=n.indexOf("-"),e=t>=0?n.substring(0,t):n,r=t>=0?n.substring(t+1):"in";return e=Uo.get(e)||Yo,r=Io.get(r)||st,xr(r(e.apply(null,Array.prototype.slice.call(arguments,1))))},ca.interpolateHcl=Dr,ca.interpolateHsl=jr,ca.interpolateLab=Lr,ca.interpolateRound=Fr,ca.layout={},ca.layout.bundle=function(){return function(n){for(var t=[],e=-1,r=n.length;++e<r;)t.push(Rr(n[e]));return t}},ca.layout.chord=function(){function n(){var n,l,s,h,g,p={},d=[],m=ca.range(i),v=[];for(e=[],r=[],n=0,h=-1;++h<i;){for(l=0,g=-1;++g<i;)l+=u[h][g];d.push(l),v.push(ca.range(i)),n+=l}for(a&&m.sort(function(n,t){return a(d[n],d[t])}),o&&v.forEach(function(n,t){n.sort(function(n,e){return o(u[t][n],u[t][e])})}),n=(2*Fa-f*i)/n,l=0,h=-1;++h<i;){for(s=l,g=-1;++g<i;){var y=m[h],M=v[y][g],x=u[y][M],b=l,_=l+=x*n;p[y+"-"+M]={index:y,subindex:M,startAngle:b,endAngle:_,value:x}}r[y]={index:y,startAngle:s,endAngle:l,value:(l-s)/n},l+=f}for(h=-1;++h<i;)for(g=h-1;++g<i;){var w=p[h+"-"+g],S=p[g+"-"+h];(w.value||S.value)&&e.push(w.value<S.value?{source:S,target:w}:{source:w,target:S})}c&&t()}function t(){e.sort(function(n,t){return c((n.source.value+n.target.value)/2,(t.source.value+t.target.value)/2)})}var e,r,u,i,a,o,c,l={},f=0;return l.matrix=function(n){return arguments.length?(i=(u=n)&&u.length,e=r=null,l):u},l.padding=function(n){return arguments.length?(f=n,e=r=null,l):f},l.sortGroups=function(n){return arguments.length?(a=n,e=r=null,l):a},l.sortSubgroups=function(n){return arguments.length?(o=n,e=null,l):o},l.sortChords=function(n){return arguments.length?(c=n,e&&t(),l):c},l.chords=function(){return e||n(),e},l.groups=function(){return r||n(),r},l},ca.layout.force=function(){function n(n){return function(t,e,r,u){if(t.point!==n){var i=t.cx-n.x,a=t.cy-n.y,o=1/Math.sqrt(i*i+a*a);if(d>(u-e)*o){var c=t.charge*o*o;return n.px-=i*c,n.py-=a*c,!0}if(t.point&&isFinite(o)){var c=t.pointCharge*o*o;n.px-=i*c,n.py-=a*c}}return!t.charge}}function t(n){n.px=ca.event.x,n.py=ca.event.y,o.resume()}var e,r,u,i,a,o={},c=ca.dispatch("start","tick","end"),l=[1,1],f=.9,s=Vo,h=Xo,g=-30,p=.1,d=.8,m=[],v=[];return o.tick=function(){if((r*=.99)<.005)return c.end({type:"end",alpha:r=0}),!0;var t,e,o,s,h,d,y,M,x,b=m.length,_=v.length;for(e=0;_>e;++e)o=v[e],s=o.source,h=o.target,M=h.x-s.x,x=h.y-s.y,(d=M*M+x*x)&&(d=r*i[e]*((d=Math.sqrt(d))-u[e])/d,M*=d,x*=d,h.x-=M*(y=s.weight/(h.weight+s.weight)),h.y-=x*y,s.x+=M*(y=1-y),s.y+=x*y);if((y=r*p)&&(M=l[0]/2,x=l[1]/2,e=-1,y))for(;++e<b;)o=m[e],o.x+=(M-o.x)*y,o.y+=(x-o.y)*y;if(g)for(Zr(t=ca.geom.quadtree(m),r,a),e=-1;++e<b;)(o=m[e]).fixed||t.visit(n(o));for(e=-1;++e<b;)o=m[e],o.fixed?(o.x=o.px,o.y=o.py):(o.x-=(o.px-(o.px=o.x))*f,o.y-=(o.py-(o.py=o.y))*f);c.tick({type:"tick",alpha:r})},o.nodes=function(n){return arguments.length?(m=n,o):m},o.links=function(n){rLine truncated
},n.y=function(t){return arguments.length?(c=t,f=hc[!o<<1|!c],n):c},n.extent=function(t){var e,r,u,a,l;return arguments.length?(i=[[0,0],[0,0]],o&&(e=t[0],r=t[1],c&&(e=e[0],r=r[0]),i[0][0]=e,i[1][0]=r,o.invert&&(e=o(e),r=o(r)),e>r&&(l=e,e=r,r=l),s[0][0]=0|e,s[1][0]=0|r),c&&(u=t[0],a=t[1],o&&(u=u[1],a=a[1]),i[0][1]=u,i[1][1]=a,c.invert&&(u=c(u),a=c(a)),u>a&&(l=u,u=a,a=l),s[0][1]=0|u,s[1][1]=0|a),n):(t=i||s,o&&(e=t[0][0],r=t[1][0],i||(e=s[0][0],r=s[1][0],o.invert&&(e=o.invert(e),r=o.invert(r)),e>r&&(l=e,e=r,r=l))),c&&(u=t[0][1],a=t[1][1],i||(u=s[0][1],a=s[1][1],c.invert&&(u=c.invert(u),a=c.invert(a)),u>a&&(l=u,u=a,a=l))),o&&c?[[e,u],[r,a]]:o?[e,r]:c&&[u,a])},n.clear=function(){return i=null,s[0][0]=s[0][1]=s[1][0]=s[1][1]=0,n},n.empty=function(){return o&&s[0][0]===s[1][0]||c&&s[0][1]===s[1][1]},ca.rebind(n,a,"on")};var sc={n:"ns-resize",e:"ew-resize",s:"ns-resize",w:"ew-resize",nw:"nwse-resize",ne:"nesw-resize",se:"nwse-resize",sw:"nesw-resize"},hc=[["n","e","s","w","nw","ne","se","sw"],["e","w"],["n","s"],[]];ca.time={};var gc=Date,pc=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];Si.prototype={getDate:function(){return this._.getUTCDate()},getDay:function(){return this._.getUTCDay()},getFullYear:function(){return this._.getUTCFullYear()},getHours:function(){return this._.getUTCHours()},getMilliseconds:function(){return this._.getUTCMilliseconds()},getMinutes:function(){return this._.getUTCMinutes()},getMonth:function(){return this._.getUTCMonth()},getSeconds:function(){return this._.getUTCSeconds()},getTime:function(){return this._.getTime()},getTimezoneOffset:function(){return 0},valueOf:function(){return this._.valueOf()},setDate:function(){dc.setUTCDate.apply(this._,arguments)},setDay:function(){dc.setUTCDay.apply(this._,arguments)},setFullYear:function(){dc.setUTCFullYear.apply(this._,arguments)},setHours:function(){dc.setUTCHours.apply(this._,arguments)},setMilliseconds:function(){dc.setUTCMilliseconds.apply(this._,arguments)},setMinutes:function(){dc.setUTCMinutes.apply(this._,arguments)},setMonth:function(){dc.setUTCMonth.apply(this._,arguments)},setSeconds:function(){dc.setUTCSeconds.apply(this._,arguments)},setTime:function(){dc.setTime.apply(this._,arguments)}};var dc=Date.prototype,mc="%a %b %e %X %Y",vc="%m/%d/%Y",yc="%H:%M:%S",Mc=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],xc=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],bc=["January","February","March","April","May","June","July","August","September","October","November","December"],_c=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];ca.time.year=Ei(function(n){return n=ca.time.day(n),n.setMonth(0,1),n},function(n,t){n.setFullYear(n.getFullYear()+t)},function(n){return n.getFullYear()}),ca.time.years=ca.time.year.range,ca.time.years.utc=ca.time.year.utc.range,ca.time.day=Ei(function(n){var t=new gc(1970,0);return t.setFullYear(n.getFullYear(),n.getMonth(),n.getDate()),t},function(n,t){n.setDate(n.getDate()+t)},function(n){return n.getDate()-1}),ca.time.days=ca.time.day.range,ca.time.days.utc=ca.time.day.utc.range,ca.time.dayOfYear=function(n){var t=ca.time.year(n);return Math.floor((n-t-(n.getTimezoneOffset()-t.getTimezoneOffset())*6e4)/864e5)},pc.forEach(function(n,t){n=n.toLowerCase(),t=7-t;var e=ca.time[n]=Ei(function(n){return(n=ca.time.day(n)).setDate(n.getDate()-(n.getDay()+t)%7),n},function(n,t){n.setDate(n.getDate()+Math.floor(t)*7)},function(n){var e=ca.time.year(n).getDay();return Math.floor((ca.time.dayOfYear(n)+(e+t)%7)/7)-(e!==t)});ca.time[n+"s"]=e.range,ca.time[n+"s"].utc=e.utc.range,ca.time[n+"OfYear"]=function(n){var e=ca.time.year(n).getDay();return Math.floor((ca.time.dayOfYear(n)+(e+t)%7)/7)}}),ca.time.week=ca.time.sunday,ca.time.weeks=ca.time.sunday.range,ca.time.weeks.utc=ca.time.sunday.utc.range,ca.time.weekOfYear=ca.time.sundayOfYear,ca.time.format=function(n){function t(t){for(var r,u,i,a=[],o=-1,c=0;++o<e;)n.charCodeAt(o)===37&&(a.push(n.substring(c,o)),(u=Nc[r=n.charAt(++o)])!=null&&(r=n.charAt(++o)),(i=Tc[r])&&(r=i(t,null==u?"e"===r?" ":"0":u)),a.push(r),c=o+1);return a.push(n.substring(c,o)),a.join("")}var e=n.length;return t.parse=function(t){var e={y:1900,m:0,d:1,H:0,M:0,S:0,L:0},r=Ai(e,n,t,0);if(r!=t.length)return null;"p"in e&&(e.H=e.H%12+e.p*12);var u=new gc;return u.setFullYear(e.y,e.m,e.d),u.setHours(e.H,e.M,e.S,e.L),u},t.toString=function(){return n},t};var wc=qi(Mc),Sc=qi(xc),Ec=qi(bc),kc=Ni(bc),Ac=qi(_c),qc=Ni(_c),Nc={"-":"",_:" ",0:"0"},Tc={a:function(n){return xc[n.getDay()]},A:function(n){return Mc[n.getDay()]},b:function(n){return _c[n.getMonth()]},B:function(n){return bc[n.getMonth()]},c:ca.time.format(mc),d:function(n,t){return Ti(n.getDate(),t,2)},e:function(n,t){return Ti(n.getDate(),t,2)},H:function(n,t){return Ti(n.getHours(),t,2)},I:function(n,t){return Ti(n.getHours()%12||12,t,2)},j:function(n,t){return Ti(1+ca.time.dayOfYear(n),t,3)},L:function(n,t){return Ti(n.getMilliseconds(),t,3)},m:function(n,t){return Ti(n.geLine truncated
+1 -1
View File
@@ -16,6 +16,6 @@ var config = new Settings(
kibana_index: "kibana-int",
modules: ['histogram','map','map2','pie','table','stringquery','sort',
'timepicker','text','fields','hits','dashcontrol',
'column'],
'column', 'parallelcoordinates'],
}
);
+74 -62
View File
@@ -5,7 +5,7 @@
"title": "Options",
"height": "50px",
"editable": true,
"collapse": true,
"collapse": false,
"collapsable": true,
"panels": [
{
@@ -28,7 +28,7 @@
"2d",
"5d"
],
"timespan": "15m",
"timespan": "6h",
"timefield": "@timestamp",
"index": "\"logstash-\"yyyy.mm.dd",
"defaultindex": "NOINDEX",
@@ -37,39 +37,7 @@
"enable": false,
"interval": 30,
"min": 3
},
"time": {
"from": "04/03/2013 08:58:07",
"to": "04/03/2013 09:13:07"
}
}
]
},
{
"title": "Query Control",
"height": "50px",
"editable": true,
"collapse": false,
"collapsable": true,
"panels": [
{
"loading": false,
"error": false,
"span": 7,
"editable": true,
"group": [
"default"
],
"type": "stringquery",
"label": "Search",
"query": "",
"size": 100,
"sort": [
"_score",
"desc"
],
"multi": false,
"multi_arrange": "horizontal"
},
{
"loading": false,
@@ -96,29 +64,12 @@
"elasticsearch_saveto": "kibana-int",
"temp": true,
"temp_ttl": "30d"
},
{
"loading": false,
"error": false,
"span": 2,
"editable": true,
"group": [
"default"
],
"type": "hits",
"query": "*",
"style": {
"font-size": "24pt",
"font-weight": "bold"
},
"run_query": false,
"title": "Hits"
}
]
},
{
"title": "Graph",
"height": "150px",
"title": "Query",
"height": "50px",
"editable": true,
"collapse": false,
"collapsable": true,
@@ -131,14 +82,41 @@
"group": [
"default"
],
"type": "stringquery",
"label": "Search",
"query": "*",
"size": 100,
"sort": [
"_score",
"desc"
],
"multi": false,
"multi_arrange": "horizontal"
}
]
},
{
"title": "Graph",
"height": "350px",
"editable": true,
"collapse": false,
"collapsable": true,
"panels": [
{
"loading": false,
"span": 12,
"editable": true,
"group": [
"default"
],
"type": "histogram",
"query": [
{
"query": "",
"label": ""
"query": "*",
"label": "*"
}
],
"interval": "30s",
"interval": "5m",
"show": [
"points",
"lines",
@@ -150,9 +128,43 @@
"spyable": true,
"zoomlinks": true,
"index": [
"logstash-2013.04.03"
"logstash-2013.04.11"
],
"fill": 1
"fill": 0,
"linewidth": 2,
"bars": true,
"stack": true,
"points": false,
"lines": false,
"legend": true,
"x-axis": true,
"y-axis": true
},
{
"loading": false,
"span": 0,
"editable": true,
"group": [
"default"
],
"type": "hits",
"query": [
{
"query": "*",
"label": "*"
}
],
"style": {
"font-size": "9pt"
},
"aggregate": false,
"arrangement": "horizontal",
"chart": true,
"counters": true,
"count_pos": "above",
"index": [
"logstash-2013.04.11"
]
}
]
},
@@ -179,7 +191,7 @@
"@timestamp",
"desc"
],
"query": ""
"query": "*"
},
{
"loading": false,
@@ -190,7 +202,7 @@
"default"
],
"type": "table",
"query": "",
"query": "*",
"interval": "1y",
"show": [
"bars",
@@ -218,11 +230,11 @@
],
"sortable": true,
"index": [
"logstash-2013.04.03"
"logstash-2013.04.11"
]
}
]
}
],
"editable": true
}
}
+4
View File
@@ -22,6 +22,10 @@ angular.module('kibana.fields', [])
$scope.panel.query = docs.query;
$scope.docs = docs.docs;
});
eventBus.register($scope,"get_fields", function(event,id) {
console.log("field.get_fields");
eventBus.broadcast($scope.$id,$scope.panel.group,"selected_fields",$scope.active);
});
}
$scope.reload_list = function () {
+2 -8
View File
@@ -249,7 +249,7 @@ angular.module('kibana.histogram', [])
},
selection: {
mode: "x",
color: '#666'
color: '#999'
},
grid: {
backgroundColor: '#fff',
@@ -258,13 +258,7 @@ angular.module('kibana.histogram', [])
color: "#eee",
hoverable: true,
},
colors: ['#86B22D',
'#BF6730',
'#1D7373',
'#BFB930',
'#BF3030',
'#77207D'
]
colors: ['#86B22D','#BF6730','#1D7373','#BFB930','#BF3030','#77207D']
})
// Work around for missing legend at initialization
+21 -7
View File
@@ -1,18 +1,32 @@
<div ng-controller="hits">
<div class="row-fluid">
<div class="span2 "><label class="small">Font Size</label>
<div class="span3">
<label class="small">Style</label>
<select class="input-small" ng-model="panel.chart" ng-options="f for f in ['bar','pie','list','total']"></select></span>
</div>
<div class="span2" ng-show="panel.chart == 'total' || panel.chart == 'list'">
<label class="small">Font Size</label>
<select class="input-mini" ng-model="panel.style['font-size']" ng-options="f for f in ['7pt','8pt','9pt','10pt','12pt','14pt','16pt','18pt','20pt','24pt','28pt','32pt','36pt','42pt','48pt','52pt','60pt','72pt']"></select></span>
</div>
<div class="span2">
<label class="small">Aggregate</label><input type="checkbox" ng-model="panel.aggregate" ng-checked="panel.aggregate">
<div class="span3" ng-show="panel.chart == 'bar' || panel.chart == 'pie'">
<label class="small">Legend</label>
<select class="input-small" ng-model="panel.counter_pos" ng-options="f for f in ['above','below','none']"></select></span>
</div>
<div class="span3" ng-show="!panel.aggregate"><label class="small">Counter Style</label>
<select class="input-small" ng-model="panel.arrangement" ng-options="f for f in ['none','horizontal','vertical']"></select></span>
<div class="span3" ng-show="panel.chart != 'total' && panel.counter_pos != 'none'">
<label class="small" >List Format</label>
<select class="input-small" ng-model="panel.arrangement" ng-options="f for f in ['horizontal','vertical']"></select></span>
</div>
<div class="span2" ng-show="!panel.aggregate">
<label class="small">Chart</label><input type="checkbox" ng-model="panel.chart" ng-checked="panel.chart">
<div class="span1" ng-show='panel.chart == "pie"'>
<label class="small">Donut</label><input type="checkbox" ng-model="panel.donut" ng-checked="panel.donut">
</div>
<div class="span1" ng-show='panel.chart == "pie"'>
<label class="small">Tilt</label><input type="checkbox" ng-model="panel.tilt" ng-checked="panel.tilt">
</div>
<div class="span1" ng-show='panel.chart == "pie"'>
<label class="small">Labels</label><input type="checkbox" ng-model="panel.labels" ng-checked="panel.labels">
</div>
</div>
<h5>Queries</h5>
<div class="row-fluid">
<div class="span3">
<form style="margin-bottom: 0px">
+37 -9
View File
@@ -1,14 +1,42 @@
<kibana-panel ng-controller='hits' ng-init="init()">
<div ng-show="panel.counters">
<p ng-style="panel.style" ng-show="panel.aggregate">{{hits}}</p>
<table ng-style="panel.style" ng-show="!panel.aggregate && panel.arrangement == 'vertical'">
<tr style="line-height:{{panel.style['font-size']}}" ng-repeat="query in plot.getData()">
<td ng-show="panel.chart" style="background:{{query.color}};width:{{panel.style['font-size']}}"></td> <td style="padding-right:10px;padding-left:10px;">{{query.label}}</td><td>{{query.hits}}</td>
<div ng-show="panel.counter_pos == 'above' && (panel.chart == 'bar' || panel.chart == 'pie')" id='{{$id}}-legend'>
<!-- vertical legend -->
<table class="small" ng-show="panel.arrangement == 'vertical'">
<tr ng-repeat="query in plot.getData()">
<td><div style="display:inline-block;border-radius:5px;background:{{query.color}};height:10px;width:10px"></div></td> <td style="padding-right:10px;padding-left:10px;">{{query.label}}</td><td>{{query.data[0][1]}}</td>
</tr>
</table>
<div ng-style="panel.style" ng-show="!panel.aggregate && panel.arrangement == 'horizontal'" ng-repeat="query in plot.getData()" style="float:left;padding-left: 10px;">
<span ng-show='panel.chart'><div style="display:inline-block;border-radius:{{panel.style['font-size']}};background:{{query.color}};height:{{panel.style['font-size']}};width:{{panel.style['font-size']}}"></div></span> {{query.label}} ({{query.hits}}) <span ng-show="!$last">|</span>
<!-- horizontal legend -->
<div class="small" ng-show="panel.arrangement == 'horizontal'" ng-repeat="query in plot.getData()" style="float:left;padding-left: 10px;">
<span><div style="display:inline-block;border-radius:5px;background:{{query.color}};height:10px;width:10px"></div></span> {{query.label}} ({{query.data[0][1]}}) </span>
</div><br>
</div><div style="clear:both"></div>
<div ng-show='panel.chart && !panel.aggregate ' hits-chart params="{{panel}}" style="height:{{panel.height || row.height}};position:relative"></div>
</div>
<div style="clear:both"></div>
<div ng-show="panel.chart == 'pie' || panel.chart == 'bar'" hits-chart params="{{panel}}" style="height:{{panel.height || row.height}};position:relative"></div>
<div ng-show="panel.counter_pos == 'below' && (panel.chart == 'bar' || panel.chart == 'pie')" id='{{$id}}-legend'>
<!-- vertical legend -->
<table class="small" ng-show="panel.arrangement == 'vertical'">
<tr ng-repeat="query in plot.getData()">
<td><div style="display:inline-block;border-radius:5px;background:{{query.color}};height:10px;width:10px"></div></td> <td style="padding-right:10px;padding-left:10px;">{{query.label}}</td><td>{{query.data[0][1]}}</td>
</tr>
</table>
<!-- horizontal legend -->
<div class="small" ng-show="panel.arrangement == 'horizontal'" ng-repeat="query in plot.getData()" style="float:left;padding-left: 10px;">
<span><div style="display:inline-block;border-radius:5px;background:{{query.color}};height:10px;width:10px"></div></span> {{query.label}} ({{query.data[0][1]}}) </span>
</div><br>
</div>
<div ng-show="panel.chart == 'total'"><div ng-style="panel.style" style="line-height:{{panel.style['font-size']}}">{{hits}}</div></div>
<span ng-show="panel.chart == 'list'"><span ng-style="panel.style" style="line-height:{{panel.style['font-size']}}" ng-repeat="query in data">{{query.label}} ({{query.hits}})<span></span><br ng-show="panel.arrangement == 'vertical' && panel.chart == 'list'">
</kibana-panel>
+64 -27
View File
@@ -8,9 +8,11 @@ angular.module('kibana.hits', [])
style : { "font-size": '10pt'},
aggregate : true,
arrangement : 'vertical',
chart : true,
counters: true,
count_pos: 'above'
chart : 'none',
counter_pos : 'above',
donut : false,
tilt : false,
labels : true
}
_.defaults($scope.panel,_d)
@@ -96,7 +98,6 @@ angular.module('kibana.hits', [])
i++;
});
$scope.$emit('render');
if(_segment < $scope.panel.index.length-1)
$scope.get_data(_segment+1,query_id)
@@ -143,31 +144,65 @@ angular.module('kibana.hits', [])
function render_panel() {
var scripts = $LAB.script("common/lib/panels/jquery.flot.js")
// Populate element. Note that jvectormap appends, does not replace.
.script("common/lib/panels/jquery.flot.pie.js")
// Populate element.
scripts.wait(function(){
// Populate element
try {
// Add plot to scope so we can build out own legend
scope.plot = $.plot(elem, scope.data, {
legend: { show: false },
series: {
lines: { show: false, },
bars: { show: true, fill: 1, barWidth: 0.8, horizontal: false },
shadowSize: 1
},
yaxis: { show: true, min: 0, color: "#000" },
xaxis: { show: false },
grid: {
backgroundColor: '#fff',
borderWidth: 0,
borderColor: '#eee',
color: "#eee",
hoverable: true,
},
colors: ['#86B22D','#BF6730','#1D7373','#BFB930','#BF3030','#77207D']
})
if(scope.panel.chart === 'bar')
scope.plot = $.plot(elem, scope.data, {
legend: { show: false },
series: {
lines: { show: false, },
bars: { show: true, fill: 1, barWidth: 0.8, horizontal: false },
shadowSize: 1
},
yaxis: { show: true, min: 0, color: "#000" },
xaxis: { show: false },
grid: {
backgroundColor: '#fff',
borderWidth: 0,
borderColor: '#eee',
color: "#eee",
hoverable: true,
},
colors: ['#86B22D','#BF6730','#1D7373','#BFB930','#BF3030','#77207D']
})
if(scope.panel.chart === 'pie')
scope.plot = $.plot(elem, scope.data, {
legend: { show: false },
series: {
pie: {
innerRadius: scope.panel.donut ? 0.4 : 0,
tilt: scope.panel.tilt ? 0.45 : 1,
radius: 1,
show: true,
combine: {
color: '#999',
label: 'The Rest'
},
label: {
show: scope.panel.labels,
radius: 2/3,
formatter: function(label, series){
return '<div ng-click="build_search(panel.query.field,\''+label+'\') "style="font-size:8pt;text-align:center;padding:2px;color:white;">'+
label+'<br/>'+Math.round(series.percent)+'%</div>';
},
threshold: 0.1
}
}
},
//grid: { hoverable: true, clickable: true },
grid: { hoverable: true, clickable: true },
colors: ['#86B22D','#BF6730','#1D7373','#BFB930','#BF3030','#77207D']
});
// Compensate for the height of the legend. Gross
elem.height(
(scope.panel.height || scope.row.height).replace('px','') - $("#"+scope.$id+"-legend").height())
// Work around for missing legend at initialization
if(!scope.$$phase)
scope.$apply()
@@ -198,9 +233,11 @@ angular.module('kibana.hits', [])
elem.bind("plothover", function (event, pos, item) {
if (item) {
var value = scope.panel.chart === 'bar' ?
item.datapoint[1] : item.datapoint[1][0][1];
tt(pos.pageX, pos.pageY,
"<div style='vertical-align:middle;border-radius:10px;display:inline-block;background:"+item.series.color+";height:20px;width:20px'></div> "+
item.datapoint[1].toFixed(0))
"<div style='vertical-align:middle;border-radius:10px;display:inline-block;background:"+
item.series.color+";height:20px;width:20px'></div> "+value.toFixed(0))
} else {
$("#pie-tooltip").remove();
}
+1 -1
View File
@@ -82,7 +82,7 @@ angular.module('kibana.map', [])
$scope.build_search = function(field,value) {
$scope.panel.query = add_to_query($scope.panel.query,field,value,false)
$scope.get_data();
eventBus.broadcast($scope.$id,$scope.panel.group,'query',$scope.panel.query);
eventBus.broadcast($scope.$id,$scope.panel.group,'query',[$scope.panel.query]);
}
})
+21
View File
@@ -0,0 +1,21 @@
<div class="row-fluid" ng-controller="parallelcoordinates">
<div style="width:90%">
<form class="input-append">
<h6>Query</h6>
<input type="text" style="width:90%" ng-model="panel.query">
<button class="btn" ng-click="get_data();"><i class="icon-search"></i></button>
</form>
</div>
</div>
<h5>Panel Spy</h5>
<div class="row-fluid">
<div class="span2">
<label class="small"> Spyable </label><input type="checkbox" ng-model="panel.spyable" ng-checked="panel.spyable">
</div>
<div class="span9 small">
The panel spy shows 'behind the scenes' information about a panel. It can
be accessed by clicking the <i class='icon-eye-open'></i> in the top right
of the panel.
</div>
</div>
+42
View File
@@ -0,0 +1,42 @@
<style>
svg {
font-size: 14px;
}
.foregroundlines {
fill: none;
stroke-opacity: 0.3;
stroke-width: 1.5px;
}
.foregroundlines.fade {
display:none
}
.legend line {
stroke-width: 2px;
}
.brush .extent {
fill-opacity: .3;
stroke: #fff;
shape-rendering: crispEdges;
}
.axis line, .axis path {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.axis text {
text-shadow: 0 1px 0 #fff;
cursor: move;
}
</style>
<kibana-panel ng-controller='parallelcoordinates' ng-init="init()">
<span ng-show="panel.spyable" style="position:absolute;right:0px;top:0px" class='panelextra pointer'>
<i bs-modal="'partials/modal.html'" class="icon-eye-open"></i>
</span>
<div parallelcoordinates params="{{panel}}" style="height:{{panel.height || row.height}}"></div>
</kibana-panel>
+444
View File
@@ -0,0 +1,444 @@
angular.module('kibana.parallelcoordinates', [])
.controller('parallelcoordinates', function ($scope, eventBus) {
$scope.activeDocs = [];
// Set and populate defaults
var _d = {
query : "*",
size : 100, // Per page
pages : 5, // Pages available
offset : 0,
sort : ['@timestamp','desc'],
group : "default",
style : {'font-size': '9pt'},
fields : [],
sortable: true,
spyable: true
}
_.defaults($scope.panel, _d)
$scope.init = function () {
$scope.set_listeners($scope.panel.group);
// Now that we're all setup, request the time from our group
eventBus.broadcast($scope.$id,$scope.panel.group,"get_time")
//and get the currently selected fields
eventBus.broadcast($scope.$id,$scope.panel.group,"get_fields")
};
$scope.set_listeners = function(group) {
eventBus.register($scope,'time',function(event,time) {
$scope.panel.offset = 0;
set_time(time)
});
eventBus.register($scope,'query',function(event,query) {
$scope.panel.offset = 0;
$scope.panel.query = _.isArray(query) ? query[0] : query;
$scope.get_data();
});
eventBus.register($scope,'sort', function(event,sort){
$scope.panel.sort = _.clone(sort);
$scope.get_data();
});
eventBus.register($scope,'selected_fields', function(event, fields) {
$scope.panel.fields = _.clone(fields)
$scope.$emit('render');
});
};
$scope.get_data = function (segment,query_id) {
// Make sure we have everything for the request to complete
if (_.isUndefined($scope.panel.index) || _.isUndefined($scope.time))
return;
var _segment = _.isUndefined(segment) ? 0 : segment
$scope.segment = _segment;
$scope.panel.loading = true;
var request = $scope.ejs.Request().indices($scope.panel.index[_segment])
.query(ejs.FilteredQuery(
ejs.QueryStringQuery($scope.panel.query || '*'),
ejs.RangeFilter($scope.time.field)
.from($scope.time.from)
.to($scope.time.to)
)
)
.size($scope.panel.size*$scope.panel.pages)
.sort($scope.panel.sort[0],$scope.panel.sort[1]);
$scope.populate_modal(request);
var results = request.doSearch();
// Populate scope when we have results
results.then(function (results) {
$scope.panel.loading = false;
if(_segment === 0) {
$scope.hits = 0;
$scope.data = [];
query_id = $scope.query_id = new Date().getTime()
}
// Check for error and abort if found
if(!(_.isUndefined(results.error))) {
$scope.panel.error = $scope.parse_error(results.error);
return;
}
// Check that we're still on the same query, if not stop
if($scope.query_id === query_id) {
$scope.data= $scope.data.concat(_.map(results.hits.hits, function(hit) {
return flatten_json(hit['_source']);
}));
$scope.hits += results.hits.total;
// Sort the data
$scope.data = _.sortBy($scope.data, function(v){
return v[$scope.panel.sort[0]]
});
// Reverse if needed
if($scope.panel.sort[1] == 'desc')
$scope.data.reverse();
// Keep only what we need for the set
$scope.data = $scope.data.slice(0,$scope.panel.size * $scope.panel.pages)
} else {
return;
}
$scope.$emit('render')
});
};
// I really don't like this function, too much dom manip. Break out into directive?
$scope.populate_modal = function (request) {
$scope.modal = {
title: "Inspector",
body: "<h5>Last Elasticsearch Query</h5><pre>" + 'curl -XGET ' + config.elasticsearch + '/' + $scope.panel.index + "/_search?pretty -d'\n" + angular.toJson(JSON.parse(request.toString()), true) + "'</pre>"
}
};
function set_time(time) {
$scope.time = time;
$scope.panel.index = _.isUndefined(time.index) ? $scope.panel.index : time.index
$scope.get_data();
}
$scope.$watch('activeDocs', function(v) {
eventBus.broadcast($scope.$id,$scope.panel.group,"table_documents",
{query:$scope.panel.query,docs:$scope.activeDocs});
});
})
.directive('parallelcoordinates', function () {
return {
restrict: 'A',
link: function (scope, elem, attrs) {
//used to store a variety of directive-level variables
var directive = {};
scope.initializing = false;
/**
* Initialize the panels if new, or render existing panels
*/
scope.init_or_render = function() {
if (typeof directive.svg === 'undefined') {
//prevent duplicate initialization steps, if render is called again
//before the svg is setup
if (!scope.initializing) {
init_panel();
}
} else {
render_panel();
}
};
/**
* Receive render events
*/
scope.$on('render', function () {
scope.init_or_render();
});
/**
* On window resize, re-render the panel
*/
angular.element(window).bind('resize', function () {
scope.init_or_render();
});
/**
* Load the various panel-specific scripts then initialize
* the svg and set appropriate D3 settings
*/
function init_panel() {
directive.m = [80, 100, 80, 100];
directive.w = $(elem[0]).width() - directive.m[1] - directive.m[3];
directive.h = $(elem[0]).height() - directive.m[0] - directive.m[2];
scope.initializing = true;
// Using LABjs, wait until all scripts are loaded before rendering panel
var scripts = $LAB.script("common/lib/d3.v3.min.js?rand="+Math.floor(Math.random()*10000));
scripts.wait(function () {
directive.x = d3.scale.ordinal().domain(scope.panel.fields).rangePoints([0, directive.w]);
directive.y = {};
directive.line = d3.svg.line().interpolate('cardinal');
directive.axis = d3.svg.axis().orient("left");
var viewbox = "0 0 " + (directive.w + directive.m[1] + directive.m[3]) + " " + (directive.h + directive.m[0] + directive.m[2]);
directive.svg = d3.select(elem[0]).append("svg")
.attr("width", "100%")
.attr("height", "100%")
.attr("viewbox", viewbox)
.append("svg:g")
.attr("transform", "translate(" + directive.m[3] + "," + directive.m[0] + ")");
// Add foreground lines.
directive.foreground = directive.svg.append("svg:g")
.attr("class", "foreground");
scope.initializing = false;
render_panel();
});
}
// Returns the path for a given data point.
function path(d) {
return directive.line(scope.panel.fields.map(function(p) { return [directive.x(p), directive.y[p](d[p])]; }));
}
// Handles a brush event, toggling the display of foreground lines.
function brush() {
var actives = scope.panel.fields.filter(function(p) { return !directive.y[p].brush.empty(); }),
extents = actives.map(function(p) { return directive.y[p].brush.extent(); });
//.fade class hides the "inactive" lines, helps speed up rendering significantly
directive.foregroundLines.classed("fade", function(d) {
return !actives.every(function(p, i) {
var inside = extents[i][0] <= d[p] && d[p] <= extents[i][1];
return inside;
});
});
//activeDocs contains the actual doc records for selected lines.
//will be broadcast out to the table
var activeDocs = _.filter(scope.data, function(v) {
return actives.every(function(p,i) {
var inside = extents[i][0] <= v[p] && v[p] <= extents[i][1];
return inside;
});
})
scope.$apply(function() {
scope.activeDocs = activeDocs;
});
}
//Drag functions are used for dragging the axis aroud
function dragstart(d) {
directive.i = scope.panel.fields.indexOf(d);
}
function drag(d) {
directive.x.range()[directive.i] = d3.event.x;
scope.panel.fields.sort(function(a, b) { return directive.x(a) - directive.x(b); });
directive.foregroundLines.attr("transform", function(d) { return "translate(" + directive.x(d) + ")"; });
directive.traits.attr("transform", function(d) { return "translate(" + directive.x(d) + ")"; });
directive.brushes.attr("transform", function(d) { return "translate(" + directive.x(d) + ")"; });
directive.axisLines.attr("transform", function(d) { return "translate(" + directive.x(d) + ")"; });
directive.foregroundLines.attr("d", path);
}
function dragend(d) {
directive.x.domain(scope.panel.fields).rangePoints([0, directive.w]);
var t = d3.transition().duration(500);
t.selectAll(".trait").attr("transform", function(d) { return "translate(" + directive.x(d) + ")"; });
t.selectAll(".axis").attr("transform", function(d) { return "translate(" + directive.x(d) + ")"; });
t.selectAll(".brush").attr("transform", function(d) { return "translate(" + directive.x(d) + ")"; });
t.selectAll(".foregroundlines").attr("d", path);
}
/**
* Render updates to the SVG. Typically happens when the data changes (time, query)
* or when new options are selected
*/
function render_panel() {
//update the svg if the size has changed
directive.w = $(elem[0]).width() - directive.m[1] - directive.m[3];
directive.h = $(elem[0]).height() - directive.m[0] - directive.m[2];
directive.svg.attr("viewbox", "0 0 " + (directive.w + directive.m[1] + directive.m[3]) + " " + (directive.h + directive.m[0] + directive.m[2]));
directive.x = d3.scale.ordinal().domain(scope.panel.fields).rangePoints([0, directive.w]);
directive.y = {};
directive.line = d3.svg.line().interpolate('cardinal');
directive.axis = d3.svg.axis().orient("left");
var colorExtent = d3.extent(scope.data, function(p) { return +p[scope.panel.fields[0]]; });
directive.colors = d3.scale.linear()
.domain([colorExtent[0],colorExtent[1]])
.range(["#4580FF", "#FF9245"]);
scope.panel.fields.forEach(function(d) {
//If it is a string, setup an ordinal scale.
//Otherwise, use a linear scale for numbers
if (_.isString(scope.data[0][d])) {
var value = function(v) { return v[d]; };
var values = _.map(_.uniq(scope.data, value),value);
directive.y[d] = d3.scale.ordinal()
.domain(values)
.rangeBands([directive.h, 0]);
} else if (_.isNumber(scope.data[0][d])) {
directive.y[d] = d3.scale.linear()
.domain(d3.extent(scope.data, function(p) { return +p[d]; }))
.range([directive.h, 0]);
}
directive.y[d].brush = d3.svg.brush()
.y(directive.y[d])
.on("brush", brush);
});
//pull out the actively selected columns for rendering the axis/lines
var activeData = _.map(scope.data, function(d) {
var t = {};
_.each(scope.panel.fields, function(f) {
t[f] = d[f];
});
return t;
});
//Lines
directive.foregroundLines = directive.foreground
.selectAll(".foregroundlines")
.data(activeData, function(d, i){
var id = "";
_.each(d, function(v) {
id += i + "_" + v;
});
return id;
});
directive.foregroundLines
.enter().append("svg:path")
.attr("d", path)
.attr("class", "foregroundlines")
.attr("style", function(d) {
return "stroke:" + directive.colors(d[scope.panel.fields[0]]) + ";";
});
directive.foregroundLines.exit().remove();
//Axis group
directive.traits = directive.svg.selectAll(".trait")
.data(scope.panel.fields, String);
directive.traits
.enter().append("svg:g")
.attr("class", "trait")
.attr("transform", function(d) { return "translate(" + directive.x(d) + ")"; });
directive.traits
.exit().remove();
//brushes used to select lines
directive.brushes = directive.svg.selectAll(".brush")
.data(scope.panel.fields, String);
directive.brushes
.enter()
.append("svg:g")
.attr("class", "brush")
.each(function(d) {
d3.select(this)
.call(directive.y[d].brush)
.attr("transform", function(d) { return "translate(" + directive.x(d) + ")"; });
})
.selectAll("rect")
.attr("x", -8)
.attr("width", 16);
//this section is repeated because enter() only works on "new" data, but we always need to
//update the brushes if things change. This just calls the brushing function, so it doesn't
//affect currently active rects
directive.brushes
.each(function(d) {
d3.select(this)
.call(directive.y[d].brush)
.attr("transform", function(d) { return "translate(" + directive.x(d) + ")"; });
});
directive.brushes
.exit().remove();
//vertical axis and labels
directive.axisLines = directive.svg.selectAll(".axis")
.data(scope.panel.fields, String);
directive.axisLines
.enter()
.append("svg:g")
.attr("class", "axis")
.each(function(d) {
d3.select(this)
.call(directive.axis.scale(directive.y[d]))
.attr("transform", function(d) { return "translate(" + directive.x(d) + ")"; });
}).call(d3.behavior.drag()
.origin(function(d) { return {x: directive.x(d)}; })
.on("dragstart", dragstart)
.on("drag", drag)
.on("dragend", dragend))
.append("svg:text")
.attr("text-anchor", "middle")
.attr("y", -9)
.text(String);
directive.axisLines
.exit().remove();
//Simulate a dragend in case there is new data and we need to rearrange
dragend();
}
}
};
});
+24 -54
View File
@@ -1,28 +1,32 @@
<div class="row-fluid" ng-switch="panel.mode" ng-controller="pie">
<div ng-switch-when="terms">
<div class="row-fluid">
<div class="span4">
<div class="row-fluid">
<div class="span3">
<label class="small">Mode</label>
<select class="input-small" ng-change="set_mode(panel.mode)" ng-model="panel.mode" ng-options="f for f in ['terms','goal']"></select>
</div>
<div class="span3">
<form style="margin-bottom: 0px">
<h6> Field</h6>
<label class="small">Field</label>
<input type="text" style="width:90%" bs-typeahead="fields.list" ng-model="panel.query.field">
</form>
</div>
<div class="span8">
<div class="span5">
<form class="input-append" style="margin-bottom: 0px">
<h6>Query</h6>
<label class="small">Query</label>
<input type="text" style="width:80%" ng-model="panel.query.query">
<button class="btn" ng-click="get_data()"><i class="icon-search"></i></button>
</form>
</div>
</div>
<div class="row-fluid">
<div class="span1">
<h6>Length</h6>
<div class="span3">
<label class="small">Length</label>
<input type="number" style="width:80%" ng-model="panel.size" ng-change="get_data()">
</div>
<div class="span11">
<div class="span8">
<form class="input-append" style="margin-bottom: 0px">
<h6>Exclude Terms(s) (comma seperated)</h6>
<label class="small">Exclude Terms(s) (comma seperated)</label>
<input array-join type="text" style="width:90%" ng-model='panel.exclude'></input>
<button class="btn" ng-click="get_data()"><i class="icon-search"></i></button>
</form>
@@ -30,57 +34,26 @@
</div>
</div>
<div ng-switch-when="goal">
<div class="row-fluid">
<div class="row-fluid">
<div class="span3">
<label class="small">Mode</label>
<select class="input-small" ng-change="set_mode(panel.mode)" ng-model="panel.mode" ng-options="f for f in ['terms','goal']"></select>
</div>
<div class="span2">
<form style="margin-bottom: 0px">
<h6>Goal</h6>
<label class="small">Goal</label>
<input type="number" style="width:90%" ng-model="panel.query.goal">
</form>
</div>
<div class="span9">
<div class="span5">
<form class="input-append" style="margin-bottom: 0px">
<h6>Query</h6>
<label class="small">Query</label>
<input type="text" style="width:80%" ng-model="panel.query.query">
<button class="btn" ng-click="get_data()"><i class="icon-search"></i></button>
</form>
</div>
</div>
</div>
<div ng-switch-when="query">
<div class="row-fluid">
<div class="span3">
<form style="margin-bottom: 0px">
<h6>Label</h6>
<input type="text" placeholder="New Label" style="width:70%" ng-model="newlabel">
</form>
</div>
<div class="span8">
<form class="input-append" style="margin-bottom: 0px">
<h6>Query</h6>
<input type="text" placeholder="New Query" style="width:80%" ng-model="newquery">
<button class="btn" ng-click="add_query(newlabel,newquery);newlabel='';newquery=''"><i class="icon-plus"></i></button>
</form>
</div>
<div class="span1">
</div>
</div>
<div class="row-fluid" ng-repeat="q in panel.query">
<div class="span3">
<form style="margin-bottom: 0px">
<input type="text" style="width:70%" ng-model="q.label">
</form>
</div>
<div class="span8">
<form class="input-append" style="margin-bottom: 0px">
<input type="text" style="width:80%" ng-model="q.query">
<button class="btn" ng-click="get_data()"><i class="icon-search"></i></button>
</form>
</div>
<div class="span1">
<i class="icon-remove pointer" ng-click="remove_query(q)"></i>
</div>
</div>
</div>
</div>
<div class="row-fluid">
<div class="span1">
@@ -89,15 +62,12 @@
<div class="span1">
<label class="small"> Tilt </label><input type="checkbox" ng-model="panel.tilt" ng-checked="panel.tilt">
</div>
<div class="span1">
<label class="small"> Legend </label><input type="checkbox" ng-model="panel.legend" ng-checked="panel.legend">
</div>
<div class="span1">
<label class="small"> Labels </label><input type="checkbox" ng-model="panel.labels" ng-checked="panel.labels">
</div>
<div class="span2">
<label class="small">Mode</label>
<select class="input-small" ng-change="set_mode(panel.mode)" ng-model="panel.mode" ng-options="f for f in ['query','terms','goal']"></select>
<div class="span3">
<label class="small">Legend</label>
<select class="input-small" ng-model="panel.legend" ng-options="f for f in ['above','below','none']"></select></span>
</div>
</div>
<h5>Panel Spy</h5>
+10 -6
View File
@@ -2,11 +2,15 @@
<span ng-show='panel.spyable' style="position:absolute;right:0px;top:0px" class='panelextra pointer'>
<i bs-modal="'partials/modal.html'" class="icon-eye-open"></i>
</span>
<span ng-show="panel.legend" ng-repeat='series in legend' style='padding-right:5px'>
<div style='white-space:nowrap;display:table-cell'>
<div style="display:inline-block;background:{{series.color}};height:10px;width:10px;border-radius:5px;"></div>
<div class='small' style='display:inline-block'>{{series.label}} ({{series.percent}}%)</div>
</div>
</span>
<div ng-show="panel.legend == 'above'" ng-repeat="query in plot.getData()" style="float:left;padding-left: 10px;">
<span ng-show='panel.chart != "none"'><div style="display:inline-block;border-radius:5px;background:{{query.color}};height:10px;width:10px"></div></span><span class="small"> {{query.label}} ({{query.data[0][1]}}) </span></span>
</div><br>
<div style="clear:both"></div>
<div pie params="{{panel}}" style="height:{{panel.height || row.height}};position:relative"></div>
<div ng-show="panel.legend == 'below'" ng-repeat="query in plot.getData()" style="float:left;padding-left: 10px;">
<span ng-show='panel.chart != "none"'><div style="display:inline-block;border-radius:5px;background:{{query.color}};height:10px;width:10px"></div></span><span class="small"> {{query.label}} ({{query.data[0][1]}}) </span></span>
</div>
</kibana-panel>
+8 -68
View File
@@ -12,7 +12,7 @@ angular.module('kibana.pie', [])
labels : true,
mode : "terms",
group : "default",
default_field : '_all',
default_field : 'DEFAULT',
spyable : true,
}
_.defaults($scope.panel,_d)
@@ -20,16 +20,7 @@ angular.module('kibana.pie', [])
$scope.init = function() {
eventBus.register($scope,'time', function(event,time){set_time(time)});
eventBus.register($scope,'query', function(event, query) {
if($scope.panel.mode !== 'query') {
$scope.panel.query.query = query;
$scope.panel.query.query = _.isArray(query) ? query[0] : query;
} else {
if(_.isArray(query))
$scope.panel.query = _.map(query,function(q) {
return {query: q, label: q}})
else
$scope.panel.query[0] = {query: query, label: query}
}
$scope.panel.query.query = _.isArray(query) ? query[0] : query;
$scope.get_data();
});
// Now that we're all setup, request the time from our group
@@ -60,9 +51,6 @@ angular.module('kibana.pie', [])
case 'terms':
$scope.panel.query = {query:"*",field:"_all"};
break;
case 'query':
$scope.panel.query = [{query:"*",label:"*"}];
break;
case 'goal':
$scope.panel.query = {query:"*",goal:100};
break;
@@ -77,49 +65,8 @@ angular.module('kibana.pie', [])
$scope.panel.loading = true;
var request = $scope.ejs.Request().indices($scope.panel.index);
// If we have an array, use query facet
if($scope.panel.mode == "query") {
if(!(_.isArray($scope.panel.query)))
$scope.panel.query = [$scope.panel.query];
var queries = [];
// Build the question part of the query
_.each($scope.panel.query, function(v) {
queries.push(ejs.FilteredQuery(
ejs.QueryStringQuery(v.query || '*'),
ejs.RangeFilter($scope.time.field)
.from($scope.time.from)
.to($scope.time.to))
)
});
// Then the insert into facet and make the request
_.each(queries, function(v) {
request = request.facet(ejs.QueryFacet(_.indexOf(queries,v))
.query(v)
.facetFilter(ejs.QueryFilter(v))
)
})
$scope.populate_modal(request);
var results = request.doSearch();
// Populate scope when we have results
results.then(function(results) {
$scope.panel.loading = false;
$scope.hits = results.hits.total;
$scope.data = [];
_.each(results.facets, function(v, k) {
var series = {};
var label = _.isUndefined($scope.panel.query[k].label) ?
$scope.panel.query[k].query : $scope.panel.query[k].label
var slice = { label : label, data : v.count };
if (!(_.isUndefined($scope.panel.query[k].color)))
slice.color = $scope.panel.query[k].color;
$scope.data.push(slice)
});
$scope.$emit('render');
});
// If we don't have an array, assume its a term facet.
} else if ($scope.panel.mode == "terms") {
// Terms mode
if ($scope.panel.mode == "terms") {
request = request
.facet(ejs.TermsFacet('pie')
.field($scope.panel.query.field || $scope.panel.default_field)
@@ -131,7 +78,6 @@ angular.module('kibana.pie', [])
ejs.RangeFilter($scope.time.field)
.from($scope.time.from)
.to($scope.time.to)
.cache(false)
)))).size(0)
$scope.populate_modal(request);
@@ -157,6 +103,7 @@ angular.module('kibana.pie', [])
});
$scope.$emit('render');
});
// Goal mode
} else {
request = request
.query(ejs.QueryStringQuery($scope.panel.query.query || '*'))
@@ -175,7 +122,7 @@ angular.module('kibana.pie', [])
var complete = results.hits.total;
var remaining = $scope.panel.query.goal - complete;
$scope.data = [
{ label : 'Complete', data : complete, color: '#51A351' },
{ label : 'Complete', data : complete, color: '#86B22D' },
{ data : remaining, color: '#EEE'}]
$scope.$emit('render');
});
@@ -196,7 +143,7 @@ angular.module('kibana.pie', [])
$scope.build_search = function(field,value) {
$scope.panel.query.query = add_to_query($scope.panel.query.query,field,value,false)
$scope.get_data();
eventBus.broadcast($scope.$id,$scope.panel.group,'query',$scope.panel.query.query);
eventBus.broadcast($scope.$id,$scope.panel.group,'query',[$scope.panel.query.query]);
}
function set_time(time) {
@@ -275,14 +222,7 @@ angular.module('kibana.pie', [])
// Populate element
if(elem.is(":visible")){
scripts.wait(function(){
var plot = $.plot(elem, scope.data, pie);
scope.legend = [];
_.each(plot.getData(),function(series) {
var item = _.pick(series,'label','color','percent')
item.percent = parseFloat(item.percent).toFixed(1)
scope.legend.push(item)
})
console.log(scope.legend)
scope.plot = $.plot(elem, scope.data, pie);
});
}
}
+5 -11
View File
@@ -13,24 +13,18 @@ angular.module('kibana.stringquery', [])
}
_.defaults($scope.panel,_d);
var _groups = _.isArray($scope.panel.group) ?
$scope.panel.group : [$scope.panel.group];
$scope.init = function() {
// I don't like this compromise. I'm not totally sure what this panel
// Should do if its in multi query mode and receives a query. For now, just
// replace the first one, though I feel like that isn't right.
// If we're in multi query mode, they all get wiped out if we receive a
// query. Query events must be exchanged as arrays.
eventBus.register($scope,'query',function(event,query) {
if (_.isArray($scope.panel.query))
$scope.panel.query[0] = query
else
$scope.panel.query = query;
});
}
$scope.send_query = function(query) {
eventBus.broadcast($scope.$id,$scope.panel.group,'query',query)
var _query = _.isArray(query) ? query : [query]
eventBus.broadcast($scope.$id,$scope.panel.group,'query',_query)
}
$scope.add_query = function() {
@@ -40,7 +34,7 @@ angular.module('kibana.stringquery', [])
$scope.panel.query = new Array($scope.panel.query)
$scope.panel.query.push("")
}
}
}
$scope.set_multi = function(multi) {
$scope.panel.query = multi ?
+4
View File
@@ -40,6 +40,10 @@ angular.module('kibana.table', [])
eventBus.register($scope,'selected_fields', function(event, fields) {
$scope.panel.fields = _.clone(fields)
});
eventBus.register($scope,'table_documents', function(event, docs) {
$scope.panel.query = docs.query;
$scope.data = docs.docs;
});
}
$scope.set_sort = function(field) {