From b369b1aef77c5eef7728ed3e62f39a836332b111 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Thu, 13 Feb 2020 15:06:11 -0700 Subject: [PATCH 01/27] [Maps] Blended layer that switches between documents and clusters --- .../legacy/plugins/maps/common/constants.ts | 6 + .../filter_editor/filter_editor.js | 28 ---- .../public/layers/blended_vector_layer.js | 20 +++ .../es_search_source/es_search_source.js | 48 ++++-- .../es_search_source/update_source_editor.js | 141 ++++++++++++++---- .../maps/public/layers/sources/es_source.js | 4 +- .../public/layers/sources/vector_source.js | 4 - .../maps/public/selectors/map_selectors.js | 3 + 8 files changed, 178 insertions(+), 76 deletions(-) create mode 100644 x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.js diff --git a/x-pack/legacy/plugins/maps/common/constants.ts b/x-pack/legacy/plugins/maps/common/constants.ts index ab9a696fa3a177..963c57528af2e0 100644 --- a/x-pack/legacy/plugins/maps/common/constants.ts +++ b/x-pack/legacy/plugins/maps/common/constants.ts @@ -158,3 +158,9 @@ export const SYMBOLIZE_AS_TYPES = { }; export const DEFAULT_ICON = 'airfield'; + +export const SCALING_TYPES = { + LIMIT: 'LIMIT', + CLUSTERS: 'CLUSTERS', + TOP_HITS: 'TOP_HITS', +}; diff --git a/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/filter_editor/filter_editor.js b/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/filter_editor/filter_editor.js index 94e855fc6708f0..60bbaa9825db74 100644 --- a/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/filter_editor/filter_editor.js +++ b/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/filter_editor/filter_editor.js @@ -16,8 +16,6 @@ import { EuiTextColor, EuiTextAlign, EuiButtonEmpty, - EuiFormRow, - EuiSwitch, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; @@ -80,14 +78,6 @@ export class FilterEditor extends Component { this._close(); }; - _onFilterByMapBoundsChange = event => { - this.props.updateSourceProp( - this.props.layer.getId(), - 'filterByMapBounds', - event.target.checked - ); - }; - _onApplyGlobalQueryChange = applyGlobalQuery => { this.props.updateSourceProp(this.props.layer.getId(), 'applyGlobalQuery', applyGlobalQuery); }; @@ -182,22 +172,6 @@ export class FilterEditor extends Component { } render() { - let filterByBoundsSwitch; - if (this.props.layer.getSource().isFilterByMapBoundsConfigurable()) { - filterByBoundsSwitch = ( - - - - ); - } - return ( @@ -217,8 +191,6 @@ export class FilterEditor extends Component { - {filterByBoundsSwitch} - @@ -395,8 +427,8 @@ export class ESSearchSource extends AbstractESSource { } _isTopHits() { - const { useTopHits, topHitsSplitField } = this._descriptor; - return !!(useTopHits && topHitsSplitField); + const { scalingType, topHitsSplitField } = this._descriptor; + return !!(scalingType === SCALING_TYPES.TOP_HITS && topHitsSplitField); } _hasSort() { @@ -505,11 +537,7 @@ export class ESSearchSource extends AbstractESSource { } isFilterByMapBounds() { - return _.get(this._descriptor, 'filterByMapBounds', false); - } - - isFilterByMapBoundsConfigurable() { - return true; + return this._descriptor.filterByMapBounds; } async getLeftJoinFields() { @@ -596,7 +624,7 @@ export class ESSearchSource extends AbstractESSource { return { sortField: this._descriptor.sortField, sortOrder: this._descriptor.sortOrder, - useTopHits: this._descriptor.useTopHits, + scalingType: this._descriptor.scalingType, topHitsSplitField: this._descriptor.topHitsSplitField, topHitsSize: this._descriptor.topHitsSize, }; diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/update_source_editor.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/update_source_editor.js index 52702c1f4ecc79..61b914207069c1 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/update_source_editor.js +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/update_source_editor.js @@ -14,6 +14,7 @@ import { EuiPanel, EuiSpacer, EuiHorizontalRule, + EuiRadioGroup, } from '@elastic/eui'; import { SingleFieldSelect } from '../../../components/single_field_select'; import { TooltipSelector } from '../../../components/tooltip_selector'; @@ -22,7 +23,12 @@ import { indexPatternService } from '../../../kibana_services'; import { i18n } from '@kbn/i18n'; import { getTermsFields, getSourceFields } from '../../../index_pattern_util'; import { ValidatedRange } from '../../../components/validated_range'; -import { DEFAULT_MAX_INNER_RESULT_WINDOW, SORT_ORDER } from '../../../../common/constants'; +import { + DEFAULT_MAX_INNER_RESULT_WINDOW, + DEFAULT_MAX_RESULT_WINDOW, + SORT_ORDER, + SCALING_TYPES, +} from '../../../../common/constants'; import { ESDocField } from '../../fields/es_doc_field'; import { FormattedMessage } from '@kbn/i18n/react'; import { loadIndexSettings } from './load_index_settings'; @@ -35,7 +41,7 @@ export class UpdateSourceEditor extends Component { tooltipFields: PropTypes.arrayOf(PropTypes.object).isRequired, sortField: PropTypes.string, sortOrder: PropTypes.string.isRequired, - useTopHits: PropTypes.bool.isRequired, + scalingType: PropTypes.string.isRequired, topHitsSplitField: PropTypes.string, topHitsSize: PropTypes.number.isRequired, source: PropTypes.object, @@ -46,6 +52,8 @@ export class UpdateSourceEditor extends Component { termFields: null, sortFields: null, maxInnerResultWindow: DEFAULT_MAX_INNER_RESULT_WINDOW, + maxResultWindow: DEFAULT_MAX_RESULT_WINDOW, + supportsClustering: false, }; componentDidMount() { @@ -61,9 +69,9 @@ export class UpdateSourceEditor extends Component { async loadIndexSettings() { try { const indexPattern = await indexPatternService.get(this.props.indexPatternId); - const { maxInnerResultWindow } = await loadIndexSettings(indexPattern.title); + const { maxInnerResultWindow, maxResultWindow } = await loadIndexSettings(indexPattern.title); if (this._isMounted) { - this.setState({ maxInnerResultWindow }); + this.setState({ maxInnerResultWindow, maxResultWindow }); } } catch (err) { return; @@ -88,6 +96,16 @@ export class UpdateSourceEditor extends Component { return; } + let geoField; + try { + geoField = await this.props.getGeoField(); + } catch (err) { + if (this._isMounted) { + this.setState({ loadError: err.message }); + } + return; + } + if (!this._isMounted) { return; } @@ -102,6 +120,7 @@ export class UpdateSourceEditor extends Component { }); this.setState({ + supportsClustering: geoField.aggregatable, sourceFields: sourceFields, termFields: getTermsFields(indexPattern.fields), //todo change term fields to use fields sortFields: indexPattern.fields.filter( @@ -113,8 +132,12 @@ export class UpdateSourceEditor extends Component { this.props.onChange({ propName: 'tooltipProperties', value: propertyNames }); }; - onUseTopHitsChange = event => { - this.props.onChange({ propName: 'useTopHits', value: event.target.checked }); + _onScalingTypeChange = optionId => { + this.props.onChange({ propName: 'scalingType', value: optionId }); + }; + + _onFilterByMapBoundsChange = event => { + this.props.onChange({ propName: 'filterByMapBounds', value: event.target.checked }); }; onTopHitsSplitFieldChange = topHitsSplitField => { @@ -133,29 +156,7 @@ export class UpdateSourceEditor extends Component { this.props.onChange({ propName: 'topHitsSize', value: size }); }; - renderTopHitsForm() { - const topHitsSwitch = ( - - - - ); - - if (!this.props.useTopHits) { - return topHitsSwitch; - } - + _renderTopHitsForm() { let sizeSlider; if (this.props.topHitsSplitField) { sizeSlider = ( @@ -183,7 +184,6 @@ export class UpdateSourceEditor extends Component { return ( - {topHitsSwitch} + + ); + } + + _renderScalingPanel() { + const scalingOptions = [ + { + id: SCALING_TYPES.LIMIT, + label: i18n.translate('xpack.maps.source.esSearch.limitScalingLabel', { + defaultMessage: 'Limit results to {maxResultWindow}.', + values: { maxResultWindow: this.state.maxResultWindow }, + }), + }, + { + id: SCALING_TYPES.TOP_HITS, + label: i18n.translate('xpack.maps.source.esSearch.useTopHitsLabel', { + defaultMessage: 'Show top hits per entity.', + }), + }, + ]; + if (this.state.supportsClustering) { + scalingOptions.push({ + id: SCALING_TYPES.CLUSTERS, + label: i18n.translate('xpack.maps.source.esSearch.clusterScalingLabel', { + defaultMessage: 'Show clusters when results exceed {maxResultWindow}.', + values: { maxResultWindow: this.state.maxResultWindow }, + }), + }); + } - - {this.renderTopHitsForm()} + let filterByBoundsSwitch; + if (this.props.scalingType !== SCALING_TYPES.CLUSTERS) { + filterByBoundsSwitch = ( + + + + ); + } + + let scalingForm = null; + if (this.props.scalingType === SCALING_TYPES.TOP_HITS) { + scalingForm = ( + + + {this._renderTopHitsForm()} + + ); + } + + return ( + + +
+ +
+
+ + + + + + + + {filterByBoundsSwitch} + + {scalingForm}
); } @@ -302,6 +376,9 @@ export class UpdateSourceEditor extends Component { {this._renderSortPanel()} + + {this._renderScalingPanel()} +
); } diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_source.js index d78d3038f870d9..23ff5397ee04c9 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_source.js +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_source.js @@ -232,7 +232,7 @@ export class AbstractESSource extends AbstractVectorSource { } } - async _getGeoField() { + _getGeoField = async () => { const indexPattern = await this.getIndexPattern(); const geoField = indexPattern.fields.getByName(this._descriptor.geoField); if (!geoField) { @@ -244,7 +244,7 @@ export class AbstractESSource extends AbstractVectorSource { ); } return geoField; - } + }; async getDisplayName() { try { diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/vector_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/vector_source.js index 3952aacf03b334..09d27033bea1e8 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/vector_source.js +++ b/x-pack/legacy/plugins/maps/public/layers/sources/vector_source.js @@ -98,10 +98,6 @@ export class AbstractVectorSource extends AbstractSource { return false; } - isFilterByMapBoundsConfigurable() { - return false; - } - isBoundsAware() { return false; } diff --git a/x-pack/legacy/plugins/maps/public/selectors/map_selectors.js b/x-pack/legacy/plugins/maps/public/selectors/map_selectors.js index 4b3d1355e4264f..fbf456e559842a 100644 --- a/x-pack/legacy/plugins/maps/public/selectors/map_selectors.js +++ b/x-pack/legacy/plugins/maps/public/selectors/map_selectors.js @@ -10,6 +10,7 @@ import { TileLayer } from '../layers/tile_layer'; import { VectorTileLayer } from '../layers/vector_tile_layer'; import { VectorLayer } from '../layers/vector_layer'; import { HeatmapLayer } from '../layers/heatmap_layer'; +import { BlendedVectorLayer } from '../layers/blended_vector_layer'; import { ALL_SOURCES } from '../layers/sources/all_sources'; import { timefilter } from 'ui/timefilter'; import { getInspectorAdapters } from '../reducers/non_serializable_instances'; @@ -27,6 +28,8 @@ function createLayerInstance(layerDescriptor, inspectorAdapters) { return new VectorTileLayer({ layerDescriptor, source }); case HeatmapLayer.type: return new HeatmapLayer({ layerDescriptor, source }); + case BlendedVectorLayer.type: + return new BlendedVectorLayer({ layerDescriptor, source }); default: throw new Error(`Unrecognized layerType ${layerDescriptor.type}`); } From a1d170de7abf09e43307242d8fcc25dfba695653 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Thu, 13 Feb 2020 19:14:20 -0700 Subject: [PATCH 02/27] change layer type when scalingType changes --- .../legacy/plugins/maps/common/constants.ts | 1 + .../maps/public/actions/map_actions.js | 3 ++- .../connected_components/layer_panel/index.js | 3 ++- .../connected_components/layer_panel/view.js | 4 +-- .../public/layers/blended_vector_layer.js | 13 ++++++++++ .../es_search_source/update_source_editor.js | 5 +++- .../maps/public/layers/vector_layer.js | 26 ++++++++++++------- .../plugins/maps/public/reducers/map.js | 13 ++++++++-- 8 files changed, 52 insertions(+), 16 deletions(-) diff --git a/x-pack/legacy/plugins/maps/common/constants.ts b/x-pack/legacy/plugins/maps/common/constants.ts index 963c57528af2e0..8b01025139ff80 100644 --- a/x-pack/legacy/plugins/maps/common/constants.ts +++ b/x-pack/legacy/plugins/maps/common/constants.ts @@ -42,6 +42,7 @@ export const LAYER_TYPE = { VECTOR: 'VECTOR', VECTOR_TILE: 'VECTOR_TILE', HEATMAP: 'HEATMAP', + BLENDED_VECTOR: 'BLENDED_VECTOR', }; export const SORT_ORDER = { diff --git a/x-pack/legacy/plugins/maps/public/actions/map_actions.js b/x-pack/legacy/plugins/maps/public/actions/map_actions.js index 59b54c2434d171..e94727a91794c3 100644 --- a/x-pack/legacy/plugins/maps/public/actions/map_actions.js +++ b/x-pack/legacy/plugins/maps/public/actions/map_actions.js @@ -580,13 +580,14 @@ export function onDataLoadError(layerId, dataId, requestToken, errorMessage) { }; } -export function updateSourceProp(layerId, propName, value) { +export function updateSourceProp(layerId, propName, value, newLayerType) { return async dispatch => { dispatch({ type: UPDATE_SOURCE_PROP, layerId, propName, value, + newLayerType, }); await dispatch(clearMissingStyleProperties(layerId)); dispatch(syncDataForLayer(layerId)); diff --git a/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/index.js b/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/index.js index 89ab7cf927d5b1..c7e21e0baef867 100644 --- a/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/index.js +++ b/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/index.js @@ -20,7 +20,8 @@ function mapDispatchToProps(dispatch) { fitToBounds: layerId => { dispatch(fitToLayerExtent(layerId)); }, - updateSourceProp: (id, propName, value) => dispatch(updateSourceProp(id, propName, value)), + updateSourceProp: (id, propName, value, newLayerType) => + dispatch(updateSourceProp(id, propName, value, newLayerType)), }; } diff --git a/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/view.js b/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/view.js index 50c0949cf91ae6..734607f6c8695d 100644 --- a/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/view.js +++ b/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/view.js @@ -94,8 +94,8 @@ export class LayerPanel extends React.Component { } }; - _onSourceChange = ({ propName, value }) => { - this.props.updateSourceProp(this.props.selectedLayer.getId(), propName, value); + _onSourceChange = ({ propName, value, newLayerType }) => { + this.props.updateSourceProp(this.props.selectedLayer.getId(), propName, value, newLayerType); }; _renderFilterSection() { diff --git a/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.js b/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.js index a9a783294a3465..d92e3924316f72 100644 --- a/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.js +++ b/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.js @@ -16,5 +16,18 @@ export class BlendedVectorLayer extends VectorLayer { return layerDescriptor; } + isJoinable() { + return false; + } + + getJoins() { + return []; + } + + async syncData(syncContext) { + console.log('BlendedVectorLayer.syncData'); + super.syncData(syncContext); + } + /*syncLayerWithMB(mbMap) {}*/ } diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/update_source_editor.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/update_source_editor.js index 61b914207069c1..b85cca113cf98a 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/update_source_editor.js +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/update_source_editor.js @@ -28,6 +28,7 @@ import { DEFAULT_MAX_RESULT_WINDOW, SORT_ORDER, SCALING_TYPES, + LAYER_TYPE, } from '../../../../common/constants'; import { ESDocField } from '../../fields/es_doc_field'; import { FormattedMessage } from '@kbn/i18n/react'; @@ -133,7 +134,9 @@ export class UpdateSourceEditor extends Component { }; _onScalingTypeChange = optionId => { - this.props.onChange({ propName: 'scalingType', value: optionId }); + const layerType = + optionId === SCALING_TYPES.CLUSTERS ? LAYER_TYPE.BLENDED_VECTOR : LAYER_TYPE.VECTOR; + this.props.onChange({ propName: 'scalingType', value: optionId, newLayerType: layerType }); }; _onFilterByMapBoundsChange = event => { diff --git a/x-pack/legacy/plugins/maps/public/layers/vector_layer.js b/x-pack/legacy/plugins/maps/public/layers/vector_layer.js index 31c3831fb612a6..e452c95386d59b 100644 --- a/x-pack/legacy/plugins/maps/public/layers/vector_layer.js +++ b/x-pack/legacy/plugins/maps/public/layers/vector_layer.js @@ -68,7 +68,7 @@ export class VectorLayer extends AbstractLayer { if (this._source) { this._source.destroy(); } - this._joins.forEach(joinSource => { + this.getJoins().forEach(joinSource => { joinSource.destroy(); }); } @@ -78,7 +78,7 @@ export class VectorLayer extends AbstractLayer { } getValidJoins() { - return this._joins.filter(join => { + return this.getJoins().filter(join => { return join.hasCompleteConfig(); }); } @@ -118,7 +118,7 @@ export class VectorLayer extends AbstractLayer { } if ( - this._joins.length && + this.getJoins().length && !featureCollection.features.some(feature => feature.properties[FEATURE_VISIBLE_PROPERTY_NAME]) ) { return { @@ -838,9 +838,13 @@ export class VectorLayer extends AbstractLayer { for (let i = 0; i < tooltipsFromSource.length; i++) { const tooltipProperty = tooltipsFromSource[i]; const matchingJoins = []; - for (let j = 0; j < this._joins.length; j++) { - if (this._joins[j].getLeftField().getName() === tooltipProperty.getPropertyKey()) { - matchingJoins.push(this._joins[j]); + for (let j = 0; j < this.getJoins().length; j++) { + if ( + this.getJoins() + [j].getLeftField() + .getName() === tooltipProperty.getPropertyKey() + ) { + matchingJoins.push(this.getJoins()[j]); } } if (matchingJoins.length) { @@ -853,15 +857,19 @@ export class VectorLayer extends AbstractLayer { let allTooltips = await this._source.filterAndFormatPropertiesToHtml(properties); this._addJoinsToSourceTooltips(allTooltips); - for (let i = 0; i < this._joins.length; i++) { - const propsFromJoin = await this._joins[i].filterAndFormatPropertiesForTooltip(properties); + for (let i = 0; i < this.getJoins().length; i++) { + const propsFromJoin = await this.getJoins()[i].filterAndFormatPropertiesForTooltip( + properties + ); allTooltips = [...allTooltips, ...propsFromJoin]; } return allTooltips; } canShowTooltip() { - return this.isVisible() && (this._source.canFormatFeatureProperties() || this._joins.length); + return ( + this.isVisible() && (this._source.canFormatFeatureProperties() || this.getJoins().length) + ); } getFeatureById(id) { diff --git a/x-pack/legacy/plugins/maps/public/reducers/map.js b/x-pack/legacy/plugins/maps/public/reducers/map.js index 234584d08a3114..b7db3f4e458d0b 100644 --- a/x-pack/legacy/plugins/maps/public/reducers/map.js +++ b/x-pack/legacy/plugins/maps/public/reducers/map.js @@ -75,7 +75,7 @@ const updateLayerInList = (state, layerId, attribute, newValue) => { return { ...state, layerList: updatedList }; }; -const updateLayerSourceDescriptorProp = (state, layerId, propName, value) => { +const updateLayerSourceDescriptorProp = (state, layerId, propName, value, newLayerType) => { const { layerList } = state; const layerIdx = getLayerIndex(layerList, layerId); const updatedLayer = { @@ -85,6 +85,9 @@ const updateLayerSourceDescriptorProp = (state, layerId, propName, value) => { [propName]: value, }, }; + if (newLayerType) { + updatedLayer.type = newLayerType; + } const updatedList = [ ...layerList.slice(0, layerIdx), updatedLayer, @@ -270,7 +273,13 @@ export function map(state = INITIAL_STATE, action) { case UPDATE_LAYER_PROP: return updateLayerInList(state, action.id, action.propName, action.newValue); case UPDATE_SOURCE_PROP: - return updateLayerSourceDescriptorProp(state, action.layerId, action.propName, action.value); + return updateLayerSourceDescriptorProp( + state, + action.layerId, + action.propName, + action.value, + action.newLayerType + ); case SET_JOINS: const layerDescriptor = state.layerList.find( descriptor => descriptor.id === action.layer.getId() From 9eb460a85aa85905ec8322e668746f479c4950a9 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Fri, 14 Feb 2020 11:17:01 -0700 Subject: [PATCH 03/27] getSource --- .../public/layers/blended_vector_layer.js | 42 +++++++++++++++- .../maps/public/layers/heatmap_layer.js | 6 +-- .../plugins/maps/public/layers/layer.js | 20 ++++---- .../es_geo_grid_source/es_geo_grid_source.js | 1 + .../es_search_source/es_search_source.js | 2 +- .../plugins/maps/public/layers/tile_layer.js | 2 +- .../maps/public/layers/vector_layer.js | 49 ++++++++++--------- .../maps/public/layers/vector_tile_layer.js | 8 +-- 8 files changed, 86 insertions(+), 44 deletions(-) diff --git a/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.js b/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.js index d92e3924316f72..25a981272a0a9c 100644 --- a/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.js +++ b/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.js @@ -5,7 +5,7 @@ */ import { VectorLayer } from './vector_layer'; -import { LAYER_TYPE } from '../../common/constants'; +import { ES_GEO_GRID, LAYER_TYPE } from '../../common/constants'; export class BlendedVectorLayer extends VectorLayer { static type = LAYER_TYPE.BLENDED_VECTOR; @@ -16,6 +16,27 @@ export class BlendedVectorLayer extends VectorLayer { return layerDescriptor; } + constructor(options) { + super(options); + + this._initActiveSourceAndStyle(); + } + + _initActiveSourceAndStyle() { + // VectorLayer constructor sets _source as document source + this._documentSource = this._source; + this._clusterSource = this._source; + this._activeSource = this._documentSource; + + const sourceDataRequest = this.getSourceDataRequest(); + if (sourceDataRequest) { + const requestMeta = sourceDataRequest.getMeta(); + if (requestMeta && requestMeta.sourceType === ES_GEO_GRID) { + this._activeSource = this._clusterSource; + } + } + } + isJoinable() { return false; } @@ -24,8 +45,27 @@ export class BlendedVectorLayer extends VectorLayer { return []; } + getSource() { + return this._activeSource; + } + async syncData(syncContext) { console.log('BlendedVectorLayer.syncData'); + //console.log(syncContext); + + /*const searchFilters = this._getSearchFilters(dataFilters); + const prevDataRequest = this.getSourceDataRequest(); + const canSkipFetch = await canSkipSourceUpdate({ + source: this._source, + prevDataRequest, + nextMeta: searchFilters, + }); + if (!canSkipFetch) { + return { + refreshed: false, + featureCollection: prevDataRequest.getData(), + }; + }*/ super.syncData(syncContext); } diff --git a/x-pack/legacy/plugins/maps/public/layers/heatmap_layer.js b/x-pack/legacy/plugins/maps/public/layers/heatmap_layer.js index 29223d6a67c6b8..c722719f9aaf6b 100644 --- a/x-pack/legacy/plugins/maps/public/layers/heatmap_layer.js +++ b/x-pack/legacy/plugins/maps/public/layers/heatmap_layer.js @@ -32,7 +32,7 @@ export class HeatmapLayer extends VectorLayer { } _getPropKeyOfSelectedMetric() { - const metricfields = this._source.getMetricFields(); + const metricfields = this.getSource().getMetricFields(); return metricfields[0].getName(); } @@ -88,7 +88,7 @@ export class HeatmapLayer extends VectorLayer { mbMap, layerId: heatmapLayerId, propertyName: SCALED_PROPERTY_NAME, - resolution: this._source.getGridResolution(), + resolution: this.getSource().getGridResolution(), }); mbMap.setPaintProperty(heatmapLayerId, 'heatmap-opacity', this.getAlpha()); mbMap.setLayerZoomRange(heatmapLayerId, this._descriptor.minZoom, this._descriptor.maxZoom); @@ -103,7 +103,7 @@ export class HeatmapLayer extends VectorLayer { } renderLegendDetails() { - const metricFields = this._source.getMetricFields(); + const metricFields = this.getSource().getMetricFields(); return this._style.renderLegendDetails(metricFields[0]); } } diff --git a/x-pack/legacy/plugins/maps/public/layers/layer.js b/x-pack/legacy/plugins/maps/public/layers/layer.js index b76f1ebce15d21..f0b35ead938019 100644 --- a/x-pack/legacy/plugins/maps/public/layers/layer.js +++ b/x-pack/legacy/plugins/maps/public/layers/layer.js @@ -51,8 +51,8 @@ export class AbstractLayer { } destroy() { - if (this._source) { - this._source.destroy(); + if (this.getSource()) { + this.getSource().destroy(); } } @@ -62,7 +62,7 @@ export class AbstractLayer { clonedDescriptor.id = uuid(); const displayName = await this.getDisplayName(); clonedDescriptor.label = `Clone of ${displayName}`; - clonedDescriptor.sourceDescriptor = this._source.cloneDescriptor(); + clonedDescriptor.sourceDescriptor = this.getSource().cloneDescriptor(); if (clonedDescriptor.joins) { clonedDescriptor.joins.forEach(joinDescriptor => { // right.id is uuid used to track requests in inspector @@ -77,15 +77,15 @@ export class AbstractLayer { } isJoinable() { - return this._source.isJoinable(); + return this.getSource().isJoinable(); } supportsElasticsearchFilters() { - return this._source.isESSource(); + return this.getSource().isESSource(); } async supportsFitToBounds() { - return await this._source.supportsFitToBounds(); + return await this.getSource().supportsFitToBounds(); } async getDisplayName() { @@ -93,12 +93,12 @@ export class AbstractLayer { return this._descriptor.label; } - return (await this._source.getDisplayName()) || `Layer ${this._descriptor.id}`; + return (await this.getSource().getDisplayName()) || `Layer ${this._descriptor.id}`; } async getAttributions() { if (!this.hasErrors()) { - return await this._source.getAttributions(); + return await this.getSource().getAttributions(); } return []; } @@ -226,11 +226,11 @@ export class AbstractLayer { } async getImmutableSourceProperties() { - return this._source.getImmutableProperties(); + return this.getSource().getImmutableProperties(); } renderSourceSettingsEditor = ({ onChange }) => { - return this._source.renderSourceSettingsEditor({ onChange }); + return this.getSource().renderSourceSettingsEditor({ onChange }); }; getPrevRequestToken(dataId) { diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.js index cb8b43a6c312b2..9a720dc0558c66 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.js +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.js @@ -204,6 +204,7 @@ export class ESGeoGridSource extends AbstractESAggSource { data: featureCollection, meta: { areResultsTrimmed: false, + sourceType: ES_GEO_GRID, }, }; } diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/es_search_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/es_search_source.js index 0df34676952cb3..26986693692451 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/es_search_source.js +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/es_search_source.js @@ -478,7 +478,7 @@ export class ESSearchSource extends AbstractESSource { return { data: featureCollection, - meta, + meta: { ...meta, sourceType: ES_SEARCH }, }; } diff --git a/x-pack/legacy/plugins/maps/public/layers/tile_layer.js b/x-pack/legacy/plugins/maps/public/layers/tile_layer.js index b35adcad976c32..aa2619e96f834a 100644 --- a/x-pack/legacy/plugins/maps/public/layers/tile_layer.js +++ b/x-pack/legacy/plugins/maps/public/layers/tile_layer.js @@ -30,7 +30,7 @@ export class TileLayer extends AbstractLayer { const requestToken = Symbol(`layer-source-refresh:${this.getId()} - source`); startLoading(SOURCE_DATA_ID_ORIGIN, requestToken, dataFilters); try { - const url = await this._source.getUrlTemplate(); + const url = await this.getSource().getUrlTemplate(); stopLoading(SOURCE_DATA_ID_ORIGIN, requestToken, url, {}); } catch (error) { onLoadError(SOURCE_DATA_ID_ORIGIN, requestToken, error.message); diff --git a/x-pack/legacy/plugins/maps/public/layers/vector_layer.js b/x-pack/legacy/plugins/maps/public/layers/vector_layer.js index e452c95386d59b..6c765c8f2a2f66 100644 --- a/x-pack/legacy/plugins/maps/public/layers/vector_layer.js +++ b/x-pack/legacy/plugins/maps/public/layers/vector_layer.js @@ -57,7 +57,7 @@ export class VectorLayer extends AbstractLayer { this._joins = []; if (options.layerDescriptor.joins) { options.layerDescriptor.joins.forEach(joinDescriptor => { - const join = new InnerJoin(joinDescriptor, this._source); + const join = new InnerJoin(joinDescriptor, this.getSource()); this._joins.push(join); }); } @@ -65,8 +65,8 @@ export class VectorLayer extends AbstractLayer { } destroy() { - if (this._source) { - this._source.destroy(); + if (this.getSource()) { + this.getSource().destroy(); } this.getJoins().forEach(joinSource => { joinSource.destroy(); @@ -130,7 +130,7 @@ export class VectorLayer extends AbstractLayer { } const sourceDataRequest = this.getSourceDataRequest(); - const { tooltipContent, areResultsTrimmed } = this._source.getSourceTooltipContent( + const { tooltipContent, areResultsTrimmed } = this.getSource().getSourceTooltipContent( sourceDataRequest ); return { @@ -174,21 +174,22 @@ export class VectorLayer extends AbstractLayer { } async getBounds(dataFilters) { - const isStaticLayer = !this._source.isBoundsAware() || !this._source.isFilterByMapBounds(); + const isStaticLayer = + !this.getSource().isBoundsAware() || !this.getSource().isFilterByMapBounds(); if (isStaticLayer) { return this._getBoundsBasedOnData(); } const searchFilters = this._getSearchFilters(dataFilters); - return await this._source.getBoundsForFilters(searchFilters); + return await this.getSource().getBoundsForFilters(searchFilters); } async getLeftJoinFields() { - return await this._source.getLeftJoinFields(); + return await this.getSource().getLeftJoinFields(); } async getSourceName() { - return this._source.getDisplayName(); + return this.getSource().getDisplayName(); } _getJoinFields() { @@ -201,25 +202,25 @@ export class VectorLayer extends AbstractLayer { } async getDateFields() { - return await this._source.getDateFields(); + return await this.getSource().getDateFields(); } async getNumberFields() { - const numberFieldOptions = await this._source.getNumberFields(); + const numberFieldOptions = await this.getSource().getNumberFields(); return [...numberFieldOptions, ...this._getJoinFields()]; } async getCategoricalFields() { - return await this._source.getCategoricalFields(); + return await this.getSource().getCategoricalFields(); } async getFields() { - const sourceFields = await this._source.getFields(); + const sourceFields = await this.getSource().getFields(); return [...sourceFields, ...this._getJoinFields()]; } getIndexPatternIds() { - const indexPatternIds = this._source.getIndexPatternIds(); + const indexPatternIds = this.getSource().getIndexPatternIds(); this.getValidJoins().forEach(join => { indexPatternIds.push(...join.getIndexPatternIds()); }); @@ -227,7 +228,7 @@ export class VectorLayer extends AbstractLayer { } getQueryableIndexPatternIds() { - const indexPatternIds = this._source.getQueryableIndexPatternIds(); + const indexPatternIds = this.getSource().getQueryableIndexPatternIds(); this.getValidJoins().forEach(join => { indexPatternIds.push(...join.getQueryableIndexPatternIds()); }); @@ -309,7 +310,7 @@ export class VectorLayer extends AbstractLayer { _getSearchFilters(dataFilters) { const fieldNames = [ - ...this._source.getFieldNames(), + ...this.getSource().getFieldNames(), ...this._style.getSourceFieldNames(), ...this.getValidJoins().map(join => join.getLeftField().getName()), ]; @@ -317,10 +318,10 @@ export class VectorLayer extends AbstractLayer { return { ...dataFilters, fieldNames: _.uniq(fieldNames).sort(), - geogridPrecision: this._source.getGeoGridPrecision(dataFilters.zoom), + geogridPrecision: this.getSource().getGeoGridPrecision(dataFilters.zoom), sourceQuery: this.getQuery(), - applyGlobalQuery: this._source.getApplyGlobalQuery(), - sourceMeta: this._source.getSyncMeta(), + applyGlobalQuery: this.getSource().getApplyGlobalQuery(), + sourceMeta: this.getSource().getSyncMeta(), }; } @@ -374,7 +375,7 @@ export class VectorLayer extends AbstractLayer { const searchFilters = this._getSearchFilters(dataFilters); const prevDataRequest = this.getSourceDataRequest(); const canSkipFetch = await canSkipSourceUpdate({ - source: this._source, + source: this.getSource(), prevDataRequest, nextMeta: searchFilters, }); @@ -388,7 +389,7 @@ export class VectorLayer extends AbstractLayer { try { startLoading(SOURCE_DATA_ID_ORIGIN, requestToken, searchFilters); const layerName = await this.getDisplayName(); - const { data: sourceFeatureCollection, meta } = await this._source.getGeoJsonWithMeta( + const { data: sourceFeatureCollection, meta } = await this.getSource().getGeoJsonWithMeta( layerName, searchFilters, registerCancelCallback.bind(null, requestToken) @@ -415,7 +416,7 @@ export class VectorLayer extends AbstractLayer { } return this._syncStyleMeta({ - source: this._source, + source: this.getSource(), sourceQuery: this.getQuery(), dataRequestId: SOURCE_META_ID_ORIGIN, dynamicStyleProps: this._style.getDynamicPropertiesArray().filter(dynamicStyleProp => { @@ -504,7 +505,7 @@ export class VectorLayer extends AbstractLayer { } return this._syncFormatters({ - source: this._source, + source: this.getSource(), dataRequestId: SOURCE_FORMATTERS_ID_ORIGIN, fields: this._style .getDynamicPropertiesArray() @@ -854,7 +855,7 @@ export class VectorLayer extends AbstractLayer { } async getPropertiesForTooltip(properties) { - let allTooltips = await this._source.filterAndFormatPropertiesToHtml(properties); + let allTooltips = await this.getSource().filterAndFormatPropertiesToHtml(properties); this._addJoinsToSourceTooltips(allTooltips); for (let i = 0; i < this.getJoins().length; i++) { @@ -868,7 +869,7 @@ export class VectorLayer extends AbstractLayer { canShowTooltip() { return ( - this.isVisible() && (this._source.canFormatFeatureProperties() || this.getJoins().length) + this.isVisible() && (this.getSource().canFormatFeatureProperties() || this.getJoins().length) ); } diff --git a/x-pack/legacy/plugins/maps/public/layers/vector_tile_layer.js b/x-pack/legacy/plugins/maps/public/layers/vector_tile_layer.js index b09ccdc3af8bae..44987fd3e78f02 100644 --- a/x-pack/legacy/plugins/maps/public/layers/vector_tile_layer.js +++ b/x-pack/legacy/plugins/maps/public/layers/vector_tile_layer.js @@ -48,7 +48,7 @@ export class VectorTileLayer extends TileLayer { return; } - const nextMeta = { tileLayerId: this._source.getTileLayerId() }; + const nextMeta = { tileLayerId: this.getSource().getTileLayerId() }; const canSkipSync = this._canSkipSync({ prevDataRequest: this.getSourceDataRequest(), nextMeta, @@ -60,7 +60,7 @@ export class VectorTileLayer extends TileLayer { const requestToken = Symbol(`layer-source-refresh:${this.getId()} - source`); try { startLoading(SOURCE_DATA_ID_ORIGIN, requestToken, dataFilters); - const styleAndSprites = await this._source.getVectorStyleSheetAndSpriteMeta(isRetina()); + const styleAndSprites = await this.getSource().getVectorStyleSheetAndSpriteMeta(isRetina()); const spriteSheetImageData = await loadSpriteSheetImageData(styleAndSprites.spriteMeta.png); const data = { ...styleAndSprites, @@ -78,7 +78,7 @@ export class VectorTileLayer extends TileLayer { _generateMbSourceIdPrefix() { const DELIMITTER = '___'; - return `${this.getId()}${DELIMITTER}${this._source.getTileLayerId()}${DELIMITTER}`; + return `${this.getId()}${DELIMITTER}${this.getSource().getTileLayerId()}${DELIMITTER}`; } _generateMbSourceId(name) { @@ -141,7 +141,7 @@ export class VectorTileLayer extends TileLayer { } _makeNamespacedImageId(imageId) { - const prefix = this._source.getSpriteNamespacePrefix() + '/'; + const prefix = this.getSource().getSpriteNamespacePrefix() + '/'; return prefix + imageId; } From 3e5010ddc32ab11aa7f96449165965e12301053e Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Fri, 14 Feb 2020 12:12:02 -0700 Subject: [PATCH 04/27] use cluster source when count exceeds value --- .../public/layers/blended_vector_layer.js | 40 ++++++++++++++----- .../es_geo_grid_source/es_geo_grid_source.js | 4 +- .../sources/es_geo_grid_source/index.js | 1 + .../es_pew_pew_source/es_pew_pew_source.js | 4 +- .../es_search_source/es_search_source.js | 4 +- .../maps/public/layers/sources/es_source.js | 18 ++++++--- .../public/layers/sources/es_term_source.js | 6 +-- 7 files changed, 52 insertions(+), 25 deletions(-) diff --git a/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.js b/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.js index 25a981272a0a9c..960bc155cd390a 100644 --- a/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.js +++ b/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.js @@ -6,6 +6,8 @@ import { VectorLayer } from './vector_layer'; import { ES_GEO_GRID, LAYER_TYPE } from '../../common/constants'; +import { ESGeoGridSource, RENDER_AS } from './sources/es_geo_grid_source'; +import { canSkipSourceUpdate } from './util/can_skip_fetch'; export class BlendedVectorLayer extends VectorLayer { static type = LAYER_TYPE.BLENDED_VECTOR; @@ -22,12 +24,28 @@ export class BlendedVectorLayer extends VectorLayer { this._initActiveSourceAndStyle(); } + destroy() { + if (this._documentSource) { + this._documentSource.destroy(); + } + if (this._clusterSource) { + this._clusterSource.destroy(); + } + } + _initActiveSourceAndStyle() { - // VectorLayer constructor sets _source as document source - this._documentSource = this._source; - this._clusterSource = this._source; + this._documentSource = this._source; // VectorLayer constructor sets _source as document source this._activeSource = this._documentSource; + const clusterSourceDescriptor = ESGeoGridSource.createDescriptor({ + indexPatternId: this._documentSource.getIndexPatternId(), + geoField: this._documentSource.getGeoFieldName(), + requestType: RENDER_AS.POINT, + }); + this._clusterSource = new ESGeoGridSource( + clusterSourceDescriptor, + this._documentSource.getInspectorAdapters() + ); const sourceDataRequest = this.getSourceDataRequest(); if (sourceDataRequest) { const requestMeta = sourceDataRequest.getMeta(); @@ -53,7 +71,7 @@ export class BlendedVectorLayer extends VectorLayer { console.log('BlendedVectorLayer.syncData'); //console.log(syncContext); - /*const searchFilters = this._getSearchFilters(dataFilters); + const searchFilters = this._getSearchFilters(syncContext.dataFilters); const prevDataRequest = this.getSourceDataRequest(); const canSkipFetch = await canSkipSourceUpdate({ source: this._source, @@ -61,11 +79,15 @@ export class BlendedVectorLayer extends VectorLayer { nextMeta: searchFilters, }); if (!canSkipFetch) { - return { - refreshed: false, - featureCollection: prevDataRequest.getData(), - }; - }*/ + const searchSource = await this._documentSource._makeSearchSource(searchFilters, 0); + const resp = await searchSource.fetch(); + if (resp.hits.total > 100) { + this._activeSource = this._clusterSource; + } else { + this._activeSource = this._documentSource; + } + } + super.syncData(syncContext); } diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.js index 9a720dc0558c66..47db7e3a96e203 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.js +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.js @@ -87,7 +87,7 @@ export class ESGeoGridSource extends AbstractESAggSource { renderSourceSettingsEditor({ onChange }) { return ( Date: Fri, 14 Feb 2020 12:41:35 -0700 Subject: [PATCH 05/27] ensure doc source stays in editor --- .../plugins/maps/public/layers/blended_vector_layer.js | 7 +++++++ x-pack/legacy/plugins/maps/public/layers/layer.js | 6 +++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.js b/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.js index 960bc155cd390a..73144283945fc6 100644 --- a/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.js +++ b/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.js @@ -67,6 +67,13 @@ export class BlendedVectorLayer extends VectorLayer { return this._activeSource; } + getSourceForEditing() { + // Layer is based on this._documentSource + // this._clusterSource is a derived source for rendering only. + // Regardless of this._activeSource, this._documentSource should always be displayed in the editor + return this._documentSource; + } + async syncData(syncContext) { console.log('BlendedVectorLayer.syncData'); //console.log(syncContext); diff --git a/x-pack/legacy/plugins/maps/public/layers/layer.js b/x-pack/legacy/plugins/maps/public/layers/layer.js index f0b35ead938019..b1929c8cdae277 100644 --- a/x-pack/legacy/plugins/maps/public/layers/layer.js +++ b/x-pack/legacy/plugins/maps/public/layers/layer.js @@ -190,6 +190,10 @@ export class AbstractLayer { return this._source; } + getSourceForEditing() { + return this._source; + } + isVisible() { return this._descriptor.visible; } @@ -230,7 +234,7 @@ export class AbstractLayer { } renderSourceSettingsEditor = ({ onChange }) => { - return this.getSource().renderSourceSettingsEditor({ onChange }); + return this.getSourceForEditing().renderSourceSettingsEditor({ onChange }); }; getPrevRequestToken(dataId) { From 433d693dc61c27b6d45b97f2535ee80379584a1b Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Fri, 14 Feb 2020 14:23:26 -0700 Subject: [PATCH 06/27] start creating cluster style --- .../public/layers/blended_vector_layer.js | 59 +++++++++++++-- .../maps/public/layers/heatmap_layer.js | 4 +- .../plugins/maps/public/layers/layer.js | 9 ++- .../layers/styles/vector/vector_style.js | 4 ++ .../maps/public/layers/vector_layer.js | 72 ++++++++++--------- 5 files changed, 105 insertions(+), 43 deletions(-) diff --git a/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.js b/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.js index 73144283945fc6..b46fb4707b9cbb 100644 --- a/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.js +++ b/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.js @@ -5,7 +5,15 @@ */ import { VectorLayer } from './vector_layer'; -import { ES_GEO_GRID, LAYER_TYPE } from '../../common/constants'; +import { VectorStyle } from './styles/vector/vector_style'; +import { getDefaultDynamicProperties, VECTOR_STYLES } from './styles/vector/vector_style_defaults'; +import { DynamicStyleProperty } from './styles/vector/properties/dynamic_style_property'; +import { + COUNT_PROP_NAME, + ES_GEO_GRID, + LAYER_TYPE, + SOURCE_DATA_ID_ORIGIN, +} from '../../common/constants'; import { ESGeoGridSource, RENDER_AS } from './sources/es_geo_grid_source'; import { canSkipSourceUpdate } from './util/can_skip_fetch'; @@ -35,8 +43,9 @@ export class BlendedVectorLayer extends VectorLayer { _initActiveSourceAndStyle() { this._documentSource = this._source; // VectorLayer constructor sets _source as document source - this._activeSource = this._documentSource; + this._documentStyle = this._style; // VectorLayer constructor sets _style as document source + // derive cluster source from document source const clusterSourceDescriptor = ESGeoGridSource.createDescriptor({ indexPatternId: this._documentSource.getIndexPatternId(), geoField: this._documentSource.getGeoFieldName(), @@ -46,11 +55,44 @@ export class BlendedVectorLayer extends VectorLayer { clusterSourceDescriptor, this._documentSource.getInspectorAdapters() ); + + // derive cluster style from document style + const defaultDynamicProperties = getDefaultDynamicProperties(); + const clusterStyleDescriptor = VectorStyle.createDescriptor({ + [VECTOR_STYLES.LABEL_TEXT]: { + type: DynamicStyleProperty.type, + options: { + ...defaultDynamicProperties[VECTOR_STYLES.LABEL_TEXT].options, + field: { + name: COUNT_PROP_NAME, + origin: SOURCE_DATA_ID_ORIGIN, + }, + }, + }, + }); + const documentIconSizeStyle = this._documentStyle.getIconSizeStyle(); + if (!documentIconSizeStyle.isDynamic()) { + clusterStyleDescriptor.properties[VECTOR_STYLES.ICON_SIZE] = { + type: DynamicStyleProperty.type, + options: { + ...defaultDynamicProperties[VECTOR_STYLES.ICON_SIZE].options, + field: { + name: COUNT_PROP_NAME, + origin: SOURCE_DATA_ID_ORIGIN, + }, + }, + }; + } + this._clusterStyle = new VectorStyle(clusterStyleDescriptor, this._clusterSource, this); + + this._activeSource = this._documentSource; + this._activeStyle = this._documentStyle; const sourceDataRequest = this.getSourceDataRequest(); if (sourceDataRequest) { const requestMeta = sourceDataRequest.getMeta(); if (requestMeta && requestMeta.sourceType === ES_GEO_GRID) { this._activeSource = this._clusterSource; + this._activeStyle = this._clusterStyle; } } } @@ -74,10 +116,15 @@ export class BlendedVectorLayer extends VectorLayer { return this._documentSource; } - async syncData(syncContext) { - console.log('BlendedVectorLayer.syncData'); - //console.log(syncContext); + getCurrentStyle() { + return this._activeStyle; + } + getStyleForEditing() { + return this._documentStyle; + } + + async syncData(syncContext) { const searchFilters = this._getSearchFilters(syncContext.dataFilters); const prevDataRequest = this.getSourceDataRequest(); const canSkipFetch = await canSkipSourceUpdate({ @@ -90,8 +137,10 @@ export class BlendedVectorLayer extends VectorLayer { const resp = await searchSource.fetch(); if (resp.hits.total > 100) { this._activeSource = this._clusterSource; + this._activeStyle = this._clusterStyle; } else { this._activeSource = this._documentSource; + this._activeStyle = this._documentStyle; } } diff --git a/x-pack/legacy/plugins/maps/public/layers/heatmap_layer.js b/x-pack/legacy/plugins/maps/public/layers/heatmap_layer.js index c722719f9aaf6b..ef78b5afe3a3a0 100644 --- a/x-pack/legacy/plugins/maps/public/layers/heatmap_layer.js +++ b/x-pack/legacy/plugins/maps/public/layers/heatmap_layer.js @@ -84,7 +84,7 @@ export class HeatmapLayer extends VectorLayer { } this.syncVisibilityWithMb(mbMap, heatmapLayerId); - this._style.setMBPaintProperties({ + this.getCurrentStyle().setMBPaintProperties({ mbMap, layerId: heatmapLayerId, propertyName: SCALED_PROPERTY_NAME, @@ -104,6 +104,6 @@ export class HeatmapLayer extends VectorLayer { renderLegendDetails() { const metricFields = this.getSource().getMetricFields(); - return this._style.renderLegendDetails(metricFields[0]); + return this.getCurrentStyle().renderLegendDetails(metricFields[0]); } } diff --git a/x-pack/legacy/plugins/maps/public/layers/layer.js b/x-pack/legacy/plugins/maps/public/layers/layer.js index b1929c8cdae277..963645ab7218fe 100644 --- a/x-pack/legacy/plugins/maps/public/layers/layer.js +++ b/x-pack/legacy/plugins/maps/public/layers/layer.js @@ -229,6 +229,10 @@ export class AbstractLayer { return this._style; } + getStyleForEditing() { + return this._style; + } + async getImmutableSourceProperties() { return this.getSource().getImmutableProperties(); } @@ -322,10 +326,11 @@ export class AbstractLayer { } renderStyleEditor({ onStyleDescriptorChange }) { - if (!this._style) { + const style = this.getStyleForEditing(); + if (!style) { return null; } - return this._style.renderEditor({ layer: this, onStyleDescriptorChange }); + return style.renderEditor({ layer: this, onStyleDescriptorChange }); } getIndexPatternIds() { diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.js index 62651fdd702d60..79fd729c7bdaa7 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.js @@ -121,6 +121,10 @@ export class VectorStyle extends AbstractStyle { ); } + getIconSizeStyle() { + return this._iconSizeStyleProperty; + } + _getAllStyleProperties() { return [ this._symbolizeAsStyleProperty, diff --git a/x-pack/legacy/plugins/maps/public/layers/vector_layer.js b/x-pack/legacy/plugins/maps/public/layers/vector_layer.js index 6c765c8f2a2f66..582ab2f9798037 100644 --- a/x-pack/legacy/plugins/maps/public/layers/vector_layer.js +++ b/x-pack/legacy/plugins/maps/public/layers/vector_layer.js @@ -134,7 +134,7 @@ export class VectorLayer extends AbstractLayer { sourceDataRequest ); return { - icon: this._style.getIcon(), + icon: this.getCurrentStyle().getIcon(), tooltipContent: tooltipContent, areResultsTrimmed: areResultsTrimmed, }; @@ -145,11 +145,11 @@ export class VectorLayer extends AbstractLayer { } async hasLegendDetails() { - return this._style.hasLegendDetails(); + return this.getCurrentStyle().hasLegendDetails(); } renderLegendDetails() { - return this._style.renderLegendDetails(); + return this.getCurrentStyle().renderLegendDetails(); } _getBoundsBasedOnData() { @@ -311,7 +311,7 @@ export class VectorLayer extends AbstractLayer { _getSearchFilters(dataFilters) { const fieldNames = [ ...this.getSource().getFieldNames(), - ...this._style.getSourceFieldNames(), + ...this.getCurrentStyle().getSourceFieldNames(), ...this.getValidJoins().map(join => join.getLeftField().getName()), ]; @@ -411,7 +411,7 @@ export class VectorLayer extends AbstractLayer { } async _syncSourceStyleMeta(syncContext) { - if (this._style.constructor.type !== LAYER_STYLE_TYPE.VECTOR) { + if (this.getCurrentStyle().constructor.type !== LAYER_STYLE_TYPE.VECTOR) { return; } @@ -419,12 +419,14 @@ export class VectorLayer extends AbstractLayer { source: this.getSource(), sourceQuery: this.getQuery(), dataRequestId: SOURCE_META_ID_ORIGIN, - dynamicStyleProps: this._style.getDynamicPropertiesArray().filter(dynamicStyleProp => { - return ( - dynamicStyleProp.getFieldOrigin() === FIELD_ORIGIN.SOURCE && - dynamicStyleProp.isFieldMetaEnabled() - ); - }), + dynamicStyleProps: this.getCurrentStyle() + .getDynamicPropertiesArray() + .filter(dynamicStyleProp => { + return ( + dynamicStyleProp.getFieldOrigin() === FIELD_ORIGIN.SOURCE && + dynamicStyleProp.isFieldMetaEnabled() + ); + }), ...syncContext, }); } @@ -435,16 +437,18 @@ export class VectorLayer extends AbstractLayer { source: joinSource, sourceQuery: joinSource.getWhereQuery(), dataRequestId: join.getSourceMetaDataRequestId(), - dynamicStyleProps: this._style.getDynamicPropertiesArray().filter(dynamicStyleProp => { - const matchingField = joinSource.getMetricFieldForName( - dynamicStyleProp.getField().getName() - ); - return ( - dynamicStyleProp.getFieldOrigin() === FIELD_ORIGIN.JOIN && - !!matchingField && - dynamicStyleProp.isFieldMetaEnabled() - ); - }), + dynamicStyleProps: this.getCurrentStyle() + .getDynamicPropertiesArray() + .filter(dynamicStyleProp => { + const matchingField = joinSource.getMetricFieldForName( + dynamicStyleProp.getField().getName() + ); + return ( + dynamicStyleProp.getFieldOrigin() === FIELD_ORIGIN.JOIN && + !!matchingField && + dynamicStyleProp.isFieldMetaEnabled() + ); + }), ...syncContext, }); } @@ -471,7 +475,7 @@ export class VectorLayer extends AbstractLayer { const nextMeta = { dynamicStyleFields: _.uniq(dynamicStyleFields).sort(), sourceQuery, - isTimeAware: this._style.isTimeAware() && (await source.isTimeAware()), + isTimeAware: this.getCurrentStyle().isTimeAware() && (await source.isTimeAware()), timeFilters: dataFilters.timeFilters, }; const prevDataRequest = this._findDataRequestById(dataRequestId); @@ -486,7 +490,7 @@ export class VectorLayer extends AbstractLayer { const layerName = await this.getDisplayName(); const styleMeta = await source.loadStylePropsMeta( layerName, - this._style, + this.getCurrentStyle(), dynamicStyleProps, registerCancelCallback, nextMeta @@ -500,14 +504,14 @@ export class VectorLayer extends AbstractLayer { } async _syncSourceFormatters(syncContext) { - if (this._style.constructor.type !== LAYER_STYLE_TYPE.VECTOR) { + if (this.getCurrentStyle().constructor.type !== LAYER_STYLE_TYPE.VECTOR) { return; } return this._syncFormatters({ source: this.getSource(), dataRequestId: SOURCE_FORMATTERS_ID_ORIGIN, - fields: this._style + fields: this.getCurrentStyle() .getDynamicPropertiesArray() .filter(dynamicStyleProp => { return dynamicStyleProp.getFieldOrigin() === FIELD_ORIGIN.SOURCE; @@ -524,7 +528,7 @@ export class VectorLayer extends AbstractLayer { return this._syncFormatters({ source: joinSource, dataRequestId: join.getSourceFormattersDataRequestId(), - fields: this._style + fields: this.getCurrentStyle() .getDynamicPropertiesArray() .filter(dynamicStyleProp => { const matchingField = joinSource.getMetricFieldForName( @@ -605,7 +609,7 @@ export class VectorLayer extends AbstractLayer { if (!featureCollection) { if (featureCollectionOnMap) { - this._style.clearFeatureState(featureCollectionOnMap, mbMap, this.getId()); + this.getCurrentStyle().clearFeatureState(featureCollectionOnMap, mbMap, this.getId()); } mbGeoJSONSource.setData(EMPTY_FEATURE_COLLECTION); return; @@ -614,7 +618,7 @@ export class VectorLayer extends AbstractLayer { // "feature-state" data expressions are not supported with layout properties. // To work around this limitation, // scaled layout properties (like icon-size) must fall back to geojson property values :( - const hasGeoJsonProperties = this._style.setFeatureStateAndStyleProps( + const hasGeoJsonProperties = this.getCurrentStyle().setFeatureStateAndStyleProps( featureCollection, mbMap, this.getId() @@ -635,7 +639,7 @@ export class VectorLayer extends AbstractLayer { // Point layers symbolized as icons only contain a single mapbox layer. let markerLayerId; let textLayerId; - if (this._style.arePointsSymbolizedAsCircles()) { + if (this.getCurrentStyle().arePointsSymbolizedAsCircles()) { markerLayerId = pointLayerId; textLayerId = this._getMbTextLayerId(); if (symbolLayer) { @@ -689,13 +693,13 @@ export class VectorLayer extends AbstractLayer { mbMap.setFilter(textLayerId, filterExpr); } - this._style.setMBPaintPropertiesForPoints({ + this.getCurrentStyle().setMBPaintPropertiesForPoints({ alpha: this.getAlpha(), mbMap, pointLayerId, }); - this._style.setMBPropertiesForLabelText({ + this.getCurrentStyle().setMBPropertiesForLabelText({ alpha: this.getAlpha(), mbMap, textLayerId, @@ -720,13 +724,13 @@ export class VectorLayer extends AbstractLayer { mbMap.setFilter(symbolLayerId, filterExpr); } - this._style.setMBSymbolPropertiesForPoints({ + this.getCurrentStyle().setMBSymbolPropertiesForPoints({ alpha: this.getAlpha(), mbMap, symbolLayerId, }); - this._style.setMBPropertiesForLabelText({ + this.getCurrentStyle().setMBPropertiesForLabelText({ alpha: this.getAlpha(), mbMap, textLayerId: symbolLayerId, @@ -754,7 +758,7 @@ export class VectorLayer extends AbstractLayer { paint: {}, }); } - this._style.setMBPaintProperties({ + this.getCurrentStyle().setMBPaintProperties({ alpha: this.getAlpha(), mbMap, fillLayerId, From 6a3b1948b1beaf6a3048e484927266f9d114a5c6 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Fri, 14 Feb 2020 15:23:41 -0700 Subject: [PATCH 07/27] pass all parts of style descriptor --- .../public/layers/blended_vector_layer.js | 22 +++++++++++-------- .../styles/vector/vector_style_defaults.js | 2 +- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.js b/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.js index b46fb4707b9cbb..0024e95868bafa 100644 --- a/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.js +++ b/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.js @@ -58,18 +58,22 @@ export class BlendedVectorLayer extends VectorLayer { // derive cluster style from document style const defaultDynamicProperties = getDefaultDynamicProperties(); - const clusterStyleDescriptor = VectorStyle.createDescriptor({ - [VECTOR_STYLES.LABEL_TEXT]: { - type: DynamicStyleProperty.type, - options: { - ...defaultDynamicProperties[VECTOR_STYLES.LABEL_TEXT].options, - field: { - name: COUNT_PROP_NAME, - origin: SOURCE_DATA_ID_ORIGIN, + const clusterStyleDescriptor = { + ...this._documentStyle._descriptor, + properties: { + [VECTOR_STYLES.LABEL_TEXT]: { + type: DynamicStyleProperty.type, + options: { + ...defaultDynamicProperties[VECTOR_STYLES.LABEL_TEXT].options, + field: { + name: COUNT_PROP_NAME, + origin: SOURCE_DATA_ID_ORIGIN, + }, }, }, }, - }); + }; + const documentIconSizeStyle = this._documentStyle.getIconSizeStyle(); if (!documentIconSizeStyle.isDynamic()) { clusterStyleDescriptor.properties[VECTOR_STYLES.ICON_SIZE] = { diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style_defaults.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style_defaults.js index 952f8766a61566..076812351cfdb4 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style_defaults.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style_defaults.js @@ -16,7 +16,7 @@ import chrome from 'ui/chrome'; export const MIN_SIZE = 1; export const MAX_SIZE = 64; -export const DEFAULT_MIN_SIZE = 4; +export const DEFAULT_MIN_SIZE = 7; // Make default large enough to fit default label size export const DEFAULT_MAX_SIZE = 32; export const DEFAULT_SIGMA = 3; export const DEFAULT_LABEL_SIZE = 14; From 536e06061ef1040911a9fd046a49e4273060b976 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Sat, 15 Feb 2020 06:18:09 -0700 Subject: [PATCH 08/27] get toggling between sources working --- .../plugins/maps/public/layers/blended_vector_layer.js | 5 +++-- .../sources/es_search_source/es_search_source.js | 10 +++++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.js b/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.js index 0024e95868bafa..70b718f5a8313b 100644 --- a/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.js +++ b/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.js @@ -132,14 +132,15 @@ export class BlendedVectorLayer extends VectorLayer { const searchFilters = this._getSearchFilters(syncContext.dataFilters); const prevDataRequest = this.getSourceDataRequest(); const canSkipFetch = await canSkipSourceUpdate({ - source: this._source, + source: this.getSource(), prevDataRequest, nextMeta: searchFilters, }); if (!canSkipFetch) { const searchSource = await this._documentSource._makeSearchSource(searchFilters, 0); const resp = await searchSource.fetch(); - if (resp.hits.total > 100) { + const maxResultWindow = await this._documentSource.getMaxResultWindow(); + if (resp.hits.total > maxResultWindow) { this._activeSource = this._clusterSource; this._activeStyle = this._clusterStyle; } else { diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/es_search_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/es_search_source.js index bea3a74490cbd2..708e37b05f278e 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/es_search_source.js +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/es_search_source.js @@ -436,6 +436,12 @@ export class ESSearchSource extends AbstractESSource { return !!sortField && !!sortOrder; } + async getMaxResultWindow() { + const indexPattern = await this.getIndexPattern(); + const indexSettings = await loadIndexSettings(indexPattern.title); + return indexSettings.maxResultWindow; + } + async getGeoJsonWithMeta(layerName, searchFilters, registerCancelCallback) { const indexPattern = await this.getIndexPattern(); @@ -537,7 +543,9 @@ export class ESSearchSource extends AbstractESSource { } isFilterByMapBounds() { - return this._descriptor.filterByMapBounds; + return this._descriptor.scalingType === SCALING_TYPES.CLUSTER + ? true + : this._descriptor.filterByMapBounds; } async getLeftJoinFields() { From 9a2b4d064961bec3158fca4c7b5705bd93277634 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Wed, 19 Feb 2020 09:28:02 -0700 Subject: [PATCH 09/27] derive cluster style from document style --- .../public/layers/blended_vector_layer.js | 98 ++++++++++++++----- .../layers/styles/vector/vector_style.js | 10 +- 2 files changed, 78 insertions(+), 30 deletions(-) diff --git a/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.js b/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.js index 70b718f5a8313b..8e9163408cbfe3 100644 --- a/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.js +++ b/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.js @@ -8,15 +8,23 @@ import { VectorLayer } from './vector_layer'; import { VectorStyle } from './styles/vector/vector_style'; import { getDefaultDynamicProperties, VECTOR_STYLES } from './styles/vector/vector_style_defaults'; import { DynamicStyleProperty } from './styles/vector/properties/dynamic_style_property'; +import { StaticStyleProperty } from './styles/vector/properties/static_style_property'; import { + COUNT_PROP_LABEL, COUNT_PROP_NAME, ES_GEO_GRID, LAYER_TYPE, + METRIC_TYPE, SOURCE_DATA_ID_ORIGIN, } from '../../common/constants'; import { ESGeoGridSource, RENDER_AS } from './sources/es_geo_grid_source'; import { canSkipSourceUpdate } from './util/can_skip_fetch'; +function getAggType(dynamicProperty) { + // TODO change 'terms' to constant once top terms PR is merged + return dynamicProperty.isOrdinal() ? METRIC_TYPE.AVG : 'terms'; +} + export class BlendedVectorLayer extends VectorLayer { static type = LAYER_TYPE.BLENDED_VECTOR; @@ -45,12 +53,39 @@ export class BlendedVectorLayer extends VectorLayer { this._documentSource = this._source; // VectorLayer constructor sets _source as document source this._documentStyle = this._style; // VectorLayer constructor sets _style as document source + this._initClusterSourceAndStyle(); + + this._activeSource = this._documentSource; + this._activeStyle = this._documentStyle; + const sourceDataRequest = this.getSourceDataRequest(); + if (sourceDataRequest) { + const requestMeta = sourceDataRequest.getMeta(); + if (requestMeta && requestMeta.sourceType === ES_GEO_GRID) { + this._activeSource = this._clusterSource; + this._activeStyle = this._clusterStyle; + } + } + } + + _initClusterSourceAndStyle() { // derive cluster source from document source const clusterSourceDescriptor = ESGeoGridSource.createDescriptor({ indexPatternId: this._documentSource.getIndexPatternId(), geoField: this._documentSource.getGeoFieldName(), requestType: RENDER_AS.POINT, }); + clusterSourceDescriptor.metrics = [ + { + type: METRIC_TYPE.COUNT, + label: COUNT_PROP_LABEL, + }, + ...this._documentStyle.getDynamicPropertiesArray().map(dynamicProperty => { + return { + type: getAggType(dynamicProperty), + field: dynamicProperty.getFieldName(), + }; + }), + ]; this._clusterSource = new ESGeoGridSource( clusterSourceDescriptor, this._documentSource.getInspectorAdapters() @@ -71,34 +106,51 @@ export class BlendedVectorLayer extends VectorLayer { }, }, }, + [VECTOR_STYLES.ICON_SIZE]: { + type: DynamicStyleProperty.type, + options: { + ...defaultDynamicProperties[VECTOR_STYLES.ICON_SIZE].options, + field: { + name: COUNT_PROP_NAME, + origin: SOURCE_DATA_ID_ORIGIN, + }, + }, + }, }, }; + this._documentStyle.getAllStyleProperties().forEach(styleProperty => { + const styleName = styleProperty.getStyleName(); + if ( + [VECTOR_STYLES.LABEL_TEXT, VECTOR_STYLES.ICON_SIZE].includes(styleName) && + (!styleProperty.isDynamic() || !styleProperty.isComplete()) + ) { + // Do not migrate static label and icon size properties to provide unique cluster styling out of the box + return; + } - const documentIconSizeStyle = this._documentStyle.getIconSizeStyle(); - if (!documentIconSizeStyle.isDynamic()) { - clusterStyleDescriptor.properties[VECTOR_STYLES.ICON_SIZE] = { - type: DynamicStyleProperty.type, - options: { - ...defaultDynamicProperties[VECTOR_STYLES.ICON_SIZE].options, - field: { - name: COUNT_PROP_NAME, - origin: SOURCE_DATA_ID_ORIGIN, + const options = styleProperty.getOptions(); + if (styleProperty.isDynamic()) { + clusterStyleDescriptor.properties[styleName] = { + type: DynamicStyleProperty.type, + options: { + ...options, + field: { + ...options.field, + name: this._clusterSource.formatMetricKey( + getAggType(styleProperty), + options.field.name + ), + }, }, - }, - }; - } - this._clusterStyle = new VectorStyle(clusterStyleDescriptor, this._clusterSource, this); - - this._activeSource = this._documentSource; - this._activeStyle = this._documentStyle; - const sourceDataRequest = this.getSourceDataRequest(); - if (sourceDataRequest) { - const requestMeta = sourceDataRequest.getMeta(); - if (requestMeta && requestMeta.sourceType === ES_GEO_GRID) { - this._activeSource = this._clusterSource; - this._activeStyle = this._clusterStyle; + }; + } else { + clusterStyleDescriptor.properties[styleName] = { + type: StaticStyleProperty.type, + options: { ...options }, + }; } - } + }); + this._clusterStyle = new VectorStyle(clusterStyleDescriptor, this._clusterSource, this); } isJoinable() { diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.js index 79fd729c7bdaa7..dc93d25257bc4f 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.js @@ -121,11 +121,7 @@ export class VectorStyle extends AbstractStyle { ); } - getIconSizeStyle() { - return this._iconSizeStyleProperty; - } - - _getAllStyleProperties() { + getAllStyleProperties() { return [ this._symbolizeAsStyleProperty, this._iconStyleProperty, @@ -166,7 +162,7 @@ export class VectorStyle extends AbstractStyle { }); const styleProperties = {}; - this._getAllStyleProperties().forEach(styleProperty => { + this.getAllStyleProperties().forEach(styleProperty => { styleProperties[styleProperty.getStyleName()] = styleProperty; }); @@ -332,7 +328,7 @@ export class VectorStyle extends AbstractStyle { } getDynamicPropertiesArray() { - const styleProperties = this._getAllStyleProperties(); + const styleProperties = this.getAllStyleProperties(); return styleProperties.filter( styleProperty => styleProperty.isDynamic() && styleProperty.isComplete() ); From 1eb31f78d7f0e0b3dadf4401c833a136445231f2 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Wed, 26 Feb 2020 07:55:07 -0700 Subject: [PATCH 10/27] remove references to METRIC_TYPE --- .../plugins/maps/public/layers/blended_vector_layer.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.js b/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.js index 8e9163408cbfe3..b6cfc5d333b80b 100644 --- a/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.js +++ b/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.js @@ -14,15 +14,14 @@ import { COUNT_PROP_NAME, ES_GEO_GRID, LAYER_TYPE, - METRIC_TYPE, + AGG_TYPE, SOURCE_DATA_ID_ORIGIN, } from '../../common/constants'; import { ESGeoGridSource, RENDER_AS } from './sources/es_geo_grid_source'; import { canSkipSourceUpdate } from './util/can_skip_fetch'; function getAggType(dynamicProperty) { - // TODO change 'terms' to constant once top terms PR is merged - return dynamicProperty.isOrdinal() ? METRIC_TYPE.AVG : 'terms'; + return dynamicProperty.isOrdinal() ? AGG_TYPE.AVG : AGG_TYPE.TERMS; } export class BlendedVectorLayer extends VectorLayer { @@ -76,7 +75,7 @@ export class BlendedVectorLayer extends VectorLayer { }); clusterSourceDescriptor.metrics = [ { - type: METRIC_TYPE.COUNT, + type: AGG_TYPE.COUNT, label: COUNT_PROP_LABEL, }, ...this._documentStyle.getDynamicPropertiesArray().map(dynamicProperty => { From 5eec22b52173724481b66f49f06b9b6dd2cf5c7c Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Wed, 11 Mar 2020 18:37:01 -0600 Subject: [PATCH 11/27] fix import --- .../legacy/plugins/maps/public/layers/blended_vector_layer.js | 3 ++- .../maps/public/layers/sources/es_geo_grid_source/index.js | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.js b/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.js index b6cfc5d333b80b..8711e58b9db7c5 100644 --- a/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.js +++ b/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.js @@ -16,8 +16,9 @@ import { LAYER_TYPE, AGG_TYPE, SOURCE_DATA_ID_ORIGIN, + RENDER_AS, } from '../../common/constants'; -import { ESGeoGridSource, RENDER_AS } from './sources/es_geo_grid_source'; +import { ESGeoGridSource } from './sources/es_geo_grid_source'; import { canSkipSourceUpdate } from './util/can_skip_fetch'; function getAggType(dynamicProperty) { diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/index.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/index.js index 6c8ab65b98066d..58d74c04c55529 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/index.js +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/index.js @@ -5,4 +5,3 @@ */ export { ESGeoGridSource } from './es_geo_grid_source'; -export { RENDER_AS } from './render_as'; From e18c9dd66365075771416a65af483d345cd3e436 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Thu, 12 Mar 2020 10:19:06 -0600 Subject: [PATCH 12/27] start typescripting blended_vector_layer --- .../plugins/maps/common/descriptor_types.d.ts | 8 ++--- ...ector_layer.js => blended_vector_layer.ts} | 33 ++++++++++++------- .../plugins/maps/public/layers/layer.d.ts | 9 +++++ .../es_geo_grid_source/es_geo_grid_source.js | 2 +- .../es_pew_pew_source/es_pew_pew_source.js | 2 +- .../es_search_source/es_search_source.js | 4 +-- .../maps/public/layers/sources/es_source.d.ts | 7 ++++ .../maps/public/layers/sources/es_source.js | 4 +-- .../public/layers/sources/es_term_source.js | 2 +- .../maps/public/layers/sources/source.d.ts | 4 +++ .../properties/dynamic_style_property.d.ts | 1 + .../util/{data_request.js => data_request.ts} | 23 ++++++++----- .../maps/public/layers/vector_layer.d.ts | 1 + .../maps/public/layers/vector_layer.js | 2 +- 14 files changed, 69 insertions(+), 33 deletions(-) rename x-pack/legacy/plugins/maps/public/layers/{blended_vector_layer.js => blended_vector_layer.ts} (86%) rename x-pack/legacy/plugins/maps/public/layers/util/{data_request.js => data_request.ts} (63%) diff --git a/x-pack/legacy/plugins/maps/common/descriptor_types.d.ts b/x-pack/legacy/plugins/maps/common/descriptor_types.d.ts index ce0743ba2baedf..d75123e20b9033 100644 --- a/x-pack/legacy/plugins/maps/common/descriptor_types.d.ts +++ b/x-pack/legacy/plugins/maps/common/descriptor_types.d.ts @@ -95,10 +95,10 @@ export type JoinDescriptor = { export type DataRequestDescriptor = { dataId: string; - dataMetaAtStart: object; - dataRequestToken: symbol; - data: object; - dataMeta: object; + dataMetaAtStart?: object; + dataRequestToken?: symbol; + data?: object; + dataMeta?: object; }; export type LayerDescriptor = { diff --git a/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.js b/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.ts similarity index 86% rename from x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.js rename to x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.ts index 8711e58b9db7c5..16664006876af6 100644 --- a/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.js +++ b/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.ts @@ -7,7 +7,10 @@ import { VectorLayer } from './vector_layer'; import { VectorStyle } from './styles/vector/vector_style'; import { getDefaultDynamicProperties, VECTOR_STYLES } from './styles/vector/vector_style_defaults'; -import { DynamicStyleProperty } from './styles/vector/properties/dynamic_style_property'; +import { + IDynamicStyleProperty, + DynamicStyleProperty, +} from './styles/vector/properties/dynamic_style_property'; import { StaticStyleProperty } from './styles/vector/properties/static_style_property'; import { COUNT_PROP_LABEL, @@ -20,12 +23,15 @@ import { } from '../../common/constants'; import { ESGeoGridSource } from './sources/es_geo_grid_source'; import { canSkipSourceUpdate } from './util/can_skip_fetch'; +import { IVectorLayer } from './vector_layer'; +import { IESSource } from '../sources/es_source'; +import { IESAggSource } from '../sources/es_agg_source'; -function getAggType(dynamicProperty) { +function getAggType(dynamicProperty: IDynamicStyleProperty): AGG_TYPE { return dynamicProperty.isOrdinal() ? AGG_TYPE.AVG : AGG_TYPE.TERMS; } -export class BlendedVectorLayer extends VectorLayer { +export class BlendedVectorLayer extends VectorLayer implements IVectorLayer { static type = LAYER_TYPE.BLENDED_VECTOR; static createDescriptor(options, mapColors) { @@ -34,6 +40,13 @@ export class BlendedVectorLayer extends VectorLayer { return layerDescriptor; } + private _activeSource; + private _activeStyle; + private readonly _clusterSource: IESAggSource; + private readonly _clusterStyle; + private readonly _documentSource: IESSource; + private readonly _documentStyle; + constructor(options) { super(options); @@ -136,10 +149,7 @@ export class BlendedVectorLayer extends VectorLayer { ...options, field: { ...options.field, - name: this._clusterSource.formatMetricKey( - getAggType(styleProperty), - options.field.name - ), + name: this._clusterSource.getAggKey(getAggType(styleProperty), options.field.name), }, }, }; @@ -180,16 +190,15 @@ export class BlendedVectorLayer extends VectorLayer { return this._documentStyle; } - async syncData(syncContext) { + async syncData(syncContext: unknown) { const searchFilters = this._getSearchFilters(syncContext.dataFilters); - const prevDataRequest = this.getSourceDataRequest(); const canSkipFetch = await canSkipSourceUpdate({ source: this.getSource(), - prevDataRequest, + prevDataRequest: this.getSourceDataRequest(), nextMeta: searchFilters, }); if (!canSkipFetch) { - const searchSource = await this._documentSource._makeSearchSource(searchFilters, 0); + const searchSource = await this._documentSource.makeSearchSource(searchFilters, 0); const resp = await searchSource.fetch(); const maxResultWindow = await this._documentSource.getMaxResultWindow(); if (resp.hits.total > maxResultWindow) { @@ -204,5 +213,5 @@ export class BlendedVectorLayer extends VectorLayer { super.syncData(syncContext); } - /*syncLayerWithMB(mbMap) {}*/ + /* syncLayerWithMB(mbMap) {}*/ } diff --git a/x-pack/legacy/plugins/maps/public/layers/layer.d.ts b/x-pack/legacy/plugins/maps/public/layers/layer.d.ts index eebbaac7d4f977..6ab09cd4d98562 100644 --- a/x-pack/legacy/plugins/maps/public/layers/layer.d.ts +++ b/x-pack/legacy/plugins/maps/public/layers/layer.d.ts @@ -5,9 +5,14 @@ */ import { LayerDescriptor } from '../../common/descriptor_types'; import { ISource } from './sources/source'; +import { DataRequest } from './util/data_request'; export interface ILayer { getDisplayName(): Promise; + getSourceDataRequest(): DataRequest | undefined; + getSource(): ISource; + getSourceForEditing(): ISource; + syncData(syncContext: unknown): Promise; } export interface ILayerArguments { @@ -18,4 +23,8 @@ export interface ILayerArguments { export class AbstractLayer implements ILayer { constructor(layerArguments: ILayerArguments); getDisplayName(): Promise; + getSourceDataRequest(): DataRequest | undefined; + getSource(): ISource; + getSourceForEditing(): ISource; + syncData(syncContext: unknown): Promise; } diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.js index 83519c57c377db..5ad202a02ae6d1 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.js +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.js @@ -292,7 +292,7 @@ export class ESGeoGridSource extends AbstractESAggSource { async getGeoJsonWithMeta(layerName, searchFilters, registerCancelCallback, isRequestStillActive) { const indexPattern = await this.getIndexPattern(); - const searchSource = await this._makeSearchSource(searchFilters, 0); + const searchSource = await this.makeSearchSource(searchFilters, 0); let bucketsPerGrid = 1; this.getMetricFields().forEach(metricField => { diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_pew_pew_source/es_pew_pew_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_pew_pew_source/es_pew_pew_source.js index 21f9b9596b7d95..8e1145c531f9e5 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_pew_pew_source/es_pew_pew_source.js +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_pew_pew_source/es_pew_pew_source.js @@ -167,7 +167,7 @@ export class ESPewPewSource extends AbstractESAggSource { async getGeoJsonWithMeta(layerName, searchFilters, registerCancelCallback) { const indexPattern = await this.getIndexPattern(); - const searchSource = await this._makeSearchSource(searchFilters, 0); + const searchSource = await this.makeSearchSource(searchFilters, 0); searchSource.setField('aggs', { destSplit: { terms: { diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/es_search_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/es_search_source.js index 9c23ad2f28d5f0..440b9aa89a9457 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/es_search_source.js +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/es_search_source.js @@ -271,7 +271,7 @@ export class ESSearchSource extends AbstractESSource { shard_size: DEFAULT_MAX_BUCKETS_LIMIT, }; - const searchSource = await this._makeSearchSource(searchFilters, 0); + const searchSource = await this.makeSearchSource(searchFilters, 0); searchSource.setField('aggs', { totalEntities: { cardinality: addFieldToDSL(cardinalityAgg, topHitsSplitField), @@ -332,7 +332,7 @@ export class ESSearchSource extends AbstractESSource { ); const initialSearchContext = { docvalue_fields: docValueFields }; // Request fields in docvalue_fields insted of _source - const searchSource = await this._makeSearchSource( + const searchSource = await this.makeSearchSource( searchFilters, maxResultWindow, initialSearchContext diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_source.d.ts b/x-pack/legacy/plugins/maps/public/layers/sources/es_source.d.ts index 25c4fae89f0247..903f4f32fefda3 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_source.d.ts +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_source.d.ts @@ -7,11 +7,18 @@ import { AbstractVectorSource } from './vector_source'; import { IVectorSource } from './vector_source'; import { IndexPattern } from '../../../../../../../src/plugins/data/public'; +import { SearchSource } from '../../kibana_services'; export interface IESSource extends IVectorSource { getIndexPattern(): Promise; + getGeoFieldName(): string; + getMaxResultWindow(): Promise; + makeSearchSource(): Promise; } export class AbstractESSource extends AbstractVectorSource implements IESSource { getIndexPattern(): Promise; + getGeoFieldName(): string; + getMaxResultWindow(): Promise; + makeSearchSource(): Promise; } diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_source.js index 436739ce40c238..a9c1bc736abf8d 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_source.js +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_source.js @@ -105,7 +105,7 @@ export class AbstractESSource extends AbstractVectorSource { } } - async _makeSearchSource(searchFilters, limit, initialSearchContext) { + async makeSearchSource(searchFilters, limit, initialSearchContext) { const indexPattern = await this.getIndexPattern(); const isTimeAware = await this.isTimeAware(); const applyGlobalQuery = _.get(searchFilters, 'applyGlobalQuery', true); @@ -142,7 +142,7 @@ export class AbstractESSource extends AbstractVectorSource { } async getBoundsForFilters({ sourceQuery, query, timeFilters, filters, applyGlobalQuery }) { - const searchSource = await this._makeSearchSource( + const searchSource = await this.makeSearchSource( { sourceQuery, query, timeFilters, filters, applyGlobalQuery }, 0 ); diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_term_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_term_source.js index 7cc305a73eabd4..3ce0fb58aba195 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_term_source.js +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_term_source.js @@ -86,7 +86,7 @@ export class ESTermSource extends AbstractESAggSource { } const indexPattern = await this.getIndexPattern(); - const searchSource = await this._makeSearchSource(searchFilters, 0); + const searchSource = await this.makeSearchSource(searchFilters, 0); const termsField = getField(indexPattern, this._termField.getName()); const termsAgg = { size: DEFAULT_MAX_BUCKETS_LIMIT }; searchSource.setField('aggs', { diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/source.d.ts b/x-pack/legacy/plugins/maps/public/layers/sources/source.d.ts index b5b34efabda0ae..2ca18e47a4bf93 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/source.d.ts +++ b/x-pack/legacy/plugins/maps/public/layers/sources/source.d.ts @@ -10,10 +10,14 @@ import { ILayer } from '../layer'; export interface ISource { createDefaultLayer(): ILayer; getDisplayName(): Promise; + destroy(): void; + getInspectorAdapters(): object; } export class AbstractSource implements ISource { constructor(sourceDescriptor: AbstractSourceDescriptor, inspectorAdapters: object); createDefaultLayer(): ILayer; getDisplayName(): Promise; + destroy(): void; + getInspectorAdapters(): object; } diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_style_property.d.ts b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_style_property.d.ts index f4c487b28757eb..956681094953d1 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_style_property.d.ts +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_style_property.d.ts @@ -22,6 +22,7 @@ export interface IDynamicStyleProperty extends IStyleProperty { getRangeFieldMeta(): RangeFieldMeta; getCategoryFieldMeta(): CategoryFieldMeta; isFieldMetaEnabled(): boolean; + isOrdinal(): boolean; supportsFieldMeta(): boolean; getFieldMetaRequest(): Promise; supportsMbFeatureState(): boolean; diff --git a/x-pack/legacy/plugins/maps/public/layers/util/data_request.js b/x-pack/legacy/plugins/maps/public/layers/util/data_request.ts similarity index 63% rename from x-pack/legacy/plugins/maps/public/layers/util/data_request.js rename to x-pack/legacy/plugins/maps/public/layers/util/data_request.ts index 3a6c10a9f07a6e..e318b1b23c9181 100644 --- a/x-pack/legacy/plugins/maps/public/layers/util/data_request.js +++ b/x-pack/legacy/plugins/maps/public/layers/util/data_request.ts @@ -3,42 +3,47 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ +/* eslint-disable max-classes-per-file */ + import _ from 'lodash'; +import { DataRequestDescriptor } from '../../../common/descriptor_types'; export class DataRequest { - constructor(descriptor) { + private readonly _descriptor: DataRequestDescriptor; + + constructor(descriptor: DataRequestDescriptor) { this._descriptor = { ...descriptor, }; } - getData() { + getData(): object { return this._descriptor.data; } - isLoading() { + isLoading(): boolean { return !!this._descriptor.dataRequestToken; } - getMeta() { + getMeta(): object { return this.hasData() ? _.get(this._descriptor, 'dataMeta', {}) : _.get(this._descriptor, 'dataMetaAtStart', {}); } - hasData() { + hasData(): boolean { return !!this._descriptor.data; } - hasDataOrRequestInProgress() { - return this._descriptor.data || this._descriptor.dataRequestToken; + hasDataOrRequestInProgress(): boolean { + return this.hasData() || this.isLoading(); } - getDataId() { + getDataId(): string { return this._descriptor.dataId; } - getRequestToken() { + getRequestToken(): symbol | undefined { return this._descriptor.dataRequestToken; } } diff --git a/x-pack/legacy/plugins/maps/public/layers/vector_layer.d.ts b/x-pack/legacy/plugins/maps/public/layers/vector_layer.d.ts index 748b2fd1d782c8..9922a087c7c5ee 100644 --- a/x-pack/legacy/plugins/maps/public/layers/vector_layer.d.ts +++ b/x-pack/legacy/plugins/maps/public/layers/vector_layer.d.ts @@ -24,4 +24,5 @@ export class VectorLayer extends AbstractLayer implements IVectorLayer { constructor(options: VectorLayerArguments); getValidJoins(): IJoin[]; + _getSearchFilters(dataFilters: unknown): unknown; } diff --git a/x-pack/legacy/plugins/maps/public/layers/vector_layer.js b/x-pack/legacy/plugins/maps/public/layers/vector_layer.js index c6fab3c53851a4..6dbf6039753863 100644 --- a/x-pack/legacy/plugins/maps/public/layers/vector_layer.js +++ b/x-pack/legacy/plugins/maps/public/layers/vector_layer.js @@ -58,7 +58,7 @@ export class VectorLayer extends AbstractLayer { constructor({ layerDescriptor, source, joins = [] }) { super({ layerDescriptor, source }); this._joins = joins; - this._style = new VectorStyle(this._descriptor.style, this.getSource(), this); + this._style = new VectorStyle(this._descriptor.style, source, this); } getStyle() { From 4d5e928af3d95804cdda74c2effb8c617a932b9e Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Thu, 12 Mar 2020 13:12:59 -0600 Subject: [PATCH 13/27] more typescript work --- .../common/data_request_descriptor_types.d.ts | 45 ++++ .../plugins/maps/common/descriptor_types.d.ts | 9 +- .../public/layers/blended_vector_layer.ts | 230 +++++++++--------- .../es_geo_grid_source.d.ts | 5 +- .../maps/public/layers/sources/es_source.d.ts | 15 +- .../public/layers/sources/vector_source.d.ts | 8 +- .../properties/dynamic_style_property.d.ts | 6 +- .../layers/styles/vector/vector_style.d.ts | 23 ++ .../maps/public/layers/util/data_request.ts | 6 +- .../maps/public/layers/vector_layer.d.ts | 13 +- 10 files changed, 226 insertions(+), 134 deletions(-) create mode 100644 x-pack/legacy/plugins/maps/common/data_request_descriptor_types.d.ts create mode 100644 x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.d.ts diff --git a/x-pack/legacy/plugins/maps/common/data_request_descriptor_types.d.ts b/x-pack/legacy/plugins/maps/common/data_request_descriptor_types.d.ts new file mode 100644 index 00000000000000..49be569e516f5b --- /dev/null +++ b/x-pack/legacy/plugins/maps/common/data_request_descriptor_types.d.ts @@ -0,0 +1,45 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +/* eslint-disable @typescript-eslint/consistent-type-definitions */ + +// Global map state passed to every layer. +export type MapFilters = { + buffer: unknown; + extent: unknown; + filters: unknown[]; + query: unknown; + refreshTimerLastTriggeredAt: string; + timeFilters: unknown; + zoom: number; +}; + +export type VectorLayerRequestMeta = MapFilters & { + applyGlobalQuery: boolean; + fieldNames: string[]; + geogridPrecision: number; + sourceQuery: unknown; + sourceMeta: unknown; +}; + +export type ESSearchSourceResponseMeta = { + areResultsTrimmed?: boolean; + sourceType?: string; + + // top hits meta + areEntitiesTrimmed?: boolean; + entityCount?: number; + totalEntities?: number; +}; + +export type DataMeta = VectorLayerRequestMeta & ESSearchSourceResponseMeta; + +export type DataRequestDescriptor = { + dataId: string; + dataMetaAtStart?: DataMeta; + dataRequestToken?: symbol; + data?: object; + dataMeta?: DataMeta; +}; diff --git a/x-pack/legacy/plugins/maps/common/descriptor_types.d.ts b/x-pack/legacy/plugins/maps/common/descriptor_types.d.ts index d75123e20b9033..ff62da18d2373a 100644 --- a/x-pack/legacy/plugins/maps/common/descriptor_types.d.ts +++ b/x-pack/legacy/plugins/maps/common/descriptor_types.d.ts @@ -5,6 +5,7 @@ */ /* eslint-disable @typescript-eslint/consistent-type-definitions */ +import { DataRequestDescriptor } from 'data_request_descriptor_types'; import { AGG_TYPE, GRID_RESOLUTION, RENDER_AS, SORT_ORDER } from './constants'; export type AbstractSourceDescriptor = { @@ -93,14 +94,6 @@ export type JoinDescriptor = { right: ESTermSourceDescriptor; }; -export type DataRequestDescriptor = { - dataId: string; - dataMetaAtStart?: object; - dataRequestToken?: symbol; - data?: object; - dataMeta?: object; -}; - export type LayerDescriptor = { __dataRequests?: DataRequestDescriptor[]; __isInErrorState?: boolean; diff --git a/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.ts b/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.ts index 16664006876af6..e5ed1538259ece 100644 --- a/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.ts +++ b/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.ts @@ -5,13 +5,11 @@ */ import { VectorLayer } from './vector_layer'; -import { VectorStyle } from './styles/vector/vector_style'; +import { IVectorStyle, VectorStyle } from './styles/vector/vector_style'; +// @ts-ignore import { getDefaultDynamicProperties, VECTOR_STYLES } from './styles/vector/vector_style_defaults'; -import { - IDynamicStyleProperty, - DynamicStyleProperty, -} from './styles/vector/properties/dynamic_style_property'; -import { StaticStyleProperty } from './styles/vector/properties/static_style_property'; +import { IDynamicStyleProperty } from './styles/vector/properties/dynamic_style_property'; +import { IStyleProperty } from './styles/vector/properties/style_property'; import { COUNT_PROP_LABEL, COUNT_PROP_NAME, @@ -20,147 +18,154 @@ import { AGG_TYPE, SOURCE_DATA_ID_ORIGIN, RENDER_AS, + STYLE_TYPE, } from '../../common/constants'; -import { ESGeoGridSource } from './sources/es_geo_grid_source'; +import { ESGeoGridSource } from './sources/es_geo_grid_source/es_geo_grid_source'; +// @ts-ignore import { canSkipSourceUpdate } from './util/can_skip_fetch'; -import { IVectorLayer } from './vector_layer'; -import { IESSource } from '../sources/es_source'; -import { IESAggSource } from '../sources/es_agg_source'; +import { IVectorLayer, VectorLayerArguments } from './vector_layer'; +import { IESSource } from './sources/es_source'; +import { IESAggSource } from './sources/es_agg_source'; function getAggType(dynamicProperty: IDynamicStyleProperty): AGG_TYPE { return dynamicProperty.isOrdinal() ? AGG_TYPE.AVG : AGG_TYPE.TERMS; } +function getClusterSource(documentSource: IESSource, documentStyle: IVectorStyle): IESAggSource { + const clusterSourceDescriptor = ESGeoGridSource.createDescriptor({ + indexPatternId: documentSource.getIndexPatternId(), + geoField: documentSource.getGeoFieldName(), + requestType: RENDER_AS.POINT, + }); + clusterSourceDescriptor.metrics = [ + { + type: AGG_TYPE.COUNT, + label: COUNT_PROP_LABEL, + }, + ...documentStyle.getDynamicPropertiesArray().map(dynamicProperty => { + return { + type: getAggType(dynamicProperty), + field: dynamicProperty.getFieldName(), + }; + }), + ]; + return new ESGeoGridSource(clusterSourceDescriptor, documentSource.getInspectorAdapters()); +} + +function getClusterStyleDescriptor( + documentStyle: IVectorStyle, + clusterSource: IESAggSource +): unknown { + const defaultDynamicProperties = getDefaultDynamicProperties(); + const clusterStyleDescriptor: any = { + ...documentStyle.getDescriptor(), + properties: { + [VECTOR_STYLES.LABEL_TEXT]: { + type: STYLE_TYPE.DYNAMIC, + options: { + ...defaultDynamicProperties[VECTOR_STYLES.LABEL_TEXT].options, + field: { + name: COUNT_PROP_NAME, + origin: SOURCE_DATA_ID_ORIGIN, + }, + }, + }, + [VECTOR_STYLES.ICON_SIZE]: { + type: STYLE_TYPE.DYNAMIC, + options: { + ...defaultDynamicProperties[VECTOR_STYLES.ICON_SIZE].options, + field: { + name: COUNT_PROP_NAME, + origin: SOURCE_DATA_ID_ORIGIN, + }, + }, + }, + }, + }; + documentStyle.getAllStyleProperties().forEach((styleProperty: IStyleProperty) => { + const styleName = styleProperty.getStyleName(); + if ( + [VECTOR_STYLES.LABEL_TEXT, VECTOR_STYLES.ICON_SIZE].includes(styleName) && + (!styleProperty.isDynamic() || !styleProperty.isComplete()) + ) { + // Do not migrate static label and icon size properties to provide unique cluster styling out of the box + return; + } + + const options = styleProperty.getOptions(); + if (styleProperty.isDynamic()) { + clusterStyleDescriptor.properties[styleName] = { + type: STYLE_TYPE.DYNAMIC, + options: { + ...options, + field: { + ...options.field, + name: clusterSource.getAggKey( + getAggType(styleProperty as IDynamicStyleProperty), + options.field.name + ), + }, + }, + }; + } else { + clusterStyleDescriptor.properties[styleName] = { + type: STYLE_TYPE.STATIC, + options: { ...options }, + }; + } + }); + + return clusterStyleDescriptor; +} + export class BlendedVectorLayer extends VectorLayer implements IVectorLayer { static type = LAYER_TYPE.BLENDED_VECTOR; - static createDescriptor(options, mapColors) { + static createDescriptor(options: VectorLayerArguments, mapColors: string[]) { const layerDescriptor = VectorLayer.createDescriptor(options, mapColors); layerDescriptor.type = BlendedVectorLayer.type; return layerDescriptor; } - private _activeSource; - private _activeStyle; + private _activeSource: IESSource; + private _activeStyle: IVectorStyle; private readonly _clusterSource: IESAggSource; - private readonly _clusterStyle; + private readonly _clusterStyle: IVectorStyle; private readonly _documentSource: IESSource; - private readonly _documentStyle; + private readonly _documentStyle: IVectorStyle; - constructor(options) { + constructor(options: VectorLayerArguments) { super(options); - this._initActiveSourceAndStyle(); - } - - destroy() { - if (this._documentSource) { - this._documentSource.destroy(); - } - if (this._clusterSource) { - this._clusterSource.destroy(); - } - } - - _initActiveSourceAndStyle() { this._documentSource = this._source; // VectorLayer constructor sets _source as document source this._documentStyle = this._style; // VectorLayer constructor sets _style as document source - this._initClusterSourceAndStyle(); + this._clusterSource = getClusterSource(this._documentSource, this._documentStyle); + const clusterStyleDescriptor = getClusterStyleDescriptor( + this._documentStyle, + this._clusterSource + ); + this._clusterStyle = new VectorStyle(clusterStyleDescriptor, this._clusterSource, this); this._activeSource = this._documentSource; this._activeStyle = this._documentStyle; const sourceDataRequest = this.getSourceDataRequest(); if (sourceDataRequest) { const requestMeta = sourceDataRequest.getMeta(); - if (requestMeta && requestMeta.sourceType === ES_GEO_GRID) { + if (requestMeta && requestMeta.sourceType && requestMeta.sourceType === ES_GEO_GRID) { this._activeSource = this._clusterSource; this._activeStyle = this._clusterStyle; } } } - _initClusterSourceAndStyle() { - // derive cluster source from document source - const clusterSourceDescriptor = ESGeoGridSource.createDescriptor({ - indexPatternId: this._documentSource.getIndexPatternId(), - geoField: this._documentSource.getGeoFieldName(), - requestType: RENDER_AS.POINT, - }); - clusterSourceDescriptor.metrics = [ - { - type: AGG_TYPE.COUNT, - label: COUNT_PROP_LABEL, - }, - ...this._documentStyle.getDynamicPropertiesArray().map(dynamicProperty => { - return { - type: getAggType(dynamicProperty), - field: dynamicProperty.getFieldName(), - }; - }), - ]; - this._clusterSource = new ESGeoGridSource( - clusterSourceDescriptor, - this._documentSource.getInspectorAdapters() - ); - - // derive cluster style from document style - const defaultDynamicProperties = getDefaultDynamicProperties(); - const clusterStyleDescriptor = { - ...this._documentStyle._descriptor, - properties: { - [VECTOR_STYLES.LABEL_TEXT]: { - type: DynamicStyleProperty.type, - options: { - ...defaultDynamicProperties[VECTOR_STYLES.LABEL_TEXT].options, - field: { - name: COUNT_PROP_NAME, - origin: SOURCE_DATA_ID_ORIGIN, - }, - }, - }, - [VECTOR_STYLES.ICON_SIZE]: { - type: DynamicStyleProperty.type, - options: { - ...defaultDynamicProperties[VECTOR_STYLES.ICON_SIZE].options, - field: { - name: COUNT_PROP_NAME, - origin: SOURCE_DATA_ID_ORIGIN, - }, - }, - }, - }, - }; - this._documentStyle.getAllStyleProperties().forEach(styleProperty => { - const styleName = styleProperty.getStyleName(); - if ( - [VECTOR_STYLES.LABEL_TEXT, VECTOR_STYLES.ICON_SIZE].includes(styleName) && - (!styleProperty.isDynamic() || !styleProperty.isComplete()) - ) { - // Do not migrate static label and icon size properties to provide unique cluster styling out of the box - return; - } - - const options = styleProperty.getOptions(); - if (styleProperty.isDynamic()) { - clusterStyleDescriptor.properties[styleName] = { - type: DynamicStyleProperty.type, - options: { - ...options, - field: { - ...options.field, - name: this._clusterSource.getAggKey(getAggType(styleProperty), options.field.name), - }, - }, - }; - } else { - clusterStyleDescriptor.properties[styleName] = { - type: StaticStyleProperty.type, - options: { ...options }, - }; - } - }); - this._clusterStyle = new VectorStyle(clusterStyleDescriptor, this._clusterSource, this); + destroy() { + if (this._documentSource) { + this._documentSource.destroy(); + } + if (this._clusterSource) { + this._clusterSource.destroy(); + } } isJoinable() { @@ -191,6 +196,7 @@ export class BlendedVectorLayer extends VectorLayer implements IVectorLayer { } async syncData(syncContext: unknown) { + // @ts-ignore const searchFilters = this._getSearchFilters(syncContext.dataFilters); const canSkipFetch = await canSkipSourceUpdate({ source: this.getSource(), diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.d.ts b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.d.ts index 48e90b6c41d51a..e6ab8c2919b2ba 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.d.ts +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.d.ts @@ -6,10 +6,13 @@ import { AbstractESAggSource } from '../es_agg_source'; import { ESGeoGridSourceDescriptor } from '../../../../common/descriptor_types'; -import { GRID_RESOLUTION } from '../../../../common/constants'; +import { GRID_RESOLUTION, RENDER_AS } from '../../../../common/constants'; export class ESGeoGridSource extends AbstractESAggSource { + static createDescriptor({ indexPatternId: string, geoField: string, requestType: RENDER_AS, resolution?: GRID_RESOLUTION }): ESGeoGridSourceDescriptor; + constructor(sourceDescriptor: ESGeoGridSourceDescriptor, inspectorAdapters: unknown); + getGridResolution(): GRID_RESOLUTION; getGeoGridPrecision(zoom: number): number; } diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_source.d.ts b/x-pack/legacy/plugins/maps/public/layers/sources/es_source.d.ts index 903f4f32fefda3..f411c58b2c36a9 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_source.d.ts +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_source.d.ts @@ -8,17 +8,28 @@ import { AbstractVectorSource } from './vector_source'; import { IVectorSource } from './vector_source'; import { IndexPattern } from '../../../../../../../src/plugins/data/public'; import { SearchSource } from '../../kibana_services'; +import { VectorLayerRequestMeta } from '../../../common/data_request_descriptor_types'; export interface IESSource extends IVectorSource { getIndexPattern(): Promise; + getIndexPatternId(): string; getGeoFieldName(): string; getMaxResultWindow(): Promise; - makeSearchSource(): Promise; + makeSearchSource( + searchFilters: VectorLayerRequestMeta, + limit: number, + initialSearchContext?: object + ): Promise; } export class AbstractESSource extends AbstractVectorSource implements IESSource { getIndexPattern(): Promise; + getIndexPatternId(): string; getGeoFieldName(): string; getMaxResultWindow(): Promise; - makeSearchSource(): Promise; + makeSearchSource( + searchFilters: VectorLayerRequestMeta, + limit: number, + initialSearchContext?: object + ): Promise; } diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/vector_source.d.ts b/x-pack/legacy/plugins/maps/public/layers/sources/vector_source.d.ts index 5fa8b28aa837b0..2074bbe9d46a8a 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/vector_source.d.ts +++ b/x-pack/legacy/plugins/maps/public/layers/sources/vector_source.d.ts @@ -7,13 +7,9 @@ import { AbstractSource, ISource } from './source'; import { IField } from '../fields/field'; +import { ESSearchSourceResponseMeta } from '../../../common/data_request_descriptor_types'; -export type GeoJsonFetchMeta = { - areResultsTrimmed: boolean; - areEntitiesTrimmed?: boolean; - entityCount?: number; - totalEntities?: number; -}; +export type GeoJsonFetchMeta = ESSearchSourceResponseMeta; export type GeoJsonWithMeta = { data: unknown; // geojson feature collection diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_style_property.d.ts b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_style_property.d.ts index 956681094953d1..25063944b88914 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_style_property.d.ts +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_style_property.d.ts @@ -7,13 +7,17 @@ import { IStyleProperty } from './style_property'; import { FIELD_ORIGIN } from '../../../../../common/constants'; -import { FieldMetaOptions } from '../../../../../common/style_property_descriptor_types'; +import { + FieldMetaOptions, + DynamicStylePropertyOptions, +} from '../../../../../common/style_property_descriptor_types'; import { IField } from '../../../fields/field'; import { IVectorLayer } from '../../../vector_layer'; import { IVectorSource } from '../../../sources/vector_source'; import { CategoryFieldMeta, RangeFieldMeta } from '../../../../../common/descriptor_types'; export interface IDynamicStyleProperty extends IStyleProperty { + getOptions(): DynamicStylePropertyOptions; getFieldMetaOptions(): FieldMetaOptions; getField(): IField | undefined; getFieldName(): string; diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.d.ts b/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.d.ts new file mode 100644 index 00000000000000..ac84a3b6447d2a --- /dev/null +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.d.ts @@ -0,0 +1,23 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { IStyleProperty } from './properties/style_property'; +import { IDynamicStyleProperty } from './properties/dynamic_style_property'; +import { IVectorLayer } from '../../vector_layer'; +import { IVectorSource } from '../../sources/vector_source'; + +export interface IVectorStyle { + getAllStyleProperties(): IStyleProperty[]; + getDescriptor(): object; + getDynamicPropertiesArray(): IDynamicStyleProperty[]; +} + +export class VectorStyle implements IVectorStyle { + constructor(descriptor: unknown, source: IVectorSource, layer: IVectorLayer); + + getAllStyleProperties(): IStyleProperty[]; + getDescriptor(): object; + getDynamicPropertiesArray(): IDynamicStyleProperty[]; +} diff --git a/x-pack/legacy/plugins/maps/public/layers/util/data_request.ts b/x-pack/legacy/plugins/maps/public/layers/util/data_request.ts index e318b1b23c9181..e361574194628b 100644 --- a/x-pack/legacy/plugins/maps/public/layers/util/data_request.ts +++ b/x-pack/legacy/plugins/maps/public/layers/util/data_request.ts @@ -6,7 +6,7 @@ /* eslint-disable max-classes-per-file */ import _ from 'lodash'; -import { DataRequestDescriptor } from '../../../common/descriptor_types'; +import { DataRequestDescriptor, DataMeta } from '../../../common/data_request_descriptor_types'; export class DataRequest { private readonly _descriptor: DataRequestDescriptor; @@ -17,7 +17,7 @@ export class DataRequest { }; } - getData(): object { + getData(): object | undefined { return this._descriptor.data; } @@ -25,7 +25,7 @@ export class DataRequest { return !!this._descriptor.dataRequestToken; } - getMeta(): object { + getMeta(): DataMeta { return this.hasData() ? _.get(this._descriptor, 'dataMeta', {}) : _.get(this._descriptor, 'dataMetaAtStart', {}); diff --git a/x-pack/legacy/plugins/maps/public/layers/vector_layer.d.ts b/x-pack/legacy/plugins/maps/public/layers/vector_layer.d.ts index 9922a087c7c5ee..312cbd8991d299 100644 --- a/x-pack/legacy/plugins/maps/public/layers/vector_layer.d.ts +++ b/x-pack/legacy/plugins/maps/public/layers/vector_layer.d.ts @@ -8,11 +8,14 @@ import { AbstractLayer } from './layer'; import { IVectorSource } from './sources/vector_source'; import { VectorLayerDescriptor } from '../../common/descriptor_types'; +import { MapFilters, VectorLayerRequestMeta } from '../../common/data_request_descriptor_types'; import { ILayer } from './layer'; import { IJoin } from './joins/join'; +import { IVectorStyle } from './styles/vector/vector_style'; type VectorLayerArguments = { source: IVectorSource; + joins: IJoin[]; layerDescriptor: VectorLayerDescriptor; }; @@ -21,8 +24,16 @@ export interface IVectorLayer extends ILayer { } export class VectorLayer extends AbstractLayer implements IVectorLayer { + static createDescriptor( + options: VectorLayerArguments, + mapColors: string[] + ): VectorLayerDescriptor; + + protected readonly _source: IVectorSource; + protected readonly _style: IVectorStyle; + constructor(options: VectorLayerArguments); getValidJoins(): IJoin[]; - _getSearchFilters(dataFilters: unknown): unknown; + _getSearchFilters(dataFilters: MapFilters): VectorLayerRequestMeta; } From 8a0e24fc2216bfd8419fdc71492975621cef678b Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Thu, 12 Mar 2020 14:39:53 -0600 Subject: [PATCH 14/27] last of the TS errors --- .../maps/common/data_request_descriptor_types.d.ts | 2 +- .../legacy/plugins/maps/common/descriptor_types.d.ts | 2 +- .../maps/public/layers/blended_vector_layer.ts | 9 +++++---- .../es_geo_grid_source/es_geo_grid_source.d.ts | 12 +++++++++++- .../maps/public/layers/sources/es_source.d.ts | 3 +-- .../plugins/maps/public/layers/tile_layer.test.ts | 8 ++++++++ 6 files changed, 27 insertions(+), 9 deletions(-) diff --git a/x-pack/legacy/plugins/maps/common/data_request_descriptor_types.d.ts b/x-pack/legacy/plugins/maps/common/data_request_descriptor_types.d.ts index 49be569e516f5b..81d0ae8adb0fca 100644 --- a/x-pack/legacy/plugins/maps/common/data_request_descriptor_types.d.ts +++ b/x-pack/legacy/plugins/maps/common/data_request_descriptor_types.d.ts @@ -34,7 +34,7 @@ export type ESSearchSourceResponseMeta = { totalEntities?: number; }; -export type DataMeta = VectorLayerRequestMeta & ESSearchSourceResponseMeta; +export type DataMeta = Partial & Partial; export type DataRequestDescriptor = { dataId: string; diff --git a/x-pack/legacy/plugins/maps/common/descriptor_types.d.ts b/x-pack/legacy/plugins/maps/common/descriptor_types.d.ts index ff62da18d2373a..1d0890db7cfe85 100644 --- a/x-pack/legacy/plugins/maps/common/descriptor_types.d.ts +++ b/x-pack/legacy/plugins/maps/common/descriptor_types.d.ts @@ -5,7 +5,7 @@ */ /* eslint-disable @typescript-eslint/consistent-type-definitions */ -import { DataRequestDescriptor } from 'data_request_descriptor_types'; +import { DataRequestDescriptor } from './data_request_descriptor_types'; import { AGG_TYPE, GRID_RESOLUTION, RENDER_AS, SORT_ORDER } from './constants'; export type AbstractSourceDescriptor = { diff --git a/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.ts b/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.ts index e5ed1538259ece..0dab97157284cf 100644 --- a/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.ts +++ b/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.ts @@ -92,8 +92,8 @@ function getClusterStyleDescriptor( return; } - const options = styleProperty.getOptions(); - if (styleProperty.isDynamic()) { + if (styleProperty.isDynamic() && styleProperty.isComplete()) { + const options = (styleProperty as IDynamicStyleProperty).getOptions(); clusterStyleDescriptor.properties[styleName] = { type: STYLE_TYPE.DYNAMIC, options: { @@ -102,6 +102,7 @@ function getClusterStyleDescriptor( ...options.field, name: clusterSource.getAggKey( getAggType(styleProperty as IDynamicStyleProperty), + // @ts-ignore styleProperty.isComplete() check ensures options.field.name exists options.field.name ), }, @@ -110,7 +111,7 @@ function getClusterStyleDescriptor( } else { clusterStyleDescriptor.properties[styleName] = { type: STYLE_TYPE.STATIC, - options: { ...options }, + options: { ...styleProperty.getOptions() }, }; } }); @@ -137,7 +138,7 @@ export class BlendedVectorLayer extends VectorLayer implements IVectorLayer { constructor(options: VectorLayerArguments) { super(options); - this._documentSource = this._source; // VectorLayer constructor sets _source as document source + this._documentSource = this._source as IESSource; // VectorLayer constructor sets _source as document source this._documentStyle = this._style; // VectorLayer constructor sets _style as document source this._clusterSource = getClusterSource(this._documentSource, this._documentStyle); diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.d.ts b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.d.ts index e6ab8c2919b2ba..3f596cea1ae393 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.d.ts +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.d.ts @@ -9,7 +9,17 @@ import { ESGeoGridSourceDescriptor } from '../../../../common/descriptor_types'; import { GRID_RESOLUTION, RENDER_AS } from '../../../../common/constants'; export class ESGeoGridSource extends AbstractESAggSource { - static createDescriptor({ indexPatternId: string, geoField: string, requestType: RENDER_AS, resolution?: GRID_RESOLUTION }): ESGeoGridSourceDescriptor; + static createDescriptor({ + indexPatternId, + geoField, + requestType, + resolution, + }: { + indexPatternId: string; + geoField: string; + requestType: RENDER_AS; + resolution?: GRID_RESOLUTION; + }): ESGeoGridSourceDescriptor; constructor(sourceDescriptor: ESGeoGridSourceDescriptor, inspectorAdapters: unknown); diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_source.d.ts b/x-pack/legacy/plugins/maps/public/layers/sources/es_source.d.ts index f411c58b2c36a9..695340ecd9b824 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_source.d.ts +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_source.d.ts @@ -6,8 +6,7 @@ import { AbstractVectorSource } from './vector_source'; import { IVectorSource } from './vector_source'; -import { IndexPattern } from '../../../../../../../src/plugins/data/public'; -import { SearchSource } from '../../kibana_services'; +import { IndexPattern, SearchSource } from '../../../../../../../src/plugins/data/public'; import { VectorLayerRequestMeta } from '../../../common/data_request_descriptor_types'; export interface IESSource extends IVectorSource { diff --git a/x-pack/legacy/plugins/maps/public/layers/tile_layer.test.ts b/x-pack/legacy/plugins/maps/public/layers/tile_layer.test.ts index 065fbd79d97895..0ec9385194cc09 100644 --- a/x-pack/legacy/plugins/maps/public/layers/tile_layer.test.ts +++ b/x-pack/legacy/plugins/maps/public/layers/tile_layer.test.ts @@ -32,6 +32,14 @@ class MockTileSource implements ITMSSource { async getUrlTemplate(): Promise { return 'template/{x}/{y}/{z}.png'; } + + destroy(): void { + // no-op + } + + getInspectorAdapters(): object { + return {}; + } } describe('TileLayer', () => { From 8db2894ef6eb6f1206c29e13fe2852c6af090c0a Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Fri, 13 Mar 2020 10:17:03 -0600 Subject: [PATCH 15/27] add migration to convert useTopTerm to scalingType --- .../plugins/maps/common/descriptor_types.d.ts | 18 +++++- .../maps/common/map_saved_object_types.d.ts | 26 +++++++++ .../common/migrations/scaling_type.test.ts | 56 +++++++++++++++++++ .../maps/common/migrations/scaling_type.ts | 45 +++++++++++++++ x-pack/legacy/plugins/maps/migrations.js | 6 +- .../server/maps_telemetry/maps_telemetry.ts | 33 ++--------- 6 files changed, 150 insertions(+), 34 deletions(-) create mode 100644 x-pack/legacy/plugins/maps/common/map_saved_object_types.d.ts create mode 100644 x-pack/legacy/plugins/maps/common/migrations/scaling_type.test.ts create mode 100644 x-pack/legacy/plugins/maps/common/migrations/scaling_type.ts diff --git a/x-pack/legacy/plugins/maps/common/descriptor_types.d.ts b/x-pack/legacy/plugins/maps/common/descriptor_types.d.ts index 1d0890db7cfe85..fdb19b8f16564d 100644 --- a/x-pack/legacy/plugins/maps/common/descriptor_types.d.ts +++ b/x-pack/legacy/plugins/maps/common/descriptor_types.d.ts @@ -6,7 +6,7 @@ /* eslint-disable @typescript-eslint/consistent-type-definitions */ import { DataRequestDescriptor } from './data_request_descriptor_types'; -import { AGG_TYPE, GRID_RESOLUTION, RENDER_AS, SORT_ORDER } from './constants'; +import { AGG_TYPE, GRID_RESOLUTION, RENDER_AS, SORT_ORDER, SCALING_TYPES } from './constants'; export type AbstractSourceDescriptor = { id?: string; @@ -50,7 +50,7 @@ export type ESSearchSourceDescriptor = AbstractESSourceDescriptor & { tooltipProperties?: string[]; sortField?: string; sortOrder?: SORT_ORDER; - useTopHits?: boolean; + scalingType?: SCALING_TYPES; topHitsSplitField?: string; topHitsSize?: number; }; @@ -89,6 +89,18 @@ export type XYZTMSSourceDescriptor = { urlTemplate: string; }; +export type SourceDescriptor = + | EMSTMSSourceDescriptor + | EMSFileSourceDescriptor + | ESGeoGridSourceDescriptor + | ESSearchSourceDescriptor + | ESPewPewSourceDescriptor + | ESTermSourceDescriptor + | KibanaRegionmapSourceDescriptor + | KibanaTilemapSourceDescriptor + | WMSSourceDescriptor + | XYZTMSSourceDescriptor; + export type JoinDescriptor = { leftField: string; right: ESTermSourceDescriptor; @@ -103,7 +115,7 @@ export type LayerDescriptor = { label?: string; minZoom?: number; maxZoom?: number; - sourceDescriptor: AbstractSourceDescriptor; + sourceDescriptor: SourceDescriptor; type?: string; visible?: boolean; }; diff --git a/x-pack/legacy/plugins/maps/common/map_saved_object_types.d.ts b/x-pack/legacy/plugins/maps/common/map_saved_object_types.d.ts new file mode 100644 index 00000000000000..aa94088c0a54b0 --- /dev/null +++ b/x-pack/legacy/plugins/maps/common/map_saved_object_types.d.ts @@ -0,0 +1,26 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +/* eslint-disable @typescript-eslint/consistent-type-definitions */ + +export type MapSavedObjectAttributes = { + title?: string; + description?: string; + mapStateJSON?: string; + layerListJSON?: string; + uiStateJSON?: string; + bounds?: { + type?: string; + coordinates?: []; + }; +}; + +export type MapSavedObject = { + [key: string]: any; + title: string; + id?: string; + type?: string; + attributes?: MapSavedObjectAttributes; +}; diff --git a/x-pack/legacy/plugins/maps/common/migrations/scaling_type.test.ts b/x-pack/legacy/plugins/maps/common/migrations/scaling_type.test.ts new file mode 100644 index 00000000000000..9c64837cf3a141 --- /dev/null +++ b/x-pack/legacy/plugins/maps/common/migrations/scaling_type.test.ts @@ -0,0 +1,56 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { migrateUseTopHitsToScalingType } from './scaling_type'; + +describe('migrateUseTopHitsToScalingType', () => { + test('Should handle missing layerListJSON attribute', () => { + const attributes = { + title: 'my map', + }; + expect(migrateUseTopHitsToScalingType({ attributes })).toEqual({ + title: 'my map', + }); + }); + + test('Should migrate useTopHits: true to scalingType TOP_HITS for ES documents sources', () => { + const layerListJSON = JSON.stringify([ + { + sourceDescriptor: { + type: 'ES_SEARCH', + useTopHits: true, + }, + }, + ]); + const attributes = { + title: 'my map', + layerListJSON, + }; + expect(migrateUseTopHitsToScalingType({ attributes })).toEqual({ + title: 'my map', + layerListJSON: '[{"sourceDescriptor":{"type":"ES_SEARCH","scalingType":"TOP_HITS"}}]', + }); + }); + + test('Should migrate useTopHits: false to scalingType LIMIT for ES documents sources', () => { + const layerListJSON = JSON.stringify([ + { + sourceDescriptor: { + type: 'ES_SEARCH', + useTopHits: false, + }, + }, + ]); + const attributes = { + title: 'my map', + layerListJSON, + }; + expect(migrateUseTopHitsToScalingType({ attributes })).toEqual({ + title: 'my map', + layerListJSON: '[{"sourceDescriptor":{"type":"ES_SEARCH","scalingType":"LIMIT"}}]', + }); + }); +}); diff --git a/x-pack/legacy/plugins/maps/common/migrations/scaling_type.ts b/x-pack/legacy/plugins/maps/common/migrations/scaling_type.ts new file mode 100644 index 00000000000000..561e0a8f65d266 --- /dev/null +++ b/x-pack/legacy/plugins/maps/common/migrations/scaling_type.ts @@ -0,0 +1,45 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import _ from 'lodash'; +import { ES_SEARCH, SCALING_TYPES } from '../constants'; +import { LayerDescriptor } from '../descriptor_types'; +import { MapSavedObject } from '../map_saved_object_types'; + +function isEsDocumentSource(layerDescriptor: LayerDescriptor) { + const sourceType = _.get(layerDescriptor, 'sourceDescriptor.type'); + return sourceType === ES_SEARCH; +} + +export function migrateUseTopHitsToScalingType({ attributes }: Partial) { + if (!attributes || !attributes.layerListJSON) { + return attributes; + } + + const layerList: LayerDescriptor[] = JSON.parse(attributes.layerListJSON); + layerList.forEach((layerDescriptor: LayerDescriptor) => { + if (isEsDocumentSource(layerDescriptor)) { + if (_.has(layerDescriptor, 'sourceDescriptor.useTopHits')) { + // @ts-ignore TS is too stupid to figure out that scalingType is available on sourceDescriptor + layerDescriptor.sourceDescriptor.scalingType = _.get( + layerDescriptor, + 'sourceDescriptor.useTopHits', + false + ) + ? SCALING_TYPES.TOP_HITS + : SCALING_TYPES.LIMIT; + // @ts-ignore useTopHits no longer in type definition but that does not mean its not in live data + // hence the entire point of this method + delete layerDescriptor.sourceDescriptor.useTopHits; + } + } + }); + + return { + ...attributes, + layerListJSON: JSON.stringify(layerList), + }; +} diff --git a/x-pack/legacy/plugins/maps/migrations.js b/x-pack/legacy/plugins/maps/migrations.js index 9622f6ba63fac5..6a1f5bc937497b 100644 --- a/x-pack/legacy/plugins/maps/migrations.js +++ b/x-pack/legacy/plugins/maps/migrations.js @@ -10,6 +10,7 @@ import { topHitsTimeToSort } from './common/migrations/top_hits_time_to_sort'; import { moveApplyGlobalQueryToSources } from './common/migrations/move_apply_global_query'; import { addFieldMetaOptions } from './common/migrations/add_field_meta_options'; import { migrateSymbolStyleDescriptor } from './common/migrations/migrate_symbol_style_descriptor'; +import { migrateUseTopHitsToScalingType } from './common/migrations/scaling_type'; export const migrations = { map: { @@ -48,11 +49,12 @@ export const migrations = { }; }, '7.7.0': doc => { - const attributes = migrateSymbolStyleDescriptor(doc); + const attributesPhase1 = migrateSymbolStyleDescriptor(doc); + const attributesPhase2 = migrateUseTopHitsToScalingType({ attributes: attributesPhase1 }); return { ...doc, - attributes, + attributes: attributesPhase2, }; }, }, diff --git a/x-pack/legacy/plugins/maps/server/maps_telemetry/maps_telemetry.ts b/x-pack/legacy/plugins/maps/server/maps_telemetry/maps_telemetry.ts index 3ce46e2955f50c..821abb953ed85d 100644 --- a/x-pack/legacy/plugins/maps/server/maps_telemetry/maps_telemetry.ts +++ b/x-pack/legacy/plugins/maps/server/maps_telemetry/maps_telemetry.ts @@ -19,6 +19,7 @@ import { // @ts-ignore } from '../../common/constants'; import { LayerDescriptor } from '../../common/descriptor_types'; +import { MapSavedObject } from '../../common/map_saved_object_types'; interface IStats { [key: string]: { @@ -32,33 +33,6 @@ interface ILayerTypeCount { [key: string]: number; } -interface IMapSavedObject { - [key: string]: any; - fields: IFieldType[]; - title: string; - id?: string; - type?: string; - timeFieldName?: string; - fieldFormatMap?: Record< - string, - { - id: string; - params: unknown; - } - >; - attributes?: { - title?: string; - description?: string; - mapStateJSON?: string; - layerListJSON?: string; - uiStateJSON?: string; - bounds?: { - type?: string; - coordinates?: []; - }; - }; -} - function getUniqueLayerCounts(layerCountsList: ILayerTypeCount[], mapsCount: number) { const uniqueLayerTypes = _.uniq(_.flatten(layerCountsList.map(lTypes => Object.keys(lTypes)))); @@ -102,7 +76,7 @@ export function buildMapsTelemetry({ indexPatternSavedObjects, settings, }: { - mapSavedObjects: IMapSavedObject[]; + mapSavedObjects: MapSavedObject[]; indexPatternSavedObjects: IIndexPattern[]; settings: SavedObjectAttribute; }): SavedObjectAttributes { @@ -114,6 +88,7 @@ export function buildMapsTelemetry({ const mapsCount = layerLists.length; const dataSourcesCount = layerLists.map(lList => { + // @ts-ignore const sourceIdList = lList.map((layer: LayerDescriptor) => layer.sourceDescriptor.id); return _.uniq(sourceIdList).length; }); @@ -183,7 +158,7 @@ export async function getMapsTelemetry( savedObjectsClient: SavedObjectsClientContract, config: Function ) { - const mapSavedObjects: IMapSavedObject[] = await getMapSavedObjects(savedObjectsClient); + const mapSavedObjects: MapSavedObject[] = await getMapSavedObjects(savedObjectsClient); const indexPatternSavedObjects: IIndexPattern[] = await getIndexPatternSavedObjects( savedObjectsClient ); From 9d6faa9406fd110027ad4c0122fb678f5dc218a4 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Fri, 13 Mar 2020 14:06:47 -0600 Subject: [PATCH 16/27] clean up --- .../public/layers/blended_vector_layer.ts | 21 +++++++++++-------- .../plugins/maps/public/layers/layer.js | 4 ---- .../vector/components/vector_style_editor.js | 2 +- .../maps/public/layers/vector_layer.d.ts | 5 +++++ .../maps/public/layers/vector_layer.js | 5 +++++ 5 files changed, 23 insertions(+), 14 deletions(-) diff --git a/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.ts b/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.ts index 0dab97157284cf..1fcca04d2f94d2 100644 --- a/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.ts +++ b/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.ts @@ -92,20 +92,23 @@ function getClusterStyleDescriptor( return; } - if (styleProperty.isDynamic() && styleProperty.isComplete()) { + if (styleProperty.isDynamic()) { const options = (styleProperty as IDynamicStyleProperty).getOptions(); + const field = + options && options.field && options.field.name + ? { + ...options.field, + name: clusterSource.getAggKey( + getAggType(styleProperty as IDynamicStyleProperty), + options.field.name + ), + } + : undefined; clusterStyleDescriptor.properties[styleName] = { type: STYLE_TYPE.DYNAMIC, options: { ...options, - field: { - ...options.field, - name: clusterSource.getAggKey( - getAggType(styleProperty as IDynamicStyleProperty), - // @ts-ignore styleProperty.isComplete() check ensures options.field.name exists - options.field.name - ), - }, + field, }, }; } else { diff --git a/x-pack/legacy/plugins/maps/public/layers/layer.js b/x-pack/legacy/plugins/maps/public/layers/layer.js index 13da7fbff56d76..50f074f2400310 100644 --- a/x-pack/legacy/plugins/maps/public/layers/layer.js +++ b/x-pack/legacy/plugins/maps/public/layers/layer.js @@ -342,10 +342,6 @@ export class AbstractLayer { return []; } - async getFields() { - return []; - } - syncVisibilityWithMb(mbMap, mbLayerId) { mbMap.setLayoutProperty(mbLayerId, 'visibility', this.isVisible() ? 'visible' : 'none'); } diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector_style_editor.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector_style_editor.js index 8e05cf287efa62..acc26e5fce6996 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector_style_editor.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector_style_editor.js @@ -69,7 +69,7 @@ export class VectorStyleEditor extends Component { }; //These are all fields (only used for text labeling) - const fields = await this.props.layer.getFields(); + const fields = await this.props.layer.getStyleEditorFields(); const fieldPromises = fields.map(getFieldMeta); const fieldsArrayAll = await Promise.all(fieldPromises); if (!this._isMounted || _.isEqual(fieldsArrayAll, this.state.fields)) { diff --git a/x-pack/legacy/plugins/maps/public/layers/vector_layer.d.ts b/x-pack/legacy/plugins/maps/public/layers/vector_layer.d.ts index 312cbd8991d299..c587e678fb6ac1 100644 --- a/x-pack/legacy/plugins/maps/public/layers/vector_layer.d.ts +++ b/x-pack/legacy/plugins/maps/public/layers/vector_layer.d.ts @@ -12,6 +12,7 @@ import { MapFilters, VectorLayerRequestMeta } from '../../common/data_request_de import { ILayer } from './layer'; import { IJoin } from './joins/join'; import { IVectorStyle } from './styles/vector/vector_style'; +import { IField } from './fields/field'; type VectorLayerArguments = { source: IVectorSource; @@ -20,6 +21,8 @@ type VectorLayerArguments = { }; export interface IVectorLayer extends ILayer { + getFields(): Promise; + getStyleEditorFields(): Promise; getValidJoins(): IJoin[]; } @@ -34,6 +37,8 @@ export class VectorLayer extends AbstractLayer implements IVectorLayer { constructor(options: VectorLayerArguments); + getFields(): Promise; + getStyleEditorFields(): Promise; getValidJoins(): IJoin[]; _getSearchFilters(dataFilters: MapFilters): VectorLayerRequestMeta; } diff --git a/x-pack/legacy/plugins/maps/public/layers/vector_layer.js b/x-pack/legacy/plugins/maps/public/layers/vector_layer.js index 6dbf6039753863..7ca33f7163699c 100644 --- a/x-pack/legacy/plugins/maps/public/layers/vector_layer.js +++ b/x-pack/legacy/plugins/maps/public/layers/vector_layer.js @@ -203,6 +203,11 @@ export class VectorLayer extends AbstractLayer { return [...sourceFields, ...this._getJoinFields()]; } + async getStyleEditorFields() { + const sourceFields = await this.getSourceForEditing().getFields(); + return [...sourceFields, ...this._getJoinFields()]; + } + getIndexPatternIds() { const indexPatternIds = this.getSource().getIndexPatternIds(); this.getValidJoins().forEach(join => { From ff8129b21063a9263028ab1a6130c03a2c932579 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Fri, 13 Mar 2020 14:37:32 -0600 Subject: [PATCH 17/27] remove MapSavedObject work since its in a seperate PR now --- .../plugins/maps/common/descriptor_types.d.ts | 14 +------- .../maps/common/map_saved_object_types.d.ts | 26 --------------- .../maps/common/migrations/scaling_type.ts | 19 +++++------ .../server/maps_telemetry/maps_telemetry.ts | 33 ++++++++++++++++--- 4 files changed, 39 insertions(+), 53 deletions(-) delete mode 100644 x-pack/legacy/plugins/maps/common/map_saved_object_types.d.ts diff --git a/x-pack/legacy/plugins/maps/common/descriptor_types.d.ts b/x-pack/legacy/plugins/maps/common/descriptor_types.d.ts index fdb19b8f16564d..d7849d09a21f7e 100644 --- a/x-pack/legacy/plugins/maps/common/descriptor_types.d.ts +++ b/x-pack/legacy/plugins/maps/common/descriptor_types.d.ts @@ -89,18 +89,6 @@ export type XYZTMSSourceDescriptor = { urlTemplate: string; }; -export type SourceDescriptor = - | EMSTMSSourceDescriptor - | EMSFileSourceDescriptor - | ESGeoGridSourceDescriptor - | ESSearchSourceDescriptor - | ESPewPewSourceDescriptor - | ESTermSourceDescriptor - | KibanaRegionmapSourceDescriptor - | KibanaTilemapSourceDescriptor - | WMSSourceDescriptor - | XYZTMSSourceDescriptor; - export type JoinDescriptor = { leftField: string; right: ESTermSourceDescriptor; @@ -115,7 +103,7 @@ export type LayerDescriptor = { label?: string; minZoom?: number; maxZoom?: number; - sourceDescriptor: SourceDescriptor; + sourceDescriptor: AbstractSourceDescriptor; type?: string; visible?: boolean; }; diff --git a/x-pack/legacy/plugins/maps/common/map_saved_object_types.d.ts b/x-pack/legacy/plugins/maps/common/map_saved_object_types.d.ts deleted file mode 100644 index aa94088c0a54b0..00000000000000 --- a/x-pack/legacy/plugins/maps/common/map_saved_object_types.d.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -/* eslint-disable @typescript-eslint/consistent-type-definitions */ - -export type MapSavedObjectAttributes = { - title?: string; - description?: string; - mapStateJSON?: string; - layerListJSON?: string; - uiStateJSON?: string; - bounds?: { - type?: string; - coordinates?: []; - }; -}; - -export type MapSavedObject = { - [key: string]: any; - title: string; - id?: string; - type?: string; - attributes?: MapSavedObjectAttributes; -}; diff --git a/x-pack/legacy/plugins/maps/common/migrations/scaling_type.ts b/x-pack/legacy/plugins/maps/common/migrations/scaling_type.ts index 561e0a8f65d266..fc71970e53cb2f 100644 --- a/x-pack/legacy/plugins/maps/common/migrations/scaling_type.ts +++ b/x-pack/legacy/plugins/maps/common/migrations/scaling_type.ts @@ -6,15 +6,18 @@ import _ from 'lodash'; import { ES_SEARCH, SCALING_TYPES } from '../constants'; -import { LayerDescriptor } from '../descriptor_types'; -import { MapSavedObject } from '../map_saved_object_types'; +import { LayerDescriptor, ESSearchSourceDescriptor } from '../descriptor_types'; function isEsDocumentSource(layerDescriptor: LayerDescriptor) { const sourceType = _.get(layerDescriptor, 'sourceDescriptor.type'); return sourceType === ES_SEARCH; } -export function migrateUseTopHitsToScalingType({ attributes }: Partial) { +export function migrateUseTopHitsToScalingType({ + attributes, +}: { + attributes: { layerListJSON?: string; title?: string }; +}) { if (!attributes || !attributes.layerListJSON) { return attributes; } @@ -23,17 +26,13 @@ export function migrateUseTopHitsToScalingType({ attributes }: Partial { if (isEsDocumentSource(layerDescriptor)) { if (_.has(layerDescriptor, 'sourceDescriptor.useTopHits')) { - // @ts-ignore TS is too stupid to figure out that scalingType is available on sourceDescriptor - layerDescriptor.sourceDescriptor.scalingType = _.get( - layerDescriptor, - 'sourceDescriptor.useTopHits', - false - ) + const sourceDescriptor = layerDescriptor.sourceDescriptor as ESSearchSourceDescriptor; + sourceDescriptor.scalingType = _.get(layerDescriptor, 'sourceDescriptor.useTopHits', false) ? SCALING_TYPES.TOP_HITS : SCALING_TYPES.LIMIT; // @ts-ignore useTopHits no longer in type definition but that does not mean its not in live data // hence the entire point of this method - delete layerDescriptor.sourceDescriptor.useTopHits; + delete sourceDescriptor.useTopHits; } } }); diff --git a/x-pack/legacy/plugins/maps/server/maps_telemetry/maps_telemetry.ts b/x-pack/legacy/plugins/maps/server/maps_telemetry/maps_telemetry.ts index 821abb953ed85d..3ce46e2955f50c 100644 --- a/x-pack/legacy/plugins/maps/server/maps_telemetry/maps_telemetry.ts +++ b/x-pack/legacy/plugins/maps/server/maps_telemetry/maps_telemetry.ts @@ -19,7 +19,6 @@ import { // @ts-ignore } from '../../common/constants'; import { LayerDescriptor } from '../../common/descriptor_types'; -import { MapSavedObject } from '../../common/map_saved_object_types'; interface IStats { [key: string]: { @@ -33,6 +32,33 @@ interface ILayerTypeCount { [key: string]: number; } +interface IMapSavedObject { + [key: string]: any; + fields: IFieldType[]; + title: string; + id?: string; + type?: string; + timeFieldName?: string; + fieldFormatMap?: Record< + string, + { + id: string; + params: unknown; + } + >; + attributes?: { + title?: string; + description?: string; + mapStateJSON?: string; + layerListJSON?: string; + uiStateJSON?: string; + bounds?: { + type?: string; + coordinates?: []; + }; + }; +} + function getUniqueLayerCounts(layerCountsList: ILayerTypeCount[], mapsCount: number) { const uniqueLayerTypes = _.uniq(_.flatten(layerCountsList.map(lTypes => Object.keys(lTypes)))); @@ -76,7 +102,7 @@ export function buildMapsTelemetry({ indexPatternSavedObjects, settings, }: { - mapSavedObjects: MapSavedObject[]; + mapSavedObjects: IMapSavedObject[]; indexPatternSavedObjects: IIndexPattern[]; settings: SavedObjectAttribute; }): SavedObjectAttributes { @@ -88,7 +114,6 @@ export function buildMapsTelemetry({ const mapsCount = layerLists.length; const dataSourcesCount = layerLists.map(lList => { - // @ts-ignore const sourceIdList = lList.map((layer: LayerDescriptor) => layer.sourceDescriptor.id); return _.uniq(sourceIdList).length; }); @@ -158,7 +183,7 @@ export async function getMapsTelemetry( savedObjectsClient: SavedObjectsClientContract, config: Function ) { - const mapSavedObjects: MapSavedObject[] = await getMapSavedObjects(savedObjectsClient); + const mapSavedObjects: IMapSavedObject[] = await getMapSavedObjects(savedObjectsClient); const indexPatternSavedObjects: IIndexPattern[] = await getIndexPatternSavedObjects( savedObjectsClient ); From 08b0fb490d4599bf8097463642a405eaed4f8978 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Sat, 14 Mar 2020 06:57:58 -0600 Subject: [PATCH 18/27] fix EsSearchSource update editor jest test --- .../update_source_editor.test.js.snap | 159 ++++++++++++++++-- .../update_source_editor.test.js | 9 +- 2 files changed, 147 insertions(+), 21 deletions(-) diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/__snapshots__/update_source_editor.test.js.snap b/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/__snapshots__/update_source_editor.test.js.snap index 80368fd5d5e3eb..c94f305773f359 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/__snapshots__/update_source_editor.test.js.snap +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/__snapshots__/update_source_editor.test.js.snap @@ -86,22 +86,62 @@ exports[`should enable sort order select when sort field provided 1`] = ` value="DESC" /> - + + + +
+ +
+
+ + + + @@ -112,7 +152,7 @@ exports[`should enable sort order select when sort field provided 1`] = `
`; -exports[`should render top hits form when useTopHits is true 1`] = ` +exports[`should render top hits form when scaling type is TOP_HITS 1`] = ` - + + + +
+ +
+
+ + + + + - + + + +
+ +
+
+ + + + diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/update_source_editor.test.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/update_source_editor.test.js index badfba7665dfdd..e8a845c4b16696 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/update_source_editor.test.js +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/update_source_editor.test.js @@ -16,6 +16,7 @@ import React from 'react'; import { shallow } from 'enzyme'; import { UpdateSourceEditor } from './update_source_editor'; +import { SCALING_TYPES } from '../../../../common/constants'; const defaultProps = { indexPatternId: 'indexPattern1', @@ -23,7 +24,7 @@ const defaultProps = { filterByMapBounds: true, tooltipFields: [], sortOrder: 'DESC', - useTopHits: false, + scalingType: SCALING_TYPES.LIMIT, topHitsSplitField: 'trackId', topHitsSize: 1, }; @@ -40,8 +41,10 @@ test('should enable sort order select when sort field provided', async () => { expect(component).toMatchSnapshot(); }); -test('should render top hits form when useTopHits is true', async () => { - const component = shallow(); +test('should render top hits form when scaling type is TOP_HITS', async () => { + const component = shallow( + + ); expect(component).toMatchSnapshot(); }); From 56ef68555926f8bfab9bd47e76aa3b1572b2e838 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Sat, 14 Mar 2020 08:44:13 -0600 Subject: [PATCH 19/27] fix map_selector jest test --- .../legacy/plugins/maps/public/selectors/map_selectors.test.js | 1 + 1 file changed, 1 insertion(+) diff --git a/x-pack/legacy/plugins/maps/public/selectors/map_selectors.test.js b/x-pack/legacy/plugins/maps/public/selectors/map_selectors.test.js index 5ec40a57ebc7f4..ef2e23e51a0924 100644 --- a/x-pack/legacy/plugins/maps/public/selectors/map_selectors.test.js +++ b/x-pack/legacy/plugins/maps/public/selectors/map_selectors.test.js @@ -5,6 +5,7 @@ */ jest.mock('../layers/vector_layer', () => {}); +jest.mock('../layers/blended_vector_layer', () => {}); jest.mock('../layers/heatmap_layer', () => {}); jest.mock('../layers/vector_tile_layer', () => {}); jest.mock('../layers/sources/all_sources', () => {}); From 11615d092223fe7164c34317041fddf66c666060 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Tue, 17 Mar 2020 10:03:03 -0600 Subject: [PATCH 20/27] move mutable state out of BlendedVectorLayer --- .../public/layers/blended_vector_layer.ts | 36 +++--- .../plugins/maps/public/layers/layer.d.ts | 6 +- .../plugins/maps/public/layers/layer.js | 7 +- .../properties/dynamic_color_property.test.js | 2 +- .../properties/dynamic_style_property.js | 4 +- .../layers/styles/vector/vector_style.js | 2 +- .../maps/public/layers/vector_layer.d.ts | 7 +- .../maps/public/layers/vector_layer.js | 118 ++++++++++-------- 8 files changed, 106 insertions(+), 76 deletions(-) diff --git a/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.ts b/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.ts index 1fcca04d2f94d2..abafffc6f8b5cb 100644 --- a/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.ts +++ b/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.ts @@ -131,8 +131,7 @@ export class BlendedVectorLayer extends VectorLayer implements IVectorLayer { return layerDescriptor; } - private _activeSource: IESSource; - private _activeStyle: IVectorStyle; + private readonly _isClustered: boolean; private readonly _clusterSource: IESAggSource; private readonly _clusterStyle: IVectorStyle; private readonly _documentSource: IESSource; @@ -151,16 +150,15 @@ export class BlendedVectorLayer extends VectorLayer implements IVectorLayer { ); this._clusterStyle = new VectorStyle(clusterStyleDescriptor, this._clusterSource, this); - this._activeSource = this._documentSource; - this._activeStyle = this._documentStyle; + let isClustered = false; const sourceDataRequest = this.getSourceDataRequest(); if (sourceDataRequest) { const requestMeta = sourceDataRequest.getMeta(); if (requestMeta && requestMeta.sourceType && requestMeta.sourceType === ES_GEO_GRID) { - this._activeSource = this._clusterSource; - this._activeStyle = this._clusterStyle; + isClustered = true; } } + this._isClustered = isClustered; } destroy() { @@ -181,7 +179,7 @@ export class BlendedVectorLayer extends VectorLayer implements IVectorLayer { } getSource() { - return this._activeSource; + return this._isClustered ? this._clusterSource : this._documentSource; } getSourceForEditing() { @@ -192,7 +190,7 @@ export class BlendedVectorLayer extends VectorLayer implements IVectorLayer { } getCurrentStyle() { - return this._activeStyle; + return this._isClustered ? this._clusterStyle : this._documentStyle; } getStyleForEditing() { @@ -201,27 +199,33 @@ export class BlendedVectorLayer extends VectorLayer implements IVectorLayer { async syncData(syncContext: unknown) { // @ts-ignore - const searchFilters = this._getSearchFilters(syncContext.dataFilters); + const searchFilters = this._getSearchFilters( + syncContext.dataFilters, + this.getSource(), + this.getCurrentStyle() + ); const canSkipFetch = await canSkipSourceUpdate({ source: this.getSource(), prevDataRequest: this.getSourceDataRequest(), nextMeta: searchFilters, }); + + let activeSource = this.getSource(); + let activeStyle = this.getCurrentStyle(); if (!canSkipFetch) { const searchSource = await this._documentSource.makeSearchSource(searchFilters, 0); const resp = await searchSource.fetch(); const maxResultWindow = await this._documentSource.getMaxResultWindow(); + if (resp.hits.total > maxResultWindow) { - this._activeSource = this._clusterSource; - this._activeStyle = this._clusterStyle; + activeSource = this._clusterSource; + activeStyle = this._clusterStyle; } else { - this._activeSource = this._documentSource; - this._activeStyle = this._documentStyle; + activeSource = this._documentSource; + activeStyle = this._documentStyle; } } - super.syncData(syncContext); + super._syncData(syncContext, activeSource, activeStyle); } - - /* syncLayerWithMB(mbMap) {}*/ } diff --git a/x-pack/legacy/plugins/maps/public/layers/layer.d.ts b/x-pack/legacy/plugins/maps/public/layers/layer.d.ts index 6ab09cd4d98562..bc32d8a9ddf21f 100644 --- a/x-pack/legacy/plugins/maps/public/layers/layer.d.ts +++ b/x-pack/legacy/plugins/maps/public/layers/layer.d.ts @@ -8,7 +8,8 @@ import { ISource } from './sources/source'; import { DataRequest } from './util/data_request'; export interface ILayer { - getDisplayName(): Promise; + getDataRequest(id: string): DataRequest | undefined; + getDisplayName(source?: ISource): Promise; getSourceDataRequest(): DataRequest | undefined; getSource(): ISource; getSourceForEditing(): ISource; @@ -22,7 +23,8 @@ export interface ILayerArguments { export class AbstractLayer implements ILayer { constructor(layerArguments: ILayerArguments); - getDisplayName(): Promise; + getDataRequest(id: string): DataRequest | undefined; + getDisplayName(source?: ISource): Promise; getSourceDataRequest(): DataRequest | undefined; getSource(): ISource; getSourceForEditing(): ISource; diff --git a/x-pack/legacy/plugins/maps/public/layers/layer.js b/x-pack/legacy/plugins/maps/public/layers/layer.js index 50f074f2400310..eadece23eb701e 100644 --- a/x-pack/legacy/plugins/maps/public/layers/layer.js +++ b/x-pack/legacy/plugins/maps/public/layers/layer.js @@ -89,12 +89,15 @@ export class AbstractLayer { return await this.getSource().supportsFitToBounds(); } - async getDisplayName() { + async getDisplayName(source) { if (this._descriptor.label) { return this._descriptor.label; } - return (await this.getSource().getDisplayName()) || `Layer ${this._descriptor.id}`; + const sourceDisplayName = source + ? await source.getDisplayName() + : await this.getSource().getDisplayName(); + return sourceDisplayName || `Layer ${this._descriptor.id}`; } async getAttributions() { diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_color_property.test.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_color_property.test.js index f74deb17fff7c8..5b5028f68f08cf 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_color_property.test.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_color_property.test.js @@ -71,7 +71,7 @@ class MockLayer { return new MockStyle(); } - findDataRequestById() { + getDataRequest() { return null; } } diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_style_property.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_style_property.js index 030d3a2a1ef87c..68e06bacfa7b7d 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_style_property.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_style_property.js @@ -62,7 +62,7 @@ export class DynamicStyleProperty extends AbstractStyleProperty { return rangeFieldMetaFromLocalFeatures; } - const styleMetaDataRequest = this._layer.findDataRequestById(dataRequestId); + const styleMetaDataRequest = this._layer.getDataRequest(dataRequestId); if (!styleMetaDataRequest || !styleMetaDataRequest.hasData()) { return rangeFieldMetaFromLocalFeatures; } @@ -87,7 +87,7 @@ export class DynamicStyleProperty extends AbstractStyleProperty { return categoryFieldMetaFromLocalFeatures; } - const styleMetaDataRequest = this._layer.findDataRequestById(dataRequestId); + const styleMetaDataRequest = this._layer.getDataRequest(dataRequestId); if (!styleMetaDataRequest || !styleMetaDataRequest.hasData()) { return categoryFieldMetaFromLocalFeatures; } diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.js index 96ed2d163461e6..6ad60e15f10e16 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.js @@ -390,7 +390,7 @@ export class VectorStyle extends AbstractStyle { return null; } - const formattersDataRequest = this._layer.findDataRequestById(dataRequestId); + const formattersDataRequest = this._layer.getDataRequest(dataRequestId); if (!formattersDataRequest || !formattersDataRequest.hasData()) { return null; } diff --git a/x-pack/legacy/plugins/maps/public/layers/vector_layer.d.ts b/x-pack/legacy/plugins/maps/public/layers/vector_layer.d.ts index c587e678fb6ac1..afe392bfd93a5d 100644 --- a/x-pack/legacy/plugins/maps/public/layers/vector_layer.d.ts +++ b/x-pack/legacy/plugins/maps/public/layers/vector_layer.d.ts @@ -40,5 +40,10 @@ export class VectorLayer extends AbstractLayer implements IVectorLayer { getFields(): Promise; getStyleEditorFields(): Promise; getValidJoins(): IJoin[]; - _getSearchFilters(dataFilters: MapFilters): VectorLayerRequestMeta; + _getSearchFilters( + dataFilters: MapFilters, + source: IVectorSource, + style: IVectorStyle + ): VectorLayerRequestMeta; + _syncData(syncContext: unknown, source: IVectorSource, style: IVectorStyle): Promise; } diff --git a/x-pack/legacy/plugins/maps/public/layers/vector_layer.js b/x-pack/legacy/plugins/maps/public/layers/vector_layer.js index 7ca33f7163699c..102828f361bb44 100644 --- a/x-pack/legacy/plugins/maps/public/layers/vector_layer.js +++ b/x-pack/legacy/plugins/maps/public/layers/vector_layer.js @@ -181,7 +181,11 @@ export class VectorLayer extends AbstractLayer { return this._getBoundsBasedOnData(); } - const searchFilters = this._getSearchFilters(dataFilters); + const searchFilters = this._getSearchFilters( + dataFilters, + this.getSource(), + this.getCurrentStyle() + ); return await this.getSource().getBoundsForFilters(searchFilters); } @@ -224,10 +228,6 @@ export class VectorLayer extends AbstractLayer { return indexPatternIds; } - findDataRequestById(sourceDataId) { - return this._dataRequests.find(dataRequest => dataRequest.getDataId() === sourceDataId); - } - async _syncJoin({ join, startLoading, @@ -245,7 +245,7 @@ export class VectorLayer extends AbstractLayer { sourceQuery: joinSource.getWhereQuery(), applyGlobalQuery: joinSource.getApplyGlobalQuery(), }; - const prevDataRequest = this.findDataRequestById(sourceDataId); + const prevDataRequest = this.getDataRequest(sourceDataId); const canSkipFetch = await canSkipSourceUpdate({ source: joinSource, @@ -287,30 +287,30 @@ export class VectorLayer extends AbstractLayer { } } - async _syncJoins(syncContext) { + async _syncJoins(syncContext, style) { const joinSyncs = this.getValidJoins().map(async join => { - await this._syncJoinStyleMeta(syncContext, join); - await this._syncJoinFormatters(syncContext, join); + await this._syncJoinStyleMeta(syncContext, join, style); + await this._syncJoinFormatters(syncContext, join, style); return this._syncJoin({ join, ...syncContext }); }); return await Promise.all(joinSyncs); } - _getSearchFilters(dataFilters) { + _getSearchFilters(dataFilters, source, style) { const fieldNames = [ - ...this.getSource().getFieldNames(), - ...this.getCurrentStyle().getSourceFieldNames(), + ...source.getFieldNames(), + ...style.getSourceFieldNames(), ...this.getValidJoins().map(join => join.getLeftField().getName()), ]; return { ...dataFilters, fieldNames: _.uniq(fieldNames).sort(), - geogridPrecision: this.getSource().getGeoGridPrecision(dataFilters.zoom), + geogridPrecision: source.getGeoGridPrecision(dataFilters.zoom), sourceQuery: this.getQuery(), - applyGlobalQuery: this.getSource().getApplyGlobalQuery(), - sourceMeta: this.getSource().getSyncMeta(), + applyGlobalQuery: source.getApplyGlobalQuery(), + sourceMeta: source.getSyncMeta(), }; } @@ -353,20 +353,21 @@ export class VectorLayer extends AbstractLayer { } } - async _syncSource({ - startLoading, - stopLoading, - onLoadError, - registerCancelCallback, - dataFilters, - isRequestStillActive, - }) { + async _syncSource(syncContext, source, style) { + const { + startLoading, + stopLoading, + onLoadError, + registerCancelCallback, + dataFilters, + isRequestStillActive, + } = syncContext; const dataRequestId = SOURCE_DATA_ID_ORIGIN; const requestToken = Symbol(`layer-${this.getId()}-${dataRequestId}`); - const searchFilters = this._getSearchFilters(dataFilters); + const searchFilters = this._getSearchFilters(dataFilters, source, style); const prevDataRequest = this.getSourceDataRequest(); const canSkipFetch = await canSkipSourceUpdate({ - source: this.getSource(), + source, prevDataRequest, nextMeta: searchFilters, }); @@ -379,8 +380,8 @@ export class VectorLayer extends AbstractLayer { try { startLoading(dataRequestId, requestToken, searchFilters); - const layerName = await this.getDisplayName(); - const { data: sourceFeatureCollection, meta } = await this.getSource().getGeoJsonWithMeta( + const layerName = await this.getDisplayName(source); + const { data: sourceFeatureCollection, meta } = await source.getGeoJsonWithMeta( layerName, searchFilters, registerCancelCallback.bind(null, requestToken), @@ -404,31 +405,31 @@ export class VectorLayer extends AbstractLayer { } } - async _syncSourceStyleMeta(syncContext) { + async _syncSourceStyleMeta(syncContext, source, style) { if (this.getCurrentStyle().constructor.type !== LAYER_STYLE_TYPE.VECTOR) { return; } return this._syncStyleMeta({ - source: this.getSource(), + source, + style, sourceQuery: this.getQuery(), dataRequestId: SOURCE_META_ID_ORIGIN, - dynamicStyleProps: this.getCurrentStyle() - .getDynamicPropertiesArray() - .filter(dynamicStyleProp => { - return ( - dynamicStyleProp.getFieldOrigin() === FIELD_ORIGIN.SOURCE && - dynamicStyleProp.isFieldMetaEnabled() - ); - }), + dynamicStyleProps: style.getDynamicPropertiesArray().filter(dynamicStyleProp => { + return ( + dynamicStyleProp.getFieldOrigin() === FIELD_ORIGIN.SOURCE && + dynamicStyleProp.isFieldMetaEnabled() + ); + }), ...syncContext, }); } - async _syncJoinStyleMeta(syncContext, join) { + async _syncJoinStyleMeta(syncContext, join, style) { const joinSource = join.getRightJoinSource(); return this._syncStyleMeta({ source: joinSource, + style, sourceQuery: joinSource.getWhereQuery(), dataRequestId: join.getSourceMetaDataRequestId(), dynamicStyleProps: this.getCurrentStyle() @@ -449,6 +450,7 @@ export class VectorLayer extends AbstractLayer { async _syncStyleMeta({ source, + style, sourceQuery, dataRequestId, dynamicStyleProps, @@ -472,7 +474,7 @@ export class VectorLayer extends AbstractLayer { isTimeAware: this.getCurrentStyle().isTimeAware() && (await source.isTimeAware()), timeFilters: dataFilters.timeFilters, }; - const prevDataRequest = this.findDataRequestById(dataRequestId); + const prevDataRequest = this.getDataRequest(dataRequestId); const canSkipFetch = canSkipStyleMetaUpdate({ prevDataRequest, nextMeta }); if (canSkipFetch) { return; @@ -484,7 +486,7 @@ export class VectorLayer extends AbstractLayer { const layerName = await this.getDisplayName(); const styleMeta = await source.loadStylePropsMeta( layerName, - this.getCurrentStyle(), + style, dynamicStyleProps, registerCancelCallback, nextMeta @@ -497,15 +499,15 @@ export class VectorLayer extends AbstractLayer { } } - async _syncSourceFormatters(syncContext) { - if (this.getCurrentStyle().constructor.type !== LAYER_STYLE_TYPE.VECTOR) { + async _syncSourceFormatters(syncContext, source, style) { + if (style.constructor.type !== LAYER_STYLE_TYPE.VECTOR) { return; } return this._syncFormatters({ - source: this.getSource(), + source, dataRequestId: SOURCE_FORMATTERS_ID_ORIGIN, - fields: this.getCurrentStyle() + fields: style .getDynamicPropertiesArray() .filter(dynamicStyleProp => { return dynamicStyleProp.getFieldOrigin() === FIELD_ORIGIN.SOURCE; @@ -517,12 +519,12 @@ export class VectorLayer extends AbstractLayer { }); } - async _syncJoinFormatters(syncContext, join) { + async _syncJoinFormatters(syncContext, join, style) { const joinSource = join.getRightJoinSource(); return this._syncFormatters({ source: joinSource, dataRequestId: join.getSourceFormattersDataRequestId(), - fields: this.getCurrentStyle() + fields: style .getDynamicPropertiesArray() .filter(dynamicStyleProp => { const matchingField = joinSource.getMetricFieldForName( @@ -548,7 +550,7 @@ export class VectorLayer extends AbstractLayer { const nextMeta = { fieldNames: _.uniq(fieldNames).sort(), }; - const prevDataRequest = this.findDataRequestById(dataRequestId); + const prevDataRequest = this.getDataRequest(dataRequestId); const canSkipUpdate = canSkipFormattersUpdate({ prevDataRequest, nextMeta }); if (canSkipUpdate) { return; @@ -575,13 +577,27 @@ export class VectorLayer extends AbstractLayer { } async syncData(syncContext) { + this._syncData(syncContext, this.getSource(), this.getCurrentStyle()); + } + + // TLDR: Do not call getSource or getCurrentStyle in syncData flow. Use 'source' and 'style' arguments instead. + // + // 1) State is contained in the redux store. Layer instance state is readonly. + // 2) Even though data request descriptor updates trigger new instances for rendering, + // syncing data executes on a single object instance. Syncing data can not use updated redux store state. + // + // Blended layer data syncing branches on the source/style depending on whether clustering is used or not. + // Given 1 above, which source/style to use can not be stored in Layer instance state. + // Given 2 above, which source/style to use can not be pulled from data request state. + // Therefore, source and style are provided as arugments and must be used instead of calling getSource or getCurrentStyle. + async _syncData(syncContext, source, style) { if (!this.isVisible() || !this.showAtZoomLevel(syncContext.dataFilters.zoom)) { return; } - await this._syncSourceStyleMeta(syncContext); - await this._syncSourceFormatters(syncContext); - const sourceResult = await this._syncSource(syncContext); + await this._syncSourceStyleMeta(syncContext, source, style); + await this._syncSourceFormatters(syncContext, source, style); + const sourceResult = await this._syncSource(syncContext, source, style); if ( !sourceResult.featureCollection || !sourceResult.featureCollection.features.length || @@ -590,7 +606,7 @@ export class VectorLayer extends AbstractLayer { return; } - const joinStates = await this._syncJoins(syncContext); + const joinStates = await this._syncJoins(syncContext, style); await this._performInnerJoins(sourceResult, joinStates, syncContext.updateSourceData); } From 7c5fa30769b796701e1518a7d8669204afddaa47 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Tue, 17 Mar 2020 10:11:16 -0600 Subject: [PATCH 21/27] one more change for removing mutable BlendedVectorLayer state --- x-pack/legacy/plugins/maps/public/layers/vector_layer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/legacy/plugins/maps/public/layers/vector_layer.js b/x-pack/legacy/plugins/maps/public/layers/vector_layer.js index 102828f361bb44..6b89554546330b 100644 --- a/x-pack/legacy/plugins/maps/public/layers/vector_layer.js +++ b/x-pack/legacy/plugins/maps/public/layers/vector_layer.js @@ -483,7 +483,7 @@ export class VectorLayer extends AbstractLayer { const requestToken = Symbol(`layer-${this.getId()}-${dataRequestId}`); try { startLoading(dataRequestId, requestToken, nextMeta); - const layerName = await this.getDisplayName(); + const layerName = await this.getDisplayName(source); const styleMeta = await source.loadStylePropsMeta( layerName, style, From 6e70f5122977187d4c9e9d59da3f187c571ba05e Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Tue, 17 Mar 2020 11:00:54 -0600 Subject: [PATCH 22/27] integrate newly merged MapSavedObjectAttributes type --- .../plugins/maps/common/migrations/scaling_type.ts | 5 +++-- .../maps/public/layers/blended_vector_layer.ts | 14 +++++++++++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/x-pack/legacy/plugins/maps/common/migrations/scaling_type.ts b/x-pack/legacy/plugins/maps/common/migrations/scaling_type.ts index fc71970e53cb2f..96e55419800362 100644 --- a/x-pack/legacy/plugins/maps/common/migrations/scaling_type.ts +++ b/x-pack/legacy/plugins/maps/common/migrations/scaling_type.ts @@ -7,6 +7,7 @@ import _ from 'lodash'; import { ES_SEARCH, SCALING_TYPES } from '../constants'; import { LayerDescriptor, ESSearchSourceDescriptor } from '../descriptor_types'; +import { MapSavedObjectAttributes } from '../../../../../plugins/maps/common/map_saved_object_type'; function isEsDocumentSource(layerDescriptor: LayerDescriptor) { const sourceType = _.get(layerDescriptor, 'sourceDescriptor.type'); @@ -16,8 +17,8 @@ function isEsDocumentSource(layerDescriptor: LayerDescriptor) { export function migrateUseTopHitsToScalingType({ attributes, }: { - attributes: { layerListJSON?: string; title?: string }; -}) { + attributes: MapSavedObjectAttributes; +}): MapSavedObjectAttributes { if (!attributes || !attributes.layerListJSON) { return attributes; } diff --git a/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.ts b/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.ts index abafffc6f8b5cb..910a59c9db718c 100644 --- a/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.ts +++ b/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +import { i18n } from '@kbn/i18n'; import { VectorLayer } from './vector_layer'; import { IVectorStyle, VectorStyle } from './styles/vector/vector_style'; // @ts-ignore @@ -26,6 +27,7 @@ import { canSkipSourceUpdate } from './util/can_skip_fetch'; import { IVectorLayer, VectorLayerArguments } from './vector_layer'; import { IESSource } from './sources/es_source'; import { IESAggSource } from './sources/es_agg_source'; +import { ISource } from './sources/source'; function getAggType(dynamicProperty: IDynamicStyleProperty): AGG_TYPE { return dynamicProperty.isOrdinal() ? AGG_TYPE.AVG : AGG_TYPE.TERMS; @@ -170,6 +172,16 @@ export class BlendedVectorLayer extends VectorLayer implements IVectorLayer { } } + async getDisplayName(source: ISource) { + const displayName = await super.getDisplayName(source); + return this._isClustered + ? i18n.translate('xpack.maps.blendedVectorLayer.clusteredLayerName', { + defaultMessage: 'Clustered {displayName}', + values: { displayName }, + }) + : displayName; + } + isJoinable() { return false; } @@ -198,8 +210,8 @@ export class BlendedVectorLayer extends VectorLayer implements IVectorLayer { } async syncData(syncContext: unknown) { - // @ts-ignore const searchFilters = this._getSearchFilters( + // @ts-ignore syncContext.dataFilters, this.getSource(), this.getCurrentStyle() From deca3c33b242a9fd266c54e5e46897fee58db6e3 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Tue, 17 Mar 2020 11:16:43 -0600 Subject: [PATCH 23/27] review feedback --- .../plugins/maps/common/descriptor_types.d.ts | 2 +- .../common/migrations/scaling_type.test.ts | 18 ++++++++++++++++++ .../maps/common/migrations/scaling_type.ts | 16 +++++++--------- 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/x-pack/legacy/plugins/maps/common/descriptor_types.d.ts b/x-pack/legacy/plugins/maps/common/descriptor_types.d.ts index d7849d09a21f7e..2f45c525828dbb 100644 --- a/x-pack/legacy/plugins/maps/common/descriptor_types.d.ts +++ b/x-pack/legacy/plugins/maps/common/descriptor_types.d.ts @@ -50,7 +50,7 @@ export type ESSearchSourceDescriptor = AbstractESSourceDescriptor & { tooltipProperties?: string[]; sortField?: string; sortOrder?: SORT_ORDER; - scalingType?: SCALING_TYPES; + scalingType: SCALING_TYPES; topHitsSplitField?: string; topHitsSize?: number; }; diff --git a/x-pack/legacy/plugins/maps/common/migrations/scaling_type.test.ts b/x-pack/legacy/plugins/maps/common/migrations/scaling_type.test.ts index 9c64837cf3a141..4fbb1ef4c55ed3 100644 --- a/x-pack/legacy/plugins/maps/common/migrations/scaling_type.test.ts +++ b/x-pack/legacy/plugins/maps/common/migrations/scaling_type.test.ts @@ -53,4 +53,22 @@ describe('migrateUseTopHitsToScalingType', () => { layerListJSON: '[{"sourceDescriptor":{"type":"ES_SEARCH","scalingType":"LIMIT"}}]', }); }); + + test('Should set scalingType to LIMIT when useTopHits is not set', () => { + const layerListJSON = JSON.stringify([ + { + sourceDescriptor: { + type: 'ES_SEARCH', + }, + }, + ]); + const attributes = { + title: 'my map', + layerListJSON, + }; + expect(migrateUseTopHitsToScalingType({ attributes })).toEqual({ + title: 'my map', + layerListJSON: '[{"sourceDescriptor":{"type":"ES_SEARCH","scalingType":"LIMIT"}}]', + }); + }); }); diff --git a/x-pack/legacy/plugins/maps/common/migrations/scaling_type.ts b/x-pack/legacy/plugins/maps/common/migrations/scaling_type.ts index 96e55419800362..5823ddd6b42e35 100644 --- a/x-pack/legacy/plugins/maps/common/migrations/scaling_type.ts +++ b/x-pack/legacy/plugins/maps/common/migrations/scaling_type.ts @@ -26,15 +26,13 @@ export function migrateUseTopHitsToScalingType({ const layerList: LayerDescriptor[] = JSON.parse(attributes.layerListJSON); layerList.forEach((layerDescriptor: LayerDescriptor) => { if (isEsDocumentSource(layerDescriptor)) { - if (_.has(layerDescriptor, 'sourceDescriptor.useTopHits')) { - const sourceDescriptor = layerDescriptor.sourceDescriptor as ESSearchSourceDescriptor; - sourceDescriptor.scalingType = _.get(layerDescriptor, 'sourceDescriptor.useTopHits', false) - ? SCALING_TYPES.TOP_HITS - : SCALING_TYPES.LIMIT; - // @ts-ignore useTopHits no longer in type definition but that does not mean its not in live data - // hence the entire point of this method - delete sourceDescriptor.useTopHits; - } + const sourceDescriptor = layerDescriptor.sourceDescriptor as ESSearchSourceDescriptor; + sourceDescriptor.scalingType = _.get(layerDescriptor, 'sourceDescriptor.useTopHits', false) + ? SCALING_TYPES.TOP_HITS + : SCALING_TYPES.LIMIT; + // @ts-ignore useTopHits no longer in type definition but that does not mean its not in live data + // hence the entire point of this method + delete sourceDescriptor.useTopHits; } }); From 12078731c5f22320418ca6520f27734d5d9499f5 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Tue, 17 Mar 2020 12:40:40 -0600 Subject: [PATCH 24/27] use data request for fetching feature count --- .../maps/public/actions/map_actions.d.ts | 18 ++++++++ .../public/layers/blended_vector_layer.ts | 43 +++++++++++++------ .../plugins/maps/public/layers/layer.d.ts | 7 ++- .../es_search_source/es_search_source.d.ts | 2 +- .../es_search_source/es_search_source.test.ts | 3 +- .../maps/public/layers/vector_layer.d.ts | 3 +- 6 files changed, 58 insertions(+), 18 deletions(-) create mode 100644 x-pack/legacy/plugins/maps/public/actions/map_actions.d.ts diff --git a/x-pack/legacy/plugins/maps/public/actions/map_actions.d.ts b/x-pack/legacy/plugins/maps/public/actions/map_actions.d.ts new file mode 100644 index 00000000000000..418f2880c10773 --- /dev/null +++ b/x-pack/legacy/plugins/maps/public/actions/map_actions.d.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +/* eslint-disable @typescript-eslint/consistent-type-definitions */ + +import { DataMeta, MapFilters } from '../../common/data_request_descriptor_types'; + +export type SyncContext = { + startLoading(dataId: string, requestToken: symbol, meta: DataMeta): void; + stopLoading(dataId: string, requestToken: symbol, data: unknown, meta: DataMeta): void; + onLoadError(dataId: string, requestToken: symbol, errorMessage: string): void; + updateSourceData(newData: unknown): void; + isRequestStillActive(dataId: string, requestToken: symbol): boolean; + registerCancelCallback(requestToken: symbol, callback: () => void): void; + dataFilters: MapFilters; +}; diff --git a/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.ts b/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.ts index 910a59c9db718c..3a8cba02e48651 100644 --- a/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.ts +++ b/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.ts @@ -28,6 +28,10 @@ import { IVectorLayer, VectorLayerArguments } from './vector_layer'; import { IESSource } from './sources/es_source'; import { IESAggSource } from './sources/es_agg_source'; import { ISource } from './sources/source'; +import { SyncContext } from '../actions/map_actions'; +import { DataRequestAbortError } from './util/data_request'; + +const ACTIVE_COUNT_DATA_ID = 'ACTIVE_COUNT_DATA_ID'; function getAggType(dynamicProperty: IDynamicStyleProperty): AGG_TYPE { return dynamicProperty.isOrdinal() ? AGG_TYPE.AVG : AGG_TYPE.TERMS; @@ -209,33 +213,46 @@ export class BlendedVectorLayer extends VectorLayer implements IVectorLayer { return this._documentStyle; } - async syncData(syncContext: unknown) { + async syncData(syncContext: SyncContext) { + const dataRequestId = ACTIVE_COUNT_DATA_ID; + const requestToken = Symbol(`layer-active-count:${this.getId()}`); const searchFilters = this._getSearchFilters( - // @ts-ignore syncContext.dataFilters, this.getSource(), this.getCurrentStyle() ); const canSkipFetch = await canSkipSourceUpdate({ source: this.getSource(), - prevDataRequest: this.getSourceDataRequest(), + prevDataRequest: this.getDataRequest(dataRequestId), nextMeta: searchFilters, }); + if (canSkipFetch) { + return; + } - let activeSource = this.getSource(); - let activeStyle = this.getCurrentStyle(); - if (!canSkipFetch) { + let isSyncClustered; + try { + syncContext.startLoading(dataRequestId, requestToken, searchFilters); const searchSource = await this._documentSource.makeSearchSource(searchFilters, 0); const resp = await searchSource.fetch(); const maxResultWindow = await this._documentSource.getMaxResultWindow(); - - if (resp.hits.total > maxResultWindow) { - activeSource = this._clusterSource; - activeStyle = this._clusterStyle; - } else { - activeSource = this._documentSource; - activeStyle = this._documentStyle; + isSyncClustered = resp.hits.total > maxResultWindow; + syncContext.stopLoading(dataRequestId, requestToken, { isSyncClustered }, searchFilters); + } catch (error) { + if (!(error instanceof DataRequestAbortError)) { + syncContext.onLoadError(dataRequestId, requestToken, error.message); } + return; + } + + let activeSource; + let activeStyle; + if (isSyncClustered) { + activeSource = this._clusterSource; + activeStyle = this._clusterStyle; + } else { + activeSource = this._documentSource; + activeStyle = this._documentStyle; } super._syncData(syncContext, activeSource, activeStyle); diff --git a/x-pack/legacy/plugins/maps/public/layers/layer.d.ts b/x-pack/legacy/plugins/maps/public/layers/layer.d.ts index bc32d8a9ddf21f..777566298e6077 100644 --- a/x-pack/legacy/plugins/maps/public/layers/layer.d.ts +++ b/x-pack/legacy/plugins/maps/public/layers/layer.d.ts @@ -6,14 +6,16 @@ import { LayerDescriptor } from '../../common/descriptor_types'; import { ISource } from './sources/source'; import { DataRequest } from './util/data_request'; +import { SyncContext } from '../actions/map_actions'; export interface ILayer { getDataRequest(id: string): DataRequest | undefined; getDisplayName(source?: ISource): Promise; + getId(): string; getSourceDataRequest(): DataRequest | undefined; getSource(): ISource; getSourceForEditing(): ISource; - syncData(syncContext: unknown): Promise; + syncData(syncContext: SyncContext): Promise; } export interface ILayerArguments { @@ -25,8 +27,9 @@ export class AbstractLayer implements ILayer { constructor(layerArguments: ILayerArguments); getDataRequest(id: string): DataRequest | undefined; getDisplayName(source?: ISource): Promise; + getId(): string; getSourceDataRequest(): DataRequest | undefined; getSource(): ISource; getSourceForEditing(): ISource; - syncData(syncContext: unknown): Promise; + syncData(syncContext: SyncContext): Promise; } diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/es_search_source.d.ts b/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/es_search_source.d.ts index 5d8188f19f4eaa..0a4e48a195ec66 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/es_search_source.d.ts +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/es_search_source.d.ts @@ -8,5 +8,5 @@ import { AbstractESSource } from '../es_source'; import { ESSearchSourceDescriptor } from '../../../../common/descriptor_types'; export class ESSearchSource extends AbstractESSource { - constructor(sourceDescriptor: ESSearchSourceDescriptor, inspectorAdapters: unknown); + constructor(sourceDescriptor: Partial, inspectorAdapters: unknown); } diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/es_search_source.test.ts b/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/es_search_source.test.ts index 1e10923cea1d0e..59120e221ca499 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/es_search_source.test.ts +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/es_search_source.test.ts @@ -7,7 +7,7 @@ jest.mock('ui/new_platform'); import { ESSearchSource } from './es_search_source'; import { VectorLayer } from '../../vector_layer'; -import { ES_SEARCH } from '../../../../common/constants'; +import { ES_SEARCH, SCALING_TYPES } from '../../../../common/constants'; import { ESSearchSourceDescriptor } from '../../../../common/descriptor_types'; const descriptor: ESSearchSourceDescriptor = { @@ -15,6 +15,7 @@ const descriptor: ESSearchSourceDescriptor = { id: '1234', indexPatternId: 'myIndexPattern', geoField: 'myLocation', + scalingType: SCALING_TYPES.LIMIT, }; describe('ES Search Source', () => { diff --git a/x-pack/legacy/plugins/maps/public/layers/vector_layer.d.ts b/x-pack/legacy/plugins/maps/public/layers/vector_layer.d.ts index afe392bfd93a5d..77e8ab768cd00e 100644 --- a/x-pack/legacy/plugins/maps/public/layers/vector_layer.d.ts +++ b/x-pack/legacy/plugins/maps/public/layers/vector_layer.d.ts @@ -13,6 +13,7 @@ import { ILayer } from './layer'; import { IJoin } from './joins/join'; import { IVectorStyle } from './styles/vector/vector_style'; import { IField } from './fields/field'; +import { SyncContext } from '../actions/map_actions'; type VectorLayerArguments = { source: IVectorSource; @@ -45,5 +46,5 @@ export class VectorLayer extends AbstractLayer implements IVectorLayer { source: IVectorSource, style: IVectorStyle ): VectorLayerRequestMeta; - _syncData(syncContext: unknown, source: IVectorSource, style: IVectorStyle): Promise; + _syncData(syncContext: SyncContext, source: IVectorSource, style: IVectorStyle): Promise; } From 41a4bff12ac1bb34b972ff84d3ffcefd9c710e52 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Tue, 17 Mar 2020 15:02:43 -0600 Subject: [PATCH 25/27] add functional test --- .../public/layers/blended_vector_layer.ts | 1 + .../maps/public/layers/sources/es_source.d.ts | 2 + .../maps/public/layers/sources/es_source.js | 4 ++ .../apps/maps/blended_vector_layer.js | 42 ++++++++++++++ x-pack/test/functional/apps/maps/index.js | 1 + .../es_archives/maps/kibana/data.json | 56 +++++++++++++++++++ 6 files changed, 106 insertions(+) create mode 100644 x-pack/test/functional/apps/maps/blended_vector_layer.js diff --git a/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.ts b/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.ts index 3a8cba02e48651..b35eeedfa44fa3 100644 --- a/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.ts +++ b/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.ts @@ -55,6 +55,7 @@ function getClusterSource(documentSource: IESSource, documentStyle: IVectorStyle }; }), ]; + clusterSourceDescriptor.id = documentSource.getId(); return new ESGeoGridSource(clusterSourceDescriptor, documentSource.getInspectorAdapters()); } diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_source.d.ts b/x-pack/legacy/plugins/maps/public/layers/sources/es_source.d.ts index 695340ecd9b824..963a30c7413e83 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_source.d.ts +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_source.d.ts @@ -10,6 +10,7 @@ import { IndexPattern, SearchSource } from '../../../../../../../src/plugins/dat import { VectorLayerRequestMeta } from '../../../common/data_request_descriptor_types'; export interface IESSource extends IVectorSource { + getId(): string; getIndexPattern(): Promise; getIndexPatternId(): string; getGeoFieldName(): string; @@ -22,6 +23,7 @@ export interface IESSource extends IVectorSource { } export class AbstractESSource extends AbstractVectorSource implements IESSource { + getId(): string; getIndexPattern(): Promise; getIndexPatternId(): string; getGeoFieldName(): string; diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_source.js index ced80a73fa64a9..c5bf9a8be75bd1 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_source.js +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_source.js @@ -35,6 +35,10 @@ export class AbstractESSource extends AbstractVectorSource { ); } + getId() { + return this._descriptor.id; + } + isFieldAware() { return true; } diff --git a/x-pack/test/functional/apps/maps/blended_vector_layer.js b/x-pack/test/functional/apps/maps/blended_vector_layer.js new file mode 100644 index 00000000000000..a01f796fe34556 --- /dev/null +++ b/x-pack/test/functional/apps/maps/blended_vector_layer.js @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; + +export default function({ getPageObjects, getService }) { + const PageObjects = getPageObjects(['maps']); + const inspector = getService('inspector'); + + describe('blended vector layer', () => { + before(async () => { + await PageObjects.maps.loadSavedMap('blended document example'); + }); + + it('should request documents when zoomed to smaller regions showing less data', async () => { + const hits = await PageObjects.maps.getHits(); + expect(hits).to.equal('33'); + }); + + it('should request clusters when zoomed to larger regions showing lots of data', async () => { + await PageObjects.maps.setView(20, -90, 2); + await inspector.open(); + await inspector.openInspectorRequestsView(); + const requestStats = await inspector.getTableData(); + const hits = PageObjects.maps.getInspectorStatRowHit(requestStats, 'Hits'); + const totalHits = PageObjects.maps.getInspectorStatRowHit(requestStats, 'Hits (total)'); + await inspector.close(); + + expect(hits).to.equal('0'); + expect(totalHits).to.equal('14000'); + }); + + it('should request documents when query narrows data', async () => { + await PageObjects.maps.setAndSubmitQuery('bytes > 19000'); + const hits = await PageObjects.maps.getHits(); + expect(hits).to.equal('75'); + }); + }); +} diff --git a/x-pack/test/functional/apps/maps/index.js b/x-pack/test/functional/apps/maps/index.js index 44a7c4c9a5f866..ae7de986cf8677 100644 --- a/x-pack/test/functional/apps/maps/index.js +++ b/x-pack/test/functional/apps/maps/index.js @@ -30,6 +30,7 @@ export default function({ loadTestFile, getService }) { describe('', function() { this.tags('ciGroup7'); loadTestFile(require.resolve('./documents_source')); + loadTestFile(require.resolve('./blended_vector_layer')); loadTestFile(require.resolve('./saved_object_management')); loadTestFile(require.resolve('./sample_data')); loadTestFile(require.resolve('./feature_controls/maps_security')); diff --git a/x-pack/test/functional/es_archives/maps/kibana/data.json b/x-pack/test/functional/es_archives/maps/kibana/data.json index e50ec593cc9902..2961e2f0333dc6 100644 --- a/x-pack/test/functional/es_archives/maps/kibana/data.json +++ b/x-pack/test/functional/es_archives/maps/kibana/data.json @@ -861,6 +861,62 @@ } } +{ + "type": "doc", + "value": { + "id": "map:279e1f20-6883-11ea-952a-b102add99cf8", + "index": ".kibana", + "source": { + "map" : { + "title" : "blended document example", + "description" : "", + "mapStateJSON" : "{\"zoom\":10.27,\"center\":{\"lon\":-83.70716,\"lat\":32.73679},\"timeFilters\":{\"from\":\"2015-09-20T00:00:00.000Z\",\"to\":\"2015-09-23T00:00:00.000Z\"},\"refreshConfig\":{\"isPaused\":true,\"interval\":0},\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filters\":[]}", + "layerListJSON" : "[{\"sourceDescriptor\":{\"type\":\"EMS_TMS\",\"isAutoSelect\":true},\"id\":\"43a70a86-00fd-43af-9e84-4d9fe2d7513d\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"alpha\":1,\"visible\":true,\"style\":{},\"type\":\"VECTOR_TILE\"},{\"id\":\"307c8495-89f7-431b-83d8-78724d9a8f72\",\"label\":\"logstash-*\",\"sourceDescriptor\":{\"geoField\":\"geo.coordinates\",\"id\":\"20fc58c3-3c0a-4c7b-9cdc-37552cafdc21\",\"tooltipProperties\":[],\"type\":\"ES_SEARCH\",\"scalingType\":\"CLUSTERS\",\"indexPatternRefName\":\"layer_1_source_index_pattern\"},\"type\":\"BLENDED_VECTOR\",\"visible\":true,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"icon\":{\"type\":\"STATIC\",\"options\":{\"value\":\"airfield\"}},\"fillColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#54B399\"}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#41937c\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"STATIC\",\"options\":{\"size\":6}},\"iconOrientation\":{\"type\":\"STATIC\",\"options\":{\"orientation\":0}},\"labelText\":{\"type\":\"STATIC\",\"options\":{\"value\":\"\"}},\"labelColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#000000\"}},\"labelSize\":{\"type\":\"STATIC\",\"options\":{\"size\":14}},\"labelBorderColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#FFFFFF\"}},\"symbolizeAs\":{\"options\":{\"value\":\"circle\"}},\"labelBorderSize\":{\"options\":{\"size\":\"SMALL\"}}},\"isTimeAware\":true}}]", + "uiStateJSON" : "{\"isLayerTOCOpen\":true,\"openTOCDetails\":[]}", + "bounds" : { + "type" : "Polygon", + "coordinates" : [ + [ + [ + -84.07816, + 32.95327 + ], + [ + -84.07816, + 32.51978 + ], + [ + -83.33616, + 32.51978 + ], + [ + -83.33616, + 32.95327 + ], + [ + -84.07816, + 32.95327 + ] + ] + ] + } + }, + "type" : "map", + "references" : [ + { + "name" : "layer_1_source_index_pattern", + "type" : "index-pattern", + "id" : "c698b940-e149-11e8-a35a-370a8516603a" + } + ], + "migrationVersion" : { + "map" : "7.7.0" + }, + "updated_at" : "2020-03-17T19:11:50.290Z" + } + } +} + { "type": "doc", "value": { From fe3499fc6b22e64c1a91306f66a17e5da9466b04 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Tue, 17 Mar 2020 18:39:36 -0600 Subject: [PATCH 26/27] fix functional test --- x-pack/test/functional/es_archives/maps/kibana/data.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/test/functional/es_archives/maps/kibana/data.json b/x-pack/test/functional/es_archives/maps/kibana/data.json index 2961e2f0333dc6..cb3598652a39ae 100644 --- a/x-pack/test/functional/es_archives/maps/kibana/data.json +++ b/x-pack/test/functional/es_archives/maps/kibana/data.json @@ -288,7 +288,7 @@ "title" : "document example top hits split with scripted field", "description" : "", "mapStateJSON" : "{\"zoom\":4.1,\"center\":{\"lon\":-100.61091,\"lat\":33.23887},\"timeFilters\":{\"from\":\"2015-09-20T00:00:00.000Z\",\"to\":\"2015-09-24T01:00:00.000Z\"},\"refreshConfig\":{\"isPaused\":true,\"interval\":1000},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[]}", - "layerListJSON" : "[{\"id\":\"0hmz5\",\"sourceDescriptor\":{\"type\":\"EMS_TMS\",\"id\":\"road_map\"},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"TILE\",\"properties\":{}},\"type\":\"VECTOR_TILE\",\"minZoom\":0,\"maxZoom\":24},{\"id\":\"z52lq\",\"label\":\"logstash\",\"minZoom\":0,\"maxZoom\":24,\"sourceDescriptor\":{\"id\":\"e1a5e1a6-676c-4a89-8ea9-0d91d64b73c6\",\"type\":\"ES_SEARCH\",\"geoField\":\"geo.coordinates\",\"limit\":2048,\"filterByMapBounds\":true,\"showTooltip\":true,\"tooltipProperties\":[],\"useTopHits\":true,\"topHitsSplitField\":\"hour_of_day\",\"topHitsSize\":1,\"sortField\":\"@timestamp\",\"sortOrder\":\"desc\",\"applyGlobalQuery\":true,\"indexPatternRefName\":\"layer_1_source_index_pattern\"},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#e6194b\"}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#FFFFFF\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"STATIC\",\"options\":{\"size\":10}},\"symbolizeAs\":{\"options\":{\"value\":\"circle\"}},\"icon\":{\"type\":\"STATIC\",\"options\":{\"value\":\"airfield\"}}},\"previousStyle\":null},\"type\":\"VECTOR\"}]", + "layerListJSON" : "[{\"id\":\"0hmz5\",\"sourceDescriptor\":{\"type\":\"EMS_TMS\",\"id\":\"road_map\"},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"TILE\",\"properties\":{}},\"type\":\"VECTOR_TILE\",\"minZoom\":0,\"maxZoom\":24},{\"id\":\"z52lq\",\"label\":\"logstash\",\"minZoom\":0,\"maxZoom\":24,\"sourceDescriptor\":{\"id\":\"e1a5e1a6-676c-4a89-8ea9-0d91d64b73c6\",\"type\":\"ES_SEARCH\",\"geoField\":\"geo.coordinates\",\"limit\":2048,\"filterByMapBounds\":true,\"showTooltip\":true,\"tooltipProperties\":[],\"scalingType\":\"TOP_HITS\",\"topHitsSplitField\":\"hour_of_day\",\"topHitsSize\":1,\"sortField\":\"@timestamp\",\"sortOrder\":\"desc\",\"applyGlobalQuery\":true,\"indexPatternRefName\":\"layer_1_source_index_pattern\"},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#e6194b\"}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#FFFFFF\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"STATIC\",\"options\":{\"size\":10}},\"symbolizeAs\":{\"options\":{\"value\":\"circle\"}},\"icon\":{\"type\":\"STATIC\",\"options\":{\"value\":\"airfield\"}}},\"previousStyle\":null},\"type\":\"VECTOR\"}]", "uiStateJSON" : "{\"isLayerTOCOpen\":true,\"openTOCDetails\":[]}", "bounds" : { "type" : "Polygon", From 5f3236ce061e0e578cddcfc7feb01900e6b32fc2 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Wed, 18 Mar 2020 10:12:42 -0600 Subject: [PATCH 27/27] review feedback --- .../plugins/maps/common/data_request_descriptor_types.d.ts | 1 + x-pack/legacy/plugins/maps/public/layers/layer.js | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/x-pack/legacy/plugins/maps/common/data_request_descriptor_types.d.ts b/x-pack/legacy/plugins/maps/common/data_request_descriptor_types.d.ts index 81d0ae8adb0fca..3281fb5892eac7 100644 --- a/x-pack/legacy/plugins/maps/common/data_request_descriptor_types.d.ts +++ b/x-pack/legacy/plugins/maps/common/data_request_descriptor_types.d.ts @@ -34,6 +34,7 @@ export type ESSearchSourceResponseMeta = { totalEntities?: number; }; +// Partial because objects are justified downstream in constructors export type DataMeta = Partial & Partial; export type DataRequestDescriptor = { diff --git a/x-pack/legacy/plugins/maps/public/layers/layer.js b/x-pack/legacy/plugins/maps/public/layers/layer.js index eadece23eb701e..d162e342dfd1a8 100644 --- a/x-pack/legacy/plugins/maps/public/layers/layer.js +++ b/x-pack/legacy/plugins/maps/public/layers/layer.js @@ -52,8 +52,8 @@ export class AbstractLayer { } destroy() { - if (this.getSource()) { - this.getSource().destroy(); + if (this._source) { + this._source.destroy(); } }