From 5c2419072b3644802310a8a65b19419df429af1b Mon Sep 17 00:00:00 2001 From: Rashid Khan Date: Thu, 17 Apr 2014 11:21:01 -0700 Subject: [PATCH] Implemented quick, relative and absolute timepicker. Closes #57 --- src/kibana/apps/discover/index.html | 2 +- src/kibana/directives/input_datetime.js | 34 +++++++++++++++ src/kibana/directives/timepicker.js | 36 +++++++++++++--- src/kibana/filters/moment.js | 8 +++- src/kibana/partials/timepicker.html | 55 ++++++++++++++++++++----- src/kibana/styles/main.css | 5 +++ src/kibana/styles/main.less | 10 ++++- src/kibana/utils/datemath.js | 1 + test/unit/specs/utils/datemath.js | 4 ++ 9 files changed, 135 insertions(+), 20 deletions(-) create mode 100644 src/kibana/directives/input_datetime.js diff --git a/src/kibana/apps/discover/index.html b/src/kibana/apps/discover/index.html index 320253a5c4db7f..fd41f55f5f8f12 100644 --- a/src/kibana/apps/discover/index.html +++ b/src/kibana/apps/discover/index.html @@ -31,7 +31,7 @@
-
{{opts.time.from|moment}} through {{opts.time.to|moment}}
+
{{opts.time.from}} through {{opts.time.to}}
' + format + '
'); + + // What should I make with the input from the user? + var fromUser = function (text) { + var parsed = moment(text, format); + return parsed.isValid() ? parsed : undefined; + }; + + // How should I present the data back to the user in the input field? + var toUser = function (datetime) { + return moment(datetime).format(format); + }; + + ngModel.$parsers.push(fromUser); + ngModel.$formatters.push(toUser); + + } + }; + }); +}); \ No newline at end of file diff --git a/src/kibana/directives/timepicker.js b/src/kibana/directives/timepicker.js index 44e62d94d03d47..549617e74aa91c 100644 --- a/src/kibana/directives/timepicker.js +++ b/src/kibana/directives/timepicker.js @@ -5,6 +5,9 @@ define(function (require) { var datemath = require('utils/datemath'); var moment = require('moment'); + require('directives/input_datetime'); + + module.directive('kbnTimepicker', function () { return { restrict: 'E', @@ -30,6 +33,11 @@ define(function (require) { round: false }; + $scope.absolute = { + from: moment(), + to: moment() + }; + $scope.units = { s: 'second', m: 'minute', @@ -50,14 +58,22 @@ define(function (require) { {text: 'Years ago', value: 'y'}, ]; - if (_.isUndefined($scope.mode)) $scope.mode = 'quick'; + if (_.isUndefined($scope.mode)) $scope.mode = 'absolute'; + + $scope.$watch('absolute.from', function (date) { + if (_.isDate(date)) $scope.absolute.from = moment(date); + }); + + $scope.$watch('absolute.to', function (date) { + if (_.isDate(date)) $scope.absolute.to = moment(date); + }); $scope.setMode = function (thisMode) { switch (thisMode) { case 'quick': break; case 'relative': - var duration = moment.duration(moment().diff($scope.from)); + var duration = moment.duration(moment().diff(datemath.parse($scope.from))); var units = _.pluck(_.clone($scope.relativeOptions).reverse(), 'value'); for (var i = 0; i < units.length; i++) { var as = duration.as(units[i]); @@ -69,6 +85,8 @@ define(function (require) { } break; case 'absolute': + $scope.absolute.from = datemath.parse($scope.from); + $scope.absolute.to = datemath.parse($scope.to, true); break; } @@ -76,8 +94,8 @@ define(function (require) { }; $scope.setQuick = function (from, to) { - $scope.from = datemath.parse(from); - $scope.to = datemath.parse(to, true); + $scope.from = from; + $scope.to = to; }; $scope.formatRelative = function () { @@ -88,8 +106,14 @@ define(function (require) { }; $scope.applyRelative = function () { - $scope.from = $scope.formatRelative(); - $scope.to = datemath.parse('now', $scope.relative.round); + $scope.from = 'now-' + $scope.relative.count + $scope.relative.unit + + ($scope.relative.round ? '/' + $scope.relative.unit : ''); + $scope.to = 'now'; + }; + + $scope.applyAbsolute = function () { + $scope.from = moment($scope.absolute.from); + $scope.to = moment($scope.absolute.to); }; init(); diff --git a/src/kibana/filters/moment.js b/src/kibana/filters/moment.js index eb493ef80e5788..d781c3627e8d77 100644 --- a/src/kibana/filters/moment.js +++ b/src/kibana/filters/moment.js @@ -1,12 +1,16 @@ define(function (require) { var moment = require('moment'); + var _ = require('lodash'); + var datemath = require('utils/datemath'); require('modules') .get('kibana/filters') .filter('moment', function () { - return function (datetime) { + return function (datetime, roundUp) { var format = 'MMMM Do YYYY, HH:mm:ss.SSS'; - return moment.isMoment(datetime) ? datetime.format(format) : undefined; + var parsed = datemath.parse(datetime, roundUp); + if (parsed) return parsed.format(format); + return undefined; }; }); }); \ No newline at end of file diff --git a/src/kibana/partials/timepicker.html b/src/kibana/partials/timepicker.html index 6e70d1dafe95ca..860de106fcc712 100644 --- a/src/kibana/partials/timepicker.html +++ b/src/kibana/partials/timepicker.html @@ -12,6 +12,10 @@ float: left; padding: 0px 15px; } + + .kbn-timepicket-alert { + width: 100px; + }
@@ -64,9 +68,12 @@
- From: - {{relative.preview}}Invalid Expression +
+
- To: +
+ +
+ +
+
+
@@ -106,15 +121,35 @@
- From: - -
- + +
+ + +
+
+
+ +
+ +
+
+
+ + +
+
+ +
+
+
+ +
+
+
- + + From must occur before To
diff --git a/src/kibana/styles/main.css b/src/kibana/styles/main.css index f2923637b93ce3..ca1b02df4baab6 100644 --- a/src/kibana/styles/main.css +++ b/src/kibana/styles/main.css @@ -6851,3 +6851,8 @@ saved-object-finder .finder-options > li.active a { width: 65px; height: 65px; } +.input-datetime-format { + font-size: 12px; + color: #999999; + padding: 6px 12px; +} diff --git a/src/kibana/styles/main.less b/src/kibana/styles/main.less index 0bad476384d174..89f2e4ca5281b9 100644 --- a/src/kibana/styles/main.less +++ b/src/kibana/styles/main.less @@ -235,4 +235,12 @@ saved-object-finder { // image in result list width: 65px; height: 65px; -} \ No newline at end of file +} + + +//== inputDatetime +.input-datetime-format { + font-size: @font-size-small; + color: @text-muted; + padding: @padding-base-vertical @padding-base-horizontal; +} diff --git a/src/kibana/utils/datemath.js b/src/kibana/utils/datemath.js index 682663d6d8bef1..eee4db5dd33cb1 100644 --- a/src/kibana/utils/datemath.js +++ b/src/kibana/utils/datemath.js @@ -4,6 +4,7 @@ define(function (require) { /* This is a simplified version of elasticsearch's date parser */ var parse = function (text, roundUp) { + if (!text) return undefined; if (moment.isMoment(text)) return text; if (_.isDate(text)) return moment(text); diff --git a/test/unit/specs/utils/datemath.js b/test/unit/specs/utils/datemath.js index df9d88e072b099..3ec316b6a9eccc 100644 --- a/test/unit/specs/utils/datemath.js +++ b/test/unit/specs/utils/datemath.js @@ -13,6 +13,10 @@ define(function (require) { clock; describe('errors', function () { + it('should return undefined if passed something falsy', function () { + expect(datemath.parse()).to.be(undefined); + }); + it('should return undefined if I pass an operator besides [+-/]', function () { expect(datemath.parse('now&1d')).to.be(undefined); });