diff --git a/src/dev/license_checker/config.js b/src/dev/license_checker/config.js index 04b0ceedb4168..6c72c918279d7 100644 --- a/src/dev/license_checker/config.js +++ b/src/dev/license_checker/config.js @@ -52,6 +52,7 @@ export const LICENSE_WHITELIST = [ 'CC-BY-3.0', 'CC-BY-4.0', 'Eclipse Distribution License - v 1.0', + 'FreeBSD', 'ISC', 'ISC*', 'MIT OR GPL-2.0', diff --git a/x-pack/package.json b/x-pack/package.json index 773e642dd4ed1..6012327c9a776 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -178,6 +178,7 @@ "@kbn/i18n": "1.0.0", "@kbn/interpreter": "1.0.0", "@kbn/ui-framework": "1.0.0", + "@mapbox/mapbox-gl-draw": "^1.1.1", "@samverschueren/stream-to-observable": "^0.3.0", "@scant/router": "^0.1.0", "@slack/client": "^4.8.0", @@ -255,6 +256,7 @@ "lodash.uniqby": "^4.7.0", "lz-string": "^1.4.4", "mapbox-gl": "0.52.0", + "mapbox-gl-draw-rectangle-mode": "^1.0.4", "markdown-it": "^8.4.1", "mime": "^2.2.2", "mkdirp": "0.5.1", diff --git a/x-pack/plugins/maps/common/constants.js b/x-pack/plugins/maps/common/constants.js index cfa31fa390301..26d0ed204ae95 100644 --- a/x-pack/plugins/maps/common/constants.js +++ b/x-pack/plugins/maps/common/constants.js @@ -28,3 +28,8 @@ export const APP_ICON = 'gisApp'; export const SOURCE_DATA_ID_ORIGIN = 'source'; export const FEATURE_ID_PROPERTY_NAME = '__kbn__feature_id__'; + +export const ES_GEO_FIELD_TYPE = { + GEO_POINT: 'geo_point', + GEO_SHAPE: 'geo_shape' +}; diff --git a/x-pack/plugins/maps/public/_main.scss b/x-pack/plugins/maps/public/_main.scss index 620a5d41069fd..74f670641574c 100644 --- a/x-pack/plugins/maps/public/_main.scss +++ b/x-pack/plugins/maps/public/_main.scss @@ -23,29 +23,39 @@ .mapContainer { flex-grow: 1; -} -.mapboxgl-popup { - z-index: 100; - border-color: $euiColorEmptyShade; -} + .mapboxgl-popup { + z-index: 100; + border-color: $euiColorEmptyShade; + } -.mapboxgl-popup-content { - background-color: $euiColorEmptyShade; -} + .mapboxgl-popup-content { + background-color: $euiColorEmptyShade; + } -.mapboxgl-popup-tip { - border-top-color: $euiColorEmptyShade !important; -} + .mapboxgl-popup-tip { + border-top-color: $euiColorEmptyShade !important; + } + + .mapboxgl-ctrl-top-left .mapboxgl-ctrl { + margin-left: $euiSizeM; + margin-top: $euiSizeM; + } -// This is not good practice to create such a generic class. -// I can't seem to find it being applied anywhere in GIS -// .hidden { -// display: none -// } + .mapboxgl-ctrl-group:not(:empty) { + @include euiBottomShadowLarge; + background-color: $euiColorEmptyShade; + border-radius: $euiBorderRadius; -// EUIFIXTODO: + > button { + @include size($euiSizeXL); + + button { + border: none; + } + } + } +} .euiColorPicker__emptySwatch { position: relative; } diff --git a/x-pack/plugins/maps/public/actions/store_actions.js b/x-pack/plugins/maps/public/actions/store_actions.js index 3596d0e63d7b6..3301e4af24112 100644 --- a/x-pack/plugins/maps/public/actions/store_actions.js +++ b/x-pack/plugins/maps/public/actions/store_actions.js @@ -52,6 +52,12 @@ export const TRACK_CURRENT_LAYER_STATE = 'TRACK_CURRENT_LAYER_STATE'; export const ROLLBACK_TO_TRACKED_LAYER_STATE = 'ROLLBACK_TO_TRACKED_LAYER_STATE'; export const REMOVE_TRACKED_LAYER_STATE = 'REMOVE_TRACKED_LAYER_STATE'; export const SET_TOOLTIP_STATE = 'SET_TOOLTIP_STATE'; +export const UPDATE_DRAW_STATE = 'UPDATE_DRAW_STATE'; + +export const DRAW_TYPE = { + BOUNDS: 'BOUNDS', + POLYGON: 'POLYGON' +}; export const SET_SCROLL_ZOOM = 'SET_SCROLL_ZOOM'; function getLayerLoadingCallbacks(dispatch, layerId) { @@ -685,3 +691,15 @@ export function setJoinsForLayer(layer, joins) { dispatch(syncDataForLayer(layer.getId())); }; } + +export function updateDrawState(drawState) { + return async (dispatch) => { + if (drawState !== null) { + await dispatch(setTooltipState(null));//tooltips just get in the way + } + dispatch({ + type: UPDATE_DRAW_STATE, + drawState: drawState + }); + }; +} diff --git a/x-pack/plugins/maps/public/components/_index.scss b/x-pack/plugins/maps/public/components/_index.scss index 52735dc92a8bb..3979c1b66fcb3 100644 --- a/x-pack/plugins/maps/public/components/_index.scss +++ b/x-pack/plugins/maps/public/components/_index.scss @@ -2,3 +2,4 @@ @import './layer_addpanel/layer_addpanel'; @import './layer_panel/index'; @import './widget_overlay/index'; +@import './toolbar_overlay/index'; diff --git a/x-pack/plugins/maps/public/components/gis_map/view.js b/x-pack/plugins/maps/public/components/gis_map/view.js index 095d0872d29ce..bac69761333d1 100644 --- a/x-pack/plugins/maps/public/components/gis_map/view.js +++ b/x-pack/plugins/maps/public/components/gis_map/view.js @@ -7,6 +7,7 @@ import React, { Component } from 'react'; import { MBMapContainer } from '../map/mb'; import { WidgetOverlay } from '../widget_overlay/index'; +import { ToolbarOverlay } from '../toolbar_overlay/index'; import { LayerPanel } from '../layer_panel/index'; import { AddLayerPanel } from '../layer_addpanel/index'; import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; @@ -47,13 +48,13 @@ export class GisMap extends Component { interval ); } - } + }; clearRefreshTimer = () => { if (this.refreshTimerId) { clearInterval(this.refreshTimerId); } - } + }; render() { const { @@ -91,6 +92,7 @@ export class GisMap extends Component { + diff --git a/x-pack/plugins/maps/public/components/map/mb/index.js b/x-pack/plugins/maps/public/components/map/mb/index.js index 9ef411a92b9cc..71ee2dc243ab4 100644 --- a/x-pack/plugins/maps/public/components/map/mb/index.js +++ b/x-pack/plugins/maps/public/components/map/mb/index.js @@ -13,9 +13,17 @@ import { setMouseCoordinates, clearMouseCoordinates, clearGoto, - setTooltipState + setTooltipState, + updateDrawState } from '../../../actions/store_actions'; -import { getTooltipState, getLayerList, getMapReady, getGoto, getScrollZoom } from '../../../selectors/map_selectors'; +import { + getTooltipState, + getLayerList, + getMapReady, + getGoto, + getDrawState, + getScrollZoom +} from '../../../selectors/map_selectors'; import { getIsFilterable } from '../../../store/ui'; import { getInspectorAdapters } from '../../../store/non_serializable_instances'; @@ -27,7 +35,8 @@ function mapStateToProps(state = {}) { goto: getGoto(state), inspectorAdapters: getInspectorAdapters(state), tooltipState: getTooltipState(state), - scrollZoom: getScrollZoom(state), + drawState: getDrawState(state), + scrollZoom: getScrollZoom(state) }; } @@ -55,6 +64,9 @@ function mapDispatchToProps(dispatch) { }, setTooltipState(tooltipState) { dispatch(setTooltipState(tooltipState)); + }, + disableDrawState() { + dispatch(updateDrawState(null)); } }; } diff --git a/x-pack/plugins/maps/public/components/map/mb/view.js b/x-pack/plugins/maps/public/components/map/mb/view.js index 8eb46a93dc544..dc1bdc64b2c29 100644 --- a/x-pack/plugins/maps/public/components/map/mb/view.js +++ b/x-pack/plugins/maps/public/components/map/mb/view.js @@ -9,10 +9,21 @@ import React from 'react'; import ReactDOM from 'react-dom'; import { ResizeChecker } from 'ui/resize_checker'; import { syncLayerOrder, removeOrphanedSourcesAndLayers, createMbMapInstance } from './utils'; -import { DECIMAL_DEGREES_PRECISION, FEATURE_ID_PROPERTY_NAME, ZOOM_PRECISION } from '../../../../common/constants'; +import { + DECIMAL_DEGREES_PRECISION, + FEATURE_ID_PROPERTY_NAME, + ZOOM_PRECISION +} from '../../../../common/constants'; import mapboxgl from 'mapbox-gl'; +import MapboxDraw from '@mapbox/mapbox-gl-draw'; +import DrawRectangle from 'mapbox-gl-draw-rectangle-mode'; import { FeatureTooltip } from '../feature_tooltip'; +import { DRAW_TYPE } from '../../../actions/store_actions'; +import { filterBarQueryFilter } from '../../../kibana_services'; +import { createShapeFilterWithMeta, createExtentFilterWithMeta } from '../../../elasticsearch_geo_utils'; +const mbDrawModes = MapboxDraw.modes; +mbDrawModes.draw_rectangle = DrawRectangle; const TOOLTIP_TYPE = { HOVER: 'HOVER', @@ -21,6 +32,21 @@ const TOOLTIP_TYPE = { export class MBMapContainer extends React.Component { + + state = { + isDrawingFilter: false + }; + + static getDerivedStateFromProps(nextProps, prevState) { + const nextIsDrawingFilter = nextProps.drawState !== null; + if (nextIsDrawingFilter === prevState.isDrawingFilter) { + return null; + } + return { + isDrawingFilter: nextIsDrawingFilter + }; + } + constructor() { super(); this._mbMap = null; @@ -29,22 +55,69 @@ export class MBMapContainer extends React.Component { closeButton: false, closeOnClick: false, }); + this._mbDrawControl = new MapboxDraw({ + displayControlsDefault: false, + modes: mbDrawModes + }); + this._mbDrawControlAdded = false; } _onTooltipClose = () => { this.props.setTooltipState(null); }; + _onDraw = async (e) => { + + if (!e.features.length) { + return; + } + const { geoField, geoFieldType, indexPatternId, drawType } = this.props.drawState; + this.props.disableDrawState(); + + + let filter; + if (drawType === DRAW_TYPE.POLYGON) { + filter = createShapeFilterWithMeta(e.features[0].geometry, indexPatternId, geoField, geoFieldType); + } else if (drawType === DRAW_TYPE.BOUNDS) { + const coordinates = e.features[0].geometry.coordinates[0]; + const extent = { + minLon: coordinates[0][0], + minLat: coordinates[0][1], + maxLon: coordinates[0][0], + maxLat: coordinates[0][1] + }; + for (let i = 1; i < coordinates.length; i++) { + extent.minLon = Math.min(coordinates[i][0], extent.minLon); + extent.minLat = Math.min(coordinates[i][1], extent.minLat); + extent.maxLon = Math.max(coordinates[i][0], extent.maxLon); + extent.maxLat = Math.max(coordinates[i][1], extent.maxLat); + } + filter = createExtentFilterWithMeta(extent, indexPatternId, geoField, geoFieldType); + } + + if (!filter) { + return; + } + + filterBarQueryFilter.addFilters([filter]); + }; + _debouncedSync = _.debounce(() => { if (this._isMounted) { this._syncMbMapWithLayerList(); this._syncMbMapWithInspector(); + this._syncDrawControl(); } }, 256); _lockTooltip = (e) => { + if (this.state.isDrawingFilter) { + //ignore click events when in draw mode + return; + } + this._updateHoverTooltipState.cancel();//ignore any possible moves const features = this._getFeaturesUnderPointer(e.point); @@ -54,7 +127,7 @@ export class MBMapContainer extends React.Component { } const targetFeature = features[0]; - const layer = this._getLayer(targetFeature.layer.id); + const layer = this._getLayerByMbLayerId(targetFeature.layer.id); const popupAnchorLocation = this._justifyAnchorLocation(e.lngLat, targetFeature); this.props.setTooltipState({ type: TOOLTIP_TYPE.LOCKED, @@ -66,6 +139,11 @@ export class MBMapContainer extends React.Component { _updateHoverTooltipState = _.debounce((e) => { + if (this.state.isDrawingFilter) { + //ignore hover events when in draw mode + return; + } + if (this.props.tooltipState && this.props.tooltipState.type === TOOLTIP_TYPE.LOCKED) { //ignore hover events when tooltip is locked return; @@ -85,7 +163,7 @@ export class MBMapContainer extends React.Component { } } - const layer = this._getLayer(targetFeature.layer.id); + const layer = this._getLayerByMbLayerId(targetFeature.layer.id); const popupAnchorLocation = this._justifyAnchorLocation(e.lngLat, targetFeature); this.props.setTooltipState({ @@ -97,6 +175,7 @@ export class MBMapContainer extends React.Component { }, 100); + _justifyAnchorLocation(mbLngLat, targetFeature) { let popupAnchorLocation = [mbLngLat.lng, mbLngLat.lat]; // default popup location to mouse location if (targetFeature.geometry.type === 'Point') { @@ -195,6 +274,30 @@ export class MBMapContainer extends React.Component { this.props.onMapDestroyed(); } + _removeDrawControl() { + if (!this._mbDrawControlAdded) { + return; + } + + this._mbMap.getCanvas().style.cursor = ''; + this._mbMap.off('draw.create', this._onDraw); + this._mbMap.removeControl(this._mbDrawControl); + this._mbDrawControlAdded = false; + + } + + _updateDrawControl() { + if (!this._mbDrawControlAdded) { + this._mbMap.addControl(this._mbDrawControl); + this._mbDrawControlAdded = true; + this._mbMap.getCanvas().style.cursor = 'crosshair'; + this._mbMap.on('draw.create', this._onDraw); + } + const mbDrawMode = this.props.drawState.drawType === DRAW_TYPE.POLYGON ? + this._mbDrawControl.modes.DRAW_POLYGON : 'draw_rectangle'; + this._mbDrawControl.changeMode(mbDrawMode); + } + async _initializeMap() { this._mbMap = await createMbMapInstance({ @@ -293,6 +396,14 @@ export class MBMapContainer extends React.Component { } } + _syncDrawControl() { + if (this.state.isDrawingFilter) { + this._updateDrawControl(); + } else { + this._removeDrawControl(); + } + } + _syncMbMapWithMapState = () => { const { isMapReady, @@ -326,7 +437,13 @@ export class MBMapContainer extends React.Component { }; - _getLayer(mbLayerId) { + _getLayerById(layerId) { + return this.props.layerList.find((layer) => { + return layer.getId() === layerId; + }); + } + + _getLayerByMbLayerId(mbLayerId) { return this.props.layerList.find((layer) => { const mbLayerIds = layer.getMbLayerIds(); return mbLayerIds.indexOf(mbLayerId) > -1; diff --git a/x-pack/plugins/maps/public/components/toolbar_overlay/_index.scss b/x-pack/plugins/maps/public/components/toolbar_overlay/_index.scss new file mode 100644 index 0000000000000..da662d99d080d --- /dev/null +++ b/x-pack/plugins/maps/public/components/toolbar_overlay/_index.scss @@ -0,0 +1,17 @@ +.mapToolbarOverlay { + position: absolute; + top: ($euiSizeM * 2) + ($euiSizeXL * 2); // Position and height of mapbox controls plus margin + left: $euiSizeM; + z-index: 2; // Sit on top of mapbox controls shadow +} + +.mapToolbarOverlay__button { + @include size($euiSizeXL); + background-color: $euiColorEmptyShade !important; + + &:enabled, + &:enabled:hover, + &:enabled:focus { + @include euiBottomShadowLarge; + } +} diff --git a/x-pack/plugins/maps/public/components/toolbar_overlay/index.js b/x-pack/plugins/maps/public/components/toolbar_overlay/index.js new file mode 100644 index 0000000000000..7c5b24a611511 --- /dev/null +++ b/x-pack/plugins/maps/public/components/toolbar_overlay/index.js @@ -0,0 +1,31 @@ +/* + * 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 { connect } from 'react-redux'; +import { ToolbarOverlay } from './view'; +import { getDrawState, getUniqueIndexPatternIds } from '../../selectors/map_selectors'; +import { getIsFilterable } from '../../store/ui'; +import { updateDrawState } from '../../actions/store_actions'; + + +function mapStateToProps(state = {}) { + return { + isFilterable: getIsFilterable(state), + drawState: getDrawState(state), + uniqueIndexPatternIds: getUniqueIndexPatternIds(state) + }; +} + +function mapDispatchToProps(dispatch) { + return { + initiateDraw: (options) => { + dispatch(updateDrawState(options)); + } + }; +} + +const connectedToolbarOverlay = connect(mapStateToProps, mapDispatchToProps)(ToolbarOverlay); +export { connectedToolbarOverlay as ToolbarOverlay }; diff --git a/x-pack/plugins/maps/public/components/toolbar_overlay/view.js b/x-pack/plugins/maps/public/components/toolbar_overlay/view.js new file mode 100644 index 0000000000000..9b8c81a828fef --- /dev/null +++ b/x-pack/plugins/maps/public/components/toolbar_overlay/view.js @@ -0,0 +1,282 @@ +/* + * 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 React, { Fragment } from 'react'; +import { + EuiFlexGroup, + EuiFlexItem, + EuiButtonIcon, + EuiPopover, + EuiContextMenu, + EuiSelectable, + EuiHighlight, + EuiTextColor, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { getIndexPatternsFromIds } from '../../index_pattern_util'; +import _ from 'lodash'; +import { DRAW_TYPE } from '../../actions/store_actions'; +import { ES_GEO_FIELD_TYPE } from '../../../common/constants'; + +const RESET_STATE = { + isPopoverOpen: false, + drawType: null +}; + +export class ToolbarOverlay extends React.Component { + + + state = { + isPopoverOpen: false, + uniqueIndexPatternsAndGeoFields: [], + drawType: null + }; + + _toggleToolbar = () => { + if (!this._isMounted) { + return; + } + this.setState(prevState => ({ + isPopoverOpen: !prevState.isPopoverOpen, + drawType: null + })); + }; + + _closePopover = () => { + if (!this._isMounted) { + return; + } + this.setState(RESET_STATE); + }; + + _onIndexPatternSelection = (options) => { + if (!this._isMounted) { + return; + } + + const selection = options.find((option) => option.checked); + const drawType = this.state.drawType; + this.setState(RESET_STATE, () => { + if (drawType) { + this.props.initiateDraw({ drawType: drawType, ...selection.value }); + } + }); + }; + + _activateDrawForFirstIndexPattern = (drawType) => { + if (!this._isMounted) { + return; + } + const indexPatternAndGeofield = this.state.uniqueIndexPatternsAndGeoFields[0]; + this.setState(RESET_STATE, () => { + this.props.initiateDraw({ drawType: drawType, ...indexPatternAndGeofield }); + }); + }; + + componentDidMount() { + this._isMounted = true; + } + + componentWillUnmount() { + this._isMounted = false; + } + + async _getuniqueIndexPatternAndFieldCombos() { + try { + const indexPatterns = await getIndexPatternsFromIds(this.props.uniqueIndexPatternIds); + const uniqueIndexPatternsAndGeofields = []; + indexPatterns.forEach((indexPattern) => { + indexPattern.fields.forEach(field => { + if (field.type === ES_GEO_FIELD_TYPE.GEO_POINT || field.type === ES_GEO_FIELD_TYPE.GEO_SHAPE) { + uniqueIndexPatternsAndGeofields.push({ + geoField: field.name, + geoFieldType: field.type, + indexPatternTitle: indexPattern.title, + indexPatternId: indexPattern.id + }); + } + }); + }); + if (this._isMounted && !_.isEqual(this.state.uniqueIndexPatternsAndGeoFields, uniqueIndexPatternsAndGeofields)) { + this.setState({ + uniqueIndexPatternsAndGeoFields: uniqueIndexPatternsAndGeofields + }); + } + } catch(e) { + // swallow errors. + // the Layer-TOC will indicate which layers are disfunctional on a per-layer basis + return []; + } + } + + componentDidUpdate() { + this._getuniqueIndexPatternAndFieldCombos(); + } + + _getDrawActionsPanel() { + + const drawPolygonAction = { + name: i18n.translate('xpack.maps.toolbarOverlay.drawShapeLabel', { + defaultMessage: 'Draw shape to filter data', + }), + }; + + const drawBoundsAction = { + name: i18n.translate('xpack.maps.toolbarOverlay.drawBoundsLabel', { + defaultMessage: 'Draw bounds to filter data', + }), + }; + + if (this.state.uniqueIndexPatternsAndGeoFields.length === 1) { + drawPolygonAction.onClick = () => this._activateDrawForFirstIndexPattern(DRAW_TYPE.POLYGON); + drawBoundsAction.onClick = () => this._activateDrawForFirstIndexPattern(DRAW_TYPE.BOUNDS); + } else { + drawPolygonAction.panel = this._getIndexPatternSelectionPanel(1); + drawPolygonAction.onClick = () => { + this.setState({ drawType: DRAW_TYPE.POLYGON }); + }; + drawBoundsAction.panel = this._getIndexPatternSelectionPanel(2); + drawBoundsAction.onClick = () => { + this.setState({ drawType: DRAW_TYPE.BOUNDS }); + }; + } + + return flattenPanelTree({ + id: 0, + title: i18n.translate('xpack.maps.toolbarOverlay.tools.toolbarTitle', { + defaultMessage: 'Tools', + }), + items: [drawPolygonAction, drawBoundsAction] + }); + } + + _getIndexPatternSelectionPanel(id) { + const options = this.state.uniqueIndexPatternsAndGeoFields.map((indexPatternAndGeoField) => { + return { + label: `${indexPatternAndGeoField.indexPatternTitle} : ${indexPatternAndGeoField.geoField}`, + value: indexPatternAndGeoField + }; + }); + + const renderGeoField = (option, searchValue) => { + return ( + + + + {option.value.indexPatternTitle} + + +
+ + {option.value.geoField} + +
+ ); + }; + + const indexPatternSelection = ( + + {(list, search) => ( +
+ {search} + {list} +
+ )} +
+ ); + + return { + id: id, + title: i18n.translate('xpack.maps.toolbarOverlay.geofield.toolbarTitle', { + defaultMessage: 'Select geo field', + }), + content: indexPatternSelection + }; + } + + _renderToolbarButton() { + return ( + + ); + } + + render() { + + if ( + !this.props.isFilterable || + !this.state.uniqueIndexPatternsAndGeoFields.length + ) { + return null; + } + + return ( + + + + + + + + ); + } +} + + +function flattenPanelTree(tree, array = []) { + array.push(tree); + + if (tree.items) { + tree.items.forEach(item => { + if (item.panel) { + flattenPanelTree(item.panel, array); + item.panel = item.panel.id; + } + }); + } + + return array; +} diff --git a/x-pack/plugins/maps/public/elasticsearch_geo_utils.js b/x-pack/plugins/maps/public/elasticsearch_geo_utils.js index f1d16972b7707..9cf06bf814b77 100644 --- a/x-pack/plugins/maps/public/elasticsearch_geo_utils.js +++ b/x-pack/plugins/maps/public/elasticsearch_geo_utils.js @@ -6,6 +6,7 @@ import _ from 'lodash'; import { i18n } from '@kbn/i18n'; +import { DECIMAL_DEGREES_PRECISION, ES_GEO_FIELD_TYPE } from '../common/constants'; /** * Converts Elasticsearch search results into GeoJson FeatureCollection @@ -25,9 +26,9 @@ export function hitsToGeoJson(hits, flattenHit, geoFieldName, geoFieldType) { const properties = flattenHit(hits[i]); tmpGeometriesAccumulator.length = 0;//truncate accumulator - if (geoFieldType === 'geo_point') { + if (geoFieldType === ES_GEO_FIELD_TYPE.GEO_POINT) { geoPointToGeometry(properties[geoFieldName], tmpGeometriesAccumulator); - } else if (geoFieldType === 'geo_shape') { + } else if (geoFieldType === ES_GEO_FIELD_TYPE.GEO_SHAPE) { geoShapeToGeometry(properties[geoFieldName], tmpGeometriesAccumulator); } else { const errorMessage = i18n.translate('xpack.maps.elasticsearch_geo_utils.unsupportedFieldTypeErrorMessage', { @@ -184,8 +185,7 @@ const BOTTOM_RIGHT_INDEX = 2; export function createExtentFilter(mapExtent, geoFieldName, geoFieldType) { const safePolygon = convertMapExtentToPolygon(mapExtent); - - if (geoFieldType === 'geo_point') { + if (geoFieldType === ES_GEO_FIELD_TYPE.GEO_POINT) { const verticies = safePolygon.coordinates[POLYGON_COORDINATES_EXTERIOR_INDEX]; return { geo_bounding_box: { @@ -195,7 +195,7 @@ export function createExtentFilter(mapExtent, geoFieldName, geoFieldType) { } } }; - } else if (geoFieldType === 'geo_shape') { + } else if (geoFieldType === ES_GEO_FIELD_TYPE.GEO_SHAPE) { return { geo_shape: { [geoFieldName]: { @@ -205,7 +205,7 @@ export function createExtentFilter(mapExtent, geoFieldName, geoFieldType) { } }; } else { - const errorMessage = i18n.translate('xpack.maps.elasticsearch_geo_utils.unsupportedGeoFieldTypeErrorMessage', { + const errorMessage = i18n.translate('xpack.maps.elasticsearch_geo_utils.extent.unsupportedGeoFieldTypeErrorMessage', { defaultMessage: `Unsupported field type, expected: geo_shape or geo_point, you provided: {geoFieldType}`, values: { geoFieldType } }); @@ -213,6 +213,85 @@ export function createExtentFilter(mapExtent, geoFieldName, geoFieldType) { } } + +export function createExtentFilterWithMeta(mapExtent, indexPatternId, geoFieldName, geoFieldType) { + + const roundedExtent = { + minLon: _.round(mapExtent.minLon, DECIMAL_DEGREES_PRECISION), + minLat: _.round(mapExtent.minLat, DECIMAL_DEGREES_PRECISION), + maxLon: _.round(mapExtent.maxLon, DECIMAL_DEGREES_PRECISION), + maxLat: _.round(mapExtent.maxLat, DECIMAL_DEGREES_PRECISION) + }; + + const filter = createExtentFilter(roundedExtent, geoFieldName, geoFieldType); + filter.meta = { + negate: false, + index: indexPatternId, + alias: i18n.translate('xpack.maps.elasticsearch_geo_utils.extentFilter.aliasTitle', { + defaultMessage: `extent at {coordinate}`, + values: { + coordinate: `[${roundedExtent.minLon}, ${roundedExtent.minLat}, ${roundedExtent.maxLon}, ${roundedExtent.maxLat}]` + } + }) + }; + return filter; +} + +export function createShapeFilterWithMeta(geojsonPolygon, indexPatternId, geoFieldName, geoFieldType) { + + const filter = { + meta: { + negate: false, + index: indexPatternId, + alias: i18n.translate('xpack.maps.elasticsearch_geo_utils.shapeFilter.aliasTitle', { + defaultMessage: `shape at {coordinate}`, + values: { + // eslint-disable-next-line max-len + coordinate: `${_.round(geojsonPolygon.coordinates[0][0][0], DECIMAL_DEGREES_PRECISION)}, ${_.round(geojsonPolygon.coordinates[0][0][1], DECIMAL_DEGREES_PRECISION)}` + } + }) + } + }; + + if (geoFieldType === ES_GEO_FIELD_TYPE.GEO_POINT) { + const pointsArray = geojsonPolygon.coordinates[0].map(coordinatePair => { + return { + lon: _.round(coordinatePair[0], DECIMAL_DEGREES_PRECISION), + lat: _.round(coordinatePair[1], DECIMAL_DEGREES_PRECISION) + }; + }); + filter.geo_polygon = { + ignore_unmapped: true, + [geoFieldName]: { + points: pointsArray + } + }; + } else if (geoFieldType === ES_GEO_FIELD_TYPE.GEO_SHAPE) { + const geojsonCoordinateArray = geojsonPolygon.coordinates[0].map(coordinatePair => { + return [_.round(coordinatePair[0], DECIMAL_DEGREES_PRECISION), _.round(coordinatePair[1], DECIMAL_DEGREES_PRECISION)]; + }); + filter.geo_shape = { + ignore_unmapped: true, + [geoFieldName]: { + shape: { + type: 'Polygon', + coordinates: [geojsonCoordinateArray] + }, + relation: 'INTERSECTS' + } + }; + } else { + const errorMessage = i18n.translate('xpack.maps.elasticsearch_geo_utils.shape.unsupportedGeoFieldTypeErrorMessage', { + defaultMessage: `Unsupported field type, expected: geo_shape or geo_point, you provided: {geoFieldType}`, + values: { geoFieldType } + }); + throw new Error(errorMessage); + } + return filter; +} + + + function formatEnvelopeAsPolygon({ maxLat, maxLon, minLat, minLon }) { // GeoJSON mandates that the outer polygon must be counterclockwise to avoid ambiguous polygons // when the shape crosses the dateline diff --git a/x-pack/plugins/maps/public/index.js b/x-pack/plugins/maps/public/index.js index 8d4ccb2910a68..e663cbf7cd9d8 100644 --- a/x-pack/plugins/maps/public/index.js +++ b/x-pack/plugins/maps/public/index.js @@ -24,8 +24,6 @@ import 'ui/autoload/styles'; import 'ui/autoload/all'; import 'react-vis/dist/style.css'; -import 'mapbox-gl/dist/mapbox-gl.css'; - import './angular/services/gis_map_saved_object_loader'; import './angular/map_controller'; import listingTemplate from './angular/listing_ng_wrapper.html'; diff --git a/x-pack/plugins/maps/public/index_pattern_util.js b/x-pack/plugins/maps/public/index_pattern_util.js new file mode 100644 index 0000000000000..705371c433a4e --- /dev/null +++ b/x-pack/plugins/maps/public/index_pattern_util.js @@ -0,0 +1,21 @@ +/* + * 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 { indexPatternService } from './kibana_services'; + +export async function getIndexPatternsFromIds(indexPatternIds) { + + const promises = []; + indexPatternIds.forEach((id) => { + const indexPatternPromise = indexPatternService.get(id); + if (indexPatternPromise) { + promises.push(indexPatternPromise); + } + }); + + return await Promise.all(promises); + +} diff --git a/x-pack/plugins/maps/public/selectors/map_selectors.js b/x-pack/plugins/maps/public/selectors/map_selectors.js index 392912709f5db..d6548b71104db 100644 --- a/x-pack/plugins/maps/public/selectors/map_selectors.js +++ b/x-pack/plugins/maps/public/selectors/map_selectors.js @@ -113,6 +113,8 @@ export const getQuery = ({ map }) => map.mapState.query; export const getFilters = ({ map }) => map.mapState.filters; +export const getDrawState = ({ map }) => map.mapState.drawState; + export const getRefreshConfig = ({ map }) => { if (map.mapState.refreshConfig) { return map.mapState.refreshConfig; diff --git a/x-pack/plugins/maps/public/shared/layers/sources/es_geo_grid_source/create_source_editor.js b/x-pack/plugins/maps/public/shared/layers/sources/es_geo_grid_source/create_source_editor.js index 6ad05379a9f50..b412a5b0acf29 100644 --- a/x-pack/plugins/maps/public/shared/layers/sources/es_geo_grid_source/create_source_editor.js +++ b/x-pack/plugins/maps/public/shared/layers/sources/es_geo_grid_source/create_source_editor.js @@ -20,9 +20,10 @@ import { EuiComboBox, EuiSpacer, } from '@elastic/eui'; +import { ES_GEO_FIELD_TYPE } from '../../../../../common/constants'; function filterGeoField({ type }) { - return ['geo_point'].includes(type); + return [ES_GEO_FIELD_TYPE.GEO_POINT].includes(type); } const requestTypeOptions = [ @@ -206,7 +207,7 @@ export class CreateSourceEditor extends Component { placeholder={i18n.translate('xpack.maps.source.esGeoGrid.indexPatternPlaceholder', { defaultMessage: 'Select index pattern' })} - fieldTypes={['geo_point']} + fieldTypes={[ES_GEO_FIELD_TYPE.GEO_POINT]} onNoIndexPatterns={this._onNoIndexPatterns} /> diff --git a/x-pack/plugins/maps/public/shared/layers/sources/es_geo_grid_source/es_geo_grid_source.js b/x-pack/plugins/maps/public/shared/layers/sources/es_geo_grid_source/es_geo_grid_source.js index a5f86290bc054..469504b4fca4a 100644 --- a/x-pack/plugins/maps/public/shared/layers/sources/es_geo_grid_source/es_geo_grid_source.js +++ b/x-pack/plugins/maps/public/shared/layers/sources/es_geo_grid_source/es_geo_grid_source.js @@ -176,9 +176,7 @@ export class ESGeoGridSource extends AbstractESSource { } async getGeoJsonWithMeta(layerName, searchFilters) { - const featureCollection = await this.getGeoJsonPoints(layerName, searchFilters); - return { data: featureCollection, meta: { diff --git a/x-pack/plugins/maps/public/shared/layers/sources/es_search_source/create_source_editor.js b/x-pack/plugins/maps/public/shared/layers/sources/es_search_source/create_source_editor.js index 3c54163e284c8..b52c0de0e632c 100644 --- a/x-pack/plugins/maps/public/shared/layers/sources/es_search_source/create_source_editor.js +++ b/x-pack/plugins/maps/public/shared/layers/sources/es_search_source/create_source_editor.js @@ -16,11 +16,11 @@ import { NoIndexPatternCallout } from '../../../components/no_index_pattern_call import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; import { kfetch } from 'ui/kfetch'; -import { GIS_API_PATH } from '../../../../../common/constants'; +import { ES_GEO_FIELD_TYPE, GIS_API_PATH } from '../../../../../common/constants'; import { DEFAULT_ES_DOC_LIMIT, DEFAULT_FILTER_BY_MAP_BOUNDS } from './constants'; function filterGeoField(field) { - return ['geo_point', 'geo_shape'].includes(field.type); + return [ES_GEO_FIELD_TYPE.GEO_POINT, ES_GEO_FIELD_TYPE.GEO_SHAPE].includes(field.type); } const RESET_INDEX_PATTERN_STATE = { indexPattern: undefined, @@ -252,7 +252,7 @@ export class CreateSourceEditor extends Component { placeholder={i18n.translate('xpack.maps.source.esSearch.selectIndexPatternPlaceholder', { defaultMessage: 'Select index pattern' })} - fieldTypes={['geo_point', 'geo_shape']} + fieldTypes={[ES_GEO_FIELD_TYPE.GEO_POINT, ES_GEO_FIELD_TYPE.GEO_SHAPE]} onNoIndexPatterns={this._onNoIndexPatterns} /> diff --git a/x-pack/plugins/maps/public/shared/layers/sources/es_source.js b/x-pack/plugins/maps/public/shared/layers/sources/es_source.js index 93a37eb4ca0ee..db340a3485557 100644 --- a/x-pack/plugins/maps/public/shared/layers/sources/es_source.js +++ b/x-pack/plugins/maps/public/shared/layers/sources/es_source.js @@ -19,6 +19,7 @@ import { ESAggMetricTooltipProperty } from '../tooltips/es_aggmetric_tooltip_pro import uuid from 'uuid/v4'; import { copyPersistentState } from '../../../store/util'; +import { ES_GEO_FIELD_TYPE } from '../../../../common/constants'; export class AbstractESSource extends AbstractVectorSource { @@ -245,7 +246,7 @@ export class AbstractESSource extends AbstractVectorSource { const geoField = await this._getGeoField(); // geo_bounds aggregation only supports geo_point // there is currently no backend support for getting bounding box of geo_shape field - return geoField.type !== 'geo_shape'; + return geoField.type !== ES_GEO_FIELD_TYPE.GEO_SHAPE; } catch (error) { return false; } diff --git a/x-pack/plugins/maps/public/shared/layers/sources/source.js b/x-pack/plugins/maps/public/shared/layers/sources/source.js index e28b46cba8497..82627cdc1c82e 100644 --- a/x-pack/plugins/maps/public/shared/layers/sources/source.js +++ b/x-pack/plugins/maps/public/shared/layers/sources/source.js @@ -16,10 +16,6 @@ export class AbstractSource { throw new Error('Must implement Source.createDescriptor'); } - static renderDropdownDisplayOption() { - throw new Error('Must implement Source.renderDropdownDisplayOption'); - } - constructor(descriptor, inspectorAdapters) { this._descriptor = descriptor; this._inspectorAdapters = inspectorAdapters; diff --git a/x-pack/plugins/maps/public/store/map.js b/x-pack/plugins/maps/public/store/map.js index d4439a18ada98..f6dcea568cc8f 100644 --- a/x-pack/plugins/maps/public/store/map.js +++ b/x-pack/plugins/maps/public/store/map.js @@ -38,6 +38,7 @@ import { REMOVE_TRACKED_LAYER_STATE, UPDATE_SOURCE_DATA_REQUEST, SET_TOOLTIP_STATE, + UPDATE_DRAW_STATE, SET_SCROLL_ZOOM } from '../actions/store_actions'; @@ -102,17 +103,26 @@ const INITIAL_STATE = { filters: [], refreshConfig: null, refreshTimerLastTriggeredAt: null, + drawState: null }, selectedLayerId: null, __transientLayerId: null, layerList: [], - waitingForMapReadyLayerList: [], + waitingForMapReadyLayerList: [] }; export function map(state = INITIAL_STATE, action) { switch (action.type) { + case UPDATE_DRAW_STATE: + return { + ...state, + mapState: { + ...state.mapState, + drawState: action.drawState + } + }; case REMOVE_TRACKED_LAYER_STATE: return removeTrackedLayerState(state, action.layerId); case TRACK_CURRENT_LAYER_STATE: diff --git a/yarn.lock b/yarn.lock index 9fe13192de7ac..ef977303a9d79 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1938,23 +1938,76 @@ dependencies: core-js "^2.5.7" -"@mapbox/geojson-area@0.2.2": +"@mapbox/extent@0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@mapbox/extent/-/extent-0.4.0.tgz#3e591f32e1f0c3981c864239f7b0ac06e610f8a9" + integrity sha1-PlkfMuHww5gchkI597CsBuYQ+Kk= + +"@mapbox/geojson-area@0.2.2", "@mapbox/geojson-area@^0.2.1": version "0.2.2" resolved "https://registry.yarnpkg.com/@mapbox/geojson-area/-/geojson-area-0.2.2.tgz#18d7814aa36bf23fbbcc379f8e26a22927debf10" integrity sha1-GNeBSqNr8j+7zDefjiaiKSfevxA= dependencies: wgs84 "0.0.0" +"@mapbox/geojson-coords@0.0.0": + version "0.0.0" + resolved "https://registry.yarnpkg.com/@mapbox/geojson-coords/-/geojson-coords-0.0.0.tgz#4847a5b96059666e527a2139e75e35d84fd58f50" + integrity sha1-SEeluWBZZm5SeiE551412E/Vj1A= + dependencies: + "@mapbox/geojson-normalize" "0.0.1" + geojson-flatten "~0.2.1" + +"@mapbox/geojson-extent@^0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@mapbox/geojson-extent/-/geojson-extent-0.3.2.tgz#a1bdb2015afd0e031c18c3f29f7eb229e4e1950f" + integrity sha1-ob2yAVr9DgMcGMPyn36yKeThlQ8= + dependencies: + "@mapbox/extent" "0.4.0" + "@mapbox/geojson-coords" "0.0.0" + rw "~0.1.4" + traverse "~0.6.6" + +"@mapbox/geojson-normalize@0.0.1": + version "0.0.1" + resolved "https://registry.yarnpkg.com/@mapbox/geojson-normalize/-/geojson-normalize-0.0.1.tgz#1da1e6b3a7add3ad29909b30f438f60581b7cd80" + integrity sha1-HaHms6et060pkJsw9Dj2BYG3zYA= + "@mapbox/geojson-types@^1.0.2": version "1.0.2" resolved "https://registry.yarnpkg.com/@mapbox/geojson-types/-/geojson-types-1.0.2.tgz#9aecf642cb00eab1080a57c4f949a65b4a5846d6" integrity sha512-e9EBqHHv3EORHrSfbR9DqecPNn+AmuAoQxV6aL8Xu30bJMJR1o8PZLZzpk1Wq7/NfCbuhmakHTPYRhoqLsXRnw== +"@mapbox/geojsonhint@^2.0.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@mapbox/geojsonhint/-/geojsonhint-2.2.0.tgz#75ca94706e9a56e6debf4e1c78fabdc67978b883" + integrity sha512-8qQYRB+/2z2JsN5s6D0WAnpo69+3V3nvJsSFLwMB1dsaWz1V4oZeuoje9srbYAxxL8PXCwIywfhYa3GxOkBv5Q== + dependencies: + concat-stream "^1.6.1" + jsonlint-lines "1.7.1" + minimist "1.2.0" + vfile "^4.0.0" + vfile-reporter "^5.1.1" + "@mapbox/jsonlint-lines-primitives@^2.0.2": version "2.0.2" resolved "https://registry.yarnpkg.com/@mapbox/jsonlint-lines-primitives/-/jsonlint-lines-primitives-2.0.2.tgz#ce56e539f83552b58d10d672ea4d6fc9adc7b234" integrity sha1-zlblOfg1UrWNENZy6k1vya3HsjQ= +"@mapbox/mapbox-gl-draw@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@mapbox/mapbox-gl-draw/-/mapbox-gl-draw-1.1.1.tgz#b88a7919c8de04eb7946885e747e22049c3a3138" + integrity sha512-Xg+R0VUXKdXC7MaSSMiWfz96eLssJZa28/D6MxK/Xc19G5HvU6w/wytm8EeI28T7Sa2C7FII/0/XOwuAfJgDJw== + dependencies: + "@mapbox/geojson-area" "^0.2.1" + "@mapbox/geojson-extent" "^0.3.2" + "@mapbox/geojson-normalize" "0.0.1" + "@mapbox/geojsonhint" "^2.0.0" + "@mapbox/point-geometry" "0.1.0" + hat "0.0.3" + lodash.isequal "^4.2.0" + xtend "^4.0.1" + "@mapbox/mapbox-gl-supported@^1.4.0": version "1.4.0" resolved "https://registry.yarnpkg.com/@mapbox/mapbox-gl-supported/-/mapbox-gl-supported-1.4.0.tgz#36946b22944fe2cfa43cfafd5ef36fdb54a069e4" @@ -3739,7 +3792,7 @@ resolved "https://registry.yarnpkg.com/@types/type-detect/-/type-detect-4.0.1.tgz#3b0f5ac82ea630090cbf57c57a1bf5a63a29b9b6" integrity sha512-0+S1S9Iq0oJ9w9IaBC5W/z1WsPNDUIAJG+THGmqR4vUAxUPCzIY+dApTvyGsaBUWjafTDL0Dg8Z9+iRuk3/BQA== -"@types/unist@*", "@types/unist@^2.0.0": +"@types/unist@*", "@types/unist@^2.0.0", "@types/unist@^2.0.2": version "2.0.3" resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.3.tgz#9c088679876f374eb5983f150d4787aa6fb32d7e" integrity sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ== @@ -4314,6 +4367,11 @@ JSONStream@1.1.1: jsonparse "^1.1.0" through ">=2.2.7 <3" +"JSV@>= 4.0.x": + version "4.0.2" + resolved "https://registry.yarnpkg.com/JSV/-/JSV-4.0.2.tgz#d077f6825571f82132f9dffaed587b4029feff57" + integrity sha1-0Hf2glVx+CEy+d/67Vh7QCn+/1c= + abab@^1.0.3, abab@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/abab/-/abab-1.0.4.tgz#5faad9c2c07f60dd76770f71cf025b62a63cfd4e" @@ -4779,6 +4837,11 @@ ansi-styles@^3.1.0, ansi-styles@^3.2.0: dependencies: color-convert "^1.9.0" +ansi-styles@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-1.0.0.tgz#cb102df1c56f5123eab8b67cd7b98027a0279178" + integrity sha1-yxAt8cVvUSPquLZ817mAJ6AnkXg= + ansi-wrap@0.1.0, ansi-wrap@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf" @@ -7190,6 +7253,15 @@ chalk@^2.3.0: escape-string-regexp "^1.0.5" supports-color "^5.2.0" +chalk@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-0.4.0.tgz#5199a3ddcd0c1efe23bc08c1b027b06176e0c64f" + integrity sha1-UZmj3c0MHv4jvAjBsCewYXbgxk8= + dependencies: + ansi-styles "~1.0.0" + has-color "~0.1.0" + strip-ansi "~0.1.0" + chalk@~0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/chalk/-/chalk-0.5.1.tgz#663b3a648b68b55d04690d49167aa837858f2174" @@ -8006,7 +8078,7 @@ concat-stream@1.5.1: readable-stream "~2.0.0" typedarray "~0.0.5" -concat-stream@1.6.2, concat-stream@^1.4.6, concat-stream@^1.5.0: +concat-stream@1.6.2, concat-stream@^1.4.6, concat-stream@^1.5.0, concat-stream@^1.6.1: version "1.6.2" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== @@ -12235,6 +12307,14 @@ geojson-area@^0.2.1: dependencies: wgs84 "0.0.0" +geojson-flatten@~0.2.1: + version "0.2.4" + resolved "https://registry.yarnpkg.com/geojson-flatten/-/geojson-flatten-0.2.4.tgz#8f3396f31a0f5b747e39c9e6a14088f43ba4ecfb" + integrity sha512-LiX6Jmot8adiIdZ/fthbcKKPOfWjTQchX/ggHnwMZ2e4b0I243N1ANUos0LvnzepTEsj0+D4fIJ5bKhBrWnAHA== + dependencies: + get-stdin "^6.0.0" + minimist "1.2.0" + geojson-normalize@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/geojson-normalize/-/geojson-normalize-0.0.0.tgz#2dbc3678cd1b31b8179e876bda70cd120dde35c0" @@ -13501,6 +13581,11 @@ has-binary2@~1.0.2: dependencies: isarray "2.0.1" +has-color@~0.1.0: + version "0.1.7" + resolved "https://registry.yarnpkg.com/has-color/-/has-color-0.1.7.tgz#67144a5260c34fc3cca677d041daf52fe7b78b2f" + integrity sha1-ZxRKUmDDT8PMpnfQQdr1L+e3iy8= + has-cors@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/has-cors/-/has-cors-1.1.0.tgz#5e474793f7ea9843d1bb99c23eef49ff126fff39" @@ -13644,6 +13729,11 @@ hastscript@^5.0.0: property-information "^5.0.1" space-separated-tokens "^1.0.0" +hat@0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/hat/-/hat-0.0.3.tgz#bb014a9e64b3788aed8005917413d4ff3d502d8a" + integrity sha1-uwFKnmSzeIrtgAWRdBPU/z1QLYo= + hawk@~3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4" @@ -16205,6 +16295,14 @@ jsonify@~0.0.0: resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= +jsonlint-lines@1.7.1: + version "1.7.1" + resolved "https://registry.yarnpkg.com/jsonlint-lines/-/jsonlint-lines-1.7.1.tgz#507de680d3fb8c4be1641cc57d6f679f29f178ff" + integrity sha1-UH3mgNP7jEvhZBzFfW9nnynxeP8= + dependencies: + JSV ">= 4.0.x" + nomnom ">= 1.5.x" + jsonparse@^1.1.0: version "1.3.1" resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" @@ -17058,7 +17156,7 @@ lodash.isempty@^4.4.0: resolved "https://registry.yarnpkg.com/lodash.isempty/-/lodash.isempty-4.4.0.tgz#6f86cbedd8be4ec987be9aaf33c9684db1b31e7e" integrity sha1-b4bL7di+TsmHvpqvM8loTbGzHn4= -lodash.isequal@^4.0.0, lodash.isequal@^4.1.1, lodash.isequal@^4.5.0: +lodash.isequal@^4.0.0, lodash.isequal@^4.1.1, lodash.isequal@^4.2.0, lodash.isequal@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA= @@ -17571,6 +17669,11 @@ map-visit@^1.0.0: dependencies: object-visit "^1.0.0" +mapbox-gl-draw-rectangle-mode@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mapbox-gl-draw-rectangle-mode/-/mapbox-gl-draw-rectangle-mode-1.0.4.tgz#42987d68872a5fb5cc5d76d3375ee20cd8bab8f7" + integrity sha512-BdF6nwEK2p8n9LQoMPzBO8LhddW1fe+d5vK8HQIei+4VcRnUbKNsEj7Z15FsJxCHzsc2BQKXbESx5GaE8x0imQ== + mapbox-gl@0.52.0: version "0.52.0" resolved "https://registry.yarnpkg.com/mapbox-gl/-/mapbox-gl-0.52.0.tgz#a43b61caa339ae28e43c87ecfbe9ce4032795859" @@ -18772,6 +18875,14 @@ nodemailer@^4.6.4: resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-4.6.4.tgz#f0d72d0c6a6ec5f4369fa8f4bf5127a31baa2014" integrity sha512-SD4uuX7NMzZ5f5m1XHDd13J4UC3SmdJk8DsmU1g6Nrs5h3x9LcXr6EBPZIqXRJ3LrF7RdklzGhZRF/TuylTcLg== +"nomnom@>= 1.5.x": + version "1.8.1" + resolved "https://registry.yarnpkg.com/nomnom/-/nomnom-1.8.1.tgz#2151f722472ba79e50a76fc125bb8c8f2e4dc2a7" + integrity sha1-IVH3Ikcrp55Qp2/BJbuMjy5Nwqc= + dependencies: + chalk "~0.4.0" + underscore "~1.6.0" + "nopt@2 || 3", nopt@3.x, nopt@~3.0.6: version "3.0.6" resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" @@ -22494,7 +22605,7 @@ repeat-string@^0.2.2: resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-0.2.2.tgz#c7a8d3236068362059a7e4651fc6884e8b1fb4ae" integrity sha1-x6jTI2BoNiBZp+RlH8aITosftK4= -repeat-string@^1.5.2, repeat-string@^1.5.4, repeat-string@^1.6.1: +repeat-string@^1.5.0, repeat-string@^1.5.2, repeat-string@^1.5.4, repeat-string@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= @@ -22979,6 +23090,11 @@ rw@1, rw@^1.3.3: resolved "https://registry.yarnpkg.com/rw/-/rw-1.3.3.tgz#3f862dfa91ab766b14885ef4d01124bfda074fb4" integrity sha1-P4Yt+pGrdmsUiF700BEkv9oHT7Q= +rw@~0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/rw/-/rw-0.1.4.tgz#4903cbd80248ae0ede685bf58fd236a7a9b29a3e" + integrity sha1-SQPL2AJIrg7eaFv1j9I2p6mymj4= + rx-lite-aggregates@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be" @@ -24424,6 +24540,11 @@ strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" +strip-ansi@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-0.1.1.tgz#39e8a98d044d150660abe4a6808acf70bb7bc991" + integrity sha1-OeipjQRNFQZgq+SmgIrPcLt7yZE= + strip-bom-stream@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strip-bom-stream/-/strip-bom-stream-2.0.0.tgz#f87db5ef2613f6968aa545abfe1ec728b6a829ca" @@ -25406,7 +25527,7 @@ tr46@^1.0.0, tr46@^1.0.1: dependencies: punycode "^2.1.0" -traverse@0.6.6: +traverse@0.6.6, traverse@~0.6.6: version "0.6.6" resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.6.6.tgz#cbdf560fd7b9af632502fed40f918c157ea97137" integrity sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc= @@ -26152,6 +26273,11 @@ underscore.string@~3.3.4: sprintf-js "^1.0.3" util-deprecate "^1.0.2" +underscore@~1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.6.0.tgz#8b38b10cacdef63337b8b24e4ff86d45aea529a8" + integrity sha1-izixDKze9jM3uLJOT/htRa6lKag= + underscore@~1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.7.0.tgz#6bbaf0877500d36be34ecaa584e0db9fef035209" @@ -26307,6 +26433,13 @@ unist-util-stringify-position@^1.0.0, unist-util-stringify-position@^1.1.1: resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-1.1.1.tgz#3ccbdc53679eed6ecf3777dd7f5e3229c1b6aa3c" integrity sha1-PMvcU2ee7W7PN3fdf14yKcG2qjw= +unist-util-stringify-position@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-2.0.0.tgz#4c452c0dbcbc509f7bcd366e9a8afd646f9d51ae" + integrity sha512-Uz5negUTrf9zm2ZT2Z9kdOL7Mr7FJLyq3ByqagUi7QZRVK1HnspVazvSqwHt73jj7APHtpuJ4K110Jm8O6/elw== + dependencies: + "@types/unist" "^2.0.2" + unist-util-visit-parents@1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-1.1.2.tgz#f6e3afee8bdbf961c0e6f028ea3c0480028c3d06" @@ -26963,6 +27096,36 @@ vfile-message@^1.0.0: dependencies: unist-util-stringify-position "^1.1.1" +vfile-message@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-2.0.0.tgz#750bbb86fe545988a67e899b329bbcabb73edef6" + integrity sha512-YS6qg6UpBfIeiO+6XlhPOuJaoLvt1Y9g2cmlwqhBOOU0XRV8j5RLeoz72t6PWLvNXq3EBG1fQ05wNPrUoz0deQ== + dependencies: + "@types/unist" "^2.0.2" + unist-util-stringify-position "^1.1.1" + +vfile-reporter@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/vfile-reporter/-/vfile-reporter-5.1.1.tgz#419688c7e9dcaf65ba81bfdb0ad443e9e0248e09" + integrity sha512-A/cfKvfVmeEmAKx1yyOWggCjC/k184Vkl5pVJAw5CEdppHd5FHBVcdyJ1JBSqIdJjJqyhZY4ZD3JycHr/uwmlA== + dependencies: + repeat-string "^1.5.0" + string-width "^2.0.0" + supports-color "^5.4.0" + unist-util-stringify-position "^1.0.0" + vfile-sort "^2.1.2" + vfile-statistics "^1.1.0" + +vfile-sort@^2.1.2: + version "2.2.0" + resolved "https://registry.yarnpkg.com/vfile-sort/-/vfile-sort-2.2.0.tgz#383a8727ec4c5daf37c05683684a5eb686366d39" + integrity sha512-RgxLXVWrJBWb2GuP8FsSkqK7HmbjXjnI8qx3nD6NTWhsWaelaKvJuxfh1F1d1lkCPD7imo4zzi8cf6IOMgaTnQ== + +vfile-statistics@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vfile-statistics/-/vfile-statistics-1.1.2.tgz#c50132627e4669a3afa07c64ff1e7aa7695e8151" + integrity sha512-16wAC9eEGXdsD35LX9m/iXCRIZyX5LIrDgDtAF92rbATSqsBRbC4n05e0Rj5vt3XRpcKu0UJeWnTxWsSyvNZ+w== + vfile@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/vfile/-/vfile-2.3.0.tgz#e62d8e72b20e83c324bc6c67278ee272488bf84a" @@ -26983,6 +27146,17 @@ vfile@^3.0.0, vfile@^3.0.1: unist-util-stringify-position "^1.0.0" vfile-message "^1.0.0" +vfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/vfile/-/vfile-4.0.0.tgz#ebf3b48af9fcde524d5e08d5f75812058a5f78ad" + integrity sha512-WMNeHy5djSl895BqE86D7WqA0Ie5fAIeGCa7V1EqiXyJg5LaGch2SUaZueok5abYQGH6mXEAsZ45jkoILIOlyA== + dependencies: + "@types/unist" "^2.0.2" + is-buffer "^2.0.0" + replace-ext "1.0.0" + unist-util-stringify-position "^2.0.0" + vfile-message "^2.0.0" + vinyl-file@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/vinyl-file/-/vinyl-file-2.0.0.tgz#a7ebf5ffbefda1b7d18d140fcb07b223efb6751a"