mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[Maps] refactor ITiledSingleLayerVectorSource into MvtVectorSource (#120566)
* [Maps] refactor MvtVectorSource * clean up * more cleanup * remove file with no extension * lint
This commit is contained in:
parent
d64d7ae0b7
commit
defdc8c30b
18 changed files with 152 additions and 260 deletions
|
@ -36,8 +36,6 @@ export const MVT_GETGRIDTILE_API_PATH = 'mvt/getGridTile';
|
|||
// Centroids are a single point for representing lines, multiLines, polygons, and multiPolygons
|
||||
export const KBN_IS_CENTROID_FEATURE = '__kbn_is_centroid_feature__';
|
||||
|
||||
export const MVT_TOKEN_PARAM_NAME = 'token';
|
||||
|
||||
export function getNewMapPath() {
|
||||
return `/${MAPS_APP_PATH}/${MAP_PATH}`;
|
||||
}
|
||||
|
|
|
@ -8,11 +8,11 @@
|
|||
import { AbstractField, IField } from './field';
|
||||
import { FIELD_ORIGIN, MVT_FIELD_TYPE } from '../../../common/constants';
|
||||
import { IVectorSource } from '../sources/vector_source';
|
||||
import { ITiledSingleLayerVectorSource } from '../sources/tiled_single_layer_vector_source';
|
||||
import { IMvtVectorSource } from '../sources/vector_source';
|
||||
import { MVTFieldDescriptor } from '../../../common/descriptor_types';
|
||||
|
||||
export class MVTField extends AbstractField implements IField {
|
||||
private readonly _source: ITiledSingleLayerVectorSource;
|
||||
private readonly _source: IMvtVectorSource;
|
||||
private readonly _type: MVT_FIELD_TYPE;
|
||||
constructor({
|
||||
fieldName,
|
||||
|
@ -21,7 +21,7 @@ export class MVTField extends AbstractField implements IField {
|
|||
origin,
|
||||
}: {
|
||||
fieldName: string;
|
||||
source: ITiledSingleLayerVectorSource;
|
||||
source: IMvtVectorSource;
|
||||
origin: FIELD_ORIGIN;
|
||||
type: MVT_FIELD_TYPE;
|
||||
}) {
|
||||
|
|
|
@ -14,7 +14,7 @@ import { ESGeoGridSource } from '../../sources/es_geo_grid_source';
|
|||
import { syncBoundsData, MvtSourceData, syncMvtSourceData } from '../vector_layer';
|
||||
import { DataRequestContext } from '../../../actions';
|
||||
import { buildVectorRequestMeta } from '../build_vector_request_meta';
|
||||
import { ITiledSingleLayerVectorSource } from '../../sources/tiled_single_layer_vector_source';
|
||||
import { IMvtVectorSource } from '../../sources/vector_source';
|
||||
|
||||
export class HeatmapLayer extends AbstractLayer {
|
||||
private readonly _style: HeatmapStyle;
|
||||
|
@ -91,7 +91,7 @@ export class HeatmapLayer extends AbstractLayer {
|
|||
this.getQuery(),
|
||||
syncContext.isForceRefresh
|
||||
),
|
||||
source: this.getSource() as ITiledSingleLayerVectorSource,
|
||||
source: this.getSource() as IMvtVectorSource,
|
||||
syncContext,
|
||||
});
|
||||
}
|
||||
|
@ -111,7 +111,7 @@ export class HeatmapLayer extends AbstractLayer {
|
|||
return false;
|
||||
}
|
||||
|
||||
return mbSource.tiles?.[0] !== sourceData.urlTemplate;
|
||||
return mbSource.tiles?.[0] !== sourceData.tileUrl;
|
||||
}
|
||||
|
||||
syncLayerWithMB(mbMap: MbMap) {
|
||||
|
@ -130,9 +130,9 @@ export class HeatmapLayer extends AbstractLayer {
|
|||
if (!mbSource) {
|
||||
mbMap.addSource(mbSourceId, {
|
||||
type: 'vector',
|
||||
tiles: [sourceData.urlTemplate],
|
||||
minzoom: sourceData.minSourceZoom,
|
||||
maxzoom: sourceData.maxSourceZoom,
|
||||
tiles: [sourceData.tileUrl],
|
||||
minzoom: sourceData.tileMinZoom,
|
||||
maxzoom: sourceData.tileMaxZoom,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -142,7 +142,7 @@ export class HeatmapLayer extends AbstractLayer {
|
|||
id: heatmapLayerId,
|
||||
type: 'heatmap',
|
||||
source: mbSourceId,
|
||||
['source-layer']: sourceData.layerName,
|
||||
['source-layer']: sourceData.tileSourceLayer,
|
||||
paint: {},
|
||||
});
|
||||
}
|
||||
|
@ -153,7 +153,7 @@ export class HeatmapLayer extends AbstractLayer {
|
|||
}
|
||||
const metricField = metricFields[0];
|
||||
|
||||
// do not use tile meta features from previous urlTemplate to avoid styling new tiles from previous tile meta features
|
||||
// do not use tile meta features from previous tile URL to avoid styling new tiles from previous tile meta features
|
||||
const tileMetaFeatures = this._requiresPrevSourceCleanup(mbMap) ? [] : this._getMetaFromTiles();
|
||||
let max = 0;
|
||||
for (let i = 0; i < tileMetaFeatures.length; i++) {
|
||||
|
|
|
@ -13,12 +13,12 @@ jest.mock('uuid/v4', () => {
|
|||
|
||||
import sinon from 'sinon';
|
||||
import { MockSyncContext } from '../../__fixtures__/mock_sync_context';
|
||||
import { ITiledSingleLayerVectorSource } from '../../../sources/tiled_single_layer_vector_source';
|
||||
import { IMvtVectorSource } from '../../../sources/vector_source';
|
||||
import { DataRequest } from '../../../util/data_request';
|
||||
import { syncMvtSourceData } from './mvt_source_data';
|
||||
|
||||
const mockSource = {
|
||||
getLayerName: () => {
|
||||
getTileSourceLayer: () => {
|
||||
return 'aggs';
|
||||
},
|
||||
getMinZoom: () => {
|
||||
|
@ -27,14 +27,8 @@ const mockSource = {
|
|||
getMaxZoom: () => {
|
||||
return 14;
|
||||
},
|
||||
getUrlTemplateWithMeta: () => {
|
||||
return {
|
||||
refreshTokenParamName: 'token',
|
||||
layerName: 'aggs',
|
||||
minSourceZoom: 4,
|
||||
maxSourceZoom: 14,
|
||||
urlTemplate: 'https://example.com/{x}/{y}/{z}.pbf',
|
||||
};
|
||||
getTileUrl: () => {
|
||||
return 'https://example.com/{x}/{y}/{z}.pbf';
|
||||
},
|
||||
isTimeAware: () => {
|
||||
return true;
|
||||
|
@ -48,7 +42,7 @@ const mockSource = {
|
|||
isGeoGridPrecisionAware: () => {
|
||||
return false;
|
||||
},
|
||||
} as unknown as ITiledSingleLayerVectorSource;
|
||||
} as unknown as IMvtVectorSource;
|
||||
|
||||
describe('syncMvtSourceData', () => {
|
||||
test('Should sync source data when there are no previous data request', async () => {
|
||||
|
@ -78,12 +72,11 @@ describe('syncMvtSourceData', () => {
|
|||
const call = syncContext.stopLoading.getCall(0);
|
||||
const sourceData = call.args[2];
|
||||
expect(sourceData).toEqual({
|
||||
minSourceZoom: 4,
|
||||
maxSourceZoom: 14,
|
||||
layerName: 'aggs',
|
||||
refreshTokenParamName: 'token',
|
||||
urlTemplate: 'https://example.com/{x}/{y}/{z}.pbf?token=12345',
|
||||
urlToken: '12345',
|
||||
tileMinZoom: 4,
|
||||
tileMaxZoom: 14,
|
||||
tileSourceLayer: 'aggs',
|
||||
tileUrl: 'https://example.com/{x}/{y}/{z}.pbf',
|
||||
refreshToken: '12345',
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -107,12 +100,11 @@ describe('syncMvtSourceData', () => {
|
|||
},
|
||||
getData: () => {
|
||||
return {
|
||||
minSourceZoom: 4,
|
||||
maxSourceZoom: 14,
|
||||
layerName: 'aggs',
|
||||
refreshTokenParamName: 'token',
|
||||
urlTemplate: 'https://example.com/{x}/{y}/{z}.pbf?token=12345',
|
||||
urlToken: '12345',
|
||||
tileMinZoom: 4,
|
||||
tileMaxZoom: 14,
|
||||
tileSourceLayer: 'aggs',
|
||||
tileUrl: 'https://example.com/{x}/{y}/{z}.pbf?token=12345',
|
||||
refreshToken: '12345',
|
||||
};
|
||||
},
|
||||
} as unknown as DataRequest,
|
||||
|
@ -146,12 +138,11 @@ describe('syncMvtSourceData', () => {
|
|||
},
|
||||
getData: () => {
|
||||
return {
|
||||
minSourceZoom: 4,
|
||||
maxSourceZoom: 14,
|
||||
layerName: 'aggs',
|
||||
refreshTokenParamName: 'token',
|
||||
urlTemplate: 'https://example.com/{x}/{y}/{z}.pbf?token=12345',
|
||||
urlToken: '12345',
|
||||
tileMinZoom: 4,
|
||||
tileMaxZoom: 14,
|
||||
tileSourceLayer: 'aggs',
|
||||
tileUrl: 'https://example.com/{x}/{y}/{z}.pbf?token=12345',
|
||||
refreshToken: '12345',
|
||||
};
|
||||
},
|
||||
} as unknown as DataRequest,
|
||||
|
@ -173,7 +164,7 @@ describe('syncMvtSourceData', () => {
|
|||
sinon.assert.calledOnce(syncContext.stopLoading);
|
||||
});
|
||||
|
||||
test('Should re-sync when layerName source state changes: ', async () => {
|
||||
test('Should re-sync when tileSourceLayer source state changes: ', async () => {
|
||||
const syncContext = new MockSyncContext({ dataFilters: {} });
|
||||
const prevRequestMeta = {
|
||||
...syncContext.dataFilters,
|
||||
|
@ -193,12 +184,11 @@ describe('syncMvtSourceData', () => {
|
|||
},
|
||||
getData: () => {
|
||||
return {
|
||||
minSourceZoom: 4,
|
||||
maxSourceZoom: 14,
|
||||
layerName: 'barfoo', // layerName is different then mockSource
|
||||
refreshTokenParamName: 'token',
|
||||
urlTemplate: 'https://example.com/{x}/{y}/{z}.pbf?token=12345',
|
||||
urlToken: '12345',
|
||||
tileMinZoom: 4,
|
||||
tileMaxZoom: 14,
|
||||
tileSourceLayer: 'barfoo', // tileSourceLayer is different then mockSource
|
||||
tileUrl: 'https://example.com/{x}/{y}/{z}.pbf?token=12345',
|
||||
refreshToken: '12345',
|
||||
};
|
||||
},
|
||||
} as unknown as DataRequest,
|
||||
|
@ -232,12 +222,11 @@ describe('syncMvtSourceData', () => {
|
|||
},
|
||||
getData: () => {
|
||||
return {
|
||||
minSourceZoom: 2, // minSourceZoom is different then mockSource
|
||||
maxSourceZoom: 14,
|
||||
layerName: 'aggs',
|
||||
refreshTokenParamName: 'token',
|
||||
urlTemplate: 'https://example.com/{x}/{y}/{z}.pbf?token=12345',
|
||||
urlToken: '12345',
|
||||
tileMinZoom: 2, // tileMinZoom is different then mockSource
|
||||
tileMaxZoom: 14,
|
||||
tileSourceLayer: 'aggs',
|
||||
tileUrl: 'https://example.com/{x}/{y}/{z}.pbf?token=12345',
|
||||
refreshToken: '12345',
|
||||
};
|
||||
},
|
||||
} as unknown as DataRequest,
|
||||
|
@ -271,12 +260,11 @@ describe('syncMvtSourceData', () => {
|
|||
},
|
||||
getData: () => {
|
||||
return {
|
||||
minSourceZoom: 4,
|
||||
maxSourceZoom: 9, // minSourceZoom is different then mockSource
|
||||
layerName: 'aggs',
|
||||
refreshTokenParamName: 'token',
|
||||
urlTemplate: 'https://example.com/{x}/{y}/{z}.pbf?token=12345',
|
||||
urlToken: '12345',
|
||||
tileMinZoom: 4,
|
||||
tileMaxZoom: 9, // tileMinZoom is different then mockSource
|
||||
tileSourceLayer: 'aggs',
|
||||
tileUrl: 'https://example.com/{x}/{y}/{z}.pbf?token=12345',
|
||||
refreshToken: '12345',
|
||||
};
|
||||
},
|
||||
} as unknown as DataRequest,
|
||||
|
|
|
@ -6,22 +6,21 @@
|
|||
*/
|
||||
|
||||
import uuid from 'uuid/v4';
|
||||
import { parse as parseUrl } from 'url';
|
||||
import { SOURCE_DATA_REQUEST_ID } from '../../../../../common/constants';
|
||||
import { Timeslice, VectorSourceRequestMeta } from '../../../../../common/descriptor_types';
|
||||
import { DataRequest } from '../../../util/data_request';
|
||||
import { DataRequestContext } from '../../../../actions';
|
||||
import { canSkipSourceUpdate } from '../../../util/can_skip_fetch';
|
||||
import {
|
||||
ITiledSingleLayerMvtParams,
|
||||
ITiledSingleLayerVectorSource,
|
||||
} from '../../../sources/tiled_single_layer_vector_source';
|
||||
import { IMvtVectorSource } from '../../../sources/vector_source';
|
||||
|
||||
// shape of sourceDataRequest.getData()
|
||||
export type MvtSourceData = ITiledSingleLayerMvtParams & {
|
||||
urlTemplate: string;
|
||||
urlToken: string;
|
||||
};
|
||||
export interface MvtSourceData {
|
||||
tileSourceLayer: string;
|
||||
tileMinZoom: number;
|
||||
tileMaxZoom: number;
|
||||
tileUrl: string;
|
||||
refreshToken: string;
|
||||
}
|
||||
|
||||
export async function syncMvtSourceData({
|
||||
layerId,
|
||||
|
@ -33,7 +32,7 @@ export async function syncMvtSourceData({
|
|||
layerId: string;
|
||||
prevDataRequest: DataRequest | undefined;
|
||||
requestMeta: VectorSourceRequestMeta;
|
||||
source: ITiledSingleLayerVectorSource;
|
||||
source: IMvtVectorSource;
|
||||
syncContext: DataRequestContext;
|
||||
}): Promise<void> {
|
||||
const requestToken: symbol = Symbol(`${layerId}-${SOURCE_DATA_REQUEST_ID}`);
|
||||
|
@ -42,9 +41,9 @@ export async function syncMvtSourceData({
|
|||
|
||||
if (prevData) {
|
||||
const noChangesInSourceState: boolean =
|
||||
prevData.layerName === source.getLayerName() &&
|
||||
prevData.minSourceZoom === source.getMinZoom() &&
|
||||
prevData.maxSourceZoom === source.getMaxZoom();
|
||||
prevData.tileSourceLayer === source.getTileSourceLayer() &&
|
||||
prevData.tileMinZoom === source.getMinZoom() &&
|
||||
prevData.tileMaxZoom === source.getMaxZoom();
|
||||
const noChangesInSearchState: boolean = await canSkipSourceUpdate({
|
||||
extentAware: false, // spatial extent knowledge is already fully automated by tile-loading based on pan-zooming
|
||||
source,
|
||||
|
@ -63,26 +62,18 @@ export async function syncMvtSourceData({
|
|||
|
||||
syncContext.startLoading(SOURCE_DATA_REQUEST_ID, requestToken, requestMeta);
|
||||
try {
|
||||
const urlToken =
|
||||
const refreshToken =
|
||||
!prevData || (requestMeta.isForceRefresh && requestMeta.applyForceRefresh)
|
||||
? uuid()
|
||||
: prevData.urlToken;
|
||||
|
||||
const newUrlTemplateAndMeta = await source.getUrlTemplateWithMeta(requestMeta);
|
||||
|
||||
let urlTemplate;
|
||||
if (newUrlTemplateAndMeta.refreshTokenParamName) {
|
||||
const parsedUrl = parseUrl(newUrlTemplateAndMeta.urlTemplate, true);
|
||||
const separator = !parsedUrl.query || Object.keys(parsedUrl.query).length === 0 ? '?' : '&';
|
||||
urlTemplate = `${newUrlTemplateAndMeta.urlTemplate}${separator}${newUrlTemplateAndMeta.refreshTokenParamName}=${urlToken}`;
|
||||
} else {
|
||||
urlTemplate = newUrlTemplateAndMeta.urlTemplate;
|
||||
}
|
||||
: prevData.refreshToken;
|
||||
|
||||
const tileUrl = await source.getTileUrl(requestMeta, refreshToken);
|
||||
const sourceData = {
|
||||
...newUrlTemplateAndMeta,
|
||||
urlToken,
|
||||
urlTemplate,
|
||||
tileUrl,
|
||||
tileSourceLayer: source.getTileSourceLayer(),
|
||||
tileMinZoom: source.getMinZoom(),
|
||||
tileMaxZoom: source.getMaxZoom(),
|
||||
refreshToken,
|
||||
};
|
||||
syncContext.stopLoading(SOURCE_DATA_REQUEST_ID, requestToken, sourceData, {});
|
||||
} catch (error) {
|
||||
|
|
|
@ -34,8 +34,7 @@ const defaultConfig = {
|
|||
function createLayer(
|
||||
layerOptions: Partial<VectorLayerDescriptor> = {},
|
||||
sourceOptions: Partial<TiledSingleLayerVectorSourceDescriptor> = {},
|
||||
isTimeAware: boolean = false,
|
||||
includeToken: boolean = false
|
||||
isTimeAware: boolean = false
|
||||
): MvtVectorLayer {
|
||||
const sourceDescriptor: TiledSingleLayerVectorSourceDescriptor = {
|
||||
type: SOURCE_TYPES.MVT_SINGLE_LAYER,
|
||||
|
@ -54,19 +53,6 @@ function createLayer(
|
|||
};
|
||||
}
|
||||
|
||||
if (includeToken) {
|
||||
mvtSource.getUrlTemplateWithMeta = async (...args) => {
|
||||
const superReturn = await MVTSingleLayerVectorSource.prototype.getUrlTemplateWithMeta.call(
|
||||
mvtSource,
|
||||
...args
|
||||
);
|
||||
return {
|
||||
...superReturn,
|
||||
refreshTokenParamName: 'token',
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
const defaultLayerOptions = {
|
||||
...layerOptions,
|
||||
sourceDescriptor,
|
||||
|
|
|
@ -20,7 +20,7 @@ import {
|
|||
AbstractVectorLayer,
|
||||
VectorLayerArguments,
|
||||
} from '../vector_layer';
|
||||
import { ITiledSingleLayerVectorSource } from '../../../sources/tiled_single_layer_vector_source';
|
||||
import { IMvtVectorSource } from '../../../sources/vector_source';
|
||||
import { DataRequestContext } from '../../../../actions';
|
||||
import {
|
||||
StyleMetaDescriptor,
|
||||
|
@ -52,11 +52,11 @@ export class MvtVectorLayer extends AbstractVectorLayer {
|
|||
return layerDescriptor;
|
||||
}
|
||||
|
||||
readonly _source: ITiledSingleLayerVectorSource; // downcast to the more specific type
|
||||
readonly _source: IMvtVectorSource;
|
||||
|
||||
constructor({ layerDescriptor, source }: VectorLayerArguments) {
|
||||
super({ layerDescriptor, source });
|
||||
this._source = source as ITiledSingleLayerVectorSource;
|
||||
this._source = source as IMvtVectorSource;
|
||||
}
|
||||
|
||||
getFeatureId(feature: Feature): string | number | undefined {
|
||||
|
@ -180,7 +180,7 @@ export class MvtVectorLayer extends AbstractVectorLayer {
|
|||
this.getSource(),
|
||||
this.getCurrentStyle()
|
||||
),
|
||||
source: this.getSource() as ITiledSingleLayerVectorSource,
|
||||
source: this.getSource() as IMvtVectorSource,
|
||||
syncContext,
|
||||
});
|
||||
}
|
||||
|
@ -206,9 +206,9 @@ export class MvtVectorLayer extends AbstractVectorLayer {
|
|||
const mbSourceId = this.getMbSourceId();
|
||||
mbMap.addSource(mbSourceId, {
|
||||
type: 'vector',
|
||||
tiles: [sourceData.urlTemplate],
|
||||
minzoom: sourceData.minSourceZoom,
|
||||
maxzoom: sourceData.maxSourceZoom,
|
||||
tiles: [sourceData.tileUrl],
|
||||
minzoom: sourceData.tileMinZoom,
|
||||
maxzoom: sourceData.tileMaxZoom,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -236,13 +236,13 @@ export class MvtVectorLayer extends AbstractVectorLayer {
|
|||
return;
|
||||
}
|
||||
const sourceData = sourceDataRequest.getData() as MvtSourceData | undefined;
|
||||
if (!sourceData || sourceData.layerName === '') {
|
||||
if (!sourceData || sourceData.tileSourceLayer === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
this._setMbLabelProperties(mbMap, sourceData.layerName);
|
||||
this._setMbPointsProperties(mbMap, sourceData.layerName);
|
||||
this._setMbLinePolygonProperties(mbMap, sourceData.layerName);
|
||||
this._setMbLabelProperties(mbMap, sourceData.tileSourceLayer);
|
||||
this._setMbPointsProperties(mbMap, sourceData.tileSourceLayer);
|
||||
this._setMbLinePolygonProperties(mbMap, sourceData.tileSourceLayer);
|
||||
this._syncTooManyFeaturesProperties(mbMap);
|
||||
}
|
||||
|
||||
|
@ -308,9 +308,9 @@ export class MvtVectorLayer extends AbstractVectorLayer {
|
|||
}
|
||||
|
||||
const isSourceDifferent =
|
||||
mbTileSource.tiles?.[0] !== sourceData.urlTemplate ||
|
||||
mbTileSource.minzoom !== sourceData.minSourceZoom ||
|
||||
mbTileSource.maxzoom !== sourceData.maxSourceZoom;
|
||||
mbTileSource.tiles?.[0] !== sourceData.tileUrl ||
|
||||
mbTileSource.minzoom !== sourceData.tileMinZoom ||
|
||||
mbTileSource.maxzoom !== sourceData.tileMaxZoom;
|
||||
|
||||
if (isSourceDifferent) {
|
||||
return true;
|
||||
|
@ -324,7 +324,7 @@ export class MvtVectorLayer extends AbstractVectorLayer {
|
|||
if (
|
||||
mbLayer &&
|
||||
// @ts-expect-error
|
||||
mbLayer.sourceLayer !== sourceData.layerName &&
|
||||
mbLayer.sourceLayer !== sourceData.tileSourceLayer &&
|
||||
// @ts-expect-error
|
||||
mbLayer.sourceLayer !== ES_MVT_META_LAYER_NAME
|
||||
) {
|
||||
|
|
|
@ -281,7 +281,7 @@ describe('ESGeoGridSource', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('ITiledSingleLayerVectorSource', () => {
|
||||
describe('IMvtVectorSource', () => {
|
||||
const mvtGeogridSource = new ESGeoGridSource(
|
||||
{
|
||||
id: 'foobar',
|
||||
|
@ -295,28 +295,15 @@ describe('ESGeoGridSource', () => {
|
|||
{}
|
||||
);
|
||||
|
||||
it('getLayerName', () => {
|
||||
expect(mvtGeogridSource.getLayerName()).toBe('aggs');
|
||||
it('getTileSourceLayer', () => {
|
||||
expect(mvtGeogridSource.getTileSourceLayer()).toBe('aggs');
|
||||
});
|
||||
|
||||
it('getMinZoom', () => {
|
||||
expect(mvtGeogridSource.getMinZoom()).toBe(0);
|
||||
});
|
||||
it('getTileUrl', async () => {
|
||||
const tileUrl = await mvtGeogridSource.getTileUrl(vectorSourceRequestMeta, '1234');
|
||||
|
||||
it('getMaxZoom', () => {
|
||||
expect(mvtGeogridSource.getMaxZoom()).toBe(24);
|
||||
});
|
||||
|
||||
it('getUrlTemplateWithMeta', async () => {
|
||||
const urlTemplateWithMeta = await mvtGeogridSource.getUrlTemplateWithMeta(
|
||||
vectorSourceRequestMeta
|
||||
);
|
||||
|
||||
expect(urlTemplateWithMeta.layerName).toBe('aggs');
|
||||
expect(urlTemplateWithMeta.minSourceZoom).toBe(0);
|
||||
expect(urlTemplateWithMeta.maxSourceZoom).toBe(24);
|
||||
expect(urlTemplateWithMeta.urlTemplate).toEqual(
|
||||
"rootdir/api/maps/mvt/getGridTile/{z}/{x}/{y}.pbf?geometryFieldName=bar&index=undefined&gridPrecision=8&requestBody=(foobar:ES_DSL_PLACEHOLDER,params:('0':('0':index,'1':(fields:())),'1':('0':size,'1':0),'2':('0':filter,'1':!()),'3':('0':query),'4':('0':index,'1':(fields:())),'5':('0':query,'1':(language:KQL,query:'')),'6':('0':aggs,'1':())))&requestType=point"
|
||||
expect(tileUrl).toEqual(
|
||||
"rootdir/api/maps/mvt/getGridTile/{z}/{x}/{y}.pbf?geometryFieldName=bar&index=undefined&gridPrecision=8&requestBody=(foobar:ES_DSL_PLACEHOLDER,params:('0':('0':index,'1':(fields:())),'1':('0':size,'1':0),'2':('0':filter,'1':!()),'3':('0':query),'4':('0':index,'1':(fields:())),'5':('0':query,'1':(language:KQL,query:'')),'6':('0':aggs,'1':())))&requestType=point&token=1234"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -22,7 +22,6 @@ import {
|
|||
GIS_API_PATH,
|
||||
GRID_RESOLUTION,
|
||||
MVT_GETGRIDTILE_API_PATH,
|
||||
MVT_TOKEN_PARAM_NAME,
|
||||
RENDER_AS,
|
||||
SOURCE_TYPES,
|
||||
VECTOR_SHAPE_TYPE,
|
||||
|
@ -34,8 +33,7 @@ import { registerSource } from '../source_registry';
|
|||
import { LICENSED_FEATURES } from '../../../licensed_features';
|
||||
|
||||
import { getHttp } from '../../../kibana_services';
|
||||
import { GeoJsonWithMeta } from '../vector_source';
|
||||
import { ITiledSingleLayerVectorSource } from '../tiled_single_layer_vector_source';
|
||||
import { GeoJsonWithMeta, IMvtVectorSource } from '../vector_source';
|
||||
import {
|
||||
ESGeoGridSourceDescriptor,
|
||||
MapExtent,
|
||||
|
@ -46,12 +44,9 @@ import { ISearchSource } from '../../../../../../../src/plugins/data/common/sear
|
|||
import { IndexPattern } from '../../../../../../../src/plugins/data/common';
|
||||
import { Adapters } from '../../../../../../../src/plugins/inspector/common/adapters';
|
||||
import { isValidStringConfig } from '../../util/valid_string_config';
|
||||
import { ITiledSingleLayerMvtParams } from '../tiled_single_layer_vector_source/tiled_single_layer_vector_source';
|
||||
|
||||
type ESGeoGridSourceSyncMeta = Pick<ESGeoGridSourceDescriptor, 'requestType' | 'resolution'>;
|
||||
|
||||
const ES_MVT_AGGS_LAYER_NAME = 'aggs';
|
||||
|
||||
const MAX_GEOTILE_LEVEL = 29;
|
||||
|
||||
export const clustersTitle = i18n.translate('xpack.maps.source.esGridClustersTitle', {
|
||||
|
@ -62,7 +57,7 @@ export const heatmapTitle = i18n.translate('xpack.maps.source.esGridHeatmapTitle
|
|||
defaultMessage: 'Heat map',
|
||||
});
|
||||
|
||||
export class ESGeoGridSource extends AbstractESAggSource implements ITiledSingleLayerVectorSource {
|
||||
export class ESGeoGridSource extends AbstractESAggSource implements IMvtVectorSource {
|
||||
static createDescriptor(
|
||||
descriptor: Partial<ESGeoGridSourceDescriptor>
|
||||
): ESGeoGridSourceDescriptor {
|
||||
|
@ -424,15 +419,11 @@ export class ESGeoGridSource extends AbstractESAggSource implements ITiledSingle
|
|||
} as GeoJsonWithMeta;
|
||||
}
|
||||
|
||||
// TODO rename to getMvtSourceLayerName
|
||||
getLayerName(): string {
|
||||
return ES_MVT_AGGS_LAYER_NAME;
|
||||
getTileSourceLayer(): string {
|
||||
return 'aggs';
|
||||
}
|
||||
|
||||
// TODO rename to getMvtUrlTemplateWithMeta
|
||||
async getUrlTemplateWithMeta(
|
||||
searchFilters: VectorSourceRequestMeta
|
||||
): Promise<ITiledSingleLayerMvtParams> {
|
||||
async getTileUrl(searchFilters: VectorSourceRequestMeta, refreshToken: string): Promise<string> {
|
||||
const indexPattern = await this.getIndexPattern();
|
||||
const searchSource = await this.makeSearchSource(searchFilters, 0);
|
||||
searchSource.setField('aggs', this.getValueAggsDsl(indexPattern));
|
||||
|
@ -447,20 +438,13 @@ export class ESGeoGridSource extends AbstractESAggSource implements ITiledSingle
|
|||
const requestType =
|
||||
this._descriptor.requestType === RENDER_AS.GRID ? RENDER_AS.GRID : RENDER_AS.POINT;
|
||||
|
||||
const urlTemplate = `${mvtUrlServicePath}\
|
||||
return `${mvtUrlServicePath}\
|
||||
?geometryFieldName=${this._descriptor.geoField}\
|
||||
&index=${indexPattern.title}\
|
||||
&gridPrecision=${this._getGeoGridPrecisionResolutionDelta()}\
|
||||
&requestBody=${risonDsl}\
|
||||
&requestType=${requestType}`;
|
||||
|
||||
return {
|
||||
refreshTokenParamName: MVT_TOKEN_PARAM_NAME,
|
||||
layerName: this.getLayerName(),
|
||||
minSourceZoom: this.getMinZoom(),
|
||||
maxSourceZoom: this.getMaxZoom(),
|
||||
urlTemplate,
|
||||
};
|
||||
&requestType=${requestType}\
|
||||
&token=${refreshToken}`;
|
||||
}
|
||||
|
||||
isFilterByMapBounds(): boolean {
|
||||
|
|
|
@ -26,15 +26,13 @@ describe('ESSearchSource', () => {
|
|||
expect(esSearchSource instanceof ESSearchSource).toBe(true);
|
||||
});
|
||||
|
||||
describe('ITiledSingleLayerVectorSource', () => {
|
||||
it('mb-source params', () => {
|
||||
describe('IMvtVectorSource', () => {
|
||||
it('getTileSourceLayer', () => {
|
||||
const esSearchSource = new ESSearchSource(mockDescriptor);
|
||||
expect(esSearchSource.getMinZoom()).toBe(0);
|
||||
expect(esSearchSource.getMaxZoom()).toBe(24);
|
||||
expect(esSearchSource.getLayerName()).toBe('hits');
|
||||
expect(esSearchSource.getTileSourceLayer()).toBe('hits');
|
||||
});
|
||||
|
||||
describe('getUrlTemplateWithMeta', () => {
|
||||
describe('getTileUrl', () => {
|
||||
const geoFieldName = 'bar';
|
||||
const mockIndexPatternService = {
|
||||
get() {
|
||||
|
@ -115,9 +113,9 @@ describe('ESSearchSource', () => {
|
|||
geoField: geoFieldName,
|
||||
indexPatternId: 'ipId',
|
||||
});
|
||||
const urlTemplateWithMeta = await esSearchSource.getUrlTemplateWithMeta(searchFilters);
|
||||
expect(urlTemplateWithMeta.urlTemplate).toBe(
|
||||
`rootdir/api/maps/mvt/getTile/{z}/{x}/{y}.pbf?geometryFieldName=bar&index=foobar-title-*&requestBody=(foobar:ES_DSL_PLACEHOLDER,params:('0':('0':index,'1':(fields:(),title:'foobar-title-*')),'1':('0':size,'1':1000),'2':('0':filter,'1':!()),'3':('0':query),'4':('0':index,'1':(fields:(),title:'foobar-title-*')),'5':('0':query,'1':(language:KQL,query:'tooltipField: foobar')),'6':('0':fieldsFromSource,'1':!(tooltipField,styleField)),'7':('0':source,'1':!(tooltipField,styleField))))`
|
||||
const tileUrl = await esSearchSource.getTileUrl(searchFilters, '1234');
|
||||
expect(tileUrl).toBe(
|
||||
`rootdir/api/maps/mvt/getTile/{z}/{x}/{y}.pbf?geometryFieldName=bar&index=foobar-title-*&requestBody=(foobar:ES_DSL_PLACEHOLDER,params:('0':('0':index,'1':(fields:(),title:'foobar-title-*')),'1':('0':size,'1':1000),'2':('0':filter,'1':!()),'3':('0':query),'4':('0':index,'1':(fields:(),title:'foobar-title-*')),'5':('0':query,'1':(language:KQL,query:'tooltipField: foobar')),'6':('0':fieldsFromSource,'1':!(tooltipField,styleField)),'7':('0':source,'1':!(tooltipField,styleField))))&token=1234`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -35,7 +35,6 @@ import {
|
|||
FIELD_ORIGIN,
|
||||
GIS_API_PATH,
|
||||
MVT_GETTILE_API_PATH,
|
||||
MVT_TOKEN_PARAM_NAME,
|
||||
SCALING_TYPES,
|
||||
SOURCE_TYPES,
|
||||
VECTOR_SHAPE_TYPE,
|
||||
|
@ -60,14 +59,12 @@ import {
|
|||
} from '../../../../../../../src/plugins/data/common';
|
||||
import { ImmutableSourceProperty, SourceEditorArgs } from '../source';
|
||||
import { IField } from '../../fields/field';
|
||||
import { GeoJsonWithMeta, SourceStatus } from '../vector_source';
|
||||
import { ITiledSingleLayerVectorSource } from '../tiled_single_layer_vector_source';
|
||||
import { GeoJsonWithMeta, IMvtVectorSource, SourceStatus } from '../vector_source';
|
||||
import { ITooltipProperty } from '../../tooltips/tooltip_property';
|
||||
import { DataRequest } from '../../util/data_request';
|
||||
import { isValidStringConfig } from '../../util/valid_string_config';
|
||||
import { TopHitsUpdateSourceEditor } from './top_hits';
|
||||
import { getDocValueAndSourceFields, ScriptField } from './util/get_docvalue_source_fields';
|
||||
import { ITiledSingleLayerMvtParams } from '../tiled_single_layer_vector_source/tiled_single_layer_vector_source';
|
||||
import {
|
||||
addFeatureToIndex,
|
||||
deleteFeatureFromIndex,
|
||||
|
@ -85,8 +82,6 @@ type ESSearchSourceSyncMeta = Pick<
|
|||
| 'topHitsSize'
|
||||
>;
|
||||
|
||||
const ES_MVT_HITS_LAYER_NAME = 'hits';
|
||||
|
||||
export function timerangeToTimeextent(timerange: TimeRange): Timeslice | undefined {
|
||||
const timeRangeBounds = getTimeFilter().calculateBounds(timerange);
|
||||
return timeRangeBounds.min !== undefined && timeRangeBounds.max !== undefined
|
||||
|
@ -101,7 +96,7 @@ export const sourceTitle = i18n.translate('xpack.maps.source.esSearchTitle', {
|
|||
defaultMessage: 'Documents',
|
||||
});
|
||||
|
||||
export class ESSearchSource extends AbstractESSource implements ITiledSingleLayerVectorSource {
|
||||
export class ESSearchSource extends AbstractESSource implements IMvtVectorSource {
|
||||
readonly _descriptor: ESSearchSourceDescriptor;
|
||||
protected readonly _tooltipFields: ESDocField[];
|
||||
|
||||
|
@ -764,10 +759,6 @@ export class ESSearchSource extends AbstractESSource implements ITiledSingleLaye
|
|||
return reason;
|
||||
}
|
||||
|
||||
getLayerName(): string {
|
||||
return ES_MVT_HITS_LAYER_NAME;
|
||||
}
|
||||
|
||||
async _getEditableIndex(): Promise<string> {
|
||||
const indexList = await this.getSourceIndexList();
|
||||
if (indexList.length === 0) {
|
||||
|
@ -800,9 +791,11 @@ export class ESSearchSource extends AbstractESSource implements ITiledSingleLaye
|
|||
await deleteFeatureFromIndex(index, featureId);
|
||||
}
|
||||
|
||||
async getUrlTemplateWithMeta(
|
||||
searchFilters: VectorSourceRequestMeta
|
||||
): Promise<ITiledSingleLayerMvtParams> {
|
||||
getTileSourceLayer(): string {
|
||||
return 'hits';
|
||||
}
|
||||
|
||||
async getTileUrl(searchFilters: VectorSourceRequestMeta, refreshToken: string): Promise<string> {
|
||||
const indexPattern = await this.getIndexPattern();
|
||||
const indexSettings = await loadIndexSettings(indexPattern.title);
|
||||
|
||||
|
@ -836,18 +829,11 @@ export class ESSearchSource extends AbstractESSource implements ITiledSingleLaye
|
|||
`/${GIS_API_PATH}/${MVT_GETTILE_API_PATH}/{z}/{x}/{y}.pbf`
|
||||
);
|
||||
|
||||
const urlTemplate = `${mvtUrlServicePath}\
|
||||
return `${mvtUrlServicePath}\
|
||||
?geometryFieldName=${this._descriptor.geoField}\
|
||||
&index=${indexPattern.title}\
|
||||
&requestBody=${risonDsl}`;
|
||||
|
||||
return {
|
||||
refreshTokenParamName: MVT_TOKEN_PARAM_NAME,
|
||||
layerName: this.getLayerName(),
|
||||
minSourceZoom: this.getMinZoom(),
|
||||
maxSourceZoom: this.getMaxZoom(),
|
||||
urlTemplate,
|
||||
};
|
||||
&requestBody=${risonDsl}\
|
||||
&token=${refreshToken}`;
|
||||
}
|
||||
|
||||
async getTimesliceMaskFieldName(): Promise<string | null> {
|
||||
|
|
|
@ -19,14 +19,11 @@ const descriptor: TiledSingleLayerVectorSourceDescriptor = {
|
|||
tooltipProperties: [],
|
||||
};
|
||||
|
||||
describe('getUrlTemplateWithMeta', () => {
|
||||
it('should echo configuration', async () => {
|
||||
describe('IMvtVectorSoucegetTileUrl', () => {
|
||||
it('getTileUrl', async () => {
|
||||
const source = new MVTSingleLayerVectorSource(descriptor);
|
||||
const config = await source.getUrlTemplateWithMeta();
|
||||
expect(config.urlTemplate).toEqual(descriptor.urlTemplate);
|
||||
expect(config.layerName).toEqual(descriptor.layerName);
|
||||
expect(config.minSourceZoom).toEqual(descriptor.minSourceZoom);
|
||||
expect(config.maxSourceZoom).toEqual(descriptor.maxSourceZoom);
|
||||
const tileUrl = await source.getTileUrl();
|
||||
expect(tileUrl).toEqual(descriptor.urlTemplate);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -10,8 +10,7 @@ import uuid from 'uuid/v4';
|
|||
import React from 'react';
|
||||
import { GeoJsonProperties, Geometry, Position } from 'geojson';
|
||||
import { AbstractSource, ImmutableSourceProperty, SourceEditorArgs } from '../source';
|
||||
import { BoundsRequestMeta, GeoJsonWithMeta } from '../vector_source';
|
||||
import { ITiledSingleLayerVectorSource } from '../tiled_single_layer_vector_source';
|
||||
import { BoundsRequestMeta, GeoJsonWithMeta, IMvtVectorSource } from '../vector_source';
|
||||
import {
|
||||
FIELD_ORIGIN,
|
||||
MAX_ZOOM,
|
||||
|
@ -30,7 +29,6 @@ import { MVTField } from '../../fields/mvt_field';
|
|||
import { UpdateSourceEditor } from './update_source_editor';
|
||||
import { ITooltipProperty, TooltipProperty } from '../../tooltips/tooltip_property';
|
||||
import { Adapters } from '../../../../../../../src/plugins/inspector/common/adapters';
|
||||
import { ITiledSingleLayerMvtParams } from '../tiled_single_layer_vector_source/tiled_single_layer_vector_source';
|
||||
|
||||
export const sourceTitle = i18n.translate(
|
||||
'xpack.maps.source.MVTSingleLayerVectorSource.sourceTitle',
|
||||
|
@ -39,10 +37,7 @@ export const sourceTitle = i18n.translate(
|
|||
}
|
||||
);
|
||||
|
||||
export class MVTSingleLayerVectorSource
|
||||
extends AbstractSource
|
||||
implements ITiledSingleLayerVectorSource
|
||||
{
|
||||
export class MVTSingleLayerVectorSource extends AbstractSource implements IMvtVectorSource {
|
||||
static createDescriptor({
|
||||
urlTemplate,
|
||||
layerName,
|
||||
|
@ -145,7 +140,7 @@ export class MVTSingleLayerVectorSource
|
|||
}
|
||||
|
||||
getGeoJsonWithMeta(): Promise<GeoJsonWithMeta> {
|
||||
// Having this method here is a consequence of ITiledSingleLayerVectorSource extending IVectorSource.
|
||||
// Having this method here is a consequence of IMvtVectorSource extending IVectorSource.
|
||||
throw new Error('Does not implement getGeoJsonWithMeta');
|
||||
}
|
||||
|
||||
|
@ -153,7 +148,7 @@ export class MVTSingleLayerVectorSource
|
|||
return this.getMVTFields();
|
||||
}
|
||||
|
||||
getLayerName(): string {
|
||||
getTileSourceLayer(): string {
|
||||
return this._descriptor.layerName;
|
||||
}
|
||||
|
||||
|
@ -165,16 +160,11 @@ export class MVTSingleLayerVectorSource
|
|||
}
|
||||
|
||||
async getDisplayName(): Promise<string> {
|
||||
return this.getLayerName();
|
||||
return this.getTileSourceLayer();
|
||||
}
|
||||
|
||||
async getUrlTemplateWithMeta(): Promise<ITiledSingleLayerMvtParams> {
|
||||
return {
|
||||
urlTemplate: this._descriptor.urlTemplate,
|
||||
layerName: this._descriptor.layerName,
|
||||
minSourceZoom: this._descriptor.minSourceZoom,
|
||||
maxSourceZoom: this._descriptor.maxSourceZoom,
|
||||
};
|
||||
async getTileUrl(): Promise<string> {
|
||||
return this._descriptor.urlTemplate;
|
||||
}
|
||||
|
||||
async getSupportedShapeTypes(): Promise<VECTOR_SHAPE_TYPE[]> {
|
||||
|
|
|
@ -33,7 +33,7 @@ export class UpdateSourceEditor extends Component<Props, State> {
|
|||
|
||||
_handleChange = (settings: MVTSettings) => {
|
||||
const changes: OnSourceChangeArgs[] = [];
|
||||
if (settings.layerName !== this.props.source.getLayerName()) {
|
||||
if (settings.layerName !== this.props.source.getTileSourceLayer()) {
|
||||
changes.push({ propName: 'layerName', value: settings.layerName });
|
||||
}
|
||||
if (settings.minSourceZoom !== this.props.source.getMinZoom()) {
|
||||
|
@ -87,7 +87,7 @@ export class UpdateSourceEditor extends Component<Props, State> {
|
|||
<EuiSpacer size="m" />
|
||||
<MVTSingleLayerSourceSettings
|
||||
handleChange={this._handleChange}
|
||||
layerName={this.props.source.getLayerName() || ''}
|
||||
layerName={this.props.source.getTileSourceLayer() || ''}
|
||||
fields={fieldDescriptors}
|
||||
minSourceZoom={this.props.source.getMinZoom()}
|
||||
maxSourceZoom={this.props.source.getMaxZoom()}
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
export type {
|
||||
ITiledSingleLayerMvtParams,
|
||||
ITiledSingleLayerVectorSource,
|
||||
} from './tiled_single_layer_vector_source';
|
|
@ -1,26 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { VectorSourceRequestMeta } from '../../../../common/descriptor_types';
|
||||
import { IVectorSource } from '../vector_source';
|
||||
|
||||
export interface ITiledSingleLayerMvtParams {
|
||||
layerName: string;
|
||||
urlTemplate: string;
|
||||
minSourceZoom: number;
|
||||
maxSourceZoom: number;
|
||||
refreshTokenParamName?: string;
|
||||
}
|
||||
|
||||
export interface ITiledSingleLayerVectorSource extends IVectorSource {
|
||||
getUrlTemplateWithMeta(
|
||||
searchFilters: VectorSourceRequestMeta
|
||||
): Promise<ITiledSingleLayerMvtParams>;
|
||||
getMinZoom(): number;
|
||||
getMaxZoom(): number;
|
||||
getLayerName(): string;
|
||||
}
|
|
@ -6,3 +6,4 @@
|
|||
*/
|
||||
|
||||
export * from './vector_source';
|
||||
export type { IMvtVectorSource } from './mvt_vector_source';
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { VectorSourceRequestMeta } from '../../../../common/descriptor_types';
|
||||
import { IVectorSource } from '../vector_source';
|
||||
|
||||
export interface IMvtVectorSource extends IVectorSource {
|
||||
/*
|
||||
* IMvtVectorSource.getTileUrl returns the tile source URL.
|
||||
* Append refreshToken as a URL parameter to force tile re-fetch on refresh (not required)
|
||||
*/
|
||||
getTileUrl(searchFilters: VectorSourceRequestMeta, refreshToken: string): Promise<string>;
|
||||
|
||||
/*
|
||||
* Tile vector sources can contain multiple layers. For example, elasticsearch _mvt tiles contain the layers "hits", "aggs", and "meta".
|
||||
* Use getTileSourceLayer to specify the displayed source layer.
|
||||
*/
|
||||
getTileSourceLayer(): string;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue