Commit 0d560c24 by Rashid Khan

Refactoring query communication into service

parent e399c328
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -107,6 +107,10 @@ ...@@ -107,6 +107,10 @@
cursor: pointer; cursor: pointer;
} }
.pointer:hover {
color: #fff;
}
.pointer { .pointer {
cursor: pointer; cursor: pointer;
} }
......
...@@ -91,7 +91,7 @@ function top_field_values(docs,field,count) { ...@@ -91,7 +91,7 @@ function top_field_values(docs,field,count) {
} }
function add_to_query(original,field,value,negate) { function add_to_query(original,field,value,negate) {
var not = negate ? "NOT " : ""; var not = negate ? "-" : "";
if(value !== '') if(value !== '')
var query = field + ":" + "\"" + addslashes(value.toString()) + "\""; var query = field + ":" + "\"" + addslashes(value.toString()) + "\"";
else else
......
...@@ -22,6 +22,6 @@ var config = new Settings( ...@@ -22,6 +22,6 @@ var config = new Settings(
kibana_index: "kibana-int", kibana_index: "kibana-int",
modules: ['histogram','map','pie','table','stringquery','sort', modules: ['histogram','map','pie','table','stringquery','sort',
'timepicker','text','fields','hits','dashcontrol', 'timepicker','text','fields','hits','dashcontrol',
'column','derivequeries','trends','bettermap'], 'column','derivequeries','trends','bettermap','query'],
} }
); );
...@@ -186,7 +186,89 @@ angular.module('kibana.services', []) ...@@ -186,7 +186,89 @@ angular.module('kibana.services', [])
} }
}) })
.service('query', function() { .service('query', function(dashboard) {
// Create an object to hold our service state on the dashboard
dashboard.current.services.query = dashboard.current.services.query || {};
_.defaults(dashboard.current.services.query,{
idQueue : [],
list : {},
ids : [],
});
// For convenience
var _q = dashboard.current.services.query;
this.colors = [
"#7EB26D","#EAB839","#6ED0E0","#EF843C","#E24D42","#1F78C1","#BA43A9","#705DA0", //1
"#508642","#CCA300","#447EBC","#C15C17","#890F02","#0A437C","#6D1F62","#584477", //2
"#B7DBAB","#F4D598","#70DBED","#F9BA8F","#F29191","#82B5D8","#E5A8E2","#AEA2E0", //3
"#629E51","#E5AC0E","#64B0C8","#E0752D","#BF1B00","#0A50A1","#962D82","#614D93", //4
"#9AC48A","#F2C96D","#65C5DB","#F9934E","#EA6460","#5195CE","#D683CE","#806EB7", //5
"#3F6833","#967302","#2F575E","#99440A","#58140C","#052B51","#511749","#3F2B5B", //6
"#E0F9D7","#FCEACA","#CFFAFF","#F9E2D2","#FCE2DE","#BADFF4","#F9D9F9","#DEDAF7" //7
];
// Save a reference to this
this.list = dashboard.current.services.query.list;
this.ids = dashboard.current.services.query.ids;
var self = this;
var init = function() {
if (self.ids.length == 0) {
self.set({});
}
}
// This is used both for adding queries and modifying them. If an id is passed, the query at that id is updated
this.set = function(query,id) {
if(!_.isUndefined(id)) {
if(!_.isUndefined(self.list[id])) {
_.extend(self.list[id],query);
return id;
} else {
return false;
}
} else {
var _id = nextId();
var _query = {
query: '*',
alias: '',
color: colorAt(_id)
}
_.defaults(query,_query)
self.list[_id] = query;
self.ids.push(_id)
return id;
}
}
this.remove = function(id) {
if(!_.isUndefined(self.list[id])) {
delete self.list[id];
// This must happen on the full path also since _.without returns a copy
self.ids = dashboard.current.services.query.ids = _.without(self.ids,id)
_q.idQueue.unshift(id)
_q.idQueue.sort(function(a,b){return a-b});
return true;
} else {
return false;
}
}
var nextId = function() {
if(_q.idQueue.length > 0) {
return _q.idQueue.shift()
} else {
return self.ids.length;
}
}
var colorAt = function(id) {
return self.colors[id % self.colors.length]
}
init();
}) })
.service('dashboard', function($routeParams, $http, $rootScope, ejsResource, timer) { .service('dashboard', function($routeParams, $http, $rootScope, ejsResource, timer) {
......
...@@ -5,13 +5,6 @@ ...@@ -5,13 +5,6 @@
Also note that geoJSON is <strong>long,lat NOT lat,long</strong>. Also note that geoJSON is <strong>long,lat NOT lat,long</strong>.
</div> </div>
</div> </div>
<div class="row-fluid">
<div class="span11">
<h6>Query</h6>
<input type="text" style="width:100%" ng-model="panel.query">
</div>
</div>
<div class="row-fluid"> <div class="row-fluid">
<div class="span4"> <div class="span4">
<form> <form>
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
*/ */
angular.module('kibana.bettermap', []) angular.module('kibana.bettermap', [])
.controller('bettermap', function($scope, eventBus) { .controller('bettermap', function($scope, eventBus, query) {
// Set and populate defaults // Set and populate defaults
var _d = { var _d = {
...@@ -37,11 +37,12 @@ angular.module('kibana.bettermap', []) ...@@ -37,11 +37,12 @@ angular.module('kibana.bettermap', [])
_.defaults($scope.panel,_d) _.defaults($scope.panel,_d)
$scope.init = function() { $scope.init = function() {
eventBus.register($scope,'time', function(event,time){set_time(time)});
eventBus.register($scope,'query', function(event, query) { $scope.$on('refresh',function(){
$scope.panel.query = _.isArray(query) ? query[0] : query;
$scope.get_data(); $scope.get_data();
}); })
eventBus.register($scope,'time', function(event,time){set_time(time)});
// Now that we're all setup, request the time from our group // Now that we're all setup, request the time from our group
eventBus.broadcast($scope.$id,$scope.panel.group,'get_time') eventBus.broadcast($scope.$id,$scope.panel.group,'get_time')
...@@ -64,9 +65,14 @@ $scope.get_data = function(segment,query_id) { ...@@ -64,9 +65,14 @@ $scope.get_data = function(segment,query_id) {
var _segment = _.isUndefined(segment) ? 0 : segment var _segment = _.isUndefined(segment) ? 0 : segment
$scope.segment = _segment; $scope.segment = _segment;
var boolQuery = ejs.BoolQuery();
_.each(query.list,function(q) {
boolQuery = boolQuery.should(ejs.QueryStringQuery((q.query || '*') + " AND _exists_:"+$scope.panel.field))
})
var request = $scope.ejs.Request().indices($scope.index[_segment]) var request = $scope.ejs.Request().indices($scope.index[_segment])
.query(ejs.FilteredQuery( .query(ejs.FilteredQuery(
ejs.QueryStringQuery(($scope.panel.query || '*') + " AND _exists_:"+$scope.panel.field), boolQuery,
ejs.RangeFilter($scope.time.field) ejs.RangeFilter($scope.time.field)
.from($scope.time.from) .from($scope.time.from)
.to($scope.time.to) .to($scope.time.to)
...@@ -142,12 +148,6 @@ $scope.get_data = function(segment,query_id) { ...@@ -142,12 +148,6 @@ $scope.get_data = function(segment,query_id) {
$scope.get_data(); $scope.get_data();
} }
$scope.build_search = function(field,value) {
$scope.panel.query = add_to_query($scope.panel.query,field,value,false)
$scope.get_data();
eventBus.broadcast($scope.$id,$scope.panel.group,'query',[$scope.panel.query]);
}
}) })
.directive('bettermap', function() { .directive('bettermap', function() {
return { return {
......
...@@ -14,38 +14,6 @@ ...@@ -14,38 +14,6 @@
<label class="small">Note</label><small> In <strong>{{panel.mode}}</strong> mode the configured field <strong>must</strong> be a numeric type</small> <label class="small">Note</label><small> In <strong>{{panel.mode}}</strong> mode the configured field <strong>must</strong> be a numeric type</small>
</div> </div>
</div> </div>
<div class="row-fluid">
<div class="span3">
<form style="margin-bottom: 0px">
<label class="small">Label</label>
<input type="text" placeholder="New Label" style="width:70%" ng-model="newlabel">
</form>
</div>
<div class="span8">
<label class="small">Query</label>
<form class="input-append" style="margin-bottom: 0px">
<input type="text" placeholder="New Query" style="width:80%" ng-model="newquery">
<button class="btn" ng-click="add_query(newlabel,newquery);newlabel='';newquery='';set_refresh(true)"><i class="icon-plus"></i></button>
</form>
</div>
<div class="span1">
</div>
</div>
<div class="row-fluid" ng-repeat="q in panel.query">
<div class="span3">
<form style="margin-bottom: 0px">
<input type="text" style="width:70%" ng-model="q.label" ng-change="set_refresh(true)">
</form>
</div>
<div class="span8">
<form style="margin-bottom: 0px">
<input type="text" style="width:80%" ng-model="q.query" ng-change="set_refresh(true)">
</form>
</div>
<div class="span1">
<i class="icon-remove pointer" ng-click="remove_query(q)"></i>
</div>
</div>
<h5>Chart Options</h5> <h5>Chart Options</h5>
<div class="row-fluid" style="margin-bottom:10px;"> <div class="row-fluid" style="margin-bottom:10px;">
<div class="span1"> <label class="small">Bars</label><input type="checkbox" ng-model="panel.bars" ng-checked="panel.bars"></div> <div class="span1"> <label class="small">Bars</label><input type="checkbox" ng-model="panel.bars" ng-checked="panel.bars"></div>
......
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
*/ */
angular.module('kibana.histogram', []) angular.module('kibana.histogram', [])
.controller('histogram', function($scope, eventBus) { .controller('histogram', function($scope, eventBus,query) {
// Set and populate defaults // Set and populate defaults
var _d = { var _d = {
...@@ -72,19 +72,14 @@ angular.module('kibana.histogram', []) ...@@ -72,19 +72,14 @@ angular.module('kibana.histogram', [])
_.defaults($scope.panel,_d) _.defaults($scope.panel,_d)
$scope.init = function() { $scope.init = function() {
$scope.queries = query;
eventBus.register($scope,'time', function(event,time){$scope.set_time(time)}); eventBus.register($scope,'time', function(event,time){$scope.set_time(time)});
// Consider eliminating the check for array, this should always be an array $scope.$on('refresh',function(){
eventBus.register($scope,'query', function(event, query) {
if(_.isArray(query)) {
$scope.panel.query = _.map(query,function(q) {
return {query: q, label: q};
})
} else {
$scope.panel.query[0] = {query: query, label: query}
}
$scope.get_data(); $scope.get_data();
}); })
// Now that we're all setup, request the time from our group if we don't // Now that we're all setup, request the time from our group if we don't
// have it yet // have it yet
...@@ -92,21 +87,6 @@ angular.module('kibana.histogram', []) ...@@ -92,21 +87,6 @@ angular.module('kibana.histogram', [])
eventBus.broadcast($scope.$id,$scope.panel.group,'get_time') eventBus.broadcast($scope.$id,$scope.panel.group,'get_time')
} }
$scope.remove_query = function(q) {
$scope.panel.query = _.without($scope.panel.query,q);
$scope.get_data();
}
$scope.add_query = function(label,query) {
if(!(_.isArray($scope.panel.query)))
$scope.panel.query = new Array();
$scope.panel.query.unshift({
query: query,
label: label,
});
$scope.get_data();
}
$scope.get_data = function(segment,query_id) { $scope.get_data = function(segment,query_id) {
delete $scope.panel.error delete $scope.panel.error
// Make sure we have everything for the request to complete // Make sure we have everything for the request to complete
...@@ -120,21 +100,16 @@ angular.module('kibana.histogram', []) ...@@ -120,21 +100,16 @@ angular.module('kibana.histogram', [])
var _segment = _.isUndefined(segment) ? 0 : segment var _segment = _.isUndefined(segment) ? 0 : segment
var request = $scope.ejs.Request().indices($scope.index[_segment]); var request = $scope.ejs.Request().indices($scope.index[_segment]);
// Build the question part of the query // Build the query
var queries = []; _.each($scope.queries.ids, function(id) {
_.each($scope.panel.query, function(v) { var query = $scope.ejs.FilteredQuery(
queries.push($scope.ejs.FilteredQuery( ejs.QueryStringQuery($scope.queries.list[id].query || '*'),
ejs.QueryStringQuery(v.query || '*'),
ejs.RangeFilter($scope.time.field) ejs.RangeFilter($scope.time.field)
.from($scope.time.from) .from($scope.time.from)
.to($scope.time.to)) .to($scope.time.to)
) )
});
// Build the facet part, injecting the query in as a facet filter
_.each(queries, function(v) {
var facet = $scope.ejs.DateHistogramFacet("chart"+_.indexOf(queries,v)) var facet = $scope.ejs.DateHistogramFacet(id)
if($scope.panel.mode === 'count') { if($scope.panel.mode === 'count') {
facet = facet.field($scope.time.field) facet = facet.field($scope.time.field)
...@@ -145,9 +120,9 @@ angular.module('kibana.histogram', []) ...@@ -145,9 +120,9 @@ angular.module('kibana.histogram', [])
} }
facet = facet.keyField($scope.time.field).valueField($scope.panel.value_field) facet = facet.keyField($scope.time.field).valueField($scope.panel.value_field)
} }
facet = facet.interval($scope.panel.interval).facetFilter($scope.ejs.QueryFilter(v)) facet = facet.interval($scope.panel.interval).facetFilter($scope.ejs.QueryFilter(query))
request = request.facet(facet).size(0) request = request.facet(facet).size(0)
}) });
// Populate the inspector panel // Populate the inspector panel
$scope.populate_modal(request); $scope.populate_modal(request);
...@@ -174,7 +149,7 @@ angular.module('kibana.histogram', []) ...@@ -174,7 +149,7 @@ angular.module('kibana.histogram', [])
if($scope.query_id === query_id) { if($scope.query_id === query_id) {
var i = 0; var i = 0;
_.each(results.facets, function(v, k) { _.each(results.facets, function(v, id) {
// Null values at each end of the time range ensure we see entire range // Null values at each end of the time range ensure we see entire range
if(_.isUndefined($scope.data[i]) || _segment == 0) { if(_.isUndefined($scope.data[i]) || _segment == 0) {
...@@ -197,15 +172,12 @@ angular.module('kibana.histogram', []) ...@@ -197,15 +172,12 @@ angular.module('kibana.histogram', [])
// Create the flot series object // Create the flot series object
var series = { var series = {
data: { data: {
label: $scope.panel.query[i].label || "query"+(parseInt(i)+1), id: id,
data: data, data: data,
hits: hits hits: hits
}, },
}; };
if (!(_.isUndefined($scope.panel.query[i].color)))
series.data.color = $scope.panel.query[i].color;
$scope.data[i] = series.data $scope.data[i] = series.data
i++; i++;
...@@ -276,6 +248,12 @@ angular.module('kibana.histogram', []) ...@@ -276,6 +248,12 @@ angular.module('kibana.histogram', [])
// Function for rendering panel // Function for rendering panel
function render_panel() { function render_panel() {
// Populate from the query service
_.each(scope.data,function(series) {
series.label = scope.queries.list[series.id].alias,
series.color = scope.queries.list[series.id].color
})
// Set barwidth based on specified interval // Set barwidth based on specified interval
var barwidth = interval_to_seconds(scope.panel.interval)*1000 var barwidth = interval_to_seconds(scope.panel.interval)*1000
......
...@@ -26,38 +26,4 @@ ...@@ -26,38 +26,4 @@
<label class="small">Labels</label><input type="checkbox" ng-model="panel.labels" ng-checked="panel.labels"> <label class="small">Labels</label><input type="checkbox" ng-model="panel.labels" ng-checked="panel.labels">
</div> </div>
</div> </div>
<h5>Queries</h5>
<div class="row-fluid">
<div class="span3">
<form style="margin-bottom: 0px">
<label class="small">Label</label>
<input type="text" placeholder="New Label" style="width:70%" ng-model="newlabel">
</form>
</div>
<div class="span8">
<form class="input-append" style="margin-bottom: 0px">
<label class="small">Query</label>
<input type="text" placeholder="New Query" style="width:80%" ng-model="newquery">
<button class="btn" ng-click="add_query(newlabel,newquery);newlabel='';newquery='';set_refresh(true)"><i class="icon-plus"></i></button>
</form>
</div>
<div class="span1">
</div>
</div>
<div class="row-fluid" ng-repeat="q in panel.query">
<div class="span3">
<form style="margin-bottom: 0px">
<input type="text" style="width:70%" ng-model="q.label" ng-change="set_refresh(true)">
</form>
</div>
<div class="span8">
<form class="input-append" style="margin-bottom: 0px">
<input type="text" style="width:80%" ng-model="q.query" ng-change="set_refresh(true)">
<button class="btn" ng-click="get_data()"><i class="icon-search"></i></button>
</form>
</div>
<div class="span1">
<i class="icon-remove pointer" ng-click="remove_query(q)"></i>
</div>
</div>
</div> </div>
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
*/ */
angular.module('kibana.hits', []) angular.module('kibana.hits', [])
.controller('hits', function($scope, eventBus) { .controller('hits', function($scope, eventBus, query) {
// Set and populate defaults // Set and populate defaults
var _d = { var _d = {
...@@ -40,16 +40,20 @@ angular.module('kibana.hits', []) ...@@ -40,16 +40,20 @@ angular.module('kibana.hits', [])
_.defaults($scope.panel,_d) _.defaults($scope.panel,_d)
$scope.init = function () { $scope.init = function () {
$scope.queries = query;
$scope.hits = 0; $scope.hits = 0;
eventBus.register($scope,'time', function(event,time){ eventBus.register($scope,'time', function(event,time){
set_time(time) set_time(time)
}); });
eventBus.register($scope,'query', function(event, query) {
$scope.panel.query = _.map(query,function(q) {
return {query: q, label: q}; $scope.$on('refresh',function(){
}) console.log($scope.queries)
console.log(query)
$scope.get_data(); $scope.get_data();
}); })
// Now that we're all setup, request the time from our group // Now that we're all setup, request the time from our group
eventBus.broadcast($scope.$id,$scope.panel.group,'get_time') eventBus.broadcast($scope.$id,$scope.panel.group,'get_time')
} }
...@@ -66,23 +70,18 @@ angular.module('kibana.hits', []) ...@@ -66,23 +70,18 @@ angular.module('kibana.hits', [])
var request = $scope.ejs.Request().indices($scope.index[_segment]); var request = $scope.ejs.Request().indices($scope.index[_segment]);
// Build the question part of the query // Build the question part of the query
var queries = []; _.each($scope.queries.ids, function(id) {
_.each($scope.panel.query, function(v) { var query = $scope.ejs.FilteredQuery(
queries.push($scope.ejs.FilteredQuery( ejs.QueryStringQuery($scope.queries.list[id].query || '*'),
ejs.QueryStringQuery(v.query || '*'),
ejs.RangeFilter($scope.time.field) ejs.RangeFilter($scope.time.field)
.from($scope.time.from) .from($scope.time.from)
.to($scope.time.to)) .to($scope.time.to))
)
});
// Build the facet part
_.each(queries, function(v) {
request = request request = request
.facet($scope.ejs.QueryFacet("query"+_.indexOf(queries,v)) .facet($scope.ejs.QueryFacet(id)
.query(v) .query(query)
).size(0) ).size(0)
}) });
// TODO: Spy for hits panel // TODO: Spy for hits panel
//$scope.populate_modal(request); //$scope.populate_modal(request);
...@@ -107,14 +106,15 @@ angular.module('kibana.hits', []) ...@@ -107,14 +106,15 @@ angular.module('kibana.hits', [])
} }
if($scope.query_id === query_id) { if($scope.query_id === query_id) {
var i = 0; var i = 0;
_.each(results.facets, function(v, k) { _.each(results.facets, function(v, id) {
var hits = _.isUndefined($scope.data[i]) || _segment == 0 ? var hits = _.isUndefined($scope.data[i]) || _segment == 0 ?
v.count : $scope.data[i].hits+v.count v.count : $scope.data[i].hits+v.count
$scope.hits += v.count $scope.hits += v.count
// Create series // Create series
$scope.data[i] = { $scope.data[i] = {
label: $scope.panel.query[i].label || "query"+(parseInt(i)+1), //label: $scope.panel.query[i].label || "query"+(parseInt(i)+1),
id: id,
hits: hits, hits: hits,
data: [[i,hits]] data: [[i,hits]]
}; };
...@@ -177,6 +177,11 @@ angular.module('kibana.hits', []) ...@@ -177,6 +177,11 @@ angular.module('kibana.hits', [])
// Function for rendering panel // Function for rendering panel
function render_panel() { function render_panel() {
_.each(scope.data,function(series) {
series.label = scope.queries.list[series.id].alias,
series.color = scope.queries.list[series.id].color
})
var scripts = $LAB.script("common/lib/panels/jquery.flot.js").wait() var scripts = $LAB.script("common/lib/panels/jquery.flot.js").wait()
.script("common/lib/panels/jquery.flot.pie.js") .script("common/lib/panels/jquery.flot.pie.js")
......
<div>
<div class="row-fluid">
<div class="span12">
No options here
</div>
</div>
</div>
\ No newline at end of file
<style>
</style>
<a class="close" ng-click="render();dismiss();" href="">×</a>
<input class="input-medium" type="text" ng-model="queries.list[id].alias" placeholder='Alias...' />
<i ng-repeat="color in queries.colors" class="pointer" ng-class="{'icon-circle-blank':queries.list[id].color == color,'icon-circle':queries.list[id].color != color}" style="color:{{color}}" ng-click="queries.list[id].color = color;render();"> </i>
<kibana-panel ng-controller='query' ng-init="init()">
<style>
.short-query {
display:inline-block;
margin-left: 10px;
}
.begin-query {
position:absolute;
left:15px;
top:5px;
}
.end-query {
position:absolute;
right:15px;
top:5px;
}
.panel-query {
padding-left: 35px !important;
height: 31px !important;
-webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
-moz-box-sizing: border-box; /* Firefox, other Gecko */
box-sizing: border-box; /* Opera/IE 8+ */
}
.form-search:hover .has-remove {
padding-left: 50px !important;
}
.remove-query {
opacity: 0;
}
.last-query {
padding-right: 45px !important;
}
.form-search:hover .remove-query {
opacity: 1;
}
</style>
<label class="small">{{panel.label}}</label>
<div ng-repeat="id in queries.ids" ng-class="{'short-query': queries.ids.length>1}">
<form class="form-search" style="position:relative" ng-submit="refresh()">
<span class="begin-query">
<i class="icon-circle pointer" data-unique="1" bs-popover="'panels/query/meta.html'" data-placement="right" style="color:{{queries.list[id].color}}"></i>
<i class="icon-remove-sign pointer remove-query" ng-show="queries.ids.length>1" ng-click="queries.remove(id);refresh()"></i>
</span>
<input class="search-query panel-query" ng-class="{'input-block-level': queries.ids.length==1,'last-query': $last,'has-remove': queries.ids.length>1}" bs-typeahead="panel.history" data-min-length=0 data-items=100 type="text" ng-model="queries.list[id].query"/>
<span class="end-query">
<i class="icon-search pointer" ng-click="refresh()" ng-show="$last"></i>
<i class="icon-plus pointer" ng-click="queries.set({})" ng-show="$last"></i>
</span
</form>
</div>
</kibana-panel>
\ No newline at end of file
/*
## query
An experimental panel for the query service
### Parameters
* label :: The label to stick over the field
* query :: A string or an array of querys. String if multi is off, array if it is on
This should be fixed, it should always be an array even if its only
one element
* multi :: Allow input of multiple queries? true/false
* multi_arrange :: How to arrange multu query string panels, 'vertical' or 'horizontal'
### Group Events
#### Sends
* query :: Always broadcast as an array, even in multi: false
#### Receives
* query :: An array of queries. This is probably needs to be fixed.
*/
angular.module('kibana.query', [])
.controller('query', function($scope, eventBus, query, $rootScope) {
// Set and populate defaults
var _d = {
status : "Experimental",
label : "Search",
query : "*",
group : "default",
history : [],
remember: 10 // max: 100, angular strap can't take a variable for items param
}
_.defaults($scope.panel,_d);
$scope.queries = query;
$scope.init = function() {
}
$scope.refresh = function(query) {
console.log('refresh')
$rootScope.$broadcast('refresh')
}
$scope.render = function(query) {
console.log('render')
$rootScope.$broadcast('render')
}
$scope.add_query = function() {
if (_.isArray($scope.panel.query))
$scope.panel.query.push("")
else {
$scope.panel.query = new Array($scope.panel.query)
$scope.panel.query.push("")
}
}
var update_history = function(query) {
if($scope.panel.remember > 0) {
$scope.panel.history = _.union(query.reverse(),$scope.panel.history)
var _length = $scope.panel.history.length
if(_length > $scope.panel.remember) {
$scope.panel.history = $scope.panel.history.slice(0,$scope.panel.remember)
}
}
}
});
\ No newline at end of file
<div class="row-fluid"> <div class="row-fluid">
<div style="width:90%">
<form class="input-append">
<h6>Query</h6>
<input type="text" style="width:90%" ng-model="panel.query">
<button class="btn" ng-click="get_data();"><i class="icon-search"></i></button>
</form>
</div>
</div>
<div class="row-fluid">
<div class="span4"> <div class="span4">
<form class="input-append"> <form class="input-append">
<h6>Add field</h6> <h6>Add field</h6>
......
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
*/ */
angular.module('kibana.table', []) angular.module('kibana.table', [])
.controller('table', function($scope, eventBus, fields) { .controller('table', function($rootScope, $scope, eventBus, fields, query) {
// Set and populate defaults // Set and populate defaults
var _d = { var _d = {
...@@ -60,15 +60,11 @@ angular.module('kibana.table', []) ...@@ -60,15 +60,11 @@ angular.module('kibana.table', [])
} }
$scope.set_listeners = function(group) { $scope.set_listeners = function(group) {
$scope.$on('refresh',function(){$scope.get_data()})
eventBus.register($scope,'time',function(event,time) { eventBus.register($scope,'time',function(event,time) {
$scope.panel.offset = 0; $scope.panel.offset = 0;
set_time(time) set_time(time)
}); });
eventBus.register($scope,'query',function(event,query) {
$scope.panel.offset = 0;
$scope.panel.query = _.isArray(query) ? query[0] : query;
$scope.get_data();
});
eventBus.register($scope,'sort', function(event,sort){ eventBus.register($scope,'sort', function(event,sort){
$scope.panel.sort = _.clone(sort); $scope.panel.sort = _.clone(sort);
$scope.get_data(); $scope.get_data();
...@@ -77,7 +73,7 @@ angular.module('kibana.table', []) ...@@ -77,7 +73,7 @@ angular.module('kibana.table', [])
$scope.panel.fields = _.clone(fields) $scope.panel.fields = _.clone(fields)
}); });
eventBus.register($scope,'table_documents', function(event, docs) { eventBus.register($scope,'table_documents', function(event, docs) {
$scope.panel.query = docs.query; query.list[query.ids[0]].query = docs.query;
$scope.data = docs.docs; $scope.data = docs.docs;
}); });
} }
...@@ -116,10 +112,11 @@ angular.module('kibana.table', []) ...@@ -116,10 +112,11 @@ angular.module('kibana.table', [])
} }
$scope.build_search = function(field,value,negate) { $scope.build_search = function(field,value,negate) {
$scope.panel.query = add_to_query($scope.panel.query,field,value,negate) _.each(query.list,function(q) {
q.query = add_to_query(q.query,field,value,negate);
})
$scope.panel.offset = 0; $scope.panel.offset = 0;
$scope.get_data(); $rootScope.$broadcast('refresh')
eventBus.broadcast($scope.$id,$scope.panel.group,'query',[$scope.panel.query]);
} }
$scope.get_data = function(segment,query_id) { $scope.get_data = function(segment,query_id) {
...@@ -135,8 +132,15 @@ angular.module('kibana.table', []) ...@@ -135,8 +132,15 @@ angular.module('kibana.table', [])
$scope.segment = _segment; $scope.segment = _segment;
var request = $scope.ejs.Request().indices($scope.index[_segment]) var request = $scope.ejs.Request().indices($scope.index[_segment])
.query(ejs.FilteredQuery(
ejs.QueryStringQuery($scope.panel.query || '*'), var boolQuery = ejs.BoolQuery();
_.each(query.list,function(q) {
boolQuery = boolQuery.should(ejs.QueryStringQuery(q.query || '*'))
})
request = request.query(
ejs.FilteredQuery(
boolQuery,
ejs.RangeFilter($scope.time.field) ejs.RangeFilter($scope.time.field)
.from($scope.time.from) .from($scope.time.from)
.to($scope.time.to) .to($scope.time.to)
...@@ -244,7 +248,7 @@ angular.module('kibana.table', []) ...@@ -244,7 +248,7 @@ angular.module('kibana.table', [])
}); });
eventBus.broadcast($scope.$id,$scope.panel.group,"table_documents", eventBus.broadcast($scope.$id,$scope.panel.group,"table_documents",
{ {
query: $scope.panel.query, query: query.list[query.ids[0]].query,
docs : _.pluck($scope.data,'_source'), docs : _.pluck($scope.data,'_source'),
index: $scope.index index: $scope.index
}); });
......
...@@ -26,36 +26,4 @@ ...@@ -26,36 +26,4 @@
<select class="input-small" ng-model="panel.arrangement" ng-options="f for f in ['horizontal','vertical']"></select></span> <select class="input-small" ng-model="panel.arrangement" ng-options="f for f in ['horizontal','vertical']"></select></span>
</div> </div>
</div> </div>
<h5>Queries</h5>
<div class="row-fluid">
<div class="span3">
<form style="margin-bottom: 0px">
<label class="small">Label</label>
<input type="text" placeholder="New Label" style="width:70%" ng-model="newlabel">
</form>
</div>
<div class="span8">
<form class="input-append" style="margin-bottom: 0px">
<label class="small">Query</label>
<input type="text" placeholder="New Query" style="width:80%" ng-model="newquery">
<button class="btn" ng-click="add_query(newlabel,newquery);newlabel='';newquery='';set_refresh(true)"><i class="icon-plus"></i></button>
</form>
</div>
<div class="span1">
</div>
</div>
<div class="row-fluid" ng-repeat="q in panel.query">
<div class="span3">
<form style="margin-bottom: 0px">
<input type="text" style="width:70%" ng-model="q.label" ng-change="set_refresh(true)">
</form>
</div>
<div class="span8">
<input type="text" style="width:80%" ng-model="q.query" ng-change="set_refresh(true)">
</div>
<div class="span1">
<i class="icon-remove pointer" ng-click="remove_query(q)"></i>
</div>
</div>
</div> </div>
<kibana-panel ng-controller='trends' ng-init="init()"> <kibana-panel ng-controller='trends' ng-init="init()">
<div ng-style="panel.style" style="line-height:{{panel.style['font-size']}};display:inline-block;padding-right: 5px;" ng-repeat="query in trends"> <div ng-style="panel.style" style="line-height:{{panel.style['font-size']}};display:inline-block;padding-right: 5px;" ng-repeat="query in trends">
<i class="icon-circle" style="color:{{query.info.color}}"></i>
<span ng-class="{'text-success': query.hits.new >= query.hits.old, 'text-error': query.hits.old > query.hits.new}" class='strong'> <span ng-class="{'text-success': query.hits.new >= query.hits.old, 'text-error': query.hits.old > query.hits.new}" class='strong'>
<i class='large' ng-class="{'icon-caret-up': query.hits.new >= query.hits.old, 'icon-caret-down': query.hits.old > query.hits.new}"></i> {{query.percent}}% <i class='large' ng-class="{'icon-caret-up': query.hits.new >= query.hits.old, 'icon-caret-down': query.hits.old > query.hits.new}"></i> {{query.percent}}%
</span> </span>
<span class="tiny pointer light" bs-tooltip="'Then: '+query.hits.old+', Now: '+query.hits.new">({{query.label}})</span> <span class="tiny pointer light" bs-tooltip="'Then: '+query.hits.old+', Now: '+query.hits.new" ng-show="query.label != ''">({{query.info.alias}})</span>
<br ng-show="panel.arrangement == 'vertical'"> <br ng-show="panel.arrangement == 'vertical'">
</div> </div>
</kibana-panel> </kibana-panel>
\ No newline at end of file
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
*/ */
angular.module('kibana.trends', []) angular.module('kibana.trends', [])
.controller('trends', function($scope, eventBus, kbnIndex) { .controller('trends', function($scope, eventBus, kbnIndex, query) {
// Set and populate defaults // Set and populate defaults
var _d = { var _d = {
...@@ -64,43 +64,32 @@ angular.module('kibana.trends', []) ...@@ -64,43 +64,32 @@ angular.module('kibana.trends', [])
var request = $scope.ejs.Request(); var request = $scope.ejs.Request();
// Build the question part of the query // Build the question part of the query
var queries = []; _.each(query.ids, function(id) {
_.each($scope.panel.query, function(v) { var q = $scope.ejs.FilteredQuery(
queries.push($scope.ejs.FilteredQuery( ejs.QueryStringQuery(query.list[id].query || '*'),
ejs.QueryStringQuery(v.query || '*'),
ejs.RangeFilter($scope.time.field) ejs.RangeFilter($scope.time.field)
.from($scope.time.from) .from($scope.time.from)
.to($scope.time.to)) .to($scope.time.to))
)
});
// Build the facet part
_.each(queries, function(v) {
request = request request = request
.facet($scope.ejs.QueryFacet("new"+_.indexOf(queries,v)) .facet($scope.ejs.QueryFacet(id)
.query(v) .query(q)
).size(0) ).size(0)
}) });
var queries = []; // And again for the old time period
_.each($scope.panel.query, function(v) { _.each(query.ids, function(id) {
queries.push($scope.ejs.FilteredQuery( var q = $scope.ejs.FilteredQuery(
ejs.QueryStringQuery(v.query || '*'), ejs.QueryStringQuery(query.list[id].query || '*'),
ejs.RangeFilter($scope.time.field) ejs.RangeFilter($scope.time.field)
.from($scope.old_time.from) .from($scope.old_time.from)
.to($scope.old_time.to)) .to($scope.old_time.to))
)
});
// Build the facet part
_.each(queries, function(v) {
request = request request = request
.facet($scope.ejs.QueryFacet("old"+_.indexOf(queries,v)) .facet($scope.ejs.QueryFacet("old_"+id)
.query(v) .query(q)
).size(0) ).size(0)
}) });
// TODO: Spy for hits panel // TODO: Spy for trend panel
//$scope.populate_modal(request); //$scope.populate_modal(request);
// If we're on the first segment we need to get our indices // If we're on the first segment we need to get our indices
...@@ -121,6 +110,7 @@ angular.module('kibana.trends', []) ...@@ -121,6 +110,7 @@ angular.module('kibana.trends', [])
// Populate scope when we have results // Populate scope when we have results
function process_results(results) { function process_results(results) {
results.then(function(results) { results.then(function(results) {
console.log(results)
$scope.panel.loading = false; $scope.panel.loading = false;
if(_segment == 0) { if(_segment == 0) {
...@@ -136,9 +126,9 @@ angular.module('kibana.trends', []) ...@@ -136,9 +126,9 @@ angular.module('kibana.trends', [])
} }
if($scope.query_id === query_id) { if($scope.query_id === query_id) {
var i = 0; var i = 0;
_.each($scope.panel.query, function(k) { _.each(query.ids, function(id) {
var n = results.facets['new'+i].count var n = results.facets[id].count
var o = results.facets['old'+i].count var o = results.facets['old_'+id].count
var hits = { var hits = {
new : _.isUndefined($scope.data[i]) || _segment == 0 ? n : $scope.data[i].hits.new+n, new : _.isUndefined($scope.data[i]) || _segment == 0 ? n : $scope.data[i].hits.new+n,
...@@ -152,7 +142,7 @@ angular.module('kibana.trends', []) ...@@ -152,7 +142,7 @@ angular.module('kibana.trends', [])
'?' : Math.round(percentage(hits.old,hits.new)*100)/100 '?' : Math.round(percentage(hits.old,hits.new)*100)/100
// Create series // Create series
$scope.data[i] = { $scope.data[i] = {
label: $scope.panel.query[i].label || "query"+(parseInt(i)+1), info: query.list[id],
hits: { hits: {
new : hits.new, new : hits.new,
old : hits.old old : hits.old
......
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