From 7762c1d57f4951567778fade6950b2439860bc2c Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Wed, 27 Mar 2019 15:15:00 -0400 Subject: [PATCH] add multiple draw modes --- x-pack/package.json | 1 + .../maps/public/actions/store_actions.js | 22 +--- .../components/draw_control/_index.scss | 4 +- .../public/components/draw_control/index.js | 3 +- .../draw_control/initiate_draw_button.js | 107 ++++++++++++++++ .../public/components/draw_control/view.js | 114 ++++-------------- .../maps/public/components/map/mb/index.js | 6 +- .../maps/public/components/map/mb/view.js | 40 +++--- .../layer_toc/toc_entry/index.js | 7 +- yarn.lock | 5 + 10 files changed, 168 insertions(+), 141 deletions(-) create mode 100644 x-pack/plugins/maps/public/components/draw_control/initiate_draw_button.js diff --git a/x-pack/package.json b/x-pack/package.json index 6bb4348024c4bb4..39b0752ddea7218 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -220,6 +220,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/public/actions/store_actions.js b/x-pack/plugins/maps/public/actions/store_actions.js index 38c963ef757e469..326ed1289f07abc 100644 --- a/x-pack/plugins/maps/public/actions/store_actions.js +++ b/x-pack/plugins/maps/public/actions/store_actions.js @@ -58,6 +58,11 @@ export const DRAW_STATE_TYPE = { ACTIVE: 'ACTIVE' }; +export const DRAW_STATE_DRAW_TYPE = { + BOUNDS: 'BOUNDS', + POLYGON: 'POLYGON' +}; + function getLayerLoadingCallbacks(dispatch, layerId) { return { startLoading: (dataId, requestToken, meta) => dispatch(startDataLoad(layerId, dataId, requestToken, meta)), @@ -623,20 +628,3 @@ export function updateDrawStateWithOptions(type, options) { }); }; } - - -export function updateDrawState(type, layerId) { - return async (dispatch) => { - if (type === DRAW_STATE_TYPE.ACTIVE) { - await dispatch(setTooltipState(null));//tooltips just get in the way - } - dispatch({ - type: UPDATE_DRAW_STATE, - drawState: { - type: type, - layerId: layerId - } - }); - }; -} - diff --git a/x-pack/plugins/maps/public/components/draw_control/_index.scss b/x-pack/plugins/maps/public/components/draw_control/_index.scss index c169c33d8babebe..9f062ba9cf6c6a9 100644 --- a/x-pack/plugins/maps/public/components/draw_control/_index.scss +++ b/x-pack/plugins/maps/public/components/draw_control/_index.scss @@ -1,7 +1,7 @@ .drawControl { position: absolute; - top: 12px; + top: 10px; + width: 200px; padding: 0; - margin: 0 auto; left: 46px; } diff --git a/x-pack/plugins/maps/public/components/draw_control/index.js b/x-pack/plugins/maps/public/components/draw_control/index.js index eea4252d9092cee..5935a3b83e19464 100644 --- a/x-pack/plugins/maps/public/components/draw_control/index.js +++ b/x-pack/plugins/maps/public/components/draw_control/index.js @@ -6,13 +6,12 @@ import { connect } from 'react-redux'; import { DrawControl } from './view'; -import { getDrawState, getLayerList, getUniqueIndexPatternIds } from '../../selectors/map_selectors'; +import { getDrawState, getUniqueIndexPatternIds } from '../../selectors/map_selectors'; import { DRAW_STATE_TYPE, updateDrawStateWithOptions } from '../../actions/store_actions'; import { getIsReadOnly } from '../../store/ui'; function mapStateToProps(state = {}) { return { - layerList: getLayerList(state), isReadOnly: getIsReadOnly(state), drawState: getDrawState(state), uniqueIndexPatternIds: getUniqueIndexPatternIds(state) diff --git a/x-pack/plugins/maps/public/components/draw_control/initiate_draw_button.js b/x-pack/plugins/maps/public/components/draw_control/initiate_draw_button.js new file mode 100644 index 000000000000000..2317677061068af --- /dev/null +++ b/x-pack/plugins/maps/public/components/draw_control/initiate_draw_button.js @@ -0,0 +1,107 @@ +/* + * 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 from 'react'; +import { + EuiButton, + EuiPopover +} from '@elastic/eui'; +import { IpSelectionList } from './ip_selection_list'; +import { DRAW_STATE_TYPE } from '../../actions/store_actions'; +import _ from 'lodash'; +import { getIndexPatternsFromIds } from '../../index_pattern_util'; + +export class InitiateDrawButton extends React.Component { + + state = { + openPopover: false, + uniqueIndexPatternsAndGeoFields: [] + }; + + _openIndexPatternSelection = () => { + if (this._isMounted) { + this.setState({ openPopover: true }); + } + }; + + _closePopover = () => { + if (this._isMounted) { + this.setState({ openPopover: false }); + } + }; + + _onSelect = (e) => { + this._closePopover(); + this.props.initiateDraw(e); + }; + + async _getuniqueIndexPatternAndFieldCombos() { + + const indexPatterns = await getIndexPatternsFromIds(this.props.uniqueIndexPatternIds); + try { + + const uniqueIndexPatternsAndGeofields = []; + indexPatterns.forEach((indexPattern) => { + indexPattern.fields.forEach(field => { + if (field.type === 'geo_point') { + uniqueIndexPatternsAndGeofields.push({ + geoField: field.name, + indexPatternTitle: indexPattern.title, + indexPatternId: indexPattern.id + }); + } + }); + }); + + + if (this._isMounted && !_.isEqual(this.state.uniqueIndexPatternsAndGeoFields, uniqueIndexPatternsAndGeofields)) { + this.setState({ + uniqueIndexPatternsAndGeoFields: uniqueIndexPatternsAndGeofields, + openPopover: false + }); + } + } catch(e) { + console.error(e); + throw e; + } + } + + componentDidMount() { + this._isMounted = true; + } + + componentWillUnmount() { + this._isMounted = false; + } + + componentDidUpdate() { + this._getuniqueIndexPatternAndFieldCombos(); + } + + render() { + return ( + + {this.props.buttonText} + + } + isOpen={this.state.openPopover} + closePopover={this._closePopover} + anchorPosition="downLeft" + > + + + ); + } + +} diff --git a/x-pack/plugins/maps/public/components/draw_control/view.js b/x-pack/plugins/maps/public/components/draw_control/view.js index 41ccf112c66ce7a..1c266f47646c5fb 100644 --- a/x-pack/plugins/maps/public/components/draw_control/view.js +++ b/x-pack/plugins/maps/public/components/draw_control/view.js @@ -5,86 +5,22 @@ */ import React from 'react'; -import _ from 'lodash'; +import { InitiateDrawButton } from './initiate_draw_button'; import { - EuiButton, - EuiPopover + EuiFlexGroup, + EuiFlexItem } from '@elastic/eui'; -import { IpSelectionList } from './ip_selection_list'; -import { DRAW_STATE_TYPE } from '../../actions/store_actions'; -import { getIndexPatternsFromIds } from '../../index_pattern_util'; -export class DrawControl extends React.Component { - - state = { - openPopover: false, - uniqueIndexPatternsAndGeoFields: [] - }; - _openIndexPatternSelection = () => { - if (this._isMounted) { - this.setState({ openPopover: true }); - } - }; +import { DRAW_STATE_DRAW_TYPE } from '../../actions/store_actions'; - _closePopover = () => { - if (this._isMounted) { - this.setState({ openPopover: false }); - } - }; +export class DrawControl extends React.Component { - _onSelect = (e) => { - this._closePopover(); - // this.props.initiateDraw(e.layerId); - this.props.initiateDraw(e); + _initiateDraw = (drawType, e) => { + this.props.initiateDraw({ drawType, ...e }); }; - async _getuniqueIndexPatternAndFieldCombos() { - - const indexPatterns = await getIndexPatternsFromIds(this.props.uniqueIndexPatternIds); - try { - - const uniqueIndexPatternsAndGeofields = []; - indexPatterns.forEach((indexPattern) => { - - indexPattern.fields.forEach(field => { - if (field.type === 'geo_point') { - uniqueIndexPatternsAndGeofields.push({ - geoField: field.name, - indexPatternTitle: indexPattern.title, - indexPatternId: indexPattern.id - }); - } - }); - - }); - - - if (this._isMounted && !_.isEqual(this.state.uniqueIndexPatternsAndGeoFields, uniqueIndexPatternsAndGeofields)) { - this.setState({ - uniqueIndexPatternsAndGeoFields: uniqueIndexPatternsAndGeofields, - openPopover: false - }); - } - } catch(e) { - console.error(e); - throw e; - } - } - - componentDidMount() { - this._isMounted = true; - } - - componentWillUnmount() { - this._isMounted = false; - } - - componentDidUpdate() { - this._getuniqueIndexPatternAndFieldCombos(); - } - render() { if (!this.props.isReadOnly) { @@ -93,24 +29,24 @@ export class DrawControl extends React.Component { return (
- - Draw - - } - isOpen={this.state.openPopover} - closePopover={this._closePopover} - anchorPosition="downLeft" - > - - + + + this._initiateDraw(DRAW_STATE_DRAW_TYPE.POLYGON, e)} + uniqueIndexPatternIds={this.props.uniqueIndexPatternIds} + drawState={this.props.drawState} + buttonText="Draw polygon" + /> + + + this._initiateDraw(DRAW_STATE_DRAW_TYPE.BOUNDS, e)} + uniqueIndexPatternIds={this.props.uniqueIndexPatternIds} + drawState={this.props.drawState} + buttonText="Draw bounds" + /> + +
); } 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 290f47d24f1ad75..83bec195f812698 100644 --- a/x-pack/plugins/maps/public/components/map/mb/index.js +++ b/x-pack/plugins/maps/public/components/map/mb/index.js @@ -13,8 +13,8 @@ import { setMouseCoordinates, clearMouseCoordinates, clearGoto, - setTooltipState, updateDrawState, - DRAW_STATE_TYPE + setTooltipState, + DRAW_STATE_TYPE, updateDrawStateWithOptions } from '../../../actions/store_actions'; import { getTooltipState, @@ -62,7 +62,7 @@ function mapDispatchToProps(dispatch) { dispatch(setTooltipState(tooltipState)); }, disableDrawState() { - dispatch(updateDrawState(DRAW_STATE_TYPE.NONE, null)); + dispatch(updateDrawStateWithOptions(DRAW_STATE_TYPE.NONE, 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 b160e8227e01e42..e05590c7e9406b1 100644 --- a/x-pack/plugins/maps/public/components/map/mb/view.js +++ b/x-pack/plugins/maps/public/components/map/mb/view.js @@ -12,12 +12,16 @@ import { syncLayerOrder, removeOrphanedSourcesAndLayers, createMbMapInstance } f 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_STATE_TYPE } from '../../../actions/store_actions'; +import { DRAW_STATE_DRAW_TYPE, DRAW_STATE_TYPE } from '../../../actions/store_actions'; import { filterBarQueryFilter } from '../../../kibana_services'; import { createShapeFilter } from '../../../index_pattern_util'; +const mbDrawModes = MapboxDraw.modes; +mbDrawModes.draw_rectangle = DrawRectangle; + const TOOLTIP_TYPE = { HOVER: 'HOVER', LOCKED: 'LOCKED' @@ -34,7 +38,8 @@ export class MBMapContainer extends React.Component { closeOnClick: false, }); this._mbDrawControl = new MapboxDraw({ - displayControlsDefault: false + displayControlsDefault: false, + modes: mbDrawModes }); this._mbDrawControlAdded = false; } @@ -50,7 +55,6 @@ export class MBMapContainer extends React.Component { return; } const featureCollection = this._mbDrawControl.getAll(); - // const layerId = this.props.drawState.layerId; const geoField = this.props.drawState.geoField; const indexPatternId = this.props.drawState.indexPatternId; this.props.disableDrawState(); @@ -60,17 +64,7 @@ export class MBMapContainer extends React.Component { return; } - // const layer = this._getLayerById(layerId); - // if (!layer) { - // return; - // } - // - // const geoPolygonFilter = await layer.createShapeFilter(featureCollection.features[0].geometry); - // if (!geoPolygonFilter) { - // return; - // } - - + //todo: should change filter-type based on drawmodetype and underlying index pattern/geofield combo const geoPolygonFilter = createShapeFilter(featureCollection.features[0].geometry, indexPatternId, geoField); if (!geoPolygonFilter) { return; @@ -251,14 +245,16 @@ export class MBMapContainer extends React.Component { this._mbDrawControlAdded = false; } - _addDrawControl() { - if (this._mbDrawControlAdded) { - return; + _updateDrawControl() { + if (!this._mbDrawControlAdded) { + this._mbMap.addControl(this._mbDrawControl); + this._mbMap.on('draw.selectionchange', this._onPolygonSelectionChange); + this._mbDrawControlAdded = true; } - this._mbMap.addControl(this._mbDrawControl); - this._mbMap.on('draw.selectionchange', this._onPolygonSelectionChange); - this._mbDrawControlAdded = true; - this._mbDrawControl.changeMode(this._mbDrawControl.modes.DRAW_POLYGON); + + const mbDrawMode = this.props.drawState.drawType === DRAW_STATE_DRAW_TYPE.POLYGON ? + this._mbDrawControl.modes.DRAW_POLYGON : 'draw_rectangle'; + this._mbDrawControl.changeMode(mbDrawMode); } async _initializeMap() { @@ -345,7 +341,7 @@ export class MBMapContainer extends React.Component { this._removeDrawControl(); return; } - this._addDrawControl(); + this._updateDrawControl(); } _syncMbMapWithMapState = () => { diff --git a/x-pack/plugins/maps/public/components/widget_overlay/layer_control/layer_toc/toc_entry/index.js b/x-pack/plugins/maps/public/components/widget_overlay/layer_control/layer_toc/toc_entry/index.js index b3f0967b882e569..a9b1b68db350651 100644 --- a/x-pack/plugins/maps/public/components/widget_overlay/layer_control/layer_toc/toc_entry/index.js +++ b/x-pack/plugins/maps/public/components/widget_overlay/layer_control/layer_toc/toc_entry/index.js @@ -12,9 +12,7 @@ import { fitToLayerExtent, setSelectedLayer, toggleLayerVisible, - removeTransientLayer, - updateDrawState, - DRAW_STATE_TYPE + removeTransientLayer } from '../../../../../actions/store_actions'; import { @@ -49,9 +47,6 @@ function mapDispatchToProps(dispatch) { }, fitToBounds: (layerId) => { dispatch(fitToLayerExtent(layerId)); - }, - initiateDraw: (layerId) => { - dispatch(updateDrawState(DRAW_STATE_TYPE.ACTIVE, layerId)); } }); } diff --git a/yarn.lock b/yarn.lock index ee4c12d2575263a..68b8cd1b9f0f4a1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -15864,6 +15864,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"