From 06e4b6845bf2caf0d3d45ab2bde40ac50fa7058a Mon Sep 17 00:00:00 2001 From: ppisljar Date: Wed, 13 Jun 2018 17:58:09 +0200 Subject: [PATCH 1/9] fixing other bucket filter --- .../public/tag_cloud_visualization.js | 6 +++-- .../buckets/_terms_other_bucket_helper.js | 17 +++--------- .../buckets/_terms_other_bucket_helper.js | 17 ++++++------ .../agg_types/buckets/create_filter/terms.js | 27 +++++++++++++++++-- src/ui/public/agg_types/buckets/terms.js | 11 ++++++++ src/ui/public/vis/agg_config.js | 4 +-- src/ui/public/vis/vis.js | 23 +++++++++++++++- .../public/vis/vis_types/vislib_vis_type.js | 2 +- 8 files changed, 77 insertions(+), 30 deletions(-) diff --git a/src/core_plugins/tagcloud/public/tag_cloud_visualization.js b/src/core_plugins/tagcloud/public/tag_cloud_visualization.js index 10224879d31f0..93def0c807641 100644 --- a/src/core_plugins/tagcloud/public/tag_cloud_visualization.js +++ b/src/core_plugins/tagcloud/public/tag_cloud_visualization.js @@ -46,8 +46,9 @@ export class TagCloudVisualization { if (!this._bucketAgg) { return; } - const filter = this._bucketAgg.createFilter(event); - this._vis.API.queryFilter.addFilters(filter); + this._vis.API.events.filter( + this._data, 0, this._data.rows.findIndex(row => row[0] === event) + ); }); this._renderComplete$ = Observable.fromEvent(this._tagCloud, 'renderComplete'); @@ -112,6 +113,7 @@ export class TagCloudVisualization { } const data = response.tables[0]; + this._data = data; const segmentAggs = this._vis.aggs.bySchemaName.segment; if (segmentAggs && segmentAggs.length > 0) { this._bucketAgg = segmentAggs[0]; diff --git a/src/ui/public/agg_types/__tests__/buckets/_terms_other_bucket_helper.js b/src/ui/public/agg_types/__tests__/buckets/_terms_other_bucket_helper.js index 440b96dbeda27..3ea1c45d42897 100644 --- a/src/ui/public/agg_types/__tests__/buckets/_terms_other_bucket_helper.js +++ b/src/ui/public/agg_types/__tests__/buckets/_terms_other_bucket_helper.js @@ -245,8 +245,7 @@ describe('Terms Agg Other bucket helper', () => { vis.aggs[0], otherAggConfig); - expect(mergedResponse.aggregations['1'].buckets[3].key).to.equal('Other'); - expect(mergedResponse.aggregations['1'].buckets[3].filters.length).to.equal(2); + expect(mergedResponse.aggregations['1'].buckets[3].key).to.equal('__other__'); }); it('correctly merges other bucket with nested terms agg', () => { @@ -255,8 +254,7 @@ describe('Terms Agg Other bucket helper', () => { const mergedResponse = mergeOtherBucketAggResponse(vis.aggs, nestedTermResponse, nestedOtherResponse, vis.aggs[1], otherAggConfig); - expect(mergedResponse.aggregations['1'].buckets[1]['2'].buckets[3].key).to.equal('Other'); - expect(mergedResponse.aggregations['1'].buckets[1]['2'].buckets[3].filters.length).to.equal(2); + expect(mergedResponse.aggregations['1'].buckets[1]['2'].buckets[3].key).to.equal('__other__'); }); }); @@ -265,17 +263,8 @@ describe('Terms Agg Other bucket helper', () => { it('correctly updates missing bucket key', () => { init(visConfigNestedTerm); const updatedResponse = updateMissingBucket(singleTermResponse, vis.aggs, vis.aggs[0]); - expect(updatedResponse.aggregations['1'].buckets.find(bucket => bucket.key === 'Missing')).to.not.be('undefined'); + expect(updatedResponse.aggregations['1'].buckets.find(bucket => bucket.key === '__missing__')).to.not.be('undefined'); }); - it('correctly sets the bucket filter', () => { - const updatedResponse = updateMissingBucket(singleTermResponse, vis.aggs, vis.aggs[0]); - const missingBucket = updatedResponse.aggregations['1'].buckets.find(bucket => bucket.key === 'Missing'); - expect(missingBucket.filters).to.not.be('undefined'); - expect(missingBucket.filters[0]).to.eql({ - meta: { index: 'logstash-*', negate: true }, - exists: { field: 'geo.src' } - }); - }); }); }); diff --git a/src/ui/public/agg_types/buckets/_terms_other_bucket_helper.js b/src/ui/public/agg_types/buckets/_terms_other_bucket_helper.js index c51ab5090e136..f20c169baa53c 100644 --- a/src/ui/public/agg_types/buckets/_terms_other_bucket_helper.js +++ b/src/ui/public/agg_types/buckets/_terms_other_bucket_helper.js @@ -19,8 +19,8 @@ import _ from 'lodash'; import { AggConfig } from '../../vis/agg_config'; -import { buildPhrasesFilter } from '../../filter_manager/lib/phrases'; import { buildExistsFilter } from '../../filter_manager/lib/exists'; +import { buildPhrasesFilter } from '../../filter_manager/lib/phrases'; import { buildQueryFromFilters } from '../../courier/data_source/build_query/from_filters'; /** @@ -102,6 +102,7 @@ const getOtherAggTerms = (requestAgg, key, otherAgg) => { ); }; + const buildOtherBucketAgg = (aggConfigs, aggWithOtherBucket, response) => { const bucketAggs = aggConfigs.filter(agg => agg.type.type === 'buckets'); const index = bucketAggs.findIndex(agg => agg.id === aggWithOtherBucket.id); @@ -175,12 +176,11 @@ const mergeOtherBucketAggResponse = (aggsConfig, response, otherResponse, otherA const phraseFilter = buildPhrasesFilter(otherAgg.params.field, requestFilterTerms, otherAgg.params.field.indexPattern); phraseFilter.meta.negate = true; bucket.filters = [ phraseFilter ]; - bucket.key = otherAgg.params.otherBucketLabel; + bucket.key = '__other__'; if (aggResultBuckets.some(bucket => bucket.key === '__missing__')) { bucket.filters.push(buildExistsFilter(otherAgg.params.field, otherAgg.params.field.indexPattern)); } - aggResultBuckets.push(bucket); }); return updatedResponse; @@ -190,12 +190,13 @@ const updateMissingBucket = (response, aggConfigs, agg) => { const updatedResponse = _.cloneDeep(response); const aggResultBuckets = getAggConfigResultMissingBuckets(updatedResponse.aggregations, agg.id); aggResultBuckets.forEach(bucket => { - bucket.key = agg.params.missingBucketLabel; - const existsFilter = buildExistsFilter(agg.params.field, agg.params.field.indexPattern); - existsFilter.meta.negate = true; - bucket.filters = [ existsFilter ]; + bucket.key = '__missing__'; }); return updatedResponse; }; -export { buildOtherBucketAgg, mergeOtherBucketAggResponse, updateMissingBucket }; +export { + buildOtherBucketAgg, + mergeOtherBucketAggResponse, + updateMissingBucket, +}; diff --git a/src/ui/public/agg_types/buckets/create_filter/terms.js b/src/ui/public/agg_types/buckets/create_filter/terms.js index c2fd5fd36e2ca..cd3377d6e473b 100644 --- a/src/ui/public/agg_types/buckets/create_filter/terms.js +++ b/src/ui/public/agg_types/buckets/create_filter/terms.js @@ -18,7 +18,30 @@ */ import { buildPhraseFilter } from '../../../filter_manager/lib/phrase'; +import { buildPhrasesFilter } from '../../../filter_manager/lib/phrases'; +import { buildExistsFilter } from '../../../filter_manager/lib/exists'; -export function createFilterTerms(aggConfig, key) { - return buildPhraseFilter(aggConfig.params.field, key, aggConfig.vis.indexPattern); +export function createFilterTerms(aggConfig, key, params) { + const field = aggConfig.params.field; + const indexPattern = field.indexPattern; + + if (key === '__other__') { + const terms = params.terms; + + const phraseFilter = buildPhrasesFilter(field, terms, indexPattern); + phraseFilter.meta.negate = true; + + const filters = [phraseFilter]; + + if (terms.some(term => term === '__missing__')) { + filters.push(buildExistsFilter(field, indexPattern)); + } + + return filters; + } else if (key === '__missing__') { + const existsFilter = buildExistsFilter(field, indexPattern); + existsFilter.meta.negate = true; + return existsFilter; + } + return buildPhraseFilter(field, key, indexPattern); } diff --git a/src/ui/public/agg_types/buckets/terms.js b/src/ui/public/agg_types/buckets/terms.js index f4bb28ae7b7b9..6a362fc49e52c 100644 --- a/src/ui/public/agg_types/buckets/terms.js +++ b/src/ui/public/agg_types/buckets/terms.js @@ -73,6 +73,17 @@ export const termsBucketAgg = new BucketAggType({ const params = agg.params; return agg.getFieldDisplayName() + ': ' + params.order.display; }, + getFormat: function (bucket) { + return { + getConverterFor: (type) => { + return (val) => { + if (val === '__other__') return bucket.params.otherBucketLabel; + if (val === '__missing__') return bucket.params.missingBucketLabel; + return bucket.params.field.format.getConverterFor(type)(val); + }; + } + }; + }, createFilter: createFilterTerms, postFlightRequest: async (resp, aggConfigs, aggConfig, nestedSearchSource) => { if (aggConfig.params.otherBucket) { diff --git a/src/ui/public/vis/agg_config.js b/src/ui/public/vis/agg_config.js index e53a406bd2a29..dcf701ef438c3 100644 --- a/src/ui/public/vis/agg_config.js +++ b/src/ui/public/vis/agg_config.js @@ -182,7 +182,7 @@ AggConfig.prototype.isFilterable = function () { return _.isFunction(this.type.createFilter); }; -AggConfig.prototype.createFilter = function (key) { +AggConfig.prototype.createFilter = function (key, params = {}) { if (!this.isFilterable()) { throw new TypeError('The "' + this.type.title + '" aggregation does not support filtering.'); } @@ -197,7 +197,7 @@ AggConfig.prototype.createFilter = function (key) { throw new TypeError(message); } - return this.type.createFilter(this, key); + return this.type.createFilter(this, key, params); }; /** diff --git a/src/ui/public/vis/vis.js b/src/ui/public/vis/vis.js index e25608a17a276..207ebc1f0a555 100644 --- a/src/ui/public/vis/vis.js +++ b/src/ui/public/vis/vis.js @@ -40,6 +40,15 @@ import { queryManagerFactory } from '../query_manager'; import { SearchSourceProvider } from '../courier/data_source/search_source'; import { SavedObjectsClientProvider } from '../saved_objects'; +const getTerms = (table, columnIndex, rowIndex) => { + return [...new Set( + table.rows.filter(row => { + if (row[columnIndex] === '__other__') return false; + return row.every((cell, i) => cell === table.rows[rowIndex][i] || i >= columnIndex); + }).map(row => row[columnIndex]) + )]; +}; + export function VisProvider(Private, Promise, indexPatterns, timefilter, getAppState) { const visTypes = Private(VisTypesRegistryProvider); const brushEvent = Private(UtilsBrushEventProvider); @@ -75,9 +84,21 @@ export function VisProvider(Private, Promise, indexPatterns, timefilter, getAppS queryFilter: queryFilter, queryManager: queryManagerFactory(getAppState), events: { - filter: (event) => { + filter_legacy: (event) => { const appState = getAppState(); filterBarClickHandler(appState)(event); + }, + filter: (data, columnIndex, rowIndex) => { + const agg = data.columns[columnIndex].aggConfig; + let filter = []; + const value = data.rows[rowIndex][columnIndex]; + if (agg.type.name === 'terms' && agg.params.otherBucket) { + const terms = getTerms(data, columnIndex, rowIndex); + filter = agg.createFilter(value, { terms }); + } else { + filter = agg.createFilter(value); + } + queryFilter.addFilters(filter); }, brush: (event) => { const appState = getAppState(); brushEvent(appState)(event); diff --git a/src/ui/public/vis/vis_types/vislib_vis_type.js b/src/ui/public/vis/vis_types/vislib_vis_type.js index 93dcd3eaf1b61..dda7e7ee6acf9 100644 --- a/src/ui/public/vis/vis_types/vislib_vis_type.js +++ b/src/ui/public/vis/vis_types/vislib_vis_type.js @@ -87,7 +87,7 @@ export function VislibVisTypeProvider(Private, $rootScope, $timeout, $compile) { this.vis.vislibVis = new vislib.Vis(this.chartEl, this.vis.params); this.vis.vislibVis.on('brush', this.vis.API.events.brush); - this.vis.vislibVis.on('click', this.vis.API.events.filter); + this.vis.vislibVis.on('click', this.vis.API.events.filter_legacy); this.vis.vislibVis.on('renderComplete', resolve); this.vis.vislibVis.render(esResponse, this.vis.getUiState()); From e0ae00e940c65cb6b95d27374eb27a6c46518a10 Mon Sep 17 00:00:00 2001 From: ppisljar Date: Fri, 15 Jun 2018 11:16:39 +0200 Subject: [PATCH 2/9] adding and fixing tests --- .../__tests__/buckets/create_filter/terms.js | 31 +++++++++++++++++++ .../agg_types/__tests__/buckets/terms.js | 30 ++++++++++++++++++ src/ui/public/vis/__tests__/_agg_config.js | 2 +- 3 files changed, 62 insertions(+), 1 deletion(-) diff --git a/src/ui/public/agg_types/__tests__/buckets/create_filter/terms.js b/src/ui/public/agg_types/__tests__/buckets/create_filter/terms.js index 9505d9b6ad0f7..9195df7b1b662 100644 --- a/src/ui/public/agg_types/__tests__/buckets/create_filter/terms.js +++ b/src/ui/public/agg_types/__tests__/buckets/create_filter/terms.js @@ -70,5 +70,36 @@ describe('AggConfig Filters', function () { expect(filterTrue.query.match).to.have.property('ssl'); expect(filterTrue.query.match.ssl).to.have.property('query', true); }); + + it('should generate correct __missing__ filter', () => { + const vis = new Vis(indexPattern, { + type: 'histogram', + aggs: [ { type: 'terms', schema: 'segment', params: { field: '_type' } } ] + }); + const aggConfig = vis.aggs.byTypeName.terms[0]; + const filter = createFilterTerms(aggConfig, '__missing__'); + expect(filter).to.have.property('exists'); + expect(filter.exists).to.have.property('field', '_type'); + expect(filter).to.have.property('meta'); + expect(filter.meta).to.have.property('index', indexPattern.id); + expect(filter.meta).to.have.property('negate', true); + }); + + it('should generate correct __other__ filter', () => { + const vis = new Vis(indexPattern, { + type: 'histogram', + aggs: [ { type: 'terms', schema: 'segment', params: { field: '_type' } } ] + }); + const aggConfig = vis.aggs.byTypeName.terms[0]; + const filter = createFilterTerms(aggConfig, '__other__', { terms: ['apache'] })[0]; + expect(filter).to.have.property('query'); + expect(filter.query).to.have.property('bool'); + expect(filter.query.bool).to.have.property('should'); + expect(filter.query.bool.should[0]).to.have.property('match_phrase'); + expect(filter.query.bool.should[0].match_phrase).to.have.property('_type', 'apache'); + expect(filter).to.have.property('meta'); + expect(filter.meta).to.have.property('index', indexPattern.id); + expect(filter.meta).to.have.property('negate', true); + }); }); }); diff --git a/src/ui/public/agg_types/__tests__/buckets/terms.js b/src/ui/public/agg_types/__tests__/buckets/terms.js index e4f72c916125c..923f662451240 100644 --- a/src/ui/public/agg_types/__tests__/buckets/terms.js +++ b/src/ui/public/agg_types/__tests__/buckets/terms.js @@ -194,6 +194,36 @@ describe('Terms Agg', function () { expect($rootScope.agg.params.orderBy).to.be('_key'); }); + describe('custom field formatter', () => { + beforeEach(() => { + init({ + responseValueAggs: [ + { + id: 'agg1', + type: { + name: 'count' + } + } + ], + aggParams: { + otherBucketLabel: 'Other', + missingBucketLabel: 'Missing' + } + }); + $rootScope.$digest(); + }); + + it ('converts __other__ key', () => { + const formatter = $rootScope.agg.type.getFormat($rootScope.agg).getConverterFor('text'); + expect(formatter('__other__')).to.be('Other'); + }); + + it ('converts __missing__ key', () => { + const formatter = $rootScope.agg.type.getFormat($rootScope.agg).getConverterFor('text'); + expect(formatter('__missing__')).to.be('Missing'); + }); + }); + it('adds "custom metric" option'); it('lists all metric agg responses'); it('lists individual values of a multi-value metric'); diff --git a/src/ui/public/vis/__tests__/_agg_config.js b/src/ui/public/vis/__tests__/_agg_config.js index 80d0d7c224e1a..2e87f1a9bffb8 100644 --- a/src/ui/public/vis/__tests__/_agg_config.js +++ b/src/ui/public/vis/__tests__/_agg_config.js @@ -452,7 +452,7 @@ describe('AggConfig', function () { type: 'table', aggs: [ { - type: 'terms', + type: 'histogram', schema: 'bucket', params: { field: 'bytes' } } From 32b918150850519efd3bfb38586c5f604020c8ba Mon Sep 17 00:00:00 2001 From: ppisljar Date: Mon, 18 Jun 2018 11:11:59 +0200 Subject: [PATCH 3/9] adding comments and changing filter event name --- src/core_plugins/tagcloud/public/tag_cloud_visualization.js | 2 +- src/ui/public/vis/vis.js | 6 ++++-- src/ui/public/vis/vis_types/vislib_vis_type.js | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/core_plugins/tagcloud/public/tag_cloud_visualization.js b/src/core_plugins/tagcloud/public/tag_cloud_visualization.js index 93def0c807641..e9cc02ee9e2e1 100644 --- a/src/core_plugins/tagcloud/public/tag_cloud_visualization.js +++ b/src/core_plugins/tagcloud/public/tag_cloud_visualization.js @@ -46,7 +46,7 @@ export class TagCloudVisualization { if (!this._bucketAgg) { return; } - this._vis.API.events.filter( + this._vis.API.events.addFilter( this._data, 0, this._data.rows.findIndex(row => row[0] === event) ); }); diff --git a/src/ui/public/vis/vis.js b/src/ui/public/vis/vis.js index 207ebc1f0a555..df629e0e8bde6 100644 --- a/src/ui/public/vis/vis.js +++ b/src/ui/public/vis/vis.js @@ -84,11 +84,13 @@ export function VisProvider(Private, Promise, indexPatterns, timefilter, getAppS queryFilter: queryFilter, queryManager: queryManagerFactory(getAppState), events: { - filter_legacy: (event) => { + // the filter method will be removed in the near feature + // you should rather use addFilter method below + filter: (event) => { const appState = getAppState(); filterBarClickHandler(appState)(event); }, - filter: (data, columnIndex, rowIndex) => { + addFilter: (data, columnIndex, rowIndex) => { const agg = data.columns[columnIndex].aggConfig; let filter = []; const value = data.rows[rowIndex][columnIndex]; diff --git a/src/ui/public/vis/vis_types/vislib_vis_type.js b/src/ui/public/vis/vis_types/vislib_vis_type.js index dda7e7ee6acf9..93dcd3eaf1b61 100644 --- a/src/ui/public/vis/vis_types/vislib_vis_type.js +++ b/src/ui/public/vis/vis_types/vislib_vis_type.js @@ -87,7 +87,7 @@ export function VislibVisTypeProvider(Private, $rootScope, $timeout, $compile) { this.vis.vislibVis = new vislib.Vis(this.chartEl, this.vis.params); this.vis.vislibVis.on('brush', this.vis.API.events.brush); - this.vis.vislibVis.on('click', this.vis.API.events.filter_legacy); + this.vis.vislibVis.on('click', this.vis.API.events.filter); this.vis.vislibVis.on('renderComplete', resolve); this.vis.vislibVis.render(esResponse, this.vis.getUiState()); From 9986996e9298cc724e6cc28b048cdfd23528e8f4 Mon Sep 17 00:00:00 2001 From: ppisljar Date: Mon, 18 Jun 2018 11:17:36 +0200 Subject: [PATCH 4/9] adding support to region map --- .../region_map/public/region_map_visualization.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/core_plugins/region_map/public/region_map_visualization.js b/src/core_plugins/region_map/public/region_map_visualization.js index 47ec427e3e0b1..73935c96f75c4 100644 --- a/src/core_plugins/region_map/public/region_map_visualization.js +++ b/src/core_plugins/region_map/public/region_map_visualization.js @@ -153,9 +153,8 @@ export function RegionMapsVisualizationProvider(Private, Notifier, config) { return; } - const agg = this._vis.aggs.bySchemaName.segment[0]; - const filter = agg.createFilter(event); - this._vis.API.queryFilter.addFilters(filter); + const rowIndex = this._chartData.tables[0].rows.findIndex(row => row[0] === event); + this._vis.API.events.addFilter(this._chartData.tables[0], 0, rowIndex); }); this._choroplethLayer.on('styleChanged', (event) => { const shouldShowWarning = this._vis.params.isDisplayWarning && config.get('visualization:regionmap:showWarnings'); From fd967c68c022bae17eeece301749f11ea09818da Mon Sep 17 00:00:00 2001 From: ppisljar Date: Mon, 18 Jun 2018 11:23:48 +0200 Subject: [PATCH 5/9] adding support to metric vis --- .../metric_vis/public/metric_vis_controller.js | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/core_plugins/metric_vis/public/metric_vis_controller.js b/src/core_plugins/metric_vis/public/metric_vis_controller.js index 3afcace106c74..3412dec05c1f0 100644 --- a/src/core_plugins/metric_vis/public/metric_vis_controller.js +++ b/src/core_plugins/metric_vis/public/metric_vis_controller.js @@ -98,25 +98,25 @@ export class MetricVisComponent extends Component { const labels = this._getLabels(); const metrics = []; - tableGroups.tables.forEach((table) => { + tableGroups.tables.forEach((table, tableIndex) => { let bucketAgg; let rowHeaderIndex; - table.columns.forEach((column, i) => { + table.columns.forEach((column, columnIndex) => { const aggConfig = column.aggConfig; if (aggConfig && aggConfig.schema.group === 'buckets') { bucketAgg = aggConfig; // Store the current index, so we later know in which position in the // row array, the bucket agg key will be, so we can create filters on it. - rowHeaderIndex = i; + rowHeaderIndex = columnIndex; return; } - table.rows.forEach(row => { + table.rows.forEach((row, rowIndex) => { let title = column.title; - let value = row[i]; + let value = row[columnIndex]; const color = this._getColor(value, labels, colors); if (isPercentageMode) { @@ -143,6 +143,9 @@ export class MetricVisComponent extends Component { bgColor: shouldColor && config.style.bgColor ? color : null, lightText: shouldColor && config.style.bgColor && this._needsLightText(color), filterKey: rowHeaderIndex !== undefined ? row[rowHeaderIndex] : null, + tableIndex: tableIndex, + rowIndex: rowIndex, + columnIndex: columnIndex, bucketAgg: bucketAgg, }); }); @@ -156,8 +159,8 @@ export class MetricVisComponent extends Component { if (!metric.filterKey || !metric.bucketAgg) { return; } - const filter = metric.bucketAgg.createFilter(metric.filterKey); - this.props.vis.API.queryFilter.addFilters(filter); + const table = this.props.visData.tables[metric.tableIndex]; + this._vis.API.events.addFilter(table, metric.columnIndex, metric.rowIndex); }; _renderMetric = (metric, index) => { From fcc9df62908c02261a96429d222413012bc9af8e Mon Sep 17 00:00:00 2001 From: ppisljar Date: Tue, 19 Jun 2018 10:41:06 +0200 Subject: [PATCH 6/9] applying tim's suggestions --- .../metric_vis/public/metric_vis_controller.js | 4 ++-- src/core_plugins/tagcloud/public/tag_cloud.js | 2 +- .../tagcloud/public/tag_cloud_visualization.js | 10 +++++++--- src/ui/public/agg_types/buckets/terms.js | 3 ++- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/core_plugins/metric_vis/public/metric_vis_controller.js b/src/core_plugins/metric_vis/public/metric_vis_controller.js index 3412dec05c1f0..dc423a426946a 100644 --- a/src/core_plugins/metric_vis/public/metric_vis_controller.js +++ b/src/core_plugins/metric_vis/public/metric_vis_controller.js @@ -145,7 +145,7 @@ export class MetricVisComponent extends Component { filterKey: rowHeaderIndex !== undefined ? row[rowHeaderIndex] : null, tableIndex: tableIndex, rowIndex: rowIndex, - columnIndex: columnIndex, + columnIndex: rowHeaderIndex, bucketAgg: bucketAgg, }); }); @@ -160,7 +160,7 @@ export class MetricVisComponent extends Component { return; } const table = this.props.visData.tables[metric.tableIndex]; - this._vis.API.events.addFilter(table, metric.columnIndex, metric.rowIndex); + this.props.vis.API.events.addFilter(table, metric.columnIndex, metric.rowIndex); }; _renderMetric = (metric, index) => { diff --git a/src/core_plugins/tagcloud/public/tag_cloud.js b/src/core_plugins/tagcloud/public/tag_cloud.js index db3b1a85063e6..3d158ec4d5e25 100644 --- a/src/core_plugins/tagcloud/public/tag_cloud.js +++ b/src/core_plugins/tagcloud/public/tag_cloud.js @@ -224,7 +224,7 @@ class TagCloud extends EventEmitter { const self = this; enteringTags.on({ click: function (event) { - self.emit('select', event.rawText); + self.emit('select', event); }, mouseover: function () { d3.select(this).style('cursor', 'pointer'); diff --git a/src/core_plugins/tagcloud/public/tag_cloud_visualization.js b/src/core_plugins/tagcloud/public/tag_cloud_visualization.js index e9cc02ee9e2e1..b124e0abc8549 100644 --- a/src/core_plugins/tagcloud/public/tag_cloud_visualization.js +++ b/src/core_plugins/tagcloud/public/tag_cloud_visualization.js @@ -47,7 +47,7 @@ export class TagCloudVisualization { return; } this._vis.API.events.addFilter( - this._data, 0, this._data.rows.findIndex(row => row[0] === event) + event.meta.data, 0, event.meta.rowIndex ); }); this._renderComplete$ = Observable.fromEvent(this._tagCloud, 'renderComplete'); @@ -121,12 +121,16 @@ export class TagCloudVisualization { this._bucketAgg = null; } - const tags = data.rows.map(row => { + const tags = data.rows.map((row, rowIndex) => { const [tag, count] = row; return { displayText: this._bucketAgg ? this._bucketAgg.fieldFormatter()(tag) : tag, rawText: tag, - value: count + value: count, + meta: { + data: data, + rowIndex: rowIndex, + } }; }); diff --git a/src/ui/public/agg_types/buckets/terms.js b/src/ui/public/agg_types/buckets/terms.js index 6a362fc49e52c..ea7f968a8cefa 100644 --- a/src/ui/public/agg_types/buckets/terms.js +++ b/src/ui/public/agg_types/buckets/terms.js @@ -76,10 +76,11 @@ export const termsBucketAgg = new BucketAggType({ getFormat: function (bucket) { return { getConverterFor: (type) => { + const converter = bucket.params.field.format.getConverterFor(type); return (val) => { if (val === '__other__') return bucket.params.otherBucketLabel; if (val === '__missing__') return bucket.params.missingBucketLabel; - return bucket.params.field.format.getConverterFor(type)(val); + return converter(val); }; } }; From eac9af57dc07e9142d2b61c0a370992c0f803fb7 Mon Sep 17 00:00:00 2001 From: ppisljar Date: Tue, 19 Jun 2018 11:02:46 +0200 Subject: [PATCH 7/9] rewrite getTerms function --- .../tagcloud/public/tag_cloud_visualization.js | 1 - src/ui/public/vis/vis.js | 10 ++++------ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/core_plugins/tagcloud/public/tag_cloud_visualization.js b/src/core_plugins/tagcloud/public/tag_cloud_visualization.js index b124e0abc8549..8cb9e8b90b120 100644 --- a/src/core_plugins/tagcloud/public/tag_cloud_visualization.js +++ b/src/core_plugins/tagcloud/public/tag_cloud_visualization.js @@ -113,7 +113,6 @@ export class TagCloudVisualization { } const data = response.tables[0]; - this._data = data; const segmentAggs = this._vis.aggs.bySchemaName.segment; if (segmentAggs && segmentAggs.length > 0) { this._bucketAgg = segmentAggs[0]; diff --git a/src/ui/public/vis/vis.js b/src/ui/public/vis/vis.js index df629e0e8bde6..bfaf222bce698 100644 --- a/src/ui/public/vis/vis.js +++ b/src/ui/public/vis/vis.js @@ -41,12 +41,10 @@ import { SearchSourceProvider } from '../courier/data_source/search_source'; import { SavedObjectsClientProvider } from '../saved_objects'; const getTerms = (table, columnIndex, rowIndex) => { - return [...new Set( - table.rows.filter(row => { - if (row[columnIndex] === '__other__') return false; - return row.every((cell, i) => cell === table.rows[rowIndex][i] || i >= columnIndex); - }).map(row => row[columnIndex]) - )]; + // get only rows where cell value matches current row for all the fields before columnIndex + const rows = table.rows.filter(row => row.every((cell, i) => cell === table.rows[rowIndex][i] || i >= columnIndex)); + const terms = rows.map(row => row[columnIndex]); + return [...new Set(terms.filter(term => term !== '__other__'))]; }; export function VisProvider(Private, Promise, indexPatterns, timefilter, getAppState) { From adf08b9d96da839622e0aa38299b520077ce44bd Mon Sep 17 00:00:00 2001 From: ppisljar Date: Tue, 19 Jun 2018 12:35:55 +0200 Subject: [PATCH 8/9] reverting one of tims suggestion as test fails for some reason :| --- src/ui/public/agg_types/buckets/terms.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ui/public/agg_types/buckets/terms.js b/src/ui/public/agg_types/buckets/terms.js index ea7f968a8cefa..94312672a2df4 100644 --- a/src/ui/public/agg_types/buckets/terms.js +++ b/src/ui/public/agg_types/buckets/terms.js @@ -76,10 +76,10 @@ export const termsBucketAgg = new BucketAggType({ getFormat: function (bucket) { return { getConverterFor: (type) => { - const converter = bucket.params.field.format.getConverterFor(type); return (val) => { if (val === '__other__') return bucket.params.otherBucketLabel; if (val === '__missing__') return bucket.params.missingBucketLabel; + const converter = bucket.params.field.format.getConverterFor(type); return converter(val); }; } From 6b6db6188483f4531a349a72300f09012d897db1 Mon Sep 17 00:00:00 2001 From: ppisljar Date: Tue, 19 Jun 2018 15:53:09 +0200 Subject: [PATCH 9/9] fixing based on marcos review --- src/ui/public/agg_types/buckets/terms.js | 8 ++++++-- src/ui/public/vis/vis.js | 7 ++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/ui/public/agg_types/buckets/terms.js b/src/ui/public/agg_types/buckets/terms.js index 94312672a2df4..ca545ad1a18e0 100644 --- a/src/ui/public/agg_types/buckets/terms.js +++ b/src/ui/public/agg_types/buckets/terms.js @@ -77,8 +77,12 @@ export const termsBucketAgg = new BucketAggType({ return { getConverterFor: (type) => { return (val) => { - if (val === '__other__') return bucket.params.otherBucketLabel; - if (val === '__missing__') return bucket.params.missingBucketLabel; + if (val === '__other__') { + return bucket.params.otherBucketLabel; + } + if (val === '__missing__') { + return bucket.params.missingBucketLabel; + } const converter = bucket.params.field.format.getConverterFor(type); return converter(val); }; diff --git a/src/ui/public/vis/vis.js b/src/ui/public/vis/vis.js index bfaf222bce698..0c9006fa997c9 100644 --- a/src/ui/public/vis/vis.js +++ b/src/ui/public/vis/vis.js @@ -44,7 +44,12 @@ const getTerms = (table, columnIndex, rowIndex) => { // get only rows where cell value matches current row for all the fields before columnIndex const rows = table.rows.filter(row => row.every((cell, i) => cell === table.rows[rowIndex][i] || i >= columnIndex)); const terms = rows.map(row => row[columnIndex]); - return [...new Set(terms.filter(term => term !== '__other__'))]; + + return [...new Set(terms.filter(term => { + const notOther = term !== '__other__'; + const notMissing = term !== '__missing__'; + return notOther && notMissing; + }))]; }; export function VisProvider(Private, Promise, indexPatterns, timefilter, getAppState) {