module.js 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. angular.module('kibana.hits', [])
  2. .controller('hits', function($scope, eventBus) {
  3. // Set and populate defaults
  4. var _d = {
  5. query : "*",
  6. group : "default",
  7. style : { "font-size": '10pt'},
  8. aggregate : true,
  9. arrangement : 'vertical',
  10. chart : 'none',
  11. counter_pos : 'above',
  12. donut : false,
  13. tilt : false,
  14. labels : true
  15. }
  16. _.defaults($scope.panel,_d)
  17. $scope.init = function () {
  18. $scope.hits = 0;
  19. eventBus.register($scope,'time', function(event,time){
  20. set_time(time)
  21. });
  22. eventBus.register($scope,'query', function(event, query) {
  23. $scope.panel.query = _.map(query,function(q) {
  24. return {query: q, label: q};
  25. })
  26. $scope.get_data();
  27. });
  28. // Now that we're all setup, request the time from our group
  29. eventBus.broadcast($scope.$id,$scope.panel.group,'get_time')
  30. }
  31. $scope.get_data = function(segment,query_id) {
  32. delete $scope.panel.error
  33. $scope.panel.loading = true;
  34. // Make sure we have everything for the request to complete
  35. if(_.isUndefined($scope.panel.index) || _.isUndefined($scope.time))
  36. return
  37. var _segment = _.isUndefined(segment) ? 0 : segment
  38. var request = $scope.ejs.Request().indices($scope.panel.index[_segment]);
  39. // Build the question part of the query
  40. var queries = [];
  41. _.each($scope.panel.query, function(v) {
  42. queries.push($scope.ejs.FilteredQuery(
  43. ejs.QueryStringQuery(v.query || '*'),
  44. ejs.RangeFilter($scope.time.field)
  45. .from($scope.time.from)
  46. .to($scope.time.to))
  47. )
  48. });
  49. // Build the facet part
  50. _.each(queries, function(v) {
  51. request = request
  52. .facet($scope.ejs.QueryFacet("query"+_.indexOf(queries,v))
  53. .query(v)
  54. ).size(0)
  55. })
  56. // TODO: Spy for hits panel
  57. //$scope.populate_modal(request);
  58. // Then run it
  59. var results = request.doSearch();
  60. // Populate scope when we have results
  61. results.then(function(results) {
  62. $scope.panel.loading = false;
  63. if(_segment == 0) {
  64. $scope.hits = 0;
  65. $scope.data = [];
  66. query_id = $scope.query_id = new Date().getTime();
  67. }
  68. // Check for error and abort if found
  69. if(!(_.isUndefined(results.error))) {
  70. $scope.panel.error = $scope.parse_error(results.error);
  71. return;
  72. }
  73. if($scope.query_id === query_id) {
  74. var i = 0;
  75. _.each(results.facets, function(v, k) {
  76. var hits = _.isUndefined($scope.data[i]) || _segment == 0 ?
  77. v.count : $scope.data[i].hits+v.count
  78. $scope.hits += v.count
  79. // Create series
  80. $scope.data[i] = {
  81. label: $scope.panel.query[i].label || "query"+(parseInt(i)+1),
  82. hits: hits,
  83. data: [[i,hits]]
  84. };
  85. i++;
  86. });
  87. $scope.$emit('render');
  88. if(_segment < $scope.panel.index.length-1)
  89. $scope.get_data(_segment+1,query_id)
  90. }
  91. });
  92. }
  93. $scope.remove_query = function(q) {
  94. $scope.panel.query = _.without($scope.panel.query,q);
  95. $scope.get_data();
  96. }
  97. $scope.add_query = function(label,query) {
  98. $scope.panel.query.unshift({
  99. query: query,
  100. label: label,
  101. });
  102. $scope.get_data();
  103. }
  104. function set_time(time) {
  105. $scope.time = time;
  106. $scope.panel.index = _.isUndefined(time.index) ? $scope.panel.index : time.index
  107. $scope.get_data();
  108. }
  109. }).directive('hitsChart', function(eventBus) {
  110. return {
  111. restrict: 'A',
  112. link: function(scope, elem, attrs, ctrl) {
  113. // Receive render events
  114. scope.$on('render',function(){
  115. render_panel();
  116. });
  117. // Re-render if the window is resized
  118. angular.element(window).bind('resize', function(){
  119. render_panel();
  120. });
  121. // Function for rendering panel
  122. function render_panel() {
  123. var scripts = $LAB.script("common/lib/panels/jquery.flot.js")
  124. .script("common/lib/panels/jquery.flot.pie.js")
  125. // Populate element.
  126. scripts.wait(function(){
  127. // Populate element
  128. try {
  129. // Add plot to scope so we can build out own legend
  130. if(scope.panel.chart === 'bar')
  131. scope.plot = $.plot(elem, scope.data, {
  132. legend: { show: false },
  133. series: {
  134. lines: { show: false, },
  135. bars: { show: true, fill: 1, barWidth: 0.8, horizontal: false },
  136. shadowSize: 1
  137. },
  138. yaxis: { show: true, min: 0, color: "#000" },
  139. xaxis: { show: false },
  140. grid: {
  141. backgroundColor: '#fff',
  142. borderWidth: 0,
  143. borderColor: '#eee',
  144. color: "#eee",
  145. hoverable: true,
  146. },
  147. colors: ['#86B22D','#BF6730','#1D7373','#BFB930','#BF3030','#77207D']
  148. })
  149. if(scope.panel.chart === 'pie')
  150. scope.plot = $.plot(elem, scope.data, {
  151. legend: { show: false },
  152. series: {
  153. pie: {
  154. innerRadius: scope.panel.donut ? 0.4 : 0,
  155. tilt: scope.panel.tilt ? 0.45 : 1,
  156. radius: 1,
  157. show: true,
  158. combine: {
  159. color: '#999',
  160. label: 'The Rest'
  161. },
  162. label: {
  163. show: scope.panel.labels,
  164. radius: 2/3,
  165. formatter: function(label, series){
  166. return '<div ng-click="build_search(panel.query.field,\''+label+'\') "style="font-size:8pt;text-align:center;padding:2px;color:white;">'+
  167. label+'<br/>'+Math.round(series.percent)+'%</div>';
  168. },
  169. threshold: 0.1
  170. }
  171. }
  172. },
  173. //grid: { hoverable: true, clickable: true },
  174. grid: { hoverable: true, clickable: true },
  175. colors: ['#86B22D','#BF6730','#1D7373','#BFB930','#BF3030','#77207D']
  176. });
  177. // Compensate for the height of the legend. Gross
  178. elem.height(
  179. (scope.panel.height || scope.row.height).replace('px','') - $("#"+scope.$id+"-legend").height())
  180. // Work around for missing legend at initialization
  181. if(!scope.$$phase)
  182. scope.$apply()
  183. } catch(e) {
  184. elem.text(e)
  185. }
  186. })
  187. }
  188. function tt(x, y, contents) {
  189. var tooltip = $('#pie-tooltip').length ?
  190. $('#pie-tooltip') : $('<div id="pie-tooltip"></div>');
  191. //var tooltip = $('#pie-tooltip')
  192. tooltip.html(contents).css({
  193. position: 'absolute',
  194. top : y + 5,
  195. left : x + 5,
  196. color : "#000",
  197. border : '2px solid #000',
  198. padding : '10px',
  199. 'font-size': '11pt',
  200. 'font-weight' : 200,
  201. 'background-color': '#FFF',
  202. 'border-radius': '10px',
  203. }).appendTo("body");
  204. }
  205. elem.bind("plothover", function (event, pos, item) {
  206. if (item) {
  207. var value = scope.panel.chart === 'bar' ?
  208. item.datapoint[1] : item.datapoint[1][0][1];
  209. tt(pos.pageX, pos.pageY,
  210. "<div style='vertical-align:middle;border-radius:10px;display:inline-block;background:"+
  211. item.series.color+";height:20px;width:20px'></div> "+value.toFixed(0))
  212. } else {
  213. $("#pie-tooltip").remove();
  214. }
  215. });
  216. }
  217. };
  218. })