From ae139f927f14f59086ebe5a4ace84830084fb6f4 Mon Sep 17 00:00:00 2001 From: Daniil Date: Thu, 14 Jan 2021 16:09:05 +0300 Subject: [PATCH] [TileMap][RegionMap] Implement custom renderers and expression builders (#84775) (#88308) * Convert to typescript * Move related files directly into plugin * Implement toExpressionAst * Remove build_pipeline dedicated fn * Async import converter * Create a custom renderer * Remove ExprVis instance usage in maps visualizations * Use uiState updates * Create wrapper component * Update rendering * Create region map expression renderer * Remove resize subscription * Fix custom visualization expression * Update interpreter functional tests * Use types from geojson Co-authored-by: Alexey Antonov Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Alexey Antonov Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- src/plugins/expressions/public/render.ts | 2 +- .../external_basemap_types.ts => types.ts} | 15 +-- .../components/wms_internal_options.tsx | 2 +- .../public/components/wms_options.tsx | 9 +- src/plugins/maps_legacy/public/index.ts | 8 -- .../public/map/base_maps_visualization.js | 41 +++---- .../public/map/geohash_columns.test.ts | 27 +++++ .../maps_legacy/public/map/geohash_columns.ts | 38 +++++++ .../maps_legacy/public/map/kibana_map.js | 20 +--- .../maps_legacy/public/map/precision.ts | 2 +- .../public/map/zoom_to_precision.ts | 2 +- ...est.js.snap => region_map_fn.test.ts.snap} | 5 +- .../region_map/public/components/index.tsx | 29 +++++ .../public/components/region_map_options.tsx | 7 +- src/plugins/region_map/public/plugin.ts | 4 +- ...n_map_fn.test.js => region_map_fn.test.ts} | 7 +- .../{region_map_fn.js => region_map_fn.ts} | 30 ++++- .../region_map/public/region_map_renderer.tsx | 52 +++++++++ ...{region_map_type.js => region_map_type.ts} | 33 +++--- .../public}/region_map_types.ts | 9 +- .../public/region_map_visualization.js | 24 ++-- .../public/region_map_visualization.scss | 4 + .../region_map_visualization_component.tsx | 103 ++++++++++++++++++ src/plugins/region_map/public/to_ast.ts | 59 ++++++++++ ....test.js.snap => tile_map_fn.test.ts.snap} | 5 +- src/plugins/tile_map/public/_tile_map.scss | 15 --- .../tile_map/public/components/index.tsx | 25 +++++ .../public/components/tile_map_options.tsx | 8 +- src/plugins/tile_map/public/geohash_layer.js | 3 +- src/plugins/tile_map/public/index.scss | 8 -- src/plugins/tile_map/public/plugin.ts | 16 ++- ...tilemap_fn.test.js => tile_map_fn.test.ts} | 17 +-- .../public/{tile_map_fn.js => tile_map_fn.ts} | 40 +++++-- .../tile_map/public/tile_map_renderer.tsx | 52 +++++++++ .../{tile_map_type.js => tile_map_type.ts} | 26 +++-- .../tile_map/public/tile_map_visualization.js | 22 ++-- .../public/tile_map_visualization.scss | 4 + .../tile_map_visualization_component.tsx | 103 ++++++++++++++++++ src/plugins/tile_map/public/to_ast.ts | 59 ++++++++++ src/plugins/tile_map/public/types.ts | 57 ++++++++++ .../public/utils/convert_to_geojson.ts} | 52 +++++---- .../public/utils}/decode_geo_hash.test.ts | 9 +- .../public/utils}/decode_geo_hash.ts | 23 +--- .../public/utils/grid_dimensions.ts} | 4 +- .../types => tile_map/public/utils}/index.ts | 9 +- .../public/utils}/map_types.ts | 0 .../__snapshots__/build_pipeline.test.ts.snap | 6 - .../public/legacy/build_pipeline.test.ts | 56 +--------- .../public/legacy/build_pipeline.ts | 71 +----------- .../screenshots/baseline/partial_test_3.png | Bin 1994 -> 10749 bytes .../snapshots/baseline/partial_test_3.json | 2 +- .../snapshots/session/partial_test_3.json | 2 +- .../test_suites/run_pipeline/basic.ts | 2 +- 53 files changed, 841 insertions(+), 387 deletions(-) rename src/plugins/maps_legacy/public/common/{types/external_basemap_types.ts => types.ts} (73%) create mode 100644 src/plugins/maps_legacy/public/map/geohash_columns.test.ts create mode 100644 src/plugins/maps_legacy/public/map/geohash_columns.ts rename src/plugins/region_map/public/__snapshots__/{region_map_fn.test.js.snap => region_map_fn.test.ts.snap} (93%) create mode 100644 src/plugins/region_map/public/components/index.tsx rename src/plugins/region_map/public/{region_map_fn.test.js => region_map_fn.test.ts} (92%) rename src/plugins/region_map/public/{region_map_fn.js => region_map_fn.ts} (67%) create mode 100644 src/plugins/region_map/public/region_map_renderer.tsx rename src/plugins/region_map/public/{region_map_type.js => region_map_type.ts} (87%) rename src/plugins/{maps_legacy/public/common/types => region_map/public}/region_map_types.ts (81%) create mode 100644 src/plugins/region_map/public/region_map_visualization.scss create mode 100644 src/plugins/region_map/public/region_map_visualization_component.tsx create mode 100644 src/plugins/region_map/public/to_ast.ts rename src/plugins/tile_map/public/__snapshots__/{tilemap_fn.test.js.snap => tile_map_fn.test.ts.snap} (93%) delete mode 100644 src/plugins/tile_map/public/_tile_map.scss create mode 100644 src/plugins/tile_map/public/components/index.tsx delete mode 100644 src/plugins/tile_map/public/index.scss rename src/plugins/tile_map/public/{tilemap_fn.test.js => tile_map_fn.test.ts} (83%) rename src/plugins/tile_map/public/{tile_map_fn.js => tile_map_fn.ts} (66%) create mode 100644 src/plugins/tile_map/public/tile_map_renderer.tsx rename src/plugins/tile_map/public/{tile_map_type.js => tile_map_type.ts} (90%) create mode 100644 src/plugins/tile_map/public/tile_map_visualization.scss create mode 100644 src/plugins/tile_map/public/tile_map_visualization_component.tsx create mode 100644 src/plugins/tile_map/public/to_ast.ts create mode 100644 src/plugins/tile_map/public/types.ts rename src/plugins/{maps_legacy/public/map/convert_to_geojson.js => tile_map/public/utils/convert_to_geojson.ts} (75%) rename src/plugins/{maps_legacy/public/map => tile_map/public/utils}/decode_geo_hash.test.ts (79%) rename src/plugins/{maps_legacy/public/map => tile_map/public/utils}/decode_geo_hash.ts (79%) rename src/plugins/{maps_legacy/public/map/grid_dimensions.js => tile_map/public/utils/grid_dimensions.ts} (92%) rename src/plugins/{maps_legacy/public/common/types => tile_map/public/utils}/index.ts (79%) rename src/plugins/{maps_legacy/public/common/types => tile_map/public/utils}/map_types.ts (100%) diff --git a/src/plugins/expressions/public/render.ts b/src/plugins/expressions/public/render.ts index e3091b908dec..c57f01dbd902 100644 --- a/src/plugins/expressions/public/render.ts +++ b/src/plugins/expressions/public/render.ts @@ -110,7 +110,7 @@ export class ExpressionRenderHandler { }; } - render = async (value: any, uiState: any = {}) => { + render = async (value: any, uiState?: any) => { if (!value || typeof value !== 'object') { return this.handleRenderError(new Error('invalid data provided to the expression renderer')); } diff --git a/src/plugins/maps_legacy/public/common/types/external_basemap_types.ts b/src/plugins/maps_legacy/public/common/types.ts similarity index 73% rename from src/plugins/maps_legacy/public/common/types/external_basemap_types.ts rename to src/plugins/maps_legacy/public/common/types.ts index be9c4d0d9c37..802bed9f4b90 100644 --- a/src/plugins/maps_legacy/public/common/types/external_basemap_types.ts +++ b/src/plugins/maps_legacy/public/common/types.ts @@ -17,8 +17,7 @@ * under the License. */ -import { TmsLayer } from '../../index'; -import { MapTypes } from './map_types'; +import { TmsLayer } from '..'; export interface WMSOptions { selectedTmsLayer?: TmsLayer; @@ -33,15 +32,3 @@ export interface WMSOptions { styles?: string; }; } - -export interface TileMapVisParams { - colorSchema: string; - mapType: MapTypes; - isDesaturated: boolean; - addTooltip: boolean; - heatClusterSize: number; - legendPosition: 'bottomright' | 'bottomleft' | 'topright' | 'topleft'; - mapZoom: number; - mapCenter: [number, number]; - wms: WMSOptions; -} diff --git a/src/plugins/maps_legacy/public/components/wms_internal_options.tsx b/src/plugins/maps_legacy/public/components/wms_internal_options.tsx index 86c15f10ae55..b8a325ee539d 100644 --- a/src/plugins/maps_legacy/public/components/wms_internal_options.tsx +++ b/src/plugins/maps_legacy/public/components/wms_internal_options.tsx @@ -22,7 +22,7 @@ import { EuiLink, EuiSpacer, EuiText, EuiScreenReaderOnly } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { TextInputOption } from '../../../vis_default_editor/public'; -import { WMSOptions } from '../common/types/external_basemap_types'; +import { WMSOptions } from '../common/types'; interface WmsInternalOptions { wms: WMSOptions; diff --git a/src/plugins/maps_legacy/public/components/wms_options.tsx b/src/plugins/maps_legacy/public/components/wms_options.tsx index 79e08478f215..37ec3fcc9001 100644 --- a/src/plugins/maps_legacy/public/components/wms_options.tsx +++ b/src/plugins/maps_legacy/public/components/wms_options.tsx @@ -23,20 +23,19 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { TmsLayer } from '../index'; import { Vis } from '../../../visualizations/public'; -import { RegionMapVisParams } from '../common/types/region_map_types'; import { SelectOption, SwitchOption } from '../../../vis_default_editor/public'; import { WmsInternalOptions } from './wms_internal_options'; -import { WMSOptions, TileMapVisParams } from '../common/types/external_basemap_types'; +import { WMSOptions } from '../common/types'; -interface Props { - stateParams: TileMapVisParams | RegionMapVisParams; +interface Props { + stateParams: K; setValue: (title: 'wms', options: WMSOptions) => void; vis: Vis; } const mapLayerForOption = ({ id }: TmsLayer) => ({ text: id, value: id }); -function WmsOptions({ stateParams, setValue, vis }: Props) { +function WmsOptions({ stateParams, setValue, vis }: Props) { const { wms } = stateParams; const { tmsLayers } = vis.type.editorConfig.collections; const tmsLayerOptions = useMemo(() => tmsLayers.map(mapLayerForOption), [tmsLayers]); diff --git a/src/plugins/maps_legacy/public/index.ts b/src/plugins/maps_legacy/public/index.ts index 2654ded907cc..84edce6dbf8e 100644 --- a/src/plugins/maps_legacy/public/index.ts +++ b/src/plugins/maps_legacy/public/index.ts @@ -17,17 +17,12 @@ * under the License. */ -// @ts-ignore import { PluginInitializerContext } from 'kibana/public'; import { MapsLegacyPlugin } from './plugin'; // @ts-ignore import * as colorUtil from './map/color_util'; // @ts-ignore import { KibanaMapLayer } from './map/kibana_map_layer'; -// @ts-ignore -import { convertToGeoJson } from './map/convert_to_geojson'; -// @ts-ignore -import { getPrecision, geoContains } from './map/decode_geo_hash'; import { VectorLayer, FileLayerField, @@ -46,10 +41,7 @@ export function plugin(initializerContext: PluginInitializerContext) { /** @public */ export { - getPrecision, - geoContains, colorUtil, - convertToGeoJson, IServiceSettings, KibanaMapLayer, VectorLayer, diff --git a/src/plugins/maps_legacy/public/map/base_maps_visualization.js b/src/plugins/maps_legacy/public/map/base_maps_visualization.js index 406dae43c9b5..39612a1b6024 100644 --- a/src/plugins/maps_legacy/public/map/base_maps_visualization.js +++ b/src/plugins/maps_legacy/public/map/base_maps_visualization.js @@ -34,8 +34,9 @@ export function BaseMapsVisualizationProvider() { * @constructor */ return class BaseMapsVisualization { - constructor(element, vis) { - this.vis = vis; + constructor(element, handlers, initialVisParams) { + this.handlers = handlers; + this._params = initialVisParams; this._container = element; this._kibanaMap = null; this._chartData = null; //reference to data currently on the map. @@ -61,25 +62,31 @@ export function BaseMapsVisualizationProvider() { * @param status * @return {Promise} */ - async render(esResponse, visParams) { + async render(esResponse = this._esResponse, visParams = this._params) { + await this._mapIsLoaded; + if (!this._kibanaMap) { //the visualization has been destroyed; return; } - await this._mapIsLoaded; - this._kibanaMap.resize(); + this.resize(); this._params = visParams; await this._updateParams(); if (this._hasESResponseChanged(esResponse)) { + this._esResponse = esResponse; await this._updateData(esResponse); } - this._kibanaMap.useUiStateFromVisualization(this.vis); + this._kibanaMap.useUiStateFromVisualization(this.handlers.uiState); await this._whenBaseLayerIsLoaded(); } + resize() { + this._kibanaMap?.resize(); + } + /** * Creates an instance of a kibana-map with a single baselayer and assigns it to the this._kibanaMap property. * Clients can override this method to customize the initialization. @@ -87,11 +94,11 @@ export function BaseMapsVisualizationProvider() { */ async _makeKibanaMap() { const options = {}; - const uiState = this.vis.getUiState(); - const zoomFromUiState = parseInt(uiState.get('mapZoom')); - const centerFromUIState = uiState.get('mapCenter'); - options.zoom = !isNaN(zoomFromUiState) ? zoomFromUiState : this.vis.params.mapZoom; - options.center = centerFromUIState ? centerFromUIState : this.vis.params.mapCenter; + const zoomFromUiState = parseInt(this.handlers.uiState?.get('mapZoom')); + const centerFromUIState = this.handlers.uiState?.get('mapCenter'); + const { mapZoom, mapCenter } = this._getMapsParams(); + options.zoom = !isNaN(zoomFromUiState) ? zoomFromUiState : mapZoom; + options.center = centerFromUIState ? centerFromUIState : mapCenter; const modules = await lazyLoadMapsLegacyModules(); this._kibanaMap = new modules.KibanaMap(this._container, options); @@ -100,7 +107,7 @@ export function BaseMapsVisualizationProvider() { this._kibanaMap.addLegendControl(); this._kibanaMap.addFitControl(); - this._kibanaMap.persistUiStateForVisualization(this.vis); + this._kibanaMap.persistUiStateForVisualization(this.handlers.uiState); this._kibanaMap.on('baseLayer:loaded', () => { this._baseLayerDirty = false; @@ -212,7 +219,7 @@ export function BaseMapsVisualizationProvider() { } _hasESResponseChanged(data) { - return this._chartData !== data; + return this._esResponse !== data; } /** @@ -223,15 +230,11 @@ export function BaseMapsVisualizationProvider() { await this._updateBaseLayer(); this._kibanaMap.setLegendPosition(mapParams.legendPosition); this._kibanaMap.setShowTooltip(mapParams.addTooltip); - this._kibanaMap.useUiStateFromVisualization(this.vis); + this._kibanaMap.useUiStateFromVisualization(this.handlers.uiState); } _getMapsParams() { - return { - ...this.vis.type.visConfig.defaults, - type: this.vis.type.name, - ...this._params, - }; + return this._params; } _whenBaseLayerIsLoaded() { diff --git a/src/plugins/maps_legacy/public/map/geohash_columns.test.ts b/src/plugins/maps_legacy/public/map/geohash_columns.test.ts new file mode 100644 index 000000000000..e2a8eb575a9e --- /dev/null +++ b/src/plugins/maps_legacy/public/map/geohash_columns.test.ts @@ -0,0 +1,27 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { geohashColumns } from './geohash_columns'; + +test('geohashColumns', () => { + expect(geohashColumns(1)).toBe(8); + expect(geohashColumns(2)).toBe(8 * 4); + expect(geohashColumns(3)).toBe(8 * 4 * 8); + expect(geohashColumns(4)).toBe(8 * 4 * 8 * 4); +}); diff --git a/src/plugins/maps_legacy/public/map/geohash_columns.ts b/src/plugins/maps_legacy/public/map/geohash_columns.ts new file mode 100644 index 000000000000..db592306dc70 --- /dev/null +++ b/src/plugins/maps_legacy/public/map/geohash_columns.ts @@ -0,0 +1,38 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export function geohashColumns(precision: number): number { + return geohashCells(precision, 0); +} + +/** + * Get the number of geohash cells for a given precision + * + * @param {number} precision the geohash precision (1<=precision<=12). + * @param {number} axis constant for the axis 0=lengthwise (ie. columns, along longitude), 1=heightwise (ie. rows, along latitude). + * @returns {number} Number of geohash cells (rows or columns) at that precision + */ +function geohashCells(precision: number, axis: number) { + let cells = 1; + for (let i = 1; i <= precision; i += 1) { + /* On odd precisions, rows divide by 4 and columns by 8. Vice-versa on even precisions */ + cells *= i % 2 === axis ? 4 : 8; + } + return cells; +} diff --git a/src/plugins/maps_legacy/public/map/kibana_map.js b/src/plugins/maps_legacy/public/map/kibana_map.js index 3948692e5567..074c11e77b8a 100644 --- a/src/plugins/maps_legacy/public/map/kibana_map.js +++ b/src/plugins/maps_legacy/public/map/kibana_map.js @@ -672,14 +672,13 @@ export class KibanaMap extends EventEmitter { } } - persistUiStateForVisualization(visualization) { + persistUiStateForVisualization(uiState) { function persistMapStateInUiState() { - const uiState = visualization.getUiState(); const centerFromUIState = uiState.get('mapCenter'); const zoomFromUiState = parseInt(uiState.get('mapZoom')); if (isNaN(zoomFromUiState) || this.getZoomLevel() !== zoomFromUiState) { - visualization.uiStateVal('mapZoom', this.getZoomLevel()); + uiState.set('mapZoom', this.getZoomLevel()); } const centerFromMap = this.getCenter(); if ( @@ -687,24 +686,17 @@ export class KibanaMap extends EventEmitter { centerFromMap.lon !== centerFromUIState[1] || centerFromMap.lat !== centerFromUIState[0] ) { - visualization.uiStateVal('mapCenter', [centerFromMap.lat, centerFromMap.lon]); + uiState.set('mapCenter', [centerFromMap.lat, centerFromMap.lon]); } } - this._leafletMap.on('resize', () => { - visualization.sessionState.mapBounds = this.getBounds(); - }); - this._leafletMap.on('load', () => { - visualization.sessionState.mapBounds = this.getBounds(); - }); this.on('dragend', persistMapStateInUiState); this.on('zoomend', persistMapStateInUiState); } - useUiStateFromVisualization(visualization) { - const uiState = visualization.getUiState(); - const zoomFromUiState = parseInt(uiState.get('mapZoom')); - const centerFromUIState = uiState.get('mapCenter'); + useUiStateFromVisualization(uiState) { + const zoomFromUiState = parseInt(uiState?.get('mapZoom')); + const centerFromUIState = uiState?.get('mapCenter'); if (!isNaN(zoomFromUiState)) { this.setZoomLevel(zoomFromUiState); } diff --git a/src/plugins/maps_legacy/public/map/precision.ts b/src/plugins/maps_legacy/public/map/precision.ts index a1b3b72f201a..3dafd0813a17 100644 --- a/src/plugins/maps_legacy/public/map/precision.ts +++ b/src/plugins/maps_legacy/public/map/precision.ts @@ -19,7 +19,7 @@ // @ts-ignore import { getUiSettings } from '../kibana_services'; -import { geohashColumns } from './decode_geo_hash'; +import { geohashColumns } from './geohash_columns'; /** * Get the number of geohash columns (world-wide) for a given precision diff --git a/src/plugins/maps_legacy/public/map/zoom_to_precision.ts b/src/plugins/maps_legacy/public/map/zoom_to_precision.ts index 552c50959028..abad0a730a12 100644 --- a/src/plugins/maps_legacy/public/map/zoom_to_precision.ts +++ b/src/plugins/maps_legacy/public/map/zoom_to_precision.ts @@ -17,7 +17,7 @@ * under the License. */ -import { geohashColumns } from './decode_geo_hash'; +import { geohashColumns } from './geohash_columns'; const defaultMaxPrecision = 12; const minGeoHashPixels = 16; diff --git a/src/plugins/region_map/public/__snapshots__/region_map_fn.test.js.snap b/src/plugins/region_map/public/__snapshots__/region_map_fn.test.ts.snap similarity index 93% rename from src/plugins/region_map/public/__snapshots__/region_map_fn.test.js.snap rename to src/plugins/region_map/public/__snapshots__/region_map_fn.test.ts.snap index cb12712ae824..df72e75f5ad6 100644 --- a/src/plugins/region_map/public/__snapshots__/region_map_fn.test.js.snap +++ b/src/plugins/region_map/public/__snapshots__/region_map_fn.test.ts.snap @@ -2,12 +2,9 @@ exports[`interpreter/functions#regionmap returns an object with the correct structure 1`] = ` Object { - "as": "visualization", + "as": "region_map_vis", "type": "render", "value": Object { - "params": Object { - "listenOnChange": true, - }, "visConfig": Object { "addTooltip": true, "colorSchema": "Yellow to Red", diff --git a/src/plugins/region_map/public/components/index.tsx b/src/plugins/region_map/public/components/index.tsx new file mode 100644 index 000000000000..871bcde41400 --- /dev/null +++ b/src/plugins/region_map/public/components/index.tsx @@ -0,0 +1,29 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { lazy } from 'react'; +import { IServiceSettings } from 'src/plugins/maps_legacy/public'; +import { VisOptionsProps } from 'src/plugins/vis_default_editor/public'; +import { RegionMapVisParams } from '../region_map_types'; + +const RegionMapOptions = lazy(() => import('./region_map_options')); + +export const createRegionMapOptions = (getServiceSettings: () => Promise) => ( + props: VisOptionsProps +) => ; diff --git a/src/plugins/region_map/public/components/region_map_options.tsx b/src/plugins/region_map/public/components/region_map_options.tsx index b2bb250d66ee..497d75853ceb 100644 --- a/src/plugins/region_map/public/components/region_map_options.tsx +++ b/src/plugins/region_map/public/components/region_map_options.tsx @@ -24,7 +24,8 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { VisOptionsProps } from 'src/plugins/vis_default_editor/public'; import { FileLayerField, VectorLayer, IServiceSettings } from '../../../maps_legacy/public'; import { SelectOption, SwitchOption, NumberInputOption } from '../../../vis_default_editor/public'; -import { RegionMapVisParams, WmsOptions } from '../../../maps_legacy/public'; +import { WmsOptions } from '../../../maps_legacy/public'; +import { RegionMapVisParams } from '../region_map_types'; const mapLayerForOption = ({ layerId, name }: VectorLayer) => ({ text: name, @@ -212,4 +213,6 @@ function RegionMapOptions(props: RegionMapOptionsProps) { ); } -export { RegionMapOptions }; +// default export required for React.Lazy +// eslint-disable-next-line import/no-default-export +export { RegionMapOptions as default }; diff --git a/src/plugins/region_map/public/plugin.ts b/src/plugins/region_map/public/plugin.ts index e9978803ad5e..6bb98858ad12 100644 --- a/src/plugins/region_map/public/plugin.ts +++ b/src/plugins/region_map/public/plugin.ts @@ -44,9 +44,10 @@ import { RegionMapsConfigType } from './index'; import { MapsLegacyConfig } from '../../maps_legacy/config'; import { KibanaLegacyStart } from '../../kibana_legacy/public'; import { SharePluginStart } from '../../share/public'; +import { getRegionMapRenderer } from './region_map_renderer'; /** @private */ -interface RegionMapVisualizationDependencies { +export interface RegionMapVisualizationDependencies { uiSettings: IUiSettingsClient; regionmapsConfig: RegionMapsConfig; getServiceSettings: () => Promise; @@ -107,6 +108,7 @@ export class RegionMapPlugin implements Plugin { }; it('returns an object with the correct structure', () => { - const actual = fn( - context, - { visConfig: JSON.stringify(visConfig) }, - { logDatatable: jest.fn() } - ); + const actual = fn(context, { visConfig: JSON.stringify(visConfig) }); expect(actual).toMatchSnapshot(); }); }); diff --git a/src/plugins/region_map/public/region_map_fn.js b/src/plugins/region_map/public/region_map_fn.ts similarity index 67% rename from src/plugins/region_map/public/region_map_fn.js rename to src/plugins/region_map/public/region_map_fn.ts index cc99a5595d09..74f41cf647b5 100644 --- a/src/plugins/region_map/public/region_map_fn.js +++ b/src/plugins/region_map/public/region_map_fn.ts @@ -19,7 +19,27 @@ import { i18n } from '@kbn/i18n'; -export const createRegionMapFn = () => ({ +import type { ExpressionFunctionDefinition, Datatable, Render } from '../../expressions/public'; +import { RegionMapVisConfig } from './region_map_types'; + +interface Arguments { + visConfig: string | null; +} + +export interface RegionMapVisRenderValue { + visData: Datatable; + visType: 'region_map'; + visConfig: RegionMapVisConfig; +} + +export type RegionMapExpressionFunctionDefinition = ExpressionFunctionDefinition< + 'regionmap', + Datatable, + Arguments, + Render +>; + +export const createRegionMapFn = (): RegionMapExpressionFunctionDefinition => ({ name: 'regionmap', type: 'render', context: { @@ -32,24 +52,22 @@ export const createRegionMapFn = () => ({ visConfig: { types: ['string', 'null'], default: '"{}"', + help: '', }, }, fn(context, args, handlers) { - const visConfig = JSON.parse(args.visConfig); + const visConfig = args.visConfig && JSON.parse(args.visConfig); if (handlers?.inspectorAdapters?.tables) { handlers.inspectorAdapters.tables.logDatatable('default', context); } return { type: 'render', - as: 'visualization', + as: 'region_map_vis', value: { visData: context, visType: 'region_map', visConfig, - params: { - listenOnChange: true, - }, }, }; }, diff --git a/src/plugins/region_map/public/region_map_renderer.tsx b/src/plugins/region_map/public/region_map_renderer.tsx new file mode 100644 index 000000000000..f0597389b3d0 --- /dev/null +++ b/src/plugins/region_map/public/region_map_renderer.tsx @@ -0,0 +1,52 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { lazy } from 'react'; +import { render, unmountComponentAtNode } from 'react-dom'; + +import { ExpressionRenderDefinition } from 'src/plugins/expressions'; +import { VisualizationContainer } from '../../visualizations/public'; +import { RegionMapVisualizationDependencies } from './plugin'; +import { RegionMapVisRenderValue } from './region_map_fn'; + +const RegionMapVisualization = lazy(() => import('./region_map_visualization_component')); + +export const getRegionMapRenderer: ( + deps: RegionMapVisualizationDependencies +) => ExpressionRenderDefinition = (deps) => ({ + name: 'region_map_vis', + reuseDomNode: true, + render: async (domNode, { visConfig, visData }, handlers) => { + handlers.onDestroy(() => { + unmountComponentAtNode(domNode); + }); + + render( + + + , + domNode + ); + }, +}); diff --git a/src/plugins/region_map/public/region_map_type.js b/src/plugins/region_map/public/region_map_type.ts similarity index 87% rename from src/plugins/region_map/public/region_map_type.js rename to src/plugins/region_map/public/region_map_type.ts index e7a339a6cc8b..1603cfc1e2c0 100644 --- a/src/plugins/region_map/public/region_map_type.js +++ b/src/plugins/region_map/public/region_map_type.ts @@ -16,19 +16,24 @@ * specific language governing permissions and limitations * under the License. */ -import React from 'react'; import { i18n } from '@kbn/i18n'; -import { mapToLayerWithId } from './util'; -import { createRegionMapVisualization } from './region_map_visualization'; -import { RegionMapOptions } from './components/region_map_options'; + +import { BaseVisTypeOptions } from '../../visualizations/public'; import { truncatedColorSchemas } from '../../charts/public'; import { ORIGIN } from '../../maps_legacy/public'; + import { getDeprecationMessage } from './get_deprecation_message'; +import { RegionMapVisualizationDependencies } from './plugin'; +import { createRegionMapOptions } from './components'; +import { toExpressionAst } from './to_ast'; +import { RegionMapVisParams } from './region_map_types'; +import { mapToLayerWithId } from './util'; -export function createRegionMapTypeDefinition(dependencies) { - const { uiSettings, regionmapsConfig, getServiceSettings } = dependencies; - const visualization = createRegionMapVisualization(dependencies); - +export function createRegionMapTypeDefinition({ + uiSettings, + regionmapsConfig, + getServiceSettings, +}: RegionMapVisualizationDependencies): BaseVisTypeOptions { return { name: 'region_map', getInfoMessage: getDeprecationMessage, @@ -50,14 +55,11 @@ provided base maps, or add your own. Darker colors represent higher values.', mapZoom: 2, mapCenter: [0, 0], outlineWeight: 1, - showAllShapes: true, //still under consideration + showAllShapes: true, // still under consideration }, }, - visualization, editorConfig: { - optionsTemplate: (props) => ( - - ), + optionsTemplate: createRegionMapOptions(getServiceSettings), collections: { colorSchemas: truncatedColorSchemas, vectorLayers: [], @@ -99,6 +101,7 @@ provided base maps, or add your own. Darker colors represent higher values.', }, ], }, + toExpressionAst, setup: async (vis) => { const serviceSettings = await getServiceSettings(); const tmsLayers = await serviceSettings.getTMSServices(); @@ -111,7 +114,7 @@ provided base maps, or add your own. Darker colors represent higher values.', mapToLayerWithId.bind(null, ORIGIN.KIBANA_YML) ); let selectedLayer = vectorLayers[0]; - let selectedJoinField = selectedLayer ? selectedLayer.fields[0] : null; + let selectedJoinField = selectedLayer ? selectedLayer.fields[0] : undefined; if (regionmapsConfig.includeElasticMapsService) { const layers = await serviceSettings.getFileLayers(); const newLayers = layers @@ -132,7 +135,7 @@ provided base maps, or add your own. Darker colors represent higher values.', vis.type.editorConfig.collections.vectorLayers = [...vectorLayers, ...newLayers]; [selectedLayer] = vis.type.editorConfig.collections.vectorLayers; - selectedJoinField = selectedLayer ? selectedLayer.fields[0] : null; + selectedJoinField = selectedLayer ? selectedLayer.fields[0] : undefined; if (selectedLayer && !vis.params.selectedLayer && selectedLayer.isEMS) { vis.params.emsHotLink = await serviceSettings.getEMSHotLink(selectedLayer); diff --git a/src/plugins/maps_legacy/public/common/types/region_map_types.ts b/src/plugins/region_map/public/region_map_types.ts similarity index 81% rename from src/plugins/maps_legacy/public/common/types/region_map_types.ts rename to src/plugins/region_map/public/region_map_types.ts index 0da597068f11..044872be7a7c 100644 --- a/src/plugins/maps_legacy/public/common/types/region_map_types.ts +++ b/src/plugins/region_map/public/region_map_types.ts @@ -17,8 +17,8 @@ * under the License. */ -import { VectorLayer, FileLayerField } from '../../index'; -import { WMSOptions } from './external_basemap_types'; +import { SchemaConfig } from 'src/plugins/visualizations/public'; +import { VectorLayer, FileLayerField, WMSOptions } from '../../maps_legacy/public/index'; export interface RegionMapVisParams { readonly addTooltip: true; @@ -34,3 +34,8 @@ export interface RegionMapVisParams { selectedJoinField?: FileLayerField; wms: WMSOptions; } + +export interface RegionMapVisConfig extends RegionMapVisParams { + metric: SchemaConfig; + bucket?: SchemaConfig; +} diff --git a/src/plugins/region_map/public/region_map_visualization.js b/src/plugins/region_map/public/region_map_visualization.js index ecb3541827cb..4dfc6ead7944 100644 --- a/src/plugins/region_map/public/region_map_visualization.js +++ b/src/plugins/region_map/public/region_map_visualization.js @@ -30,9 +30,8 @@ export function createRegionMapVisualization({ getServiceSettings, }) { return class RegionMapsVisualization extends BaseMapsVisualization { - constructor(container, vis) { - super(container, vis); - this._vis = this.vis; + constructor(container, handlers, initialVisParams) { + super(container, handlers, initialVisParams); this._choroplethLayer = null; this._tooltipFormatter = mapTooltipProvider(container, tooltipFormatter); } @@ -88,7 +87,7 @@ export function createRegionMapVisualization({ ); } - this._kibanaMap.useUiStateFromVisualization(this._vis); + this._kibanaMap.useUiStateFromVisualization(this.handlers.uiState); } async _loadConfig(fileLayerConfig) { @@ -201,11 +200,18 @@ export function createRegionMapVisualization({ this._choroplethLayer.on('select', (event) => { const { rows, columns } = this._chartData; const rowIndex = rows.findIndex((row) => row[columns[0].id] === event); - this._vis.API.events.filter({ - table: this._chartData, - column: 0, - row: rowIndex, - value: event, + this.handlers.event({ + name: 'filterBucket', + data: { + data: [ + { + table: this._chartData, + column: 0, + row: rowIndex, + value: event, + }, + ], + }, }); }); diff --git a/src/plugins/region_map/public/region_map_visualization.scss b/src/plugins/region_map/public/region_map_visualization.scss new file mode 100644 index 000000000000..ee593e2fc9c8 --- /dev/null +++ b/src/plugins/region_map/public/region_map_visualization.scss @@ -0,0 +1,4 @@ +.rgmChart__wrapper, .rgmChart { + flex: 1 1 0; + display: flex; +} diff --git a/src/plugins/region_map/public/region_map_visualization_component.tsx b/src/plugins/region_map/public/region_map_visualization_component.tsx new file mode 100644 index 000000000000..7be210f953bf --- /dev/null +++ b/src/plugins/region_map/public/region_map_visualization_component.tsx @@ -0,0 +1,103 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { useEffect, useMemo, useRef } from 'react'; +import { EuiResizeObserver } from '@elastic/eui'; +import { throttle } from 'lodash'; + +import { IInterpreterRenderHandlers, Datatable } from 'src/plugins/expressions'; +import { PersistedState } from 'src/plugins/visualizations/public'; +import { RegionMapVisualizationDependencies } from './plugin'; +import { RegionMapVisConfig } from './region_map_types'; +// @ts-expect-error +import { createRegionMapVisualization } from './region_map_visualization'; + +import './region_map_visualization.scss'; + +interface RegionMapVisController { + render(visData?: Datatable, visConfig?: RegionMapVisConfig): Promise; + resize(): void; + destroy(): void; +} + +interface TileMapVisualizationProps { + deps: RegionMapVisualizationDependencies; + handlers: IInterpreterRenderHandlers; + visData: Datatable; + visConfig: RegionMapVisConfig; +} + +const RegionMapVisualization = ({ + deps, + handlers, + visData, + visConfig, +}: TileMapVisualizationProps) => { + const chartDiv = useRef(null); + const visController = useRef(null); + const isFirstRender = useRef(true); + const uiState = handlers.uiState as PersistedState | undefined; + + useEffect(() => { + if (chartDiv.current && isFirstRender.current) { + isFirstRender.current = false; + const Controller = createRegionMapVisualization(deps); + visController.current = new Controller(chartDiv.current, handlers, visConfig); + } + }, [deps, handlers, visConfig, visData]); + + useEffect(() => { + visController.current?.render(visData, visConfig).then(handlers.done); + }, [visData, visConfig, handlers.done]); + + useEffect(() => { + const onUiStateChange = () => { + visController.current?.render().then(handlers.done); + }; + + uiState?.on('change', onUiStateChange); + + return () => { + uiState?.off('change', onUiStateChange); + }; + }, [uiState, handlers.done]); + + useEffect(() => { + return () => { + visController.current?.destroy(); + visController.current = null; + }; + }, []); + + const updateChartSize = useMemo(() => throttle(() => visController.current?.resize(), 300), []); + + return ( + + {(resizeRef) => ( +
+
+
+ )} + + ); +}; + +// default export required for React.Lazy +// eslint-disable-next-line import/no-default-export +export { RegionMapVisualization as default }; diff --git a/src/plugins/region_map/public/to_ast.ts b/src/plugins/region_map/public/to_ast.ts new file mode 100644 index 000000000000..90dc6583732b --- /dev/null +++ b/src/plugins/region_map/public/to_ast.ts @@ -0,0 +1,59 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { + EsaggsExpressionFunctionDefinition, + IndexPatternLoadExpressionFunctionDefinition, +} from '../../data/public'; +import { buildExpression, buildExpressionFunction } from '../../expressions/public'; +import { getVisSchemas, Vis, BuildPipelineParams } from '../../visualizations/public'; +import { RegionMapExpressionFunctionDefinition } from './region_map_fn'; +import { RegionMapVisConfig, RegionMapVisParams } from './region_map_types'; + +export const toExpressionAst = (vis: Vis, params: BuildPipelineParams) => { + const esaggs = buildExpressionFunction('esaggs', { + index: buildExpression([ + buildExpressionFunction('indexPatternLoad', { + id: vis.data.indexPattern!.id!, + }), + ]), + metricsAtAllLevels: false, + partialRows: false, + aggs: vis.data.aggs!.aggs.map((agg) => buildExpression(agg.toExpressionAst())), + }); + + const schemas = getVisSchemas(vis, params); + + const visConfig: RegionMapVisConfig = { + ...vis.params, + metric: schemas.metric[0], + }; + + if (schemas.segment) { + visConfig.bucket = schemas.segment[0]; + } + + const regionmap = buildExpressionFunction('regionmap', { + visConfig: JSON.stringify(visConfig), + }); + + const ast = buildExpression([esaggs, regionmap]); + + return ast.toAst(); +}; diff --git a/src/plugins/tile_map/public/__snapshots__/tilemap_fn.test.js.snap b/src/plugins/tile_map/public/__snapshots__/tile_map_fn.test.ts.snap similarity index 93% rename from src/plugins/tile_map/public/__snapshots__/tilemap_fn.test.js.snap rename to src/plugins/tile_map/public/__snapshots__/tile_map_fn.test.ts.snap index d5f5127bae91..7aab8b02890c 100644 --- a/src/plugins/tile_map/public/__snapshots__/tilemap_fn.test.js.snap +++ b/src/plugins/tile_map/public/__snapshots__/tile_map_fn.test.ts.snap @@ -2,12 +2,9 @@ exports[`interpreter/functions#tilemap returns an object with the correct structure 1`] = ` Object { - "as": "visualization", + "as": "tile_map_vis", "type": "render", "value": Object { - "params": Object { - "listenOnChange": true, - }, "visConfig": Object { "addTooltip": true, "colorSchema": "Yellow to Red", diff --git a/src/plugins/tile_map/public/_tile_map.scss b/src/plugins/tile_map/public/_tile_map.scss deleted file mode 100644 index 5e4b20f79fed..000000000000 --- a/src/plugins/tile_map/public/_tile_map.scss +++ /dev/null @@ -1,15 +0,0 @@ -// SASSTODO: Does this selector exist today? -.tilemap { - margin-bottom: 6px; - border: $euiBorderThin; - position: relative; -} - -/** -* 1. Visualizations have some padding by default but tilemaps look nice flush against the edge to maximize viewing -* space. -*/ -// SASSTODO: Does this selector exist today? -.tile_map { - padding: 0; /* 1. */ -} diff --git a/src/plugins/tile_map/public/components/index.tsx b/src/plugins/tile_map/public/components/index.tsx new file mode 100644 index 000000000000..4a4f887046fe --- /dev/null +++ b/src/plugins/tile_map/public/components/index.tsx @@ -0,0 +1,25 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { lazy } from 'react'; +import type { TileMapOptionsProps } from './tile_map_options'; + +const TileMapOptions = lazy(() => import('./tile_map_options')); + +export const TileMapOptionsLazy = (props: TileMapOptionsProps) => ; diff --git a/src/plugins/tile_map/public/components/tile_map_options.tsx b/src/plugins/tile_map/public/components/tile_map_options.tsx index a6c0bb8a50dd..eda6b7b52fb4 100644 --- a/src/plugins/tile_map/public/components/tile_map_options.tsx +++ b/src/plugins/tile_map/public/components/tile_map_options.tsx @@ -28,7 +28,9 @@ import { SwitchOption, RangeOption, } from '../../../vis_default_editor/public'; -import { WmsOptions, TileMapVisParams, MapTypes } from '../../../maps_legacy/public'; +import { WmsOptions } from '../../../maps_legacy/public'; +import { TileMapVisParams } from '../types'; +import { MapTypes } from '../utils/map_types'; export type TileMapOptionsProps = VisOptionsProps; @@ -102,4 +104,6 @@ function TileMapOptions(props: TileMapOptionsProps) { ); } -export { TileMapOptions }; +// default export required for React.Lazy +// eslint-disable-next-line import/no-default-export +export { TileMapOptions as default }; diff --git a/src/plugins/tile_map/public/geohash_layer.js b/src/plugins/tile_map/public/geohash_layer.js index ca992a0d09ec..83c86149de53 100644 --- a/src/plugins/tile_map/public/geohash_layer.js +++ b/src/plugins/tile_map/public/geohash_layer.js @@ -19,11 +19,12 @@ import { min, isEqual } from 'lodash'; import { i18n } from '@kbn/i18n'; -import { KibanaMapLayer, MapTypes } from '../../maps_legacy/public'; +import { KibanaMapLayer } from '../../maps_legacy/public'; import { HeatmapMarkers } from './markers/heatmap'; import { ScaledCirclesMarkers } from './markers/scaled_circles'; import { ShadedCirclesMarkers } from './markers/shaded_circles'; import { GeohashGridMarkers } from './markers/geohash_grid'; +import { MapTypes } from './utils/map_types'; export class GeohashLayer extends KibanaMapLayer { constructor(featureCollection, featureCollectionMetaData, options, zoom, kibanaMap, leaflet) { diff --git a/src/plugins/tile_map/public/index.scss b/src/plugins/tile_map/public/index.scss deleted file mode 100644 index f4b86b0c3119..000000000000 --- a/src/plugins/tile_map/public/index.scss +++ /dev/null @@ -1,8 +0,0 @@ -// Prefix all styles with "tlm" to avoid conflicts. -// Examples -// tlmChart -// tlmChart__legend -// tlmChart__legend--small -// tlmChart__legend-isLoading - -@import 'tile_map'; diff --git a/src/plugins/tile_map/public/plugin.ts b/src/plugins/tile_map/public/plugin.ts index dfcafafbe47f..0a877d9595ec 100644 --- a/src/plugins/tile_map/public/plugin.ts +++ b/src/plugins/tile_map/public/plugin.ts @@ -25,13 +25,6 @@ import { } from 'kibana/public'; import { Plugin as ExpressionsPublicPlugin } from '../../expressions/public'; import { VisualizationsSetup } from '../../visualizations/public'; -// TODO: Determine why visualizations don't populate without this -import 'angular-sanitize'; - -// @ts-ignore -import { createTileMapFn } from './tile_map_fn'; -// @ts-ignore -import { createTileMapTypeDefinition } from './tile_map_type'; import { IServiceSettings, MapsLegacyPluginSetup } from '../../maps_legacy/public'; import { DataPublicPluginStart } from '../../data/public'; import { @@ -44,12 +37,16 @@ import { import { KibanaLegacyStart } from '../../kibana_legacy/public'; import { SharePluginStart } from '../../share/public'; +import { createTileMapFn } from './tile_map_fn'; +import { createTileMapTypeDefinition } from './tile_map_type'; +import { getTileMapRenderer } from './tile_map_renderer'; + export interface TileMapConfigType { tilemap: any; } /** @private */ -interface TileMapVisualizationDependencies { +export interface TileMapVisualizationDependencies { uiSettings: IUiSettingsClient; getZoomPrecision: any; getPrecision: any; @@ -98,7 +95,8 @@ export class TileMapPlugin implements Plugin createTileMapFn(visualizationDependencies)); + expressions.registerFunction(createTileMapFn); + expressions.registerRenderer(getTileMapRenderer(visualizationDependencies)); visualizations.createBaseVisualization(createTileMapTypeDefinition(visualizationDependencies)); diff --git a/src/plugins/tile_map/public/tilemap_fn.test.js b/src/plugins/tile_map/public/tile_map_fn.test.ts similarity index 83% rename from src/plugins/tile_map/public/tilemap_fn.test.js rename to src/plugins/tile_map/public/tile_map_fn.test.ts index 895842ea1e8f..dde98b7fe84c 100644 --- a/src/plugins/tile_map/public/tilemap_fn.test.js +++ b/src/plugins/tile_map/public/tile_map_fn.test.ts @@ -17,11 +17,10 @@ * under the License. */ -// eslint-disable-next-line import { functionWrapper } from '../../expressions/common/expression_functions/specs/tests/utils'; import { createTileMapFn } from './tile_map_fn'; -jest.mock('../../maps_legacy/public', () => ({ +jest.mock('./utils', () => ({ convertToGeoJson: jest.fn().mockReturnValue({ featureCollection: { type: 'FeatureCollection', @@ -36,7 +35,7 @@ jest.mock('../../maps_legacy/public', () => ({ }), })); -import { convertToGeoJson } from '../../maps_legacy/public'; +import { convertToGeoJson } from './utils'; describe('interpreter/functions#tilemap', () => { const fn = functionWrapper(createTileMapFn()); @@ -79,18 +78,14 @@ describe('interpreter/functions#tilemap', () => { jest.clearAllMocks(); }); - it('returns an object with the correct structure', () => { - const actual = fn( - context, - { visConfig: JSON.stringify(visConfig) }, - { logDatatable: jest.fn() } - ); + it('returns an object with the correct structure', async () => { + const actual = await fn(context, { visConfig: JSON.stringify(visConfig) }); expect(actual).toMatchSnapshot(); }); - it('calls response handler with correct values', () => { + it('calls response handler with correct values', async () => { const { geohash, metric, geocentroid } = visConfig.dimensions; - fn(context, { visConfig: JSON.stringify(visConfig) }, { logDatatable: jest.fn() }); + await fn(context, { visConfig: JSON.stringify(visConfig) }); expect(convertToGeoJson).toHaveBeenCalledTimes(1); expect(convertToGeoJson).toHaveBeenCalledWith(context, { geohash, diff --git a/src/plugins/tile_map/public/tile_map_fn.js b/src/plugins/tile_map/public/tile_map_fn.ts similarity index 66% rename from src/plugins/tile_map/public/tile_map_fn.js rename to src/plugins/tile_map/public/tile_map_fn.ts index 7a5f36be1eb9..786913a1d2b1 100644 --- a/src/plugins/tile_map/public/tile_map_fn.js +++ b/src/plugins/tile_map/public/tile_map_fn.ts @@ -16,10 +16,30 @@ * specific language governing permissions and limitations * under the License. */ -import { convertToGeoJson } from '../../maps_legacy/public'; + import { i18n } from '@kbn/i18n'; -export const createTileMapFn = () => ({ +import type { ExpressionFunctionDefinition, Datatable, Render } from '../../expressions/public'; +import { TileMapVisConfig, TileMapVisData } from './types'; + +interface Arguments { + visConfig: string | null; +} + +export interface TileMapVisRenderValue { + visData: TileMapVisData; + visType: 'tile_map'; + visConfig: TileMapVisConfig; +} + +export type TileMapExpressionFunctionDefinition = ExpressionFunctionDefinition< + 'tilemap', + Datatable, + Arguments, + Promise> +>; + +export const createTileMapFn = (): TileMapExpressionFunctionDefinition => ({ name: 'tilemap', type: 'render', context: { @@ -32,34 +52,30 @@ export const createTileMapFn = () => ({ visConfig: { types: ['string', 'null'], default: '"{}"', + help: '', }, }, - fn(context, args, handlers) { - const visConfig = JSON.parse(args.visConfig); + async fn(context, args, handlers) { + const visConfig = args.visConfig && JSON.parse(args.visConfig); const { geohash, metric, geocentroid } = visConfig.dimensions; + + const { convertToGeoJson } = await import('./utils'); const convertedData = convertToGeoJson(context, { geohash, metric, geocentroid, }); - if (geohash && geohash.accessor) { - convertedData.meta.geohash = context.columns[geohash.accessor].meta; - } - if (handlers?.inspectorAdapters?.tables) { handlers.inspectorAdapters.tables.logDatatable('default', context); } return { type: 'render', - as: 'visualization', + as: 'tile_map_vis', value: { visData: convertedData, visType: 'tile_map', visConfig, - params: { - listenOnChange: true, - }, }, }; }, diff --git a/src/plugins/tile_map/public/tile_map_renderer.tsx b/src/plugins/tile_map/public/tile_map_renderer.tsx new file mode 100644 index 000000000000..a61d4a0cb79d --- /dev/null +++ b/src/plugins/tile_map/public/tile_map_renderer.tsx @@ -0,0 +1,52 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { lazy } from 'react'; +import { render, unmountComponentAtNode } from 'react-dom'; + +import { ExpressionRenderDefinition } from 'src/plugins/expressions'; +import { VisualizationContainer } from '../../visualizations/public'; +import { TileMapVisualizationDependencies } from './plugin'; +import { TileMapVisRenderValue } from './tile_map_fn'; + +const TileMapVisualization = lazy(() => import('./tile_map_visualization_component')); + +export const getTileMapRenderer: ( + deps: TileMapVisualizationDependencies +) => ExpressionRenderDefinition = (deps) => ({ + name: 'tile_map_vis', + reuseDomNode: true, + render: async (domNode, { visConfig, visData }, handlers) => { + handlers.onDestroy(() => { + unmountComponentAtNode(domNode); + }); + + render( + + + , + domNode + ); + }, +}); diff --git a/src/plugins/tile_map/public/tile_map_type.js b/src/plugins/tile_map/public/tile_map_type.ts similarity index 90% rename from src/plugins/tile_map/public/tile_map_type.js rename to src/plugins/tile_map/public/tile_map_type.ts index 3e9b5516322d..e1d0dfb9a116 100644 --- a/src/plugins/tile_map/public/tile_map_type.js +++ b/src/plugins/tile_map/public/tile_map_type.ts @@ -17,17 +17,22 @@ * under the License. */ -import React from 'react'; import { i18n } from '@kbn/i18n'; -import { convertToGeoJson, MapTypes } from '../../maps_legacy/public'; -import { createTileMapVisualization } from './tile_map_visualization'; -import { TileMapOptions } from './components/tile_map_options'; -import { supportsCssFilters } from './css_filters'; +import { BaseVisTypeOptions } from 'src/plugins/visualizations/public'; import { truncatedColorSchemas } from '../../charts/public'; -import { getDeprecationMessage } from './get_deprecation_message'; -export function createTileMapTypeDefinition(dependencies) { - const CoordinateMapsVisualization = createTileMapVisualization(dependencies); +// @ts-expect-error +import { supportsCssFilters } from './css_filters'; +import { TileMapOptionsLazy } from './components'; +import { getDeprecationMessage } from './get_deprecation_message'; +import { TileMapVisualizationDependencies } from './plugin'; +import { toExpressionAst } from './to_ast'; +import { TileMapVisParams } from './types'; +import { MapTypes } from './utils/map_types'; + +export function createTileMapTypeDefinition( + dependencies: TileMapVisualizationDependencies +): BaseVisTypeOptions { const { uiSettings, getServiceSettings } = dependencies; return { @@ -54,8 +59,7 @@ export function createTileMapTypeDefinition(dependencies) { wms: uiSettings.get('visualization:tileMap:WMSdefaults'), }, }, - visualization: CoordinateMapsVisualization, - responseHandler: convertToGeoJson, + toExpressionAst, editorConfig: { collections: { colorSchemas: truncatedColorSchemas, @@ -113,7 +117,7 @@ export function createTileMapTypeDefinition(dependencies) { ], tmsLayers: [], }, - optionsTemplate: (props) => , + optionsTemplate: TileMapOptionsLazy, schemas: [ { group: 'metrics', diff --git a/src/plugins/tile_map/public/tile_map_visualization.js b/src/plugins/tile_map/public/tile_map_visualization.js index 80084be28365..2128aec49992 100644 --- a/src/plugins/tile_map/public/tile_map_visualization.js +++ b/src/plugins/tile_map/public/tile_map_visualization.js @@ -19,12 +19,9 @@ import { get, round } from 'lodash'; import { getFormatService, getQueryService, getKibanaLegacy } from './services'; -import { - geoContains, - mapTooltipProvider, - lazyLoadMapsLegacyModules, -} from '../../maps_legacy/public'; +import { mapTooltipProvider, lazyLoadMapsLegacyModules } from '../../maps_legacy/public'; import { tooltipFormatter } from './tooltip_formatter'; +import { geoContains } from './utils'; function scaleBounds(bounds) { const scale = 0.5; // scale bounds by 50% @@ -57,8 +54,8 @@ export const createTileMapVisualization = (dependencies) => { const { getZoomPrecision, getPrecision, BaseMapsVisualization } = dependencies; return class CoordinateMapsVisualization extends BaseMapsVisualization { - constructor(element, vis) { - super(element, vis); + constructor(element, handlers, initialVisParams) { + super(element, handlers, initialVisParams); this._geohashLayer = null; this._tooltipFormatter = mapTooltipProvider(element, tooltipFormatter); @@ -84,10 +81,10 @@ export const createTileMapVisualization = (dependencies) => { // todo: autoPrecision should be vis parameter, not aggConfig one const zoomPrecision = getZoomPrecision(); updateVarsObject.data.precision = geohashAgg.sourceParams.params.autoPrecision - ? zoomPrecision[this.vis.getUiState().get('mapZoom')] + ? zoomPrecision[this.handlers.uiState.get('mapZoom')] : getPrecision(geohashAgg.sourceParams.params.precision); - this.vis.eventsSubject.next(updateVarsObject); + this.handlers.event(updateVarsObject); }; async render(esResponse, visParams) { @@ -96,13 +93,12 @@ export const createTileMapVisualization = (dependencies) => { } async _makeKibanaMap() { - await super._makeKibanaMap(); + await super._makeKibanaMap(this._params); let previousPrecision = this._kibanaMap.getGeohashPrecision(); let precisionChange = false; - const uiState = this.vis.getUiState(); - uiState.on('change', (prop) => { + this.handlers.uiState.on('change', (prop) => { if (prop === 'mapZoom' || prop === 'mapCenter') { this.updateGeohashAgg(); } @@ -250,8 +246,6 @@ export const createTileMapVisualization = (dependencies) => { const { filterManager } = getQueryService(); filterManager.addFilters([filter]); - - this.vis.updateState(); } _getGeoHashAgg() { diff --git a/src/plugins/tile_map/public/tile_map_visualization.scss b/src/plugins/tile_map/public/tile_map_visualization.scss new file mode 100644 index 000000000000..4298b06c763d --- /dev/null +++ b/src/plugins/tile_map/public/tile_map_visualization.scss @@ -0,0 +1,4 @@ +.tlmChart__wrapper, .tlmChart { + flex: 1 1 0; + display: flex; +} diff --git a/src/plugins/tile_map/public/tile_map_visualization_component.tsx b/src/plugins/tile_map/public/tile_map_visualization_component.tsx new file mode 100644 index 000000000000..f087ab59fe73 --- /dev/null +++ b/src/plugins/tile_map/public/tile_map_visualization_component.tsx @@ -0,0 +1,103 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { useEffect, useMemo, useRef } from 'react'; +import { EuiResizeObserver } from '@elastic/eui'; +import { throttle } from 'lodash'; + +import { IInterpreterRenderHandlers } from 'src/plugins/expressions'; +import { PersistedState } from 'src/plugins/visualizations/public'; +import { TileMapVisualizationDependencies } from './plugin'; +import { TileMapVisConfig, TileMapVisData } from './types'; +// @ts-expect-error +import { createTileMapVisualization } from './tile_map_visualization'; + +import './tile_map_visualization.scss'; + +interface TileMapVisController { + render(visData?: TileMapVisData, visConfig?: TileMapVisConfig): Promise; + resize(): void; + destroy(): void; +} + +interface TileMapVisualizationProps { + deps: TileMapVisualizationDependencies; + handlers: IInterpreterRenderHandlers; + visData: TileMapVisData; + visConfig: TileMapVisConfig; +} + +const TileMapVisualization = ({ + deps, + handlers, + visData, + visConfig, +}: TileMapVisualizationProps) => { + const chartDiv = useRef(null); + const visController = useRef(null); + const isFirstRender = useRef(true); + const uiState = handlers.uiState as PersistedState; + + useEffect(() => { + if (chartDiv.current && isFirstRender.current) { + isFirstRender.current = false; + const Controller = createTileMapVisualization(deps); + visController.current = new Controller(chartDiv.current, handlers, visConfig); + } + }, [deps, handlers, visConfig, visData]); + + useEffect(() => { + visController.current?.render(visData, visConfig).then(handlers.done); + }, [visData, visConfig, handlers.done]); + + useEffect(() => { + const onUiStateChange = () => { + visController.current?.render().then(handlers.done); + }; + + uiState.on('change', onUiStateChange); + + return () => { + uiState.off('change', onUiStateChange); + }; + }, [uiState, handlers.done]); + + useEffect(() => { + return () => { + visController.current?.destroy(); + visController.current = null; + }; + }, []); + + const updateChartSize = useMemo(() => throttle(() => visController.current?.resize(), 300), []); + + return ( + + {(resizeRef) => ( +
+
+
+ )} + + ); +}; + +// default export required for React.Lazy +// eslint-disable-next-line import/no-default-export +export { TileMapVisualization as default }; diff --git a/src/plugins/tile_map/public/to_ast.ts b/src/plugins/tile_map/public/to_ast.ts new file mode 100644 index 000000000000..313ca3218591 --- /dev/null +++ b/src/plugins/tile_map/public/to_ast.ts @@ -0,0 +1,59 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { + EsaggsExpressionFunctionDefinition, + IndexPatternLoadExpressionFunctionDefinition, +} from '../../data/public'; +import { buildExpression, buildExpressionFunction } from '../../expressions/public'; +import { getVisSchemas, Vis, BuildPipelineParams } from '../../visualizations/public'; +import { TileMapExpressionFunctionDefinition } from './tile_map_fn'; +import { TileMapVisConfig, TileMapVisParams } from './types'; + +export const toExpressionAst = (vis: Vis, params: BuildPipelineParams) => { + const esaggs = buildExpressionFunction('esaggs', { + index: buildExpression([ + buildExpressionFunction('indexPatternLoad', { + id: vis.data.indexPattern!.id!, + }), + ]), + metricsAtAllLevels: false, + partialRows: false, + aggs: vis.data.aggs!.aggs.map((agg) => buildExpression(agg.toExpressionAst())), + }); + + const schemas = getVisSchemas(vis, params); + + const visConfig: TileMapVisConfig = { + ...vis.params, + dimensions: { + metric: schemas.metric[0], + geohash: schemas.segment ? schemas.segment[0] : null, + geocentroid: schemas.geo_centroid ? schemas.geo_centroid[0] : null, + }, + }; + + const tilemap = buildExpressionFunction('tilemap', { + visConfig: JSON.stringify(visConfig), + }); + + const ast = buildExpression([esaggs, tilemap]); + + return ast.toAst(); +}; diff --git a/src/plugins/tile_map/public/types.ts b/src/plugins/tile_map/public/types.ts new file mode 100644 index 000000000000..360e0c474b21 --- /dev/null +++ b/src/plugins/tile_map/public/types.ts @@ -0,0 +1,57 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { FeatureCollection } from 'geojson'; +import type { SchemaConfig } from 'src/plugins/visualizations/public'; +import type { DatatableColumnMeta } from 'src/plugins/expressions'; +import type { WMSOptions } from 'src/plugins/maps_legacy/public'; +import type { MapTypes } from './utils/map_types'; + +export interface TileMapVisData { + featureCollection: FeatureCollection; + meta: { + min: number; + max: number; + geohash?: DatatableColumnMeta; + geohashPrecision: number | undefined; + geohashGridDimensionsAtEquator: [number, number] | undefined; + }; +} + +export interface TileMapVisDimensions { + metric: SchemaConfig; + geohash: SchemaConfig | null; + geocentroid: SchemaConfig | null; +} + +export interface TileMapVisParams { + colorSchema: string; + mapType: MapTypes; + isDesaturated: boolean; + addTooltip: boolean; + heatClusterSize: number; + legendPosition: 'bottomright' | 'bottomleft' | 'topright' | 'topleft'; + mapZoom: number; + mapCenter: [number, number]; + wms: WMSOptions; +} + +export interface TileMapVisConfig extends TileMapVisParams { + dimensions: TileMapVisDimensions; +} diff --git a/src/plugins/maps_legacy/public/map/convert_to_geojson.js b/src/plugins/tile_map/public/utils/convert_to_geojson.ts similarity index 75% rename from src/plugins/maps_legacy/public/map/convert_to_geojson.js rename to src/plugins/tile_map/public/utils/convert_to_geojson.ts index bca21e4deea9..34fa0d8d4a6c 100644 --- a/src/plugins/maps_legacy/public/map/convert_to_geojson.js +++ b/src/plugins/tile_map/public/utils/convert_to_geojson.ts @@ -17,11 +17,17 @@ * under the License. */ +import { Feature } from 'geojson'; +import type { Datatable } from '../../../expressions/public'; +import type { TileMapVisDimensions, TileMapVisData } from '../types'; import { decodeGeoHash } from './decode_geo_hash'; import { gridDimensions } from './grid_dimensions'; -export function convertToGeoJson(tabifiedResponse, { geohash, geocentroid, metric }) { - let features; +export function convertToGeoJson( + tabifiedResponse: Datatable, + { geohash, geocentroid, metric }: TileMapVisDimensions +): TileMapVisData { + let features: Feature[]; let min = Infinity; let max = -Infinity; @@ -41,7 +47,7 @@ export function convertToGeoJson(tabifiedResponse, { geohash, geocentroid, metri if (!geohashValue) return false; const geohashLocation = decodeGeoHash(geohashValue); - let pointCoordinates; + let pointCoordinates: number[]; if (geocentroidColumn) { const location = row[geocentroidColumn.id]; pointCoordinates = [location.lon, location.lat]; @@ -58,7 +64,7 @@ export function convertToGeoJson(tabifiedResponse, { geohash, geocentroid, metri const centerLatLng = [geohashLocation.latitude[2], geohashLocation.longitude[2]]; - if (geohash.params.useGeocentroid) { + if (geohash?.params.useGeocentroid) { // see https://github.com/elastic/elasticsearch/issues/24694 for why clampGrid is used pointCoordinates[0] = clampGrid( pointCoordinates[0], @@ -86,35 +92,41 @@ export function convertToGeoJson(tabifiedResponse, { geohash, geocentroid, metri geohash: geohashValue, geohash_meta: { center: centerLatLng, - rectangle: rectangle, + rectangle, }, - value: value, + value, }, - }; + } as Feature; }) - .filter((row) => row); + .filter((row): row is Feature => !!row); } } else { features = []; } - const featureCollection = { - type: 'FeatureCollection', - features: features, - }; - - return { - featureCollection: featureCollection, + const convertedData: TileMapVisData = { + featureCollection: { + type: 'FeatureCollection', + features, + }, meta: { - min: min, - max: max, - geohashPrecision: geohash && geohash.params.precision, - geohashGridDimensionsAtEquator: geohash && gridDimensions(geohash.params.precision), + min, + max, + geohashPrecision: geohash?.params.precision, + geohashGridDimensionsAtEquator: geohash?.params.precision + ? gridDimensions(geohash.params.precision) + : undefined, }, }; + + if (geohash && geohash.accessor) { + convertedData.meta.geohash = tabifiedResponse.columns[geohash.accessor].meta; + } + + return convertedData; } -function clampGrid(val, min, max) { +function clampGrid(val: number, min: number, max: number) { if (val > max) val = max; else if (val < min) val = min; return val; diff --git a/src/plugins/maps_legacy/public/map/decode_geo_hash.test.ts b/src/plugins/tile_map/public/utils/decode_geo_hash.test.ts similarity index 79% rename from src/plugins/maps_legacy/public/map/decode_geo_hash.test.ts rename to src/plugins/tile_map/public/utils/decode_geo_hash.test.ts index c1ca7e4c8038..5114314f2c0a 100644 --- a/src/plugins/maps_legacy/public/map/decode_geo_hash.test.ts +++ b/src/plugins/tile_map/public/utils/decode_geo_hash.test.ts @@ -17,14 +17,7 @@ * under the License. */ -import { geohashColumns, decodeGeoHash } from './decode_geo_hash'; - -test('geohashColumns', () => { - expect(geohashColumns(1)).toBe(8); - expect(geohashColumns(2)).toBe(8 * 4); - expect(geohashColumns(3)).toBe(8 * 4 * 8); - expect(geohashColumns(4)).toBe(8 * 4 * 8 * 4); -}); +import { decodeGeoHash } from './decode_geo_hash'; test('decodeGeoHash', () => { expect(decodeGeoHash('drm3btev3e86')).toEqual({ diff --git a/src/plugins/maps_legacy/public/map/decode_geo_hash.ts b/src/plugins/tile_map/public/utils/decode_geo_hash.ts similarity index 79% rename from src/plugins/maps_legacy/public/map/decode_geo_hash.ts rename to src/plugins/tile_map/public/utils/decode_geo_hash.ts index 65184a824477..3ee8ab69e996 100644 --- a/src/plugins/maps_legacy/public/map/decode_geo_hash.ts +++ b/src/plugins/tile_map/public/utils/decode_geo_hash.ts @@ -55,10 +55,11 @@ export function decodeGeoHash(geohash: string): DecodedGeoHash { }); lat[2] = (lat[0] + lat[1]) / 2; lon[2] = (lon[0] + lon[1]) / 2; + return { latitude: lat, longitude: lon, - } as DecodedGeoHash; + }; } function refineInterval(interval: number[], cd: number, mask: number) { @@ -69,26 +70,6 @@ function refineInterval(interval: number[], cd: number, mask: number) { } } -export function geohashColumns(precision: number): number { - return geohashCells(precision, 0); -} - -/** - * Get the number of geohash cells for a given precision - * - * @param {number} precision the geohash precision (1<=precision<=12). - * @param {number} axis constant for the axis 0=lengthwise (ie. columns, along longitude), 1=heightwise (ie. rows, along latitude). - * @returns {number} Number of geohash cells (rows or columns) at that precision - */ -function geohashCells(precision: number, axis: number) { - let cells = 1; - for (let i = 1; i <= precision; i += 1) { - /* On odd precisions, rows divide by 4 and columns by 8. Vice-versa on even precisions */ - cells *= i % 2 === axis ? 4 : 8; - } - return cells; -} - interface GeoBoundingBoxCoordinate { lat: number; lon: number; diff --git a/src/plugins/maps_legacy/public/map/grid_dimensions.js b/src/plugins/tile_map/public/utils/grid_dimensions.ts similarity index 92% rename from src/plugins/maps_legacy/public/map/grid_dimensions.js rename to src/plugins/tile_map/public/utils/grid_dimensions.ts index 0f84e972104b..113909930598 100644 --- a/src/plugins/maps_legacy/public/map/grid_dimensions.js +++ b/src/plugins/tile_map/public/utils/grid_dimensions.ts @@ -19,7 +19,7 @@ // geohash precision mapping of geohash grid cell dimensions (width x height, in meters) at equator. // https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-geohashgrid-aggregation.html#_cell_dimensions_at_the_equator -const gridAtEquator = { +const gridAtEquator: { [key: number]: [number, number] } = { 1: [5009400, 4992600], 2: [1252300, 624100], 3: [156500, 156000], @@ -34,6 +34,6 @@ const gridAtEquator = { 12: [0.037, 0.019], }; -export function gridDimensions(precision) { +export function gridDimensions(precision: number) { return gridAtEquator[precision]; } diff --git a/src/plugins/maps_legacy/public/common/types/index.ts b/src/plugins/tile_map/public/utils/index.ts similarity index 79% rename from src/plugins/maps_legacy/public/common/types/index.ts rename to src/plugins/tile_map/public/utils/index.ts index e6cabdde82cd..1c3dd02f4842 100644 --- a/src/plugins/maps_legacy/public/common/types/index.ts +++ b/src/plugins/tile_map/public/utils/index.ts @@ -17,10 +17,5 @@ * under the License. */ -/** - * Use * syntax so that these exports do not break when internal - * types are stripped. - */ -export * from './external_basemap_types'; -export * from './map_types'; -export * from './region_map_types'; +export { convertToGeoJson } from './convert_to_geojson'; +export { geoContains } from './decode_geo_hash'; diff --git a/src/plugins/maps_legacy/public/common/types/map_types.ts b/src/plugins/tile_map/public/utils/map_types.ts similarity index 100% rename from src/plugins/maps_legacy/public/common/types/map_types.ts rename to src/plugins/tile_map/public/utils/map_types.ts diff --git a/src/plugins/visualizations/public/legacy/__snapshots__/build_pipeline.test.ts.snap b/src/plugins/visualizations/public/legacy/__snapshots__/build_pipeline.test.ts.snap index 3ff0c83961e2..3d685064111d 100644 --- a/src/plugins/visualizations/public/legacy/__snapshots__/build_pipeline.test.ts.snap +++ b/src/plugins/visualizations/public/legacy/__snapshots__/build_pipeline.test.ts.snap @@ -1,9 +1,3 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`visualize loader pipeline helpers: build pipeline buildPipeline calls toExpression on vis_type if it exists 1`] = `"kibana | kibana_context | test"`; - -exports[`visualize loader pipeline helpers: build pipeline buildPipelineVisFunction handles region_map function with buckets 1`] = `"regionmap visConfig='{\\"metric\\":{\\"accessor\\":0,\\"label\\":\\"\\",\\"format\\":{},\\"params\\":{},\\"aggType\\":\\"\\"},\\"bucket\\":1}' "`; - -exports[`visualize loader pipeline helpers: build pipeline buildPipelineVisFunction handles region_map function without buckets 1`] = `"regionmap visConfig='{\\"metric\\":{\\"accessor\\":0,\\"label\\":\\"\\",\\"format\\":{},\\"params\\":{},\\"aggType\\":\\"\\"}}' "`; - -exports[`visualize loader pipeline helpers: build pipeline buildPipelineVisFunction handles tile_map function 1`] = `"tilemap visConfig='{\\"metric\\":{},\\"dimensions\\":{\\"metric\\":{\\"accessor\\":0,\\"label\\":\\"\\",\\"format\\":{},\\"params\\":{},\\"aggType\\":\\"\\"},\\"geohash\\":1,\\"geocentroid\\":3}}' "`; diff --git a/src/plugins/visualizations/public/legacy/build_pipeline.test.ts b/src/plugins/visualizations/public/legacy/build_pipeline.test.ts index 57c58a99f09e..1b86488c0635 100644 --- a/src/plugins/visualizations/public/legacy/build_pipeline.test.ts +++ b/src/plugins/visualizations/public/legacy/build_pipeline.test.ts @@ -17,14 +17,7 @@ * under the License. */ -import { - prepareJson, - prepareString, - buildPipelineVisFunction, - buildPipeline, - SchemaConfig, - Schemas, -} from './build_pipeline'; +import { prepareJson, prepareString, buildPipeline } from './build_pipeline'; import { Vis } from '..'; import { dataPluginMock } from '../../../../plugins/data/public/mocks'; import { parseExpression } from '../../../expressions/common'; @@ -74,53 +67,6 @@ describe('visualize loader pipeline helpers: build pipeline', () => { }); }); - describe('buildPipelineVisFunction', () => { - let schemaConfig: SchemaConfig; - let schemasDef: Schemas; - let uiState: any; - - beforeEach(() => { - schemaConfig = { - accessor: 0, - label: '', - format: {}, - params: {}, - aggType: '', - }; - - schemasDef = { metric: [schemaConfig] }; - uiState = {}; - }); - - describe('handles region_map function', () => { - it('without buckets', () => { - const params = { metric: {} }; - const actual = buildPipelineVisFunction.region_map(params, schemasDef, uiState); - expect(actual).toMatchSnapshot(); - }); - - it('with buckets', () => { - const schemas = { - ...schemasDef, - segment: [1, 2], - }; - const actual = buildPipelineVisFunction.region_map({}, schemas, uiState); - expect(actual).toMatchSnapshot(); - }); - }); - - it('handles tile_map function', () => { - const params = { metric: {} }; - const schemas = { - ...schemasDef, - segment: [1, 2], - geo_centroid: [3, 4], - }; - const actual = buildPipelineVisFunction.tile_map(params, schemas, uiState); - expect(actual).toMatchSnapshot(); - }); - }); - describe('buildPipeline', () => { const dataStart = dataPluginMock.createStartContract(); diff --git a/src/plugins/visualizations/public/legacy/build_pipeline.ts b/src/plugins/visualizations/public/legacy/build_pipeline.ts index 0b422802a7e1..7c5991d498fa 100644 --- a/src/plugins/visualizations/public/legacy/build_pipeline.ts +++ b/src/plugins/visualizations/public/legacy/build_pipeline.ts @@ -23,9 +23,7 @@ import { SerializedFieldFormat, } from '../../../../plugins/expressions/public'; import { IAggConfig, search, TimefilterContract } from '../../../../plugins/data/public'; - -import { Vis, VisParams } from '../types'; - +import { Vis } from '../types'; const { isDateHistogramBucketAggConfig } = search.aggs; interface SchemaConfigParams { @@ -55,25 +53,6 @@ export interface Schemas { // catch all for schema name [key: string]: any[] | undefined; } - -type BuildVisFunction = ( - params: VisParams, - schemas: Schemas, - uiState: any, - meta?: { savedObjectId?: string } -) => string; - -// eslint-disable-next-line @typescript-eslint/naming-convention -type buildVisConfigFunction = (schemas: Schemas, visParams?: VisParams) => VisParams; - -interface BuildPipelineVisFunction { - [key: string]: BuildVisFunction; -} - -interface BuildVisConfigFunction { - [key: string]: buildVisConfigFunction; -} - export interface BuildPipelineParams { timefilter: TimefilterContract; timeRange?: any; @@ -224,43 +203,6 @@ export const prepareDimension = (variable: string, data: any) => { return expr; }; -export const buildPipelineVisFunction: BuildPipelineVisFunction = { - region_map: (params, schemas) => { - const visConfig = { - ...params, - ...buildVisConfig.region_map(schemas), - }; - return `regionmap ${prepareJson('visConfig', visConfig)}`; - }, - tile_map: (params, schemas) => { - const visConfig = { - ...params, - ...buildVisConfig.tile_map(schemas), - }; - return `tilemap ${prepareJson('visConfig', visConfig)}`; - }, -}; - -const buildVisConfig: BuildVisConfigFunction = { - region_map: (schemas) => { - const visConfig = {} as any; - visConfig.metric = schemas.metric[0]; - if (schemas.segment) { - visConfig.bucket = schemas.segment[0]; - } - return visConfig; - }, - tile_map: (schemas) => { - const visConfig = {} as any; - visConfig.dimensions = { - metric: schemas.metric[0], - geohash: schemas.segment ? schemas.segment[0] : null, - geocentroid: schemas.geo_centroid ? schemas.geo_centroid[0] : null, - }; - return visConfig; - }, -}; - export const buildPipeline = async (vis: Vis, params: BuildPipelineParams) => { const { indexPattern, searchSource } = vis.data; const query = searchSource!.getField('query'); @@ -299,17 +241,8 @@ export const buildPipeline = async (vis: Vis, params: BuildPipelineParams) => { }); } pipeline += `| `; - } - - const schemas = getSchemas(vis, params); - - if (buildPipelineVisFunction[vis.type.name]) { - pipeline += buildPipelineVisFunction[vis.type.name]( - { title, ...vis.params }, - schemas, - uiState - ); } else { + const schemas = getSchemas(vis, params); const visConfig = { ...vis.params }; visConfig.dimensions = schemas; visConfig.title = title; diff --git a/test/interpreter_functional/screenshots/baseline/partial_test_3.png b/test/interpreter_functional/screenshots/baseline/partial_test_3.png index c43169bfb71014d53fe5cbdc7a75e82fc7f32a13..93a8e53540744bada4360e60a48df113aed0ca51 100644 GIT binary patch literal 10749 zcmeHtcTkgCw>KbFrHEZRh!AN95jY@SktQG@O^OO4O^9?u=paf5Y0{D21SJRp0py@` z3B40kLYJ1%OLBK4`kuM>oilgt{p*|W&HzL5?7jBdYyDP#LT+oR&>y{Ul#GmwUQP9e zE*Tl+Uu0zDg0$4&8!mE=4KgywC$$@jcb<|jH6F_x!hPE&%r3gg^=PH_Mo2HK*@q-` zv^8Qr+-go}9@i5V^$_R6B=oB;S5=>c^xy6=b)G2fd^>Um!pr;a1*?X189{E0fICP} zgX*SbW8v}~QPFrRwU-yc&pg5D#NmICBiui~QPZWqL42b2GUxaU)x)pOGsPT!b%m4r zaJ7}fjl)Oneyo%Co5RnOR@&EAI*gUe{BLQ#I6N+n{5K)zene5x<(bZ;rthD_jMz{P zbzZ42Pt%yKsJIw*urZV*3zvW**QnE^-INY*RV1XVjfStt{$6Tk5xzgCB2RjJH(gbB z2iqaiWLJEakRu{hWCG^`z7hqx7xWFWDu? zzdicsf~sr%(870nY_%3@W!&B_5Pe8~fxDb~{hBpdM{m9Nwfe3%RTIw+A5;`^7mo<| zdPe9wEiQTR9G>!~sMXGW@r?%;>7%2R0YbiRQ<|!2r9OUhX-uatu05pxj)A#9iFre? zKxoXNv7#zJ*5e@x-G4RLncHgmG)V~?LgmR04HK25kHsbr#TUnBPZ=mrHAj#bG|+!Y zZ`0>_#9&ZNJ5u>jws-Yo#J|RfGQJfAqy#lqEa43aGmi)tlRosLPp!{w`f9|Z!q5L!PK-F_yGC&L zN-DV^Y7aM~^EbT#0awqOKOCPrX{7TneYu@5KC+u8<`?g_=$GQVY z(#7>p8-EElbCV_6!a{>|xVdNJWu0IqX^Qm

