mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[Maps] Fix fit to bounds requests not getting canceled (#67629)
* rename data request constants * register cancel callback * clean up
This commit is contained in:
parent
043ecaca1a
commit
e28028b36c
17 changed files with 219 additions and 147 deletions
|
@ -72,11 +72,12 @@ export enum FIELD_ORIGIN {
|
|||
}
|
||||
export const JOIN_FIELD_NAME_PREFIX = '__kbnjoin__';
|
||||
|
||||
export const SOURCE_DATA_ID_ORIGIN = 'source';
|
||||
export const META_ID_ORIGIN_SUFFIX = 'meta';
|
||||
export const SOURCE_META_ID_ORIGIN = `${SOURCE_DATA_ID_ORIGIN}_${META_ID_ORIGIN_SUFFIX}`;
|
||||
export const FORMATTERS_ID_ORIGIN_SUFFIX = 'formatters';
|
||||
export const SOURCE_FORMATTERS_ID_ORIGIN = `${SOURCE_DATA_ID_ORIGIN}_${FORMATTERS_ID_ORIGIN_SUFFIX}`;
|
||||
export const META_DATA_REQUEST_ID_SUFFIX = 'meta';
|
||||
export const FORMATTERS_DATA_REQUEST_ID_SUFFIX = 'formatters';
|
||||
export const SOURCE_DATA_REQUEST_ID = 'source';
|
||||
export const SOURCE_META_DATA_REQUEST_ID = `${SOURCE_DATA_REQUEST_ID}_${META_DATA_REQUEST_ID_SUFFIX}`;
|
||||
export const SOURCE_FORMATTERS_DATA_REQUEST_ID = `${SOURCE_DATA_REQUEST_ID}_${FORMATTERS_DATA_REQUEST_ID_SUFFIX}`;
|
||||
export const SOURCE_BOUNDS_DATA_REQUEST_ID = `${SOURCE_DATA_REQUEST_ID}_bounds`;
|
||||
|
||||
export const MIN_ZOOM = 0;
|
||||
export const MAX_ZOOM = 24;
|
||||
|
|
|
@ -6,12 +6,15 @@
|
|||
/* eslint-disable @typescript-eslint/consistent-type-definitions */
|
||||
|
||||
import { Dispatch } from 'redux';
|
||||
// @ts-ignore
|
||||
import turf from 'turf';
|
||||
import { FeatureCollection } from 'geojson';
|
||||
import { MapStoreState } from '../reducers/store';
|
||||
import { LAYER_TYPE, SOURCE_DATA_ID_ORIGIN } from '../../common/constants';
|
||||
import { LAYER_TYPE, SOURCE_DATA_REQUEST_ID } from '../../common/constants';
|
||||
import {
|
||||
getDataFilters,
|
||||
getDataRequestDescriptor,
|
||||
getFittableLayers,
|
||||
getLayerById,
|
||||
getLayerList,
|
||||
} from '../selectors/map_selectors';
|
||||
|
@ -27,13 +30,15 @@ import {
|
|||
LAYER_DATA_LOAD_ENDED,
|
||||
LAYER_DATA_LOAD_ERROR,
|
||||
LAYER_DATA_LOAD_STARTED,
|
||||
SET_GOTO,
|
||||
SET_LAYER_ERROR_STATUS,
|
||||
SET_LAYER_STYLE_META,
|
||||
UPDATE_LAYER_PROP,
|
||||
UPDATE_SOURCE_DATA_REQUEST,
|
||||
} from './map_action_constants';
|
||||
import { ILayer } from '../classes/layers/layer';
|
||||
import { DataMeta, MapFilters } from '../../common/descriptor_types';
|
||||
import { DataMeta, MapExtent, MapFilters } from '../../common/descriptor_types';
|
||||
import { DataRequestAbortError } from '../classes/util/data_request';
|
||||
|
||||
export type DataRequestContext = {
|
||||
startLoading(dataId: string, requestToken: symbol, meta: DataMeta): void;
|
||||
|
@ -269,7 +274,7 @@ export function updateSourceDataRequest(layerId: string, newData: unknown) {
|
|||
return (dispatch: Dispatch) => {
|
||||
dispatch({
|
||||
type: UPDATE_SOURCE_DATA_REQUEST,
|
||||
dataId: SOURCE_DATA_ID_ORIGIN,
|
||||
dataId: SOURCE_DATA_REQUEST_ID,
|
||||
layerId,
|
||||
newData,
|
||||
});
|
||||
|
@ -277,3 +282,99 @@ export function updateSourceDataRequest(layerId: string, newData: unknown) {
|
|||
dispatch<any>(updateStyleMeta(layerId));
|
||||
};
|
||||
}
|
||||
|
||||
export function fitToLayerExtent(layerId: string) {
|
||||
return async (dispatch: Dispatch, getState: () => MapStoreState) => {
|
||||
const targetLayer = getLayerById(layerId, getState());
|
||||
|
||||
if (targetLayer) {
|
||||
try {
|
||||
const bounds = await targetLayer.getBounds(
|
||||
getDataRequestContext(dispatch, getState, layerId)
|
||||
);
|
||||
if (bounds) {
|
||||
await dispatch(setGotoWithBounds(bounds));
|
||||
}
|
||||
} catch (error) {
|
||||
if (!(error instanceof DataRequestAbortError)) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(
|
||||
'Unhandled getBounds error for layer. Only DataRequestAbortError should be surfaced',
|
||||
error
|
||||
);
|
||||
}
|
||||
// new fitToLayerExtent request has superseded this thread of execution. Results no longer needed.
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function fitToDataBounds() {
|
||||
return async (dispatch: Dispatch, getState: () => MapStoreState) => {
|
||||
const layerList = getFittableLayers(getState());
|
||||
|
||||
if (!layerList.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const boundsPromises = layerList.map(async (layer: ILayer) => {
|
||||
return layer.getBounds(getDataRequestContext(dispatch, getState, layer.getId()));
|
||||
});
|
||||
|
||||
let bounds;
|
||||
try {
|
||||
bounds = await Promise.all(boundsPromises);
|
||||
} catch (error) {
|
||||
if (!(error instanceof DataRequestAbortError)) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(
|
||||
'Unhandled getBounds error for layer. Only DataRequestAbortError should be surfaced',
|
||||
error
|
||||
);
|
||||
}
|
||||
// new fitToDataBounds request has superseded this thread of execution. Results no longer needed.
|
||||
return;
|
||||
}
|
||||
|
||||
const corners = [];
|
||||
for (let i = 0; i < bounds.length; i++) {
|
||||
const b = bounds[i];
|
||||
|
||||
// filter out undefined bounds (uses Infinity due to turf responses)
|
||||
if (
|
||||
b === null ||
|
||||
b.minLon === Infinity ||
|
||||
b.maxLon === Infinity ||
|
||||
b.minLat === -Infinity ||
|
||||
b.maxLat === -Infinity
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
corners.push([b.minLon, b.minLat]);
|
||||
corners.push([b.maxLon, b.maxLat]);
|
||||
}
|
||||
|
||||
if (!corners.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const turfUnionBbox = turf.bbox(turf.multiPoint(corners));
|
||||
const dataBounds = {
|
||||
minLon: turfUnionBbox[0],
|
||||
minLat: turfUnionBbox[1],
|
||||
maxLon: turfUnionBbox[2],
|
||||
maxLat: turfUnionBbox[3],
|
||||
};
|
||||
|
||||
dispatch(setGotoWithBounds(dataBounds));
|
||||
};
|
||||
}
|
||||
|
||||
function setGotoWithBounds(bounds: MapExtent) {
|
||||
return {
|
||||
type: SET_GOTO,
|
||||
bounds,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -9,7 +9,12 @@ export * from './ui_actions';
|
|||
export * from './map_actions';
|
||||
export * from './map_action_constants';
|
||||
export * from './layer_actions';
|
||||
export { cancelAllInFlightRequests, DataRequestContext } from './data_request_actions';
|
||||
export {
|
||||
cancelAllInFlightRequests,
|
||||
DataRequestContext,
|
||||
fitToLayerExtent,
|
||||
fitToDataBounds,
|
||||
} from './data_request_actions';
|
||||
export {
|
||||
closeOnClickTooltip,
|
||||
openOnClickTooltip,
|
||||
|
|
|
@ -12,11 +12,9 @@ import turfBooleanContains from '@turf/boolean-contains';
|
|||
import { Filter, Query, TimeRange } from 'src/plugins/data/public';
|
||||
import { MapStoreState } from '../reducers/store';
|
||||
import {
|
||||
getLayerById,
|
||||
getDataFilters,
|
||||
getWaitingForMapReadyLayerListRaw,
|
||||
getQuery,
|
||||
getFittableLayers,
|
||||
} from '../selectors/map_selectors';
|
||||
import {
|
||||
CLEAR_GOTO,
|
||||
|
@ -184,76 +182,6 @@ export function disableScrollZoom() {
|
|||
return { type: SET_SCROLL_ZOOM, scrollZoom: false };
|
||||
}
|
||||
|
||||
export function fitToLayerExtent(layerId: string) {
|
||||
return async (dispatch: Dispatch, getState: () => MapStoreState) => {
|
||||
const targetLayer = getLayerById(layerId, getState());
|
||||
|
||||
if (targetLayer) {
|
||||
const dataFilters = getDataFilters(getState());
|
||||
const bounds = await targetLayer.getBounds(dataFilters);
|
||||
if (bounds) {
|
||||
await dispatch(setGotoWithBounds(bounds));
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function fitToDataBounds() {
|
||||
return async (dispatch: Dispatch, getState: () => MapStoreState) => {
|
||||
const layerList = getFittableLayers(getState());
|
||||
|
||||
if (!layerList.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const dataFilters = getDataFilters(getState());
|
||||
const boundsPromises = layerList.map(async (layer) => {
|
||||
return layer.getBounds(dataFilters);
|
||||
});
|
||||
|
||||
const bounds = await Promise.all(boundsPromises);
|
||||
const corners = [];
|
||||
for (let i = 0; i < bounds.length; i++) {
|
||||
const b = bounds[i];
|
||||
|
||||
// filter out undefined bounds (uses Infinity due to turf responses)
|
||||
if (
|
||||
b === null ||
|
||||
b.minLon === Infinity ||
|
||||
b.maxLon === Infinity ||
|
||||
b.minLat === -Infinity ||
|
||||
b.maxLat === -Infinity
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
corners.push([b.minLon, b.minLat]);
|
||||
corners.push([b.maxLon, b.maxLat]);
|
||||
}
|
||||
|
||||
if (!corners.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const turfUnionBbox = turf.bbox(turf.multiPoint(corners));
|
||||
const dataBounds = {
|
||||
minLon: turfUnionBbox[0],
|
||||
minLat: turfUnionBbox[1],
|
||||
maxLon: turfUnionBbox[2],
|
||||
maxLat: turfUnionBbox[3],
|
||||
};
|
||||
|
||||
dispatch(setGotoWithBounds(dataBounds));
|
||||
};
|
||||
}
|
||||
|
||||
export function setGotoWithBounds(bounds: MapExtent) {
|
||||
return {
|
||||
type: SET_GOTO,
|
||||
bounds,
|
||||
};
|
||||
}
|
||||
|
||||
export function setGotoWithCenter({ lat, lon, zoom }: MapCenterAndZoom) {
|
||||
return {
|
||||
type: SET_GOTO,
|
||||
|
|
|
@ -6,7 +6,10 @@
|
|||
|
||||
import { ESTermSource } from '../sources/es_term_source';
|
||||
import { getComputedFieldNamePrefix } from '../styles/vector/style_util';
|
||||
import { META_ID_ORIGIN_SUFFIX, FORMATTERS_ID_ORIGIN_SUFFIX } from '../../../common/constants';
|
||||
import {
|
||||
META_DATA_REQUEST_ID_SUFFIX,
|
||||
FORMATTERS_DATA_REQUEST_ID_SUFFIX,
|
||||
} from '../../../common/constants';
|
||||
|
||||
export class InnerJoin {
|
||||
constructor(joinDescriptor, leftSource) {
|
||||
|
@ -42,11 +45,11 @@ export class InnerJoin {
|
|||
}
|
||||
|
||||
getSourceMetaDataRequestId() {
|
||||
return `${this.getSourceDataRequestId()}_${META_ID_ORIGIN_SUFFIX}`;
|
||||
return `${this.getSourceDataRequestId()}_${META_DATA_REQUEST_ID_SUFFIX}`;
|
||||
}
|
||||
|
||||
getSourceFormattersDataRequestId() {
|
||||
return `${this.getSourceDataRequestId()}_${FORMATTERS_ID_ORIGIN_SUFFIX}`;
|
||||
return `${this.getSourceDataRequestId()}_${FORMATTERS_DATA_REQUEST_ID_SUFFIX}`;
|
||||
}
|
||||
|
||||
getLeftField() {
|
||||
|
|
|
@ -17,21 +17,16 @@ import {
|
|||
MAX_ZOOM,
|
||||
MB_SOURCE_ID_LAYER_ID_PREFIX_DELIMITER,
|
||||
MIN_ZOOM,
|
||||
SOURCE_DATA_ID_ORIGIN,
|
||||
SOURCE_DATA_REQUEST_ID,
|
||||
} from '../../../common/constants';
|
||||
import { copyPersistentState } from '../../reducers/util';
|
||||
import {
|
||||
LayerDescriptor,
|
||||
MapExtent,
|
||||
MapFilters,
|
||||
StyleDescriptor,
|
||||
} from '../../../common/descriptor_types';
|
||||
import { LayerDescriptor, MapExtent, StyleDescriptor } from '../../../common/descriptor_types';
|
||||
import { Attribution, ImmutableSourceProperty, ISource, SourceEditorArgs } from '../sources/source';
|
||||
import { DataRequestContext } from '../../actions';
|
||||
import { IStyle } from '../styles/style';
|
||||
|
||||
export interface ILayer {
|
||||
getBounds(mapFilters: MapFilters): Promise<MapExtent>;
|
||||
getBounds(dataRequestContext: DataRequestContext): Promise<MapExtent | null>;
|
||||
getDataRequest(id: string): DataRequest | undefined;
|
||||
getDisplayName(source?: ISource): Promise<string>;
|
||||
getId(): string;
|
||||
|
@ -401,7 +396,7 @@ export class AbstractLayer implements ILayer {
|
|||
}
|
||||
|
||||
getSourceDataRequest(): DataRequest | undefined {
|
||||
return this.getDataRequest(SOURCE_DATA_ID_ORIGIN);
|
||||
return this.getDataRequest(SOURCE_DATA_REQUEST_ID);
|
||||
}
|
||||
|
||||
getDataRequest(id: string): DataRequest | undefined {
|
||||
|
@ -455,13 +450,8 @@ export class AbstractLayer implements ILayer {
|
|||
return sourceDataRequest ? sourceDataRequest.hasData() : false;
|
||||
}
|
||||
|
||||
async getBounds(mapFilters: MapFilters): Promise<MapExtent> {
|
||||
return {
|
||||
minLon: -180,
|
||||
maxLon: 180,
|
||||
minLat: -89,
|
||||
maxLat: 89,
|
||||
};
|
||||
async getBounds(dataRequestContext: DataRequestContext): Promise<MapExtent | null> {
|
||||
return null;
|
||||
}
|
||||
|
||||
renderStyleEditor({
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
import { AbstractLayer } from '../layer';
|
||||
import _ from 'lodash';
|
||||
import { SOURCE_DATA_ID_ORIGIN, LAYER_TYPE, LAYER_STYLE_TYPE } from '../../../../common/constants';
|
||||
import { SOURCE_DATA_REQUEST_ID, LAYER_TYPE, LAYER_STYLE_TYPE } from '../../../../common/constants';
|
||||
import { TileStyle } from '../../styles/tile/tile_style';
|
||||
|
||||
export class TileLayer extends AbstractLayer {
|
||||
|
@ -31,12 +31,12 @@ export class TileLayer extends AbstractLayer {
|
|||
return;
|
||||
}
|
||||
const requestToken = Symbol(`layer-source-refresh:${this.getId()} - source`);
|
||||
startLoading(SOURCE_DATA_ID_ORIGIN, requestToken, dataFilters);
|
||||
startLoading(SOURCE_DATA_REQUEST_ID, requestToken, dataFilters);
|
||||
try {
|
||||
const url = await this.getSource().getUrlTemplate();
|
||||
stopLoading(SOURCE_DATA_ID_ORIGIN, requestToken, url, {});
|
||||
stopLoading(SOURCE_DATA_REQUEST_ID, requestToken, url, {});
|
||||
} catch (error) {
|
||||
onLoadError(SOURCE_DATA_ID_ORIGIN, requestToken, error.message);
|
||||
onLoadError(SOURCE_DATA_REQUEST_ID, requestToken, error.message);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
import React from 'react';
|
||||
import { EuiIcon } from '@elastic/eui';
|
||||
import { VectorStyle } from '../../styles/vector/vector_style';
|
||||
import { SOURCE_DATA_ID_ORIGIN, LAYER_TYPE } from '../../../../common/constants';
|
||||
import { SOURCE_DATA_REQUEST_ID, LAYER_TYPE } from '../../../../common/constants';
|
||||
import { VectorLayer, VectorLayerArguments } from '../vector_layer/vector_layer';
|
||||
import { canSkipSourceUpdate } from '../../util/can_skip_fetch';
|
||||
import { ITiledSingleLayerVectorSource } from '../../sources/vector_source';
|
||||
|
@ -56,7 +56,7 @@ export class TiledVectorLayer extends VectorLayer {
|
|||
onLoadError,
|
||||
dataFilters,
|
||||
}: DataRequestContext) {
|
||||
const requestToken: symbol = Symbol(`layer-${this.getId()}-${SOURCE_DATA_ID_ORIGIN}`);
|
||||
const requestToken: symbol = Symbol(`layer-${this.getId()}-${SOURCE_DATA_REQUEST_ID}`);
|
||||
const searchFilters: VectorSourceRequestMeta = this._getSearchFilters(
|
||||
dataFilters,
|
||||
this.getSource(),
|
||||
|
@ -73,12 +73,12 @@ export class TiledVectorLayer extends VectorLayer {
|
|||
return null;
|
||||
}
|
||||
|
||||
startLoading(SOURCE_DATA_ID_ORIGIN, requestToken, searchFilters);
|
||||
startLoading(SOURCE_DATA_REQUEST_ID, requestToken, searchFilters);
|
||||
try {
|
||||
const templateWithMeta = await this._source.getUrlTemplateWithMeta();
|
||||
stopLoading(SOURCE_DATA_ID_ORIGIN, requestToken, templateWithMeta, {});
|
||||
stopLoading(SOURCE_DATA_REQUEST_ID, requestToken, templateWithMeta, {});
|
||||
} catch (error) {
|
||||
onLoadError(SOURCE_DATA_ID_ORIGIN, requestToken, error.message);
|
||||
onLoadError(SOURCE_DATA_REQUEST_ID, requestToken, error.message);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,9 +9,10 @@ import { AbstractLayer } from '../layer';
|
|||
import { VectorStyle } from '../../styles/vector/vector_style';
|
||||
import {
|
||||
FEATURE_ID_PROPERTY_NAME,
|
||||
SOURCE_DATA_ID_ORIGIN,
|
||||
SOURCE_META_ID_ORIGIN,
|
||||
SOURCE_FORMATTERS_ID_ORIGIN,
|
||||
SOURCE_DATA_REQUEST_ID,
|
||||
SOURCE_META_DATA_REQUEST_ID,
|
||||
SOURCE_FORMATTERS_DATA_REQUEST_ID,
|
||||
SOURCE_BOUNDS_DATA_REQUEST_ID,
|
||||
FEATURE_VISIBLE_PROPERTY_NAME,
|
||||
EMPTY_FEATURE_COLLECTION,
|
||||
LAYER_TYPE,
|
||||
|
@ -155,18 +156,41 @@ export class VectorLayer extends AbstractLayer {
|
|||
return this.getCurrentStyle().renderLegendDetails();
|
||||
}
|
||||
|
||||
async getBounds(dataFilters) {
|
||||
async getBounds({ startLoading, stopLoading, registerCancelCallback, dataFilters }) {
|
||||
const isStaticLayer = !this.getSource().isBoundsAware();
|
||||
if (isStaticLayer) {
|
||||
return getFeatureCollectionBounds(this._getSourceFeatureCollection(), this._hasJoins());
|
||||
}
|
||||
|
||||
const requestToken = Symbol(`${SOURCE_BOUNDS_DATA_REQUEST_ID}-${this.getId()}`);
|
||||
const searchFilters = this._getSearchFilters(
|
||||
dataFilters,
|
||||
this.getSource(),
|
||||
this.getCurrentStyle()
|
||||
);
|
||||
return await this.getSource().getBoundsForFilters(searchFilters);
|
||||
// Do not pass all searchFilters to source.getBoundsForFilters().
|
||||
// For example, do not want to filter bounds request by extent and buffer.
|
||||
const boundsFilters = {
|
||||
sourceQuery: searchFilters.sourceQuery,
|
||||
query: searchFilters.query,
|
||||
timeFilters: searchFilters.timeFilters,
|
||||
filters: searchFilters.filters,
|
||||
applyGlobalQuery: searchFilters.applyGlobalQuery,
|
||||
};
|
||||
|
||||
let bounds = null;
|
||||
try {
|
||||
startLoading(SOURCE_BOUNDS_DATA_REQUEST_ID, requestToken, boundsFilters);
|
||||
bounds = await this.getSource().getBoundsForFilters(
|
||||
boundsFilters,
|
||||
registerCancelCallback.bind(null, requestToken)
|
||||
);
|
||||
} finally {
|
||||
// Use stopLoading callback instead of onLoadError callback.
|
||||
// Function is loading bounds and not feature data.
|
||||
stopLoading(SOURCE_BOUNDS_DATA_REQUEST_ID, requestToken, bounds, boundsFilters);
|
||||
}
|
||||
return bounds;
|
||||
}
|
||||
|
||||
async getLeftJoinFields() {
|
||||
|
@ -342,7 +366,7 @@ export class VectorLayer extends AbstractLayer {
|
|||
dataFilters,
|
||||
isRequestStillActive,
|
||||
} = syncContext;
|
||||
const dataRequestId = SOURCE_DATA_ID_ORIGIN;
|
||||
const dataRequestId = SOURCE_DATA_REQUEST_ID;
|
||||
const requestToken = Symbol(`layer-${this.getId()}-${dataRequestId}`);
|
||||
const searchFilters = this._getSearchFilters(dataFilters, source, style);
|
||||
const prevDataRequest = this.getSourceDataRequest();
|
||||
|
@ -394,7 +418,7 @@ export class VectorLayer extends AbstractLayer {
|
|||
source,
|
||||
style,
|
||||
sourceQuery: this.getQuery(),
|
||||
dataRequestId: SOURCE_META_ID_ORIGIN,
|
||||
dataRequestId: SOURCE_META_DATA_REQUEST_ID,
|
||||
dynamicStyleProps: style.getDynamicPropertiesArray().filter((dynamicStyleProp) => {
|
||||
return (
|
||||
dynamicStyleProp.getFieldOrigin() === FIELD_ORIGIN.SOURCE &&
|
||||
|
@ -470,7 +494,7 @@ export class VectorLayer extends AbstractLayer {
|
|||
layerName,
|
||||
style,
|
||||
dynamicStyleProps,
|
||||
registerCancelCallback,
|
||||
registerCancelCallback.bind(null, requestToken),
|
||||
nextMeta
|
||||
);
|
||||
stopLoading(dataRequestId, requestToken, styleMeta, nextMeta);
|
||||
|
@ -488,7 +512,7 @@ export class VectorLayer extends AbstractLayer {
|
|||
|
||||
return this._syncFormatters({
|
||||
source,
|
||||
dataRequestId: SOURCE_FORMATTERS_ID_ORIGIN,
|
||||
dataRequestId: SOURCE_FORMATTERS_DATA_REQUEST_ID,
|
||||
fields: style
|
||||
.getDynamicPropertiesArray()
|
||||
.filter((dynamicStyleProp) => {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
import { TileLayer } from '../tile_layer/tile_layer';
|
||||
import _ from 'lodash';
|
||||
import { SOURCE_DATA_ID_ORIGIN, LAYER_TYPE, LAYER_STYLE_TYPE } from '../../../../common/constants';
|
||||
import { SOURCE_DATA_REQUEST_ID, LAYER_TYPE, LAYER_STYLE_TYPE } from '../../../../common/constants';
|
||||
import { isRetina } from '../../../meta';
|
||||
import {
|
||||
addSpriteSheetToMapFromImageData,
|
||||
|
@ -56,16 +56,16 @@ export class VectorTileLayer extends TileLayer {
|
|||
|
||||
const requestToken = Symbol(`layer-source-refresh:${this.getId()} - source`);
|
||||
try {
|
||||
startLoading(SOURCE_DATA_ID_ORIGIN, requestToken, dataFilters);
|
||||
startLoading(SOURCE_DATA_REQUEST_ID, requestToken, dataFilters);
|
||||
const styleAndSprites = await this.getSource().getVectorStyleSheetAndSpriteMeta(isRetina());
|
||||
const spriteSheetImageData = await loadSpriteSheetImageData(styleAndSprites.spriteMeta.png);
|
||||
const data = {
|
||||
...styleAndSprites,
|
||||
spriteSheetImageData,
|
||||
};
|
||||
stopLoading(SOURCE_DATA_ID_ORIGIN, requestToken, data, nextMeta);
|
||||
stopLoading(SOURCE_DATA_REQUEST_ID, requestToken, data, nextMeta);
|
||||
} catch (error) {
|
||||
onLoadError(SOURCE_DATA_ID_ORIGIN, requestToken, error.message);
|
||||
onLoadError(SOURCE_DATA_REQUEST_ID, requestToken, error.message);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -145,11 +145,8 @@ export class AbstractESSource extends AbstractVectorSource {
|
|||
return searchSource;
|
||||
}
|
||||
|
||||
async getBoundsForFilters({ sourceQuery, query, timeFilters, filters, applyGlobalQuery }) {
|
||||
const searchSource = await this.makeSearchSource(
|
||||
{ sourceQuery, query, timeFilters, filters, applyGlobalQuery },
|
||||
0
|
||||
);
|
||||
async getBoundsForFilters(boundsFilters, registerCancelCallback) {
|
||||
const searchSource = await this.makeSearchSource(boundsFilters, 0);
|
||||
searchSource.setField('aggs', {
|
||||
fitToBounds: {
|
||||
geo_bounds: {
|
||||
|
@ -160,13 +157,19 @@ export class AbstractESSource extends AbstractVectorSource {
|
|||
|
||||
let esBounds;
|
||||
try {
|
||||
const esResp = await searchSource.fetch();
|
||||
const abortController = new AbortController();
|
||||
registerCancelCallback(() => abortController.abort());
|
||||
const esResp = await searchSource.fetch({ abortSignal: abortController.signal });
|
||||
if (!esResp.aggregations.fitToBounds.bounds) {
|
||||
// aggregations.fitToBounds is empty object when there are no matching documents
|
||||
return null;
|
||||
}
|
||||
esBounds = esResp.aggregations.fitToBounds.bounds;
|
||||
} catch (error) {
|
||||
if (error.name === 'AbortError') {
|
||||
throw new DataRequestAbortError();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import uuid from 'uuid/v4';
|
||||
import { AbstractSource, ImmutableSourceProperty } from '../source';
|
||||
import { GeoJsonWithMeta, ITiledSingleLayerVectorSource } from '../vector_source';
|
||||
import { BoundsFilters, GeoJsonWithMeta, ITiledSingleLayerVectorSource } from '../vector_source';
|
||||
import { MAX_ZOOM, MIN_ZOOM, SOURCE_TYPES } from '../../../../common/constants';
|
||||
import { VECTOR_SHAPE_TYPES } from '../vector_feature_types';
|
||||
import { IField } from '../../fields/field';
|
||||
|
@ -16,7 +16,6 @@ import { getDataSourceLabel, getUrlLabel } from '../../../../common/i18n_getters
|
|||
import {
|
||||
MapExtent,
|
||||
TiledSingleLayerVectorSourceDescriptor,
|
||||
VectorSourceRequestMeta,
|
||||
VectorSourceSyncMeta,
|
||||
} from '../../../../common/descriptor_types';
|
||||
import { MVTSingleLayerVectorSourceConfig } from './mvt_single_layer_vector_source_editor';
|
||||
|
@ -133,13 +132,11 @@ export class MVTSingleLayerVectorSource extends AbstractSource
|
|||
return this._descriptor.maxSourceZoom;
|
||||
}
|
||||
|
||||
getBoundsForFilters(searchFilters: VectorSourceRequestMeta): MapExtent {
|
||||
return {
|
||||
maxLat: 90,
|
||||
maxLon: 180,
|
||||
minLat: -90,
|
||||
minLon: -180,
|
||||
};
|
||||
getBoundsForFilters(
|
||||
boundsFilters: BoundsFilters,
|
||||
registerCancelCallback: (requestToken: symbol, callback: () => void) => void
|
||||
): MapExtent | null {
|
||||
return null;
|
||||
}
|
||||
|
||||
getFieldByName(fieldName: string): IField | null {
|
||||
|
|
|
@ -6,11 +6,13 @@
|
|||
/* eslint-disable @typescript-eslint/consistent-type-definitions */
|
||||
|
||||
import { FeatureCollection } from 'geojson';
|
||||
import { Filter, TimeRange } from 'src/plugins/data/public';
|
||||
import { AbstractSource, ISource } from '../source';
|
||||
import { IField } from '../../fields/field';
|
||||
import {
|
||||
ESSearchSourceResponseMeta,
|
||||
MapExtent,
|
||||
MapQuery,
|
||||
VectorSourceRequestMeta,
|
||||
VectorSourceSyncMeta,
|
||||
} from '../../../../common/descriptor_types';
|
||||
|
@ -24,9 +26,20 @@ export type GeoJsonWithMeta = {
|
|||
meta?: GeoJsonFetchMeta;
|
||||
};
|
||||
|
||||
export type BoundsFilters = {
|
||||
applyGlobalQuery: boolean;
|
||||
filters: Filter[];
|
||||
query: MapQuery;
|
||||
sourceQuery: MapQuery;
|
||||
timeFilters: TimeRange;
|
||||
};
|
||||
|
||||
export interface IVectorSource extends ISource {
|
||||
filterAndFormatPropertiesToHtml(properties: unknown): Promise<ITooltipProperty[]>;
|
||||
getBoundsForFilters(searchFilters: VectorSourceRequestMeta): MapExtent;
|
||||
getBoundsForFilters(
|
||||
boundsFilters: BoundsFilters,
|
||||
registerCancelCallback: (requestToken: symbol, callback: () => void) => void
|
||||
): MapExtent | null;
|
||||
getGeoJsonWithMeta(
|
||||
layerName: 'string',
|
||||
searchFilters: unknown[],
|
||||
|
@ -42,7 +55,10 @@ export interface IVectorSource extends ISource {
|
|||
|
||||
export class AbstractVectorSource extends AbstractSource implements IVectorSource {
|
||||
filterAndFormatPropertiesToHtml(properties: unknown): Promise<ITooltipProperty[]>;
|
||||
getBoundsForFilters(searchFilters: VectorSourceRequestMeta): MapExtent;
|
||||
getBoundsForFilters(
|
||||
boundsFilters: BoundsFilters,
|
||||
registerCancelCallback: (requestToken: symbol, callback: () => void) => void
|
||||
): MapExtent | null;
|
||||
getGeoJsonWithMeta(
|
||||
layerName: 'string',
|
||||
searchFilters: unknown[],
|
||||
|
|
|
@ -7,7 +7,11 @@
|
|||
import _ from 'lodash';
|
||||
import { AbstractStyleProperty } from './style_property';
|
||||
import { DEFAULT_SIGMA } from '../vector_style_defaults';
|
||||
import { STYLE_TYPE, SOURCE_META_ID_ORIGIN, FIELD_ORIGIN } from '../../../../../common/constants';
|
||||
import {
|
||||
STYLE_TYPE,
|
||||
SOURCE_META_DATA_REQUEST_ID,
|
||||
FIELD_ORIGIN,
|
||||
} from '../../../../../common/constants';
|
||||
import React from 'react';
|
||||
import { OrdinalFieldMetaPopover } from '../components/field_meta/ordinal_field_meta_popover';
|
||||
import { CategoricalFieldMetaPopover } from '../components/field_meta/categorical_field_meta_popover';
|
||||
|
@ -30,7 +34,7 @@ export class DynamicStyleProperty extends AbstractStyleProperty {
|
|||
|
||||
_getStyleMetaDataRequestId(fieldName) {
|
||||
if (this.getFieldOrigin() === FIELD_ORIGIN.SOURCE) {
|
||||
return SOURCE_META_ID_ORIGIN;
|
||||
return SOURCE_META_DATA_REQUEST_ID;
|
||||
}
|
||||
|
||||
const join = this._layer.getValidJoins().find((join) => {
|
||||
|
|
|
@ -13,7 +13,7 @@ import {
|
|||
GEO_JSON_TYPE,
|
||||
FIELD_ORIGIN,
|
||||
STYLE_TYPE,
|
||||
SOURCE_FORMATTERS_ID_ORIGIN,
|
||||
SOURCE_FORMATTERS_DATA_REQUEST_ID,
|
||||
LAYER_STYLE_TYPE,
|
||||
DEFAULT_ICON,
|
||||
VECTOR_STYLES,
|
||||
|
@ -373,7 +373,7 @@ export class VectorStyle extends AbstractStyle {
|
|||
|
||||
let dataRequestId;
|
||||
if (dynamicProp.getFieldOrigin() === FIELD_ORIGIN.SOURCE) {
|
||||
dataRequestId = SOURCE_FORMATTERS_ID_ORIGIN;
|
||||
dataRequestId = SOURCE_FORMATTERS_DATA_REQUEST_ID;
|
||||
} else {
|
||||
const join = this._layer.getValidJoins().find((join) => {
|
||||
return join.getRightJoinSource().hasMatchingMetricField(fieldName);
|
||||
|
|
|
@ -53,7 +53,7 @@ import {
|
|||
|
||||
import { getDefaultMapSettings } from './default_map_settings';
|
||||
import { copyPersistentState, TRACKED_LAYER_DESCRIPTOR } from './util';
|
||||
import { SOURCE_DATA_ID_ORIGIN } from '../../common/constants';
|
||||
import { SOURCE_DATA_REQUEST_ID } from '../../common/constants';
|
||||
|
||||
const getLayerIndex = (list, layerId) => list.findIndex(({ id }) => layerId === id);
|
||||
|
||||
|
@ -443,7 +443,7 @@ function updateSourceDataRequest(state, action) {
|
|||
return state;
|
||||
}
|
||||
const dataRequest = layerDescriptor.__dataRequests.find((dataRequest) => {
|
||||
return dataRequest.dataId === SOURCE_DATA_ID_ORIGIN;
|
||||
return dataRequest.dataId === SOURCE_DATA_REQUEST_ID;
|
||||
});
|
||||
if (!dataRequest) {
|
||||
return state;
|
||||
|
|
|
@ -26,7 +26,7 @@ import { getSourceByType } from '../classes/sources/source_registry';
|
|||
import { GeojsonFileSource } from '../classes/sources/client_file_source';
|
||||
import {
|
||||
LAYER_TYPE,
|
||||
SOURCE_DATA_ID_ORIGIN,
|
||||
SOURCE_DATA_REQUEST_ID,
|
||||
STYLE_TYPE,
|
||||
VECTOR_STYLES,
|
||||
SPATIAL_FILTERS_LAYER_ID,
|
||||
|
@ -263,7 +263,7 @@ export const getSpatialFiltersLayer = createSelector(
|
|||
alpha: settings.spatialFiltersAlpa,
|
||||
__dataRequests: [
|
||||
{
|
||||
dataId: SOURCE_DATA_ID_ORIGIN,
|
||||
dataId: SOURCE_DATA_REQUEST_ID,
|
||||
data: featureCollection,
|
||||
},
|
||||
],
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue