diff --git a/x-pack/plugins/maps/public/components/distance_filter_form.tsx b/x-pack/plugins/maps/public/components/distance_filter_form.tsx index 14ae6b11b85c8..263ab1d6023d4 100644 --- a/x-pack/plugins/maps/public/components/distance_filter_form.tsx +++ b/x-pack/plugins/maps/public/components/distance_filter_form.tsx @@ -16,15 +16,15 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { ActionExecutionContext, Action } from 'src/plugins/ui_actions/public'; -import { MultiIndexGeoFieldSelect } from './multi_index_geo_field_select'; -import { GeoFieldWithIndex } from './geo_field_with_index'; +import { GeoFieldSelect } from './geo_field_select'; +import { IFieldType } from '../../../../../plugins/data/public'; import { ActionSelect } from './action_select'; import { ACTION_GLOBAL_APPLY_FILTER } from '../../../../../src/plugins/data/public'; interface Props { className?: string; buttonLabel: string; - geoFields: GeoFieldWithIndex[]; + geoFields: IFieldType[]; getFilterActions?: () => Promise; getActionContext?: () => ActionExecutionContext; onSubmit: ({ @@ -42,7 +42,7 @@ interface Props { interface State { actionId: string; - selectedField: GeoFieldWithIndex | undefined; + selectedField: IFieldType | undefined; filterLabel: string; } @@ -53,7 +53,7 @@ export class DistanceFilterForm extends Component { filterLabel: '', }; - _onGeoFieldChange = (selectedField: GeoFieldWithIndex | undefined) => { + _onGeoFieldChange = (selectedField: IFieldType | undefined) => { this.setState({ selectedField }); }; @@ -74,8 +74,7 @@ export class DistanceFilterForm extends Component { this.props.onSubmit({ actionId: this.state.actionId, filterLabel: this.state.filterLabel, - indexPatternId: this.state.selectedField.indexPatternId, - geoFieldName: this.state.selectedField.geoFieldName, + geoFieldName: this.state.selectedField, }); }; @@ -95,9 +94,9 @@ export class DistanceFilterForm extends Component { /> - diff --git a/x-pack/plugins/maps/public/components/geometry_filter_form.js b/x-pack/plugins/maps/public/components/geometry_filter_form.js index 624d3b60fe14b..fdb1373b6164f 100644 --- a/x-pack/plugins/maps/public/components/geometry_filter_form.js +++ b/x-pack/plugins/maps/public/components/geometry_filter_form.js @@ -20,7 +20,7 @@ import { import { i18n } from '@kbn/i18n'; import { ES_GEO_FIELD_TYPE, ES_SPATIAL_RELATIONS } from '../../common/constants'; import { getEsSpatialRelationLabel } from '../../common/i18n_getters'; -import { MultiIndexGeoFieldSelect } from './multi_index_geo_field_select'; +import { GeoFieldSelect } from './geo_field_select'; import { ActionSelect } from './action_select'; import { ACTION_GLOBAL_APPLY_FILTER } from '../../../../../src/plugins/data/public'; @@ -71,8 +71,7 @@ export class GeometryFilterForm extends Component { this.props.onSubmit({ actionId: this.state.actionId, geometryLabel: this.state.geometryLabel, - indexPatternId: this.state.selectedField.indexPatternId, - geoFieldName: this.state.selectedField.geoFieldName, + geoFieldName: this.state.selectedField, relation: this.state.relation, }); }; @@ -137,9 +136,9 @@ export class GeometryFilterForm extends Component { /> - diff --git a/x-pack/plugins/maps/public/connected_components/map_container/index.ts b/x-pack/plugins/maps/public/connected_components/map_container/index.ts index cda96792fc6d6..6ae19565ed1dc 100644 --- a/x-pack/plugins/maps/public/connected_components/map_container/index.ts +++ b/x-pack/plugins/maps/public/connected_components/map_container/index.ts @@ -16,7 +16,7 @@ import { getRefreshConfig, getMapInitError, getMapSettings, - getQueryableUniqueIndexPatternIds, + getQueryableUniqueIndexPatternIdsAndFieldNames, } from '../../selectors/map_selectors'; import { MapStoreState } from '../../reducers/store'; import { getCoreChrome } from '../../kibana_services'; @@ -28,7 +28,7 @@ function mapStateToProps(state: MapStoreState) { isFullScreen: getIsFullScreen(state), refreshConfig: getRefreshConfig(state), mapInitError: getMapInitError(state), - indexPatternIds: getQueryableUniqueIndexPatternIds(state), + indexPatternIdsAndFieldNames: getQueryableUniqueIndexPatternIdsAndFieldNames(state), settings: getMapSettings(state), }; } diff --git a/x-pack/plugins/maps/public/connected_components/map_container/map_container.tsx b/x-pack/plugins/maps/public/connected_components/map_container/map_container.tsx index e0cfe978bf45c..dbe5a943da49b 100644 --- a/x-pack/plugins/maps/public/connected_components/map_container/map_container.tsx +++ b/x-pack/plugins/maps/public/connected_components/map_container/map_container.tsx @@ -20,7 +20,7 @@ import { ToolbarOverlay } from '../toolbar_overlay'; import { LayerPanel } from '../layer_panel'; import { AddLayerPanel } from '../add_layer_panel'; import { ExitFullScreenButton } from '../../../../../../src/plugins/kibana_react/public'; -import { getIndexPatternsFromIds } from '../../index_pattern_util'; +import { getFieldsFromIds, getGeoFields } from '../../index_pattern_util'; import { ES_GEO_FIELD_TYPE, RawValue } from '../../../common/constants'; import { indexPatterns as indexPatternsUtils } from '../../../../../../src/plugins/data/public'; import { FLYOUT_STATE } from '../../reducers/ui'; @@ -28,7 +28,7 @@ import { MapSettings } from '../../reducers/map'; import { MapSettingsPanel } from '../map_settings_panel'; import { registerLayerWizards } from '../../classes/layers/load_layer_wizards'; import { RenderToolTipContent } from '../../classes/tooltips/tooltip_property'; -import { GeoFieldWithIndex } from '../../components/geo_field_with_index'; +import { IFieldType } from '../../../../../../src/plugins/data/public'; import { MapRefreshConfig } from '../../../common/descriptor_types'; import 'mapbox-gl/dist/mapbox-gl.css'; @@ -44,7 +44,7 @@ export interface Props { exitFullScreen: () => void; flyoutDisplay: FLYOUT_STATE; isFullScreen: boolean; - indexPatternIds: string[]; + indexPatternIdsAndFieldNames: Array<{ indexPatternId: string; fieldName: string }>; mapInitError: string | null | undefined; refreshConfig: MapRefreshConfig; renderTooltipContent?: RenderToolTipContent; @@ -57,13 +57,16 @@ export interface Props { interface State { isInitialLoadRenderTimeoutComplete: boolean; domId: string; - geoFields: GeoFieldWithIndex[]; + geoFields: IFieldType[]; } export class MapContainer extends Component { private _isMounted: boolean = false; private _isInitalLoadRenderTimerStarted: boolean = false; - private _prevIndexPatternIds: string[] = []; + private _prevIndexPatternIdsAndFieldNames: Array<{ + indexPatternId: string; + fieldName: string; + }> = []; private _refreshTimerId: number | null = null; private _prevIsPaused: boolean | null = null; private _prevInterval: number | null = null; @@ -88,7 +91,7 @@ export class MapContainer extends Component { } if (!!this.props.addFilters) { - this._loadGeoFields(this.props.indexPatternIds); + this._loadGeoFields(this.props.indexPatternIdsAndFieldNames); } } @@ -113,37 +116,22 @@ export class MapContainer extends Component { } }; - _loadGeoFields = async (nextIndexPatternIds: string[]) => { - if (_.isEqual(nextIndexPatternIds, this._prevIndexPatternIds)) { + _loadGeoFields = async ( + nextIndexPatternIdsAndFieldNames: Array<{ indexPatternId: string; fieldName: string }> + ) => { + if (_.isEqual(nextIndexPatternIdsAndFieldNames, this._prevIndexPatternIdsAndFieldNames)) { // all ready loaded index pattern ids return; } - this._prevIndexPatternIds = nextIndexPatternIds; - - const geoFields: GeoFieldWithIndex[] = []; - const indexPatterns = await getIndexPatternsFromIds(nextIndexPatternIds); - indexPatterns.forEach((indexPattern) => { - indexPattern.fields.forEach((field) => { - if ( - indexPattern.id && - !indexPatternsUtils.isNestedField(field) && - (field.type === ES_GEO_FIELD_TYPE.GEO_POINT || field.type === ES_GEO_FIELD_TYPE.GEO_SHAPE) - ) { - geoFields.push({ - geoFieldName: field.name, - geoFieldType: field.type, - indexPatternTitle: indexPattern.title, - indexPatternId: indexPattern.id, - }); - } - }); - }); + this._prevIndexPatternIdsAndFieldNames = nextIndexPatternIdsAndFieldNames; + const queryableFields = await getFieldsFromIds(nextIndexPatternIdsAndFieldNames); + let geoFields: IFieldType[] = getGeoFields(_.map(queryableFields, 'field')); + geoFields = _.uniqWith(geoFields, _.isEqual); if (!this._isMounted) { return; } - this.setState({ geoFields }); }; diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/draw_control/draw_filter_control/draw_filter_control.tsx b/x-pack/plugins/maps/public/connected_components/mb_map/draw_control/draw_filter_control/draw_filter_control.tsx index e6359394cd741..80bbc8bce19c7 100644 --- a/x-pack/plugins/maps/public/connected_components/mb_map/draw_control/draw_filter_control/draw_filter_control.tsx +++ b/x-pack/plugins/maps/public/connected_components/mb_map/draw_control/draw_filter_control/draw_filter_control.tsx @@ -33,12 +33,7 @@ export interface Props { export class DrawFilterControl extends Component { _onDraw = async (e: { features: Feature[] }) => { - if ( - !e.features.length || - !this.props.drawState || - !this.props.drawState.geoFieldName || - !this.props.drawState.indexPatternId - ) { + if (!e.features.length || !this.props.drawState || !this.props.drawState.geoFieldName) { return; } diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/features_tooltip/feature_geometry_filter_form.tsx b/x-pack/plugins/maps/public/connected_components/mb_map/features_tooltip/feature_geometry_filter_form.tsx index 61732d1c268c2..6c84848478863 100644 --- a/x-pack/plugins/maps/public/connected_components/mb_map/features_tooltip/feature_geometry_filter_form.tsx +++ b/x-pack/plugins/maps/public/connected_components/mb_map/features_tooltip/feature_geometry_filter_form.tsx @@ -21,7 +21,7 @@ import { import { ES_SPATIAL_RELATIONS, GEO_JSON_TYPE } from '../../../../common/constants'; // @ts-expect-error import { GeometryFilterForm } from '../../../components/geometry_filter_form'; -import { GeoFieldWithIndex } from '../../../components/geo_field_with_index'; +import { IFieldType } from '../../../../../../../src/plugins/data/public'; // over estimated and imprecise value to ensure filter has additional room for any meta keys added when filter is mapped. const META_OVERHEAD = 100; @@ -29,7 +29,7 @@ const META_OVERHEAD = 100; interface Props { onClose: () => void; geometry: Geometry; - geoFields: GeoFieldWithIndex[]; + geoFields: IFieldType[]; addFilters: (filters: Filter[], actionId: string) => Promise; getFilterActions?: () => Promise; getActionContext?: () => ActionExecutionContext; diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx b/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx index 9ec6cbcb5d4ac..6b19097623c76 100644 --- a/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx +++ b/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx @@ -42,7 +42,7 @@ import { // @ts-expect-error } from './utils'; import { ResizeChecker } from '../../../../../../src/plugins/kibana_utils/public'; -import { GeoFieldWithIndex } from '../../components/geo_field_with_index'; +import { IFieldType } from '../../../../../../src/plugins/data/public'; import { RenderToolTipContent } from '../../classes/tooltips/tooltip_property'; import { MapExtentState } from '../../actions'; import { TileStatusTracker } from './tile_status_tracker'; @@ -74,7 +74,7 @@ export interface Props { getFilterActions?: () => Promise; getActionContext?: () => ActionExecutionContext; onSingleValueTrigger?: (actionId: string, key: string, value: RawValue) => void; - geoFields: GeoFieldWithIndex[]; + geoFields: IFieldType[]; renderTooltipContent?: RenderToolTipContent; setAreTilesLoaded: (layerId: string, areTilesLoaded: boolean) => void; } diff --git a/x-pack/plugins/maps/public/connected_components/toolbar_overlay/toolbar_overlay.tsx b/x-pack/plugins/maps/public/connected_components/toolbar_overlay/toolbar_overlay.tsx index c5208bc254fc8..8aef1076e61f2 100644 --- a/x-pack/plugins/maps/public/connected_components/toolbar_overlay/toolbar_overlay.tsx +++ b/x-pack/plugins/maps/public/connected_components/toolbar_overlay/toolbar_overlay.tsx @@ -7,16 +7,15 @@ import React from 'react'; import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import { Filter } from 'src/plugins/data/public'; +import { IFieldType, Filter } from 'src/plugins/data/public'; import { ActionExecutionContext, Action } from 'src/plugins/ui_actions/public'; import { SetViewControl } from './set_view_control'; import { ToolsControl } from './tools_control'; import { FitToData } from './fit_to_data'; -import { GeoFieldWithIndex } from '../../components/geo_field_with_index'; export interface Props { addFilters?: ((filters: Filter[], actionId: string) => Promise) | null; - geoFields: GeoFieldWithIndex[]; + geoFields: IFieldType[]; getFilterActions?: () => Promise; getActionContext?: () => ActionExecutionContext; } diff --git a/x-pack/plugins/maps/public/connected_components/toolbar_overlay/tools_control/tools_control.tsx b/x-pack/plugins/maps/public/connected_components/toolbar_overlay/tools_control/tools_control.tsx index 6779fe945137e..9dc8faff43cc3 100644 --- a/x-pack/plugins/maps/public/connected_components/toolbar_overlay/tools_control/tools_control.tsx +++ b/x-pack/plugins/maps/public/connected_components/toolbar_overlay/tools_control/tools_control.tsx @@ -22,7 +22,7 @@ import { DRAW_TYPE, ES_GEO_FIELD_TYPE, ES_SPATIAL_RELATIONS } from '../../../../ // @ts-expect-error import { GeometryFilterForm } from '../../../components/geometry_filter_form'; import { DistanceFilterForm } from '../../../components/distance_filter_form'; -import { GeoFieldWithIndex } from '../../../components/geo_field_with_index'; +import { IFieldType } from '../../../../../plugins/data/public'; import { DrawState } from '../../../../common/descriptor_types'; const DRAW_SHAPE_LABEL = i18n.translate('xpack.maps.toolbarOverlay.drawShapeLabel', { @@ -54,7 +54,7 @@ const DRAW_DISTANCE_LABEL_SHORT = i18n.translate( export interface Props { cancelDraw: () => void; - geoFields: GeoFieldWithIndex[]; + geoFields: IFieldType[]; initiateDraw: (drawState: DrawState) => void; isDrawingFilter: boolean; getFilterActions?: () => Promise; diff --git a/x-pack/plugins/maps/public/index_pattern_util.ts b/x-pack/plugins/maps/public/index_pattern_util.ts index 3b1cb461c8779..c4771e62d9994 100644 --- a/x-pack/plugins/maps/public/index_pattern_util.ts +++ b/x-pack/plugins/maps/public/index_pattern_util.ts @@ -29,6 +29,27 @@ export function getGeoTileAggNotSupportedReason(field: IFieldType): string | nul return null; } +export async function getFieldFromIndexByName(indexPatternId: string, fieldName: string) { + const indexPattern = await getIndexPatternService().get(indexPatternId); + const field = indexPattern.fields.getByName(fieldName); + return { indexPattern, field }; +} + +export async function getFieldsFromIds(indexPatternIdsWithFields) { + const promises: IndexPattern[] = []; + indexPatternIdsWithFields.forEach(async ({ indexPatternId, fieldName }) => { + try { + // @ts-ignore + promises.push(getFieldFromIndexByName(indexPatternId, fieldName)); + } catch (error) { + // Unable to load index pattern, better to not throw error so map can render + // Error will be surfaced by layer since it too will be unable to locate the index pattern + return null; + } + }); + return await Promise.all(promises); +} + export async function getIndexPatternsFromIds( indexPatternIds: string[] = [] ): Promise { diff --git a/x-pack/plugins/maps/public/routes/map_page/map_app/index.ts b/x-pack/plugins/maps/public/routes/map_page/map_app/index.ts index 62e645198ba30..968d9afc34369 100644 --- a/x-pack/plugins/maps/public/routes/map_page/map_app/index.ts +++ b/x-pack/plugins/maps/public/routes/map_page/map_app/index.ts @@ -14,7 +14,7 @@ import { getFlyoutDisplay, getIsFullScreen } from '../../../selectors/ui_selecto import { getFilters, getQuery, - getQueryableUniqueIndexPatternIds, + getQueryableUniqueIndexPatternIdsAndFieldNames, getRefreshConfig, getTimeFilters, hasDirtyState, @@ -31,7 +31,7 @@ function mapStateToProps(state: MapStoreState) { isOpenSettingsDisabled: getFlyoutDisplay(state) !== FLYOUT_STATE.NONE, isSaveDisabled: hasDirtyState(state), inspectorAdapters: getInspectorAdapters(state), - nextIndexPatternIds: getQueryableUniqueIndexPatternIds(state), + nextIndexPatternIdsAndFieldNames: getQueryableUniqueIndexPatternIdsAndFieldNames(state), flyoutDisplay: getFlyoutDisplay(state), refreshConfig: getRefreshConfig(state), filters: getFilters(state), diff --git a/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx b/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx index 6a31e25197210..3fa490ac9599c 100644 --- a/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx +++ b/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx @@ -37,7 +37,10 @@ import { QueryState, } from '../../../../../../../src/plugins/data/public'; import { MapContainer } from '../../../connected_components/map_container'; -import { getIndexPatternsFromIds } from '../../../index_pattern_util'; +import { + getIndexPatternsFromIds, + getQueryableUniqueIndexPatternIdsAndFieldNames, +} from '../../../index_pattern_util'; import { getTopNavConfig } from '../top_nav_config'; import { MapRefreshConfig, MapQuery } from '../../../../common/descriptor_types'; import { goToSpecifiedPath } from '../../../render_app'; @@ -63,7 +66,7 @@ export interface Props { enableFullScreen: () => void; openMapSettings: () => void; inspectorAdapters: Adapters; - nextIndexPatternIds: string[]; + nextIndexPatternIdsAndFieldNames: Array<{ indexPatternId: string; fieldName: string }>; dispatchSetQuery: ({ forceRefresh, filters, @@ -94,7 +97,10 @@ export class MapApp extends React.Component { _globalSyncChangeMonitorSubscription: Subscription | null = null; _appSyncUnsubscribe: (() => void) | null = null; _appStateManager = new AppStateManager(); - _prevIndexPatternIds: string[] | null = null; + _prevIndexPatternIdsAndFieldNames: Array<{ + indexPatternId: string; + fieldName: string; + }> | null = null; _isMounted: boolean = false; constructor(props: Props) { @@ -131,7 +137,7 @@ export class MapApp extends React.Component { } componentDidUpdate() { - this._updateIndexPatterns(); + this._updateIndexPatternsAndFieldNames(); } componentWillUnmount() { @@ -166,16 +172,17 @@ export class MapApp extends React.Component { this._onQueryChange({ time: globalState.time }); }; - async _updateIndexPatterns() { - const { nextIndexPatternIds } = this.props; + async _updateIndexPatternsAndFieldNames() { + const { nextIndexPatternIdsAndFieldNames } = this.props; - if (_.isEqual(nextIndexPatternIds, this._prevIndexPatternIds)) { + if (_.isEqual(nextIndexPatternIdsAndFieldNames, this._prevIndexPatternIdsAndFieldNames)) { return; } - this._prevIndexPatternIds = nextIndexPatternIds; + this._prevIndexPatternIdsAndFieldNames = nextIndexPatternIdsAndFieldNames; - const indexPatterns = await getIndexPatternsFromIds(nextIndexPatternIds); + const indexPatternIds = _.map(nextIndexPatternIdsAndFieldNames, 'indexPatternId'); + const indexPatterns = await getIndexPatternsFromIds(indexPatternIds); if (this._isMounted) { this.setState({ indexPatterns }); } diff --git a/x-pack/plugins/maps/public/selectors/map_selectors.ts b/x-pack/plugins/maps/public/selectors/map_selectors.ts index a818cdd2d00f9..04d2a8d95ee96 100644 --- a/x-pack/plugins/maps/public/selectors/map_selectors.ts +++ b/x-pack/plugins/maps/public/selectors/map_selectors.ts @@ -24,6 +24,7 @@ import { import { TiledVectorLayer } from '../classes/layers/tiled_vector_layer/tiled_vector_layer'; import { copyPersistentState, TRACKED_LAYER_DESCRIPTOR } from '../reducers/copy_persistent_state'; import { InnerJoin } from '../classes/joins/inner_join'; +import { IESSource } from '../classes/sources/es_source'; import { getSourceByType } from '../classes/sources/source_registry'; import { GeoJsonFileSource } from '../classes/sources/geojson_file_source'; import { @@ -401,6 +402,39 @@ export const getQueryableUniqueIndexPatternIds = createSelector( } ); +// Get list of unique index patterns, excluding index patterns from layers that disable applyGlobalQuery +export const getQueryableUniqueIndexPatternIdsAndFieldNames = createSelector( + getLayerList, + getWaitingForMapReadyLayerListRaw, + (layerList, waitingForMapReadyLayerList) => { + const indexPatternIdsAndFieldNames: Array<{ indexPatternId: string; fieldName: string }> = []; + + if (waitingForMapReadyLayerList.length) { + waitingForMapReadyLayerList.forEach((layerDescriptor) => { + const layer = createLayerInstance(layerDescriptor); + const indexPatternIds = layer.getQueryableIndexPatternIds(); + if (layer.getSource().isESSource()) { + const fieldName = (layer.getSource() as IESSource).getGeoFieldName(); + indexPatternIds.forEach((indexPatternId) => { + indexPatternIdsAndFieldNames.push({ indexPatternId, fieldName }); + }); + } + }); + } else { + layerList.forEach((layer) => { + const indexPatternIds = layer.getQueryableIndexPatternIds(); + if (layer.getSource().isESSource()) { + const fieldName = (layer.getSource() as IESSource).getGeoFieldName(); + indexPatternIds.forEach((indexPatternId) => { + indexPatternIdsAndFieldNames.push({ indexPatternId, fieldName }); + }); + } + }); + } + return _.uniq(indexPatternIdsAndFieldNames); + } +); + export const hasDirtyState = createSelector(getLayerListRaw, (layerListRaw) => { return layerListRaw.some((layerDescriptor) => { if (layerDescriptor.__isPreviewLayer) {