![JAR search and dependency download from the Maven repository](/logo.png)
app.panels.map.module.js Maven / Gradle / Ivy
The newest version!
/** @scratch /panels/5
*
* include::panels/map.asciidoc[]
*/
/** @scratch /panels/map/0
*
* == Map
* Status: *Stable*
*
* The map panel translates 2 letter country or state codes into shaded regions on a map. Currently
* available maps are world, usa and europe.
*
*/
define([
'angular',
'app',
'lodash',
'jquery',
'config',
'./lib/jquery.jvectormap.min'
],
function (angular, app, _, $) {
'use strict';
var module = angular.module('kibana.panels.map', []);
app.useModule(module);
module.controller('map', function($scope, $rootScope, querySrv, dashboard, filterSrv) {
$scope.panelMeta = {
editorTabs : [
{title:'Queries', src:'app/partials/querySelect.html'}
],
modals : [
{
description: "Inspect",
icon: "icon-info-sign",
partial: "app/partials/inspector.html",
show: $scope.panel.spyable
}
],
status : "Stable",
description : "Displays a map of shaded regions using a field containing a 2 letter country "+
", or US state, code. Regions with more hit are shaded darker. Node that this does use the"+
" Elasticsearch terms facet, so it is important that you set it to the correct field."
};
// Set and populate defaults
var _d = {
/** @scratch /panels/map/3
*
* === Parameters
*
* map:: Map to display. world, usa, europe
*/
map : "world",
/** @scratch /panels/map/3
* colors:: An array of colors to use to shade the map. If 2 colors are specified, shades
* between them will be used. For example [`#A0E2E2', `#265656']
*/
colors : ['#A0E2E2', '#265656'],
/** @scratch /panels/map/3
* size:: Max number of regions to shade
*/
size : 100,
/** @scratch /panels/map/3
* exclude:: exclude this array of regions. For example [`US',`BR',`IN']
*/
exclude : [],
/** @scratch /panels/map/3
* spyable:: Setting spyable to false disables the inspect icon.
*/
spyable : true,
/** @scratch /panels/map/5
*
* ==== Queries
* queries object:: This object describes the queries to use on this panel.
* queries.mode::: Of the queries available, which to use. Options: +all, pinned, unpinned, selected+
* queries.ids::: In +selected+ mode, which query ids are selected.
*/
queries : {
mode : 'all',
ids : []
},
/** @scratch /panels/map/3
* tmode:: Facet mode: terms or terms_stats
*/
tmode : 'terms',
/** @scratch /panels/map/3
* tstat:: Terms_stats facet stats field
*/
tstat : 'total',
/** @scratch /panels/map/3
* valuefield:: Terms_stats facet value field
*/
valuefield : ''
};
_.defaults($scope.panel,_d);
$scope.init = function() {
$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;
}
$scope.panelMeta.loading = true;
var request,
boolQuery,
queries;
$scope.panel.queries.ids = querySrv.idsByMode($scope.panel.queries);
request = $scope.ejs.Request();
queries = querySrv.getQueryObjs($scope.panel.queries.ids);
boolQuery = $scope.ejs.BoolQuery();
_.each(queries,function(q) {
boolQuery = boolQuery.should(querySrv.toEjsObj(q));
});
// Then the insert into facet and make the request
// Terms mode
if($scope.panel.tmode === 'terms') {
request = request
.facet($scope.ejs.TermsFacet('map')
.field($scope.panel.field)
.size($scope.panel.size)
.exclude($scope.panel.exclude)
.facetFilter($scope.ejs.QueryFilter(
$scope.ejs.FilteredQuery(
boolQuery,
filterSrv.getBoolFilter(filterSrv.ids())
)))).size(0);
}
if($scope.panel.tmode === 'terms_stats') {
request = request
.facet($scope.ejs.TermStatsFacet('map')
.valueField($scope.panel.valuefield)
.keyField($scope.panel.field)
.size($scope.panel.size)
.facetFilter($scope.ejs.QueryFilter(
$scope.ejs.FilteredQuery(
boolQuery,
filterSrv.getBoolFilter(filterSrv.ids())
)))).size(0);
}
$scope.populate_modal(request);
var results = $scope.ejs.doSearch(dashboard.indices, request);
// Populate scope when we have results
results.then(function(results) {
$scope.panelMeta.loading = false;
$scope.hits = results.hits.total;
$scope.data = {};
_.each(results.facets.map.terms, function(v) {
if($scope.panel.tmode === 'terms') {
//slice = { label : v.term, data : [[k,v.count]], actions: true};
$scope.data[v.term.toUpperCase()] = v.count;
}
if($scope.panel.tmode === 'terms_stats') {
$scope.data[v.term.toUpperCase()] = v[$scope.panel.tstat];
//slice = { label : v.term, data : [[k,v[scope.panel.tstat]]], actions: true};
}
//$scope.data[v.term.toUpperCase()] = v.total;
});
$scope.$emit('render');
});
};
// I really don't like this function, too much dom manip. Break out into directive?
$scope.populate_modal = function(request) {
$scope.inspector = request.toJSON();
};
$scope.build_search = function(field, value) {
filterSrv.set({type:'field', field:field, query:value, mandate:"must"});
};
$scope.set_refresh = function (state) {
$scope.refresh = state;
};
$scope.close_edit = function() {
if($scope.refresh) {
$scope.get_data();
}
$scope.refresh = false;
$scope.$emit('render');
};
});
module.directive('map', function() {
return {
restrict: 'A',
link: function(scope, elem) {
elem.html('![](img/load_big.gif)
');
// Receive render events
scope.$on('render',function(){
slow();
});
elem.closest('.panel').resize(function () {
elem.empty();
});
function render_panel() {
elem.empty();
elem.css({height:scope.panel.height||scope.row.height});
$('.jvectormap-zoomin,.jvectormap-zoomout,.jvectormap-label').remove();
require(['./panels/map/lib/map.'+scope.panel.map], function () {
elem.vectorMap({
map: scope.panel.map,
regionStyle: {initial: {fill: '#8c8c8c'}},
zoomOnScroll: false,
backgroundColor: null,
series: {
regions: [{
values: scope.data,
scale: scope.panel.colors,
normalizeFunction: 'polynomial'
}]
},
onRegionLabelShow: function(event, label, code){
elem.children('.map-legend').show();
var count = _.isUndefined(scope.data[code]) ? 0 : scope.data[code];
elem.children('.map-legend').text(label.text() + ": " + count);
},
onRegionOut: function() {
elem.children('.map-legend').hide();
},
onRegionClick: function(event, code) {
var count = _.isUndefined(scope.data[code]) ? 0 : scope.data[code];
if (count !== 0) {
scope.build_search(scope.panel.field,code);
}
}
});
elem.prepend('');
elem.children('.map-legend').hide();
});
}
var slow = _.debounce(render_panel, 200);
}
};
});
});
© 2015 - 2025 Weber Informatics LLC | Privacy Policy