Linted, moved shared functions to kbn object

This commit is contained in:
Rashid Khan 2013-07-20 14:56:59 -07:00
parent 7c9f14ad5e
commit 5a3028f784
17 changed files with 955 additions and 920 deletions

58
Gruntfile.js Normal file
View File

@ -0,0 +1,58 @@
'use strict';
module.exports = function (grunt) {
var post = ['src/client.js','src/post.js'];
// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
meta: {
banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +
'<%= grunt.template.today("yyyy-mm-dd") %>\n' +
'<%= pkg.homepage ? " * " + pkg.homepage + "\\n" : "" %>' +
' * Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' +
' Licensed <%= pkg.license %> */\n\n'
},
jshint: {
files: ['Gruntfile.js', 'js/*.js', 'panels/*/*.js' ],
options: {
bitwise: true,
curly: true,
eqeqeq: true,
immed: true,
indent: 2,
latedef: true,
newcap: true,
noarg: true,
sub: true,
undef: true,
boss: true,
eqnull: true,
globalstrict: true,
devel: true,
node: true,
globals: {
'$LAB': false,
'_': false,
'$': false,
'kbn' : false,
window: false,
document: false,
exports: true,
module: false,
config: false,
moment: false
}
}
}
});
// load plugins
grunt.loadNpmTasks('grunt-contrib-jshint');
// Default task.
grunt.registerTask('default', ['jshint']);
};

View File

@ -1,13 +1,28 @@
function get_object_fields(obj) { // Wrap this all up in a 'kbn' object so I don't have a billion globals
(function() {
// Save a reference to this
var self = this;
// Save a reference to the old versionof this
var wasKbn = self.kbn;
// Create a safe refernce to the kbn object, for use below
var kbn = function(obj) { return new wrapper(obj); };
// Create a global object for accessing these functions
self.kbn = kbn;
kbn.get_object_fields = function(obj) {
var field_array = []; var field_array = [];
obj = flatten_json(obj._source) obj = kbn.flatten_json(obj._source)
for (field in obj) { for (field in obj) {
field_array.push(field); field_array.push(field);
} }
return field_array.sort(); return field_array.sort();
} }
function get_all_fields(data) { kbn.get_all_fields = function(data) {
var fields = []; var fields = [];
_.each(data,function(hit) { _.each(data,function(hit) {
fields = _.uniq(fields.concat(_.keys(hit))) fields = _.uniq(fields.concat(_.keys(hit)))
@ -15,18 +30,18 @@ function get_all_fields(data) {
// Remove stupid angular key // Remove stupid angular key
fields = _.without(fields,'$$hashKey') fields = _.without(fields,'$$hashKey')
return fields; return fields;
} }
function has_field(obj,field) { kbn.has_field = function(obj,field) {
var obj_fields = get_object_fields(obj); var obj_fields = get_object_fields(obj);
if (_.inArray(obj_fields,field) < 0) { if (_.inArray(obj_fields,field) < 0) {
return false; return false;
} else { } else {
return true; return true;
} }
} }
function get_related_fields(docs,field) { kbn.get_related_fields = function(docs,field) {
var field_array = [] var field_array = []
_.each(docs, function(doc) { _.each(docs, function(doc) {
var keys = _.keys(doc) var keys = _.keys(doc)
@ -35,9 +50,9 @@ function get_related_fields(docs,field) {
}) })
var counts = _.countBy(_.without(field_array,field),function(field){return field;}); var counts = _.countBy(_.without(field_array,field),function(field){return field;});
return counts; return counts;
} }
function recurse_field_dots(object,field) { kbn.recurse_field_dots = function(object,field) {
var value = null; var value = null;
if (typeof object[field] != 'undefined') if (typeof object[field] != 'undefined')
value = object[field]; value = object[field];
@ -48,12 +63,12 @@ function recurse_field_dots(object,field) {
object[nested[1]],nested[2]); object[nested[1]],nested[2]);
return value; return value;
} }
// Probably useless now, leaving for cases where you might not want // Probably useless now, leaving for cases where you might not want
// a flat dot notated data structure // a flat dot notated data structure
function get_field_value(object,field,opt) { kbn.get_field_value = function(object,field,opt) {
var value = recurse_field_dots(object['_source'],field); var value = kbn.recurse_field_dots(object['_source'],field);
if(value === null) if(value === null)
return '' return ''
@ -79,26 +94,17 @@ function get_field_value(object,field,opt) {
return JSON.stringify(value,null,4) return JSON.stringify(value,null,4)
return (value != null) ? value.toString() : ''; return (value != null) ? value.toString() : '';
} }
function top_field_values(docs,field,count) { kbn.top_field_values = function(docs,field,count) {
var counts = _.countBy(_.pluck(docs,field),function(field){ var counts = _.countBy(_.pluck(docs,field),function(field){
return _.isUndefined(field) ? '' : field; return _.isUndefined(field) ? '' : field;
}); });
return _.pairs(counts).sort(function(a, b) { return _.pairs(counts).sort(function(a, b) {
return a[1] - b[1] return a[1] - b[1]
}).reverse().slice(0,count) }).reverse().slice(0,count)
} }
function add_to_query(original,field,value,negate) {
var not = negate ? "-" : "";
if(value !== '')
var query = field + ":" + "\"" + addslashes(value.toString()) + "\"";
else
var query = "_missing_:" + field;
var glue = original != "" ? " AND " : "";
return original + glue + not + query;
}
/** /**
* Calculate a graph interval * Calculate a graph interval
* *
@ -108,19 +114,15 @@ function add_to_query(original,field,value,negate) {
* user_interval:: User specified histogram interval * user_interval:: User specified histogram interval
* *
*/ */
function calculate_interval(from,to,size,user_interval) { kbn.calculate_interval = function(from,to,size,user_interval) {
if(_.isObject(from)) if(_.isObject(from))
from = from.valueOf(); from = from.valueOf();
if(_.isObject(to)) if(_.isObject(to))
to = to.valueOf(); to = to.valueOf();
return user_interval == 0 ? round_interval((to - from)/size) : user_interval; return user_interval == 0 ? kbn.round_interval((to - from)/size) : user_interval;
} }
function get_bar_count(from,to,interval) { kbn.round_interval = function(interval) {
return (to - from)/interval;
}
function round_interval (interval) {
switch (true) { switch (true) {
// 0.5s // 0.5s
case (interval <= 500): return 100; // 0.1s case (interval <= 500): return 100; // 0.1s
@ -156,9 +158,9 @@ function round_interval (interval) {
case (interval < 3628800000): return 2592000000; // 30d case (interval < 3628800000): return 2592000000; // 30d
default: return 31536000000; // 1y default: return 31536000000; // 1y
} }
} }
function secondsToHms(seconds){ kbn.secondsToHms = function(seconds){
var numyears = Math.floor(seconds / 31536000); var numyears = Math.floor(seconds / 31536000);
if(numyears){ if(numyears){
return numyears + 'y'; return numyears + 'y';
@ -180,71 +182,22 @@ function secondsToHms(seconds){
return numseconds + 's'; return numseconds + 's';
} }
return 'less then a second'; //'just now' //or other string you like; return 'less then a second'; //'just now' //or other string you like;
} }
function to_percent(number,outof) { kbn.to_percent = function(number,outof) {
return Math.round((number/outof)*10000)/100 + "%"; return Math.round((number/outof)*10000)/100 + "%";
} }
function addslashes(str) { kbn.addslashes = function(str) {
str = str.replace(/\\/g, '\\\\'); str = str.replace(/\\/g, '\\\\');
str = str.replace(/\'/g, '\\\''); str = str.replace(/\'/g, '\\\'');
str = str.replace(/\"/g, '\\"'); str = str.replace(/\"/g, '\\"');
str = str.replace(/\0/g, '\\0'); str = str.replace(/\0/g, '\\0');
return str; return str;
}
// Create an ISO8601 compliant timestamp for ES
//function ISODateString(unixtime) {
//var d = new Date(parseInt(unixtime));
function ISODateString(d) {
if(is_int(d)) {
d = new Date(parseInt(d));
} }
function pad(n) { // histogram & trends
return n < 10 ? '0' + n : n kbn.interval_to_seconds = function(string) {
}
return d.getFullYear() + '-' +
pad(d.getMonth() + 1) + '-' +
pad(d.getDate()) + 'T' +
pad(d.getHours()) + ':' +
pad(d.getMinutes()) + ':' +
pad(d.getSeconds());
}
function pickDateString(d) {
return dateFormat(d,'yyyy-mm-dd HH:MM:ss')
}
function prettyDateString(d) {
d = new Date(parseInt(d));
d = utc_date_obj(d);
return dateFormat(d,window.time_format);
}
function utc_date_obj(d) {
return new Date(
d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(),
d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds(),
d.getUTCMilliseconds());
}
function local_date_obj(d) {
return new Date(Date.UTC(
d.getFullYear(), d.getMonth(), d.getDate(),
d.getHours(), d.getMinutes(), d.getSeconds()));
}
function is_int(value) {
if ((parseFloat(value) == parseInt(value)) && !isNaN(value)) {
return true;
} else {
return false;
}
}
function interval_to_seconds(string) {
var matches = string.match(/(\d+)([Mwdhmsy])/); var matches = string.match(/(\d+)([Mwdhmsy])/);
switch (matches[2]) { switch (matches[2]) {
case 'y': return matches[1]*31536000;; case 'y': return matches[1]*31536000;;
@ -255,13 +208,15 @@ function interval_to_seconds(string) {
case 'm': return matches[1]*60;; case 'm': return matches[1]*60;;
case 's': return matches[1]; case 's': return matches[1];
} }
} }
function time_ago(string) { // This should go away, moment.js can do this
return new Date(new Date().getTime() - (interval_to_seconds(string)*1000)) kbn.time_ago = function(string) {
} return new Date(new Date().getTime() - (kbn.interval_to_seconds(string)*1000))
}
function flatten_json(object,root,array) { // LOL. hahahahaha. DIE.
kbn.flatten_json = function(object,root,array) {
if (typeof array === 'undefined') if (typeof array === 'undefined')
var array = {}; var array = {};
if (typeof root === 'undefined') if (typeof root === 'undefined')
@ -287,16 +242,16 @@ function flatten_json(object,root,array) {
array[rootname] = typeof obj === 'undefined' ? null : obj; array[rootname] = typeof obj === 'undefined' ? null : obj;
} }
} else { } else {
flatten_json(obj,rootname,array) kbn.flatten_json(obj,rootname,array)
} }
} else { } else {
array[rootname] = typeof obj === 'undefined' ? null : obj; array[rootname] = typeof obj === 'undefined' ? null : obj;
} }
} }
return sortObj(array); return kbn.sortObj(array);
} }
function xmlEnt(value) { kbn.xmlEnt = function(value) {
if(_.isString(value)) { if(_.isString(value)) {
var stg1 = value.replace(/</g, '&lt;') var stg1 = value.replace(/</g, '&lt;')
.replace(/>/g, '&gt;') .replace(/>/g, '&gt;')
@ -307,13 +262,13 @@ function xmlEnt(value) {
.replace(/ /g, '&nbsp;&nbsp;') .replace(/ /g, '&nbsp;&nbsp;')
.replace(/&lt;del&gt;/g, '<del>') .replace(/&lt;del&gt;/g, '<del>')
.replace(/&lt;\/del&gt;/g, '</del>'); .replace(/&lt;\/del&gt;/g, '</del>');
return stg1 return stg1;
} else { } else {
return value return value;
}
} }
}
function sortObj(arr) { kbn.sortObj = function(arr) {
// Setup Arrays // Setup Arrays
var sortedKeys = new Array(); var sortedKeys = new Array();
var sortedObj = {}; var sortedObj = {};
@ -329,84 +284,12 @@ function sortObj(arr) {
sortedObj[sortedKeys[i]] = arr[sortedKeys[i]]; sortedObj[sortedKeys[i]] = arr[sortedKeys[i]];
} }
return sortedObj; return sortedObj;
} }
}).call(this);
// WTF. Has to be a better way to do this. Hi Tyler. /*
function int_to_tz(offset) { UNDERSCORE.js Mixins
var hour = offset / 1000 / 3600 */
var str = ""
if (hour == 0) {
str = "+0000"
}
if (hour < 0) {
if (hour > -10)
str = "-0" + (hour * -100)
else
str = "-" + (hour * -100)
}
if (hour > 0) {
if (hour < 10)
str = "+0" + (hour * 100)
else
str = "+" + (hour * 100)
}
str = str.substring(0,3) + ":" + str.substring(3);
return str
}
// Sets #hash, thus refreshing results
function setHash(json) {
window.location.hash = encodeURIComponent(Base64.encode(JSON.stringify(json)));
}
// Add commas to numbers
function addCommas(nStr) {
nStr += '';
var x = nStr.split('.');
var x1 = x[0];
var x2 = x.length > 1 ? '.' + x[1] : '';
var rgx = /(\d+)(\d{3})/;
while (rgx.test(x1)) {
x1 = x1.replace(rgx, '$1' + ',' + '$2');
}
return x1 + x2;
}
// Split up log spaceless strings
// Str = string to split
// num = number of letters between <wbr> tags
function wbr(str, num) {
str = htmlEntities(str);
return str.replace(
RegExp("(@?\\w{" + num + "}|[:;,])([\\w\"'])([\\w@]*)", "g"),
function (all, text, char, trailer) {
if (/@KIBANA_\w+_(START|END)@/.test(all)) {
return text + char + trailer;
} else {
return text + "<del>&#8203;</del>" + char + trailer;
}
}
);
}
function htmlEntities(str) {
return String(str).replace(
/&/g, '&amp;').replace(
/</g, '&lt;').replace(
/>/g, '&gt;').replace(
/"/g, '&quot;');
}
function bucket_round(start,num,dir) {
var resto = start%num;
if (resto <= (num/2) || dir === 'down') {
// Down
return start-resto;
} else {
// Up
return start+num-resto;
}
}
_.mixin({ _.mixin({
move: function (array, fromIndex, toIndex) { move: function (array, fromIndex, toIndex) {

View File

@ -77,6 +77,6 @@ angular.module('kibana.directives', [])
fn(scope, {$event:event}); fn(scope, {$event:event});
}); });
}); });
} };
}]); }]);

View File

@ -243,7 +243,8 @@ angular.module('kibana.services', [])
query: '*', query: '*',
alias: '', alias: '',
color: colorAt(_id), color: colorAt(_id),
id: _id id: _id,
type: 'lucene'
}; };
_.defaults(query,_query); _.defaults(query,_query);
self.list[_id] = query; self.list[_id] = query;
@ -386,7 +387,7 @@ angular.module('kibana.services', [])
.from(filter.from) .from(filter.from)
.to(filter.to); .to(filter.to);
case 'querystring': case 'querystring':
return ejs.QueryFilter(ejs.QueryStringQuery(filter.query)); return ejs.QueryFilter(ejs.QueryStringQuery(filter.query)).cache(true);
case 'terms': case 'terms':
return ejs.TermsFilter(filter.field,filter.value); return ejs.TermsFilter(filter.field,filter.value);
case 'exists': case 'exists':

14
package.json Normal file
View File

@ -0,0 +1,14 @@
{
"author": {
"name": "Rashid Khan",
"company": "Elasticsearch BV"
},
"name": "kibana",
"version": "3.0.0m3pre",
"devDependencies": {
"grunt": "~0.4.0",
"grunt-contrib": "~0.7.0",
"grunt-contrib-jshint": "~0.6.0"
},
"license": "Apache License"
}

View File

@ -1,3 +1,5 @@
/*jshint globalstrict:true */
/*global angular:true */
/* /*
## Derivequeries ## Derivequeries
@ -14,6 +16,8 @@
*/ */
'use strict';
angular.module('kibana.derivequeries', []) angular.module('kibana.derivequeries', [])
.controller('derivequeries', function($scope, $rootScope, query, fields, dashboard, filterSrv) { .controller('derivequeries', function($scope, $rootScope, query, fields, dashboard, filterSrv) {
@ -33,19 +37,19 @@ angular.module('kibana.derivequeries', [])
exclude : [], exclude : [],
history : [], history : [],
remember: 10 // max: 100, angular strap can't take a variable for items param remember: 10 // max: 100, angular strap can't take a variable for items param
} };
_.defaults($scope.panel,_d); _.defaults($scope.panel,_d);
$scope.init = function() { $scope.init = function() {
$scope.panel.fields = fields.list $scope.panel.fields = fields.list;
} };
$scope.get_data = function() { $scope.get_data = function() {
update_history($scope.panel.query); update_history($scope.panel.query);
// Make sure we have everything for the request to complete // Make sure we have everything for the request to complete
if(dashboard.indices.length == 0) { if(dashboard.indices.length === 0) {
return return;
} }
$scope.panel.loading = true; $scope.panel.loading = true;
@ -53,15 +57,15 @@ angular.module('kibana.derivequeries', [])
// Terms mode // Terms mode
request = request request = request
.facet(ejs.TermsFacet('query') .facet($scope.ejs.TermsFacet('query')
.field($scope.panel.field) .field($scope.panel.field)
.size($scope.panel['size']) .size($scope.panel.size)
.exclude($scope.panel.exclude) .exclude($scope.panel.exclude)
.facetFilter(ejs.QueryFilter( .facetFilter($scope.ejs.QueryFilter(
ejs.FilteredQuery( $scope.ejs.FilteredQuery(
ejs.QueryStringQuery($scope.panel.query || '*'), $scope.ejs.QueryStringQuery($scope.panel.query || '*'),
filterSrv.getBoolFilter(filterSrv.ids) filterSrv.getBoolFilter(filterSrv.ids)
)))).size(0) )))).size(0);
$scope.populate_modal(request); $scope.populate_modal(request);
@ -70,19 +74,20 @@ angular.module('kibana.derivequeries', [])
// Populate scope when we have results // Populate scope when we have results
results.then(function(results) { results.then(function(results) {
$scope.panel.loading = false; $scope.panel.loading = false;
var data = []; var suffix,
data = [];
if ($scope.panel.query === '' || $scope.panel.mode === 'terms only') { if ($scope.panel.query === '' || $scope.panel.mode === 'terms only') {
var suffix = ''; suffix = '';
} else if ($scope.panel.mode === 'AND') { } else if ($scope.panel.mode === 'AND') {
var suffix = ' AND (' + $scope.panel.query + ')'; suffix = ' AND (' + $scope.panel.query + ')';
} else if ($scope.panel.mode === 'OR') { } else if ($scope.panel.mode === 'OR') {
var suffix = ' OR (' + $scope.panel.query + ')'; suffix = ' OR (' + $scope.panel.query + ')';
} }
var ids = []; var ids = [];
_.each(results.facets.query.terms, function(v) { _.each(results.facets.query.terms, function(v) {
var _q = $scope.panel.field+':"'+v.term+'"'+suffix; var _q = $scope.panel.field+':"'+v.term+'"'+suffix;
// if it isn't in the list, remove it // if it isn't in the list, remove it
var _iq = query.findQuery(_q) var _iq = query.findQuery(_q);
if(!_iq) { if(!_iq) {
ids.push(query.set({query:_q})); ids.push(query.set({query:_q}));
} else { } else {
@ -90,22 +95,23 @@ angular.module('kibana.derivequeries', [])
} }
}); });
_.each(_.difference($scope.panel.ids,ids),function(id){ _.each(_.difference($scope.panel.ids,ids),function(id){
query.remove(id) query.remove(id);
}) });
$scope.panel.ids = ids; $scope.panel.ids = ids;
dashboard.refresh(); dashboard.refresh();
}); });
} };
$scope.set_refresh = function (state) { $scope.set_refresh = function (state) {
$scope.refresh = state; $scope.refresh = state;
} };
$scope.close_edit = function() { $scope.close_edit = function() {
if($scope.refresh) if($scope.refresh) {
$scope.get_data(); $scope.get_data();
$scope.refresh = false;
} }
$scope.refresh = false;
};
$scope.populate_modal = function(request) { $scope.populate_modal = function(request) {
$scope.modal = { $scope.modal = {
@ -114,18 +120,18 @@ angular.module('kibana.derivequeries', [])
'curl -XGET '+config.elasticsearch+'/'+dashboard.indices+"/_search?pretty -d'\n"+ 'curl -XGET '+config.elasticsearch+'/'+dashboard.indices+"/_search?pretty -d'\n"+
angular.toJson(JSON.parse(request.toString()),true)+ angular.toJson(JSON.parse(request.toString()),true)+
"'</pre>", "'</pre>",
} };
} };
var update_history = function(query) { var update_history = function(query) {
query = _.isArray(query) ? query : [query]; query = _.isArray(query) ? query : [query];
if($scope.panel.remember > 0) { if($scope.panel.remember > 0) {
$scope.panel.history = _.union(query.reverse(),$scope.panel.history) $scope.panel.history = _.union(query.reverse(),$scope.panel.history);
var _length = $scope.panel.history.length var _length = $scope.panel.history.length;
if(_length > $scope.panel.remember) { if(_length > $scope.panel.remember) {
$scope.panel.history = $scope.panel.history.slice(0,$scope.panel.remember) $scope.panel.history = $scope.panel.history.slice(0,$scope.panel.remember);
}
} }
} }
};
}); });

View File

@ -1,3 +1,6 @@
/*jshint globalstrict:true */
/*global angular:true */
/* /*
## Fields ## Fields
@ -17,6 +20,9 @@
* fields :: an object containing the sort order, existing fields and selected fields * fields :: an object containing the sort order, existing fields and selected fields
*/ */
'use strict';
angular.module('kibana.fields', []) angular.module('kibana.fields', [])
.controller('fields', function($scope, eventBus, $timeout, dashboard, query, filterSrv) { .controller('fields', function($scope, eventBus, $timeout, dashboard, query, filterSrv) {
@ -27,7 +33,7 @@ angular.module('kibana.fields', [])
style : {}, style : {},
arrange : 'vertical', arrange : 'vertical',
micropanel_position : 'right', micropanel_position : 'right',
} };
_.defaults($scope.panel,_d); _.defaults($scope.panel,_d);
$scope.init = function() { $scope.init = function() {
@ -35,7 +41,7 @@ angular.module('kibana.fields', [])
$scope.fields = []; $scope.fields = [];
eventBus.register($scope,'fields', function(event, fields) { eventBus.register($scope,'fields', function(event, fields) {
$scope.panel.sort = _.clone(fields.sort); $scope.panel.sort = _.clone(fields.sort);
$scope.fields = fields.all, $scope.fields = fields.all;
$scope.active = _.clone(fields.active); $scope.active = _.clone(fields.active);
}); });
eventBus.register($scope,'table_documents', function(event, docs) { eventBus.register($scope,'table_documents', function(event, docs) {
@ -46,57 +52,57 @@ angular.module('kibana.fields', [])
eventBus.register($scope,"get_fields", function(event,id) { eventBus.register($scope,"get_fields", function(event,id) {
eventBus.broadcast($scope.$id,$scope.panel.group,"selected_fields",$scope.active); eventBus.broadcast($scope.$id,$scope.panel.group,"selected_fields",$scope.active);
}); });
} };
$scope.reload_list = function () { $scope.reload_list = function () {
var temp = _.clone($scope.fields); var temp = _.clone($scope.fields);
$scope.fields = [] $scope.fields = [];
$timeout(function(){ $timeout(function(){
$scope.fields = temp; $scope.fields = temp;
},10) },10);
} };
$scope.toggle_micropanel = function(field) { $scope.toggle_micropanel = function(field) {
$scope.micropanel = { $scope.micropanel = {
field: field, field: field,
values : top_field_values($scope.docs,field,10), values : kbn.top_field_values($scope.docs,field,10),
related : get_related_fields($scope.docs,field), related : kbn.get_related_fields($scope.docs,field),
count: _.countBy($scope.docs,function(doc){ count: _.countBy($scope.docs,function(doc){return _.contains(_.keys(doc),field);})['true']
return _.contains(_.keys(doc),field)})['true'], };
} };
}
$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.toggle_field = function(field) { $scope.toggle_field = function(field) {
if (_.indexOf($scope.active,field) > -1) if (_.indexOf($scope.active,field) > -1) {
$scope.active = _.without($scope.active,field) $scope.active = _.without($scope.active,field);
else } else {
$scope.active.push(field) $scope.active.push(field);
eventBus.broadcast($scope.$id,$scope.panel.group,"selected_fields",$scope.active)
} }
eventBus.broadcast($scope.$id,$scope.panel.group,"selected_fields",$scope.active);
};
$scope.build_search = function(field,value,mandate) { $scope.build_search = function(field,value,mandate) {
var query; var query;
if(_.isArray(value)) { if(_.isArray(value)) {
query = field+":(" + _.map(value,function(v){return "\""+v+"\""}).join(",") + ")"; query = field+":(" + _.map(value,function(v){return "\""+v+"\"";}).join(",") + ")";
} else { } else {
query = field+":"+angular.toJson(value); query = field+":"+angular.toJson(value);
} }
filterSrv.set({type:'querystring',query:query,mandate:mandate}) filterSrv.set({type:'querystring',query:query,mandate:mandate});
dashboard.refresh(); dashboard.refresh();
} };
$scope.fieldExists = function(field,mandate) { $scope.fieldExists = function(field,mandate) {
filterSrv.set({type:'exists',field:field,mandate:mandate}) filterSrv.set({type:'exists',field:field,mandate:mandate});
dashboard.refresh(); dashboard.refresh();
} };
$scope.is_active = function(field) { $scope.is_active = function(field) {
return _.indexOf($scope.active,field) > -1 ? ['label','label-info'] : ''; return _.indexOf($scope.active,field) > -1 ? ['label','label-info'] : '';
} };
}) });

View File

@ -1,3 +1,5 @@
/*jshint globalstrict:true */
/*global angular:true */
/* /*
## filtering ## filtering
@ -8,39 +10,41 @@
*/ */
'use strict';
angular.module('kibana.filtering', []) angular.module('kibana.filtering', [])
.controller('filtering', function($scope, filterSrv, $rootScope, dashboard) { .controller('filtering', function($scope, filterSrv, $rootScope, dashboard) {
// Set and populate defaults // Set and populate defaults
var _d = { var _d = {
status : "Experimental" status : "Experimental"
} };
_.defaults($scope.panel,_d); _.defaults($scope.panel,_d);
$scope.init = function() { $scope.init = function() {
$scope.filterSrv = filterSrv $scope.filterSrv = filterSrv;
} };
$scope.remove = function(id) { $scope.remove = function(id) {
filterSrv.remove(id); filterSrv.remove(id);
dashboard.refresh(); dashboard.refresh();
} };
$scope.toggle = function(id) { $scope.toggle = function(id) {
filterSrv.list[id].active = !filterSrv.list[id].active; filterSrv.list[id].active = !filterSrv.list[id].active;
dashboard.refresh(); dashboard.refresh();
} };
$scope.refresh = function(query) { $scope.refresh = function(query) {
$rootScope.$broadcast('refresh') $rootScope.$broadcast('refresh');
} };
$scope.render = function(query) { $scope.render = function(query) {
$rootScope.$broadcast('render') $rootScope.$broadcast('render');
} };
$scope.show_key = function(key) { $scope.show_key = function(key) {
return !_.contains(['type','id','alias','mandate','active','editing'],key) return !_.contains(['type','id','alias','mandate','active','editing'],key);
} };
}); });

View File

@ -1,3 +1,6 @@
/*jshint globalstrict:true */
/*global angular:true */
/* /*
## Histogram ## Histogram
@ -35,6 +38,8 @@
*/ */
'use strict';
angular.module('kibana.histogram', []) angular.module('kibana.histogram', [])
.controller('histogram', function($scope, eventBus, query, dashboard, filterSrv) { .controller('histogram', function($scope, eventBus, query, dashboard, filterSrv) {
@ -63,8 +68,8 @@ angular.module('kibana.histogram', [])
'y-axis' : true, 'y-axis' : true,
percentage : false, percentage : false,
interactive : true, interactive : true,
} };
_.defaults($scope.panel,_d) _.defaults($scope.panel,_d);
$scope.init = function() { $scope.init = function() {
@ -72,49 +77,51 @@ angular.module('kibana.histogram', [])
$scope.$on('refresh',function(){ $scope.$on('refresh',function(){
$scope.get_data(); $scope.get_data();
}) });
$scope.get_data() $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
if(dashboard.indices.length == 0) { if(dashboard.indices.length === 0) {
return return;
} }
var _range = $scope.range = filterSrv.timeRange('min'); var _range = $scope.range = filterSrv.timeRange('min');
if ($scope.panel.auto_int) if ($scope.panel.auto_int) {
$scope.panel.interval = secondsToHms(calculate_interval(_range.from,_range.to,$scope.panel.resolution,0)/1000); $scope.panel.interval = kbn.secondsToHms(
kbn.calculate_interval(_range.from,_range.to,$scope.panel.resolution,0)/1000);
}
$scope.panel.loading = true; $scope.panel.loading = true;
var _segment = _.isUndefined(segment) ? 0 : segment var _segment = _.isUndefined(segment) ? 0 : segment;
var request = $scope.ejs.Request().indices(dashboard.indices[_segment]); var request = $scope.ejs.Request().indices(dashboard.indices[_segment]);
// Build the query // Build the query
_.each($scope.queries.ids, function(id) { _.each($scope.queries.ids, function(id) {
var query = $scope.ejs.FilteredQuery( var query = $scope.ejs.FilteredQuery(
ejs.QueryStringQuery($scope.queries.list[id].query || '*'), $scope.ejs.QueryStringQuery($scope.queries.list[id].query || '*'),
filterSrv.getBoolFilter(filterSrv.ids) filterSrv.getBoolFilter(filterSrv.ids)
) );
var facet = $scope.ejs.DateHistogramFacet(id) var facet = $scope.ejs.DateHistogramFacet(id);
if($scope.panel.mode === 'count') { if($scope.panel.mode === 'count') {
facet = facet.field($scope.panel.time_field) facet = facet.field($scope.panel.time_field);
} else { } else {
if(_.isNull($scope.panel.value_field)) { if(_.isNull($scope.panel.value_field)) {
$scope.panel.error = "In " + $scope.panel.mode + " mode a field must be specified"; $scope.panel.error = "In " + $scope.panel.mode + " mode a field must be specified";
return return;
} }
facet = facet.keyField($scope.panel.time_field).valueField($scope.panel.value_field) facet = facet.keyField($scope.panel.time_field).valueField($scope.panel.value_field);
} }
facet = facet.interval($scope.panel.interval).facetFilter($scope.ejs.QueryFilter(query)) 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
@ -127,7 +134,7 @@ angular.module('kibana.histogram', [])
results.then(function(results) { results.then(function(results) {
$scope.panel.loading = false; $scope.panel.loading = false;
if(_segment == 0) { if(_segment === 0) {
$scope.hits = 0; $scope.hits = 0;
$scope.data = []; $scope.data = [];
query_id = $scope.query_id = new Date().getTime(); query_id = $scope.query_id = new Date().getTime();
@ -140,37 +147,39 @@ angular.module('kibana.histogram', [])
} }
// Convert facet ids to numbers // Convert facet ids to numbers
var facetIds = _.map(_.keys(results.facets),function(k){return parseInt(k);}) var facetIds = _.map(_.keys(results.facets),function(k){return parseInt(k, 10);});
// Make sure we're still on the same query/queries // Make sure we're still on the same query/queries
if($scope.query_id === query_id && if($scope.query_id === query_id &&
_.intersection(facetIds,query.ids).length == query.ids.length _.intersection(facetIds,query.ids).length === query.ids.length
) { ) {
var i = 0; var i = 0;
var data, hits;
_.each(query.ids, function(id) { _.each(query.ids, function(id) {
var v = results.facets[id]; var v = results.facets[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) {
var data = [] data = [];
if(filterSrv.idsByType('time').length > 0) { if(filterSrv.idsByType('time').length > 0) {
data = [[_range.from.getTime(), null],[_range.to.getTime(), null]]; data = [[_range.from.getTime(), null],[_range.to.getTime(), null]];
} }
var hits = 0; hits = 0;
} else { } else {
var data = $scope.data[i].data data = $scope.data[i].data;
var hits = $scope.data[i].hits hits = $scope.data[i].hits;
} }
// Assemble segments // Assemble segments
var segment_data = []; var segment_data = [];
_.each(v.entries, function(v, k) { _.each(v.entries, function(v, k) {
segment_data.push([v['time'],v[$scope.panel.mode]]) segment_data.push([v.time,v[$scope.panel.mode]]);
hits += v['count']; // The series level hits counter hits += v.count; // The series level hits counter
$scope.hits += v['count']; // Entire dataset level hits counter $scope.hits += v.count; // Entire dataset level hits counter
}); });
data.splice.apply(data,[1,0].concat(segment_data)) // Join histogram data data.splice.apply(data,[1,0].concat(segment_data)); // Join histogram data
// Create the flot series object // Create the flot series object
var series = { var series = {
@ -181,22 +190,22 @@ angular.module('kibana.histogram', [])
}, },
}; };
$scope.data[i] = series.data $scope.data[i] = series.data;
i++; i++;
}); });
// Tell the histogram directive to render. // Tell the histogram directive to render.
$scope.$emit('render') $scope.$emit('render');
// If we still have segments left, get them // If we still have segments left, get them
if(_segment < dashboard.indices.length-1) { if(_segment < dashboard.indices.length-1) {
$scope.get_data(_segment+1,query_id) $scope.get_data(_segment+1,query_id);
} }
} }
}); });
} };
// function $scope.zoom // function $scope.zoom
// factor :: Zoom factor, so 0.5 = cuts timespan in half, 2 doubles timespan // factor :: Zoom factor, so 0.5 = cuts timespan in half, 2 doubles timespan
@ -204,31 +213,31 @@ angular.module('kibana.histogram', [])
var _now = Date.now(); var _now = Date.now();
var _range = filterSrv.timeRange('min'); var _range = filterSrv.timeRange('min');
var _timespan = (_range.to.valueOf() - _range.from.valueOf()); var _timespan = (_range.to.valueOf() - _range.from.valueOf());
var _center = _range.to.valueOf() - _timespan/2 var _center = _range.to.valueOf() - _timespan/2;
var _to = (_center + (_timespan*factor)/2) var _to = (_center + (_timespan*factor)/2);
var _from = (_center - (_timespan*factor)/2) var _from = (_center - (_timespan*factor)/2);
// If we're not already looking into the future, don't. // If we're not already looking into the future, don't.
if(_to > Date.now() && _range.to < Date.now()) { if(_to > Date.now() && _range.to < Date.now()) {
var _offset = _to - Date.now() var _offset = _to - Date.now();
_from = _from - _offset _from = _from - _offset;
_to = Date.now(); _to = Date.now();
} }
if(factor > 1) { if(factor > 1) {
filterSrv.removeByType('time') filterSrv.removeByType('time');
} }
filterSrv.set({ filterSrv.set({
type:'time', type:'time',
from:moment.utc(_from), from:moment.utc(_from),
to:moment.utc(_to), to:moment.utc(_to),
field:$scope.panel.time_field field:$scope.panel.time_field
}) });
dashboard.refresh(); dashboard.refresh();
} };
// I really don't like this function, too much dom manip. Break out into directive? // I really don't like this function, too much dom manip. Break out into directive?
$scope.populate_modal = function(request) { $scope.populate_modal = function(request) {
@ -238,19 +247,20 @@ angular.module('kibana.histogram', [])
'curl -XGET '+config.elasticsearch+'/'+dashboard.indices+"/_search?pretty -d'\n"+ 'curl -XGET '+config.elasticsearch+'/'+dashboard.indices+"/_search?pretty -d'\n"+
angular.toJson(JSON.parse(request.toString()),true)+ angular.toJson(JSON.parse(request.toString()),true)+
"'</pre>", "'</pre>",
} };
} };
$scope.set_refresh = function (state) { $scope.set_refresh = function (state) {
$scope.refresh = state; $scope.refresh = state;
} };
$scope.close_edit = function() { $scope.close_edit = function() {
if($scope.refresh) if($scope.refresh) {
$scope.get_data(); $scope.get_data();
}
$scope.refresh = false; $scope.refresh = false;
$scope.$emit('render'); $scope.$emit('render');
} };
}) })
.directive('histogramChart', function(dashboard, eventBus, filterSrv, $rootScope) { .directive('histogramChart', function(dashboard, eventBus, filterSrv, $rootScope) {
@ -274,19 +284,19 @@ angular.module('kibana.histogram', [])
// Populate from the query service // Populate from the query service
try { try {
_.each(scope.data,function(series) { _.each(scope.data,function(series) {
series.label = series.info.alias, series.label = series.info.alias;
series.color = series.info.color series.color = series.info.color;
}) });
} catch(e) {return} } catch(e) {return;}
// Set barwidth based on specified interval // Set barwidth based on specified interval
var barwidth = interval_to_seconds(scope.panel.interval)*1000 var barwidth = kbn.interval_to_seconds(scope.panel.interval)*1000;
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.time.js") .script("common/lib/panels/jquery.flot.time.js")
.script("common/lib/panels/jquery.flot.stack.js") .script("common/lib/panels/jquery.flot.stack.js")
.script("common/lib/panels/jquery.flot.selection.js") .script("common/lib/panels/jquery.flot.selection.js")
.script("common/lib/panels/timezone.js") .script("common/lib/panels/timezone.js");
// Populate element. Note that jvectormap appends, does not replace. // Populate element. Note that jvectormap appends, does not replace.
scripts.wait(function(){ scripts.wait(function(){
@ -331,33 +341,38 @@ angular.module('kibana.histogram', [])
hoverable: true, hoverable: true,
}, },
colors: ['#86B22D','#BF6730','#1D7373','#BFB930','#BF3030','#77207D'] colors: ['#86B22D','#BF6730','#1D7373','#BFB930','#BF3030','#77207D']
};
if(scope.panel.interactive) {
options.selection = { mode: "x", color: '#aaa' };
} }
if(scope.panel.interactive) scope.plot = $.plot(elem, scope.data, options);
options.selection = { mode: "x", color: '#aaa' };
scope.plot = $.plot(elem, scope.data, options) // Work around for missing legend at initialization.
if(!scope.$$phase) {
// Work around for missing legend at initialization scope.$apply();
if(!scope.$$phase) }
scope.$apply()
} catch(e) { } catch(e) {
elem.text(e) elem.text(e);
} }
}) });
} }
function time_format(interval) { function time_format(interval) {
var _int = interval_to_seconds(interval) var _int = kbn.interval_to_seconds(interval);
if(_int >= 2628000) if(_int >= 2628000) {
return "%m/%y" return "%m/%y";
if(_int >= 86400) }
return "%m/%d/%y" if(_int >= 86400) {
if(_int >= 60) return "%m/%d/%y";
return "%H:%M<br>%m/%d" }
else if(_int >= 60) {
return "%H:%M:%S" return "%H:%M<br>%m/%d";
}
return "%H:%M:%S";
} }
function tt(x, y, contents) { function tt(x, y, contents) {
@ -396,9 +411,9 @@ angular.module('kibana.histogram', [])
from : moment.utc(ranges.xaxis.from), from : moment.utc(ranges.xaxis.from),
to : moment.utc(ranges.xaxis.to), to : moment.utc(ranges.xaxis.to),
field : scope.panel.time_field field : scope.panel.time_field
}) });
dashboard.refresh(); dashboard.refresh();
}); });
} }
}; };
}) });

View File

@ -1,3 +1,6 @@
/*jshint globalstrict:true */
/*global angular:true */
/* /*
## Hits ## Hits
@ -15,6 +18,9 @@
* lables :: Only 'pie' charts. Labels on the pie? * lables :: Only 'pie' charts. Labels on the pie?
*/ */
'use strict';
angular.module('kibana.hits', []) angular.module('kibana.hits', [])
.controller('hits', function($scope, query, dashboard, filterSrv) { .controller('hits', function($scope, query, dashboard, filterSrv) {
@ -30,41 +36,41 @@ angular.module('kibana.hits', [])
donut : false, donut : false,
tilt : false, tilt : false,
labels : true labels : true
} };
_.defaults($scope.panel,_d) _.defaults($scope.panel,_d);
$scope.init = function () { $scope.init = function () {
$scope.hits = 0; $scope.hits = 0;
$scope.$on('refresh',function(){ $scope.$on('refresh',function(){
$scope.get_data(); $scope.get_data();
}) });
$scope.get_data(); $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;
$scope.panel.loading = true; $scope.panel.loading = true;
// Make sure we have everything for the request to complete // Make sure we have everything for the request to complete
if(dashboard.indices.length == 0) { if(dashboard.indices.length === 0) {
return return;
} }
var _segment = _.isUndefined(segment) ? 0 : segment var _segment = _.isUndefined(segment) ? 0 : segment;
var request = $scope.ejs.Request().indices(dashboard.indices[_segment]); var request = $scope.ejs.Request().indices(dashboard.indices[_segment]);
// Build the question part of the query // Build the question part of the query
_.each(query.ids, function(id) { _.each(query.ids, function(id) {
var _q = $scope.ejs.FilteredQuery( var _q = $scope.ejs.FilteredQuery(
ejs.QueryStringQuery(query.list[id].query || '*'), $scope.ejs.QueryStringQuery(query.list[id].query || '*'),
filterSrv.getBoolFilter(filterSrv.ids)); filterSrv.getBoolFilter(filterSrv.ids));
request = request request = request
.facet($scope.ejs.QueryFacet(id) .facet($scope.ejs.QueryFacet(id)
.query(_q) .query(_q)
).size(0) ).size(0);
}); });
// TODO: Spy for hits panel // TODO: Spy for hits panel
@ -76,7 +82,7 @@ angular.module('kibana.hits', [])
// Populate scope when we have results // Populate scope when we have results
results.then(function(results) { results.then(function(results) {
$scope.panel.loading = false; $scope.panel.loading = false;
if(_segment == 0) { if(_segment === 0) {
$scope.hits = 0; $scope.hits = 0;
$scope.data = []; $scope.data = [];
query_id = $scope.query_id = new Date().getTime(); query_id = $scope.query_id = new Date().getTime();
@ -89,18 +95,18 @@ angular.module('kibana.hits', [])
} }
// Convert facet ids to numbers // Convert facet ids to numbers
var facetIds = _.map(_.keys(results.facets),function(k){return parseInt(k);}) var facetIds = _.map(_.keys(results.facets),function(k){return parseInt(k, 10);});
// Make sure we're still on the same query/queries // Make sure we're still on the same query/queries
if($scope.query_id === query_id && if($scope.query_id === query_id &&
_.intersection(facetIds,query.ids).length == query.ids.length _.intersection(facetIds,query.ids).length === query.ids.length
) { ) {
var i = 0; var i = 0;
_.each(query.ids, function(id) { _.each(query.ids, function(id) {
var v = results.facets[id] var v = results.facets[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] = {
@ -113,23 +119,25 @@ angular.module('kibana.hits', [])
i++; i++;
}); });
$scope.$emit('render'); $scope.$emit('render');
if(_segment < dashboard.indices.length-1) if(_segment < dashboard.indices.length-1) {
$scope.get_data(_segment+1,query_id) $scope.get_data(_segment+1,query_id);
}
} }
}); });
} };
$scope.set_refresh = function (state) { $scope.set_refresh = function (state) {
$scope.refresh = state; $scope.refresh = state;
} };
$scope.close_edit = function() { $scope.close_edit = function() {
if($scope.refresh) if($scope.refresh) {
$scope.get_data(); $scope.get_data();
}
$scope.refresh = false; $scope.refresh = false;
$scope.$emit('render'); $scope.$emit('render');
} };
function set_time(time) { function set_time(time) {
$scope.time = time; $scope.time = time;
@ -156,20 +164,20 @@ angular.module('kibana.hits', [])
try { try {
_.each(scope.data,function(series) { _.each(scope.data,function(series) {
series.label = series.info.alias, series.label = series.info.alias;
series.color = series.info.color series.color = series.info.color;
}) });
} catch(e) {return} } catch(e) {return;}
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");
// Populate element. // Populate element.
scripts.wait(function(){ scripts.wait(function(){
// Populate element // Populate element
try { try {
// Add plot to scope so we can build out own legend // Add plot to scope so we can build out own legend
if(scope.panel.chart === 'bar') if(scope.panel.chart === 'bar') {
scope.plot = $.plot(elem, scope.data, { scope.plot = $.plot(elem, scope.data, {
legend: { show: false }, legend: { show: false },
series: { series: {
@ -186,8 +194,9 @@ angular.module('kibana.hits', [])
hoverable: true, hoverable: true,
}, },
colors: query.colors colors: query.colors
}) });
if(scope.panel.chart === 'pie') }
if(scope.panel.chart === 'pie') {
scope.plot = $.plot(elem, scope.data, { scope.plot = $.plot(elem, scope.data, {
legend: { show: false }, legend: { show: false },
series: { series: {
@ -218,19 +227,20 @@ angular.module('kibana.hits', [])
grid: { hoverable: true, clickable: true }, grid: { hoverable: true, clickable: true },
colors: query.colors colors: query.colors
}); });
}
// Compensate for the height of the legend. Gross // Compensate for the height of the legend. Gross
elem.height( elem.height(
(scope.panel.height || scope.row.height).replace('px','') - $("#"+scope.$id+"-legend").height()) (scope.panel.height || scope.row.height).replace('px','') - $("#"+scope.$id+"-legend").height());
// Work around for missing legend at initialization // Work around for missing legend at initialization
if(!scope.$$phase) if(!scope.$$phase) {
scope.$apply() scope.$apply();
}
} catch(e) { } catch(e) {
elem.text(e) elem.text(e);
} }
}) });
} }
function tt(x, y, contents) { function tt(x, y, contents) {
@ -256,7 +266,7 @@ angular.module('kibana.hits', [])
item.datapoint[1] : item.datapoint[1][0][1]; item.datapoint[1] : item.datapoint[1][0][1];
tt(pos.pageX, pos.pageY, tt(pos.pageX, pos.pageY,
"<div style='vertical-align:middle;border-radius:10px;display:inline-block;background:"+ "<div style='vertical-align:middle;border-radius:10px;display:inline-block;background:"+
item.series.color+";height:20px;width:20px'></div> "+value.toFixed(0)) item.series.color+";height:20px;width:20px'></div> "+value.toFixed(0));
} else { } else {
$("#pie-tooltip").remove(); $("#pie-tooltip").remove();
} }
@ -264,4 +274,4 @@ angular.module('kibana.hits', [])
} }
}; };
}) });

View File

@ -1,3 +1,6 @@
/*jshint globalstrict:true */
/*global angular:true */
/* /*
## Map ## Map
@ -22,6 +25,8 @@
*/ */
'use strict';
angular.module('kibana.map', []) angular.module('kibana.map', [])
.controller('map', function($scope, $rootScope, query, dashboard, filterSrv) { .controller('map', function($scope, $rootScope, query, dashboard, filterSrv) {
@ -36,37 +41,39 @@ angular.module('kibana.map', [])
spyable : true, spyable : true,
group : "default", group : "default",
index_limit : 0 index_limit : 0
} };
_.defaults($scope.panel,_d) _.defaults($scope.panel,_d);
$scope.init = function() { $scope.init = function() {
$scope.$on('refresh',function(){$scope.get_data()}) $scope.$on('refresh',function(){$scope.get_data();});
$scope.get_data(); $scope.get_data();
} };
$scope.get_data = function() { $scope.get_data = function() {
// Make sure we have everything for the request to complete // Make sure we have everything for the request to complete
if(dashboard.indices.length == 0) { if(dashboard.indices.length === 0) {
return return;
} }
$scope.panel.loading = true; $scope.panel.loading = true;
var request = $scope.ejs.Request().indices(dashboard.indices);
var boolQuery = ejs.BoolQuery();
var request;
request = $scope.ejs.Request().indices(dashboard.indices);
var boolQuery = $scope.ejs.BoolQuery();
_.each(query.list,function(q) { _.each(query.list,function(q) {
boolQuery = boolQuery.should(ejs.QueryStringQuery(q.query || '*')) boolQuery = boolQuery.should($scope.ejs.QueryStringQuery(q.query || '*'));
}) });
// Then the insert into facet and make the request // Then the insert into facet and make the request
var request = request request = request
.facet(ejs.TermsFacet('map') .facet($scope.ejs.TermsFacet('map')
.field($scope.panel.field) .field($scope.panel.field)
.size($scope.panel['size']) .size($scope.panel.size)
.exclude($scope.panel.exclude) .exclude($scope.panel.exclude)
.facetFilter(ejs.QueryFilter( .facetFilter($scope.ejs.QueryFilter(
ejs.FilteredQuery( $scope.ejs.FilteredQuery(
boolQuery, boolQuery,
filterSrv.getBoolFilter(filterSrv.ids) filterSrv.getBoolFilter(filterSrv.ids)
)))).size(0); )))).size(0);
@ -83,9 +90,9 @@ angular.module('kibana.map', [])
_.each(results.facets.map.terms, function(v) { _.each(results.facets.map.terms, function(v) {
$scope.data[v.term.toUpperCase()] = v.count; $scope.data[v.term.toUpperCase()] = v.count;
}); });
$scope.$emit('render') $scope.$emit('render');
}); });
} };
// I really don't like this function, too much dom manip. Break out into directive? // I really don't like this function, too much dom manip. Break out into directive?
$scope.populate_modal = function(request) { $scope.populate_modal = function(request) {
@ -95,13 +102,13 @@ angular.module('kibana.map', [])
'curl -XGET '+config.elasticsearch+'/'+dashboard.indices+"/_search?pretty -d'\n"+ 'curl -XGET '+config.elasticsearch+'/'+dashboard.indices+"/_search?pretty -d'\n"+
angular.toJson(JSON.parse(request.toString()),true)+ angular.toJson(JSON.parse(request.toString()),true)+
"'</pre>", "'</pre>",
} };
} };
$scope.build_search = function(field,value) { $scope.build_search = function(field,value) {
filterSrv.set({type:'querystring',mandate:'must',query:field+":"+value}) filterSrv.set({type:'querystring',mandate:'must',query:field+":"+value});
dashboard.refresh(); dashboard.refresh();
} };
}) })
.directive('map', function() { .directive('map', function() {
@ -109,7 +116,7 @@ angular.module('kibana.map', [])
restrict: 'A', restrict: 'A',
link: function(scope, elem, attrs) { link: function(scope, elem, attrs) {
elem.html('<center><img src="common/img/load_big.gif"></center>') elem.html('<center><img src="common/img/load_big.gif"></center>');
// Receive render events // Receive render events
scope.$on('render',function(){ scope.$on('render',function(){
@ -124,7 +131,7 @@ angular.module('kibana.map', [])
function render_panel() { function render_panel() {
// Using LABjs, wait until all scripts are loaded before rendering panel // Using LABjs, wait until all scripts are loaded before rendering panel
var scripts = $LAB.script("panels/map/lib/jquery.jvectormap.min.js").wait() var scripts = $LAB.script("panels/map/lib/jquery.jvectormap.min.js").wait()
.script("panels/map/lib/map."+scope.panel.map+".js") .script("panels/map/lib/map."+scope.panel.map+".js");
// Populate element. Note that jvectormap appends, does not replace. // Populate element. Note that jvectormap appends, does not replace.
scripts.wait(function(){ scripts.wait(function(){
@ -143,7 +150,7 @@ angular.module('kibana.map', [])
}] }]
}, },
onRegionLabelShow: function(event, label, code){ onRegionLabelShow: function(event, label, code){
elem.children('.map-legend').show() elem.children('.map-legend').show();
var count = _.isUndefined(scope.data[code]) ? 0 : scope.data[code]; var count = _.isUndefined(scope.data[code]) ? 0 : scope.data[code];
elem.children('.map-legend').text(label.text() + ": " + count); elem.children('.map-legend').text(label.text() + ": " + count);
}, },
@ -152,13 +159,14 @@ angular.module('kibana.map', [])
}, },
onRegionClick: function(event, code) { onRegionClick: function(event, code) {
var count = _.isUndefined(scope.data[code]) ? 0 : scope.data[code]; var count = _.isUndefined(scope.data[code]) ? 0 : scope.data[code];
if (count != 0) if (count !== 0) {
scope.build_search(scope.panel.field,code) scope.build_search(scope.panel.field,code);
}
} }
}); });
elem.prepend('<span class="map-legend"></span>'); elem.prepend('<span class="map-legend"></span>');
$('.map-legend').hide(); $('.map-legend').hide();
}) });
} }
} }
}; };

View File

@ -1,3 +1,5 @@
/*jshint globalstrict:true */
/*global angular:true */
/* /*
## Pie ## Pie
@ -22,9 +24,10 @@
* default_field :: LOL wat? A dumb fail over field if for some reason the query object * default_field :: LOL wat? A dumb fail over field if for some reason the query object
doesn't have a field doesn't have a field
* spyable :: Show the 'eye' icon that displays the last ES query for this panel * spyable :: Show the 'eye' icon that displays the last ES query for this panel
*/ */
'use strict';
angular.module('kibana.pie', []) angular.module('kibana.pie', [])
.controller('pie', function($scope, $rootScope, query, dashboard, filterSrv) { .controller('pie', function($scope, $rootScope, query, dashboard, filterSrv) {
@ -42,13 +45,13 @@ angular.module('kibana.pie', [])
group : "default", group : "default",
default_field : 'DEFAULT', default_field : 'DEFAULT',
spyable : true, spyable : true,
} };
_.defaults($scope.panel,_d) _.defaults($scope.panel,_d);
$scope.init = function() { $scope.init = function() {
$scope.$on('refresh',function(){$scope.get_data()}) $scope.$on('refresh',function(){$scope.get_data();});
$scope.get_data(); $scope.get_data();
} };
$scope.set_mode = function(mode) { $scope.set_mode = function(mode) {
switch(mode) switch(mode)
@ -60,51 +63,54 @@ angular.module('kibana.pie', [])
$scope.panel.query = {goal:100}; $scope.panel.query = {goal:100};
break; break;
} }
} };
$scope.set_refresh = function (state) { $scope.set_refresh = function (state) {
$scope.refresh = state; $scope.refresh = state;
} };
$scope.close_edit = function() { $scope.close_edit = function() {
if($scope.refresh) if($scope.refresh) {
$scope.get_data(); $scope.get_data();
}
$scope.refresh = false; $scope.refresh = false;
$scope.$emit('render'); $scope.$emit('render');
} };
$scope.get_data = function() { $scope.get_data = function() {
// Make sure we have everything for the request to complete // Make sure we have everything for the request to complete
if(dashboard.indices.length == 0) { if(dashboard.indices.length === 0) {
return return;
} }
$scope.panel.loading = true; $scope.panel.loading = true;
var request = $scope.ejs.Request().indices(dashboard.indices); var request = $scope.ejs.Request().indices(dashboard.indices);
// This could probably be changed to a BoolFilter // This could probably be changed to a BoolFilter
var boolQuery = ejs.BoolQuery(); var boolQuery = $scope.ejs.BoolQuery();
_.each(query.list,function(q) { _.each(query.list,function(q) {
boolQuery = boolQuery.should(ejs.QueryStringQuery(q.query || '*')) boolQuery = boolQuery.should($scope.ejs.QueryStringQuery(q.query || '*'));
}) });
var results;
// Terms mode // Terms mode
if ($scope.panel.mode == "terms") { if ($scope.panel.mode === "terms") {
request = request request = request
.facet(ejs.TermsFacet('pie') .facet($scope.ejs.TermsFacet('pie')
.field($scope.panel.query.field || $scope.panel.default_field) .field($scope.panel.query.field || $scope.panel.default_field)
.size($scope.panel['size']) .size($scope.panel.size)
.exclude($scope.panel.exclude) .exclude($scope.panel.exclude)
.facetFilter(ejs.QueryFilter( .facetFilter($scope.ejs.QueryFilter(
ejs.FilteredQuery( $scope.ejs.FilteredQuery(
boolQuery, boolQuery,
filterSrv.getBoolFilter(filterSrv.ids) filterSrv.getBoolFilter(filterSrv.ids)
)))).size(0) )))).size(0);
$scope.populate_modal(request); $scope.populate_modal(request);
var results = request.doSearch(); results = request.doSearch();
// Populate scope when we have results // Populate scope when we have results
results.then(function(results) { results.then(function(results) {
@ -115,12 +121,7 @@ angular.module('kibana.pie', [])
_.each(results.facets.pie.terms, function(v) { _.each(results.facets.pie.terms, function(v) {
var slice = { label : v.term, data : v.count }; var slice = { label : v.term, data : v.count };
$scope.data.push(); $scope.data.push();
if(!(_.isUndefined($scope.panel.colors)) $scope.data.push(slice);
&& _.isArray($scope.panel.colors)
&& $scope.panel.colors.length > 0) {
slice.color = $scope.panel.colors[k%$scope.panel.colors.length];
}
$scope.data.push(slice)
k = k + 1; k = k + 1;
}); });
$scope.$emit('render'); $scope.$emit('render');
@ -130,11 +131,11 @@ angular.module('kibana.pie', [])
request = request request = request
.query(boolQuery) .query(boolQuery)
.filter(filterSrv.getBoolFilter(filterSrv.ids)) .filter(filterSrv.getBoolFilter(filterSrv.ids))
.size(0) .size(0);
$scope.populate_modal(request); $scope.populate_modal(request);
var results = request.doSearch(); results = request.doSearch();
results.then(function(results) { results.then(function(results) {
$scope.panel.loading = false; $scope.panel.loading = false;
@ -142,11 +143,12 @@ angular.module('kibana.pie', [])
var remaining = $scope.panel.query.goal - complete; var remaining = $scope.panel.query.goal - complete;
$scope.data = [ $scope.data = [
{ label : 'Complete', data : complete, color: '#BF6730' }, { label : 'Complete', data : complete, color: '#BF6730' },
{ data : remaining, color: '#e2d0c4'}] { data : remaining, color: '#e2d0c4' }
];
$scope.$emit('render'); $scope.$emit('render');
}); });
} }
} };
// I really don't like this function, too much dom manip. Break out into directive? // I really don't like this function, too much dom manip. Break out into directive?
$scope.populate_modal = function(request) { $scope.populate_modal = function(request) {
@ -156,8 +158,8 @@ angular.module('kibana.pie', [])
'curl -XGET '+config.elasticsearch+'/'+dashboard.indices+"/_search?pretty -d'\n"+ 'curl -XGET '+config.elasticsearch+'/'+dashboard.indices+"/_search?pretty -d'\n"+
angular.toJson(JSON.parse(request.toString()),true)+ angular.toJson(JSON.parse(request.toString()),true)+
"'</pre>", "'</pre>",
} };
} };
}) })
.directive('pie', function(query, filterSrv, dashboard) { .directive('pie', function(query, filterSrv, dashboard) {
@ -165,7 +167,7 @@ angular.module('kibana.pie', [])
restrict: 'A', restrict: 'A',
link: function(scope, elem, attrs) { link: function(scope, elem, attrs) {
elem.html('<center><img src="common/img/load_big.gif"></center>') elem.html('<center><img src="common/img/load_big.gif"></center>');
// Receive render events // Receive render events
scope.$on('render',function(){ scope.$on('render',function(){
@ -180,23 +182,25 @@ angular.module('kibana.pie', [])
// Function for rendering panel // Function for rendering panel
function render_panel() { function render_panel() {
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");
if(scope.panel.mode === 'goal') var label;
var label = { if(scope.panel.mode === 'goal') {
label = {
show: scope.panel.labels, show: scope.panel.labels,
radius: 0, radius: 0,
formatter: function(label, series){ formatter: function(label, series){
var font = parseInt(scope.row.height.replace('px',''))/8 + String('px') var font = parseInt(scope.row.height.replace('px',''),10)/8 + String('px');
if(!(_.isUndefined(label))) if(!(_.isUndefined(label))) {
return '<div style="font-size:'+font+';font-weight:bold;text-align:center;padding:2px;color:#fff;">'+ return '<div style="font-size:'+font+';font-weight:bold;text-align:center;padding:2px;color:#fff;">'+
Math.round(series.percent)+'%</div>'; Math.round(series.percent)+'%</div>';
else } else {
return '' return '';
},
} }
else },
var label = { };
} else {
label = {
show: scope.panel.labels, show: scope.panel.labels,
radius: 2/3, radius: 2/3,
formatter: function(label, series){ formatter: function(label, series){
@ -204,6 +208,7 @@ angular.module('kibana.pie', [])
label+'<br/>'+Math.round(series.percent)+'%</div>'; label+'<br/>'+Math.round(series.percent)+'%</div>';
}, },
threshold: 0.1 threshold: 0.1
};
} }
var pie = { var pie = {
@ -263,7 +268,7 @@ angular.module('kibana.pie', [])
return; return;
} }
if(scope.panel.mode === 'terms') { if(scope.panel.mode === 'terms') {
filterSrv.set({type:'terms',field:scope.panel.query.field,value:object.series.label}) filterSrv.set({type:'terms',field:scope.panel.query.field,value:object.series.label});
dashboard.refresh(); dashboard.refresh();
} }
}); });
@ -280,4 +285,4 @@ angular.module('kibana.pie', [])
} }
}; };
}) });

View File

