Skip to content

Commit

Permalink
[Maps] move apply global filter settting from layer to source (elasti…
Browse files Browse the repository at this point in the history
…c#50523)

* [Maps] move apply global filter settting from layer to source

* add checkbox to join UI

* update edit UI for grid and pew-pew source

* add migrations

* update docs

* remove setting of applyGlobalQuery from geojson upload

* upgrade SIEM layer descriptors

* fix jest tests and api integration tests

* fix functional tests

* fix functional test

* i18n

* review feedback

* doc re-wording

* i18n fixes
  • Loading branch information
nreese authored Nov 18, 2019
1 parent e5ef878 commit e2dc921
Show file tree
Hide file tree
Showing 36 changed files with 343 additions and 143 deletions.
9 changes: 6 additions & 3 deletions docs/maps/search.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ You can create a layer that requests data from {es} from the following:

** Grid aggregation source

** <<terms-join>>. The search context is applied to both the terms join and the vector source when the vector source is provided by Elasticsearch documents.
** <<terms-join>>

* <<heatmap-layer>> with Grid aggregation source

Expand Down Expand Up @@ -87,8 +87,11 @@ The most common cause for empty layers are searches for a field that exists in o
[[maps-disable-search-for-layer]]
==== Disable search for layer

To prevent the global search bar from applying search context to a layer, clear the *Apply global filter to layer* checkbox in Layer settings.
Disabling the search context applies to the layer source and all <<terms-join, term joins>> configured for the layer.
You can prevent the search bar from applying search context to a layer by configuring the following:

* In *Source settings*, clear the *Apply global filter to source* checkbox to turn off the global search context for the layer source.

* In *Term joins*, clear the *Apply global filter to join* checkbox to turn off the global search context for the <<terms-join, term join>>.

[float]
[[maps-add-index-search]]
Expand Down
3 changes: 3 additions & 0 deletions x-pack/legacy/plugins/maps/common/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ export const SOURCE_DATA_ID_ORIGIN = 'source';

export const GEOJSON_FILE = 'GEOJSON_FILE';

export const MIN_ZOOM = 0;
export const MAX_ZOOM = 24;

export const DECIMAL_DEGREES_PRECISION = 5; // meters precision
export const ZOOM_PRECISION = 2;
export const ES_SIZE_LIMIT = 10000;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import _ from 'lodash';
import {
ES_GEO_GRID,
ES_PEW_PEW,
ES_SEARCH,
} from '../constants';

function isEsSource(layerDescriptor) {
const sourceType = _.get(layerDescriptor, 'sourceDescriptor.type');
return [ES_GEO_GRID, ES_PEW_PEW, ES_SEARCH].includes(sourceType);
}

// Migration to move applyGlobalQuery from layer to sources.
// Moving to source to provide user the granularity needed to apply global filter per source.
export function moveApplyGlobalQueryToSources({ attributes }) {
if (!attributes.layerListJSON) {
return attributes;
}

const layerList = JSON.parse(attributes.layerListJSON);
layerList.forEach((layerDescriptor) => {

const applyGlobalQuery = _.get(layerDescriptor, 'applyGlobalQuery', true);
delete layerDescriptor.applyGlobalQuery;

if (isEsSource(layerDescriptor)) {
layerDescriptor.sourceDescriptor.applyGlobalQuery = applyGlobalQuery;
}

if (_.has(layerDescriptor, 'joins')) {
layerDescriptor.joins.forEach(joinDescriptor => {
if (_.has(joinDescriptor, 'right')) {
// joinDescriptor.right is ES_TERM_SOURCE source descriptor
joinDescriptor.right.applyGlobalQuery = applyGlobalQuery;
}
});
}

});

return {
...attributes,
layerListJSON: JSON.stringify(layerList),
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

/* eslint max-len: 0 */

import { moveApplyGlobalQueryToSources } from './move_apply_global_query';

describe('moveApplyGlobalQueryToSources', () => {

test('Should handle missing layerListJSON attribute', () => {
const attributes = {
title: 'my map',
};
expect(moveApplyGlobalQueryToSources({ attributes })).toEqual({
title: 'my map',
});
});

test('Should ignore layers without ES sources', () => {
const layerListJSON = JSON.stringify([
{
type: 'TILE',
sourceDescriptor: {
type: 'EMS_TMS'
}
}
]);
const attributes = {
title: 'my map',
layerListJSON
};
expect(moveApplyGlobalQueryToSources({ attributes })).toEqual({
title: 'my map',
layerListJSON,
});
});

test('Should move applyGlobalQuery from layer to source', () => {
const layerListJSON = JSON.stringify([
{
type: 'HEATMAP',
applyGlobalQuery: false,
sourceDescriptor: {
type: 'ES_GEO_GRID'
}
}
]);
const attributes = {
title: 'my map',
layerListJSON
};
expect(moveApplyGlobalQueryToSources({ attributes })).toEqual({
title: 'my map',
layerListJSON: '[{\"type\":\"HEATMAP\",\"sourceDescriptor\":{\"type\":\"ES_GEO_GRID\",\"applyGlobalQuery\":false}}]',
});
});

test('Should move applyGlobalQuery from layer to join', () => {
const layerListJSON = JSON.stringify([
{
type: 'VECTOR',
applyGlobalQuery: false,
sourceDescriptor: {
type: 'EMS_FILE'
},
joins: [
{
right: {}
}
]
}
]);
const attributes = {
title: 'my map',
layerListJSON
};
expect(moveApplyGlobalQueryToSources({ attributes })).toEqual({
title: 'my map',
layerListJSON: '[{\"type\":\"VECTOR\",\"sourceDescriptor\":{\"type\":\"EMS_FILE\"},\"joins\":[{\"right\":{\"applyGlobalQuery\":false}}]}]',
});
});

test('Should set applyGlobalQuery to true sources when no value is provided in layer', () => {
const layerListJSON = JSON.stringify([
{
type: 'VECTOR',
sourceDescriptor: {
type: 'ES_GEO_GRID'
},
joins: [
{
right: {}
}
]
}
]);
const attributes = {
title: 'my map',
layerListJSON
};
expect(moveApplyGlobalQueryToSources({ attributes })).toEqual({
title: 'my map',
layerListJSON: '[{\"type\":\"VECTOR\",\"sourceDescriptor\":{\"type\":\"ES_GEO_GRID\",\"applyGlobalQuery\":true},\"joins\":[{\"right\":{\"applyGlobalQuery\":true}}]}]',
});
});
});
9 changes: 9 additions & 0 deletions x-pack/legacy/plugins/maps/migrations.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import { extractReferences } from './common/migrations/references';
import { emsRasterTileToEmsVectorTile } from './common/migrations/ems_raster_tile_to_ems_vector_tile';
import { topHitsTimeToSort } from './common/migrations/top_hits_time_to_sort';
import { moveApplyGlobalQueryToSources } from './common/migrations/move_apply_global_query';

export const migrations = {
'map': {
Expand All @@ -30,6 +31,14 @@ export const migrations = {
'7.5.0': (doc) => {
const attributes = topHitsTimeToSort(doc);

return {
...doc,
attributes,
};
},
'7.6.0': (doc) => {
const attributes = moveApplyGlobalQueryToSources(doc);

return {
...doc,
attributes,
Expand Down
13 changes: 0 additions & 13 deletions x-pack/legacy/plugins/maps/public/actions/map_actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -634,19 +634,6 @@ export function setLayerQuery(id, query) {
};
}

export function setLayerApplyGlobalQuery(id, applyGlobalQuery) {
return (dispatch) => {
dispatch({
type: UPDATE_LAYER_PROP,
id,
propName: 'applyGlobalQuery',
newValue: applyGlobalQuery,
});

dispatch(syncDataForLayer(id));
};
}

export function removeSelectedLayer() {
return (dispatch, getState) => {
const state = getState();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ describe('kibana.yml configured with map.tilemap.url', () => {
alpha: 1,
__dataRequests: [],
id: layers[0].id,
applyGlobalQuery: true,
label: null,
maxZoom: 24,
minZoom: 0,
Expand Down Expand Up @@ -87,7 +86,6 @@ describe('EMS is enabled', () => {
alpha: 1,
__dataRequests: [],
id: layers[0].id,
applyGlobalQuery: true,
label: null,
maxZoom: 24,
minZoom: 0,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import React from 'react';
import { EuiFormRow, EuiSwitch } from '@elastic/eui';
import { i18n } from '@kbn/i18n';

const label = i18n.translate('xpack.maps.layerPanel.applyGlobalQueryCheckboxLabel', {
defaultMessage: `Apply global filter to source`,
});

export function GlobalFilterCheckbox({ applyGlobalQuery, customLabel, setApplyGlobalQuery }) {
const onApplyGlobalQueryChange = event => {
setApplyGlobalQuery(event.target.checked);
};

return (
<EuiFormRow
display="columnCompressedSwitch"
>
<EuiSwitch
label={customLabel ? customLabel : label}
checked={applyGlobalQuery}
onChange={onApplyGlobalQueryChange}
data-test-subj="mapLayerPanelApplyGlobalQueryCheckbox"
compressed
/>
</EuiFormRow>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ export class FilterEditor extends Component {
}

_loadIndexPatterns = async () => {
const indexPatternIds = this.props.layer.getIndexPatternIds();
// Filter only effects source so only load source indices.
const indexPatternIds = this.props.layer.getSource().getIndexPatternIds();
const indexPatterns = [];
const getIndexPatternPromises = indexPatternIds.map(async indexPatternId => {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { i18n } from '@kbn/i18n';
import { JoinExpression } from './join_expression';
import { MetricsExpression } from './metrics_expression';
import { WhereExpression } from './where_expression';
import { GlobalFilterCheckbox } from '../../../../components/global_filter_checkbox';

import {
indexPatternService,
Expand Down Expand Up @@ -168,6 +169,16 @@ export class Join extends Component {
});
}

_onApplyGlobalQueryChange = applyGlobalQuery => {
this.props.onChange({
leftField: this.props.join.leftField,
right: {
...this.props.join.right,
applyGlobalQuery,
},
});
}

render() {
const {
join,
Expand All @@ -184,6 +195,7 @@ export class Join extends Component {
const isJoinConfigComplete = join.leftField && right.indexPatternId && right.term;

let metricsExpression;
let globalFilterCheckbox;
if (isJoinConfigComplete) {
metricsExpression = (
<EuiFlexItem grow={false}>
Expand All @@ -194,6 +206,15 @@ export class Join extends Component {
/>
</EuiFlexItem>
);
globalFilterCheckbox = (
<GlobalFilterCheckbox
applyGlobalQuery={right.applyGlobalQuery}
setApplyGlobalQuery={this._onApplyGlobalQueryChange}
customLabel={i18n.translate('xpack.maps.layerPanel.join.applyGlobalQueryCheckboxLabel', {
defaultMessage: `Apply global filter to join`,
})}
/>
);
}

let whereExpression;
Expand Down Expand Up @@ -234,6 +255,8 @@ export class Join extends Component {

{whereExpression}

{globalFilterCheckbox}

<EuiButtonIcon
className="mapJoinItem__delete"
iconType="trash"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ export function JoinEditor({ joins, layer, onChange }) {
...joins,
{
right: {
id: uuid()
id: uuid(),
applyGlobalQuery: true,
}
}
]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,16 @@ import {
updateLayerMaxZoom,
updateLayerMinZoom,
updateLayerAlpha,
setLayerApplyGlobalQuery,
} from '../../../actions/map_actions';

function mapStateToProps(state = {}) {
const selectedLayer = getSelectedLayer(state);
return {
alpha: selectedLayer.getAlpha(),
applyGlobalQuery: selectedLayer.getApplyGlobalQuery(),
label: selectedLayer.getLabel(),
layerId: selectedLayer.getId(),
maxZoom: selectedLayer.getMaxZoom(),
minZoom: selectedLayer.getMinZoom(),
layer: selectedLayer
};
}

Expand All @@ -34,9 +31,6 @@ function mapDispatchToProps(dispatch) {
updateMinZoom: (id, minZoom) => dispatch(updateLayerMinZoom(id, minZoom)),
updateMaxZoom: (id, maxZoom) => dispatch(updateLayerMaxZoom(id, maxZoom)),
updateAlpha: (id, alpha) => dispatch(updateLayerAlpha(id, alpha)),
setLayerApplyGlobalQuery: (layerId, applyGlobalQuery) => {
dispatch(setLayerApplyGlobalQuery(layerId, applyGlobalQuery));
}
};
}

Expand Down
Loading

0 comments on commit e2dc921

Please sign in to comment.