Skip to content

Commit

Permalink
[Maps] Add 3rd party vector tile support (#62084) (#63761)
Browse files Browse the repository at this point in the history
Adds support for adding an external vector tile service to Maps. This is experimental functionality. To enable, add `xpack.maps.enableVectorTiles: true` to the `kibana.yml`configuration file.

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
  • Loading branch information
thomasneirynck and elasticmachine authored Apr 21, 2020
1 parent e400469 commit b469fe2
Show file tree
Hide file tree
Showing 37 changed files with 816 additions and 118 deletions.
2 changes: 1 addition & 1 deletion src/plugins/kibana_react/public/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export * from './ui_settings';
export * from './field_icon';
export * from './table_list_view';
export * from './split_panel';
export { ValidatedDualRange } from './validated_range';
export { ValidatedDualRange, Value } from './validated_range';
export * from './notifications';
export { Markdown, MarkdownSimple } from './markdown';
export { reactToUiComponent, uiToReactComponent } from './adapters';
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/kibana_react/public/validated_range/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@
* under the License.
*/

export { ValidatedDualRange } from './validated_dual_range';
export { ValidatedDualRange, Value } from './validated_dual_range';
2 changes: 2 additions & 0 deletions x-pack/legacy/plugins/maps/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export function maps(kibana) {
return {
showMapVisualizationTypes: serverConfig.get('xpack.maps.showMapVisualizationTypes'),
showMapsInspectorAdapter: serverConfig.get('xpack.maps.showMapsInspectorAdapter'),
enableVectorTiles: serverConfig.get('xpack.maps.enableVectorTiles'),
preserveDrawingBuffer: serverConfig.get('xpack.maps.preserveDrawingBuffer'),
isEmsEnabled: mapConfig.includeElasticMapsService,
emsFontLibraryUrl: mapConfig.emsFontLibraryUrl,
Expand Down Expand Up @@ -85,6 +86,7 @@ export function maps(kibana) {
showMapVisualizationTypes: Joi.boolean().default(false),
showMapsInspectorAdapter: Joi.boolean().default(false), // flag used in functional testing
preserveDrawingBuffer: Joi.boolean().default(false), // flag used in functional testing
enableVectorTiles: Joi.boolean().default(false), // flag used to enable/disable vector-tiles
}).default();
},

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,13 @@ export class AddLayerPanel extends Component {
return;
}

const style =
const styleDescriptor =
this.state.layer && this.state.layer.getCurrentStyle()
? this.state.layer.getCurrentStyle().getDescriptor()
: null;
const layerInitProps = {
...options,
style: style,
style: styleDescriptor,
};
const newLayer = source.createDefaultLayer(layerInitProps, this.props.mapColors);
if (!this._isMounted) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,13 @@ import {
updateLayerMinZoom,
updateLayerAlpha,
} from '../../../actions/map_actions';
import { MAX_ZOOM } from '../../../../../../../plugins/maps/common/constants';

function mapStateToProps(state = {}) {
const selectedLayer = getSelectedLayer(state);
return {
minVisibilityZoom: selectedLayer.getMinSourceZoom(),
maxVisibilityZoom: MAX_ZOOM,
alpha: selectedLayer.getAlpha(),
label: selectedLayer.getLabel(),
layerId: selectedLayer.getId(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,15 @@ import { ValidatedRange } from '../../../../../../../plugins/maps/public/compone
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import { ValidatedDualRange } from '../../../../../../../../src/plugins/kibana_react/public';
import { MAX_ZOOM, MIN_ZOOM } from '../../../../common/constants';

export function LayerSettings(props) {
const onLabelChange = event => {
const label = event.target.value;
props.updateLabel(props.layerId, label);
};

const onZoomChange = ([min, max]) => {
props.updateMinZoom(props.layerId, Math.max(MIN_ZOOM, parseInt(min, 10)));
props.updateMaxZoom(props.layerId, Math.min(MAX_ZOOM, parseInt(max, 10)));
props.updateMinZoom(props.layerId, Math.max(props.minVisibilityZoom, parseInt(min, 10)));
props.updateMaxZoom(props.layerId, Math.min(props.maxVisibilityZoom, parseInt(max, 10)));
};

const onAlphaChange = alpha => {
Expand All @@ -38,8 +36,8 @@ export function LayerSettings(props) {
defaultMessage: 'Visibility',
})}
formRowDisplay="columnCompressed"
min={MIN_ZOOM}
max={MAX_ZOOM}
min={props.minVisibilityZoom}
max={props.maxVisibilityZoom}
value={[props.minZoom, props.maxZoom]}
showInput="inputWithPopover"
showRange
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@ import {
} from './utils';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { getGlyphUrl, isRetina } from '../../../../../../../plugins/maps/public/meta';
import { DECIMAL_DEGREES_PRECISION, ZOOM_PRECISION } from '../../../../common/constants';
import {
DECIMAL_DEGREES_PRECISION,
MAX_ZOOM,
MIN_ZOOM,
ZOOM_PRECISION,
} from '../../../../common/constants';
import mapboxgl from 'mapbox-gl/dist/mapbox-gl-csp';
import mbWorkerUrl from '!!file-loader!mapbox-gl/dist/mapbox-gl-csp-worker';
import mbRtlPlugin from '!!file-loader!@mapbox/mapbox-gl-rtl-text/mapbox-gl-rtl-text.min.js';
Expand Down Expand Up @@ -132,6 +137,8 @@ export class MBMapContainer extends React.Component {
scrollZoom: this.props.scrollZoom,
preserveDrawingBuffer: getInjectedVarFunc()('preserveDrawingBuffer', false),
interactive: !this.props.disableInteractive,
minZoom: MIN_ZOOM,
maxZoom: MAX_ZOOM,
};
const initialView = _.get(this.props.goto, 'center');
if (initialView) {
Expand Down
7 changes: 0 additions & 7 deletions x-pack/legacy/plugins/maps/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,6 @@
* you may not use this file except in compliance with the Elastic License.
*/

// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import '../../../../plugins/maps/public/layers/layer_wizard_registry';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import '../../../../plugins/maps/public/layers/sources/source_registry';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import '../../../../plugins/maps/public/layers/load_layer_wizards';

import { Plugin, CoreStart, CoreSetup } from 'src/core/public';
// @ts-ignore
import { Start as InspectorStartContract } from 'src/plugins/inspector/public';
Expand Down
4 changes: 4 additions & 0 deletions x-pack/legacy/plugins/maps/public/selectors/map_selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import { BlendedVectorLayer } from '../../../../../plugins/maps/public/layers/bl
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { getTimeFilter } from '../../../../../plugins/maps/public/kibana_services';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { TiledVectorLayer } from '../../../../../plugins/maps/public/layers/tiled_vector_layer';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { getInspectorAdapters } from '../../../../../plugins/maps/public/reducers/non_serializable_instances';
import {
copyPersistentState,
Expand Down Expand Up @@ -51,6 +53,8 @@ function createLayerInstance(layerDescriptor, inspectorAdapters) {
return new HeatmapLayer({ layerDescriptor, source });
case BlendedVectorLayer.type:
return new BlendedVectorLayer({ layerDescriptor, source });
case TiledVectorLayer.type:
return new TiledVectorLayer({ layerDescriptor, source });
default:
throw new Error(`Unrecognized layerType ${layerDescriptor.type}`);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*/

jest.mock('../../../../../plugins/maps/public/layers/vector_layer', () => {});
jest.mock('../../../../../plugins/maps/public/layers/tiled_vector_layer', () => {});
jest.mock('../../../../../plugins/maps/public/layers/blended_vector_layer', () => {});
jest.mock('../../../../../plugins/maps/public/layers/heatmap_layer', () => {});
jest.mock('../../../../../plugins/maps/public/layers/vector_tile_layer', () => {});
Expand Down
4 changes: 3 additions & 1 deletion x-pack/plugins/maps/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,10 @@ export function createMapPath(id: string) {
export enum LAYER_TYPE {
TILE = 'TILE',
VECTOR = 'VECTOR',
VECTOR_TILE = 'VECTOR_TILE',
VECTOR_TILE = 'VECTOR_TILE', // for static display of mvt vector tiles with a mapbox stylesheet. Does not support any ad-hoc configurations. Used for consuming EMS vector tiles.
HEATMAP = 'HEATMAP',
BLENDED_VECTOR = 'BLENDED_VECTOR',
TILED_VECTOR = 'TILED_VECTOR', // similar to a regular vector-layer, but it consumes the data as .mvt tilea iso GeoJson. It supports similar ad-hoc configurations like a regular vector layer (E.g. using IVectorStyle), although there is some loss of functionality e.g. does not support term joining
}

export enum SORT_ORDER {
Expand All @@ -61,6 +62,7 @@ export enum SOURCE_TYPES {
KIBANA_TILEMAP = 'KIBANA_TILEMAP',
REGIONMAP_FILE = 'REGIONMAP_FILE',
GEOJSON_FILE = 'GEOJSON_FILE',
MVT_SINGLE_LAYER = 'MVT_SINGLE_LAYER',
}

export enum FIELD_ORIGIN {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ type ESGeoGridSourceSyncMeta = {
requestType: RENDER_AS;
};

export type VectorSourceSyncMeta = ESSearchSourceSyncMeta | ESGeoGridSourceSyncMeta;
export type VectorSourceSyncMeta = ESSearchSourceSyncMeta | ESGeoGridSourceSyncMeta | null;

export type VectorSourceRequestMeta = MapFilters & {
applyGlobalQuery: boolean;
fieldNames: string[];
geogridPrecision: number;
geogridPrecision?: number;
sourceQuery: MapQuery;
sourceMeta: VectorSourceSyncMeta;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,18 @@ export type XYZTMSSourceDescriptor = AbstractSourceDescriptor &
urlTemplate: string;
};

export type TiledSingleLayerVectorSourceDescriptor = AbstractSourceDescriptor & {
urlTemplate: string;
layerName: string;

// These are the min/max zoom levels of the availability of the a particular layerName in the tileset at urlTemplate.
// These are _not_ the visible zoom-range of the data on a map.
// Tiled data can be displayed at higher levels of zoom than that they are stored in the tileset.
// e.g. EMS basemap data from level 14 is at most detailed resolution and can be displayed at higher levels
minSourceZoom: number;
maxSourceZoom: number;
};

export type JoinDescriptor = {
leftField: string;
right: ESTermSourceDescriptor;
Expand All @@ -107,7 +119,9 @@ export type SourceDescriptor =
| ESTermSourceDescriptor
| ESSearchSourceDescriptor
| ESGeoGridSourceDescriptor
| EMSFileSourceDescriptor;
| EMSFileSourceDescriptor
| ESPewPewSourceDescriptor
| TiledSingleLayerVectorSourceDescriptor;

export type LayerDescriptor = {
__dataRequests?: DataRequestDescriptor[];
Expand Down
4 changes: 3 additions & 1 deletion x-pack/plugins/maps/public/kibana_services.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ export const getFileUploadComponent = () => {
};

let getInjectedVar;
export const setInjectedVarFunc = getInjectedVarFunc => (getInjectedVar = getInjectedVarFunc);
export const setInjectedVarFunc = getInjectedVarFunc => {
getInjectedVar = getInjectedVarFunc;
};
export const getInjectedVarFunc = () => getInjectedVar;

let uiSettings;
Expand Down
15 changes: 14 additions & 1 deletion x-pack/plugins/maps/public/layers/layer.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { LayerDescriptor, MapExtent, MapFilters } from '../../common/descriptor_types';
import { LayerDescriptor, MapExtent, MapFilters, MapQuery } from '../../common/descriptor_types';
import { ISource } from './sources/source';
import { DataRequest } from './util/data_request';
import { SyncContext } from '../actions/map_actions';
Expand All @@ -17,6 +17,11 @@ export interface ILayer {
getSource(): ISource;
getSourceForEditing(): ISource;
syncData(syncContext: SyncContext): Promise<void>;
isVisible(): boolean;
showAtZoomLevel(zoomLevel: number): boolean;
getMinZoom(): number;
getMaxZoom(): number;
getMinSourceZoom(): number;
}

export interface ILayerArguments {
Expand All @@ -35,4 +40,12 @@ export class AbstractLayer implements ILayer {
getSource(): ISource;
getSourceForEditing(): ISource;
syncData(syncContext: SyncContext): Promise<void>;
isVisible(): boolean;
showAtZoomLevel(zoomLevel: number): boolean;
getMinZoom(): number;
getMaxZoom(): number;
getMinSourceZoom(): number;
getQuery(): MapQuery;
_removeStaleMbSourcesAndLayers(mbMap: unknown): void;
_requiresPrevSourceCleanup(mbMap: unknown): boolean;
}
36 changes: 27 additions & 9 deletions x-pack/plugins/maps/public/layers/layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,8 @@ export class AbstractLayer {
defaultMessage: `Layer is hidden.`,
});
} else if (!this.showAtZoomLevel(zoomLevel)) {
const { minZoom, maxZoom } = this.getZoomConfig();
const minZoom = this.getMinZoom();
const maxZoom = this.getMaxZoom();
icon = <EuiIcon size="m" type="expand" />;
tooltipContent = i18n.translate('xpack.maps.layer.zoomFeedbackTooltip', {
defaultMessage: `Layer is visible between zoom levels {minZoom} and {maxZoom}.`,
Expand Down Expand Up @@ -203,7 +204,7 @@ export class AbstractLayer {
}

showAtZoomLevel(zoom) {
return zoom >= this._descriptor.minZoom && zoom <= this._descriptor.maxZoom;
return zoom >= this.getMinZoom() && zoom <= this.getMaxZoom();
}

getMinZoom() {
Expand All @@ -214,6 +215,30 @@ export class AbstractLayer {
return this._descriptor.maxZoom;
}

getMinSourceZoom() {
return this._source.getMinZoom();
}

_requiresPrevSourceCleanup() {
return false;
}

_removeStaleMbSourcesAndLayers(mbMap) {
if (this._requiresPrevSourceCleanup(mbMap)) {
const mbStyle = mbMap.getStyle();
mbStyle.layers.forEach(mbLayer => {
if (this.ownsMbLayerId(mbLayer.id)) {
mbMap.removeLayer(mbLayer.id);
}
});
Object.keys(mbStyle.sources).some(mbSourceId => {
if (this.ownsMbSourceId(mbSourceId)) {
mbMap.removeSource(mbSourceId);
}
});
}
}

getAlpha() {
return this._descriptor.alpha;
}
Expand All @@ -222,13 +247,6 @@ export class AbstractLayer {
return this._descriptor.query;
}

getZoomConfig() {
return {
minZoom: this._descriptor.minZoom,
maxZoom: this._descriptor.maxZoom,
};
}

getCurrentStyle() {
return this._style;
}
Expand Down
30 changes: 0 additions & 30 deletions x-pack/plugins/maps/public/layers/load_layer_wizards.js

This file was deleted.

Loading

0 comments on commit b469fe2

Please sign in to comment.