[Maps] refactor ITiledSingleLayerVectorSource into MvtVectorSource (#120566)

* [Maps] refactor MvtVectorSource

* clean up

* more cleanup

* remove file with no extension

* lint
This commit is contained in:
Nathan Reese 2021-12-07 08:58:33 -07:00 committed by GitHub
parent d64d7ae0b7
commit defdc8c30b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 152 additions and 260 deletions

View file

@ -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}`;
}

View file

@ -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;
}) {

View file

@ -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++) {

View file

@ -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,

View file

@ -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) {

View file

@ -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,

View file

@ -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
) {

View file

@ -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"
);
});
});

View file

@ -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 {

View file

@ -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`
);
});
});

View file

@ -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> {

View file

@ -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);
});
});

View file

@ -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[]> {

View file

@ -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()}

View file

@ -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';

View file

@ -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;
}

View file

@ -6,3 +6,4 @@
*/
export * from './vector_source';
export type { IMvtVectorSource } from './mvt_vector_source';

View file

@ -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;
}