@ -1,3 +1,5 @@
/*jshint globalstrict:true */
/*global angular:true */
/* /*
## query ## query
@ -11,6 +13,8 @@
one element one element
*/ */
'use strict';
angular.module('kibana.query', []) angular.module('kibana.query', [])
.controller('query', function($scope, query, $rootScope) { .controller('query', function($scope, query, $rootScope) {
@ -22,39 +26,39 @@ angular.module('kibana.query', [])
group : "default", group : "default",
history : [], history : [],
remember: 10 // max: 100, angular strap can't take a variable for items param remember: 10 // max: 100, angular strap can't take a variable for items param
} };
_.defaults($scope.panel,_d); _.defaults($scope.panel,_d);
$scope.queries = query; $scope.queries = query;
$scope.init = function() { $scope.init = function() {
} };
$scope.refresh = function(query) { $scope.refresh = function(query) {
$rootScope.$broadcast('refresh') $rootScope.$broadcast('refresh');
} };
$scope.render = function(query) { $scope.render = function(query) {
$rootScope.$broadcast('render') $rootScope.$broadcast('render');
} };
$scope.add_query = function() { $scope.add_query = function() {
if (_.isArray($scope.panel.query)) if (_.isArray($scope.panel.query)) {
$scope.panel.query.push("") $scope.panel.query.push("");
else { } else {
$scope.panel.query = new Array($scope.panel.query) $scope.panel.query = new Array($scope.panel.query);
$scope.panel.query.push("") $scope.panel.query.push("");
}
} }
};
var update_history = function(query) { var update_history = function(query) {
if($scope.panel.remember > 0) { if($scope.panel.remember > 0) {
$scope.panel.history = _.union(query.reverse(),$scope.panel.history) $scope.panel.history = _.union(query.reverse(),$scope.panel.history);
var _length = $scope.panel.history.length var _length = $scope.panel.history.length;
if(_length > $scope.panel.remember) { if(_length > $scope.panel.remember) {
$scope.panel.history = $scope.panel.history.slice(0,$scope.panel.remember) $scope.panel.history = $scope.panel.history.slice(0,$scope.panel.remember);
}
} }
} }
};
}); });

View File

@ -1,3 +1,5 @@
/*jshint globalstrict:true */
/*global angular:true */
/* /*
## Table ## Table
@ -22,12 +24,11 @@
* table_documents :: An array containing all of the documents in the table. * table_documents :: An array containing all of the documents in the table.
Only used by the fields panel so far. Only used by the fields panel so far.
#### Receives #### Receives
* time :: An object containing the time range to use and the index(es) to query
* query :: An Array of queries, even if its only one
* sort :: An array with 2 elements. sort[0]: field, sort[1]: direction ('asc' or 'desc')
* selected_fields :: An array of fields to show * selected_fields :: An array of fields to show
*/ */
'use strict';
angular.module('kibana.table', []) angular.module('kibana.table', [])
.controller('table', function($rootScope, $scope, eventBus, fields, query, dashboard, filterSrv) { .controller('table', function($rootScope, $scope, eventBus, fields, query, dashboard, filterSrv) {
@ -48,104 +49,107 @@ angular.module('kibana.table', [])
header : true, header : true,
paging : true, paging : true,
spyable: true spyable: true
} };
_.defaults($scope.panel,_d) _.defaults($scope.panel,_d);
$scope.init = function () { $scope.init = function () {
$scope.set_listeners($scope.panel.group) $scope.set_listeners($scope.panel.group);
$scope.get_data(); $scope.get_data();
} };
$scope.set_listeners = function(group) { $scope.set_listeners = function(group) {
$scope.$on('refresh',function(){$scope.get_data()}) $scope.$on('refresh',function(){$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();
}); });
eventBus.register($scope,'selected_fields', function(event, fields) { eventBus.register($scope,'selected_fields', function(event, fields) {
$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) {
query.list[query.ids[0]].query = docs.query; query.list[query.ids[0]].query = docs.query;
$scope.data = docs.docs; $scope.data = docs.docs;
}); });
} };
$scope.set_sort = function(field) { $scope.set_sort = function(field) {
if($scope.panel.sort[0] === field) if($scope.panel.sort[0] === field) {
$scope.panel.sort[1] = $scope.panel.sort[1] == 'asc' ? 'desc' : 'asc'; $scope.panel.sort[1] = $scope.panel.sort[1] === 'asc' ? 'desc' : 'asc';
else } else {
$scope.panel.sort[0] = field; $scope.panel.sort[0] = field;
$scope.get_data();
} }
$scope.get_data();
};
$scope.toggle_field = function(field) { $scope.toggle_field = function(field) {
if (_.indexOf($scope.panel.fields,field) > -1) if (_.indexOf($scope.panel.fields,field) > -1) {
$scope.panel.fields = _.without($scope.panel.fields,field) $scope.panel.fields = _.without($scope.panel.fields,field);
else } else {
$scope.panel.fields.push(field) $scope.panel.fields.push(field);
broadcast_results();
} }
broadcast_results();
};
$scope.toggle_highlight = function(field) { $scope.toggle_highlight = function(field) {
if (_.indexOf($scope.panel.highlight,field) > -1) if (_.indexOf($scope.panel.highlight,field) > -1) {
$scope.panel.highlight = _.without($scope.panel.highlight,field) $scope.panel.highlight = _.without($scope.panel.highlight,field);
else } else {
$scope.panel.highlight.push(field) $scope.panel.highlight.push(field);
} }
};
$scope.toggle_details = function(row) { $scope.toggle_details = function(row) {
row.kibana = row.kibana || {}; row.kibana = row.kibana || {};
row.kibana.details = !row.kibana.details ? $scope.without_kibana(row) : false; row.kibana.details = !row.kibana.details ? $scope.without_kibana(row) : false;
} };
$scope.page = function(page) { $scope.page = function(page) {
$scope.panel.offset = page*$scope.panel.size $scope.panel.offset = page*$scope.panel.size;
$scope.get_data(); $scope.get_data();
} };
$scope.build_search = function(field,value,negate) { $scope.build_search = function(field,value,negate) {
var query; var query = field+":";
// This needs to be abstracted somewhere // This needs to be abstracted somewhere
if(_.isArray(value)) { if(_.isArray(value)) {
query = field+":(" + _.map(value,function(v){return angular.toJson(v)}).join(" AND ") + ")"; query = query+"(" + _.map(value,function(v){return angular.toJson(v);}).join(" AND ") + ")";
} else { } else {
query = field+":"+angular.toJson(value); query = query+angular.toJson(value);
} }
filterSrv.set({type:'querystring',query:query,mandate:(negate ? 'mustNot':'must')}) filterSrv.set({type:'querystring',query:query,mandate:(negate ? 'mustNot':'must')});
$scope.panel.offset = 0; $scope.panel.offset = 0;
dashboard.refresh(); dashboard.refresh();
} };
$scope.get_data = function(segment,query_id) { $scope.get_data = function(segment,query_id) {
$scope.panel.error = false; $scope.panel.error = false;
// Make sure we have everything for the request to complete // Make sure we have everything for the request to complete
if(dashboard.indices.length == 0) { if(dashboard.indices.length === 0) {
return return;
} }
$scope.panel.loading = true; $scope.panel.loading = true;
var _segment = _.isUndefined(segment) ? 0 : segment var _segment = _.isUndefined(segment) ? 0 : segment;
$scope.segment = _segment; $scope.segment = _segment;
var request = $scope.ejs.Request().indices(dashboard.indices[_segment]) var request = $scope.ejs.Request().indices(dashboard.indices[_segment]);
var boolQuery = ejs.BoolQuery(); var boolQuery = $scope.ejs.BoolQuery();
_.each(query.list,function(q) { _.each(query.list,function(q) {
boolQuery = boolQuery.should(ejs.QueryStringQuery(q.query || '*')) boolQuery = boolQuery.should($scope.ejs.QueryStringQuery(q.query || '*'));
}) });
request = request.query( request = request.query(
ejs.FilteredQuery( $scope.ejs.FilteredQuery(
boolQuery, boolQuery,
filterSrv.getBoolFilter(filterSrv.ids) filterSrv.getBoolFilter(filterSrv.ids)
)) ))
.highlight( .highlight(
ejs.Highlight($scope.panel.highlight) $scope.ejs.Highlight($scope.panel.highlight)
.fragmentSize(2147483647) // Max size of a 32bit unsigned int .fragmentSize(2147483647) // Max size of a 32bit unsigned int
.preTags('@start-highlight@') .preTags('@start-highlight@')
.postTags('@end-highlight@') .postTags('@end-highlight@')
@ -153,9 +157,9 @@ angular.module('kibana.table', [])
.size($scope.panel.size*$scope.panel.pages) .size($scope.panel.size*$scope.panel.pages)
.sort($scope.panel.sort[0],$scope.panel.sort[1]); .sort($scope.panel.sort[0],$scope.panel.sort[1]);
$scope.populate_modal(request) $scope.populate_modal(request);
var results = request.doSearch() var results = request.doSearch();
// Populate scope when we have results // Populate scope when we have results
results.then(function(results) { results.then(function(results) {
@ -164,7 +168,7 @@ angular.module('kibana.table', [])
if(_segment === 0) { if(_segment === 0) {
$scope.hits = 0; $scope.hits = 0;
$scope.data = []; $scope.data = [];
query_id = $scope.query_id = new Date().getTime() query_id = $scope.query_id = new Date().getTime();
} }
// Check for error and abort if found // Check for error and abort if found
@ -177,46 +181,46 @@ angular.module('kibana.table', [])
if($scope.query_id === query_id) { if($scope.query_id === query_id) {
$scope.data= $scope.data.concat(_.map(results.hits.hits, function(hit) { $scope.data= $scope.data.concat(_.map(results.hits.hits, function(hit) {
return { return {
_source : flatten_json(hit['_source']), _source : kbn.flatten_json(hit._source),
highlight : flatten_json(hit['highlight']||{}) highlight : kbn.flatten_json(hit.highlight||{})
} };
})); }));
$scope.hits += results.hits.total; $scope.hits += results.hits.total;
// Sort the data // Sort the data
$scope.data = _.sortBy($scope.data, function(v){ $scope.data = _.sortBy($scope.data, function(v){
return v._source[$scope.panel.sort[0]] return v._source[$scope.panel.sort[0]];
}); });
// Reverse if needed // Reverse if needed
if($scope.panel.sort[1] == 'desc') if($scope.panel.sort[1] === 'desc') {
$scope.data.reverse(); $scope.data.reverse();
}
// Keep only what we need for the set // Keep only what we need for the set
$scope.data = $scope.data.slice(0,$scope.panel.size * $scope.panel.pages) $scope.data = $scope.data.slice(0,$scope.panel.size * $scope.panel.pages);
} else { } else {
return; return;
} }
// This breaks, use $scope.data for this // This breaks, use $scope.data for this
$scope.all_fields = get_all_fields(_.pluck($scope.data,'_source')); $scope.all_fields = kbn.get_all_fields(_.pluck($scope.data,'_source'));
broadcast_results(); broadcast_results();
// If we're not sorting in reverse chrono order, query every index for // If we're not sorting in reverse chrono order, query every index for
// size*pages results // size*pages results
// Otherwise, only get size*pages results then stop querying // Otherwise, only get size*pages results then stop querying
if($scope.data.length < $scope.panel.size*$scope.panel.pages
//($scope.data.length < $scope.panel.size*$scope.panel.pages //($scope.data.length < $scope.panel.size*$scope.panel.pages
// || !(($scope.panel.sort[0] === $scope.time.field) && $scope.panel.sort[1] === 'desc')) // || !(($scope.panel.sort[0] === $scope.time.field) && $scope.panel.sort[1] === 'desc'))
&& _segment+1 < dashboard.indices.length if($scope.data.length < $scope.panel.size*$scope.panel.pages &&
) { _segment+1 < dashboard.indices.length ) {
$scope.get_data(_segment+1,$scope.query_id) $scope.get_data(_segment+1,$scope.query_id);
} }
}); });
} };
$scope.populate_modal = function(request) { $scope.populate_modal = function(request) {
$scope.modal = { $scope.modal = {
@ -225,15 +229,15 @@ angular.module('kibana.table', [])
'curl -XGET '+config.elasticsearch+'/'+dashboard.indices+"/_search?pretty -d'\n"+ 'curl -XGET '+config.elasticsearch+'/'+dashboard.indices+"/_search?pretty -d'\n"+
angular.toJson(JSON.parse(request.toString()),true)+ angular.toJson(JSON.parse(request.toString()),true)+
"'</pre>", "'</pre>",
} };
} };
$scope.without_kibana = function (row) { $scope.without_kibana = function (row) {
return { return {
_source : row._source, _source : row._source,
highlight : row.highlight highlight : row.highlight
} };
} };
// Broadcast a list of all fields. Note that receivers of field array // Broadcast a list of all fields. Note that receivers of field array
// events should be able to receive from multiple sources, merge, dedupe // events should be able to receive from multiple sources, merge, dedupe
@ -254,13 +258,14 @@ angular.module('kibana.table', [])
$scope.set_refresh = function (state) { $scope.set_refresh = function (state) {
$scope.refresh = state; $scope.refresh = state;
} };
$scope.close_edit = function() { $scope.close_edit = function() {
if($scope.refresh) if($scope.refresh) {
$scope.get_data(); $scope.get_data();
$scope.refresh = false;
} }
$scope.refresh = false;
};
}) })
@ -273,8 +278,8 @@ angular.module('kibana.table', [])
replace(/>/g, '&gt;'). replace(/>/g, '&gt;').
replace(/\r?\n/g, '<br/>'). replace(/\r?\n/g, '<br/>').
replace(/@start-highlight@/g, '<code class="highlight">'). replace(/@start-highlight@/g, '<code class="highlight">').
replace(/@end-highlight@/g, '</code>') replace(/@end-highlight@/g, '</code>');
} }
return ''; return '';
} };
}); });

View File

@ -1,3 +1,6 @@
/*jshint globalstrict:true */
/*global angular:true */
/*global Showdown:false */
/* /*
## Text ## Text
@ -11,6 +14,8 @@
*/ */
'use strict';
angular.module('kibana.text', []) angular.module('kibana.text', [])
.controller('text', function($scope, $rootScope) { .controller('text', function($scope, $rootScope) {
@ -21,12 +26,12 @@ angular.module('kibana.text', [])
mode : "markdown", mode : "markdown",
content : "", content : "",
style: {}, style: {},
} };
_.defaults($scope.panel,_d); _.defaults($scope.panel,_d);
$scope.init = function() { $scope.init = function() {
$scope.ready = false; $scope.ready = false;
} };
}).directive('markdown', function() { }).directive('markdown', function() {
return { return {
@ -34,10 +39,10 @@ angular.module('kibana.text', [])
link: function(scope, element, attrs) { link: function(scope, element, attrs) {
scope.$on('render', function() { scope.$on('render', function() {
render_panel(); render_panel();
}) });
function render_panel() { function render_panel() {
var scripts = $LAB.script("panels/text/lib/showdown.js") var scripts = $LAB.script("panels/text/lib/showdown.js");
scripts.wait(function(){ scripts.wait(function(){
scope.ready = true; scope.ready = true;
var converter = new Showdown.converter(); var converter = new Showdown.converter();
@ -48,18 +53,18 @@ angular.module('kibana.text', [])
element.html(htmlText); element.html(htmlText);
// For whatever reason, this fixes chrome. I don't like it, I think // For whatever reason, this fixes chrome. I don't like it, I think
// it makes things slow? // it makes things slow?
scope.$apply() scope.$apply();
}); });
} }
render_panel(); render_panel();
} }
} };
}) })
.filter('newlines', function(){ .filter('newlines', function(){
return function (input) { return function (input) {
return input.replace(/\n/g, '<br/>'); return input.replace(/\n/g, '<br/>');
} };
}) })
.filter('striphtml', function () { .filter('striphtml', function () {
return function(text) { return function(text) {
@ -67,5 +72,5 @@ angular.module('kibana.text', [])
.replace(/&/g, '&amp;') .replace(/&/g, '&amp;')
.replace(/>/g, '&gt;') .replace(/>/g, '&gt;')
.replace(/</g, '&lt;'); .replace(/</g, '&lt;');
} };
}); });

View File

@ -1,3 +1,5 @@
/*jshint globalstrict:true */
/*global angular:true */
/* /*
## Timepicker ## Timepicker
@ -17,6 +19,8 @@
* min :: The lowest interval a user may set * min :: The lowest interval a user may set
*/ */
'use strict';
angular.module('kibana.timepicker', []) angular.module('kibana.timepicker', [])
.controller('timepicker', function($scope, $rootScope, $timeout, timer, $http, dashboard, filterSrv) { .controller('timepicker', function($scope, $rootScope, $timeout, timer, $http, dashboard, filterSrv) {
@ -34,8 +38,8 @@ angular.module('kibana.timepicker', [])
interval: 30, interval: 30,
min : 3 min : 3
} }
} };
_.defaults($scope.panel,_d) _.defaults($scope.panel,_d);
var _groups = _.isArray($scope.panel.group) ? var _groups = _.isArray($scope.panel.group) ?
$scope.panel.group : [$scope.panel.group]; $scope.panel.group : [$scope.panel.group];
@ -43,91 +47,91 @@ angular.module('kibana.timepicker', [])
$scope.init = function() { $scope.init = function() {
// Private refresh interval that we can use for view display without causing // Private refresh interval that we can use for view display without causing
// unnecessary refreshes during changes // unnecessary refreshes during changes
$scope.refresh_interval = $scope.panel.refresh.interval $scope.refresh_interval = $scope.panel.refresh.interval;
$scope.filterSrv = filterSrv; $scope.filterSrv = filterSrv;
// Init a private time object with Date() objects depending on mode // Init a private time object with Date() objects depending on mode
switch($scope.panel.mode) { switch($scope.panel.mode) {
case 'absolute': case 'absolute':
$scope.time = { $scope.time = {
from : moment($scope.panel.time.from,'MM/DD/YYYY HH:mm:ss') || moment(time_ago($scope.panel.timespan)), from : moment($scope.panel.time.from,'MM/DD/YYYY HH:mm:ss') || moment(kbn.time_ago($scope.panel.timespan)),
to : moment($scope.panel.time.to,'MM/DD/YYYY HH:mm:ss') || moment() to : moment($scope.panel.time.to,'MM/DD/YYYY HH:mm:ss') || moment()
} };
break; break;
case 'since': case 'since':
$scope.time = { $scope.time = {
from : moment($scope.panel.time.from,'MM/DD/YYYY HH:mm:ss') || moment(time_ago($scope.panel.timespan)), from : moment($scope.panel.time.from,'MM/DD/YYYY HH:mm:ss') || moment(kbn.time_ago($scope.panel.timespan)),
to : moment() to : moment()
} };
break; break;
case 'relative': case 'relative':
$scope.time = { $scope.time = {
from : moment(time_ago($scope.panel.timespan)), from : moment(kbn.time_ago($scope.panel.timespan)),
to : moment() to : moment()
} };
break; break;
} }
$scope.time.field = $scope.panel.timefield; $scope.time.field = $scope.panel.timefield;
// These 3 statements basicly do everything time_apply() does // These 3 statements basicly do everything time_apply() does
set_timepicker($scope.time.from,$scope.time.to) set_timepicker($scope.time.from,$scope.time.to);
update_panel() update_panel();
set_time_filter($scope.time) set_time_filter($scope.time);
dashboard.refresh(); dashboard.refresh();
// Start refresh timer if enabled // Start refresh timer if enabled
if ($scope.panel.refresh.enable) if ($scope.panel.refresh.enable) {
$scope.set_interval($scope.panel.refresh.interval); $scope.set_interval($scope.panel.refresh.interval);
}
// In case some other panel broadcasts a time, set us to an absolute range // In case some other panel broadcasts a time, set us to an absolute range
$scope.$on('refresh', function() { $scope.$on('refresh', function() {
if(filterSrv.idsByType('time').length > 0) { if(filterSrv.idsByType('time').length > 0) {
var time = filterSrv.timeRange('min') var time = filterSrv.timeRange('min');
if($scope.time.from.diff(moment.utc(time.from),'seconds') !== 0 if($scope.time.from.diff(moment.utc(time.from),'seconds') !== 0 ||
|| $scope.time.to.diff(moment.utc(time.to),'seconds') !== 0) $scope.time.to.diff(moment.utc(time.to),'seconds') !== 0)
{ {
console.log($scope.time.from+ " and "+ moment.utc(time.from)) console.log($scope.time.from+ " and "+ moment.utc(time.from));
console.log($scope.time.to+" and "+moment.utc(time.to)) console.log($scope.time.to+" and "+moment.utc(time.to));
$scope.set_mode('absolute'); $scope.set_mode('absolute');
// These 3 statements basicly do everything time_apply() does // These 3 statements basicly do everything time_apply() does
set_timepicker(moment(time.from),moment(time.to)) set_timepicker(moment(time.from),moment(time.to));
$scope.time = $scope.time_calc(); $scope.time = $scope.time_calc();
update_panel() update_panel();
} }
} }
}); });
} };
$scope.set_interval = function (refresh_interval) { $scope.set_interval = function (refresh_interval) {
$scope.panel.refresh.interval = refresh_interval $scope.panel.refresh.interval = refresh_interval;
if(_.isNumber($scope.panel.refresh.interval)) { if(_.isNumber($scope.panel.refresh.interval)) {
if($scope.panel.refresh.interval < $scope.panel.refresh.min) { if($scope.panel.refresh.interval < $scope.panel.refresh.min) {
$scope.panel.refresh.interval = $scope.panel.refresh.min $scope.panel.refresh.interval = $scope.panel.refresh.min;
timer.cancel($scope.refresh_timer) timer.cancel($scope.refresh_timer);
return; return;
} }
timer.cancel($scope.refresh_timer) timer.cancel($scope.refresh_timer);
$scope.refresh() $scope.refresh();
} else { } else {
timer.cancel($scope.refresh_timer) timer.cancel($scope.refresh_timer);
}
} }
};
$scope.refresh = function() { $scope.refresh = function() {
if ($scope.panel.refresh.enable) { if ($scope.panel.refresh.enable) {
timer.cancel($scope.refresh_timer) timer.cancel($scope.refresh_timer);
$scope.refresh_timer = timer.register($timeout(function() { $scope.refresh_timer = timer.register($timeout(function() {
$scope.refresh(); $scope.refresh();
$scope.time_apply(); $scope.time_apply();
},$scope.panel.refresh.interval*1000 },$scope.panel.refresh.interval*1000));
));
} else { } else {
timer.cancel($scope.refresh_timer) timer.cancel($scope.refresh_timer);
}
} }
};
var update_panel = function() { var update_panel = function() {
// Update panel's string representation of the time object.Don't update if // Update panel's string representation of the time object.Don't update if
@ -141,92 +145,94 @@ angular.module('kibana.timepicker', [])
} else { } else {
delete $scope.panel.time; delete $scope.panel.time;
} }
} };
$scope.set_mode = function(mode) { $scope.set_mode = function(mode) {
$scope.panel.mode = mode; $scope.panel.mode = mode;
$scope.panel.refresh.enable = mode === 'absolute' ? $scope.panel.refresh.enable = mode === 'absolute' ?
false : $scope.panel.refresh.enable false : $scope.panel.refresh.enable;
update_panel(); update_panel();
} };
$scope.to_now = function() { $scope.to_now = function() {
$scope.timepicker.to = { $scope.timepicker.to = {
time : moment().format("HH:mm:ss"), time : moment().format("HH:mm:ss"),
date : moment().format("MM/DD/YYYY") date : moment().format("MM/DD/YYYY")
} };
} };
$scope.set_timespan = function(timespan) { $scope.set_timespan = function(timespan) {
$scope.panel.timespan = timespan; $scope.panel.timespan = timespan;
$scope.timepicker.from = { $scope.timepicker.from = {
time : moment(time_ago(timespan)).format("HH:mm:ss"), time : moment(kbn.time_ago(timespan)).format("HH:mm:ss"),
date : moment(time_ago(timespan)).format("MM/DD/YYYY") date : moment(kbn.time_ago(timespan)).format("MM/DD/YYYY")
} };
$scope.time_apply(); $scope.time_apply();
} };
$scope.close_edit = function() { $scope.close_edit = function() {
$scope.time_apply(); $scope.time_apply();
} };
// //
$scope.time_calc = function(){ $scope.time_calc = function(){
var from,to;
// If time picker is defined (usually is) // If time picker is defined (usually is)
if(!(_.isUndefined($scope.timepicker))) { if(!(_.isUndefined($scope.timepicker))) {
var from = $scope.panel.mode === 'relative' ? moment(time_ago($scope.panel.timespan)) : from = $scope.panel.mode === 'relative' ? moment(kbn.time_ago($scope.panel.timespan)) :
moment($scope.timepicker.from.date + " " + $scope.timepicker.from.time,'MM/DD/YYYY HH:mm:ss') moment($scope.timepicker.from.date + " " + $scope.timepicker.from.time,'MM/DD/YYYY HH:mm:ss');
var to = $scope.panel.mode !== 'absolute' ? moment() : to = $scope.panel.mode !== 'absolute' ? moment() :
moment($scope.timepicker.to.date + " " + $scope.timepicker.to.time,'MM/DD/YYYY HH:mm:ss') moment($scope.timepicker.to.date + " " + $scope.timepicker.to.time,'MM/DD/YYYY HH:mm:ss');
// Otherwise (probably initialization) // Otherwise (probably initialization)
} else { } else {
var from = $scope.panel.mode === 'relative' ? moment(time_ago($scope.panel.timespan)) : from = $scope.panel.mode === 'relative' ? moment(kbn.time_ago($scope.panel.timespan)) :
$scope.time.from; $scope.time.from;
var to = $scope.panel.mode !== 'absolute' ? moment() : to = $scope.panel.mode !== 'absolute' ? moment() :
$scope.time.to; $scope.time.to;
} }
if (from.valueOf() >= to.valueOf()) if (from.valueOf() >= to.valueOf()) {
from = moment(to.valueOf() - 1000) from = moment(to.valueOf() - 1000);
}
$timeout(function(){ $timeout(function(){
set_timepicker(from,to) set_timepicker(from,to);
}); });
return { return {
from : from, from : from,
to : to to : to
}; };
} };
$scope.time_apply = function() { $scope.time_apply = function() {
$scope.panel.error = ""; $scope.panel.error = "";
// Update internal time object // Update internal time object
// Remove all other time filters // Remove all other time filters
filterSrv.removeByType('time') filterSrv.removeByType('time');
$scope.time = $scope.time_calc(); $scope.time = $scope.time_calc();
$scope.time.field = $scope.panel.timefield $scope.time.field = $scope.panel.timefield;
update_panel() update_panel();
set_time_filter($scope.time) set_time_filter($scope.time);
dashboard.refresh(); dashboard.refresh();
}; };
function set_time_filter(time) { function set_time_filter(time) {
time.type = 'time' time.type = 'time';
// Check if there's a time filter we remember, if not, set one and remember it // Check if there's a time filter we remember, if not, set one and remember it
if(!_.isUndefined($scope.panel.filter_id) && if(!_.isUndefined($scope.panel.filter_id) &&
!_.isUndefined(filterSrv.list[$scope.panel.filter_id]) && !_.isUndefined(filterSrv.list[$scope.panel.filter_id]) &&
filterSrv.list[$scope.panel.filter_id].type == 'time') filterSrv.list[$scope.panel.filter_id].type === 'time')
{ {
filterSrv.set(compile_time(time),$scope.panel.filter_id) filterSrv.set(compile_time(time),$scope.panel.filter_id);
} else { } else {
$scope.panel.filter_id = filterSrv.set(compile_time(time)) $scope.panel.filter_id = filterSrv.set(compile_time(time));
} }
return $scope.panel.filter_id; return $scope.panel.filter_id;
} }
@ -234,9 +240,9 @@ angular.module('kibana.timepicker', [])
// Prefer to pass around Date() objects since interacting with // Prefer to pass around Date() objects since interacting with
// moment objects in libraries that are expecting Date()s can be tricky // moment objects in libraries that are expecting Date()s can be tricky
function compile_time(time) { function compile_time(time) {
time = _.clone(time) time = _.clone(time);
time.from = time.from.toDate() time.from = time.from.toDate();
time.to = time.to.toDate() time.to = time.to.toDate();
return time; return time;
} }
@ -251,7 +257,7 @@ angular.module('kibana.timepicker', [])
time : to.format("HH:mm:ss"), time : to.format("HH:mm:ss"),
date : to.format("MM/DD/YYYY") date : to.format("MM/DD/YYYY")
} }
} };
} }
}) });

View File

@ -18,6 +18,9 @@
* query :: An Array of queries, even if its only one * query :: An Array of queries, even if its only one
*/ */
'use strict';
angular.module('kibana.trends', []) angular.module('kibana.trends', [])
.controller('trends', function($scope, kbnIndex, query, dashboard, filterSrv) { .controller('trends', function($scope, kbnIndex, query, dashboard, filterSrv) {
@ -29,87 +32,87 @@ angular.module('kibana.trends', [])
style : { "font-size": '14pt'}, style : { "font-size": '14pt'},
ago : '1d', ago : '1d',
arrangement : 'vertical', arrangement : 'vertical',
} };
_.defaults($scope.panel,_d) _.defaults($scope.panel,_d);
$scope.init = function () { $scope.init = function () {
$scope.hits = 0; $scope.hits = 0;
$scope.$on('refresh',function(){$scope.get_data()}) $scope.$on('refresh',function(){$scope.get_data();});
$scope.get_data(); $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;
$scope.panel.loading = true; $scope.panel.loading = true;
// Make sure we have everything for the request to complete // Make sure we have everything for the request to complete
if(dashboard.indices.length == 0) { if(dashboard.indices.length === 0) {
return return;
} else { } else {
$scope.index = segment > 0 ? $scope.index : dashboard.indices; $scope.index = segment > 0 ? $scope.index : dashboard.indices;
} }
// Determine a time field // Determine a time field
var timeField = _.uniq(_.pluck(filterSrv.getByType('time'),'field')) var timeField = _.uniq(_.pluck(filterSrv.getByType('time'),'field'));
if(timeField.length > 1) { if(timeField.length > 1) {
$scope.panel.error = "Time field must be consistent amongst time filters" $scope.panel.error = "Time field must be consistent amongst time filters";
return return;
} else if(timeField.length == 0) { } else if(timeField.length === 0) {
$scope.panel.error = "A time filter must exist for this panel to function" $scope.panel.error = "A time filter must exist for this panel to function";
return return;
} else { } else {
timeField = timeField[0] timeField = timeField[0];
} }
$scope.time = filterSrv.timeRange('min'); $scope.time = filterSrv.timeRange('min');
$scope.old_time = { $scope.old_time = {
from : new Date($scope.time.from.getTime() - interval_to_seconds($scope.panel.ago)*1000), from : new Date($scope.time.from.getTime() - kbn.interval_to_seconds($scope.panel.ago)*1000),
to : new Date($scope.time.to.getTime() - interval_to_seconds($scope.panel.ago)*1000) to : new Date($scope.time.to.getTime() - kbn.interval_to_seconds($scope.panel.ago)*1000)
} };
var _segment = _.isUndefined(segment) ? 0 : segment var _segment = _.isUndefined(segment) ? 0 : segment;
var request = $scope.ejs.Request(); var request = $scope.ejs.Request();
var _ids_without_time = _.difference(filterSrv.ids,filterSrv.idsByType('time')) var _ids_without_time = _.difference(filterSrv.ids,filterSrv.idsByType('time'));
// Build the question part of the query // Build the question part of the query
_.each(query.ids, function(id) { _.each(query.ids, function(id) {
var q = $scope.ejs.FilteredQuery( var q = $scope.ejs.FilteredQuery(
ejs.QueryStringQuery(query.list[id].query || '*'), $scope.ejs.QueryStringQuery(query.list[id].query || '*'),
filterSrv.getBoolFilter(_ids_without_time).must( filterSrv.getBoolFilter(_ids_without_time).must(
ejs.RangeFilter(timeField) $scope.ejs.RangeFilter(timeField)
.from($scope.time.from) .from($scope.time.from)
.to($scope.time.to) .to($scope.time.to)
)) ));
request = request request = request
.facet($scope.ejs.QueryFacet(id) .facet($scope.ejs.QueryFacet(id)
.query(q) .query(q)
).size(0) ).size(0);
}); });
// And again for the old time period // And again for the old time period
_.each(query.ids, function(id) { _.each(query.ids, function(id) {
var q = $scope.ejs.FilteredQuery( var q = $scope.ejs.FilteredQuery(
ejs.QueryStringQuery(query.list[id].query || '*'), $scope.ejs.QueryStringQuery(query.list[id].query || '*'),
filterSrv.getBoolFilter(_ids_without_time).must( filterSrv.getBoolFilter(_ids_without_time).must(
ejs.RangeFilter(timeField) $scope.ejs.RangeFilter(timeField)
.from($scope.old_time.from) .from($scope.old_time.from)
.to($scope.old_time.to) .to($scope.old_time.to)
)) ));
request = request request = request
.facet($scope.ejs.QueryFacet("old_"+id) .facet($scope.ejs.QueryFacet("old_"+id)
.query(q) .query(q)
).size(0) ).size(0);
}); });
// TODO: Spy for trend 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
if (_segment == 0) { if (_segment === 0) {
kbnIndex.indices( kbnIndex.indices(
$scope.old_time.from, $scope.old_time.from,
$scope.old_time.to, $scope.old_time.to,
@ -117,20 +120,22 @@ angular.module('kibana.trends', [])
dashboard.current.index.interval dashboard.current.index.interval
).then(function (p) { ).then(function (p) {
$scope.index = _.union(p,$scope.index); $scope.index = _.union(p,$scope.index);
request = request.indices($scope.index[_segment]) request = request.indices($scope.index[_segment]);
process_results(request.doSearch()); process_results(request.doSearch());
}); });
} else { } else {
process_results(request.indices($scope.index[_segment]).doSearch()); process_results(request.indices($scope.index[_segment]).doSearch(),_segment,query_id);
} }
};
// Populate scope when we have results // Populate scope when we have results
function process_results(results) { var process_results = function(results,_segment,query_id) {
results.then(function(results) { results.then(function(results) {
$scope.panel.loading = false; $scope.panel.loading = false;
if(_segment == 0) { if(_segment === 0) {
$scope.hits = {}; $scope.hits = {};
$scope.data = []; $scope.data = [];
query_id = $scope.query_id = new Date().getTime(); query_id = $scope.query_id = new Date().getTime();
@ -143,28 +148,28 @@ angular.module('kibana.trends', [])
} }
// Convert facet ids to numbers // Convert facet ids to numbers
var facetIds = _.map(_.keys(results.facets),function(k){if(!isNaN(k)){return parseInt(k)}}) var facetIds = _.map(_.keys(results.facets),function(k){if(!isNaN(k)){return parseInt(k, 10);}});
// Make sure we're still on the same query/queries // Make sure we're still on the same query/queries
if($scope.query_id === query_id && if($scope.query_id === query_id &&
_.intersection(facetIds,query.ids).length == query.ids.length _.intersection(facetIds,query.ids).length === query.ids.length
) { ) {
var i = 0; var i = 0;
_.each(query.ids, function(id) { _.each(query.ids, function(id) {
var v = results.facets[id] var v = results.facets[id];
var n = results.facets[id].count var n = results.facets[id].count;
var o = results.facets['old_'+id].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,
old : _.isUndefined($scope.data[i]) || _segment == 0 ? o : $scope.data[i].hits.old+o old : _.isUndefined($scope.data[i]) || _segment === 0 ? o : $scope.data[i].hits.old+o
} };
$scope.hits.new += n; $scope.hits.new += n;
$scope.hits.old += o; $scope.hits.old += o;
var percent = percentage(hits.old,hits.new) == null ? var percent = percentage(hits.old,hits.new) == null ?
'?' : 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] = {
info: query.list[id], info: query.list[id],
@ -178,29 +183,29 @@ angular.module('kibana.trends', [])
i++; i++;
}); });
$scope.$emit('render'); $scope.$emit('render');
if(_segment < $scope.index.length-1) if(_segment < $scope.index.length-1) {
$scope.get_data(_segment+1,query_id) $scope.get_data(_segment+1,query_id);
else } else {
$scope.trends = $scope.data $scope.trends = $scope.data;
}
} }
}); });
} };
}
function percentage(x,y) { function percentage(x,y) {
return x == 0 ? null : 100*(y-x)/x return x === 0 ? null : 100*(y-x)/x;
} }
$scope.set_refresh = function (state) { $scope.set_refresh = function (state) {
$scope.refresh = state; $scope.refresh = state;
} };
$scope.close_edit = function() { $scope.close_edit = function() {
if($scope.refresh) if($scope.refresh) {
$scope.get_data(); $scope.get_data();
}
$scope.refresh = false; $scope.refresh = false;
$scope.$emit('render'); $scope.$emit('render');
} };
}) });