Byj} 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 literal 1994 zcmeAS@N?(olHy`uVBq!ia0y~yU^&FVz^KE)1{6_bl>f@Wz&_E_#WAFU@$JDz#sdlr zObXBc+i!p8@xVG9sD$A`AuovH$pDcF4$L5mSqel-TmX>=8bBs7u$h2Jg9VI0vVn0_ z%V>y=CYaIuGFn^!i^I{<5*P@hl?5;mh^;H@SWDPK_W9mV0P11zboFyt=akR{0B(}e AN&o-= diff --git a/test/interpreter_functional/snapshots/baseline/partial_test_3.json b/test/interpreter_functional/snapshots/baseline/partial_test_3.json index 595127526156..e011b69de202 100644 --- a/test/interpreter_functional/snapshots/baseline/partial_test_3.json +++ b/test/interpreter_functional/snapshots/baseline/partial_test_3.json @@ -1 +1 @@ -{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"bucket":{"accessor":0},"metric":{"accessor":1,"format":{"id":"number"}}},"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"2","indexPatternId":"logstash-*","params":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{},"schema":"metric","type":"count"},"type":"number"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"datatable"},"visType":"region_map"}} \ No newline at end of file +{"as":"region_map_vis","type":"render","value":{"visConfig":{"addTooltip":true,"bucket":{"accessor":0},"colorSchema":"Yellow to Red","isDisplayWarning":true,"legendPosition":"bottomright","mapCenter":[0,0],"mapZoom":2,"metric":{"accessor":1,"format":{"id":"number"}},"outlineWeight":1,"selectedJoinField":{},"selectedLayer":{},"showAllShapes":true,"wms":{}},"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"2","indexPatternId":"logstash-*","params":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{},"schema":"metric","type":"count"},"type":"number"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"datatable"},"visType":"region_map"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/session/partial_test_3.json b/test/interpreter_functional/snapshots/session/partial_test_3.json index 595127526156..e011b69de202 100644 --- a/test/interpreter_functional/snapshots/session/partial_test_3.json +++ b/test/interpreter_functional/snapshots/session/partial_test_3.json @@ -1 +1 @@ -{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"bucket":{"accessor":0},"metric":{"accessor":1,"format":{"id":"number"}}},"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"2","indexPatternId":"logstash-*","params":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{},"schema":"metric","type":"count"},"type":"number"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"datatable"},"visType":"region_map"}} \ No newline at end of file +{"as":"region_map_vis","type":"render","value":{"visConfig":{"addTooltip":true,"bucket":{"accessor":0},"colorSchema":"Yellow to Red","isDisplayWarning":true,"legendPosition":"bottomright","mapCenter":[0,0],"mapZoom":2,"metric":{"accessor":1,"format":{"id":"number"}},"outlineWeight":1,"selectedJoinField":{},"selectedLayer":{},"showAllShapes":true,"wms":{}},"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"2","indexPatternId":"logstash-*","params":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{},"schema":"metric","type":"count"},"type":"number"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"datatable"},"visType":"region_map"}} \ No newline at end of file diff --git a/test/interpreter_functional/test_suites/run_pipeline/basic.ts b/test/interpreter_functional/test_suites/run_pipeline/basic.ts index fc7c0428631c..6bd00b42502d 100644 --- a/test/interpreter_functional/test_suites/run_pipeline/basic.ts +++ b/test/interpreter_functional/test_suites/run_pipeline/basic.ts @@ -110,7 +110,7 @@ export default function ({ await expectExpression('partial_test_2', metricExpr, context).toMatchSnapshot() ).toMatchScreenshot(); - const regionMapExpr = `regionmap visConfig='{"metric":{"accessor":1,"format":{"id":"number"}},"bucket":{"accessor":0}}'`; + const regionMapExpr = `regionmap visConfig='{"metric":{"accessor":1,"format":{"id":"number"}},"bucket":{"accessor":0},"legendPosition":"bottomright","addTooltip":true,"colorSchema":"Yellow to Red","isDisplayWarning":true,"wms":{},"mapZoom":2,"mapCenter":[0,0],"outlineWeight":1,"showAllShapes":true,"selectedLayer":{},"selectedJoinField":{}}'`; await ( await expectExpression('partial_test_3', regionMapExpr, context).toMatchSnapshot() ).toMatchScreenshot();