module.js 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. /*
  2. ## Timepicker
  3. The timepicker panel is used to select time ranges and inform other panel of
  4. them. It also handles searching for indices that match the given time range and
  5. a pattern
  6. ### Parameters
  7. * mode :: The default mode of the panel. Options: 'relative', 'absolute' 'since' Default: 'relative'
  8. * time_options :: An array of possible time options. Default: ['5m','15m','1h','6h','12h','24h','2d','7d','30d']
  9. * timespan :: The default options selected for the relative view. Default: '15m'
  10. * timefield :: The field in which time is stored in the document.
  11. * index :: Index pattern to match. Literals should be double quoted. Default: '_all'
  12. * defaultindex :: Index to failover to if index not found
  13. * index_interval :: Time between timestamped indices (can be 'none') for static index
  14. * refresh: Object containing refresh parameters
  15. * enable :: true/false, enable auto refresh by default. Default: false
  16. * interval :: Seconds between auto refresh. Default: 30
  17. * min :: The lowest interval a user may set
  18. ### Group Events
  19. #### Sends
  20. * time :: Object Includes from, to and index
  21. #### Receives
  22. * get_time :: Receives an object containing a $id, broadcasts back to it.
  23. */
  24. angular.module('kibana.timepicker', [])
  25. .controller('timepicker', function($scope, eventBus, $timeout, timer, $http, kbnIndex) {
  26. // Set and populate defaults
  27. var _d = {
  28. status : "Stable",
  29. mode : "relative",
  30. time_options : ['5m','15m','1h','6h','12h','24h','2d','7d','30d'],
  31. timespan : '15m',
  32. timefield : '@timestamp',
  33. index : '_all',
  34. defaultindex : "_all",
  35. index_interval: "none",
  36. timeformat : "",
  37. group : "default",
  38. refresh : {
  39. enable : false,
  40. interval: 30,
  41. min : 3
  42. }
  43. }
  44. _.defaults($scope.panel,_d)
  45. var _groups = _.isArray($scope.panel.group) ?
  46. $scope.panel.group : [$scope.panel.group];
  47. $scope.init = function() {
  48. // Private refresh interval that we can use for view display without causing
  49. // unnecessary refreshes during changes
  50. $scope.refresh_interval = $scope.panel.refresh.interval
  51. // Init a private time object with Date() objects depending on mode
  52. switch($scope.panel.mode) {
  53. case 'absolute':
  54. $scope.time = {
  55. from : moment($scope.panel.time.from,'MM/DD/YYYY HH:mm:ss') || moment(time_ago($scope.panel.timespan)),
  56. to : moment($scope.panel.time.to,'MM/DD/YYYY HH:mm:ss') || moment()
  57. }
  58. break;
  59. case 'since':
  60. $scope.time = {
  61. from : moment($scope.panel.time.from,'MM/DD/YYYY HH:mm:ss') || moment(time_ago($scope.panel.timespan)),
  62. to : moment()
  63. }
  64. break;
  65. case 'relative':
  66. $scope.time = {
  67. from : moment(time_ago($scope.panel.timespan)),
  68. to : moment()
  69. }
  70. break;
  71. }
  72. $scope.time.field = $scope.panel.timefield;
  73. $scope.time_apply();
  74. // Start refresh timer if enabled
  75. if ($scope.panel.refresh.enable)
  76. $scope.set_interval($scope.panel.refresh.interval);
  77. // In the case that a panel is not ready to receive a time event, it may
  78. // request one be sent by broadcasting a 'get_time' with its _id to its group
  79. // This panel can handle multiple groups
  80. eventBus.register($scope,"get_time", function(event,id) {
  81. eventBus.broadcast($scope.$id,id,'time',compile_time($scope.time))
  82. });
  83. // In case some other panel broadcasts a time, set us to an absolute range
  84. eventBus.register($scope,"set_time", function(event,time) {
  85. $scope.panel.mode = 'absolute';
  86. set_timepicker(moment(time.from),moment(time.to))
  87. $scope.time_apply()
  88. });
  89. eventBus.register($scope,"zoom", function(event,factor) {
  90. var _timespan = ($scope.time.to.valueOf() - $scope.time.from.valueOf());
  91. try {
  92. if($scope.panel.mode != 'absolute') {
  93. $scope.panel.mode = 'since'
  94. set_timepicker(moment($scope.time.to.valueOf() - _timespan*factor),$scope.time.to)
  95. } else {
  96. var _center = $scope.time.to.valueOf() - _timespan/2
  97. set_timepicker(moment(_center - (_timespan*factor)/2),
  98. moment(_center + (_timespan*factor)/2))
  99. }
  100. } catch (e) {
  101. console.log(e)
  102. }
  103. $scope.time_apply();
  104. });
  105. }
  106. $scope.set_interval = function (refresh_interval) {
  107. $scope.panel.refresh.interval = refresh_interval
  108. if(_.isNumber($scope.panel.refresh.interval)) {
  109. if($scope.panel.refresh.interval < $scope.panel.refresh.min) {
  110. $scope.panel.refresh.interval = $scope.panel.refresh.min
  111. timer.cancel($scope.refresh_timer)
  112. return;
  113. }
  114. timer.cancel($scope.refresh_timer)
  115. $scope.refresh()
  116. } else {
  117. timer.cancel($scope.refresh_timer)
  118. }
  119. }
  120. $scope.refresh = function() {
  121. if ($scope.panel.refresh.enable) {
  122. timer.cancel($scope.refresh_timer)
  123. $scope.refresh_timer = timer.register($timeout(function() {
  124. $scope.refresh();
  125. $scope.time_apply();
  126. },$scope.panel.refresh.interval*1000
  127. ));
  128. } else {
  129. timer.cancel($scope.refresh_timer)
  130. }
  131. }
  132. $scope.set_mode = function(mode) {
  133. $scope.panel.mode = mode;
  134. $scope.panel.refresh.enable = mode === 'absolute' ?
  135. false : $scope.panel.refresh.enable
  136. }
  137. $scope.to_now = function() {
  138. $scope.timepicker.to = {
  139. time : moment().format("HH:mm:ss"),
  140. date : moment().format("MM/DD/YYYY")
  141. }
  142. }
  143. $scope.set_timespan = function(timespan) {
  144. $scope.panel.timespan = timespan;
  145. $scope.timepicker.from = {
  146. time : moment(time_ago(timespan)).format("HH:mm:ss"),
  147. date : moment(time_ago(timespan)).format("MM/DD/YYYY")
  148. }
  149. $scope.time_apply();
  150. }
  151. $scope.close_edit = function() {
  152. $scope.time_apply();
  153. }
  154. //
  155. $scope.time_calc = function(){
  156. // If time picker is defined (usually is)
  157. if(!(_.isUndefined($scope.timepicker))) {
  158. var from = $scope.panel.mode === 'relative' ? moment(time_ago($scope.panel.timespan)) :
  159. moment($scope.timepicker.from.date + " " + $scope.timepicker.from.time,'MM/DD/YYYY HH:mm:ss')
  160. var to = $scope.panel.mode !== 'absolute' ? moment() :
  161. moment($scope.timepicker.to.date + " " + $scope.timepicker.to.time,'MM/DD/YYYY HH:mm:ss')
  162. // Otherwise (probably initialization)
  163. } else {
  164. var from = $scope.panel.mode === 'relative' ? moment(time_ago($scope.panel.timespan)) :
  165. $scope.time.from;
  166. var to = $scope.panel.mode !== 'absolute' ? moment() :
  167. $scope.time.to;
  168. }
  169. if (from.valueOf() >= to.valueOf())
  170. from = moment(to.valueOf() - 1000)
  171. $timeout(function(){
  172. set_timepicker(from,to)
  173. });
  174. return {
  175. from : from,
  176. to : to
  177. };
  178. }
  179. $scope.time_apply = function() {
  180. $scope.panel.error = "";
  181. // Update internal time object
  182. $scope.time = $scope.time_calc();
  183. $scope.time.field = $scope.panel.timefield
  184. // Get indices for the time period, then broadcast time range and index list
  185. // in a single object. Not sure if I like this.
  186. if($scope.panel.index_interval !== 'none') {
  187. kbnIndex.indices($scope.time.from,
  188. $scope.time.to,
  189. $scope.panel.index,
  190. $scope.panel.index_interval
  191. ).then(function (p) {
  192. if(p.length > 0) {
  193. $scope.time.index = p;
  194. eventBus.broadcast($scope.$id,$scope.panel.group,'time',compile_time($scope.time))
  195. } else {
  196. $scope.panel.error = "Could not match index pattern to any ElasticSearch indices"
  197. }
  198. });
  199. } else {
  200. $scope.time.index = [$scope.panel.index];
  201. eventBus.broadcast($scope.$id,$scope.panel.group,'time',compile_time($scope.time))
  202. }
  203. // Update panel's string representation of the time object.Don't update if
  204. // we're in relative mode since we dont want to store the time object in the
  205. // json for relative periods
  206. if($scope.panel.mode !== 'relative') {
  207. $scope.panel.time = {
  208. from : $scope.time.from.format("MM/DD/YYYY HH:mm:ss"),
  209. to : $scope.time.to.format("MM/DD/YYYY HH:mm:ss"),
  210. index : $scope.time.index,
  211. };
  212. } else {
  213. delete $scope.panel.time;
  214. }
  215. };
  216. // Prefer to pass around Date() objects in the EventBus since interacting with
  217. // moment objects in libraries that are expecting Date()s can be tricky
  218. function compile_time(time) {
  219. time = _.clone(time)
  220. time.from = time.from.toDate()
  221. time.to = time.to.toDate()
  222. time.interval = $scope.panel.index_interval
  223. time.pattern = $scope.panel.index
  224. return time;
  225. }
  226. function set_timepicker(from,to) {
  227. // Janky 0s timeout to get around $scope queue processing view issue
  228. $scope.timepicker = {
  229. from : {
  230. time : from.format("HH:mm:ss"),
  231. date : from.format("MM/DD/YYYY")
  232. },
  233. to : {
  234. time : to.format("HH:mm:ss"),
  235. date : to.format("MM/DD/YYYY")
  236. }
  237. }
  238. }
  239. })