mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
Implemented quick, relative and absolute timepicker. Closes #57
This commit is contained in:
parent
c14821c842
commit
5c2419072b
9 changed files with 135 additions and 20 deletions
|
@ -31,7 +31,7 @@
|
|||
</disc-field-chooser>
|
||||
</div>
|
||||
<div class="col-md-10">
|
||||
<center ng-show="opts.time.from && opts.time.to"><small>{{opts.time.from|moment}} through {{opts.time.to|moment}}</small></center>
|
||||
<center ng-show="opts.time.from && opts.time.to"><small>{{opts.time.from}} through {{opts.time.to}}</small></center>
|
||||
|
||||
<discover-timechart data="chart" height="150" ng-if="opts.timefield"></discover-timechart>
|
||||
<div class="discover-table"
|
||||
|
|
34
src/kibana/directives/input_datetime.js
Normal file
34
src/kibana/directives/input_datetime.js
Normal file
|
@ -0,0 +1,34 @@
|
|||
define(function (require) {
|
||||
var module = require('modules').get('kibana/directives');
|
||||
var $ = require('jquery');
|
||||
var _ = require('lodash');
|
||||
var moment = require('moment');
|
||||
|
||||
module.directive('inputDatetime', function () {
|
||||
return {
|
||||
restrict: 'A',
|
||||
require: 'ngModel',
|
||||
link: function ($scope, $elem, attrs, ngModel) {
|
||||
|
||||
var format = 'YYYY-MM-DD HH:mm:ss.SSS';
|
||||
|
||||
$elem.after('<div class="input-datetime-format">' + format + '</div>');
|
||||
|
||||
// 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);
|
||||
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
});
|
||||
});
|
|
@ -12,6 +12,10 @@
|
|||
float: left;
|
||||
padding: 0px 15px;
|
||||
}
|
||||
|
||||
.kbn-timepicket-alert {
|
||||
width: 100px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="row">
|
||||
|
@ -64,9 +68,12 @@
|
|||
<div ng-switch-when="relative">
|
||||
|
||||
<div class="kbn-timepicker-section">
|
||||
From:
|
||||
<span ng-show="relative.preview">{{relative.preview}}</span><span ng-hide="relative.preview"><i>Invalid Expression</i></span>
|
||||
|
||||
<form class="form-inline" role="form">
|
||||
<label>
|
||||
From:
|
||||
<span ng-show="relative.preview">{{relative.preview}}</span><span ng-hide="relative.preview"><i>Invalid Expression</i></span>
|
||||
</label><br>
|
||||
<div class="form-group">
|
||||
<input type="number" class="form-control"
|
||||
ng-model="relative.count"
|
||||
|
@ -91,11 +98,19 @@
|
|||
</div>
|
||||
|
||||
<div class="kbn-timepicker-section">
|
||||
To:
|
||||
<form class="form-inline" role="form">
|
||||
<label>
|
||||
To: Now
|
||||
</label><br>
|
||||
<div class="form-group">
|
||||
<input type="text" disabled class="form-control" value="Now">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="kbn-timepicker-section">
|
||||
<form role="form">
|
||||
<label> </label>
|
||||
<div class="form-group">
|
||||
<button class="btn btn-primary" ng-disabled="!relative.preview" ng-click="applyRelative()">Go</button>
|
||||
</div>
|
||||
|
@ -106,15 +121,35 @@
|
|||
|
||||
<div ng-switch-when="absolute">
|
||||
<div class="kbn-timepicker-section">
|
||||
From:
|
||||
<form class="form-inline" role="form">
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control"
|
||||
ng-model="absolute.from.date">
|
||||
<form role="form">
|
||||
<div>
|
||||
<label class="small">From: <span ng-show="!absolute.from"><i>Invalid Date</i></span></label>
|
||||
<input type="text" class="form-control" input-datetime="{{format}}" ng-model="absolute.from">
|
||||
</div>
|
||||
<div ng-model="absolute.from">
|
||||
<datepicker max="absolute.to" show-weeks="false"></datepicker>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="kbn-timepicker-section">
|
||||
<form role="form">
|
||||
<div>
|
||||
<label class="small">To: <span ng-show="!absolute.to"><i>Invalid Date</i></span></label>
|
||||
<input type="text" class="form-control" input-datetime="{{format}}" ng-model="absolute.to">
|
||||
</div>
|
||||
<div ng-model="absolute.to">
|
||||
<datepicker min="absolute.from" show-weeks="false"></datepicker>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="kbn-timepicker-section kbn-timepicker-alert">
|
||||
<form role="form">
|
||||
<label> </label>
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control"
|
||||
ng-model="absolute.from.time">
|
||||
<button class="btn btn-primary" ng-disabled="absolute.from > absolute.to || !absolute.from || !absolute.to" ng-click="applyAbsolute()">Go</button>
|
||||
<span class="small" ng-show="absolute.from > absolute.to"><strong>From</strong> must occur before <strong>To</strong></span>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -235,4 +235,12 @@ saved-object-finder {
|
|||
// image in result list
|
||||
width: 65px;
|
||||
height: 65px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//== inputDatetime
|
||||
.input-datetime-format {
|
||||
font-size: @font-size-small;
|
||||
color: @text-muted;
|
||||
padding: @padding-base-vertical @padding-base-horizontal;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue