UNPKG

@spalger/kibana

Version:

Kibana is an open source (Apache Licensed), browser based analytics and search dashboard for Elasticsearch. Kibana is a snap to setup and start using. Kibana strives to be easy to get started with, while also being flexible and powerful, just like Elastic

259 lines (230 loc) 8.63 kB
define(function (require) { var app = require('ui/modules').get('apps/discover'); require('ui/directives/css_truncate'); require('ui/directives/field_name'); require('ui/filters/unique'); require('plugins/kibana/discover/components/field_chooser/discover_field'); app.directive('discFieldChooser', function ($location, globalState, config, $route, Private) { var _ = require('lodash'); var rison = require('ui/utils/rison'); var fieldCalculator = require('plugins/kibana/discover/components/field_chooser/lib/field_calculator'); var FieldList = Private(require('ui/index_patterns/_field_list')); return { restrict: 'E', scope: { columns: '=', hits: '=', fieldCounts: '=', state: '=', indexPattern: '=', indexPatternList: '=', updateFilterInQuery: '=filter' }, template: require('plugins/kibana/discover/components/field_chooser/field_chooser.html'), link: function ($scope) { $scope.setIndexPattern = function (id) { $scope.state.index = id; $scope.state.save(); }; $scope.$watch('state.index', function (id, previousId) { if (previousId == null || previousId === id) return; $route.reload(); }); var filter = $scope.filter = { props: [ 'type', 'indexed', 'analyzed', 'missing', 'name' ], defaults: { missing: true }, boolOpts: [ {label: 'any', value: undefined }, {label: 'yes', value: true }, {label: 'no', value: false } ], toggleVal: function (name, def) { if (filter.vals[name] !== def) filter.vals[name] = def; else filter.vals[name] = undefined; }, reset: function () { filter.vals = _.clone(filter.defaults); }, isFieldSelected: function (field) { return field.display; }, isFieldFiltered: function (field) { var matchFilter = (filter.vals.type == null || field.type === filter.vals.type); var isAnalyzed = (filter.vals.analyzed == null || field.analyzed === filter.vals.analyzed); var isIndexed = (filter.vals.indexed == null || field.indexed === filter.vals.indexed); var scriptedOrMissing = (!filter.vals.missing || field.scripted || field.rowCount > 0); var matchName = (!filter.vals.name || field.name.indexOf(filter.vals.name) !== -1); return !field.display && matchFilter && isAnalyzed && isIndexed && scriptedOrMissing && matchName ; }, popularity: function (field) { return field.count > 0; }, getActive: function () { return _.some(filter.props, function (prop) { return filter.vals[prop] !== filter.defaults[prop]; }); } }; // set the initial values to the defaults filter.reset(); $scope.$watchCollection('filter.vals', function () { filter.active = filter.getActive(); }); $scope.toggle = function (fieldName) { $scope.increaseFieldCounter(fieldName); _.toggleInOut($scope.columns, fieldName); }; $scope.$watchMulti([ '[]fieldCounts', '[]columns', '[]hits' ], function (cur, prev) { var newHits = cur[2] !== prev[2]; var fields = $scope.fields; var columns = $scope.columns || []; var fieldCounts = $scope.fieldCounts; if (!fields || newHits) { $scope.fields = fields = getFields(); } if (!fields) return; // group the fields into popular and up-popular lists _.chain(fields) .each(function (field) { field.displayOrder = _.indexOf(columns, field.name) + 1; field.display = !!field.displayOrder; field.rowCount = fieldCounts[field.name]; }) .sortBy(function (field) { return (field.count || 0) * -1; }) .groupBy(function (field) { if (field.display) return 'selected'; return field.count > 0 ? 'popular' : 'unpopular'; }) .tap(function (groups) { groups.selected = _.sortBy(groups.selected || [], 'displayOrder'); groups.popular = groups.popular || []; groups.unpopular = groups.unpopular || []; // move excess popular fields to un-popular list var extras = groups.popular.splice(config.get('fields:popularLimit')); groups.unpopular = extras.concat(groups.unpopular); }) .each(function (group, name) { $scope[name + 'Fields'] = _.sortBy(group, name === 'selected' ? 'display' : 'name'); }) .commit(); // include undefined so the user can clear the filter $scope.fieldTypes = _.union([undefined], _.pluck(fields, 'type')); }); $scope.increaseFieldCounter = function (fieldName) { $scope.indexPattern.popularizeField(fieldName, 1); }; $scope.runAgg = function (field) { var agg = {}; var isGeoPoint = field.type === 'geo_point'; var type = isGeoPoint ? 'tile_map' : 'histogram'; // If we're visualizing a date field, and our index is time based (and thus has a time filter), // then run a date histogram if (field.type === 'date' && $scope.indexPattern.timeFieldName === field.name) { agg = { type: 'date_histogram', schema: 'segment', params: { field: field.name, interval: 'auto' } }; } else if (isGeoPoint) { agg = { type: 'geohash_grid', schema: 'segment', params: { field: field.name, precision: 3 } }; } else { agg = { type: 'terms', schema: 'segment', params: { field: field.name, size: config.get('discover:aggs:terms:size', 20), orderBy: '2' } }; } $location.path('/visualize/create').search({ indexPattern: $scope.state.index, type: type, _a: rison.encode({ filters: $scope.state.filters || [], query: $scope.state.query || undefined, vis: { type: type, aggs: [ agg, {schema: 'metric', type: 'count', 'id': '2'} ] } }) }); }; $scope.details = function (field, recompute) { if (_.isUndefined(field.details) || recompute) { field.details = fieldCalculator.getFieldValueCounts({ hits: $scope.hits, field: field, count: 5, grouped: false }); _.each(field.details.buckets, function (bucket) { bucket.display = field.format.convert(bucket.value); }); $scope.increaseFieldCounter(field, 1); } else { delete field.details; } }; function getFields() { var prevFields = $scope.fields; var indexPattern = $scope.indexPattern; var hits = $scope.hits; var fieldCounts = $scope.fieldCounts; if (!indexPattern || !hits || !fieldCounts) return; var fieldSpecs = indexPattern.fields.slice(0); var fieldNamesInDocs = _.keys(fieldCounts); var fieldNamesInIndexPattern = _.keys(indexPattern.fields.byName); _.difference(fieldNamesInDocs, fieldNamesInIndexPattern) .forEach(function (unknownFieldName) { fieldSpecs.push({ name: unknownFieldName, type: 'unknown' }); }); var fields = new FieldList(indexPattern, fieldSpecs); if (prevFields) { fields.forEach(function (field) { field.details = _.get(prevFields, ['byName', field.name, 'details']); }); } return fields; } } }; }); });