Commit 834e63a1 by Rashid Khan

Added relative/absolute/since time selector. Moved refresh func out to panel

parent a73242ca
/* =========================================================
* bootstrap-datepicker.js
* original by Stefan Petre
* tweaked by gus
* ========================================================= */
.bs-sc-datepicker.dropdown-menu {
max-width: inherit;
}
.bs-sc-datepicker {
top: 0;
left: 0;
padding: 4px;
margin-top: 1px;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
z-index: 1051;
}
.bs-sc-datepicker:before {
content: '';
display: inline-block;
border-left: 7px solid transparent;
border-right: 7px solid transparent;
border-bottom: 7px solid #ccc;
border-bottom-color: rgba(0, 0, 0, 0.2);
position: absolute;
top: -7px;
left: 6px;
}
.bs-sc-datepicker:after {
content: '';
display: inline-block;
border-left: 6px solid transparent;
border-right: 6px solid transparent;
border-bottom: 6px solid #ffffff;
position: absolute;
top: -6px;
left: 7px;
}
.bs-sc-datepicker table {
width: 100%;
margin: 0;
}
.bs-sc-datepicker th {
border-bottom: 1px solid #efefef;
}
.bs-sc-datepicker td, .bs-sc-datepicker th {
text-align: center;
width: 20px;
height: 20px;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
padding: 5px !important;
}
.bs-sc-datepicker td.day:hover {
background: #eeeeee;
cursor: pointer;
}
.bs-sc-datepicker td.old, .bs-sc-datepicker td.new {
color: #DDDDDD;
}
.bs-sc-datepicker td.active, .bs-sc-datepicker td.active:hover {
background-color: #006dcc;
background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
background-image: -ms-linear-gradient(top, #0088cc, #0044cc);
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);
background-image: -o-linear-gradient(top, #0088cc, #0044cc);
background-image: linear-gradient(top, #0088cc, #0044cc);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);
border-color: #0044cc #0044cc #002a80;
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
color: #fff;
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
}
.bs-sc-datepicker td.active:hover,
.bs-sc-datepicker td.active:hover:hover,
.bs-sc-datepicker td.active:active,
.bs-sc-datepicker td.active:hover:active,
.bs-sc-datepicker td.active.active,
.bs-sc-datepicker td.active:hover.active,
.bs-sc-datepicker td.active.disabled,
.bs-sc-datepicker td.active:hover.disabled,
.bs-sc-datepicker td.active[disabled],
.bs-sc-datepicker td.active:hover[disabled] {
background-color: #0044cc;
}
.bs-sc-datepicker td.active:active,
.bs-sc-datepicker td.active:hover:active,
.bs-sc-datepicker td.active.active,
.bs-sc-datepicker td.active:hover.active {
background-color: #003399 \9;
}
.bs-sc-datepicker td span {
display: block;
width: 47px;
height: 54px;
line-height: 54px;
float: left;
margin: 2px;
cursor: pointer;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
}
.bs-sc-datepicker td span:hover {
background: #eeeeee;
}
.bs-sc-datepicker td span.active {
background-color: #006dcc;
background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
background-image: -ms-linear-gradient(top, #0088cc, #0044cc);
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);
background-image: -o-linear-gradient(top, #0088cc, #0044cc);
background-image: linear-gradient(top, #0088cc, #0044cc);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);
border-color: #0044cc #0044cc #002a80;
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
color: #fff;
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
}
.bs-sc-datepicker td span.active:hover,
.bs-sc-datepicker td span.active:active,
.bs-sc-datepicker td span.active.active,
.bs-sc-datepicker td span.active.disabled,
.bs-sc-datepicker td span.active[disabled] {
background-color: #0044cc;
}
.bs-sc-datepicker td span.active:active, .bs-sc-datepicker td span.active.active {
background-color: #003399 \9;
}
.bs-sc-datepicker td span.old {
color: #999999;
}
.bs-sc-datepicker th.switch {
width: 145px;
}
.bs-sc-datepicker thead tr:first-child th {
cursor: pointer;
}
.bs-sc-datepicker thead tr:first-child th:hover {
background: #eeeeee;
}
.input-append.date .add-on i, .input-prepend.date .add-on i {
display: block;
cursor: pointer;
width: 16px;
height: 16px;
}
\ No newline at end of file
...@@ -22,4 +22,33 @@ ...@@ -22,4 +22,33 @@
.pointer { .pointer {
cursor: pointer; cursor: pointer;
}
.small {
font-size: 85%;
}
.nomargin {
margin: 0px;
}
.strong {
font-weight: bold;
}
.btn-active {
background-color: #E6E6E6;
background-image: none;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15) inset, 0 1px 2px rgba(0, 0, 0, 0.05);
outline: 0 none
}
.popover-title { display: none; }
.input-smaller {
width: 75px;
}
.tiny {
font-size: 50%;
} }
\ No newline at end of file
/*
Datepicker for Bootstrap
Copyright 2012 Stefan Petre
Licensed under the Apache License v2.0
http://www.apache.org/licenses/LICENSE-2.0
*/
input[type="date"] { -webkit-appearance: none; } .datepicker { top: 0; left: 0; padding: 4px; margin-top: 1px; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; /*.dow { border-top: 1px solid #ddd !important; }*/ } .datepicker:before { content: ''; display: inline-block; border-left: 7px solid transparent; border-right: 7px solid transparent; border-bottom: 7px solid #ccc; border-bottom-color: rgba(0, 0, 0, 0.2); position: absolute; top: -7px; left: 6px; } .datepicker:after { content: ''; display: inline-block; border-left: 6px solid transparent; border-right: 6px solid transparent; border-bottom: 6px solid #ffffff; position: absolute; top: -6px; left: 7px; } .datepicker > div { display: none; } .datepicker table { width: 100%; margin: 0; } .datepicker td, .datepicker th { text-align: center; width: 20px; height: 20px; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; } .datepicker td.day:hover { background: #eeeeee; cursor: pointer; } .datepicker td.old, .datepicker td.new { color: #999999; } .datepicker td.active, .datepicker td.active:hover { background-color: #006dcc; background-image: -moz-linear-gradient(top, #0088cc, #0044cc); background-image: -ms-linear-gradient(top, #0088cc, #0044cc); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc)); background-image: -webkit-linear-gradient(top, #0088cc, #0044cc); background-image: -o-linear-gradient(top, #0088cc, #0044cc); background-image: linear-gradient(top, #0088cc, #0044cc); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0); border-color: #0044cc #0044cc #002a80; border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); color: #fff; text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); } .datepicker td.active:hover, .datepicker td.active:hover:hover, .datepicker td.active:active, .datepicker td.active:hover:active, .datepicker td.active.active, .datepicker td.active:hover.active, .datepicker td.active.disabled, .datepicker td.active:hover.disabled, .datepicker td.active[disabled], .datepicker td.active:hover[disabled] { background-color: #0044cc; } .datepicker td.active:active, .datepicker td.active:hover:active, .datepicker td.active.active, .datepicker td.active:hover.active { background-color: #003399 \9; } .datepicker td span { display: block; width: 47px; height: 54px; line-height: 54px; float: left; margin: 2px; cursor: pointer; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; } .datepicker td span:hover { background: #eeeeee; } .datepicker td span.active { background-color: #006dcc; background-image: -moz-linear-gradient(top, #0088cc, #0044cc); background-image: -ms-linear-gradient(top, #0088cc, #0044cc); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc)); background-image: -webkit-linear-gradient(top, #0088cc, #0044cc); background-image: -o-linear-gradient(top, #0088cc, #0044cc); background-image: linear-gradient(top, #0088cc, #0044cc); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0); border-color: #0044cc #0044cc #002a80; border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); color: #fff; text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); } .datepicker td span.active:hover, .datepicker td span.active:active, .datepicker td span.active.active, .datepicker td span.active.disabled, .datepicker td span.active[disabled] { background-color: #0044cc; } .datepicker td span.active:active, .datepicker td span.active.active { background-color: #003399 \9; } .datepicker td span.old { color: #999999; } .datepicker th.switch { width: 145px; } .datepicker th.next, .datepicker th.prev { font-size: 19.5px; } .datepicker thead tr:first-child th { cursor: pointer; } .datepicker thead tr:first-child th:hover { background: #eeeeee; } .input-append.date .add-on i, .input-prepend.date .add-on i { display: block; cursor: pointer; width: 16px; height: 16px; }
.bootstrap-timepicker.dropdown-menu {
border-radius: 4px 4px 4px 4px;
display: none;
left: 0;
margin-top: 1px;
padding: 4px;
top: 0;
min-width: 10px;
z-index: 99999;
}
.bootstrap-timepicker.dropdown-menu.open {
display: inline-block;
}
.bootstrap-timepicker.dropdown-menu:before {
border-bottom: 7px solid rgba(0, 0, 0, 0.2);
border-left: 7px solid transparent;
border-right: 7px solid transparent;
content: "";
left: 6px;
position: absolute;
top: -7px;
}
.bootstrap-timepicker.dropdown-menu:after {
border-bottom: 6px solid #FFFFFF;
border-left: 6px solid transparent;
border-right: 6px solid transparent;
content: "";
left: 7px;
position: absolute;
top: -6px;
}
.bootstrap-timepicker.modal {
margin-left: -100px;
margin-top: 0;
top: 30%;
width: 200px;
}
.bootstrap-timepicker.modal .modal-content {
padding: 0;
}
.bootstrap-timepicker table {
margin: 0;
width: 100%;
}
.bootstrap-timepicker table td {
height: 30px;
margin: 0;
padding: 2px;
text-align: center;
}
.bootstrap-timepicker table td span {
width: 100%;
}
.bootstrap-timepicker table td a {
border: 1px solid transparent;
display: inline-block;
margin: 0;
outline: 0 none;
padding: 8px 0;
width: 3em;
}
.bootstrap-timepicker table td a:hover {
background-color: #EEEEEE;
border-color: #DDDDDD;
border-radius: 4px 4px 4px 4px;
}
.bootstrap-timepicker table td a i {
margin-top: 2px;
}
.bootstrap-timepicker table td input {
margin: 0;
text-align: center;
width: 25px;
}
.bootstrap-timepicker-component .add-on {
cursor: pointer;
}
.bootstrap-timepicker-component .add-on i {
display: block;
height: 16px;
width: 16px;
}
...@@ -30,7 +30,8 @@ var config = new Settings( ...@@ -30,7 +30,8 @@ var config = new Settings(
timefield: '@timestamp', timefield: '@timestamp',
//indexpattern: '"logstash-"yyyy.mm.dd', //indexpattern: '"logstash-"yyyy.mm.dd',
indexpattern: '"shakespeare"', indexpattern: '"shakespeare"',
modules: ['histogram','map','pie','table','stringquery','sort'], modules: ['histogram','map','pie','table','stringquery','sort',
'timepicker'],
defaultfields: ['line_text'], defaultfields: ['line_text'],
perpage: 50, perpage: 50,
......
...@@ -2,18 +2,38 @@ var dashboards = ...@@ -2,18 +2,38 @@ var dashboards =
{ {
title: "Infinite Monkey Dashboard", title: "Infinite Monkey Dashboard",
rows: [ rows: [
{ {
title: "Query Control", title: "Query Control",
height: "30px", height: "30px",
panels: [ panels: [
{ {
type : "stringquery", type : "stringquery",
span : 9, span : 12,
group : "main",
query : "wine"
}
]
},
{
title: "Options",
collapse: true,
height: "30px",
panels: [
{
type : "timepicker",
span : 5,
mode : 'relative',
refresh : {
enable : false,
interval: 30,
min : 10
},
timespan: '1h',
group : "main" group : "main"
}, },
{ {
type : "sort", type : "sort",
span : 3, span : 4,
group : "main" group : "main"
} }
] ]
...@@ -51,7 +71,7 @@ var dashboards = ...@@ -51,7 +71,7 @@ var dashboards =
}, },
{ {
title: "Lines of Plays", title: "Lines of Plays",
height: "300px", height: "250px",
panels: [ panels: [
{ {
title : "Plays", title : "Plays",
...@@ -70,7 +90,7 @@ var dashboards = ...@@ -70,7 +90,7 @@ var dashboards =
type : "table", type : "table",
span : 8, span : 8,
query : "*", query : "*",
fields : ['@timestamp','speaker','text_entry'], fields : ['@timestamp','play_name','speaker','text_entry'],
group : "main" group : "main"
} }
] ]
......
<!DOCTYPE html> <!DOCTYPE html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7 ng-app:kibana" lang="en" id="ng-app"> <![endif]--> <!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="en" id="ng-app"> <![endif]-->
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8 ng-app:kibana" lang="en" id="ng-app"> <![endif]--> <!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8" lang="en" id="ng-app"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9" lang="en" ng-app="kibana"> <![endif]--> <!--[if IE 8]> <html class="no-js lt-ie9" lang="en"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" ng-app="kibana"> <!--<![endif]--> <!--[if gt IE 8]><!--> <html class="no-js" lang="en"> <!--<![endif]-->
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
<link rel="stylesheet" href="/common/css/bootstrap.min.css"> <link rel="stylesheet" href="/common/css/bootstrap.min.css">
<link rel="stylesheet" href="/common/css/bootstrap-responsive.min.css"> <link rel="stylesheet" href="/common/css/bootstrap-responsive.min.css">
<link rel="stylesheet" href="/common/css/elasticjs.css"> <link rel="stylesheet" href="/common/css/elasticjs.css">
<link rel="stylesheet" href="/common/css/datepicker.css"> <link rel="stylesheet" href="/common/css/timepicker.css">
<!-- project dependency libs --> <!-- project dependency libs -->
<script src="/common/lib/LAB.min.js"></script> <script src="/common/lib/LAB.min.js"></script>
...@@ -34,11 +34,6 @@ ...@@ -34,11 +34,6 @@
<span class="brand">{{dashboards.title}}</span> <span class="brand">{{dashboards.title}}</span>
<span class="brand"><small><small>Kibana Preview</small></small></span> <span class="brand"><small><small>Kibana Preview</small></small></span>
<div class='pull-right' style="padding-top: 5px; padding-left: 10px"><input type="file" id="upload" upload /></div> <div class='pull-right' style="padding-top: 5px; padding-left: 10px"><input type="file" id="upload" upload /></div>
<div class="btn-group pull-right">
<button class="btn" ng-click="pause()"><i ng-class="{'icon-pause': playing,'icon-play': !playing}"></i></button>
<button class="btn" ng-repeat='timespan in time_options' ng-click="set_timespan(timespan)">{{timespan}}</button>
</div>
</div> </div>
</div> </div>
</div> </div>
......
...@@ -9,6 +9,7 @@ var modules = [ ...@@ -9,6 +9,7 @@ var modules = [
'kibana.services', 'kibana.services',
'kibana.directives', 'kibana.directives',
'elasticjs.service', 'elasticjs.service',
'$strap.directives',
'kibana.panels', 'kibana.panels',
] ]
...@@ -17,7 +18,10 @@ var scripts = [] ...@@ -17,7 +18,10 @@ var scripts = []
var labjs = $LAB var labjs = $LAB
.script("common/lib/jquery-1.8.0.min.js").wait() .script("common/lib/jquery-1.8.0.min.js").wait()
.script("common/lib/modernizr-2.6.1.min.js") .script("common/lib/modernizr-2.6.1.min.js")
.script("common/lib/underscore.min.js") .script("common/lib/underscore.min.js")
.script("common/lib/bootstrap.min.js")
.script('common/lib/datepicker.js')
.script('common/lib/timepicker.js')
.script("common/lib/angular.min.js") .script("common/lib/angular.min.js")
.script("common/lib/angular-strap.min.js") .script("common/lib/angular-strap.min.js")
.script("common/lib/elastic.min.js") .script("common/lib/elastic.min.js")
...@@ -26,12 +30,12 @@ var labjs = $LAB ...@@ -26,12 +30,12 @@ var labjs = $LAB
.script("common/lib/date.js") .script("common/lib/date.js")
.script("common/lib/datepicker.js") .script("common/lib/datepicker.js")
.script("common/lib/shared.js") .script("common/lib/shared.js")
.script("dashboards.js")
.script("js/services.js") .script("js/services.js")
.script("js/controllers.js") .script("js/controllers.js")
.script("js/filters.js") .script("js/filters.js")
.script("js/directives.js") .script("js/directives.js")
.script("js/panels.js") .script("js/panels.js")
.script("dashboards.js");
_.each(config.modules, function(v) { _.each(config.modules, function(v) {
labjs = labjs.script('panels/'+v+'/module.js').wait() labjs = labjs.script('panels/'+v+'/module.js').wait()
...@@ -49,5 +53,8 @@ labjs.wait(function(){ ...@@ -49,5 +53,8 @@ labjs.wait(function(){
redirectTo: '/dashboard' redirectTo: '/dashboard'
}); });
}]); }]);
angular.element(document).ready(function() {
$('body').attr('ng-controller', 'DashCtrl')
angular.bootstrap(document, ['kibana']);
});
}); });
...@@ -9,17 +9,20 @@ angular.module('kibana.controllers', []) ...@@ -9,17 +9,20 @@ angular.module('kibana.controllers', [])
$scope.config = config; $scope.config = config;
$scope.dashboards = dashboards $scope.dashboards = dashboards
$scope.timespan = config.timespan $scope.timespan = config.timespan
$scope.from = time_ago($scope.timespan); $scope.time = {
$scope.to = new Date(); from : time_ago($scope.timespan),
to : new Date()
$scope.time_options = ['5m','15m','1h','6h','12h','24h','2d','7d','30d']; }
// I'm leaving in all this refresh stuff until I figure out how index
// list caching should work. Maybe it should be handled by each time panel?
// That would require dashboard to contain a time panel. Hmm.
$scope.counter = 0; $scope.counter = 0;
$scope.playing = true; $scope.playing = true;
$scope.play = function(){ $scope.play = function(){
$scope.counter++; $scope.counter++;
$scope.to = new Date(); $scope.time.to = new Date();
$scope.from = time_ago($scope.timespan); $scope.time.from = time_ago($scope.timespan);
$scope.$root.$eval() $scope.$root.$eval()
mytimeout = $timeout($scope.play,config.refresh); mytimeout = $timeout($scope.play,config.refresh);
} }
...@@ -37,9 +40,9 @@ angular.module('kibana.controllers', []) ...@@ -37,9 +40,9 @@ angular.module('kibana.controllers', [])
// If from/to to change, update index list // If from/to to change, update index list
$scope.$watch(function() { $scope.$watch(function() {
return angular.toJson([$scope.from, $scope.to]) return angular.toJson([$scope.time.from, $scope.time.to])
}, function(){ }, function(){
indices($scope.from,$scope.to).then(function (p) { indices($scope.time.from,$scope.time.to).then(function (p) {
$scope.index = p.join(); $scope.index = p.join();
}); });
}); });
...@@ -54,7 +57,7 @@ angular.module('kibana.controllers', []) ...@@ -54,7 +57,7 @@ angular.module('kibana.controllers', [])
$scope.set_timespan = function(timespan) { $scope.set_timespan = function(timespan) {
$scope.timespan = timespan; $scope.timespan = timespan;
$scope.from = time_ago($scope.timespan); $scope.time.from = time_ago($scope.timespan);
} }
// returns a promise containing an array of all indices matching the index // returns a promise containing an array of all indices matching the index
......
angular.module('kibana.histogram', []) angular.module('kibana.histogram', [])
.controller('histogram', function($scope, $location) { .controller('histogram', function($scope, $rootScope) {
// Set and populate defaults // Set and populate defaults
var _d = { var _d = {
...@@ -14,14 +14,11 @@ angular.module('kibana.histogram', []) ...@@ -14,14 +14,11 @@ angular.module('kibana.histogram', [])
? _d[k] : $scope.panel[k]; ? _d[k] : $scope.panel[k];
}); });
if (!(_.isUndefined($scope.panel.group))) {
$scope.$on($scope.panel.group+"-query", function(event, query) {
$scope.panel.query[0].query = query;
$scope.get_data();
});
}
$scope.get_data = function() { $scope.get_data = function() {
// Make sure we have everything for the request to complete
if(_.isUndefined($scope.panel.time))
return
var request = $scope.ejs.Request().indices($scope.index); var request = $scope.ejs.Request().indices($scope.index);
// Build the question part of the query // Build the question part of the query
...@@ -30,8 +27,8 @@ angular.module('kibana.histogram', []) ...@@ -30,8 +27,8 @@ angular.module('kibana.histogram', [])
queries.push($scope.ejs.FilteredQuery( queries.push($scope.ejs.FilteredQuery(
ejs.QueryStringQuery(v.query || '*'), ejs.QueryStringQuery(v.query || '*'),
ejs.RangeFilter(config.timefield) ejs.RangeFilter(config.timefield)
.from($scope.from) .from($scope.panel.time.from)
.to($scope.to) .to($scope.panel.time.to)
.cache(false)) .cache(false))
) )
}); });
...@@ -53,15 +50,14 @@ angular.module('kibana.histogram', []) ...@@ -53,15 +50,14 @@ angular.module('kibana.histogram', [])
results.then(function(results) { results.then(function(results) {
$scope.hits = results.hits.total; $scope.hits = results.hits.total;
// Null values at each end of the time range make sure we see entire range // Null values at each end of the time range make sure we see entire range
$scope.data = []; $scope.data = [];
_.each(results.facets, function(v, k) { _.each(results.facets, function(v, k) {
var series = {}; var series = {};
var data = [[$scope.from.getTime(), null]]; var data = [[$scope.panel.time.from.getTime(), null]];
_.each(v.entries, function(v, k) { _.each(v.entries, function(v, k) {
data.push([v['time'],v['count']]) data.push([v['time'],v['count']])
}); });
data.push([$scope.to.getTime(), null]) data.push([$scope.panel.time.to.getTime(), null])
series.data = { series.data = {
label: $scope.panel.query[k].label, label: $scope.panel.query[k].label,
data: data, data: data,
...@@ -73,13 +69,22 @@ angular.module('kibana.histogram', []) ...@@ -73,13 +69,22 @@ angular.module('kibana.histogram', [])
}); });
} }
$scope.$watch(function() { if (!(_.isUndefined($scope.panel.group))) {
return angular.toJson([$scope.from, $scope.to]) $scope.$on($scope.panel.group+"-query", function(event, query) {
}, function(){ $scope.panel.query[0].query = query;
$scope.panel.interval = secondsToHms( $scope.get_data();
calculate_interval($scope.from,$scope.to,50,0)/1000), });
$scope.get_data(); $scope.$on($scope.panel.group+"-time", function(event, time) {
}); $scope.panel.time = time;
$scope.panel.interval = secondsToHms(
calculate_interval(time.from,time.to,50,0)/1000),
$scope.get_data();
});
}
// Now that we're all setup, request the time from our group
$rootScope.$broadcast($scope.panel.group+"-get_time")
}) })
.directive('histogram', function() { .directive('histogram', function() {
......
angular.module('kibana.map', []) angular.module('kibana.map', [])
.controller('map', function($scope, $location) { .controller('map', function($scope, $rootScope) {
// Set and populate defaults // Set and populate defaults
var _d = { var _d = {
...@@ -14,15 +14,11 @@ angular.module('kibana.map', []) ...@@ -14,15 +14,11 @@ angular.module('kibana.map', [])
? _d[k] : $scope.panel[k]; ? _d[k] : $scope.panel[k];
}); });
if (!(_.isUndefined($scope.panel.group))) {
$scope.$on($scope.panel.group+"-query", function(event, query) {
$scope.panel.query = query;
$scope.get_data();
});
}
$scope.get_data = function() { $scope.get_data = function() {
// Make sure we have everything for the request to complete
if(_.isUndefined($scope.panel.time))
return
var request = $scope.ejs.Request().indices($scope.index); var request = $scope.ejs.Request().indices($scope.index);
// Then the insert into facet and make the request // Then the insert into facet and make the request
...@@ -35,8 +31,8 @@ angular.module('kibana.map', []) ...@@ -35,8 +31,8 @@ angular.module('kibana.map', [])
ejs.FilteredQuery( ejs.FilteredQuery(
ejs.QueryStringQuery($scope.panel.query || '*'), ejs.QueryStringQuery($scope.panel.query || '*'),
ejs.RangeFilter(config.timefield) ejs.RangeFilter(config.timefield)
.from($scope.from) .from($scope.panel.time.from)
.to($scope.to) .to($scope.panel.time.to)
.cache(false) .cache(false)
)))).size(0) )))).size(0)
.doSearch(); .doSearch();
...@@ -51,11 +47,19 @@ angular.module('kibana.map', []) ...@@ -51,11 +47,19 @@ angular.module('kibana.map', [])
}); });
} }
$scope.$watch(function() { if (!(_.isUndefined($scope.panel.group))) {
return angular.toJson([$scope.from, $scope.to]) $scope.$on($scope.panel.group+"-query", function(event, query) {
}, function(){ $scope.panel.query = query;
$scope.get_data(); $scope.get_data();
}); });
$scope.$on($scope.panel.group+"-time", function(event, time) {
$scope.panel.time = time;
$scope.get_data();
});
}
// Now that we're all setup, request the time from our group
$rootScope.$broadcast($scope.panel.group+"-get_time")
}) })
.directive('map', function() { .directive('map', function() {
......
...@@ -2,7 +2,7 @@ labjs = labjs.script("common/lib/panels/jquery.flot.js") ...@@ -2,7 +2,7 @@ labjs = labjs.script("common/lib/panels/jquery.flot.js")
.script("common/lib/panels/jquery.flot.pie.js") .script("common/lib/panels/jquery.flot.pie.js")
angular.module('kibana.pie', []) angular.module('kibana.pie', [])
.controller('pie', function($scope, $location) { .controller('pie', function($scope, $rootScope) {
// Set and populate defaults // Set and populate defaults
var _d = { var _d = {
...@@ -26,6 +26,9 @@ angular.module('kibana.pie', []) ...@@ -26,6 +26,9 @@ angular.module('kibana.pie', [])
} }
$scope.get_data = function() { $scope.get_data = function() {
if(_.isUndefined($scope.panel.time))
return
var request = $scope.ejs.Request().indices($scope.index); var request = $scope.ejs.Request().indices($scope.index);
// If we have an array, use query facet // If we have an array, use query facet
...@@ -36,8 +39,8 @@ angular.module('kibana.pie', []) ...@@ -36,8 +39,8 @@ angular.module('kibana.pie', [])
queries.push(ejs.FilteredQuery( queries.push(ejs.FilteredQuery(
ejs.QueryStringQuery(v.query || '*'), ejs.QueryStringQuery(v.query || '*'),
ejs.RangeFilter(config.timefield) ejs.RangeFilter(config.timefield)
.from($scope.from) .from($scope.panel.time.from)
.to($scope.to) .to($scope.panel.time.to)
.cache(false)) .cache(false))
) )
}); });
...@@ -74,8 +77,8 @@ angular.module('kibana.pie', []) ...@@ -74,8 +77,8 @@ angular.module('kibana.pie', [])
ejs.FilteredQuery( ejs.FilteredQuery(
ejs.QueryStringQuery($scope.panel.query.query || '*'), ejs.QueryStringQuery($scope.panel.query.query || '*'),
ejs.RangeFilter(config.timefield) ejs.RangeFilter(config.timefield)
.from($scope.from) .from($scope.panel.time.from)
.to($scope.to) .to($scope.panel.time.to)
.cache(false) .cache(false)
)))).size(0) )))).size(0)
.doSearch(); .doSearch();
...@@ -100,11 +103,19 @@ angular.module('kibana.pie', []) ...@@ -100,11 +103,19 @@ angular.module('kibana.pie', [])
} }
} }
$scope.$watch(function() { if (!(_.isUndefined($scope.panel.group))) {
return angular.toJson([$scope.from, $scope.to]) $scope.$on($scope.panel.group+"-query", function(event, query) {
}, function(){ $scope.panel.query.query = query;
$scope.get_data(); $scope.get_data();
}); });
$scope.$on($scope.panel.group+"-time", function(event, time) {
$scope.panel.time = time;
$scope.get_data();
});
}
// Now that we're all setup, request the time from our group
$rootScope.$broadcast($scope.panel.group+"-get_time")
}) })
.directive('pie', function() { .directive('pie', function() {
......
<div ng-controller='sort' style="white-space: nowrap;"> <div ng-controller='sort' style="white-space: nowrap;">
<h4 ng-class="{'ng-cloak': !panel.title}">{{panel.title}}</h4> <h4 ng-class="{'ng-cloak': !panel.title}">{{panel.title}}</h4>
<label><small>{{panel.label}}</small></label>
<select style="width:85%" ng-model="panel.sort[0]" ng-options="f for f in fields"></select>
<i ng-click="toggle_sort()" ng-class="{'icon-chevron-up': panel.sort[1] == 'asc','icon-chevron-down': panel.sort[1] == 'desc'}"></i> <i ng-click="toggle_sort()" ng-class="{'icon-chevron-up': panel.sort[1] == 'asc','icon-chevron-down': panel.sort[1] == 'desc'}"></i>
<select ng-model="panel.sort[0]" ng-options="f for f in fields"></select>
</div> </div>
\ No newline at end of file
...@@ -3,6 +3,7 @@ angular.module('kibana.sort', []) ...@@ -3,6 +3,7 @@ angular.module('kibana.sort', [])
// Set and populate defaults // Set and populate defaults
var _d = { var _d = {
label : "Sort",
query : "*", query : "*",
size : 100, size : 100,
sort : [config.timefield,'desc'], sort : [config.timefield,'desc'],
......
<div ng-controller='stringquery'> <div ng-controller='stringquery'>
<h4 ng-class="{'ng-cloak': !panel.title}">{{panel.title}}</h4> <h4 ng-class="{'ng-cloak': !panel.title}">{{panel.title}}</h4>
<form class="form-search" style="margin-bottom:0px"> <form class="input-append" style="margin-bottom:0px; white-space:nowrap;">
<input type="text" class="input-medium search-query" ng-model="query" style="width:85%"> <label><small>{{panel.label}}</small></label>
<button type="submit" class="btn" ng-click="send_query(query)">Search</button> <input type="text" ng-model="panel.query" style="width:90%">
<button type="submit" class="btn" ng-click="send_query(panel.query)"><i class="icon-search"></i></button>
</form> </form>
</div> </div>
\ No newline at end of file
...@@ -3,6 +3,7 @@ angular.module('kibana.stringquery', []) ...@@ -3,6 +3,7 @@ angular.module('kibana.stringquery', [])
// Set and populate defaults // Set and populate defaults
var _d = { var _d = {
label : "Search",
query : "*", query : "*",
size : 100, size : 100,
sort : [config.timefield,'desc'], sort : [config.timefield,'desc'],
......
...@@ -12,28 +12,23 @@ angular.module('kibana.table', []) ...@@ -12,28 +12,23 @@ angular.module('kibana.table', [])
? _d[k] : $scope.panel[k]; ? _d[k] : $scope.panel[k];
}); });
// Events which this panel receives and sends
if (!(_.isUndefined($scope.panel.group))) {
// Receives these events
$scope.$on($scope.panel.group+"-query", function(event, query) {
$scope.panel.query = query;
$scope.get_data();
});
}
$scope.toggle_sort = function() { $scope.toggle_sort = function() {
$scope.panel.sort[1] = $scope.panel.sort[1] == 'asc' ? 'desc' : 'asc'; $scope.panel.sort[1] = $scope.panel.sort[1] == 'asc' ? 'desc' : 'asc';
} }
$scope.get_data = function() { $scope.get_data = function() {
// Make sure we have everything for the request to complete
if(_.isUndefined($scope.panel.time))
return
var request = $scope.ejs.Request().indices($scope.index); var request = $scope.ejs.Request().indices($scope.index);
var results = request var results = request
.query(ejs.FilteredQuery( .query(ejs.FilteredQuery(
ejs.QueryStringQuery($scope.panel.query || '*'), ejs.QueryStringQuery($scope.panel.query || '*'),
ejs.RangeFilter(config.timefield) ejs.RangeFilter(config.timefield)
.from($scope.from) .from($scope.panel.time.from)
.to($scope.to) .to($scope.panel.time.to)
.cache(false) .cache(false)
) )
) )
...@@ -63,10 +58,22 @@ angular.module('kibana.table', []) ...@@ -63,10 +58,22 @@ angular.module('kibana.table', [])
}); });
} }
$scope.$watch(function() { $scope.$watch(function() {
return angular.toJson([$scope.from, $scope.to, $scope.panel.sort]) return angular.toJson($scope.panel.sort)
}, function(){ }, function(){$scope.get_data()});
$scope.get_data();
}); if (!(_.isUndefined($scope.panel.group))) {
$scope.$on($scope.panel.group+"-query", function(event, query) {
$scope.panel.query = query;
$scope.get_data();
});
$scope.$on($scope.panel.group+"-time", function(event, time) {
$scope.panel.time = time;
$scope.get_data();
});
}
// Now that we're all setup, request the time from our group
$rootScope.$broadcast($scope.panel.group+"-get_time")
}) })
<div ng-controller='timepicker' style="white-space: nowrap;">
<h4 ng-class="{'ng-cloak': !panel.title}">{{panel.title}}</h4>
<div class="row-fluid" ng-switch="panel.mode">
<div ng-switch-when="absolute">
<div class="span5">
<form class="nomargin">
<label><small>From</small></label>
<input type="text" class="input-smaller" ng-change="time_check()" ng-model="timepicker.from.date" data-date-format="mm/dd/yyyy" bs-datepicker>
<input type="text" class="input-mini" ng-change="time_check()" data-show-meridian="false" data-show-seconds="true" ng-model="timepicker.from.time" bs-timepicker>
</form>
</div>
<div class="span5" style="margin-left:10px">
<form class="nomargin">
<label style="margin-left:5px"><small>To (<a ng-click="to_now()">now</a>)</small></label>
<input type="text" class="input-smaller" ng-change="time_check()" ng-model="timepicker.to.date" data-date-format="mm/dd/yyyy" bs-datepicker>
<input type="text" class="input-mini" ng-change="time_check()" data-show-meridian="false" data-show-seconds="true" ng-model="timepicker.to.time" bs-timepicker>
</form>
</div>
<div class="span1">
<form class="nomargin">
<label><small><br></small></label>
<button class="btn" ng-click="time_apply()" ><i class="icon-check"></i></button>
</form>
</div>
</div>
<div ng-switch-when="since">
<div class="span5">
<form class="nomargin">
<label><small>Since</small></label>
<input type="text" class="input-smaller" ng-change="time_check()" ng-model="timepicker.from.date" data-date-format="mm/dd/yyyy" bs-datepicker>
<input type="text" class="input-mini" ng-change="time_check()" data-show-meridian="false" data-show-seconds="true" ng-model="timepicker.from.time" bs-timepicker>
</form>
</div>
<div class="span1" style="margin-left:10px">
<form class="nomargin">
<label><small><br></small></label>
<button class="btn" ng-click="time_apply()" ><i class="icon-check"></i></button>
</form>
</div>
</div>
<div ng-switch-when="relative">
<div class="span11">
<form class="nomargin input-append">
<label><small>The last</small></label>
<button class="btn btn" ng-repeat='timespan in panel.time_options' ng-class="{'btn-success': (panel.timespan == timespan)}" ng-click="set_timespan(timespan)">{{timespan}}</button>
<!--<select ng-model="panel.sort[0]" ng-options="f for f in fields"></select>-->
</form>
</div>
</div>
</div>
<div class="row-fluid nomargin">
<div class="span12 small">
<a ng-click="set_mode('relative')" ng-class="{'strong': (panel.mode == 'relative')}">Relative</a> |
<a ng-click="set_mode('absolute')" ng-class="{'strong': (panel.mode == 'absolute')}">Absolute</a> |
<a ng-click="set_mode('since')" ng-class="{'strong': (panel.mode == 'since')}">Since</a>
<span ng-hide="panel.mode == 'absolute'"> |
<input type="checkbox" ng-model="panel.refresh.enable"> Auto-refresh
<span ng-class="{'ng-cloak': !panel.refresh.enable}">
every <a data-title="<small>Auto-refresh Settings</small>" data-placement="bottom" bs-popover="'panels/timepicker/refreshctrl.html'">{{panel.refresh.interval}}s</a>.
</span>
</span>
</div>
</div>
</div>
\ No newline at end of file
angular.module('kibana.timepicker', [])
.controller('timepicker', function($scope, $rootScope, $timeout) {
// Set and populate defaults
var _d = {
mode : "relative",
time_options : ['5m','15m','1h','6h','12h','24h','2d','7d','30d'],
timespan : '15m',
refresh : {
enable: false,
interval: 3,
min: 3
},
time : {
from : $scope.time.from,
to : $scope.time.to
}
}
_.each(_d, function(v, k) {
$scope.panel[k] = _.isUndefined($scope.panel[k])
? _d[k] : $scope.panel[k];
});
// Private refresh interval that we can use for view display without causing
// unnecessary refreshes during changes
$scope.refresh_interval = $scope.panel.refresh.interval
// Init a private time object with Date() objects depending on mode
switch($scope.panel.mode) {
case 'absolute':
$scope.time = {
from : Date.parse($scope.panel.time.from),
to : Date.parse($scope.panel.time.to)
}
break;
case 'since':
$scope.time = {
from : Date.parse($scope.panel.time.from),
to : new Date()
}
break;
case 'relative':
$scope.time = {
from : time_ago($scope.panel.timespan),
to : new Date()
}
break;
}
// Init the values for the time/date pickers
$scope.timepicker = {
from : {
time : $scope.time.from.format("HH:MM:ss"),
date : $scope.time.from.format("mm/dd/yyyy")
},
to : {
time : $scope.time.to.format("HH:MM:ss"),
date : $scope.time.to.format("mm/dd/yyyy")
}
}
// In the case that a panel is not ready to receive a time event, it may
// request one be sent by broadcasting a 'get_time' even to its group
if (!(_.isUndefined($scope.panel.group))) {
// Broadcast time when initializing
$rootScope.$broadcast($scope.panel.group+"-time", $scope.time)
// And whenever it is requested
$scope.$on($scope.panel.group+"-get_time", function(event) {
$rootScope.$broadcast($scope.panel.group+"-time", $scope.time)
});
}
$scope.$watch('panel.refresh.enable', function() {$scope.refresh()});
$scope.$watch('panel.refresh.interval', function() {
$timeout(function(){
if(_.isNumber($scope.panel.refresh.interval)) {
if($scope.panel.refresh.interval < $scope.panel.refresh.min) {
$scope.panel.refresh.interval = $scope.panel.refresh.min
$timeout.cancel($scope.panel.refresh.timer)
return;
}
$timeout.cancel($scope.panel.refresh.timer)
$scope.refresh()
} else {
$timeout.cancel($scope.panel.refresh.timer)
}
});
});
$scope.refresh = function() {
if ($scope.panel.refresh.enable) {
$scope.time_apply();
$scope.panel.refresh.timer = $timeout(
$scope.refresh,
$scope.panel.refresh.interval*1000
);
} else {
$timeout.cancel($scope.panel.refresh.timer)
}
}
$scope.set_mode = function(mode) {
$scope.panel.mode = mode;
$scope.panel.refresh.enable = mode === 'absolute' ?
false : $scope.panel.refresh.enable
}
$scope.to_now = function() {
$scope.timepicker.to = {
time : new Date().format("HH:MM:ss"),
date : new Date().format("mm/dd/yyyy")
}
}
$scope.set_timespan = function(timespan) {
$scope.panel.timespan = timespan;
$scope.timepicker.from = {
time : time_ago(timespan).format("HH:MM:ss"),
date : time_ago(timespan).format("mm/dd/yyyy")
}
$scope.time_apply();
}
$scope.time_check = function(){
var from = $scope.panel.mode === 'relative' ? time_ago($scope.panel.timespan) :
Date.parse($scope.timepicker.from.date + " " + $scope.timepicker.from.time)
var to = $scope.panel.mode !== 'absolute' ? new Date() :
Date.parse($scope.timepicker.to.date + " " + $scope.timepicker.to.time)
if (from.getTime() >= to.getTime())
from = new Date(to.getTime() - 1000)
// Janky 0s timeout to get around $scope queue processing view issue
$timeout(function(){
$scope.timepicker = {
from : {
time : from.format("HH:MM:ss"),
date : from.format("mm/dd/yyyy")
},
to : {
time : to.format("HH:MM:ss"),
date : to.format("mm/dd/yyyy")
}
}
});
}
$scope.time_apply = function() {
$scope.time_check();
// Update internal time object
$scope.time = {
from : Date.parse($scope.timepicker.from.date + " " + $scope.timepicker.from.time),
to : Date.parse($scope.timepicker.to.date + " " + $scope.timepicker.to.time)
};
// Broadcast time
$rootScope.$broadcast($scope.panel.group+"-time", $scope.time)
// Update panel's string representation of the time object
$scope.panel.time = {
from : $scope.time.from.format("mm/dd/yyyy HH:MM:ss"),
to : $scope.time.to.format("mm/dd/yyyy HH:MM:ss")
};
};
})
\ No newline at end of file
<form name="refreshPopover" class='form-inline' style="margin:0px">
<label><small>Interval (seconds)</small></label>
<input type="number" class="input-mini" ng-model="refresh_interval">
<button type="button" class="btn" ng-click="panel.refresh.interval=refresh_interval;dismiss()"><i class="icon-check"></i></button>
</form>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment