diff --git a/x-pack/plugins/maps/common/descriptor_types/data_request_descriptor_types.ts b/x-pack/plugins/maps/common/descriptor_types/data_request_descriptor_types.ts index 17af934ce4837..996e556ca1704 100644 --- a/x-pack/plugins/maps/common/descriptor_types/data_request_descriptor_types.ts +++ b/x-pack/plugins/maps/common/descriptor_types/data_request_descriptor_types.ts @@ -21,8 +21,12 @@ export type Timeslice = { export type DataFilters = { buffer?: MapExtent; // extent with additional buffer extent?: MapExtent; // map viewport - filters: Filter[]; - query?: Query; + filters: Filter[]; // search bar filters + query?: Query; // search bar query + embeddableSearchContext?: { + query?: Query; + filters: Filter[]; + }; searchSessionId?: string; timeFilters: TimeRange; timeslice?: Timeslice; diff --git a/x-pack/plugins/maps/public/actions/map_action_constants.ts b/x-pack/plugins/maps/public/actions/map_action_constants.ts index 62fed40a4171c..aabca948ec80a 100644 --- a/x-pack/plugins/maps/public/actions/map_action_constants.ts +++ b/x-pack/plugins/maps/public/actions/map_action_constants.ts @@ -30,6 +30,7 @@ export const SET_LAYER_STYLE_META = 'SET_LAYER_STYLE_META'; export const UPDATE_SOURCE_PROP = 'UPDATE_SOURCE_PROP'; export const SET_MOUSE_COORDINATES = 'SET_MOUSE_COORDINATES'; export const CLEAR_MOUSE_COORDINATES = 'CLEAR_MOUSE_COORDINATES'; +export const SET_EMBEDDABLE_SEARCH_CONTEXT = 'SET_EMBEDDABLE_SEARCH_CONTEXT'; export const SET_GOTO = 'SET_GOTO'; export const CLEAR_GOTO = 'CLEAR_GOTO'; export const TRACK_CURRENT_LAYER_STATE = 'TRACK_CURRENT_LAYER_STATE'; diff --git a/x-pack/plugins/maps/public/actions/map_actions.ts b/x-pack/plugins/maps/public/actions/map_actions.ts index f21f09a6cff3b..f122d664ecf66 100644 --- a/x-pack/plugins/maps/public/actions/map_actions.ts +++ b/x-pack/plugins/maps/public/actions/map_actions.ts @@ -43,6 +43,7 @@ import { MAP_EXTENT_CHANGED, MAP_READY, ROLLBACK_MAP_SETTINGS, + SET_EMBEDDABLE_SEARCH_CONTEXT, SET_GOTO, SET_MAP_INIT_ERROR, SET_MAP_SETTINGS, @@ -340,6 +341,19 @@ export function setQuery({ }; } +export function setEmbeddableSearchContext({ + query, + filters, +}: { + filters: Filter[]; + query?: Query; +}) { + return { + type: SET_EMBEDDABLE_SEARCH_CONTEXT, + embeddableSearchContext: { filters, query }, + }; +} + export function updateDrawState(drawState: DrawState | null) { return (dispatch: Dispatch) => { if (drawState !== null) { diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/bounds_data.ts b/x-pack/plugins/maps/public/classes/layers/vector_layer/bounds_data.ts index 7136c9d0c2235..d7382782d1af7 100644 --- a/x-pack/plugins/maps/public/classes/layers/vector_layer/bounds_data.ts +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/bounds_data.ts @@ -39,6 +39,7 @@ export async function syncBoundsData({ query: dataFilters.query, timeFilters: dataFilters.timeFilters, timeslice: dataFilters.timeslice, + embeddableSearchContext: dataFilters.embeddableSearchContext, filters: dataFilters.filters, joinKeyFilter: dataFilters.joinKeyFilter, applyGlobalQuery: source.getApplyGlobalQuery(), diff --git a/x-pack/plugins/maps/public/classes/sources/es_source/es_source.ts b/x-pack/plugins/maps/public/classes/sources/es_source/es_source.ts index 1272438e11e39..8f2ac92415d44 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_source/es_source.ts +++ b/x-pack/plugins/maps/public/classes/sources/es_source/es_source.ts @@ -262,12 +262,27 @@ export class AbstractESSource extends AbstractVectorSource implements IESSource searchSource.setField('query', searchFilters.query); } + const parents = []; if (searchFilters.sourceQuery && !isFeatureEditorOpenForLayer) { const layerSearchSource = searchService.searchSource.createEmpty(); - layerSearchSource.setField('index', indexPattern); layerSearchSource.setField('query', searchFilters.sourceQuery); - searchSource.setParent(layerSearchSource); + parents.push(layerSearchSource); + } + + if (searchFilters.embeddableSearchContext && !isFeatureEditorOpenForLayer) { + const embeddableSearchSource = searchService.searchSource.createEmpty(); + embeddableSearchSource.setField('index', indexPattern); + embeddableSearchSource.setField('query', searchFilters.embeddableSearchContext.query); + embeddableSearchSource.setField('filter', searchFilters.embeddableSearchContext.filters); + parents.push(embeddableSearchSource); + } + + if (parents.length === 1) { + searchSource.setParent(parents[0]); + } else if (parents.length === 2) { + parents[1].setParent(parents[0]); + searchSource.setParent(parents[1]); } return searchSource; diff --git a/x-pack/plugins/maps/public/classes/sources/vector_source/vector_source.tsx b/x-pack/plugins/maps/public/classes/sources/vector_source/vector_source.tsx index 64082a85df6b7..0620386fda4c1 100644 --- a/x-pack/plugins/maps/public/classes/sources/vector_source/vector_source.tsx +++ b/x-pack/plugins/maps/public/classes/sources/vector_source/vector_source.tsx @@ -53,6 +53,10 @@ export interface BoundsRequestMeta { applyGlobalTime: boolean; filters: Filter[]; query?: Query; + embeddableSearchContext?: { + query?: Query; + filters: Filter[]; + }; sourceQuery?: Query; timeFilters: TimeRange; timeslice?: Timeslice; diff --git a/x-pack/plugins/maps/public/embeddable/map_embeddable.tsx b/x-pack/plugins/maps/public/embeddable/map_embeddable.tsx index d271ee053d8c7..76f6dbbb15133 100644 --- a/x-pack/plugins/maps/public/embeddable/map_embeddable.tsx +++ b/x-pack/plugins/maps/public/embeddable/map_embeddable.tsx @@ -36,6 +36,7 @@ import { setReadOnly, updateLayerById, setGotoWithCenter, + setEmbeddableSearchContext, } from '../actions'; import { getIsLayerTOCOpen, getOpenTOCDetails } from '../selectors/ui_selectors'; import { @@ -48,6 +49,7 @@ import { import { areLayersLoaded, getGeoFieldNames, + getEmbeddableSearchContext, getLayerList, getGoto, getMapCenter, @@ -194,6 +196,21 @@ export class MapEmbeddable forceRefresh: false, }); + const mapStateJSON = this._savedMap.getAttributes().mapStateJSON; + if (mapStateJSON) { + try { + const mapState = JSON.parse(mapStateJSON); + store.dispatch( + setEmbeddableSearchContext({ + filters: mapState.filters ? mapState.filters : [], + query: mapState.query, + }) + ); + } catch (e) { + // ignore malformed mapStateJSON, not a critical error for viewing map - map will just use defaults + } + } + this._unsubscribeFromStore = store.subscribe(() => { this._handleStoreChanges(); }); @@ -249,20 +266,18 @@ export class MapEmbeddable return this._isInitialized ? this._savedMap.getAttributes().description : ''; } - /** - * TODO: Implement this function once https://github.com/elastic/kibana/issues/91282 is resolved - * @returns [] - */ public async getFilters() { - return []; + const embeddableSearchContext = getEmbeddableSearchContext( + this._savedMap.getStore().getState() + ); + return embeddableSearchContext ? embeddableSearchContext.filters : []; } - /** - * TODO: Implement this function once https://github.com/elastic/kibana/issues/91282 is resolved - * @returns undefined - */ public async getQuery() { - return undefined; + const embeddableSearchContext = getEmbeddableSearchContext( + this._savedMap.getStore().getState() + ); + return embeddableSearchContext?.query; } public supportedTriggers(): string[] { diff --git a/x-pack/plugins/maps/public/reducers/map/map.ts b/x-pack/plugins/maps/public/reducers/map/map.ts index d0e77268fd58c..41de8ab0b8b0f 100644 --- a/x-pack/plugins/maps/public/reducers/map/map.ts +++ b/x-pack/plugins/maps/public/reducers/map/map.ts @@ -21,6 +21,7 @@ import { MAP_EXTENT_CHANGED, MAP_READY, MAP_DESTROYED, + SET_EMBEDDABLE_SEARCH_CONTEXT, SET_QUERY, UPDATE_LAYER, UPDATE_LAYER_PROP, @@ -313,6 +314,14 @@ export function map(state: MapState = DEFAULT_MAP_STATE, action: Record & { timeslice?: Timeslice; query?: Query; filters: Filter[]; + embeddableSearchContext?: { + query?: Query; + filters: Filter[]; + }; drawState?: DrawState; editState?: EditState; searchSessionId?: string; diff --git a/x-pack/plugins/maps/public/selectors/map_selectors.test.ts b/x-pack/plugins/maps/public/selectors/map_selectors.test.ts index baca2d79b833d..584bdd0160b8c 100644 --- a/x-pack/plugins/maps/public/selectors/map_selectors.test.ts +++ b/x-pack/plugins/maps/public/selectors/map_selectors.test.ts @@ -57,6 +57,7 @@ describe('getDataFilters', () => { const timeFilters = { to: '2001-01-01', from: '2001-12-31' }; const timeslice = undefined; const query = undefined; + const embeddableSearchContext = undefined; const filters: Filter[] = []; const searchSessionId = '12345'; const searchSessionMapBuffer = { @@ -76,6 +77,7 @@ describe('getDataFilters', () => { timeslice, query, filters, + embeddableSearchContext, searchSessionId, searchSessionMapBuffer, isReadOnly @@ -92,6 +94,7 @@ describe('getDataFilters', () => { timeslice, query, filters, + embeddableSearchContext, searchSessionId, undefined, isReadOnly diff --git a/x-pack/plugins/maps/public/selectors/map_selectors.ts b/x-pack/plugins/maps/public/selectors/map_selectors.ts index a069b07d1f2c6..8adb3f8f927ab 100644 --- a/x-pack/plugins/maps/public/selectors/map_selectors.ts +++ b/x-pack/plugins/maps/public/selectors/map_selectors.ts @@ -198,6 +198,9 @@ export const getQuery = ({ map }: MapStoreState): Query | undefined => map.mapSt export const getFilters = ({ map }: MapStoreState): Filter[] => map.mapState.filters; +export const getEmbeddableSearchContext = ({ map }: MapStoreState) => + map.mapState.embeddableSearchContext; + export const getSearchSessionId = ({ map }: MapStoreState): string | undefined => map.mapState.searchSessionId; @@ -239,6 +242,7 @@ export const getDataFilters = createSelector( getTimeslice, getQuery, getFilters, + getEmbeddableSearchContext, getSearchSessionId, getSearchSessionMapBuffer, getIsReadOnly, @@ -250,6 +254,7 @@ export const getDataFilters = createSelector( timeslice, query, filters, + embeddableSearchContext, searchSessionId, searchSessionMapBuffer, isReadOnly @@ -262,6 +267,7 @@ export const getDataFilters = createSelector( timeslice, query, filters, + embeddableSearchContext, searchSessionId, isReadOnly, }; diff --git a/x-pack/test/functional/apps/maps/group2/embeddable/dashboard.js b/x-pack/test/functional/apps/maps/group2/embeddable/dashboard.js index 11e81c3ecbbfc..00c80db1d4895 100644 --- a/x-pack/test/functional/apps/maps/group2/embeddable/dashboard.js +++ b/x-pack/test/functional/apps/maps/group2/embeddable/dashboard.js @@ -17,6 +17,7 @@ export default function ({ getPageObjects, getService }) { const browser = getService('browser'); const retry = getService('retry'); const security = getService('security'); + const testSubjects = getService('testSubjects'); describe('embed in dashboard', () => { before(async () => { @@ -25,7 +26,8 @@ export default function ({ getPageObjects, getService }) { 'test_logstash_reader', 'geoshape_data_reader', 'meta_for_geoshape_data_reader', - 'global_dashboard_read', + 'global_dashboard_all', + 'global_maps_all', ], { skipBrowserRefresh: true } ); @@ -121,6 +123,24 @@ export default function ({ getPageObjects, getService }) { expect(joinResponse.aggregations.join.buckets.length).to.equal(1); }); + it('should apply embeddable query and filters to panel', async () => { + // clear filters from previous test + await filterBar.removeAllFilters(); + + await PageObjects.dashboard.switchToEditMode(); + + await dashboardPanelActions.editPanelByTitle('geo grid vector grid example'); + await PageObjects.maps.waitForLayersToLoad(); + + await filterBar.addFilter('machine.os', 'is', 'ios'); + await PageObjects.maps.waitForLayersToLoad(); + await testSubjects.click('mapSaveAndReturnButton'); + const { rawResponse: gridResponse } = await PageObjects.maps.getResponseFromDashboardPanel( + 'geo grid vector grid example' + ); + expect(gridResponse.aggregations.gridSplit.buckets.length).to.equal(2); + }); + it('should re-fetch query when "refresh" is clicked', async () => { await dashboardPanelActions.openInspectorByTitle('geo grid vector grid example'); const beforeQueryRefreshTimestamp = await getRequestTimestamp();