mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[Maps] fix Filters applied to map visualization not preserved when added to dashboard (#138188)
* [Maps] fix Tool tip with large field list exceeds browser screen and cannot be accessed or dismissed * add min-width to mapFeatureTooltip__propertyLabel * [Maps] fix Filters applied to map visualization not preserved when added to dashboard * clean up * [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' * clean-up * publish query and filter to container * [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' * fix checks * tslint and add to bounds filter * functional test * review feedback Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
cb8cf84720
commit
7303ef8991
12 changed files with 111 additions and 15 deletions
|
@ -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;
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -53,6 +53,10 @@ export interface BoundsRequestMeta {
|
|||
applyGlobalTime: boolean;
|
||||
filters: Filter[];
|
||||
query?: Query;
|
||||
embeddableSearchContext?: {
|
||||
query?: Query;
|
||||
filters: Filter[];
|
||||
};
|
||||
sourceQuery?: Query;
|
||||
timeFilters: TimeRange;
|
||||
timeslice?: Timeslice;
|
||||
|
|
|
@ -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[] {
|
||||
|
|
|
@ -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<string,
|
|||
visible: !action.hiddenLayerIds.includes(layer.id),
|
||||
})),
|
||||
};
|
||||
case SET_EMBEDDABLE_SEARCH_CONTEXT:
|
||||
return {
|
||||
...state,
|
||||
mapState: {
|
||||
...state.mapState,
|
||||
embeddableSearchContext: action.embeddableSearchContext,
|
||||
},
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
|
|
@ -41,6 +41,10 @@ export type MapContext = Partial<MapViewContext> & {
|
|||
timeslice?: Timeslice;
|
||||
query?: Query;
|
||||
filters: Filter[];
|
||||
embeddableSearchContext?: {
|
||||
query?: Query;
|
||||
filters: Filter[];
|
||||
};
|
||||
drawState?: DrawState;
|
||||
editState?: EditState;
|
||||
searchSessionId?: string;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue