mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
* fixing other bucket filters * adding selenium tests * using lodash flatten * using lodash flatten * fixing based on tims review * Fix functional tests
This commit is contained in:
parent
260cf636f9
commit
2488277279
6 changed files with 131 additions and 35 deletions
|
@ -112,6 +112,8 @@ const buildOtherBucketAgg = (aggConfigs, aggWithOtherBucket, response) => {
|
|||
const filterAgg = aggConfigs.createAggConfig({
|
||||
type: 'filters',
|
||||
id: 'other',
|
||||
}, {
|
||||
addToAggConfigs: false,
|
||||
});
|
||||
|
||||
// nest all the child aggregations of aggWithOtherBucket
|
||||
|
@ -129,8 +131,8 @@ const buildOtherBucketAgg = (aggConfigs, aggWithOtherBucket, response) => {
|
|||
if (aggIndex < index) {
|
||||
_.each(agg.buckets, (bucket, bucketObjKey) => {
|
||||
const bucketKey = currentAgg.getKey(bucket, Number.isInteger(bucketObjKey) ? null : bucketObjKey);
|
||||
const filter = _.cloneDeep(bucket.filter) || currentAgg.createFilter(bucketKey);
|
||||
const newFilters = [...filters, filter];
|
||||
const filter = _.cloneDeep(bucket.filters) || currentAgg.createFilter(bucketKey);
|
||||
const newFilters = _.flatten([...filters, filter]);
|
||||
walkBucketTree(newAggIndex, bucket, newAgg.id, newFilters, `${key}-${bucketKey.toString()}`);
|
||||
});
|
||||
return;
|
||||
|
|
29
src/ui/public/filter_bar/push_filters.js
Normal file
29
src/ui/public/filter_bar/push_filters.js
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import _ from 'lodash';
|
||||
|
||||
export function FilterBarPushFiltersProvider() {
|
||||
return function ($state) {
|
||||
if (!_.isObject($state)) throw new Error('pushFilters requires a state object');
|
||||
return function (filters) {
|
||||
$state.$newFilters = filters;
|
||||
};
|
||||
};
|
||||
}
|
|
@ -43,7 +43,7 @@ const LegacyResponseHandlerProvider = function () {
|
|||
const splitMap = {};
|
||||
let splitIndex = 0;
|
||||
|
||||
table.rows.forEach(row => {
|
||||
table.rows.forEach((row, rowIndex) => {
|
||||
const splitValue = row[splitColumn.id];
|
||||
const splitColumnIndex = table.columns.findIndex(column => column === splitColumn);
|
||||
|
||||
|
@ -74,6 +74,11 @@ const LegacyResponseHandlerProvider = function () {
|
|||
const newRow = _.map(converted.tables[tableIndex].tables[0].columns, column => {
|
||||
const value = row[column.id];
|
||||
const aggConfigResult = new AggConfigResult(column.aggConfig, previousSplitAgg, value, value);
|
||||
aggConfigResult.rawData = {
|
||||
table: table,
|
||||
columnIndex: table.columns.findIndex(c => c.id === column.id),
|
||||
rowIndex: rowIndex,
|
||||
};
|
||||
if (column.aggConfig.type.type === 'buckets') {
|
||||
previousSplitAgg = aggConfigResult;
|
||||
}
|
||||
|
@ -86,11 +91,16 @@ const LegacyResponseHandlerProvider = function () {
|
|||
|
||||
converted.tables.push({
|
||||
columns: table.columns.map(column => ({ title: column.name, ...column })),
|
||||
rows: table.rows.map(row => {
|
||||
rows: table.rows.map((row, rowIndex) => {
|
||||
let previousSplitAgg;
|
||||
return table.columns.map(column => {
|
||||
return table.columns.map((column, columnIndex) => {
|
||||
const value = row[column.id];
|
||||
const aggConfigResult = new AggConfigResult(column.aggConfig, previousSplitAgg, value, value);
|
||||
aggConfigResult.rawData = {
|
||||
table: table,
|
||||
column: columnIndex,
|
||||
row: rowIndex,
|
||||
};
|
||||
if (column.aggConfig.type.type === 'buckets') {
|
||||
previousSplitAgg = aggConfigResult;
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ import { AggConfigs } from './agg_configs';
|
|||
import { PersistedState } from '../persisted_state';
|
||||
import { onBrushEvent } from '../utils/brush_event';
|
||||
import { FilterBarQueryFilterProvider } from '../filter_bar/query_filter';
|
||||
import { FilterBarClickHandlerProvider } from '../filter_bar/filter_bar_click_handler';
|
||||
import { FilterBarPushFiltersProvider } from '../filter_bar/push_filters';
|
||||
import { updateVisualizationConfig } from './vis_update';
|
||||
import { SearchSourceProvider } from '../courier/search_source';
|
||||
import { SavedObjectsClientProvider } from '../saved_objects';
|
||||
|
@ -54,7 +54,7 @@ const getTerms = (table, columnIndex, rowIndex) => {
|
|||
return row[column.id] === table.rows[rowIndex][column.id] || i >= columnIndex;
|
||||
});
|
||||
});
|
||||
const terms = rows.map(row => row[columnIndex]);
|
||||
const terms = rows.map(row => row[table.columns[columnIndex].id]);
|
||||
|
||||
return [...new Set(terms.filter(term => {
|
||||
const notOther = term !== '__other__';
|
||||
|
@ -66,9 +66,9 @@ const getTerms = (table, columnIndex, rowIndex) => {
|
|||
export function VisProvider(Private, indexPatterns, getAppState) {
|
||||
const visTypes = Private(VisTypesRegistryProvider);
|
||||
const queryFilter = Private(FilterBarQueryFilterProvider);
|
||||
const filterBarClickHandler = Private(FilterBarClickHandlerProvider);
|
||||
const SearchSource = Private(SearchSourceProvider);
|
||||
const savedObjectsClient = Private(SavedObjectsClientProvider);
|
||||
const filterBarPushFilters = Private(FilterBarPushFiltersProvider);
|
||||
|
||||
class Vis extends EventEmitter {
|
||||
constructor(indexPattern, visState) {
|
||||
|
@ -99,14 +99,22 @@ export function VisProvider(Private, indexPatterns, getAppState) {
|
|||
// the filter method will be removed in the near feature
|
||||
// you should rather use addFilter method below
|
||||
filter: (event) => {
|
||||
let data = event.datum.aggConfigResult;
|
||||
const filters = [];
|
||||
while (data.$parent) {
|
||||
const { key, rawData } = data.$parent;
|
||||
const { table, column, row } = rawData;
|
||||
filters.push(this.API.events.createFilter(table, column, row, key));
|
||||
data = data.$parent;
|
||||
}
|
||||
const appState = getAppState();
|
||||
filterBarClickHandler(appState)(event);
|
||||
filterBarPushFilters(appState)(_.flatten(filters));
|
||||
},
|
||||
addFilter: (data, columnIndex, rowIndex, cellValue) => {
|
||||
createFilter: (data, columnIndex, rowIndex, cellValue) => {
|
||||
const { aggConfig, id: columnId } = data.columns[columnIndex];
|
||||
let filter = [];
|
||||
const value = rowIndex > -1 ? data.rows[rowIndex][columnId] : cellValue;
|
||||
if (!value) {
|
||||
if (value === null || value === undefined) {
|
||||
return;
|
||||
}
|
||||
if (aggConfig.type.name === 'terms' && aggConfig.params.otherBucket) {
|
||||
|
@ -115,6 +123,10 @@ export function VisProvider(Private, indexPatterns, getAppState) {
|
|||
} else {
|
||||
filter = aggConfig.createFilter(value);
|
||||
}
|
||||
return filter;
|
||||
},
|
||||
addFilter: (data, columnIndex, rowIndex, cellValue) => {
|
||||
const filter = this.API.events.createFilter(data, columnIndex, rowIndex, cellValue);
|
||||
queryFilter.addFilters(filter);
|
||||
}, brush: (event) => {
|
||||
onBrushEvent(event, getAppState());
|
||||
|
|
|
@ -21,6 +21,7 @@ import expect from 'expect.js';
|
|||
|
||||
export default function ({ getService, getPageObjects }) {
|
||||
const log = getService('log');
|
||||
const filterBar = getService('filterBar');
|
||||
const PageObjects = getPageObjects(['common', 'visualize', 'header', 'settings']);
|
||||
const fromTime = '2015-09-19 06:31:44.000';
|
||||
const toTime = '2015-09-23 18:31:44.000';
|
||||
|
@ -89,29 +90,64 @@ export default function ({ getService, getPageObjects }) {
|
|||
expect(data).to.eql(expectedTableData);
|
||||
});
|
||||
|
||||
it('should show other and missing bucket', async function () {
|
||||
const expectedTableData = [ 'win 8', 'win xp', 'win 7', 'ios', 'Missing', 'Other' ];
|
||||
describe('other bucket', () => {
|
||||
it('should show other and missing bucket', async function () {
|
||||
const expectedTableData = [ 'win 8', 'win xp', 'win 7', 'ios', 'Missing', 'Other' ];
|
||||
|
||||
await PageObjects.visualize.navigateToNewVisualization();
|
||||
log.debug('clickPieChart');
|
||||
await PageObjects.visualize.clickPieChart();
|
||||
await PageObjects.visualize.clickNewSearch();
|
||||
log.debug('Set absolute time range from \"' + fromTime + '\" to \"' + toTime + '\"');
|
||||
await PageObjects.header.setAbsoluteRange(fromTime, toTime);
|
||||
log.debug('select bucket Split Slices');
|
||||
await PageObjects.visualize.clickBucket('Split Slices');
|
||||
log.debug('Click aggregation Histogram');
|
||||
await PageObjects.visualize.selectAggregation('Terms');
|
||||
log.debug('Click field memory');
|
||||
await PageObjects.visualize.selectField('machine.os.raw');
|
||||
await PageObjects.visualize.toggleOtherBucket();
|
||||
await PageObjects.visualize.toggleMissingBucket();
|
||||
log.debug('clickGo');
|
||||
await PageObjects.visualize.clickGo();
|
||||
await PageObjects.common.sleep(1003);
|
||||
const pieData = await PageObjects.visualize.getPieChartLabels();
|
||||
log.debug('pieData.length = ' + pieData.length);
|
||||
expect(pieData).to.eql(expectedTableData);
|
||||
await PageObjects.visualize.navigateToNewVisualization();
|
||||
log.debug('clickPieChart');
|
||||
await PageObjects.visualize.clickPieChart();
|
||||
await PageObjects.visualize.clickNewSearch();
|
||||
log.debug(`Set absolute time range from "${fromTime}" to "${toTime}"`);
|
||||
await PageObjects.header.setAbsoluteRange(fromTime, toTime);
|
||||
log.debug('select bucket Split Slices');
|
||||
await PageObjects.visualize.clickBucket('Split Slices');
|
||||
log.debug('Click aggregation Terms');
|
||||
await PageObjects.visualize.selectAggregation('Terms');
|
||||
log.debug('Click field machine.os.raw');
|
||||
await PageObjects.visualize.selectField('machine.os.raw');
|
||||
await PageObjects.visualize.toggleOtherBucket();
|
||||
await PageObjects.visualize.toggleMissingBucket();
|
||||
log.debug('clickGo');
|
||||
await PageObjects.visualize.clickGo();
|
||||
await PageObjects.common.sleep(1003);
|
||||
const pieData = await PageObjects.visualize.getPieChartLabels();
|
||||
log.debug(`pieData.length = ${pieData.length}`);
|
||||
expect(pieData).to.eql(expectedTableData);
|
||||
});
|
||||
|
||||
it('should apply correct filter on other bucket', async () => {
|
||||
const expectedTableData = [ 'Missing', 'osx' ];
|
||||
|
||||
await PageObjects.visualize.filterPieSlice('Other');
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
const pieData = await PageObjects.visualize.getPieChartLabels();
|
||||
log.debug(`pieData.length = ${pieData.length}`);
|
||||
expect(pieData).to.eql(expectedTableData);
|
||||
await filterBar.removeFilter('machine.os.raw');
|
||||
});
|
||||
|
||||
it('should show two levels of other buckets', async () => {
|
||||
const expectedTableData = [ 'win 8', 'CN', 'IN', 'US', 'ID', 'BR', 'Other', 'win xp',
|
||||
'CN', 'IN', 'US', 'ID', 'BR', 'Other', 'win 7', 'CN', 'IN', 'US', 'ID', 'BR', 'Other',
|
||||
'ios', 'IN', 'CN', 'US', 'ID', 'BR', 'Other', 'Missing', 'CN', 'IN', 'US', 'BR', 'PK',
|
||||
'Other', 'Other', 'IN', 'CN', 'US', 'ID', 'BR', 'Other' ];
|
||||
|
||||
await PageObjects.visualize.toggleOpenEditor(2, 'false');
|
||||
await PageObjects.visualize.clickAddBucket();
|
||||
await PageObjects.visualize.clickBucket('Split Slices');
|
||||
await PageObjects.visualize.selectAggregation('Terms');
|
||||
log.debug('Click field geo.src');
|
||||
await PageObjects.visualize.selectField('geo.src');
|
||||
await PageObjects.visualize.toggleOtherBucket();
|
||||
await PageObjects.visualize.toggleMissingBucket();
|
||||
log.debug('clickGo');
|
||||
await PageObjects.visualize.clickGo();
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
const pieData = await PageObjects.visualize.getPieChartLabels();
|
||||
log.debug(`pieData.length = ${pieData.length}`);
|
||||
expect(pieData).to.eql(expectedTableData);
|
||||
});
|
||||
});
|
||||
|
||||
describe('disabled aggs', () => {
|
||||
|
|
|
@ -586,11 +586,11 @@ export function VisualizePageProvider({ getService, getPageObjects }) {
|
|||
}
|
||||
|
||||
async toggleOtherBucket() {
|
||||
return await find.clickByCssSelector('input[name="showOther"]');
|
||||
return await find.clickByCssSelector('vis-editor-agg-params:not(.ng-hide) input[name="showOther"]');
|
||||
}
|
||||
|
||||
async toggleMissingBucket() {
|
||||
return await find.clickByCssSelector('input[name="showMissing"]');
|
||||
return await find.clickByCssSelector('vis-editor-agg-params:not(.ng-hide) input[name="showMissing"]');
|
||||
}
|
||||
|
||||
async isApplyEnabled() {
|
||||
|
@ -1114,6 +1114,13 @@ export function VisualizePageProvider({ getService, getPageObjects }) {
|
|||
return await bucketType.click();
|
||||
}
|
||||
|
||||
async filterPieSlice(name) {
|
||||
const slice = await this.getPieSlice(name);
|
||||
// Since slice is an SVG element we can't simply use .click() for it
|
||||
await remote.moveMouseTo(slice);
|
||||
await remote.clickMouseButton();
|
||||
}
|
||||
|
||||
async getPieSlice(name) {
|
||||
return await testSubjects.find(`pieSlice-${name.split(' ').join('-')}`);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue