From 5a3028f784df60012f45e6d9bfb53624a5aa10e6 Mon Sep 17 00:00:00 2001 From: Rashid Khan Date: Sat, 20 Jul 2013 14:56:59 -0700 Subject: [PATCH] Linted, moved shared functions to kbn object --- Gruntfile.js | 58 +++ common/lib/shared.js | 671 ++++++++++++++------------------- js/directives.js | 2 +- js/services.js | 5 +- package.json | 14 + panels/derivequeries/module.js | 62 +-- panels/fields/module.js | 60 +-- panels/filtering/module.js | 26 +- panels/histogram/module.js | 165 ++++---- panels/hits/module.js | 88 +++-- panels/map/module.js | 64 ++-- panels/pie/module.js | 101 ++--- panels/query/module.js | 36 +- panels/table/module.js | 145 +++---- panels/text/module.js | 21 +- panels/timepicker/module.js | 162 ++++---- panels/trends/module.js | 195 +++++----- 17 files changed, 955 insertions(+), 920 deletions(-) create mode 100644 Gruntfile.js create mode 100644 package.json diff --git a/Gruntfile.js b/Gruntfile.js new file mode 100644 index 00000000000..237f3d66693 --- /dev/null +++ b/Gruntfile.js @@ -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']); + +}; diff --git a/common/lib/shared.js b/common/lib/shared.js index 4568130c43a..b654ef13103 100644 --- a/common/lib/shared.js +++ b/common/lib/shared.js @@ -1,412 +1,295 @@ -function get_object_fields(obj) { - var field_array = []; - obj = flatten_json(obj._source) - for (field in obj) { - field_array.push(field); +// 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 = []; + obj = kbn.flatten_json(obj._source) + for (field in obj) { + field_array.push(field); + } + return field_array.sort(); } - return field_array.sort(); -} -function get_all_fields(data) { - var fields = []; - _.each(data,function(hit) { - fields = _.uniq(fields.concat(_.keys(hit))) - }) - // Remove stupid angular key - fields = _.without(fields,'$$hashKey') - return fields; -} - -function has_field(obj,field) { - var obj_fields = get_object_fields(obj); - if (_.inArray(obj_fields,field) < 0) { - return false; - } else { - return true; + kbn.get_all_fields = function(data) { + var fields = []; + _.each(data,function(hit) { + fields = _.uniq(fields.concat(_.keys(hit))) + }) + // Remove stupid angular key + fields = _.without(fields,'$$hashKey') + return fields; } -} -function get_related_fields(docs,field) { - var field_array = [] - _.each(docs, function(doc) { - var keys = _.keys(doc) - if(_.contains(keys,field)) - field_array = field_array.concat(keys) - }) - var counts = _.countBy(_.without(field_array,field),function(field){return field;}); - return counts; -} + kbn.has_field = function(obj,field) { + var obj_fields = get_object_fields(obj); + if (_.inArray(obj_fields,field) < 0) { + return false; + } else { + return true; + } + } -function recurse_field_dots(object,field) { - var value = null; - if (typeof object[field] != 'undefined') - value = object[field]; - else if (nested = field.match(/(.*?)\.(.*)/)) - if(typeof object[nested[1]] != 'undefined') - value = (typeof object[nested[1]][nested[2]] != 'undefined') ? - object[nested[1]][nested[2]] : recurse_field_dots( - object[nested[1]],nested[2]); + kbn.get_related_fields = function(docs,field) { + var field_array = [] + _.each(docs, function(doc) { + var keys = _.keys(doc) + if(_.contains(keys,field)) + field_array = field_array.concat(keys) + }) + var counts = _.countBy(_.without(field_array,field),function(field){return field;}); + return counts; + } - return value; -} + kbn.recurse_field_dots = function(object,field) { + var value = null; + if (typeof object[field] != 'undefined') + value = object[field]; + else if (nested = field.match(/(.*?)\.(.*)/)) + if(typeof object[nested[1]] != 'undefined') + value = (typeof object[nested[1]][nested[2]] != 'undefined') ? + object[nested[1]][nested[2]] : recurse_field_dots( + object[nested[1]],nested[2]); -// Probably useless now, leaving for cases where you might not want -// a flat dot notated data structure -function get_field_value(object,field,opt) { - var value = recurse_field_dots(object['_source'],field); + return value; + } - if(value === null) - return '' - if(_.isArray(value)) - if (opt == 'raw') { + // Probably useless now, leaving for cases where you might not want + // a flat dot notated data structure + kbn.get_field_value = function(object,field,opt) { + var value = kbn.recurse_field_dots(object['_source'],field); + + if(value === null) + return '' + if(_.isArray(value)) + if (opt == 'raw') { + return value; + } + else { + var complex = false; + _.each(value, function(el, index) { + if (typeof(el) == 'object') { + complex = true; + } + }) + if (complex) { + return JSON.stringify(value, null, 4); + } + return value.toString(); + } + if(typeof value === 'object' && value != null) + // Leaving this out for now + //return opt == 'raw' ? value : JSON.stringify(value,null,4) + return JSON.stringify(value,null,4) + + return (value != null) ? value.toString() : ''; + } + + kbn.top_field_values = function(docs,field,count) { + var counts = _.countBy(_.pluck(docs,field),function(field){ + return _.isUndefined(field) ? '' : field; + }); + return _.pairs(counts).sort(function(a, b) { + return a[1] - b[1] + }).reverse().slice(0,count) + } + + /** + * Calculate a graph interval + * + * from:: Date object containing the start time + * to:: Date object containing the finish time + * size:: Calculate to approximately this many bars + * user_interval:: User specified histogram interval + * + */ + kbn.calculate_interval = function(from,to,size,user_interval) { + if(_.isObject(from)) + from = from.valueOf(); + if(_.isObject(to)) + to = to.valueOf(); + return user_interval == 0 ? kbn.round_interval((to - from)/size) : user_interval; + } + + kbn.round_interval = function(interval) { + switch (true) { + // 0.5s + case (interval <= 500): return 100; // 0.1s + // 5s + case (interval <= 5000): return 1000; // 1s + // 7.5s + case (interval <= 7500): return 5000; // 5s + // 15s + case (interval <= 15000): return 10000; // 10s + // 45s + case (interval <= 45000): return 30000; // 30s + // 3m + case (interval <= 180000): return 60000; // 1m + // 9m + case (interval <= 450000): return 300000; // 5m + // 20m + case (interval <= 1200000): return 600000; // 10m + // 45m + case (interval <= 2700000): return 1800000; // 30m + // 2h + case (interval <= 7200000): return 3600000; // 1h + // 6h + case (interval <= 21600000): return 10800000; // 3h + // 24h + case (interval <= 86400000): return 43200000; // 12h + // 48h + case (interval <= 172800000): return 86400000; // 24h + // 1w + case (interval <= 604800000): return 86400000; // 24h + // 3w + case (interval <= 1814400000): return 604800000; // 1w + // 2y + case (interval < 3628800000): return 2592000000; // 30d + default: return 31536000000; // 1y + } + } + + kbn.secondsToHms = function(seconds){ + var numyears = Math.floor(seconds / 31536000); + if(numyears){ + return numyears + 'y'; + } + var numdays = Math.floor((seconds % 31536000) / 86400); + if(numdays){ + return numdays + 'd'; + } + var numhours = Math.floor(((seconds % 31536000) % 86400) / 3600); + if(numhours){ + return numhours + 'h'; + } + var numminutes = Math.floor((((seconds % 31536000) % 86400) % 3600) / 60); + if(numminutes){ + return numminutes + 'm'; + } + var numseconds = (((seconds % 31536000) % 86400) % 3600) % 60; + if(numseconds){ + return numseconds + 's'; + } + return 'less then a second'; //'just now' //or other string you like; + } + + kbn.to_percent = function(number,outof) { + return Math.round((number/outof)*10000)/100 + "%"; + } + + kbn.addslashes = function(str) { + str = str.replace(/\\/g, '\\\\'); + str = str.replace(/\'/g, '\\\''); + str = str.replace(/\"/g, '\\"'); + str = str.replace(/\0/g, '\\0'); + return str; + } + + // histogram & trends + kbn.interval_to_seconds = function(string) { + var matches = string.match(/(\d+)([Mwdhmsy])/); + switch (matches[2]) { + case 'y': return matches[1]*31536000;; + case 'M': return matches[1]*2592000;; + case 'w': return matches[1]*604800;; + case 'd': return matches[1]*86400;; + case 'h': return matches[1]*3600;; + case 'm': return matches[1]*60;; + case 's': return matches[1]; + } + } + + // This should go away, moment.js can do this + kbn.time_ago = function(string) { + return new Date(new Date().getTime() - (kbn.interval_to_seconds(string)*1000)) + } + + // LOL. hahahahaha. DIE. + kbn.flatten_json = function(object,root,array) { + if (typeof array === 'undefined') + var array = {}; + if (typeof root === 'undefined') + var root = ''; + for(var index in object) { + var obj = object[index] + var rootname = root.length == 0 ? index : root + '.' + index; + if(typeof obj == 'object' ) { + if(_.isArray(obj)) { + if(obj.length > 0 && typeof obj[0] === 'object') { + var strval = ''; + for (var objidx = 0, objlen = obj.length; objidx < objlen; objidx++) { + if (objidx > 0) { + strval = strval + ', '; + } + + strval = strval + JSON.stringify(obj[objidx]); + } + array[rootname] = strval; + } else if(obj.length === 1 && _.isNumber(obj[0])) { + array[rootname] = parseFloat(obj[0]); + } else { + array[rootname] = typeof obj === 'undefined' ? null : obj; + } + } else { + kbn.flatten_json(obj,rootname,array) + } + } else { + array[rootname] = typeof obj === 'undefined' ? null : obj; + } + } + return kbn.sortObj(array); + } + + kbn.xmlEnt = function(value) { + if(_.isString(value)) { + var stg1 = value.replace(//g, '>') + .replace(/\r\n/g, '
') + .replace(/\r/g, '
') + .replace(/\n/g, '
') + .replace(/\t/g, '    ') + .replace(/ /g, '  ') + .replace(/<del>/g, '') + .replace(/<\/del>/g, ''); + return stg1; + } else { return value; } - else { - var complex = false; - _.each(value, function(el, index) { - if (typeof(el) == 'object') { - complex = true; - } - }) - if (complex) { - return JSON.stringify(value, null, 4); - } - return value.toString(); + } + + kbn.sortObj = function(arr) { + // Setup Arrays + var sortedKeys = new Array(); + var sortedObj = {}; + + // Separate keys and sort them + for (var i in arr) { + sortedKeys.push(i); } - if(typeof value === 'object' && value != null) - // Leaving this out for now - //return opt == 'raw' ? value : JSON.stringify(value,null,4) - return JSON.stringify(value,null,4) + sortedKeys.sort(); - return (value != null) ? value.toString() : ''; -} - -function top_field_values(docs,field,count) { - var counts = _.countBy(_.pluck(docs,field),function(field){ - return _.isUndefined(field) ? '' : field; - }); - return _.pairs(counts).sort(function(a, b) { - return a[1] - b[1] - }).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 - * - * from:: Date object containing the start time - * to:: Date object containing the finish time - * size:: Calculate to approximately this many bars - * user_interval:: User specified histogram interval - * - */ -function calculate_interval(from,to,size,user_interval) { - if(_.isObject(from)) - from = from.valueOf(); - if(_.isObject(to)) - to = to.valueOf(); - return user_interval == 0 ? round_interval((to - from)/size) : user_interval; -} - -function get_bar_count(from,to,interval) { - return (to - from)/interval; -} - -function round_interval (interval) { - switch (true) { - // 0.5s - case (interval <= 500): return 100; // 0.1s - // 5s - case (interval <= 5000): return 1000; // 1s - // 7.5s - case (interval <= 7500): return 5000; // 5s - // 15s - case (interval <= 15000): return 10000; // 10s - // 45s - case (interval <= 45000): return 30000; // 30s - // 3m - case (interval <= 180000): return 60000; // 1m - // 9m - case (interval <= 450000): return 300000; // 5m - // 20m - case (interval <= 1200000): return 600000; // 10m - // 45m - case (interval <= 2700000): return 1800000; // 30m - // 2h - case (interval <= 7200000): return 3600000; // 1h - // 6h - case (interval <= 21600000): return 10800000; // 3h - // 24h - case (interval <= 86400000): return 43200000; // 12h - // 48h - case (interval <= 172800000): return 86400000; // 24h - // 1w - case (interval <= 604800000): return 86400000; // 24h - // 3w - case (interval <= 1814400000): return 604800000; // 1w - // 2y - case (interval < 3628800000): return 2592000000; // 30d - default: return 31536000000; // 1y - } -} - -function secondsToHms(seconds){ - var numyears = Math.floor(seconds / 31536000); - if(numyears){ - return numyears + 'y'; + // Reconstruct sorted obj based on keys + for (var i in sortedKeys) { + sortedObj[sortedKeys[i]] = arr[sortedKeys[i]]; } - var numdays = Math.floor((seconds % 31536000) / 86400); - if(numdays){ - return numdays + 'd'; - } - var numhours = Math.floor(((seconds % 31536000) % 86400) / 3600); - if(numhours){ - return numhours + 'h'; - } - var numminutes = Math.floor((((seconds % 31536000) % 86400) % 3600) / 60); - if(numminutes){ - return numminutes + 'm'; - } - var numseconds = (((seconds % 31536000) % 86400) % 3600) % 60; - if(numseconds){ - return numseconds + 's'; - } - return 'less then a second'; //'just now' //or other string you like; -} - -function to_percent(number,outof) { - return Math.round((number/outof)*10000)/100 + "%"; -} - -function addslashes(str) { - str = str.replace(/\\/g, '\\\\'); - str = str.replace(/\'/g, '\\\''); - str = str.replace(/\"/g, '\\"'); - str = str.replace(/\0/g, '\\0'); - 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)); + return sortedObj; } +}).call(this); - function pad(n) { - return n < 10 ? '0' + n : n - } - 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])/); - switch (matches[2]) { - case 'y': return matches[1]*31536000;; - case 'M': return matches[1]*2592000;; - case 'w': return matches[1]*604800;; - case 'd': return matches[1]*86400;; - case 'h': return matches[1]*3600;; - case 'm': return matches[1]*60;; - case 's': return matches[1]; - } -} - -function time_ago(string) { - return new Date(new Date().getTime() - (interval_to_seconds(string)*1000)) -} - -function flatten_json(object,root,array) { - if (typeof array === 'undefined') - var array = {}; - if (typeof root === 'undefined') - var root = ''; - for(var index in object) { - var obj = object[index] - var rootname = root.length == 0 ? index : root + '.' + index; - if(typeof obj == 'object' ) { - if(_.isArray(obj)) { - if(obj.length > 0 && typeof obj[0] === 'object') { - var strval = ''; - for (var objidx = 0, objlen = obj.length; objidx < objlen; objidx++) { - if (objidx > 0) { - strval = strval + ', '; - } - - strval = strval + JSON.stringify(obj[objidx]); - } - array[rootname] = strval; - } else if(obj.length === 1 && _.isNumber(obj[0])) { - array[rootname] = parseFloat(obj[0]); - } else { - array[rootname] = typeof obj === 'undefined' ? null : obj; - } - } else { - flatten_json(obj,rootname,array) - } - } else { - array[rootname] = typeof obj === 'undefined' ? null : obj; - } - } - return sortObj(array); -} - -function xmlEnt(value) { - if(_.isString(value)) { - var stg1 = value.replace(//g, '>') - .replace(/\r\n/g, '
') - .replace(/\r/g, '
') - .replace(/\n/g, '
') - .replace(/\t/g, '    ') - .replace(/ /g, '  ') - .replace(/<del>/g, '') - .replace(/<\/del>/g, ''); - return stg1 - } else { - return value - } -} - -function sortObj(arr) { - // Setup Arrays - var sortedKeys = new Array(); - var sortedObj = {}; - - // Separate keys and sort them - for (var i in arr) { - sortedKeys.push(i); - } - sortedKeys.sort(); - - // Reconstruct sorted obj based on keys - for (var i in sortedKeys) { - sortedObj[sortedKeys[i]] = arr[sortedKeys[i]]; - } - return sortedObj; -} - -// WTF. Has to be a better way to do this. Hi Tyler. -function int_to_tz(offset) { - 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 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 + "" + char + trailer; - } - } - ); -} - -function htmlEntities(str) { - return String(str).replace( - /&/g, '&').replace( - //g, '>').replace( - /"/g, '"'); -} - -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; - } -} +/* + UNDERSCORE.js Mixins +*/ _.mixin({ move: function (array, fromIndex, toIndex) { diff --git a/js/directives.js b/js/directives.js index 73986619ad1..44fce2e020a 100644 --- a/js/directives.js +++ b/js/directives.js @@ -77,6 +77,6 @@ angular.module('kibana.directives', []) fn(scope, {$event:event}); }); }); - } + }; }]); diff --git a/js/services.js b/js/services.js index 5c2990cabdf..ed4a6794138 100644 --- a/js/services.js +++ b/js/services.js @@ -243,7 +243,8 @@ angular.module('kibana.services', []) query: '*', alias: '', color: colorAt(_id), - id: _id + id: _id, + type: 'lucene' }; _.defaults(query,_query); self.list[_id] = query; @@ -386,7 +387,7 @@ angular.module('kibana.services', []) .from(filter.from) .to(filter.to); case 'querystring': - return ejs.QueryFilter(ejs.QueryStringQuery(filter.query)); + return ejs.QueryFilter(ejs.QueryStringQuery(filter.query)).cache(true); case 'terms': return ejs.TermsFilter(filter.field,filter.value); case 'exists': diff --git a/package.json b/package.json new file mode 100644 index 00000000000..4740c76ad27 --- /dev/null +++ b/package.json @@ -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" +} diff --git a/panels/derivequeries/module.js b/panels/derivequeries/module.js index 3b92e4ff76f..8af9f6c0083 100644 --- a/panels/derivequeries/module.js +++ b/panels/derivequeries/module.js @@ -1,3 +1,5 @@ +/*jshint globalstrict:true */ +/*global angular:true */ /* ## Derivequeries @@ -14,6 +16,8 @@ */ +'use strict'; + angular.module('kibana.derivequeries', []) .controller('derivequeries', function($scope, $rootScope, query, fields, dashboard, filterSrv) { @@ -33,19 +37,19 @@ angular.module('kibana.derivequeries', []) exclude : [], history : [], remember: 10 // max: 100, angular strap can't take a variable for items param - } + }; _.defaults($scope.panel,_d); $scope.init = function() { - $scope.panel.fields = fields.list - } + $scope.panel.fields = fields.list; + }; $scope.get_data = function() { update_history($scope.panel.query); // Make sure we have everything for the request to complete - if(dashboard.indices.length == 0) { - return + if(dashboard.indices.length === 0) { + return; } $scope.panel.loading = true; @@ -53,15 +57,15 @@ angular.module('kibana.derivequeries', []) // Terms mode request = request - .facet(ejs.TermsFacet('query') + .facet($scope.ejs.TermsFacet('query') .field($scope.panel.field) - .size($scope.panel['size']) + .size($scope.panel.size) .exclude($scope.panel.exclude) - .facetFilter(ejs.QueryFilter( - ejs.FilteredQuery( - ejs.QueryStringQuery($scope.panel.query || '*'), + .facetFilter($scope.ejs.QueryFilter( + $scope.ejs.FilteredQuery( + $scope.ejs.QueryStringQuery($scope.panel.query || '*'), filterSrv.getBoolFilter(filterSrv.ids) - )))).size(0) + )))).size(0); $scope.populate_modal(request); @@ -70,19 +74,20 @@ angular.module('kibana.derivequeries', []) // Populate scope when we have results results.then(function(results) { $scope.panel.loading = false; - var data = []; + var suffix, + data = []; if ($scope.panel.query === '' || $scope.panel.mode === 'terms only') { - var suffix = ''; + suffix = ''; } else if ($scope.panel.mode === 'AND') { - var suffix = ' AND (' + $scope.panel.query + ')'; + suffix = ' AND (' + $scope.panel.query + ')'; } else if ($scope.panel.mode === 'OR') { - var suffix = ' OR (' + $scope.panel.query + ')'; + suffix = ' OR (' + $scope.panel.query + ')'; } var ids = []; _.each(results.facets.query.terms, function(v) { var _q = $scope.panel.field+':"'+v.term+'"'+suffix; // if it isn't in the list, remove it - var _iq = query.findQuery(_q) + var _iq = query.findQuery(_q); if(!_iq) { ids.push(query.set({query:_q})); } else { @@ -90,22 +95,23 @@ angular.module('kibana.derivequeries', []) } }); _.each(_.difference($scope.panel.ids,ids),function(id){ - query.remove(id) - }) + query.remove(id); + }); $scope.panel.ids = ids; dashboard.refresh(); }); - } + }; $scope.set_refresh = function (state) { $scope.refresh = state; - } + }; $scope.close_edit = function() { - if($scope.refresh) + if($scope.refresh) { $scope.get_data(); + } $scope.refresh = false; - } + }; $scope.populate_modal = function(request) { $scope.modal = { @@ -114,18 +120,18 @@ angular.module('kibana.derivequeries', []) 'curl -XGET '+config.elasticsearch+'/'+dashboard.indices+"/_search?pretty -d'\n"+ angular.toJson(JSON.parse(request.toString()),true)+ "'", - } - } + }; + }; var update_history = function(query) { query = _.isArray(query) ? query : [query]; if($scope.panel.remember > 0) { - $scope.panel.history = _.union(query.reverse(),$scope.panel.history) - var _length = $scope.panel.history.length + $scope.panel.history = _.union(query.reverse(),$scope.panel.history); + var _length = $scope.panel.history.length; if(_length > $scope.panel.remember) { - $scope.panel.history = $scope.panel.history.slice(0,$scope.panel.remember) + $scope.panel.history = $scope.panel.history.slice(0,$scope.panel.remember); } } - } + }; }); diff --git a/panels/fields/module.js b/panels/fields/module.js index a9ad74b744a..35ae3193213 100644 --- a/panels/fields/module.js +++ b/panels/fields/module.js @@ -1,3 +1,6 @@ +/*jshint globalstrict:true */ +/*global angular:true */ + /* ## Fields @@ -17,6 +20,9 @@ * fields :: an object containing the sort order, existing fields and selected fields */ + +'use strict'; + angular.module('kibana.fields', []) .controller('fields', function($scope, eventBus, $timeout, dashboard, query, filterSrv) { @@ -27,7 +33,7 @@ angular.module('kibana.fields', []) style : {}, arrange : 'vertical', micropanel_position : 'right', - } + }; _.defaults($scope.panel,_d); $scope.init = function() { @@ -35,7 +41,7 @@ angular.module('kibana.fields', []) $scope.fields = []; eventBus.register($scope,'fields', function(event, fields) { $scope.panel.sort = _.clone(fields.sort); - $scope.fields = fields.all, + $scope.fields = fields.all; $scope.active = _.clone(fields.active); }); 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.broadcast($scope.$id,$scope.panel.group,"selected_fields",$scope.active); }); - } + }; $scope.reload_list = function () { var temp = _.clone($scope.fields); - $scope.fields = [] + $scope.fields = []; $timeout(function(){ $scope.fields = temp; - },10) + },10); - } + }; $scope.toggle_micropanel = function(field) { $scope.micropanel = { field: field, - values : top_field_values($scope.docs,field,10), - related : get_related_fields($scope.docs,field), - count: _.countBy($scope.docs,function(doc){ - return _.contains(_.keys(doc),field)})['true'], - } - } + values : kbn.top_field_values($scope.docs,field,10), + related : kbn.get_related_fields($scope.docs,field), + count: _.countBy($scope.docs,function(doc){return _.contains(_.keys(doc),field);})['true'] + }; + }; $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) { - if (_.indexOf($scope.active,field) > -1) - $scope.active = _.without($scope.active,field) - else - $scope.active.push(field) - eventBus.broadcast($scope.$id,$scope.panel.group,"selected_fields",$scope.active) - } + if (_.indexOf($scope.active,field) > -1) { + $scope.active = _.without($scope.active,field); + } else { + $scope.active.push(field); + } + eventBus.broadcast($scope.$id,$scope.panel.group,"selected_fields",$scope.active); + }; $scope.build_search = function(field,value,mandate) { var query; if(_.isArray(value)) { - query = field+":(" + _.map(value,function(v){return "\""+v+"\""}).join(",") + ")"; + query = field+":(" + _.map(value,function(v){return "\""+v+"\"";}).join(",") + ")"; } else { query = field+":"+angular.toJson(value); } - filterSrv.set({type:'querystring',query:query,mandate:mandate}) + filterSrv.set({type:'querystring',query:query,mandate:mandate}); dashboard.refresh(); - } + }; $scope.fieldExists = function(field,mandate) { - filterSrv.set({type:'exists',field:field,mandate:mandate}) + filterSrv.set({type:'exists',field:field,mandate:mandate}); dashboard.refresh(); - } + }; $scope.is_active = function(field) { return _.indexOf($scope.active,field) > -1 ? ['label','label-info'] : ''; - } + }; -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/panels/filtering/module.js b/panels/filtering/module.js index dd78d7326d6..7f3595667e5 100644 --- a/panels/filtering/module.js +++ b/panels/filtering/module.js @@ -1,3 +1,5 @@ +/*jshint globalstrict:true */ +/*global angular:true */ /* ## filtering @@ -8,39 +10,41 @@ */ +'use strict'; + angular.module('kibana.filtering', []) .controller('filtering', function($scope, filterSrv, $rootScope, dashboard) { // Set and populate defaults var _d = { status : "Experimental" - } + }; _.defaults($scope.panel,_d); $scope.init = function() { - $scope.filterSrv = filterSrv - } + $scope.filterSrv = filterSrv; + }; $scope.remove = function(id) { filterSrv.remove(id); dashboard.refresh(); - } + }; $scope.toggle = function(id) { filterSrv.list[id].active = !filterSrv.list[id].active; dashboard.refresh(); - } + }; $scope.refresh = function(query) { - $rootScope.$broadcast('refresh') - } + $rootScope.$broadcast('refresh'); + }; $scope.render = function(query) { - $rootScope.$broadcast('render') - } + $rootScope.$broadcast('render'); + }; $scope.show_key = function(key) { - return !_.contains(['type','id','alias','mandate','active','editing'],key) - } + return !_.contains(['type','id','alias','mandate','active','editing'],key); + }; }); \ No newline at end of file diff --git a/panels/histogram/module.js b/panels/histogram/module.js index 4406b64b9fd..0030d453fa3 100644 --- a/panels/histogram/module.js +++ b/panels/histogram/module.js @@ -1,3 +1,6 @@ +/*jshint globalstrict:true */ +/*global angular:true */ + /* ## Histogram @@ -35,6 +38,8 @@ */ +'use strict'; + angular.module('kibana.histogram', []) .controller('histogram', function($scope, eventBus, query, dashboard, filterSrv) { @@ -63,8 +68,8 @@ angular.module('kibana.histogram', []) 'y-axis' : true, percentage : false, interactive : true, - } - _.defaults($scope.panel,_d) + }; + _.defaults($scope.panel,_d); $scope.init = function() { @@ -72,49 +77,51 @@ angular.module('kibana.histogram', []) $scope.$on('refresh',function(){ $scope.get_data(); - }) + }); - $scope.get_data() + $scope.get_data(); - } + }; $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 - if(dashboard.indices.length == 0) { - return + if(dashboard.indices.length === 0) { + return; } var _range = $scope.range = filterSrv.timeRange('min'); - if ($scope.panel.auto_int) - $scope.panel.interval = secondsToHms(calculate_interval(_range.from,_range.to,$scope.panel.resolution,0)/1000); - + if ($scope.panel.auto_int) { + $scope.panel.interval = kbn.secondsToHms( + kbn.calculate_interval(_range.from,_range.to,$scope.panel.resolution,0)/1000); + } + $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]); // Build the query _.each($scope.queries.ids, function(id) { var query = $scope.ejs.FilteredQuery( - ejs.QueryStringQuery($scope.queries.list[id].query || '*'), + $scope.ejs.QueryStringQuery($scope.queries.list[id].query || '*'), filterSrv.getBoolFilter(filterSrv.ids) - ) + ); - var facet = $scope.ejs.DateHistogramFacet(id) + var facet = $scope.ejs.DateHistogramFacet(id); if($scope.panel.mode === 'count') { - facet = facet.field($scope.panel.time_field) + facet = facet.field($scope.panel.time_field); } else { if(_.isNull($scope.panel.value_field)) { $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)) - request = request.facet(facet).size(0) + facet = facet.interval($scope.panel.interval).facetFilter($scope.ejs.QueryFilter(query)); + request = request.facet(facet).size(0); }); // Populate the inspector panel @@ -127,7 +134,7 @@ angular.module('kibana.histogram', []) results.then(function(results) { $scope.panel.loading = false; - if(_segment == 0) { + if(_segment === 0) { $scope.hits = 0; $scope.data = []; query_id = $scope.query_id = new Date().getTime(); @@ -140,37 +147,39 @@ angular.module('kibana.histogram', []) } // 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 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 data, hits; + _.each(query.ids, function(id) { var v = results.facets[id]; // Null values at each end of the time range ensure we see entire range - if(_.isUndefined($scope.data[i]) || _segment == 0) { - var data = [] + if(_.isUndefined($scope.data[i]) || _segment === 0) { + data = []; if(filterSrv.idsByType('time').length > 0) { data = [[_range.from.getTime(), null],[_range.to.getTime(), null]]; } - var hits = 0; + hits = 0; } else { - var data = $scope.data[i].data - var hits = $scope.data[i].hits + data = $scope.data[i].data; + hits = $scope.data[i].hits; } // Assemble segments var segment_data = []; _.each(v.entries, function(v, k) { - segment_data.push([v['time'],v[$scope.panel.mode]]) - hits += v['count']; // The series level hits counter - $scope.hits += v['count']; // Entire dataset level hits counter + segment_data.push([v.time,v[$scope.panel.mode]]); + hits += v.count; // The series 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 var series = { @@ -181,22 +190,22 @@ angular.module('kibana.histogram', []) }, }; - $scope.data[i] = series.data + $scope.data[i] = series.data; i++; }); // Tell the histogram directive to render. - $scope.$emit('render') + $scope.$emit('render'); // If we still have segments left, get them if(_segment < dashboard.indices.length-1) { - $scope.get_data(_segment+1,query_id) + $scope.get_data(_segment+1,query_id); } } }); - } + }; // function $scope.zoom // 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 _range = filterSrv.timeRange('min'); 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 _from = (_center - (_timespan*factor)/2) + var _to = (_center + (_timespan*factor)/2); + var _from = (_center - (_timespan*factor)/2); // If we're not already looking into the future, don't. if(_to > Date.now() && _range.to < Date.now()) { - var _offset = _to - Date.now() - _from = _from - _offset + var _offset = _to - Date.now(); + _from = _from - _offset; _to = Date.now(); } if(factor > 1) { - filterSrv.removeByType('time') + filterSrv.removeByType('time'); } filterSrv.set({ type:'time', from:moment.utc(_from), to:moment.utc(_to), field:$scope.panel.time_field - }) + }); dashboard.refresh(); - } + }; // I really don't like this function, too much dom manip. Break out into directive? $scope.populate_modal = function(request) { @@ -238,19 +247,20 @@ angular.module('kibana.histogram', []) 'curl -XGET '+config.elasticsearch+'/'+dashboard.indices+"/_search?pretty -d'\n"+ angular.toJson(JSON.parse(request.toString()),true)+ "'", - } - } + }; + }; $scope.set_refresh = function (state) { $scope.refresh = state; - } + }; $scope.close_edit = function() { - if($scope.refresh) + if($scope.refresh) { $scope.get_data(); + } $scope.refresh = false; $scope.$emit('render'); - } + }; }) .directive('histogramChart', function(dashboard, eventBus, filterSrv, $rootScope) { @@ -274,19 +284,19 @@ angular.module('kibana.histogram', []) // Populate from the query service try { _.each(scope.data,function(series) { - series.label = series.info.alias, - series.color = series.info.color - }) - } catch(e) {return} + series.label = series.info.alias; + series.color = series.info.color; + }); + } catch(e) {return;} // 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() .script("common/lib/panels/jquery.flot.time.js") .script("common/lib/panels/jquery.flot.stack.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. scripts.wait(function(){ @@ -331,33 +341,38 @@ angular.module('kibana.histogram', []) hoverable: true, }, colors: ['#86B22D','#BF6730','#1D7373','#BFB930','#BF3030','#77207D'] + }; + + if(scope.panel.interactive) { + options.selection = { mode: "x", color: '#aaa' }; } - if(scope.panel.interactive) - options.selection = { mode: "x", color: '#aaa' }; - - scope.plot = $.plot(elem, scope.data, options) + scope.plot = $.plot(elem, scope.data, options); - // Work around for missing legend at initialization - if(!scope.$$phase) - scope.$apply() + // Work around for missing legend at initialization. + if(!scope.$$phase) { + scope.$apply(); + } } catch(e) { - elem.text(e) + elem.text(e); } - }) + }); } function time_format(interval) { - var _int = interval_to_seconds(interval) - if(_int >= 2628000) - return "%m/%y" - if(_int >= 86400) - return "%m/%d/%y" - if(_int >= 60) - return "%H:%M
%m/%d" - else - return "%H:%M:%S" + var _int = kbn.interval_to_seconds(interval); + if(_int >= 2628000) { + return "%m/%y"; + } + if(_int >= 86400) { + return "%m/%d/%y"; + } + if(_int >= 60) { + return "%H:%M
%m/%d"; + } + + return "%H:%M:%S"; } function tt(x, y, contents) { @@ -396,9 +411,9 @@ angular.module('kibana.histogram', []) from : moment.utc(ranges.xaxis.from), to : moment.utc(ranges.xaxis.to), field : scope.panel.time_field - }) + }); dashboard.refresh(); }); } }; -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/panels/hits/module.js b/panels/hits/module.js index e38f66223aa..3a0e03fe974 100644 --- a/panels/hits/module.js +++ b/panels/hits/module.js @@ -1,3 +1,6 @@ +/*jshint globalstrict:true */ +/*global angular:true */ + /* ## Hits @@ -15,6 +18,9 @@ * lables :: Only 'pie' charts. Labels on the pie? */ + +'use strict'; + angular.module('kibana.hits', []) .controller('hits', function($scope, query, dashboard, filterSrv) { @@ -30,41 +36,41 @@ angular.module('kibana.hits', []) donut : false, tilt : false, labels : true - } - _.defaults($scope.panel,_d) + }; + _.defaults($scope.panel,_d); $scope.init = function () { $scope.hits = 0; $scope.$on('refresh',function(){ $scope.get_data(); - }) + }); $scope.get_data(); - } + }; $scope.get_data = function(segment,query_id) { - delete $scope.panel.error + delete $scope.panel.error; $scope.panel.loading = true; // Make sure we have everything for the request to complete - if(dashboard.indices.length == 0) { - return + if(dashboard.indices.length === 0) { + return; } - var _segment = _.isUndefined(segment) ? 0 : segment + var _segment = _.isUndefined(segment) ? 0 : segment; var request = $scope.ejs.Request().indices(dashboard.indices[_segment]); // Build the question part of the query _.each(query.ids, function(id) { var _q = $scope.ejs.FilteredQuery( - ejs.QueryStringQuery(query.list[id].query || '*'), + $scope.ejs.QueryStringQuery(query.list[id].query || '*'), filterSrv.getBoolFilter(filterSrv.ids)); request = request .facet($scope.ejs.QueryFacet(id) .query(_q) - ).size(0) + ).size(0); }); // TODO: Spy for hits panel @@ -76,7 +82,7 @@ angular.module('kibana.hits', []) // Populate scope when we have results results.then(function(results) { $scope.panel.loading = false; - if(_segment == 0) { + if(_segment === 0) { $scope.hits = 0; $scope.data = []; query_id = $scope.query_id = new Date().getTime(); @@ -89,18 +95,18 @@ angular.module('kibana.hits', []) } // 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 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; _.each(query.ids, function(id) { - var v = results.facets[id] - var hits = _.isUndefined($scope.data[i]) || _segment == 0 ? - v.count : $scope.data[i].hits+v.count - $scope.hits += v.count + var v = results.facets[id]; + var hits = _.isUndefined($scope.data[i]) || _segment === 0 ? + v.count : $scope.data[i].hits+v.count; + $scope.hits += v.count; // Create series $scope.data[i] = { @@ -113,23 +119,25 @@ angular.module('kibana.hits', []) i++; }); $scope.$emit('render'); - if(_segment < dashboard.indices.length-1) - $scope.get_data(_segment+1,query_id) + if(_segment < dashboard.indices.length-1) { + $scope.get_data(_segment+1,query_id); + } } }); - } + }; $scope.set_refresh = function (state) { $scope.refresh = state; - } + }; $scope.close_edit = function() { - if($scope.refresh) + if($scope.refresh) { $scope.get_data(); + } $scope.refresh = false; $scope.$emit('render'); - } + }; function set_time(time) { $scope.time = time; @@ -156,20 +164,20 @@ angular.module('kibana.hits', []) try { _.each(scope.data,function(series) { - series.label = series.info.alias, - series.color = series.info.color - }) - } catch(e) {return} + series.label = series.info.alias; + series.color = series.info.color; + }); + } catch(e) {return;} 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. scripts.wait(function(){ // Populate element try { // 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, { legend: { show: false }, series: { @@ -186,8 +194,9 @@ angular.module('kibana.hits', []) hoverable: true, }, colors: query.colors - }) - if(scope.panel.chart === 'pie') + }); + } + if(scope.panel.chart === 'pie') { scope.plot = $.plot(elem, scope.data, { legend: { show: false }, series: { @@ -218,19 +227,20 @@ angular.module('kibana.hits', []) grid: { hoverable: true, clickable: true }, colors: query.colors }); - + } // Compensate for the height of the legend. Gross 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 - if(!scope.$$phase) - scope.$apply() + if(!scope.$$phase) { + scope.$apply(); + } } catch(e) { - elem.text(e) + elem.text(e); } - }) + }); } function tt(x, y, contents) { @@ -256,7 +266,7 @@ angular.module('kibana.hits', []) item.datapoint[1] : item.datapoint[1][0][1]; tt(pos.pageX, pos.pageY, "
"+value.toFixed(0)) + item.series.color+";height:20px;width:20px'> "+value.toFixed(0)); } else { $("#pie-tooltip").remove(); } @@ -264,4 +274,4 @@ angular.module('kibana.hits', []) } }; -}) +}); diff --git a/panels/map/module.js b/panels/map/module.js index e38f3ee0a4e..1c7e698c21a 100644 --- a/panels/map/module.js +++ b/panels/map/module.js @@ -1,3 +1,6 @@ +/*jshint globalstrict:true */ +/*global angular:true */ + /* ## Map @@ -22,6 +25,8 @@ */ +'use strict'; + angular.module('kibana.map', []) .controller('map', function($scope, $rootScope, query, dashboard, filterSrv) { @@ -36,37 +41,39 @@ angular.module('kibana.map', []) spyable : true, group : "default", index_limit : 0 - } - _.defaults($scope.panel,_d) + }; + _.defaults($scope.panel,_d); $scope.init = function() { - $scope.$on('refresh',function(){$scope.get_data()}) + $scope.$on('refresh',function(){$scope.get_data();}); $scope.get_data(); - } + }; $scope.get_data = function() { // Make sure we have everything for the request to complete - if(dashboard.indices.length == 0) { - return + if(dashboard.indices.length === 0) { + return; } - $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) { - boolQuery = boolQuery.should(ejs.QueryStringQuery(q.query || '*')) - }) + boolQuery = boolQuery.should($scope.ejs.QueryStringQuery(q.query || '*')); + }); // Then the insert into facet and make the request - var request = request - .facet(ejs.TermsFacet('map') + request = request + .facet($scope.ejs.TermsFacet('map') .field($scope.panel.field) - .size($scope.panel['size']) + .size($scope.panel.size) .exclude($scope.panel.exclude) - .facetFilter(ejs.QueryFilter( - ejs.FilteredQuery( + .facetFilter($scope.ejs.QueryFilter( + $scope.ejs.FilteredQuery( boolQuery, filterSrv.getBoolFilter(filterSrv.ids) )))).size(0); @@ -83,9 +90,9 @@ angular.module('kibana.map', []) _.each(results.facets.map.terms, function(v) { $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? $scope.populate_modal = function(request) { @@ -95,13 +102,13 @@ angular.module('kibana.map', []) 'curl -XGET '+config.elasticsearch+'/'+dashboard.indices+"/_search?pretty -d'\n"+ angular.toJson(JSON.parse(request.toString()),true)+ "'", - } - } + }; + }; $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(); - } + }; }) .directive('map', function() { @@ -109,7 +116,7 @@ angular.module('kibana.map', []) restrict: 'A', link: function(scope, elem, attrs) { - elem.html('
') + elem.html('
'); // Receive render events scope.$on('render',function(){ @@ -124,7 +131,7 @@ angular.module('kibana.map', []) function render_panel() { // Using LABjs, wait until all scripts are loaded before rendering panel 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. scripts.wait(function(){ @@ -143,7 +150,7 @@ angular.module('kibana.map', []) }] }, 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]; elem.children('.map-legend').text(label.text() + ": " + count); }, @@ -152,13 +159,14 @@ angular.module('kibana.map', []) }, onRegionClick: function(event, code) { var count = _.isUndefined(scope.data[code]) ? 0 : scope.data[code]; - if (count != 0) - scope.build_search(scope.panel.field,code) + if (count !== 0) { + scope.build_search(scope.panel.field,code); + } } }); elem.prepend(''); $('.map-legend').hide(); - }) + }); } } }; diff --git a/panels/pie/module.js b/panels/pie/module.js index bd5bdf19b84..3e0c8740386 100644 --- a/panels/pie/module.js +++ b/panels/pie/module.js @@ -1,3 +1,5 @@ +/*jshint globalstrict:true */ +/*global angular:true */ /* ## Pie @@ -22,9 +24,10 @@ * default_field :: LOL wat? A dumb fail over field if for some reason the query object doesn't have a field * spyable :: Show the 'eye' icon that displays the last ES query for this panel - */ +'use strict'; + angular.module('kibana.pie', []) .controller('pie', function($scope, $rootScope, query, dashboard, filterSrv) { @@ -42,13 +45,13 @@ angular.module('kibana.pie', []) group : "default", default_field : 'DEFAULT', spyable : true, - } - _.defaults($scope.panel,_d) + }; + _.defaults($scope.panel,_d); $scope.init = function() { - $scope.$on('refresh',function(){$scope.get_data()}) + $scope.$on('refresh',function(){$scope.get_data();}); $scope.get_data(); - } + }; $scope.set_mode = function(mode) { switch(mode) @@ -60,51 +63,54 @@ angular.module('kibana.pie', []) $scope.panel.query = {goal:100}; break; } - } + }; $scope.set_refresh = function (state) { $scope.refresh = state; - } + }; $scope.close_edit = function() { - if($scope.refresh) + if($scope.refresh) { $scope.get_data(); + } $scope.refresh = false; $scope.$emit('render'); - } + }; $scope.get_data = function() { // Make sure we have everything for the request to complete - if(dashboard.indices.length == 0) { - return + if(dashboard.indices.length === 0) { + return; } $scope.panel.loading = true; var request = $scope.ejs.Request().indices(dashboard.indices); // This could probably be changed to a BoolFilter - var boolQuery = ejs.BoolQuery(); + var boolQuery = $scope.ejs.BoolQuery(); _.each(query.list,function(q) { - boolQuery = boolQuery.should(ejs.QueryStringQuery(q.query || '*')) - }) + boolQuery = boolQuery.should($scope.ejs.QueryStringQuery(q.query || '*')); + }); + + var results; // Terms mode - if ($scope.panel.mode == "terms") { + if ($scope.panel.mode === "terms") { request = request - .facet(ejs.TermsFacet('pie') + .facet($scope.ejs.TermsFacet('pie') .field($scope.panel.query.field || $scope.panel.default_field) - .size($scope.panel['size']) + .size($scope.panel.size) .exclude($scope.panel.exclude) - .facetFilter(ejs.QueryFilter( - ejs.FilteredQuery( + .facetFilter($scope.ejs.QueryFilter( + $scope.ejs.FilteredQuery( boolQuery, filterSrv.getBoolFilter(filterSrv.ids) - )))).size(0) + )))).size(0); $scope.populate_modal(request); - var results = request.doSearch(); + results = request.doSearch(); // Populate scope when we have results results.then(function(results) { @@ -115,12 +121,7 @@ angular.module('kibana.pie', []) _.each(results.facets.pie.terms, function(v) { var slice = { label : v.term, data : v.count }; $scope.data.push(); - if(!(_.isUndefined($scope.panel.colors)) - && _.isArray($scope.panel.colors) - && $scope.panel.colors.length > 0) { - slice.color = $scope.panel.colors[k%$scope.panel.colors.length]; - } - $scope.data.push(slice) + $scope.data.push(slice); k = k + 1; }); $scope.$emit('render'); @@ -130,11 +131,11 @@ angular.module('kibana.pie', []) request = request .query(boolQuery) .filter(filterSrv.getBoolFilter(filterSrv.ids)) - .size(0) + .size(0); $scope.populate_modal(request); - var results = request.doSearch(); + results = request.doSearch(); results.then(function(results) { $scope.panel.loading = false; @@ -142,11 +143,12 @@ angular.module('kibana.pie', []) var remaining = $scope.panel.query.goal - complete; $scope.data = [ { label : 'Complete', data : complete, color: '#BF6730' }, - { data : remaining, color: '#e2d0c4'}] + { data : remaining, color: '#e2d0c4' } + ]; $scope.$emit('render'); }); } - } + }; // I really don't like this function, too much dom manip. Break out into directive? $scope.populate_modal = function(request) { @@ -156,8 +158,8 @@ angular.module('kibana.pie', []) 'curl -XGET '+config.elasticsearch+'/'+dashboard.indices+"/_search?pretty -d'\n"+ angular.toJson(JSON.parse(request.toString()),true)+ "'", - } - } + }; + }; }) .directive('pie', function(query, filterSrv, dashboard) { @@ -165,7 +167,7 @@ angular.module('kibana.pie', []) restrict: 'A', link: function(scope, elem, attrs) { - elem.html('
') + elem.html('
'); // Receive render events scope.$on('render',function(){ @@ -180,23 +182,25 @@ angular.module('kibana.pie', []) // Function for rendering panel function render_panel() { var scripts = $LAB.script("common/lib/panels/jquery.flot.js").wait() - .script("common/lib/panels/jquery.flot.pie.js") - - if(scope.panel.mode === 'goal') - var label = { + .script("common/lib/panels/jquery.flot.pie.js"); + + var label; + if(scope.panel.mode === 'goal') { + label = { show: scope.panel.labels, radius: 0, formatter: function(label, series){ - var font = parseInt(scope.row.height.replace('px',''))/8 + String('px') - if(!(_.isUndefined(label))) + var font = parseInt(scope.row.height.replace('px',''),10)/8 + String('px'); + if(!(_.isUndefined(label))) { return '
'+ Math.round(series.percent)+'%
'; - else - return '' + } else { + return ''; + } }, - } - else - var label = { + }; + } else { + label = { show: scope.panel.labels, radius: 2/3, formatter: function(label, series){ @@ -204,7 +208,8 @@ angular.module('kibana.pie', []) label+'
'+Math.round(series.percent)+'%'; }, threshold: 0.1 - } + }; + } var pie = { series: { @@ -263,7 +268,7 @@ angular.module('kibana.pie', []) return; } 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(); } }); @@ -280,4 +285,4 @@ angular.module('kibana.pie', []) } }; -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/panels/query/module.js b/panels/query/module.js index eee355b1def..be536d49ae5 100644 --- a/panels/query/module.js +++ b/panels/query/module.js @@ -1,3 +1,5 @@ +/*jshint globalstrict:true */ +/*global angular:true */ /* ## query @@ -11,6 +13,8 @@ one element */ +'use strict'; + angular.module('kibana.query', []) .controller('query', function($scope, query, $rootScope) { @@ -22,39 +26,39 @@ angular.module('kibana.query', []) group : "default", history : [], remember: 10 // max: 100, angular strap can't take a variable for items param - } + }; _.defaults($scope.panel,_d); $scope.queries = query; $scope.init = function() { - } + }; $scope.refresh = function(query) { - $rootScope.$broadcast('refresh') - } + $rootScope.$broadcast('refresh'); + }; $scope.render = function(query) { - $rootScope.$broadcast('render') - } + $rootScope.$broadcast('render'); + }; $scope.add_query = function() { - if (_.isArray($scope.panel.query)) - $scope.panel.query.push("") - else { - $scope.panel.query = new Array($scope.panel.query) - $scope.panel.query.push("") + if (_.isArray($scope.panel.query)) { + $scope.panel.query.push(""); + } else { + $scope.panel.query = new Array($scope.panel.query); + $scope.panel.query.push(""); } - } + }; var update_history = function(query) { if($scope.panel.remember > 0) { - $scope.panel.history = _.union(query.reverse(),$scope.panel.history) - var _length = $scope.panel.history.length + $scope.panel.history = _.union(query.reverse(),$scope.panel.history); + var _length = $scope.panel.history.length; if(_length > $scope.panel.remember) { - $scope.panel.history = $scope.panel.history.slice(0,$scope.panel.remember) + $scope.panel.history = $scope.panel.history.slice(0,$scope.panel.remember); } } - } + }; }); \ No newline at end of file diff --git a/panels/table/module.js b/panels/table/module.js index bc27b906dd7..7878f913a82 100644 --- a/panels/table/module.js +++ b/panels/table/module.js @@ -1,3 +1,5 @@ +/*jshint globalstrict:true */ +/*global angular:true */ /* ## Table @@ -22,12 +24,11 @@ * table_documents :: An array containing all of the documents in the table. Only used by the fields panel so far. #### 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 */ +'use strict'; + angular.module('kibana.table', []) .controller('table', function($rootScope, $scope, eventBus, fields, query, dashboard, filterSrv) { @@ -48,104 +49,107 @@ angular.module('kibana.table', []) header : true, paging : true, spyable: true - } - _.defaults($scope.panel,_d) + }; + _.defaults($scope.panel,_d); $scope.init = function () { - $scope.set_listeners($scope.panel.group) + $scope.set_listeners($scope.panel.group); $scope.get_data(); - } + }; $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){ $scope.panel.sort = _.clone(sort); $scope.get_data(); }); 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) { - query.list[query.ids[0]].query = docs.query; - $scope.data = docs.docs; + query.list[query.ids[0]].query = docs.query; + $scope.data = docs.docs; }); - } + }; $scope.set_sort = function(field) { - if($scope.panel.sort[0] === field) - $scope.panel.sort[1] = $scope.panel.sort[1] == 'asc' ? 'desc' : 'asc'; - else + if($scope.panel.sort[0] === field) { + $scope.panel.sort[1] = $scope.panel.sort[1] === 'asc' ? 'desc' : 'asc'; + } else { $scope.panel.sort[0] = field; + } $scope.get_data(); - } + }; $scope.toggle_field = function(field) { - if (_.indexOf($scope.panel.fields,field) > -1) - $scope.panel.fields = _.without($scope.panel.fields,field) - else - $scope.panel.fields.push(field) + if (_.indexOf($scope.panel.fields,field) > -1) { + $scope.panel.fields = _.without($scope.panel.fields,field); + } else { + $scope.panel.fields.push(field); + } broadcast_results(); - } + }; $scope.toggle_highlight = function(field) { - if (_.indexOf($scope.panel.highlight,field) > -1) - $scope.panel.highlight = _.without($scope.panel.highlight,field) - else - $scope.panel.highlight.push(field) - } + if (_.indexOf($scope.panel.highlight,field) > -1) { + $scope.panel.highlight = _.without($scope.panel.highlight,field); + } else { + $scope.panel.highlight.push(field); + } + }; $scope.toggle_details = function(row) { row.kibana = row.kibana || {}; row.kibana.details = !row.kibana.details ? $scope.without_kibana(row) : false; - } + }; $scope.page = function(page) { - $scope.panel.offset = page*$scope.panel.size + $scope.panel.offset = page*$scope.panel.size; $scope.get_data(); - } + }; $scope.build_search = function(field,value,negate) { - var query; + var query = field+":"; // This needs to be abstracted somewhere 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 { - 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; dashboard.refresh(); - } + }; $scope.get_data = function(segment,query_id) { $scope.panel.error = false; // Make sure we have everything for the request to complete - if(dashboard.indices.length == 0) { - return + if(dashboard.indices.length === 0) { + return; } $scope.panel.loading = true; - var _segment = _.isUndefined(segment) ? 0 : segment + var _segment = _.isUndefined(segment) ? 0 : 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) { - boolQuery = boolQuery.should(ejs.QueryStringQuery(q.query || '*')) - }) + boolQuery = boolQuery.should($scope.ejs.QueryStringQuery(q.query || '*')); + }); request = request.query( - ejs.FilteredQuery( + $scope.ejs.FilteredQuery( boolQuery, filterSrv.getBoolFilter(filterSrv.ids) )) .highlight( - ejs.Highlight($scope.panel.highlight) + $scope.ejs.Highlight($scope.panel.highlight) .fragmentSize(2147483647) // Max size of a 32bit unsigned int .preTags('@start-highlight@') .postTags('@end-highlight@') @@ -153,9 +157,9 @@ angular.module('kibana.table', []) .size($scope.panel.size*$scope.panel.pages) .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 results.then(function(results) { @@ -164,7 +168,7 @@ angular.module('kibana.table', []) if(_segment === 0) { $scope.hits = 0; $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 @@ -177,46 +181,46 @@ angular.module('kibana.table', []) if($scope.query_id === query_id) { $scope.data= $scope.data.concat(_.map(results.hits.hits, function(hit) { return { - _source : flatten_json(hit['_source']), - highlight : flatten_json(hit['highlight']||{}) - } + _source : kbn.flatten_json(hit._source), + highlight : kbn.flatten_json(hit.highlight||{}) + }; })); $scope.hits += results.hits.total; // Sort the data $scope.data = _.sortBy($scope.data, function(v){ - return v._source[$scope.panel.sort[0]] + return v._source[$scope.panel.sort[0]]; }); // Reverse if needed - if($scope.panel.sort[1] == 'desc') + if($scope.panel.sort[1] === 'desc') { $scope.data.reverse(); - + } + // 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 { return; } // 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(); // If we're not sorting in reverse chrono order, query every index for // size*pages results // 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.panel.sort[0] === $scope.time.field) && $scope.panel.sort[1] === 'desc')) - && _segment+1 < dashboard.indices.length - ) { - $scope.get_data(_segment+1,$scope.query_id) + //($scope.data.length < $scope.panel.size*$scope.panel.pages + // || !(($scope.panel.sort[0] === $scope.time.field) && $scope.panel.sort[1] === 'desc')) + if($scope.data.length < $scope.panel.size*$scope.panel.pages && + _segment+1 < dashboard.indices.length ) { + $scope.get_data(_segment+1,$scope.query_id); } }); - } + }; $scope.populate_modal = function(request) { $scope.modal = { @@ -225,15 +229,15 @@ angular.module('kibana.table', []) 'curl -XGET '+config.elasticsearch+'/'+dashboard.indices+"/_search?pretty -d'\n"+ angular.toJson(JSON.parse(request.toString()),true)+ "'", - } - } + }; + }; $scope.without_kibana = function (row) { return { _source : row._source, highlight : row.highlight - } - } + }; + }; // Broadcast a list of all fields. Note that receivers of field array // 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.refresh = state; - } + }; $scope.close_edit = function() { - if($scope.refresh) + if($scope.refresh) { $scope.get_data(); + } $scope.refresh = false; - } + }; }) @@ -273,8 +278,8 @@ angular.module('kibana.table', []) replace(/>/g, '>'). replace(/\r?\n/g, '
'). replace(/@start-highlight@/g, ''). - replace(/@end-highlight@/g, '') + replace(/@end-highlight@/g, ''); } return ''; - } + }; }); diff --git a/panels/text/module.js b/panels/text/module.js index 3cc09deb532..fb0beb70876 100644 --- a/panels/text/module.js +++ b/panels/text/module.js @@ -1,3 +1,6 @@ +/*jshint globalstrict:true */ +/*global angular:true */ +/*global Showdown:false */ /* ## Text @@ -11,6 +14,8 @@ */ +'use strict'; + angular.module('kibana.text', []) .controller('text', function($scope, $rootScope) { @@ -21,12 +26,12 @@ angular.module('kibana.text', []) mode : "markdown", content : "", style: {}, - } + }; _.defaults($scope.panel,_d); $scope.init = function() { $scope.ready = false; - } + }; }).directive('markdown', function() { return { @@ -34,10 +39,10 @@ angular.module('kibana.text', []) link: function(scope, element, attrs) { scope.$on('render', 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(){ scope.ready = true; var converter = new Showdown.converter(); @@ -48,18 +53,18 @@ angular.module('kibana.text', []) element.html(htmlText); // For whatever reason, this fixes chrome. I don't like it, I think // it makes things slow? - scope.$apply() + scope.$apply(); }); } render_panel(); } - } + }; }) .filter('newlines', function(){ return function (input) { return input.replace(/\n/g, '
'); - } + }; }) .filter('striphtml', function () { return function(text) { @@ -67,5 +72,5 @@ angular.module('kibana.text', []) .replace(/&/g, '&') .replace(/>/g, '>') .replace(/ 0) { - var time = filterSrv.timeRange('min') + var time = filterSrv.timeRange('min'); - if($scope.time.from.diff(moment.utc(time.from),'seconds') !== 0 - || $scope.time.to.diff(moment.utc(time.to),'seconds') !== 0) + if($scope.time.from.diff(moment.utc(time.from),'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.to+" and "+moment.utc(time.to)) + console.log($scope.time.from+ " and "+ moment.utc(time.from)); + console.log($scope.time.to+" and "+moment.utc(time.to)); $scope.set_mode('absolute'); // 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(); - update_panel() + update_panel(); } } }); - } + }; $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($scope.panel.refresh.interval < $scope.panel.refresh.min) { - $scope.panel.refresh.interval = $scope.panel.refresh.min - timer.cancel($scope.refresh_timer) + $scope.panel.refresh.interval = $scope.panel.refresh.min; + timer.cancel($scope.refresh_timer); return; } - timer.cancel($scope.refresh_timer) - $scope.refresh() + timer.cancel($scope.refresh_timer); + $scope.refresh(); } else { - timer.cancel($scope.refresh_timer) + timer.cancel($scope.refresh_timer); } - } + }; $scope.refresh = function() { if ($scope.panel.refresh.enable) { - timer.cancel($scope.refresh_timer) + timer.cancel($scope.refresh_timer); $scope.refresh_timer = timer.register($timeout(function() { $scope.refresh(); $scope.time_apply(); - },$scope.panel.refresh.interval*1000 - )); + },$scope.panel.refresh.interval*1000)); } else { - timer.cancel($scope.refresh_timer) + timer.cancel($scope.refresh_timer); } - } + }; var update_panel = function() { // Update panel's string representation of the time object.Don't update if @@ -141,92 +145,94 @@ angular.module('kibana.timepicker', []) } else { delete $scope.panel.time; } - } + }; $scope.set_mode = function(mode) { $scope.panel.mode = mode; $scope.panel.refresh.enable = mode === 'absolute' ? - false : $scope.panel.refresh.enable + false : $scope.panel.refresh.enable; update_panel(); - } + }; $scope.to_now = function() { $scope.timepicker.to = { time : moment().format("HH:mm:ss"), date : moment().format("MM/DD/YYYY") - } - } + }; + }; $scope.set_timespan = function(timespan) { $scope.panel.timespan = timespan; $scope.timepicker.from = { - time : moment(time_ago(timespan)).format("HH:mm:ss"), - date : moment(time_ago(timespan)).format("MM/DD/YYYY") - } + time : moment(kbn.time_ago(timespan)).format("HH:mm:ss"), + date : moment(kbn.time_ago(timespan)).format("MM/DD/YYYY") + }; $scope.time_apply(); - } + }; $scope.close_edit = function() { $scope.time_apply(); - } + }; // $scope.time_calc = function(){ + var from,to; // If time picker is defined (usually is) if(!(_.isUndefined($scope.timepicker))) { - var from = $scope.panel.mode === 'relative' ? moment(time_ago($scope.panel.timespan)) : - moment($scope.timepicker.from.date + " " + $scope.timepicker.from.time,'MM/DD/YYYY HH:mm:ss') - var to = $scope.panel.mode !== 'absolute' ? moment() : - moment($scope.timepicker.to.date + " " + $scope.timepicker.to.time,'MM/DD/YYYY HH:mm:ss') + 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'); + to = $scope.panel.mode !== 'absolute' ? moment() : + moment($scope.timepicker.to.date + " " + $scope.timepicker.to.time,'MM/DD/YYYY HH:mm:ss'); // Otherwise (probably initialization) } 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; - var to = $scope.panel.mode !== 'absolute' ? moment() : + to = $scope.panel.mode !== 'absolute' ? moment() : $scope.time.to; } - if (from.valueOf() >= to.valueOf()) - from = moment(to.valueOf() - 1000) + if (from.valueOf() >= to.valueOf()) { + from = moment(to.valueOf() - 1000); + } $timeout(function(){ - set_timepicker(from,to) + set_timepicker(from,to); }); return { from : from, to : to }; - } + }; $scope.time_apply = function() { $scope.panel.error = ""; // Update internal time object // Remove all other time filters - filterSrv.removeByType('time') + filterSrv.removeByType('time'); $scope.time = $scope.time_calc(); - $scope.time.field = $scope.panel.timefield - update_panel() + $scope.time.field = $scope.panel.timefield; + update_panel(); - set_time_filter($scope.time) + set_time_filter($scope.time); dashboard.refresh(); }; 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 if(!_.isUndefined($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 { - $scope.panel.filter_id = filterSrv.set(compile_time(time)) + $scope.panel.filter_id = filterSrv.set(compile_time(time)); } return $scope.panel.filter_id; } @@ -234,9 +240,9 @@ angular.module('kibana.timepicker', []) // Prefer to pass around Date() objects since interacting with // moment objects in libraries that are expecting Date()s can be tricky function compile_time(time) { - time = _.clone(time) - time.from = time.from.toDate() - time.to = time.to.toDate() + time = _.clone(time); + time.from = time.from.toDate(); + time.to = time.to.toDate(); return time; } @@ -251,7 +257,7 @@ angular.module('kibana.timepicker', []) time : to.format("HH:mm:ss"), date : to.format("MM/DD/YYYY") } - } + }; } -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/panels/trends/module.js b/panels/trends/module.js index 4b2ec418b81..65a9fa42eef 100644 --- a/panels/trends/module.js +++ b/panels/trends/module.js @@ -18,6 +18,9 @@ * query :: An Array of queries, even if its only one */ + +'use strict'; + angular.module('kibana.trends', []) .controller('trends', function($scope, kbnIndex, query, dashboard, filterSrv) { @@ -29,87 +32,87 @@ angular.module('kibana.trends', []) style : { "font-size": '14pt'}, ago : '1d', arrangement : 'vertical', - } - _.defaults($scope.panel,_d) + }; + _.defaults($scope.panel,_d); $scope.init = function () { $scope.hits = 0; - $scope.$on('refresh',function(){$scope.get_data()}) + $scope.$on('refresh',function(){$scope.get_data();}); $scope.get_data(); - } + }; $scope.get_data = function(segment,query_id) { - delete $scope.panel.error + delete $scope.panel.error; $scope.panel.loading = true; // Make sure we have everything for the request to complete - if(dashboard.indices.length == 0) { - return + if(dashboard.indices.length === 0) { + return; } else { $scope.index = segment > 0 ? $scope.index : dashboard.indices; } // Determine a time field - var timeField = _.uniq(_.pluck(filterSrv.getByType('time'),'field')) + var timeField = _.uniq(_.pluck(filterSrv.getByType('time'),'field')); if(timeField.length > 1) { - $scope.panel.error = "Time field must be consistent amongst time filters" - return - } else if(timeField.length == 0) { - $scope.panel.error = "A time filter must exist for this panel to function" - return + $scope.panel.error = "Time field must be consistent amongst time filters"; + return; + } else if(timeField.length === 0) { + $scope.panel.error = "A time filter must exist for this panel to function"; + return; } else { - timeField = timeField[0] + timeField = timeField[0]; } $scope.time = filterSrv.timeRange('min'); $scope.old_time = { - from : new Date($scope.time.from.getTime() - interval_to_seconds($scope.panel.ago)*1000), - to : new Date($scope.time.to.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() - 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 _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 _.each(query.ids, function(id) { var q = $scope.ejs.FilteredQuery( - ejs.QueryStringQuery(query.list[id].query || '*'), + $scope.ejs.QueryStringQuery(query.list[id].query || '*'), filterSrv.getBoolFilter(_ids_without_time).must( - ejs.RangeFilter(timeField) + $scope.ejs.RangeFilter(timeField) .from($scope.time.from) .to($scope.time.to) - )) + )); request = request .facet($scope.ejs.QueryFacet(id) .query(q) - ).size(0) + ).size(0); }); // And again for the old time period _.each(query.ids, function(id) { var q = $scope.ejs.FilteredQuery( - ejs.QueryStringQuery(query.list[id].query || '*'), + $scope.ejs.QueryStringQuery(query.list[id].query || '*'), filterSrv.getBoolFilter(_ids_without_time).must( - ejs.RangeFilter(timeField) + $scope.ejs.RangeFilter(timeField) .from($scope.old_time.from) .to($scope.old_time.to) - )) + )); request = request .facet($scope.ejs.QueryFacet("old_"+id) .query(q) - ).size(0) + ).size(0); }); // TODO: Spy for trend panel //$scope.populate_modal(request); // If we're on the first segment we need to get our indices - if (_segment == 0) { + if (_segment === 0) { kbnIndex.indices( $scope.old_time.from, $scope.old_time.to, @@ -117,90 +120,92 @@ angular.module('kibana.trends', []) dashboard.current.index.interval ).then(function (p) { $scope.index = _.union(p,$scope.index); - request = request.indices($scope.index[_segment]) + request = request.indices($scope.index[_segment]); process_results(request.doSearch()); }); } 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 - function process_results(results) { - results.then(function(results) { + }; - $scope.panel.loading = false; - if(_segment == 0) { - $scope.hits = {}; - $scope.data = []; - query_id = $scope.query_id = new Date().getTime(); + // Populate scope when we have results + var process_results = function(results,_segment,query_id) { + results.then(function(results) { + + $scope.panel.loading = false; + if(_segment === 0) { + $scope.hits = {}; + $scope.data = []; + query_id = $scope.query_id = new Date().getTime(); + } + + // Check for error and abort if found + if(!(_.isUndefined(results.error))) { + $scope.panel.error = $scope.parse_error(results.error); + return; + } + + // Convert facet ids to numbers + 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 + if($scope.query_id === query_id && + _.intersection(facetIds,query.ids).length === query.ids.length + ) { + var i = 0; + _.each(query.ids, function(id) { + var v = results.facets[id]; + var n = results.facets[id].count; + var o = results.facets['old_'+id].count; + + var hits = { + 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 + }; + + $scope.hits.new += n; + $scope.hits.old += o; + + var percent = percentage(hits.old,hits.new) == null ? + '?' : Math.round(percentage(hits.old,hits.new)*100)/100; + // Create series + $scope.data[i] = { + info: query.list[id], + hits: { + new : hits.new, + old : hits.old + }, + percent: percent + }; + + i++; + }); + $scope.$emit('render'); + if(_segment < $scope.index.length-1) { + $scope.get_data(_segment+1,query_id); + } else { + $scope.trends = $scope.data; } - - // Check for error and abort if found - if(!(_.isUndefined(results.error))) { - $scope.panel.error = $scope.parse_error(results.error); - return; - } - - // Convert facet ids to numbers - var facetIds = _.map(_.keys(results.facets),function(k){if(!isNaN(k)){return parseInt(k)}}) - - // Make sure we're still on the same query/queries - if($scope.query_id === query_id && - _.intersection(facetIds,query.ids).length == query.ids.length - ) { - var i = 0; - _.each(query.ids, function(id) { - var v = results.facets[id] - var n = results.facets[id].count - var o = results.facets['old_'+id].count - - var hits = { - 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 - } - - $scope.hits.new += n; - $scope.hits.old += o; - - var percent = percentage(hits.old,hits.new) == null ? - '?' : Math.round(percentage(hits.old,hits.new)*100)/100 - // Create series - $scope.data[i] = { - info: query.list[id], - hits: { - new : hits.new, - old : hits.old - }, - percent: percent - }; - - i++; - }); - $scope.$emit('render'); - if(_segment < $scope.index.length-1) - $scope.get_data(_segment+1,query_id) - else - $scope.trends = $scope.data - } - }); - } - - } + } + }); + }; 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.refresh = state; - } + }; $scope.close_edit = function() { - if($scope.refresh) + if($scope.refresh) { $scope.get_data(); + } $scope.refresh = false; $scope.$emit('render'); - } + }; -}) \ No newline at end of file +}); \ No newline at end of file