module.js 8.8 KB

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